From e50f27d6b683c7c781f78e296ec3d66f4f1637a6 Mon Sep 17 00:00:00 2001 From: Sami Saari Date: Sat, 28 Mar 2026 15:31:09 +0000 Subject: [PATCH 001/111] #1244 Add CPU32 processor variant with full instruction set support Add Motorola CPU32 processor variant to the 68000 processor module. CPU32 is based on the 68020 with some instructions removed and table lookup/interpolation instructions added. Used in MC68330, MC68340, MC68360 and similar microcontrollers. Changes: - 68000.sinc: @ifdef/@ifndef CPU32 conditionals - Added: TBL instructions, LPSTOP, BGND - Excluded: BFxxx, CALLM, CAS, CAS2, PACK, RTM, UNPK - CPU32.slaspec: new language specification - 68000.ldefs: CPU32 variant definition - certification.manifest: CPU32.slaspec entry - Emulator test classes and pcode_defs.py configuration All 79 CPU32 instructions verified against CPU32 Reference Manual (Rev 1, Dec 1990). Pcode emulator tests pass: 16/16 O0, 16/16 O3. --- .../SleighDevTools/pcodetest/pcode_defs.py | 16 ++ .../Processors/68000/certification.manifest | 1 + .../68000/data/languages/68000.ldefs | 13 ++ .../68000/data/languages/68000.sinc | 141 +++++++++++++++++- .../68000/data/languages/CPU32.slaspec | 6 + .../processors/CPU32_O0_EmulatorTest.java | 40 +++++ .../processors/CPU32_O3_EmulatorTest.java | 40 +++++ 7 files changed, 255 insertions(+), 2 deletions(-) create mode 100644 Ghidra/Processors/68000/data/languages/CPU32.slaspec create mode 100644 Ghidra/Processors/68000/src/test.processors/java/ghidra/test/processors/CPU32_O0_EmulatorTest.java create mode 100644 Ghidra/Processors/68000/src/test.processors/java/ghidra/test/processors/CPU32_O3_EmulatorTest.java diff --git a/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py b/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py index 0e70268d34c..44d612a11ba 100644 --- a/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py +++ b/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py @@ -842,3 +842,19 @@ 'language_id': 'Xtensa:BE:32:default', 'ccflags': '-L %(toolchain_dir)s/lib/gcc/xtensa-elf/%(gcc_version)s', }) + + +PCodeTest({ + 'name': 'CPU32', + 'build_all': 1, + 'build_exe': 0, + 'has_float': 0, + 'has_double': 0, + 'toolchain': 'm68k/m68k-linux-gnu', + 'exec_prefix': 'm68k-linux-gnu-', + 'gcc_version': '14', + 'ccflags': '-mcpu=cpu32 -nostdlib -static', + 'cclibs': '-lgcc', + 'gcc_libdir': '/usr/lib/gcc-cross/m68k-linux-gnu/14', + 'language_id': '68000:BE:32:CPU32', +}) diff --git a/Ghidra/Processors/68000/certification.manifest b/Ghidra/Processors/68000/certification.manifest index 55d58490e3a..caf51979e76 100644 --- a/Ghidra/Processors/68000/certification.manifest +++ b/Ghidra/Processors/68000/certification.manifest @@ -12,6 +12,7 @@ data/languages/68020.slaspec||GHIDRA||reviewed||END| data/languages/68030.slaspec||GHIDRA||||END| data/languages/68040.slaspec||GHIDRA||||END| data/languages/coldfire.slaspec||GHIDRA||||END| +data/languages/CPU32.slaspec||GHIDRA||||END| data/manuals/68000.idx||GHIDRA||||END| data/patterns/68000_patterns.xml||GHIDRA||||END| data/patterns/patternconstraints.xml||GHIDRA||||END| diff --git a/Ghidra/Processors/68000/data/languages/68000.ldefs b/Ghidra/Processors/68000/data/languages/68000.ldefs index 5115f2d878b..7fe13fc6bf4 100644 --- a/Ghidra/Processors/68000/data/languages/68000.ldefs +++ b/Ghidra/Processors/68000/data/languages/68000.ldefs @@ -73,4 +73,17 @@ + + Motorola 32-bit CPU32 (MC68340) + + + diff --git a/Ghidra/Processors/68000/data/languages/68000.sinc b/Ghidra/Processors/68000/data/languages/68000.sinc index 674c9d06535..963f0829d3a 100644 --- a/Ghidra/Processors/68000/data/languages/68000.sinc +++ b/Ghidra/Processors/68000/data/languages/68000.sinc @@ -59,6 +59,10 @@ define register offset=0x746 size=10 [ FP7 ]; @define DAT_DIR_CTL_ADDR_MODES2 "(mode2=0 | mode2=2 | mode2=5 | mode2=6 | mode=7)" # Data direct and control addressing modes @define CTL_ADDR_MODES2 "(mode2=2 | mode2=5 | mode2=6 | mode2=7)" # Control addressing modes +@ifdef CPU32 +@define TBL_ADDR_MODES "(tbl_mode=2 | tbl_mode=4 | tbl_mode=5 | tbl_mode=6 | tbl_mode=7)" +@endif + # Floating-point condition code bits within FPSR @define N_FP "FPSR[27,1]" @define Z_FP "FPSR[26,1]" @@ -173,9 +177,29 @@ define token extword (16) reg12x = (12,15) reg12xwu = (12,15) reg12xwl = (12,15) -@endif +@endif +@ifdef CPU32 + tbl_dr_size = (6,7) + tbl_dr_round = (10,10) + tbl_dr_sign = (11,11) + tbl_dr_reg = (0,2) +@endif ; +@ifdef CPU32 +define token tbl_instrA(32) + tbl_regan=(16,18) + tbl_mode=(19,21) + tbl_op37=(19,23) + tbl_op67=(22,23) + tbl_opbig=(24,31) + tbl_size=(6,7) + tbl_round=(10,10) + tbl_sign=(11,11) + tbl_regxdn=(12,14) +; +@endif + define token extword2 (16) regda2 = (12,15) ext2_911 = (9,11) @@ -307,12 +331,20 @@ define context contextreg extGUARD = (14,14) # guard for saving off modes before starting instructions ; +@ifdef CPU32 +attach variables [ regdn regxdn reg9dn regdr regdq regsdn regdu regdc regdu2 regdc2 tbl_regxdn tbl_dr_reg ] [ D0 D1 D2 D3 D4 D5 D6 D7 ]; +@else attach variables [ regdn regxdn reg9dn regdr regdq regsdn regdu regdc regdu2 regdc2 ] [ D0 D1 D2 D3 D4 D5 D6 D7 ]; +@endif attach variables [ fldoffreg fldwdreg f_reg fcnt fkfacreg fldynreg ] [ D0 D1 D2 D3 D4 D5 D6 D7 ]; attach variables [ regdnw regxdnw reg9dnw regsdnw regduw regdcw regdu2w regdc2w ] [ D0w D1w D2w D3w D4w D5w D6w D7w ]; attach variables [ regdnb reg9dnb regsdnb regdub regdcb ] [ D0b D1b D2b D3b D4b D5b D6b D7b ]; attach variables [ regda regda2 ] [ D0 D1 D2 D3 D4 D5 D6 D7 A0 A1 A2 A3 A4 A5 A6 SP ]; +@ifdef CPU32 +attach variables [ regan regxan reg9an regfan regsan aregx tbl_regan ] [ A0 A1 A2 A3 A4 A5 A6 SP ]; +@else attach variables [ regan regxan reg9an regfan regsan aregx ] [ A0 A1 A2 A3 A4 A5 A6 SP ]; +@endif attach variables [ reganw regxanw regsanw ] [ A0w A1w A2w A3w A4w A5w A6w A7w ]; attach variables [ reganb regsanb ] [ A0b A1b A2b A3b A4b A5b A6b A7b ]; @@ -1051,6 +1083,7 @@ with : extGUARD=1 { local source = regdn; mask:4 = 1 << (const8 & 31); ZF = (source & mask) == 0; regdn = source & (~mask); } +@ifndef CPU32 bfOffWd: {f_off:f_wd} is f_off & f_wd { } :bfchg e2l^bfOffWd is opbig=0xea & op67=3 & $(DAT_DIR_CTL_ADDR_MODES); bfOffWd & f_off & f_wd; e2l [ savmod2=savmod1; regtsan=regtfan; ] { logflags(); @@ -1144,6 +1177,7 @@ bfOffWd: {f_off:f_wd} is f_off & f_wd { } getbitfield(tmp, f_off, f_wd); resbitflags(tmp, f_wd-1); } +@endif # CPU32 - no bitfield instructions define pcodeop breakpoint; :bkpt "#"op02 is opbig=0x48 & op67=1 & op5=0 & op34=1 & op02 { breakpoint(); } @@ -1205,7 +1239,8 @@ define pcodeop breakpoint; } @endif # COLDFIRE -# TODO: Determine layout of a module descriptor +@ifndef CPU32 +# TODO: Determine layout of a module descriptor define pcodeop callm; :callm const8,e2l is opbig=6 & op67=3 & $(CTL_ADDR_MODES); const8; e2l [ savmod2=savmod1; regtsan=regtfan; ] { PC = callm(const8, e2l); @@ -1283,6 +1318,7 @@ define pcodeop callm; ZF = 1; NF = 0; } +@endif # CPU32 - no CALLM, CAS, CAS2 :chk.w eaw,reg9dnw is (op=4 & reg9dnw & op68=6 & $(DAT_ALTER_ADDR_MODES))... & eaw { build eaw; @@ -2060,6 +2096,7 @@ macro negResFlags(result) { :ori const8,"CCR" is opbig=0 & op37=7 & op02=4; const8 { packflags(SR); SR=SR|zext(const8); unpackflags(SR); } :ori const16,SR is SR; opbig=0x00 & d8base=0x7c; const16 { packflags(SR); SR=SR|const16; unpackflags(SR); } +@ifndef CPU32 :pack Tyw,Txw,const16 is op=8 & op48=20 & Txw & Tyw & rmbit=0; const16 { local value = (Tyw & 0x0F0F) + const16; Txw = (Txw & 0xFF00) | ((value & 0x0F00) >> 4) | (value & 0x000F); @@ -2070,6 +2107,7 @@ macro negResFlags(result) { local result:2 = ((value & 0x0F00) >> 4) | (value & 0x000F); Txb = result:1; } +@endif # CPU32 - no PACK :pea eaptr is (opbig=0x48 & op67=1 & $(CTL_ADDR_MODES))... & eaptr { value:4 = eaptr; SP = SP-4; *SP = value; } @@ -2227,9 +2265,11 @@ ptestLevel: "#"^mregn is mregn { export *[const]:1 mregn; } :rtd const16 is opbig=0x4e & op37=14 & op02=4; const16 { PC = *SP; SP = SP + 4 + zext(const16); return [PC]; } :rte is d16=0x4e73 { tmp:4 = 0; return [tmp]; } +@ifndef CPU32 define pcodeop rtm; :rtm regdn is opbig=0x06 & op37=24 & regdn { PC = rtm(regdn); return [PC]; } :rtm regan is opbig=0x06 & op37=25 & regan { PC = rtm(regan); return [PC];} +@endif # CPU32 - no RTM :rtr is opbig=0x4e & op37=14 & op02=7 { SR = *SP; SP = SP+2; PC = *SP; SP = SP+4; unpackflags(SR); return [PC]; } @@ -2306,6 +2346,7 @@ define pcodeop stop; :unlk regan is opbig=0x4e & op37=11 & regan { SP = regan; regan = *SP; SP = SP+4; } +@ifndef CPU32 :unpk Tyw,Txw,const16 is op=8 & Txw & op48=24 & Tyw & rmbit=0; const16 { Txw = (Txw & 0xF0F0) | ((((Tyw & 0x00F0) << 4) | (Tyw & 0x000F)) + const16); } @@ -2315,7 +2356,9 @@ define pcodeop stop; source = (((source & 0x00F0) << 4) | (source & 0x000F)) + const16; Txw = (Txw & 0xF0F0) | source; } +@endif # CPU32 - no UNPK +@ifndef CPU32 # Floating Point Instructions # 68040 directly implements Floating Point instructions but requires Coprocessor ID be 001 @@ -2883,6 +2926,7 @@ fsubrnd: "d" is fdst & fopmode=0x6c { tmp:4 = float2float(fdst); fdst = float2f :ftwotox.x fsrc, fdst is op=15 & $(FP_COP) & op68=0 & mode=0 & regan=0; frm=0 & f1515=0 & f1313=0 & fsrc & fdst & fopmode=0x11 { fdst = ftwotox(fsrc); } +@endif # CPU32 - no FPU instructions @ifdef COLDFIRE @@ -3151,4 +3195,97 @@ moveaccreg2: ACC3 is ACC3 & op01=3 { export ACC3; } @endif +@ifdef CPU32 + +tbl_eal: (tbl_regan) is tbl_mode=2 & tbl_regan { export *:4 tbl_regan; } +tbl_eal: -(tbl_regan) is tbl_mode=4 & tbl_regan { tbl_regan = tbl_regan - 4; export *:4 tbl_regan; } +tbl_eal: (d16,tbl_regan) is tbl_mode=5 & tbl_regan; d16 { local tmp = tbl_regan + d16; export *:4 tmp; } +tbl_eal: (extw) is tbl_mode=6 & tbl_regan; extw [ regtfan = tbl_regan; pcmode = 0; ] { build extw; export *:4 extw; } +tbl_eal: (d16,PC) is PC & tbl_mode=7 & tbl_regan=2; d16 { tmp:4 = inst_start + 2 + d16; export *:4 tmp; } +tbl_eal: (extw) is tbl_mode=7 & tbl_regan=3; extw [ pcmode=1; ] { build extw; export *:4 extw; } +tbl_eal: (d16)".w" is tbl_mode=7 & tbl_regan=0; d16 { export *:4 d16; } +tbl_eal: (d32)".l" is tbl_mode=7 & tbl_regan=1; d32 { export *:4 d32; } +tbl_eal: "#"^d32 is tbl_mode=7 & tbl_regan=4; d32 { export *[const]:4 d32; } + +tbl_eaw: (tbl_regan) is tbl_mode=2 & tbl_regan { export *:2 tbl_regan; } +tbl_eaw: -(tbl_regan) is tbl_mode=4 & tbl_regan { tbl_regan = tbl_regan - 2; export *:2 tbl_regan; } +tbl_eaw: (d16,tbl_regan) is tbl_mode=5 & tbl_regan; d16 { local tmp = tbl_regan + d16; export *:2 tmp; } +tbl_eaw: (extw) is tbl_mode=6 & tbl_regan; extw [ pcmode=0; regtfan=tbl_regan; ] { build extw; export *:2 extw; } +tbl_eaw: (d16,PC) is PC & tbl_mode=7 & tbl_regan=2; d16 { tmp:4 = inst_start + 2 + d16; export *:2 tmp; } +tbl_eaw: (extw) is tbl_mode=7 & tbl_regan=3; extw [ pcmode=1; ] { build extw; export *:2 extw; } +tbl_eaw: (d16)".w" is tbl_mode=7 & tbl_regan=0; d16 { export *:2 d16; } +tbl_eaw: (d32)".l" is tbl_mode=7 & tbl_regan=1; d32 { export *:2 d32; } +tbl_eaw: "#"^d16 is tbl_mode=7 & tbl_regan=4; d16 { export *[const]:2 d16; } + +tbl_eab: (tbl_regan) is tbl_mode=2 & tbl_regan { export *:1 tbl_regan; } +tbl_eab: -(tbl_regan) is tbl_mode=4 & tbl_regan { tbl_regan = tbl_regan - 1; export *:1 tbl_regan; } +tbl_eab: (d16,tbl_regan) is tbl_mode=5 & tbl_regan; d16 { local tmp = tbl_regan + d16; export *:1 tmp; } +tbl_eab: (extw) is tbl_mode=6 & tbl_regan; extw [ pcmode=0; regtfan=tbl_regan; ] { build extw; export *:1 extw; } +tbl_eab: (d16,PC) is PC & tbl_mode=7 & tbl_regan=2; d16 { tmp:4 = inst_start + 2 + d16; export *:1 tmp; } +tbl_eab: (extw) is tbl_mode=7 & tbl_regan=3; extw [ pcmode=1; ] { build extw; export *:1 extw; } +tbl_eab: (d16)".w" is tbl_mode=7 & tbl_regan=0; d16 { export *:1 d16; } +tbl_eab: (d32)".l" is tbl_mode=7 & tbl_regan=1; d32 { export *:1 d32; } +tbl_eab: "#"^d8 is tbl_mode=7 & tbl_regan=4; d8 { export *[const]:1 d8; } + +tblsign: "u" is tbl_sign=0 { } +tblsign: "s" is tbl_sign=1 { } + +tbldrsign: "u" is tbl_dr_sign=0 { } +tbldrsign: "s" is tbl_dr_sign=1 { } + +define pcodeop tableLookup; + +# Rounded Table Lookup and Interpolate + +:tbl^tblsign^".b" tbl_eab,tbl_regxdn is (tbl_opbig=0xF8 & tbl_op67=0 & $(TBL_ADDR_MODES) & tbl_size=0 & tblsign & tbl_round=0 & tbl_regxdn) ... & tbl_eab + { tbl_regxdn = tableLookup(tbl_regxdn, tbl_eab); } + +:tbl^tblsign^".w" tbl_eaw,tbl_regxdn is (tbl_opbig=0xF8 & tbl_op67=0 & $(TBL_ADDR_MODES) & tbl_size=1 & tblsign & tbl_round=0 & tbl_regxdn) ... & tbl_eaw + { tbl_regxdn = tableLookup(tbl_regxdn, tbl_eaw); } + +:tbl^tblsign^".l" tbl_eal,tbl_regxdn is (tbl_opbig=0xF8 & tbl_op67=0 & $(TBL_ADDR_MODES) & tbl_size=2 & tblsign & tbl_round=0 & tbl_regxdn) ... & tbl_eal + { tbl_regxdn = tableLookup(tbl_regxdn, tbl_eal); } + +# Unrounded Table Lookup and Interpolate + +:tbl^tblsign^"n.b" tbl_eab,tbl_regxdn is (tbl_opbig=0xF8 & tbl_op67=0 & $(TBL_ADDR_MODES) & tbl_size=0 & tblsign & tbl_round=1 & tbl_regxdn) ... & tbl_eab + { tbl_regxdn = tableLookup(tbl_regxdn, tbl_eab); } + +:tbl^tblsign^"n.w" tbl_eaw,tbl_regxdn is (tbl_opbig=0xF8 & tbl_op67=0 & $(TBL_ADDR_MODES) & tbl_size=1 & tblsign & tbl_round=1 & tbl_regxdn) ... & tbl_eaw + { tbl_regxdn = tableLookup(tbl_regxdn, tbl_eaw); } + +:tbl^tblsign^"n.l" tbl_eal,tbl_regxdn is (tbl_opbig=0xF8 & tbl_op67=0 & $(TBL_ADDR_MODES) & tbl_size=2 & tblsign & tbl_round=1 & tbl_regxdn) ... & tbl_eal + { tbl_regxdn = tableLookup(tbl_regxdn, tbl_eal); } + +define pcodeop interpolate; + +# Rounded Data Register Interpolate + +:tbl^tbldrsign^".b" regdn:tbl_dr_reg,regxdn is opbig=0xF8 & op37=0 & mode=0 & regdn ; tbl_dr_size=0 & tbldrsign & tbl_dr_round=0 & tbl_dr_reg & regxdn + { regxdn = interpolate(regdn, tbl_dr_reg); } + +:tbl^tbldrsign^".w" regdn:tbl_dr_reg,regxdn is opbig=0xF8 & op37=0 & mode=0 & regdn ; tbl_dr_size=1 & tbldrsign & tbl_dr_round=0 & tbl_dr_reg & regxdn + { regxdn = interpolate(regdn, tbl_dr_reg); } + +:tbl^tbldrsign^".l" regdn:tbl_dr_reg,regxdn is opbig=0xF8 & op37=0 & mode=0 & regdn ; tbl_dr_size=2 & tbldrsign & tbl_dr_round=0 & tbl_dr_reg & regxdn + { regxdn = interpolate(regdn, tbl_dr_reg); } + +# Unrounded Data Register Interpolate + +:tbl^tbldrsign^"n.b" regdn:tbl_dr_reg,regxdn is opbig=0xF8 & op37=0 & mode=0 & regdn ; tbl_dr_size=0 & tbldrsign & tbl_dr_round=1 & tbl_dr_reg & regxdn + { regxdn = interpolate(regdn, tbl_dr_reg); } + +:tbl^tbldrsign^"n.w" regdn:tbl_dr_reg,regxdn is opbig=0xF8 & op37=0 & mode=0 & regdn ; tbl_dr_size=1 & tbldrsign & tbl_dr_round=1 & tbl_dr_reg & regxdn + { regxdn = interpolate(regdn, tbl_dr_reg); } + +:tbl^tbldrsign^"n.l" regdn:tbl_dr_reg,regxdn is opbig=0xF8 & op37=0 & mode=0 & regdn ; tbl_dr_size=2 & tbldrsign & tbl_dr_round=1 & tbl_dr_reg & regxdn + { regxdn = interpolate(regdn, tbl_dr_reg); } + +define pcodeop low_power_stop; +:lpstop "#"^d16 is opbig=0xf8 & d8base=0x00; opbig=0x01 & d8base=0xC0; d16 { SR = d16; low_power_stop(); } + +define pcodeop background_mode; +:bgnd is opbig=0x4A & d8base=0xFA { background_mode(); } + +@endif # CPU32 } # end with : extGUARD=1 diff --git a/Ghidra/Processors/68000/data/languages/CPU32.slaspec b/Ghidra/Processors/68000/data/languages/CPU32.slaspec new file mode 100644 index 00000000000..dc2c54ab6f1 --- /dev/null +++ b/Ghidra/Processors/68000/data/languages/CPU32.slaspec @@ -0,0 +1,6 @@ +# Motorola's CPU32 processor + +@define CPU32 "" +@define MC68332 "" + +@include "68000.sinc" diff --git a/Ghidra/Processors/68000/src/test.processors/java/ghidra/test/processors/CPU32_O0_EmulatorTest.java b/Ghidra/Processors/68000/src/test.processors/java/ghidra/test/processors/CPU32_O0_EmulatorTest.java new file mode 100644 index 00000000000..583c7052a99 --- /dev/null +++ b/Ghidra/Processors/68000/src/test.processors/java/ghidra/test/processors/CPU32_O0_EmulatorTest.java @@ -0,0 +1,40 @@ +/* ### + * 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.test.processors; + +import ghidra.test.processors.support.ProcessorEmulatorTestAdapter; +import junit.framework.Test; + +public class CPU32_O0_EmulatorTest extends ProcessorEmulatorTestAdapter { + + private static final String LANGUAGE_ID = "68000:BE:32:CPU32"; + private static final String COMPILER_SPEC_ID = "default"; + + private static final String[] REG_DUMP_SET = new String[] {}; + + public CPU32_O0_EmulatorTest(String name) throws Exception { + super(name, LANGUAGE_ID, COMPILER_SPEC_ID, REG_DUMP_SET); + } + + @Override + protected String getProcessorDesignator() { + return "CPU32_GCC_O0"; + } + + public static Test suite() { + return ProcessorEmulatorTestAdapter.buildEmulatorTestSuite(CPU32_O0_EmulatorTest.class); + } +} diff --git a/Ghidra/Processors/68000/src/test.processors/java/ghidra/test/processors/CPU32_O3_EmulatorTest.java b/Ghidra/Processors/68000/src/test.processors/java/ghidra/test/processors/CPU32_O3_EmulatorTest.java new file mode 100644 index 00000000000..086c4ab070c --- /dev/null +++ b/Ghidra/Processors/68000/src/test.processors/java/ghidra/test/processors/CPU32_O3_EmulatorTest.java @@ -0,0 +1,40 @@ +/* ### + * 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.test.processors; + +import ghidra.test.processors.support.ProcessorEmulatorTestAdapter; +import junit.framework.Test; + +public class CPU32_O3_EmulatorTest extends ProcessorEmulatorTestAdapter { + + private static final String LANGUAGE_ID = "68000:BE:32:CPU32"; + private static final String COMPILER_SPEC_ID = "default"; + + private static final String[] REG_DUMP_SET = new String[] {}; + + public CPU32_O3_EmulatorTest(String name) throws Exception { + super(name, LANGUAGE_ID, COMPILER_SPEC_ID, REG_DUMP_SET); + } + + @Override + protected String getProcessorDesignator() { + return "CPU32_GCC_O3"; + } + + public static Test suite() { + return ProcessorEmulatorTestAdapter.buildEmulatorTestSuite(CPU32_O3_EmulatorTest.class); + } +} From e9d14bb5561faec9f9e4a46448b1aaf931014aaf Mon Sep 17 00:00:00 2001 From: caheckman <48068198+caheckman@users.noreply.github.com> Date: Thu, 28 May 2026 23:07:32 +0000 Subject: [PATCH 002/111] GP-6892 writeOpcode for ordinal --- .../src/main/java/ghidra/program/model/pcode/Encoder.java | 8 ++++++++ .../java/ghidra/program/model/pcode/PackedEncode.java | 6 ++++++ .../src/main/java/ghidra/program/model/pcode/PcodeOp.java | 2 +- .../main/java/ghidra/program/model/pcode/XmlEncode.java | 7 ++++++- 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Encoder.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Encoder.java index 45f085bd33e..15273c60419 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Encoder.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Encoder.java @@ -138,4 +138,12 @@ public interface Encoder { * @throws IOException for errors in the underlying stream */ void writeOpcode(AttributeId attribId, OpCode opcode) throws IOException; + + /** + * Write a p-code operation opcode into the encoding, given the opcode ordinal, defined in {@link PcodeOp} + * @param attribId is the attribute to associate with the opcode + * @param opcode is the opcode ordinal + * @throws IOException for errors in the underlying stream + */ + void writeOpcode(AttributeId attribId, int opcode) throws IOException; } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PackedEncode.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PackedEncode.java index d2fbf89ee1c..c5e4f14ce57 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PackedEncode.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PackedEncode.java @@ -207,6 +207,12 @@ public void writeOpcode(AttributeId attribId, OpCode opcode) throws IOException writeInteger((TYPECODE_SIGNEDINT_POSITIVE << TYPECODE_SHIFT), opcode.ordinal()); } + @Override + public void writeOpcode(AttributeId attribId, int opcode) throws IOException { + writeHeader(ATTRIBUTE, attribId.id()); + writeInteger((TYPECODE_SIGNEDINT_POSITIVE << TYPECODE_SHIFT), opcode); + } + /** * @return the underlying stream */ diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeOp.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeOp.java index e89815450ba..ba657b0883f 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeOp.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeOp.java @@ -439,7 +439,7 @@ public final void setOutput(Varnode vn) { */ public void encodeRaw(Encoder encoder, AddressFactory addrFactory) throws IOException { encoder.openElement(ELEM_OP); - encoder.writeSignedInteger(ATTRIB_CODE, opcode); + encoder.writeOpcode(ATTRIB_CODE, opcode); encoder.writeSignedInteger(ATTRIB_SIZE, input.length); if (output == null) { encoder.openElement(ELEM_VOID); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/XmlEncode.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/XmlEncode.java index c74da2042ee..7809b2eadbc 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/XmlEncode.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/XmlEncode.java @@ -15,7 +15,7 @@ */ package ghidra.program.model.pcode; -import static ghidra.program.model.pcode.AttributeId.ATTRIB_CONTENT; +import static ghidra.program.model.pcode.AttributeId.*; import java.io.IOException; import java.io.OutputStream; @@ -250,6 +250,11 @@ public void writeOpcode(AttributeId attribId, OpCode opcode) throws IOException buffer.append("\""); } + @Override + public void writeOpcode(AttributeId attribId, int opcode) throws IOException { + writeOpcode(attribId, OpCode.getOpcode(opcode)); + } + @Override public void writeTo(OutputStream stream) throws IOException { byte[] res = buffer.toString().getBytes(); From 3ca3a44e4cd2a848b81fb77864a5124775fb4bb4 Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Fri, 29 May 2026 13:38:19 +0000 Subject: [PATCH 003/111] GP-6818: Added missing x86 gfni instructions --- Ghidra/Processors/x86/certification.manifest | 1 + .../Processors/x86/data/languages/avx512.sinc | 96 --------- .../Processors/x86/data/languages/gfni.sinc | 193 ++++++++++++++++++ .../Processors/x86/data/languages/x86.slaspec | 1 + 4 files changed, 195 insertions(+), 96 deletions(-) create mode 100644 Ghidra/Processors/x86/data/languages/gfni.sinc diff --git a/Ghidra/Processors/x86/certification.manifest b/Ghidra/Processors/x86/certification.manifest index 71dfe249477..7dbc81ad507 100644 --- a/Ghidra/Processors/x86/certification.manifest +++ b/Ghidra/Processors/x86/certification.manifest @@ -23,6 +23,7 @@ data/languages/bmi2.sinc||GHIDRA||||END| data/languages/cet.sinc||GHIDRA||||END| data/languages/clwb.sinc||GHIDRA||||END| data/languages/fma.sinc||GHIDRA||||END| +data/languages/gfni.sinc||GHIDRA||||END| data/languages/ia.sinc||GHIDRA||||END| data/languages/lockable.sinc||GHIDRA||||END| data/languages/lzcnt.sinc||GHIDRA||||END| diff --git a/Ghidra/Processors/x86/data/languages/avx512.sinc b/Ghidra/Processors/x86/data/languages/avx512.sinc index 4c344929889..709a356937c 100644 --- a/Ghidra/Processors/x86/data/languages/avx512.sinc +++ b/Ghidra/Processors/x86/data/languages/avx512.sinc @@ -13745,102 +13745,6 @@ define pcodeop vaesenclast_vaes ; ZmmReg1 = vaesenclast_vaes( evexV5_ZmmReg, ZmmReg2_m512 ); } -# GF2P8AFFINEINVQB 3-476 PAGE 1046 LINE 56498 -define pcodeop vgf2p8affineinvqb_avx512vl ; -:VGF2P8AFFINEINVQB XmmReg1 XmmOpMask8, evexV5_XmmReg, XmmReg2_m128_m64bcst, imm8 is $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1) & XmmOpMask8 & evexV5_XmmReg; byte=0xCF; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128_m64bcst; imm8 -[ evexD8Type = 0; evexTType = 0; ] # (TupleType Full) -{ - XmmResult = vgf2p8affineinvqb_avx512vl( evexV5_XmmReg, XmmReg2_m128_m64bcst, imm8:1 ); - XmmMask = XmmReg1; - build XmmOpMask8; - ZmmReg1 = zext(XmmResult); -} - -# GF2P8AFFINEINVQB 3-476 PAGE 1046 LINE 56501 -:VGF2P8AFFINEINVQB YmmReg1 YmmOpMask8, evexV5_YmmReg, YmmReg2_m256_m64bcst, imm8 is $(EVEX_NONE) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1) & YmmOpMask8 & evexV5_YmmReg; byte=0xCF; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256_m64bcst; imm8 -[ evexD8Type = 0; evexTType = 0; ] # (TupleType Full) -{ - YmmResult = vgf2p8affineinvqb_avx512vl( evexV5_YmmReg, YmmReg2_m256_m64bcst, imm8:1 ); - YmmMask = YmmReg1; - build YmmOpMask8; - ZmmReg1 = zext(YmmResult); -} - -# GF2P8AFFINEINVQB 3-476 PAGE 1046 LINE 56504 -define pcodeop vgf2p8affineinvqb_avx512f ; -:VGF2P8AFFINEINVQB ZmmReg1 ZmmOpMask8, evexV5_ZmmReg, ZmmReg2_m512_m64bcst, imm8 is $(EVEX_NONE) & $(EVEX_L512) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1) & ZmmOpMask8 & evexV5_ZmmReg; byte=0xCF; ZmmReg1 ... & ZmmReg2_m512_m64bcst; imm8 -[ evexD8Type = 0; evexTType = 0; ] # (TupleType Full) -{ - ZmmResult = vgf2p8affineinvqb_avx512f( evexV5_ZmmReg, ZmmReg2_m512_m64bcst, imm8:1 ); - ZmmMask = ZmmReg1; - build ZmmOpMask8; - ZmmReg1 = ZmmResult; -} - -# GF2P8AFFINEQB 3-479 PAGE 1049 LINE 56642 -define pcodeop vgf2p8affineqb_avx512vl ; -:VGF2P8AFFINEQB XmmReg1 XmmOpMask8, evexV5_XmmReg, XmmReg2_m128_m64bcst, imm8 is $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1) & XmmOpMask8 & evexV5_XmmReg; byte=0xCE; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128_m64bcst; imm8 -[ evexD8Type = 0; evexTType = 0; ] # (TupleType Full) -{ - XmmResult = vgf2p8affineqb_avx512vl( evexV5_XmmReg, XmmReg2_m128_m64bcst, imm8:1 ); - XmmMask = XmmReg1; - build XmmOpMask8; - ZmmReg1 = zext(XmmResult); -} - -# GF2P8AFFINEQB 3-479 PAGE 1049 LINE 56645 -:VGF2P8AFFINEQB YmmReg1 YmmOpMask8, evexV5_YmmReg, YmmReg2_m256_m64bcst, imm8 is $(EVEX_NONE) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1) & YmmOpMask8 & evexV5_YmmReg; byte=0xCE; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256_m64bcst; imm8 -[ evexD8Type = 0; evexTType = 0; ] # (TupleType Full) -{ - YmmResult = vgf2p8affineqb_avx512vl( evexV5_YmmReg, YmmReg2_m256_m64bcst, imm8:1 ); - YmmMask = YmmReg1; - build YmmOpMask8; - ZmmReg1 = zext(YmmResult); -} - -# GF2P8AFFINEQB 3-479 PAGE 1049 LINE 56648 -define pcodeop vgf2p8affineqb_avx512f ; -:VGF2P8AFFINEQB ZmmReg1 ZmmOpMask8, evexV5_ZmmReg, ZmmReg2_m512_m64bcst, imm8 is $(EVEX_NONE) & $(EVEX_L512) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1) & ZmmOpMask8 & evexV5_ZmmReg; byte=0xCE; ZmmReg1 ... & ZmmReg2_m512_m64bcst; imm8 -[ evexD8Type = 0; evexTType = 0; ] # (TupleType Full) -{ - ZmmResult = vgf2p8affineqb_avx512f( evexV5_ZmmReg, ZmmReg2_m512_m64bcst, imm8:1 ); - ZmmMask = ZmmReg1; - build ZmmOpMask8; - ZmmReg1 = ZmmResult; -} - -# GF2P8MULB 3-481 PAGE 1051 LINE 56754 -define pcodeop vgf2p8mulb_avx512vl ; -:VGF2P8MULB XmmReg1 XmmOpMask8, evexV5_XmmReg, XmmReg2_m128 is $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & XmmOpMask8 & evexV5_XmmReg; byte=0xCF; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 -[ evexD8Type = 1; evexTType = 0; ] # (TupleType Full Mem) -{ - XmmResult = vgf2p8mulb_avx512vl( evexV5_XmmReg, XmmReg2_m128 ); - XmmMask = XmmReg1; - build XmmOpMask8; - ZmmReg1 = zext(XmmResult); -} - -# GF2P8MULB 3-481 PAGE 1051 LINE 56757 -:VGF2P8MULB YmmReg1 YmmOpMask8, evexV5_YmmReg, YmmReg2_m256 is $(EVEX_NONE) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & YmmOpMask8 & evexV5_YmmReg; byte=0xCF; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 -[ evexD8Type = 1; evexTType = 0; ] # (TupleType Full Mem) -{ - YmmResult = vgf2p8mulb_avx512vl( evexV5_YmmReg, YmmReg2_m256 ); - YmmMask = YmmReg1; - build YmmOpMask8; - ZmmReg1 = zext(YmmResult); -} - -# GF2P8MULB 3-481 PAGE 1051 LINE 56760 -define pcodeop vgf2p8mulb_avx512f ; -:VGF2P8MULB ZmmReg1 ZmmOpMask8, evexV5_ZmmReg, ZmmReg2_m512 is $(EVEX_NONE) & $(EVEX_L512) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & ZmmOpMask8 & evexV5_ZmmReg; byte=0xCF; ZmmReg1 ... & ZmmReg2_m512 -[ evexD8Type = 1; evexTType = 0; ] # (TupleType Full Mem) -{ - ZmmResult = vgf2p8mulb_avx512f( evexV5_ZmmReg, ZmmReg2_m512 ); - ZmmMask = ZmmReg1; - build ZmmOpMask8; - ZmmReg1 = ZmmResult; -} - # PCLMULQDQ 4-242 PAGE 1362 LINE 76037 define pcodeop vpclmulqdq_vpclmulqdq ; :VPCLMULQDQ XmmReg1, evexV5_XmmReg, XmmReg2_m128, imm8 is $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_WIG) & evexV5_XmmReg; byte=0x44; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128; imm8 diff --git a/Ghidra/Processors/x86/data/languages/gfni.sinc b/Ghidra/Processors/x86/data/languages/gfni.sinc new file mode 100644 index 00000000000..469187f7ef5 --- /dev/null +++ b/Ghidra/Processors/x86/data/languages/gfni.sinc @@ -0,0 +1,193 @@ +#66 0F3A CF /r /ib +#GF2P8AFFINEINVQB xmm1, +#xmm2/m128, imm8 A V/V +#GFNI Computes inverse affine transformation in the finite field GF(2^8). +define pcodeop gf2p8affineinvqb; +:GF2P8AFFINEINVQB XmmReg1, XmmReg2_m128, imm8 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x3A; byte=0xCF; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128; imm8 +[ evexD8Type = 0; evexTType = 0; ] # (TupleType Full) +{ + XmmReg1 = gf2p8affineinvqb(XmmReg2_m128, XmmReg1, imm8:1 ); + ZmmReg1 = zext(XmmReg1); +} + +#VEX.128.66.0F3A.W1 CF /r /ib +#VGF2P8AFFINEINVQB xmm1, xmm2, +#xmm3/m128, imm8 B V/V +#AVX GFNI Computes inverse affine transformation in the finite field GF(2^8). +define pcodeop vgf2p8affineinvqb_avx; +:VGF2P8AFFINEINVQB XmmReg1, vexVVVV_XmmReg, XmmReg2_m128, imm8 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xCF; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128; imm8 +[ evexD8Type = 0; evexTType = 0; ] # (TupleType Full) +{ + XmmReg1 = vgf2p8affineinvqb_avx( vexVVVV_XmmReg, XmmReg2_m128, imm8:1 ); + ZmmReg1 = zext(XmmReg1); +} +#VEX.256.66.0F3A.W1 CF /r /ib +#VGF2P8AFFINEINVQB ymm1, ymm2, +#ymm3/m256, imm8 B V/V AVX +#GFNI Computes inverse affine transformation in the finite field GF(2^8). +:VGF2P8AFFINEINVQB YmmReg1, vexVVVV_YmmReg, YmmReg2_m256, imm8 is $(VEX_NONE) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xCF; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256; imm8 +[ evexD8Type = 0; evexTType = 0; ] # (TupleType Full) +{ + YmmReg1 = vgf2p8affineinvqb_avx( vexVVVV_YmmReg, YmmReg2_m256, imm8:1 ); + ZmmReg1 = zext(YmmReg1); +} + +# GF2P8AFFINEINVQB 3-476 PAGE 1046 LINE 56498 +define pcodeop vgf2p8affineinvqb_avx512vl ; +:VGF2P8AFFINEINVQB XmmReg1 XmmOpMask8, evexV5_XmmReg, XmmReg2_m128_m64bcst, imm8 is $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1) & XmmOpMask8 & evexV5_XmmReg; byte=0xCF; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128_m64bcst; imm8 +[ evexD8Type = 0; evexTType = 0; ] # (TupleType Full) +{ + XmmResult = vgf2p8affineinvqb_avx512vl( evexV5_XmmReg, XmmReg2_m128_m64bcst, imm8:1 ); + XmmMask = XmmReg1; + build XmmOpMask8; + ZmmReg1 = zext(XmmResult); +} + +# GF2P8AFFINEINVQB 3-476 PAGE 1046 LINE 56501 +:VGF2P8AFFINEINVQB YmmReg1 YmmOpMask8, evexV5_YmmReg, YmmReg2_m256_m64bcst, imm8 is $(EVEX_NONE) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1) & YmmOpMask8 & evexV5_YmmReg; byte=0xCF; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256_m64bcst; imm8 +[ evexD8Type = 0; evexTType = 0; ] # (TupleType Full) +{ + YmmResult = vgf2p8affineinvqb_avx512vl( evexV5_YmmReg, YmmReg2_m256_m64bcst, imm8:1 ); + YmmMask = YmmReg1; + build YmmOpMask8; + ZmmReg1 = zext(YmmResult); +} + +# GF2P8AFFINEINVQB 3-476 PAGE 1046 LINE 56504 +define pcodeop vgf2p8affineinvqb_avx512f ; +:VGF2P8AFFINEINVQB ZmmReg1 ZmmOpMask8, evexV5_ZmmReg, ZmmReg2_m512_m64bcst, imm8 is $(EVEX_NONE) & $(EVEX_L512) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1) & ZmmOpMask8 & evexV5_ZmmReg; byte=0xCF; ZmmReg1 ... & ZmmReg2_m512_m64bcst; imm8 +[ evexD8Type = 0; evexTType = 0; ] # (TupleType Full) +{ + ZmmResult = vgf2p8affineinvqb_avx512f( evexV5_ZmmReg, ZmmReg2_m512_m64bcst, imm8:1 ); + ZmmMask = ZmmReg1; + build ZmmOpMask8; + ZmmReg1 = ZmmResult; +} + +#66 0F3A CE /r /ib +#GF2P8AFFINEQB xmm1, xmm2/m128, imm8 A V/V GFNI +#Computes affine transformation in the finite field GF(2^8). +define pcodeop gf2p8affineqb; +:GF2P8AFFINEQB XmmReg1, XmmReg2_m128, imm8 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x3A; byte=0xCE; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128; imm8 +[ evexD8Type = 0; evexTType = 0; ] # (TupleType Full) +{ + XmmReg1 = gf2p8affineqb(XmmReg2_m128, XmmReg1, imm8:1 ); + ZmmReg1 = zext(XmmReg1); +} + +#VEX.128.66.0F3A.W1 CE /r /ib +#VGF2P8AFFINEQB xmm1, xmm2, xmm3/m128, imm8 B V/V AVX +#GFNI Computes affine transformation in the finite field GF(2^8). +define pcodeop vgf2p8affineqb_avx; +:VGF2P8AFFINEQB XmmReg1, vexVVVV_XmmReg, XmmReg2_m128, imm8 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xCE; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128; imm8 +[ evexD8Type = 0; evexTType = 0; ] # (TupleType Full) +{ + XmmReg1 = vgf2p8affineqb_avx( vexVVVV_XmmReg, XmmReg2_m128, imm8:1 ); + ZmmReg1 = zext(XmmReg1); +} + +#VEX.256.66.0F3A.W1 CE /r /ib +#VGF2P8AFFINEQB ymm1, ymm2, ymm3/m256, imm8 B V/V AVX +#GFNI Computes affine transformation in the finite field GF(2^8). +:VGF2P8AFFINEQB YmmReg1, vexVVVV_YmmReg, YmmReg2_m256, imm8 is $(VEX_NONE) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xCE; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256; imm8 +[ evexD8Type = 0; evexTType = 0; ] # (TupleType Full) +{ + YmmReg1 = vgf2p8affineqb_avx( vexVVVV_YmmReg, YmmReg2_m256, imm8:1 ); + ZmmReg1 = zext(YmmReg1); +} + +# GF2P8AFFINEQB 3-479 PAGE 1049 LINE 56642 +define pcodeop vgf2p8affineqb_avx512vl ; +:VGF2P8AFFINEQB XmmReg1 XmmOpMask8, evexV5_XmmReg, XmmReg2_m128_m64bcst, imm8 is $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1) & XmmOpMask8 & evexV5_XmmReg; byte=0xCE; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128_m64bcst; imm8 +[ evexD8Type = 0; evexTType = 0; ] # (TupleType Full) +{ + XmmResult = vgf2p8affineqb_avx512vl( evexV5_XmmReg, XmmReg2_m128_m64bcst, imm8:1 ); + XmmMask = XmmReg1; + build XmmOpMask8; + ZmmReg1 = zext(XmmResult); +} + +# GF2P8AFFINEQB 3-479 PAGE 1049 LINE 56645 +:VGF2P8AFFINEQB YmmReg1 YmmOpMask8, evexV5_YmmReg, YmmReg2_m256_m64bcst, imm8 is $(EVEX_NONE) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1) & YmmOpMask8 & evexV5_YmmReg; byte=0xCE; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256_m64bcst; imm8 +[ evexD8Type = 0; evexTType = 0; ] # (TupleType Full) +{ + YmmResult = vgf2p8affineqb_avx512vl( evexV5_YmmReg, YmmReg2_m256_m64bcst, imm8:1 ); + YmmMask = YmmReg1; + build YmmOpMask8; + ZmmReg1 = zext(YmmResult); +} + +# GF2P8AFFINEQB 3-479 PAGE 1049 LINE 56648 +define pcodeop vgf2p8affineqb_avx512f ; +:VGF2P8AFFINEQB ZmmReg1 ZmmOpMask8, evexV5_ZmmReg, ZmmReg2_m512_m64bcst, imm8 is $(EVEX_NONE) & $(EVEX_L512) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1) & ZmmOpMask8 & evexV5_ZmmReg; byte=0xCE; ZmmReg1 ... & ZmmReg2_m512_m64bcst; imm8 +[ evexD8Type = 0; evexTType = 0; ] # (TupleType Full) +{ + ZmmResult = vgf2p8affineqb_avx512f( evexV5_ZmmReg, ZmmReg2_m512_m64bcst, imm8:1 ); + ZmmMask = ZmmReg1; + build ZmmOpMask8; + ZmmReg1 = ZmmResult; +} + +#66 0F38 CF /r +#GF2P8MULB xmm1, xmm2/m128 A V/V +#GFNI Multiplies elements in the finite field GF(2^8). +define pcodeop gf2p8mulb; +:GF2P8MULB XmmReg1, XmmReg2_m128, imm8 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x38; byte=0xCF; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128; imm8 +[ evexD8Type = 0; evexTType = 0; ] # (TupleType Full) +{ + XmmReg1 = gf2p8mulb(XmmReg2_m128, XmmReg1, imm8:1 ); + ZmmReg1 = zext(XmmReg1); +} + +#VEX.128.66.0F38.W0 CF /r +#VGF2P8MULB xmm1, xmm2, xmm3/m128 B V/V AVX +#GFNI Multiplies elements in the finite field GF(2^8). +define pcodeop vgf2p8mulb_avx; +:VGF2P8MULB XmmReg1, vexVVVV_XmmReg, XmmReg2_m128, imm8 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xCF; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128; imm8 +[ evexD8Type = 0; evexTType = 0; ] # (TupleType Full) +{ + XmmReg1 = vgf2p8affineqb_avx( vexVVVV_XmmReg, XmmReg2_m128, imm8:1 ); + ZmmReg1 = zext(XmmReg1); +} + +#VEX.256.66.0F38.W0 CF /r +#VGF2P8MULB ymm1, ymm2, ymm3/m256 B V/V AVX +#GFNI Multiplies elements in the finite field GF(2^8). +:VGF2P8MULB YmmReg1, vexVVVV_YmmReg, YmmReg2_m256, imm8 is $(VEX_NONE) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xCF; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256; imm8 +[ evexD8Type = 0; evexTType = 0; ] # (TupleType Full) +{ + YmmReg1 = vgf2p8mulb_avx( vexVVVV_YmmReg, YmmReg2_m256, imm8:1 ); + ZmmReg1 = zext(YmmReg1); +} + +# GF2P8MULB 3-481 PAGE 1051 LINE 56754 +define pcodeop vgf2p8mulb_avx512vl ; +:VGF2P8MULB XmmReg1 XmmOpMask8, evexV5_XmmReg, XmmReg2_m128 is $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & XmmOpMask8 & evexV5_XmmReg; byte=0xCF; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 +[ evexD8Type = 1; evexTType = 0; ] # (TupleType Full Mem) +{ + XmmResult = vgf2p8mulb_avx512vl( evexV5_XmmReg, XmmReg2_m128 ); + XmmMask = XmmReg1; + build XmmOpMask8; + ZmmReg1 = zext(XmmResult); +} + +# GF2P8MULB 3-481 PAGE 1051 LINE 56757 +:VGF2P8MULB YmmReg1 YmmOpMask8, evexV5_YmmReg, YmmReg2_m256 is $(EVEX_NONE) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & YmmOpMask8 & evexV5_YmmReg; byte=0xCF; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 +[ evexD8Type = 1; evexTType = 0; ] # (TupleType Full Mem) +{ + YmmResult = vgf2p8mulb_avx512vl( evexV5_YmmReg, YmmReg2_m256 ); + YmmMask = YmmReg1; + build YmmOpMask8; + ZmmReg1 = zext(YmmResult); +} + +# GF2P8MULB 3-481 PAGE 1051 LINE 56760 +define pcodeop vgf2p8mulb_avx512f ; +:VGF2P8MULB ZmmReg1 ZmmOpMask8, evexV5_ZmmReg, ZmmReg2_m512 is $(EVEX_NONE) & $(EVEX_L512) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & ZmmOpMask8 & evexV5_ZmmReg; byte=0xCF; ZmmReg1 ... & ZmmReg2_m512 +[ evexD8Type = 1; evexTType = 0; ] # (TupleType Full Mem) +{ + ZmmResult = vgf2p8mulb_avx512f( evexV5_ZmmReg, ZmmReg2_m512 ); + ZmmMask = ZmmReg1; + build ZmmOpMask8; + ZmmReg1 = ZmmResult; +} \ No newline at end of file diff --git a/Ghidra/Processors/x86/data/languages/x86.slaspec b/Ghidra/Processors/x86/data/languages/x86.slaspec index 5ec52e50f49..fa0cfe90acf 100644 --- a/Ghidra/Processors/x86/data/languages/x86.slaspec +++ b/Ghidra/Processors/x86/data/languages/x86.slaspec @@ -7,6 +7,7 @@ with : lockprefx=0 { @include "avx2_manual.sinc" @include "avx512.sinc" @include "avx512_manual.sinc" +@include "gfni.sinc" @include "adx.sinc" @include "clwb.sinc" @include "pclmulqdq.sinc" From b3fedff1fb55ef303e2c5b53e4b55ff678af78a1 Mon Sep 17 00:00:00 2001 From: dev747368 <48332326+dev747368@users.noreply.github.com> Date: Wed, 3 Jun 2026 22:03:14 +0000 Subject: [PATCH 004/111] GP-6843 update SymbolUtilities invalidChars logic Addresses PR #9172 --- .../bin/format/elf/ElfSymbolNameUtils.java | 60 +++++++ .../AbstractElfRelocationHandler.java | 9 +- .../app/util/opinion/ElfProgramBuilder.java | 33 +--- .../symbol/SymbolUtilitiesNamingTest.java | 92 ++++++++++ .../ghidra_scripts/VxWorksSymTab_Finder.java | 5 +- .../program/model/symbol/SymbolUtilities.java | 159 +++++++++++++----- 6 files changed, 280 insertions(+), 78 deletions(-) create mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbolNameUtils.java create mode 100644 Ghidra/Features/Base/src/test/java/ghidra/program/model/symbol/SymbolUtilitiesNamingTest.java diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbolNameUtils.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbolNameUtils.java new file mode 100644 index 00000000000..64f138b068f --- /dev/null +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbolNameUtils.java @@ -0,0 +1,60 @@ +/* ### + * 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.util.bin.format.elf; + +import ghidra.program.model.symbol.SymbolUtilities; + +public class ElfSymbolNameUtils { + + /** + * Converts a string with possible invalid characters into a valid symbol string. + *

+ * See {@link #getBadElfSymbolStringCodePointReplacement(int, int)} + * + * @param str symbol string to fix, null ok + * @return original str instance if already valid, otherwise fixed value + */ + public static String replaceInvalidChars(String str) { + return SymbolUtilities.replaceInvalidChars(str, + ElfSymbolNameUtils::getBadElfSymbolStringCodePointReplacement); + } + + /** + * Returns a replacement value for any bad code points found in an Elf symbol string. + * + * @param index index of the bad code point in the original string + * @param cp the bad code point + * @return replacement value to use instead of the bad code point + */ + public static String getBadElfSymbolStringCodePointReplacement(int index, int cp) { + if (cp < 0x20) { + // Format as ^Control character for consistency with readelf + // will range between ^@ .. ^_ (0..31) + return "^%c".formatted('@' + cp); + } + else if (cp == 0x7F) { + // Format as ^? character for consistency with readelf + return "^?"; + } + else if (cp == ' ') { + return "_"; + } + else { + return null; // omit the bad codepoint that caused this callback to be invoked + } + } + +} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/relocation/AbstractElfRelocationHandler.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/relocation/AbstractElfRelocationHandler.java index 0d4b18a7d25..a0d06dd15ac 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/relocation/AbstractElfRelocationHandler.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/relocation/AbstractElfRelocationHandler.java @@ -4,9 +4,9 @@ * 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. @@ -18,8 +18,7 @@ import java.util.HashMap; import java.util.Map; -import ghidra.app.util.bin.format.elf.ElfRelocation; -import ghidra.app.util.bin.format.elf.ElfSymbol; +import ghidra.app.util.bin.format.elf.*; import ghidra.app.util.importer.MessageLog; import ghidra.program.model.address.Address; import ghidra.program.model.listing.BookmarkType; @@ -103,6 +102,7 @@ protected final RelocationResult relocate(ElfRelocationContext elfRelocationCont Address symbolAddr = elfRelocationContext.getSymbolAddress(sym); // may be null long symbolValue = elfRelocationContext.getSymbolValue(sym); String symbolName = elfRelocationContext.getSymbolName(symbolIndex); + symbolName = ElfSymbolNameUtils.replaceInvalidChars(symbolName); int typeId = relocation.getType(); if (typeId == 0) { @@ -170,6 +170,7 @@ protected boolean handleUnresolvedSymbol(ElfRelocationContext elfRelocationCo T type = getRelocationType(typeId); String symbolName = elfRelocationContext.getSymbolName(symbolIndex); + symbolName = ElfSymbolNameUtils.replaceInvalidChars(symbolName); Program program = elfRelocationContext.getProgram(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java index 54d0888fb4a..26f9241a4ad 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java @@ -996,9 +996,7 @@ private void processRelocationTableEntries(ElfRelocationTable relocationTable, int symbolIndex = reloc.getSymbolIndex(); String symbolName = symbolTable != null ? symbolTable.getSymbolName(symbolIndex) : ""; - if (symbolName != null && SymbolUtilities.containsInvalidChars(symbolName)) { - symbolName = getEscapedSymbolName(symbolName); - } + symbolName = ElfSymbolNameUtils.replaceInvalidChars(symbolName); Address baseAddress = relocationSpace.getTruncatedAddress(baseWordOffset, true); @@ -2119,10 +2117,10 @@ else if (!isPrimary && (elfSymbol.isGlobal() || elfSymbol.isWeak())) { isPrimary = (existingSym == null); } - if (SymbolUtilities.containsInvalidChars(name)) { - String escapedName = getEscapedSymbolName(name); - log("Unsupported symbol name has been escaped: \"" + escapedName + "\""); - name = escapedName; + String validatedName = ElfSymbolNameUtils.replaceInvalidChars(name); + if (name != validatedName) { + log("Unsupported symbol name has been escaped: \"" + validatedName + "\""); + name = validatedName; } createSymbol(address, name, isPrimary, elfSymbol.isAbsolute(), null); @@ -2159,27 +2157,6 @@ else if (!isPrimary && (elfSymbol.isGlobal() || elfSymbol.isWeak())) { } } - private String getEscapedSymbolName(String name) { - // Do not preclude use of UTF8 strings - StringBuilder escapedBuf = new StringBuilder(); - name.codePoints().forEach(cp -> { - if (cp < 0x20) { - // Format as ^Control character for consistency with readelf - cp += 0x40; // get ASCII control character, starts with ^@ - escapedBuf.append('^'); - escapedBuf.appendCodePoint(cp); - } - else if (cp == 0x7F) { - // Format as ^? character for consistency with readelf - escapedBuf.append("^?"); - } - else { - // Assume valid code point - escapedBuf.appendCodePoint(cp); - } - }); - return escapedBuf.toString(); - } @Override public void setElfSymbolAddress(ElfSymbol elfSymbol, Address address) { diff --git a/Ghidra/Features/Base/src/test/java/ghidra/program/model/symbol/SymbolUtilitiesNamingTest.java b/Ghidra/Features/Base/src/test/java/ghidra/program/model/symbol/SymbolUtilitiesNamingTest.java new file mode 100644 index 00000000000..483586eff8c --- /dev/null +++ b/Ghidra/Features/Base/src/test/java/ghidra/program/model/symbol/SymbolUtilitiesNamingTest.java @@ -0,0 +1,92 @@ +/* ### + * 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.program.model.symbol; + +import static ghidra.program.model.symbol.SymbolUtilities.*; +import static org.junit.Assert.*; + +import org.junit.Test; + +import ghidra.util.StringUtilities; + +public class SymbolUtilitiesNamingTest { + + @Test + public void testGoodStringObjectPassthru() { + String s = "testsym"; + assertSame(s, replaceInvalidChars(s, OMIT_BAD_CHARS)); + + s = "test sym"; + assertNotSame(s, replaceInvalidChars(s, OMIT_BAD_CHARS)); + } + + @Test + public void testNullString() { + assertNull(replaceInvalidChars(null, OMIT_BAD_CHARS)); + assertNull(SymbolUtilities.replaceInvalidChars(null, true)); + } + + @Test + public void testNullChar() { + assertEquals("testsym", replaceInvalidChars("test\0sym", OMIT_BAD_CHARS)); + assertTrue(SymbolUtilities.isInvalidCodePoint(0)); + } + + @Test + public void testBOMChar() { + assertEquals("testsym", + replaceInvalidChars( + "test" + Character.toString(StringUtilities.UNICODE_BE_BYTE_ORDER_MARK) + "sym", + OMIT_BAD_CHARS)); + } + + @Test + public void testRTLOChar() { + assertEquals("testsym", replaceInvalidChars("test\u202esym", OMIT_BAD_CHARS)); + } + + @Test + public void testBadCharRemoval() { + assertEquals("testsym", replaceInvalidChars("test sym", OMIT_BAD_CHARS)); + assertEquals("testsym", replaceInvalidChars("test\u007fsym", OMIT_BAD_CHARS)); + assertEquals("testsym", replaceInvalidChars("test\tsym", OMIT_BAD_CHARS)); + + assertEquals("test\uaabbsym", replaceInvalidChars("test\uaabbsym", OMIT_BAD_CHARS)); + } + + @Test + public void testBadCharReplaceWithUnderscores() { + assertEquals("test_sym", replaceInvalidChars("test sym", USE_UNDERSCORES)); + assertEquals("test_sym", replaceInvalidChars("test\u007fsym", USE_UNDERSCORES)); + assertEquals("test_sym", replaceInvalidChars("test\tsym", USE_UNDERSCORES)); + } + + @Test + public void testBadCharReplaceWithCustom() { + assertEquals("test_4_sym", + replaceInvalidChars("test sym", (index, cp) -> "_" + index + "_")); + } + + @Test + public void testAsciiRange() { + assertEquals( + "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", + replaceInvalidChars( + "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", + OMIT_BAD_CHARS)); + } + +} diff --git a/Ghidra/Features/GnuDemangler/ghidra_scripts/VxWorksSymTab_Finder.java b/Ghidra/Features/GnuDemangler/ghidra_scripts/VxWorksSymTab_Finder.java index 0ffcf0206ee..49e8f910d58 100644 --- a/Ghidra/Features/GnuDemangler/ghidra_scripts/VxWorksSymTab_Finder.java +++ b/Ghidra/Features/GnuDemangler/ghidra_scripts/VxWorksSymTab_Finder.java @@ -41,8 +41,6 @@ // // @category VxWorks -import java.util.List; - import ghidra.app.cmd.data.CreateDataCmd; import ghidra.app.cmd.disassemble.DisassembleCommand; import ghidra.app.cmd.label.DemanglerCmd; @@ -57,7 +55,6 @@ import ghidra.program.model.listing.*; import ghidra.program.model.mem.MemoryBlock; import ghidra.program.model.symbol.*; -import ghidra.program.model.util.CodeUnitInsertionException; public class VxWorksSymTab_Finder extends GhidraScript { @@ -323,7 +320,7 @@ private boolean isValidSymbolString(Address addr) { return false; } - while (!SymbolUtilities.isInvalidChar((char) _byte) && _byte != 0x00) { + while (_byte != 0x00 && !SymbolUtilities.isInvalidCodePoint(Byte.toUnsignedInt(_byte))) { if (monitor.isCancelled()) { return false; diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolUtilities.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolUtilities.java index 76975364c8a..edc9d5c6fbf 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolUtilities.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolUtilities.java @@ -98,11 +98,6 @@ public class SymbolUtilities { */ public final static String ORDINAL_PREFIX = "Ordinal_"; - /** - * Invalid characters for a symbol name. - */ - public final static char[] INVALIDCHARS = { ' ' }; - private static final Comparator CASE_INSENSITIVE_SYMBOL_NAME_COMPARATOR = (s1, s2) -> { return s1.getName().compareToIgnoreCase(s2.getName()); }; @@ -135,24 +130,23 @@ public static int getOrdinalValue(String symbolName) { } /** - * Check for invalid characters - * (space or unprintable ascii below 0x20) - * in labels. + * Checks a string for invalid characters (control chars, space chars, whitespace chars). * * @param str the string to be checked for invalid characters. - * @return boolean true if no invalid chars + * @return boolean true if the string has invalid chars, false if string is valid */ public static boolean containsInvalidChars(String str) { - int len = str.length(); - for (int i = 0; i < len; i++) { - char c = str.charAt(i); - if (isInvalidChar(c)) { + for (int i = 0; i < str.length();) { + int codePoint = str.codePointAt(i); + if (isInvalidCodePoint(codePoint)) { return true; } + i += Character.charCount(codePoint); } return false; } + /** * Generates a default function name for a given address. * @param addr the entry point of the function. @@ -329,54 +323,135 @@ private static boolean isHexDigit(char c) { } /** - * Returns true if the specified char - * is not valid for use in a symbol name + * Returns true if the specified char is not valid for use in a symbol name. + *

+ * See {@link #isInvalidCodePoint(int)} for better method that uses code points instead of + * chars. + * * @param c the character to be tested as a valid symbol character. - * @return return true if c is an invalid char within a symbol name, else false + * @return boolean true if c is an invalid char within a symbol name, else false */ public static boolean isInvalidChar(char c) { - if (c < ' ') { // non-printable ASCII - return true; - } + return isInvalidCodePoint(c); + } - for (char element : INVALIDCHARS) { - if (c == element) { + /** + * Returns true if the specified code point is not valid for use in a symbol name. + * + * @param cp the code point to be tested as a valid symbol character. + * @return boolean true if the code point is an invalid character within a symbol name, + * else false + */ + public static boolean isInvalidCodePoint(int cp) { + // Invisible / unprintable / whitespace unicode character categories. + // This bad list + the good list in the following comment are an exhaustive list of all + // unicode categories + switch (Character.getType(cp)) { + case Character.SPACE_SEPARATOR: + case Character.COMBINING_SPACING_MARK: + case Character.CONTROL: + case Character.ENCLOSING_MARK: + case Character.FORMAT: + case Character.LINE_SEPARATOR: + case Character.NON_SPACING_MARK: + case Character.PARAGRAPH_SEPARATOR: + case Character.PRIVATE_USE: + case Character.SURROGATE: + case Character.UNASSIGNED: return true; - } + /* + Unicode Character categories that are allowed: + Character.UPPERCASE_LETTER + Character.LOWERCASE_LETTER + Character.TITLECASE_LETTER + Character.MODIFIER_LETTER + Character.OTHER_LETTER + Character.DECIMAL_DIGIT_NUMBER + Character.LETTER_NUMBER + Character.OTHER_NUMBER + Character.DASH_PUNCTUATION + Character.START_PUNCTUATION + Character.END_PUNCTUATION + Character.CONNECTOR_PUNCTUATION + Character.OTHER_PUNCTUATION + Character.MATH_SYMBOL + Character.CURRENCY_SYMBOL + Character.MODIFIER_SYMBOL + Character.OTHER_SYMBOL + Character.INITIAL_QUOTE_PUNCTUATION + Character.FINAL_QUOTE_PUNCTUATION + */ } return false; } /** - * Removes from the given string any invalid characters or replaces - * them with underscores. - * - * For example: - * given "a:b*c", the return value would be "a_b_c" - * - * @param str the string to have invalid chars converted to underscores or removed. - * @param replaceWithUnderscore - true means replace the invalid - * chars with underscore. if false, then just drop the invalid chars - * @return modified string + * Callback functional interface, called by + * {@link SymbolUtilities#replaceInvalidChars(String, BadCharFixupFunc)} when it encounters a + * bad code point that needs addressing. (good characters in a string are NOT sent to + * this method) + */ + public interface BadCharFixupFunc { + String fixBadChar(int origIndex, int badCodePoint); + } + + /** + * BadCharFixupFunc that replaces bad characters with '_' underscores + */ + public static final BadCharFixupFunc USE_UNDERSCORES = (i, cp) -> "_"; + /** + * BadCharFixupFunc that removes bad characters from the string + */ + public static final BadCharFixupFunc OMIT_BAD_CHARS = (i, cp) -> null; + + /** + * Converts a string with possible invalid characters into a valid symbol string. + * + * @param str String to fix, {@code null} ok + * @param replaceWithUnderscore - true means replace the invalid chars with underscores, else + * if false, then just drop the invalid chars + * @return either the original String instance if already valid (or {@code null}), or a new + * string that contains the valid portions of the original with any bad chars removed or + * replaced with underscores. */ public static String replaceInvalidChars(String str, boolean replaceWithUnderscore) { + return replaceInvalidChars(str, replaceWithUnderscore ? USE_UNDERSCORES : OMIT_BAD_CHARS); + } + + /** + * Converts a string with possible invalid characters into a valid symbol string. + * + * @param str String to fix, {@code null} ok + * @param badCharFixup callback that controls how each bad char is fixed. It should return + * a string that should be used in place of the invalid character, or {@code null} if nothing + * should be used. + * @return either the original String instance if already valid (or {@code null}), or a new + * string that contains the valid portions of the original with any fixed-ups as returned by + * the badCharFixup callback. + */ + public static String replaceInvalidChars(String str, BadCharFixupFunc badCharFixup) { if (str == null) { return null; } - int len = str.length(); - StringBuilder buf = new StringBuilder(len); - for (int i = 0; i < len; ++i) { - char c = str.charAt(i); - if (isInvalidChar(c)) { - if (replaceWithUnderscore) { - buf.append(UNDERSCORE); + StringBuilder result = null; + for (int i = 0; i < str.length();) { + int codePoint = str.codePointAt(i); + if (isInvalidCodePoint(codePoint)) { + if (result == null) { + result = new StringBuilder(str.length()); + result.append(str.substring(0, i)); + } + String replacement = badCharFixup.fixBadChar(i, codePoint); + if (replacement != null) { + result.append(replacement); } } - else { - buf.append(c); + else if (result != null) { + result.appendCodePoint(codePoint); } + i += Character.charCount(codePoint); } - return buf.toString(); + return result != null ? result.toString() : str; } /** From 299fb1cc8ca031a556d6d24defbdf0d6437102ad Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Fri, 5 Jun 2026 07:44:02 -0400 Subject: [PATCH 005/111] GP-6885: Fixing potential path traversal in AndroidProjectCreator --- .../ghidra/file/eclipse/AndroidProjectCreator.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/eclipse/AndroidProjectCreator.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/eclipse/AndroidProjectCreator.java index 19249412a9d..b0b34315b0c 100644 --- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/eclipse/AndroidProjectCreator.java +++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/eclipse/AndroidProjectCreator.java @@ -115,8 +115,7 @@ private void createEclipseProjectDirectories() throws IOException { } private void processListing(File outputDirectory, GFileSystem fs, List listing, - TaskMonitor monitor) - throws IOException, CancelledException { + TaskMonitor monitor) throws IOException, CancelledException { for (GFile child : listing) { String childName = child.getName(); @@ -131,6 +130,10 @@ private void processListing(File outputDirectory, GFileSystem fs, List li continue; } File subDir = new File(outputDirectory, childName); + if (!FileUtilities.isPathContainedWithin(outputDirectory, subDir)) { + Msg.error(this, "Skipping directory with path traversal: " + childName); + continue; + } FileUtilities.checkedMkdir(subDir); processListing(subDir, fs, child.getListing(), monitor); continue; @@ -220,6 +223,9 @@ private static File copyFile(ResourceFile inputFile, File outputDirectory, Strin try (InputStream is = inputFile.getInputStream()) { FileUtilities.checkedMkdirs(outputDirectory); File destFile = new File(outputDirectory, outputName); + if (!FileUtilities.isPathContainedWithin(outputDirectory, destFile)) { + throw new IOException("Path traversal detected in entry name: " + outputName); + } monitor.setMessage("Copying [" + inputFile.getName() + "] to Eclipse project..."); FileUtilities.copyStreamToFile(is, destFile, false, monitor); From ff48c3337b6b76f96bad2efcebb26266d71b6db5 Mon Sep 17 00:00:00 2001 From: Dan <46821332+nsadeveloper789@users.noreply.github.com> Date: Fri, 5 Jun 2026 18:01:48 +0000 Subject: [PATCH 006/111] GP-0: Fix ClassSearcherTest. --- .../test/java/ghidra/util/classfinder/ClassSearcherTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/Ghidra/Framework/Generic/src/test/java/ghidra/util/classfinder/ClassSearcherTest.java b/Ghidra/Framework/Generic/src/test/java/ghidra/util/classfinder/ClassSearcherTest.java index e3187136e1a..e32f54fabf6 100644 --- a/Ghidra/Framework/Generic/src/test/java/ghidra/util/classfinder/ClassSearcherTest.java +++ b/Ghidra/Framework/Generic/src/test/java/ghidra/util/classfinder/ClassSearcherTest.java @@ -54,9 +54,7 @@ public void testForNameSafeNoClinit() throws Exception { "ghidra.util.classfinder.ClassSearcherTest$ClassWithStaticInitializerSideEffects", TestSuper.class, getClass().getClassLoader()); assertNotNull(found); - assertEquals(Canary.ALIVE, canary); Constructor constructor = found.getConstructor(); - assertEquals(Canary.ALIVE, canary); TestSuper instance = constructor.newInstance(); assertNotNull(instance); assertEquals(Canary.DEAD, canary); From 4b48e2337ebf74dbd77b1c29422e4eef8fa7cabd Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Fri, 5 Jun 2026 14:12:39 -0400 Subject: [PATCH 007/111] GP-0: Upping patch to 12.1.3 --- Ghidra/application.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ghidra/application.properties b/Ghidra/application.properties index 5b99998751b..badad2cc75e 100644 --- a/Ghidra/application.properties +++ b/Ghidra/application.properties @@ -1,5 +1,5 @@ application.name=Ghidra -application.version=12.1.2 +application.version=12.1.3 application.release.name=DEV application.layout.version=3 application.gradle.min=8.5 From 5194daa9e57a213f233ed122160a101a1131acce Mon Sep 17 00:00:00 2001 From: Daniele Pusceddu Date: Sat, 6 Jun 2026 13:34:24 +0200 Subject: [PATCH 008/111] ARM M-profile: fix mrsipsr ISR_NUMBER mask (0x1f -> 0x1ff) --- Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc b/Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc index 1f6b9f8c49f..18e646f45b8 100644 --- a/Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc +++ b/Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc @@ -2775,7 +2775,7 @@ mrsipsr: "i" is thc0000=1 & Rd0811 { b:1 = isCurrentModePrivileged(); if (!b) goto ; ipsr:4 = getCurrentExceptionNumber(); - Rd0811 = Rd0811 | (ipsr & 0x1f); + Rd0811 = Rd0811 | (ipsr & 0x1ff); } mrsipsr: is thc0000=0 { } From 4f1b1bdefffffbdf4feeadfbc0f32f8da39f33a4 Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Mon, 8 Jun 2026 18:57:31 +0000 Subject: [PATCH 009/111] GP-6937: Fixed x86 Xmmreg2 accessing EVEX registers in non-EVEX --- Ghidra/Processors/x86/data/languages/ia.sinc | 32 ++++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Ghidra/Processors/x86/data/languages/ia.sinc b/Ghidra/Processors/x86/data/languages/ia.sinc index f1a2aec952c..145068474ee 100644 --- a/Ghidra/Processors/x86/data/languages/ia.sinc +++ b/Ghidra/Processors/x86/data/languages/ia.sinc @@ -865,28 +865,28 @@ XmmReg1: xmmreg1 is rexRprefix=0 & xmmreg1 { export XmmReg1: xmmreg1_x is rexRprefix=1 & xmmreg1_x { export xmmreg1_x; } XmmReg1: xmmreg1_r is rexRprefix=0 & evexRp=1 & xmmreg1_r { export xmmreg1_r; } XmmReg1: xmmreg1_rx is rexRprefix=1 & evexRp=1 & xmmreg1_rx { export xmmreg1_rx; } -XmmReg2: xmmreg2 is rexBprefix=0 & xmmreg2 { export xmmreg2; } -XmmReg2: xmmreg2_b is rexBprefix=1 & xmmreg2_b { export xmmreg2_b; } -XmmReg2: xmmreg2_x is rexBprefix=0 & rexXprefix=1 & xmmreg2_x { export xmmreg2_x; } -XmmReg2: xmmreg2_bx is rexBprefix=1 & rexXprefix=1 & xmmreg2_bx { export xmmreg2_bx; } +XmmReg2: xmmreg2 is rexBprefix=0 & xmmreg2 { export xmmreg2; } +XmmReg2: xmmreg2_b is rexBprefix=1 & xmmreg2_b { export xmmreg2_b; } +XmmReg2: xmmreg2_x is vexMode=2 & rexBprefix=0 & rexXprefix=1 & xmmreg2_x { export xmmreg2_x; } +XmmReg2: xmmreg2_bx is vexMode=2 & rexBprefix=1 & rexXprefix=1 & xmmreg2_bx { export xmmreg2_bx; } -YmmReg1: ymmreg1 is rexRprefix=0 & ymmreg1 { export ymmreg1; } -YmmReg1: ymmreg1_x is rexRprefix=1 & ymmreg1_x { export ymmreg1_x; } +YmmReg1: ymmreg1 is rexRprefix=0 & ymmreg1 { export ymmreg1; } +YmmReg1: ymmreg1_x is rexRprefix=1 & ymmreg1_x { export ymmreg1_x; } YmmReg1: ymmreg1_r is rexRprefix=0 & evexRp=1 & ymmreg1_r { export ymmreg1_r; } YmmReg1: ymmreg1_rx is rexRprefix=1 & evexRp=1 & ymmreg1_rx { export ymmreg1_rx; } -YmmReg2: ymmreg2 is rexBprefix=0 & ymmreg2 { export ymmreg2; } -YmmReg2: ymmreg2_b is rexBprefix=1 & ymmreg2_b { export ymmreg2_b; } -YmmReg2: ymmreg2_x is rexBprefix=0 & rexXprefix=1 & ymmreg2_x { export ymmreg2_x; } -YmmReg2: ymmreg2_bx is rexBprefix=1 & rexXprefix=1 & ymmreg2_bx { export ymmreg2_bx; } +YmmReg2: ymmreg2 is rexBprefix=0 & ymmreg2 { export ymmreg2; } +YmmReg2: ymmreg2_b is rexBprefix=1 & ymmreg2_b { export ymmreg2_b; } +YmmReg2: ymmreg2_x is vexMode=2 & rexBprefix=0 & rexXprefix=1 & ymmreg2_x { export ymmreg2_x; } +YmmReg2: ymmreg2_bx is vexMode=2 & rexBprefix=1 & rexXprefix=1 & ymmreg2_bx { export ymmreg2_bx; } -ZmmReg1: zmmreg1 is rexRprefix=0 & zmmreg1 { export zmmreg1; } -ZmmReg1: zmmreg1_x is rexRprefix=1 & zmmreg1_x { export zmmreg1_x; } +ZmmReg1: zmmreg1 is rexRprefix=0 & zmmreg1 { export zmmreg1; } +ZmmReg1: zmmreg1_x is rexRprefix=1 & zmmreg1_x { export zmmreg1_x; } ZmmReg1: zmmreg1_r is rexRprefix=0 & evexRp=1 & zmmreg1_r { export zmmreg1_r; } ZmmReg1: zmmreg1_rx is rexRprefix=1 & evexRp=1 & zmmreg1_rx { export zmmreg1_rx; } -ZmmReg2: zmmreg2 is rexBprefix=0 & zmmreg2 { export zmmreg2; } -ZmmReg2: zmmreg2_b is rexBprefix=1 & zmmreg2_b { export zmmreg2_b; } -ZmmReg2: zmmreg2_x is rexBprefix=0 & rexXprefix=1 & zmmreg2_x { export zmmreg2_x; } -ZmmReg2: zmmreg2_bx is rexBprefix=1 & rexXprefix=1 & zmmreg2_bx { export zmmreg2_bx; } +ZmmReg2: zmmreg2 is rexBprefix=0 & zmmreg2 { export zmmreg2; } +ZmmReg2: zmmreg2_b is rexBprefix=1 & zmmreg2_b { export zmmreg2_b; } +ZmmReg2: zmmreg2_x is vexMode=2 & rexBprefix=0 & rexXprefix=1 & zmmreg2_x { export zmmreg2_x; } +ZmmReg2: zmmreg2_bx is vexMode=2 & rexBprefix=1 & rexXprefix=1 & zmmreg2_bx { export zmmreg2_bx; } Xmm_vsib: xmm_vsib is rexXprefix=0 & xmm_vsib { export xmm_vsib; } Xmm_vsib: xmm_vsib_x is rexXprefix=1 & xmm_vsib_x { export xmm_vsib_x; } From 2c3ca6df4cd24ca0d809a93450b78d9e7ff2ee7a Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Mon, 8 Jun 2026 15:10:05 -0400 Subject: [PATCH 010/111] GP-5780: Added several missing x86 instructions --- Ghidra/Processors/x86/certification.manifest | 2 + .../x86/data/languages/cmpccxadd.sinc | 27 +++ Ghidra/Processors/x86/data/languages/ia.sinc | 211 +++++++++++++++++- Ghidra/Processors/x86/data/languages/rao.sinc | 44 ++++ Ghidra/Processors/x86/data/languages/sgx.sinc | 45 ++++ .../x86/data/languages/x86-64.slaspec | 1 + .../Processors/x86/data/languages/x86.slaspec | 1 + 7 files changed, 324 insertions(+), 7 deletions(-) create mode 100644 Ghidra/Processors/x86/data/languages/cmpccxadd.sinc create mode 100644 Ghidra/Processors/x86/data/languages/rao.sinc diff --git a/Ghidra/Processors/x86/certification.manifest b/Ghidra/Processors/x86/certification.manifest index 71dfe249477..59a9073fab8 100644 --- a/Ghidra/Processors/x86/certification.manifest +++ b/Ghidra/Processors/x86/certification.manifest @@ -22,6 +22,7 @@ data/languages/bmi1.sinc||GHIDRA||||END| data/languages/bmi2.sinc||GHIDRA||||END| data/languages/cet.sinc||GHIDRA||||END| data/languages/clwb.sinc||GHIDRA||||END| +data/languages/cmpccxadd.sinc||GHIDRA||||END| data/languages/fma.sinc||GHIDRA||||END| data/languages/ia.sinc||GHIDRA||||END| data/languages/lockable.sinc||GHIDRA||||END| @@ -61,6 +62,7 @@ data/languages/old/x86smmV2.trans||GHIDRA||||END| data/languages/old/x86smmV3.lang||GHIDRA||||END| data/languages/old/x86smmV3.trans||GHIDRA||||END| data/languages/pclmulqdq.sinc||GHIDRA||||END| +data/languages/rao.sinc||GHIDRA||||END| data/languages/rdrand.sinc||GHIDRA||||END| data/languages/sgx.sinc||GHIDRA||||END| data/languages/sha.sinc||GHIDRA||||END| diff --git a/Ghidra/Processors/x86/data/languages/cmpccxadd.sinc b/Ghidra/Processors/x86/data/languages/cmpccxadd.sinc new file mode 100644 index 00000000000..037ebf7144c --- /dev/null +++ b/Ghidra/Processors/x86/data/languages/cmpccxadd.sinc @@ -0,0 +1,27 @@ +#### +#### CMPccXADD instructions +#### + +@ifdef IA64 +:CMP^cc^"XADD" m32, Reg32, vexVVVV_r32 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_r32 & row=0xe & cc; Reg32 ... & m32 { + local op1 = m32; + local op2 = Reg32; + subflags(op1, op2); + local tmp = op1 - op2; + resultflags(tmp); + build cc; + if (!cc) goto inst_next; + m32 = vexVVVV_r32; +} + +:CMP^cc^"XADD" m64, Reg64, vexVVVV_r64 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64 & row=0xe & cc; Reg64 ... & m64 { + local op1 = m64; + local op2 = Reg64; + subflags(op1, op2); + local tmp = op1 - op2; + resultflags(tmp); + build cc; + if (!cc) goto inst_next; + m64 = vexVVVV_r64; +} +@endif \ No newline at end of file diff --git a/Ghidra/Processors/x86/data/languages/ia.sinc b/Ghidra/Processors/x86/data/languages/ia.sinc index d216d902dcd..234136613c5 100644 --- a/Ghidra/Processors/x86/data/languages/ia.sinc +++ b/Ghidra/Processors/x86/data/languages/ia.sinc @@ -479,6 +479,7 @@ define context contextreg # For example: CRC32 r32, r16 -- 66 F2 OF 38 F1 C8 @define PRE_NO "mandover=0" +@define PRE_NOFX "(mandover=0 | prefix_66=1)" @define PRE_66 "prefix_66=1" @define PRE_F3 "prefix_f3=1" @define PRE_F2 "prefix_f2=1" @@ -2418,6 +2419,7 @@ macro fucompe(val1, val2) { @define VEX_MAP4 "vexMMMMM=4" @define VEX_MAP5 "vexMMMMM=5" @define VEX_MAP6 "vexMMMMM=6" +@define VEX_MAP7 "vexMMMMM=7" # Specification is "WIG", "W0", or "W1". @define VEX_WIG "rexWprefix" @@ -3012,12 +3014,17 @@ with : lockprefx=0 { :CQO is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0x99 { tmp:16 = sext(RAX); RDX = tmp(8); } @endif +define pcodeop cldemote; +:CLDEMOTE m8 is vexMode=0 & $(PRE_NO) & byte=0x0F; byte=0x1C; reg_opcode=0 ... & m8 { + cldemote(m8); +} + define pcodeop clflush; :CLFLUSH m8 is vexMode=0 & mandover=0 & byte=0x0F; byte=0xAE; ( mod != 0b11 & reg_opcode=7 ) ... & m8 { clflush(m8); } -:CLAC is vexMode=0 & byte=0x0F; byte=0x01; byte=0xCA { AC = 0; } +:CLAC is $(PRE_NO) & vexMode=0 & byte=0x0F; byte=0x01; byte=0xCA { AC = 0; } :CLC is vexMode=0 & byte=0xf8 { CF = 0; } :CLD is vexMode=0 & byte=0xfc { DF = 0; } @@ -3312,6 +3319,23 @@ define pcodeop cpuid_brand_part3_info; RDX = rem:8; } @endif +define pcodeop enqcmd; +define pcodeop enqcmds; +macro enqcmdFlags() { + OF = 0; + SF = 0; + AF = 0; + CF = 0; + PF = 0; +} +:ENQCMD Reg32, m512 is $(PRE_F2) & opsize=1 & byte=0x0F; byte=0x38; byte=0xF8; (mod!=3 & Reg32) ... & m512 { ZF = enqcmd(Reg32, m512); enqcmdFlags(); } +:ENQCMDS Reg32, m512 is $(PRE_F3) & opsize=1 & byte=0x0F; byte=0x38; byte=0xF8; (mod!=3 & Reg32) ... & m512 { ZF = enqcmds(Reg32, m512); enqcmdFlags(); } +@ifdef IA64 +:ENQCMD Reg64, m512 is $(LONGMODE_ON) & $(PRE_F2) & opsize=2 & byte=0x0F; byte=0x38; byte=0xF8; (mod!=3 & Reg64) ... & m512 { ZF = enqcmd(Reg64, m512); enqcmdFlags(); } +:ENQCMDS Reg64, m512 is $(LONGMODE_ON) & $(PRE_F3) & opsize=2 & byte=0x0F; byte=0x38; byte=0xF8; (mod!=3 & Reg64) ... & m512 { ZF = enqcmds(Reg64, m512); enqcmdFlags(); } +@endif + + enterFrames: low5 is low5 { tmp:1 = low5; export tmp; } :ENTER imm16,enterFrames is $(LONGMODE_OFF) & vexMode=0 & addrsize=1 & opsize=1 & byte=0xc8; imm16; enterFrames & low5=0x00 { @@ -3544,7 +3568,39 @@ enterFrames: low5 is low5 { tmp:1 = low5; export tmp; } } @endif +#### +#### FRED instructions +#### + +@ifdef IA64 +define pcodeop eretu; +define pcodeop erets; +define pcodeop lkgs; +:ERETU is $(PRE_F3) & byte=0x0F; byte=0x01; byte=0xCA { + eretu(); + pop88(RIP); + tmp:8=0; pop88(tmp); CS=tmp(0)|0x3; + pop88(rflags); + pop88(RSP); + pop88(tmp); SS=tmp(0)|0x3; + return [RIP]; +} + +:ERETS is $(PRE_F2) & byte=0x0F; byte=0x01; byte=0xCA { + erets(); + pop88(RIP); + tmp:8=0; pop88(tmp); # Not used to load CS + pop88(rflags); + pop88(RSP); + pop88(tmp); # Not used to load SS + return [RIP]; +} + +:LKGS rm16 is $(LONGMODE_ON) & $(PRE_F2) & byte=0x0F; byte=0x00; reg_opcode=6 ... & rm16 { + lkgs(rm16); +} +@endif #def IA64 # Informs the 80287 coprocessor of the switch to protected mode, treated as NOP for 80387 and later. # We used to have a pseudo-op, but as this is a legacy instruction which is now explicitly treated @@ -3553,6 +3609,16 @@ enterFrames: low5 is low5 { tmp:1 = low5; export tmp; } :HLT is vexMode=0 & byte=0xf4 { goto inst_start; } +define pcodeop hreset; +:HRESET imm8 is vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x3A; byte=0xF0; byte=0xC0; imm8 { EAX = hreset(imm8:1); } + +@ifdef IA64 +# Indirect Branch History Fence. Treated as a NOP outside of 64-bit mode. +# Used to prevent branch history injection, added as a pseudo-op +define pcodeop ibhf; +:IBHF is $(LONGMODE_ON) & $(PRE_F3) & $(REX_W) & byte=0x0F; byte=0x1E; byte=0xF8 { ibhf(); } +@endif + :IDIV rm8 is vexMode=0 & byte=0xf6; rm8 & reg_opcode=7 ... { rm8ext:2 = sext(rm8); local quotient = AX s/ rm8ext; # DE exception if quotient doesn't fit in AL local rem = AX s% rm8ext; @@ -3692,10 +3758,14 @@ enterFrames: low5 is low5 { tmp:1 = low5; export tmp; } :IRETQ is $(LONGMODE_ON) & vexMode=0 & addrsize=2 & opsize=2 & byte=0xcf { pop88(RIP); tmp:8=0; pop88(tmp); CS=tmp(0); pop88(rflags); return [RIP]; } @endif -:J^cc rel8 is vexMode=0 & row=7 & cc; rel8 { if (cc) goto rel8; } -:J^cc rel16 is $(LONGMODE_OFF) & vexMode=0 & opsize=0 & byte=0xf; row=8 & cc; rel16 { if (cc) goto rel16; } -:J^cc rel32 is vexMode=0 & opsize=1 & byte=0xf; row=8 & cc; rel32 { if (cc) goto rel32; } -:J^cc rel32 is vexMode=0 & opsize=2 & byte=0xf; row=8 & cc; rel32 { if (cc) goto rel32; } +# Use the gcc binutils style for branch hints +bh: ", pn" is segover=1 {} # HWNT Branch Not Taken hint (prefix 2E) +bh: ", pt" is segover=3 {} # HST Branch Taken hint (prefix 3E) +bh: is epsilon {} +:J^cc rel8^bh is vexMode=0 & row=7 & cc & bh; rel8 { if (cc) goto rel8; } +:J^cc rel16^bh is $(LONGMODE_OFF) & vexMode=0 & opsize=0 & byte=0xf & bh; row=8 & cc; rel16 { if (cc) goto rel16; } +:J^cc rel32^bh is vexMode=0 & opsize=1 & byte=0xf & bh; row=8 & cc; rel32 { if (cc) goto rel32; } +:J^cc rel32^bh is vexMode=0 & opsize=2 & byte=0xf & bh; row=8 & cc; rel32 { if (cc) goto rel32; } # The following is vexMode=0 & picked up by the line above. rel32 works for both 32 and 64 bit #@ifdef IA64 #:J^cc rel32 is $(LONGMODE_ON) & vexMode=0 & addrsize=2 & byte=0xf; row=8 & cc; rel32 { if (cc) goto rel32; } @@ -4189,6 +4259,19 @@ define pcodeop swap_bytes; :PAUSE is vexMode=0 & opsize=0 & $(PRE_F3) & byte=0x90 { } :PAUSE is vexMode=0 & opsize=1 & $(PRE_F3) & byte=0x90 { } +@ifdef IA64 +define pcodeop pbndkb; +:PBNDKB is $(LONGMODE_ON) & vexMode=0 & $(PRE_NO) & byte=0x0F; byte=0x01; byte=0xC7 { RAX = pbndkb(RBX, RCX); ZF = (RAX != 0); } +@endif + +# leaf function 2 is the only one that uses RCX, and it is only available in 64-bit +# The instruction description mentions RDX, but no leaf functions use RDX +define pcodeop pconfig; +:PCONFIG is $(LONGMODE_OFF) & vexMode=0 & $(PRE_NO) & byte=0x0F; byte=0x01; byte=0xC5 { EAX = pconfig(EAX, EBX); ZF = (EAX != 0); } +@ifdef IA64 +:PCONFIG is $(LONGMODE_ON) & vexMode=0 & $(PRE_NO) & byte=0x0F; byte=0x01; byte=0xC5 { RAX = pconfig(RAX, RBX, RCX); ZF = (RAX != 0); } +@endif + :POP rm16 is $(LONGMODE_OFF) & vexMode=0 & addrsize=0 & opsize=0 & byte=0x8f; rm16 & reg_opcode=0 ... { local val:2 = 0; pop22(val); build rm16; rm16 = val; } :POP rm16 is $(LONGMODE_OFF) & vexMode=0 & addrsize=1 & opsize=0 & byte=0x8f; rm16 & reg_opcode=0 ... { local val:2 = 0; pop42(val); build rm16; rm16 = val; } :POP rm32 is $(LONGMODE_OFF) & vexMode=0 & addrsize=0 & opsize=1 & byte=0x8f; rm32 & reg_opcode=0 ... { local val:4 = 0; pop24(val); build rm32; rm32 = val; } @@ -4584,6 +4667,10 @@ define pcodeop smm_restore_state; :SCASQ^repe^repetail eseDI8 is $(LONGMODE_ON) & vexMode=0 & repe & repetail & opsize=2 & byte=0xaf & eseDI8 { build repe; build eseDI8; subflags(RAX,eseDI8); local diff=RAX-eseDI8; resultflags(diff); build repetail; } @endif +define pcodeop serialize; +:SERIALIZE is vexMode=0 & $(PRE_NO) & byte=0x0F; byte=0x01; byte=0xE8 { serialize(); } + + :SET^cc rm8 is vexMode=0 & byte=0xf; row=9 & cc; rm8 { rm8 = cc; } # manual is not consistent on operands @@ -4841,6 +4928,33 @@ define pcodeop invalidInstructionException; :UD1 Reg32, rm32 is vexMode=0 & byte=0x0f; byte=0xb9; rm32 & Reg32 ... { local target:$(SIZE) = invalidInstructionException(); goto [target]; } :UD2 is vexMode=0 & byte=0xf; byte=0xb { local target:$(SIZE) = invalidInstructionException(); goto [target]; } +define pcodeop umonitor; +:UMONITOR Rmr16 is vexMode=0 & opsize=0 & $(PRE_F3) & byte=0x0F; byte=0xAE; reg_opcode=6 & mod=3 & Rmr16 { + umonitor(Rmr16); +} + +:UMONITOR Rmr32 is vexMode=0 & opsize=1 & $(PRE_F3) & byte=0x0F; byte=0xAE; reg_opcode=6 & mod=3 & Rmr32 { + umonitor(Rmr32); +} + +@ifdef IA64 +:UMONITOR Rmr64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & $(PRE_F3) & byte=0x0F; byte=0xAE; reg_opcode=6 & mod=3 & Rmr64 { + umonitor(Rmr64); +} +@endif + +define pcodeop umwait; +:UMWAIT Rmr32 is vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0xAE; reg_opcode=6 & mod=3 & Rmr32 { + umwait(Rmr32, EDX, EAX); +} + +define pcodeop tpause; +:TPAUSE Rmr32 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0xAE; reg_opcode=6 & mod=3 & Rmr32 { + tpause(Rmr32, EDX, EAX); +} + + + define pcodeop verr; define pcodeop verw; :VERR rm16 is vexMode=0 & byte=0xf; byte=0x0; rm16 & reg_opcode=4 ... { ZF = verr(); } @@ -4853,7 +4967,7 @@ define pcodeop verw; @ifdef IA64 :VMLOAD RAX is $(LONGMODE_ON) & vexMode=0 & addrsize=2 & byte=0x0f; byte=0x01; byte=0xda & RAX { vmload(RAX); } @endif -:VMMCALL is vexMode=0 & byte=0x0f; byte=0x01; byte=0xd9 { vmmcall(); } +:VMMCALL is $(PRE_NOFX) & vexMode=0 & byte=0x0f; byte=0x01; byte=0xd9 { vmmcall(); } # Limiting the effective address size to 32 and 64 bit. Surely we're not expecting a 16-bit VM address, are we? :VMRUN EAX is vexMode=0 & addrsize=1 & byte=0x0f; byte=0x01; byte=0xd8 & EAX { vmrun(EAX); } @ifdef IA64 @@ -4864,7 +4978,57 @@ define pcodeop verw; @ifdef IA64 :VMSAVE RAX is $(LONGMODE_ON) & vexMode=0 & addrsize=2 & byte=0x0f; byte=0x01; byte=0xdb & RAX { vmsave(RAX); } @endif -# + +@ifdef IA64 + +define pcodeop rmpFlags; + +# rFLAGS bits OF, ZF, AF, PF and SF are set based on return code +macro rmpFlagSet() { + local result:1 = rmpFlags(EAX); + OF = result[0,1]; + ZF = result[1,1]; + AF = result[2,1]; + PF = result[3,1]; + SF = result[4,1]; +} + +# Exit to VMM +define pcodeop vmgexit; +:VMGEXIT is ($(PRE_F2) | $(PRE_F3)) & vexMode=0 & byte=0x0f; byte=0x01; byte=0xd9 { vmgexit(); } + +# Page Smash +define pcodeop psmash; +:PSMASH is $(LONGMODE_ON) & vexMode=0 & $(PRE_F3) & byte=0x0f; byte=0x01; byte=0xff { EAX = psmash(RAX); rmpFlagSet(); } + +# Validate guest page RMP entry +define pcodeop pvalidate; +:PVALIDATE is $(LONGMODE_ON) & vexMode=0 & $(PRE_F2) & byte=0x0f; byte=0x01; byte=0xff { EAX = pvalidate(RAX, RCX, RDX); rmpFlagSet(); } + +# Adjust RMP permissions for guest page +define pcodeop rmpadjust; +:RMPADJUST is $(LONGMODE_ON) & vexMode=0 & $(PRE_F3) & byte=0x0f; byte=0x01; byte=0xfe { EAX = rmpadjust(RAX, RCX, RDX); rmpFlagSet(); } + +# Read the RMP permission mask for a guest page +define pcodeop rmpquery; +:RMPQUERY is $(LONGMODE_ON) & vexMode=0 & $(PRE_F3) & byte=0x0f; byte=0x01; byte=0xfd { EAX = rmpquery(RAX, RDX); rmpFlagSet(); } + +# Read an RMP entry +define pcodeop rmpread; +:RMPREAD is $(LONGMODE_ON) & vexMode=0 & $(PRE_F2) & byte=0x0f; byte=0x01; byte=0xfd { EAX = rmpread(RAX, RCX); rmpFlagSet(); } + +# Check RMP dirty status +define pcodeop rmpchkd; +:RMPCHKD is $(LONGMODE_ON) & vexMode=0 & $(PRE_F3) & byte=0x0f; byte=0x01; byte=0xfc { local result:1 = rmpchkd(RAX, RCX); ZF = result[1,1]; CF = result[2,1]; } + +# RMP Optimization +define pcodeop rmpopt; +:RMPOPT is $(LONGMODE_ON) & vexMode=0 & $(PRE_F2) & byte=0x0f; byte=0x01; byte=0xfc { CF = rmpopt(RAX, RCX); } + +# Write a new RMP entry +define pcodeop rmpupdate; +:RMPUPDATE is $(LONGMODE_ON) & vexMode=0 & $(PRE_F2) & byte=0x0f; byte=0x01; byte=0xfe { EAX = rmpupdate(RAX, RCX); rmpFlagSet(); } +@endif # # Intel hardware assisted virtualization opcodes @@ -4927,6 +5091,23 @@ define pcodeop wrpkru; define pcodeop wrmsr; :WRMSR is vexMode=0 & byte=0xf; byte=0x30 { tmp:8 = (zext(EDX) << 32) | zext(EAX); wrmsr(ECX,tmp); } + +@ifdef IA64 +define pcodeop urdmsr; +define pcodeop uwrmsr; +:URDMSR Rmr64, Reg64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x38; byte=0xF8; mod=3 & Reg64 & Rmr64 { Rmr64 = urdmsr(Reg64); } +:URDMSR Rmr64, imm32 is $(LONGMODE_ON) & $(VEX_L128) & $(PRE_F2) & $(VEX_MAP7) & $(VEX_W0) & byte=0xF8; mod=3 & reg_opcode=0 & Rmr64; imm32 { Rmr64 = urdmsr(imm32:4); } +:UWRMSR Reg64, Rmr64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x38; byte=0xF8; mod=3 & Reg64 & Rmr64 { Rmr64 = uwrmsr(Reg64, Rmr64); } +:UWRMSR imm32, Rmr64 is $(LONGMODE_ON) & $(VEX_L128) & $(PRE_F3) & $(VEX_MAP7) & $(VEX_W0) & byte=0xF8; mod=3 & reg_opcode=0 & Rmr64; imm32 { uwrmsr(imm32:4, Rmr64); } + +define pcodeop rdmsrlist; +define pcodeop wrmsrlist; +define pcodeop wrmsrns; +:RDMSRLIST is $(LONGMODE_ON) & vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x01; byte=0xC6 { rdmsrlist(RCX, RDI, RSI); } +:WRMSRLIST is $(LONGMODE_ON) & vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x01; byte=0xC6 { wrmsrlist(RCX, RDI, RSI); } +:WRMSRNS is $(LONGMODE_ON) & vexMode=0 & $(PRE_NO) & byte=0x0F; byte=0x01; byte=0xC6 { tmp:8 = (zext(EDX) << 32) | zext(EAX); wrmsrns(ECX,tmp); } +@endif + # See 'lockable.sinc' for memory destination, lockable variants :XADD Rmr8,Reg8 is vexMode=0 & byte=0x0F; byte=0xC0; mod=3 & Rmr8 & Reg8 { addflags( Rmr8,Reg8 ); local tmp = Rmr8 + Reg8; Reg8 = Rmr8; Rmr8 = tmp; resultflags(tmp); } :XADD Rmr16,Reg16 is vexMode=0 & opsize=0 & byte=0x0F; byte=0xC1; mod=3 & Rmr16 & Reg16 { addflags(Rmr16,Reg16); local tmp = Rmr16 + Reg16; Reg16 = Rmr16; Rmr16 = tmp; resultflags(tmp); } @@ -5051,6 +5232,7 @@ define pcodeop xtest; :MFENCE is vexMode=0 & $(PRE_NO) & byte=0x0F; byte=0xAE; mod = 0b11 & reg_opcode=6 & r_m=0 { } :SFENCE is vexMode=0 & $(PRE_NO) & byte=0x0F; byte=0xAE; mod = 0b11 & reg_opcode=7 & r_m=0 { } + # # floating point instructions # @@ -9605,6 +9787,18 @@ define pcodeop rsqrtss; :RSQRTSS XmmReg, m32 is vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x52; XmmReg ... & m32 { XmmReg = rsqrtss(XmmReg, m32); } :RSQRTSS XmmReg1, XmmReg2 is vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x52; xmmmod = 3 & XmmReg1 & XmmReg2 { XmmReg1 = rsqrtss(XmmReg1, XmmReg2); } +@ifdef IA64 +define pcodeop senduipi; +define pcodeop testui; +define pcodeop setui; +define pcodeop clearui; +:SENDUIPI Rmr64 is $(LONGMODE_ON) & $(PRE_F3) & byte=0x0F; byte=0xC7; mod=3 & reg_opcode=0x6 & Rmr64 { senduipi(Rmr64); } +:TESTUI is $(LONGMODE_ON) & $(PRE_F3) & byte=0x0F; byte=0x01; byte=0xED { CF = testui(); } +:UIRET is $(LONGMODE_ON) & $(PRE_F3) & byte=0x0F; byte=0x01; byte=0xEC { pop88(RIP); pop88(rflags); pop88(RSP); unpackflags(rflags); unpackeflags(rflags); setui(); return [RIP]; } +:CLUI is $(LONGMODE_ON) & $(PRE_F3) & byte=0x0F; byte=0x01; byte=0xEE { clearui(); } +:STUI is $(LONGMODE_ON) & $(PRE_F3) & byte=0x0F; byte=0x01; byte=0xEF { setui(); } +@endif + :SHUFPD XmmReg1, XmmReg2_m128, imm8 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0xC6; XmmReg1 ... & XmmReg2_m128; imm8 { local srcLow:8 = XmmReg2_m128[0,64]; @@ -10499,4 +10693,7 @@ lsbOffset: val is imm8 [ val=imm8 & 0x3f; ] { export *[const]:1 val; } :MOVNTSS m32, XmmReg1 is vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x2B; XmmReg1 ... & m32 { m32 = XmmReg1[0,32]; } + + + } # end with : lockprefx=0 diff --git a/Ghidra/Processors/x86/data/languages/rao.sinc b/Ghidra/Processors/x86/data/languages/rao.sinc new file mode 100644 index 00000000000..ed804bfdec1 --- /dev/null +++ b/Ghidra/Processors/x86/data/languages/rao.sinc @@ -0,0 +1,44 @@ +#### +#### RAO-INT instructions +#### + +:AADD m32,Reg32 is vexMode=0 & rexprefix=0 & $(PRE_NO) & byte=0x0F; byte=0x38; byte=0xFC; Reg32 ... & m32 { + m32 = m32 + Reg32; +} + +@ifdef IA64 +:AADD m64,Reg64 is $(REX_W) & $(PRE_NO) & byte=0x0F; byte=0x38; byte=0xFC; Reg64 ... & m64 { + m64 = m64 + Reg64; +} +@endif + +:AAND m32,Reg32 is vexMode=0 & rexprefix=0 & $(PRE_66) & byte=0x0F; byte=0x38; byte=0xFC; Reg32 ... & m32 { + m32 = m32 & Reg32; +} + +@ifdef IA64 +:AAND m64,Reg64 is $(REX_W) & $(PRE_66) & byte=0x0F; byte=0x38; byte=0xFC; Reg64 ... & m64 { + m64 = m64 & Reg64; +} +@endif + +:AOR m32,Reg32 is vexMode=0 & rexprefix=0 & $(PRE_F2) & byte=0x0F; byte=0x38; byte=0xFC; Reg32 ... & m32 { + m32 = m32 | Reg32; +} + +@ifdef IA64 +:AOR m64,Reg64 is $(REX_W) & $(PRE_F2) & byte=0x0F; byte=0x38; byte=0xFC; Reg64 ... & m64 { + m64 = m64 | Reg64; +} +@endif + +:AXOR m32,Reg32 is vexMode=0 & rexprefix=0 & $(PRE_F3) & byte=0x0F; byte=0x38; byte=0xFC; Reg32 ... & m32 { + m32 = m32 ^ Reg32; +} + +@ifdef IA64 +:AXOR m64,Reg64 is $(REX_W) & $(PRE_F3) & byte=0x0F; byte=0x38; byte=0xFC; Reg64 ... & m64 { + m64 = m64 ^ Reg64; +} +@endif + diff --git a/Ghidra/Processors/x86/data/languages/sgx.sinc b/Ghidra/Processors/x86/data/languages/sgx.sinc index 9c124e14e2d..54812ed3e29 100644 --- a/Ghidra/Processors/x86/data/languages/sgx.sinc +++ b/Ghidra/Processors/x86/data/languages/sgx.sinc @@ -255,3 +255,48 @@ define pcodeop enclu_unknown; } + +define pcodeop enclv_edecvirtchild; +define pcodeop enclv_eincvirtchild; +define pcodeop enclv_esetcontext; +define pcodeop enclv_unknown; + +:ENCLV is vexMode=0 & byte=0x0f; byte=0x01; byte=0xc0 { + + if ( EAX != 0x0 ) goto ; + RAX = enclv_edecvirtchild( RBX, RCX ); + ZF = (RAX != 0); + CF = 0; + PF = 0; + AF = 0; + OF = 0; + SF = 0; + goto ; + + + if ( EAX != 0x1 ) goto ; + RAX = enclv_eincvirtchild( RBX, RCX ); + ZF = (RAX != 0); + CF = 0; + PF = 0; + AF = 0; + OF = 0; + SF = 0; + goto ; + + + if ( EAX != 0x2 ) goto ; + RAX = enclv_esetcontext( RCX, RDX ); + ZF = (RAX != 0); + CF = 0; + PF = 0; + AF = 0; + OF = 0; + SF = 0; + goto ; + + enclv_unknown(); + + + +} diff --git a/Ghidra/Processors/x86/data/languages/x86-64.slaspec b/Ghidra/Processors/x86/data/languages/x86-64.slaspec index 8b442ec169a..a682d8aa5d7 100644 --- a/Ghidra/Processors/x86/data/languages/x86-64.slaspec +++ b/Ghidra/Processors/x86/data/languages/x86-64.slaspec @@ -3,4 +3,5 @@ with : lockprefx=0 { @include "sgx.sinc" @include "fma.sinc" +@include "cmpccxadd.sinc" } diff --git a/Ghidra/Processors/x86/data/languages/x86.slaspec b/Ghidra/Processors/x86/data/languages/x86.slaspec index 5ec52e50f49..43087715257 100644 --- a/Ghidra/Processors/x86/data/languages/x86.slaspec +++ b/Ghidra/Processors/x86/data/languages/x86.slaspec @@ -18,4 +18,5 @@ with : lockprefx=0 { @include "smx.sinc" @include "cet.sinc" @include "rdrand.sinc" +@include "rao.sinc" } From 21a825a05d7a24848a36758861898abaad9a1ca5 Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Mon, 8 Jun 2026 15:11:29 -0400 Subject: [PATCH 011/111] GP-6642: Corrected disassembly of HCS-H12 BRN instruction --- Ghidra/Processors/HCS12/data/languages/HCS_HC12.sinc | 6 ++---- .../plugin/core/analysis/HCS12ConventionAnalyzer.java | 11 ++++++----- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Ghidra/Processors/HCS12/data/languages/HCS_HC12.sinc b/Ghidra/Processors/HCS12/data/languages/HCS_HC12.sinc index 26ff2c0eaa6..646d9d4eca4 100644 --- a/Ghidra/Processors/HCS12/data/languages/HCS_HC12.sinc +++ b/Ghidra/Processors/HCS12/data/languages/HCS_HC12.sinc @@ -271,7 +271,7 @@ macro setHCSphysPage(addr) { (zext(isPpage) * (0x400000 | ((zext(PPAGE) << 14 ) ^ 0x8000))) + (zext(isPpage_FF) * (0x400000 | ((0x3FC000) ^ 0xC000))) ; } -@elif defined(HCS12) && SIZE=="3" +@elif defined(HCS12) && SIZE=="3" macro setHCSphysPage(addr) { local a3:3 = zext(addr); @@ -1961,11 +1961,9 @@ with : XGATE=0 { } # branch never is a two-byte nop -SkipNextInstr: dest is epsilon [ dest = inst_next + 1; ] { export *[RAM]:1 dest; } -:BRN SkipNextInstr is Prefix18=0 & op8=0x21 & SkipNextInstr +:BRN rel8 is Prefix18=0 & op8=0x21; rel8 { - goto SkipNextInstr; } :BRSET opr8a_8, msk8, rel8 is Prefix18=0 & op8=0x4E; opr8a_8; msk8; rel8 diff --git a/Ghidra/Processors/HCS12/src/main/java/ghidra/app/plugin/core/analysis/HCS12ConventionAnalyzer.java b/Ghidra/Processors/HCS12/src/main/java/ghidra/app/plugin/core/analysis/HCS12ConventionAnalyzer.java index b2c0f2f61ad..79d649fd1fc 100644 --- a/Ghidra/Processors/HCS12/src/main/java/ghidra/app/plugin/core/analysis/HCS12ConventionAnalyzer.java +++ b/Ghidra/Processors/HCS12/src/main/java/ghidra/app/plugin/core/analysis/HCS12ConventionAnalyzer.java @@ -4,9 +4,9 @@ * 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. @@ -53,8 +53,8 @@ public HCS12ConventionAnalyzer() { public boolean canAnalyze(Program program) { // Only analyze HCS12 Programs Processor processor = program.getLanguage().getProcessor(); - - boolean canDo = processor.equals(Processor.findOrPossiblyCreateProcessor("HCS12")); + String procName = processor.toString(); + boolean canDo = "HCS-12".equals(procName) || "HCS-12X".equals(procName); if (canDo) { xgate = program.getRegister("XGATE"); } @@ -63,12 +63,13 @@ public boolean canAnalyze(Program program) { } void checkReturn(Program program, Instruction instr) { - String mnemonic = instr.getMnemonicString().toLowerCase(); if (instr == null || !instr.getFlowType().isTerminal()) { return; } + String mnemonic = instr.getMnemonicString().toLowerCase(); + // if XGATE set on instruction is XGATE RegisterValue xgateValue = program.getProgramContext().getRegisterValue(xgate, instr.getMinAddress()); if (xgateValue != null && xgateValue.hasValue() && xgateValue.getUnsignedValue().equals(BigInteger.ONE)) { From 1de7de83e4e1987f46d9e4fce0ab45e1e17c907a Mon Sep 17 00:00:00 2001 From: Daniel Lehmann Date: Wed, 29 May 2024 23:19:58 -0700 Subject: [PATCH 012/111] Fix input register for msr apsr The msr instruction get the output register from the second 16-bit word, but it must come out of the first 16-bit word. This patch fixes the decoding. --- .../ARM/data/languages/ARMTHUMBinstructions.sinc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc b/Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc index 1f6b9f8c49f..d1f9c2d0879 100644 --- a/Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc +++ b/Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc @@ -2931,12 +2931,12 @@ define pcodeop getProcessStackPointerLimit; @if defined(VERSION_7M) -msripsr: "i" is thc0000=1 { } -msripsr: is thc0000=0 { } -msrepsr: "e" is thc0101=1 { } -msrepsr: is thc0101=0 { } -msrapsr: is thc0202=1 { } -msrapsr: "a" is thc0202=0 & Rn0003 { +msripsr: "i" is Rn0003; thc0000=1 { } +msripsr: is Rn0003; thc0000=0 { } +msrepsr: "e" is Rn0003; thc0101=1 { } +msrepsr: is Rn0003; thc0101=0 { } +msrapsr: is Rn0003; thc0202=1 { } +msrapsr: "a" is Rn0003; thc0202=0 { cpsr = cpsr | (Rn0003 & 0xf8000000); writeAPSR_nzcvq(cpsr); } @@ -2944,11 +2944,11 @@ msrapsr: "a" is thc0202=0 & Rn0003 { msrpsr: msripsr^msrepsr^msrapsr^"psr" is msripsr & msrepsr & msrapsr { build msrapsr; } -msrpsr: "xpsr" is sysm02=3 & msrapsr { +msrpsr: "xpsr" is (Rn0003 ; sysm02=3) & msrapsr { build msrapsr; } -:msr^ItCond msrpsr,Rn0003 is TMode=1 & ItCond & op4=0xf38 & Rn0003; op12=0x8 & th_psrmask=8 & sysm37=0 & msrpsr +:msr^ItCond msrpsr,Rn0003 is TMode=1 & ItCond & (op4=0xf38 & Rn0003; op12=0x8 & th_psrmask=8 & sysm37=0) & msrpsr { build ItCond; build msrpsr; From 120207872b5c4e94734f1b8c070d2eb162e363f1 Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Tue, 9 Jun 2026 11:26:02 -0400 Subject: [PATCH 013/111] GP-0 Corrected invalid test random string generation --- .../Generic/src/main/java/generic/test/AbstractGTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ghidra/Framework/Generic/src/main/java/generic/test/AbstractGTest.java b/Ghidra/Framework/Generic/src/main/java/generic/test/AbstractGTest.java index a8ca9b9b8cc..3d54c7a9ea1 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/test/AbstractGTest.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/test/AbstractGTest.java @@ -172,7 +172,7 @@ public static String getRandomString(int min, int max) { int stringLength = getRandomInt(min, max); StringBuilder buffy = new StringBuilder(); for (int i = 0; i < stringLength; i++) { - buffy.append((char) getRandomInt(65, 127)); + buffy.append((char) getRandomInt(65, 126)); } return buffy.toString(); } From 718d9a05a305a745cb14da8e961f8ac7e877c7b6 Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Tue, 9 Jun 2026 11:41:38 -0400 Subject: [PATCH 014/111] GP-0 Ignore test failure which is resolved for 12.2 --- .../app/decompiler/component/DecompilerClangTest.java | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/Ghidra/Features/Decompiler/src/test.slow/java/ghidra/app/decompiler/component/DecompilerClangTest.java b/Ghidra/Features/Decompiler/src/test.slow/java/ghidra/app/decompiler/component/DecompilerClangTest.java index 900f4106b61..0b7f43f6020 100644 --- a/Ghidra/Features/Decompiler/src/test.slow/java/ghidra/app/decompiler/component/DecompilerClangTest.java +++ b/Ghidra/Features/Decompiler/src/test.slow/java/ghidra/app/decompiler/component/DecompilerClangTest.java @@ -26,8 +26,7 @@ import javax.swing.*; -import org.junit.Before; -import org.junit.Test; +import org.junit.*; import docking.action.DockingActionIf; import docking.options.OptionsService; @@ -44,7 +43,6 @@ import ghidra.app.plugin.core.decompile.DecompilerProvider; import ghidra.app.plugin.core.decompile.actions.*; import ghidra.app.util.AddEditDialog; -import ghidra.framework.Application; import ghidra.framework.options.ToolOptions; import ghidra.program.model.listing.CommentType; import ghidra.program.model.listing.Function; @@ -958,6 +956,7 @@ public void testSecondaryHighlighting_MiddleMouseDoesNotClearSecondaryHighlight_ } @Test + @Ignore("Resolved for 12.2") public void testSecondaryHighlighting_CloneDecompiler() { /* @@ -979,12 +978,6 @@ public void testSecondaryHighlighting_CloneDecompiler() { */ - // TODO temp workaround; delete when 12.2 is released - String version = Application.getApplicationVersion(); - if ("12.1".equals(version)) { - return; - } - decompile("100000d60"); // '_call_structure_A' // 5:2 "_printf" From a3167f7bd774f6482e193dcffebf72d6adccf1bf Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Tue, 9 Jun 2026 15:53:44 +0000 Subject: [PATCH 015/111] GP-0: Refactor x86 jcc bh change to reduce impact on existing code --- Ghidra/Processors/x86/data/languages/ia.sinc | 25 +++++++++++++------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/Ghidra/Processors/x86/data/languages/ia.sinc b/Ghidra/Processors/x86/data/languages/ia.sinc index 4517dee68f4..fdf3ea0e3a3 100644 --- a/Ghidra/Processors/x86/data/languages/ia.sinc +++ b/Ghidra/Processors/x86/data/languages/ia.sinc @@ -3766,14 +3766,23 @@ define pcodeop ibhf; :IRETQ is $(LONGMODE_ON) & vexMode=0 & addrsize=2 & opsize=2 & byte=0xcf { pop88(RIP); tmp:8=0; pop88(tmp); CS=tmp(0); pop88(rflags); return [RIP]; } @endif -# Use the gcc binutils style for branch hints -bh: ", pn" is segover=1 {} # HWNT Branch Not Taken hint (prefix 2E) -bh: ", pt" is segover=3 {} # HST Branch Taken hint (prefix 3E) -bh: is epsilon {} -:J^cc rel8^bh is vexMode=0 & row=7 & cc & bh; rel8 { if (cc) goto rel8; } -:J^cc rel16^bh is $(LONGMODE_OFF) & vexMode=0 & opsize=0 & byte=0xf & bh; row=8 & cc; rel16 { if (cc) goto rel16; } -:J^cc rel32^bh is vexMode=0 & opsize=1 & byte=0xf & bh; row=8 & cc; rel32 { if (cc) goto rel32; } -:J^cc rel32^bh is vexMode=0 & opsize=2 & byte=0xf & bh; row=8 & cc; rel32 { if (cc) goto rel32; } +# HWNT Branch Not Taken hint (prefix 2E) +# HST Branch Taken hint (prefix 3E) +jccRel8: rel8 is rel8 { export rel8; } +jccRel8: rel8, "bn" is segover=1 & rel8 { export rel8; } +jccRel8: rel8, "bt" is segover=3 & rel8 { export rel8; } +jccRel16: rel16 is rel16 { export rel16; } +jccRel16: rel16, "bn" is segover=1 & rel16 { export rel16; } +jccRel16: rel16, "bt" is segover=3 & rel16 { export rel16; } +jccRel32: rel32 is rel32 { export rel32; } +jccRel32: rel32, "bn" is segover=1 & rel32 { export rel32; } +jccRel32: rel32, "bt" is segover=3 & rel32 { export rel32; } + +:J^cc jccRel8 is vexMode=0 & row=7 & cc; jccRel8 { if (cc) goto jccRel8; } +:J^cc jccRel16 is $(LONGMODE_OFF) & vexMode=0 & opsize=0 & byte=0xf; row=8 & cc; jccRel16 { if (cc) goto jccRel16; } +:J^cc jccRel32 is vexMode=0 & opsize=1 & byte=0xf; row=8 & cc; jccRel32 { if (cc) goto jccRel32; } +:J^cc jccRel32 is vexMode=0 & opsize=2 & byte=0xf; row=8 & cc; jccRel32 { if (cc) goto jccRel32; } + # The following is vexMode=0 & picked up by the line above. rel32 works for both 32 and 64 bit #@ifdef IA64 #:J^cc rel32 is $(LONGMODE_ON) & vexMode=0 & addrsize=2 & byte=0xf; row=8 & cc; rel32 { if (cc) goto rel32; } From 70b7ec590ad646ebe767e099a88309fad37035cc Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Wed, 10 Jun 2026 07:25:22 -0400 Subject: [PATCH 016/111] GP-6061: Implemented several x86 AVX instructions --- Ghidra/Processors/x86/data/languages/avx.sinc | 165 ++- .../Processors/x86/data/languages/avx2.sinc | 84 +- .../x86/data/languages/avx2_manual.sinc | 20 +- .../Processors/x86/data/languages/avx512.sinc | 120 +- .../x86/data/languages/avx512_manual.sinc | 63 +- .../x86/data/languages/avx_manual.sinc | 30 + Ghidra/Processors/x86/data/languages/fma.sinc | 1005 ++++++++++------- 7 files changed, 931 insertions(+), 556 deletions(-) diff --git a/Ghidra/Processors/x86/data/languages/avx.sinc b/Ghidra/Processors/x86/data/languages/avx.sinc index 6184fd39ac3..962aee4b1c3 100644 --- a/Ghidra/Processors/x86/data/languages/avx.sinc +++ b/Ghidra/Processors/x86/data/languages/avx.sinc @@ -95,63 +95,97 @@ define pcodeop vaddsubps_avx ; } # ANDPD 3-64 PAGE 634 LINE 34821 -define pcodeop vandpd_avx ; :VANDPD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & vexVVVV_XmmReg; byte=0x54; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vandpd_avx( vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + local m:16 = XmmReg2_m128; + XmmReg1[0,64] = vexVVVV_XmmReg[0,64] & m[0,64]; + XmmReg1[64,64] = vexVVVV_XmmReg[64,64] & m[64,64]; + ZmmReg1 = zext(XmmReg1); } # ANDPD 3-64 PAGE 634 LINE 34824 :VANDPD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_NDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F) & vexVVVV_YmmReg; byte=0x54; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:32 = vandpd_avx( vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + local m:32 = YmmReg2_m256; + YmmReg1[0,64] = vexVVVV_YmmReg[0,64] & m[0,64]; + YmmReg1[64,64] = vexVVVV_YmmReg[64,64] & m[64,64]; + YmmReg1[128,64] = vexVVVV_YmmReg[128,64] & m[128,64]; + YmmReg1[192,64] = vexVVVV_YmmReg[192,64] & m[192,64]; + ZmmReg1 = zext(YmmReg1); } # ANDPS 3-67 PAGE 637 LINE 34947 -define pcodeop vandps_avx ; :VANDPS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_NONE) & $(VEX_0F) & vexVVVV_XmmReg; byte=0x54; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vandps_avx( vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + local tmp:16 = XmmReg2_m128; + XmmReg1[0,32] = vexVVVV_XmmReg[0,32] & tmp[0,32]; + XmmReg1[32,32] = vexVVVV_XmmReg[32,32] & tmp[32,32]; + XmmReg1[64,32] = vexVVVV_XmmReg[64,32] & tmp[64,32]; + XmmReg1[96,32] = vexVVVV_XmmReg[96,32] & tmp[96,32]; + ZmmReg1 = zext(XmmReg1); } # ANDPS 3-67 PAGE 637 LINE 34950 :VANDPS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_NDS) & $(VEX_L256) & $(VEX_PRE_NONE) & $(VEX_0F) & vexVVVV_YmmReg; byte=0x54; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:32 = vandps_avx( vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + local tmp:32 = YmmReg2_m256; + YmmReg1[0,32] = vexVVVV_YmmReg[0,32] & tmp[0,32]; + YmmReg1[32,32] = vexVVVV_YmmReg[32,32] & tmp[32,32]; + YmmReg1[64,32] = vexVVVV_YmmReg[64,32] & tmp[64,32]; + YmmReg1[96,32] = vexVVVV_YmmReg[96,32] & tmp[96,32]; + YmmReg1[128,32] = vexVVVV_YmmReg[128,32] & tmp[128,32]; + YmmReg1[160,32] = vexVVVV_YmmReg[160,32] & tmp[160,32]; + YmmReg1[192,32] = vexVVVV_YmmReg[192,32] & tmp[192,32]; + YmmReg1[224,32] = vexVVVV_YmmReg[224,32] & tmp[224,32]; + + ZmmReg1 = zext(YmmReg1); } # ANDNPD 3-70 PAGE 640 LINE 35081 -define pcodeop vandnpd_avx ; :VANDNPD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & vexVVVV_XmmReg; byte=0x55; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vandnpd_avx( vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + local m:16 = XmmReg2_m128; + XmmReg1[0,64] = ~vexVVVV_XmmReg[0,64] & m[0,64]; + XmmReg1[64,64] = ~vexVVVV_XmmReg[64,64] & m[64,64]; + ZmmReg1 = zext(XmmReg1); } # ANDNPD 3-70 PAGE 640 LINE 35084 :VANDNPD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_NDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F) & vexVVVV_YmmReg; byte=0x55; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:32 = vandnpd_avx( vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + local m:32 = YmmReg2_m256; + YmmReg1[0,64] = ~vexVVVV_YmmReg[0,64] & m[0,64]; + YmmReg1[64,64] = ~vexVVVV_YmmReg[64,64] & m[64,64]; + YmmReg1[128,64] = ~vexVVVV_YmmReg[128,64] & m[128,64]; + YmmReg1[192,64] = ~vexVVVV_YmmReg[192,64] & m[192,64]; + ZmmReg1 = zext(YmmReg1); } # ANDNPS 3-73 PAGE 643 LINE 35207 define pcodeop vandnps_avx ; :VANDNPS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_NONE) & $(VEX_0F) & vexVVVV_XmmReg; byte=0x55; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vandnps_avx( vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + local tmp:16 = XmmReg2_m128; + XmmReg1[0,32] = ~vexVVVV_XmmReg[0,32] & tmp[0,32]; + XmmReg1[32,32] = ~vexVVVV_XmmReg[32,32] & tmp[32,32]; + XmmReg1[64,32] = ~vexVVVV_XmmReg[64,32] & tmp[64,32]; + XmmReg1[96,32] = ~vexVVVV_XmmReg[96,32] & tmp[96,32]; + ZmmReg1 = zext(XmmReg1); } # ANDNPS 3-73 PAGE 643 LINE 35210 :VANDNPS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_NDS) & $(VEX_L256) & $(VEX_PRE_NONE) & $(VEX_0F) & vexVVVV_YmmReg; byte=0x55; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:32 = vandnps_avx( vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + local tmp:32 = YmmReg2_m256; + YmmReg1[0,32] = ~vexVVVV_YmmReg[0,32] & tmp[0,32]; + YmmReg1[32,32] = ~vexVVVV_YmmReg[32,32] & tmp[32,32]; + YmmReg1[64,32] = ~vexVVVV_YmmReg[64,32] & tmp[64,32]; + YmmReg1[96,32] = ~vexVVVV_YmmReg[96,32] & tmp[96,32]; + YmmReg1[128,32] = ~vexVVVV_YmmReg[128,32] & tmp[128,32]; + YmmReg1[160,32] = ~vexVVVV_YmmReg[160,32] & tmp[160,32]; + YmmReg1[192,32] = ~vexVVVV_YmmReg[192,32] & tmp[192,32]; + YmmReg1[224,32] = ~vexVVVV_YmmReg[224,32] & tmp[224,32]; + ZmmReg1 = zext(YmmReg1); } # BLENDPD 3-78 PAGE 648 LINE 35433 @@ -1475,30 +1509,30 @@ define pcodeop vmpsadbw_avx ; define pcodeop vorpd_avx ; :VORPD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & vexVVVV_XmmReg; byte=0x56; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vorpd_avx( vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + XmmReg1 = vexVVVV_XmmReg | XmmReg2_m128; + ZmmReg1 = zext(XmmReg1); } # ORPD 4-168 PAGE 1288 LINE 66722 :VORPD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_NDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F) & vexVVVV_YmmReg; byte=0x56; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:32 = vorpd_avx( vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + YmmReg1 = vexVVVV_YmmReg | YmmReg2_m256; + ZmmReg1 = zext(YmmReg1); } # ORPS 4-171 PAGE 1291 LINE 66846 define pcodeop vorps_avx ; :VORPS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_NONE) & $(VEX_0F) & vexVVVV_XmmReg; byte=0x56; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vorps_avx( vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + XmmReg1 = vexVVVV_XmmReg | XmmReg2_m128; + ZmmReg1 = zext(XmmReg1); } # ORPS 4-171 PAGE 1291 LINE 66848 :VORPS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_NDS) & $(VEX_L256) & $(VEX_PRE_NONE) & $(VEX_0F) & vexVVVV_YmmReg; byte=0x56; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:32 = vorps_avx( vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + YmmReg1 = vexVVVV_YmmReg | YmmReg2_m256; + ZmmReg1 = zext(YmmReg1); } # PABSB/PABSW/PABSD/PABSQ 4-180 PAGE 1300 LINE 67302 @@ -1561,24 +1595,53 @@ define pcodeop vpackuswb_avx ; define pcodeop vpaddb_avx ; :VPADDB XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG) & vexVVVV_XmmReg; byte=0xFC; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vpaddb_avx( vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + local result:16 = 0; + result[0,8] = vexVVVV_XmmReg[0,8] + XmmReg2_m128[0,8]; + result[8,8] = vexVVVV_XmmReg[8,8] + XmmReg2_m128[8,8]; + result[16,8] = vexVVVV_XmmReg[16,8] + XmmReg2_m128[16,8]; + result[24,8] = vexVVVV_XmmReg[24,8] + XmmReg2_m128[24,8]; + result[32,8] = vexVVVV_XmmReg[32,8] + XmmReg2_m128[32,8]; + result[40,8] = vexVVVV_XmmReg[40,8] + XmmReg2_m128[40,8]; + result[48,8] = vexVVVV_XmmReg[48,8] + XmmReg2_m128[48,8]; + result[56,8] = vexVVVV_XmmReg[56,8] + XmmReg2_m128[56,8]; + result[64,8] = vexVVVV_XmmReg[64,8] + XmmReg2_m128[64,8]; + result[72,8] = vexVVVV_XmmReg[72,8] + XmmReg2_m128[72,8]; + result[80,8] = vexVVVV_XmmReg[80,8] + XmmReg2_m128[80,8]; + result[88,8] = vexVVVV_XmmReg[88,8] + XmmReg2_m128[88,8]; + result[96,8] = vexVVVV_XmmReg[96,8] + XmmReg2_m128[96,8]; + result[104,8] = vexVVVV_XmmReg[104,8] + XmmReg2_m128[104,8]; + result[112,8] = vexVVVV_XmmReg[112,8] + XmmReg2_m128[112,8]; + result[120,8] = vexVVVV_XmmReg[120,8] + XmmReg2_m128[120,8]; + + ZmmReg1 = zext(result); } # PADDB/PADDW/PADDD/PADDQ 4-204 PAGE 1324 LINE 68660 -define pcodeop vpaddw_avx ; :VPADDW XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG) & vexVVVV_XmmReg; byte=0xFD; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vpaddw_avx( vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + local result:16 = 0; + result[0,16] = vexVVVV_XmmReg[0,16] + XmmReg2_m128[0,16]; + result[16,16] = vexVVVV_XmmReg[16,16] + XmmReg2_m128[16,16]; + result[32,16] = vexVVVV_XmmReg[32,16] + XmmReg2_m128[32,16]; + result[48,16] = vexVVVV_XmmReg[48,16] + XmmReg2_m128[48,16]; + result[64,16] = vexVVVV_XmmReg[64,16] + XmmReg2_m128[64,16]; + result[80,16] = vexVVVV_XmmReg[80,16] + XmmReg2_m128[80,16]; + result[96,16] = vexVVVV_XmmReg[96,16] + XmmReg2_m128[96,16]; + result[112,16] = vexVVVV_XmmReg[112,16] + XmmReg2_m128[112,16]; + + ZmmReg1 = zext(result); } # PADDB/PADDW/PADDD/PADDQ 4-204 PAGE 1324 LINE 68662 -define pcodeop vpaddd_avx ; :VPADDD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG) & vexVVVV_XmmReg; byte=0xFE; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vpaddd_avx( vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + local result:16 = 0; + result[0,32] = vexVVVV_XmmReg[0,32] + XmmReg2_m128[0,32]; + result[32,32] = vexVVVV_XmmReg[32,32] + XmmReg2_m128[32,32]; + result[64,32] = vexVVVV_XmmReg[64,32] + XmmReg2_m128[64,32]; + result[96,32] = vexVVVV_XmmReg[96,32] + XmmReg2_m128[96,32]; + + ZmmReg1 = zext(result); } # PADDB/PADDW/PADDD/PADDQ 4-204 PAGE 1324 LINE 68664 @@ -1885,24 +1948,6 @@ define pcodeop vpinsrb_avx ; ZmmReg1 = zext(tmp); } -# PINSRB/PINSRD/PINSRQ 4-293 PAGE 1413 LINE 73324 -define pcodeop vpinsrd_avx ; -:VPINSRD XmmReg1, vexVVVV_XmmReg, rm32, imm8 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x22; (XmmReg1 & ZmmReg1) ... & rm32; imm8 -{ - local tmp:16 = vpinsrd_avx( vexVVVV_XmmReg, rm32, imm8:1 ); - ZmmReg1 = zext(tmp); -} - -# PINSRB/PINSRD/PINSRQ 4-293 PAGE 1413 LINE 73327 -define pcodeop vpinsrq_avx ; -@ifdef IA64 -:VPINSRQ XmmReg1, vexVVVV_XmmReg, rm64, imm8 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x22; (XmmReg1 & ZmmReg1) ... & rm64; imm8 -{ - local tmp:16 = vpinsrq_avx( vexVVVV_XmmReg, rm64, imm8:1 ); - ZmmReg1 = zext(tmp); -} -@endif - # PINSRW 4-296 PAGE 1416 LINE 73446 define pcodeop vpinsrw_avx ; :VPINSRW XmmReg1, vexVVVV_XmmReg, Reg32_m16, imm8 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xC4; (XmmReg1 & ZmmReg1) ... & Reg32_m16; imm8 @@ -2688,19 +2733,21 @@ define pcodeop vsqrtps_avx ; } # SQRTSD 4-638 PAGE 1758 LINE 91272 -define pcodeop vsqrtsd_avx ; :VSQRTSD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_F2) & $(VEX_0F) & $(VEX_WIG) & vexVVVV_XmmReg; byte=0x51; (XmmReg1 & ZmmReg1) ... & XmmReg2_m64 { - local tmp:16 = vsqrtsd_avx( vexVVVV_XmmReg, XmmReg2_m64 ); - ZmmReg1 = zext(tmp); + local m:16 = XmmReg2_m64; + XmmReg1[0,64] = sqrt(vexVVVV_XmmReg[0,64]); + XmmReg1[64,64]= m[64,64]; + ZmmReg1 = zext(XmmReg1); } # SQRTSS 4-640 PAGE 1760 LINE 91367 -define pcodeop vsqrtss_avx ; :VSQRTSS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_F3) & $(VEX_0F) & $(VEX_WIG) & vexVVVV_XmmReg; byte=0x51; (XmmReg1 & ZmmReg1) ... & XmmReg2_m32 { - local tmp:16 = vsqrtss_avx( vexVVVV_XmmReg, XmmReg2_m32 ); - ZmmReg1 = zext(tmp); + local m:16 = XmmReg2_m32; + XmmReg1[0,32] = sqrt(vexVVVV_XmmReg[0,32]); + XmmReg1[32,96]= m[32,96]; + ZmmReg1 = zext(XmmReg1); } # STMXCSR 4-647 PAGE 1767 LINE 91697 diff --git a/Ghidra/Processors/x86/data/languages/avx2.sinc b/Ghidra/Processors/x86/data/languages/avx2.sinc index 5bba08c71d3..b465d62d44b 100644 --- a/Ghidra/Processors/x86/data/languages/avx2.sinc +++ b/Ghidra/Processors/x86/data/languages/avx2.sinc @@ -75,35 +75,95 @@ define pcodeop vpackuswb_avx2 ; } # PADDB/PADDW/PADDD/PADDQ 4-204 PAGE 1324 LINE 68666 -define pcodeop vpaddb_avx2 ; :VPADDB YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_NDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG) & vexVVVV_YmmReg; byte=0xFC; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:32 = vpaddb_avx2( vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + local result:32 = 0; + result[0,8] = vexVVVV_YmmReg[0,8] + YmmReg2_m256[0,8]; + result[8,8] = vexVVVV_YmmReg[8,8] + YmmReg2_m256[8,8]; + result[16,8] = vexVVVV_YmmReg[16,8] + YmmReg2_m256[16,8]; + result[24,8] = vexVVVV_YmmReg[24,8] + YmmReg2_m256[24,8]; + result[32,8] = vexVVVV_YmmReg[32,8] + YmmReg2_m256[32,8]; + result[40,8] = vexVVVV_YmmReg[40,8] + YmmReg2_m256[40,8]; + result[48,8] = vexVVVV_YmmReg[48,8] + YmmReg2_m256[48,8]; + result[56,8] = vexVVVV_YmmReg[56,8] + YmmReg2_m256[56,8]; + result[64,8] = vexVVVV_YmmReg[64,8] + YmmReg2_m256[64,8]; + result[72,8] = vexVVVV_YmmReg[72,8] + YmmReg2_m256[72,8]; + result[80,8] = vexVVVV_YmmReg[80,8] + YmmReg2_m256[80,8]; + result[88,8] = vexVVVV_YmmReg[88,8] + YmmReg2_m256[88,8]; + result[96,8] = vexVVVV_YmmReg[96,8] + YmmReg2_m256[96,8]; + result[104,8] = vexVVVV_YmmReg[104,8] + YmmReg2_m256[104,8]; + result[112,8] = vexVVVV_YmmReg[112,8] + YmmReg2_m256[112,8]; + result[120,8] = vexVVVV_YmmReg[120,8] + YmmReg2_m256[120,8]; + result[128,8] = vexVVVV_YmmReg[128,8] + YmmReg2_m256[128,8]; + result[136,8] = vexVVVV_YmmReg[136,8] + YmmReg2_m256[136,8]; + result[144,8] = vexVVVV_YmmReg[144,8] + YmmReg2_m256[144,8]; + result[152,8] = vexVVVV_YmmReg[152,8] + YmmReg2_m256[152,8]; + result[160,8] = vexVVVV_YmmReg[160,8] + YmmReg2_m256[160,8]; + result[168,8] = vexVVVV_YmmReg[168,8] + YmmReg2_m256[168,8]; + result[176,8] = vexVVVV_YmmReg[176,8] + YmmReg2_m256[176,8]; + result[184,8] = vexVVVV_YmmReg[184,8] + YmmReg2_m256[184,8]; + result[192,8] = vexVVVV_YmmReg[192,8] + YmmReg2_m256[192,8]; + result[200,8] = vexVVVV_YmmReg[200,8] + YmmReg2_m256[200,8]; + result[208,8] = vexVVVV_YmmReg[208,8] + YmmReg2_m256[208,8]; + result[216,8] = vexVVVV_YmmReg[216,8] + YmmReg2_m256[216,8]; + result[224,8] = vexVVVV_YmmReg[224,8] + YmmReg2_m256[224,8]; + result[232,8] = vexVVVV_YmmReg[232,8] + YmmReg2_m256[232,8]; + result[240,8] = vexVVVV_YmmReg[240,8] + YmmReg2_m256[240,8]; + result[248,8] = vexVVVV_YmmReg[248,8] + YmmReg2_m256[248,8]; + + ZmmReg1 = zext(result); } # PADDB/PADDW/PADDD/PADDQ 4-204 PAGE 1324 LINE 68668 -define pcodeop vpaddw_avx2 ; :VPADDW YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_NDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG) & vexVVVV_YmmReg; byte=0xFD; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:32 = vpaddw_avx2( vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + local result:32 = 0; + result[0,16] = vexVVVV_YmmReg[0,16] + YmmReg2_m256[0,16]; + result[16,16] = vexVVVV_YmmReg[16,16] + YmmReg2_m256[16,16]; + result[32,16] = vexVVVV_YmmReg[32,16] + YmmReg2_m256[32,16]; + result[48,16] = vexVVVV_YmmReg[48,16] + YmmReg2_m256[48,16]; + result[64,16] = vexVVVV_YmmReg[64,16] + YmmReg2_m256[64,16]; + result[80,16] = vexVVVV_YmmReg[80,16] + YmmReg2_m256[80,16]; + result[96,16] = vexVVVV_YmmReg[96,16] + YmmReg2_m256[96,16]; + result[112,16] = vexVVVV_YmmReg[112,16] + YmmReg2_m256[112,16]; + result[128,16] = vexVVVV_YmmReg[128,16] + YmmReg2_m256[128,16]; + result[144,16] = vexVVVV_YmmReg[144,16] + YmmReg2_m256[144,16]; + result[160,16] = vexVVVV_YmmReg[160,16] + YmmReg2_m256[160,16]; + result[176,16] = vexVVVV_YmmReg[176,16] + YmmReg2_m256[176,16]; + result[192,16] = vexVVVV_YmmReg[192,16] + YmmReg2_m256[192,16]; + result[208,16] = vexVVVV_YmmReg[208,16] + YmmReg2_m256[208,16]; + result[224,16] = vexVVVV_YmmReg[224,16] + YmmReg2_m256[224,16]; + result[240,16] = vexVVVV_YmmReg[240,16] + YmmReg2_m256[240,16]; + + ZmmReg1 = zext(result); } # PADDB/PADDW/PADDD/PADDQ 4-204 PAGE 1324 LINE 68670 -define pcodeop vpaddd_avx2 ; :VPADDD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_NDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG) & vexVVVV_YmmReg; byte=0xFE; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:32 = vpaddd_avx2( vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + local result:32 = 0; + result[0,32] = vexVVVV_YmmReg[0,32] + YmmReg2_m256[0,32]; + result[32,32] = vexVVVV_YmmReg[32,32] + YmmReg2_m256[32,32]; + result[64,32] = vexVVVV_YmmReg[64,32] + YmmReg2_m256[64,32]; + result[96,32] = vexVVVV_YmmReg[96,32] + YmmReg2_m256[96,32]; + result[128,32] = vexVVVV_YmmReg[128,32] + YmmReg2_m256[128,32]; + result[160,32] = vexVVVV_YmmReg[160,32] + YmmReg2_m256[160,32]; + result[192,32] = vexVVVV_YmmReg[192,32] + YmmReg2_m256[192,32]; + result[224,32] = vexVVVV_YmmReg[224,32] + YmmReg2_m256[224,32]; + + ZmmReg1 = zext(result); } # PADDB/PADDW/PADDD/PADDQ 4-204 PAGE 1324 LINE 68672 -define pcodeop vpaddq_avx2 ; :VPADDQ YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_NDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG) & vexVVVV_YmmReg; byte=0xD4; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:32 = vpaddq_avx2( vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + local result:32 = 0; + result[0,64] = vexVVVV_YmmReg[0,64] + YmmReg2_m256[0,64]; + result[64,64] = vexVVVV_YmmReg[64,64] + YmmReg2_m256[64,64]; + result[128,64] = vexVVVV_YmmReg[128,64] + YmmReg2_m256[128,64]; + result[192,64] = vexVVVV_YmmReg[192,64] + YmmReg2_m256[192,64]; + + ZmmReg1 = zext(result); } # PADDSB/PADDSW 4-211 PAGE 1331 LINE 69045 diff --git a/Ghidra/Processors/x86/data/languages/avx2_manual.sinc b/Ghidra/Processors/x86/data/languages/avx2_manual.sinc index ad617794177..7fdaafa2d3d 100644 --- a/Ghidra/Processors/x86/data/languages/avx2_manual.sinc +++ b/Ghidra/Processors/x86/data/languages/avx2_manual.sinc @@ -1,13 +1,15 @@ # VINSERTI128/VINSERTI32x4/VINSERTI64x2/VINSERTI32x8/VINSERTI64x4 5-314 PAGE 2138 LINE 109785 -define pcodeop vinserti128 ; -:VINSERTI128 YmmReg1, vexVVVV_YmmReg, XmmReg2_m128, imm8 is $(VEX_NDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W0) & vexVVVV_YmmReg; byte=0x38; YmmReg1 ... & XmmReg2_m128; imm8 & imm8_0 { - local tmp:16 = XmmReg2_m128; - local cond0:16 = zext((imm8_0:1 & 0x1) == 0); - local cond1:16 = zext((imm8_0:1 & 0x1) == 1); - # ignoring all but the least significant bit - YmmReg1[0,128] = (cond0 * tmp) + (cond1 * vexVVVV_YmmReg[0,128]); - YmmReg1[128,128] = (cond0 * vexVVVV_YmmReg[128,128]) + (cond1 * tmp); - +:VINSERTI128 YmmReg1, vexVVVV_YmmReg, XmmReg2_m128, imm8 is $(VEX_NDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W0) & vexVVVV_YmmReg; byte=0x38; YmmReg1 ... & XmmReg2_m128; imm8 & imm8_0{ + local scr1l:16 = vexVVVV_YmmReg[0,128]; + local scr1h:16 = vexVVVV_YmmReg[128,128]; + local src2:16 = XmmReg2_m128; + local vcond:1 = (imm8_0:1 & 0x1) == 0; + local part1:16 = 0; + conditionalAssign(part1, vcond, src2, scr1l); + local part2:16 = 0; + conditionalAssign(part2, vcond, scr1h, src2); + YmmReg1[0,128] = part1; + YmmReg1[128,128] = part2; } # VGATHERDPD/VGATHERQPD 5-251 PAGE 2075 LINE 106903 diff --git a/Ghidra/Processors/x86/data/languages/avx512.sinc b/Ghidra/Processors/x86/data/languages/avx512.sinc index 4c344929889..0b887ee2a29 100644 --- a/Ghidra/Processors/x86/data/languages/avx512.sinc +++ b/Ghidra/Processors/x86/data/languages/avx512.sinc @@ -2140,11 +2140,10 @@ define pcodeop vmulss_avx512f ; } # ORPD 4-168 PAGE 1288 LINE 66724 -define pcodeop vorpd_avx512vl ; :VORPD XmmReg1^XmmOpMask64, evexV5_XmmReg, XmmReg2_m128_m64bcst is $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W1) & evexV5_XmmReg; byte=0x56; (XmmReg1 & ZmmReg1 & XmmOpMask64) ... & XmmReg2_m128_m64bcst [ evexD8Type = 0; evexTType = 0; ] # (TupleType FV) { - XmmResult = vorpd_avx512vl( evexV5_XmmReg, XmmReg2_m128_m64bcst ); + XmmResult = evexV5_XmmReg | XmmReg2_m128_m64bcst; XmmMask = XmmReg1; build XmmOpMask64; ZmmReg1 = zext(XmmResult); @@ -2154,29 +2153,27 @@ define pcodeop vorpd_avx512vl ; :VORPD YmmReg1^YmmOpMask64, evexV5_YmmReg, YmmReg2_m256_m64bcst is $(EVEX_NONE) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W1) & evexV5_YmmReg; byte=0x56; (YmmReg1 & ZmmReg1 & YmmOpMask64) ... & YmmReg2_m256_m64bcst [ evexD8Type = 0; evexTType = 0; ] # (TupleType FV) { - YmmResult = vorpd_avx512vl( evexV5_YmmReg, YmmReg2_m256_m64bcst ); + YmmResult = evexV5_YmmReg | YmmReg2_m256_m64bcst; YmmMask = YmmReg1; build YmmOpMask64; ZmmReg1 = zext(YmmResult); } # ORPD 4-168 PAGE 1288 LINE 66730 -define pcodeop vorpd_avx512dq ; :VORPD ZmmReg1^ZmmOpMask64, evexV5_ZmmReg, ZmmReg2_m512_m64bcst is $(EVEX_NONE) & $(EVEX_L512) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W1) & evexV5_ZmmReg; byte=0x56; (ZmmReg1 & ZmmOpMask64) ... & ZmmReg2_m512_m64bcst [ evexD8Type = 0; evexTType = 0; ] # (TupleType FV) { - ZmmResult = vorpd_avx512dq( evexV5_ZmmReg, ZmmReg2_m512_m64bcst ); + ZmmResult = evexV5_ZmmReg | ZmmReg2_m512_m64bcst; ZmmMask = ZmmReg1; build ZmmOpMask64; ZmmReg1 = ZmmResult; } # ORPS 4-171 PAGE 1291 LINE 66850 -define pcodeop vorps_avx512vl ; :VORPS XmmReg1^XmmOpMask32, evexV5_XmmReg, XmmReg2_m128_m32bcst is $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_NONE) & $(VEX_0F) & $(VEX_W0) & evexV5_XmmReg; byte=0x56; (XmmReg1 & ZmmReg1 & XmmOpMask32) ... & XmmReg2_m128_m32bcst [ evexD8Type = 0; evexTType = 0; ] # (TupleType FV) { - XmmResult = vorps_avx512vl( evexV5_XmmReg, XmmReg2_m128_m32bcst ); + XmmResult = evexV5_XmmReg | XmmReg2_m128_m32bcst; XmmMask = XmmReg1; build XmmOpMask32; ZmmReg1 = zext(XmmResult); @@ -2186,18 +2183,17 @@ define pcodeop vorps_avx512vl ; :VORPS YmmReg1^YmmOpMask32, evexV5_YmmReg, YmmReg2_m256_m32bcst is $(EVEX_NONE) & $(VEX_L256) & $(VEX_PRE_NONE) & $(VEX_0F) & $(VEX_W0) & evexV5_YmmReg; byte=0x56; (YmmReg1 & ZmmReg1 & YmmOpMask32) ... & YmmReg2_m256_m32bcst [ evexD8Type = 0; evexTType = 0; ] # (TupleType FV) { - YmmResult = vorps_avx512vl( evexV5_YmmReg, YmmReg2_m256_m32bcst ); + YmmResult = evexV5_YmmReg | YmmReg2_m256_m32bcst; YmmMask = YmmReg1; build YmmOpMask32; ZmmReg1 = zext(YmmResult); } # ORPS 4-171 PAGE 1291 LINE 66856 -define pcodeop vorps_avx512dq ; :VORPS ZmmReg1^ZmmOpMask32, evexV5_ZmmReg, ZmmReg2_m512_m32bcst is $(EVEX_NONE) & $(EVEX_L512) & $(VEX_PRE_NONE) & $(VEX_0F) & $(VEX_W0) & evexV5_ZmmReg; byte=0x56; (ZmmReg1 & ZmmOpMask32) ... & ZmmReg2_m512_m32bcst [ evexD8Type = 0; evexTType = 0; ] # (TupleType FV) { - ZmmResult = vorps_avx512dq( evexV5_ZmmReg, ZmmReg2_m512_m32bcst ); + ZmmResult = evexV5_ZmmReg | ZmmReg2_m512_m32bcst; ZmmMask = ZmmReg1; build ZmmOpMask32; ZmmReg1 = ZmmResult; @@ -2717,20 +2713,20 @@ define pcodeop vpaddusw_avx512bw ; # PALIGNR 4-219 PAGE 1339 LINE 69495 define pcodeop vpalignr_avx512vl ; -:VPALIGNR XmmReg1^XmmOpMask8, evexV5_XmmReg, XmmReg2_m128 is $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_WIG) & evexV5_XmmReg; byte=0x0F; (XmmReg1 & ZmmReg1 & XmmOpMask8) ... & XmmReg2_m128 +:VPALIGNR XmmReg1^XmmOpMask8, evexV5_XmmReg, XmmReg2_m128, imm8 is $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_WIG) & evexV5_XmmReg; byte=0x0F; (XmmReg1 & ZmmReg1 & XmmOpMask8) ... & XmmReg2_m128; imm8 [ evexD8Type = 1; evexTType = 0; ] # (TupleType FVM) { - XmmResult = vpalignr_avx512vl( evexV5_XmmReg, XmmReg2_m128 ); + XmmResult = vpalignr_avx512vl( evexV5_XmmReg, XmmReg2_m128, imm8:1 ); XmmMask = XmmReg1; build XmmOpMask8; ZmmReg1 = zext(XmmResult); } # PALIGNR 4-219 PAGE 1339 LINE 69499 -:VPALIGNR YmmReg1^YmmOpMask8, evexV5_YmmReg, YmmReg2_m256 is $(EVEX_NONE) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_WIG) & evexV5_YmmReg; byte=0x0F; (YmmReg1 & ZmmReg1 & YmmOpMask8) ... & YmmReg2_m256 +:VPALIGNR YmmReg1^YmmOpMask8, evexV5_YmmReg, YmmReg2_m256, imm8 is $(EVEX_NONE) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_WIG) & evexV5_YmmReg; byte=0x0F; (YmmReg1 & ZmmReg1 & YmmOpMask8) ... & YmmReg2_m256; imm8 [ evexD8Type = 1; evexTType = 0; ] # (TupleType FVM) { - YmmResult = vpalignr_avx512vl( evexV5_YmmReg, YmmReg2_m256 ); + YmmResult = vpalignr_avx512vl( evexV5_YmmReg, YmmReg2_m256, imm8:1 ); YmmMask = YmmReg1; build YmmOpMask8; ZmmReg1 = zext(YmmResult); @@ -2738,15 +2734,16 @@ define pcodeop vpalignr_avx512vl ; # PALIGNR 4-219 PAGE 1339 LINE 69505 define pcodeop vpalignr_avx512bw ; -:VPALIGNR ZmmReg1^ZmmOpMask8, evexV5_ZmmReg, ZmmReg2_m512 is $(EVEX_NONE) & $(EVEX_L512) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_WIG) & evexV5_ZmmReg; byte=0x0F; (ZmmReg1 & ZmmOpMask8) ... & ZmmReg2_m512 +:VPALIGNR ZmmReg1^ZmmOpMask8, evexV5_ZmmReg, ZmmReg2_m512, imm8 is $(EVEX_NONE) & $(EVEX_L512) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_WIG) & evexV5_ZmmReg; byte=0x0F; (ZmmReg1 & ZmmOpMask8) ... & ZmmReg2_m512; imm8 [ evexD8Type = 1; evexTType = 0; ] # (TupleType FVM) { - ZmmResult = vpalignr_avx512bw( evexV5_ZmmReg, ZmmReg2_m512 ); + ZmmResult = vpalignr_avx512bw( evexV5_ZmmReg, ZmmReg2_m512, imm8:1 ); ZmmMask = ZmmReg1; build ZmmOpMask8; ZmmReg1 = ZmmResult; } + # PAND 4-223 PAGE 1343 LINE 69684 define pcodeop vpandd_avx512vl ; :VPANDD XmmReg1^XmmOpMask32, evexV5_XmmReg, XmmReg2_m128_m32bcst is $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W0) & evexV5_XmmReg; byte=0xDB; (XmmReg1 & ZmmReg1 & XmmOpMask32) ... & XmmReg2_m128_m32bcst @@ -5816,70 +5813,6 @@ define pcodeop vpunpcklqdq_avx512f ; ZmmReg1 = ZmmResult; } -# PXOR 4-518 PAGE 1638 LINE 85503 -define pcodeop vpxord_avx512vl ; -:VPXORD XmmReg1^XmmOpMask32, evexV5_XmmReg, XmmReg2_m128_m32bcst is $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W0) & evexV5_XmmReg; byte=0xEF; (XmmReg1 & ZmmReg1 & XmmOpMask32) ... & XmmReg2_m128_m32bcst -[ evexD8Type = 0; evexTType = 0; ] # (TupleType FV) -{ - XmmResult = vpxord_avx512vl( evexV5_XmmReg, XmmReg2_m128_m32bcst ); - XmmMask = XmmReg1; - build XmmOpMask32; - ZmmReg1 = zext(XmmResult); -} - -# PXOR 4-518 PAGE 1638 LINE 85505 -:VPXORD YmmReg1^YmmOpMask32, evexV5_YmmReg, YmmReg2_m256_m32bcst is $(EVEX_NONE) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W0) & evexV5_YmmReg; byte=0xEF; (YmmReg1 & ZmmReg1 & YmmOpMask32) ... & YmmReg2_m256_m32bcst -[ evexD8Type = 0; evexTType = 0; ] # (TupleType FV) -{ - YmmResult = vpxord_avx512vl( evexV5_YmmReg, YmmReg2_m256_m32bcst ); - YmmMask = YmmReg1; - build YmmOpMask32; - ZmmReg1 = zext(YmmResult); -} - -# PXOR 4-518 PAGE 1638 LINE 85507 -define pcodeop vpxord_avx512f ; -:VPXORD ZmmReg1^ZmmOpMask32, evexV5_ZmmReg, ZmmReg2_m512_m32bcst is $(EVEX_NONE) & $(EVEX_L512) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W0) & evexV5_ZmmReg; byte=0xEF; (ZmmReg1 & ZmmOpMask32) ... & ZmmReg2_m512_m32bcst -[ evexD8Type = 0; evexTType = 0; ] # (TupleType FV) -{ - ZmmResult = vpxord_avx512f( evexV5_ZmmReg, ZmmReg2_m512_m32bcst ); - ZmmMask = ZmmReg1; - build ZmmOpMask32; - ZmmReg1 = ZmmResult; -} - -# PXOR 4-518 PAGE 1638 LINE 85514 -define pcodeop vpxorq_avx512vl ; -:VPXORQ XmmReg1^XmmOpMask64, evexV5_XmmReg, XmmReg2_m128_m64bcst is $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W1) & evexV5_XmmReg; byte=0xEF; (XmmReg1 & ZmmReg1 & XmmOpMask64) ... & XmmReg2_m128_m64bcst -[ evexD8Type = 0; evexTType = 0; ] # (TupleType FV) -{ - XmmResult = vpxorq_avx512vl( evexV5_XmmReg, XmmReg2_m128_m64bcst ); - XmmMask = XmmReg1; - build XmmOpMask64; - ZmmReg1 = zext(XmmResult); -} - -# PXOR 4-518 PAGE 1638 LINE 85521 -:VPXORQ YmmReg1^YmmOpMask64, evexV5_YmmReg, YmmReg2_m256_m64bcst is $(EVEX_NONE) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W1) & evexV5_YmmReg; byte=0xEF; (YmmReg1 & ZmmReg1 & YmmOpMask64) ... & YmmReg2_m256_m64bcst -[ evexD8Type = 0; evexTType = 0; ] # (TupleType FV) -{ - YmmResult = vpxorq_avx512vl( evexV5_YmmReg, YmmReg2_m256_m64bcst ); - YmmMask = YmmReg1; - build YmmOpMask64; - ZmmReg1 = zext(YmmResult); -} - -# PXOR 4-518 PAGE 1638 LINE 85523 -define pcodeop vpxorq_avx512f ; -:VPXORQ ZmmReg1^ZmmOpMask64, evexV5_ZmmReg, ZmmReg2_m512_m64bcst is $(EVEX_NONE) & $(EVEX_L512) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W1) & evexV5_ZmmReg; byte=0xEF; (ZmmReg1 & ZmmOpMask64) ... & ZmmReg2_m512_m64bcst -[ evexD8Type = 0; evexTType = 0; ] # (TupleType FV) -{ - ZmmResult = vpxorq_avx512f( evexV5_ZmmReg, ZmmReg2_m512_m64bcst ); - ZmmMask = ZmmReg1; - build ZmmOpMask64; - ZmmReg1 = ZmmResult; -} - # SHUFPD 4-617 PAGE 1737 LINE 90231 define pcodeop vshufpd_avx512vl ; :VSHUFPD XmmReg1^XmmOpMask64, evexV5_XmmReg, XmmReg2_m128_m64bcst, imm8 is $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W1) & evexV5_XmmReg; byte=0xC6; (XmmReg1 & ZmmReg1 & XmmOpMask64) ... & XmmReg2_m128_m64bcst; imm8 @@ -6009,25 +5942,27 @@ define pcodeop vsqrtps_avx512f ; } # SQRTSD 4-638 PAGE 1758 LINE 91276 -define pcodeop vsqrtsd_avx512f ; -:VSQRTSD XmmReg1^XmmOpMask64, evexV5_XmmReg, XmmReg2_m64 is $(EVEX_NONE) & $(VEX_LIG) & $(VEX_PRE_F2) & $(VEX_0F) & $(VEX_W1) & evexV5_XmmReg; byte=0x51; (XmmReg1 & ZmmReg1 & XmmOpMask64) ... & XmmReg2_m64 +:VSQRTSD XmmReg1^XmmOpMask, evexV5_XmmReg, XmmReg2_m64 is $(EVEX_NONE) & $(VEX_LIG) & $(VEX_PRE_F2) & $(VEX_0F) & $(VEX_W1) & evexV5_XmmReg; byte=0x51; (XmmReg1 & ZmmReg1 & XmmOpMask) ... & XmmReg2_m64 [ evexD8Type = 1; evexTType = 3; ] # (TupleType T1S) { - XmmResult = vsqrtsd_avx512f( evexV5_XmmReg, XmmReg2_m64 ); + XmmResult[0,64] = sqrt(XmmReg2_m64[0,64]); XmmMask = XmmReg1; - build XmmOpMask64; - ZmmReg1 = zext(XmmResult); + conditionalAssign(XmmResult[0,64], XmmOpMask[0,1], XmmResult[0,64], XmmMask[0,64]); + XmmReg1[0,64] = XmmResult[0,64]; + XmmReg1[64,64]= evexV5_XmmReg[64,64]; + ZmmReg1 = zext(XmmReg1); } # SQRTSS 4-640 PAGE 1760 LINE 91371 -define pcodeop vsqrtss_avx512f ; -:VSQRTSS XmmReg1^XmmOpMask32, evexV5_XmmReg, XmmReg2_m32 is $(EVEX_NONE) & $(VEX_LIG) & $(VEX_PRE_F3) & $(VEX_0F) & $(VEX_W0) & evexV5_XmmReg; byte=0x51; (XmmReg1 & ZmmReg1 & XmmOpMask32) ... & XmmReg2_m32 +:VSQRTSS XmmReg1^XmmOpMask, evexV5_XmmReg, XmmReg2_m32 is $(EVEX_NONE) & $(VEX_LIG) & $(VEX_PRE_F3) & $(VEX_0F) & $(VEX_W0) & evexV5_XmmReg; byte=0x51; (XmmReg1 & ZmmReg1 & XmmOpMask) ... & XmmReg2_m32 [ evexD8Type = 1; evexTType = 3; ] # (TupleType T1S) { - XmmResult = vsqrtss_avx512f( evexV5_XmmReg, XmmReg2_m32 ); + XmmResult[0,32] = sqrt(XmmReg2_m32[0,32]); XmmMask = XmmReg1; - build XmmOpMask32; - ZmmReg1 = zext(XmmResult); + conditionalAssign(XmmResult[0,32], XmmOpMask[0,1], XmmResult[0,32], XmmMask[0,32]); + XmmReg1[0,32] = XmmResult[0,32]; + XmmReg1[32,96]=evexV5_XmmReg[32,96]; + ZmmReg1 = zext(XmmReg1); } # SUBPD 4-656 PAGE 1776 LINE 92120 @@ -17646,11 +17581,10 @@ define pcodeop vsqrtph_avx512fp16 ; define pcodeop vsqrtsh_avx512fp16 ; :VSQRTSH XmmReg1^XmmOpMask, evexV5_XmmReg, XmmReg2_m16 is $(EVEX_NONE) & $(EVEX_LLIG) & $(VEX_PRE_F3) & $(VEX_MAP5) & $(VEX_W0) & XmmOpMask & evexV5_XmmReg; byte=0x51; (XmmReg1 & ZmmReg1) ... & XmmReg2_m16 { - XmmResult = vsqrtsh_avx512fp16( evexV5_XmmReg, XmmReg2_m16 ); + XmmResult[0,16] = sqrt(XmmReg2_m16[0,16]); XmmMask = XmmReg1; - build XmmOpMask; conditionalAssign(XmmResult[0,16], XmmOpMask[0,1], XmmResult[0,16], XmmMask[0,16]); - XmmResult[16,112] = XmmReg1[16,112]; # DEST[127:16] remains unchanged + XmmResult[16,112] = evexV5_XmmReg[16,112]; # DEST[127:16] = src1[127:16] ZmmReg1 = zext(XmmResult); } diff --git a/Ghidra/Processors/x86/data/languages/avx512_manual.sinc b/Ghidra/Processors/x86/data/languages/avx512_manual.sinc index ef603b157d3..27e2c708036 100644 --- a/Ghidra/Processors/x86/data/languages/avx512_manual.sinc +++ b/Ghidra/Processors/x86/data/languages/avx512_manual.sinc @@ -1582,4 +1582,65 @@ define pcodeop vpmovuswb_avx512bw ; YmmMask = m256; build YmmOpMask8; m256 = zext(YmmResult); -} \ No newline at end of file +} + +# PXOR 4-518 PAGE 1638 LINE 85503 +:VPXORD XmmReg1^XmmOpMask32, evexV5_XmmReg, XmmReg2_m128_m32bcst is $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W0) & evexV5_XmmReg; byte=0xEF; (XmmReg1 & ZmmReg1 & XmmOpMask32) ... & XmmReg2_m128_m32bcst +[ evexD8Type = 0; evexTType = 0; ] # (TupleType FV) +{ + XmmResult = evexV5_XmmReg ^ XmmReg2_m128_m32bcst; + XmmMask = XmmReg1; + build XmmOpMask32; + ZmmReg1 = zext(XmmResult); +} + +# PXOR 4-518 PAGE 1638 LINE 85505 +:VPXORD YmmReg1^YmmOpMask32, evexV5_YmmReg, YmmReg2_m256_m32bcst is $(EVEX_NONE) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W0) & evexV5_YmmReg; byte=0xEF; (YmmReg1 & ZmmReg1 & YmmOpMask32) ... & YmmReg2_m256_m32bcst +[ evexD8Type = 0; evexTType = 0; ] # (TupleType FV) +{ + YmmResult = evexV5_YmmReg ^ YmmReg2_m256_m32bcst; + YmmMask = YmmReg1; + build YmmOpMask32; + ZmmReg1 = zext(YmmResult); +} + +# PXOR 4-518 PAGE 1638 LINE 85507 +:VPXORD ZmmReg1^ZmmOpMask32, evexV5_ZmmReg, ZmmReg2_m512_m32bcst is $(EVEX_NONE) & $(EVEX_L512) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W0) & evexV5_ZmmReg; byte=0xEF; (ZmmReg1 & ZmmOpMask32) ... & ZmmReg2_m512_m32bcst +[ evexD8Type = 0; evexTType = 0; ] # (TupleType FV) +{ + ZmmResult = evexV5_ZmmReg ^ ZmmReg2_m512_m32bcst; + ZmmMask = ZmmReg1; + build ZmmOpMask32; + ZmmReg1 = ZmmResult; +} + +# PXOR 4-518 PAGE 1638 LINE 85514 +:VPXORQ XmmReg1^XmmOpMask64, evexV5_XmmReg, XmmReg2_m128_m64bcst is $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W1) & evexV5_XmmReg; byte=0xEF; (XmmReg1 & ZmmReg1 & XmmOpMask64) ... & XmmReg2_m128_m64bcst +[ evexD8Type = 0; evexTType = 0; ] # (TupleType FV) +{ + XmmResult = evexV5_XmmReg ^ XmmReg2_m128_m64bcst; + XmmMask = XmmReg1; + build XmmOpMask64; + ZmmReg1 = zext(XmmResult); +} + +# PXOR 4-518 PAGE 1638 LINE 85521 +:VPXORQ YmmReg1^YmmOpMask64, evexV5_YmmReg, YmmReg2_m256_m64bcst is $(EVEX_NONE) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W1) & evexV5_YmmReg; byte=0xEF; (YmmReg1 & ZmmReg1 & YmmOpMask64) ... & YmmReg2_m256_m64bcst +[ evexD8Type = 0; evexTType = 0; ] # (TupleType FV) +{ + YmmResult = evexV5_YmmReg ^ YmmReg2_m256_m64bcst; + YmmMask = YmmReg1; + build YmmOpMask64; + ZmmReg1 = zext(YmmResult); +} + +# PXOR 4-518 PAGE 1638 LINE 85523 +:VPXORQ ZmmReg1^ZmmOpMask64, evexV5_ZmmReg, ZmmReg2_m512_m64bcst is $(EVEX_NONE) & $(EVEX_L512) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W1) & evexV5_ZmmReg; byte=0xEF; (ZmmReg1 & ZmmOpMask64) ... & ZmmReg2_m512_m64bcst +[ evexD8Type = 0; evexTType = 0; ] # (TupleType FV) +{ + ZmmResult = evexV5_ZmmReg ^ ZmmReg2_m512_m64bcst; + ZmmMask = ZmmReg1; + build ZmmOpMask64; + ZmmReg1 = ZmmResult; +} + diff --git a/Ghidra/Processors/x86/data/languages/avx_manual.sinc b/Ghidra/Processors/x86/data/languages/avx_manual.sinc index 9b84e34e1d1..15ab16d5cc1 100644 --- a/Ghidra/Processors/x86/data/languages/avx_manual.sinc +++ b/Ghidra/Processors/x86/data/languages/avx_manual.sinc @@ -192,6 +192,36 @@ ZmmReg1 = zext(XmmReg1); } +# PINSRB/PINSRD/PINSRQ 4-293 PAGE 1413 LINE 73324 +#define pcodeop vpinsrd_avx ; +:VPINSRD XmmReg1, vexVVVV_XmmReg, rm32, imm8 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x22; (XmmReg1 & ZmmReg1) ... & rm32; imm8 +{ + local tmp:4 = rm32; + local cond0:1 = (imm8:1 & 0x3) == 0; + local cond1:1 = (imm8:1 & 0x3) == 1; + local cond2:1 = (imm8:1 & 0x3) == 2; + local cond3:1 = (imm8:1 & 0x3) == 3; + conditionalAssign(XmmReg1[ 0,32], cond0, tmp, vexVVVV_XmmReg[ 0,32]); + conditionalAssign(XmmReg1[32,32], cond0, tmp, vexVVVV_XmmReg[32,32]); + conditionalAssign(XmmReg1[64,32], cond0, tmp, vexVVVV_XmmReg[64,32]); + conditionalAssign(XmmReg1[96,32], cond0, tmp, vexVVVV_XmmReg[96,32]); + ZmmReg1 = zext(XmmReg1); +} + +# PINSRB/PINSRD/PINSRQ 4-293 PAGE 1413 LINE 73327 +#define pcodeop vpinsrq_avx ; +@ifdef IA64 +:VPINSRQ XmmReg1, vexVVVV_XmmReg, rm64, imm8 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x22; (XmmReg1 & ZmmReg1) ... & rm64; imm8 +{ + local tmp:8 = rm64; + local cond0:8 = zext((imm8:1 & 0x1) == 0); + local cond1:8 = zext((imm8:1 & 0x1) == 1); + # ignoring all but the least significant bit + XmmReg1[0,64] = (cond0 * tmp) + (cond1 * vexVVVV_XmmReg[0,64]); + XmmReg1[64,64] = (cond0 * vexVVVV_XmmReg[64,64]) + (cond1 * tmp); + ZmmReg1 = zext(XmmReg1); +} +@endif # PMOVMSKB 4-338 PAGE 1458 LINE 75651 :VPMOVMSKB Reg32, XmmReg2 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG); byte=0xD7; Reg32 & (mod=0x3 & XmmReg2) & check_Reg32_dest diff --git a/Ghidra/Processors/x86/data/languages/fma.sinc b/Ghidra/Processors/x86/data/languages/fma.sinc index 930a0f4e270..297d3af2c1b 100644 --- a/Ghidra/Processors/x86/data/languages/fma.sinc +++ b/Ghidra/Processors/x86/data/languages/fma.sinc @@ -1,740 +1,981 @@ # # x86 FMA instructions # +macro fmadd(dest, src1, src2, src3) { + dest = (src1 f* src2) f+ src3; +} +macro fmadd132(dest, src1, src2, src3) { + fmadd(dest, src1, src3, src2); +} + +macro fmadd213(dest, src1, src2, src3) { + fmadd(dest, src2, src1, src3); +} + +macro fmadd231(dest, src1, src2, src3) { + fmadd(dest, src2, src3, src1); +} + +macro fmsub(dest, src1, src2, src3) { + dest = (src1 f* src2) f- src3; +} + +macro fmsub132(dest, src1, src2, src3) { + fmsub(dest, src1, src3, src2); +} + +macro fmsub213(dest, src1, src2, src3) { + fmsub(dest, src2, src1, src3); +} + +macro fmsub231(dest, src1, src2, src3) { + fmsub(dest, src2, src3, src1); +} + +macro fnmadd(dest, src1, src2, src3) { + dest = f- (src1 f* src2) f+ src3; +} + +macro fnmadd132(dest, src1, src2, src3) { + fnmadd(dest, src1, src3, src2); +} + +macro fnmadd213(dest, src1, src2, src3) { + fnmadd(dest, src2, src1, src3); +} + +macro fnmadd231(dest, src1, src2, src3) { + fnmadd(dest, src2, src3, src1); +} + +macro fnmsub(dest, src1, src2, src3) { + dest = f- (src1 f* src2) f- src3; +} + +macro fnmsub132(dest, src1, src2, src3) { + fnmsub(dest, src1, src3, src2); +} + +macro fnmsub213(dest, src1, src2, src3) { + fnmsub(dest, src2, src1, src3); +} + +macro fnmsub231(dest, src1, src2, src3) { + fnmsub(dest, src2, src3, src1); +} -# VFIXUPIMMSD 5-120 PAGE 1944 LINE 101211 -define pcodeop vfmadd132pd_fma ; +# VFMADD132PD/VFMADD213PD/VFMADD231PD :VFMADD132PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x98; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfmadd132pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fmadd132(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m128[ 0,64]); + fmadd132(XmmReg1[64,64],XmmReg1[64,64],vexVVVV_XmmReg[64,64],XmmReg2_m128[64,64]); + ZmmReg1 = zext(XmmReg1); } -# VFIXUPIMMSD 5-120 PAGE 1944 LINE 101214 -define pcodeop vfmadd213pd_fma ; :VFMADD213PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xA8; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfmadd213pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + + fmadd213(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m128[ 0,64]); + fmadd213(XmmReg1[64,64],XmmReg1[64,64],vexVVVV_XmmReg[64,64],XmmReg2_m128[64,64]); + ZmmReg1 = zext(XmmReg1); } -# VFIXUPIMMSD 5-120 PAGE 1944 LINE 101217 -define pcodeop vfmadd231pd_fma ; :VFMADD231PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xB8; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfmadd231pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fmadd231(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m128[ 0,64]); + fmadd231(XmmReg1[64,64],XmmReg1[64,64],vexVVVV_XmmReg[64,64],XmmReg2_m128[64,64]); + ZmmReg1 = zext(XmmReg1); } -# VFIXUPIMMSD 5-120 PAGE 1944 LINE 101220 :VFMADD132PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0x98; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfmadd132pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fmadd132(YmmReg1[ 0,64], YmmReg1[ 0,64], vexVVVV_YmmReg[ 0,64], YmmReg2_m256[ 0,64]); + fmadd132(YmmReg1[ 64,64], YmmReg1[ 64,64], vexVVVV_YmmReg[ 64,64], YmmReg2_m256[ 64,64]); + fmadd132(YmmReg1[128,64], YmmReg1[128,64], vexVVVV_YmmReg[128,64], YmmReg2_m256[128,64]); + fmadd132(YmmReg1[192,64], YmmReg1[192,64], vexVVVV_YmmReg[192,64], YmmReg2_m256[192,64]); + ZmmReg1 = zext(YmmReg1); } -# VFIXUPIMMSD 5-120 PAGE 1944 LINE 101223 :VFMADD213PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xA8; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfmadd213pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fmadd213(YmmReg1[ 0,64], YmmReg1[ 0,64], vexVVVV_YmmReg[ 0,64], YmmReg2_m256[ 0,64]); + fmadd213(YmmReg1[ 64,64], YmmReg1[ 64,64], vexVVVV_YmmReg[ 64,64], YmmReg2_m256[ 64,64]); + fmadd213(YmmReg1[128,64], YmmReg1[128,64], vexVVVV_YmmReg[128,64], YmmReg2_m256[128,64]); + fmadd213(YmmReg1[192,64], YmmReg1[192,64], vexVVVV_YmmReg[192,64], YmmReg2_m256[192,64]); + ZmmReg1 = zext(YmmReg1); } -# VFIXUPIMMSD 5-120 PAGE 1944 LINE 101226 :VFMADD231PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xB8; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfmadd231pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fmadd231(YmmReg1[ 0,64], YmmReg1[ 0,64], vexVVVV_YmmReg[ 0,64], YmmReg2_m256[ 0,64]); + fmadd231(YmmReg1[ 64,64], YmmReg1[ 64,64], vexVVVV_YmmReg[ 64,64], YmmReg2_m256[ 64,64]); + fmadd231(YmmReg1[128,64], YmmReg1[128,64], vexVVVV_YmmReg[128,64], YmmReg2_m256[128,64]); + fmadd231(YmmReg1[192,64], YmmReg1[192,64], vexVVVV_YmmReg[192,64], YmmReg2_m256[192,64]); + ZmmReg1 = zext(YmmReg1); } -# VFIXUPIMMSS 5-127 PAGE 1951 LINE 101572 -define pcodeop vfmadd132ps_fma ; +# VFMADD132PS/VFMADD213PS/VFMADD231PS :VFMADD132PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x98; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfmadd132ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fmadd132(XmmReg1[ 0,32], XmmReg1[ 0,32], vexVVVV_XmmReg[ 0,32], XmmReg2_m128[ 0,32]); + fmadd132(XmmReg1[32,32], XmmReg1[32,32], vexVVVV_XmmReg[32,32], XmmReg2_m128[32,32]); + fmadd132(XmmReg1[64,32], XmmReg1[64,32], vexVVVV_XmmReg[64,32], XmmReg2_m128[64,32]); + fmadd132(XmmReg1[96,32], XmmReg1[96,32], vexVVVV_XmmReg[96,32], XmmReg2_m128[96,32]); + ZmmReg1 = zext(XmmReg1); } -# VFIXUPIMMSS 5-127 PAGE 1951 LINE 101575 -define pcodeop vfmadd213ps_fma ; :VFMADD213PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xA8; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfmadd213ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fmadd213(XmmReg1[ 0,32], XmmReg1[ 0,32], vexVVVV_XmmReg[ 0,32], XmmReg2_m128[ 0,32]); + fmadd213(XmmReg1[32,32], XmmReg1[32,32], vexVVVV_XmmReg[32,32], XmmReg2_m128[32,32]); + fmadd213(XmmReg1[64,32], XmmReg1[64,32], vexVVVV_XmmReg[64,32], XmmReg2_m128[64,32]); + fmadd213(XmmReg1[96,32], XmmReg1[96,32], vexVVVV_XmmReg[96,32], XmmReg2_m128[96,32]); + ZmmReg1 = zext(XmmReg1); } -# VFIXUPIMMSS 5-127 PAGE 1951 LINE 101578 -define pcodeop vfmadd231ps_fma ; :VFMADD231PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xB8; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfmadd231ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fmadd231(XmmReg1[ 0,32], XmmReg1[ 0,32], vexVVVV_XmmReg[ 0,32], XmmReg2_m128[ 0,32]); + fmadd231(XmmReg1[32,32], XmmReg1[32,32], vexVVVV_XmmReg[32,32], XmmReg2_m128[32,32]); + fmadd231(XmmReg1[64,32], XmmReg1[64,32], vexVVVV_XmmReg[64,32], XmmReg2_m128[64,32]); + fmadd231(XmmReg1[96,32], XmmReg1[96,32], vexVVVV_XmmReg[96,32], XmmReg2_m128[96,32]); + ZmmReg1 = zext(XmmReg1); } -# VFIXUPIMMSS 5-127 PAGE 1951 LINE 101581 :VFMADD132PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0x98; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfmadd132ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fmadd132(YmmReg1[ 0,32], YmmReg1[ 0,32], vexVVVV_YmmReg[ 0,32], YmmReg2_m256[ 0,32]); + fmadd132(YmmReg1[ 32,32], YmmReg1[ 32,32], vexVVVV_YmmReg[ 32,32], YmmReg2_m256[ 32,32]); + fmadd132(YmmReg1[ 64,32], YmmReg1[ 64,32], vexVVVV_YmmReg[ 64,32], YmmReg2_m256[ 64,32]); + fmadd132(YmmReg1[ 96,32], YmmReg1[ 96,32], vexVVVV_YmmReg[ 96,32], YmmReg2_m256[ 96,32]); + fmadd132(YmmReg1[128,32], YmmReg1[128,32], vexVVVV_YmmReg[128,32], YmmReg2_m256[128,32]); + fmadd132(YmmReg1[160,32], YmmReg1[160,32], vexVVVV_YmmReg[160,32], YmmReg2_m256[160,32]); + fmadd132(YmmReg1[192,32], YmmReg1[192,32], vexVVVV_YmmReg[192,32], YmmReg2_m256[192,32]); + fmadd132(YmmReg1[224,32], YmmReg1[224,32], vexVVVV_YmmReg[224,32], YmmReg2_m256[224,32]); + ZmmReg1 = zext(YmmReg1); } -# VFIXUPIMMSS 5-127 PAGE 1951 LINE 101584 :VFMADD213PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xA8; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfmadd213ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fmadd213(YmmReg1[ 0,32], YmmReg1[ 0,32], vexVVVV_YmmReg[ 0,32], YmmReg2_m256[ 0,32]); + fmadd213(YmmReg1[ 32,32], YmmReg1[ 32,32], vexVVVV_YmmReg[ 32,32], YmmReg2_m256[ 32,32]); + fmadd213(YmmReg1[ 64,32], YmmReg1[ 64,32], vexVVVV_YmmReg[ 64,32], YmmReg2_m256[ 64,32]); + fmadd213(YmmReg1[ 96,32], YmmReg1[ 96,32], vexVVVV_YmmReg[ 96,32], YmmReg2_m256[ 96,32]); + fmadd213(YmmReg1[128,32], YmmReg1[128,32], vexVVVV_YmmReg[128,32], YmmReg2_m256[128,32]); + fmadd213(YmmReg1[160,32], YmmReg1[160,32], vexVVVV_YmmReg[160,32], YmmReg2_m256[160,32]); + fmadd213(YmmReg1[192,32], YmmReg1[192,32], vexVVVV_YmmReg[192,32], YmmReg2_m256[192,32]); + fmadd213(YmmReg1[224,32], YmmReg1[224,32], vexVVVV_YmmReg[224,32], YmmReg2_m256[224,32]); + ZmmReg1 = zext(YmmReg1); } -# VFIXUPIMMSS 5-127 PAGE 1951 LINE 101587 -# WARNING: did not recognize VEX field 0 for "VFMADD231PS ymm1, ymm2, ymm3/m256" :VFMADD231PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xB8; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfmadd231ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fmadd231(YmmReg1[ 0,32], YmmReg1[ 0,32], vexVVVV_YmmReg[ 0,32], YmmReg2_m256[ 0,32]); + fmadd231(YmmReg1[ 32,32], YmmReg1[ 32,32], vexVVVV_YmmReg[ 32,32], YmmReg2_m256[ 32,32]); + fmadd231(YmmReg1[ 64,32], YmmReg1[ 64,32], vexVVVV_YmmReg[ 64,32], YmmReg2_m256[ 64,32]); + fmadd231(YmmReg1[ 96,32], YmmReg1[ 96,32], vexVVVV_YmmReg[ 96,32], YmmReg2_m256[ 96,32]); + fmadd231(YmmReg1[128,32], YmmReg1[128,32], vexVVVV_YmmReg[128,32], YmmReg2_m256[128,32]); + fmadd231(YmmReg1[160,32], YmmReg1[160,32], vexVVVV_YmmReg[160,32], YmmReg2_m256[160,32]); + fmadd231(YmmReg1[192,32], YmmReg1[192,32], vexVVVV_YmmReg[192,32], YmmReg2_m256[192,32]); + fmadd231(YmmReg1[224,32], YmmReg1[224,32], vexVVVV_YmmReg[224,32], YmmReg2_m256[224,32]); + ZmmReg1 = zext(YmmReg1); } -# VFMADD132PS/VFMADD213PS/VFMADD231PS 5-134 PAGE 1958 LINE 101931 -define pcodeop vfmadd132sd_fma ; +# VFMADD132SD/VFMADD213SD/VFMADD231SD :VFMADD132SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x99; (XmmReg1 & ZmmReg1) ... & XmmReg2_m64 { - local tmp:16 = vfmadd132sd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 ); - ZmmReg1 = zext(tmp); + fmadd132(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m64[ 0,64]); + # XmmReg1[64,64] = XmmReg1[64,64]; + ZmmReg1 = zext(XmmReg1); } -# VFMADD132PS/VFMADD213PS/VFMADD231PS 5-134 PAGE 1958 LINE 101934 -define pcodeop vfmadd213sd_fma ; :VFMADD213SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xA9; (XmmReg1 & ZmmReg1) ... & XmmReg2_m64 { - local tmp:16 = vfmadd213sd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 ); - ZmmReg1 = zext(tmp); + fmadd213(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m64[ 0,64]); + # XmmReg1[64,64] = XmmReg1[64,64]; + ZmmReg1 = zext(XmmReg1); } -# VFMADD132PS/VFMADD213PS/VFMADD231PS 5-134 PAGE 1958 LINE 101937 -define pcodeop vfmadd231sd_fma ; :VFMADD231SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xB9; (XmmReg1 & ZmmReg1) ... & XmmReg2_m64 { - local tmp:16 = vfmadd231sd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 ); - ZmmReg1 = zext(tmp); + fmadd231(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m64[ 0,64]); + # XmmReg1[64,64] = XmmReg1[64,64]; + ZmmReg1 = zext(XmmReg1); } -# VFMADD132SS/VFMADD213SS/VFMADD231SS 5-137 PAGE 1961 LINE 102099 -define pcodeop vfmadd132ss_fma ; +# VFMADD132SS/VFMADD213SS/VFMADD231SS :VFMADD132SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x99; (XmmReg1 & ZmmReg1) ... & XmmReg2_m32 { - local tmp:16 = vfmadd132ss_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 ); - ZmmReg1 = zext(tmp); + fmadd132(XmmReg1[ 0,32], XmmReg1[ 0,32], vexVVVV_XmmReg[ 0,32], XmmReg2_m32[ 0,32]); + # XmmReg1[32,96] = XmmReg1[32,96]; + ZmmReg1 = zext(XmmReg1); } -# VFMADD132SS/VFMADD213SS/VFMADD231SS 5-137 PAGE 1961 LINE 102102 -define pcodeop vfmadd213ss_fma ; :VFMADD213SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xA9; (XmmReg1 & ZmmReg1) ... & XmmReg2_m32 { - local tmp:16 = vfmadd213ss_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 ); - ZmmReg1 = zext(tmp); + fmadd213(XmmReg1[ 0,32], XmmReg1[ 0,32], vexVVVV_XmmReg[ 0,32], XmmReg2_m32[ 0,32]); + # XmmReg1[32,96] = XmmReg1[32,96]; + ZmmReg1 = zext(XmmReg1); } -# VFMADD132SS/VFMADD213SS/VFMADD231SS 5-137 PAGE 1961 LINE 102105 -define pcodeop vfmadd231ss_fma ; :VFMADD231SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xB9; (XmmReg1 & ZmmReg1) ... & XmmReg2_m32 { - local tmp:16 = vfmadd231ss_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 ); - ZmmReg1 = zext(tmp); + fmadd231(XmmReg1[ 0,32], XmmReg1[ 0,32], vexVVVV_XmmReg[ 0,32], XmmReg2_m32[ 0,32]); + # XmmReg1[32,96] = XmmReg1[32,96]; + ZmmReg1 = zext(XmmReg1); } -# VFMADDSUB132PD/VFMADDSUB213PD/VFMADDSUB231PD 5-140 PAGE 1964 LINE 102272 -define pcodeop vfmaddsub132pd_fma ; +# VFMADDSUB132PD/VFMADDSUB213PD/VFMADDSUB231PD :VFMADDSUB132PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x96; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfmaddsub132pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fmsub132(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m128[ 0,64]); + fmadd132(XmmReg1[64,64],XmmReg1[64,64],vexVVVV_XmmReg[64,64],XmmReg2_m128[64,64]); + ZmmReg1 = zext(XmmReg1); } -# VFMADDSUB132PD/VFMADDSUB213PD/VFMADDSUB231PD 5-140 PAGE 1964 LINE 102275 -define pcodeop vfmaddsub213pd_fma ; :VFMADDSUB213PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xA6; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfmaddsub213pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fmsub213(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m128[ 0,64]); + fmadd213(XmmReg1[64,64],XmmReg1[64,64],vexVVVV_XmmReg[64,64],XmmReg2_m128[64,64]); + ZmmReg1 = zext(XmmReg1); } -# VFMADDSUB132PD/VFMADDSUB213PD/VFMADDSUB231PD 5-140 PAGE 1964 LINE 102278 -define pcodeop vfmaddsub231pd_fma ; :VFMADDSUB231PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xB6; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfmaddsub231pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fmsub231(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m128[ 0,64]); + fmadd231(XmmReg1[64,64],XmmReg1[64,64],vexVVVV_XmmReg[64,64],XmmReg2_m128[64,64]); + ZmmReg1 = zext(XmmReg1); } -# VFMADDSUB132PD/VFMADDSUB213PD/VFMADDSUB231PD 5-140 PAGE 1964 LINE 102281 :VFMADDSUB132PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0x96; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfmaddsub132pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fmsub132(YmmReg1[ 0,64],YmmReg1[ 0,64],vexVVVV_YmmReg[ 0,64],YmmReg2_m256[ 0,64]); + fmadd132(YmmReg1[ 64,64],YmmReg1[ 64,64],vexVVVV_YmmReg[ 64,64],YmmReg2_m256[ 64,64]); + fmsub132(YmmReg1[128,64],YmmReg1[128,64],vexVVVV_YmmReg[128,64],YmmReg2_m256[128,64]); + fmadd132(YmmReg1[192,64],YmmReg1[192,64],vexVVVV_YmmReg[192,64],YmmReg2_m256[192,64]); + ZmmReg1 = zext(YmmReg1); } -# VFMADDSUB132PD/VFMADDSUB213PD/VFMADDSUB231PD 5-140 PAGE 1964 LINE 102284 :VFMADDSUB213PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xA6; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfmaddsub213pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fmsub213(YmmReg1[ 0,64],YmmReg1[ 0,64],vexVVVV_YmmReg[ 0,64],YmmReg2_m256[ 0,64]); + fmadd213(YmmReg1[ 64,64],YmmReg1[ 64,64],vexVVVV_YmmReg[ 64,64],YmmReg2_m256[ 64,64]); + fmsub213(YmmReg1[128,64],YmmReg1[128,64],vexVVVV_YmmReg[128,64],YmmReg2_m256[128,64]); + fmadd213(YmmReg1[192,64],YmmReg1[192,64],vexVVVV_YmmReg[192,64],YmmReg2_m256[192,64]); + ZmmReg1 = zext(YmmReg1); } -# VFMADDSUB132PD/VFMADDSUB213PD/VFMADDSUB231PD 5-140 PAGE 1964 LINE 102287 :VFMADDSUB231PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xB6; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfmaddsub231pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fmsub231(YmmReg1[ 0,64],YmmReg1[ 0,64],vexVVVV_YmmReg[ 0,64],YmmReg2_m256[ 0,64]); + fmadd231(YmmReg1[ 64,64],YmmReg1[ 64,64],vexVVVV_YmmReg[ 64,64],YmmReg2_m256[ 64,64]); + fmsub231(YmmReg1[128,64],YmmReg1[128,64],vexVVVV_YmmReg[128,64],YmmReg2_m256[128,64]); + fmadd231(YmmReg1[192,64],YmmReg1[192,64],vexVVVV_YmmReg[192,64],YmmReg2_m256[192,64]); + ZmmReg1 = zext(YmmReg1); } -# VFMADD132SS/VFMADD213SS/VFMADD231SS 5-150 PAGE 1974 LINE 102711 -define pcodeop vfmaddsub132ps_fma ; +# VFMADDSUB132PS/VFMADDSUB213PS/VFMADDSUB231PS :VFMADDSUB132PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x96; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfmaddsub132ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fmsub132(XmmReg1[ 0,32],XmmReg1[ 0,32],vexVVVV_XmmReg[ 0,32],XmmReg2_m128[ 0,32]); + fmadd132(XmmReg1[32,32],XmmReg1[32,32],vexVVVV_XmmReg[32,32],XmmReg2_m128[32,32]); + fmsub132(XmmReg1[64,32],XmmReg1[64,32],vexVVVV_XmmReg[64,32],XmmReg2_m128[64,32]); + fmadd132(XmmReg1[96,32],XmmReg1[96,32],vexVVVV_XmmReg[96,32],XmmReg2_m128[96,32]); + ZmmReg1 = zext(XmmReg1); } -# VFMADD132SS/VFMADD213SS/VFMADD231SS 5-150 PAGE 1974 LINE 102714 -define pcodeop vfmaddsub213ps_fma ; :VFMADDSUB213PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xA6; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfmaddsub213ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fmsub213(XmmReg1[ 0,32],XmmReg1[ 0,32],vexVVVV_XmmReg[ 0,32],XmmReg2_m128[ 0,32]); + fmadd213(XmmReg1[32,32],XmmReg1[32,32],vexVVVV_XmmReg[32,32],XmmReg2_m128[32,32]); + fmsub213(XmmReg1[64,32],XmmReg1[64,32],vexVVVV_XmmReg[64,32],XmmReg2_m128[64,32]); + fmadd213(XmmReg1[96,32],XmmReg1[96,32],vexVVVV_XmmReg[96,32],XmmReg2_m128[96,32]); + ZmmReg1 = zext(XmmReg1); } -# VFMADD132SS/VFMADD213SS/VFMADD231SS 5-150 PAGE 1974 LINE 102717 -define pcodeop vfmaddsub231ps_fma ; :VFMADDSUB231PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xB6; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfmaddsub231ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fmsub231(XmmReg1[ 0,32],XmmReg1[ 0,32],vexVVVV_XmmReg[ 0,32],XmmReg2_m128[ 0,32]); + fmadd231(XmmReg1[32,32],XmmReg1[32,32],vexVVVV_XmmReg[32,32],XmmReg2_m128[32,32]); + fmsub231(XmmReg1[64,32],XmmReg1[64,32],vexVVVV_XmmReg[64,32],XmmReg2_m128[64,32]); + fmadd231(XmmReg1[96,32],XmmReg1[96,32],vexVVVV_XmmReg[96,32],XmmReg2_m128[96,32]); + ZmmReg1 = zext(XmmReg1); } -# VFMADD132SS/VFMADD213SS/VFMADD231SS 5-150 PAGE 1974 LINE 102720 :VFMADDSUB132PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0x96; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfmaddsub132ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fmsub132(YmmReg1[ 0,32], YmmReg1[ 0,32], vexVVVV_YmmReg[ 0,32], YmmReg2_m256[ 0,32]); + fmadd132(YmmReg1[ 32,32], YmmReg1[ 32,32], vexVVVV_YmmReg[ 32,32], YmmReg2_m256[ 32,32]); + fmsub132(YmmReg1[ 64,32], YmmReg1[ 64,32], vexVVVV_YmmReg[ 64,32], YmmReg2_m256[ 64,32]); + fmadd132(YmmReg1[ 96,32], YmmReg1[ 96,32], vexVVVV_YmmReg[ 96,32], YmmReg2_m256[ 96,32]); + fmsub132(YmmReg1[128,32], YmmReg1[128,32], vexVVVV_YmmReg[128,32], YmmReg2_m256[128,32]); + fmadd132(YmmReg1[160,32], YmmReg1[160,32], vexVVVV_YmmReg[160,32], YmmReg2_m256[160,32]); + fmsub132(YmmReg1[192,32], YmmReg1[192,32], vexVVVV_YmmReg[192,32], YmmReg2_m256[192,32]); + fmadd132(YmmReg1[224,32], YmmReg1[224,32], vexVVVV_YmmReg[224,32], YmmReg2_m256[224,32]); + ZmmReg1 = zext(YmmReg1); } -# VFMADD132SS/VFMADD213SS/VFMADD231SS 5-150 PAGE 1974 LINE 102723 :VFMADDSUB213PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xA6; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfmaddsub213ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fmsub213(YmmReg1[ 0,32], YmmReg1[ 0,32], vexVVVV_YmmReg[ 0,32], YmmReg2_m256[ 0,32]); + fmadd213(YmmReg1[ 32,32], YmmReg1[ 32,32], vexVVVV_YmmReg[ 32,32], YmmReg2_m256[ 32,32]); + fmsub213(YmmReg1[ 64,32], YmmReg1[ 64,32], vexVVVV_YmmReg[ 64,32], YmmReg2_m256[ 64,32]); + fmadd213(YmmReg1[ 96,32], YmmReg1[ 96,32], vexVVVV_YmmReg[ 96,32], YmmReg2_m256[ 96,32]); + fmsub213(YmmReg1[128,32], YmmReg1[128,32], vexVVVV_YmmReg[128,32], YmmReg2_m256[128,32]); + fmadd213(YmmReg1[160,32], YmmReg1[160,32], vexVVVV_YmmReg[160,32], YmmReg2_m256[160,32]); + fmsub213(YmmReg1[192,32], YmmReg1[192,32], vexVVVV_YmmReg[192,32], YmmReg2_m256[192,32]); + fmadd213(YmmReg1[224,32], YmmReg1[224,32], vexVVVV_YmmReg[224,32], YmmReg2_m256[224,32]); + ZmmReg1 = zext(YmmReg1); } -# VFMADD132SS/VFMADD213SS/VFMADD231SS 5-150 PAGE 1974 LINE 102726 :VFMADDSUB231PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xB6; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfmaddsub231ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fmsub231(YmmReg1[ 0,32], YmmReg1[ 0,32], vexVVVV_YmmReg[ 0,32], YmmReg2_m256[ 0,32]); + fmadd231(YmmReg1[ 32,32], YmmReg1[ 32,32], vexVVVV_YmmReg[ 32,32], YmmReg2_m256[ 32,32]); + fmsub231(YmmReg1[ 64,32], YmmReg1[ 64,32], vexVVVV_YmmReg[ 64,32], YmmReg2_m256[ 64,32]); + fmadd231(YmmReg1[ 96,32], YmmReg1[ 96,32], vexVVVV_YmmReg[ 96,32], YmmReg2_m256[ 96,32]); + fmsub231(YmmReg1[128,32], YmmReg1[128,32], vexVVVV_YmmReg[128,32], YmmReg2_m256[128,32]); + fmadd231(YmmReg1[160,32], YmmReg1[160,32], vexVVVV_YmmReg[160,32], YmmReg2_m256[160,32]); + fmsub231(YmmReg1[192,32], YmmReg1[192,32], vexVVVV_YmmReg[192,32], YmmReg2_m256[192,32]); + fmadd231(YmmReg1[224,32], YmmReg1[224,32], vexVVVV_YmmReg[224,32], YmmReg2_m256[224,32]); + ZmmReg1 = zext(YmmReg1); } -# VFMSUBADD132PD/VFMSUBADD213PD/VFMSUBADD231PD 5-159 PAGE 1983 LINE 103141 -define pcodeop vfmsubadd132pd_fma ; -:VFMSUBADD132PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x97; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 +# VFMSUB132PD/VFMSUB213PD/VFMSUB231PD +:VFMSUB132PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x9A; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfmsubadd132pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fmsub132(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m128[ 0,64]); + fmsub132(XmmReg1[64,64],XmmReg1[64,64],vexVVVV_XmmReg[64,64],XmmReg2_m128[64,64]); + ZmmReg1 = zext(XmmReg1); } -# VFMSUBADD132PD/VFMSUBADD213PD/VFMSUBADD231PD 5-159 PAGE 1983 LINE 103144 -define pcodeop vfmsubadd213pd_fma ; -:VFMSUBADD213PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xA7; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 +# VFMSUB132PD/VFMSUB213PD/VFMSUB231PD +:VFMSUB213PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xAA; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfmsubadd213pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fmsub213(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m128[ 0,64]); + fmsub213(XmmReg1[64,64],XmmReg1[64,64],vexVVVV_XmmReg[64,64],XmmReg2_m128[64,64]); + ZmmReg1 = zext(XmmReg1); } -# VFMSUBADD132PD/VFMSUBADD213PD/VFMSUBADD231PD 5-159 PAGE 1983 LINE 103147 -define pcodeop vfmsubadd231pd_fma ; -:VFMSUBADD231PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xB7; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 +# VFMSUB132PD/VFMSUB213PD/VFMSUB231PD +:VFMSUB231PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xBA; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfmsubadd231pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fmsub231(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m128[ 0,64]); + fmsub231(XmmReg1[64,64],XmmReg1[64,64],vexVVVV_XmmReg[64,64],XmmReg2_m128[64,64]); + ZmmReg1 = zext(XmmReg1); } -# VFMSUBADD132PD/VFMSUBADD213PD/VFMSUBADD231PD 5-159 PAGE 1983 LINE 103150 -:VFMSUBADD132PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0x97; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 +# VFMSUB132PD/VFMSUB213PD/VFMSUB231PD +:VFMSUB132PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0x9A; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfmsubadd132pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fmsub132(YmmReg1[ 0,64], YmmReg1[ 0,64], vexVVVV_YmmReg[ 0,64], YmmReg2_m256[ 0,64]); + fmsub132(YmmReg1[ 64,64], YmmReg1[ 64,64], vexVVVV_YmmReg[ 64,64], YmmReg2_m256[ 64,64]); + fmsub132(YmmReg1[128,64], YmmReg1[128,64], vexVVVV_YmmReg[128,64], YmmReg2_m256[128,64]); + fmsub132(YmmReg1[192,64], YmmReg1[192,64], vexVVVV_YmmReg[192,64], YmmReg2_m256[192,64]); + ZmmReg1 = zext(YmmReg1); } -# VFMSUBADD132PD/VFMSUBADD213PD/VFMSUBADD231PD 5-159 PAGE 1983 LINE 103153 -:VFMSUBADD213PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xA7; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 +# VFMSUB132PD/VFMSUB213PD/VFMSUB231PD +:VFMSUB213PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xAA; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfmsubadd213pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fmsub213(YmmReg1[ 0,64], YmmReg1[ 0,64], vexVVVV_YmmReg[ 0,64], YmmReg2_m256[ 0,64]); + fmsub213(YmmReg1[ 64,64], YmmReg1[ 64,64], vexVVVV_YmmReg[ 64,64], YmmReg2_m256[ 64,64]); + fmsub213(YmmReg1[128,64], YmmReg1[128,64], vexVVVV_YmmReg[128,64], YmmReg2_m256[128,64]); + fmsub213(YmmReg1[192,64], YmmReg1[192,64], vexVVVV_YmmReg[192,64], YmmReg2_m256[192,64]); + ZmmReg1 = zext(YmmReg1); } -# VFMSUBADD132PD/VFMSUBADD213PD/VFMSUBADD231PD 5-159 PAGE 1983 LINE 103156 -:VFMSUBADD231PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xB7; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 +# VFMSUB132PD/VFMSUB213PD/VFMSUB231PD +:VFMSUB231PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xBA; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfmsubadd231pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fmsub231(YmmReg1[ 0,64], YmmReg1[ 0,64], vexVVVV_YmmReg[ 0,64], YmmReg2_m256[ 0,64]); + fmsub231(YmmReg1[ 64,64], YmmReg1[ 64,64], vexVVVV_YmmReg[ 64,64], YmmReg2_m256[ 64,64]); + fmsub231(YmmReg1[128,64], YmmReg1[128,64], vexVVVV_YmmReg[128,64], YmmReg2_m256[128,64]); + fmsub231(YmmReg1[192,64], YmmReg1[192,64], vexVVVV_YmmReg[192,64], YmmReg2_m256[192,64]); + ZmmReg1 = zext(YmmReg1); } -# VFMSUBADD132PS/VFMSUBADD213PS/VFMSUBADD231PS 5-169 PAGE 1993 LINE 103581 -define pcodeop vfmsubadd132ps_fma ; -:VFMSUBADD132PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x97; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 +# VFMSUB132PS/VFMSUB213PS/VFMSUB231PS +:VFMSUB132PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x9A; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfmsubadd132ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fmsub132(XmmReg1[ 0,32], XmmReg1[ 0,32], vexVVVV_XmmReg[ 0,32], XmmReg2_m128[ 0,32]); + fmsub132(XmmReg1[32,32], XmmReg1[32,32], vexVVVV_XmmReg[32,32], XmmReg2_m128[32,32]); + fmsub132(XmmReg1[64,32], XmmReg1[64,32], vexVVVV_XmmReg[64,32], XmmReg2_m128[64,32]); + fmsub132(XmmReg1[96,32], XmmReg1[96,32], vexVVVV_XmmReg[96,32], XmmReg2_m128[96,32]); + ZmmReg1 = zext(XmmReg1); } -# VFMSUBADD132PS/VFMSUBADD213PS/VFMSUBADD231PS 5-169 PAGE 1993 LINE 103584 -define pcodeop vfmsubadd213ps_fma ; -:VFMSUBADD213PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xA7; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 +# VFMSUB132PS/VFMSUB213PS/VFMSUB231PS +:VFMSUB213PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xAA; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfmsubadd213ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fmsub213(XmmReg1[ 0,32], XmmReg1[ 0,32], vexVVVV_XmmReg[ 0,32], XmmReg2_m128[ 0,32]); + fmsub213(XmmReg1[32,32], XmmReg1[32,32], vexVVVV_XmmReg[32,32], XmmReg2_m128[32,32]); + fmsub213(XmmReg1[64,32], XmmReg1[64,32], vexVVVV_XmmReg[64,32], XmmReg2_m128[64,32]); + fmsub213(XmmReg1[96,32], XmmReg1[96,32], vexVVVV_XmmReg[96,32], XmmReg2_m128[96,32]); + ZmmReg1 = zext(XmmReg1); } -# VFMSUBADD132PS/VFMSUBADD213PS/VFMSUBADD231PS 5-169 PAGE 1993 LINE 103587 -define pcodeop vfmsubadd231ps_fma ; -:VFMSUBADD231PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xB7; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 +# VFMSUB132PS/VFMSUB213PS/VFMSUB231PS +:VFMSUB231PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xBA; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfmsubadd231ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fmsub231(XmmReg1[ 0,32], XmmReg1[ 0,32], vexVVVV_XmmReg[ 0,32], XmmReg2_m128[ 0,32]); + fmsub231(XmmReg1[32,32], XmmReg1[32,32], vexVVVV_XmmReg[32,32], XmmReg2_m128[32,32]); + fmsub231(XmmReg1[64,32], XmmReg1[64,32], vexVVVV_XmmReg[64,32], XmmReg2_m128[64,32]); + fmsub231(XmmReg1[96,32], XmmReg1[96,32], vexVVVV_XmmReg[96,32], XmmReg2_m128[96,32]); + ZmmReg1 = zext(XmmReg1); } -# VFMSUBADD132PS/VFMSUBADD213PS/VFMSUBADD231PS 5-169 PAGE 1993 LINE 103590 -:VFMSUBADD132PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0x97; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 +# VFMSUB132PS/VFMSUB213PS/VFMSUB231PS +:VFMSUB132PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0x9A; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfmsubadd132ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fmsub132(YmmReg1[ 0,32], YmmReg1[ 0,32], vexVVVV_YmmReg[ 0,32], YmmReg2_m256[ 0,32]); + fmsub132(YmmReg1[ 32,32], YmmReg1[ 32,32], vexVVVV_YmmReg[ 32,32], YmmReg2_m256[ 32,32]); + fmsub132(YmmReg1[ 64,32], YmmReg1[ 64,32], vexVVVV_YmmReg[ 64,32], YmmReg2_m256[ 64,32]); + fmsub132(YmmReg1[ 96,32], YmmReg1[ 96,32], vexVVVV_YmmReg[ 96,32], YmmReg2_m256[ 96,32]); + fmsub132(YmmReg1[128,32], YmmReg1[128,32], vexVVVV_YmmReg[128,32], YmmReg2_m256[128,32]); + fmsub132(YmmReg1[160,32], YmmReg1[160,32], vexVVVV_YmmReg[160,32], YmmReg2_m256[160,32]); + fmsub132(YmmReg1[192,32], YmmReg1[192,32], vexVVVV_YmmReg[192,32], YmmReg2_m256[192,32]); + fmsub132(YmmReg1[224,32], YmmReg1[224,32], vexVVVV_YmmReg[224,32], YmmReg2_m256[224,32]); + ZmmReg1 = zext(YmmReg1); } -# VFMSUBADD132PS/VFMSUBADD213PS/VFMSUBADD231PS 5-169 PAGE 1993 LINE 103593 -:VFMSUBADD213PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xA7; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 +# VFMSUB132PS/VFMSUB213PS/VFMSUB231PS +:VFMSUB213PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xAA; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfmsubadd213ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fmsub213(YmmReg1[ 0,32], YmmReg1[ 0,32], vexVVVV_YmmReg[ 0,32], YmmReg2_m256[ 0,32]); + fmsub213(YmmReg1[ 32,32], YmmReg1[ 32,32], vexVVVV_YmmReg[ 32,32], YmmReg2_m256[ 32,32]); + fmsub213(YmmReg1[ 64,32], YmmReg1[ 64,32], vexVVVV_YmmReg[ 64,32], YmmReg2_m256[ 64,32]); + fmsub213(YmmReg1[ 96,32], YmmReg1[ 96,32], vexVVVV_YmmReg[ 96,32], YmmReg2_m256[ 96,32]); + fmsub213(YmmReg1[128,32], YmmReg1[128,32], vexVVVV_YmmReg[128,32], YmmReg2_m256[128,32]); + fmsub213(YmmReg1[160,32], YmmReg1[160,32], vexVVVV_YmmReg[160,32], YmmReg2_m256[160,32]); + fmsub213(YmmReg1[192,32], YmmReg1[192,32], vexVVVV_YmmReg[192,32], YmmReg2_m256[192,32]); + fmsub213(YmmReg1[224,32], YmmReg1[224,32], vexVVVV_YmmReg[224,32], YmmReg2_m256[224,32]); + ZmmReg1 = zext(YmmReg1); } -# VFMSUBADD132PS/VFMSUBADD213PS/VFMSUBADD231PS 5-169 PAGE 1993 LINE 103596 -:VFMSUBADD231PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xB7; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 +# VFMSUB132PS/VFMSUB213PS/VFMSUB231PS +:VFMSUB231PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xBA; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfmsubadd231ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fmsub231(YmmReg1[ 0,32], YmmReg1[ 0,32], vexVVVV_YmmReg[ 0,32], YmmReg2_m256[ 0,32]); + fmsub231(YmmReg1[ 32,32], YmmReg1[ 32,32], vexVVVV_YmmReg[ 32,32], YmmReg2_m256[ 32,32]); + fmsub231(YmmReg1[ 64,32], YmmReg1[ 64,32], vexVVVV_YmmReg[ 64,32], YmmReg2_m256[ 64,32]); + fmsub231(YmmReg1[ 96,32], YmmReg1[ 96,32], vexVVVV_YmmReg[ 96,32], YmmReg2_m256[ 96,32]); + fmsub231(YmmReg1[128,32], YmmReg1[128,32], vexVVVV_YmmReg[128,32], YmmReg2_m256[128,32]); + fmsub231(YmmReg1[160,32], YmmReg1[160,32], vexVVVV_YmmReg[160,32], YmmReg2_m256[160,32]); + fmsub231(YmmReg1[192,32], YmmReg1[192,32], vexVVVV_YmmReg[192,32], YmmReg2_m256[192,32]); + fmsub231(YmmReg1[224,32], YmmReg1[224,32], vexVVVV_YmmReg[224,32], YmmReg2_m256[224,32]); + ZmmReg1 = zext(YmmReg1); } -# VFMSUB132PD/VFMSUB213PD/VFMSUB231PD 5-179 PAGE 2003 LINE 104019 -define pcodeop vfmsub132pd_fma ; -:VFMSUB132PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x9A; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 +# VFMSUB132SD/VFMSUB213SD/VFMSUB231SD +:VFMSUB132SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x9B; (XmmReg1 & ZmmReg1) ... & XmmReg2_m64 { - local tmp:16 = vfmsub132pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fmsub132(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m64[ 0,64]); + # XmmReg1[64,64] = XmmReg1[64,64]; + ZmmReg1 = zext(XmmReg1); } -# VFMSUB132PD/VFMSUB213PD/VFMSUB231PD 5-179 PAGE 2003 LINE 104022 -define pcodeop vfmsub213pd_fma ; -:VFMSUB213PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xAA; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 +# VFMSUB132SD/VFMSUB213SD/VFMSUB231SD +:VFMSUB213SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xAB; (XmmReg1 & ZmmReg1) ... & XmmReg2_m64 { - local tmp:16 = vfmsub213pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fmsub213(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m64[ 0,64]); + # XmmReg1[64,64] = XmmReg1[64,64]; + ZmmReg1 = zext(XmmReg1); } -# VFMSUB132PD/VFMSUB213PD/VFMSUB231PD 5-179 PAGE 2003 LINE 104025 -define pcodeop vfmsub231pd_fma ; -:VFMSUB231PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xBA; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 +# VFMSUB132SD/VFMSUB213SD/VFMSUB231SD +:VFMSUB231SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xBB; (XmmReg1 & ZmmReg1) ... & XmmReg2_m64 { - local tmp:16 = vfmsub231pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fmsub231(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m64[ 0,64]); + # XmmReg1[64,64] = XmmReg1[64,64]; + ZmmReg1 = zext(XmmReg1); } -# VFMSUB132PD/VFMSUB213PD/VFMSUB231PD 5-179 PAGE 2003 LINE 104028 -:VFMSUB132PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0x9A; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 +# VFMSUB132SS/VFMSUB213SS/VFMSUB231SS +:VFMSUB132SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x9B; (XmmReg1 & ZmmReg1) ... & XmmReg2_m32 { - local tmp:16 = vfmsub132pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fmsub132(XmmReg1[ 0,32], XmmReg1[ 0,32], vexVVVV_XmmReg[ 0,32], XmmReg2_m32[ 0,32]); + # XmmReg1[32,96] = XmmReg1[32,96]; + ZmmReg1 = zext(XmmReg1); } -# VFMSUB132PD/VFMSUB213PD/VFMSUB231PD 5-179 PAGE 2003 LINE 104031 -:VFMSUB213PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xAA; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 +# VFMSUB132SS/VFMSUB213SS/VFMSUB231SS +:VFMSUB213SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xAB; (XmmReg1 & ZmmReg1) ... & XmmReg2_m32 { - local tmp:16 = vfmsub213pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fmsub213(XmmReg1[ 0,32], XmmReg1[ 0,32], vexVVVV_XmmReg[ 0,32], XmmReg2_m32[ 0,32]); + # XmmReg1[32,96] = XmmReg1[32,96]; + ZmmReg1 = zext(XmmReg1); } -# VFMSUB132PD/VFMSUB213PD/VFMSUB231PD 5-179 PAGE 2003 LINE 104034 -:VFMSUB231PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xBA; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 +# VFMSUB132SS/VFMSUB213SS/VFMSUB231SS +:VFMSUB231SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xBB; (XmmReg1 & ZmmReg1) ... & XmmReg2_m32 { - local tmp:16 = vfmsub231pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fmsub231(XmmReg1[ 0,32], XmmReg1[ 0,32], vexVVVV_XmmReg[ 0,32], XmmReg2_m32[ 0,32]); + # XmmReg1[32,96] = XmmReg1[32,96]; + ZmmReg1 = zext(XmmReg1); } -# VFMSUB132PS/VFMSUB213PS/VFMSUB231PS 5-186 PAGE 2010 LINE 104379 -define pcodeop vfmsub132ps_fma ; -:VFMSUB132PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x9A; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 +# VFMSUBADD132PD/VFMSUBADD213PD/VFMSUBADD231PD +:VFMSUBADD132PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x97; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfmsub132ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fmadd132(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m128[ 0,64]); + fmsub132(XmmReg1[64,64],XmmReg1[64,64],vexVVVV_XmmReg[64,64],XmmReg2_m128[64,64]); + ZmmReg1 = zext(XmmReg1); } -# VFMSUB132PS/VFMSUB213PS/VFMSUB231PS 5-186 PAGE 2010 LINE 104382 -define pcodeop vfmsub213ps_fma ; -:VFMSUB213PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xAA; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 +:VFMSUBADD213PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xA7; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfmsub213ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fmadd213(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m128[ 0,64]); + fmsub213(XmmReg1[64,64],XmmReg1[64,64],vexVVVV_XmmReg[64,64],XmmReg2_m128[64,64]); + ZmmReg1 = zext(XmmReg1); } -# VFMSUB132PS/VFMSUB213PS/VFMSUB231PS 5-186 PAGE 2010 LINE 104385 -define pcodeop vfmsub231ps_fma ; -:VFMSUB231PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xBA; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 +:VFMSUBADD231PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xB7; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfmsub231ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fmadd231(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m128[ 0,64]); + fmsub231(XmmReg1[64,64],XmmReg1[64,64],vexVVVV_XmmReg[64,64],XmmReg2_m128[64,64]); + ZmmReg1 = zext(XmmReg1); } -# VFMSUB132PS/VFMSUB213PS/VFMSUB231PS 5-186 PAGE 2010 LINE 104388 -:VFMSUB132PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0x9A; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 +:VFMSUBADD132PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0x97; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfmsub132ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fmadd132(YmmReg1[ 0,64],YmmReg1[ 0,64],vexVVVV_YmmReg[ 0,64],YmmReg2_m256[ 0,64]); + fmsub132(YmmReg1[ 64,64],YmmReg1[ 64,64],vexVVVV_YmmReg[ 64,64],YmmReg2_m256[ 64,64]); + fmadd132(YmmReg1[128,64],YmmReg1[128,64],vexVVVV_YmmReg[128,64],YmmReg2_m256[128,64]); + fmsub132(YmmReg1[192,64],YmmReg1[192,64],vexVVVV_YmmReg[192,64],YmmReg2_m256[192,64]); + ZmmReg1 = zext(YmmReg1); } -# VFMSUB132PS/VFMSUB213PS/VFMSUB231PS 5-186 PAGE 2010 LINE 104391 -:VFMSUB213PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xAA; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 +:VFMSUBADD213PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xA7; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfmsub213ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fmadd213(YmmReg1[ 0,64],YmmReg1[ 0,64],vexVVVV_YmmReg[ 0,64],YmmReg2_m256[ 0,64]); + fmsub213(YmmReg1[ 64,64],YmmReg1[ 64,64],vexVVVV_YmmReg[ 64,64],YmmReg2_m256[ 64,64]); + fmadd213(YmmReg1[128,64],YmmReg1[128,64],vexVVVV_YmmReg[128,64],YmmReg2_m256[128,64]); + fmsub213(YmmReg1[192,64],YmmReg1[192,64],vexVVVV_YmmReg[192,64],YmmReg2_m256[192,64]); + ZmmReg1 = zext(YmmReg1); } -# VFMSUB132PS/VFMSUB213PS/VFMSUB231PS 5-186 PAGE 2010 LINE 104394 -# WARNING: did not recognize VEX field 0 for "VFMSUB231PS ymm1, ymm2, ymm3/m256" -:VFMSUB231PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xBA; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 +:VFMSUBADD231PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xB7; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfmsub231ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fmadd231(YmmReg1[ 0,64],YmmReg1[ 0,64],vexVVVV_YmmReg[ 0,64],YmmReg2_m256[ 0,64]); + fmsub231(YmmReg1[ 64,64],YmmReg1[ 64,64],vexVVVV_YmmReg[ 64,64],YmmReg2_m256[ 64,64]); + fmadd231(YmmReg1[128,64],YmmReg1[128,64],vexVVVV_YmmReg[128,64],YmmReg2_m256[128,64]); + fmsub231(YmmReg1[192,64],YmmReg1[192,64],vexVVVV_YmmReg[192,64],YmmReg2_m256[192,64]); + ZmmReg1 = zext(YmmReg1); } -# VFMSUB132SD/VFMSUB213SD/VFMSUB231SD 5-193 PAGE 2017 LINE 104738 -define pcodeop vfmsub132sd_fma ; -:VFMSUB132SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x9B; (XmmReg1 & ZmmReg1) ... & XmmReg2_m64 +# VFMSUBADD132PS/VFMSUBADD213PS/VFMSUBADD231PS +:VFMSUBADD132PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x97; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfmsub132sd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 ); - ZmmReg1 = zext(tmp); + fmadd132(XmmReg1[ 0,32],XmmReg1[ 0,32],vexVVVV_XmmReg[ 0,32],XmmReg2_m128[ 0,32]); + fmsub132(XmmReg1[32,32],XmmReg1[32,32],vexVVVV_XmmReg[32,32],XmmReg2_m128[32,32]); + fmadd132(XmmReg1[64,32],XmmReg1[64,32],vexVVVV_XmmReg[64,32],XmmReg2_m128[64,32]); + fmsub132(XmmReg1[96,32],XmmReg1[96,32],vexVVVV_XmmReg[96,32],XmmReg2_m128[96,32]); + ZmmReg1 = zext(XmmReg1); } -# VFMSUB132SD/VFMSUB213SD/VFMSUB231SD 5-193 PAGE 2017 LINE 104741 -define pcodeop vfmsub213sd_fma ; -:VFMSUB213SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xAB; (XmmReg1 & ZmmReg1) ... & XmmReg2_m64 +:VFMSUBADD213PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xA7; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfmsub213sd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 ); - ZmmReg1 = zext(tmp); + fmadd213(XmmReg1[ 0,32],XmmReg1[ 0,32],vexVVVV_XmmReg[ 0,32],XmmReg2_m128[ 0,32]); + fmsub213(XmmReg1[32,32],XmmReg1[32,32],vexVVVV_XmmReg[32,32],XmmReg2_m128[32,32]); + fmadd213(XmmReg1[64,32],XmmReg1[64,32],vexVVVV_XmmReg[64,32],XmmReg2_m128[64,32]); + fmsub213(XmmReg1[96,32],XmmReg1[96,32],vexVVVV_XmmReg[96,32],XmmReg2_m128[96,32]); + ZmmReg1 = zext(XmmReg1); } -# VFMSUB132SD/VFMSUB213SD/VFMSUB231SD 5-193 PAGE 2017 LINE 104744 -define pcodeop vfmsub231sd_fma ; -:VFMSUB231SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xBB; (XmmReg1 & ZmmReg1) ... & XmmReg2_m64 +:VFMSUBADD231PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xB7; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfmsub231sd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 ); - ZmmReg1 = zext(tmp); + fmadd231(XmmReg1[ 0,32],XmmReg1[ 0,32],vexVVVV_XmmReg[ 0,32],XmmReg2_m128[ 0,32]); + fmsub231(XmmReg1[32,32],XmmReg1[32,32],vexVVVV_XmmReg[32,32],XmmReg2_m128[32,32]); + fmadd231(XmmReg1[64,32],XmmReg1[64,32],vexVVVV_XmmReg[64,32],XmmReg2_m128[64,32]); + fmsub231(XmmReg1[96,32],XmmReg1[96,32],vexVVVV_XmmReg[96,32],XmmReg2_m128[96,32]); + ZmmReg1 = zext(XmmReg1); } -# VFMSUB132SS/VFMSUB213SS/VFMSUB231SS 5-196 PAGE 2020 LINE 104913 -define pcodeop vfmsub132ss_fma ; -:VFMSUB132SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x9B; (XmmReg1 & ZmmReg1) ... & XmmReg2_m32 +:VFMSUBADD132PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0x97; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfmsub132ss_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 ); - ZmmReg1 = zext(tmp); + fmadd132(YmmReg1[ 0,32], YmmReg1[ 0,32], vexVVVV_YmmReg[ 0,32], YmmReg2_m256[ 0,32]); + fmsub132(YmmReg1[ 32,32], YmmReg1[ 32,32], vexVVVV_YmmReg[ 32,32], YmmReg2_m256[ 32,32]); + fmadd132(YmmReg1[ 64,32], YmmReg1[ 64,32], vexVVVV_YmmReg[ 64,32], YmmReg2_m256[ 64,32]); + fmsub132(YmmReg1[ 96,32], YmmReg1[ 96,32], vexVVVV_YmmReg[ 96,32], YmmReg2_m256[ 96,32]); + fmadd132(YmmReg1[128,32], YmmReg1[128,32], vexVVVV_YmmReg[128,32], YmmReg2_m256[128,32]); + fmsub132(YmmReg1[160,32], YmmReg1[160,32], vexVVVV_YmmReg[160,32], YmmReg2_m256[160,32]); + fmadd132(YmmReg1[192,32], YmmReg1[192,32], vexVVVV_YmmReg[192,32], YmmReg2_m256[192,32]); + fmsub132(YmmReg1[224,32], YmmReg1[224,32], vexVVVV_YmmReg[224,32], YmmReg2_m256[224,32]); + ZmmReg1 = zext(YmmReg1); } -# VFMSUB132SS/VFMSUB213SS/VFMSUB231SS 5-196 PAGE 2020 LINE 104916 -define pcodeop vfmsub213ss_fma ; -:VFMSUB213SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xAB; (XmmReg1 & ZmmReg1) ... & XmmReg2_m32 +:VFMSUBADD213PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xA7; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfmsub213ss_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 ); - ZmmReg1 = zext(tmp); + fmadd213(YmmReg1[ 0,32], YmmReg1[ 0,32], vexVVVV_YmmReg[ 0,32], YmmReg2_m256[ 0,32]); + fmsub213(YmmReg1[ 32,32], YmmReg1[ 32,32], vexVVVV_YmmReg[ 32,32], YmmReg2_m256[ 32,32]); + fmadd213(YmmReg1[ 64,32], YmmReg1[ 64,32], vexVVVV_YmmReg[ 64,32], YmmReg2_m256[ 64,32]); + fmsub213(YmmReg1[ 96,32], YmmReg1[ 96,32], vexVVVV_YmmReg[ 96,32], YmmReg2_m256[ 96,32]); + fmadd213(YmmReg1[128,32], YmmReg1[128,32], vexVVVV_YmmReg[128,32], YmmReg2_m256[128,32]); + fmsub213(YmmReg1[160,32], YmmReg1[160,32], vexVVVV_YmmReg[160,32], YmmReg2_m256[160,32]); + fmadd213(YmmReg1[192,32], YmmReg1[192,32], vexVVVV_YmmReg[192,32], YmmReg2_m256[192,32]); + fmsub213(YmmReg1[224,32], YmmReg1[224,32], vexVVVV_YmmReg[224,32], YmmReg2_m256[224,32]); + ZmmReg1 = zext(YmmReg1); } -# VFMSUB132SS/VFMSUB213SS/VFMSUB231SS 5-196 PAGE 2020 LINE 104919 -define pcodeop vfmsub231ss_fma ; -:VFMSUB231SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xBB; (XmmReg1 & ZmmReg1) ... & XmmReg2_m32 +:VFMSUBADD231PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xB7; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfmsub231ss_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 ); - ZmmReg1 = zext(tmp); + fmadd231(YmmReg1[ 0,32], YmmReg1[ 0,32], vexVVVV_YmmReg[ 0,32], YmmReg2_m256[ 0,32]); + fmsub231(YmmReg1[ 32,32], YmmReg1[ 32,32], vexVVVV_YmmReg[ 32,32], YmmReg2_m256[ 32,32]); + fmadd231(YmmReg1[ 64,32], YmmReg1[ 64,32], vexVVVV_YmmReg[ 64,32], YmmReg2_m256[ 64,32]); + fmsub231(YmmReg1[ 96,32], YmmReg1[ 96,32], vexVVVV_YmmReg[ 96,32], YmmReg2_m256[ 96,32]); + fmadd231(YmmReg1[128,32], YmmReg1[128,32], vexVVVV_YmmReg[128,32], YmmReg2_m256[128,32]); + fmsub231(YmmReg1[160,32], YmmReg1[160,32], vexVVVV_YmmReg[160,32], YmmReg2_m256[160,32]); + fmadd231(YmmReg1[192,32], YmmReg1[192,32], vexVVVV_YmmReg[192,32], YmmReg2_m256[192,32]); + fmsub231(YmmReg1[224,32], YmmReg1[224,32], vexVVVV_YmmReg[224,32], YmmReg2_m256[224,32]); + ZmmReg1 = zext(YmmReg1); } -# VFNMADD132PD/VFNMADD213PD/VFNMADD231PD 5-199 PAGE 2023 LINE 105088 -define pcodeop vfnmadd132pd_fma ; +# VFNMADD132PD/VFNMADD213PD/VFNMADD231PD :VFNMADD132PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x9C; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfnmadd132pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fnmadd132(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m128[ 0,64]); + fnmadd132(XmmReg1[64,64],XmmReg1[64,64],vexVVVV_XmmReg[64,64],XmmReg2_m128[64,64]); + ZmmReg1 = zext(XmmReg1); } -# VFNMADD132PD/VFNMADD213PD/VFNMADD231PD 5-199 PAGE 2023 LINE 105091 -define pcodeop vfnmadd213pd_fma ; +# VFNMADD132PD/VFNMADD213PD/VFNMADD231PD :VFNMADD213PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xAC; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfnmadd213pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fnmadd213(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m128[ 0,64]); + fnmadd213(XmmReg1[64,64],XmmReg1[64,64],vexVVVV_XmmReg[64,64],XmmReg2_m128[64,64]); + ZmmReg1 = zext(XmmReg1); } -# VFNMADD132PD/VFNMADD213PD/VFNMADD231PD 5-199 PAGE 2023 LINE 105094 -define pcodeop vfnmadd231pd_fma ; +# VFNMADD132PD/VFNMADD213PD/VFNMADD231PD :VFNMADD231PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xBC; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfnmadd231pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fnmadd231(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m128[ 0,64]); + fnmadd231(XmmReg1[64,64],XmmReg1[64,64],vexVVVV_XmmReg[64,64],XmmReg2_m128[64,64]); + ZmmReg1 = zext(XmmReg1); } -# VFNMADD132PD/VFNMADD213PD/VFNMADD231PD 5-199 PAGE 2023 LINE 105097 +# VFNMADD132PD/VFNMADD213PD/VFNMADD231PD :VFNMADD132PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0x9C; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfnmadd132pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fnmadd132(YmmReg1[ 0,64], YmmReg1[ 0,64], vexVVVV_YmmReg[ 0,64], YmmReg2_m256[ 0,64]); + fnmadd132(YmmReg1[ 64,64], YmmReg1[ 64,64], vexVVVV_YmmReg[ 64,64], YmmReg2_m256[ 64,64]); + fnmadd132(YmmReg1[128,64], YmmReg1[128,64], vexVVVV_YmmReg[128,64], YmmReg2_m256[128,64]); + fnmadd132(YmmReg1[192,64], YmmReg1[192,64], vexVVVV_YmmReg[192,64], YmmReg2_m256[192,64]); + ZmmReg1 = zext(YmmReg1); } -# VFNMADD132PD/VFNMADD213PD/VFNMADD231PD 5-199 PAGE 2023 LINE 105100 +# VFNMADD132PD/VFNMADD213PD/VFNMADD231PD :VFNMADD213PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xAC; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfnmadd213pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fnmadd213(YmmReg1[ 0,64], YmmReg1[ 0,64], vexVVVV_YmmReg[ 0,64], YmmReg2_m256[ 0,64]); + fnmadd213(YmmReg1[ 64,64], YmmReg1[ 64,64], vexVVVV_YmmReg[ 64,64], YmmReg2_m256[ 64,64]); + fnmadd213(YmmReg1[128,64], YmmReg1[128,64], vexVVVV_YmmReg[128,64], YmmReg2_m256[128,64]); + fnmadd213(YmmReg1[192,64], YmmReg1[192,64], vexVVVV_YmmReg[192,64], YmmReg2_m256[192,64]); + ZmmReg1 = zext(YmmReg1); } -# VFNMADD132PD/VFNMADD213PD/VFNMADD231PD 5-199 PAGE 2023 LINE 105103 +# VFNMADD132PD/VFNMADD213PD/VFNMADD231PD :VFNMADD231PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xBC; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfnmadd231pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fnmadd231(YmmReg1[ 0,64], YmmReg1[ 0,64], vexVVVV_YmmReg[ 0,64], YmmReg2_m256[ 0,64]); + fnmadd231(YmmReg1[ 64,64], YmmReg1[ 64,64], vexVVVV_YmmReg[ 64,64], YmmReg2_m256[ 64,64]); + fnmadd231(YmmReg1[128,64], YmmReg1[128,64], vexVVVV_YmmReg[128,64], YmmReg2_m256[128,64]); + fnmadd231(YmmReg1[192,64], YmmReg1[192,64], vexVVVV_YmmReg[192,64], YmmReg2_m256[192,64]); + ZmmReg1 = zext(YmmReg1); } -# VFNMADD132PS/VFNMADD213PS/VFNMADD231PS 5-206 PAGE 2030 LINE 105447 -define pcodeop vfnmadd132ps_fma ; +# VFNMADD132PS/VFNMADD213PS/VFNMADD231PS :VFNMADD132PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x9C; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfnmadd132ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fnmadd132(XmmReg1[ 0,32], XmmReg1[ 0,32], vexVVVV_XmmReg[ 0,32], XmmReg2_m128[ 0,32]); + fnmadd132(XmmReg1[32,32], XmmReg1[32,32], vexVVVV_XmmReg[32,32], XmmReg2_m128[32,32]); + fnmadd132(XmmReg1[64,32], XmmReg1[64,32], vexVVVV_XmmReg[64,32], XmmReg2_m128[64,32]); + fnmadd132(XmmReg1[96,32], XmmReg1[96,32], vexVVVV_XmmReg[96,32], XmmReg2_m128[96,32]); + ZmmReg1 = zext(XmmReg1); } -# VFNMADD132PS/VFNMADD213PS/VFNMADD231PS 5-206 PAGE 2030 LINE 105450 -define pcodeop vfnmadd213ps_fma ; +# VFNMADD132PS/VFNMADD213PS/VFNMADD231PS :VFNMADD213PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xAC; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfnmadd213ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fnmadd213(XmmReg1[ 0,32], XmmReg1[ 0,32], vexVVVV_XmmReg[ 0,32], XmmReg2_m128[ 0,32]); + fnmadd213(XmmReg1[32,32], XmmReg1[32,32], vexVVVV_XmmReg[32,32], XmmReg2_m128[32,32]); + fnmadd213(XmmReg1[64,32], XmmReg1[64,32], vexVVVV_XmmReg[64,32], XmmReg2_m128[64,32]); + fnmadd213(XmmReg1[96,32], XmmReg1[96,32], vexVVVV_XmmReg[96,32], XmmReg2_m128[96,32]); + ZmmReg1 = zext(XmmReg1); } -# VFNMADD132PS/VFNMADD213PS/VFNMADD231PS 5-206 PAGE 2030 LINE 105453 -define pcodeop vfnmadd231ps_fma ; +# VFNMADD132PS/VFNMADD213PS/VFNMADD231PS :VFNMADD231PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xBC; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfnmadd231ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fnmadd231(XmmReg1[ 0,32], XmmReg1[ 0,32], vexVVVV_XmmReg[ 0,32], XmmReg2_m128[ 0,32]); + fnmadd231(XmmReg1[32,32], XmmReg1[32,32], vexVVVV_XmmReg[32,32], XmmReg2_m128[32,32]); + fnmadd231(XmmReg1[64,32], XmmReg1[64,32], vexVVVV_XmmReg[64,32], XmmReg2_m128[64,32]); + fnmadd231(XmmReg1[96,32], XmmReg1[96,32], vexVVVV_XmmReg[96,32], XmmReg2_m128[96,32]); + ZmmReg1 = zext(XmmReg1); } -# VFNMADD132PS/VFNMADD213PS/VFNMADD231PS 5-206 PAGE 2030 LINE 105456 +# VFNMADD132PS/VFNMADD213PS/VFNMADD231PS :VFNMADD132PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0x9C; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfnmadd132ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fnmadd132(YmmReg1[ 0,32], YmmReg1[ 0,32], vexVVVV_YmmReg[ 0,32], YmmReg2_m256[ 0,32]); + fnmadd132(YmmReg1[ 32,32], YmmReg1[ 32,32], vexVVVV_YmmReg[ 32,32], YmmReg2_m256[ 32,32]); + fnmadd132(YmmReg1[ 64,32], YmmReg1[ 64,32], vexVVVV_YmmReg[ 64,32], YmmReg2_m256[ 64,32]); + fnmadd132(YmmReg1[ 96,32], YmmReg1[ 96,32], vexVVVV_YmmReg[ 96,32], YmmReg2_m256[ 96,32]); + fnmadd132(YmmReg1[128,32], YmmReg1[128,32], vexVVVV_YmmReg[128,32], YmmReg2_m256[128,32]); + fnmadd132(YmmReg1[160,32], YmmReg1[160,32], vexVVVV_YmmReg[160,32], YmmReg2_m256[160,32]); + fnmadd132(YmmReg1[192,32], YmmReg1[192,32], vexVVVV_YmmReg[192,32], YmmReg2_m256[192,32]); + fnmadd132(YmmReg1[224,32], YmmReg1[224,32], vexVVVV_YmmReg[224,32], YmmReg2_m256[224,32]); + ZmmReg1 = zext(YmmReg1); } -# VFNMADD132PS/VFNMADD213PS/VFNMADD231PS 5-206 PAGE 2030 LINE 105459 +# VFNMADD132PS/VFNMADD213PS/VFNMADD231PS 5-206 :VFNMADD213PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xAC; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfnmadd213ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fnmadd213(YmmReg1[ 0,32], YmmReg1[ 0,32], vexVVVV_YmmReg[ 0,32], YmmReg2_m256[ 0,32]); + fnmadd213(YmmReg1[ 32,32], YmmReg1[ 32,32], vexVVVV_YmmReg[ 32,32], YmmReg2_m256[ 32,32]); + fnmadd213(YmmReg1[ 64,32], YmmReg1[ 64,32], vexVVVV_YmmReg[ 64,32], YmmReg2_m256[ 64,32]); + fnmadd213(YmmReg1[ 96,32], YmmReg1[ 96,32], vexVVVV_YmmReg[ 96,32], YmmReg2_m256[ 96,32]); + fnmadd213(YmmReg1[128,32], YmmReg1[128,32], vexVVVV_YmmReg[128,32], YmmReg2_m256[128,32]); + fnmadd213(YmmReg1[160,32], YmmReg1[160,32], vexVVVV_YmmReg[160,32], YmmReg2_m256[160,32]); + fnmadd213(YmmReg1[192,32], YmmReg1[192,32], vexVVVV_YmmReg[192,32], YmmReg2_m256[192,32]); + fnmadd213(YmmReg1[224,32], YmmReg1[224,32], vexVVVV_YmmReg[224,32], YmmReg2_m256[224,32]); + ZmmReg1 = zext(YmmReg1); } -# VFNMADD132PS/VFNMADD213PS/VFNMADD231PS 5-206 PAGE 2030 LINE 105462 -# WARNING: did not recognize VEX field 0 for "VFNMADD231PS ymm1, ymm2, ymm3/m256" +# VFNMADD132PS/VFNMADD213PS/VFNMADD231PS :VFNMADD231PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xBC; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfnmadd231ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fnmadd231(YmmReg1[ 0,32], YmmReg1[ 0,32], vexVVVV_YmmReg[ 0,32], YmmReg2_m256[ 0,32]); + fnmadd231(YmmReg1[ 32,32], YmmReg1[ 32,32], vexVVVV_YmmReg[ 32,32], YmmReg2_m256[ 32,32]); + fnmadd231(YmmReg1[ 64,32], YmmReg1[ 64,32], vexVVVV_YmmReg[ 64,32], YmmReg2_m256[ 64,32]); + fnmadd231(YmmReg1[ 96,32], YmmReg1[ 96,32], vexVVVV_YmmReg[ 96,32], YmmReg2_m256[ 96,32]); + fnmadd231(YmmReg1[128,32], YmmReg1[128,32], vexVVVV_YmmReg[128,32], YmmReg2_m256[128,32]); + fnmadd231(YmmReg1[160,32], YmmReg1[160,32], vexVVVV_YmmReg[160,32], YmmReg2_m256[160,32]); + fnmadd231(YmmReg1[192,32], YmmReg1[192,32], vexVVVV_YmmReg[192,32], YmmReg2_m256[192,32]); + fnmadd231(YmmReg1[224,32], YmmReg1[224,32], vexVVVV_YmmReg[224,32], YmmReg2_m256[224,32]); + ZmmReg1 = zext(YmmReg1); } -# VFNMADD132SD/VFNMADD213SD/VFNMADD231SD 5-212 PAGE 2036 LINE 105794 -define pcodeop vfnmadd132sd_fma ; +# VFNMADD132SD/VFNMADD213SD/VFNMADD231SD :VFNMADD132SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x9D; (XmmReg1 & ZmmReg1) ... & XmmReg2_m64 { - local tmp:16 = vfnmadd132sd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 ); - ZmmReg1 = zext(tmp); + fnmadd132(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m64[ 0,64]); + # XmmReg1[64,64] = XmmReg1[64,64]; + ZmmReg1 = zext(XmmReg1); } -# VFNMADD132SD/VFNMADD213SD/VFNMADD231SD 5-212 PAGE 2036 LINE 105797 -define pcodeop vfnmadd213sd_fma ; +# VFNMADD132SD/VFNMADD213SD/VFNMADD231SD :VFNMADD213SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xAD; (XmmReg1 & ZmmReg1) ... & XmmReg2_m64 { - local tmp:16 = vfnmadd213sd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 ); - ZmmReg1 = zext(tmp); + fnmadd213(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m64[ 0,64]); + # XmmReg1[64,64] = XmmReg1[64,64]; + ZmmReg1 = zext(XmmReg1); } -# VFNMADD132SD/VFNMADD213SD/VFNMADD231SD 5-212 PAGE 2036 LINE 105800 -define pcodeop vfnmadd231sd_fma ; +# VFNMADD132SD/VFNMADD213SD/VFNMADD231SD :VFNMADD231SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xBD; (XmmReg1 & ZmmReg1) ... & XmmReg2_m64 { - local tmp:16 = vfnmadd231sd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 ); - ZmmReg1 = zext(tmp); + fnmadd231(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m64[ 0,64]); + # XmmReg1[64,64] = XmmReg1[64,64]; + ZmmReg1 = zext(XmmReg1); } -# VFNMADD132SS/VFNMADD213SS/VFNMADD231SS 5-215 PAGE 2039 LINE 105966 -define pcodeop vfnmadd132ss_fma ; +# VFNMADD132SS/VFNMADD213SS/VFNMADD231SS :VFNMADD132SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x9D; (XmmReg1 & ZmmReg1) ... & XmmReg2_m32 { - local tmp:16 = vfnmadd132ss_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 ); - ZmmReg1 = zext(tmp); + fnmadd132(XmmReg1[ 0,32], XmmReg1[ 0,32], vexVVVV_XmmReg[ 0,32], XmmReg2_m32[ 0,32]); + # XmmReg1[32,96] = XmmReg1[32,96]; + ZmmReg1 = zext(XmmReg1); } -# VFNMADD132SS/VFNMADD213SS/VFNMADD231SS 5-215 PAGE 2039 LINE 105969 -define pcodeop vfnmadd213ss_fma ; +# VFNMADD132SS/VFNMADD213SS/VFNMADD231SS :VFNMADD213SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xAD; (XmmReg1 & ZmmReg1) ... & XmmReg2_m32 { - local tmp:16 = vfnmadd213ss_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 ); - ZmmReg1 = zext(tmp); + fnmadd213(XmmReg1[ 0,32], XmmReg1[ 0,32], vexVVVV_XmmReg[ 0,32], XmmReg2_m32[ 0,32]); + # XmmReg1[32,96] = XmmReg1[32,96]; + ZmmReg1 = zext(XmmReg1); } -# VFNMADD132SS/VFNMADD213SS/VFNMADD231SS 5-215 PAGE 2039 LINE 105972 -define pcodeop vfnmadd231ss_fma ; +# VFNMADD132SS/VFNMADD213SS/VFNMADD231SS :VFNMADD231SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xBD; (XmmReg1 & ZmmReg1) ... & XmmReg2_m32 { - local tmp:16 = vfnmadd231ss_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 ); - ZmmReg1 = zext(tmp); + fnmadd231(XmmReg1[ 0,32], XmmReg1[ 0,32], vexVVVV_XmmReg[ 0,32], XmmReg2_m32[ 0,32]); + # XmmReg1[32,96] = XmmReg1[32,96]; + ZmmReg1 = zext(XmmReg1); } -# VFNMSUB132PD/VFNMSUB213PD/VFNMSUB231PD 5-218 PAGE 2042 LINE 106138 -define pcodeop vfnmsub132pd_fma ; +# VFNMSUB132PD/VFNMSUB213PD/VFNMSUB231PD :VFNMSUB132PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x9E; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfnmsub132pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fnmsub132(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m128[ 0,64]); + fnmsub132(XmmReg1[64,64],XmmReg1[64,64],vexVVVV_XmmReg[64,64],XmmReg2_m128[64,64]); + ZmmReg1 = zext(XmmReg1); } -# VFNMSUB132PD/VFNMSUB213PD/VFNMSUB231PD 5-218 PAGE 2042 LINE 106141 -define pcodeop vfnmsub213pd_fma ; +# VFNMSUB132PD/VFNMSUB213PD/VFNMSUB231PD :VFNMSUB213PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xAE; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfnmsub213pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fnmsub213(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m128[ 0,64]); + fnmsub213(XmmReg1[64,64],XmmReg1[64,64],vexVVVV_XmmReg[64,64],XmmReg2_m128[64,64]); + ZmmReg1 = zext(XmmReg1); } -# VFNMSUB132PD/VFNMSUB213PD/VFNMSUB231PD 5-218 PAGE 2042 LINE 106144 -define pcodeop vfnmsub231pd_fma ; +# VFNMSUB132PD/VFNMSUB213PD/VFNMSUB231PD :VFNMSUB231PD XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xBE; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfnmsub231pd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fnmsub231(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m128[ 0,64]); + fnmsub231(XmmReg1[64,64],XmmReg1[64,64],vexVVVV_XmmReg[64,64],XmmReg2_m128[64,64]); + ZmmReg1 = zext(XmmReg1); } -# VFNMSUB132PD/VFNMSUB213PD/VFNMSUB231PD 5-218 PAGE 2042 LINE 106147 +# VFNMSUB132PD/VFNMSUB213PD/VFNMSUB231PD :VFNMSUB132PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0x9E; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfnmsub132pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fnmsub132(YmmReg1[ 0,64], YmmReg1[ 0,64], vexVVVV_YmmReg[ 0,64], YmmReg2_m256[ 0,64]); + fnmsub132(YmmReg1[ 64,64], YmmReg1[ 64,64], vexVVVV_YmmReg[ 64,64], YmmReg2_m256[ 64,64]); + fnmsub132(YmmReg1[128,64], YmmReg1[128,64], vexVVVV_YmmReg[128,64], YmmReg2_m256[128,64]); + fnmsub132(YmmReg1[192,64], YmmReg1[192,64], vexVVVV_YmmReg[192,64], YmmReg2_m256[192,64]); + ZmmReg1 = zext(YmmReg1); } -# VFNMSUB132PD/VFNMSUB213PD/VFNMSUB231PD 5-218 PAGE 2042 LINE 106150 +# VFNMSUB132PD/VFNMSUB213PD/VFNMSUB231PD :VFNMSUB213PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xAE; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfnmsub213pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fnmsub213(YmmReg1[ 0,64], YmmReg1[ 0,64], vexVVVV_YmmReg[ 0,64], YmmReg2_m256[ 0,64]); + fnmsub213(YmmReg1[ 64,64], YmmReg1[ 64,64], vexVVVV_YmmReg[ 64,64], YmmReg2_m256[ 64,64]); + fnmsub213(YmmReg1[128,64], YmmReg1[128,64], vexVVVV_YmmReg[128,64], YmmReg2_m256[128,64]); + fnmsub213(YmmReg1[192,64], YmmReg1[192,64], vexVVVV_YmmReg[192,64], YmmReg2_m256[192,64]); + ZmmReg1 = zext(YmmReg1); } -# VFNMSUB132PD/VFNMSUB213PD/VFNMSUB231PD 5-218 PAGE 2042 LINE 106153 +# VFNMSUB132PD/VFNMSUB213PD/VFNMSUB231PD :VFNMSUB231PD YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0xBE; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfnmsub231pd_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fnmsub231(YmmReg1[ 0,64], YmmReg1[ 0,64], vexVVVV_YmmReg[ 0,64], YmmReg2_m256[ 0,64]); + fnmsub231(YmmReg1[ 64,64], YmmReg1[ 64,64], vexVVVV_YmmReg[ 64,64], YmmReg2_m256[ 64,64]); + fnmsub231(YmmReg1[128,64], YmmReg1[128,64], vexVVVV_YmmReg[128,64], YmmReg2_m256[128,64]); + fnmsub231(YmmReg1[192,64], YmmReg1[192,64], vexVVVV_YmmReg[192,64], YmmReg2_m256[192,64]); + ZmmReg1 = zext(YmmReg1); } -# VFNMSUB132PS/VFNMSUB213PS/VFNMSUB231PS 5-224 PAGE 2048 LINE 106487 -define pcodeop vfnmsub132ps_fma ; +# VFNMSUB132PS/VFNMSUB213PS/VFNMSUB231PS :VFNMSUB132PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x9E; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfnmsub132ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fnmsub132(XmmReg1[ 0,32], XmmReg1[ 0,32], vexVVVV_XmmReg[ 0,32], XmmReg2_m128[ 0,32]); + fnmsub132(XmmReg1[32,32], XmmReg1[32,32], vexVVVV_XmmReg[32,32], XmmReg2_m128[32,32]); + fnmsub132(XmmReg1[64,32], XmmReg1[64,32], vexVVVV_XmmReg[64,32], XmmReg2_m128[64,32]); + fnmsub132(XmmReg1[96,32], XmmReg1[96,32], vexVVVV_XmmReg[96,32], XmmReg2_m128[96,32]); + ZmmReg1 = zext(XmmReg1); } -# VFNMSUB132PS/VFNMSUB213PS/VFNMSUB231PS 5-224 PAGE 2048 LINE 106490 -define pcodeop vfnmsub213ps_fma ; +# VFNMSUB132PS/VFNMSUB213PS/VFNMSUB231PS :VFNMSUB213PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xAE; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfnmsub213ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fnmsub213(XmmReg1[ 0,32], XmmReg1[ 0,32], vexVVVV_XmmReg[ 0,32], XmmReg2_m128[ 0,32]); + fnmsub213(XmmReg1[32,32], XmmReg1[32,32], vexVVVV_XmmReg[32,32], XmmReg2_m128[32,32]); + fnmsub213(XmmReg1[64,32], XmmReg1[64,32], vexVVVV_XmmReg[64,32], XmmReg2_m128[64,32]); + fnmsub213(XmmReg1[96,32], XmmReg1[96,32], vexVVVV_XmmReg[96,32], XmmReg2_m128[96,32]); + ZmmReg1 = zext(XmmReg1); } -# VFNMSUB132PS/VFNMSUB213PS/VFNMSUB231PS 5-224 PAGE 2048 LINE 106493 -define pcodeop vfnmsub231ps_fma ; +# VFNMSUB132PS/VFNMSUB213PS/VFNMSUB231PS :VFNMSUB231PS XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 is $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xBE; (XmmReg1 & ZmmReg1) ... & XmmReg2_m128 { - local tmp:16 = vfnmsub231ps_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m128 ); - ZmmReg1 = zext(tmp); + fnmsub231(XmmReg1[ 0,32], XmmReg1[ 0,32], vexVVVV_XmmReg[ 0,32], XmmReg2_m128[ 0,32]); + fnmsub231(XmmReg1[32,32], XmmReg1[32,32], vexVVVV_XmmReg[32,32], XmmReg2_m128[32,32]); + fnmsub231(XmmReg1[64,32], XmmReg1[64,32], vexVVVV_XmmReg[64,32], XmmReg2_m128[64,32]); + fnmsub231(XmmReg1[96,32], XmmReg1[96,32], vexVVVV_XmmReg[96,32], XmmReg2_m128[96,32]); + ZmmReg1 = zext(XmmReg1); } -# VFNMSUB132PS/VFNMSUB213PS/VFNMSUB231PS 5-224 PAGE 2048 LINE 106496 +# VFNMSUB132PS/VFNMSUB213PS/VFNMSUB231PS :VFNMSUB132PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0x9E; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfnmsub132ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fnmsub132(YmmReg1[ 0,32], YmmReg1[ 0,32], vexVVVV_YmmReg[ 0,32], YmmReg2_m256[ 0,32]); + fnmsub132(YmmReg1[ 32,32], YmmReg1[ 32,32], vexVVVV_YmmReg[ 32,32], YmmReg2_m256[ 32,32]); + fnmsub132(YmmReg1[ 64,32], YmmReg1[ 64,32], vexVVVV_YmmReg[ 64,32], YmmReg2_m256[ 64,32]); + fnmsub132(YmmReg1[ 96,32], YmmReg1[ 96,32], vexVVVV_YmmReg[ 96,32], YmmReg2_m256[ 96,32]); + fnmsub132(YmmReg1[128,32], YmmReg1[128,32], vexVVVV_YmmReg[128,32], YmmReg2_m256[128,32]); + fnmsub132(YmmReg1[160,32], YmmReg1[160,32], vexVVVV_YmmReg[160,32], YmmReg2_m256[160,32]); + fnmsub132(YmmReg1[192,32], YmmReg1[192,32], vexVVVV_YmmReg[192,32], YmmReg2_m256[192,32]); + fnmsub132(YmmReg1[224,32], YmmReg1[224,32], vexVVVV_YmmReg[224,32], YmmReg2_m256[224,32]); + ZmmReg1 = zext(YmmReg1); } -# VFNMSUB132PS/VFNMSUB213PS/VFNMSUB231PS 5-224 PAGE 2048 LINE 106499 +# VFNMSUB132PS/VFNMSUB213PS/VFNMSUB231PS :VFNMSUB213PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xAE; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfnmsub213ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fnmsub213(YmmReg1[ 0,32], YmmReg1[ 0,32], vexVVVV_YmmReg[ 0,32], YmmReg2_m256[ 0,32]); + fnmsub213(YmmReg1[ 32,32], YmmReg1[ 32,32], vexVVVV_YmmReg[ 32,32], YmmReg2_m256[ 32,32]); + fnmsub213(YmmReg1[ 64,32], YmmReg1[ 64,32], vexVVVV_YmmReg[ 64,32], YmmReg2_m256[ 64,32]); + fnmsub213(YmmReg1[ 96,32], YmmReg1[ 96,32], vexVVVV_YmmReg[ 96,32], YmmReg2_m256[ 96,32]); + fnmsub213(YmmReg1[128,32], YmmReg1[128,32], vexVVVV_YmmReg[128,32], YmmReg2_m256[128,32]); + fnmsub213(YmmReg1[160,32], YmmReg1[160,32], vexVVVV_YmmReg[160,32], YmmReg2_m256[160,32]); + fnmsub213(YmmReg1[192,32], YmmReg1[192,32], vexVVVV_YmmReg[192,32], YmmReg2_m256[192,32]); + fnmsub213(YmmReg1[224,32], YmmReg1[224,32], vexVVVV_YmmReg[224,32], YmmReg2_m256[224,32]); + ZmmReg1 = zext(YmmReg1); } -# VFNMSUB132PS/VFNMSUB213PS/VFNMSUB231PS 5-224 PAGE 2048 LINE 106502 -# WARNING: did not recognize VEX field 0 for "VFNMSUB231PS ymm1, ymm2, ymm3/m256" +# VFNMSUB132PS/VFNMSUB213PS/VFNMSUB231PS :VFNMSUB231PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xBE; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256 { - local tmp:16 = vfnmsub231ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 ); - ZmmReg1 = zext(tmp); + fnmsub231(YmmReg1[ 0,32], YmmReg1[ 0,32], vexVVVV_YmmReg[ 0,32], YmmReg2_m256[ 0,32]); + fnmsub231(YmmReg1[ 32,32], YmmReg1[ 32,32], vexVVVV_YmmReg[ 32,32], YmmReg2_m256[ 32,32]); + fnmsub231(YmmReg1[ 64,32], YmmReg1[ 64,32], vexVVVV_YmmReg[ 64,32], YmmReg2_m256[ 64,32]); + fnmsub231(YmmReg1[ 96,32], YmmReg1[ 96,32], vexVVVV_YmmReg[ 96,32], YmmReg2_m256[ 96,32]); + fnmsub231(YmmReg1[128,32], YmmReg1[128,32], vexVVVV_YmmReg[128,32], YmmReg2_m256[128,32]); + fnmsub231(YmmReg1[160,32], YmmReg1[160,32], vexVVVV_YmmReg[160,32], YmmReg2_m256[160,32]); + fnmsub231(YmmReg1[192,32], YmmReg1[192,32], vexVVVV_YmmReg[192,32], YmmReg2_m256[192,32]); + fnmsub231(YmmReg1[224,32], YmmReg1[224,32], vexVVVV_YmmReg[224,32], YmmReg2_m256[224,32]); + ZmmReg1 = zext(YmmReg1); } -# VFNMSUB132SD/VFNMSUB213SD/VFNMSUB231SD 5-230 PAGE 2054 LINE 106832 -define pcodeop vfnmsub132sd_fma ; +# VFNMSUB132SD/VFNMSUB213SD/VFNMSUB231SD :VFNMSUB132SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x9F; (XmmReg1 & ZmmReg1) ... & XmmReg2_m64 { - local tmp:16 = vfnmsub132sd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 ); - ZmmReg1 = zext(tmp); + fnmsub132(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m64[ 0,64]); + # XmmReg1[64,64] = XmmReg1[64,64]; + ZmmReg1 = zext(XmmReg1); } -# VFNMSUB132SD/VFNMSUB213SD/VFNMSUB231SD 5-230 PAGE 2054 LINE 106835 -define pcodeop vfnmsub213sd_fma ; +# VFNMSUB132SD/VFNMSUB213SD/VFNMSUB231SD :VFNMSUB213SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xAF; (XmmReg1 & ZmmReg1) ... & XmmReg2_m64 { - local tmp:16 = vfnmsub213sd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 ); - ZmmReg1 = zext(tmp); + fnmsub213(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m64[ 0,64]); + # XmmReg1[64,64] = XmmReg1[64,64]; + ZmmReg1 = zext(XmmReg1); } -# VFNMSUB132SD/VFNMSUB213SD/VFNMSUB231SD 5-230 PAGE 2054 LINE 106838 -define pcodeop vfnmsub231sd_fma ; +# VFNMSUB132SD/VFNMSUB213SD/VFNMSUB231SD :VFNMSUB231SD XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0xBF; (XmmReg1 & ZmmReg1) ... & XmmReg2_m64 { - local tmp:16 = vfnmsub231sd_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m64 ); - ZmmReg1 = zext(tmp); + fnmsub231(XmmReg1[ 0,64],XmmReg1[ 0,64],vexVVVV_XmmReg[ 0,64],XmmReg2_m64[ 0,64]); + # XmmReg1[64,64] = XmmReg1[64,64]; + ZmmReg1 = zext(XmmReg1); } -# VFNMSUB132SS/VFNMSUB213SS/VFNMSUB231SS 5-233 PAGE 2057 LINE 107004 -define pcodeop vfnmsub132ss_fma ; +# VFNMSUB132SS/VFNMSUB213SS/VFNMSUB231SS :VFNMSUB132SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x9F; (XmmReg1 & ZmmReg1) ... & XmmReg2_m32 { - local tmp:16 = vfnmsub132ss_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 ); - ZmmReg1 = zext(tmp); + fnmsub132(XmmReg1[ 0,32], XmmReg1[ 0,32], vexVVVV_XmmReg[ 0,32], XmmReg2_m32[ 0,32]); + # XmmReg1[32,96] = XmmReg1[32,96]; + ZmmReg1 = zext(XmmReg1); } -# VFNMSUB132SS/VFNMSUB213SS/VFNMSUB231SS 5-233 PAGE 2057 LINE 107007 -define pcodeop vfnmsub213ss_fma ; +# VFNMSUB132SS/VFNMSUB213SS/VFNMSUB231SS :VFNMSUB213SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xAF; (XmmReg1 & ZmmReg1) ... & XmmReg2_m32 { - local tmp:16 = vfnmsub213ss_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 ); - ZmmReg1 = zext(tmp); + fnmsub213(XmmReg1[ 0,32], XmmReg1[ 0,32], vexVVVV_XmmReg[ 0,32], XmmReg2_m32[ 0,32]); + # XmmReg1[32,96] = XmmReg1[32,96]; + ZmmReg1 = zext(XmmReg1); } -# VFNMSUB132SS/VFNMSUB213SS/VFNMSUB231SS 5-233 PAGE 2057 LINE 107010 -define pcodeop vfnmsub231ss_fma ; +# VFNMSUB132SS/VFNMSUB213SS/VFNMSUB231SS :VFNMSUB231SS XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 is $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xBF; (XmmReg1 & ZmmReg1) ... & XmmReg2_m32 { - local tmp:16 = vfnmsub231ss_fma( XmmReg1, vexVVVV_XmmReg, XmmReg2_m32 ); - ZmmReg1 = zext(tmp); + fnmsub231(XmmReg1[ 0,32], XmmReg1[ 0,32], vexVVVV_XmmReg[ 0,32], XmmReg2_m32[ 0,32]); + # XmmReg1[32,96] = XmmReg1[32,96]; + ZmmReg1 = zext(XmmReg1); } From 1ea11b20df71c5c54dd2bed718e019479a7caf1a Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Wed, 10 Jun 2026 12:26:44 -0400 Subject: [PATCH 017/111] GP-6891 Improved Debugger Trace import/export support and added packed DBTrace GZT file type. --- .../main/java/ghidra/dbg/isf/IsfServer.java | 43 ++-- .../debug/export/TraceViewAsciiExporter.java | 27 --- .../debug/export/TraceViewBinaryExporter.java | 27 --- .../debug/export/TraceViewHtmlExporter.java | 27 --- .../export/TraceViewIntelHexExporter.java | 27 --- .../debug/export/TraceViewXmlExporter.java | 56 ----- .../debug/gui/export/TraceExportPlugin.java | 197 ++++++++++++++++++ .../DebuggerTraceManagerServicePlugin.java | 6 +- .../plugin/core/debug/utils/GztExporter.java | 122 +++++++++++ .../plugin/core/debug/utils/GztLoader.java | 177 ++++++++++++++++ .../gui/AbstractGhidraHeadedDebuggerTest.java | 2 +- .../trace/database/ToyDBTraceBuilder.java | 6 +- .../help/topics/ExporterPlugin/exporter.htm | 14 +- .../help/help/topics/Glossary/glossary.htm | 14 +- .../help/topics/ImporterPlugin/importer.htm | 14 +- .../plugin/core/exporter/ExporterDialog.java | 2 +- .../plugin/core/exporter/ExporterPlugin.java | 67 +++--- .../core/progmgr/MultiProgramManager.java | 21 +- .../core/progmgr/ProgramManagerPlugin.java | 3 +- .../SourceFilesTablePlugin.java | 12 +- .../app/util/exporter/AsciiExporter.java | 13 +- .../app/util/exporter/BinaryExporter.java | 32 ++- .../ghidra/app/util/exporter/Exporter.java | 19 +- .../ghidra/app/util/exporter/GdtExporter.java | 5 +- .../ghidra/app/util/exporter/GzfExporter.java | 5 +- .../app/util/exporter/HtmlExporter.java | 13 +- .../app/util/exporter/IntelHexExporter.java | 8 +- .../util/exporter/OriginalFileExporter.java | 21 +- .../app/util/exporter/ProgramExporter.java | 55 +++++ .../ghidra/app/util/exporter/XmlExporter.java | 15 +- .../ghidra/app/util/opinion/GdtLoader.java | 2 +- .../ghidra/app/util/opinion/GzfLoader.java | 3 +- .../plugin/importer/ImporterPlugin.java | 2 +- .../plugin/importer/ImporterUtilities.java | 85 +++++--- .../ghidra/app/util/exporter/CppExporter.java | 11 +- .../main/java/sarif/export/SarifExporter.java | 14 +- .../ghidra/framework/store/FolderItem.java | 8 +- .../store/local/ItemDeserializer.java | 12 +- .../store/local/LocalDataFileItem.java | 11 +- .../store/local/LocalDatabaseItem.java | 13 +- .../store/local/LocalTextDataItem.java | 2 +- .../store/local/LocalUnknownFolderItem.java | 3 +- .../ghidra/framework/model/DomainObject.java | 2 +- .../main/java/skeleton/SkeletonExporter.java | 6 + 44 files changed, 864 insertions(+), 360 deletions(-) delete mode 100644 Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/export/TraceViewAsciiExporter.java delete mode 100644 Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/export/TraceViewBinaryExporter.java delete mode 100644 Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/export/TraceViewHtmlExporter.java delete mode 100644 Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/export/TraceViewIntelHexExporter.java delete mode 100644 Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/export/TraceViewXmlExporter.java create mode 100644 Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/export/TraceExportPlugin.java create mode 100644 Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/utils/GztExporter.java create mode 100644 Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/utils/GztLoader.java create mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/ProgramExporter.java diff --git a/Ghidra/Debug/Debugger-isf/src/main/java/ghidra/dbg/isf/IsfServer.java b/Ghidra/Debug/Debugger-isf/src/main/java/ghidra/dbg/isf/IsfServer.java index f60cd30bced..ccf8613a3c9 100644 --- a/Ghidra/Debug/Debugger-isf/src/main/java/ghidra/dbg/isf/IsfServer.java +++ b/Ghidra/Debug/Debugger-isf/src/main/java/ghidra/dbg/isf/IsfServer.java @@ -37,7 +37,6 @@ import ghidra.program.model.data.FileDataTypeManager; import ghidra.program.model.listing.Program; import ghidra.util.Msg; -import ghidra.util.exception.VersionException; import ghidra.util.task.TaskMonitor; public class IsfServer extends Thread { @@ -102,13 +101,13 @@ public DataTypeManager getDataTypeManager(String ns) { try { DataTypeManager dtm; if (ns.endsWith(".gdt")) { - dtm = openAsArchive(ns); + dtm = openAsDataTypeArchive(ns); } else if (ns.endsWith(".gzf")) { - dtm = openAsDatabase(ns); + dtm = openAsProgramDatabase(ns); } else { - dtm = openAsDomainFile(ns); + dtm = openAsProgramFile(ns); } managers.put(ns, dtm); return dtm; @@ -120,43 +119,43 @@ else if (ns.endsWith(".gzf")) { } } - private DataTypeManager openAsDomainFile(String ns) throws Exception { + private DataTypeManager openAsProgramFile(String ns) throws Exception { ProjectData projectData = project.getProjectData(); DomainFile df = projectData.getFile(ns); + if (!Program.class.isAssignableFrom(df.getDomainObjectClass())) { + throw new IOException("File does not correspond to Program content: " + ns); + } + + // FIXME: Need to track and release Program instance after DTM use is complete (GP-6895) Program program = (Program) df.getDomainObject(this, false, false, TaskMonitor.DUMMY); return program.getDataTypeManager(); } - private DataTypeManager openAsArchive(String ns) throws Exception { + private DataTypeManager openAsDataTypeArchive(String ns) throws Exception { File gdt = new File(ns); return FileDataTypeManager.openFileArchive(gdt, false); } - private DataTypeManager openAsDatabase(String ns) throws Exception { + private DataTypeManager openAsProgramDatabase(String ns) throws Exception { File gzf = new File(ns); TaskMonitor dummy = TaskMonitor.DUMMY; PackedDatabase db = PackedDatabase.getPackedDatabase(gzf, dummy); + DBHandle dbh = db.openForUpdate(dummy); - ProgramDB p = null; + + Program p; + boolean success = false; try { - p = new ProgramDB(dbh, OpenMode.UPDATE, dummy, this); - } - catch (VersionException e) { - if (!e.isUpgradable()) { - throw new RuntimeException(p + " uses an older version and is not upgradable."); - } + p = new ProgramDB(dbh, OpenMode.UPGRADE, dummy, this); + success = true; } finally { - dbh.close(); - } - - dbh = db.openForUpdate(dummy); - p = new ProgramDB(dbh, OpenMode.UPGRADE, dummy, this); - - if (!p.isChanged()) { - throw new RuntimeException(p + " uses an older version and was not upgraded."); + if (!success) { + dbh.close(); + } } + // FIXME: Need to track and release Program instance after DTM use is complete (GP-6895) return p.getListing().getDataTypeManager(); } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/export/TraceViewAsciiExporter.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/export/TraceViewAsciiExporter.java deleted file mode 100644 index f31c1ffe8a5..00000000000 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/export/TraceViewAsciiExporter.java +++ /dev/null @@ -1,27 +0,0 @@ -/* ### - * 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.core.debug.export; - -import ghidra.app.util.exporter.AsciiExporter; -import ghidra.framework.model.DomainObject; -import ghidra.trace.model.Trace; - -public class TraceViewAsciiExporter extends AsciiExporter { - @Override - public boolean canExportDomainObject(Class domainObjectClass) { - return Trace.class.isAssignableFrom(domainObjectClass); - } -} diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/export/TraceViewBinaryExporter.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/export/TraceViewBinaryExporter.java deleted file mode 100644 index 2949322a91b..00000000000 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/export/TraceViewBinaryExporter.java +++ /dev/null @@ -1,27 +0,0 @@ -/* ### - * 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.core.debug.export; - -import ghidra.app.util.exporter.BinaryExporter; -import ghidra.framework.model.DomainObject; -import ghidra.trace.model.Trace; - -public class TraceViewBinaryExporter extends BinaryExporter { - @Override - public boolean canExportDomainObject(Class domainObjectClass) { - return Trace.class.isAssignableFrom(domainObjectClass); - } -} diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/export/TraceViewHtmlExporter.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/export/TraceViewHtmlExporter.java deleted file mode 100644 index b9c581e2c98..00000000000 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/export/TraceViewHtmlExporter.java +++ /dev/null @@ -1,27 +0,0 @@ -/* ### - * 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.core.debug.export; - -import ghidra.app.util.exporter.HtmlExporter; -import ghidra.framework.model.DomainObject; -import ghidra.trace.model.Trace; - -public class TraceViewHtmlExporter extends HtmlExporter { - @Override - public boolean canExportDomainObject(Class domainObjectClass) { - return Trace.class.isAssignableFrom(domainObjectClass); - } -} diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/export/TraceViewIntelHexExporter.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/export/TraceViewIntelHexExporter.java deleted file mode 100644 index 96c85d60fd5..00000000000 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/export/TraceViewIntelHexExporter.java +++ /dev/null @@ -1,27 +0,0 @@ -/* ### - * 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.core.debug.export; - -import ghidra.app.util.exporter.IntelHexExporter; -import ghidra.framework.model.DomainObject; -import ghidra.trace.model.Trace; - -public class TraceViewIntelHexExporter extends IntelHexExporter { - @Override - public boolean canExportDomainObject(Class domainObjectClass) { - return Trace.class.isAssignableFrom(domainObjectClass); - } -} diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/export/TraceViewXmlExporter.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/export/TraceViewXmlExporter.java deleted file mode 100644 index 46ab514eb6d..00000000000 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/export/TraceViewXmlExporter.java +++ /dev/null @@ -1,56 +0,0 @@ -/* ### - * 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.core.debug.export; - -import java.util.*; -import java.util.stream.Collectors; - -import ghidra.app.util.*; -import ghidra.app.util.exporter.XmlExporter; -import ghidra.framework.model.DomainObject; -import ghidra.trace.model.Trace; - -// TODO: perhaps getApplicableExporters should use domainObject's class, not file's object class. -// TODO: Where un-supported, be less abrasive, e.g., present empty managers. -public class TraceViewXmlExporter extends XmlExporter { - private final Map hideOpts = Map.of( - "Properties", false, - "Relocation Table", false, - "External Libraries", false); - - @Override - public boolean canExportDomainObject(Class domainObjectClass) { - return Trace.class.isAssignableFrom(domainObjectClass); - } - - @Override - public List

Exporting Files

-

Ghidra provides an Exporter that allows a user to output program information into a - file in various formats. 

+

Ghidra provides an Exporter that allows a user to output Program information into a + file in various formats.

-

Some of the formats the Exporter supports are:

+

Some of the Program file formats the Exporter supports are:

@@ -25,8 +25,6 @@

Exporting Files

  • C/C++
  • Ghidra Zip File (GZF)
  • - -
  • Ghidra Data Type Archive File (GDT)
  • HTML
  • @@ -40,6 +38,12 @@

    Exporting Files

  • SARIF Export Format
  • + +

    Content types other than Program may support + export and will present those export formats which are supported. Example: A + Debugger Trace may be exported as a Ghidra Zip Debugger Trace file (GZT). A data + type archive may be exported as a compressed Ghidra Data Type (GDT) archive file. +

    Export Action

    diff --git a/Ghidra/Features/Base/src/main/help/help/topics/Glossary/glossary.htm b/Ghidra/Features/Base/src/main/help/help/topics/Glossary/glossary.htm index 652ec485a1c..292ca17ea1d 100644 --- a/Ghidra/Features/Base/src/main/help/help/topics/Glossary/glossary.htm +++ b/Ghidra/Features/Base/src/main/help/help/topics/Glossary/glossary.htm @@ -599,11 +599,23 @@

    Global Namespace 

    The global namespace is the default namespace.

    +

    gdt

    + +
    +

    File extension given to a compressed Ghidra Data Type Archive database file.

    +
    +

    gzf

    -

    File extension given to Ghidra program database files that have been "zipped up".

    +

    File extension given to a compressed Ghidra Program database file.

    + +

    gzt

    + +
    +

    File extension given to a compressed Ghidra Debugger Trace database file.

    +

    H

    diff --git a/Ghidra/Features/Base/src/main/help/help/topics/ImporterPlugin/importer.htm b/Ghidra/Features/Base/src/main/help/help/topics/ImporterPlugin/importer.htm index 5a95a954945..4581f782ab5 100644 --- a/Ghidra/Features/Base/src/main/help/help/topics/ImporterPlugin/importer.htm +++ b/Ghidra/Features/Base/src/main/help/help/topics/ImporterPlugin/importer.htm @@ -38,6 +38,7 @@

    Supported Formats

  • Executable and Linking Format (ELF)
  • Ghidra Data Type Archive File (GDT)
  • Ghidra Zip File (GZF)
  • +
  • Ghidra Zip Debugger Trace File (GZT)
  • Intel Hex
  • Java Class File
  • Mac OS X Mach-O
  • @@ -96,10 +97,12 @@

    Alternative Steps (drag-and-drop):

    • Project Window: Drag a file from the system file explorer application and drop onto the Ghidra Project Tree destination folder. Dropping onto the table view is not - supported. In the case of Ghidra Zip File (GZF) or Ghidra Data Type Archive (GDT) file + supported. In the case of Ghidra Zip File (GZF), Ghidra Zip Debugger Trace file (GZT), + or Ghidra Data Type Archive (GDT) file imports, an immediate unpack can be performed wthout a popup dialog if the Front End option - Enable simple GZF/GDT unpack is enabled ( - EditTool Options...File ImportEnable simple GZF/GDT unpack). + Enable simple GZF/GZT/GDT unpack is enabled ( + EditTool Options... + File ImportEnable simple GZF/GZT/GDT unpack).
    • or Running Tool: Drag a file from the system file explorer application and drop @@ -274,9 +277,10 @@

      Dialog Fields

      folder, otherwise the root folder will be the default. The ... will bring up a dialog for changing the destination folder.

    • -
    • Program Name - This field specifies the name for the newly imported program. +
    • Program Name - This field specifies the name for the newly imported file into + the active project. By default, it will be the name of the imported file with any format specific extenstion - removed (e.g., .xml, .gzf). Path information at the beginning of this field + removed (e.g., .xml, .gzf, .gzt, .gdt). Path information at the beginning of this field will be used to create a destination folder in the current project under the root folder specified by the Destination Folder field.

    • diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/exporter/ExporterDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/exporter/ExporterDialog.java index 6b6ce755429..d99e4ec2b61 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/exporter/ExporterDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/exporter/ExporterDialog.java @@ -317,7 +317,7 @@ private String getFileName() { private void chooseDestinationFile() { GhidraFileChooser chooser = new GhidraFileChooser(getComponent()); - chooser.setSelectedFile(getLastExportDirectory()); + chooser.setCurrentDirectory(getLastExportDirectory()); chooser.setTitle("Select Output File"); chooser.setApproveButtonText("Select Output File"); chooser.setApproveButtonToolTipText("Select File"); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/exporter/ExporterPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/exporter/ExporterPlugin.java index 9e46e72e4b3..a73c8c3aff4 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/exporter/ExporterPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/exporter/ExporterPlugin.java @@ -18,19 +18,25 @@ import java.awt.event.KeyEvent; import java.util.List; -import docking.action.*; +import javax.swing.KeyStroke; + +import docking.ActionContext; +import docking.action.DockingAction; +import docking.action.MenuData; +import docking.action.builder.ActionBuilder; +import docking.tool.ToolConstants; import ghidra.app.CorePluginPackage; -import ghidra.app.context.NavigatableActionContext; -import ghidra.app.context.NavigatableContextAction; +import ghidra.app.context.ProgramLocationActionContext; import ghidra.app.plugin.PluginCategoryNames; -import ghidra.app.services.CodeViewerService; +import ghidra.app.plugin.ProgramPlugin; import ghidra.framework.main.ApplicationLevelPlugin; import ghidra.framework.main.FrontEndService; import ghidra.framework.main.datatable.FrontendProjectTreeAction; import ghidra.framework.main.datatable.ProjectDataContext; import ghidra.framework.model.DomainFile; import ghidra.framework.model.DomainFolder; -import ghidra.framework.plugintool.*; +import ghidra.framework.plugintool.PluginInfo; +import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.util.PluginStatus; import ghidra.program.model.listing.Program; import ghidra.program.util.ProgramSelection; @@ -45,7 +51,7 @@ description = "This plugin exports a program or datatype archive to an external file." ) //@formatter:on -public class ExporterPlugin extends Plugin implements ApplicationLevelPlugin { +public class ExporterPlugin extends ProgramPlugin implements ApplicationLevelPlugin { private FrontEndService frontEndService; @@ -64,32 +70,39 @@ private void createToolAction() { return; // do not add File menu Export Program action to front-end } - DockingAction action = new NavigatableContextAction("Export Program", getName()) { + new ActionBuilder("Export Program", getName()) + .description(getPluginDescription().getDescription()) + .helpLocation(new HelpLocation("ExporterPlugin", "Export")) + .menuPath(ToolConstants.MENU_FILE, "Export Program...") + .menuGroup("DomainObjectSaveExport") + .keyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_O, 0)) + .enabledWhen(c -> getProgram(c) != null) + .onAction(c -> doExport(c)) + .buildAndInstall(tool); + } - @Override - protected void actionPerformed(NavigatableActionContext context) { - Program program = context.getProgram(); - DomainFile domainFile = program.getDomainFile(); - ExporterDialog.showExporterDialog(tool, domainFile, program, - context.getSelection()); + private Program getProgram(ActionContext ctx) { + if (ctx instanceof ProgramLocationActionContext programCtx) { + Program p = programCtx.getProgram(); + if (p != null) { + return p; } - }; - MenuData menuData = - new MenuData(new String[] { "&File", "Export Program..." }, "Import Export"); - menuData.setMenuSubGroup("z"); // last in the "Save" group - action.setMenuBarData(menuData); - action.setKeyBindingData(new KeyBindingData(KeyEvent.VK_O, 0)); - action.setHelpLocation(new HelpLocation("ExporterPlugin", "Export")); - action.setDescription(getPluginDescription().getDescription()); - tool.addAction(action); + } + return getCurrentProgram(); } - protected ProgramSelection getSelection() { - CodeViewerService service = tool.getService(CodeViewerService.class); - if (service != null) { - return service.getCurrentSelection(); + private ProgramSelection getProgramSelection(ActionContext ctx) { + if (ctx instanceof ProgramLocationActionContext programCtx) { + return programCtx.getSelection(); } - return null; + return getProgramSelection(); + } + + private void doExport(ActionContext ctx) { + Program program = getProgram(ctx); + DomainFile domainFile = program.getDomainFile(); + ExporterDialog.showExporterDialog(tool, domainFile, program, + getProgramSelection(ctx)); } private void createFrontEndAction() { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/MultiProgramManager.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/MultiProgramManager.java index acd7db4b746..21ee8b06829 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/MultiProgramManager.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/MultiProgramManager.java @@ -4,9 +4,9 @@ * 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. @@ -76,8 +76,23 @@ class MultiProgramManager implements TransactionListener { }; } - void addProgram(Program p, ProgramLocator locator, int state) { + /** + * Add specified program. + *

      + * NOTE: If this is the first program to be added it will be forced to CURRENT state. + * + * @param p program to be added + * @param locator program location source information + * @param state initial state + * @return true if program is the current program + */ + boolean addProgram(Program p, ProgramLocator locator, int state) { + if (programMap.isEmpty()) { + // Tool does not handle case where single open program is not current program + state = ProgramManager.OPEN_CURRENT; + } addProgram(new ProgramInfo(p, locator, state != ProgramManager.OPEN_HIDDEN), state); + return state == ProgramManager.OPEN_CURRENT; } private void addProgram(ProgramInfo programInfo, int state) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramManagerPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramManagerPlugin.java index 718d4463498..cb8d23d8a90 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramManagerPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramManagerPlugin.java @@ -484,8 +484,7 @@ private void showProgram(Program p, ProgramLocator locator, final int state) { } Runnable r = () -> { - programMgr.addProgram(p, locator, state); - if (state == ProgramManager.OPEN_CURRENT) { + if (programMgr.addProgram(p, locator, state)) { programMgr.saveLocation(); } contextChanged(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/sourcefilestable/SourceFilesTablePlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/sourcefilestable/SourceFilesTablePlugin.java index 0e2c3e1297d..dd6e4796a53 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/sourcefilestable/SourceFilesTablePlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/sourcefilestable/SourceFilesTablePlugin.java @@ -161,14 +161,22 @@ private void createAction() { } private boolean isEnabled(ListingActionContext context) { + Program p = getCurrentProgram(); + if (p == null || p != context.getProgram()) { + return false; + } Address address = context.getAddress(); - SourceFileManager manager = getCurrentProgram().getSourceFileManager(); + SourceFileManager manager = p.getSourceFileManager(); return manager.getSourceMapEntries(address).size() > 0; } private void viewSourceFile(ListingActionContext context) { + Program p = getCurrentProgram(); + if (p == null || p != context.getProgram()) { + return; + } Address address = context.getAddress(); - SourceFileManager manager = getCurrentProgram().getSourceFileManager(); + SourceFileManager manager = p.getSourceFileManager(); List entries = manager.getSourceMapEntries(address); if (entries.isEmpty()) { return; // sanity check diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/AsciiExporter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/AsciiExporter.java index ece1a6ecfe6..dc6caf57850 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/AsciiExporter.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/AsciiExporter.java @@ -4,9 +4,9 @@ * 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. @@ -30,7 +30,7 @@ * An implementation of exporter that creates * an Ascii representation of the program. */ -public class AsciiExporter extends Exporter { +public class AsciiExporter extends ProgramExporter { private ProgramTextOptions options; /** @@ -60,11 +60,14 @@ public boolean export(File file, DomainObject domainObj, AddressSetView addressS log.clear(); - if (!(domainObj instanceof Program)) { + Program program; + try { + program = getProgram(domainObj); + } + catch (ClassCastException e) { log.appendMsg("Unsupported type: " + domainObj.getClass().getName()); return false; } - Program program = (Program) domainObj; getOptions(() -> program); new ProgramTextWriter(file, program, addressSet, monitor, options, provider); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/BinaryExporter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/BinaryExporter.java index be5ef9a2858..39b6189fdce 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/BinaryExporter.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/BinaryExporter.java @@ -4,9 +4,9 @@ * 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. @@ -23,14 +23,15 @@ import ghidra.framework.model.DomainObject; import ghidra.program.model.address.*; import ghidra.program.model.listing.Program; -import ghidra.program.model.mem.*; +import ghidra.program.model.mem.Memory; +import ghidra.program.model.mem.MemoryAccessException; import ghidra.util.HelpLocation; import ghidra.util.task.TaskMonitor; /** * An {@link Exporter} that can export memory blocks as raw bytes */ -public class BinaryExporter extends Exporter { +public class BinaryExporter extends ProgramExporter { public BinaryExporter() { super("Raw Bytes", "bin", new HelpLocation("ExporterPlugin", "binary")); @@ -40,30 +41,27 @@ public BinaryExporter() { public boolean export(File file, DomainObject domainObj, AddressSetView addrSet, TaskMonitor monitor) throws IOException, ExporterException { - if (!(domainObj instanceof Program)) { + Program program; + try { + program = getProgram(domainObj); + } + catch (ClassCastException e) { log.appendMsg("Unsupported type: " + domainObj.getClass().getName()); return false; } - Program program = (Program) domainObj; Memory memory = program.getMemory(); + AddressSetView initializedAddressSet = memory.getAllInitializedAddressSet(); if (addrSet == null) { - addrSet = memory; + addrSet = initializedAddressSet; } - - AddressSet set = new AddressSet(addrSet); - - //skip blocks that are not initialized... - MemoryBlock[] blocks = memory.getBlocks(); - for (int i = 0; i < blocks.length; ++i) { - if (!blocks[i].isInitialized()) { - set.delete(new AddressRangeImpl(blocks[i].getStart(), blocks[i].getEnd())); - } + else { + addrSet = addrSet.intersect(initializedAddressSet); } try (FileOutputStream fos = new FileOutputStream(file)) { - AddressRangeIterator iter = set.getAddressRanges(); + AddressRangeIterator iter = addrSet.getAddressRanges(); while (iter.hasNext()) { AddressRange range = iter.next(); byte[] mem = new byte[(int) range.getLength()]; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/Exporter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/Exporter.java index dc0b9b39e93..ff940a07578 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/Exporter.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/Exporter.java @@ -25,7 +25,6 @@ import ghidra.framework.model.DomainObject; import ghidra.framework.plugintool.ServiceProvider; import ghidra.program.model.address.AddressSetView; -import ghidra.program.model.listing.Program; import ghidra.util.HelpLocation; import ghidra.util.classfinder.ExtensionPoint; import ghidra.util.task.TaskMonitor; @@ -101,34 +100,32 @@ final public void setExporterServiceProvider(ServiceProvider provider) { /** * Returns true if this exporter is capable of exporting the given domain file/object content * type. For example, some exporters have the ability to export programs, other exporters can - * export project data type archives. + * export other {@link DomainFile} or {@link DomainObject} types such as project data type + * archives. *

      - * NOTE: This method should only be used as a preliminary check, if neccessary, to identify + * NOTE: This method should only be used as a preliminary check, if necessary, to identify * exporter implementations that are capable of handling a specified content type/class. Prior * to export a final check should be performed based on the export or either a * {@link DomainFile} or {@link DomainObject}: *

      * {@link DomainFile} export - the method {@link #canExportDomainFile(DomainFile)} should be * used to verify a direct project file export is possible using the - * {@link #export(File, DomainFile, TaskMonitor)} method. + * {@link #export(File, DomainFile, TaskMonitor)} method which may avoid opening the file first. *

      * {@link DomainObject} export - the method {@link #canExportDomainObject(DomainObject)} should - * be used to verify an export of a specific object is possible using the + * be used to verify an export of a specific object is possible before using the * {@link #export(File, DomainObject, AddressSetView, TaskMonitor)} method. * - * avoid opening DomainFile when possible. * @param domainObjectClass the class of the domain object to test for exporting. * @return true if this exporter knows how to export the given domain object type. */ - public boolean canExportDomainObject(Class domainObjectClass) { - return Program.class.isAssignableFrom(domainObjectClass); - } + public abstract boolean canExportDomainObject(Class domainObjectClass); /** * Returns true if exporter can export the specified {@link DomainFile} without instantiating * a {@link DomainObject}. This method should be used prior to exporting using the - * {@link #export(File, DomainFile, TaskMonitor)} method. All exporter capable of a - * {@link DomainFile} export must also support a export of a {@link DomainObject} so that any + * {@link #export(File, DomainFile, TaskMonitor)} method. All exporters capable of a + * {@link DomainFile} export must also support an export of a {@link DomainObject} so that any * possible data modification/upgrade is included within resulting export. * * @param domainFile domain file diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/GdtExporter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/GdtExporter.java index 21d049525ae..1246f6d6d5d 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/GdtExporter.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/GdtExporter.java @@ -47,7 +47,7 @@ public boolean canExportDomainObject(Class domainObjectC @Override public boolean canExportDomainFile(DomainFile domainFile) { - // Avoid exporting link-file itself + // Avoid exporting link-file itself or non-Datatype Archives return !domainFile.isLink() && canExportDomainObject(domainFile.getDomainObjectClass()); } @@ -59,6 +59,9 @@ public boolean equals(Object obj) { @Override public boolean export(File file, DomainObject domainObj, AddressSetView addrSet, TaskMonitor monitor) { + if (!canExportDomainObject(domainObj.getClass())) { + throw new UnsupportedOperationException("only DataTypeArchiveDB objects are supported"); + } try { file.delete(); domainObj.saveToPackedFile(file, monitor); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/GzfExporter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/GzfExporter.java index 1e735b916f0..e15f1651440 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/GzfExporter.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/GzfExporter.java @@ -42,7 +42,7 @@ public GzfExporter() { @Override public boolean canExportDomainFile(DomainFile domainFile) { - // Avoid exporting link-file itself + // Avoid exporting link-file itself or non-Program files return !domainFile.isLink() && canExportDomainObject(domainFile.getDomainObjectClass()); } @@ -59,6 +59,9 @@ public boolean equals(Object obj) { @Override public boolean export(File file, DomainObject domainObj, AddressSetView addrSet, TaskMonitor monitor) { + if (!canExportDomainObject(domainObj.getClass())) { + throw new UnsupportedOperationException("only ProgramDB objects are supported"); + } try { file.delete(); domainObj.saveToPackedFile(file, monitor); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/HtmlExporter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/HtmlExporter.java index 92c39e40ec6..2140212bdf9 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/HtmlExporter.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/HtmlExporter.java @@ -4,9 +4,9 @@ * 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. @@ -30,7 +30,7 @@ * An implementation of exporter that creates * an HTML representation of the program. */ -public class HtmlExporter extends Exporter { +public class HtmlExporter extends ProgramExporter { private ProgramTextOptions options; /** @@ -58,11 +58,14 @@ public void setOptions(List

      * Various system path utilities are also provided in support of local Ghidra project URLs and * {@link ProjectLocator}. + *

      + * NOTE: Avoid using {@link URL#getRef()} which returns the encoded refereance fragment as it + * appears in the URL. The proper technique is to use {@code URL.toURI().getFragment()}. + * Alternatively, the method {@link #getDecodedReference(URL)} may be used. Encoding of space + * character in URL reference can be inconsistent. URI encodes space as {@code %20} while + * some other implementation may encode space as '+'. Creation and decoding of Ghidra URLs + * should use this utility class to ensure proper round-trip encode/decode. */ public class GhidraURL { @@ -265,40 +271,21 @@ else if (uri.getAuthority() != null) { } /** - * {@return Get the URL-decoded reference/fragment from the URL or null} + * {@return Get the URL-decoded reference fragment from the URL or null} *

      - * NOTE: The presence of "+" in the original reference fragment is problematic and - * requires consistent use of this method in conjunction with the URL instantiation - * methods provided by this utility class. + * NOTE: Avoid using {@link URL#getRef()} which returns the encoded refereance fragment as it + * appears in the URL. * - * @param url Ghidra URL + * @param url URL or null if no ref or URL failure occurs */ public static String getDecodedReference(URL url) { - String ref = url.getRef(); - if (StringUtils.isBlank(ref)) { - return null; - } try { - // NOTE: original "+" may appear encoded in final URL as "%252B" - ref = URLDecoder.decode(ref, "UTF-8"); - ref = ref.replace("%2B", "+"); // force double-decode of original "+" - return ref; + return url.toURI().getFragment(); } - catch (UnsupportedEncodingException e) { - return null; + catch (URISyntaxException e) { + // ignore } - } - - /** - * Perform preliminary encode of '+' within raw ref string so that it may be preserved - * and properly decoded from {@link URI#getFragment()} by {@link #getDecodedReference(URL)}. - * Once fully encoded by URI a raw '+' will appear with a double encoding of "%252B". - * - * @param rawRef raw ref/fragment to be prepared for use with URI creation. - * @return preliminary encoding of specified raw ref string. - */ - private static String encodeRefPlus(String rawRef) { - return StringUtils.isBlank(rawRef) ? null : rawRef.replace("+", "%2B"); + return null; } /** @@ -310,10 +297,15 @@ private static String encodeRefPlus(String rawRef) { * @return repository name or null if not applicable to URL */ public static String getRepositoryName(URL url) { - if (!isServerURL(url)) { + + if (isLocalURL(url)) { return null; } + if (!isServerURL(url)) { + throw new IllegalArgumentException("Invalid project/repository URL"); + } + try { URI uri = url.toURI(); String path = getServerURIPath(uri); @@ -453,6 +445,12 @@ private static void checkValidProjectPath(String path, int startIndex) { /** * Create a Ghidra URL from a string form of a Ghidra URL or local project path. * This method can consume strings produced by the getDisplayString method. + *

      + * NOTE: If a Ghidra URL string is improperly encode (e.g., had been made by simple string + * concatentaion) an exception may be thrown. In such situations, a URL re-encoding will be + * attempted but may produce an incorrect URL if partial encoding was used. The following + * characters present in an improperly encoded URL may not handled properly: + * {@code ' ', '?', '%', '+', '&', '#', '=' } * * @param projectPathOrURL {@literal project path (/)} or * string form of Ghidra URL. @@ -478,12 +476,42 @@ public static URL toURL(String projectPathOrURL) { return makeURL(location, projectName); } - // NOTE: We must assume URL is properly encoded in its external form + URL url; try { - return URI.create(projectPathOrURL).toURL(); + // NOTE: will fail if URL has improper encoding + url = URI.create(projectPathOrURL).toURL(); } catch (Exception e) { - throw new IllegalArgumentException("Invalid Ghidra URL", e); + // Since URL string may have been improperly formed via simple string concatentenation + // attempt to repair encodes (primarily handles presence of spaces). + url = getReformedGhidraURL(projectPathOrURL); + if (url == null) { + throw new IllegalArgumentException("Invalid Ghidra URL: " + projectPathOrURL, e); + } + } + if (!isLocalURL(url) && url.getQuery() != null) { + throw new IllegalArgumentException("Invalid Ghidra URL: " + projectPathOrURL); + } + return url; + } + + private static URL getReformedGhidraURL(String invalidGhidraUrl) { + + if (!invalidGhidraUrl.startsWith(PROTOCOL_URL_START + "/")) { + // Assume opaque ghidra URL (i.e., ghidra protocol extension) + return null; + } + + try { + // Assume old code was used to directly for URL without the use of URI + URL url = new URL(invalidGhidraUrl); + + URI repairedUri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), + url.getPort(), url.getPath(), url.getQuery(), url.getRef()); + return repairedUri.toURL(); + } + catch (Exception e) { + return null; } } @@ -513,8 +541,6 @@ public static URL resolve(URL ghidraUrl, String projectFilePath, String ref) { projectFilePath = null; } - ref = encodeRefPlus(ref); - Exception exc = null; try { URI uri = ghidraUrl.toURI(); @@ -691,6 +717,10 @@ public static URL getNormalizedURL(URL url) { return new URI(PROTOCOL, ssp, null).toURL(); } + if (uri.getQuery() != null) { + throw new URISyntaxException(url.toExternalForm(), "Invalid Ghidra URL"); + } + String host = uri.getHost(); String revisedHost = getHostAsIpAddress(host); if (Objects.equals(host, revisedHost) && url.getRef() == null) { @@ -818,7 +848,7 @@ public static URL makeURL(String projectLocation, String projectName, String pro } try { - return new URI(GhidraURL.PROTOCOL, null, path, projectFilePath, encodeRefPlus(ref)) + return new URI(GhidraURL.PROTOCOL, null, path, projectFilePath, ref) .toURL(); } catch (URISyntaxException | MalformedURLException e) { @@ -937,7 +967,7 @@ public static URL makeURL(String host, int port, String repositoryName, String r } try { - return new URI(PROTOCOL, null, host, port, path, null, encodeRefPlus(ref)).toURL(); + return new URI(PROTOCOL, null, host, port, path, null, ref).toURL(); } catch (URISyntaxException | MalformedURLException e) { throw new IllegalArgumentException(e); diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/protocol/ghidra/Handler.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/protocol/ghidra/Handler.java index 23665815e72..b0f0d58af67 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/protocol/ghidra/Handler.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/protocol/ghidra/Handler.java @@ -70,8 +70,8 @@ public static boolean isSupportedURL(URL url) { } if (url.getAuthority() != null) { - // assume standard ghidra URL (ghidra://...) - return true; + // assume standard ghidra URL (ghidra://...) - query not allowed + return url.getQuery() == null; } try { return getProtocolExtensionHandler(url) != null; diff --git a/Ghidra/Framework/Project/src/test/java/ghidra/framework/protocol/ghidra/GhidraURLTest.java b/Ghidra/Framework/Project/src/test/java/ghidra/framework/protocol/ghidra/GhidraURLTest.java index 72bbed1ba55..c2833b75373 100644 --- a/Ghidra/Framework/Project/src/test/java/ghidra/framework/protocol/ghidra/GhidraURLTest.java +++ b/Ghidra/Framework/Project/src/test/java/ghidra/framework/protocol/ghidra/GhidraURLTest.java @@ -607,6 +607,60 @@ public void testIsServerURL() throws Exception { assertTrue(GhidraURL.isServerURL(ghidraUrl)); } + @Test + public void testBadServerURL() throws Exception { + + try { + GhidraURL.toURL("ghidra://localhost:123/Test/foo/bar?/a/b#ref%20+123"); + fail("Expected failure due to invalid query"); + } + catch (IllegalArgumentException e) { + // expected + } + + URL url = URI.create("ghidra://localhost:123/Test/foo/bar?/a/b#ref%20+123").toURL(); + + try { + GhidraURL.getRepositoryName(url); + fail("Expected failure due to invalid query"); + } + catch (IllegalArgumentException e) { + // expected + } + + try { + GhidraURL.getFolderURL(url); + fail("Expected failure due to invalid query"); + } + catch (IllegalArgumentException e) { + // expected + } + + try { + GhidraURL.getNormalizedURL(url); + fail("Expected failure due to invalid query"); + } + catch (IllegalArgumentException e) { + // expected + } + + try { + GhidraURL.getProjectPathname(url); + fail("Expected failure due to invalid query"); + } + catch (IllegalArgumentException e) { + // expected + } + + try { + GhidraURL.getProjectURL(url); + fail("Expected failure due to invalid query"); + } + catch (IllegalArgumentException e) { + // expected + } + } + // toURL(String) @Test public void testToURL() throws Exception { @@ -641,17 +695,32 @@ public void testToURL() throws Exception { assertEquals(ghidraUrl, GhidraURL.toURL(ghidraUrl.toString())); assertEquals(ghidraUrl, GhidraURL.toURL(GhidraURL.getDisplayString(ghidraUrl))); - ghidraUrl = GhidraURL.makeURL("/x/y", "Test", "/a/", "ref"); - assertEquals(ghidraUrl, GhidraURL.toURL("ghidra:/x/y/Test?/a/#ref")); + ghidraUrl = GhidraURL.makeURL("/x/y", "Test", "/a/", "ref +123"); + assertEquals("ref%20+123", ghidraUrl.getRef()); + assertEquals("ref +123", ghidraUrl.toURI().getFragment()); + + assertEquals(ghidraUrl, GhidraURL.toURL("ghidra:/x/y/Test?/a/#ref%20+123")); assertEquals(ghidraUrl, GhidraURL.toURL(ghidraUrl.toString())); assertEquals(ghidraUrl, GhidraURL.toURL(GhidraURL.getDisplayString(ghidraUrl))); - assertEquals("ref", GhidraURL.getDecodedReference(ghidraUrl)); + assertEquals("ref +123", GhidraURL.getDecodedReference(ghidraUrl)); + + ghidraUrl = GhidraURL.makeURL("localhost", 123, "Test", "/foo", "bar", "ref +123"); + assertEquals("ref%20+123", ghidraUrl.getRef()); + assertEquals("ref +123", ghidraUrl.toURI().getFragment()); - ghidraUrl = GhidraURL.makeURL("localhost", 123, "Test", "/foo", "bar", "ref+123"); - // GhidraURL.toURL requires external URL form with double-encoding for '+' in ref - assertEquals(ghidraUrl, GhidraURL.toURL("ghidra://localhost:123/Test/foo/bar#ref%252B123")); + assertEquals(ghidraUrl, GhidraURL.toURL("ghidra://localhost:123/Test/foo/bar#ref%20+123")); assertEquals(ghidraUrl, GhidraURL.toURL(ghidraUrl.toString())); assertEquals(ghidraUrl, GhidraURL.toURL(GhidraURL.getDisplayString(ghidraUrl))); + assertEquals("ref +123", GhidraURL.getDecodedReference(ghidraUrl)); + + ghidraUrl = GhidraURL.makeURL("localhost", 123, "Test", "/foo", "bar", "ref++123"); + assertEquals("ref++123", ghidraUrl.getRef()); + assertEquals("ref++123", ghidraUrl.toURI().getFragment()); + + assertEquals(ghidraUrl, GhidraURL.toURL("ghidra://localhost:123/Test/foo/bar#ref++123")); + assertEquals(ghidraUrl, GhidraURL.toURL(ghidraUrl.toString())); + assertEquals(ghidraUrl, GhidraURL.toURL(GhidraURL.getDisplayString(ghidraUrl))); + assertEquals("ref++123", GhidraURL.getDecodedReference(ghidraUrl)); // Unicode foreign language example ghidraUrl = GhidraURL.makeURL("localhost", 123, "Gr\u00FCnerTee", "/\u6771\u4EAC/", @@ -662,6 +731,33 @@ public void testToURL() throws Exception { assertEquals(ghidraUrl, GhidraURL.toURL(GhidraURL.getDisplayString(ghidraUrl))); } + @Test + public void testRelaxedToURL() throws Exception { + String path = "/Test/my foo/bar"; + String improperUrl = "ghidra://127.0.0.1:123" + path + "#a b+c"; + URL ghidraUrl = GhidraURL.toURL(improperUrl); + + assertEquals("a b+c", GhidraURL.getDecodedReference(ghidraUrl)); + assertEquals("Test", GhidraURL.getRepositoryName(ghidraUrl)); + assertEquals("/my foo/bar", GhidraURL.getProjectPathname(ghidraUrl)); + + assertEquals(path.replace(" ", "%20"), ghidraUrl.getPath()); + assertEquals(null, ghidraUrl.getQuery()); + assertEquals("a%20b+c", ghidraUrl.getRef()); + + improperUrl = "ghidra:" + path + "?" + path + "#a b+c"; + ghidraUrl = GhidraURL.toURL(improperUrl); + + assertEquals("a b+c", GhidraURL.getDecodedReference(ghidraUrl)); + assertEquals(path + ".rep", + GhidraURL.getProjectStorageLocator(ghidraUrl).getProjectDir().toString()); + assertEquals(path, GhidraURL.getProjectPathname(ghidraUrl)); + + assertEquals(path.replace(" ", "%20"), ghidraUrl.getPath()); + assertEquals(path.replace(" ", "%20"), ghidraUrl.getQuery()); + assertEquals("a%20b+c", ghidraUrl.getRef()); + } + @Test public void testGetProjectURL() throws Exception { @@ -846,9 +942,6 @@ private URL toGhidraLocalURL(String path, String projectFilePath) private URL toGhidraLocalURL(String path, String projectFilePath, String ref) throws MalformedURLException, URISyntaxException { - if (ref != null) { - ref = ref.replace("+", "%2B"); // force encoding of "+" - } return new URI(GhidraURL.PROTOCOL, null, path, projectFilePath, ref).toURL(); } @@ -866,9 +959,6 @@ private URL toGhidraServerURL(String host, int port, String repo, String path, S if (path != null) { repoAndPath += path; } - if (ref != null) { - ref = ref.replace("+", "%2B"); // force encoding of "+" - } return new URI(GhidraURL.PROTOCOL, null, host, port, repoAndPath, null, ref).toURL(); } } From c34a6604c9d58664aa0bd2d6c999f0511ab8f86c Mon Sep 17 00:00:00 2001 From: ghizard <50744617+ghizard@users.noreply.github.com> Date: Tue, 16 Jun 2026 06:25:44 -0400 Subject: [PATCH 030/111] GP-6971 - Fix memory-consumption issue in malformed PDB directory stream --- .../format/pdb2/pdbreader/AbstractPdb.java | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/AbstractPdb.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/AbstractPdb.java index cfaddaf4609..a5a1ca1a6ed 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/AbstractPdb.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/AbstractPdb.java @@ -684,26 +684,37 @@ protected void deserializeParameters(PdbByteReader reader) throws IOException, PdbException, CancelledException { nameTable.deserializeDirectory(reader); // Read the parameters. + // 20260616: Modified processing to prevent unabated growth of parameters. Will continue + // processing data from stream, looking only for expected parameter types. Loop will + // terminate upon repeated or unknown param signature (we will keep the first unknown + // parameter for diagnostic sake). The parameters list will only contain the values up to + // the point of termination. Since there are so few signatures that we are looking for, + // we are keeping parameters as a list and using the contains() method. + // If VC110_ID is found, then we terminate after capture, as no other parameters are + // supposed to be valid (here, we are now mimicking what is in the spec). while (reader.hasMore()) { checkCancelled(); - int val = reader.parseInt(); - parameters.add(val); - } - // Check the parameters for IDs - for (int param : parameters) { - checkCancelled(); - if (param == MINIMAL_DEBUG_INFO_PARAM) { + int param = reader.parseInt(); + if (parameters.contains(param)) { + break; + } + parameters.add(param); // capture non-repeating param, which can be first "unknown" + if (param == PdbParser.VC110_ID) { + hasIdStream = true; + break; // no other parameters are supposed to be valid + } + else if (param == MINIMAL_DEBUG_INFO_PARAM) { minimalDebugInfo = true; } else if (param == NO_TYPE_MERGE_PARAM) { noTypeMerge = true; } - // Putting all of these >= ID after the specific == tests above - // so that no >= tests in the ID section trigger off of any - // of the above flags - else if (param >= PdbParser.VC110_ID) { + else if (param == PdbParser.VC140_ID) { hasIdStream = true; } + else { + break; + } } } From 4170459fddba20856f22dc839421cd5e7473e78d Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Tue, 16 Jun 2026 14:01:12 +0000 Subject: [PATCH 031/111] GP-6964: Added index entries for 1dc/lds/stc/sts.l instructions --- Ghidra/Processors/SuperH/data/manuals/superh.idx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Ghidra/Processors/SuperH/data/manuals/superh.idx b/Ghidra/Processors/SuperH/data/manuals/superh.idx index 7c607d9e028..31825e1360a 100644 --- a/Ghidra/Processors/SuperH/data/manuals/superh.idx +++ b/Ghidra/Processors/SuperH/data/manuals/superh.idx @@ -35,7 +35,9 @@ extu.w, 101 jmp, 102 jsr, 103 ldc, 105 +ldc.l, 105 lds, 107 +lds.l, 107 mac.l, 109 mac, 112 mac.w, 113 @@ -73,7 +75,9 @@ shlr8, 154 shlr16, 154 sleep, 156 stc, 157 +stc.l, 157 sts, 159 +sts.l, 159 sub, 161 subc, 162 subv, 163 From d0478ad2f6ce214496c6a9695c4505cf35c5fded Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Tue, 16 Jun 2026 10:19:12 -0400 Subject: [PATCH 032/111] GP-1 Corrected folder URL creation for HeadlessAnalyzer.processURL --- .../ghidra/app/util/headless/HeadlessAnalyzer.java | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/headless/HeadlessAnalyzer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/headless/HeadlessAnalyzer.java index 9fa1cf111d6..8048bacdbd6 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/headless/HeadlessAnalyzer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/headless/HeadlessAnalyzer.java @@ -291,18 +291,6 @@ public void processURL(URL ghidraURL, List filesToImport) Msg.warn(this, "REPORT: Nothing to do ... must specify files for import."); return; } - - if (!path.endsWith("/")) { - // force explicit folder path so that non-existent folders are created on import - ghidraURL = new URI("ghidra", null, ghidraURL.getHost(), ghidraURL.getPort(), - path + "/", null, null).toURL(); - } - } - else { // Running in -process mode - if (path.endsWith("/") && path.length() > 1) { - ghidraURL = new URI("ghidra", null, ghidraURL.getHost(), ghidraURL.getPort(), - path.substring(0, path.length() - 1), null, null).toURL(); - } } BundleHost bundleHost = GhidraScriptUtil.acquireBundleHostReference(); From 80cd37bc3b8da759b0dcc0e3a5ba99b21a3298c1 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Tue, 16 Jun 2026 15:19:41 -0400 Subject: [PATCH 033/111] GP-0: Fixing ServerTestUtil so it can run on Windows --- .../ghidra/server/remote/ServerTestUtil.java | 56 ++++++++++--------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/server/remote/ServerTestUtil.java b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/server/remote/ServerTestUtil.java index 207a3973fbe..0f4bb425198 100644 --- a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/server/remote/ServerTestUtil.java +++ b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/server/remote/ServerTestUtil.java @@ -17,6 +17,8 @@ import java.io.*; import java.net.*; +import java.nio.file.Files; +import java.nio.file.Path; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.security.KeyStore.PrivateKeyEntry; @@ -27,6 +29,7 @@ import javax.rmi.ssl.SslRMIClientSocketFactory; +import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.RandomStringUtils; import db.buffers.DataBuffer; @@ -99,6 +102,7 @@ public class ServerTestUtil { private static IOThread cmdErr; private static Process serverProcess; private static String serverRepositories; + private static Path argsFile; static { Runtime.getRuntime().addShutdownHook(new ShutdownHook()); @@ -435,19 +439,15 @@ public static synchronized void startServer(String dirPath, int port, int authMo getTestPkiCACertsPath()); DefaultSSLContextInitializer.initialize(true); - ArrayList argList = new ArrayList<>(); String javaCommand = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java"; - argList.add(javaCommand); + List argList = new ArrayList<>(); argList.add("-cp"); - argList.add(System.getProperty("java.class.path")); + argList.add("\"" + System.getProperty("java.class.path").replace("\\", "/") + "\""); argList.add("-Xmx512M"); - argList.add("-Xdebug"); - argList.add("-Xnoagent"); - argList.add("-Djava.compiler=NONE"); argList.add("-Ddb.buffers.DataBuffer.compressedOutput=" + enableCompressionOnServerStart); argList.add("-D" + DefaultTrustManagerFactory.GHIDRA_CACERTS_PATH_PROPERTY + "=" + getTestPkiCACertsPath()); @@ -483,25 +483,15 @@ public static synchronized void startServer(String dirPath, int port, int authMo argList.add("-p" + port); argList.add(dirPath); - String[] args = new String[argList.size()]; - argList.toArray(args); - - System.out.println(); - for (String arg : argList) { - boolean includeQuotes = arg.indexOf(' ') != -1; - if (includeQuotes) { - System.out.print("'"); - } - System.out.print(arg); - if (includeQuotes) { - System.out.print("'"); - } - System.out.print(" "); - } - System.out.println(); try { - serverProcess = Runtime.getRuntime().exec(args); + // Command line argument is too long on Windows, so use an @arg-file + argsFile = + Files.createTempFile(Application.getUserTempDirectory().toPath(), "args", ".txt"); + Files.write(argsFile, argList); + System.out.println(javaCommand + " \"@" + argsFile + "\""); + + serverProcess = new ProcessBuilder(javaCommand, "@" + argsFile).start(); serverRepositories = dirPath; cmdOut = new IOThread(serverProcess.getInputStream()); @@ -658,8 +648,24 @@ public static synchronized void disposeServer() { serverRepositories = null; if (testPkiDirectory != null) { - FileUtilities.deleteDir(testPkiDirectory); - testPkiDirectory = null; + try { + FileUtils.deleteDirectory(testPkiDirectory); + } + catch (IOException e) { + // Will likely be an error the next time the test starts + e.printStackTrace(); + } + finally { + testPkiDirectory = null; + } + } + } + if (argsFile != null && Files.exists(argsFile)) { + try { + Files.delete(argsFile); + } + catch (IOException e) { + // don't care } } } From 1ceb72249795f483560dbd013243c786a692519d Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Mon, 15 Jun 2026 08:13:25 -0400 Subject: [PATCH 034/111] GP-0: Removing ancient/useless debug JVM args --- .../file/formats/ios/dmg/DmgServerProcessManager.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dmg/DmgServerProcessManager.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dmg/DmgServerProcessManager.java index 23a2513fccb..f641625a0bd 100644 --- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dmg/DmgServerProcessManager.java +++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/ios/dmg/DmgServerProcessManager.java @@ -4,9 +4,9 @@ * 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. @@ -240,7 +240,7 @@ private Process createProcess() { String java = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java"; - // optional: -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=18200 + // optional: -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=18200 try { Process p = Runtime.getRuntime().exec( new String[] { java, "-classpath", classPath, "-Xmx" + dmgServerMemoryMB + "m", //need more memory to load and xfer data across pipe From 190949f2675cacd7b8ae5acc2c8e4b8ba1d92422 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Wed, 17 Jun 2026 10:45:56 -0400 Subject: [PATCH 035/111] GP-0: Upping gradle wrapper to 9.5.1 --- .../Common/support/gradle/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ghidra/RuntimeScripts/Common/support/gradle/gradle-wrapper.properties b/Ghidra/RuntimeScripts/Common/support/gradle/gradle-wrapper.properties index c61a118f7dd..5dd3c0121b3 100644 --- a/Ghidra/RuntimeScripts/Common/support/gradle/gradle-wrapper.properties +++ b/Ghidra/RuntimeScripts/Common/support/gradle/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From da1ad47350207dcfc7a0fe1855ff9710a1c990df Mon Sep 17 00:00:00 2001 From: James <49045138+ghidracadabra@users.noreply.github.com> Date: Wed, 17 Jun 2026 13:20:13 -0400 Subject: [PATCH 036/111] GP-6977 improve escaping in BSimControlLaunchable --- .../bsim/query/BSimControlLaunchable.java | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimControlLaunchable.java b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimControlLaunchable.java index ff315bf4541..ac1d53e3b97 100644 --- a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimControlLaunchable.java +++ b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimControlLaunchable.java @@ -30,6 +30,7 @@ import javax.security.auth.DestroyFailedException; import org.apache.commons.lang3.StringUtils; +import org.postgresql.core.Utils; import org.xml.sax.ErrorHandler; import org.xml.sax.SAXException; @@ -1153,9 +1154,9 @@ private void addUserCommand() throws GeneralSecurityException, Exception { localConnection = getOrCreateLocalConnection(); StringBuilder buffer = new StringBuilder(); - buffer.append("CREATE ROLE \""); - buffer.append(specifiedUserName); - buffer.append("\" WITH LOGIN"); + buffer.append("CREATE ROLE "); + Utils.escapeIdentifier(buffer, specifiedUserName); + buffer.append(" WITH LOGIN"); try (Statement st = localConnection.createStatement()) { st.executeUpdate(buffer.toString()); @@ -1217,9 +1218,8 @@ private void dropUserCommand() throws Exception { boolean userDoesNotExist = false; localConnection = getOrCreateLocalConnection(); StringBuilder buffer = new StringBuilder(); - buffer.append("DROP ROLE \""); - buffer.append(specifiedUserName); - buffer.append('\"'); + buffer.append("DROP ROLE "); + Utils.escapeIdentifier(buffer, specifiedUserName); try (Statement st = localConnection.createStatement()) { st.executeUpdate(buffer.toString()); @@ -1359,9 +1359,9 @@ else if (hostAuthentication == AUTHENTICATION_PKI) { */ private void resetPassword(Connection pdb, String username) throws SQLException { StringBuilder buffer = new StringBuilder(); - buffer.append("ALTER ROLE \""); - buffer.append(username); - buffer.append("\" WITH PASSWORD '"); + buffer.append("ALTER ROLE "); + Utils.escapeIdentifier(buffer, username); + buffer.append(" WITH PASSWORD '"); buffer.append(DEFAULT_PASSWORD); buffer.append('\''); executeSQLStatement(pdb, buffer.toString()); @@ -1389,16 +1389,17 @@ private void passwordCommand() throws Exception { private void changePrivilegeCommand() throws Exception { localConnection = getOrCreateLocalConnection(); try { + StringBuilder buffer = new StringBuilder("ALTER ROLE "); + Utils.escapeIdentifier(buffer, specifiedUserName); if (adminPrivilegeRequested) { System.out.println("Granting admin privileges to " + specifiedUserName); - executeSQLStatement(localConnection, - "ALTER ROLE " + specifiedUserName + " SUPERUSER CREATEROLE CREATEDB"); + buffer.append(" SUPERUSER CREATEROLE CREATEDB"); } else { System.out.println("Revoking admin privileges from " + specifiedUserName); - executeSQLStatement(localConnection, - "ALTER ROLE " + specifiedUserName + " NOSUPERUSER NOCREATEROLE NOCREATEDB"); + buffer.append(" NOSUPERUSER NOCREATEROLE NOCREATEDB"); } + executeSQLStatement(localConnection, buffer.toString()); } finally { localConnection.close(); From ef20124903f25b9cbe241a356217a6c9aee2dffe Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Thu, 18 Jun 2026 09:49:57 -0400 Subject: [PATCH 037/111] GP-6896: ImporterDialog 'Program Name' to 'Name' label change --- .../ImporterPlugin/images/ImporterDialog.png | Bin 18687 -> 12755 bytes .../help/topics/ImporterPlugin/importer.htm | 20 +++++++++--------- .../plugin/importer/ImporterDialog.java | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Ghidra/Features/Base/src/main/help/help/topics/ImporterPlugin/images/ImporterDialog.png b/Ghidra/Features/Base/src/main/help/help/topics/ImporterPlugin/images/ImporterDialog.png index 3f70064d349eeedd87ba88c2177535cc2d70eb36..386d3f7c3b6803d67d27a65f597d02b79ba64fe3 100644 GIT binary patch literal 12755 zcmcheWmuc-x~6F<(4xgX6p9rKv;+?t;43Xw+?}GqwMcP?wm6|s0>!1cyA>-?2p-(s zU3U1o*387!?Crn8}77v>W8x0K&@AY4hcW7u2j#2mT z9%G_zvCJ87P`@5Hy_1zhEB-~ZfqL-hy@b338d_-#&b1K+>hTl%zqFjt(C|C%e;&lM z<5Q!d@mRcuNT|B&?;r_Ob;pgE_w7unU%Pg8kf~N}G4fe37v@0Pp!UjzS@M(&;+E0` zhgJ2KB#W5uh99?kBJ58s6n_m@)r_(S)_rPwE$RHlcATteoA|*?*6FTr={H+&kT6#= zp}>Jqm>FYt0PPz|qVls@xA&_9+^_muaE;TN<^=b+_XcOq-UpvGe%OOiPH%79pg|yz zxJo{oiI1R59zsGwGagJKLc-4&+(TiZp&TFm6d(}O2e{4*3=BAi--rnbwOYQQBlpgh zjyFcm*JYg!Y6n*q*$pn_EIe&@GS3&u#X>doJ*4HIGcdsWwGY>Z=)8}WXFlw)*WCHc z>&*E--Ulwt)H>Dp+_1Q>XK4IzS|fl=_^JZsQOig!%Noq+)4s@QvI+6sRU`311f>@> zl76_|A&hLgjDMaJuP;TOrb}Wk*poQtUhy&%)Lg@dkAeNH0?*-)$4Rb^@P$bg&t{pdwdn zw36bBA+z*zUyp^D{gAY|wke(BMYkp=yxMc_;sz%?KbLBF;T>V2+XVOJ!r8&ky|m8c zSIEoco+r5c^wpM{F<}RJTyblw4EzFdZbocR#h-CUX3sb}%X4mXa;Fi$*Y{szdS2t* zE}w1t5^qIM#j|InXW28-ib!oX-S4a_5@rx1Iz{L*o9MVoiX zEL1~7BP2Na?ud&klzy!VPvD@x{k;C7WP=IMZRYk3>(#-I`;mMuz1AV)Z{)7Tv}iRC zmxAZ+m!(|FGZR-=b-WucAX&sq9i!(818I^b8S;v+364(HoT;Xl&dxINzgvtG`J0)^I3%T372DkJK6$i};FWHJ)OI2fEb*>R2Q9lXro7Zi}uW8(NG*|>(;5HUP1-^`nSsKHWVc64nLQhhvfSKx6V2NET zhthdJV5;z>_4k;s9^OF;ah_foXfRO^nqt1sR{Bdss!chajHBDEN=pUG=XbwieueMz z#F0OX%0Bq!-*~0W?@E(xo$%@Y;_wY;q=j)Oet|j;PM6Ue*KkLFgyr1j5qkar15Sq>N&8m{DUDsQZx&dGk=x{{L8 z+u6XZCKY9|7;RM*HPQ5_e+wspT`_Kzx!)UzyY%D(=OqNMxUvIKS{$#f`12>)rJVKC z{$$f$JU&iYF6$J)4OLQ?3GLZ(uVOO0Yv029%k%bUwPXfnL|Ea<{%6NGm| z&{zBf*^id`);Uah>C?bR@M7R}&KhOcyu)dzhs=N&JgmM1%)5{!Wjb}1{)S;mmD+*JIOU+k$OX;awQHjR|LV8wtdT1 zdZ%EeHs=$U-P7}VE-?LcNLx2D%F?<1jeUc;h|EQgZ3OBR!mELol`%d=^*KnM7`3v! zC$OTY_~S{%pCb0j4w^DsqBez)m-N8Y&HSYb?y&K8c73ecG>pBKeQQ#h?aj9Kr)L74 zgxkoH})_mKv8zFCYs*?-;sw*oq zvR2rrLP{1F2Ad-LfKf{yn$HNYeW0|Mn3zhsx`m04m}Lj^v)v|rXGh~q@$^!+MQpDa z6kSagZV%hKRO;v^-=?~Mi1fXz8R#mbE3d$7u=8+f)EnAb7Yr0Lvj z$;x3Z?X8%$VCH0Fu(Jp%iPw(7=k$09#6vs_Qtegi3$}JD({lCI;~pY25!$U&ukp1T zO%_9VM~b>0UOdsiswr`aQ=KKw@NwoT8C+4?lP|5!rvp#;0$}c7f9ksV#zG)BBncxV z^e)J~`$bx(KL5y_p3QIWzC65u)FM1QI$fwv#9l>x(hC^d7ojUqbk#DPZr4}-FezRopii*lh-Z;rXZup+%Yu-T)#E$&PEg|yRu=nb) z_vS{K#kV=1LTxQ@cm+ghPbyECC~n zdmDGl(#pdsJ;)Wnk_@v)Ws~A8lTKNGeaT8tt0sH&I&qv8CNF@CccoMFN3Ak~3Ne~A zO`cfybR%M#kyVGPOPbBySTC<|)D!+QrJ$g))xuH!yKbY+{xYz=q!Flj#2#2as=5^m zQopf(K+AwLmfTy_A%wcN2l`j;B`y`JbHw>{jii-D;<+!msxwPSi|Xz~cE|)3a2VZ@ zrq!*pH-{<&r=byiwQt8?axI#cd#tC03rrWJj3GK>3$tOjdn!mVxEk{;o_+G;6KV9D z-*$JPho=Nf{?XsQWray7txriWZCE^^r??;WJ5~(<%(ERQcJkfsOos| z+~ihz&A^uvQ)*&4!>U&Jm>@gxu~K7|zWm#feIc`?tg@KW=&znW4dbG}tQ+Swzn`al zx+=?*;V|74=IbRPSUgP!DmE;UDB53WmcUXBhV!lvQ5ROpn1-^Bb_3F#Gqc`vlGQr5 zzI|M{7e2?|#%#ToIT1I{wdI!+JH0mE7-&CTm1tE;?8{n;FeAI+a+@X<8*4bhF7~yr zPcxoCXod}hK-*_d&h}lKHRS6H#=`1nah{zC1DA@bPZ#rY(%y{_Te9u7HEDX=7JSSH z)p%3RHKDdNY0+`%lC?A>?~_F1L}C|XdB5?pTP<*-TWdLS;CdlleR2Fs)PJ1o_AmK* z*BdJAz3IsEW}X~qTzP~x-aRwUe(_0_{z50~6fc3gTC#}cr;NUS@;;d~s3(h3neM#U z?(g8gDb7H_*YIYWI12+q8QT9AG=G4P`d?j7P!SR;lYQ7O?T!>rBnS-+WxW!)+Aja> zce`7^x2bi{t(?KZ!K&ZN3BHDg{(MNWj`|Z>%m3kj|AAOE^#3O>nSM1WLhO!O;r{)S zUOSi9?ni7ecxS|EL<8zY$D6TX1#nhb-ZTk6o$iWuD^_MhB zi1X29_xNmkM9DRU?{OZ%#)|?S?xD#Lg~i|n(tgky*cO% zIFNziZ3OdlEboVo#SA(lW~)zrvxnUG1aVoV<8!iWXFkCpe8})Qu3IzRX6)-}#kux7 z?M1TL7;%2lCr%VPf~;SDERRFDcghNFL*6zThXX&CY1BmK&_}r{|rp+03Nr z`hiC)3TA)4e7RWke7HdqUX2V6rUzRi{#v`G@}iwKR1v0Xyjv|Zrh{c*QdfPilZ3-M zboTVx`Sm?<(%lWgqK;>n4bHo?sj!30{WRhEhBN%@<+a3pU`cbp)%I5D(l7yhYfry( zkW2sf;4cwOPwhCk?M%$%q!uXEieq#{Big}8Il4IStygpdZb-v}6H1po`fp~6SntGE zfSjobz=j>i^}Ny8SG$-yB_-$|qIZJ%D>B3M>w~(p%eo_w-KR4j$HQ1(t*#QCy$ABm zZC|aK8#S-6h41!s=I+_{hf!T1*pJTpOOOGBUfcS*jjp6l8msdjOSCiT@4NLb1Su}M z$4|;%#rP?_aNwmAzgg!=oqyu1cKB5Qb9?ql2!Q|1Zl%+=3vnLpG<_F&O2~^?qZ>qt z52=2MhGH0FPTxgO@a0*<-u&k){>4iExpqW>hJ(wkQ1PHa`&?90bTeuD3_`G957z!6 zk!wNrRk^$KR*1vq_wnQV_e_)UL$xljltox@)RfZ?KIEt>S2q7bkcVD903QfU{JQz& zh@5YUfIq0O-!1#DCzP1iM~ZOosIhw6PAa8%%{@yc+S8qWO5F~dB$*GFE_8-@KGcOj6vW&f5^bCPGK9)-+C0Cqi*v+X-~L0? zKvZ!M^-@T~;a=2)0bQg>4C&g73EjZ5u-7W`X{^F4%ggge>31TYA3l%=*3l%6ta#Px zzMO4vf8qwMArP2vx1ZF#mCAm30YSW_k|rub_MOmWbV5YVEm$E2Q zd+^Mj+x+RK5?;`^T)#9*h(q7VVkv7THigJYp>@SUZ=BI?M=4Uju`vv`yMpm{5N~qM zDT#(tMmbd^#%m{Q-6T^mTuDUeh1~OAAB7y^lamv|3;?c^px!UVgu))IRrDHWg-)mO z;!w2aXb+yx6!+I(Xa^smvYhBW@47Wwso?3AQ#dnn<7WYp0GY zgt^#c4Y0DoT1*SKp2Imz@lO^O7MOx+=2C~hm|RFkD7f0GWCByjF|}{2iwiJ zU$}{@4$v2Df|`BAZjm9o9Xngl_C)Kd+@=$2WA}NeutK_M$e}H}TP!a+SOuHLKJ4hd+n#$hIcuJKjGWcn@1Zp^Ep^0WbUzxMpOnRT7&L>k$Fb0gJ> zgvm#{vmtyH@D6B5V=GQ#aYo;X+IWy%xDI9fy7J9x9i`^UL018Wy0Jzh^fsP9P)#&U z%EC`Y)NYV5{JB-38Ee{1W?!85acM8_7$-JwLafwrlzDhwvNo<+h|CauelKxI8VQr? zVviJYE;f>cyrkc-`Gb31DVv9^JJ>Ve>MpfV3JV!}<6^i54Fuwok$Tuj@-Ov7#4IwX zjEH=8Vf=uu%W*bS3y2c_O5x-4u!&Nv7tla{L8lp`WAmU;%S7t73-A1V3~PTZzVE#C z2)Gy{cE!5eGl)Q`%Iy?Yo`KF)(HE@!{SfH53afQb_6@jYIJD_d^(Qr&+5^p9PISoR z=F0e7_gR-g#Fe!*u<4rkdd1-GmFPY@T}x&RiSZJ!Cn6AS_Ryd!;=NC(!S!;^`Qe(V zpQ4wInbq2LC5VCDk#}i**TlZdrbu%}DS()>6N_RM^2BR#!9Ze7qqo%iNKfG8nxg4c zOkv*I_d@Tw-EDBbI-C!F)UsEsnFK2hRwzVaSTcvYl!2|LRL*0KlEE!m2!y}d2258L ztRNud39yC^v`S%6J4~lIdqKa3vI^_{7cOa~5<>rKzd%0DbKZ;5;On8_t)CpaZq6ij z;BZw(qiWkDJG(PE96Im^$4>9TPwVl&p{`jHS%D9yg+3^DlhCQMY3=XF<&G|u!b5r$06+Ko1Ni8p5Vl6uKuL%&$4&q8cMby>8*;zYc z>M1r3W#P^*hyGu`!WT%Wa8xe(&GOhr+;=&I*x~8I7~MW5O}-6yX;UoR9FppoUrV$V zW2VwpxKGOoTyEgoDp9Put821})P+@TGO2PGNkqc~DBt$YtDS(H3QS?_y zedQMkexP|vsX=|7=jh9IZ2t5H^B?=%v;2#BNN$7d6E;IEm9gJv`1}Q_kmDJOHH7vK zpwxau5>!+?G4M-f#KPWFBUhbFPbvZsQ_1y0-(&d5(FqnwRba!cZ%ka8Y%`0$s{u*I z5LOCU5)icAZWlM8%|{w%e133T+aO?EO+B5NXz=T_!@F2lLl4A8Hky(%PwUi5U;F}| zZY`?53r$ZUBk`s&NFuLvLU~!-!DB=p)&&^7#5z3mzKa_&!bL80k4}3W1N0u_^u|sz zC-Tb^fE5O(^Xz!6 z;=teq&m!fTe9OLi5<0&%GN}2s(1nR@Fv*PuRF|wRg13WYFdH%53$+!FsfV^7x(p%Fa;T!LJg?8BjQL=~@P>6;H;wTOJHrkNLUQ)B zck?w3#zfhQ0NHJG|IxXC;iJf6oa(8VtSY1B$J%-~o3)Ob6P%K!wuc2e0|s+-6X$Y9 z-&iCNaMO>uQ}M|HJbST-cddGy3ZsDYA?)uL}IrT)SC0dhlEUKnMN4fva+&Aj23Xdp8 z@^?^~uZbU10~VrblZ;ftRbzWxkNLH2fNpjP9~|^C6e@yw$)IZA!$I7-au$=xS>#>* zIiaao=p@xJ>V5U`rOKu9TIHho4e=Mujw7ddPMS}apC9_ zQo_S5zU*vfX1g&e>rTS2b|c80?3C07qc`KhjFSX~bX|HH@Wat4BX69P$;_+hL^;r4 zK3Xioc`4d4uVtYvDZiF-={dSLYy3cISpvl-+f(}K*$^RRQr%ytN$J!S0DRkknJPa~ z@AeccO#EuxN799EPr4oaYW6}Nl~_Mq-HAm~2%84gWY7X!N*TMs6atG;HSTh9L|0S| zw_nI#>|6puRjVYb;vys1sbZ{%p24Z3`~a;pz6EyNj(bwn+RDb&?X&Yi>|s>N!*4mQ z3M*x_@ZjdeHoL0cgIDcG+vsKbxt&@Xi-#Qz2YjJ;1h&-|=5;HZWC-OQzE%8 zZqy6Ut-6;$-H57Qmoc~jA~I^{$!SqyZqwL=cOg%-OWTHa2EmT!SDCq+Q0xQCbgV_R zpfvKWT1&xb2ZPK-#&vuX>@{}6T8z<9dJ0~V8rj!ooU3J zv!M5-^VDGV^~ESDuVWTy<}D0!gDWO9w2TfNj1Cve(V5mDzpNR5msKxMfd#ENetZ=rE)wmxp z(BR8zHzDQ!v8a2&WX04f(64tb0_ccpjXA=0iH-iw;r^3_@u^gt;8E~!mT$8#Dt(gQ zsO=+8+LZKw3f5&m^z1#%YHVQIu0KefnEqrjD|a~@;}bY{Juo+F0)bSdnAQaAhgUf? zU*g#{H`5i55iRrKZF%%W;Pd`7`&sxc+LyR{XpFO0Pon@L+uWGkg3VnsH|+-j*LfHi zwB^+cdywV@Eei*Hai@5O0`?}>DRDv`?^oTLuk=R8#x`HvzfYkJoo6flXxyn0s@#E6 z>H-FS%d@Sc`@L|E4}s;MHF8I?Y*((gQ)s{0&JVULHVOf_fr8RZptArdb|R@46n>cX zbEj8&Fz@FyiS|4dwLMsA_R`BXU zL9@OhJp&xE9E>E%@vmGKu=1Bbyb=F!#>?&asHpf>N#*3TVnj+~k`}p5+iu|yQ&O1y zsrr`VCQ2_DN3oTLE#scUu2E7l4Bk=DOe@tZvOn3{p|T6e8MEDNj&3gg>(XBWs|0tq zvyTq~91mDpeApoZ>~c`~JBrx&nk(+vtgXaXEp~gpmB;SDde`I|cHktL$wa>C^7(#bic1ev0pP4JUHtr`3u?o>a5~)~qDxjE>V0p{%%yGE|8o>h9LHr$~N2nlVR*57yG*gDS;V{ti|eaLqFv zsi-HjqV>5Gn36k*EUezIG5bBmimd z{1*+BD_V8J9eatv4_sQ%-1DdAy7<=CB`K*8k4&5GuG#J3jOQmZO_r@VniL7Z6Jfhh zf@&@f#~FXsJ_yz25Kyl!u=(z)x%<875hXY%G*mqk7ppGMa$**Lt!B=`lg!_(F#==M z3uW7mIuqB@$Z6|MG*^pr>geV4$*q{!?Rr~CvCD0{PEa@4Z%}!{5B;ZC@(|NSmjx%% zKVLHGRB0DC<9mD7VvYu;%mkQ0=&Ij(oKC(kwI1i1ahGqO;@`kDxsl;ifQEEcc!Zgnl~ITk2fmrbV0tN@n0BV)0C?aNC67*{)ZpQvy3t< zdgIwWZ7xi;%KG2_y>~l*I4sGWdx@SP#`~E1KAH8rd=Xm;Vx@6ne;s;(IhQgKfd4*Dss zcy>lgOlVgA)@#i(d!NhgKFt3&MdY8>sb}z`d-5HShNAYGF?V)irZwBQoIg zAiz8%tu!S!0*{56;8BNkJRtfZi)6ieu#~<@-PzNjG8T%{cW@8X=|)Efw_BZ7w~ow4 zy&%NYvUDQsWoDLouqy0;+Zh7Mmruh{@Jk9r3Tv2zV}+$$q>+&jU=FF|vAkYT86tNa-VBTD{ygk%}^COXyjNy zAFh6bf99c z%$i}eADC6=3xPc09@6-DWiO^%gvWC=z%KNjM_3pKRj^&Wce2g8hNke3&u{k6#xqLB zqA`yt`oa%N$DYgBN9_B;Q6;bI#uG3ESX(r*q+w+PAV?hvXBlSQgxE?8d>+QWOb$+y zvb*8x_|>ai@pkuRN;TFN&(vYXi;51B_uT#dQly?Ix-Js)BEiVIJYnv~G;iG{o+a{I zEm(Q%(Z5wqzO3&H|Dh$O8(FgS%(HLVXY&d3!5Zhx?A_P{-gHVx>69H$^SyD!5pA)( zLcB*usBDaTOlnxJHgDgIQzR>M9LKE|O9ry8ZzS{fOvxaz1%FUx^~c|}8Vx&0p~dLp z0PXrIuAWvXiV!Ur81wh$?X)MkVgD&KGB zja^CbvGhlx-9&tX0Aot|Gen4Fb3S=yhWRbU=wY^YO(rGQW&k-u+j>?F&1=R6uJ>x2Oa$J7>$F#^B~IO(cqF`*WOxX1B}DEC5oX0Dl&eq7X6Ubmb%uyG#S~v@iF(G`1&{TGNKTLY1vIu&)uRt!Z4T>@o)C(Z zzLjnJWYDj4p5|9GT>zUhgL%g1rHi1VB?j$B=-wEU*wn)&#ld~r!vDld>n9**M5@>< zW<|m}Y_a3%$>iCJli}L#OJ!xy8Ev1B^8pL=?!r+GF6%ARZ^`?*kNyz-Ksj=S1!7TP zrgm46$ESy)X2gk?;PwO8Y}+Lh8@rqF;nE`PdxOS_{a`uciE0ou{Ef>UihGs@bBIs{ zG?W$l{x&oe`uN{OLk%yYN97$*eD-1*8g6orKxRCDH~FUY|2m%ZpRnkk745&DX!>_A zxxJ69zUw`E+VaPc_*h#j2#zO1iDy7VgUIsQTDy7qMqb##8EQ<5)#O*YSWI6cuzkZh z{}X)qX9Qizc!bN=n9)eKyr-4%H5gU2dy^u_fo%)+-2EzyF^MA3!}IUq_vPD?#X7}$ zycl5;hwU+w@LRr>*^NP))HKS}(eWKF>R9j)iNW3a>kbsBc$T(QUOtul2>9?weprcdY zFo;y#Fdt{-(jhyrs+$)Dn9_yQn#|?XpW}n6MrEu0+pF-?(>^m8U{y_48RaPslA*3h z*|&Fbo>SzHvT%PrFEa7OMY+a{quVcd$(YYP=DxE_PuI|umzP@!AT(?IxA;tv(gCc|Bm)FnX#XJwfNECMr$XyX9|nz>U{QAk%2hxhG8AHdTdhcS zx9X1)q)1Kpt!9RNOvsVeRpGc_0pnWJjeRAc^+zu9wONy@xcK0^@2+_z4)U3^BbZ8@>QLlZ$!;w}-BZ!Bq9`|MM-_~?#!MhkNL04n9$w$m; z13KevA*N1swXgLRN+f|Y!;2&%)TY<6hzT`fubLMIobdG(p*H!O1+oVYpG!H%oYV>K zk2a1P;o?m}F`PNV;y?qMQ2y3!LKV0vf2XF$Ht26lisDTWp zj$b?cTb<#E?|bR%6ISC7(|&+vgSX^cxs{m@9OsrDT_|4Zv6{WrBIMf&`7FcZp&%BQ z;r&#A4G3u{J8hB;bY=2<7?3NQJghrM?5*}pa{4|1@i;IRv4i){G;{T)&Y1O67j|3x zkTzVmtRNwv8tMG;Z9?sS$}nMNmPN9T(k%%KCu=H_#pa<8(5@v=2`K1w2cL<|; zeU$PfR#P(+cUH*^bXjZu*?awK7edm;3RR)eJ{09@^u?11DNkuoYYDq*WER^!Q!NMV zR~V(wG->w9L{tN$ZR}!dxId9IJJPOtt1JP|;hwL4L!F5-W}=mX;Yzr5)eaBS^C1W^#Oe$Co;3Llj+j79{wX%wnUGcvQYG3sv+mDigOsg@J!>~WPtwc{_Jvl*E{9a8- zeyh=)t4>P?)JdMnx;kJh`c`2*B>5Y(5NDqC6lGk5T6~|h37V*%3mThJ4`s_%Uee7+ z;q_zwg}&Rh(U-~50}>oss|Hl*se(Dod4iJ*vJ8K0Nt32ckm3UTKpAme*+_-H&} zjHnU-;>DxpZ`e5aqOM`#t2)wLK;T_`lM&O>sjZ%XqI1}Uw8z0%xs~eaGw#Q#J!DuQ z)dv9&Qp3)-wJ5_`qNvK{Pa@9Nf0T3-dmhOptJaifC^1Cr7b;1HXQ~ykC6TL@*xpLNV2s8*D*-({`Q6lHlFCpI=D{9Y{ zhaIcJw_C+?3ajkqiDt<_M`ClegwoAkFw`1gUR!Lp%N^1)Ojet+`Qux8pY^>@)NGJ- zr1uJ~@>iYX3ihuwa0C{emy#lVFW@>`px5eUKU1)W=Dy~m7rTdYGZOVBT*fgjlx^NV*mjU4Tgf| z#buC1yzw_;Cizha!71ElA2)^8lZeJb)bp{0hxRDx^9!M>4D0{_V*Lr@j)RF2|HW1` zhGGqx0gI~j6P#hIE^!vQguO@6QDY_=&YJ%auz~nvVmy1mG+v3C_3FEZC8L+4hF0MO zF2d{Phtc-q(xy1Fro=w$mieG(0*ywk7$n03(Wu3TmoeCk5j>AFK1}st1yomrrd<1( zEBjX0)O5EiO%mIL(?PuVBvcHl1!Q9DBRv96DDW!ne{zo_N$Q@=)i4v0Klo)bLA$+4 z@d&?cDV6mh`d3!c%-F{(u7NK}g1!{thF}sH!8e&}wAgnKh9vo)s%K~@z6>=v&MKa| zr+;Uhkm3`%(B15P`EaHV>5nSoLj|6l`NYM^>)Gx1hiRp~*Xe{K)MxgXH1lVw1Ptb2 z{zLQ8ryyAH5^c=0Nr*lMZhlG?c}VZ^F;l^~*+y$Gk`nR;g_UwCf9To_-*S><=AkmO z!{0q`+wW}XQNH@Ii7xvKcagU@GhZGb;tTqqLfKYk50~NRbR3cfj2spUZX_9+qX(1y z3M442fR&UX%k0ipZGDwP4I}CUOMT`AE@p(ze1%nR-_k-n5~p>EJ{a7h;NhZj!H6%h zU7x}iwwPtLzR0l9|14Z5HRCWcB1rBy^rVFsIhDS{B1h|M8&x*;KITU9#`_k>t)SWT z{HtA4-mTC3Gull%-irw1>1w-i6I0jAW6P5_&XCFA<|-M~{w4h9{#6;P+j3pn5xy8x zJ4tNoW^lJL?)is}N`cX1!VrU}TxCorWL9*mQL-dBXa<%suh-pDx|-+o#MKWSc`mNwVLkr468nT zY<>*H2L^q)#y$H-7U&-tsUGo%x(kHY!^-gf6i1Y|feHep|H~H@;DuP%zNrD@3cqw~ R?!T;o_F7s2QY>lc{~r!)AuIp@ literal 18687 zcmc({bx@V-`!B50-Q6MGAV^CIg0xC^N_UrZsDObeC7^;LCADa25F|vASfr%jA|<5G zwf5fMeSYtI&dm9}GiT=gW6$had##7(zV9nOaosyfPe+{ypC13hg$qPCG*k^PT)4Og z{}A9_f=^z0{UEz=L8JSIs?x0>%U?M-#+2#|J*9cc&1!bK%3qBuo{{Pc&=Tf3hERut-!nhEF^R(4Wf4xl9HB*&tBt+kn)-0bznSs*OZ!|%h!Oc_pgk-+BWb9JZL z;J^UKfEC5f4JN(0<uYIgIo|)JeM9HZZu;`J;<;S#NhbMa%_ls~Kk$5r zM&kWcKAxVO7#J9^u95CvIusTXLXB7285tOy{n;JKF_S8L{l@%;4kDXUHwpc-nQhGa zcxROcw(Yd-LiJSTFKioFj~+dGxe>UDtPdC04xvXsTmKV3o*1!c!YgiWZkns1`x{IB zH>Aoe>a!`;|9Z-f-zUo5C!AJRvzLzdQO*88LNsj|FNYh<#rbL&$X?d;lp1+_BZ<3n z6JBY%QuK@1?KcXi?pZZQ5?nvYWsz0Kb)rAI!#$=;UI)vTpyau42JFfEzM!h{a2m-^ zd0HL6+Us?-?rea4|Mq3M(?9FPRT-r;4UJkuU$`r4pPQK$kl%e#XWg<#xfDx%-2z`b znP%3U!@O8GQr2?bDTAq%R%UODO?NFRm_Lb`Ib*MB?F*ZM&W35;!A9Jtz+aPnzf`W@ zKdDwxpO-gn4j>B45VCl;Wv|IM)Fi8P?;>&`{Dem!lfb~qhFk}~93NM%{@=v8pdDC;OyzDh)btGQWD&v z7c%Bb;W-sJsAJc9g#A{lj=A_(3Y*Hrys(+1){ueD?9J>%dYzm-GWrL;Y?9JF_kFL$ zF*W$9wJa6odJ?NBR2MLd3RQT@Z_GL9^A5SA*@G*_1vMs!xV9_3c`&FB$u9U=u03{5EOCd(8E^ z$pu?8T|g#KiP={~NJhDyCy$%3>tkC?M~v`?j;&!kDd@V8;0&| zjmPO5&n?HFOy-TTE6$||3u7PpCZxSgksHdjxO*8t>9eoYLEM*u?_4%h#(&28@G?{q zh&6M5-@K`(llz}lb|}ZB^>{e-Zlzx}uMVo*LpD8n^`rYyu9St0Dt?mH`p0|C8@vwt z@{RId<4vW~XGBdwxpb8QwN)FjN*QAu&&H?cudp&jUPk?Ws`A{uj~ul0cN0enCpyyJ zhcj37X$<~JQ;kokSaq4I75t=jB=@^|EhT^TTe+3-R@YYAHAy{MmbcsnKcBw3ggf_` z!uD34Mes-P{8~Tx$uxi9g8i}MnOLc>hQ5j@qTp+ zeD7?Tn(!4NFFUQ`fZSHUtdn1qMp8x_*DJ^4v8=AS=b4$=K@NrUiiz09`$t_`)P;{Ee@&|J9BfWKo_4giR2K2@k+MKhYb9t58u|&+&PU-~ z(J@Q*ki7fNaryngpvU;3xWHM9QyPm@#3fn%L;DZjnF_wxUs>9Ov17jvp>*cDe33hv z$es@>^=-kIR~MR)?$Jyf6Ws+WLA`1bg1M?BcqlTK8*%J5UnX?!V`o1Tw2D8GJ{KPs z3qXxA)!i)e&DFX`bFw|2dG~j7;Q3kaOLZR^Y#ZS;MwZ7c23E4N$TdW<)=Jp<$Cu-i zQ(ECc?RNMqP*_?SC9{9U9h@w;rHB=!Nh$I)iD~7IpJZngd%0ioAw$ z2QGeXb>zIypwqc#C404^an8S&BH*iAcc;brz5z1u?1cbbfMwsxSaY}Ti`aJ$nWeL* z9XXwtr0TPT0#jbAaIWw+k5%Xw>V&hjbqj~hbh`@w@Ae8LZr3ve4EHHs8cD z>MYrmIpsKcP|=$ZXD%_CEW4Y1q=|gY*%2Z7k>#mh6^f~(`Kf?I3Ed5o9_^zyyPOSO zU)Ub)Qcf2x@ke}2>W?s{CJ(yk;oF**;6?lH&vS>O*zw*z!xpu>QLVzh%eq|s9I9%) zsVC&_i~TItYtuG&_r@!4?7;qZz79SWDEG>elZ&|0k2DVJ&>?$mgdai1bToaO`TE-m z!aKrAm!D?))$rg02J!DrmXlcilLK_027`s>Z&+KXw8t<7&1Zj2D7tjRd*q#N>#xbX zZ^D12oNO0b_8zb}4<*-n&c@#m8yOk7pVT;(d9)EwYkSlj8lgg_nnvTGlaE-q)2MhIyCbC9tLtE_)LMuL}xo9wZK3d4>KYQChZM#O=7o3b5Vd0LH8vP{Xx_cHL zYVCI-x!ZVQrYF_fT5)qCpfYW_r@wK&%n_j`+&W4SX_3FFKN3n(Bz|$m?RR)i+Y|=o;y8oa_=;B zz%u!`pZ!;L(qv0G|Ax5ZpnX7_+|WYzqs`}!$6bGP2QiP+gl)^!?oJ*FcrfUeO9Zmi zRUpVmdL|TgwkR2roTRF@8v{@uvz;_615>EHQjDp%=vpIMfe$k%G|tmiGoA4&*K z9nRXba1VE;!WtggmHe+g8R5~B+^Y-Hoc05l?=EX&Rg4&h|8$aisol6gF8!h7?W8W* z@zfMf_O3(5YOjcK$U&V$!p4Nd(W$9--p+Jj6YeNB9j5Jb61^eIpeQfI*~;&$eio}- zK6XjX%sES9IKdJaS_I4D{NyzcUh|eqJTnu*wns%Ot`Cb!97YdQm>ET&9yvT`u@JIs zz&yfx%*_$G^)d1aBt7)G$2l#YR?AJwPIiUuRkwHFK7QWe`mNBZIv{A`!h&hiWEK|I z-QUl#_-)1Nd{-W-_EiA%k=Xq?ZFQ&Jp!P+2razL>qoG}pnkYTGXpdQYEW(MVyR9Q$ zoFLSH^!?|eit|6~0Vs5IZvNIpPOvq~(qcxi(;TQCwb}Ta`kj?WWEdf|HH@)7S9@xN z4dpKUu9(4NA=fwHX*X^6s8*Ie*yuyvGfvNXz^C@`3Bp z-A{pr!TQV9Bg-bnF7BhAC!I;d^othL=C3_8668rsjh!~{b zz1>%7%1M*%tKgV$RTS)$eFHR?}uFUXg~_;JRwZaF4{BIXg&GRck`Iu zW_v*m**h35o@?(xxo?qqAoC=+zVD&o_`H_4;%1Mo+_HZ!l)8Prl{r@bwHb{4&6UX1 zZ)%ya>pZ_)pV7J5UhL2zkRssNxcb{{hVU#6_pv!y=#4nPne&?kH)Tax5rMyC{E6i@ z6ZE?vHHSo{oxXAZPC52ue!eOC?7ZTp^ZgWjs}Fv7Tt5L`$@;DR=^D;ok1%Cm2~T?Z zlNU8kXQOGIvCucu;2_RyF72)UqSabKAkQS=g-9^@pzW@S(-gUb1kL9T!kz$TL)?b= z8;?jS=EFC7)8;w0Bf%vB{jrr6ruN%jb_L$>(cRdVM4w4+x_Do##iEUVCa3?b9RCp3j-z3!bn%`qPzz=At_`d{G+r{vxw)1*oouBOm|g z-wz+K;zsMy(9zL7U&vL0Qe7M;uu#T^8_jy_Vv?*9X)HdQH#dBPjT42bM9LT2nZt^! z9G8ZmfNzqL2S&5vQYkO!kYeU5YasF9N4Wp@ek5;|7WSjfWiz%bS3iaLxyq9SNl4eIDkI_~Q=vvN!H87Hq@+FLq3GfIz;P8ZuLit_UsvJ*G z4`yw-kb^Ws+G$z)~#$%)t#nOKPCyy(IwA$ z6sm!&BI=wT92C;OR_iy$I*=>hsP#<9wnPqp;jD|s3fUCA3x%pN;8!#cA)T1&#w#2G zYJt_U(yVblC8cS~pr>Ixs7=(m%?4#k?u+;)Ann^EyLOXWP|gtE`u_vMc_*H%i~ zTF=sVmTWh_HC~EyT4IJn;^0QDt*xa{3%;{zjad8gT2MgXU`P9GMviVbn zV58$_ddIfG1|Zm8-Ml!&j9Xh<&Ty=Kk1m_ly7dh<2X5vT7XIjAi8L=z#oH*KMk0;f z%gV~aFo^5h{JlR7=c^noy;|i(r83Ja=Ulvav9~p7`;z9@mr5~W4xfxoP2=O^eWVh< zj+L6B>rI(?y>^zQphd%zx}M3&KeLhN{s94HM&-;eEQ)k;9QrfxbT_6O1AlZs7}37} zvEFwjR?Yk{S0Oz4+j<9yqUx%Pr>C%m+v4KJ@n&m}KZ|0-{gW!Ep%+q~50wV>-h07| zJCmRYsQXiBgxd`YuRn;vA^Gs7F>tfM@Oznscm#`n2L!l}J$tv>nO_K*RiE>CANKxQrL_u2EiIeF{3 zTX|u&?%kWzxljKNz3{n@_nu){JGLtXqReqCQ&V*{G;m+l-g;}0l$5kVdDG{nT5N>V zVD>#l0Y^v2ilE?NHFfn=CRys>!)&==F)=Z6*N^Hf;hj32yrBmuB0@s@g@v`Xw@{>R^pD#vTq#VvK3u~Rc|w*;OA%oEYqG{WXm54o@GuAmC&9KW z*+wEL$NZ2>H~0P|IXO9L5HYRDOL&!mL8U4j66P?Y3!xW@K6ia=KpoPu39VF2!YZDr+AIeuxJ`ofJHH?Rn(7gv;B^|*7h&YNm7 zv$AxvBp)mhota`sQ!y~4VA*vhlF>~f$Xz1-?A=|CH;CQZUH)vBK+0=oHudbbvwo1n zJ?(*PXcb59qRaNbKjS_Wkzc(J4n#wZjALd2Tb^qdE^qSt<^72S;G<>h& zA#p*{SVu?aB(0ZD`HGR=KB2|JjK|q?jFoa3cLJ4c)Yju!L`_8cv(59Pp;1wOom9(+ zpCwC0-K8=$$L61$FvjqQKFM>UCa$lzJ|7;|!`;h~4MbpVU!_c2Vq1c|Ur;mX58Z68 za~fjKX!ZVqz3k-WC9-2wX08;Q7?&S@yf31YeKq}vRu5Uveyhx!E(M3+52=5F?8YfJ z#g?nsQh6^ zb+tsqop{dsRQLMlDL3TC^UdQD$I{y*dDbWXBp);U;*dP9z_nWIo#wssN`(H-ojcAk z3VFPn7pX3I6#mtAGd(3$ zcWUwc$F`QFofN@8i!VapU}9R2DLt!q`10z;mi^K9AW6Lw^4hv}`hVyX+I|GccHzeEgF`U&SbQ|7vLPiRrmF{}3}t z)6T|G3V<7%q`HKL5F&s1rZbJjsOQHeVufM#O60#737jZs1QvT{*a%gf9C&xDB zQ@*%yIh7XWUYP)H^;Bl62@sZ2Q58)Z$OjWWT-q&ML4$F91%Lz$Vh8!t-klzzfE%1#Om3cC8Wr>pC-q$ITx<9%oqb_xuV zZXaJYd(B^B4`JNjm>3-yN&n7uxp5&kKb$0nmYQJTTZz%i!1LX++6*$MCqL+B}E5_lJ8tQ78Uy$t1|Jy;iyh^V`HNQQol$ykG<7x z;sbQGjj6iLyvVZ~T3WLHKPg*D?GTF`s{14Cs-x}gm-tzBIMg35nhF@rLk}d4s*%QL>4?S254-c<6Hl;EBI5AYvoRbn=BJG{6%Bi5=r>l>NCrTyWLf(7kiFC5^ z$ZF=_dNym9BlYK@d6*v}>-&?Mq6isARMYgVZB*m;K9LdL`h-sTsoo@6E-K1e$ImY^ zXXHcnqVTs0vXf+Ywv@w<_P2x@_vgE2N zU+4v7xCf}|EVVYmw}^9SuB4in{eot-_Otn&lh_tjm6iAI;Lob7Ob-WA`v3fjr_$-V z_4{|+V6FR91`|YNt@n>^(ov|Gm7cA*WGzvS6?uKC#VMNO>R1PxvpvJxd0Ssi*z7|f z_l)a?eKxA2qoc*Dg-4-~8a4Q>=_(xApPd{P$0otXtZr_mO0MqOT6jo^RnHPVjUY(~ zDqN)uob#7i-W{339+cnvQCXbRf+rjP!zjq&ryOi&T>y<&(dm<(hQa#M~wfV@N}+5Ipjf`-o9DE{-pX^)Ca^YI%ON zeljET-=HnKSWbA+K{(c}1`@2S*UZzXu6`sMTzH<%gnqps^G>d4*82o+Y?PIiRaHA( zBYEW*=dhi;sV43Ly#U5Q>d8d?h~PZr^(C*EDn#-Inw9{YNUS3cU1GoE9qc3Reghs< zAEt>L-3x6ccD`@PP?=N}1;mO_S19jMQ_9vR4W9^r7{Kpi?@dNWM-9#QWnM+9i1u8S zl_fauZpdAoP+urjS@4isJfna2r+3V72Y?HmxZ~HihOi~%0DY!v-6=9=nu2|i2yY?= zN!7c}A-}1>~o6QGq?(WcBts@V&=Aks1 z)wtY#ck3<0n|7W8(=W;#el?bPS-(}%vN$$;0s<{({Sey|Nb^!q$Ev z;qBu?Zf2FB5Y9P+1vM)n8~bgloBUsBeE=5R!Q4he<~)UP)1wH=VC_RX7UqV=J%p+VAp@)n0QO<_Vr_*NTEnw)tV;N?$+3Hw`ts#N@UZXtwa zHVdz_qMXUg@y#yUbYK(G4i~DESbjS{J5Zdbzw79@KdP&E_d^-QCz3347H|EpQPa1f z%2uvz@9x?K$TQ3>Eq#MveRNrC;ri6nlrK&@YZ`)qM7p#sB64%4`QE*IKoYxDmsmd7 z5YKG^nE?fTxDDuD)mrJu^~lV7J*g}t#KgH*z1fjZx-2*%VN)0x8AYZ#+S^I{_Se4; zefpF<0o+i=rX4fmd(vPLrt%mNxwX+E*Xs7znYQQ?2z*u|Tu0y^Q!U}gyoPT?A_Xu2 zrS9$T#~VE1H!6cD9##rS=5l3N#HJ1qV0eawZ17K^N^0;rKv{Hd04KW^)Z)K>$799V z%q*4uO7c?NigHWUl@L-*Khhfc;ezy5VV{F^ez91pm?W*2%(qI&BnT}&rrG){ogwRe zuhQ(i$jEpz;-QUCBXmD9?)F_u7Rfk;!5mo{{>OjQlrgGRg%XoI>^V}c7bz)P=H`rH z#4HK}KRF4pk{Y+uMp@Z#vx~H|x_2@|<(@PK?{Yb|KV*`XFny|e)|<|8^1eVVrR5GX zZmWdn78a9$!7B|tJ<=*WY&3`cJeP~#D}NbkM%&W<<}67i_1V?z#>UW#f{^>M2oXDb zdrpDG>-m(!(SS#r4`xDv&n-K7FJkX&_2Im8yPJOLfgLd}8;!7~0H1vLABp%&e=dKp z+aq0e3f!Z#?8n_~L56=_sUh^MGOo03JwF4~@HyMF7&||iVjK1u+@1`8{2mV`?byF*}T8!D*;3{`CyO7CAV;g zP$HVcktTfY*JE7;lR6J3G2EA=Up^c#5YD^mN$U>>LqJq?3B3&W*RvqFl~A;`glB8ki=(*sS6*`ub4gf3 zMWs!Hp6eCr;_?$s1rI2ceI!HJy}t)rN$ecxvv}i-^N8fQkG}alQmEc~x<929gFR1b zM%QvJxl_K8#LU^bxEQx?XlyKF$!h8X;ngs&#^b%UAM^9+{j;WO8f@ND%rZ6DY|Q&j znN(+IXKCVYaRI|a9GC#mg^hqsFLF4Ap8Ksfeg{8iTlbyXF>}Ut~R{ms~|K}21 zBOX+ir2D&_pHr*27{>>jLn);7b%1OBvmA53flN{QUqz6;`)Y(KHk7h=`zBWLx-3vF z&i1In>+C4wP-9C~W#x9LO06srhxa0lKhIp9w?Y-BBKY_8O=DSe0wKG+V5mlq>Qb2Z z#dHFw(m2)F?PUBH%uHA5_iKfOgsyfjQ~Cx$;~TK@Xt`KS!rlnt#dUS{p)9HLs5$X6 zGLGwEhw}+5LwO_w1Po&KxD;4%kZ?=O%Xa`lG06t7zDiC_Ri7K!kPqEg4g0(!0|olp z=D_FAIXOA$>K&PUY)@2LUr4%#9B$e4o(i{~7=Q!>eWc1zPq)&x%S+SQd3B~alx)wN zm#kK4<)c{RD#kacPl-ASFRd{ld07}4?<)a*%m78Byj<8c#kW60Fy-(`-k`!Dm8A?$ zAva}U+;PFKLi@wt*!e=o?|nMri2&#z0GJmE(zn@=9`e zXD)_XZf>rqsOab$?Gn?PcOq#<9@ku4_+GIzLtUNhe!u`s+i&g5N_zZHCbdf@uK>_M|gKn(~^c51`ruqKYCXiepJ ztcf=%7t0Fts6Ou5DKaHTrG(Qz&&_?f>a#W1hEz`;EV74Y4bAapfN152$o}sDT$Tmb zuc;-h=FozL427^eX?{eZBwW5agJdwk;}V1XsQJrHmsO4_3-A49+@bt62<+MqA7p?P zYzzyJ)MHhDOBNEOZ-!-f&yTLs%RgAmX+(ynH>S?a%+Oxnf6htG@ZN=V7?8Wo74m5s zuFefvzPZEgA6F@7%;mc*@>2shXS#e0svNc5dI3AP1=ukzVXHz$_OHs0c_IT>k0YJP z1^DA-PR`ia zShPTrD`&EiFNOU+`SHKM<=+1N8w$;Xq@)|b4RW%x{UY>rbqS5BxS#3bDUky0$PtnI z=aEipfP%5%6V@4-%y{58WMpLUOfuKtJ98JLuBMdq5_6)CF4eMd;x7Dp1ZNG5E6w~b z_$v6U^s6*nGpfqE0Yvtctn8LM$F zgw{>FbWDQ3cQ#*tK+nv~Y|F1iihbEL1q~Z*ZEfA$HlT2G-^|o|r9pP)lvvfjF;Ug% zx5i$(OxZEU6?^c4!(7d8M<*%N-rhc6InKb)unP-QiS|j8APO>x!nD?H!T^#f`!w9C z<5Q)LD+T+n->$($o#Cf{evkJgmcn=GZzst*PkdN{I&ORhg2mwAAn-L_tCl99e?C59 zRiVMbH7?)Y+4nuV;_|hkt}dbL+qb8!OK2sWtAv$Z5jr*WcF3#luV4LE26F}?HfQA3 z)q7GE&kz9M;kQ1%zIFjilV3(h)64&>u$-Awzt)sSn$tYiRAw6SJAs5{Fk5;zhD0Ii zec?NU*P7nm&lrTViPca*#(`R+;W2?tS^_cCCr$r?ttX($$66vNV#)Nf5GoVFy&H3L z7xD=S2vU-g*1nhLJ$?H0`mrRV>BhnWISow$?fKSx2YsoS4&eVm5@xxmle-`A3!Xox zv;Xrqii4BsN})-8@W4S04sg6N(9_y_4*2){kF~X<$;suxoRr@mdwRGzIWfucf&r6; z{ffJ~`WxV@FaaX`xb}Lb>HIggS!2nEEQ-vGjB?%!s^$+<8VBcXi#mwp<$ae4g>bY0 z)WLCn{OkSE#d)tihxLBcWM?>#Sx7OpWl&etk}2`<@ofV%g5gL#W}5H_UL{XS7trt) z^ya896<>7ifc-{r_aKpBlhtK?h93h1LqxIyz^wPCA@e$<*RS!QZt_3b^%=dRJA*)QoK)A; zsC5qwkvu2^jN~r}h`7ThEKDwzM3mRBN;gjdm+fftQ~F~&ede&8KJN9gQoAFl`vN8( zFeksagol1jHO`z^av>lh5;U%ugIX9g0`$ZrCeDL!KJKbaXsJ_8;+UGp3Dh<(Jl*fm zV(ptntvgKAuSeE1K#TiJ2ClPI{aKV-xcbe(CE4lQNl?kSLS9)5Xo z)LgX@s&ATpWaK$WOJ)FendM&`^?su!C5^f>jqr}40TzeHL{=|)7#F*`QIq>ka~gr* zCwz9X>$If2rGN&_&|??MNd8**d&K5sO^MIaC!=!9Z_ZZQ0JR6Fr!7`l*?D>2I*$|p z^!etzH2&qwBbqf1l!Af+giGYs+{G#yUV~SE;Rz##F${D4Lkw;A$?EwBPa4xm@0MQ) zG2-|C!BWhJ{;SOqr+@xhrpgR;;QolMkIxRE{p_3^HeKZ}}4 z%oi{IfQ=Cw7iZBJ;10?acudf{$u~g1;?XbYj3b~Sjd9(hH~$Y7xSfvgFrPop3ELh%M?709U+ZgSM>w{Pw{0!pBw6 z`zCEpf1~8uP_8@^6H^>DnM~fJCr_TV#}SMYpiRVJGvovTN9;fz96yLw?Ck8S3d7s+ zL=4JKu3wAWB3gL)_&!ZeHfTQO0~4{ttWIbzCwQhY5TIr)6q3&`u4w7%epg3c+$er` z^SM~D?_ZKrqp~}+uQ)NlwN-$(K$%Lsf8Rdf!9v_spM^5L(z?33w{P!)te4gb3^FFB z17s&FX!%f9Yh1tU9Lfi-dEMnKRSv9BqLT{}sY4S^>xq}>QYn7f&2X{2OiU_Vk+ zW;kIH|4)6y`dA4bEd(|iU>@AQE-aIK7|6p-+djJgmR_?!@&hlrmmtx}Cjf2cW`7LSBL^L?ErW@uc!zF<(7qg&?=BPXhJ9h88 z2uPyTxKjBAcj8IXWM|Gf+ZY^T){7T1($dg;v^Mt2qPu}A$w^4uaz?@~Ca^^CRMWEL zEO^-2jlR~R$#;OmqCI-~k~M!DD)V@QKfl=LEU7#Ibrl-i9SJ08ds4OgjdoU3=*iLVhOjt<;R>0a`4yGE*hp#O0$5l$C7+dt`NW z6`pDI)}U)<#u8qs{SFra0l|E^Z>Uojx>W%rBs~kb%g@hW9SJQ0`6xTvyu!MTLCV9c z-&OPjLO1(rCFCtcMgt(njN5YJC#uzpDZ(uXpaB4}yl6nPkg@Mg`%X>PDI1O76+T{J za{_F6I*mc&{>P>1B`rZP0HV{pf5`Hq-oAZHJ0opPw-$Ve!{{8ctoouetQ0{i!ZJ8WA_MT#M zq>8d~=9qIee&Pw#E>btkmN2>uaB!9R!^6Vnu>JW#v9q;hmmPr{3}3(Q0m^M_Ya=z! z=AjJKm+#%2Zj=%c@dE9JXJ>EEJ{N?-t9v^;$qyeg%LWMSTs?r%fb{fqV+Msks~pSS zHVY32z3;?Y^zt^1{9J)53%I1jJTM3HQ*OLf3ycNv)rM_otN$A zNNzAiZ(mHA1>}MQ5>#_&;N8>q6G%O_H^%b|3kv}E;(l+!1r55%R+T#lFB?KG-^c6* zUfB;N?UHT_kr!0GJwH1ZM$wp2db5a9R`g0!s6Ny$MR4rJ3#o*>q1Jf)>2I1H zGzc(_CbTCg!4jLFpVu>ZV@^lDZBgq+*MEMrl1KXs*lwlDnaOKhE);?~1R47_Tz`^!mIpl&7eUtLQl+w)oxppPulZOo{1zgof*_>o&v|9f(5CQ+GDi*4Fk~ z-zKHH{nkK@2h|>OApjdZ?RyJ$f^GiKuW8B8hHlDR;)Pnp5^NhhxQ4t~T@JkwfVr~w z(C0YP26jVWv_DN>c3r)nn!4h|%gT)cO47!@2i3}M-4MF3W9LWZZBVdBur?GCRXW=a z5^m#Oz-I-@PfW3&R>_*F5XeNU+&757dAiE#@p{Y9itt5qv%Hw`ptsN%woUDv}?jv;y z?!_=TP>|HH;pbVNE%VoL(K2)B-fAU`&v<<0ZMhFYxWX($%=!pyc-x~DHTJo9e@YCPCcrpF9}Si>v*r;)q=Qp*??tHJ^Rj_#2KwMK^1OO% z259sL3RPBxyZtsBaeR14DQwC3IGf4VcN%QQoLreJ&z`w_NS4LL$L9m=0{QtIv9hC# zd#nE`e~(P21!ZSAv?TYbS~U#7K-~|Fxgd3-lqlXkh0R_SM!`aaty)e%T2>>b6Z_5a zvb&V>Z0kvVy|iLD1SbzwxM*Hs)n&ps_J_)bj~_qghgwx)mk8II#3<1rv}oo1-Fddd z`h0zDjgEpMCdVIs6YiB1fCpRbUfxP<9 z>vJv;I}YU%NpYd-Thp?#%%J=PZj5__Z~#*g!otGKqg772pmaqvP-1zvf-Zki@cd+# zL<%NS=&3ivF&{Q`Jjqkx=X9tuSTqmM4|1RKE~A z`j6o=n!GGu7U(0oK00e1b>161w4{Z}^vZ(%$aRO{x zEI1_5BU2q-8Ac^Th#Phej^Gi1o7mbv_jI$e69|Kv?cDiQ>s{g^h|E?#sZ@B3;#M<}gq+JUkqTLW+AV&pE)RVnGx~^b#m7RT?I} zAlZO13QGQEzgKVy#+RO3IBC)Ps0mv(0Y$Fa>bQN^@R@)~bZuqoMQClQSzT6^H~wlO z+Q?Z_Toh=5+_lRLPr7ng69Y-f557|X0njrV@+5jk{tswc=MoTb1HlN?1~xV}u(uy` z>r#gGX90sWrvU;p;; zU}0jo7imce39!}WEKSfujtfj!Y(IbWq;^eSx3{-87P-2x{RtmE&bY|~TFm(;-+lkc z*i-`69>i_^%!~N51~}(K#){}n0RjNcG5C45>y4Q3_v|m;tB?L54kFJ;l2yc! zLyn9;vs@7ChgpPoApm}eDyM|MeYa0PZG(n0FPXeGt1IJL|Mq|t1*O{4FXb@?8hCU; z7Y0Y(3gita;zUd`5?8L=-gre|j*f(r3J4*PU&x=dqQSB%^~=cxlL7*mh9H`*u!-qa zh&&4$uSYQ8NOYrz|DtZ$!_#p+|B_YcA8sTcLl8FvZhF83$SUDBtz-X+isnOQa zaSRX^F27T1`c%M#{DrfpCyCbi+3Ea8%{IUt69g=8i%LrPBY81RZXxhZ#Q>tB;brP7 zZ}(V7Mzm?LsNNWeB^c7R@0wz0iV8L5cG8^jw^(ajgT$4H_4Fwv@QItj{9u zu1SL*?P2Uf*Uj@i9h#2YWQ#!eFFjSoM zdc81J!Pdjz!(~+D*^v_{!74008kn$S42?>Tb@kTxYC&lUJ(`b_VsOq zh7B_;GW{n+=pkf#wr2~(N^r1~(9dm5VA86ZkPgecuCg-t_B~<(Ws73z1@!>jBvor! z77xYfJS;&{elE;24(8uS~u%={&lLuTm z+y!`UV!3A;pK=UoEXoSl!!bZZQTY&((Yp=;sZ#C^jlexOPCL>u=rHU{G&6ms6ZiadYAyR&7h{KSy*I9G zpcc?UL$w~$=sEh3uP}{FLPBzuQrvR5Kp=tf92k_O%U6v;3xB^5d@x@4+A~CEV6qLI zj*6293{rE{jEnbkz1M`t%B}L!uQ1~bJFhDA_b16VM1^vm2;x$3 z>r~g((bS95OS&OoC4|4|(SROv^Yr-OU~jK;FzT2VADzj{s4gZpzC}Fz@mhDYJ5TJq zNpNwan3d)b=rJ<{X}^~43j9G6jg-hLL<<;I6fpM_%OmAElifTu(Ha>EeKL(sAqu7*(>SV{5-Rn~B(C@;hpMV#njWr> za9Hk52hQ5qt9lT=XTOQ012y&-W)Oi$eT5%GlqO6OUHU764i<=6F*CQuqpCU>Q)I`I zpkm`kuD<;U`$nyx$pGYs+5fPA(7;VL(=f=bu z+i&0JLJ`misrFYI<3AXWtM;7DT~a(+d<+0`haGwK%pm|d3W>JMUN#wdek%2c|KuK* zudnZ!hq?)pZbRsNyN886R0yqP2r%|`k%)SG_xM3&>5D_SR&Uy%Ck1mtZ{8dLB10Ow zbItPSz=%2$;wa@BgXV*#e=*oS5lIDwnf`tPkfFbVr^Y5AumMQ~8iByA;^Eg?&&KPo zl4*j5EFQqKQg71{5BCJjK^up9>SHvbA+xjGc?#avxQ>n7NIdu)AOH~3OB93G4lHuu zVkoh>2jD2^LQt)gU5_*?z$~Vqpa^f6^sE5m_gx-9+e*Q#!rUm@ zeE?YnM8>&C`F_R>xWx^0{EZkMx=CO0M`6OUnz8Pqm19jJXR&=E*! zEIIv`S2DG#TtM9qZpXDf=j)3W(&1>{V{tuU_Fh0iN${mB`U$EEF`e?Q9qne7a>ZC< zvfg=DUI6S$w)lo6!-En}9|G}nGYwIKM(^-Fm4z}*I9BvaBpo;E0@l3q-k7bH4-yEb zGfU&_c2F`69wRPeWtnb?b|hgIRym;fRF4Q9BxBV zjEsz2W~Dp;NgQ328yn99TkeUx{D13^1t4lV8F~2V=hEMxrQ-f85tQLT?|_uZ$+=UYXBxakRm77)-e9dGZYW!VgMGV+y|u+ z%%bi6{lOprA*a8MU@Re?kZxz8iy*y9N#qGa3an??7Tb~xsJ!0+9$GesfS6irSTqQX zEr?8Y;@h_x7-)j7)^#bKO4-Y@8{VMeYd$V9h{CZ;Xid;*=xnQl1jw|tr)MOFY^BTo*!;f4*cz7rh3e?OyXrUADy$j%AKFg*6KNlCD^9Z~VwbV^(hi^CW>r7jl(B$;Kj=&GadArJ?rv_t_>I#wo>W$ddOOJoomA6V zJF(U&Lbdg|kQ5rRLX>n2U=_}p^-oA2WCswep&fH%o?_$-TrUC{Ke2O=l~xl;mPsRM zdTXT!cl@RGZd=PG%w$U5FQ7(eJfjHQs|I!it!qh*Zql3QZ?PusI`)5wU8n*`m;r_+ zxjA0R!NxW}@LU{*$w8ktg~2Xg(uko`u)Ki;R(|*(cF0`z!;K~E85S2vNFg(en9vu5Od{o)_2Hg^f7oKX>HIQIr!}= z_bo$1LumUlA$!gqqPXx%-Tx{UuOW{lJ!crB2RHP*B$%%=Fl33^b@w*=(j1D>q`3sm`?h)kP*<{LGF?QwS+TC=(KnW zr5%Efi9GQ3Kh;hHc^eNp85G+5*8F!0=!s%_@<3bPj~LW5@2>n^#Q*0^#k%bbPLA^T zVI}Xpq%dssIiGd-_0Ed8pOk%w)ye;>7}IP2r7N(vPgT9c_%C1nKeWrVbBw5+v}@Introduction

      -

      Ghidra can import a variety of different types of files into a Ghidra project as Ghidra - "programs." There are separate actions for importing single files, importing multiple +

      Ghidra can import a variety of different types of files into a Ghidra project. + There are separate actions for importing single files, importing multiple files, and importing a file into an existing program. The actions for importing single or multiple files into a new program are available in both the front-end project window or the CodeBrowser tool. The action for adding to an existing program is only available from the @@ -87,7 +87,7 @@

      Steps:

    • Press OK from the Importer Dialog to perform the import.
    • -
    • A results summary dialog will appear and, if successful, the new program will appear +
    • A results summary dialog will appear and, if successful, the imported file will appear in the project window and if initiated from a CodeBrowser tool, it will be opened in the tool.
    @@ -99,7 +99,7 @@

    Alternative Steps (drag-and-drop):

    onto the Ghidra Project Tree destination folder. Dropping onto the table view is not supported. In the case of Ghidra Zip File (GZF), Ghidra Zip Debugger Trace file (GZT), or Ghidra Data Type Archive (GDT) file - imports, an immediate unpack can be performed wthout a popup dialog if the Front End option + imports, an immediate unpack can be performed without a popup dialog if the Front End option Enable simple GZF/GZT/GDT unpack is enabled ( EditTool Options... File ImportEnable simple GZF/GZT/GDT unpack). @@ -114,7 +114,7 @@

    Alternative Steps (drag-and-drop):

  • Press OK to initiate the import.
  • -
  • A results summary dialog will appear and, if successful, the new program will appear +
  • A results summary dialog will appear and, if successful, the newly imported file will appear in the project window and if initiated from a CodeBrowser tool, it will be opened in the tool.
  • @@ -266,20 +266,20 @@

    Dialog Fields

    file without any interpretation.
  • Language - This field specifies the language/compiler specification that will - be used in the resulting program. Often, this will be automatically detected from the + be used when importing a program. Often, this will be automatically detected from the file format. The Language/Compiler Spec Chooser Dialog can be used to enter or change the language/compiler spec that will be used.

  • Destination Folder - This field is used to specify the destination folder - within the current project for where the newly imported program will be saved. If a + within the current project for where the newly imported file will be saved. If a folder is selected in the front-end project window, then this field will default to that folder, otherwise the root folder will be the default. The ... will bring up a dialog for changing the destination folder.

  • -
  • Program Name - This field specifies the name for the newly imported file into +
  • Name - This field specifies the name for the newly imported file into the active project. - By default, it will be the name of the imported file with any format specific extenstion + By default, it will be the name of the imported file with any format specific extension removed (e.g., .xml, .gzf, .gzt, .gdt). Path information at the beginning of this field will be used to create a destination folder in the current project under the root folder specified by the Destination Folder field.

  • @@ -827,7 +827,7 @@

    Language and Compiler Specification Dialog

    This dialog is used specify of the Ghidra language (Processor/Compiler Spec) of the - program being imported. Certain formats, like "PE", "ELF", or "XML", will usually choose + file being imported. Certain formats, like "PE", "ELF", or "XML", will usually choose the appropriate language/compiler spec. If not, this dialog can be used to select one or override the default selection.


    diff --git a/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterDialog.java index 3410837d294..0b85d0c8634 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterDialog.java @@ -177,7 +177,7 @@ private Component buildMainPanel() { panel.add(buildFolderNameField()); panel.add(buildFolderNameBrowseButton()); - panel.add(new GLabel("Program Name: ", SwingConstants.RIGHT)); + panel.add(new GLabel("Name: ", SwingConstants.RIGHT)); panel.add(buildNameTextField()); panel.add(new JLabel()); From 891826dbc951afe823f07d26447728a6eb259f82 Mon Sep 17 00:00:00 2001 From: jibee Date: Tue, 23 Dec 2025 23:06:20 +0100 Subject: [PATCH 038/111] 68000: movem.w always uses 2 increments movem exists in 2 symmetrical variants, register to memory (save to stack) and memory to register (pull from stack). Per 68000 manual, when in word mode, increment (respectively decrement) is 2, and 4 in long mode. For word mode, the various registers masks are handled by m2rfw0, r2mbw0, and r2mfw0. This patch corrects the pointer increment for r2mbw0 to 2, aligning it to m2rfw0 and r2mfw0. --- .../68000/data/languages/68000.sinc | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Ghidra/Processors/68000/data/languages/68000.sinc b/Ghidra/Processors/68000/data/languages/68000.sinc index 674c9d06535..596aa17b103 100644 --- a/Ghidra/Processors/68000/data/languages/68000.sinc +++ b/Ghidra/Processors/68000/data/languages/68000.sinc @@ -1771,37 +1771,37 @@ r2mfl0: { r2mfl1} is mvm15=0 & r2mfl1 { } # Register to memory, backward direction, via word -r2mbwf: A7w is A7w & mvm0=1 { movemptr = movemptr - 4; *movemptr = A7w; } +r2mbwf: A7w is A7w & mvm0=1 { movemptr = movemptr - 2; *movemptr = A7w; } r2mbwf: is mvm0=0 { } -r2mbwe: r2mbwf" "A6w is A6w & mvm1=1 & r2mbwf { movemptr = movemptr - 4; *movemptr = A6w; } +r2mbwe: r2mbwf" "A6w is A6w & mvm1=1 & r2mbwf { movemptr = movemptr - 2; *movemptr = A6w; } r2mbwe: r2mbwf is mvm1=0 & r2mbwf { } -r2mbwd: r2mbwe" "A5w is A5w & mvm2=1 & r2mbwe { movemptr = movemptr - 4; *movemptr = A5w; } +r2mbwd: r2mbwe" "A5w is A5w & mvm2=1 & r2mbwe { movemptr = movemptr - 2; *movemptr = A5w; } r2mbwd: r2mbwe is mvm2=0 & r2mbwe { } -r2mbwc: r2mbwd" "A4w is A4w & mvm3=1 & r2mbwd { movemptr = movemptr - 4; *movemptr = A4w; } +r2mbwc: r2mbwd" "A4w is A4w & mvm3=1 & r2mbwd { movemptr = movemptr - 2; *movemptr = A4w; } r2mbwc: r2mbwd is mvm3=0 & r2mbwd { } -r2mbwb: r2mbwc" "A3w is A3w & mvm4=1 & r2mbwc { movemptr = movemptr - 4; *movemptr = A3w; } +r2mbwb: r2mbwc" "A3w is A3w & mvm4=1 & r2mbwc { movemptr = movemptr - 2; *movemptr = A3w; } r2mbwb: r2mbwc is mvm4=0 & r2mbwc { } -r2mbwa: r2mbwb" "A2w is A2w & mvm5=1 & r2mbwb { movemptr = movemptr - 4; *movemptr = A2w; } +r2mbwa: r2mbwb" "A2w is A2w & mvm5=1 & r2mbwb { movemptr = movemptr - 2; *movemptr = A2w; } r2mbwa: r2mbwb is mvm5=0 & r2mbwb { } -r2mbw9: r2mbwa" "A1w is A1w & mvm6=1 & r2mbwa { movemptr = movemptr - 4; *movemptr = A1w; } +r2mbw9: r2mbwa" "A1w is A1w & mvm6=1 & r2mbwa { movemptr = movemptr - 2; *movemptr = A1w; } r2mbw9: r2mbwa is mvm6=0 & r2mbwa { } -r2mbw8: r2mbw9" "A0w is A0w & mvm7=1 & r2mbw9 { movemptr = movemptr - 4; *movemptr = A0w; } +r2mbw8: r2mbw9" "A0w is A0w & mvm7=1 & r2mbw9 { movemptr = movemptr - 2; *movemptr = A0w; } r2mbw8: r2mbw9 is mvm7=0 & r2mbw9 { } -r2mbw7: r2mbw8" "D7w is D7w & mvm8=1 & r2mbw8 { movemptr = movemptr - 4; *movemptr = D7w; } +r2mbw7: r2mbw8" "D7w is D7w & mvm8=1 & r2mbw8 { movemptr = movemptr - 2; *movemptr = D7w; } r2mbw7: r2mbw8 is mvm8=0 & r2mbw8 { } -r2mbw6: r2mbw7" "D6w is D6w & mvm9=1 & r2mbw7 { movemptr = movemptr - 4; *movemptr = D6w; } +r2mbw6: r2mbw7" "D6w is D6w & mvm9=1 & r2mbw7 { movemptr = movemptr - 2; *movemptr = D6w; } r2mbw6: r2mbw7 is mvm9=0 & r2mbw7 { } -r2mbw5: r2mbw6" "D5w is D5w & mvm10=1 & r2mbw6 { movemptr = movemptr - 4; *movemptr = D5w; } +r2mbw5: r2mbw6" "D5w is D5w & mvm10=1 & r2mbw6 { movemptr = movemptr - 2; *movemptr = D5w; } r2mbw5: r2mbw6 is mvm10=0 & r2mbw6 { } -r2mbw4: r2mbw5" "D4w is D4w & mvm11=1 & r2mbw5 { movemptr = movemptr - 4; *movemptr = D4w; } +r2mbw4: r2mbw5" "D4w is D4w & mvm11=1 & r2mbw5 { movemptr = movemptr - 2; *movemptr = D4w; } r2mbw4: r2mbw5 is mvm11=0 & r2mbw5 { } -r2mbw3: r2mbw4" "D3w is D3w & mvm12=1 & r2mbw4 { movemptr = movemptr - 4; *movemptr = D3w; } +r2mbw3: r2mbw4" "D3w is D3w & mvm12=1 & r2mbw4 { movemptr = movemptr - 2; *movemptr = D3w; } r2mbw3: r2mbw4 is mvm12=0 & r2mbw4 { } -r2mbw2: r2mbw3" "D2w is D2w & mvm13=1 & r2mbw3 { movemptr = movemptr - 4; *movemptr = D2w; } +r2mbw2: r2mbw3" "D2w is D2w & mvm13=1 & r2mbw3 { movemptr = movemptr - 2; *movemptr = D2w; } r2mbw2: r2mbw3 is mvm13=0 & r2mbw3 { } -r2mbw1: r2mbw2" "D1w is D1w & mvm14=1 & r2mbw2 { movemptr = movemptr - 4; *movemptr = D1w; } +r2mbw1: r2mbw2" "D1w is D1w & mvm14=1 & r2mbw2 { movemptr = movemptr - 2; *movemptr = D1w; } r2mbw1: r2mbw2 is mvm14=0 & r2mbw2 { } -r2mbw0: { r2mbw1" "D0w} is D0w & mvm15=1 & r2mbw1 { movemptr = movemptr - 4; *movemptr = D0w; } +r2mbw0: { r2mbw1" "D0w} is D0w & mvm15=1 & r2mbw1 { movemptr = movemptr - 2; *movemptr = D0w; } r2mbw0: { r2mbw1} is mvm15=0 & r2mbw1 { } From 6f5fa3192c92996a81955d2183712c62b9e7d477 Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Wed, 15 Jan 2025 15:21:19 +0000 Subject: [PATCH 039/111] GP-2907: Added v850e3 language variant instructions --- Ghidra/Processors/V850/build.gradle | 8 +- Ghidra/Processors/V850/certification.manifest | 17 +- .../data/languages/Helpers/Conditions.sinc | 38 - .../V850/data/languages/Helpers/Extras.sinc | 131 -- .../V850/data/languages/Helpers/Macros.sinc | 254 --- .../V850/data/languages/Helpers/Register.sinc | 36 - .../V850/data/languages/Helpers/Tokens.sinc | 105 - .../data/languages/Helpers/Variables.sinc | 49 - .../languages/Instructions/Arithmetic.sinc | 336 ---- .../data/languages/Instructions/Float.sinc | 498 ----- .../languages/Instructions/Load_Store.sinc | 368 ---- .../data/languages/Instructions/Logic.sinc | 167 -- .../data/languages/Instructions/Special.sinc | 372 ---- .../Processors/V850/data/languages/V850.dwarf | 14 + .../Processors/V850/data/languages/V850.ldefs | 19 +- .../V850/data/languages/V850.opinion | 8 +- .../Processors/V850/data/languages/V850.pspec | 7 +- .../Processors/V850/data/languages/V850.sinc | 748 +++++++ .../V850/data/languages/V850.slaspec | 41 +- .../data/languages/V850_instructions.sinc | 1764 +++++++++++++++++ .../V850/data/languages/V850e3.pspec | 23 + .../V850/data/languages/V850e3.sinc | 323 +++ .../V850/data/languages/V850e3.slaspec | 16 + Ghidra/Processors/V850/data/manuals/v850.idx | 18 +- .../processors/RH850_O0_EmulatorTest.java | 38 + .../processors/RH850_O3_EmulatorTest.java | 40 + .../test/processors/V850_O0_EmulatorTest.java | 38 + .../test/processors/V850_O3_EmulatorTest.java | 40 + 28 files changed, 3113 insertions(+), 2403 deletions(-) delete mode 100644 Ghidra/Processors/V850/data/languages/Helpers/Conditions.sinc delete mode 100644 Ghidra/Processors/V850/data/languages/Helpers/Extras.sinc delete mode 100644 Ghidra/Processors/V850/data/languages/Helpers/Macros.sinc delete mode 100644 Ghidra/Processors/V850/data/languages/Helpers/Register.sinc delete mode 100644 Ghidra/Processors/V850/data/languages/Helpers/Tokens.sinc delete mode 100644 Ghidra/Processors/V850/data/languages/Helpers/Variables.sinc delete mode 100644 Ghidra/Processors/V850/data/languages/Instructions/Arithmetic.sinc delete mode 100644 Ghidra/Processors/V850/data/languages/Instructions/Float.sinc delete mode 100644 Ghidra/Processors/V850/data/languages/Instructions/Load_Store.sinc delete mode 100644 Ghidra/Processors/V850/data/languages/Instructions/Logic.sinc delete mode 100644 Ghidra/Processors/V850/data/languages/Instructions/Special.sinc create mode 100644 Ghidra/Processors/V850/data/languages/V850.dwarf create mode 100644 Ghidra/Processors/V850/data/languages/V850.sinc create mode 100644 Ghidra/Processors/V850/data/languages/V850_instructions.sinc create mode 100644 Ghidra/Processors/V850/data/languages/V850e3.pspec create mode 100644 Ghidra/Processors/V850/data/languages/V850e3.sinc create mode 100644 Ghidra/Processors/V850/data/languages/V850e3.slaspec create mode 100644 Ghidra/Processors/V850/src/test.processors/java/ghidra/test/processors/RH850_O0_EmulatorTest.java create mode 100644 Ghidra/Processors/V850/src/test.processors/java/ghidra/test/processors/RH850_O3_EmulatorTest.java create mode 100644 Ghidra/Processors/V850/src/test.processors/java/ghidra/test/processors/V850_O0_EmulatorTest.java create mode 100644 Ghidra/Processors/V850/src/test.processors/java/ghidra/test/processors/V850_O3_EmulatorTest.java diff --git a/Ghidra/Processors/V850/build.gradle b/Ghidra/Processors/V850/build.gradle index b5b745ae393..3ea3342f450 100644 --- a/Ghidra/Processors/V850/build.gradle +++ b/Ghidra/Processors/V850/build.gradle @@ -4,9 +4,9 @@ * 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. @@ -20,3 +20,7 @@ apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle" apply plugin: 'eclipse' eclipse.project.name = 'Processors v850' + +dependencies { + api project(':Base') +} diff --git a/Ghidra/Processors/V850/certification.manifest b/Ghidra/Processors/V850/certification.manifest index bddaec2f3cd..96ba81762a2 100644 --- a/Ghidra/Processors/V850/certification.manifest +++ b/Ghidra/Processors/V850/certification.manifest @@ -1,22 +1,17 @@ ##VERSION: 2.0 Module.manifest||GHIDRA||||END| README.md||GHIDRA||||END| -data/languages/Helpers/Conditions.sinc||GHIDRA||||END| -data/languages/Helpers/Extras.sinc||GHIDRA||||END| -data/languages/Helpers/Macros.sinc||GHIDRA||||END| -data/languages/Helpers/Register.sinc||GHIDRA||||END| -data/languages/Helpers/Tokens.sinc||GHIDRA||||END| -data/languages/Helpers/Variables.sinc||GHIDRA||||END| -data/languages/Instructions/Arithmetic.sinc||GHIDRA||||END| -data/languages/Instructions/Float.sinc||GHIDRA||||END| -data/languages/Instructions/Load_Store.sinc||GHIDRA||||END| -data/languages/Instructions/Logic.sinc||GHIDRA||||END| -data/languages/Instructions/Special.sinc||GHIDRA||||END| data/languages/V850.cspec||GHIDRA||||END| +data/languages/V850.dwarf||GHIDRA||||END| data/languages/V850.ldefs||GHIDRA||||END| data/languages/V850.opinion||GHIDRA||||END| data/languages/V850.pspec||GHIDRA||||END| +data/languages/V850.sinc||GHIDRA||||END| data/languages/V850.slaspec||GHIDRA||||END| +data/languages/V850_instructions.sinc||GHIDRA||||END| +data/languages/V850e3.pspec||GHIDRA||||END| +data/languages/V850e3.sinc||GHIDRA||||END| +data/languages/V850e3.slaspec||GHIDRA||||END| data/manuals/v850.idx||GHIDRA||||END| data/patterns/V850_patterns.xml||GHIDRA||||END| data/patterns/patternconstraints.xml||GHIDRA||||END| diff --git a/Ghidra/Processors/V850/data/languages/Helpers/Conditions.sinc b/Ghidra/Processors/V850/data/languages/Helpers/Conditions.sinc deleted file mode 100644 index e52ed22c8d9..00000000000 --- a/Ghidra/Processors/V850/data/languages/Helpers/Conditions.sinc +++ /dev/null @@ -1,38 +0,0 @@ -##################################################### -##### Conditions ##### -##################################################### - - -c0003: "v" is op0003=0x0 { tmp:1 = ($(OV)) == 1; export tmp; } -c0003: "nv" is op0003=0x8 { tmp:1 = ($(OV)) == 0; export tmp; } -c0003: "c" is op0003=0x1 { tmp:1 = ($(CY)) == 1; export tmp; } -c0003: "nc" is op0003=0x9 { tmp:1 = ($(CY)) == 0; export tmp; } -c0003: "e" is op0003=0x2 { tmp:1 = ($(Z)) == 1; export tmp; } -c0003: "ne" is op0003=0xA { tmp:1 = ($(Z)) == 0; export tmp; } -c0003: "nh" is op0003=0x3 { tmp:1 = ($(CY) || $(Z)) == 1; export tmp; } -c0003: "h" is op0003=0xB { tmp:1 = ($(CY) || $(Z)) == 0; export tmp; } -c0003: "n" is op0003=0x4 { tmp:1 = ($(S)) == 1; export tmp; } -c0003: "p" is op0003=0xC { tmp:1 = ($(S)) == 0; export tmp; } -c0003: "t" is op0003=0x5 { tmp:1 = 1; export tmp; } -c0003: "sa" is op0003=0xD { tmp:1 = ($(SAT)) == 1; export tmp; } -c0003: "lt" is op0003=0x6 { tmp:1 = ($(S) ^^ $(OV)) == 1; export tmp; } -c0003: "ge" is op0003=0xE { tmp:1 = ($(S) ^^ $(OV)) == 0; export tmp; } -c0003: "le" is op0003=0x7 { tmp:1 = ($(S) ^^ $(OV) || $(Z)) == 1; export tmp; } -c0003: "gt" is op0003=0xF { tmp:1 = ($(S) ^^ $(OV) || $(Z)) == 0; export tmp; } - -c1720: "v" is op1720=0x0 { tmp:1 = ($(OV)) == 1; export tmp; } -c1720: "nv" is op1720=0x8 { tmp:1 = ($(OV)) == 0; export tmp; } -c1720: "c" is op1720=0x1 { tmp:1 = ($(CY)) == 1; export tmp; } -c1720: "nc" is op1720=0x9 { tmp:1 = ($(CY)) == 0; export tmp; } -c1720: "e" is op1720=0x2 { tmp:1 = ($(Z)) == 1; export tmp; } -c1720: "ne" is op1720=0xA { tmp:1 = ($(Z)) == 0; export tmp; } -c1720: "nh" is op1720=0x3 { tmp:1 = ($(CY) || $(Z)) == 1; export tmp; } -c1720: "h" is op1720=0xB { tmp:1 = ($(CY) || $(Z)) == 0; export tmp; } -c1720: "n" is op1720=0x4 { tmp:1 = ($(S)) == 1; export tmp; } -c1720: "p" is op1720=0xC { tmp:1 = ($(S)) == 0; export tmp; } -c1720: "t" is op1720=0x5 { tmp:1 = 1; export tmp; } -c1720: "sa" is op1720=0xD { tmp:1 = ($(SAT)) == 1; export tmp; } -c1720: "lt" is op1720=0x6 { tmp:1 = ($(S) ^^ $(OV)) == 1; export tmp; } -c1720: "ge" is op1720=0xE { tmp:1 = ($(S) ^^ $(OV)) == 0; export tmp; } -c1720: "le" is op1720=0x7 { tmp:1 = ($(S) ^^ $(OV) || $(Z)) == 1; export tmp; } -c1720: "gt" is op1720=0xF { tmp:1 = ($(S) ^^ $(OV) || $(Z)) == 0; export tmp; } diff --git a/Ghidra/Processors/V850/data/languages/Helpers/Extras.sinc b/Ghidra/Processors/V850/data/languages/Helpers/Extras.sinc deleted file mode 100644 index 6abc080017a..00000000000 --- a/Ghidra/Processors/V850/data/languages/Helpers/Extras.sinc +++ /dev/null @@ -1,131 +0,0 @@ -##################################################### -##### Extras ##### -##################################################### - - -# read r0 always return zero -R0004: _R0004 is _R0004 & _R0004=0 { local x:4=0; export x; } -R0004: _R0004 is _R0004 { export _R0004; } - -R1115: _R1115 is _R1115 & _R1115=0 { local x:4=0; export x; } -R1115: _R1115 is _R1115 { export _R1115; } - -R2731: _R2731 is _R2731 & _R2731=0 { local x:4=0; export x; } -R2731: _R2731 is _R2731 { export _R2731; } - - -adr9: res is op0406 & s1115 -[ res = ((s1115 << 4) | (op0406 << 1)) + inst_start; ] -{ - export *:4 res; -} - -adr22: res is s0005; op1631 & op1616=0 -[ res = ((s0005 << 16) | op1631) + inst_start; ] -{ - export *:4 res; -} - -adr32: res is op1631 & op1616=0; op3247 -[ res = ((op3247 << 16) | op1631) + inst_start; ] -{ - export *:4 res; -} - -adr32i: res is op1631 & op1616=0; op3247 -[ res = ((op3247 << 16) | op1631); ] -{ - export *[const]:4 res; -} - -reg4: op0_1720 is op2323=0 & op0_1720 { export op0_1720; } -reg4: op1_1720 is op2323=1 & op1_1720 { export op1_1720; } - - - -##### Prep/Disp Loop ##### - -PrepList20: r20 is prep27=1 & r20 { push(r20); } -PrepList20: is prep27=0 { } - -PrepList21: r21 is prep26=1 & prep27=0 & r21 { push(r21); } -PrepList21: PrepList20,r21 is prep26=1 & PrepList20 & r21 { push(r21); } -PrepList21: PrepList20 is prep26=0 & PrepList20 { } - -PrepList22: r22 is prep25=1 & prep2627=0 & r22 { push(r22); } -PrepList22: PrepList21,r22 is prep25=1 & PrepList21 & r22 { push(r22); } -PrepList22: PrepList21 is prep25=0 & PrepList21 { } - -PrepList23: r23 is prep24=1 & prep2527=0 & r23 { push(r23); } -PrepList23: PrepList22,r23 is prep24=1 & PrepList22 & r23 { push(r23); } -PrepList23: PrepList22 is prep24=0 & PrepList22 { } - -PrepList24: r24 is prep31=1 & prep2427=0 & r24 { push(r24); } -PrepList24: PrepList23,r24 is prep31=1 & PrepList23 & r24 { push(r24); } -PrepList24: PrepList23 is prep31=0 & PrepList23 { } - -PrepList25: r25 is prep30=1 & prep2427=0 & prep31=0 & r25 { push(r25); } -PrepList25: PrepList24,r25 is prep30=1 & PrepList24 & r25 { push(r25); } -PrepList25: PrepList24 is prep30=0 & PrepList24 { } - -PrepList26: r26 is prep29=1 & prep2427=0 & prep3031=0 & r26 { push(r26); } -PrepList26: PrepList25,r26 is prep29=1 & PrepList25 & r26 { push(r26); } -PrepList26: PrepList25 is prep29=0 & PrepList25 { } - -PrepList27: r27 is prep28=1 & prep2427=0 & prep2931=0 & r27 { push(r27); } -PrepList27: PrepList26,r27 is prep28=1 & PrepList26 & r27 { push(r27); } -PrepList27: PrepList26 is prep28=0 & PrepList26 { } - -PrepList28: r28 is prep23=1 & prep2431=0 & r28 { push(r28); } -PrepList28: PrepList27,r28 is prep23=1 & PrepList27 & r28 { push(r28); } -PrepList28: PrepList27 is prep23=0 & PrepList27 { } - -PrepList29: r29 is prep22=1 & prep2431=0 & prep23=0 & r29 { push(r29); } -PrepList29: PrepList28,r29 is prep22=1 & PrepList28 & r29 { push(r29); } -PrepList29: PrepList28 is prep22=0 & PrepList28 { } - -PrepList30: ep is prep00=1 & prep2431=0 & prep2223=0 & ep { push(ep); } -PrepList30: PrepList29,ep is prep00=1 & PrepList29 & ep { push(ep); } -PrepList30: PrepList29 is prep00=0 & PrepList29 { } - -PrepList: { lp } is prep21=1 & prep2431=0 & prep2223=0 & prep00=0 & lp { push(lp); } -PrepList: { PrepList30,lp } is prep21=1 & PrepList30 & lp { push(lp); } -PrepList: { PrepList30 } is prep21=0 & PrepList30 { } - - - -DispList31: lp is prep21=1 & lp { pop(lp); } -DispList31: is prep21=0 { } - -DispList30: ep,DispList31 is DispList31 & prep00=1 & ep { pop(ep); } -DispList30: DispList31 is DispList31 & prep00=0 { } - -DispList29: r29,DispList30 is DispList30 & prep22=1 & r29 { pop(r29); } -DispList29: DispList30 is DispList30 & prep22=0 { } - -DispList28: r28,DispList29 is DispList29 & prep23=1 & r28 { pop(r28); } -DispList28: DispList29 is DispList29 & prep23=0 { } - -DispList27: r27,DispList28 is DispList28 & prep28=1 & r27 { pop(r27); } -DispList27: DispList28 is DispList28 & prep28=0 { } - -DispList26: r26,DispList27 is DispList27 & prep29=1 & r26 { pop(r26); } -DispList26: DispList27 is DispList27 & prep29=0 { } - -DispList25: r25,DispList26 is DispList26 & prep30=1 & r25 { pop(r25); } -DispList25: DispList26 is DispList26 & prep30=0 { } - -DispList24: r24,DispList25 is DispList25 & prep31=1 & r24 { pop(r24); } -DispList24: DispList25 is DispList25 & prep31=0 { } - -DispList23: r23,DispList24 is DispList24 & prep24=1 & r23 { pop(r23); } -DispList23: DispList24 is DispList24 & prep24=0 { } - -DispList22: r22,DispList23 is DispList23 & prep25=1 & r22 { pop(r22); } -DispList22: DispList23 is DispList23 & prep25=0 { } - -DispList21: r21,DispList22 is DispList22 & prep26=1 & r21 { pop(r21); } -DispList21: DispList22 is DispList22 & prep26=0 { } - -DispList: { r20,DispList21 } is DispList21 & prep27=1 & r20 { pop(r20); } -DispList: { DispList21 } is DispList21 & prep27=0 { } diff --git a/Ghidra/Processors/V850/data/languages/Helpers/Macros.sinc b/Ghidra/Processors/V850/data/languages/Helpers/Macros.sinc deleted file mode 100644 index 5985412f087..00000000000 --- a/Ghidra/Processors/V850/data/languages/Helpers/Macros.sinc +++ /dev/null @@ -1,254 +0,0 @@ -##################################################### -##### Macros ##### -##################################################### - - -##### CARRY-Flag ##### - -macro set_CY_pos(var1, var2) -{ - $(CY) = carry(var1, var2); -} - -macro set_CY_pos2(var1, var2, var3) -{ - local var12 = var1 + var2; - $(CY) = carry(var1, var2) || carry(var12, var3); -} - -macro set_CY_neg(var1, var2) -{ - $(CY) = var1 < var2; -} - -macro set_CY_neg2(var1, var2, var3) -{ - local var23 = var2 + var3; - $(CY) = (var1 < var23); -} - - - -##### Overflow-Flag ##### - -macro set_OV_pos(var1, var2) -{ - $(OV) = scarry(var1, var2); -} - -macro set_OV_pos2(var1, var2, var3) -{ - local var12 = var1 + var2; - $(OV) = scarry(var1, var2) || scarry(var12, var3); -} - -macro set_OV_neg(var1, var2) -{ - local A:4 = var1; - local B:4 = var2; - local R = A - B; - - local A1 = A[31,1]; - local B1 = B[31,1]; - local R1 = R[31,1]; - - $(OV) = (A1 != B1) && (B1 == R1); - - #OV = 1 if: - #pos - neg = neg - #neg - pos = pos -} - -macro set_OV_neg2(var1, var2, var3) -{ - local A:4 = var1; - local B:4 = var2; - local C:4 = var3; - local R = A - B - C; - - local A1 = A[31,1]; - local B1 = B[31,1]; - local R1 = R[31,1]; - - $(OV) = (A1 != B1) && (B1 == R1); -} - - - -##### S/Z-Flags ##### - -macro set_S(flag) -{ - $(S) = flag s< 0; -} - -macro set_Z(var) -{ - $(Z) = var == 0; -} - - - -##### General-Flag-Macros ##### - -macro set_general_flags_pos(var1, var2) -{ - local res = var1 + var2; - set_CY_pos(var1, var2); - set_OV_pos(var1, var2); - set_S(res); - set_Z(res); -} - -macro set_general_flags_neg(var1, var2) -{ - local res = var1 - var2; - set_CY_neg(var1, var2); - set_OV_neg(var1, var2); - set_S(res); - set_Z(res); -} - -macro set_OV0_S_Z(var) -{ - $(OV) = 0; - set_S(var); - set_Z(var); -} - - - -##### General-Macros ##### - -# if condition is != 0 -macro either_or(res, cond, true, false) -{ - res = (true * zext(cond != 0)) + (false * zext(cond == 0)); -} - -# if condition is == 1 -macro either_or1(res, cond, true, false) -{ - res = (true * zext(cond == 1)) + (false * zext(cond != 1)); -} - -macro shift_right_logic(res, var, shift_) -{ - local shift = shift_ & 0x1f; - local mask = (zext(shift != 0) * var) & (1 << (shift - 1)); - res = var >> shift; - set_OV0_S_Z(res); - $(CY) = ((mask != 0) && (shift != 0)); -} - -macro shift_right_arith(res, var, shift_) -{ - local shift = shift_ & 0x1f; - local mask = (zext(shift != 0) * var) & (1 << (shift - 1)); - res = var s>> shift; - set_OV0_S_Z(res); - $(CY) = ((mask != 0) && (shift != 0)); -} - -macro shift_left_logic(res, var, shift_) -{ - local shift = shift_ & 0x1f; - local mask = (zext(shift != 0) * var) & (1 << (32 - shift)); - res = var << shift; - set_OV0_S_Z(res); - $(CY) = ((mask != 0) && (shift != 0)); -} - - - -##### Prep/Disp Macros ##### - -macro push(reg) -{ - sp = sp - 4; - *:4 sp = reg; -} - -macro pop(reg) -{ - reg = *:4 sp; - sp = sp + 4; -} - - - -##### Search Macros ##### - -macro SearchRight(res, var, char) -{ - local var_:4 = var; - res = 0; - - - if ((var_ & 0x1) == char) - goto ; - - var_ = var_ >> 1; - res = res + 1; - - if (res < 32) - goto ; - - res = 0; - - -} - -macro SearchLeft(res, var, char) -{ - local var_:4 = var; - res = 0; - - - if ((var_ >> 31) == char) - goto ; - - var_ = var_ << 1; - res = res + 1; - - if (res < 32) - goto ; - - res = 0; - - -} - -# macro saturate(var) -# { -# if (var s> 0x7FFFFFFF) -# goto ; - -# if (var s< -0x80000000) -# goto ; - -# goto ; - -# -# var = 0x7FFFFFFF; -# goto ; - -# -# var = -0x80000000; -# goto ; - -# -# } - - -##### Float-Macros ##### - -macro compare_float(res, fcond, reg1, reg2) -{ - local un = ((fcond & 1) == 1) & (nan(reg2) || nan(reg1)); - local eq = ((fcond & 2) == 2) & (!(nan(reg2) || nan(reg1))) & (reg2 f== reg1); - local le = ((fcond & 4) == 4) & (!(nan(reg2) || nan(reg1))) & (reg2 f< reg1); - #local ex = (fcond & 8) & ((nan(reg2) || nan(reg1))); - - res = zext(un|eq|le); -} diff --git a/Ghidra/Processors/V850/data/languages/Helpers/Register.sinc b/Ghidra/Processors/V850/data/languages/Helpers/Register.sinc deleted file mode 100644 index 9cc9824e430..00000000000 --- a/Ghidra/Processors/V850/data/languages/Helpers/Register.sinc +++ /dev/null @@ -1,36 +0,0 @@ -##################################################### -##### Register ##### -##################################################### - - -##### General-purpose registers (r0 to r31) ##### - -define register offset=0x0 size=0x4 # offset = 0 because it's the start -[ - r0 r1 r2 sp gp tp r6 r7 r8 r9 - r10 r11 r12 r13 r14 r15 r16 r17 r18 r19 - r20 r21 r22 r23 r24 r25 r26 r27 r28 r29 - ep lp -]; - - - -##### Control/Special registers ##### - -define register offset=0x80 size=0x4 # offset = 0x80(128) = PreOffset+PreRegister*Size = 0+32*4 = 128 -[ - EIPC EIPSW FEPC FEPSW ECR PSW FPSR FPEPC FPST FPCC - FPCFG SCCFG SCBP EIIC FEIC DBIC CTPC CTPSW DBPC DBPSW - CTBP DIR DBG22 DBG23 DBG24 DBG25 DBG26 DBG27 EIWR FEWR - DBWR BSEL -]; - -define register offset=0x0 size=0x8 -[ - r0r1 r2sp r4r5 r6r7 r8r9 - r10r11 r12r13 r14r15 r16r17 r18r19 - r20r21 r22r23 r24r25 r26r27 r28r29 - eplp -]; - -define register offset=0x100 size=0x4 [ PC ]; # offset = 0x100(256) = PreOffset+PreRegister*Size = 128+32*4 = 256 diff --git a/Ghidra/Processors/V850/data/languages/Helpers/Tokens.sinc b/Ghidra/Processors/V850/data/languages/Helpers/Tokens.sinc deleted file mode 100644 index 8402ab02cd0..00000000000 --- a/Ghidra/Processors/V850/data/languages/Helpers/Tokens.sinc +++ /dev/null @@ -1,105 +0,0 @@ -##################################################### -##### Tokens ##### -##################################################### - - -define token instr(16) - op0000 = (0,0) - op0003 = (0,3) - op0004 = (0,4) - _R0004 = (0,4) - SR0004 = (0,4) - R0004x2 = (0,4) - s0004 = (0,4) signed - s0005 = (0,5) signed - op0005 = (0,5) - op0006 = (0,6) - op0010 = (0,10) - op0015 = (0,15) - op0106 = (1,6) - op0406 = (4,6) - op0410 = (4,10) - op0505 = (5,5) - op0510 = (5,10) - op0515 = (5,15) - op0610 = (6,10) - op0615 = (6,15) - op0710 = (7,10) - op1113 = (11,13) - op1114 = (11,14) - op1115 = (11,15) - _R1115 = (11,15) - SR1115 = (11,15) - R1115x2 = (11,15) - s1115 = (11,15) signed - op1415 = (14,15) - op1515 = (15,15) -; - -define token instr2(16) - op1616 = (0,0) - op1617 = (0,1) - op1619 = (0,3) - op1620 = (0,4) - R1620 = (0,4) - R1620x2 = (0,4) - op1626 = (0,10) - op1631 = (0,15) - s1631 = (0,15) signed - fcbit1719 = (1,3) - op1720 = (1,4) - op0_1720 = (1,4) - op1_1720 = (1,4) - s1731 = (1,15) signed - op1821 = (2,5) - s1821 = (2,5) signed - op2020 = (4,4) - op2026 = (4,10) - op2122 = (5,6) - op2126 = (5,10) - op2226 = (6,10) - op2323 = (7,7) - op2426 = (8,10) - op2729 = (11,13) - fcond2730 = (11,14) - op2731 = (11,15) - _R2731 = (11,15) - R2731x2 = (11,15) - op3031 = (14,15) - op3131 = (15,15) -; - -define token instr3(16) - op3247 = (0,15) - s3247 = (0,15) signed -; - -define token instr4(16) - op4863 = (0,15) -; - -# used in PREPARE/DISPOSE instructions -define token prep(32) - prep00 = (0,0) - prep0105 = (1,5) - prep0615 = (6,15) - prep1620 = (16,20) - prep21 = (21,21) - prep22 = (22,22) - prep2223 = (22,31) - prep23 = (23,23) - prep24 = (24,24) - prep2431 = (24,31) - prep25 = (25,25) - prep26 = (26,26) - prep27 = (27,27) - prep28 = (28,28) - prep29 = (29,29) - prep2931 = (29,31) - prep3031 = (30,31) - prep2427 = (24,27) - prep2527 = (25,27) - prep2627 = (26,27) - prep30 = (30,30) - prep31 = (31,31) -; diff --git a/Ghidra/Processors/V850/data/languages/Helpers/Variables.sinc b/Ghidra/Processors/V850/data/languages/Helpers/Variables.sinc deleted file mode 100644 index e427b03c9f5..00000000000 --- a/Ghidra/Processors/V850/data/languages/Helpers/Variables.sinc +++ /dev/null @@ -1,49 +0,0 @@ -##################################################### -##### Variables ##### -##################################################### - - -attach variables [ _R0004 _R1115 _R2731 R1620 prep1620] -[ - r0 r1 r2 sp gp tp r6 r7 r8 r9 - r10 r11 r12 r13 r14 r15 r16 r17 r18 r19 - r20 r21 r22 r23 r24 r25 r26 r27 r28 r29 - ep lp -]; - -attach variables [ R0004x2 R1115x2 R1620x2 R2731x2 ] -[ - r0r1 _ r2sp _ r4r5 _ r6r7 _ r8r9 _ - r10r11 _ r12r13 _ r14r15 _ r16r17 _ r18r19 _ - r20r21 _ r22r23 _ r24r25 _ r26r27 _ r28r29 _ - eplp _ -]; - -attach variables [ SR0004 SR1115 ] -[ - EIPC EIPSW FEPC FEPSW ECR PSW FPSR FPEPC FPST FPCC - FPCFG SCCFG SCBP EIIC FEIC DBIC CTPC CTPSW DBPC DBPSW - CTBP DIR DBG22 DBG23 DBG24 DBG25 DBG26 DBG27 EIWR FEWR - DBWR BSEL -]; - - -attach variables [op0_1720] [r0 r2 gp r6 r8 r10 r12 r14 r16 r18 r20 r22 r24 r26 r28 ep]; -attach variables [op1_1720] [r1 sp tp r7 r9 r11 r13 r15 r17 r19 r21 r23 r25 r27 r29 lp]; - - -attach names [fcond2730] -["f" "un" "eq" "ueq" "olt" "ult" "ole" "ule" "sd" "ngle" "seq" "ngl" "lt" "nge" "le" "ngt"]; - - -@define NP "PSW[7,1]" -@define EP "PSW[6,1]" -@define ID "PSW[5,1]" -@define SAT "PSW[4,1]" -@define CY "PSW[3,1]" -@define OV "PSW[2,1]" -@define S "PSW[1,1]" -@define Z "PSW[0,1]" - -@define EICC "ECR[0,16]" -@define FECC "ECR[16,16]" diff --git a/Ghidra/Processors/V850/data/languages/Instructions/Arithmetic.sinc b/Ghidra/Processors/V850/data/languages/Instructions/Arithmetic.sinc deleted file mode 100644 index a546e242841..00000000000 --- a/Ghidra/Processors/V850/data/languages/Instructions/Arithmetic.sinc +++ /dev/null @@ -1,336 +0,0 @@ -# (3) Multiply instructions -# (4) Multiply-accumulate instructions -# (5) Arithmetic instructions -# (7) Saturated operation instructions -# (11) Divide instructions -# (12) High-speed divide instructions - - - -##################################################### -##### Multiply ##### -##################################################### - - -# MUL reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww01000100000 -:mul R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0x220 & R2731 -{ - local res:8 = sext(R1115) * sext(R0004); - R1115 = res:4; - R2731 = res[32,32]; -} - -# MUL imm9, reg2, reg3 - rrrrr111111iiiii|wwwww01001IIII00 -:mul imm9, R1115, R2731 is op0510=0x3F & op0004 & R1115; op2226=0x9 & op1617=0x0 & s1821 & R2731 -[ imm9 = (s1821 << 5) | op0004; ] -{ - local res:8 = sext(R1115) * imm9; - R1115 = res:4; - R2731 = res[32,32]; -} - -# MULH reg1, reg2 - rrrrr000111RRRRR -:mulh R0004, R1115 is op0510=0x07 & R0004 & R1115 & op1115!=0 -{ - R1115 = sext(R1115:2) * sext(R0004:2); -} - -# MULH imm5, reg2 - rrrrr010111iiiii -:mulh s0004, R1115 is op0510=0x17 & s0004 & R1115 -{ - R1115 = sext(R1115:2) * s0004; -} - -# MULHI imm16, reg1, reg2 - rrrrr110111RRRRR|iiiiiiiiiiiiiiii -:mulhi s1631, R0004, R1115 is op0510=0x37 & R1115 & R0004; s1631 -{ - R1115 = R0004 * s1631; -} - -# MULU reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww01000100010 -:mulu R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0x222 & R2731 -{ - local res:8 = zext(R1115) * zext(R0004); - R1115 = res:4; - R2731 = res[32,32]; -} - -# MULU imm9, reg2, reg3 - rrrrr111111iiiii|wwwww01001IIII10 -:mulu imm9, R1115, R2731 is op0510=0x3F & op0004 & R1115; op2226=0x9 & op1617=0x2 & op1821 & R2731 -[ imm9 = (op1821 << 5) | op0004; ] -{ - local res:8 = zext(R1115) * imm9; - R1115 = res:4; - R2731 = res[32,32]; -} - - - -##################################################### -##### MultiplyAccumulate ##### -##################################################### - - -# MAC reg1, reg2, reg3, reg4 - rrrrr111111RRRRR wwww0011110mmmm0 -:mac R0004, R1115, R2731x2, R1620x2 is op0510=0x3F & R0004 & R1115; op2126=0x1E & op1616=0 & R1620x2 & R2731x2 -{ - R1620x2 = sext(R1115) * sext(R0004) + R2731x2; -} - -# MACU reg1, reg2, reg3, reg4 - rrrrr111111RRRRR|wwww0011111mmmm0 -:macu R0004, R1115, R2731x2, R1620x2 is op0510=0x3F & R0004 & R1115; op2126=0x1F & op1616=0 & R1620x2 & R2731x2 -{ - R1620x2 = zext(R1115) * zext(R0004) + R2731x2; -} - - - -##################################################### -##### Arithmetic ##### -##################################################### - - -# ADD reg1, reg2 - rrrrr001110RRRRR -:add R0004, R1115 is op0510=0x0E & R0004 & R1115 -{ - set_general_flags_pos(R0004, R1115); - R1115 = R1115 + R0004; -} - -# ADD imm5, reg2 - rrrrr010010iiiii -:add s0004, R1115 is op0510=0x12 & s0004 & R1115 -{ - set_general_flags_pos(s0004, R1115); - R1115 = R1115 + s0004; -} - -# ADDI imm16, reg1, reg2 - rrrrr110000RRRRR|iiiiiiiiiiiiiiii -:addi s1631, R0004, R1115 is op0510=0x30 & R1115 & R0004; s1631 -{ - set_general_flags_pos(R0004, s1631); - R1115 = R0004 + s1631; -} - -# CMP reg1, reg2 - rrrrr001111RRRRR -:cmp R0004, R1115 is op0510=0x0F & R0004 & R1115 -{ - set_general_flags_neg(R1115, R0004); -} - -# CMP imm5, reg2 - rrrrr010011iiiii -:cmp s0004, R1115 is op0510=0x13 & s0004 & R1115 -{ - set_general_flags_neg(R1115, s0004); -} - -# MOV reg1, reg2 - rrrrr000000RRRRR -:mov R0004, R1115 is op0510=0x00 & R0004 & R1115 -{ - R1115 = R0004; -} - -# MOV imm5, reg2 - rrrrr010000iiiii -:mov s0004, R1115 is op0510=0x10 & s0004 & R1115 & op1115!=0 -{ - R1115 = s0004; -} - -# MOV imm32, reg1 - 00000110001RRRRR|iiiiiiiiiiiiiiii|IIIIIIIIIIIIIIII -:mov imm32, R0004 is op0515=0x031 & R0004; op1631; op3247 -[ imm32 = (op3247 << 16) | op1631; ] -{ - R0004 = imm32; -} - -# MOVEA imm16, reg1, reg2 - rrrrr110001RRRRR|iiiiiiiiiiiiiiii -:movea s1631, R0004, R1115 is op0510=0x31 & op1115!=0 & R0004 & R1115; s1631 -{ - R1115 = R0004 + s1631; -} - -# MOVHI imm16, reg1, reg2 - rrrrr110010RRRRR|iiiiiiiiiiiiiiii -:movhi s1631, R0004, R1115 is op0510=0x32 & op1115!=0 & R0004 & R1115; s1631 -{ - R1115 = R0004 + (s1631 << 16); -} - -# SUB reg1, reg2 - rrrrr001101RRRRR -:sub R0004, R1115 is op0510=0x0D & R0004 & R1115 -{ - set_general_flags_neg(R1115, R0004); - R1115 = R1115 - R0004; -} - -# SUBR reg1, reg2 - rrrrr001100RRRRR -:subr R0004, R1115 is op0510=0x0C & R0004 & R1115 -{ - set_general_flags_neg(R0004, R1115); - R1115 = R0004 - R1115; -} - - - -##################################################### -##### Saturated ##### -##################################################### - - -define pcodeop __saturate; - -# SATADD reg1, reg2 - rrrrr000110RRRRR -:satadd R0004, R1115 is op0510=0x06 & R0004 & R1115 & op1115!=0 -{ - set_general_flags_pos(R1115, R0004); - $(SAT) = $(SAT) || $(OV); - R1115 = R1115 + R0004; - __saturate(R1115); -} - -#SATADD imm5, reg2 - rrrrr010001iiiii -:satadd s0004, R1115 is op0510=0x11 & s0004 & R1115 & op1115!=0 -{ - set_general_flags_pos(R1115, s0004); - $(SAT) = $(SAT) || $(OV); - R1115 = R1115 + s0004; - __saturate(R1115); -} - -# SATADD reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww01110111010 -:satadd R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0x3BA & R2731 -{ - set_general_flags_pos(R1115, R0004); - $(SAT) = $(SAT) || $(OV); - R2731 = R1115 + R0004; - __saturate(R2731); -} - -# SATSUB reg1, reg2 - rrrrr000101RRRRR -:satsub R0004, R1115 is op0510=0x05 & R0004 & R1115 & op1115!=0 -{ - set_general_flags_neg(R1115, R0004); - $(SAT) = $(SAT) || $(OV); - R1115 = R1115 - R0004; - __saturate(R1115); -} - -# SATSUB reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww01110011010 -:satsub R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0x39A & R2731 -{ - set_general_flags_neg(R1115, R0004); - $(SAT) = $(SAT) || $(OV); - R2731 = R1115 - R0004; - __saturate(R2731); -} - -# SATSUBI imm16, reg1, reg2 -:satsubi s1631, R0004, R1115 is op0510=0x33 & op1115!=0 & R0004 & R1115; s1631 -{ - set_general_flags_neg(R0004, s1631); - $(SAT) = $(SAT) || $(OV); - R1115 = R0004 - s1631; - __saturate(R1115); -} - -# SATSUBR reg1, reg2 -:satsubr R0004, R1115 is op0510=0x04 & R0004 & R1115 & op1115!=0 -{ - set_general_flags_neg(R0004, R1115); - $(SAT) = $(SAT) || $(OV); - R1115 = R0004 - R1115; - __saturate(R1115); -} - - - -##################################################### -##### Divide ##### -##################################################### - - -# DIV reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww01011000000 -:div R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0x2C0 & R2731 -{ - local quot:4 = R1115 s/ R0004; - local mod:4 = R1115 s% R0004; - $(OV) = ((R1115 == 0x80000000 && R0004 == 0xFFFFFFFF) || R0004 == 0x0); - set_Z(R1115); - set_S(R1115); - R1115 = quot; - R2731 = mod; -} - -# DIVH reg1, reg2 - rrrrr000010RRRRR -:divh R0004, R1115 is op0510=0x02 & R0004 & R1115 -{ - $(OV) = ((R1115 == 0x80000000 && R0004 == 0xFFFFFFFF) || R0004 == 0x0); - R1115 = R1115 / R0004; - set_Z(R1115); - set_S(R1115); -} - -# DIVH reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww01010000000 -:divh R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0x280 & R2731 -{ - local quot:4 = R1115 s/ sext(R0004:2); - local mod:4 = R1115 s% sext(R0004:2); - $(OV) = ((R1115 == 0x80000000 && R0004 == 0xFFFFFFFF) || R0004 == 0x0); - set_Z(R1115); - set_S(R1115); - R1115 = quot; - R2731 = mod; -} - -# DIVHU reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww01010000010 -:divhu R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0x282 & R2731 -{ - local quot:4 = R1115 / sext(R0004:2); - local mod:4 = R1115 % sext(R0004:2); - $(OV) = (R0004 == 0); - set_Z(R1115); - set_S(R1115); - R1115 = quot; - R2731 = mod; -} - -# DIVU reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww01011000010 -:divu R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0x2C2 & R2731 -{ - local quot:4 = R1115 / R0004; - local mod:4 = R1115 % R0004; - $(OV) = (R0004 == 0); - set_Z(R1115); - set_S(R1115); - R1115 = quot; - R2731 = mod; -} - - - -##################################################### -##### HighSpeedDivide ##### -##################################################### - - -# DIVQ reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww01011111100 -:divq R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0x2FC & R2731 -{ - local quot:4 = R1115 s/ R0004; - local mod:4 = R1115 s% R0004; - $(OV) = ((R1115 == 0x80000000 && R0004 == 0xFFFFFFFF) || R0004 == 0x0); - set_Z(R1115); - set_S(R1115); - R2731 = mod; - R1115 = quot; -} - -# DIVQU reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww01011111110 -:divqu R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0x2FE & R2731 -{ - local quot:4 = R1115 / R0004; - local mod:4 = R1115 % R0004; - $(OV) = (R0004 == 0); - set_Z(R1115); - set_S(R1115); - R2731 = mod; - R1115 = quot; -} diff --git a/Ghidra/Processors/V850/data/languages/Instructions/Float.sinc b/Ghidra/Processors/V850/data/languages/Instructions/Float.sinc deleted file mode 100644 index d708864c4eb..00000000000 --- a/Ghidra/Processors/V850/data/languages/Instructions/Float.sinc +++ /dev/null @@ -1,498 +0,0 @@ -##################################################### -##### Float ##### -##################################################### - - -# ABSF.D reg2, reg3 - rrrr011111100000|wwww010001011000 -:absf.d R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b00000; R2731x2 & op2126=0b100010 & op1620=0b11000 -{ - R2731x2 = abs(R1115x2); -} - -# ABSF.S reg2, reg3 - rrrrr11111100000|wwwww10001001000 -:absf.s R1115, R2731 is R1115 & op0510=0x3F & op0004=0b00000; R2731 & op2126=0b100010 & op1620=0b01000 -{ - R2731 = abs(R1115); -} - -# ADDF.D reg1, reg2, reg3 - rrrr0111111RRRR0|wwww010001110000 -:addf.d R0004x2, R1115x2, R2731x2 is R1115x2 & op0510=0x3F & R0004x2 ; R2731x2 & op2126=0b100011 & op1620=0b10000 -{ - R2731x2 = R1115x2 f+ R0004x2; -} - -# ADDF.S reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww10001100000 -:addf.s R0004, R1115, R2731 is R1115 & op0510=0x3F & R0004 ; R2731 & op2126=0b100011 & op1620=0b00000 -{ - R2731 = R1115 f+ R0004; -} - -# CEILF.DL reg2, reg3 - rrrr011111100010|wwww010001010100 -:ceilf.dl R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b00010; R2731x2 & op2126=0b100010 & op1620=0b10100 -{ - local var:8 = ceil(float2float(R1115x2)); - R2731x2 = trunc(var); -} - -# CEILF.DUL reg2, reg3 - rrrr011111110010|wwww010001010100 -:ceilf.dul R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b10010; R2731x2 & op2126=0b100010 & op1620=0b10100 -{ - local var:8 = ceil(float2float(R1115x2)); - R2731x2 = trunc(var); -} - -# CEILF.DUW reg2, reg3 - rrrrr11111110010|wwwww10001010000 -:ceilf.duw R1115x2, R2731 is R1115x2 & op0510=0x3F & op0004=0b10010; R2731 & op2126=0b100010 & op1620=0b10000 -{ - R2731 = trunc(ceil(R1115x2)); -} - -# CEILF.DW reg2, reg3 - rrrrr11111100010|wwwww10001010000 -:ceilf.dw R1115x2, R2731 is R1115x2 & op0510=0x3F & op0004=0b00010; R2731 & op2126=0b100010 & op1620=0b10000 -{ - R2731 = trunc(ceil(R1115x2)); -} - -# CEILF.SL reg2, reg3 - rrrrr11111100010|wwww010001000100 -:ceilf.sl R1115, R2731x2 is R1115 & op0510=0x3F & op0004=0b00010; R2731x2 & op2126=0b100010 & op1620=0b00100 -{ - local var:8 = ceil(float2float(R1115)); - R2731x2 = trunc(var); -} - -# CEILF.SUL reg2, reg3 - rrrrr11111110010|wwwww10001000100 -:ceilf.sul R1115, R2731x2 is R1115 & op0510=0x3F & op0004=0b10010; R2731x2 & op2126=0b100010 & op1620=0b00100 -{ - local var:8 = ceil(float2float(R1115)); - R2731x2 = trunc(var); -} - -# CEILF.SUW reg2, reg3 - rrrrr11111110010|wwwww10001000000 -:ceilf.sul R1115, R2731 is R1115 & op0510=0x3F & op0004=0b10010; R2731 & op2126=0b100010 & op1620=0b00000 -{ - R2731 = trunc(ceil(R1115)); -} - -# CEILF.SW reg2, reg3 - rrrrr11111100010|wwwww10001000000 -:ceilf.sw R1115, R2731 is R1115 & op0510=0x3F & op0004=0b00010; R2731 & op2126=0b100010 & op1620=0b00000 -{ - R2731 = trunc(ceil(R1115)); -} - -# CMOVF.D fcbit, reg1, reg2, reg3 - rrrr0111111RRRR0|wwww01000001fff0 -:cmovf.d fcbit1719, R1115x2, R0004x2, R2731x2 is R1115x2 & op0510=0x3F & R0004x2; R2731x2 & op2126=0b100000 & op2020=1 & fcbit1719 & op1616=0 -{ - #CC0 = Bit 24 - local bit = (FPSR >> (fcbit1719 + 24:1)) & 0x1; - either_or1(R2731x2, bit, R0004x2, R1115x2); -} - -# CMOVF.S fcbit, reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww1000000fff0 -:cmovf.s fcbit1719, R1115, R0004, R2731 is R1115 & op0510=0x3F & R0004; R2731 & op2126=0b100000 & op2020=0 & fcbit1719 & op1616=0 -{ - local bit = (FPSR >> (fcbit1719 + 24:1)) & 0x1; - either_or1(R2731, bit, R0004, R1115); -} - -# CMPF.D fcond, reg2, reg1, fcbit - rrrr0111111RRRRR|0FFFF1000011fff0 -:cmpf.d fcond2730, R1115x2, R0004x2, fcbit1719 is R1115x2 & op0510=0x3F & R0004x2; op3131=0 & fcond2730 & op2126=0b100001 & op2020=1 & fcbit1719 & op1616=0 -{ - #0 = Unordered - #1 = Equal to - #2 = Less than - #3 = Exeption - #bits = ex le eq un - - local bit:4 = 0; - compare_float(bit, fcond2730:1, R0004x2, R1115x2); - - local pos:4 = bit << (fcbit1719 + 24); #find position of the calculated bit - local mask:4 = 1 << (fcbit1719 + 24); #create mask to clean old bit in FPSR register - FPSR = (FPSR & ~mask) | pos; #set the new bit at the right position -} - -# CMPF.S fcond, reg2, reg1, fcbit - rrrrr111111RRRRR|0FFFF1000010fff0 -:cmpf.s fcond2730, R1115, R0004, fcbit1719 is R1115 & op0510=0x3F & R0004; op3131=0 & fcond2730 & op2126=0b100001 & op2020=0 & fcbit1719 & op1616=0 -{ - local bit:4 = 0; - compare_float(bit, fcond2730:1, R0004, R1115); - - local pos:4 = bit << (fcbit1719 + 24); #find position of the calculated bit - local mask:4 = 1 << (fcbit1719 + 24); #create mask to clean old bit in FPSR register - FPSR = (FPSR & ~mask) | pos; #set the new bit at the right position -} - -# CVTF.DL reg2, reg3 - rrrr011111100100|wwww010001010100 -:cvtf.dl R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b00100; R2731x2 & op2126=0b100010 & op1620=0b10100 -{ - R2731x2 = int2float(R1115x2); -} - -# CVTF.DS reg2, reg3 - rrrr011111100011|wwww010001010010 -:cvtf.ds R1115x2, R2731 is R1115x2 & op0510=0x3F & op0004=0b00011; R2731 & op2126=0b100010 & op1620=0b10010 -{ - R2731 = float2float(R1115x2); -} - -# CVTF.DUL reg2, reg3 - rrrr011111110100|wwww010001010100 -:cvtf.dul R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b10100; R2731x2 & op2126=0b100010 & op1620=0b10100 -{ - R2731x2 = trunc(R1115x2); -} - -# CVTF.DUW reg2, reg3 - rrrrr11111110100|wwwww10001010000 -:cvtf.duw R1115x2, R2731 is R1115x2 & op0510=0x3F & op0004=0b10100; R2731 & op2126=0b100010 & op1620=0b10000 -{ - R2731 = trunc(R1115x2); -} - -# CVTF.DW reg2, reg3 - rrrrr11111100100|wwwww10001010000 -:cvtf.sw R1115x2, R2731 is R1115x2 & op0510=0x3F & op0004=0b00100; R2731 & op2126=0b100010 & op1620=0b10000 -{ - R2731 = trunc(R1115x2); -} - -# CVTF.LD reg2, reg3 - rrrr011111100001|wwww010001010010 -:cvtf.ls R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b00001; R2731x2 & op2126=0b100010 & op1620=0b10010 -{ - R2731x2 = int2float(R1115x2); -} - -# CVTF.LS reg2, reg3 - rrrr011111100001|wwwww10001000010 -:cvtf.ls R1115x2, R2731 is R1115x2 & op0510=0x3F & op0004=0b00001; R2731 & op2126=0b100010 & op1620=0b00010 -{ - R2731 = int2float(R1115x2); -} - -# CVTF.SD reg2, reg3 - rrrrr11111100010|wwww010001010010 -:cvtf.sd R1115, R2731x2 is R1115 & op0510=0x3F & op0004=0b00010; R2731x2 & op2126=0b100010 & op1620=0b10010 -{ - R2731x2 = float2float(R1115); -} - -# CVTF.SL reg2, reg3 - rrrrr11111100100|wwwww10001000100 -:cvtf.sl R1115, R2731x2 is R1115 & op0510=0x3F & op0004=0b00100; R2731x2 & op2126=0b100010 & op1620=0b00100 -{ - R2731x2 = trunc(R1115); -} - -# CVTF.SUL reg2, reg3 - rrrrr11111110100|wwwww10001000100 -:cvtf.sul R1115, R2731x2 is R1115 & op0510=0x3F & op0004=0b10100; R2731x2 & op2126=0b100010 & op1620=0b00100 -{ - R2731x2 = trunc(R1115); -} - -# CVTF.SUW reg2, reg3 - rrrrr11111110100|wwwww10001000000 -:cvtf.suw R1115, R2731 is R1115 & op0510=0x3F & op0004=0b10100; R2731 & op2126=0b100010 & op1620=0b00000 -{ - R2731 = trunc(R1115); -} - -# CVTF.SW reg2, reg3 - rrrrr11111100100|wwwww10001000000 -:cvtf.sw R1115, R2731 is R1115 & op0510=0x3F & op0004=0b00100; R2731 & op2126=0b100010 & op1620=0b00000 -{ - R2731 = trunc(R1115); -} - -# CVTF.ULD reg2, reg3 - rrrr011111100001|wwww010001010010 -:cvtf.uls R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b10001; R2731x2 & op2126=0b100010 & op1620=0b10010 -{ - R2731x2 = int2float(R1115x2); -} - -# CVTF.ULS reg2, reg3 - rrrr011111110001|wwwww10001000010 -:cvtf.uls R1115x2, R2731 is R1115x2 & op0510=0x3F & op0004=0b10001; R2731 & op2126=0b100010 & op1620=0b00010 -{ - R2731 = int2float(R1115x2); -} - -# CVTF.UWD reg2, reg3 - rrrrr11111110000|wwwww10001010010 -:cvtf.uwd R1115, R2731x2 is R1115 & op0510=0x3F & op0004=0b10000; R2731x2 & op2126=0b100010 & op1620=0b10010 -{ - R2731x2 = int2float(R1115); -} - -# CVTF.UWS reg2, reg3 - rrrrr11111110000|wwwww10001000010 -:cvtf.uws R1115, R2731 is R1115 & op0510=0x3F & op0004=0b10000; R2731 & op2126=0b100010 & op1620=0b00010 -{ - R2731 = int2float(R1115); -} - -# CVTF.WD reg2, reg3 - rrrrr11111100000|wwwww10001010010 -:cvtf.wd R1115, R2731x2 is R1115 & op0510=0x3F & op0004=0b00000; R2731x2 & op2126=0b100010 & op1620=0b10010 -{ - R2731x2 = int2float(R1115); -} - -# CVTF.WS reg2, reg3 - rrrrr11111100000|wwwww10001000010 -:cvtf.ws R1115, R2731 is R1115 & op0510=0x3F & op0004=0b00000; R2731 & op2126=0b100010 & op1620=0b00010 -{ - R2731 = int2float(R1115); -} - -# DIVF.D reg1, reg2, reg3 - rrrr0111111RRRR0|wwww010001111110 -:divf.s R0004x2, R1115x2, R2731x2 is R0004x2 & op0510=0x3F & R1115x2; R2731x2 & op2126=0b100011 & op1620=0b11110 -{ - R2731x2 = R1115x2 f/ R0004x2; -} - -# DIVF.S reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww10001101110 -:divf.s R0004, R1115, R2731 is R0004 & op0510=0x3F & R1115; R2731 & op2126=0b100011 & op1620=0b01110 -{ - R2731 = R1115 f/ R0004; -} - -# FLOORF.DL reg2, reg3 - rrrr011111100011|wwww010001010100 -:floorf.dl R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b00011; R2731x2 & op2126=0b100010 & op1620=0b10100 -{ - local var:8 = floor(float2float(R1115x2)); - R2731x2 = trunc(var); -} - -# FLOORF.DUL reg2, reg3 - rrrr011111110011|wwww010001010100 -:floorf.dul R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b10011; R2731x2 & op2126=0b100010 & op1620=0b10100 -{ - local var:8 = floor(float2float(R1115x2)); - R2731x2 = trunc(var); -} - -# FLOORF.DUW reg2, reg3 - rrrrr11111110011|wwwww10001010000 -:floorf.duw R1115x2, R2731 is R1115x2 & op0510=0x3F & op0004=0b10011; R2731 & op2126=0b100010 & op1620=0b10000 -{ - R2731 = trunc(floor(R1115x2)); -} - -# FLOORF.DW reg2, reg3 - rrrrr11111100011|wwwww10001010000 -:floorf.dw R1115x2, R2731 is R1115x2 & op0510=0x3F & op0004=0b00011; R2731 & op2126=0b100010 & op1620=0b10000 -{ - R2731 = trunc(floor(R1115x2)); -} - -# FLOORF.SL reg2, reg3 - rrrrr11111100011|wwww010001000100 -:floorf.sl R1115, R2731x2 is R1115 & op0510=0x3F & op0004=0b00011; R2731x2 & op2126=0b100010 & op1620=0b00100 -{ - local var:8 = floor(float2float(R1115)); - R2731x2 = trunc(var); -} - -# FLOORF.SUL reg2, reg3 - rrrrr11111110011|wwwww10001000100 -:floorf.sul R1115, R2731x2 is R1115 & op0510=0x3F & op0004=0b10011; R2731x2 & op2126=0b100010 & op1620=0b00100 -{ - local var:8 = floor(float2float(R1115)); - R2731x2 = trunc(var); -} - -# FLOORF.SUW reg2, reg3 - rrrrr11111110011|wwwww10001000000 -:floorf.suw R1115, R2731 is R1115 & op0510=0x3F & op0004=0b10011; R2731 & op2126=0b100010 & op1620=0b00000 -{ - R2731 = trunc(floor(R1115)); -} - -# FLOORF.SW reg2, reg3 - rrrrr11111100011|wwwww10001000000 -:floorf.suw R1115, R2731 is R1115 & op0510=0x3F & op0004=0b00011; R2731 & op2126=0b100010 & op1620=0b00000 -{ - R2731 = trunc(floor(R1115)); -} - -# FMAF.S reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww10011100000 -:fmaf.s R0004, R1115, R2731 is R0004 & op0510=0x3F & R1115; R2731 & op2126=0b100111 & op1620=0b00000 -{ - R2731 = (R1115 f* R0004) f+ R2731; -} - -# FMSF.S reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww10011100010 -:fmsf.s R0004, R1115, R2731 is R0004 & op0510=0x3F & R1115; R2731 & op2126=0b100111 & op1620=0b00010 -{ - R2731 = (R1115 f* R0004) f- R2731; -} - -# FNMAF.S reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww10011100100 -:fnmaf.s R0004, R1115, R2731 is R0004 & op0510=0x3F & R1115; R2731 & op2126=0b100111 & op1620=0b00100 -{ - R2731 = -1 f* ((R1115 f* R0004) f+ R2731); -} - -# FNMSF.S reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww10011100110 -:fnmfs.s R0004, R1115, R2731 is R0004 & op0510=0x3F & R1115; R2731 & op2126=0b100111 & op1620=0b00110 -{ - R2731 = -1 f* ((R1115 f* R0004) f- R2731); -} - -# MADDF.S reg1, reg2, reg3, reg4 - rrrrr111111RRRRR|wwwww101W00WWWW0 -:maddf.s R0004, R1115, R2731, reg4 is R0004 & op0510=0x3F & R1115; R2731 & op2426=0b101 & op2122=0b00 & op1616=0 & reg4 -{ - reg4 = (R1115 f* R0004) f+ R2731; -} - -# MAXF.D reg1, reg2, reg3 - rrrr0111111RRRR0|wwww010001111000 -:maxf.d R0004x2, R1115x2, R2731x2 is R0004x2 & op0510=0x3F & R1115x2; R2731x2 & op2126=0b100011 & op1620=0b11000 -{ - local bigger:1 = R1115x2 f> R0004x2; - either_or(R2731x2, bigger, R1115x2, R0004x2); -} - -# MAXF.S reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww10001101000 -:maxf.s R0004, R1115, R2731 is R0004 & op0510=0x3F & R1115; R2731 & op2126=0b100011 & op1620=0b01000 -{ - local bigger:1 = R1115 f> R0004; - either_or(R2731, bigger, R1115, R0004); -} - -# MINF.D reg1, reg2, reg3 - rrrr0111111RRRR0|wwww010001111010 -:minf.d R0004x2, R1115x2, R2731x2 is R0004x2 & op0510=0x3F & R1115x2; R2731x2 & op2126=0b100011 & op1620=0b11010 -{ - local bigger:1 = R1115x2 f< R0004x2; - either_or(R2731x2, bigger, R1115x2, R0004x2); -} - -# MINF.S reg1, reg2, reg3 - rrrr0111111RRRRR|wwwww10001101010 -:minf.s R0004, R1115, R2731 is R0004 & op0510=0x3F & R1115; R2731 & op2126=0b100011 & op1620=0b01010 -{ - local bigger:1 = R1115 f< R0004; - either_or(R2731, bigger, R1115, R0004); -} - -# MSUBF.S reg1, reg2, reg3, reg4 - rrrrr111111RRRRR|wwwww101W01WWWW0 -:msubf.s R0004, R1115, R2731, reg4 is R0004 & op0510=0x3F & R1115; R2731 & op2426=0b101 & op2122=0b01 & op1616=0 & reg4 -{ - reg4 = (R1115 f* R0004) f- R2731; -} - -# MULF.D reg1, reg2, reg3 - rrrr0111111RRRR0|wwww010001110100 -:mulf.d R0004x2, R1115x2, R2731x2 is R0004x2 & op0510=0x3F & R1115x2; R2731x2 & op2126=0b100011 & op1620=0b10100 -{ - R2731x2 = R1115x2 f* R0004x2; -} - -# MULF.S reg1, reg2, reg3 - rrrr0111111RRRRR|wwwww10001100100 -:mulf.s R0004, R1115, R2731 is R0004 & op0510=0x3F & R1115; R2731 & op2126=0b100011 & op1620=0b00100 -{ - R2731 = R1115 f* R0004; -} - -# NEGF.D reg2, reg3 - rrrr011111100001|wwww010001011000 -:negf.d R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b00001; R2731x2 & op2126=0b100010 & op1620=0b11000 -{ - R2731x2 = f- R1115x2; -} - -# NEGF.S reg2, reg3 - rrrrr11111100001|wwwww10001001000 -:negf.s R1115, R2731 is R1115 & op0510=0x3F & op0004=0b00001; R2731 & op2126=0b100010 & op1620=0b01000 -{ - R2731 = f- R1115; -} - -# NMADDF.S reg1, reg2, reg3, reg4 - rrrrr111111RRRRR|wwwww101W10WWWW0 -:nmaddf.s R0004, R1115, R2731, reg4 is R0004 & op0510=0x3F & R1115; R2731 & op2426=0b101 & op2122=0b10 & op1616=0 & reg4 -{ - reg4 = f-((R1115 f* R0004) f+ R2731); -} - -# NMSUBF.S reg1, reg2, reg3, reg4 - rrrrr111111RRRRR|wwwww101W11WWWW0 -:nmsubf.s R0004, R1115, R2731, reg4 is R0004 & op0510=0x3F & R1115; R2731 & op2426=0b101 & op2122=0b11 & op1616=0 & reg4 -{ - reg4 = f-((R1115 f* R0004) f- R2731); -} - -# RECIPF.D reg2, reg3 - rrrr011111100001|wwww010001011110 -:recipf.d R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b00001; R2731x2 & op2126=0b100010 & op1620=0b11110 -{ - R2731x2 = 1 f/ R1115x2; -} - -# RECIPF.S reg2, reg3 - rrrrr11111100001|wwwww10001001110 -:recipf.s R1115, R2731 is R1115 & op0510=0x3F & op0004=0b00001; R2731 & op2126=0b100010 & op1620=0b01110 -{ - R2731 = 1 f/ R1115; -} - -# RSQRTF.D reg2, reg3 - rrrr011111100010|wwwww10001011110 -:rsqrtf.d R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b00010; R2731x2 & op2126=0b100010 & op1620=0b11110 -{ - R2731x2 = 1 f/ sqrt(R1115x2); -} - -# RSQRTF.S reg2, reg3 - rrrrr11111100010|wwwww10001001110 -:rsqrtf.s R1115, R2731 is R1115 & op0510=0x3F & op0004=0b00010; R2731 & op2126=0b100010 & op1620=0b01110 -{ - R2731 = 1 f/ sqrt(R1115); -} - -# SQRTF.D reg2, reg3 - rrrr011111100000|wwww010001011110 -:sqrtf.d R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b00000; R2731x2 & op2126=0b100010 & op1620=0b11110 -{ - R2731x2 = sqrt(R1115x2); -} - -# SQRTF.S reg2, reg3 - rrrrr11111100000|wwwww10001001110 -:sqrtf.s R1115, R2731 is R1115 & op0510=0x3F & op0004=0b00000; R2731 & op2126=0b100010 & op1620=0b01110 -{ - R2731 = sqrt(R1115); -} - -# SUBF.D reg1, reg2, reg3 - rrrr0111111RRRR0|wwww010001110010 -:subf.d R0004x2, R1115x2, R2731x2 is R0004x2 & op0510=0x3F & R1115x2; R2731x2 & op2126=0b100011 & op1620=0b10010 -{ - R2731x2 = R1115x2 f- R0004x2; -} - -# SUBF.S reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww10001100010 -:subf.s R0004, R1115, R2731 is R0004 & op0510=0x3F & R1115; R2731 & op2126=0b100011 & op1620=0b00010 -{ - R2731 = R1115 f- R0004; -} - -# TRFSR fcbit - 0000011111100000|000001000000fff0 -:trfsr fcbit1719 is op1115=0 & op0510=0x3F & op0004=0; op2731=0 & op2126=0b100000 & op2020=0 & fcbit1719 & op1616=0 -{ - local var:4 = FPSR & (1 << (fcbit1719 + 24)); - $(Z) = (var != 0); -} - -# TRNCF.DL reg2, reg3 - rrrr011111100001|wwww010001010100 -:trncf.dl R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b00001; R2731x2 & op2126=0b100010 & op1620=0b10100 -{ - R2731x2 = trunc(R1115x2); -} - -# TRNCF.DUL reg2, reg3 - rrrr011111110001|wwww010001010100 -:trncf.dul R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b10001; R2731x2 & op2126=0b100010 & op1620=0b10100 -{ - R2731x2 = trunc(R1115x2); -} - -# TRNCF.DUW reg2, reg3 - rrrrr11111110001|wwwww10001010000 -:trncf.duw R1115x2, R2731 is R1115x2 & op0510=0x3F & op0004=0b10001; R2731 & op2126=0b100010 & op1620=0b10000 -{ - R2731 = trunc(R1115x2); -} - -# TRNCF.DW reg2, reg3 - rrrrr11111100001|wwwww10001010000 -:trncf.dw R1115x2, R2731 is R1115x2 & op0510=0x3F & op0004=0b00001; R2731 & op2126=0b100010 & op1620=0b10000 -{ - R2731 = trunc(R1115x2); -} - -# TRNCF.SL reg2, reg3 - rrrrr11111100001|wwww010001000100 -:trncf.sl R1115, R2731x2 is R1115 & op0510=0x3F & op0004=0b00001; R2731x2 & op2126=0b100010 & op1620=0b00100 -{ - R2731x2 = trunc(R1115); -} - -# TRNCF.SUL reg2, reg3 - rrrrr11111110001|wwww010001000100 -:trncf.sul R1115, R2731x2 is R1115 & op0510=0x3F & op0004=0b10001; R2731x2 & op2126=0b100010 & op1620=0b00100 -{ - R2731x2 = trunc(R1115); -} - -# TRNCF.SUW reg2, reg3 - rrrrr11111110001|wwwww10001000000 -:trncf.suw R1115, R2731 is R1115 & op0510=0x3F & op0004=0b10001; R2731 & op2126=0b100010 & op1620=0b00000 -{ - R2731 = trunc(R1115); -} - -# TRNCF.SW reg2, reg3 - rrrrr11111100001|wwwww10001000000 -:trncf.sw R1115, R2731 is R1115 & op0510=0x3F & op0004=0b00001; R2731 & op2126=0b100010 & op1620=0b00000 -{ - R2731 = trunc(R1115); -} diff --git a/Ghidra/Processors/V850/data/languages/Instructions/Load_Store.sinc b/Ghidra/Processors/V850/data/languages/Instructions/Load_Store.sinc deleted file mode 100644 index 4ec28891665..00000000000 --- a/Ghidra/Processors/V850/data/languages/Instructions/Load_Store.sinc +++ /dev/null @@ -1,368 +0,0 @@ -# (1) Load instructions -# (2) Store instructions -# (9) Data manipulation instructions - - - -##################################################### -##### Load ##### -##################################################### - - -# LD.B disp16[reg1], reg2 - rrrrr111000RRRRR|dddddddddddddddd -:ld.b s1631[R0004], R1115 is op0510=0x38 & R0004 & R1115; s1631 -{ - local adr:4 = R0004 + s1631; - R1115 = sext(*:1 adr); -} - -# LD.B disp23[reg1], reg3 - rrrrr111100RRRRR|wwwwwddddddd0101|DDDDDDDDDDDDDDDD -:ld.b disp23[R0004], R2731 is op0515=0x3C & R0004; R2731 & op2026 & op1619=0x5; s3247 -[ disp23 = (s3247 << 7) | op2026; ] -{ - local adr:4 = R0004 + disp23; - R2731 = sext(*:1 adr); -} - -# LD.BU disp16[reg1], reg2 - rrrrr11110bRRRRR|ddddddddddddddd1 -:ld.bu disp16[R0004], R1115 is op0610=0x1E & R0004 & R1115 & op0505; op1616=0x1 & s1731 -[ disp16 = (s1731 << 1) | op0505; ] -{ - local adr:4 = R0004 + disp16; - R1115 = zext(*:1 adr); -} - -# LD.BU disp23[reg1], reg3 - 00000111101RRRRR|wwwwwddddddd0101|DDDDDDDDDDDDDDDD -:ld.bu disp23[R0004], R2731 is op0515=0x3D & R0004; R2731 & op2026 & op1619=0x5; s3247 -[ disp23 = (s3247 << 7) | op2026; ] -{ - local adr:4 = R0004 + disp23; - R2731 = zext(*:1 adr); -} - -# LD.H disp16[reg1], reg2 - rrrrr111001RRRRR|ddddddddddddddd0 -:ld.h s1631[R0004], R1115 is op0510=0x39 & R0004 & R1115; s1631 & op1616=0x0 -{ - local adr:4 = R0004 + s1631; - R1115 = sext(*:2 adr); -} - -# LD.H disp23[reg1], reg3 - 00000111100RRRRR|wwwwwdddddd00111|DDDDDDDDDDDDDDDD -:ld.h disp23[R0004], R2731 is op0515=0x3C & R0004; R2731 & op2126 & op1620=0x7; s3247 -[ disp23 = (s3247 << 7) | (op2126 << 1); ] -{ - local adr:4 = R0004 + disp23; - R2731 = sext(*:2 adr); -} - -# LD.HU disp16[reg1], reg2 - rrrrr111111RRRRR|ddddddddddddddd1 -:ld.hu disp16[R0004], R1115 is op0510=0x3F & R0004 & R1115; op1616=0x1 & s1731 -[ disp16 = s1731 << 1; ] -{ - local adr:4 = R0004 + disp16; - R1115 = zext(*:2 adr); -} - -# LD.HU disp23[reg1], reg3 - 00000111101RRRRR|wwwwwdddddd00111|DDDDDDDDDDDDDDDD -:ld.hu disp23[R0004], R2731 is op0515=0x3D & R0004; R2731 & op2026 & op1619=0x7; s3247 -[ disp23 = (s3247 << 7) | op2026; ] -{ - local adr:4 = R0004 + disp23; - R2731 = zext(*:2 adr); -} - -# LD.W disp16[reg1], reg2 - rrrrr111001RRRRR|ddddddddddddddd1 -:ld.w disp16[R0004], R1115 is op0510=0x39 & R0004 & R1115; s1731 & op1616=0x1 -[ disp16 = s1731 * 2; ] -{ - local adr:4 = R0004 + disp16; - R1115 = *:4 adr; -} - -# LD.W disp23[reg1], reg3 - 00000111100RRRRR|wwwwwdddddd01001|DDDDDDDDDDDDDDDD -:ld.w disp23[R0004], R2731 is op0515=0x03C & R0004; R2731 & op2126 & op1620=0x9; s3247 -[ disp23 = (s3247 << 7) | (op2126 << 1); ] -{ - local adr:4 = R0004 + disp23; - R2731 = *:4 adr; -} - -# SLD.B disp7[ep], reg2 - rrrrr0110ddddddd -:sld.b op0006[ep], R1115 is op0710=0x06 & op0006 & R1115 & ep -{ - local adr:4 = ep + op0006; - R1115 = sext(*:1 adr); -} - -# SLD.BU disp4[ep], reg2 - rrrrr0000110dddd -:sld.bu op0003[ep], R1115 is op0410=0x06 & R1115 & op0003 & ep -{ - local adr:4 = ep + op0003; - R1115 = zext(*:1 adr); -} - -# SLD.H disp8[ep], reg2 - rrrrr1000ddddddd -:sld.h disp8[ep], R1115 is op0710=0x08 & op0006 & R1115 & ep -[ disp8 = op0006 * 2; ] -{ - local adr:4 = ep + disp8; - R1115 = sext(*:2 adr); -} - -# SLD.HU disp5[ep], reg2 - rrrrr0000111dddd -:sld.hu disp5[ep], R1115 is op0410=0x07 & R1115 & op0003 & ep -[ disp5 = op0003 * 2; ] -{ - local adr:4 = ep + disp5; - R1115 = zext(*:2 adr); -} - -# SLD.W disp8[ep], reg2 - rrrrr1010dddddd0 -:sld.w disp8[ep], R1115 is op0710=0x0A & op0000=0x0 & op0106 & R1115 & ep -[ disp8 = op0106 * 4; ] -{ - local adr:4 = ep + disp8; - R1115 = *:4 adr; -} - - - -##################################################### -##### Store ##### -##################################################### - - -# SST.B reg2, disp7[ep] - rrrrr0111ddddddd -:sst.b R1115, op0006[ep] is op0710=0x07 & op0006 & R1115 & ep -{ - local adr:4 = ep + op0006; - local tmp:4 = R1115; - *:1 adr = tmp:1; -} - -# SST.H reg2, disp8[ep] - rrrrr1001ddddddd -:sst.h R1115, disp8[ep] is op0710=0x09 & op0006 & R1115 & ep -[ disp8 = op0006 * 2; ] -{ - local adr:4 = ep + disp8; - local tmp:4 = R1115; - *:2 adr = tmp:2; -} - -# SST.W reg2, disp8[ep] - rrrrr1010dddddd1 -:sst.w R1115, disp8[ep] is op0710=0x0A & op0000=0x1 & op0106 & R1115 & ep -[ disp8 = op0106 * 4; ] -{ - local adr:4 = ep + disp8; - local tmp:4 = R1115; - *:4 adr = tmp; -} - -# ST.B reg2, disp16[reg1] - rrrrr111010RRRRR|dddddddddddddddd -:st.b R1115, s1631[R0004] is op0510=0x3A & R0004 & R1115; s1631 -{ - local adr:4 = R0004 + s1631; - local tmp:4 = R1115; - *:1 adr = tmp:1; -} - -# ST.B reg3, disp23[reg1] - 00000111100RRRRR|dddddddddddddddd -:st.b R2731, disp23[R0004] is op0515=0x3C & R0004; R2731 & op2026 & op1619=0xD; s3247 -[ disp23 = (s3247 << 7) | op2026; ] -{ - local adr:4 = R0004 + disp23; - local tmp:4 = R2731; - *:1 adr = tmp:1; -} - -# ST.H reg2, disp16[reg1] - rrrrr111011RRRRR|ddddddddddddddd0 -:st.h R1115, s1631[R0004] is op0510=0x3B & R0004 & R1115; s1631 & op1616=0x0 -{ - local adr:4 = R0004 + s1631; - local tmp:4 = R1115; - *:2 adr = tmp:2; -} - -# ST.H reg3, disp23[reg1] - 00000111101RRRRR|wwwwwdddddd01101|DDDDDDDDDDDDDDDD -:st.h R2731, disp23[R0004] is op0515=0x3D & R0004; R2731 & op2126 & op1620=0xD; s3247 -[ disp23 = (s3247 << 7) | (op2126 << 1); ] -{ - local adr:4 = R0004 + disp23; - local tmp:4 = R2731; - *:2 adr = tmp:2; -} - -# ST.W reg2, disp16[reg1] - rrrrr111011RRRRR|ddddddddddddddd1 -:st.w R1115, disp16[R0004] is op0510=0x3B & R0004 & R1115; s1731 & op1616=0x1 -[ disp16 = s1731 * 2; ] -{ - local adr:4 = R0004 + disp16; - local tmp:4 = R1115; - *:4 adr = tmp; -} - -# ST.W reg3, disp23[reg1] - 00000111100RRRRR|wwwwwdddddd01111|DDDDDDDDDDDDDDDD -:st.w R2731, disp23[R0004] is op0515=0x3C & R0004; R2731 & op2126 & op1620=0xF; s3247 -[ disp23 = (s3247 << 7) | (op2126 << 1); ] -{ - local adr:4 = R0004 + disp23; - local tmp:4 = R2731; - *:2 adr = tmp:2; -} - - - -##################################################### -##### DataManipulation ##### -##################################################### - - -# BSH reg2, reg3 - rrrrr11111100000|wwwww01101000010 -:bsh R1115, R2731 is op0010=0x7E0 & R1115; op1626=0x342 & R2731 -{ - local x1 = R1115[0,8]; - local x2 = R1115[8,8]; - local x3 = R1115[16,8]; - local x4 = R1115[24,8]; - R2731 = zext(x3 << 24) | zext(x4 << 16) | zext(x1 << 8) | zext(x2); - set_S(R2731); - $(OV) = 0; - $(Z) = (x1 == 0) && (x2 == 0); - $(CY) = (x1 == 0) || (x2 == 0); -} - -# BSW reg2, reg3 - rrrrr11111100000|wwwww01101000000 -:bsw R1115, R2731 is op0010=0x7E0 & R1115; op1626=0x340 & R2731 -{ - local x1 = R1115[0,8]; - local x2 = R1115[8,8]; - local x3 = R1115[16,8]; - local x4 = R1115[24,8]; - R2731 = zext(x1 << 24) | zext(x2 << 16) | zext(x3 << 8) | zext(x4); - set_OV0_S_Z(R2731); - $(CY) = (x1 == 0) || (x2 == 0) || (x3 == 0) || (x4 == 0); -} - -# CMOV cccc, reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww011001cccc0 -:cmov^c1720 R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op2126=0x19 & op1616=0 & c1720 & R2731 -{ - local result:4 = zext(c1720); - R2731 = R0004 * zext(result != 0) + R1115 * zext(result == 0); -} - -# CMOV cccc, imm5, reg2, reg3 - rrrrr111111iiiii|wwwww011000cccc0 -:cmov^c1720 s0004, R1115, R2731 is op0510=0x3F & s0004 & R1115; op2126=0x18 & op1616=0 & c1720 & R2731 -{ - local result:4 = zext(c1720); - R2731 = s0004 * zext(result != 0) + R1115 * zext(result == 0); -} - -# HSH reg2, reg3 - rrrrr11111100000|wwwww01101000110 -:hsh R1115, R2731 is op0010=0x7E0 & R1115; op1626=0x346 & R2731 -{ - R2731 = R1115; - set_S(R2731); - $(OV) = 0; - $(Z) = (R2731:2 == 0); - $(CY) = $(Z); -} - -# HSW reg2, reg3 - rrrrr11111100000|wwwww01101000100 -:hsw R1115, R2731 is op0010=0x7E0 & R1115; op1626=0x344 & R2731 -{ - local x1 = R1115:2; - local x2 = R1115[16,16]; - R2731 = zext(x1 << 16) | zext(x2); - set_OV0_S_Z(R2731); - $(CY) = (x1 == 0) || (x2 == 0); -} - -# SAR reg1, reg2 - rrrrr111111RRRRR|0000000010100000 -:sar R0004, R1115 is op0510=0x3F & R0004 & R1115; op1631=0xA0 -{ - shift_right_arith(R1115, R1115, R0004); -} - -# SAR imm5, reg2 - rrrrr010101iiiii -:sar op0004, R1115 is op0510=0x15 & op0004 & R1115 -{ - shift_right_arith(R1115, R1115, op0004:5); -} - -# SAR reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww00010100010 -:sar R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0xA2 & R2731 -{ - shift_right_arith(R2731, R1115, R0004); -} - -# SASF cccc, reg2 - rrrrr1111110cccc|0000001000000000 -:sasf^c0003 R1115 is op0410=0x7E & c0003 & R1115; op1631=0x0200 -{ - R1115 = (R1115 << 1) | zext(c0003); -} - -# SETF cond, reg2 - rrrrr1111110cccc|0000000000000000 -:setf^c0003 R1115 is op0410=0x7E & c0003 & R1115; op1631=0x0 -{ - R1115 = zext(c0003); -} - -# SHL reg1, reg2 - rrrrr111111RRRRR|0000000011000000 -:shl R0004, R1115 is op0510=0x3F & R0004 & R1115; op1631=0xC0 -{ - shift_left_logic(R1115, R1115, R0004); -} - -# SHL imm5, reg2 - rrrrr010110iiiii -:shl op0004, R1115 is op0510=0x16 & op0004 & R1115 -{ - shift_left_logic(R1115, R1115, op0004:5); -} - -# SHL reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww00011000010 -:shl R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0xC2 & R2731 -{ - shift_left_logic(R2731, R1115, R0004); -} - -# SHR reg1, reg2 - rrrrr111111RRRRR|0000000010000000 -:shr R0004, R1115 is op0510=0x3F & R0004 & R1115; op1631=0x80 -{ - shift_right_logic(R1115, R1115, R0004); -} - -# SHR imm5, reg2 - rrrrr010100iiiii -:shr op0004, R1115 is op0510=0x14 & op0004 & R1115 -{ - shift_right_logic(R1115, R1115, op0004:5); -} - -# SHR reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww00010000010 -:shr R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0x82 & R2731 -{ - shift_right_logic(R2731, R1115, R0004); -} - -# SXB reg1 - 00000000101RRRRR -:sxb R0004 is op0515=0x05 & R0004 -{ - R0004 = sext(R0004:1); -} - -# SXH reg1 - 00000000111RRRRR -:sxh R0004 is op0515=0x07 & R0004 -{ - R0004 = sext(R0004:2); -} - -# ZXB reg1 - 00000000100RRRRR -:zxb R0004 is op0515=0x004 & R0004 -{ - R0004 = zext(R0004:1); -} - -# ZXH reg1 - 00000000110RRRRR -:zxh R0004 is op0515=0x006 & R0004 -{ - R0004 = zext(R0004:2); -} diff --git a/Ghidra/Processors/V850/data/languages/Instructions/Logic.sinc b/Ghidra/Processors/V850/data/languages/Instructions/Logic.sinc deleted file mode 100644 index e0a511220cd..00000000000 --- a/Ghidra/Processors/V850/data/languages/Instructions/Logic.sinc +++ /dev/null @@ -1,167 +0,0 @@ -# (6) Conditional arithmetic instructions -# (8) Logical instructions -# (14) Bit manipulation instructions - - - -##################################################### -##### Conditional ##### -##################################################### - - -# ADF cccc, reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww011101cccc0 -:adf^c1720 R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op2126=0x1D & op1616=0 & c1720 & R2731 -{ - local cond = zext(c1720); - set_OV_pos2(R1115, R0004, cond); - set_CY_pos2(R1115, R0004, cond); - R2731 = R1115 + R0004 + cond; - set_S(R2731); - set_Z(R2731); -} - -# SBF cccc, reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww011100cccc0 -:sbf^c1720 R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op2126=0x1C & op1616=0 & c1720 & R2731 -{ - local cond = zext(c1720); - set_OV_neg2(R1115, R0004, cond); - set_CY_neg2(R1115, R0004, cond); - R2731 = R1115 - R0004 - cond; - set_S(R2731); - set_Z(R2731); -} - - - -##################################################### -##### Logic ##### -##################################################### - - -# AND reg1, reg2 - rrrrr001010RRRRR -:and R0004, R1115 is op0510=0x0A & R0004 & R1115 -{ - R1115 = R1115 & R0004; - set_OV0_S_Z(R1115); -} - -# ANDI imm16, reg1, reg2 - rrrrr110110RRRRR|iiiiiiiiiiiiiiii -:andi op1631, R0004, R1115 is op0510=0x36 & R1115 & R0004; op1631 -{ - R1115 = R0004 & op1631; - set_OV0_S_Z(R1115); -} - -# NOT reg1, reg2 - rrrrr000001RRRRR -:not R0004, R1115 is op0510=0x01 & R0004 & R1115 -{ - R1115 = ~R0004; - set_OV0_S_Z(R1115); -} - -# OR reg1, reg2 - rrrrr001000RRRRR -:or R0004, R1115 is op0510=0x08 & R0004 & R1115 -{ - R1115 = R1115 | R0004; - set_OV0_S_Z(R1115); -} - -# ORI imm16, reg1, reg2 - rrrrr110100RRRRR|iiiiiiiiiiiiiiii -:ori op1631, R0004, R1115 is op0510=0x34 & R1115 & R0004; op1631 -{ - R1115 = R0004 | op1631; - set_OV0_S_Z(R1115); -} - -# TST reg1, reg2 - rrrrr001011RRRRR -:tst R0004, R1115 is op0510=0x0B & R0004 & R1115 -{ - set_OV0_S_Z(R1115 & R0004); -} - -# XOR reg1, reg2 - rrrrr001001RRRRR -:xor R0004, R1115 is op0510=0x09 & R0004 & R1115 -{ - R1115 = R1115 ^ R0004; - set_OV0_S_Z(R1115); -} - -# XORI imm16, reg1, reg2 - rrrrr110101RRRRR|iiiiiiiiiiiiiiii -:xori op1631, R0004, R1115 is op0510=0x35 & R1115 & R0004; op1631 -{ - R1115 = R0004 ^ op1631; - set_OV0_S_Z(R1115); -} - - - -##################################################### -##### BitManipulation ##### -##################################################### - - -# CLR1 bit#3, disp16[reg1] - 10bbb111110RRRRR|dddddddddddddddd -:clr1 op1113, s1631[R0004] is op0510=0x3E & op1415=2 & op1113 & R0004; s1631 -{ - local adr:4 = R0004 + s1631; - local tkn = *:1 adr; - *:1 adr = tkn & ~(1 << op1113); - set_Z(tkn & (1 << op1113)); -} - -# CLR1 reg2, [reg1] - rrrrr111111RRRRR|0000000011100100 -:clr1 R1115, [R0004] is op0510=0x3F & R0004 & R1115; op1631=0xE4 -{ - local tkn = *:1 R0004; - *:1 R0004 = tkn & ~(1 << R1115); - set_Z(tkn & (1 << R1115)); -} - -# NOT1 bit#3, disp16[reg1] - 01bbb111110RRRRR|dddddddddddddddd -:not1 op1113, s1631[R0004] is op0510=0x3E & op1415=1 & op1113 & R0004; s1631 -{ - local adr:4 = R0004 + s1631; - local tkn = *:1 adr; - *:1 adr = tkn ^ (1 << op1113); - set_Z(tkn & (1 << op1113)); -} - -# NOT1 reg2, [reg1] - rrrrr111111RRRRR|0000000011100010 -:not1 R1115, [R0004] is op0510=0x3F & R0004 & R1115; op1631=0xE2 -{ - local tkn = *:1 R0004; - *:1 R0004 = tkn ^ (1 << R1115); - set_Z(tkn & (1 << R1115)); -} - -# SET1 bit#3, disp16[reg1] - 00bbb111110RRRRR|dddddddddddddddd -:set1 op1113, s1631[R0004] is op0510=0x3E & op1415=0 & op1113 & R0004; s1631 -{ - local adr:4 = R0004 + s1631; - local tkn = *:1 adr; - *:1 adr = tkn | (1 << op1113); - set_Z(tkn & (1 << op1113)); -} - -# SET1 reg2, [reg1] - rrrrr111111RRRRR|0000000011100000 -:set1 R1115, [R0004] is op0510=0x3F & R0004 & R1115; op1631=0xE0 -{ - local tkn = *:1 R0004; - *:1 R0004 = tkn | (1 << R1115); - set_Z(tkn & (1 << R1115)); -} - -# TST1 bit#3, disp16[reg1] - 11bbb111110RRRRR|dddddddddddddddd -:tst1 op1113, s1631[R0004] is op0510=0x3E & op1415=3 & op1113 & R0004; s1631 -{ - local adr:4 = R0004 + s1631; - local tkn = *:1 adr; - set_Z(tkn & (1 << op1113)); -} - -# TST1 reg2, [reg1] - rrrrr111111RRRRR|0000000011100110 -:tst1 R0004, [R1115] is op0510=0x3F & R0004 & R1115; op1631=0xE6 -{ - local tkn = *:1 R0004; - set_Z(tkn & (1 << R1115)); -} diff --git a/Ghidra/Processors/V850/data/languages/Instructions/Special.sinc b/Ghidra/Processors/V850/data/languages/Instructions/Special.sinc deleted file mode 100644 index f94250e4dac..00000000000 --- a/Ghidra/Processors/V850/data/languages/Instructions/Special.sinc +++ /dev/null @@ -1,372 +0,0 @@ -# (10) Bit search instructions -# (13) Branch instructions -# (15) Special instructions - - - -##################################################### -##### BitSearch ##### -##################################################### - - -# SCH0L reg2, reg3 - rrrrr11111100000|wwwww01101100100 -:sch0l R1115, R2731 is op0010=0x7E0 & R1115; op1626=0x364 & R2731 -{ - SearchLeft(R2731, R1115, 0); - $(CY) = (R1115 != 0xFFFFFFFF); # zero bit found - $(Z) = (R1115 == 0xFFFFFFFF); # zero bit not found -} - -# SCH0R reg2, reg3 - rrrrr11111100000|wwwww01101100000 -:sch0r R1115, R2731 is op0010=0x7E0 & R1115; op1626=0x360 & R2731 -{ - SearchRight(R2731, R1115, 0); - $(CY) = (R1115 != 0xFFFFFFFF); # zero bit found - $(Z) = (R1115 == 0xFFFFFFFF); # zero bit not found -} - -# SCH1L reg2, reg3 - rrrrr11111100000|wwwww01101100110 -:sch1l R1115, R2731 is op0010=0x7E0 & R1115; op1626=0x366 & R2731 -{ - SearchLeft(R2731, R1115, 1); - $(CY) = (R1115 != 0x0); # one bit found - $(Z) = (R1115 == 0x0); # one bit not found -} - -# SCH1R reg2, reg3 -:sch1r R1115, R2731 is op0010=0x7E0 & R1115; op1626=0x362 & R2731 -{ - SearchRight(R2731, R1115, 1); - $(CY) = (R1115 != 0x0); # one bit found - $(Z) = (R1115 == 0x0); # one bit not found -} - - - -##################################################### -##### Branch ##### -##################################################### - - -#Bcond adr9 - ddddd1011dddcccc -:b^c0003 adr9 is op0710=0xB & c0003 & adr9 -{ - if (c0003) - goto adr9; -} -:br adr9 is op0710=0xB & op0003=0x5 & adr9 -{ - goto adr9; -} - -# JARL disp22, reg2 - rrrrr11110dddddd|ddddddddddddddd0 -:jarl adr22, R1115 is (op0610=0x1E & R1115) ... & adr22 -{ - R1115 = inst_next; - call adr22; -} - -# JARL disp32, reg1 - 00000010111RRRRR|ddddddddddddddd0|DDDDDDDDDDDDDDDD -:jarl adr32, R0004 is op0515=0x017 & R0004; adr32 -{ - R0004 = inst_next; - call adr32; -} - -# JMP [reg1] - 00000000011RRRRR -:jmp [R0004] is op0515=0x03 & R0004 & op0004=0x1F -{ - return [R0004]; -} -:jmp [R0004] is op0515=0x03 & R0004 & op0004!=0x1F -{ - call [R0004]; -} - -# JMP disp32[reg1] - 00000110111RRRRR|ddddddddddddddd0|DDDDDDDDDDDDDDDD -:jmp adr32i[R0004] is op0515=0x037 & R0004; adr32i -{ - local adr = adr32i + R0004; - goto [adr]; -} - -# JR disp22 - 00000111110ddddd|ddddddddddddddd0 -:jr adr22 is op0615=0x1E ... & adr22 -{ - goto adr22; -} - -# JR disp32 - 0000001011100000|ddddddddddddddd0|DDDDDDDDDDDDDDDD -:jr adr32 is op0015=0x2E0; adr32 -{ - goto adr32; -} - - - -##################################################### -##### Special ##### -##################################################### - - -# CALLT imm6 - 0000001000iiiiii -:callt op0005 is op0615=0x8 & op0005 -{ - CTPC = inst_next; - CTPSW = PSW; - local adr:4 = CTBP + (op0005 << 1); - PC = CTBP + zext(*:2 adr); - call [PC]; -} - -# CAXI [reg1], reg2, reg3 - rrrrr111111RRRRR|wwwww00011101110 -:caxi [R0004], R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0xEE & R2731 -{ - local tkn = *:4 (R0004 & ~(0x3)); - local result = R1115 - tkn; - *:4 R0004 = tkn * zext(result != 0) + R2731 * zext(result == 0); - R2731 = tkn; - set_general_flags_neg(R1115, tkn); -} - -# CTRET - 0000011111100000|0000000101000100 -:ctret is op0515=0x3F; op1631=0x144 -{ - PC = CTPC; - PSW = CTPSW; - return [PC]; -} - -# DI - 0000011111100000|0000000101100000 -define pcodeop __disable_irq; -:di is op0015=0x7E0; op1631=0x160 -{ - $(ID) = 1; - __disable_irq(); -} - -# DISPOSE imm5, list12 - 0000011001iiiiiL|LLLLLLLLLLL00000 -:dispose prep0105, DispList is prep0615=0x19 & prep1620=0x0 & prep0105 & DispList -{ - sp = sp + (prep0105 << 2); - build DispList; -} - -# DISPOSE imm5, list12, [reg1] - 0000011001iiiiiL|LLLLLLLLLLLRRRRR -:dispose prep0105, DispList, [prep1620] is prep0615=0x19 & prep1620 & prep0105 & DispList -{ - sp = sp + (prep0105 << 2); - build DispList; - PC = prep1620; - return [PC]; -} - -# EI - 1000011111100000|0000000101100000 -define pcodeop __enable_irq; -:ei is op0015=0x87E0; op1631=0x160 -{ - $(ID) = 0; - __enable_irq(); -} - -# EIRET - 0000011111100000|0000000101001000 -:eiret is op0515=0x3F; op1631=0x148 -{ - PC = EIPC; - PSW = EIPSW; - return [PC]; -} - -# FERET - 0000011111100000|0000000101001010 -:feret is op0515=0x3F; op1631=0x14A -{ - PC = FEPC; - PSW = FEPSW; - return [PC]; -} - -# FETRAP vector4 - 0vvvv00001000000 -:fetrap op1114 is op0010=0x40 & op1515=0 & op1114 & op1115!=0 -{ - FEPC = inst_next; - FEPSW = PSW; - $(FECC) = op1114 + 0x30; # exception code 0x30..0x3F - FEIC = op1114 + 0x30; # exception code 0x30..0x3F - $(EP) = 1; - $(ID) = 1; - $(NP) = 1; - PC = 0x30; - goto [PC]; -} - -# HALT - 0000011111100000|0000000100100000 -define pcodeop __halt; -:halt is op0015=0x7E0; op1631=0x120 -{ - __halt(); -} - -# LDSR reg2, regID - rrrrr111111RRRRR|0000000000100000 -:ldsr R0004, SR1115 is op0510=0x3F & SR1115 & R0004; op1631=0x20 -{ - SR1115 = R0004; -} - -# NOP - 0000000000000000 -:nop is op0015=0x0 -{ - PC = inst_next; -} - -# PREPARE list12, imm5 - 0000011110iiiiiL|LLLLLLLLLLL00001 -:prepare PrepList, prep0105 is prep0615=0x1E & prep0105 & prep1620=0x1 & PrepList -{ - build PrepList; - sp = sp - (prep0105 << 2); -} - -# PREPARE list12, imm5, sp - 0000011110iiiiiL|LLLLLLLLLLL00011 -:prepare PrepList, prep0105, sp is prep0615=0x1E & prep0105 & prep1620=0x3 & PrepList & sp -{ - build PrepList; - sp = sp - (prep0105 << 2); - ep = sp; -} - -# PREPARE list12, imm5, imm16 (low) - 0000011110iiiiiL|LLLLLLLLLLL01011|iiiiiiiiiiiiiiii -:prepare PrepList, prep0105, s3247 is prep0615=0x1E & prep0105 & prep1620=0xB & PrepList; s3247 -{ - build PrepList; - sp = sp - (prep0105 << 2); - ep = s3247; -} - -# PREPARE list12, imm5, imm16 (high) - 0000011110iiiiiL|LLLLLLLLLLL10011|iiiiiiiiiiiiiiii -:prepare PrepList, prep0105, s3247 is prep0615=0x1E & prep0105 & prep1620=0x13 & PrepList; s3247 -{ - build PrepList; - sp = sp - (prep0105 << 2); - ep = s3247 << 16; -} - -# PREPARE list12, imm5, imm32 - 0000011110iiiiiL|LLLLLLLLLLL11011|iiiiiiiiiiiiiiii|iiiiiiiiiiiiiiii -:prepare PrepList, prep0105, imm32 is prep0615=0x1E & prep0105 & prep1620=0x1B & PrepList; op3247; op4863 -[ imm32 = (op4863 << 16) | op3247; ] -{ - build PrepList; - sp = sp - (prep0105 << 2); - ep = imm32; -} - -# RETI - 0000011111100000|0000000101000000 -:reti is op0515=0x3F; op1631=0x140 -{ - if($(EP)!=1) - goto ; - - PC = EIPC; - PSW = EIPSW; - goto ; - - - if($(NP)!=1) - goto ; - - PC = FEPC; - PSW = FEPSW; - goto ; - - - PC = EIPC; - PSW = EIPSW; - - - return[PC]; -} - -# RIE - 0000000001000000 -:rie is op0015=0x40 -{ - FEPC = PC; - FEPSW = PSW; - $(NP) = 1; - $(EP) = 1; - $(ID) = 1; - PC = 0x30; - goto [PC]; -} - -# RIE imm5, imm4 - iiiii1111111IIII|0000000000000000 -:rie op1115, op0003 is op0410=0x7F & op1115 & op0003; op1631=0x0 -{ - FEPC = PC; - FEPSW = PSW; - $(NP) = 1; - $(EP) = 1; - $(ID) = 1; - PC = 0x30; - goto [PC]; -} - -# STSR regID, reg2 - rrrrr111111RRRRR|0000000001000000 -:stsr SR0004, R1115 is op0510=0x3F & R1115 & SR0004; op1631=0x40 -{ - R1115 = SR0004; -} - -# SWITCH reg1 - 00000000010RRRRR -:switch R0004 is op0515=0x2 & R0004 -{ - local adr:4 = inst_next + (R0004 << 1); - PC = inst_next + (sext(*:2 adr) << 1); - goto [PC]; -} - -# SYNCE - 0000000000011101 -define pcodeop __synchronize; -:synce is op0015=0x1D -{ - __synchronize(); -} - -# SYNCM - 0000000000011110 -:syncm is op0015=0x1E -{ - __synchronize(); -} - -# SYNCP - 0000000000011111 -:syncp is op0015=0x1F -{ - __synchronize(); -} - -# SYSCALL vector8 - 11010111111vvvvv|00VVV00101100000 -:syscall vector8 is op0515=0x6BF & op0004; op3031=0 & op2729 & op1626=0x160 -[ vector8 = (op2729 << 5) | op0004; ] -{ - EIPC = inst_next; - EIPSW = PSW; - EIIC = vector8 + 0x8000; # exception code 0x8000..0x80FF - $(EICC) = vector8 + 0x8000; # exception code 0x8000..0x80FF - $(EP) = 1; - $(ID) = 1; - local adr:4; - either_or(adr, (vector8 <= SCCFG), SCBP + (vector8 << 2), SCBP); - PC = SCBP + (*:4 adr); - call [PC]; -} - -# TRAP imm5 - 00000111111vvvvv|0000000100000000 -:trap op0004 is op0515=0x3F & op0004; op1631=0x100 -{ - local vector5:4 = op0004; - EIPC = inst_next; - EIPSW = PSW; - EIIC = vector5 + 0x40; # exception code 0x40..0x5F - $(EICC) = vector5:2 + 0x40; # exception code 0x40..0x5F - $(EP) = 1; - $(ID) = 1; - either_or(PC, (vector5 <= 15), 0x40, 0x50); - call [PC]; -} diff --git a/Ghidra/Processors/V850/data/languages/V850.dwarf b/Ghidra/Processors/V850/data/languages/V850.dwarf new file mode 100644 index 00000000000..0fa85f4cde0 --- /dev/null +++ b/Ghidra/Processors/V850/data/languages/V850.dwarf @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/Ghidra/Processors/V850/data/languages/V850.ldefs b/Ghidra/Processors/V850/data/languages/V850.ldefs index d0e197a0c3b..954f23a9520 100644 --- a/Ghidra/Processors/V850/data/languages/V850.ldefs +++ b/Ghidra/Processors/V850/data/languages/V850.ldefs @@ -5,12 +5,29 @@ endian="little" size="32" variant="E1, E2, E2M" - version="1.0" + version="1.1" slafile="V850.sla" processorspec="V850.pspec" manualindexfile="../manuals/v850.idx" id="V850:LE:32:default"> Renesas V850 family + + + + + + Renesas V850 family + + + diff --git a/Ghidra/Processors/V850/data/languages/V850.opinion b/Ghidra/Processors/V850/data/languages/V850.opinion index 94a0279c3f6..fcc50163663 100644 --- a/Ghidra/Processors/V850/data/languages/V850.opinion +++ b/Ghidra/Processors/V850/data/languages/V850.opinion @@ -1,6 +1,10 @@ - - + + + + \ No newline at end of file diff --git a/Ghidra/Processors/V850/data/languages/V850.pspec b/Ghidra/Processors/V850/data/languages/V850.pspec index 02fa9403d93..a55655e2d34 100644 --- a/Ghidra/Processors/V850/data/languages/V850.pspec +++ b/Ghidra/Processors/V850/data/languages/V850.pspec @@ -9,5 +9,10 @@ - + + + + + + diff --git a/Ghidra/Processors/V850/data/languages/V850.sinc b/Ghidra/Processors/V850/data/languages/V850.sinc new file mode 100644 index 00000000000..a1a0fa73d10 --- /dev/null +++ b/Ghidra/Processors/V850/data/languages/V850.sinc @@ -0,0 +1,748 @@ +########################################### +##### ##### +##### V850 SLEIGH specification ##### +##### ##### +########################################### +define endian = little; +define alignment = 2; + +# Size & default are required +define space ram type=ram_space size=4 default; +define space register type=register_space size=4; +define space sysreg type=ram_space size=2; + +########################## +##### Register ##### +########################## + + +##### General-purpose registers (r0 to r31) ##### + +define register offset=0x0 size=0x4 +[ + r0 r1 r2 sp gp tp r6 r7 r8 r9 + r10 r11 r12 r13 r14 r15 r16 r17 r18 r19 + r20 r21 r22 r23 r24 r25 r26 r27 r28 r29 + ep lp +]; + + +@define UM "UMf"#"PSW[30,1]" +@define NP "NPf"#"PSW[7,1]" +@define EP "EPf"#"PSW[6,1]" +@define ID "IDf"#"PSW[5,1]" +@define SAT "SATf"#"PSW[4,1]" +@define CY "CYf"#"PSW[3,1]" +@define OV "OVf"#"PSW[2,1]" +@define S "Sf"#"PSW[1,1]" +@define Z "Zf"#"PSW[0,1]" + +define register offset=0x800 size=1 +[ + Zf Sf OVf CYf SATf IDf EPf NPf UMf +]; + +##### Control/Special registers ##### + +@ifndef V850E3 +define sysreg offset=0x0 size=0x4 +[ + EIPC EIPSW FEPC FEPSW ECR PSW FPSR FPEPC FPST FPCC + FPCFG SCCFG SCBP EIIC FEIC DBIC CTPC CTPSW DBPC DBPSW + CTBP DIR DBG22 DBG23 DBG24 DBG25 DBG26 DBG27 EIWR FEWR + DBWR BSEL +]; + + + +@else +# The v850e3 uses a selID selector for system registers +# selID 0 +define sysreg offset=0x0 size=0x4 +[ + EIPC EIPSW FEPC FEPSW _ PSW FPSR FPEPC + FPST FPCC FPCFG FPEC _ EIIC FEIC _ + CTPC CTPSW DBPC DBPSW CTBP _ _ _ + _ _ _ _ EIWR FEWR _ BSEL +]; + +# selID 1 +define sysreg offset=0x80 size=0x4 +[ + MCFG0 MCFG1 RBASE EBASE INTBP MCTL PID FPIPR + _ _ TCSEL SCCFG SCBP HVCCFG HVCBP VSEL + VMPRT0 VMPRT1 VMPRT2 _ _ _ _ VMSCCTL + VMSCTBL0 VMSCTBL1 VMSCTBL2 VMSCTBL3 _ _ _ _ +]; + +# selID 2 +define sysreg offset=0x100 size=0x4 +[ + HTCFG0 _ _ _ _ HTCTL MEA ASID + MEI ISPR PMR ICSR INTCFG _ _ _ + TLBSCH _ _ _ _ _ _ HTSCCTL + HTSCTBL0 HTSCTBL1 HTSCTBL2 HTSCTBL3 HTSCTBL4 HTSCTBL5 HTSCTBL6 HTSCTBL7 +]; + +# no selID 3 +# selID 4 +define sysreg offset=0x200 size=0x4 +[ + TLBIDX _ _ _ TELO0 TELO1 TEHI0 TEHI1 + _ _ TLBCFG _ BWERRL BWERRH BRERRL BRERRH + ICTAGL ICTAGH ICDATL ICDATH DCTAGL DCTAGH DCDATL DCDATH + ICCTRL DCCTRL ICCFG DCCFG ICERR DCERR _ _ +]; + +# selID 5 +define sysreg offset=0x280 size=0x4 +[ + MPM MPRC _ _ MPBRGN MPTRGN _ _ + MCA MCS MCC MCR _ _ _ _ + _ _ _ _ MPPRT0 MPPRT1 MPPRT2 _ + _ _ _ _ _ _ _ _ +]; + +# selID 6 +define sysreg offset=0x300 size=0x4 +[ + MPLA0 MPUA0 MPAT0 _ MPLA1 MPUA1 MPAT1 _ + MPLA2 MPUA2 MPAT2 _ MPLA3 MPUA3 MPAT3 _ + MPLA4 MPUA4 MPAT4 _ MPLA5 MPUA5 MPAT5 _ + MPLA6 MPUA6 MPAT6 _ MPLA7 MPUA7 MPAT7 _ +]; + +# selID 7 +define sysreg offset=0x380 size=0x4 +[ + MPLA8 MPUA8 MPAT8 _ MPLA9 MPUA9 MPAT9 _ + MPLA10 MPUA10 MPAT10 _ MPLA11 MPUA11 MPAT11 _ + MPLA12 MPUA12 MPAT12 _ MPLA13 MPUA13 MPAT13 _ + MPLA14 MPUA14 MPAT14 _ MPLA15 MPUA15 MPAT15 _ +]; + +@endif #ndef V850E3 + +define register offset=0x0 size=0x8 +[ + r0r1 r2sp r4r5 r6r7 r8r9 + r10r11 r12r13 r14r15 r16r17 r18r19 + r20r21 r22r23 r24r25 r26r27 r28r29 + eplp +]; + +define register offset=0x100 size=0x4 [ PC ]; # offset = 0x100(256) = PreOffset+PreRegister*Size = 128+32*4 = 256 + +define register offset=0x200 size=4 [ _sp ]; +define register offset=0x1000 size=4 contextreg; + +define context contextreg +regNum = (17,21) +counter=(27,31) +; + +######################## +##### Tokens ##### +######################## + + +define token instr(16) + op0000 = (0,0) + op0003 = (0,3) + op0004 = (0,4) + _R0004 = (0,4) + SR0004 = (0,4) + R0004x2 = (0,4) + s0004 = (0,4) signed + s0005 = (0,5) signed + op0005 = (0,5) + op0006 = (0,6) + op0010 = (0,10) + op0015 = (0,15) + op0106 = (1,6) + s0404 = (4,4) + op0406 = (4,6) + op0410 = (4,10) + op0505 = (5,5) + op0510 = (5,10) + op0515 = (5,15) + op0610 = (6,10) + op0615 = (6,15) + op0710 = (7,10) + op1112 = (11,12) + op1113 = (11,13) + op1114 = (11,14) + op1115 = (11,15) + _R1115 = (11,15) + SR1115 = (11,15) + R1115x2 = (11,15) + regId = (11,15) + s1115 = (11,15) signed + op1315 = (13,15) + op1415 = (14,15) + op1515 = (15,15) +; + +define token instr2(16) + op1616 = (0,0) + op1617 = (0,1) + op1619 = (0,3) + op1620 = (0,4) + R1620 = (0,4) + R1620x2 = (0,4) + op1626 = (0,10) + op1631 = (0,15) + s1631 = (0,15) signed + fcbit1719 = (1,3) + op1719 = (1,3) + op1720 = (1,4) + op0_1720 = (1,4) + op1_1720 = (1,4) + op1731 = (1,15) + s1731 = (1,15) signed + op1821 = (2,5) + s1821 = (2,5) signed + op2020 = (4,4) + op2026 = (4,10) + op2122 = (5,6) + op2126 = (5,10) + op2226 = (6,10) + op2323 = (7,7) + op2426 = (8,10) + op2727 = (11,11) + op2729 = (11,13) + fcond2730 = (11,14) + op2731 = (11,15) + op2831 = (12,15) + _R2731 = (11,15) + R2731x2 = (11,15) + selId = (11,15) + op3031 = (14,15) + op3131 = (15,15) +; + +define token instr3(16) + op3247 = (0,15) + s3247 = (0,15) signed +; + +define token instr4(16) + op4863 = (0,15) +; + +# used in PREPARE/DISPOSE instructions +define token prep(32) + prep00 = (0,0) + prep0105 = (1,5) + prep0615 = (6,15) + prep1620 = (16,20) + prep21 = (21,21) + prep22 = (22,22) + prep2223 = (22,31) + prep23 = (23,23) + prep24 = (24,24) + prep25 = (25,25) + prep26 = (26,26) + prep27 = (27,27) + prep28 = (28,28) + prep2831 = (28,31) + prep29 = (29,29) + prep2931 = (29,31) + prep3031 = (30,31) + prep2231 = (22,31) + prep2331 = (23,31) + prep2431 = (24,31) + prep2427 = (24,27) + prep2527 = (25,27) + prep2627 = (26,27) + prep30 = (30,30) + prep31 = (31,31) +; + +########################### +##### Variables ##### +########################### + + +attach variables [ _R0004 _R1115 _R2731 R1620 prep1620 ] +[ + r0 r1 r2 sp gp tp r6 r7 r8 r9 + r10 r11 r12 r13 r14 r15 r16 r17 r18 r19 + r20 r21 r22 r23 r24 r25 r26 r27 r28 r29 + ep lp +]; + +attach variables [ R0004x2 R1115x2 R1620x2 R2731x2 ] +[ + r0r1 _ r2sp _ r4r5 _ r6r7 _ r8r9 _ + r10r11 _ r12r13 _ r14r15 _ r16r17 _ r18r19 _ + r20r21 _ r22r23 _ r24r25 _ r26r27 _ r28r29 _ + eplp _ +]; + +@ifndef V850E3 +attach variables [ SR0004 SR1115 ] +[ + EIPC EIPSW FEPC FEPSW ECR PSW FPSR FPEPC FPST FPCC + FPCFG SCCFG SCBP EIIC FEIC DBIC CTPC CTPSW DBPC DBPSW + CTBP DIR DBG22 DBG23 DBG24 DBG25 DBG26 DBG27 EIWR FEWR + DBWR BSEL +]; +@else + +@endif #ndef V850E3 + +attach variables [op0_1720] [r0 r2 gp r6 r8 r10 r12 r14 r16 r18 r20 r22 r24 r26 r28 ep]; +attach variables [op1_1720] [r1 sp tp r7 r9 r11 r13 r15 r17 r19 r21 r23 r25 r27 r29 lp]; + + +attach names [fcond2730] +["f" "un" "eq" "ueq" "olt" "ult" "ole" "ule" "sd" "ngle" "seq" "ngl" "lt" "nge" "le" "ngt"]; + + + +@define EICC "ECR[0,16]" +@define FECC "ECR[16,16]" + +######################## +##### Macros ##### +######################## + + +##### CARRY-Flag ##### + +macro set_CY_pos(op1, op2) +{ + $(CY) = carry(op1, op2); +} + +macro set_CY_pos2(op1, op2, carryIn) +{ + local res = op1 + op2; + $(CY) = carry(op1, op2) || carry(res, carryIn); +} + +macro set_CY_neg(op1, op2) +{ + $(CY) = op1 < op2; +} + +macro set_CY_neg2(op1, op2, carryIn) +{ + local res = op2 + carryIn; + $(CY) = (op1 < res); +} + + + +##### Overflow-Flag ##### + +macro set_OV_pos(op1, op2) +{ + $(OV) = scarry(op1, op2); +} + +macro set_OV_pos2(op1, op2, carryIn) +{ + local result = op1 + op2; + $(OV) = scarry(op1, op2) ^^ scarry(result, carryIn); +} + +macro set_OV_neg(op1, op2) +{ + $(OV) = sborrow(op1,op2); +} + +macro set_OV_neg2(op1, op2, carryIn) +{ + local borrowIn = (1-carryIn); + local result = op1 - op2; + $(OV) = sborrow( op1, op2 ) ^^ sborrow( result, borrowIn ); +} + + + +##### S/Z-Flags ##### + +macro set_S(flag) +{ + $(S) = flag s< 0; +} + +macro set_Z(var) +{ + $(Z) = var == 0; +} + + + +##### General-Flag-Macros ##### + +macro set_general_flags_pos(var1, var2) +{ + local res = var1 + var2; + set_CY_pos(var1, var2); + set_OV_pos(var1, var2); + set_S(res); + set_Z(res); +} + +macro set_general_flags_neg(var1, var2) +{ + local res = var1 - var2; + $(CY) = var1 < var2; + $(OV) = sborrow(var1, var2); + $(S) = res s< 0; + $(Z) = res == 0; +} + +macro set_OV0_S_Z(var) +{ + $(OV) = 0; + set_S(var); + set_Z(var); +} + + + +##### General-Macros ##### + +# if condition is != 0 + +macro either_or(res, cond, trueVal, falseVal) { + res = zext(cond) * trueVal | zext(!cond) * falseVal; +} +# if condition is == 1 +macro either_or1(res, cond, trueVal, falseVal) +{ + res = (trueVal * zext(cond == 1)) + (falseVal * zext(cond != 1)); +} + +macro shift_right_logic(res, var, shift_) +{ + local shift = shift_ & 0x1f; + local mask = var & (zext(shift != 0) << (shift - 1)); + res = var >> shift; + set_OV0_S_Z(res); + $(CY) = ((mask != 0) && (shift != 0)); +} + +macro shift_right_arith(res, var, shift_) +{ + local shift = shift_ & 0x1f; + local mask = (zext(shift != 0) * var) & (1 << (shift - 1)); + res = var s>> shift; + set_OV0_S_Z(res); + $(CY) = ((mask != 0) && (shift != 0)); +} + +macro shift_left_logic(res, var, shift_) +{ + local shift = shift_ & 0x1f; + local mask = (zext(shift != 0) * var) & (1 << (32 - shift)); + res = var << shift; + set_OV0_S_Z(res); + $(CY) = ((mask != 0) && (shift != 0)); +} + + +macro bfmask (res, off, width) { + res = ((1 << width) - 1) << (32 - off - width); +} + +##### Stack Macros ##### + +macro push(reg) +{ + sp = sp - 4; + *:4 sp = reg; +} + +macro pop(reg) +{ + reg = *:4 sp; + sp = sp + 4; +} + +macro pushsp(reg) +{ + _sp = _sp - 4; + *:4 _sp = reg; +} + +macro popsp(reg) +{ + reg = *:4 _sp; + _sp = _sp + 4; +} + +##### Search Macros ##### + +macro SearchRight(res, var, char) +{ + local var_:4 = var; + res = 0; + + + if ((var_ & 0x1) == char) + goto ; + + var_ = var_ >> 1; + res = res + 1; + + if (res < 32) + goto ; + + res = 0; + + +} + +macro SearchLeft(res, var, char) +{ + local var_:4 = var; + res = 0; + + + if ((var_ >> 31) == char) + goto ; + + var_ = var_ << 1; + res = res + 1; + + if (res < 32) + goto ; + + res = 0; + + +} + +# macro saturate(var) +# { +# if (var s> 0x7FFFFFFF) +# goto ; + +# if (var s< -0x80000000) +# goto ; + +# goto ; + +# +# var = 0x7FFFFFFF; +# goto ; + +# +# var = -0x80000000; +# goto ; + +# +# } + + +##### Float-Macros ##### + +macro compare_float(res, fcond, reg1, reg2) +{ + local un = ((fcond & 1) == 1) & (nan(reg2) || nan(reg1)); + local eq = ((fcond & 2) == 2) & (!(nan(reg2) || nan(reg1))) & (reg2 f== reg1); + local le = ((fcond & 4) == 4) & (!(nan(reg2) || nan(reg1))) & (reg2 f< reg1); + #local ex = (fcond & 8) & ((nan(reg2) || nan(reg1))); + + res = zext(un|eq|le); +} + + +########################### +##### Conditions #### +########################### + + +c0003: "v" is op0003=0x0 { tmp:1 = ($(OV)) == 1; export tmp; } +c0003: "nv" is op0003=0x8 { tmp:1 = ($(OV)) == 0; export tmp; } +c0003: "c" is op0003=0x1 { tmp:1 = ($(CY)) == 1; export tmp; } +c0003: "nc" is op0003=0x9 { tmp:1 = ($(CY)) == 0; export tmp; } +c0003: "e" is op0003=0x2 { tmp:1 = ($(Z)) == 1; export tmp; } +c0003: "ne" is op0003=0xA { tmp:1 = ($(Z)) == 0; export tmp; } +c0003: "nh" is op0003=0x3 { tmp:1 = ($(CY) || $(Z)) == 1; export tmp; } +c0003: "h" is op0003=0xB { tmp:1 = ($(CY) || $(Z)) == 0; export tmp; } +c0003: "n" is op0003=0x4 { tmp:1 = ($(S)) == 1; export tmp; } +c0003: "p" is op0003=0xC { tmp:1 = ($(S)) == 0; export tmp; } +c0003: "t" is op0003=0x5 { tmp:1 = 1; export tmp; } +c0003: "sa" is op0003=0xD { tmp:1 = ($(SAT)) == 1; export tmp; } +c0003: "lt" is op0003=0x6 { tmp:1 = ($(S) ^^ $(OV)) == 1; export tmp; } +c0003: "ge" is op0003=0xE { tmp:1 = ($(S) ^^ $(OV)) == 0; export tmp; } +c0003: "le" is op0003=0x7 { tmp:1 = ($(S) ^^ $(OV) || $(Z)) == 1; export tmp; } +c0003: "gt" is op0003=0xF { tmp:1 = ($(S) ^^ $(OV) || $(Z)) == 0; export tmp; } + +c1720: "v" is op1720=0x0 { tmp:1 = ($(OV)) == 1; export tmp; } +c1720: "nv" is op1720=0x8 { tmp:1 = ($(OV)) == 0; export tmp; } +c1720: "c" is op1720=0x1 { tmp:1 = ($(CY)) == 1; export tmp; } +c1720: "nc" is op1720=0x9 { tmp:1 = ($(CY)) == 0; export tmp; } +c1720: "e" is op1720=0x2 { tmp:1 = ($(Z)) == 1; export tmp; } +c1720: "ne" is op1720=0xA { tmp:1 = ($(Z)) == 0; export tmp; } +c1720: "nh" is op1720=0x3 { tmp:1 = ($(CY) || $(Z)) == 1; export tmp; } +c1720: "h" is op1720=0xB { tmp:1 = ($(CY) || $(Z)) == 0; export tmp; } +c1720: "n" is op1720=0x4 { tmp:1 = ($(S)) == 1; export tmp; } +c1720: "p" is op1720=0xC { tmp:1 = ($(S)) == 0; export tmp; } +c1720: "t" is op1720=0x5 { tmp:1 = 1; export tmp; } +c1720: "sa" is op1720=0xD { tmp:1 = ($(SAT)) == 1; export tmp; } +c1720: "lt" is op1720=0x6 { tmp:1 = ($(S) ^^ $(OV)) == 1; export tmp; } +c1720: "ge" is op1720=0xE { tmp:1 = ($(S) ^^ $(OV)) == 0; export tmp; } +c1720: "le" is op1720=0x7 { tmp:1 = ($(S) ^^ $(OV) || $(Z)) == 1; export tmp; } +c1720: "gt" is op1720=0xF { tmp:1 = ($(S) ^^ $(OV) || $(Z)) == 0; export tmp; } + +################################## +##### Sub-Constructors ##### +################################## + + +# read r0 always return zero +R0004: _R0004 is _R0004 & _R0004=0 { local x:4=0; export x; } +R0004: _R0004 is _R0004 { export _R0004; } + +R1115: _R1115 is _R1115 & _R1115=0 { local x:4=0; export x; } +R1115: _R1115 is _R1115 { export _R1115; } + +R2731: _R2731 is _R2731 & _R2731=0 { local x:4=0; export x; } +R2731: _R2731 is _R2731 { export _R2731; } + + +adr9: res is op0406 & s1115 +[ res = ((s1115 << 4) | (op0406 << 1)) + inst_start; ] +{ + export *:4 res; +} +adr17: res is s0404; s1731 +[ res = ((s0404 << 16) | (s1731 << 1)) + inst_start; ] +{ + export *:4 res; +} +adr22: res is s0005; op1631 & op1616=0 +[ res = ((s0005 << 16) | op1631) + inst_start; ] +{ + export *:4 res; +} + +adr22off4: res is s0005; op1631 & op1616=0 +[ res = ((s0005 << 16) | op1631) + inst_start + 4; ] +{ + export *:4 res; +} + +adr32: res is op1631 & op1616=0; op3247 +[ res = ((op3247 << 16) | op1631) + inst_start; ] +{ + export *:4 res; +} + +adr32i: res is op1631 & op1616=0; op3247 +[ res = ((op3247 << 16) | op1631); ] +{ + export *[const]:4 res; +} + +reg4: op0_1720 is op2323=0 & op0_1720 { export op0_1720; } +reg4: op1_1720 is op2323=1 & op1_1720 { export op1_1720; } + + + +##### Prep/Disp Loop ##### + +PrepList20: r20 is prep27=1 & r20 { push(r20); } +PrepList20: is prep27=0 { } + +PrepList21: r21 is prep26=1 & prep27=0 & r21 { push(r21); } +PrepList21: PrepList20,r21 is prep26=1 & PrepList20 & r21 { push(r21); } +PrepList21: PrepList20 is prep26=0 & PrepList20 { } + +PrepList22: r22 is prep25=1 & prep2627=0 & r22 { push(r22); } +PrepList22: PrepList21,r22 is prep25=1 & PrepList21 & r22 { push(r22); } +PrepList22: PrepList21 is prep25=0 & PrepList21 { } + +PrepList23: r23 is prep24=1 & prep2527=0 & r23 { push(r23); } +PrepList23: PrepList22,r23 is prep24=1 & PrepList22 & r23 { push(r23); } +PrepList23: PrepList22 is prep24=0 & PrepList22 { } + +PrepList24: r24 is prep31=1 & prep2427=0 & r24 { push(r24); } +PrepList24: PrepList23,r24 is prep31=1 & PrepList23 & r24 { push(r24); } +PrepList24: PrepList23 is prep31=0 & PrepList23 { } + +PrepList25: r25 is prep30=1 & prep2427=0 & prep31=0 & r25 { push(r25); } +PrepList25: PrepList24,r25 is prep30=1 & PrepList24 & r25 { push(r25); } +PrepList25: PrepList24 is prep30=0 & PrepList24 { } + +PrepList26: r26 is prep29=1 & prep2427=0 & prep3031=0 & r26 { push(r26); } +PrepList26: PrepList25,r26 is prep29=1 & PrepList25 & r26 { push(r26); } +PrepList26: PrepList25 is prep29=0 & PrepList25 { } + +PrepList27: r27 is prep28=1 & prep2427=0 & prep2931=0 & r27 { push(r27); } +PrepList27: PrepList26,r27 is prep28=1 & PrepList26 & r27 { push(r27); } +PrepList27: PrepList26 is prep28=0 & PrepList26 { } + +PrepList28: r28 is prep23=1 & prep2431=0 & r28 { push(r28); } +PrepList28: PrepList27,r28 is prep23=1 & PrepList27 & r28 { push(r28); } +PrepList28: PrepList27 is prep23=0 & PrepList27 { } + +PrepList29: r29 is prep22=1 & prep2431=0 & prep23=0 & r29 { push(r29); } +PrepList29: PrepList28,r29 is prep22=1 & PrepList28 & r29 { push(r29); } +PrepList29: PrepList28 is prep22=0 & PrepList28 { } + +PrepList30: ep is prep00=1 & prep2431=0 & prep2223=0 & ep { push(ep); } +PrepList30: PrepList29,ep is prep00=1 & PrepList29 & ep { push(ep); } +PrepList30: PrepList29 is prep00=0 & PrepList29 { } + +PrepList: { lp } is prep21=1 & prep2431=0 & prep2223=0 & prep00=0 & lp { push(lp); } +PrepList: { PrepList30,lp } is prep21=1 & PrepList30 & lp { push(lp); } +PrepList: { PrepList30 } is prep21=0 & PrepList30 { } + + + +DispList31: ,lp is prep21=1 & lp { pop(lp); } +DispList31: lp is prep21=1 & prep00=0 & prep2231=0 & lp { pop(lp); } +DispList31: is prep21=0 { } + +DispList30: ep^DispList31 is DispList31 & prep00=1 & ep { pop(ep); } +DispList30: ,ep^DispList31 is DispList31 & prep00=1 & prep2231=0 & ep { pop(ep); } +DispList30: DispList31 is DispList31 & prep00=0 { } + +DispList29: ,r29^DispList30 is DispList30 & prep22=1 & r29 { pop(r29); } +DispList29: r29^DispList30 is DispList30 & prep22=1 & prep2331=0 & r29 { pop(r29); } +DispList29: DispList30 is DispList30 & prep22=0 { } + +DispList28: ,r28^DispList29 is DispList29 & prep23=1 & r28 { pop(r28); } +DispList28: r28^DispList29 is DispList29 & prep23=1 & prep2831=0 & prep2427=0 & r28 { pop(r28); } +DispList28: DispList29 is DispList29 & prep23=0 { } + +DispList27: ,r27^DispList28 is DispList28 & prep28=1 & r27 { pop(r27); } +DispList27: r27^DispList28 is DispList28 & prep28=1 & prep2931=0 & prep2427=0 & r27 { pop(r27); } +DispList27: DispList28 is DispList28 & prep28=0 { } + +DispList26: ,r26^DispList27 is DispList27 & prep29=1 & r26 { pop(r26); } +DispList26: r26^DispList27 is DispList27 & prep29=1 & prep3031=0 & prep2427=0 & r26 { pop(r26); } +DispList26: DispList27 is DispList27 & prep29=0 { } + +DispList25: ,r25^DispList26 is DispList26 & prep30=1 & r25 { pop(r25); } +DispList25: r25^DispList26 is DispList26 & prep30=1 & prep31=0 & prep2427=0 & r25 { pop(r25); } +DispList25: DispList26 is DispList26 & prep30=0 { } + +DispList24: ,r24^DispList25 is DispList25 & prep31=1 & r24 { pop(r24); } +DispList24: r24^DispList25 is DispList25 & prep31=1 & prep2427=0 & r24 { pop(r24); } +DispList24: DispList25 is DispList25 & prep31=0 { } + +DispList23: ,r23^DispList24 is DispList24 & prep24=1 & r23 { pop(r23); } +DispList23: r23^DispList24 is DispList24 & prep24=1 & prep2527=0 & r23 { pop(r23); } +DispList23: DispList24 is DispList24 & prep24=0 { } + +DispList22: ,r22^DispList23 is DispList23 & prep25=1 & r22 { pop(r22); } +DispList22: r22^DispList23 is DispList23 & prep25=1 & prep2627=0 & r22 { pop(r22); } +DispList22: DispList23 is DispList23 & prep25=0 { } + +DispList21: ,r21^DispList22 is DispList22 & prep26=1 & r21 { pop(r21); } +DispList21: r21^DispList22 is DispList22 & prep26=1 & prep27=0 & r21 { pop(r21); } +DispList21: DispList22 is DispList22 & prep26=0 { } + +DispList: { r20^DispList21 } is DispList21 & prep27=1 & r20 { pop(r20); } +DispList: { DispList21 } is DispList21 & prep27=0 { } + + diff --git a/Ghidra/Processors/V850/data/languages/V850.slaspec b/Ghidra/Processors/V850/data/languages/V850.slaspec index 633e0e386e4..7bc060d6d8f 100644 --- a/Ghidra/Processors/V850/data/languages/V850.slaspec +++ b/Ghidra/Processors/V850/data/languages/V850.slaspec @@ -1,37 +1,16 @@ -##################################################### -##### ##### -##### V850E2M SLEIGH specification ##### -##### ##### -##################################################### +################################################ +##### ##### +##### V850E2M SLEIGH specification ##### +##### ##### +################################################ -define endian = little; -define alignment = 2; +@include "V850.sinc" -# Size & default are required -define space ram type=ram_space size=4 default; -define space register type=register_space size=4; +################################ +##### Instructions ##### +################################ -##################################################### -##### Helpers ##### -##################################################### +@include "V850_instructions.sinc" -@include "./Helpers/Register.sinc" -@include "./Helpers/Tokens.sinc" -@include "./Helpers/Variables.sinc" -@include "./Helpers/Conditions.sinc" -@include "./Helpers/Macros.sinc" -@include "./Helpers/Extras.sinc" - - - -##################################################### -##### Instructions ##### -##################################################### - -@include "./Instructions/Arithmetic.sinc" -@include "./Instructions/Float.sinc" -@include "./Instructions/Load_Store.sinc" -@include "./Instructions/Logic.sinc" -@include "./Instructions/Special.sinc" diff --git a/Ghidra/Processors/V850/data/languages/V850_instructions.sinc b/Ghidra/Processors/V850/data/languages/V850_instructions.sinc new file mode 100644 index 00000000000..f1d531bd405 --- /dev/null +++ b/Ghidra/Processors/V850/data/languages/V850_instructions.sinc @@ -0,0 +1,1764 @@ + +##################################################### +##### Multiply ##### +##################################################### + + +# MUL reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww01000100000 +:mul R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0x220 & R2731 +{ + local res:8 = sext(R1115) * sext(R0004); + R1115 = res:4; + R2731 = res[32,32]; +} + +# MUL imm9, reg2, reg3 - rrrrr111111iiiii|wwwww01001IIII00 +:mul imm9, R1115, R2731 is op0510=0x3F & op0004 & R1115; op2226=0x9 & op1617=0x0 & s1821 & R2731 +[ imm9 = (s1821 << 5) | op0004; ] +{ + local res:8 = sext(R1115) * imm9; + R1115 = res:4; + R2731 = res[32,32]; +} + +# MULH reg1, reg2 - rrrrr000111RRRRR +:mulh R0004, R1115 is op0510=0x07 & R0004 & R1115 & op1115!=0 +{ + R1115 = sext(R1115:2) * sext(R0004:2); +} + +# MULH imm5, reg2 - rrrrr010111iiiii +:mulh s0004, R1115 is op0510=0x17 & s0004 & R1115 +{ + R1115 = sext(R1115:2) * s0004; +} + +# MULHI imm16, reg1, reg2 - rrrrr110111RRRRR|iiiiiiiiiiiiiiii +:mulhi s1631, R0004, R1115 is op0510=0x37 & R1115 & R0004; s1631 +{ + R1115 = R0004 * s1631; +} + +# MULU reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww01000100010 +:mulu R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0x222 & R2731 +{ + local res:8 = zext(R1115) * zext(R0004); + R1115 = res:4; + R2731 = res[32,32]; +} + +# MULU imm9, reg2, reg3 - rrrrr111111iiiii|wwwww01001IIII10 +:mulu imm9, R1115, R2731 is op0510=0x3F & op0004 & R1115; op2226=0x9 & op1617=0x2 & op1821 & R2731 +[ imm9 = (op1821 << 5) | op0004; ] +{ + local res:8 = zext(R1115) * imm9; + R1115 = res:4; + R2731 = res[32,32]; +} + + +##################################################### +##### MultiplyAccumulate ##### +##################################################### + + +# MAC reg1, reg2, reg3, reg4 - rrrrr111111RRRRR wwww0011110mmmm0 +:mac R0004, R1115, R2731x2, R1620x2 is op0510=0x3F & R0004 & R1115; op2126=0x1E & op1616=0 & R1620x2 & R2731x2 +{ + R1620x2 = sext(R1115) * sext(R0004) + R2731x2; +} + +# MACU reg1, reg2, reg3, reg4 - rrrrr111111RRRRR|wwww0011111mmmm0 +:macu R0004, R1115, R2731x2, R1620x2 is op0510=0x3F & R0004 & R1115; op2126=0x1F & op1616=0 & R1620x2 & R2731x2 +{ + R1620x2 = zext(R1115) * zext(R0004) + R2731x2; +} + + +##################################################### +##### Arithmetic ##### +##################################################### + + +# ADD reg1, reg2 - rrrrr001110RRRRR +:add R0004, R1115 is op0510=0x0E & R0004 & R1115 +{ + set_general_flags_pos(R0004, R1115); + R1115 = R1115 + R0004; +} + +# ADD imm5, reg2 - rrrrr010010iiiii +:add s0004, R1115 is op0510=0x12 & s0004 & R1115 +{ + set_general_flags_pos(s0004, R1115); + R1115 = R1115 + s0004; +} + +# ADDI imm16, reg1, reg2 - rrrrr110000RRRRR|iiiiiiiiiiiiiiii +:addi s1631, R0004, R1115 is op0510=0x30 & R1115 & R0004; s1631 +{ + set_general_flags_pos(R0004, s1631); + R1115 = R0004 + s1631; +} + +# CMP reg1, reg2 - rrrrr001111RRRRR +:cmp R0004, R1115 is op0510=0x0F & R0004 & R1115 +{ + set_general_flags_neg(R1115, R0004); +} + +# CMP imm5, reg2 - rrrrr010011iiiii +:cmp s0004, R1115 is op0510=0x13 & s0004 & R1115 +{ + set_general_flags_neg(R1115, s0004); +} + +# MOV reg1, reg2 - rrrrr000000RRRRR +:mov R0004, R1115 is op0510=0x00 & R0004 & R1115 +{ + R1115 = R0004; +} + +# MOV imm5, reg2 - rrrrr010000iiiii +:mov s0004, R1115 is op0510=0x10 & s0004 & R1115 & op1115!=0 +{ + R1115 = s0004; +} + +# MOV imm32, reg1 - 00000110001RRRRR|iiiiiiiiiiiiiiii|IIIIIIIIIIIIIIII +:mov imm32, R0004 is op0515=0x031 & R0004; op1631; op3247 +[ imm32 = (op3247 << 16) | op1631; ] +{ + R0004 = imm32; +} + +# MOVEA imm16, reg1, reg2 - rrrrr110001RRRRR|iiiiiiiiiiiiiiii +:movea s1631, R0004, R1115 is op0510=0x31 & op1115!=0 & R0004 & R1115; s1631 +{ + R1115 = R0004 + s1631; +} + +# MOVHI imm16, reg1, reg2 - rrrrr110010RRRRR|iiiiiiiiiiiiiiii +:movhi s1631, R0004, R1115 is op0510=0x32 & op1115!=0 & R0004 & R1115; s1631 +{ + R1115 = R0004 + (s1631 << 16); +} + +# SUB reg1, reg2 - rrrrr001101RRRRR +:sub R0004, R1115 is op0510=0x0D & R0004 & R1115 +{ + set_general_flags_neg(R1115, R0004); + R1115 = R1115 - R0004; +} + +# SUBR reg1, reg2 - rrrrr001100RRRRR +:subr R0004, R1115 is op0510=0x0C & R0004 & R1115 +{ + set_general_flags_neg(R0004, R1115); + R1115 = R0004 - R1115; +} + + +##################################################### +##### Saturated ##### +##################################################### + + +define pcodeop __saturate; + +# SATADD reg1, reg2 - rrrrr000110RRRRR +:satadd R0004, R1115 is op0510=0x06 & R0004 & R1115 & op1115!=0 +{ + set_CY_pos(R1115, R0004); + set_OV_pos(R1115, R0004); + $(SAT) = $(SAT) || $(OV); + + R1115 = R1115 + R0004; + R1115 = __saturate(R1115); + + set_S(R1115); + set_Z(R1115); +} + +#SATADD imm5, reg2 - rrrrr010001iiiii +:satadd s0004, R1115 is op0510=0x11 & s0004 & R1115 & op1115!=0 +{ + set_CY_pos(R1115, s0004); + set_OV_pos(R1115, s0004); + $(SAT) = $(SAT) || $(OV); + + R1115 = R1115 + s0004; + R1115 = __saturate(R1115); + + set_S(R1115); + set_Z(R1115); +} + +# SATADD reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww01110111010 +:satadd R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0x3BA & R2731 +{ + set_CY_pos(R1115, R0004); + set_OV_pos(R1115, R0004); + $(SAT) = $(SAT) || $(OV); + + R2731 = R1115 + R0004; + R2731 = __saturate(R2731); + + set_S(R2731); + set_Z(R2731); +} + +# SATSUB reg1, reg2 - rrrrr000101RRRRR +:satsub R0004, R1115 is op0510=0x05 & R0004 & R1115 & op1115!=0 +{ + + $(CY) = R1115 < R0004; + $(OV) = sborrow(R1115, R0004); + $(SAT) = $(SAT) || $(OV); + + R1115 = R1115 - R0004; + R1115 = __saturate(R1115); + + $(S) = R1115 s< 0; + $(Z) = R1115 == 0; +} + +# SATSUB reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww01110011010 +:satsub R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0x39A & R2731 +{ + $(CY) = R1115 < R0004; + $(OV) = sborrow(R1115, R0004); + $(SAT) = $(SAT) || $(OV); + + R2731 = R1115 - R0004; + R2731 = __saturate(R2731); + + $(S) = R2731 s< 0; + $(Z) = R2731 == 0; +} + +# SATSUBI imm16, reg1, reg2 +:satsubi s1631, R0004, R1115 is op0510=0x33 & op1115!=0 & R0004 & R1115; s1631 +{ + $(CY) = R1115 < s1631; + $(OV) = sborrow(R1115, s1631); + $(SAT) = $(SAT) || $(OV); + + R1115 = R1115 - s1631; + R1115 = __saturate(R1115); + + $(S) = R1115 s< 0; + $(Z) = R1115 == 0; +} + +# SATSUBR reg1, reg2 +:satsubr R0004, R1115 is op0510=0x04 & R0004 & R1115 & op1115!=0 +{ + $(CY) = R0004 < R1115; + $(OV) = sborrow(R0004, R1115); + $(SAT) = $(SAT) || $(OV); + + R1115 = R0004 - R1115; + R1115 = __saturate(R1115); + + $(S) = R1115 s< 0; + $(Z) = R1115 == 0; +} + + +##################################################### +##### Divide ##### +##################################################### + + +# DIV reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww01011000000 +:div R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0x2C0 & R2731 +{ + local quot:4 = R1115 s/ R0004; + local mod:4 = R1115 s% R0004; + $(OV) = ((R1115 == 0x80000000 && R0004 == 0xFFFFFFFF) || R0004 == 0x0); + R1115 = quot; + R2731 = mod; + set_Z(R1115); + set_S(R1115); +} + +# DIVH reg1, reg2 - rrrrr000010RRRRR +:divh R0004, R1115 is op0510=0x02 & R0004 & R1115 +{ + $(OV) = ((R1115 == 0x80000000 && R0004 == 0xFFFFFFFF) || R0004 == 0x0); + R1115 = R1115 / R0004; + set_Z(R1115); + set_S(R1115); +} + +# DIVH reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww01010000000 +:divh R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0x280 & R2731 +{ + local quot:4 = R1115 s/ sext(R0004:2); + local mod:4 = R1115 s% sext(R0004:2); + $(OV) = ((R1115 == 0x80000000 && R0004 == 0xFFFFFFFF) || R0004 == 0x0); + R1115 = quot; + R2731 = mod; + set_Z(R1115); + set_S(R1115); +} + +# DIVHU reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww01010000010 +:divhu R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0x282 & R2731 +{ + local quot:4 = R1115 / zext(R0004:2); + local mod:4 = R1115 % zext(R0004:2); + R1115 = quot; + R2731 = mod; + $(OV) = (R0004 == 0); + set_Z(R1115); + set_S(R1115); +} + +# DIVU reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww01011000010 +:divu R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0x2C2 & R2731 +{ + local quot:4 = R1115 / R0004; + local mod:4 = R1115 % R0004; + $(OV) = (R0004 == 0); + R1115 = quot; + R2731 = mod; + set_Z(R1115); + set_S(R1115); +} + + +##################################################### +##### HighSpeedDivide ##### +##################################################### + + +# DIVQ reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww01011111100 +:divq R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0x2FC & R2731 +{ + local quot:4 = R1115 s/ R0004; + local mod:4 = R1115 s% R0004; + $(OV) = ((R1115 == 0x80000000 && R0004 == 0xFFFFFFFF) || R0004 == 0x0); + R2731 = mod; + R1115 = quot; + set_Z(R1115); + set_S(R1115); +} + +# DIVQU reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww01011111110 +:divqu R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0x2FE & R2731 +{ + local quot:4 = R1115 / R0004; + local mod:4 = R1115 % R0004; + $(OV) = (R0004 == 0); + R2731 = mod; + R1115 = quot; + set_Z(R1115); + set_S(R1115); +} + + +##################################################### +##### Conditional ##### +##################################################### + + +# ADF cccc, reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww011101cccc0 +:adf^c1720 R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op2126=0x1D & op1616=0 & c1720 & R2731 +{ + local cond = zext(c1720); + set_OV_pos2(R1115, R0004, cond); + set_CY_pos2(R1115, R0004, cond); + R2731 = R1115 + R0004 + cond; + set_S(R2731); + set_Z(R2731); +} + +# SBF cccc, reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww011100cccc0 +:sbf^c1720 R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op2126=0x1C & op1616=0 & c1720 & R2731 +{ + local cond = zext(c1720); + set_OV_neg2(R1115, R0004, cond); + set_CY_neg2(R1115, R0004, cond); + R2731 = R1115 - R0004 - cond; + set_S(R2731); + set_Z(R2731); +} + + +##################################################### +##### Logic ##### +##################################################### + + +# AND reg1, reg2 - rrrrr001010RRRRR +:and R0004, R1115 is op0510=0x0A & R0004 & R1115 +{ + R1115 = R1115 & R0004; + set_OV0_S_Z(R1115); +} + +# ANDI imm16, reg1, reg2 - rrrrr110110RRRRR|iiiiiiiiiiiiiiii +:andi op1631, R0004, R1115 is op0510=0x36 & R1115 & R0004; op1631 +{ + R1115 = R0004 & op1631; + set_OV0_S_Z(R1115); +} + +# NOT reg1, reg2 - rrrrr000001RRRRR +:not R0004, R1115 is op0510=0x01 & R0004 & R1115 +{ + R1115 = ~R0004; + set_OV0_S_Z(R1115); +} + +# OR reg1, reg2 - rrrrr001000RRRRR +:or R0004, R1115 is op0510=0x08 & R0004 & R1115 +{ + R1115 = R1115 | R0004; + set_OV0_S_Z(R1115); +} + +# ORI imm16, reg1, reg2 - rrrrr110100RRRRR|iiiiiiiiiiiiiiii +:ori op1631, R0004, R1115 is op0510=0x34 & R1115 & R0004; op1631 +{ + R1115 = R0004 | op1631; + set_OV0_S_Z(R1115); +} + +# TST reg1, reg2 - rrrrr001011RRRRR +:tst R0004, R1115 is op0510=0x0B & R0004 & R1115 +{ + set_OV0_S_Z(R1115 & R0004); +} + +# XOR reg1, reg2 - rrrrr001001RRRRR +:xor R0004, R1115 is op0510=0x09 & R0004 & R1115 +{ + R1115 = R1115 ^ R0004; + set_OV0_S_Z(R1115); +} + +# XORI imm16, reg1, reg2 - rrrrr110101RRRRR|iiiiiiiiiiiiiiii +:xori op1631, R0004, R1115 is op0510=0x35 & R1115 & R0004; op1631 +{ + R1115 = R0004 ^ op1631; + set_OV0_S_Z(R1115); +} + + +##################################################### +##### BitManipulation ##### +##################################################### + + +# CLR1 bit#3, disp16[reg1] - 10bbb111110RRRRR|dddddddddddddddd +:clr1 op1113, s1631[R0004] is op0510=0x3E & op1415=2 & op1113 & R0004; s1631 +{ + local adr:4 = R0004 + s1631; + local tkn = *:1 adr; + *:1 adr = tkn & ~(1 << op1113); + set_Z(tkn & (1 << op1113)); +} + +# CLR1 reg2, [reg1] - rrrrr111111RRRRR|0000000011100100 +:clr1 R1115, [R0004] is op0510=0x3F & R0004 & R1115; op1631=0xE4 +{ + local tkn = *:1 R0004; + *:1 R0004 = tkn & ~(1 << R1115); + set_Z(tkn & (1 << R1115)); +} + +# NOT1 bit#3, disp16[reg1] - 01bbb111110RRRRR|dddddddddddddddd +:not1 op1113, s1631[R0004] is op0510=0x3E & op1415=1 & op1113 & R0004; s1631 +{ + local adr:4 = R0004 + s1631; + local tkn = *:1 adr; + *:1 adr = tkn ^ (1 << op1113); + set_Z(tkn & (1 << op1113)); +} + +# NOT1 reg2, [reg1] - rrrrr111111RRRRR|0000000011100010 +:not1 R1115, [R0004] is op0510=0x3F & R0004 & R1115; op1631=0xE2 +{ + local tkn = *:1 R0004; + *:1 R0004 = tkn ^ (1 << R1115); + set_Z(tkn & (1 << R1115)); +} + +# SET1 bit#3, disp16[reg1] - 00bbb111110RRRRR|dddddddddddddddd +:set1 op1113, s1631[R0004] is op0510=0x3E & op1415=0 & op1113 & R0004; s1631 +{ + local adr:4 = R0004 + s1631; + local tkn = *:1 adr; + *:1 adr = tkn | (1 << op1113); + set_Z(tkn & (1 << op1113)); +} + +# SET1 reg2, [reg1] - rrrrr111111RRRRR|0000000011100000 +:set1 R1115, [R0004] is op0510=0x3F & R0004 & R1115; op1631=0xE0 +{ + local tkn = *:1 R0004; + *:1 R0004 = tkn | (1 << R1115); + set_Z(tkn & (1 << R1115)); +} + +# TST1 bit#3, disp16[reg1] - 11bbb111110RRRRR|dddddddddddddddd +:tst1 op1113, s1631[R0004] is op0510=0x3E & op1415=3 & op1113 & R0004; s1631 +{ + local adr:4 = R0004 + s1631; + local tkn = *:1 adr; + set_Z(tkn & (1 << op1113)); +} + +# TST1 reg2, [reg1] - rrrrr111111RRRRR|0000000011100110 +:tst1 R0004, [R1115] is op0510=0x3F & R0004 & R1115; op1631=0xE6 +{ + local tkn = *:1 R0004; + set_Z(tkn & (1 << R1115)); +} + + +##################################################### +##### BitSearch ##### +##################################################### + + +# SCH0L reg2, reg3 - rrrrr11111100000|wwwww01101100100 +:sch0l R1115, R2731 is op0010=0x7E0 & R1115; op1626=0x364 & R2731 +{ + SearchLeft(R2731, R1115, 0); + $(CY) = (R1115 != 0xFFFFFFFF); # zero bit found + $(Z) = (R1115 == 0xFFFFFFFF); # zero bit not found +} + +# SCH0R reg2, reg3 - rrrrr11111100000|wwwww01101100000 +:sch0r R1115, R2731 is op0010=0x7E0 & R1115; op1626=0x360 & R2731 +{ + SearchRight(R2731, R1115, 0); + $(CY) = (R1115 != 0xFFFFFFFF); # zero bit found + $(Z) = (R1115 == 0xFFFFFFFF); # zero bit not found +} + +# SCH1L reg2, reg3 - rrrrr11111100000|wwwww01101100110 +:sch1l R1115, R2731 is op0010=0x7E0 & R1115; op1626=0x366 & R2731 +{ + SearchLeft(R2731, R1115, 1); + $(CY) = (R1115 != 0x0); # one bit found + $(Z) = (R1115 == 0x0); # one bit not found +} + +# SCH1R reg2, reg3 +:sch1r R1115, R2731 is op0010=0x7E0 & R1115; op1626=0x362 & R2731 +{ + SearchRight(R2731, R1115, 1); + $(CY) = (R1115 != 0x0); # one bit found + $(Z) = (R1115 == 0x0); # one bit not found +} + + +##################################################### +##### Branch ##### +##################################################### + + +#Bcond adr9 - ddddd1011dddcccc +:b^c0003 adr9 is op0710=0xB & c0003 & adr9 +{ + if (c0003) + goto adr9; +} +:br adr9 is op0710=0xB & op0003=0x5 & adr9 +{ + goto adr9; +} + +# JARL disp22, reg2 - rrrrr11110dddddd|ddddddddddddddd0 +:jarl adr22, R1115 is (op0610=0x1E & R1115) ... & adr22 +{ + R1115 = inst_next; + call adr22; +} + +# JARL disp32, reg1 - 00000010111RRRRR|ddddddddddddddd0|DDDDDDDDDDDDDDDD +:jarl adr32, R0004 is op0515=0x017 & R0004; adr32 +{ + R0004 = inst_next; + call adr32; +} + +# JMP [reg1] - 00000000011RRRRR +:jmp [R0004] is op0515=0x03 & R0004 & op0004=0x1F +{ + return [R0004]; +} + +:jmp [R0004] is op0515=0x03 & R0004 +{ + goto [R0004]; +} + +# JMP disp32[reg1] - 00000110111RRRRR|ddddddddddddddd0|DDDDDDDDDDDDDDDD +:jmp adr32i[R0004] is op0515=0x037 & R0004; adr32i +{ + local adr = adr32i + R0004; + goto [adr]; +} + +# JR disp22 - 00000111110ddddd|ddddddddddddddd0 +:jr adr22 is op0615=0x1E ... & adr22 +{ + goto adr22; +} + +# JR disp32 - 0000001011100000|ddddddddddddddd0|DDDDDDDDDDDDDDDD +:jr adr32 is op0015=0x2E0; adr32 +{ + goto adr32; +} + + +##################################################### +##### Special ##### +##################################################### + + +# CALLT imm6 - 0000001000iiiiii +:callt op0005 is op0615=0x8 & op0005 +{ + CTPC = inst_next; + CTPSW = PSW; + local adr:4 = CTBP + (op0005 << 1); + PC = CTBP + zext(*:2 adr); + call [PC]; +} + +# CAXI [reg1], reg2, reg3 - rrrrr111111RRRRR|wwwww00011101110 +:caxi [R0004], R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0xEE & R2731 +{ + local tkn = *:4 (R0004 & ~(0x3)); + local result = R1115 - tkn; + *:4 R0004 = tkn * zext(result != 0) + R2731 * zext(result == 0); + R2731 = tkn; + set_general_flags_neg(R1115, tkn); +} + +# CTRET - 0000011111100000|0000000101000100 +:ctret is op0515=0x3F; op1631=0x144 +{ + PC = CTPC; + PSW = CTPSW; + return [PC]; +} + +# DI - 0000011111100000|0000000101100000 +define pcodeop __disable_irq; +:di is op0015=0x7E0; op1631=0x160 +{ + $(ID) = 1; + __disable_irq(); +} + +# DISPOSE imm5, list12 - 0000011001iiiiiL|LLLLLLLLLLL00000 +:dispose prep0105, DispList is prep0615=0x19 & prep1620=0x0 & prep0105 & DispList +{ + sp = sp + (prep0105 << 2); + build DispList; +} + +# DISPOSE imm5, list12, [reg1] - 0000011001iiiiiL|LLLLLLLLLLLRRRRR +:dispose prep0105, DispList, [prep1620] is prep0615=0x19 & prep1620 & prep0105 & DispList +{ + sp = sp + (prep0105 << 2); + build DispList; + PC = prep1620; + return [PC]; +} + +# EI - 1000011111100000|0000000101100000 +define pcodeop __enable_irq; +:ei is op0015=0x87E0; op1631=0x160 +{ + $(ID) = 0; + __enable_irq(); +} + +# EIRET - 0000011111100000|0000000101001000 +:eiret is op0515=0x3F; op1631=0x148 +{ + PC = EIPC; + PSW = EIPSW; + return [PC]; +} + +# FERET - 0000011111100000|0000000101001010 +:feret is op0515=0x3F; op1631=0x14A +{ + PC = FEPC; + PSW = FEPSW; + return [PC]; +} + +# FETRAP vector4 - 0vvvv00001000000 +:fetrap op1114 is op0010=0x40 & op1515=0 & op1114 & op1115!=0 +{ + FEPC = inst_next; + FEPSW = PSW; + FEIC = op1114 + 0x30; # exception code 0x30..0x3F +@ifndef V850E3 + $(FECC) = op1114 + 0x30; # exception code 0x30..0x3F +@else + $(UM) = 0; +@endif + $(EP) = 1; + $(ID) = 1; + $(NP) = 1; + PC = 0x30; + goto [PC]; +} + +# HALT - 0000011111100000|0000000100100000 +define pcodeop __halt; +:halt is op0015=0x7E0; op1631=0x120 +{ + goto inst_start; +} + +@ifndef V850E3 +# LDSR reg2, regID - rrrrr111111RRRRR|0000000000100000 +:ldsr R0004, SR1115 is op0510=0x3F & SR1115 & R0004; op1631=0x20 +{ + SR1115 = R0004; +} +@endif + +# NOP - 0000000000000000 +:nop is op0015=0x0 +{ } + +# PREPARE list12, imm5 - 0000011110iiiiiL|LLLLLLLLLLL00001 +:prepare PrepList, prep0105 is prep0615=0x1E & prep0105 & prep1620=0x1 & PrepList +{ + build PrepList; + sp = sp - (prep0105 << 2); +} + +# PREPARE list12, imm5, sp - 0000011110iiiiiL|LLLLLLLLLLL00011 +:prepare PrepList, prep0105, sp is prep0615=0x1E & prep0105 & prep1620=0x3 & PrepList & sp +{ + build PrepList; + sp = sp - (prep0105 << 2); + ep = sp; +} + +# PREPARE list12, imm5, imm16 (low) - 0000011110iiiiiL|LLLLLLLLLLL01011|iiiiiiiiiiiiiiii +:prepare PrepList, prep0105, s3247 is prep0615=0x1E & prep0105 & prep1620=0xB & PrepList; s3247 +{ + build PrepList; + sp = sp - (prep0105 << 2); + ep = s3247; +} + +# PREPARE list12, imm5, imm16 (high) - 0000011110iiiiiL|LLLLLLLLLLL10011|iiiiiiiiiiiiiiii +:prepare PrepList, prep0105, s3247 is prep0615=0x1E & prep0105 & prep1620=0x13 & PrepList; s3247 +{ + build PrepList; + sp = sp - (prep0105 << 2); + ep = s3247 << 16; +} + +# PREPARE list12, imm5, imm32 - 0000011110iiiiiL|LLLLLLLLLLL11011|iiiiiiiiiiiiiiii|iiiiiiiiiiiiiiii +:prepare PrepList, prep0105, imm32 is prep0615=0x1E & prep0105 & prep1620=0x1B & PrepList; op3247; op4863 +[ imm32 = (op4863 << 16) | op3247; ] +{ + build PrepList; + sp = sp - (prep0105 << 2); + ep = imm32; +} + +# RETI - 0000011111100000|0000000101000000 +:reti is op0515=0x3F; op1631=0x140 +{ + if($(EP)!=1) + goto ; + + PC = EIPC; + PSW = EIPSW; + goto ; + + + if($(NP)!=1) + goto ; + + PC = FEPC; + PSW = FEPSW; + goto ; + + + PC = EIPC; + PSW = EIPSW; + + + return[PC]; +} + +# RIE - 0000000001000000 +:rie is op0015=0x40 +{ + FEPC = PC; + FEPSW = PSW; + $(NP) = 1; + $(EP) = 1; + $(ID) = 1; + PC = 0x30; + goto [PC]; +} + +# RIE imm5, imm4 - iiiii1111111IIII|0000000000000000 +:rie op1115, op0003 is op0410=0x7F & op1115 & op0003; op1631=0x0 +{ + FEPC = PC; + FEPSW = PSW; + $(NP) = 1; + $(EP) = 1; + $(ID) = 1; + PC = 0x30; + goto [PC]; +} + +@ifndef V850E3 +# STSR regID, reg2 - rrrrr111111RRRRR|0000000001000000 +:stsr SR0004, R1115 is op0510=0x3F & R1115 & SR0004; op1631=0x40 +{ + R1115 = SR0004; +} +@endif + +# SWITCH reg1 - 00000000010RRRRR +:switch R0004 is op0515=0x2 & R0004 +{ + local adr:4 = inst_next + (R0004 << 1); + PC = inst_next + (sext(*:2 adr) << 1); + goto [PC]; +} + +# SYNCE - 0000000000011101 +define pcodeop __synchronize; +:synce is op0015=0x1D +{ + __synchronize(); +} + +# SYNCM - 0000000000011110 +:syncm is op0015=0x1E +{ + __synchronize(); +} + +# SYNCP - 0000000000011111 +:syncp is op0015=0x1F +{ + __synchronize(); +} + +# SYSCALL vector8 - 11010111111vvvvv|00VVV00101100000 +:syscall vector8 is op0515=0x6BF & op0004; op3031=0 & op2729 & op1626=0x160 +[ vector8 = (op2729 << 5) | op0004; ] +{ + EIPC = inst_next; + EIPSW = PSW; + EIIC = vector8 + 0x8000; # exception code 0x8000..0x80FF +@ifndef V850E3 + $(EICC) = vector8 + 0x8000; # exception code 0x8000..0x80FF +@else + $(UM) = 0; +@endif + $(EP) = 1; + $(ID) = 1; + local adr:4; + either_or(adr, (vector8 <= SCCFG), SCBP + (vector8 << 2), SCBP); + PC = SCBP + (*:4 adr); + call [PC]; +} + +# TRAP imm5 - 00000111111vvvvv|0000000100000000 +:trap op0004 is op0515=0x3F & op0004; op1631=0x100 +{ + local vector5:4 = op0004; + EIPC = inst_next; + EIPSW = PSW; + EIIC = vector5 + 0x40; # exception code 0x40..0x5F +@ifndef V850E3 + $(EICC) = vector5:2 + 0x40; # exception code 0x40..0x5F +@else + $(UM) = 0; +@endif + $(EP) = 1; + $(ID) = 1; + either_or(PC, (vector5 <= 15), 0x40, 0x50); + call [PC]; +} + + +##################################################### +##### Load ##### +##################################################### + + +# LD.B disp16[reg1], reg2 - rrrrr111000RRRRR|dddddddddddddddd +:ld.b s1631[R0004], R1115 is op0510=0x38 & R0004 & R1115; s1631 +{ + local adr:4 = R0004 + s1631; + R1115 = sext(*:1 adr); +} + +# LD.B disp23[reg1], reg3 - rrrrr111100RRRRR|wwwwwddddddd0101|DDDDDDDDDDDDDDDD +:ld.b disp23[R0004], R2731 is op0515=0x3C & R0004; R2731 & op2026 & op1619=0x5; s3247 +[ disp23 = (s3247 << 7) | op2026; ] +{ + local adr:4 = R0004 + disp23; + R2731 = sext(*:1 adr); +} + +# LD.BU disp16[reg1], reg2 - rrrrr11110bRRRRR|ddddddddddddddd1 +:ld.bu disp16[R0004], R1115 is op0610=0x1E & R0004 & R1115 & op0505; op1616=0x1 & s1731 +[ disp16 = (s1731 << 1) | op0505; ] +{ + local adr:4 = R0004 + disp16; + R1115 = zext(*:1 adr); +} + +# LD.BU disp23[reg1], reg3 - 00000111101RRRRR|wwwwwddddddd0101|DDDDDDDDDDDDDDDD +:ld.bu disp23[R0004], R2731 is op0515=0x3D & R0004; R2731 & op2026 & op1619=0x5; s3247 +[ disp23 = (s3247 << 7) | op2026; ] +{ + local adr:4 = R0004 + disp23; + R2731 = zext(*:1 adr); +} + +# LD.H disp16[reg1], reg2 - rrrrr111001RRRRR|ddddddddddddddd0 +:ld.h s1631[R0004], R1115 is op0510=0x39 & R0004 & R1115; s1631 & op1616=0x0 +{ + local adr:4 = R0004 + s1631; + R1115 = sext(*:2 adr); +} + +# LD.H disp23[reg1], reg3 - 00000111100RRRRR|wwwwwdddddd00111|DDDDDDDDDDDDDDDD +:ld.h disp23[R0004], R2731 is op0515=0x3C & R0004; R2731 & op2126 & op1620=0x7; s3247 +[ disp23 = (s3247 << 7) | (op2126 << 1); ] +{ + local adr:4 = R0004 + disp23; + R2731 = sext(*:2 adr); +} + +# LD.HU disp16[reg1], reg2 - rrrrr111111RRRRR|ddddddddddddddd1 +:ld.hu disp16[R0004], R1115 is op0510=0x3F & R0004 & R1115; op1616=0x1 & s1731 +[ disp16 = s1731 << 1; ] +{ + local adr:4 = R0004 + disp16; + R1115 = zext(*:2 adr); +} + +# LD.HU disp23[reg1], reg3 - 00000111101RRRRR|wwwwwdddddd00111|DDDDDDDDDDDDDDDD +:ld.hu disp23[R0004], R2731 is op0515=0x3D & R0004; R2731 & op2026 & op1619=0x7; s3247 +[ disp23 = (s3247 << 7) | op2026; ] +{ + local adr:4 = R0004 + disp23; + R2731 = zext(*:2 adr); +} + +# LD.W disp16[reg1], reg2 - rrrrr111001RRRRR|ddddddddddddddd1 +:ld.w disp16[R0004], R1115 is op0510=0x39 & R0004 & R1115; s1731 & op1616=0x1 +[ disp16 = s1731 * 2; ] +{ + local adr:4 = R0004 + disp16; + R1115 = *:4 adr; +} + +# LD.W disp23[reg1], reg3 - 00000111100RRRRR|wwwwwdddddd01001|DDDDDDDDDDDDDDDD +:ld.w disp23[R0004], R2731 is op0515=0x03C & R0004; R2731 & op2126 & op1620=0x9; s3247 +[ disp23 = (s3247 << 7) | (op2126 << 1); ] +{ + local adr:4 = R0004 + disp23; + R2731 = *:4 adr; +} + +# SLD.B disp7[ep], reg2 - rrrrr0110ddddddd +:sld.b op0006[ep], R1115 is op0710=0x06 & op0006 & R1115 & ep +{ + local adr:4 = ep + op0006; + R1115 = sext(*:1 adr); +} + +# SLD.BU disp4[ep], reg2 - rrrrr0000110dddd +:sld.bu op0003[ep], R1115 is op0410=0x06 & R1115 & op0003 & ep +{ + local adr:4 = ep + op0003; + R1115 = zext(*:1 adr); +} + +# SLD.H disp8[ep], reg2 - rrrrr1000ddddddd +:sld.h disp8[ep], R1115 is op0710=0x08 & op0006 & R1115 & ep +[ disp8 = op0006 * 2; ] +{ + local adr:4 = ep + disp8; + R1115 = sext(*:2 adr); +} + +# SLD.HU disp5[ep], reg2 - rrrrr0000111dddd +:sld.hu disp5[ep], R1115 is op0410=0x07 & R1115 & op0003 & ep +[ disp5 = op0003 * 2; ] +{ + local adr:4 = ep + disp5; + R1115 = zext(*:2 adr); +} + +# SLD.W disp8[ep], reg2 - rrrrr1010dddddd0 +:sld.w disp8[ep], R1115 is op0710=0x0A & op0000=0x0 & op0106 & R1115 & ep +[ disp8 = op0106 * 4; ] +{ + local adr:4 = ep + disp8; + R1115 = *:4 adr; +} + + +##################################################### +##### Store ##### +##################################################### + + +# SST.B reg2, disp7[ep] - rrrrr0111ddddddd +:sst.b R1115, op0006[ep] is op0710=0x07 & op0006 & R1115 & ep +{ + local adr:4 = ep + op0006; + local tmp:4 = R1115; + *:1 adr = tmp:1; +} + +# SST.H reg2, disp8[ep] - rrrrr1001ddddddd +:sst.h R1115, disp8[ep] is op0710=0x09 & op0006 & R1115 & ep +[ disp8 = op0006 * 2; ] +{ + local adr:4 = ep + disp8; + local tmp:4 = R1115; + *:2 adr = tmp:2; +} + +# SST.W reg2, disp8[ep] - rrrrr1010dddddd1 +:sst.w R1115, disp8[ep] is op0710=0x0A & op0000=0x1 & op0106 & R1115 & ep +[ disp8 = op0106 * 4; ] +{ + local adr:4 = ep + disp8; + local tmp:4 = R1115; + *:4 adr = tmp; +} + +# ST.B reg2, disp16[reg1] - rrrrr111010RRRRR|dddddddddddddddd +:st.b R1115, s1631[R0004] is op0510=0x3A & R0004 & R1115; s1631 +{ + local adr:4 = R0004 + s1631; + local tmp:4 = R1115; + *:1 adr = tmp:1; +} + +# ST.B reg3, disp23[reg1] - 00000111100RRRRR|dddddddddddddddd +:st.b R2731, disp23[R0004] is op0515=0x3C & R0004; R2731 & op2026 & op1619=0xD; s3247 +[ disp23 = (s3247 << 7) | op2026; ] +{ + local adr:4 = R0004 + disp23; + local tmp:4 = R2731; + *:1 adr = tmp:1; +} + +# ST.H reg2, disp16[reg1] - rrrrr111011RRRRR|ddddddddddddddd0 +:st.h R1115, s1631[R0004] is op0510=0x3B & R0004 & R1115; s1631 & op1616=0x0 +{ + local adr:4 = R0004 + s1631; + local tmp:4 = R1115; + *:2 adr = tmp:2; +} + +# ST.H reg3, disp23[reg1] - 00000111101RRRRR|wwwwwdddddd01101|DDDDDDDDDDDDDDDD +:st.h R2731, disp23[R0004] is op0515=0x3D & R0004; R2731 & op2126 & op1620=0xD; s3247 +[ disp23 = (s3247 << 7) | (op2126 << 1); ] +{ + local adr:4 = R0004 + disp23; + local tmp:4 = R2731; + *:2 adr = tmp:2; +} + +# ST.W reg2, disp16[reg1] - rrrrr111011RRRRR|ddddddddddddddd1 +:st.w R1115, disp16[R0004] is op0510=0x3B & R0004 & R1115; s1731 & op1616=0x1 +[ disp16 = s1731 * 2; ] +{ + local adr:4 = R0004 + disp16; + local tmp:4 = R1115; + *:4 adr = tmp; +} + +# ST.W reg3, disp23[reg1] - 00000111100RRRRR|wwwwwdddddd01111|DDDDDDDDDDDDDDDD +:st.w R2731, disp23[R0004] is op0515=0x3C & R0004; R2731 & op2126 & op1620=0xF; s3247 +[ disp23 = (s3247 << 7) | (op2126 << 1); ] +{ + local adr:4 = R0004 + disp23; + local tmp:4 = R2731; + *:2 adr = tmp:2; +} + + +##################################################### +##### DataManipulation ##### +##################################################### + + +# BSH reg2, reg3 - rrrrr11111100000|wwwww01101000010 +:bsh R1115, R2731 is op0010=0x7E0 & R1115; op1626=0x342 & R2731 +{ + local x1 = R1115[0,8]; + local x2 = R1115[8,8]; + local x3 = R1115[16,8]; + local x4 = R1115[24,8]; + R2731 = zext(x3 << 24) | zext(x4 << 16) | zext(x1 << 8) | zext(x2); + set_S(R2731); + $(OV) = 0; + $(Z) = (x1 == 0) && (x2 == 0); + $(CY) = (x1 == 0) || (x2 == 0); +} + +# BSW reg2, reg3 - rrrrr11111100000|wwwww01101000000 +:bsw R1115, R2731 is op0010=0x7E0 & R1115; op1626=0x340 & R2731 +{ + local x1 = R1115[0,8]; + local x2 = R1115[8,8]; + local x3 = R1115[16,8]; + local x4 = R1115[24,8]; + R2731 = zext(x1 << 24) | zext(x2 << 16) | zext(x3 << 8) | zext(x4); + set_OV0_S_Z(R2731); + $(CY) = (x1 == 0) || (x2 == 0) || (x3 == 0) || (x4 == 0); +} + +# CMOV cccc, reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww011001cccc0 +:cmov^c1720 R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op2126=0x19 & op1616=0 & c1720 & R2731 +{ + local result:4 = zext(c1720); + R2731 = R0004 * zext(result != 0) + R1115 * zext(result == 0); +} + +# CMOV cccc, imm5, reg2, reg3 - rrrrr111111iiiii|wwwww011000cccc0 +:cmov^c1720 s0004, R1115, R2731 is op0510=0x3F & s0004 & R1115; op2126=0x18 & op1616=0 & c1720 & R2731 +{ + local result:4 = zext(c1720); + R2731 = s0004 * zext(result != 0) + R1115 * zext(result == 0); +} + +# HSH reg2, reg3 - rrrrr11111100000|wwwww01101000110 +:hsh R1115, R2731 is op0010=0x7E0 & R1115; op1626=0x346 & R2731 +{ + R2731 = R1115; + set_S(R2731); + $(OV) = 0; + $(Z) = (R2731:2 == 0); + $(CY) = $(Z); +} + +# HSW reg2, reg3 - rrrrr11111100000|wwwww01101000100 +:hsw R1115, R2731 is op0010=0x7E0 & R1115; op1626=0x344 & R2731 +{ + local x1 = R1115:2; + local x2 = R1115[16,16]; + R2731 = zext(x1 << 16) | zext(x2); + set_OV0_S_Z(R2731); + $(CY) = (x1 == 0) || (x2 == 0); +} + +# SAR reg1, reg2 - rrrrr111111RRRRR|0000000010100000 +:sar R0004, R1115 is op0510=0x3F & R0004 & R1115; op1631=0xA0 +{ + shift_right_arith(R1115, R1115, R0004); +} + +# SAR imm5, reg2 - rrrrr010101iiiii +:sar op0004, R1115 is op0510=0x15 & op0004 & R1115 +{ + shift_right_arith(R1115, R1115, op0004:5); +} + +# SAR reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww00010100010 +:sar R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0xA2 & R2731 +{ + shift_right_arith(R2731, R1115, R0004); +} + +# SASF cccc, reg2 - rrrrr1111110cccc|0000001000000000 +:sasf^c0003 R1115 is op0410=0x7E & c0003 & R1115; op1631=0x0200 +{ + R1115 = (R1115 << 1) | zext(c0003); +} + +# SETF cond, reg2 - rrrrr1111110cccc|0000000000000000 +:setf^c0003 R1115 is op0410=0x7E & c0003 & R1115; op1631=0x0 +{ + R1115 = zext(c0003); +} + +# SHL reg1, reg2 - rrrrr111111RRRRR|0000000011000000 +:shl R0004, R1115 is op0510=0x3F & R0004 & R1115; op1631=0xC0 +{ + shift_left_logic(R1115, R1115, R0004); +} + +# SHL imm5, reg2 - rrrrr010110iiiii +:shl op0004, R1115 is op0510=0x16 & op0004 & R1115 +{ + shift_left_logic(R1115, R1115, op0004:5); +} + +# SHL reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww00011000010 +:shl R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0xC2 & R2731 +{ + shift_left_logic(R2731, R1115, R0004); +} + +# SHR reg1, reg2 - rrrrr111111RRRRR|0000000010000000 +:shr R0004, R1115 is op0510=0x3F & R0004 & R1115; op1631=0x80 +{ + shift_right_logic(R1115, R1115, R0004); +} + +# SHR imm5, reg2 - rrrrr010100iiiii +:shr op0004, R1115 is op0510=0x14 & op0004 & R1115 +{ + shift_right_logic(R1115, R1115, op0004:5); +} + +# SHR reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww00010000010 +:shr R0004, R1115, R2731 is op0510=0x3F & R0004 & R1115; op1626=0x82 & R2731 +{ + shift_right_logic(R2731, R1115, R0004); +} + +# SXB reg1 - 00000000101RRRRR +:sxb R0004 is op0515=0x05 & R0004 +{ + R0004 = sext(R0004:1); +} + +# SXH reg1 - 00000000111RRRRR +:sxh R0004 is op0515=0x07 & R0004 +{ + R0004 = sext(R0004:2); +} + +# ZXB reg1 - 00000000100RRRRR +:zxb R0004 is op0515=0x004 & R0004 +{ + R0004 = zext(R0004:1); +} + +# ZXH reg1 - 00000000110RRRRR +:zxh R0004 is op0515=0x006 & R0004 +{ + R0004 = zext(R0004:2); +} + + +##################################################### +##### Float ##### +##################################################### + + +# ABSF.D reg2, reg3 - rrrr011111100000|wwww010001011000 +:absf.d R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b00000; R2731x2 & op2126=0b100010 & op1620=0b11000 +{ + R2731x2 = abs(R1115x2); +} + +# ABSF.S reg2, reg3 - rrrrr11111100000|wwwww10001001000 +:absf.s R1115, R2731 is R1115 & op0510=0x3F & op0004=0b00000; R2731 & op2126=0b100010 & op1620=0b01000 +{ + R2731 = abs(R1115); +} + +# ADDF.D reg1, reg2, reg3 - rrrr0111111RRRR0|wwww010001110000 +:addf.d R0004x2, R1115x2, R2731x2 is R1115x2 & op0510=0x3F & R0004x2 ; R2731x2 & op2126=0b100011 & op1620=0b10000 +{ + R2731x2 = R1115x2 f+ R0004x2; +} + +# ADDF.S reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww10001100000 +:addf.s R0004, R1115, R2731 is R1115 & op0510=0x3F & R0004 ; R2731 & op2126=0b100011 & op1620=0b00000 +{ + R2731 = R1115 f+ R0004; +} + +# CEILF.DL reg2, reg3 - rrrr011111100010|wwww010001010100 +:ceilf.dl R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b00010; R2731x2 & op2126=0b100010 & op1620=0b10100 +{ + local var:8 = ceil(float2float(R1115x2)); + R2731x2 = trunc(var); +} + +# CEILF.DUL reg2, reg3 - rrrr011111110010|wwww010001010100 +:ceilf.dul R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b10010; R2731x2 & op2126=0b100010 & op1620=0b10100 +{ + local var:8 = ceil(float2float(R1115x2)); + R2731x2 = trunc(var); +} + +# CEILF.DUW reg2, reg3 - rrrrr11111110010|wwwww10001010000 +:ceilf.duw R1115x2, R2731 is R1115x2 & op0510=0x3F & op0004=0b10010; R2731 & op2126=0b100010 & op1620=0b10000 +{ + R2731 = trunc(ceil(R1115x2)); +} + +# CEILF.DW reg2, reg3 - rrrrr11111100010|wwwww10001010000 +:ceilf.dw R1115x2, R2731 is R1115x2 & op0510=0x3F & op0004=0b00010; R2731 & op2126=0b100010 & op1620=0b10000 +{ + R2731 = trunc(ceil(R1115x2)); +} + +# CEILF.SL reg2, reg3 - rrrrr11111100010|wwww010001000100 +:ceilf.sl R1115, R2731x2 is R1115 & op0510=0x3F & op0004=0b00010; R2731x2 & op2126=0b100010 & op1620=0b00100 +{ + local var:8 = ceil(float2float(R1115)); + R2731x2 = trunc(var); +} + +# CEILF.SUL reg2, reg3 - rrrrr11111110010|wwwww10001000100 +:ceilf.sul R1115, R2731x2 is R1115 & op0510=0x3F & op0004=0b10010; R2731x2 & op2126=0b100010 & op1620=0b00100 +{ + local var:8 = ceil(float2float(R1115)); + R2731x2 = trunc(var); +} + +# CEILF.SUW reg2, reg3 - rrrrr11111110010|wwwww10001000000 +:ceilf.sul R1115, R2731 is R1115 & op0510=0x3F & op0004=0b10010; R2731 & op2126=0b100010 & op1620=0b00000 +{ + R2731 = trunc(ceil(R1115)); +} + +# CEILF.SW reg2, reg3 - rrrrr11111100010|wwwww10001000000 +:ceilf.sw R1115, R2731 is R1115 & op0510=0x3F & op0004=0b00010; R2731 & op2126=0b100010 & op1620=0b00000 +{ + R2731 = trunc(ceil(R1115)); +} + +# CMOVF.D fcbit, reg1, reg2, reg3 - rrrr0111111RRRR0|wwww01000001fff0 +:cmovf.d fcbit1719, R1115x2, R0004x2, R2731x2 is R1115x2 & op0510=0x3F & R0004x2; R2731x2 & op2126=0b100000 & op2020=1 & fcbit1719 & op1616=0 +{ + #CC0 = Bit 24 + local bit = (FPSR >> (fcbit1719 + 24:1)) & 0x1; + either_or1(R2731x2, bit, R0004x2, R1115x2); +} + +# CMOVF.S fcbit, reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww1000000fff0 +:cmovf.s fcbit1719, R1115, R0004, R2731 is R1115 & op0510=0x3F & R0004; R2731 & op2126=0b100000 & op2020=0 & fcbit1719 & op1616=0 +{ + local bit = (FPSR >> (fcbit1719 + 24:1)) & 0x1; + either_or1(R2731, bit, R0004, R1115); +} + +# CMPF.D fcond, reg2, reg1, fcbit - rrrr0111111RRRRR|0FFFF1000011fff0 +:cmpf.d fcond2730, R1115x2, R0004x2, fcbit1719 is R1115x2 & op0510=0x3F & R0004x2; op3131=0 & fcond2730 & op2126=0b100001 & op2020=1 & fcbit1719 & op1616=0 +{ + #0 = Unordered + #1 = Equal to + #2 = Less than + #3 = Exeption + #bits = ex le eq un + + local bit:4 = 0; + compare_float(bit, fcond2730:1, R0004x2, R1115x2); + + local pos:4 = bit << (fcbit1719 + 24); #find position of the calculated bit + local mask:4 = 1 << (fcbit1719 + 24); #create mask to clean old bit in FPSR register + FPSR = (FPSR & ~mask) | pos; #set the new bit at the right position +} + +# CMPF.S fcond, reg2, reg1, fcbit - rrrrr111111RRRRR|0FFFF1000010fff0 +:cmpf.s fcond2730, R1115, R0004, fcbit1719 is R1115 & op0510=0x3F & R0004; op3131=0 & fcond2730 & op2126=0b100001 & op2020=0 & fcbit1719 & op1616=0 +{ + local bit:4 = 0; + compare_float(bit, fcond2730:1, R0004, R1115); + + local pos:4 = bit << (fcbit1719 + 24); #find position of the calculated bit + local mask:4 = 1 << (fcbit1719 + 24); #create mask to clean old bit in FPSR register + FPSR = (FPSR & ~mask) | pos; #set the new bit at the right position +} + +# CVTF.DL reg2, reg3 - rrrr011111100100|wwww010001010100 +:cvtf.dl R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b00100; R2731x2 & op2126=0b100010 & op1620=0b10100 +{ + R2731x2 = int2float(R1115x2); +} + +# CVTF.DS reg2, reg3 - rrrr011111100011|wwww010001010010 +:cvtf.ds R1115x2, R2731 is R1115x2 & op0510=0x3F & op0004=0b00011; R2731 & op2126=0b100010 & op1620=0b10010 +{ + R2731 = float2float(R1115x2); +} + +# CVTF.DUL reg2, reg3 - rrrr011111110100|wwww010001010100 +:cvtf.dul R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b10100; R2731x2 & op2126=0b100010 & op1620=0b10100 +{ + R2731x2 = trunc(R1115x2); +} + +# CVTF.DUW reg2, reg3 - rrrrr11111110100|wwwww10001010000 +:cvtf.duw R1115x2, R2731 is R1115x2 & op0510=0x3F & op0004=0b10100; R2731 & op2126=0b100010 & op1620=0b10000 +{ + R2731 = trunc(R1115x2); +} + +# CVTF.DW reg2, reg3 - rrrrr11111100100|wwwww10001010000 +:cvtf.sw R1115x2, R2731 is R1115x2 & op0510=0x3F & op0004=0b00100; R2731 & op2126=0b100010 & op1620=0b10000 +{ + R2731 = trunc(R1115x2); +} + +# CVTF.LD reg2, reg3 - rrrr011111100001|wwww010001010010 +:cvtf.ls R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b00001; R2731x2 & op2126=0b100010 & op1620=0b10010 +{ + R2731x2 = int2float(R1115x2); +} + +# CVTF.LS reg2, reg3 - rrrr011111100001|wwwww10001000010 +:cvtf.ls R1115x2, R2731 is R1115x2 & op0510=0x3F & op0004=0b00001; R2731 & op2126=0b100010 & op1620=0b00010 +{ + R2731 = int2float(R1115x2); +} + +# CVTF.SD reg2, reg3 - rrrrr11111100010|wwww010001010010 +:cvtf.sd R1115, R2731x2 is R1115 & op0510=0x3F & op0004=0b00010; R2731x2 & op2126=0b100010 & op1620=0b10010 +{ + R2731x2 = float2float(R1115); +} + +# CVTF.SL reg2, reg3 - rrrrr11111100100|wwwww10001000100 +:cvtf.sl R1115, R2731x2 is R1115 & op0510=0x3F & op0004=0b00100; R2731x2 & op2126=0b100010 & op1620=0b00100 +{ + R2731x2 = trunc(R1115); +} + +# CVTF.SUL reg2, reg3 - rrrrr11111110100|wwwww10001000100 +:cvtf.sul R1115, R2731x2 is R1115 & op0510=0x3F & op0004=0b10100; R2731x2 & op2126=0b100010 & op1620=0b00100 +{ + R2731x2 = trunc(R1115); +} + +# CVTF.SUW reg2, reg3 - rrrrr11111110100|wwwww10001000000 +:cvtf.suw R1115, R2731 is R1115 & op0510=0x3F & op0004=0b10100; R2731 & op2126=0b100010 & op1620=0b00000 +{ + R2731 = trunc(R1115); +} + +# CVTF.SW reg2, reg3 - rrrrr11111100100|wwwww10001000000 +:cvtf.sw R1115, R2731 is R1115 & op0510=0x3F & op0004=0b00100; R2731 & op2126=0b100010 & op1620=0b00000 +{ + R2731 = trunc(R1115); +} + +# CVTF.ULD reg2, reg3 - rrrr011111100001|wwww010001010010 +:cvtf.uls R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b10001; R2731x2 & op2126=0b100010 & op1620=0b10010 +{ + R2731x2 = int2float(R1115x2); +} + +# CVTF.ULS reg2, reg3 - rrrr011111110001|wwwww10001000010 +:cvtf.uls R1115x2, R2731 is R1115x2 & op0510=0x3F & op0004=0b10001; R2731 & op2126=0b100010 & op1620=0b00010 +{ + R2731 = int2float(R1115x2); +} + +# CVTF.UWD reg2, reg3 - rrrrr11111110000|wwwww10001010010 +:cvtf.uwd R1115, R2731x2 is R1115 & op0510=0x3F & op0004=0b10000; R2731x2 & op2126=0b100010 & op1620=0b10010 +{ + R2731x2 = int2float(R1115); +} + +# CVTF.UWS reg2, reg3 - rrrrr11111110000|wwwww10001000010 +:cvtf.uws R1115, R2731 is R1115 & op0510=0x3F & op0004=0b10000; R2731 & op2126=0b100010 & op1620=0b00010 +{ + R2731 = int2float(R1115); +} + +# CVTF.WD reg2, reg3 - rrrrr11111100000|wwwww10001010010 +:cvtf.wd R1115, R2731x2 is R1115 & op0510=0x3F & op0004=0b00000; R2731x2 & op2126=0b100010 & op1620=0b10010 +{ + R2731x2 = int2float(R1115); +} + +# CVTF.WS reg2, reg3 - rrrrr11111100000|wwwww10001000010 +:cvtf.ws R1115, R2731 is R1115 & op0510=0x3F & op0004=0b00000; R2731 & op2126=0b100010 & op1620=0b00010 +{ + R2731 = int2float(R1115); +} + +# DIVF.D reg1, reg2, reg3 - rrrr0111111RRRR0|wwww010001111110 +:divf.s R0004x2, R1115x2, R2731x2 is R0004x2 & op0510=0x3F & R1115x2; R2731x2 & op2126=0b100011 & op1620=0b11110 +{ + R2731x2 = R1115x2 f/ R0004x2; +} + +# DIVF.S reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww10001101110 +:divf.s R0004, R1115, R2731 is R0004 & op0510=0x3F & R1115; R2731 & op2126=0b100011 & op1620=0b01110 +{ + R2731 = R1115 f/ R0004; +} + +# FLOORF.DL reg2, reg3 - rrrr011111100011|wwww010001010100 +:floorf.dl R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b00011; R2731x2 & op2126=0b100010 & op1620=0b10100 +{ + local var:8 = floor(float2float(R1115x2)); + R2731x2 = trunc(var); +} + +# FLOORF.DUL reg2, reg3 - rrrr011111110011|wwww010001010100 +:floorf.dul R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b10011; R2731x2 & op2126=0b100010 & op1620=0b10100 +{ + local var:8 = floor(float2float(R1115x2)); + R2731x2 = trunc(var); +} + +# FLOORF.DUW reg2, reg3 - rrrrr11111110011|wwwww10001010000 +:floorf.duw R1115x2, R2731 is R1115x2 & op0510=0x3F & op0004=0b10011; R2731 & op2126=0b100010 & op1620=0b10000 +{ + R2731 = trunc(floor(R1115x2)); +} + +# FLOORF.DW reg2, reg3 - rrrrr11111100011|wwwww10001010000 +:floorf.dw R1115x2, R2731 is R1115x2 & op0510=0x3F & op0004=0b00011; R2731 & op2126=0b100010 & op1620=0b10000 +{ + R2731 = trunc(floor(R1115x2)); +} + +# FLOORF.SL reg2, reg3 - rrrrr11111100011|wwww010001000100 +:floorf.sl R1115, R2731x2 is R1115 & op0510=0x3F & op0004=0b00011; R2731x2 & op2126=0b100010 & op1620=0b00100 +{ + local var:8 = floor(float2float(R1115)); + R2731x2 = trunc(var); +} + +# FLOORF.SUL reg2, reg3 - rrrrr11111110011|wwwww10001000100 +:floorf.sul R1115, R2731x2 is R1115 & op0510=0x3F & op0004=0b10011; R2731x2 & op2126=0b100010 & op1620=0b00100 +{ + local var:8 = floor(float2float(R1115)); + R2731x2 = trunc(var); +} + +# FLOORF.SUW reg2, reg3 - rrrrr11111110011|wwwww10001000000 +:floorf.suw R1115, R2731 is R1115 & op0510=0x3F & op0004=0b10011; R2731 & op2126=0b100010 & op1620=0b00000 +{ + R2731 = trunc(floor(R1115)); +} + +# FLOORF.SW reg2, reg3 - rrrrr11111100011|wwwww10001000000 +:floorf.suw R1115, R2731 is R1115 & op0510=0x3F & op0004=0b00011; R2731 & op2126=0b100010 & op1620=0b00000 +{ + R2731 = trunc(floor(R1115)); +} + +# FMAF.S reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww10011100000 +:fmaf.s R0004, R1115, R2731 is R0004 & op0510=0x3F & R1115; R2731 & op2126=0b100111 & op1620=0b00000 +{ + R2731 = (R1115 f* R0004) f+ R2731; +} + +# FMSF.S reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww10011100010 +:fmsf.s R0004, R1115, R2731 is R0004 & op0510=0x3F & R1115; R2731 & op2126=0b100111 & op1620=0b00010 +{ + R2731 = (R1115 f* R0004) f- R2731; +} + +# FNMAF.S reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww10011100100 +:fnmaf.s R0004, R1115, R2731 is R0004 & op0510=0x3F & R1115; R2731 & op2126=0b100111 & op1620=0b00100 +{ + R2731 = f- ((R1115 f* R0004) f+ R2731); +} + +# FNMSF.S reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww10011100110 +:fnmfs.s R0004, R1115, R2731 is R0004 & op0510=0x3F & R1115; R2731 & op2126=0b100111 & op1620=0b00110 +{ + R2731 = f- ((R1115 f* R0004) f- R2731); +} + +# MADDF.S reg1, reg2, reg3, reg4 - rrrrr111111RRRRR|wwwww101W00WWWW0 +:maddf.s R0004, R1115, R2731, reg4 is R0004 & op0510=0x3F & R1115; R2731 & op2426=0b101 & op2122=0b00 & op1616=0 & reg4 +{ + reg4 = (R1115 f* R0004) f+ R2731; +} + +# MAXF.D reg1, reg2, reg3 - rrrr0111111RRRR0|wwww010001111000 +:maxf.d R0004x2, R1115x2, R2731x2 is R0004x2 & op0510=0x3F & R1115x2; R2731x2 & op2126=0b100011 & op1620=0b11000 +{ + local bigger:1 = R1115x2 f> R0004x2; + either_or(R2731x2, bigger, R1115x2, R0004x2); +} + +# MAXF.S reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww10001101000 +:maxf.s R0004, R1115, R2731 is R0004 & op0510=0x3F & R1115; R2731 & op2126=0b100011 & op1620=0b01000 +{ + local bigger:1 = R1115 f> R0004; + either_or(R2731, bigger, R1115, R0004); +} + +# MINF.D reg1, reg2, reg3 - rrrr0111111RRRR0|wwww010001111010 +:minf.d R0004x2, R1115x2, R2731x2 is R0004x2 & op0510=0x3F & R1115x2; R2731x2 & op2126=0b100011 & op1620=0b11010 +{ + local bigger:1 = R1115x2 f< R0004x2; + either_or(R2731x2, bigger, R1115x2, R0004x2); +} + +# MINF.S reg1, reg2, reg3 - rrrr0111111RRRRR|wwwww10001101010 +:minf.s R0004, R1115, R2731 is R0004 & op0510=0x3F & R1115; R2731 & op2126=0b100011 & op1620=0b01010 +{ + local bigger:1 = R1115 f< R0004; + either_or(R2731, bigger, R1115, R0004); +} + +# MSUBF.S reg1, reg2, reg3, reg4 - rrrrr111111RRRRR|wwwww101W01WWWW0 +:msubf.s R0004, R1115, R2731, reg4 is R0004 & op0510=0x3F & R1115; R2731 & op2426=0b101 & op2122=0b01 & op1616=0 & reg4 +{ + reg4 = (R1115 f* R0004) f- R2731; +} + +# MULF.D reg1, reg2, reg3 - rrrr0111111RRRR0|wwww010001110100 +:mulf.d R0004x2, R1115x2, R2731x2 is R0004x2 & op0510=0x3F & R1115x2; R2731x2 & op2126=0b100011 & op1620=0b10100 +{ + R2731x2 = R1115x2 f* R0004x2; +} + +# MULF.S reg1, reg2, reg3 - rrrr0111111RRRRR|wwwww10001100100 +:mulf.s R0004, R1115, R2731 is R0004 & op0510=0x3F & R1115; R2731 & op2126=0b100011 & op1620=0b00100 +{ + R2731 = R1115 f* R0004; +} + +# NEGF.D reg2, reg3 - rrrr011111100001|wwww010001011000 +:negf.d R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b00001; R2731x2 & op2126=0b100010 & op1620=0b11000 +{ + R2731x2 = f- R1115x2; +} + +# NEGF.S reg2, reg3 - rrrrr11111100001|wwwww10001001000 +:negf.s R1115, R2731 is R1115 & op0510=0x3F & op0004=0b00001; R2731 & op2126=0b100010 & op1620=0b01000 +{ + R2731 = f- R1115; +} + +# NMADDF.S reg1, reg2, reg3, reg4 - rrrrr111111RRRRR|wwwww101W10WWWW0 +:nmaddf.s R0004, R1115, R2731, reg4 is R0004 & op0510=0x3F & R1115; R2731 & op2426=0b101 & op2122=0b10 & op1616=0 & reg4 +{ + reg4 = f-((R1115 f* R0004) f+ R2731); +} + +# NMSUBF.S reg1, reg2, reg3, reg4 - rrrrr111111RRRRR|wwwww101W11WWWW0 +:nmsubf.s R0004, R1115, R2731, reg4 is R0004 & op0510=0x3F & R1115; R2731 & op2426=0b101 & op2122=0b11 & op1616=0 & reg4 +{ + reg4 = f-((R1115 f* R0004) f- R2731); +} + +# RECIPF.D reg2, reg3 - rrrr011111100001|wwww010001011110 +:recipf.d R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b00001; R2731x2 & op2126=0b100010 & op1620=0b11110 +{ + R2731x2 = 1 f/ R1115x2; +} + +# RECIPF.S reg2, reg3 - rrrrr11111100001|wwwww10001001110 +:recipf.s R1115, R2731 is R1115 & op0510=0x3F & op0004=0b00001; R2731 & op2126=0b100010 & op1620=0b01110 +{ + R2731 = 1 f/ R1115; +} + +# RSQRTF.D reg2, reg3 - rrrr011111100010|wwwww10001011110 +:rsqrtf.d R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b00010; R2731x2 & op2126=0b100010 & op1620=0b11110 +{ + R2731x2 = 1 f/ sqrt(R1115x2); +} + +# RSQRTF.S reg2, reg3 - rrrrr11111100010|wwwww10001001110 +:rsqrtf.s R1115, R2731 is R1115 & op0510=0x3F & op0004=0b00010; R2731 & op2126=0b100010 & op1620=0b01110 +{ + R2731 = 1 f/ sqrt(R1115); +} + +# SQRTF.D reg2, reg3 - rrrr011111100000|wwww010001011110 +:sqrtf.d R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b00000; R2731x2 & op2126=0b100010 & op1620=0b11110 +{ + R2731x2 = sqrt(R1115x2); +} + +# SQRTF.S reg2, reg3 - rrrrr11111100000|wwwww10001001110 +:sqrtf.s R1115, R2731 is R1115 & op0510=0x3F & op0004=0b00000; R2731 & op2126=0b100010 & op1620=0b01110 +{ + R2731 = sqrt(R1115); +} + +# SUBF.D reg1, reg2, reg3 - rrrr0111111RRRR0|wwww010001110010 +:subf.d R0004x2, R1115x2, R2731x2 is R0004x2 & op0510=0x3F & R1115x2; R2731x2 & op2126=0b100011 & op1620=0b10010 +{ + R2731x2 = R1115x2 f- R0004x2; +} + +# SUBF.S reg1, reg2, reg3 - rrrrr111111RRRRR|wwwww10001100010 +:subf.s R0004, R1115, R2731 is R0004 & op0510=0x3F & R1115; R2731 & op2126=0b100011 & op1620=0b00010 +{ + R2731 = R1115 f- R0004; +} + +# TRFSR fcbit - 0000011111100000|000001000000fff0 +:trfsr fcbit1719 is op1115=0 & op0510=0x3F & op0004=0; op2731=0 & op2126=0b100000 & op2020=0 & fcbit1719 & op1616=0 +{ + local var:4 = FPSR & (1 << (fcbit1719 + 24)); + $(Z) = (var != 0); +} + +# TRNCF.DL reg2, reg3 - rrrr011111100001|wwww010001010100 +:trncf.dl R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b00001; R2731x2 & op2126=0b100010 & op1620=0b10100 +{ + R2731x2 = trunc(R1115x2); +} + +# TRNCF.DUL reg2, reg3 - rrrr011111110001|wwww010001010100 +:trncf.dul R1115x2, R2731x2 is R1115x2 & op0510=0x3F & op0004=0b10001; R2731x2 & op2126=0b100010 & op1620=0b10100 +{ + R2731x2 = trunc(R1115x2); +} + +# TRNCF.DUW reg2, reg3 - rrrrr11111110001|wwwww10001010000 +:trncf.duw R1115x2, R2731 is R1115x2 & op0510=0x3F & op0004=0b10001; R2731 & op2126=0b100010 & op1620=0b10000 +{ + R2731 = trunc(R1115x2); +} + +# TRNCF.DW reg2, reg3 - rrrrr11111100001|wwwww10001010000 +:trncf.dw R1115x2, R2731 is R1115x2 & op0510=0x3F & op0004=0b00001; R2731 & op2126=0b100010 & op1620=0b10000 +{ + R2731 = trunc(R1115x2); +} + +# TRNCF.SL reg2, reg3 - rrrrr11111100001|wwww010001000100 +:trncf.sl R1115, R2731x2 is R1115 & op0510=0x3F & op0004=0b00001; R2731x2 & op2126=0b100010 & op1620=0b00100 +{ + R2731x2 = trunc(R1115); +} + +# TRNCF.SUL reg2, reg3 - rrrrr11111110001|wwww010001000100 +:trncf.sul R1115, R2731x2 is R1115 & op0510=0x3F & op0004=0b10001; R2731x2 & op2126=0b100010 & op1620=0b00100 +{ + R2731x2 = trunc(R1115); +} + +# TRNCF.SUW reg2, reg3 - rrrrr11111110001|wwwww10001000000 +:trncf.suw R1115, R2731 is R1115 & op0510=0x3F & op0004=0b10001; R2731 & op2126=0b100010 & op1620=0b00000 +{ + R2731 = trunc(R1115); +} + +# TRNCF.SW reg2, reg3 - rrrrr11111100001|wwwww10001000000 +:trncf.sw R1115, R2731 is R1115 & op0510=0x3F & op0004=0b00001; R2731 & op2126=0b100010 & op1620=0b00000 +{ + R2731 = trunc(R1115); +} + diff --git a/Ghidra/Processors/V850/data/languages/V850e3.pspec b/Ghidra/Processors/V850/data/languages/V850e3.pspec new file mode 100644 index 00000000000..380ac417640 --- /dev/null +++ b/Ghidra/Processors/V850/data/languages/V850e3.pspec @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Ghidra/Processors/V850/data/languages/V850e3.sinc b/Ghidra/Processors/V850/data/languages/V850e3.sinc new file mode 100644 index 00000000000..3f3883bb97c --- /dev/null +++ b/Ghidra/Processors/V850/data/languages/V850e3.sinc @@ -0,0 +1,323 @@ +#BCOND adr17 - 00000111111DCCCC | ddddddddddddddd1 +:b^c0003 adr17 is (op0515=0x3F & c0003; op1616=1) & adr17 +{ + if (c0003) goto adr17; +} + + +# BINS reg1, pos, width, reg2 - rrrrr111111RRRRR | MMMMK0001001LLL0 (msb >= 16, lsb >= 16) +:bins _R1115, pos, width, R0004 is R1115 & _R1115 & op0510=0x3f & R0004; op2831 & op2727 & op2026=0x9 & op1719 & op1616=0 +[ pos = (op2727 << 3) | op1719 + 16; width= op2831 - pos + 17; ] +{ + local mask:4 = 0; + bfmask(mask, pos, width); + local result = (R1115 & ~mask) | (R0004 & mask); + _R1115 = result; + set_Z(result); + set_S(result); +} + +# BINS reg1, pos, width, reg2 - rrrrr111111RRRRR | MMMMK0001011LLL0 (msb >= 16, lsb < 16) +:bins _R1115, pos, width, R0004 is R1115 & _R1115 & op0510=0x3f & R0004; op2831 & op2727 & op2026=0xb & op1719 & op1616=0 +[ pos = (op2727 << 3) | op1719; width= op2831 - pos + 17; ] +{ + local mask:4 = 0; + bfmask(mask, pos, width); + local result = (R1115 & ~mask) | (R0004 & mask); + _R1115 = result; + set_Z(result); + set_S(result); +} + +# BINS reg1, pos, width, reg2 - rrrrr111111RRRRR | MMMMK0001101LLL0 (msb < 16, lsb < 16) +:bins _R1115, pos, width, R0004 is R1115 & _R1115 & op0510=0x3f & R0004; op2831 & op2727 & op2026=0xd & op1719 & op1616=0 +[ pos = (op2727 << 3) | op1719; width= op2831 - pos + 1; ] +{ + local mask:4 = 0; + bfmask(mask, pos, width); + local result = (R1115 & ~mask) | (R0004 & mask); + _R1115 = result; + set_Z(result); + set_S(result); +} + +define pcodeop cacheHitBlockInvalidate; +define pcodeop cacheIndexedBlockInvalidate; +define pcodeop cacheFetchAndLock; +define pcodeop cacheIndexedStore; +define pcodeop cacheIndexedLoad; +define pcodeop clearLoadLinkBit; + +cacheop: "CHBII", R0004 is op1112=0 & R0004; op2731=0 +{ + cacheHitBlockInvalidate(R0004); +} + +cacheop: "CIBII", R0004 is op1112=1 & R0004; op2731=0 +{ + cacheIndexedBlockInvalidate(R0004); +} + +cacheop: "CFALI", R0004 is op1112=2 & R0004; op2731=0 +{ + cacheFetchAndLock(R0004); +} + +cacheop: "CISTI", R0004 is op1112=3 & R0004; op2731=0 +{ + cacheIndexedStore(R0004); +} + +cacheop: "CILDI", R0004 is op1112=3 & R0004; op2731=1 +{ + cacheIndexedLoad(R0004); +} + +cacheop: "CLL" is op1112=3; op2731=0x1e +{ + clearLoadLinkBit(); +} + +# CACHE cacheop, [reg1] - 111pp111111RRRRR | PPPPP00101100000 +:cache cacheop is (op1315=0x7 & op0510=0x3f; op1626=0x160) & cacheop { + build cacheop; +} + +# CLL - 1111111111111111 | 1111000101100000 +:cll is op0015=0xffff; op1631=0xf160 +{ + clearLoadLinkBit(); +} +# CVTF.HS reg2, reg3 - rrrrr11111100010|wwwwww10001000010 +:cvtf.hs R1115, R2731 is R1115 & op0510=0x3F & op0004=0b00010; R2731 & op2126=0b100010 & op1620=0b00010 +{ + R2731 = float2float(R1115:2); +} + +# CVTF.SH reg2, reg3 - rrrrr11111100100|wwwwww10001000100 +:cvtf.sh R1115, R2731 is R1115 & op0510=0x3F & op0004=0b00011; R2731 & op2126=0b100010 & op1620=0b00010 +{ + local res:2 = float2float(R1115); + R2731 = zext(res); +} + + +define pcodeop debugCheckpoint; +# dbcp - 1110100001000000 +:dbcp is op0015=0xe840 +{ + debugCheckpoint(); +} + +define pcodeop debugHVTrap; +# dbhvtrap - 1110000001000000 +:dbhvtrap is op0015=0xe040 +{ + debugHVTrap(); +} + +define pcodeop debugPush; +# dbpush - 01011111111RRRRR | rrrrr11111111111 +:dbpush _R0004, _R2731 is op0515=0x2ff & _R0004; _R2731 & op1626=0x7ff +{ + debugPush(_R0004, _R2731); +} + +# dbret - 0000011111100000 | 0000000101000110 +:dbret is op0015=0x07e0; op1631=0x0146 +{ + PC = DBPC; + PSW = DBPSW; + goto [DBPC]; +} + +define pcodeop debugTag; +# dbtag imm10u - 01011111111IIIII | iiiii11111111111 +:dbtag imm10u is op0515=0x67f & op0004; op2731 & op1626=0x7ff +[ imm10u = (op0004 << 5) | op2731; ] +{ + local tag:2 = imm10u; + debugTag(tag); +} + +# dbtrap +:dbtrap is op0015=0xf840; op1631=0xffff +{ + DBPC = inst_next; + DBPSW = PSW; + $(NP) = 1; + $(EP) = 1; + $(ID) = 1; + PC = 0x00000060; + goto [PC]; +} + +define pcodeop dst; +# dst - 0x07e0, 0x0134 +:dst is op0015=0x07e0; op1631=0x0134 +{ + dst(); +} + +define pcodeop est; +# est - 0x07e0, 0x0132 +:est is op0015=0x07e0; op1631=0x0132 +{ + est(); +} + +# JARL [reg1], reg3 - 11000111111RRRRR|WWWWW00101100000 +:jarl [R0004], R2731 is op0515=0x63F & R0004; op1626=0x160 & R2731 +{ + R2731 = inst_next; + call [R0004]; +} + +# LD.DW disp23[reg1], reg3 - 00000111101RRRRR | wwwwwdddddd01001 | DDDDDDDDDDDDDDDD +:ld.dw disp23[R0004], R2731x2 is op0515=0x3d & R0004; R2731x2 & op2126 & op1620=0x9; s3247 +[ disp23 = (s3247 << 7) | (op2126 << 1); ] +{ + local adr:4 = R0004 + disp23; + R2731x2 = sext(*:8 adr); +} + +#LDL.W [reg1], reg3 - 00000111111RRRRR | wwwww01101111000 +define pcodeop ldl; +:ldl.w R0004, R2731 is op0515=0x3f & R0004; R2731 & op1626=0x378 +{ + ldl(R0004, R2731); +} + +# LDSR reg2, regID, selID - rrrrr111111RRRRR|sssss00000100000 +:ldsr R0004, regId, selId is (regId & op0510=0x3f & R0004; selId & op1626=0x20) +{ + local sysReg:2 = (selId:2 << 5) | regId:2; + R0004 = *[sysreg]:4 sysReg; +} + +disp16: reladdr is op1731 [reladdr = inst_start - (op1731 << 1); ]{ export *:4 reladdr; } + +# LOOP reg1, disp16 - 00000110111RRRRR | ddddddddddddddd1 +:loop R0004, disp16 is op0515=0x037 & R0004; disp16 & op1616=1 +{ + set_OV_neg(R0004, -1:4); + R0004 = R0004 - 1; + if (R0004 == 0) goto inst_next; + goto disp16; +} + +ListReg: r0 is r0 & regNum=0 { export r0; } +ListReg: r1 is r1 & regNum=1 { export r1; } +ListReg: r2 is r2 & regNum=2 { export r2; } +ListReg: sp is sp & regNum=3 { export sp; } +ListReg: gp is gp & regNum=4 { export gp; } +ListReg: tp is tp & regNum=5 { export tp; } +ListReg: r6 is r6 & regNum=6 { export r6; } +ListReg: r7 is r7 & regNum=7 { export r7; } +ListReg: r8 is r8 & regNum=8 { export r8; } +ListReg: r9 is r9 & regNum=9 { export r9; } +ListReg: r10 is r10 & regNum=10 { export r10; } +ListReg: r11 is r11 & regNum=11 { export r11; } +ListReg: r12 is r12 & regNum=12 { export r12; } +ListReg: r13 is r13 & regNum=13 { export r13; } +ListReg: r14 is r14 & regNum=14 { export r14; } +ListReg: r15 is r15 & regNum=15 { export r15; } +ListReg: r16 is r16 & regNum=16 { export r16; } +ListReg: r17 is r17 & regNum=17 { export r17; } +ListReg: r18 is r18 & regNum=18 { export r18; } +ListReg: r19 is r19 & regNum=19 { export r19; } +ListReg: r20 is r20 & regNum=20 { export r20; } +ListReg: r21 is r21 & regNum=21 { export r21; } +ListReg: r22 is r22 & regNum=22 { export r22; } +ListReg: r23 is r23 & regNum=23 { export r23; } +ListReg: r24 is r24 & regNum=24 { export r24; } +ListReg: r25 is r25 & regNum=25 { export r25; } +ListReg: r26 is r26 & regNum=26 { export r26; } +ListReg: r27 is r27 & regNum=27 { export r27; } +ListReg: r28 is r28 & regNum=28 { export r28; } +ListReg: r29 is r29 & regNum=29 { export r29; } +ListReg: ep is ep & regNum=30 { export ep; } +ListReg: lp is lp & regNum=31 { export lp; } + + +PopSPList: ListReg is ListReg & counter=1 [ counter=0; regNum=regNum-1; ] { pushsp(ListReg); } +PopSPList: ListReg is ListReg & PopSPList [ counter=counter-1; regNum=regNum-1; ] { pushsp(ListReg); build PopSPList; } + +#POPSP reg1, reg2 - 01100111111RRRRR | wwwww00101100000 +:popsp R0004, R2731 is op0515=0x33f & R0004 & op0004; R2731 & op2731 & op1626=0x160 & PopSPList +[counter=op2731-op0004+1; regNum=op2731; ] +{ + _sp = sp; + build PopSPList; + sp = _sp; +} + +#PUSHSP reg1, reg2 - 01000111111RRRRR | wwwww00101100000 +PushSPList: ListReg is ListReg & counter=1 [ counter=0; regNum=regNum+1; ] { pushsp(ListReg); } +PushSPList: ListReg is ListReg & PushSPList [ counter=counter-1; regNum=regNum+1; ] { pushsp(ListReg); build PushSPList; } + +:pushsp R0004, R2731 is R0004 & op0004; R2731 & op2731 & PushSPList +[ counter=op2731-op0004+1; regNum=op0004; ] +{ + _sp = sp; + build PushSPList; + sp = _sp; +} + +#ROTL imm5, reg2, reg3 - rrrrr111111iiiii | wwwww00011000100 +:rotl op0004, R1115, _R2731 is op0004 & R1115 & op0510=0x3f; _R2731 & op1626=0x0c4 +{ + local shift = op0004; + local res = (R1115 << shift) | (R1115 >> (32 - shift)); + set_OV0_S_Z(res); + $(CY) = (shift != 0); + _R2731 = res; +} + +#ROTL reg1, reg2, reg3 - rrrrr111111RRRRR | wwwww00011000110 +:rotl R0004, R1115, _R2731 is R0004 & R1115 & op0510=0x3f; _R2731 & op1626=0x0c6 +{ + local shift = R0004 & 0x1f; + local res = (R1115 << shift) | (R1115 >> (32 - shift)); + set_OV0_S_Z(res); + $(CY) = (shift != 0); + _R2731 = res; +} + +#SNOOZE - 0000111111100000 | 0000000100100000 +define pcodeop snooze; +:snooze is op0015=0x0fe0;op1631=0x0120 +{ + snooze(); +} + +# ST.DW reg3, disp23[reg1] - 00000111101RRRRR | wwwwwdddddd01111 | DDDDDDDDDDDDDDDD +:st.dw R2731x2, disp23[R0004] is op0515=0x3d & R0004; R2731x2 & op2126 & op1620=0xf; s3247 +[ disp23 = (s3247 << 7) | (op2126 << 1); ] +{ + local addr:4 = R0004 + disp23; + *:8 addr = R2731x2; +} + +#STC.W reg3, [reg1] - 00000111111RRRRR | wwwww01101111010 +define pcodeop stc; +:stc.w R2731, R0004 is op0515=0x3f & R0004; R2731 & op1626=0x37a +{ + stc(R0004, R2731); +} + +#STSR regID, reg2, selID - rrrrr111111RRRRR | sssss00001000000 +:stsr regId, R0004, selId is (regId & op0510=0x3f & R0004; selId & op1626=0x40) +{ + local sysReg:2 = (selId:2 << 5) | regId:2; + *[sysreg]:4 sysReg = R0004; +} + +#SYNCI - 0000000000011100 +define pcodeop synci; +:synci is op0015=0x001c +{ + synci(); +} + + diff --git a/Ghidra/Processors/V850/data/languages/V850e3.slaspec b/Ghidra/Processors/V850/data/languages/V850e3.slaspec new file mode 100644 index 00000000000..be608bf8feb --- /dev/null +++ b/Ghidra/Processors/V850/data/languages/V850e3.slaspec @@ -0,0 +1,16 @@ +############################################## +##### ##### +##### V850E3 SLEIGH specification ##### +##### ##### +############################################## + +@define V850E3 "" + +@include "V850.sinc" + +################################ +##### Instructions ##### +################################ + +@include "V850_instructions.sinc" +@include "V850e3.sinc" diff --git a/Ghidra/Processors/V850/data/manuals/v850.idx b/Ghidra/Processors/V850/data/manuals/v850.idx index b09c169a049..8899a9d617a 100644 --- a/Ghidra/Processors/V850/data/manuals/v850.idx +++ b/Ghidra/Processors/V850/data/manuals/v850.idx @@ -1,4 +1,4 @@ -@r01us0001ej0100_v850e2m.pdf [V850E2M User’s Manual: Architecture RENESAS MCU V850E2M Microprocessor Core] +@r01us0001ej0100_v850e2m.pdf [V850E2M User�s Manual: Architecture RENESAS MCU V850E2M Microprocessor Core] ADD, 71 ADDI, 72 @@ -172,3 +172,19 @@ TRNCF.SL, 403 TRNCF.SUL, 404 TRNCF.SUW, 405 TRNCF.SW, 406 + +@r01us0143ej0130-rh850g3mh.pdf [RH850G3MH User's Manual: Software Renesas microcontroller] + +BINS, 162 +CACHE, 303 +CLL, 169 +LD.DW, 204 +LDL.W, 211 +LOOP, 213 +POPSP, 232 +PUSHSP, 237 +ROTL, 240 +SNOOZE, 268 +ST.DW, 274 +STC.W, 279 +SYNCI, 288 \ No newline at end of file diff --git a/Ghidra/Processors/V850/src/test.processors/java/ghidra/test/processors/RH850_O0_EmulatorTest.java b/Ghidra/Processors/V850/src/test.processors/java/ghidra/test/processors/RH850_O0_EmulatorTest.java new file mode 100644 index 00000000000..9f75675e47c --- /dev/null +++ b/Ghidra/Processors/V850/src/test.processors/java/ghidra/test/processors/RH850_O0_EmulatorTest.java @@ -0,0 +1,38 @@ +/* ### + * 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.test.processors; + +import ghidra.test.processors.support.ProcessorEmulatorTestAdapter; +import junit.framework.Test; + +public class RH850_O0_EmulatorTest extends ProcessorEmulatorTestAdapter { + private static final String LANGUAGE_ID = "V850:LE:32:v850e3v5"; + private static final String COMPILER_SPEC_ID = "default"; + private static final String[] REG_DUMP_SET = new String[] {}; + + public RH850_O0_EmulatorTest(String name) throws Exception { + super(name, LANGUAGE_ID, COMPILER_SPEC_ID, REG_DUMP_SET); + } + + @Override + protected String getProcessorDesignator() { return "RH850_GCC_O0"; } + + + public static Test suite() { + return ProcessorEmulatorTestAdapter.buildEmulatorTestSuite(RH850_O0_EmulatorTest.class); + } + +} diff --git a/Ghidra/Processors/V850/src/test.processors/java/ghidra/test/processors/RH850_O3_EmulatorTest.java b/Ghidra/Processors/V850/src/test.processors/java/ghidra/test/processors/RH850_O3_EmulatorTest.java new file mode 100644 index 00000000000..39631d14d7a --- /dev/null +++ b/Ghidra/Processors/V850/src/test.processors/java/ghidra/test/processors/RH850_O3_EmulatorTest.java @@ -0,0 +1,40 @@ +/* ### + * 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.test.processors; + +import ghidra.test.processors.support.ProcessorEmulatorTestAdapter; +import junit.framework.Test; + +public class RH850_O3_EmulatorTest extends ProcessorEmulatorTestAdapter { + + private static final String LANGUAGE_ID = "V850:LE:32:v850e3v5"; + private static final String COMPILER_SPEC_ID = "default"; + + private static final String[] REG_DUMP_SET = new String[] {}; + + public RH850_O3_EmulatorTest(String name) throws Exception { + super(name, LANGUAGE_ID, COMPILER_SPEC_ID, REG_DUMP_SET); + } + + @Override + protected String getProcessorDesignator() { + return "RH850_GCC_O3"; + } + + public static Test suite() { + return ProcessorEmulatorTestAdapter.buildEmulatorTestSuite(RH850_O3_EmulatorTest.class); + } +} diff --git a/Ghidra/Processors/V850/src/test.processors/java/ghidra/test/processors/V850_O0_EmulatorTest.java b/Ghidra/Processors/V850/src/test.processors/java/ghidra/test/processors/V850_O0_EmulatorTest.java new file mode 100644 index 00000000000..5a8e4274b25 --- /dev/null +++ b/Ghidra/Processors/V850/src/test.processors/java/ghidra/test/processors/V850_O0_EmulatorTest.java @@ -0,0 +1,38 @@ +/* ### + * 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.test.processors; + +import ghidra.test.processors.support.ProcessorEmulatorTestAdapter; +import junit.framework.Test; + +public class V850_O0_EmulatorTest extends ProcessorEmulatorTestAdapter { + private static final String LANGUAGE_ID = "V850:LE:32:default"; + private static final String COMPILER_SPEC_ID = "default"; + private static final String[] REG_DUMP_SET = new String[] {}; + + public V850_O0_EmulatorTest(String name) throws Exception { + super(name, LANGUAGE_ID, COMPILER_SPEC_ID, REG_DUMP_SET); + } + + @Override + protected String getProcessorDesignator() { return "V850_GCC_O0"; } + + + public static Test suite() { + return ProcessorEmulatorTestAdapter.buildEmulatorTestSuite(V850_O0_EmulatorTest.class); + } + +} diff --git a/Ghidra/Processors/V850/src/test.processors/java/ghidra/test/processors/V850_O3_EmulatorTest.java b/Ghidra/Processors/V850/src/test.processors/java/ghidra/test/processors/V850_O3_EmulatorTest.java new file mode 100644 index 00000000000..64e5a473d4c --- /dev/null +++ b/Ghidra/Processors/V850/src/test.processors/java/ghidra/test/processors/V850_O3_EmulatorTest.java @@ -0,0 +1,40 @@ +/* ### + * 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.test.processors; + +import ghidra.test.processors.support.ProcessorEmulatorTestAdapter; +import junit.framework.Test; + +public class V850_O3_EmulatorTest extends ProcessorEmulatorTestAdapter { + + private static final String LANGUAGE_ID = "V850:LE:32:default"; + private static final String COMPILER_SPEC_ID = "default"; + + private static final String[] REG_DUMP_SET = new String[] {}; + + public V850_O3_EmulatorTest(String name) throws Exception { + super(name, LANGUAGE_ID, COMPILER_SPEC_ID, REG_DUMP_SET); + } + + @Override + protected String getProcessorDesignator() { + return "V850_GCC_O3"; + } + + public static Test suite() { + return ProcessorEmulatorTestAdapter.buildEmulatorTestSuite(V850_O3_EmulatorTest.class); + } +} From 1541f3a78b3adccb32ab2848a0958571eb6760ae Mon Sep 17 00:00:00 2001 From: Dan <46821332+nsadeveloper789@users.noreply.github.com> Date: Tue, 23 Jun 2026 13:30:09 +0000 Subject: [PATCH 040/111] GP-6934: Implement OS/shell-dependent escaping. --- .../ghidra/dbg/jdi/rmi/jpda/JdiArguments.java | 4 +- .../launcher/AbstractTraceRmiLaunchOffer.java | 19 +- .../core/terminal/TerminalProvider.java | 4 +- .../src/main/java/ghidra/pty/ShellUtils.java | 217 +++++++++++++++++- .../java/ghidra/pty/windows/ConPtyChild.java | 47 +++- 5 files changed, 271 insertions(+), 20 deletions(-) diff --git a/Ghidra/Debug/Debugger-jpda/src/main/java/ghidra/dbg/jdi/rmi/jpda/JdiArguments.java b/Ghidra/Debug/Debugger-jpda/src/main/java/ghidra/dbg/jdi/rmi/jpda/JdiArguments.java index 64eceb37ae2..964faf7ae78 100644 --- a/Ghidra/Debug/Debugger-jpda/src/main/java/ghidra/dbg/jdi/rmi/jpda/JdiArguments.java +++ b/Ghidra/Debug/Debugger-jpda/src/main/java/ghidra/dbg/jdi/rmi/jpda/JdiArguments.java @@ -22,7 +22,7 @@ import com.sun.jdi.connect.Connector; import com.sun.jdi.connect.Connector.Argument; -import ghidra.pty.ShellUtils; +import ghidra.pty.ShellUtils.Shell; public class JdiArguments { enum Mode { @@ -101,7 +101,7 @@ public void putArguments(Map args) { } String cp = env.get("OPT_TARGET_CLASSPATH"); if (!cp.isBlank()) { - args.get("options").setValue("-cp " + ShellUtils.generateArgument(cp)); + args.get("options").setValue("-cp " + Shell.LOCAL.generateArgument(cp)); } } } diff --git a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractTraceRmiLaunchOffer.java b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractTraceRmiLaunchOffer.java index d002477d462..4cb6b0da88b 100644 --- a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractTraceRmiLaunchOffer.java +++ b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractTraceRmiLaunchOffer.java @@ -50,6 +50,7 @@ import ghidra.program.model.listing.Program; import ghidra.program.util.ProgramLocation; import ghidra.pty.*; +import ghidra.pty.ShellUtils.Shell; import ghidra.trace.model.Trace; import ghidra.trace.model.TraceLocation; import ghidra.util.*; @@ -475,7 +476,7 @@ protected PtyTerminalSession runInTerminal(List commandLine, Map withoutPath = ShellUtils.removePath(commandLine); - terminal.setSubTitle(ShellUtils.generateLine(withoutPath)); + terminal.setSubTitle(ShellUtils.generateLine(withoutPath, Shell.DISPLAY)); TerminalListener resizeListener = new TerminalListener() { @Override public void resized(short cols, short rows) { @@ -490,8 +491,19 @@ public void resized(short cols, short rows) { terminal.addTerminalListener(resizeListener); env.put("TERM", "xterm-256color"); - PtySession session = - pty.getChild().session(commandLine.toArray(String[]::new), env, workingDirectory); + PtySession session; + try { + session = + pty.getChild().session(commandLine.toArray(String[]::new), env, workingDirectory); + } + catch (Throwable t) { + terminal.terminated(-1); + pty.close(); + for (TerminalSession ss : subordinates) { + ss.terminate(); + } + throw t; + } Thread waiter = new Thread(() -> { try { @@ -718,6 +730,7 @@ public LaunchResult launchProgram(TaskMonitor monitor, LaunchConfigurator config * terminates early */ monitor.setMessage("Waiting for connection"); + monitor.addCancelledListener(acceptor::cancel); connection = acceptOrSessionEnds(acceptor, backEnd); connection.registerTerminals(sessions.values()); monitor.increment(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalProvider.java index b5e923dd863..0c4082445de 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalProvider.java @@ -442,7 +442,9 @@ public void terminated(int exitcode) { Swing.runIfSwingOrRunLater(() -> { terminated = true; panel.terminalListeners.invoke().terminated(exitcode); - removeLocalAction(actionTerminate); + if (actionTerminate != null) { + removeLocalAction(actionTerminate); + } panel.terminalListeners.clear(); panel.setOutputCallback(buf -> { }); diff --git a/Ghidra/Framework/Pty/src/main/java/ghidra/pty/ShellUtils.java b/Ghidra/Framework/Pty/src/main/java/ghidra/pty/ShellUtils.java index 9d853cc5282..e3a2e6b3b87 100644 --- a/Ghidra/Framework/Pty/src/main/java/ghidra/pty/ShellUtils.java +++ b/Ghidra/Framework/Pty/src/main/java/ghidra/pty/ShellUtils.java @@ -19,11 +19,28 @@ import java.util.*; import java.util.stream.Collectors; +import ghidra.framework.OperatingSystem; +import ghidra.framework.Platform; + public class ShellUtils { enum State { NORMAL, NORMAL_ESCAPE, DQUOTE, DQUOTE_ESCAPE, SQUOTE, SQUOTE_ESCAPE; } + /** + * Parse a command line into an argument list + *

    + * LATER: This is meant to mimic UNIX- / C-style arguments, but that's probably not appropriate + * on all systems. We should either: + * + *

      + *
    1. Let the offer specify how @args ought to be treated.
    2. + *
    3. Let the header annotations for @args include some extra specifier.
    4. + *
    + * + * @param args the arguments as a single string + * @return the list of split arguments + */ public static List parseArgs(String args) { List argsList = new ArrayList<>(); StringBuilder curArg = new StringBuilder(); @@ -123,29 +140,207 @@ public static List removePath(List args) { return List.copyOf(copy); } - public static String generateLine(List args) { + public static String generateLine(List args, Shell shell) { if (args.isEmpty()) { return ""; } - StringBuilder line = new StringBuilder(generateArgument(args.get(0))); + StringBuilder line = new StringBuilder(shell.generateArgument(args.get(0))); for (int i = 1; i < args.size(); i++) { String a = args.get(i); - line.append(" " + generateArgument(a)); + line.append(" " + shell.generateArgument(a)); } return line.toString(); } - public static String generateArgument(String a) { - if (a.contains(" ")) { - if (a.contains("\"")) { - if (a.contains("'")) { - return "\"" + a.replace("\"", "\\\"") + "\""; + /** + * A target shell for command-line arguments + *

    + * This determines how arguments are quoted and/or escaped. This should be set based on the + * shell that is going to receive the actual commands, which may or may not be the local shell. + * In many cases, it is the local shell, but please ensure for remote cases, the correct shell + * is specified. + */ + public enum Shell { + /** + * For display purposes only. DO NOT pass to any actual shell. + */ + DISPLAY { + @Override + public String generateArgument(String a) { + if (a.contains(" ")) { + if (a.contains("\"")) { + if (a.contains("'")) { + return '"' + a.replace("\"", "\\\"") + '"'; + } + return "'" + a + "'"; + } + return '"' + a + '"'; + } + return a; + } + }, + /** + * Unix shells that follow the same conventions as "sh". This is most Unix shells. + */ + UNIX_SH { + @Override + public String generateArgument(String a) { + StringBuilder b = new StringBuilder(); + for (int i = 0; i < a.length(); i++) { + char c = a.charAt(i); + boolean esc = switch (c) { + case '\t', ' ', // Whitespace + '&', '|', ';', '`', '(', ')', // Syntax, command separators + '<', '>', // Redirection + '$', // Variable substitution + '#', // Comments + '[', ']', '?', '*', // File globbing + '"', '\'', // Quotes + '\\' // The escape character itself + -> true; + default -> false; + }; + if (esc) { + b.append('\\'); + } + b.append(c); } - return "'" + a + "'"; + return b.toString(); } - return "\"" + a + "\""; + }, + /** + * Plain Windows command-line arguments for the C runtime + *

    + * See CommandLineToArgvW + * function + */ + WINDOWS { + /** + * Derived from Everyone + * quotes command line arguments the wrong way + *

    + * The section titled "The Correct Solution" invites its readers to "translate it into + * your language and coding style off choice." + */ + @Override + public String generateArgument(String a) { + if (!a.isEmpty() && a.indexOf(' ') == -1 && a.indexOf('\t') == -1 && + a.indexOf('\n') == -1 && a.indexOf('"') == -1) { + return a; + } + StringBuilder b = new StringBuilder(); + b.append('"'); + for (int i = 0;; i++) { + int nBackSlash = 0; + while (i < a.length() && a.charAt(i) == '\\') { + i++; + nBackSlash++; + } + + if (i == a.length()) { + /** + * We reached the end of the argument while counting backslashes. Escape + * them all. The terminating " we add at the end of this method will be + * interpreted as a metacharacter. + */ + b.append("\\".repeat(nBackSlash * 2)); + break; + } + else if (a.charAt(i) == '"') { + /** + * Sequence of backslashes ends in a ". Escape them all, including the ". + */ + b.append("\\".repeat(nBackSlash * 2 + 1)); + b.append(a.charAt(i)); + } + else { + /** + * They're just literal backslashes. Do not escape them. Be sure to add the + * current character, too. + */ + b.append("\\".repeat(nBackSlash)); // No *2 + b.append(a.charAt(i)); + } + } + b.append('"'); + return b.toString(); + } + }, + /** + * The Windows cmd.exe shell. + *

    + * NOTE: It seems to me using this with {@link ShellUtils#generateLine(List, Shell)} + * is futile, if the intent is to use specific argument numbers in the batch file, e.g., + * %1. If you make clear certain constraints to the user, maybe it's suitable, + * but especially involving quotes, it's not possible to encode any arbitrary string. It + * seems the cmd shell is primarily concerned with just passing the arguments along to child + * processes, as encoded, and then the child figures out the parsing. That said, if the + * child process parses to argc/argv, then so long as the full command line is + * passed through the batch file, it should work as intended. However, if grabbing + * individual arguments, they cannot be reliably controlled. + *

    + * LATER: There may be a way to factor the escaping part separately from the argument + * catenation part, so that special logic can be applied here to better guarantee argument + * numbering, but then there's still the issue if the final target is expected to parse to + * argc/argv, if that can be encoded reliably. + */ + WINDOWS_CMD { + @Override + public String generateArgument(String a) { + String quoted = WINDOWS.generateArgument(a); + StringBuilder b = new StringBuilder(); + for (int i = 0; i < quoted.length(); i++) { + char c = quoted.charAt(i); + /** + * The list and rationale for each metacharacter comes from the same blogpost: + * Everyone + * quotes command line arguments the wrong way + */ + boolean esc = switch (c) { + case '(', ')', '%', '!', '<', '>', '&', '|', // Metacharacters + '"', // Prevent cmd from interpreting quotes + '^' // The escape character itself + -> true; + default -> false; + }; + if (esc) { + b.append('^'); + } + b.append(c); + } + return b.toString(); + } + }; + + /** + * Get the probable shell for the given operating system + * + * @param os the operating system + * @return the shell, probably + */ + public static Shell forOs(OperatingSystem os) { + return switch (os) { + case OperatingSystem.WINDOWS -> Shell.WINDOWS; + default -> Shell.UNIX_SH; + }; } - return a; + + /** + * The local shell, probably + */ + public static final Shell LOCAL = forOs(Platform.CURRENT_PLATFORM.getOperatingSystem()); + + /** + * Escape and/or quote a single command-line argument + * + * @param a the argument + * @return the argument formed in such a way that the shell will interpret it as the given + * string in one argument + */ + public abstract String generateArgument(String a); } public static String generateEnvBlock(Map env) { diff --git a/Ghidra/Framework/Pty/src/main/java/ghidra/pty/windows/ConPtyChild.java b/Ghidra/Framework/Pty/src/main/java/ghidra/pty/windows/ConPtyChild.java index cbccbc6a7dc..3ab7de73a33 100644 --- a/Ghidra/Framework/Pty/src/main/java/ghidra/pty/windows/ConPtyChild.java +++ b/Ghidra/Framework/Pty/src/main/java/ghidra/pty/windows/ConPtyChild.java @@ -28,6 +28,7 @@ import ghidra.pty.PtyChild; import ghidra.pty.ShellUtils; +import ghidra.pty.ShellUtils.Shell; import ghidra.pty.local.LocalWindowsNativeProcessPtySession; import ghidra.pty.windows.jna.ConsoleApiNative; import ghidra.pty.windows.jna.ConsoleApiNative.STARTUPINFOEX; @@ -75,12 +76,51 @@ protected STARTUPINFOEX prepareStartupInfo() { return si; } + private boolean isImplicitCmd(String[] args) { + if (args.length < 1) { + return false; // Really shouldn't, but let Windows decide how to fail + } + String lower0 = args[0].toLowerCase(); + if (lower0.endsWith(".bat") || lower0.endsWith(".cmd")) { + return true; + } + /** + * I'm on the fence about this. While it's pretty clear that invoking a .bat file, which + * implicitly prefixes cmd /c, ought to escape the metacharacters, I'm not + * certain about when a user explicitly invokes cmd /c. I think it should let + * the metacharacters through, i.e., cmd should be permitted to do what the user probably + * intended. Still, if someone using this API unwittingly puts the cmd /c + * prefix on a user-supplied command line without sanitizing, they could create a + * vulnerability. + */ + /*if (args.length < 2) { + return false; + } + if (!"/c".equals(args[1])) { + return false; + } + if ("cmd".equals(lower0) || "cmd.exe".equals(lower0) || lower0.endsWith("\\cmd") || + lower0.endsWith("\\cmd.exe")) { + return true; + }*/ + return false; + } + + /** + * {@inheritDoc} + *

    + * WARNING: If arg[0], i.e., the application name, is a batch file, Windows will + * automatically invoke it using cmd /c. This method is aware of this implicit + * invocation and, upon detecting it, will appropriately escape cmd's metacharacters. + * However, if a client explicitly invokes cmd /c with any part of the + * command line formed from user-supplied arguments, IT MUST sanitize those arguments itself. + * This can be achieved using {@link Shell#generateArgument(String)} of + * {@link Shell#WINDOWS_CMD}. + */ @Override public LocalWindowsNativeProcessPtySession session(String[] args, Map env, File workingDirectory, Collection mode) throws IOException { /** - * TODO: How to incorporate environment into CreateProcess? - * * TODO: How to control local echo? */ @@ -92,7 +132,8 @@ public LocalWindowsNativeProcessPtySession session(String[] args, Map Date: Tue, 23 Jun 2026 17:59:51 -0400 Subject: [PATCH 041/111] GP-0: Adding --sun-misc-unsafe-memory-access=allow to Eclipse run configs --- Ghidra/Features/Base/.launch/Ghidra Code Coverage.launch | 2 +- Ghidra/Features/Base/.launch/Ghidra.launch | 2 +- Ghidra/Features/Base/.launch/Headless.launch | 2 +- Ghidra/Features/Base/.launch/JShell.launch | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Ghidra/Features/Base/.launch/Ghidra Code Coverage.launch b/Ghidra/Features/Base/.launch/Ghidra Code Coverage.launch index 74a36db34c5..b21276478da 100644 --- a/Ghidra/Features/Base/.launch/Ghidra Code Coverage.launch +++ b/Ghidra/Features/Base/.launch/Ghidra Code Coverage.launch @@ -29,6 +29,6 @@ - + diff --git a/Ghidra/Features/Base/.launch/Ghidra.launch b/Ghidra/Features/Base/.launch/Ghidra.launch index 2ec45957462..55365e41560 100644 --- a/Ghidra/Features/Base/.launch/Ghidra.launch +++ b/Ghidra/Features/Base/.launch/Ghidra.launch @@ -31,5 +31,5 @@ - + diff --git a/Ghidra/Features/Base/.launch/Headless.launch b/Ghidra/Features/Base/.launch/Headless.launch index 3fca8ef6805..7898a844d7c 100644 --- a/Ghidra/Features/Base/.launch/Headless.launch +++ b/Ghidra/Features/Base/.launch/Headless.launch @@ -31,5 +31,5 @@ - + diff --git a/Ghidra/Features/Base/.launch/JShell.launch b/Ghidra/Features/Base/.launch/JShell.launch index 7b9445dce7d..d68455103e6 100644 --- a/Ghidra/Features/Base/.launch/JShell.launch +++ b/Ghidra/Features/Base/.launch/JShell.launch @@ -31,5 +31,5 @@ - + From bab81cb679ca810fcb3279fb87b6c205d754dcf1 Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Mon, 8 Jun 2026 17:36:39 +0000 Subject: [PATCH 042/111] GP-941: Correct SparcV9 register operand display to be consistent --- .../Processors/Sparc/data/languages/SparcV9.sinc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Ghidra/Processors/Sparc/data/languages/SparcV9.sinc b/Ghidra/Processors/Sparc/data/languages/SparcV9.sinc index 9aeac3e76cc..6891cb1af8d 100644 --- a/Ghidra/Processors/Sparc/data/languages/SparcV9.sinc +++ b/Ghidra/Processors/Sparc/data/languages/SparcV9.sinc @@ -342,23 +342,23 @@ if (DECOMPILE_MODE) goto ; #There are special cases for source operands RS1 and RS2 which just return the constant 0 when the #specified register is g0 -RS1: rs1 is rs1 & rs1_zero=0 { export 0:$(SIZE); } -RS1: rs1 is rs1 { export rs1; } +RS1: "%"^rs1 is rs1 & rs1_zero=0 { export 0:$(SIZE); } +RS1: "%"^rs1 is rs1 { export rs1; } -RS2: rs2 is rs2 & rs2_zero=0 { export 0:$(SIZE); } -RS2: rs2 is rs2 { export rs2; } +RS2: "%"^rs2 is rs2 & rs2_zero=0 { export 0:$(SIZE); } +RS2: "%"^rs2 is rs2 { export rs2; } #For the destination operand RD, we export a temporary varnode with value 0. #This is because writes to g0 are allowed, but they have no visible effect (see the Sparc manual). #This way the value of g0 won't appear to change when using the pcode emulator. # -RD: rd is rd & rd_zero=0 { local tmp:$(SIZE) = 0; export tmp; } +RD: "%"^rd is rd & rd_zero=0 { local tmp:$(SIZE) = 0; export tmp; } # didrestore is picked up by call instruction only # this will cause any instruction that assigns to the o7 return address register # in the delay slot of a call instruction to turn the call into a call/return # -RD: rd is rd & rd_d=15 { didrestore = 1; export rd; } -RD: rd is rd { export rd; } +RD: "%"^rd is rd & rd_d=15 { didrestore = 1; export rd; } +RD: "%"^rd is rd { export rd; } regorimm: RS2 is i=0 & RS2 { export RS2; } regorimm: simm13 is i=1 & simm13 { export *[const]:$(SIZE) simm13; } From fb4bfe5aebeef7aa91d352611bee95742cabe4c6 Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Thu, 25 Jun 2026 11:30:07 -0400 Subject: [PATCH 043/111] GP-0: Corrected SparcAssemblyTest --- .../app/plugin/assembler/sleigh/SparcAssemblyTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/app/plugin/assembler/sleigh/SparcAssemblyTest.java b/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/app/plugin/assembler/sleigh/SparcAssemblyTest.java index 522b5e24e47..f68ac148322 100644 --- a/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/app/plugin/assembler/sleigh/SparcAssemblyTest.java +++ b/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/app/plugin/assembler/sleigh/SparcAssemblyTest.java @@ -4,9 +4,9 @@ * 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. @@ -27,7 +27,7 @@ protected LanguageID getLanguageID() { @Test public void testAssemble_rd_Y_g2() { - assertOneCompatRestExact("rd %Y,g2", "85:40:00:00"); + assertOneCompatRestExact("rd %Y,%g2", "85:40:00:00"); } // Too many reserved/undefined bits: 524288 instructions to test @@ -38,6 +38,6 @@ public void testAssemble_restore() { @Test public void testAssemble_wr_g3_g0() { - assertOneCompatRestExact("wr g0,g3,%Y", "81:80:00:03"); + assertOneCompatRestExact("wr %g0,%g3,%Y", "81:80:00:03"); } } From e3dc1646d2536efe80e6ea413b452a4938776e57 Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Fri, 26 Jun 2026 10:22:30 -0400 Subject: [PATCH 044/111] GP-7007: Removed usage of os.system and replaced with subprocess.run --- .../SleighDevTools/pcodetest/build.py | 43 +++++++++---------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/Ghidra/Extensions/SleighDevTools/pcodetest/build.py b/Ghidra/Extensions/SleighDevTools/pcodetest/build.py index 68f9a6483ac..1c6eacce4f4 100644 --- a/Ghidra/Extensions/SleighDevTools/pcodetest/build.py +++ b/Ghidra/Extensions/SleighDevTools/pcodetest/build.py @@ -14,6 +14,7 @@ # limitations under the License. ## import os +import shlex import shutil import subprocess import sys @@ -32,32 +33,28 @@ def __init__(self): def run(self, cmd, stdout=False, stderr=False, verbose=True): if isinstance(cmd, str): - if stdout and stderr: - cmd += ' 1>%s 2>%s' % (stdout, stderr) - elif stdout and not stderr: - cmd += ' 1>%s 2>&1' % (stdout) - elif not stdout and stderr: - cmd += ' 2>%s' % (stderr) - if verbose: self.log_info(cmd) - os.system(cmd) + proc = shlex.split(cmd) + string = cmd else: - string = ' '.join(cmd) + proc = cmd + string = " ".join(cmd) + if verbose: self.log_info(string) + try: if stdout: - f = open(stdout, 'w+') - string += ' 1>%s 2>&1' % (stdout) + stdout_f = open(stdout,'w') + stderr_f = open(stderr,'w') if stderr else subprocess.STDOUT + result = subprocess.run(proc, stdout=stdout_f, stderr=stderr_f) + elif stderr: + stdout_f = None + stderr_f = open(stderr,'w') + result = subprocess.run(proc, stdout=stdout_f, stderr=stderr_f) else: - f = subprocess.PIPE - if verbose: self.log_info(string) - try: - sp = subprocess.Popen(cmd, stdout=f, stderr=subprocess.PIPE) - except OSError as e: - self.log_err("Command: " + string) - self.log_err(e.strerror) - return 0, e.strerror - if stdout: f.close() - out, err = sp.communicate() - # print 'run returned %d bytes stdout and %d bytes stderr' % (len(out) if out else 0, len(err) if err else 0) - return out, err + result = subprocess.run(proc,capture_output=True) + except OSError as e: + self.log_err("Command: " + string) + self.log_err(e.strerror) + return 0, e.strerror + return result.stdout, result.stderr def isdir(self, dname): return os.path.isdir(dname) From daf2306fcd7e8a6601f7eaf5e8e4fcb9793162f9 Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Fri, 26 Jun 2026 10:43:42 -0400 Subject: [PATCH 045/111] GP-1 Minor fixes back-ported from GP-6779: project in-use tracking, data type archive address factory --- .../java/ghidra/framework/data/DefaultProjectData.java | 6 ++---- .../main/java/ghidra/framework/data/GhidraFileData.java | 7 +++++++ .../program/model/data/StandAloneDataTypeManager.java | 8 +++++++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/DefaultProjectData.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/DefaultProjectData.java index b0bd4244829..ce4aee0b1f3 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/DefaultProjectData.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/DefaultProjectData.java @@ -1263,11 +1263,9 @@ public synchronized boolean isDisposed() { @Override public void close() { synchronized (this) { - if (!closed) { - closed = true; - } + closed = true; if (inUseCount != 0) { - return; // delay dispose + return; // delay dispose while still in-use } } dispose(); diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/GhidraFileData.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/GhidraFileData.java index 337c68d9798..3dc3db83caa 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/GhidraFileData.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/GhidraFileData.java @@ -656,6 +656,13 @@ DomainObject getDomainObject(Object consumer, boolean okToUpgrade, boolean okToR DomainFileProxy proxy = new DomainFileProxy(name, parent.getPathname(), doa, DomainFile.DEFAULT_VERSION, fileID, parent.getProjectLocator()); proxy.setLastModified(getLastModifiedTime()); + + // Notify file manager of in-use domain object. + // A link-file object is indirect with tracking intiated by the URL-referenced file. + if (!isLink()) { + projectData.trackDomainFileInUse(doa); + } + return doa; } myFolderItem = folderItem; diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StandAloneDataTypeManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StandAloneDataTypeManager.java index 1326596935a..c2ce47e033e 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StandAloneDataTypeManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StandAloneDataTypeManager.java @@ -437,6 +437,8 @@ else if (languageVersionExc != null) { final Language lang = language; final CompilerSpec cspec = compilerSpec; + + // Use ProgramAddressFactory to provide stack space final AddressFactory addrFactory = new ProgramAddressFactory(lang, cspec, s -> null); super.setProgramArchitecture(new ProgramArchitecture() { @@ -733,6 +735,10 @@ else if (updateOption == LanguageUpdateOption.TRANSLATE) { } } + // Use ProgramAddressFactory to provide stack space + final AddressFactory addrFactory = + new ProgramAddressFactory(language, compilerSpec, s -> null); + ProgramArchitecture programArchitecture = new ProgramArchitecture() { @Override @@ -747,7 +753,7 @@ public CompilerSpec getCompilerSpec() { @Override public AddressFactory getAddressFactory() { - return language.getAddressFactory(); + return addrFactory; } }; From 971bad82b23354e06fd10520fcc433c7de7132dc Mon Sep 17 00:00:00 2001 From: axd1x8a Date: Fri, 26 Jun 2026 01:53:22 +0300 Subject: [PATCH 046/111] Remove explicit socket buffer locks in remote block stream handles --- .../server/stream/RemoteBlockStreamHandle.java | 12 ++---------- .../server/stream/RemoteInputBlockStreamHandle.java | 3 --- .../server/stream/RemoteOutputBlockStreamHandle.java | 3 --- 3 files changed, 2 insertions(+), 16 deletions(-) diff --git a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/stream/RemoteBlockStreamHandle.java b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/stream/RemoteBlockStreamHandle.java index acf3a080c18..e8a5f2d532c 100644 --- a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/stream/RemoteBlockStreamHandle.java +++ b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/stream/RemoteBlockStreamHandle.java @@ -4,9 +4,9 @@ * 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. @@ -133,14 +133,6 @@ int getBlockSize() { return blockSize; } - /** - * Get the preferred socket send/receive buffer size to be used - * @return preferred socket send/receive buffer size - */ - protected int getPreferredBufferSize() { - return (getBlockSize() + 4) * 12; - } - /** * Generate a random number for use as a block stream authentication token. * @return random value diff --git a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/stream/RemoteInputBlockStreamHandle.java b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/stream/RemoteInputBlockStreamHandle.java index e18501ef831..f98e8b9d32d 100644 --- a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/stream/RemoteInputBlockStreamHandle.java +++ b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/stream/RemoteInputBlockStreamHandle.java @@ -124,7 +124,6 @@ public int getBlockSize() { public InputBlockStream openBlockStream() throws IOException { Socket socket = connect(); - socket.setReceiveBufferSize(getPreferredBufferSize()); return new ClientInputBlockStream(socket); } @@ -135,8 +134,6 @@ void serveBlockStream(Socket socket, BlockStream blockStream) throws IOException throw new IllegalArgumentException("expected InputBlockStream"); } - socket.setSendBufferSize(getPreferredBufferSize()); - InputBlockStream inputBlockStream = (InputBlockStream) blockStream; try (OutputStream out = getBlockInputStream(socket)) { diff --git a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/stream/RemoteOutputBlockStreamHandle.java b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/stream/RemoteOutputBlockStreamHandle.java index 9cc1a5b6e3c..ae83a34e943 100644 --- a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/stream/RemoteOutputBlockStreamHandle.java +++ b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/stream/RemoteOutputBlockStreamHandle.java @@ -109,7 +109,6 @@ public void writeBlock(BufferFileBlock block) throws IOException { public OutputBlockStream openBlockStream() throws IOException { Socket socket = connect(); - socket.setSendBufferSize(getPreferredBufferSize()); return new ClientOutputBlockStream(socket); } @@ -121,8 +120,6 @@ void serveBlockStream(Socket socket, BlockStream blockStream) throws IOException throw new IllegalArgumentException("expected OutputBlockStream"); } - socket.setReceiveBufferSize(getPreferredBufferSize()); - OutputBlockStream outputBlockStream = (OutputBlockStream) blockStream; try (InputStream in = getBlockInputStream(socket)) { From ae16e34aef7b0443ea3463f992b8f8c5dbf2c70d Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Mon, 29 Jun 2026 06:01:20 -0400 Subject: [PATCH 047/111] GP-0: Fixing PyGhidra run config launch for newest Eclipse --- Ghidra/Features/PyGhidra/src/main/py/src/pyghidra/launcher.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Ghidra/Features/PyGhidra/src/main/py/src/pyghidra/launcher.py b/Ghidra/Features/PyGhidra/src/main/py/src/pyghidra/launcher.py index e8a3ebee7eb..a66118f9abb 100644 --- a/Ghidra/Features/PyGhidra/src/main/py/src/pyghidra/launcher.py +++ b/Ghidra/Features/PyGhidra/src/main/py/src/pyghidra/launcher.py @@ -252,6 +252,8 @@ def _parse_dev_args(self) -> List[str]: if "org.eclipse.jdt.launching.VM_ARGUMENTS" in line: _, _, value = line.partition("value=") value = value.removesuffix("/>") + if value.startswith('"') and value.endswith('"'): + value = value[1:-1] return html.unescape(value).split() raise Exception("org.eclipse.jdt.launching.VM_ARGUMENTS not found") From 144d4a1b54c379941a3d54b6e272731b0cb035b1 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Mon, 29 Jun 2026 06:19:02 -0400 Subject: [PATCH 048/111] GP-0: Javadoc fix --- .../Framework/Pty/src/main/java/ghidra/pty/ShellUtils.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Ghidra/Framework/Pty/src/main/java/ghidra/pty/ShellUtils.java b/Ghidra/Framework/Pty/src/main/java/ghidra/pty/ShellUtils.java index e3a2e6b3b87..d4d26d22366 100644 --- a/Ghidra/Framework/Pty/src/main/java/ghidra/pty/ShellUtils.java +++ b/Ghidra/Framework/Pty/src/main/java/ghidra/pty/ShellUtils.java @@ -210,10 +210,8 @@ public String generateArgument(String a) { }, /** * Plain Windows command-line arguments for the C runtime - *

    - * See CommandLineToArgvW - * function + * + * @see CommandLineToArgvWfunction */ WINDOWS { /** From 9767a16bde0762e4e1026979376c40baa8129f0e Mon Sep 17 00:00:00 2001 From: Dan <46821332+nsadeveloper789@users.noreply.github.com> Date: Mon, 29 Jun 2026 12:48:07 +0000 Subject: [PATCH 049/111] GP-6886: Fix OOM in ObjectStorageStreamAdapter --- .../remote/GhidraObjectInputFilter.java | 22 +- .../util/ObjectStorageStreamAdapter.java | 694 ++++++++++-------- 2 files changed, 404 insertions(+), 312 deletions(-) diff --git a/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/remote/GhidraObjectInputFilter.java b/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/remote/GhidraObjectInputFilter.java index 72219456459..9f708d1864e 100644 --- a/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/remote/GhidraObjectInputFilter.java +++ b/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/remote/GhidraObjectInputFilter.java @@ -28,6 +28,7 @@ import generic.jar.ResourceFile; import ghidra.framework.Application; +import ghidra.util.Msg; /** * {@link GhidraObjectInputFilter} provides global serial input filter for use with Ghidra server @@ -64,11 +65,24 @@ public class GhidraObjectInputFilter implements ObjectInputFilter { private static final String MAXDEPTH = "maxdepth"; private static final String MAXBYTES = "maxbytes"; + private static int getMaxArrayFromProperties() { + String limitStr = System.getProperty("ghidra.serial.array.limit", "200000"); + try { + return Integer.parseInt(limitStr); + } + catch (Exception e) { + Msg.error(GhidraObjectInputFilter.class, + "Could not parse ghidra.serial.array.limit: %s. A decimal integer is required" + .formatted(limitStr)); + } + return 200_000; + } + // NOTE: Be sure to update serialFilterREADME.md if values are updated. - private int MAXARRAY_DEFAULT = 200_000; - private int MAXREFS_DEFAULT = 10_000; - private int MAXDEPTH_DEFAULT = 50; - private int MAXBYTES_DEFAULT = 32 * 1024 * 1024; // 32MB + public static final int MAXARRAY_DEFAULT = getMaxArrayFromProperties(); + public static final int MAXREFS_DEFAULT = 10_000; + public static final int MAXDEPTH_DEFAULT = 50; + public static final int MAXBYTES_DEFAULT = 32 * 1024 * 1024; // 32MB private long maxArray; private long maxRefs; diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/ObjectStorageStreamAdapter.java b/Ghidra/Framework/Generic/src/main/java/ghidra/util/ObjectStorageStreamAdapter.java index 9010b861aeb..9a8bc990930 100644 --- a/Ghidra/Framework/Generic/src/main/java/ghidra/util/ObjectStorageStreamAdapter.java +++ b/Ghidra/Framework/Generic/src/main/java/ghidra/util/ObjectStorageStreamAdapter.java @@ -4,9 +4,9 @@ * 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. @@ -18,376 +18,454 @@ import java.io.*; /** - * Implementation for ObjectStorage to save and restore Strings and - * Java primitives using an ObjectOutputStream and ObjectInputStream, - * respectively. + * Implementation for ObjectStorage to save and restore Strings and Java primitives using an + * ObjectOutputStream and ObjectInputStream, respectively. * * */ public class ObjectStorageStreamAdapter implements ObjectStorage { + + private static int getMaxArrayFromProperties() { + String limitStr = System.getProperty("ghidra.serial.array.limit", "200000"); + try { + return Integer.parseInt(limitStr); + } + catch (Exception e) { + Msg.error(ObjectStorageStreamAdapter.class, + "Could not parse ghidra.serial.array.limit: %s. A decimal integer is required" + .formatted(limitStr)); + } + return 200_000; + } + + public static final int MAXARRAY = getMaxArrayFromProperties(); + ObjectOutputStream out; ObjectInputStream in; - /** - * Constructor for ObjectStorageStreamAdapter. - * @param out output stream to write to - */ - public ObjectStorageStreamAdapter(ObjectOutputStream out) { - this.out = out; - } - /** - * Constructor for new ObjectStorageStreamAdapter - * @param in input stream to read from - */ - public ObjectStorageStreamAdapter(ObjectInputStream in) { - this.in = in; - } - @Override - public void putInt(int value) { - try { - out.writeInt(value); - } catch (IOException e) {} - } + /** + * Constructor for ObjectStorageStreamAdapter. + * + * @param out output stream to write to + */ + public ObjectStorageStreamAdapter(ObjectOutputStream out) { + this.out = out; + } + + /** + * Constructor for new ObjectStorageStreamAdapter + * + * @param in input stream to read from + */ + public ObjectStorageStreamAdapter(ObjectInputStream in) { + this.in = in; + } @Override - public void putByte(byte value) { - try { - out.writeByte(value); - } catch (IOException e) {} - } + public void putInt(int value) { + try { + out.writeInt(value); + } + catch (IOException e) { + } + } @Override - public void putShort(short value) { - try { - out.writeShort(value); - } catch (IOException e) {} - } + public void putByte(byte value) { + try { + out.writeByte(value); + } + catch (IOException e) { + } + } @Override - public void putLong(long value) { - try { - out.writeLong(value); - } catch (IOException e) {} - } + public void putShort(short value) { + try { + out.writeShort(value); + } + catch (IOException e) { + } + } @Override - public void putString(String value) { - try { - out.writeObject(value); - } catch (IOException e) {} - } + public void putLong(long value) { + try { + out.writeLong(value); + } + catch (IOException e) { + } + } @Override - public void putBoolean(boolean value) { - try { - out.writeBoolean(value); - } catch (IOException e) {} - } + public void putString(String value) { + try { + out.writeObject(value); + } + catch (IOException e) { + } + } @Override - public void putFloat(float value) { - try { - out.writeFloat(value); - } catch (IOException e) {} - } + public void putBoolean(boolean value) { + try { + out.writeBoolean(value); + } + catch (IOException e) { + } + } @Override - public void putDouble(double value) { - try { - out.writeDouble(value); - } catch (IOException e) {} - } + public void putFloat(float value) { + try { + out.writeFloat(value); + } + catch (IOException e) { + } + } @Override - public int getInt() { - try { - return in.readInt(); - } catch (IOException e) { - return 0; - } - } + public void putDouble(double value) { + try { + out.writeDouble(value); + } + catch (IOException e) { + } + } @Override - public byte getByte() { - try { - return in.readByte(); - } catch (IOException e) { - return (byte)0; - } - } + public int getInt() { + try { + return in.readInt(); + } + catch (IOException e) { + return 0; + } + } @Override - public short getShort() { - try { - return in.readShort(); - } catch (IOException e) { - return (short)0; - } - } + public byte getByte() { + try { + return in.readByte(); + } + catch (IOException e) { + return (byte) 0; + } + } @Override - public long getLong() { - try { - return in.readLong(); - } catch (IOException e) { - return 0; - } - } + public short getShort() { + try { + return in.readShort(); + } + catch (IOException e) { + return (short) 0; + } + } @Override - public boolean getBoolean() { - try { - return in.readBoolean(); - } catch (IOException e) { - return false; - } - } + public long getLong() { + try { + return in.readLong(); + } + catch (IOException e) { + return 0; + } + } @Override - public String getString() { - try { - return (String)in.readObject(); - }catch(Exception e) { - return null; - } - } + public boolean getBoolean() { + try { + return in.readBoolean(); + } + catch (IOException e) { + return false; + } + } @Override - public float getFloat() { - try { - return in.readFloat(); - } catch (IOException e) { - return 0; - } - } + public String getString() { + try { + return (String) in.readObject(); + } + catch (Exception e) { + return null; + } + } @Override - public double getDouble() { - try { - return in.readDouble(); - } catch (IOException e) { - return 0.0; - } - } + public float getFloat() { + try { + return in.readFloat(); + } + catch (IOException e) { + return 0; + } + } @Override - public void putInts(int[] value) { - try { - if (value == null) { - out.writeInt(-1); - return; - } - out.writeInt(value.length); - for (int i = 0; i < value.length; i++) { - out.writeInt(value[i]); - } - } catch (IOException e) {} - } + public double getDouble() { + try { + return in.readDouble(); + } + catch (IOException e) { + return 0.0; + } + } + + protected void checkWriteArrayLength(int n) throws IOException { + if (n > MAXARRAY) { + throw new IOException("Array size %d exceeds max of %d".formatted(n, MAXARRAY)); + } + out.writeInt(n); + } @Override - public void putBytes(byte[] value) { - try { - if (value == null) { - out.writeInt(-1); - return; - } - out.writeInt(value.length); - for (int i = 0; i < value.length; i++) { - out.writeByte(value[i]); - } - } catch (IOException e) {} - } + public void putInts(int[] value) { + try { + if (value == null) { + out.writeInt(-1); + return; + } + checkWriteArrayLength(value.length); + for (int i = 0; i < value.length; i++) { + out.writeInt(value[i]); + } + } + catch (IOException e) { + } + } @Override - public void putShorts(short[] value) { - try { - if (value == null) { - out.writeInt(-1); - return; - } - out.writeInt(value.length); - for (int i = 0; i < value.length; i++) { - out.writeShort(value[i]); - } - } catch (IOException e) {} - - } + public void putBytes(byte[] value) { + try { + if (value == null) { + out.writeInt(-1); + return; + } + checkWriteArrayLength(value.length); + for (int i = 0; i < value.length; i++) { + out.writeByte(value[i]); + } + } + catch (IOException e) { + } + } @Override - public void putLongs(long[] value) { - try { - if (value == null) { - out.writeInt(-1); - return; - } - out.writeInt(value.length); - for (int i = 0; i < value.length; i++) { - out.writeLong(value[i]); - } - } catch (IOException e) {} - - } + public void putShorts(short[] value) { + try { + if (value == null) { + out.writeInt(-1); + return; + } + checkWriteArrayLength(value.length); + for (int i = 0; i < value.length; i++) { + out.writeShort(value[i]); + } + } + catch (IOException e) { + } + + } @Override - public void putFloats(float[] value) { - try { - if (value == null) { - out.writeInt(-1); - return; - } - out.writeInt(value.length); - for (int i = 0; i < value.length; i++) { - out.writeFloat(value[i]); - } - } catch (IOException e) {} - - } + public void putLongs(long[] value) { + try { + if (value == null) { + out.writeInt(-1); + return; + } + checkWriteArrayLength(value.length); + for (int i = 0; i < value.length; i++) { + out.writeLong(value[i]); + } + } + catch (IOException e) { + } + + } @Override - public void putDoubles(double[] value) { - try { - if (value == null) { - out.writeInt(-1); - return; - } - out.writeInt(value.length); - for (int i = 0; i < value.length; i++) { - out.writeDouble(value[i]); - } - } catch (IOException e) {} - } + public void putFloats(float[] value) { + try { + if (value == null) { + out.writeInt(-1); + return; + } + checkWriteArrayLength(value.length); + for (int i = 0; i < value.length; i++) { + out.writeFloat(value[i]); + } + } + catch (IOException e) { + } + + } @Override - public void putStrings(String[] value) { - try { - if (value == null) { - out.writeInt(-1); - return; - } - out.writeInt(value.length); - for (int i = 0; i < value.length; i++) { - out.writeObject(value[i]); - } - } catch (IOException e) {} - } + public void putDoubles(double[] value) { + try { + if (value == null) { + out.writeInt(-1); + return; + } + checkWriteArrayLength(value.length); + for (int i = 0; i < value.length; i++) { + out.writeDouble(value[i]); + } + } + catch (IOException e) { + } + } @Override - public int[] getInts() { - try { - int n = in.readInt(); - if (n < 0) { - return null; - } - int[] r = new int[n]; - for(int i=0;i MAXARRAY) { + throw new IOException("Array size %d exceeds max of %d".formatted(n, MAXARRAY)); + } + return n; + } @Override - public byte[] getBytes() { - try { - int n = in.readInt(); - if (n < 0) { - return null; - } - byte[] r = new byte[n]; - for(int i=0;i Date: Mon, 29 Jun 2026 10:09:09 -0400 Subject: [PATCH 050/111] GP-7015: Corrected rex xchg to nop --- Ghidra/Processors/x86/data/languages/ia.sinc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ghidra/Processors/x86/data/languages/ia.sinc b/Ghidra/Processors/x86/data/languages/ia.sinc index 7763d811f92..6f0be02112c 100644 --- a/Ghidra/Processors/x86/data/languages/ia.sinc +++ b/Ghidra/Processors/x86/data/languages/ia.sinc @@ -4215,7 +4215,7 @@ define pcodeop swap_bytes; :NEG Rmr64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0xf7; mod=3 & Rmr64 & reg_opcode=3 { negflags(Rmr64); Rmr64 = -Rmr64; resultflags(Rmr64); } @endif -:NOP is vexMode=0 & byte=0x90 & (mandover=0 | mandover=4 | mandover=1) & (rexprefix=0 | rexWRXBprefix=8) { } +:NOP is vexMode=0 & byte=0x90 & (mandover=0 | mandover=4 | mandover=1) & (rexprefix=0 | rexWRXBprefix=8 | rexWRXBprefix=0) { } :NOP rm16 is vexMode=0 & mandover & opsize=0 & byte=0x0f; high5=3; rm16 ... { } :NOP rm32 is vexMode=0 & mandover & opsize=1 & byte=0x0f; high5=3; rm32 ... { } :NOP^"/reserved" rm16 is vexMode=0 & mandover & opsize=0 & byte=0x0f; byte=0x18; rm16 & reg_opcode_hb=1 ... { } From 6c1352fc90d1340b96e8662bb6e94dfe0c5e18ba Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Mon, 29 Jun 2026 10:24:13 -0400 Subject: [PATCH 051/111] GP-7016: Corrected VPEXTRW to ignore the VEX.W1 bit --- Ghidra/Processors/x86/data/languages/avx.sinc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Ghidra/Processors/x86/data/languages/avx.sinc b/Ghidra/Processors/x86/data/languages/avx.sinc index 962aee4b1c3..59b3dd6f07d 100644 --- a/Ghidra/Processors/x86/data/languages/avx.sinc +++ b/Ghidra/Processors/x86/data/languages/avx.sinc @@ -1871,14 +1871,14 @@ define pcodeop vpextrq_avx ; # PEXTRW 4-277 PAGE 1397 LINE 72478 define pcodeop vpextrw_avx ; -:VPEXTRW Reg32, XmmReg2, imm8 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W0); byte=0xC5; Reg32 & (mod=0x3 & XmmReg2); imm8 +:VPEXTRW Reg32, XmmReg2, imm8 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG); byte=0xC5; Reg32 & (mod=0x3 & XmmReg2); imm8 { Reg32 = vpextrw_avx( XmmReg2, imm8:1 ); # TODO Reg64 = zext(Reg32) } # PEXTRW 4-277 PAGE 1397 LINE 72483 -:VPEXTRW Reg32_m16, XmmReg1, imm8 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W0); byte=0x15; XmmReg1 ... & Reg32_m16; imm8 +:VPEXTRW Reg32_m16, XmmReg1, imm8 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_WIG); byte=0x15; XmmReg1 ... & Reg32_m16; imm8 { Reg32_m16 = vpextrw_avx( XmmReg1, imm8:1 ); # TODO Reg64 = zext(Reg32) From f9ed6f4170cf0feffd012ced183ce02501fc22f1 Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Mon, 29 Jun 2026 12:35:55 -0400 Subject: [PATCH 052/111] GP-7018: Fixed register opsize for mov to/from segment registers --- Ghidra/Processors/x86/data/languages/ia.sinc | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/Ghidra/Processors/x86/data/languages/ia.sinc b/Ghidra/Processors/x86/data/languages/ia.sinc index 7763d811f92..7b071caba30 100644 --- a/Ghidra/Processors/x86/data/languages/ia.sinc +++ b/Ghidra/Processors/x86/data/languages/ia.sinc @@ -4035,8 +4035,18 @@ define pcodeop TaskRegister; @ifdef IA64 :MOV Reg64,rm64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0x8b; rm64 & Reg64 ... { Reg64 = rm64; } @endif -:MOV rm16,Sreg is vexMode=0 & byte=0x8c; rm16 & Sreg ... { rm16 = Sreg; } -:MOV Sreg,rm16 is vexMode=0 & byte=0x8e; rm16 & Sreg ... { Sreg=rm16; } +:MOV m16,Sreg is vexMode=0 & byte=0x8c; (mod != 3 & Sreg) ... & m16 { m16 = Sreg; } +:MOV Rmr16,Sreg is vexMode=0 & opsize=0 & byte=0x8c; mod=3 & Rmr16 & Sreg { Rmr16 = Sreg; } +:MOV Rmr32,Sreg is vexMode=0 & opsize=1 & byte=0x8c; mod=3 & Rmr32 & check_Rmr32_dest & Sreg { Rmr32 = zext(Sreg); build check_Rmr32_dest; } +@ifdef IA64 +:MOV Rmr64,Sreg is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0x8c; mod=3 & Rmr64 & Sreg { Rmr64 = zext(Sreg); } +@endif +:MOV Sreg,m16 is vexMode=0 & byte=0x8e; (mod != 3 & Sreg) ... & m16 { Sreg = m16; } +:MOV Rmr16,Sreg is vexMode=0 & opsize=0 & byte=0x8e; mod=3 & Rmr16 & Sreg { Sreg = Rmr16; } +:MOV Rmr32,Sreg is vexMode=0 & opsize=1 & byte=0x8e; mod=3 & Rmr32 & Sreg { Sreg = Rmr32(0); } +@ifdef IA64 +:MOV Rmr64,Sreg is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0x8e; mod=3 & Rmr64 & Sreg { Sreg = Rmr64(0); } +@endif :MOV AL,moffs8 is vexMode=0 & byte=0xa0; AL & moffs8 { AL=moffs8; } :MOV AX,moffs16 is vexMode=0 & opsize=0 & byte=0xa1; AX & moffs16 { AX=moffs16; } :MOV EAX,moffs32 is vexMode=0 & opsize=1 & byte=0xa1; EAX & check_EAX_dest & moffs32 { EAX=moffs32; build check_EAX_dest; } From 154f9fb0ca5de0849b76d47305658629ebde26ad Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Wed, 15 Apr 2026 15:34:29 +0000 Subject: [PATCH 053/111] GP-6699: Fixed SuperH4 bsr instruction return address --- Ghidra/Processors/SuperH4/data/languages/SuperH4.sinc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ghidra/Processors/SuperH4/data/languages/SuperH4.sinc b/Ghidra/Processors/SuperH4/data/languages/SuperH4.sinc index 1b0e76cda82..a0dac54792f 100644 --- a/Ghidra/Processors/SuperH4/data/languages/SuperH4.sinc +++ b/Ghidra/Processors/SuperH4/data/languages/SuperH4.sinc @@ -749,7 +749,7 @@ N_0txx: r0",@"^N_0 is r0 & N_0 { tmp:4 = N_0; export tmp; } # text bsr # arch arch_sh_up :bsr I_1tbranch is OP_0=0xb & I_1tbranch { - + PR = inst_next; delayslot(1); call I_1tbranch; } From 720b1a5f91304cdce0f3c8f654ab76383dbeb06a Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Tue, 30 Jun 2026 11:27:49 -0400 Subject: [PATCH 054/111] GP-6914: Added missing PowerPC v3.0 and v3.0B/C instructions. --- .../PowerPC/data/languages/altivec.sinc | 9 ++ .../PowerPC/data/languages/ppc_common.sinc | 18 ++- .../data/languages/ppc_instructions.sinc | 125 +++++++++++------ .../PowerPC/data/languages/ppc_isa.sinc | 132 +++++++++++++++++- 4 files changed, 233 insertions(+), 51 deletions(-) diff --git a/Ghidra/Processors/PowerPC/data/languages/altivec.sinc b/Ghidra/Processors/PowerPC/data/languages/altivec.sinc index 2acecf52b0e..1e5a190da0b 100644 --- a/Ghidra/Processors/PowerPC/data/languages/altivec.sinc +++ b/Ghidra/Processors/PowerPC/data/languages/altivec.sinc @@ -1850,3 +1850,12 @@ define pcodeop altv300_71; :vsrv vrD,vrA,vrB is OP=4 & vrD & vrA & vrB & XOP_0_10=1796 { vrD = altv300_71(vrA,vrB); } + +# vmsumudm 000100 ..... ..... ..... ..... 100011 +# Vector Multiply Sum Unsigned Doubleword Modulo +:vmsumudm vrD,vrA,vrB,vrC is OP=4 & vrD & vrA & vrB & vrC & XOP_0_5=35 { + local temp:16 = zext(vrC); + temp = temp + zext(vrA[ 0,32])*zext(vrB[ 0,32]); + temp = temp + zext(vrA[32,32])*zext(vrB[32,32]); + vrD = temp; +} diff --git a/Ghidra/Processors/PowerPC/data/languages/ppc_common.sinc b/Ghidra/Processors/PowerPC/data/languages/ppc_common.sinc index e7f95807135..cbcfd2bd13a 100644 --- a/Ghidra/Processors/PowerPC/data/languages/ppc_common.sinc +++ b/Ghidra/Processors/PowerPC/data/languages/ppc_common.sinc @@ -47,7 +47,7 @@ define register offset=0x500 size=1 [ fp_fx fp_fex fp_vx fp_ox fp_cc0 fp_cc1 fp_cc2 fp_cc3 fp_reserve1 fp_vxsoft fp_vxsqrt fp_vxcvi fp_ve fp_oe fp_ue fp_ze - fp_xe fp_ni fp_rn0 fp_rn1 ]; + fp_xe fp_ni fp_rn0 fp_rn1 fp_drn ]; define register offset = 0x700 size =$(REGISTER_SIZE) [MSR]; define register offset = 0x720 size=$(REGISTER_SIZE) [RESERVE_ADDRESS]; @@ -676,6 +676,7 @@ define token instr(32) CT=(21,25) CT2=(21,24) CX=(3,3) + CYex=(9,10) D0=(6,15) signed D1=(16,20) D2=(0,0) @@ -690,6 +691,7 @@ define token instr(32) DM2=(2,2) DQ=(4,15) DQs=(4,15) signed + DRM=(11,13) DS=(2,15) DSs=(2,15) signed DX=(16,20) @@ -713,6 +715,7 @@ define token instr(32) fS=(21,25) fT=(21,25) IMM=(11,15) + IMM4=(11,14) EVUIMM=(11,15) BU_UIMM=(16,20) @@ -724,6 +727,7 @@ define token instr(32) L= (21,22) L2=(21,21) L16=(16,17) + LBIT=(16,16) LEV=(5,11) LI=(2,25) signed LK=(0,0) @@ -743,6 +747,7 @@ define token instr(32) RA=(16,20) RB=(11,15) + RM=(11,12) RS=(21,25) RT=(21,25) R0=(0,0) @@ -1780,8 +1785,7 @@ macro storeRegisterPartial(reg, ea, sa) { ea = ea + 4; } - -macro packbits( D,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15, + macro packbits( D,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15, a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30,a31) { D = zext(a31) & 1; D=D|(zext(a0)&1)<<31; D=D|(zext(a1)&1)<<30; D=D|(zext(a2)&1)<<29; D=D|(zext(a3)&1)<<28; @@ -1793,6 +1797,7 @@ macro packbits( D,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15, D=D|(zext(a24)&1)<<7; D=D|(zext(a25)&1)<<6; D=D|(zext(a26)&1)<<5; D=D|(zext(a27)&1)<<4; D=D|(zext(a28)&1)<<3; D=D|(zext(a29)&1)<<2; D=D|(zext(a30)&1)<<1; } + macro unpackbits(D,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15, a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30,a31) { @@ -1803,13 +1808,15 @@ macro unpackbits(D,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15, a16=(D&0x8000)!=0; a17=(D&0x4000)!=0; a18=(D&0x2000)!=0; a19=(D&0x1000)!=0; a20=(D&0x800)!=0; a21=(D&0x400)!=0; a22=(D&0x200)!=0; a23=(D&0x100)!=0; a24=(D&0x80)!=0; a25=(D&0x40)!=0; a26=(D&0x20)!=0; a27=(D&0x10)!=0; - a28=(D&0x8)!=0; a29=(D&0x4)!=0; a30=(D&0x2)!=0; a31=(D&0x1)!=0; } + a28=(D&0x8)!=0; a29=(D&0x4)!=0; a30=(D&0x2)!=0; a31=(D&0x1)!=0; + } macro packFPSCR(tmp) { packbits(tmp, fp_fx, fp_fex, fp_vx, fp_ox, fp_ux, fp_zx, fp_xx, fp_vxsnan, fp_vxisi, fp_vxidi, fp_vxzdz, fp_vximz, fp_vxvc, fp_fr, fp_fi, fp_c, fp_cc0, fp_cc1, fp_cc2, fp_cc3, fp_reserve1, fp_vxsoft, fp_vxsqrt, fp_vxcvi, fp_ve, fp_oe, fp_ue, fp_ze, fp_xe, fp_ni, fp_rn0, fp_rn1); + tmp[32,3] = fp_drn; } macro unpackFPSCR(tmp) { unpackbits(tmp, fp_fx, fp_fex, fp_vx, fp_ox, @@ -1819,7 +1826,8 @@ macro unpackFPSCR(tmp) { fp_cc0, fp_cc1, fp_cc2, fp_cc3, fp_reserve1, fp_vxsoft, fp_vxsqrt, fp_vxcvi, fp_ve, fp_oe, fp_ue, fp_ze, - fp_xe, fp_ni, fp_rn0, fp_rn1); + fp_xe, fp_ni, fp_rn0, fp_rn1); + fp_drn = tmp[32,3]; } diff --git a/Ghidra/Processors/PowerPC/data/languages/ppc_instructions.sinc b/Ghidra/Processors/PowerPC/data/languages/ppc_instructions.sinc index fd17f4fdc7e..736c7cce31c 100644 --- a/Ghidra/Processors/PowerPC/data/languages/ppc_instructions.sinc +++ b/Ghidra/Processors/PowerPC/data/languages/ppc_instructions.sinc @@ -2401,17 +2401,17 @@ define pcodeop lswxOp; #mffs fD 0xfc 00 04 8e :mffs fD is $(NOTVLE) & OP=63 & fD & BITS_11_20=0 & XOP_1_10=583 & Rc=0 { - tmp:4 = 0; + tmp:8 = 0; packFPSCR(tmp); - fD = zext(tmp); + fD = tmp; } #mffs. fD 0xfc 00 04 8f :mffs. fD is $(NOTVLE) & OP=63 & fD & BITS_11_20=0 & XOP_1_10=583 & Rc=1 { - tmp:4 = 0; + tmp:8 = 0; packFPSCR(tmp); - fD = zext(tmp); + fD = tmp; cr1flags(); } @@ -2489,69 +2489,113 @@ define pcodeop lswxOp; #mtfsf 10,fr0 0xfc 00 05 8e :mtfsf FM,fB is $(NOTVLE) & OP=63 & BIT_25=0 & FM & FM0 & FM1 & FM2 & FM3 & FM4 & FM5 & FM6 & FM7 & BIT_16=0 & fB & XOP_1_10=711 & Rc=0 { - tmp:4 = 0; + tmp:8 = 0; packFPSCR(tmp); - mask0:4 = zext((FM0:1 == 1)* 0xf) << 28; - mask1:4 = zext((FM1:1 == 1)* 0xf) << 24; - mask2:4 = zext((FM2:1 == 1)* 0xf) << 20; - mask3:4 = zext((FM3:1 == 1)* 0xf) << 16; - mask4:4 = zext((FM4:1 == 1)* 0xf) << 12; - mask5:4 = zext((FM5:1 == 1)* 0xf) << 8; - mask6:4 = zext((FM6:1 == 1)* 0xf) << 4; - mask7:4 = zext((FM7:1 == 1)* 0xf); + mask0:8 = zext((FM0:1 == 1)* 0xf) << 28; + mask1:8 = zext((FM1:1 == 1)* 0xf) << 24; + mask2:8 = zext((FM2:1 == 1)* 0xf) << 20; + mask3:8 = zext((FM3:1 == 1)* 0xf) << 16; + mask4:8 = zext((FM4:1 == 1)* 0xf) << 12; + mask5:8 = zext((FM5:1 == 1)* 0xf) << 8; + mask6:8 = zext((FM6:1 == 1)* 0xf) << 4; + mask7:8 = zext((FM7:1 == 1)* 0xf); - mask:4 = mask0 | mask1 | mask2 | mask3 | mask4 | mask5 | mask6 | mask7; + mask:8 = mask0 | mask1 | mask2 | mask3 | mask4 | mask5 | mask6 | mask7; - tmp1:4 = fB:4; - tmp2:4 = (tmp & ~mask) | (tmp1 & mask); + tmp1:8 = fB; + tmp2:8 = (tmp & ~mask) | (tmp1 & mask); + unpackFPSCR(tmp2); +} + +:mtfsf FM,fB,1 is $(NOTVLE) & OP=63 & BIT_25=0 & FM & FM0 & FM1 & FM2 & FM3 & FM4 & FM5 & FM6 & FM7 & BIT_16=1 & fB & XOP_1_10=711 & Rc=0 +{ + tmp:8 = 0; + packFPSCR(tmp); + + mask0:8 = zext((FM0:1 == 1)* 0xf) << 60; + mask1:8 = zext((FM1:1 == 1)* 0xf) << 56; + mask2:8 = zext((FM2:1 == 1)* 0xf) << 52; + mask3:8 = zext((FM3:1 == 1)* 0xf) << 48; + mask4:8 = zext((FM4:1 == 1)* 0xf) << 44; + mask5:8 = zext((FM5:1 == 1)* 0xf) << 40; + mask6:8 = zext((FM6:1 == 1)* 0xf) << 36; + mask7:8 = zext((FM7:1 == 1)* 0xf) << 32; + + mask:8 = mask0 | mask1 | mask2 | mask3 | mask4 | mask5 | mask6 | mask7; + + tmp1:8 = fB:8; + tmp2:8 = (tmp & ~mask) | (tmp1 & mask); unpackFPSCR(tmp2); } #mtfsf. 10,fr0 0xfc 00 05 8f :mtfsf. FM,fB is $(NOTVLE) & OP=63 & BIT_25=0 & FM & FM0 & FM1 & FM2 & FM3 & FM4 & FM5 & FM6 & FM7 & BIT_16=0 & fB & XOP_1_10=711 & Rc=1 { - tmp:4 = 0; + tmp:8 = 0; packFPSCR(tmp); - mask0:4 = zext((FM0:1 == 1)* 0xf) << 28; - mask1:4 = zext((FM1:1 == 1)* 0xf) << 24; - mask2:4 = zext((FM2:1 == 1)* 0xf) << 20; - mask3:4 = zext((FM3:1 == 1)* 0xf) << 16; - mask4:4 = zext((FM4:1 == 1)* 0xf) << 12; - mask5:4 = zext((FM5:1 == 1)* 0xf) << 8; - mask6:4 = zext((FM6:1 == 1)* 0xf) << 4; - mask7:4 = zext((FM7:1 == 1)* 0xf); + mask0:8 = zext((FM0:1 == 1)* 0xf) << 28; + mask1:8 = zext((FM1:1 == 1)* 0xf) << 24; + mask2:8 = zext((FM2:1 == 1)* 0xf) << 20; + mask3:8 = zext((FM3:1 == 1)* 0xf) << 16; + mask4:8 = zext((FM4:1 == 1)* 0xf) << 12; + mask5:8 = zext((FM5:1 == 1)* 0xf) << 8; + mask6:8 = zext((FM6:1 == 1)* 0xf) << 4; + mask7:8 = zext((FM7:1 == 1)* 0xf); - mask:4 = mask0 | mask1 | mask2 | mask3 | mask4 | mask5 | mask6 | mask7; + mask:8 = mask0 | mask1 | mask2 | mask3 | mask4 | mask5 | mask6 | mask7; - tmp1:4 = fB:4; - tmp2:4 = (tmp & ~mask) | (tmp1 & mask); + tmp1:8 = fB:8; + tmp2:8 = (tmp & ~mask) | (tmp1 & mask); unpackFPSCR(tmp2); cr1flags(); } #mtfsfi 10,3 0xfc 00 01 0c -:mtfsfi crfD,IMM is $(NOTVLE) & OP=63 & crfD & BITS_16_22=0 & IMM & BIT_11=0 & XOP_1_10=134 & Rc=0 +:mtfsfi crfD,IMM4 is $(NOTVLE) & OP=63 & crfD & BITS_16_22=0 & IMM4 & BIT_11=0 & XOP_1_10=134 & Rc=0 { - tmp:4 = 0; + tmp:8 = 0; packFPSCR(tmp); shift:1 = 28-(crfD*4); - mask:4 = 0xf << shift; - tmp1:4 = IMM << shift; - tmp2:4 = (tmp & ~mask) | tmp1; + mask:8 = 0xf << shift; + tmp1:8 = IMM4 << shift; + tmp2:8 = (tmp & ~mask) | tmp1; + unpackFPSCR(tmp2); +} + +:mtfsfi crfD,IMM4,1 is $(NOTVLE) & OP=63 & crfD & BITS_16_22=0 & IMM4 & BIT_11=1 & XOP_1_10=134 & Rc=0 +{ + tmp:8 = 0; + packFPSCR(tmp); + shift:1 = 60-(crfD*4); + mask:8 = 0xf << shift; + tmp1:8 = IMM4 << shift; + tmp2:8 = (tmp & ~mask) | tmp1; unpackFPSCR(tmp2); } #mtfsfi. 10,3 0xfc 00 01 0d -:mtfsfi. crfD,IMM is $(NOTVLE) & OP=63 & crfD & BITS_16_22=0 & IMM & BIT_11=0 & XOP_1_10=134 & Rc=1 +:mtfsfi. crfD,IMM4 is $(NOTVLE) & OP=63 & crfD & BITS_16_22=0 & IMM4 & BIT_11=0 & XOP_1_10=134 & Rc=1 { - tmp:4 = 0; + tmp:8 = 0; packFPSCR(tmp); shift:1 = 28-(crfD*4); - mask:4 = 0xf << shift; - tmp1:4 = IMM << shift; - tmp2:4 = (tmp & ~mask) | tmp1; + mask:8 = 0xf << shift; + tmp1:8 = IMM4 << shift; + tmp2:8 = (tmp & ~mask) | tmp1; + unpackFPSCR(tmp2); + cr1flags(); +} + +:mtfsfi. crfD,IMM4,1 is $(NOTVLE) & OP=63 & crfD & BITS_16_22=0 & IMM4 & BIT_11=1 & XOP_1_10=134 & Rc=1 +{ + tmp:8 = 0; + packFPSCR(tmp); + shift:1 = 60-(crfD*4); + mask:8 = 0xf << shift; + tmp1:8 = IMM4 << shift; + tmp2:8 = (tmp & ~mask) | tmp1; unpackFPSCR(tmp2); cr1flags(); } @@ -3116,7 +3160,10 @@ CRM_val: crmval is CRM [crmval = CRM+0;] {export *[const]:1 crmval;} #sc 0x44 00 00 02 :sc LEV is $(NOTVLE) & OP=17 & BITS_12_25=0 & LEV & BITS_2_4=0 & BIT_1=1 & BIT_0=0 { - syscall(); + local lev:1 = LEV; + SRR0 = inst_next; + SRR1 = MSR; + syscall(lev); } #slbia 0x7C 00 03 E4 diff --git a/Ghidra/Processors/PowerPC/data/languages/ppc_isa.sinc b/Ghidra/Processors/PowerPC/data/languages/ppc_isa.sinc index bfce7736cf3..3fb587c690c 100644 --- a/Ghidra/Processors/PowerPC/data/languages/ppc_isa.sinc +++ b/Ghidra/Processors/PowerPC/data/languages/ppc_isa.sinc @@ -1131,7 +1131,7 @@ define pcodeop MessageClear; # binutils: a2.d: 548: 7c 00 51 9c msgsnd r10 # binutils: e500mc.d: 18: 7c 00 71 9c msgsnd r14 define pcodeop MessageSend; -:msgsnd B is OP=31 & BITS_21_25=0 & BITS_16_20=0 & B & XOP_1_10=206 & BIT_0=0 { MessageSend(); } +:msgsnd B is OP=31 & BITS_21_25=0 & BITS_16_20=0 & B & XOP_1_10=206 & BIT_0=0 { MessageSend(B); } # ======================================================================= @@ -2441,21 +2441,21 @@ define pcodeop InstructionCacheBlockLockSetX; } :cnttzw A,S is OP=31 & S & A & BITS_11_15=0 & XOP_1_10=538 & Rc=0 { - A = countTrailingZeros(S); + A = countTrailingZeros(S); } :cnttzw. A,S is OP=31 & S & A & BITS_11_15=0 & XOP_1_10=538 & Rc=1 { - A = countTrailingZeros(S); - cr0flags(A); + A = countTrailingZeros(S); + cr0flags(A); } :cnttzd A,S is OP=31 & S & A & BITS_11_15=0 & XOP_1_10=570 & Rc=0 { - A = countTrailingZeros(S); + A = countTrailingZeros(S); } :cnttzd. A,S is OP=31 & S & A & BITS_11_15=0 & XOP_1_10=570 & Rc=1 { - A = countTrailingZeros(S); - cr0flags(A); + A = countTrailingZeros(S); + cr0flags(A); } :copy RA_OR_ZERO,B,L2 is $(NOTVLE) & OP=31 & BITS_22_25=0 & BIT_0=0 & XOP_1_10=774 & RA_OR_ZERO & B & L2 { @@ -2580,6 +2580,23 @@ define pcodeop InstructionCacheBlockLockSetX; setCrBit(cr0, 2, 1); } +define pcodeop returnFromSyscallVectored; +:rfscv is $(NOTVLE) & OP=19 & BITS_11_25=0 & XOP_1_10=82 & BIT_0=0 +{ + MSR = returnFromSyscallVectored(MSR, CTR); + local ra = LR; + return[ra]; +} + +define pcodeop syscallVectored; +:scv LEV is $(NOTVLE) & OP=17 & BITS_12_25=0 & LEV & BITS_2_4=0 & BIT_1=0 & BIT_0=1 +{ + local lev:1 = LEV; + LR = inst_next; + CTR = MSR; + syscallVectored(lev); +} + :setb D,BFA is $(NOTVLE) & OP=31 & BITS_11_17=0 & BIT_0=0 & XOP_1_10=128 & D & BFA { tmpcr:8 = 1 << (8 * BFA:1); tmpr0:1 = (BFA & 0x8) != 0; @@ -2614,3 +2631,104 @@ define pcodeop InstructionCacheBlockLockSetX; :wait WC is $(NOTVLE) & OP=31 & BITS_23_25=0 & BITS_11_20=0 & BIT_0=0 & XOP_1_10=30 & WC { waitT(WC:1); } + +##### +# v3.0B/C instructions added + +# note: CY=0 is the only one currently defined. 1-3 are reserved +# addex 011111 ..... ..... ..... ..101 01010/ +:addex D, A, B, CYex is $(NOTVLE) & OP=31 & D & A & B & CYex & BIT_9=0 & BIT_10=0 & XOP_1_8=170 & BIT_0=0 { + local sum:$(REGISTER_SIZE) = A + B; + local carryOut = carry(A,B) | carry(sum, zext(xer_ov)); + D = sum + zext(xer_ov); + xer_ov = carryOut; +} + +@ifdef BIT_64 +# mffscdrn 111111 ..... 10100 ..... 10010 00111/ +define pcodeop mffscdrn; +:mffscdrn fT, fB is $(NOTVLE) & OP=63 & fT & BITS_16_20=20 & fB & XOP_1_10=583 & BIT_0=0 { + local tmp:8 = 0; + local _tmpDRM:1 = fB[29,3]; + packFPSCR(tmp); + fT = tmp & 0x7000000ff; + fp_drn = _tmpDRM; +} + +# mffscdrni 111111 ..... 10101 //... 10010 00111/ +:mffscdrni fT, DRM is $(NOTVLE) & OP=63 & fT & BITS_16_20=20 & BITS_13_15=0 & DRM & XOP_1_10=583 & BIT_0=0 { + local tmp:8 = 0; + local _tmpDRM:1 = DRM; + packFPSCR(tmp); + fT = tmp & 0x7000000ff; + fp_drn = _tmpDRM; +} + +# mffsce 111111 ..... 00001 ///// 10010 00111/ +:mffsce fT is $(NOTVLE) & OP=63 & fT & BITS_16_20=1 & BITS_11_15=0 & XOP_1_10=583 & BIT_0=0 { + tmp:8 = 0; + packFPSCR(tmp); + fT = tmp; + fp_ve=0; + fp_oe=0; + fp_ue=0; + fp_ze=0; + fp_xe=0; +} + +# mffscrn 111111 ..... 10110 ..... 10010 00111/ +:mffscrn fT, fB is $(NOTVLE) & OP=63 & fT & BITS_16_20=22 & fB & XOP_1_10=583 & BIT_0=0 { + tmp:8 = 0; + packFPSCR(tmp); + fT = tmp & 0x7000000ff; + fp_rn0=fB[1,1]; + fp_rn1=fB[0,1]; +} + +# mffscrni 111111 ..... 10111 ///.. 10010 00111/ +:mffscrni fT, RM is $(NOTVLE) & OP=63 & fT & BITS_16_20=23 & BITS_13_15=0 & RM & XOP_1_10=583 & BIT_0=0 { + tmp:8 = 0; + _tmpRM:1 = RM; + packFPSCR(tmp); + fT = tmp & 0x7000000ff; + fp_rn0=_tmpRM[0,1]; + fp_rn1=_tmpRM[1,1]; +} + + +:mffsl fT is $(NOTVLE) & OP=63 & fT & BITS_11_20=24 & XOP_1_10=583 & BIT_0=0 { + tmp:8 = 0; + packFPSCR(tmp); + fT = tmp & 0x7000000ff; +} +@endif + +# msgclru 011111 ///// ///// ..... 00011 01110/ +# Message Clear Ultravisor +:msgclru B is $(NOTVLE) & OP=31 & BITS_21_25=0 & BITS_16_20=0 & B & XOP_1_10=10 & BIT_0=0 { + MessageClear(B); +} + +# msgsndu 011111 ///// ///// ..... 00010 01110/ +# Message Send Ultravisor +:msgsndu B is $(NOTVLE) & OP=31 & BITS_21_25=0 & BITS_16_20=0 & B & XOP_1_10=78 & BIT_0=0 { + MessageSend(B); +} + +# urfid 000100 ..... ..... ..... ..... 100011 +# Ultravisor Return from Interrupt Doubleword +:rfid is $(NOTVLE) & OP=19 & BITS_11_25=0 & XOP_1_10=306 & BIT_0=0 +{ + MSR = returnFromInterrupt(MSR, SRR1); + local ra = SRR0; + return[ra]; +} + +# slbiag 011111 ..... ///// ..... 11010 10010/ +# SLB Invalidate All Global +define pcodeop SLBInvalidateAllGlobal; +:slbiag S, LBIT is $(NOTVLE) & OP=31 & S & BITS_17_20=0 & LBIT & BITS_11_15=0 & XOP_1_10=850 & BIT_0=0 { + SLBInvalidateAllGlobal(S, LBIT:1); +} + + From 43d043e941583ccfa974a1dc27ce34d78098deb6 Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Tue, 30 Jun 2026 14:40:20 -0400 Subject: [PATCH 055/111] GP-6876: Corrected operands for RISC-V floating point .w instructions --- .../RISCV/data/languages/riscv.rv32a.sinc | 40 +++++++++---------- .../RISCV/data/languages/riscv.rv32d.sinc | 20 +++++----- .../RISCV/data/languages/riscv.rv32f.sinc | 28 +++++++------ .../RISCV/data/languages/riscv.rv32q.sinc | 7 +++- .../RISCV/data/languages/riscv.rv64d.sinc | 5 ++- .../RISCV/data/languages/riscv.rv64f.sinc | 5 ++- .../RISCV/data/languages/riscv.rv64i.sinc | 8 ++-- .../RISCV/data/languages/riscv.table.sinc | 9 ----- 8 files changed, 61 insertions(+), 61 deletions(-) diff --git a/Ghidra/Processors/RISCV/data/languages/riscv.rv32a.sinc b/Ghidra/Processors/RISCV/data/languages/riscv.rv32a.sinc index 51960421b49..35194bb1c99 100644 --- a/Ghidra/Processors/RISCV/data/languages/riscv.rv32a.sinc +++ b/Ghidra/Processors/RISCV/data/languages/riscv.rv32a.sinc @@ -1,10 +1,10 @@ # RV32A Standard Extension # amoadd.w d,t,0(s) 0000202f fe00707f DWORD|DREF (0, 4) -:amoadd.w^aqrl rd,rs2W,(rs1) is rs1 & rs2W & rd & op0001=0x3 & op0204=0x3 & op0506=0x1 & funct3=0x2 & op2731=0 & aqrl +:amoadd.w^aqrl rd,rs2,(rs1) is rs1 & rs2 & rd & op0001=0x3 & op0204=0x3 & op0506=0x1 & funct3=0x2 & op2731=0 & aqrl { local tmprs1 = rs1; - local tmprs2 = rs2W; + local tmprs2:$(WXLEN) = rs2:$(WXLEN); local tmp:4 = *[ram]:4 tmprs1; assignW(rd, tmp); tmp = tmp + tmprs2; @@ -13,10 +13,10 @@ # amoand.w d,t,0(s) 6000202f fe00707f DWORD|DREF (0, 4) -:amoand.w^aqrl rd,rs2W,(rs1) is rs1 & rs2W & rd & op0001=0x3 & op0204=0x3 & op0506=0x1 & funct3=0x2 & op2731=0xc & aqrl +:amoand.w^aqrl rd,rs2,(rs1) is rs1 & rs2 & rd & op0001=0x3 & op0204=0x3 & op0506=0x1 & funct3=0x2 & op2731=0xc & aqrl { local tmprs1 = rs1; - local tmprs2 = rs2W; + local tmprs2:$(WXLEN) = rs2:$(WXLEN); local tmp:4 = *[ram]:4 tmprs1; assignW(rd, tmp); tmp = tmp & tmprs2; @@ -25,10 +25,10 @@ # amomax.w d,t,0(s) a000202f fe00707f DWORD|DREF (0, 4) -:amomax.w^aqrl rd,rs2W,(rs1) is rs1 & rs2W & rd & op0001=0x3 & op0204=0x3 & op0506=0x1 & funct3=0x2 & op2731=0x14 & aqrl +:amomax.w^aqrl rd,rs2,(rs1) is rs1 & rs2 & rd & op0001=0x3 & op0204=0x3 & op0506=0x1 & funct3=0x2 & op2731=0x14 & aqrl { local tmprs1 = rs1; - local tmprs2 = rs2W; + local tmprs2:$(WXLEN) = rs2:$(WXLEN); local tmp:4 = *[ram]:4 tmprs1; assignW(rd, tmp); if (tmprs2 s<= tmp) goto inst_next; @@ -37,10 +37,10 @@ # amomaxu.w d,t,0(s) e000202f fe00707f DWORD|DREF (0, 4) -:amomaxu.w^aqrl rd,rs2W,(rs1) is rs1 & rs2W & rd & op0001=0x3 & op0204=0x3 & op0506=0x1 & funct3=0x2 & op2731=0x1c & aqrl +:amomaxu.w^aqrl rd,rs2,(rs1) is rs1 & rs2 & rd & op0001=0x3 & op0204=0x3 & op0506=0x1 & funct3=0x2 & op2731=0x1c & aqrl { local tmprs1 = rs1; - local tmprs2 = rs2W; + local tmprs2:$(WXLEN) = rs2:$(WXLEN); local tmp:4 = *[ram]:4 tmprs1; assignW(rd, tmp); if (tmprs2 <= tmp) goto inst_next; @@ -49,10 +49,10 @@ # amomin.w d,t,0(s) 8000202f fe00707f DWORD|DREF (0, 4) -:amomin.w^aqrl rd,rs2W,(rs1) is rs1 & rs2W & rd & op0001=0x3 & op0204=0x3 & op0506=0x1 & funct3=0x2 & op2731=0x10 & aqrl +:amomin.w^aqrl rd,rs2,(rs1) is rs1 & rs2 & rd & op0001=0x3 & op0204=0x3 & op0506=0x1 & funct3=0x2 & op2731=0x10 & aqrl { local tmprs1 = rs1; - local tmprs2 = rs2W; + local tmprs2:$(WXLEN) = rs2:$(WXLEN); local tmp:4 = *[ram]:4 tmprs1; assignW(rd, tmp); if (tmprs2 s>= tmp) goto inst_next; @@ -61,10 +61,10 @@ # amominu.w d,t,0(s) c000202f fe00707f DWORD|DREF (0, 4) -:amominu.w^aqrl rd,rs2W,(rs1) is rs1 & rs2W & rd & op0001=0x3 & op0204=0x3 & op0506=0x1 & funct3=0x2 & op2731=0x18 & aqrl +:amominu.w^aqrl rd,rs2,(rs1) is rs1 & rs2 & rd & op0001=0x3 & op0204=0x3 & op0506=0x1 & funct3=0x2 & op2731=0x18 & aqrl { local tmprs1 = rs1; - local tmprs2 = rs2W; + local tmprs2:$(WXLEN) = rs2:$(WXLEN); local tmp:4 = *[ram]:4 tmprs1; assignW(rd, tmp); if (tmprs2 >= tmp) goto inst_next; @@ -73,10 +73,10 @@ # amoor.w d,t,0(s) 4000202f fe00707f DWORD|DREF (0, 4) -:amoor.w^aqrl rd,rs2W,(rs1) is rs1 & rs2W & rd & op0001=0x3 & op0204=0x3 & op0506=0x1 & funct3=0x2 & op2731=0x8 & aqrl +:amoor.w^aqrl rd,rs2,(rs1) is rs1 & rs2 & rd & op0001=0x3 & op0204=0x3 & op0506=0x1 & funct3=0x2 & op2731=0x8 & aqrl { local tmprs1 = rs1; - local tmprs2 = rs2W; + local tmprs2:$(WXLEN) = rs2:$(WXLEN); local tmp:4 = *[ram]:4 tmprs1; assignW(rd, tmp); tmp = tmp | tmprs2; @@ -85,10 +85,10 @@ # amoswap.w d,t,0(s) 0800202f fe00707f DWORD|DREF (0, 4) -:amoswap.w^aqrl rd,rs2W,(rs1) is rs1 & rs2W & rd & op0001=0x3 & op0204=0x3 & op0506=0x1 & funct3=0x2 & op2731=0x1 & aqrl +:amoswap.w^aqrl rd,rs2,(rs1) is rs1 & rs2 & rd & op0001=0x3 & op0204=0x3 & op0506=0x1 & funct3=0x2 & op2731=0x1 & aqrl { local tmprs1 = rs1; - local tmprs2 = rs2W; + local tmprs2:$(WXLEN) = rs2:$(WXLEN); local tmp:4 = *[ram]:4 tmprs1; assignW(rd, tmp); *[ram]:4 tmprs1 = tmprs2; @@ -96,10 +96,10 @@ # amoxor.w d,t,0(s) 2000202f fe00707f DWORD|DREF (0, 4) -:amoxor.w^aqrl rd,rs2W,(rs1) is rs1 & rs2W & rd & op0001=0x3 & op0204=0x3 & op0506=0x1 & funct3=0x2 & op2731=0x4 & aqrl +:amoxor.w^aqrl rd,rs2,(rs1) is rs1 & rs2 & rd & op0001=0x3 & op0204=0x3 & op0506=0x1 & funct3=0x2 & op2731=0x4 & aqrl { local tmprs1 = rs1; - local tmprs2 = rs2W; + local tmprs2:$(WXLEN) = rs2:$(WXLEN); local tmp:4 = *[ram]:4 tmprs1; assignW(rd, tmp); tmp = tmp ^ tmprs2; @@ -118,9 +118,9 @@ # sc.w d,t,0(s) 1800202f fe00707f DWORD|DREF (0, 4) -:sc.w^aqrl rd,rs2W,(rs1) is rs1 & rs2W & rd & op0001=0x3 & op0204=0x3 & op0506=0x1 & funct3=0x2 & op2731=0x3 & aqrl +:sc.w^aqrl rd,rs2,(rs1) is rs1 & rs2 & rd & op0001=0x3 & op0204=0x3 & op0506=0x1 & funct3=0x2 & op2731=0x3 & aqrl { - local tmprs2 = rs2W; + local tmprs2:$(WXLEN) = rs2:$(WXLEN); local tmprs1 = rs1; rd = 1; if ((RESERVE == 0)||(RESERVE_ADDRESS != tmprs1)||(RESERVE_LENGTH != 4)) goto inst_next; diff --git a/Ghidra/Processors/RISCV/data/languages/riscv.rv32d.sinc b/Ghidra/Processors/RISCV/data/languages/riscv.rv32d.sinc index e8d298bfbe2..aa2e72e19d3 100644 --- a/Ghidra/Processors/RISCV/data/languages/riscv.rv32d.sinc +++ b/Ghidra/Processors/RISCV/data/languages/riscv.rv32d.sinc @@ -35,18 +35,18 @@ # fcvt.d.w D,s d2000053 fff0707f SIMPLE (0, 0) -:fcvt.d.w frd,rs1W is frd & rs1W & op0001=0x3 & op0204=0x4 & op0506=0x2 & funct3=0x0 & funct7=0x69 & op2024=0x0 +:fcvt.d.w frd,rs1 is frd & rs1 & op0001=0x3 & op0204=0x4 & op0506=0x2 & funct3=0x0 & funct7=0x69 & op2024=0x0 { - local tmp:8 = int2float(rs1W); + local tmp:8 = int2float(rs1:$(WXLEN)); frd = tmp; } # fcvt.d.wu D,s d2100053 fff0707f SIMPLE (0, 0) -:fcvt.d.wu frd,rs1W is frd & rs1W & op0001=0x3 & op0204=0x4 & op0506=0x2 & funct3=0x0 & funct7=0x69 & op2024=0x1 +:fcvt.d.wu frd,rs1 is frd & rs1 & op0001=0x3 & op0204=0x4 & op0506=0x2 & funct3=0x0 & funct7=0x69 & op2024=0x1 { #ATTN unsigned can be an issue here - local u32:$(XLEN2) = zext(rs1W); + local u32:8 = zext(rs1:$(WXLEN)); local tmp:8 = int2float(u32); frd = tmp; } @@ -61,17 +61,19 @@ # fcvt.w.d d,S,m c2000053 fff0007f SIMPLE (0, 0) -:fcvt.w.d rdW,frs1D,FRM is frs1D & FRM & rdW & op0001=0x3 & op0204=0x4 & op0506=0x2 & funct7=0x61 & op2024=0x0 +:fcvt.w.d rd,frs1D,FRM is frs1D & FRM & rd & op0001=0x3 & op0204=0x4 & op0506=0x2 & funct7=0x61 & op2024=0x0 { - rdW = trunc(frs1D); + local tmp:4 = trunc(frs1D); + rd = sext(tmp); } # fcvt.wu.d d,S,m c2100053 fff0007f SIMPLE (0, 0) -:fcvt.wu.d rdW,frs1D,FRM is frs1D & FRM & rdW & op0001=0x3 & op0204=0x4 & op0506=0x2 & funct7=0x61 & op2024=0x1 +:fcvt.wu.d rd,frs1D,FRM is frs1D & FRM & rd & op0001=0x3 & op0204=0x4 & op0506=0x2 & funct7=0x61 & op2024=0x1 { - #TODO unsigned - rdW = trunc(frs1D); + local cond = (frs1D s<0); + local tmp:4 = (zext(cond) * 0) + (zext(!cond) * trunc(frs1D)); + rd = sext(tmp); # x[rd] = sext(f32->u32(f[rs1])) } diff --git a/Ghidra/Processors/RISCV/data/languages/riscv.rv32f.sinc b/Ghidra/Processors/RISCV/data/languages/riscv.rv32f.sinc index e830008391f..8061d87212b 100644 --- a/Ghidra/Processors/RISCV/data/languages/riscv.rv32f.sinc +++ b/Ghidra/Processors/RISCV/data/languages/riscv.rv32f.sinc @@ -27,35 +27,37 @@ # fcvt.s.w D,s,m d0000053 fff0007f SIMPLE (0, 0) -:fcvt.s.w frd,rs1W,FRM is frd & FRM & rs1W & op0001=0x3 & op0204=0x4 & op0506=0x2 & funct7=0x68 & op2024=0x0 +:fcvt.s.w frd,rs1,FRM is frd & FRM & rs1 & op0001=0x3 & op0204=0x4 & op0506=0x2 & funct7=0x68 & op2024=0x0 { - local tmp:4 = int2float(rs1W); + local tmp:4 = int2float(rs1:$(WXLEN)); fassignS(frd, tmp); } # fcvt.s.wu D,s,m d0100053 fff0007f SIMPLE (0, 0) -:fcvt.s.wu frd,rs1W,FRM is frd & FRM & rs1W & op0001=0x3 & op0204=0x4 & op0506=0x2 & funct7=0x68 & op2024=0x1 +:fcvt.s.wu frd,rs1,FRM is frd & FRM & rs1 & op0001=0x3 & op0204=0x4 & op0506=0x2 & funct7=0x68 & op2024=0x1 { #ATTN unsigned can be an issue here - local u32:$(XLEN2) = zext(rs1W); + local u32:8 = zext(rs1:$(WXLEN)); local tmp:4 = int2float(u32); fassignS(frd, tmp); } # fcvt.w.s d,S,m c0000053 fff0007f SIMPLE (0, 0) -:fcvt.w.s rdW,frs1S,FRM is frs1S & FRM & rdW & op0001=0x3 & op0204=0x4 & op0506=0x2 & funct7=0x60 & op2024=0x0 +:fcvt.w.s rd,frs1S,FRM is frs1S & FRM & rd & op0001=0x3 & op0204=0x4 & op0506=0x2 & funct7=0x60 & op2024=0x0 { - rdW = trunc(frs1S); + local tmp:4 = trunc(frs1S); + rd = sext(tmp); } # fcvt.wu.s d,S,m c0100053 fff0007f SIMPLE (0, 0) -:fcvt.wu.s rdW,frs1S,FRM is frs1S & FRM & rdW & op0001=0x3 & op0204=0x4 & op0506=0x2 & funct7=0x60 & op2024=0x1 +:fcvt.wu.s rd,frs1S,FRM is frs1S & FRM & rd & op0001=0x3 & op0204=0x4 & op0506=0x2 & funct7=0x60 & op2024=0x1 { - #TODO unsigned - rdW = trunc(frs1S); + local cond = (frs1S s<0); + local tmp:4 = (zext(cond) * 0:4) + (zext(!cond) * trunc(frs1S)); + rd = sext(tmp); # x[rd] = sext(f32->u32(f[rs1])) } @@ -153,17 +155,17 @@ # fmv.w.x D,s f0000053 fff0707f SIMPLE (0, 0) -:fmv.w.x frd,rs1W is frd & rs1W & op0001=0x3 & op0204=0x4 & op0506=0x2 & funct3=0x0 & funct7=0x78 & op2024=0x0 +:fmv.w.x frd,rs1 is frd & rs1 & op0001=0x3 & op0204=0x4 & op0506=0x2 & funct3=0x0 & funct7=0x78 & op2024=0x0 { - fassignS(frd, rs1W); + fassignS(frd, rs1:$(WXLEN)); } # fmv.x.w d,S e0000053 fff0707f SIMPLE (0, 0) -:fmv.x.w rdW,frs1S is frs1S & rdW & op0001=0x3 & op0204=0x4 & op0506=0x2 & funct3=0x0 & funct7=0x70 & op2024=0x0 +:fmv.x.w rd,frs1S is frs1S & rd & op0001=0x3 & op0204=0x4 & op0506=0x2 & funct3=0x0 & funct7=0x70 & op2024=0x0 { local tmpreg:4 = &frs1S; local tmp:4 = *[register]:4 tmpreg; - rdW = tmp; + rd = zext(tmp); } diff --git a/Ghidra/Processors/RISCV/data/languages/riscv.rv32q.sinc b/Ghidra/Processors/RISCV/data/languages/riscv.rv32q.sinc index b0339867b16..5d42914befc 100644 --- a/Ghidra/Processors/RISCV/data/languages/riscv.rv32q.sinc +++ b/Ghidra/Processors/RISCV/data/languages/riscv.rv32q.sinc @@ -64,13 +64,16 @@ # fcvt.w.q d,S,m c6000053 fff0007f SIMPLE (0, 0) :fcvt.w.q rd,frs1,FRM is frs1 & FRM & rd & op0001=0x3 & op0204=0x4 & op0506=0x2 & funct7=0x63 & op2024=0x0 { - rd = trunc(frs1); + local tmp:4 = trunc(frs1S); + rd = sext(tmp); } # fcvt.wu.q d,S,m c6100053 fff0007f SIMPLE (0, 0) :fcvt.wu.q rd,frs1,FRM is frs1 & FRM & rd & op0001=0x3 & op0204=0x4 & op0506=0x2 & funct7=0x63 & op2024=0x1 { - rd = trunc(frs1); + local cond = (frs1S s<0); + local tmp:4 = (zext(cond) * 0) + (zext(!cond) * trunc(frs1S)); + rdL = sext(tmp); } diff --git a/Ghidra/Processors/RISCV/data/languages/riscv.rv64d.sinc b/Ghidra/Processors/RISCV/data/languages/riscv.rv64d.sinc index 04365947651..7029ee677a3 100644 --- a/Ghidra/Processors/RISCV/data/languages/riscv.rv64d.sinc +++ b/Ghidra/Processors/RISCV/data/languages/riscv.rv64d.sinc @@ -28,8 +28,9 @@ # fcvt.lu.d d,S,m c2300053 fff0007f SIMPLE (64, 0) :fcvt.lu.d rdL,frs1D,FRM is frs1D & FRM & rdL & op0001=0x3 & op0204=0x4 & op0506=0x2 & funct7=0x61 & op2024=0x3 { - #TODO unsigned - rdL = trunc(frs1D); + local cond = (frs1D s<0); + local tmp:8 = (zext(cond) * 0:8) + (zext(!cond) * trunc(frs1D)); + rdL = tmp; } diff --git a/Ghidra/Processors/RISCV/data/languages/riscv.rv64f.sinc b/Ghidra/Processors/RISCV/data/languages/riscv.rv64f.sinc index 9a88490281c..55c28ca82cf 100644 --- a/Ghidra/Processors/RISCV/data/languages/riscv.rv64f.sinc +++ b/Ghidra/Processors/RISCV/data/languages/riscv.rv64f.sinc @@ -10,8 +10,9 @@ # fcvt.lu.s d,S,m c0300053 fff0007f SIMPLE (64, 0) :fcvt.lu.s rdL,frs1S,FRM is frs1S & FRM & rdL & op0001=0x3 & op0204=0x4 & op0506=0x2 & funct7=0x60 & op2024=0x3 { - #TODO unsigned - rdL = trunc(frs1S); + local cond = (frs1S s<0); + local tmp:8 = (zext(cond) * 0) + (zext(!cond) * trunc(frs1S)); + rdL = tmp; } diff --git a/Ghidra/Processors/RISCV/data/languages/riscv.rv64i.sinc b/Ghidra/Processors/RISCV/data/languages/riscv.rv64i.sinc index c0ad6f0d375..a7d21069a69 100644 --- a/Ghidra/Processors/RISCV/data/languages/riscv.rv64i.sinc +++ b/Ghidra/Processors/RISCV/data/languages/riscv.rv64i.sinc @@ -107,15 +107,15 @@ # subw d,s,t 4000003b fe00707f SIMPLE (64, 0) -:subw rd,rs1W,rs2W is rs1W & rs2W & rd & op0001=0x3 & op0204=0x6 & op0506=0x1 & funct3=0x0 & funct7=0x20 +:subw rd,rs1,rs2 is rs1 & rs2 & rd & op0001=0x3 & op0204=0x6 & op0506=0x1 & funct3=0x0 & funct7=0x20 { - local result = rs1W - rs2W; + local result = rs1:$(WXLEN)- rs2:$(WXLEN); rd = sext(result); } # negw d,t 4000003b fe0ff07f ALIAS (64, 0) -:negw rd,rs2W is rs2W & rd & op0001=0x3 & op0204=0x6 & op0506=0x1 & funct3=0x0 & funct7=0x20 & op1519=0x0 +:negw rd,rs2 is rs2 & rd & op0001=0x3 & op0204=0x6 & op0506=0x1 & funct3=0x0 & funct7=0x20 & op1519=0x0 { - local tmp = -rs2W; + local tmp = -rs2:$(WXLEN); rd = sext(tmp); } diff --git a/Ghidra/Processors/RISCV/data/languages/riscv.table.sinc b/Ghidra/Processors/RISCV/data/languages/riscv.table.sinc index 05d1692c7f9..5e7a356de70 100644 --- a/Ghidra/Processors/RISCV/data/languages/riscv.table.sinc +++ b/Ghidra/Processors/RISCV/data/languages/riscv.table.sinc @@ -617,15 +617,6 @@ rs3: zero is zero & op2731=0 { export 0:$(XLEN); } rd: r0711 is r0711 { export r0711; } rd: zero is r0711=0 & zero { local tmp:$(XLEN) = 0; export tmp; } -rs1W: r1519 is r1519 { local tmp:$(WXLEN) = r1519:$(WXLEN); export tmp; } -rs1W: zero is r1519 & zero & op1519=0 { export 0:$(WXLEN); } - -rs2W: r2024 is r2024 { local tmp:$(WXLEN) = r2024:$(WXLEN); export tmp; } -rs2W: zero is r2024 & zero & op2024=0 { export 0:$(WXLEN); } - -rdW: r0711 is r0711 { local tmp:$(WXLEN) = r0711:$(WXLEN); export tmp; } -rdW: zero is r0711=0 & zero { local tmp:$(WXLEN) = 0; export tmp; } - #TODO does this need to be in an if/endif @if ADDRSIZE == "64" From 161ba0c88d8ea5f6c649600b29fe71ee38a92908 Mon Sep 17 00:00:00 2001 From: Dan <46821332+nsadeveloper789@users.noreply.github.com> Date: Wed, 1 Jul 2026 18:14:59 +0000 Subject: [PATCH 056/111] GP-6841: Fix PC Column in Time panel for Emulated snapshots. --- .../ghidra/app/plugin/core/debug/gui/time/SnapshotRow.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/time/SnapshotRow.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/time/SnapshotRow.java index 7525014d7f2..bba2829727d 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/time/SnapshotRow.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/time/SnapshotRow.java @@ -72,7 +72,9 @@ private Address getProgramCounterByStack() { if (thread == null) { return null; } + // Use snap only for the object structure. Actual value must be in view snapshot long snap = getTime().getSnap(); + long viewSnap = snapshot.getKey(); TraceStack stack; try { stack = trace.getStackManager().getLatestStack(thread, snap); @@ -88,7 +90,7 @@ private Address getProgramCounterByStack() { if (frame == null) { return null; } - return frame.getProgramCounter(snap); + return frame.getProgramCounter(viewSnap); } private Address getProgramCounterByRegister() { From b4c3c95490e453fadeec815b8449300de9ca5d2b Mon Sep 17 00:00:00 2001 From: valium007 Date: Mon, 15 Jun 2026 02:13:25 +0530 Subject: [PATCH 057/111] AARCH64: zero-extend dest on ADDV/SMAXV/SMINV/UMAXV/UMINV Across-lane reductions wrote only the result element and left the upper bits of the destination SIMD&FP register stale, violating the ARM zero-extension-on-write semantics. Add zext_z{b,h,s} per element size, and fix ADDV.8B/.16B which used zext_zq (16-byte clear) for an 8-bit result. --- .../AARCH64/data/languages/AARCH64neon.sinc | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/Ghidra/Processors/AARCH64/data/languages/AARCH64neon.sinc b/Ghidra/Processors/AARCH64/data/languages/AARCH64neon.sinc index 4ff3386c3cf..64ff10203cf 100644 --- a/Ghidra/Processors/AARCH64/data/languages/AARCH64neon.sinc +++ b/Ghidra/Processors/AARCH64/data/languages/AARCH64neon.sinc @@ -734,7 +734,7 @@ is b_3131=0 & q=1 & u=0 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x Rd_FPR8 = Rd_FPR8 + Rn_VPR128.16B[104,8]; Rd_FPR8 = Rd_FPR8 + Rn_VPR128.16B[112,8]; Rd_FPR8 = Rd_FPR8 + Rn_VPR128.16B[120,8]; - zext_zq(Zd); # zero upper 31 bytes of Zd + zext_zb(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) } # C7.2.6 ADDV page C7-2027 line 118452 MATCH x0e31b800/mask=xbf3ffc00 @@ -753,7 +753,7 @@ is b_3131=0 & q=0 & u=0 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x Rd_FPR8 = Rd_FPR8 + Rn_VPR64.8B[40,8]; Rd_FPR8 = Rd_FPR8 + Rn_VPR64.8B[48,8]; Rd_FPR8 = Rd_FPR8 + Rn_VPR64.8B[56,8]; - zext_zq(Zd); # zero upper 31 bytes of Zd + zext_zb(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) } # C7.2.6 ADDV page C7-2027 line 118452 MATCH x0e31b800/mask=xbf3ffc00 @@ -17093,6 +17093,7 @@ is b_3131=0 & q=1 & u=0 & b_2428=0xe & advSIMD3.size=1 & b_2121=1 & Rm_VPR128.8H is b_3131=0 & q=1 & u=0 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0xa & b_1011=2 & Rn_VPR128.16B & Rd_FPR8 & Zd { Rd_FPR8 = NEON_smaxv(Rn_VPR128.16B, 1:1); + zext_zb(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) } # C7.2.270 SMAXV page C7-2616 line 152715 MATCH x0e30a800/mask=xbf3ffc00 @@ -17104,6 +17105,7 @@ is b_3131=0 & q=1 & u=0 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=0 & u=0 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0xa & b_1011=2 & Rn_VPR64.8B & Rd_FPR8 & Zd { Rd_FPR8 = NEON_smaxv(Rn_VPR64.8B, 1:1); + zext_zb(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) } # C7.2.270 SMAXV page C7-2616 line 152715 MATCH x0e30a800/mask=xbf3ffc00 @@ -17115,6 +17117,7 @@ is b_3131=0 & q=0 & u=0 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=0 & u=0 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0xa & b_1011=2 & Rn_VPR64.4H & Rd_FPR16 & Zd { Rd_FPR16 = NEON_smaxv(Rn_VPR64.4H, 2:1); + zext_zh(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) } # C7.2.270 SMAXV page C7-2616 line 152715 MATCH x0e30a800/mask=xbf3ffc00 @@ -17126,6 +17129,7 @@ is b_3131=0 & q=0 & u=0 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=1 & u=0 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0xa & b_1011=2 & Rn_VPR128.8H & Rd_FPR16 & Zd { Rd_FPR16 = NEON_smaxv(Rn_VPR128.8H, 2:1); + zext_zh(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) } # C7.2.270 SMAXV page C7-2616 line 152715 MATCH x0e30a800/mask=xbf3ffc00 @@ -17137,6 +17141,7 @@ is b_3131=0 & q=1 & u=0 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=1 & u=0 & b_2428=0xe & advSIMD3.size=2 & b_1721=0x18 & b_1216=0xa & b_1011=2 & Rn_VPR128.4S & Rd_FPR32 & Zd { Rd_FPR32 = NEON_smaxv(Rn_VPR128.4S, 4:1); + zext_zs(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) } # C7.2.271 SMIN page C7-2618 line 152818 MATCH x0e206c00/mask=xbf20fc00 @@ -17280,6 +17285,7 @@ is b_3131=0 & q=1 & u=0 & b_2428=0xe & advSIMD3.size=1 & b_2121=1 & Rm_VPR128.8H is b_3131=0 & q=1 & u=0 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x1a & b_1011=2 & Rn_VPR128.16B & Rd_FPR8 & Zd { Rd_FPR8 = NEON_sminv(Rn_VPR128.16B, 1:1); + zext_zb(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) } # C7.2.273 SMINV page C7-2622 line 153024 MATCH x0e31a800/mask=xbf3ffc00 @@ -17291,6 +17297,7 @@ is b_3131=0 & q=1 & u=0 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=0 & u=0 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x1a & b_1011=2 & Rn_VPR64.8B & Rd_FPR8 & Zd { Rd_FPR8 = NEON_sminv(Rn_VPR64.8B, 1:1); + zext_zb(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) } # C7.2.273 SMINV page C7-2622 line 153024 MATCH x0e31a800/mask=xbf3ffc00 @@ -17302,6 +17309,7 @@ is b_3131=0 & q=0 & u=0 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=0 & u=0 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0x1a & b_1011=2 & Rn_VPR64.4H & Rd_FPR16 & Zd { Rd_FPR16 = NEON_sminv(Rn_VPR64.4H, 2:1); + zext_zh(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) } # C7.2.273 SMINV page C7-2622 line 153024 MATCH x0e31a800/mask=xbf3ffc00 @@ -17313,6 +17321,7 @@ is b_3131=0 & q=0 & u=0 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=1 & u=0 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0x1a & b_1011=2 & Rn_VPR128.8H & Rd_FPR16 & Zd { Rd_FPR16 = NEON_sminv(Rn_VPR128.8H, 2:1); + zext_zh(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) } # C7.2.273 SMINV page C7-2622 line 153024 MATCH x0e31a800/mask=xbf3ffc00 @@ -17324,6 +17333,7 @@ is b_3131=0 & q=1 & u=0 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=1 & u=0 & b_2428=0xe & advSIMD3.size=2 & b_1721=0x18 & b_1216=0x1a & b_1011=2 & Rn_VPR128.4S & Rd_FPR32 & Zd { Rd_FPR32 = NEON_sminv(Rn_VPR128.4S, 4:1); + zext_zs(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) } # C7.2.274 SMLAL, SMLAL2 (by element) page C7-2624 line 153127 MATCH x0f002000/mask=xbf00f400 @@ -26673,6 +26683,7 @@ is b_3131=0 & q=1 & u=1 & b_2428=0xe & advSIMD3.size=1 & b_2121=1 & Rm_VPR128.8H is b_3131=0 & q=1 & u=1 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0xa & b_1011=2 & Rn_VPR128.16B & Rd_FPR8 & Zd { Rd_FPR8 = NEON_umaxv(Rn_VPR128.16B, 1:1); + zext_zb(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) } # C7.2.362 UMAXV page C7-2849 line 166369 MATCH x2e30a800/mask=xbf3ffc00 @@ -26684,6 +26695,7 @@ is b_3131=0 & q=1 & u=1 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=0 & u=1 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0xa & b_1011=2 & Rn_VPR64.8B & Rd_FPR8 & Zd { Rd_FPR8 = NEON_umaxv(Rn_VPR64.8B, 1:1); + zext_zb(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) } # C7.2.362 UMAXV page C7-2849 line 166369 MATCH x2e30a800/mask=xbf3ffc00 @@ -26695,6 +26707,7 @@ is b_3131=0 & q=0 & u=1 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=0 & u=1 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0xa & b_1011=2 & Rn_VPR64.4H & Rd_FPR16 & Zd { Rd_FPR16 = NEON_umaxv(Rn_VPR64.4H, 2:1); + zext_zh(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) } # C7.2.362 UMAXV page C7-2849 line 166369 MATCH x2e30a800/mask=xbf3ffc00 @@ -26706,6 +26719,7 @@ is b_3131=0 & q=0 & u=1 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=1 & u=1 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0xa & b_1011=2 & Rn_VPR128.8H & Rd_FPR16 & Zd { Rd_FPR16 = NEON_umaxv(Rn_VPR128.8H, 2:1); + zext_zh(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) } # C7.2.362 UMAXV page C7-2849 line 166369 MATCH x2e30a800/mask=xbf3ffc00 @@ -26717,6 +26731,7 @@ is b_3131=0 & q=1 & u=1 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=1 & u=1 & b_2428=0xe & advSIMD3.size=2 & b_1721=0x18 & b_1216=0xa & b_1011=2 & Rn_VPR128.4S & Rd_FPR32 & Zd { Rd_FPR32 = NEON_umaxv(Rn_VPR128.4S, 4:1); + zext_zs(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) } # C7.2.363 UMIN page C7-2851 line 166472 MATCH x2e206c00/mask=xbf20fc00 @@ -26860,6 +26875,7 @@ is b_3131=0 & q=1 & u=1 & b_2428=0xe & advSIMD3.size=1 & b_2121=1 & Rm_VPR128.8H is b_3131=0 & q=1 & u=1 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x1a & b_1011=2 & Rn_VPR128.16B & Rd_FPR8 & Zd { Rd_FPR8 = NEON_uminv(Rn_VPR128.16B, 1:1); + zext_zb(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) } # C7.2.365 UMINV page C7-2855 line 166678 MATCH x2e31a800/mask=xbf3ffc00 @@ -26871,6 +26887,7 @@ is b_3131=0 & q=1 & u=1 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=0 & u=1 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x1a & b_1011=2 & Rn_VPR64.8B & Rd_FPR8 & Zd { Rd_FPR8 = NEON_uminv(Rn_VPR64.8B, 1:1); + zext_zb(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) } # C7.2.365 UMINV page C7-2855 line 166678 MATCH x2e31a800/mask=xbf3ffc00 @@ -26882,6 +26899,7 @@ is b_3131=0 & q=0 & u=1 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=0 & u=1 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0x1a & b_1011=2 & Rn_VPR64.4H & Rd_FPR16 & Zd { Rd_FPR16 = NEON_uminv(Rn_VPR64.4H, 2:1); + zext_zh(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) } # C7.2.365 UMINV page C7-2855 line 166678 MATCH x2e31a800/mask=xbf3ffc00 @@ -26893,6 +26911,7 @@ is b_3131=0 & q=0 & u=1 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=1 & u=1 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0x1a & b_1011=2 & Rn_VPR128.8H & Rd_FPR16 & Zd { Rd_FPR16 = NEON_uminv(Rn_VPR128.8H, 2:1); + zext_zh(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) } # C7.2.365 UMINV page C7-2855 line 166678 MATCH x2e31a800/mask=xbf3ffc00 @@ -26904,6 +26923,7 @@ is b_3131=0 & q=1 & u=1 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=1 & u=1 & b_2428=0xe & advSIMD3.size=2 & b_1721=0x18 & b_1216=0x1a & b_1011=2 & Rn_VPR128.4S & Rd_FPR32 & Zd { Rd_FPR32 = NEON_uminv(Rn_VPR128.4S, 4:1); + zext_zs(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) } # C7.2.366 UMLAL, UMLAL2 (by element) page C7-2857 line 166781 MATCH x2f002000/mask=xbf00f400 From 59c854e0e9a2dad60d027537bae57fcd5fb1f080 Mon Sep 17 00:00:00 2001 From: valium007 Date: Mon, 15 Jun 2026 03:21:33 +0530 Subject: [PATCH 058/111] AARCH64: zero-extend dest on FMADD/FMSUB scalar forms The scalar FMADD and FMSUB constructors (FPR16/FPR32/FPR64) wrote only the result element and left the upper bits of the destination SIMD&FP register unchanged, violating the architectural zero-extension-on-write semantics. The sibling FNMADD/FNMSUB already do this correctly. Add the size-correct zero-extension after each: - FPR16 -> zext_zh - FPR32 -> zext_zs - FPR64 -> zext_zd --- Ghidra/Processors/AARCH64/data/languages/AARCH64neon.sinc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Ghidra/Processors/AARCH64/data/languages/AARCH64neon.sinc b/Ghidra/Processors/AARCH64/data/languages/AARCH64neon.sinc index 64ff10203cf..fb7d5ff7ccf 100644 --- a/Ghidra/Processors/AARCH64/data/languages/AARCH64neon.sinc +++ b/Ghidra/Processors/AARCH64/data/languages/AARCH64neon.sinc @@ -7275,6 +7275,7 @@ is b_1031=0b0001111001111110000000 & Rd_GPR32 & Rn_FPR64 & Rd_GPR64 is m=0 & b_3030=0 & s=0 & b_2428=0x1f & ftype=1 & b_21=0 & Rm_FPR64 & b_15=0 & Ra_FPR64 & Rn_FPR64 & Rd_FPR64 & Zd { Rd_FPR64 = Ra_FPR64 f+ (Rm_FPR64 f* Rn_FPR64); #NEON_fmadd(Rn_FPR64, Rm_FPR64, Ra_FPR64); + zext_zd(Zd); # zero upper bytes of dest (FMA, ARM SIMD&FP write semantics) } # C7.2.100 FMADD page C7-2246 line 131323 MATCH x1f000000/mask=xff208000 @@ -7286,6 +7287,7 @@ is m=0 & b_3030=0 & s=0 & b_2428=0x1f & ftype=1 & b_21=0 & Rm_FPR64 & b_15=0 & R is m=0 & b_3030=0 & s=0 & b_2428=0x1f & ftype=0 & b_21=0 & Rm_FPR32 & b_15=0 & Ra_FPR32 & Rn_FPR32 & Rd_FPR32 & Zd { Rd_FPR32 = Ra_FPR32 f+ (Rm_FPR32 f* Rn_FPR32); #NEON_fmadd(Rn_FPR32, Rm_FPR32, Ra_FPR32); + zext_zs(Zd); # zero upper bytes of dest (FMA, ARM SIMD&FP write semantics) } # C7.2.100 FMADD page C7-2246 line 131323 MATCH x1f000000/mask=xff208000 @@ -7297,6 +7299,7 @@ is m=0 & b_3030=0 & s=0 & b_2428=0x1f & ftype=0 & b_21=0 & Rm_FPR32 & b_15=0 & R is m=0 & b_3030=0 & s=0 & b_2428=0x1f & ftype=3 & b_21=0 & Rm_FPR16 & b_15=0 & Ra_FPR16 & Rn_FPR16 & Rd_FPR16 & Zd { Rd_FPR16 = Ra_FPR16 f+ (Rm_FPR16 f* Rn_FPR16); #NEON_fmadd(Rn_FPR16, Rm_FPR16, Ra_FPR16); + zext_zh(Zd); # zero upper bytes of dest (FMA, ARM SIMD&FP write semantics) } # C7.2.101 FMAX (vector) page C7-2248 line 131451 MATCH x0e20f400/mask=xbfa0fc00 @@ -9562,6 +9565,7 @@ is m=0 & b_3030=0 & s=0 & b_2428=0x1e & ftype=3 & b_2121=1 & Imm8_fmov16_operand is m=0 & b_3030=0 & s=0 & b_2428=0x1f & ftype=1 & b_21=0 & Rm_FPR64 & b_15=1 & Ra_FPR64 & Rn_FPR64 & Rd_FPR64 & Zd { Rd_FPR64 = Ra_FPR64 f- (Rm_FPR64 f* Rn_FPR64); + zext_zd(Zd); # zero upper bytes of dest (FMA, ARM SIMD&FP write semantics) } @@ -9574,6 +9578,7 @@ is m=0 & b_3030=0 & s=0 & b_2428=0x1f & ftype=1 & b_21=0 & Rm_FPR64 & b_15=1 & R is m=0 & b_3030=0 & s=0 & b_2428=0x1f & ftype=0 & b_21=0 & Rm_FPR32 & b_15=1 & Ra_FPR32 & Rn_FPR32 & Rd_FPR32 & Zd { Rd_FPR32 = Ra_FPR32 f- (Rm_FPR32 f* Rn_FPR32); + zext_zs(Zd); # zero upper bytes of dest (FMA, ARM SIMD&FP write semantics) } # C7.2.133 FMSUB page C7-2318 line 135582 MATCH x1f008000/mask=xff208000 @@ -9585,6 +9590,7 @@ is m=0 & b_3030=0 & s=0 & b_2428=0x1f & ftype=0 & b_21=0 & Rm_FPR32 & b_15=1 & R is m=0 & b_3030=0 & s=0 & b_2428=0x1f & ftype=3 & b_21=0 & Rm_FPR16 & b_15=1 & Ra_FPR16 & Rn_FPR16 & Rd_FPR16 & Zd { Rd_FPR16 = Ra_FPR16 f- (Rm_FPR16 f* Rn_FPR16); + zext_zh(Zd); # zero upper bytes of dest (FMA, ARM SIMD&FP write semantics) } # C7.2.134 FMUL (by element) page C7-2320 line 135711 MATCH x5f009000/mask=xffc0f400 From 817a3ac54d112b81c138117f65bcb0a93bdcb151 Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Mon, 6 Jul 2026 10:48:49 -0400 Subject: [PATCH 059/111] GP-7040: Comment formatting for consistency --- .../AARCH64/data/languages/AARCH64neon.sinc | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/Ghidra/Processors/AARCH64/data/languages/AARCH64neon.sinc b/Ghidra/Processors/AARCH64/data/languages/AARCH64neon.sinc index fb7d5ff7ccf..9da59d17fa3 100644 --- a/Ghidra/Processors/AARCH64/data/languages/AARCH64neon.sinc +++ b/Ghidra/Processors/AARCH64/data/languages/AARCH64neon.sinc @@ -734,7 +734,7 @@ is b_3131=0 & q=1 & u=0 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x Rd_FPR8 = Rd_FPR8 + Rn_VPR128.16B[104,8]; Rd_FPR8 = Rd_FPR8 + Rn_VPR128.16B[112,8]; Rd_FPR8 = Rd_FPR8 + Rn_VPR128.16B[120,8]; - zext_zb(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) + zext_zb(Zd); # zero upper bytes of Zd } # C7.2.6 ADDV page C7-2027 line 118452 MATCH x0e31b800/mask=xbf3ffc00 @@ -753,7 +753,7 @@ is b_3131=0 & q=0 & u=0 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x Rd_FPR8 = Rd_FPR8 + Rn_VPR64.8B[40,8]; Rd_FPR8 = Rd_FPR8 + Rn_VPR64.8B[48,8]; Rd_FPR8 = Rd_FPR8 + Rn_VPR64.8B[56,8]; - zext_zb(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) + zext_zb(Zd); # zero upper bytes of Zd } # C7.2.6 ADDV page C7-2027 line 118452 MATCH x0e31b800/mask=xbf3ffc00 @@ -7275,7 +7275,7 @@ is b_1031=0b0001111001111110000000 & Rd_GPR32 & Rn_FPR64 & Rd_GPR64 is m=0 & b_3030=0 & s=0 & b_2428=0x1f & ftype=1 & b_21=0 & Rm_FPR64 & b_15=0 & Ra_FPR64 & Rn_FPR64 & Rd_FPR64 & Zd { Rd_FPR64 = Ra_FPR64 f+ (Rm_FPR64 f* Rn_FPR64); #NEON_fmadd(Rn_FPR64, Rm_FPR64, Ra_FPR64); - zext_zd(Zd); # zero upper bytes of dest (FMA, ARM SIMD&FP write semantics) + zext_zd(Zd); # zero upper bytes of Zd } # C7.2.100 FMADD page C7-2246 line 131323 MATCH x1f000000/mask=xff208000 @@ -7287,7 +7287,7 @@ is m=0 & b_3030=0 & s=0 & b_2428=0x1f & ftype=1 & b_21=0 & Rm_FPR64 & b_15=0 & R is m=0 & b_3030=0 & s=0 & b_2428=0x1f & ftype=0 & b_21=0 & Rm_FPR32 & b_15=0 & Ra_FPR32 & Rn_FPR32 & Rd_FPR32 & Zd { Rd_FPR32 = Ra_FPR32 f+ (Rm_FPR32 f* Rn_FPR32); #NEON_fmadd(Rn_FPR32, Rm_FPR32, Ra_FPR32); - zext_zs(Zd); # zero upper bytes of dest (FMA, ARM SIMD&FP write semantics) + zext_zs(Zd); # zero upper bytes of Zd } # C7.2.100 FMADD page C7-2246 line 131323 MATCH x1f000000/mask=xff208000 @@ -7299,7 +7299,7 @@ is m=0 & b_3030=0 & s=0 & b_2428=0x1f & ftype=0 & b_21=0 & Rm_FPR32 & b_15=0 & R is m=0 & b_3030=0 & s=0 & b_2428=0x1f & ftype=3 & b_21=0 & Rm_FPR16 & b_15=0 & Ra_FPR16 & Rn_FPR16 & Rd_FPR16 & Zd { Rd_FPR16 = Ra_FPR16 f+ (Rm_FPR16 f* Rn_FPR16); #NEON_fmadd(Rn_FPR16, Rm_FPR16, Ra_FPR16); - zext_zh(Zd); # zero upper bytes of dest (FMA, ARM SIMD&FP write semantics) + zext_zh(Zd); # zero upper bytes of Zd } # C7.2.101 FMAX (vector) page C7-2248 line 131451 MATCH x0e20f400/mask=xbfa0fc00 @@ -9565,7 +9565,7 @@ is m=0 & b_3030=0 & s=0 & b_2428=0x1e & ftype=3 & b_2121=1 & Imm8_fmov16_operand is m=0 & b_3030=0 & s=0 & b_2428=0x1f & ftype=1 & b_21=0 & Rm_FPR64 & b_15=1 & Ra_FPR64 & Rn_FPR64 & Rd_FPR64 & Zd { Rd_FPR64 = Ra_FPR64 f- (Rm_FPR64 f* Rn_FPR64); - zext_zd(Zd); # zero upper bytes of dest (FMA, ARM SIMD&FP write semantics) + zext_zd(Zd); # zero upper bytes of Zd } @@ -9578,7 +9578,7 @@ is m=0 & b_3030=0 & s=0 & b_2428=0x1f & ftype=1 & b_21=0 & Rm_FPR64 & b_15=1 & R is m=0 & b_3030=0 & s=0 & b_2428=0x1f & ftype=0 & b_21=0 & Rm_FPR32 & b_15=1 & Ra_FPR32 & Rn_FPR32 & Rd_FPR32 & Zd { Rd_FPR32 = Ra_FPR32 f- (Rm_FPR32 f* Rn_FPR32); - zext_zs(Zd); # zero upper bytes of dest (FMA, ARM SIMD&FP write semantics) + zext_zs(Zd); # zero upper bytes of Zd } # C7.2.133 FMSUB page C7-2318 line 135582 MATCH x1f008000/mask=xff208000 @@ -9590,7 +9590,7 @@ is m=0 & b_3030=0 & s=0 & b_2428=0x1f & ftype=0 & b_21=0 & Rm_FPR32 & b_15=1 & R is m=0 & b_3030=0 & s=0 & b_2428=0x1f & ftype=3 & b_21=0 & Rm_FPR16 & b_15=1 & Ra_FPR16 & Rn_FPR16 & Rd_FPR16 & Zd { Rd_FPR16 = Ra_FPR16 f- (Rm_FPR16 f* Rn_FPR16); - zext_zh(Zd); # zero upper bytes of dest (FMA, ARM SIMD&FP write semantics) + zext_zh(Zd); # zero upper bytes of Zd } # C7.2.134 FMUL (by element) page C7-2320 line 135711 MATCH x5f009000/mask=xffc0f400 @@ -17099,7 +17099,7 @@ is b_3131=0 & q=1 & u=0 & b_2428=0xe & advSIMD3.size=1 & b_2121=1 & Rm_VPR128.8H is b_3131=0 & q=1 & u=0 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0xa & b_1011=2 & Rn_VPR128.16B & Rd_FPR8 & Zd { Rd_FPR8 = NEON_smaxv(Rn_VPR128.16B, 1:1); - zext_zb(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) + zext_zb(Zd); # zero upper bytes of Zd } # C7.2.270 SMAXV page C7-2616 line 152715 MATCH x0e30a800/mask=xbf3ffc00 @@ -17111,7 +17111,7 @@ is b_3131=0 & q=1 & u=0 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=0 & u=0 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0xa & b_1011=2 & Rn_VPR64.8B & Rd_FPR8 & Zd { Rd_FPR8 = NEON_smaxv(Rn_VPR64.8B, 1:1); - zext_zb(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) + zext_zb(Zd); # zero upper bytes of Zd } # C7.2.270 SMAXV page C7-2616 line 152715 MATCH x0e30a800/mask=xbf3ffc00 @@ -17123,7 +17123,7 @@ is b_3131=0 & q=0 & u=0 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=0 & u=0 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0xa & b_1011=2 & Rn_VPR64.4H & Rd_FPR16 & Zd { Rd_FPR16 = NEON_smaxv(Rn_VPR64.4H, 2:1); - zext_zh(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) + zext_zh(Zd); # zero upper bytes of Zd } # C7.2.270 SMAXV page C7-2616 line 152715 MATCH x0e30a800/mask=xbf3ffc00 @@ -17135,7 +17135,7 @@ is b_3131=0 & q=0 & u=0 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=1 & u=0 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0xa & b_1011=2 & Rn_VPR128.8H & Rd_FPR16 & Zd { Rd_FPR16 = NEON_smaxv(Rn_VPR128.8H, 2:1); - zext_zh(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) + zext_zh(Zd); # zero upper bytes of Zd } # C7.2.270 SMAXV page C7-2616 line 152715 MATCH x0e30a800/mask=xbf3ffc00 @@ -17147,7 +17147,7 @@ is b_3131=0 & q=1 & u=0 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=1 & u=0 & b_2428=0xe & advSIMD3.size=2 & b_1721=0x18 & b_1216=0xa & b_1011=2 & Rn_VPR128.4S & Rd_FPR32 & Zd { Rd_FPR32 = NEON_smaxv(Rn_VPR128.4S, 4:1); - zext_zs(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) + zext_zs(Zd); # zero upper bytes of Zd } # C7.2.271 SMIN page C7-2618 line 152818 MATCH x0e206c00/mask=xbf20fc00 @@ -17291,7 +17291,7 @@ is b_3131=0 & q=1 & u=0 & b_2428=0xe & advSIMD3.size=1 & b_2121=1 & Rm_VPR128.8H is b_3131=0 & q=1 & u=0 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x1a & b_1011=2 & Rn_VPR128.16B & Rd_FPR8 & Zd { Rd_FPR8 = NEON_sminv(Rn_VPR128.16B, 1:1); - zext_zb(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) + zext_zb(Zd); # zero upper bytes of Zd } # C7.2.273 SMINV page C7-2622 line 153024 MATCH x0e31a800/mask=xbf3ffc00 @@ -17303,7 +17303,7 @@ is b_3131=0 & q=1 & u=0 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=0 & u=0 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x1a & b_1011=2 & Rn_VPR64.8B & Rd_FPR8 & Zd { Rd_FPR8 = NEON_sminv(Rn_VPR64.8B, 1:1); - zext_zb(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) + zext_zb(Zd); # zero upper bytes of Zd } # C7.2.273 SMINV page C7-2622 line 153024 MATCH x0e31a800/mask=xbf3ffc00 @@ -17315,7 +17315,7 @@ is b_3131=0 & q=0 & u=0 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=0 & u=0 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0x1a & b_1011=2 & Rn_VPR64.4H & Rd_FPR16 & Zd { Rd_FPR16 = NEON_sminv(Rn_VPR64.4H, 2:1); - zext_zh(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) + zext_zh(Zd); # zero upper bytes of Zd } # C7.2.273 SMINV page C7-2622 line 153024 MATCH x0e31a800/mask=xbf3ffc00 @@ -17327,7 +17327,7 @@ is b_3131=0 & q=0 & u=0 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=1 & u=0 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0x1a & b_1011=2 & Rn_VPR128.8H & Rd_FPR16 & Zd { Rd_FPR16 = NEON_sminv(Rn_VPR128.8H, 2:1); - zext_zh(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) + zext_zh(Zd); # zero upper bytes of Zd } # C7.2.273 SMINV page C7-2622 line 153024 MATCH x0e31a800/mask=xbf3ffc00 @@ -17339,7 +17339,7 @@ is b_3131=0 & q=1 & u=0 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=1 & u=0 & b_2428=0xe & advSIMD3.size=2 & b_1721=0x18 & b_1216=0x1a & b_1011=2 & Rn_VPR128.4S & Rd_FPR32 & Zd { Rd_FPR32 = NEON_sminv(Rn_VPR128.4S, 4:1); - zext_zs(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) + zext_zs(Zd); # zero upper bytes of Zd } # C7.2.274 SMLAL, SMLAL2 (by element) page C7-2624 line 153127 MATCH x0f002000/mask=xbf00f400 @@ -26689,7 +26689,7 @@ is b_3131=0 & q=1 & u=1 & b_2428=0xe & advSIMD3.size=1 & b_2121=1 & Rm_VPR128.8H is b_3131=0 & q=1 & u=1 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0xa & b_1011=2 & Rn_VPR128.16B & Rd_FPR8 & Zd { Rd_FPR8 = NEON_umaxv(Rn_VPR128.16B, 1:1); - zext_zb(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) + zext_zb(Zd); # zero upper bytes of Zd } # C7.2.362 UMAXV page C7-2849 line 166369 MATCH x2e30a800/mask=xbf3ffc00 @@ -26701,7 +26701,7 @@ is b_3131=0 & q=1 & u=1 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=0 & u=1 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0xa & b_1011=2 & Rn_VPR64.8B & Rd_FPR8 & Zd { Rd_FPR8 = NEON_umaxv(Rn_VPR64.8B, 1:1); - zext_zb(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) + zext_zb(Zd); # zero upper bytes of Zd } # C7.2.362 UMAXV page C7-2849 line 166369 MATCH x2e30a800/mask=xbf3ffc00 @@ -26713,7 +26713,7 @@ is b_3131=0 & q=0 & u=1 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=0 & u=1 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0xa & b_1011=2 & Rn_VPR64.4H & Rd_FPR16 & Zd { Rd_FPR16 = NEON_umaxv(Rn_VPR64.4H, 2:1); - zext_zh(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) + zext_zh(Zd); # zero upper bytes of Zd } # C7.2.362 UMAXV page C7-2849 line 166369 MATCH x2e30a800/mask=xbf3ffc00 @@ -26725,7 +26725,7 @@ is b_3131=0 & q=0 & u=1 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=1 & u=1 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0xa & b_1011=2 & Rn_VPR128.8H & Rd_FPR16 & Zd { Rd_FPR16 = NEON_umaxv(Rn_VPR128.8H, 2:1); - zext_zh(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) + zext_zh(Zd); # zero upper bytes of Zd } # C7.2.362 UMAXV page C7-2849 line 166369 MATCH x2e30a800/mask=xbf3ffc00 @@ -26737,7 +26737,7 @@ is b_3131=0 & q=1 & u=1 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=1 & u=1 & b_2428=0xe & advSIMD3.size=2 & b_1721=0x18 & b_1216=0xa & b_1011=2 & Rn_VPR128.4S & Rd_FPR32 & Zd { Rd_FPR32 = NEON_umaxv(Rn_VPR128.4S, 4:1); - zext_zs(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) + zext_zs(Zd); # zero upper bytes of Zd } # C7.2.363 UMIN page C7-2851 line 166472 MATCH x2e206c00/mask=xbf20fc00 @@ -26881,7 +26881,7 @@ is b_3131=0 & q=1 & u=1 & b_2428=0xe & advSIMD3.size=1 & b_2121=1 & Rm_VPR128.8H is b_3131=0 & q=1 & u=1 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x1a & b_1011=2 & Rn_VPR128.16B & Rd_FPR8 & Zd { Rd_FPR8 = NEON_uminv(Rn_VPR128.16B, 1:1); - zext_zb(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) + zext_zb(Zd); # zero upper bytes of Zd } # C7.2.365 UMINV page C7-2855 line 166678 MATCH x2e31a800/mask=xbf3ffc00 @@ -26893,7 +26893,7 @@ is b_3131=0 & q=1 & u=1 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=0 & u=1 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x1a & b_1011=2 & Rn_VPR64.8B & Rd_FPR8 & Zd { Rd_FPR8 = NEON_uminv(Rn_VPR64.8B, 1:1); - zext_zb(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) + zext_zb(Zd); # zero upper bytes of Zd } # C7.2.365 UMINV page C7-2855 line 166678 MATCH x2e31a800/mask=xbf3ffc00 @@ -26905,7 +26905,7 @@ is b_3131=0 & q=0 & u=1 & b_2428=0xe & advSIMD3.size=0 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=0 & u=1 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0x1a & b_1011=2 & Rn_VPR64.4H & Rd_FPR16 & Zd { Rd_FPR16 = NEON_uminv(Rn_VPR64.4H, 2:1); - zext_zh(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) + zext_zh(Zd); # zero upper bytes of Zd } # C7.2.365 UMINV page C7-2855 line 166678 MATCH x2e31a800/mask=xbf3ffc00 @@ -26917,7 +26917,7 @@ is b_3131=0 & q=0 & u=1 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=1 & u=1 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0x1a & b_1011=2 & Rn_VPR128.8H & Rd_FPR16 & Zd { Rd_FPR16 = NEON_uminv(Rn_VPR128.8H, 2:1); - zext_zh(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) + zext_zh(Zd); # zero upper bytes of Zd } # C7.2.365 UMINV page C7-2855 line 166678 MATCH x2e31a800/mask=xbf3ffc00 @@ -26929,7 +26929,7 @@ is b_3131=0 & q=1 & u=1 & b_2428=0xe & advSIMD3.size=1 & b_1721=0x18 & b_1216=0x is b_3131=0 & q=1 & u=1 & b_2428=0xe & advSIMD3.size=2 & b_1721=0x18 & b_1216=0x1a & b_1011=2 & Rn_VPR128.4S & Rd_FPR32 & Zd { Rd_FPR32 = NEON_uminv(Rn_VPR128.4S, 4:1); - zext_zs(Zd); # zero upper bytes of dest (ARM SIMD&FP write semantics) + zext_zs(Zd); # zero upper bytes of Zd } # C7.2.366 UMLAL, UMLAL2 (by element) page C7-2857 line 166781 MATCH x2f002000/mask=xbf00f400 From adf16957cf26ad61e9cc386cb57fb92c6b623fb5 Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Mon, 6 Jul 2026 11:03:47 -0400 Subject: [PATCH 060/111] GP-G770: Corrected MCS-96 CMPL carry flag --- Ghidra/Processors/MCS96/data/languages/MCS96.sinc | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Ghidra/Processors/MCS96/data/languages/MCS96.sinc b/Ghidra/Processors/MCS96/data/languages/MCS96.sinc index b75988fac01..2ac6ab06503 100644 --- a/Ghidra/Processors/MCS96/data/languages/MCS96.sinc +++ b/Ghidra/Processors/MCS96/data/languages/MCS96.sinc @@ -617,11 +617,7 @@ macro setSignedShiftRightCarryFlag(shiftee,amount) { :CMPL dlreg, lreg is op8=0xc5; lreg; dlreg { op1:4 = lreg; tmp:4 = dlreg - op1; - $(N) = (tmp s< 0); - $(Z) = (tmp == 0); - $(C) = scarry(dlreg, op1); - $(V) = (((dlreg & ~op1 & ~tmp) | (~dlreg & op1 & tmp)) & 0x80000000 ) != 0; - $(VT) = $(VT) | $(V); + subtractFlags(dlreg, op1, tmp); } @endif From c0d344faba2f0dc8d03a9059ca16643d163761d1 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Mon, 6 Jul 2026 18:59:25 -0400 Subject: [PATCH 061/111] GP-7044 - Find Uses - Updated finding code for FunctionDefinitions to find all references --- .../FunctionDefinitionLocationDescriptor.java | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/locationreferences/FunctionDefinitionLocationDescriptor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/locationreferences/FunctionDefinitionLocationDescriptor.java index 9da5e83915d..0f217cc1fa0 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/locationreferences/FunctionDefinitionLocationDescriptor.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/locationreferences/FunctionDefinitionLocationDescriptor.java @@ -4,9 +4,9 @@ * 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. @@ -16,6 +16,7 @@ package ghidra.app.plugin.core.navigation.locationreferences; import ghidra.program.database.symbol.FunctionSymbol; +import ghidra.program.model.address.Address; import ghidra.program.model.data.*; import ghidra.program.model.listing.*; import ghidra.program.model.symbol.*; @@ -39,6 +40,13 @@ public class FunctionDefinitionLocationDescriptor extends GenericDataTypeLocatio protected void doGetReferences(Accumulator accumulator, TaskMonitor monitor) throws CancelledException { + findAppliedFunctionDefinition(accumulator); + + ReferenceUtils.findDataTypeReferences(accumulator, functionDefinition, program, true, + monitor); + } + + private void findAppliedFunctionDefinition(Accumulator accumulator) { DataType myReturnType = functionDefinition.getReturnType(); ParameterDefinition[] myParameters = functionDefinition.getArguments(); @@ -48,15 +56,14 @@ protected void doGetReferences(Accumulator accumulator, TaskM // the definition could be applied in more than one namespace, so handle each application while (symbols.hasNext()) { - Symbol symbol = symbols.next(); - if (!(symbol instanceof FunctionSymbol)) { + Symbol symbol = symbols.next(); + if (!(symbol instanceof FunctionSymbol functionSymbol)) { continue; } - FunctionSymbol functionSymbol = (FunctionSymbol) symbol; + long symbolID = functionSymbol.getID(); Function function = functionManager.getFunction(symbolID); - FunctionSignature signature = function.getSignature(true); ParameterDefinition[] theirParameters = signature.getArguments(); if (!isSameParamters(myParameters, theirParameters)) { @@ -67,7 +74,14 @@ protected void doGetReferences(Accumulator accumulator, TaskM continue; } - accumulator.add(new LocationReference(symbol.getAddress())); + ProgramLocation location = symbol.getProgramLocation(); + Address address = symbol.getAddress(); + if (location != null) { + accumulator.add(new LocationReference(address, null, location)); + } + else { + accumulator.add(new LocationReference(address)); + } } } From c03a70ddb702ef0dbf096eb649d53999ef4c1696 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Tue, 7 Jul 2026 05:53:08 -0400 Subject: [PATCH 062/111] GP-7045: The Swift Demangler now requires Swift to be on the PATH --- Ghidra/Features/SwiftDemangler/README.md | 7 ++--- .../ghidra_scripts/SwiftDemanglerScript.java | 2 +- .../core/analysis/SwiftDemanglerAnalyzer.java | 15 ++-------- .../util/demangler/swift/SwiftDemangler.java | 2 +- .../swift/SwiftDemanglerOptions.java | 30 ++----------------- .../demangler/swift/SwiftNativeDemangler.java | 21 +++++-------- .../demangler/swift/SwiftDemanglerTest.java | 2 +- 7 files changed, 19 insertions(+), 60 deletions(-) diff --git a/Ghidra/Features/SwiftDemangler/README.md b/Ghidra/Features/SwiftDemangler/README.md index 5801dc56e01..e8e34ce1282 100644 --- a/Ghidra/Features/SwiftDemangler/README.md +++ b/Ghidra/Features/SwiftDemangler/README.md @@ -1,7 +1,7 @@ # SwiftDemangler -This module provides support for demanling mangled [Swift](https://www.swift.org) symbols. Supported -mangled symbols begin with `$S`, `$s`, `_$S"`, `_$s`, or `_T`. +This module provides support for demangling mangled [Swift](https://www.swift.org) symbols. +Supported mangled symbols begin with `$S`, `$s`, `_$S"`, `_$s`, or `_T`. The demangler currently relies on making direct calls to the native Swift demangler tool, which comes [bundled with Swift](https://www.swift.org/download/). For example: @@ -21,5 +21,4 @@ protocol descriptor for SwiftUI.View The resulting tree is parsed by the Ghidra Swift Demangler to form and apply a demangled symbol name. -By default, the `Demangler Swift` Analyzer will search for the native Swift Demangler on the `PATH`. -If it resides elsewhere, its path can be specified in the analyzer's options. +The `Demangler Swift` Analyzer assumes that the native Swift Demangler is on the `PATH`. diff --git a/Ghidra/Features/SwiftDemangler/ghidra_scripts/SwiftDemanglerScript.java b/Ghidra/Features/SwiftDemangler/ghidra_scripts/SwiftDemanglerScript.java index 7dcdcb0ab41..abfa9911a35 100644 --- a/Ghidra/Features/SwiftDemangler/ghidra_scripts/SwiftDemanglerScript.java +++ b/Ghidra/Features/SwiftDemangler/ghidra_scripts/SwiftDemanglerScript.java @@ -55,7 +55,7 @@ protected void run() throws Exception { return; } - SwiftNativeDemangler nativeDemangler = new SwiftNativeDemangler(options.getSwiftDir()); + SwiftNativeDemangler nativeDemangler = new SwiftNativeDemangler(); SwiftNativeDemangledOutput demangledOutput = nativeDemangler.demangle(mangled); println(demangledOutput.toString()); diff --git a/Ghidra/Features/SwiftDemangler/src/main/java/ghidra/app/plugin/core/analysis/SwiftDemanglerAnalyzer.java b/Ghidra/Features/SwiftDemangler/src/main/java/ghidra/app/plugin/core/analysis/SwiftDemanglerAnalyzer.java index 48c58cd410e..aeb1beddf42 100644 --- a/Ghidra/Features/SwiftDemangler/src/main/java/ghidra/app/plugin/core/analysis/SwiftDemanglerAnalyzer.java +++ b/Ghidra/Features/SwiftDemangler/src/main/java/ghidra/app/plugin/core/analysis/SwiftDemanglerAnalyzer.java @@ -15,7 +15,6 @@ */ package ghidra.app.plugin.core.analysis; -import java.io.File; import java.io.IOException; import ghidra.app.util.demangler.*; @@ -36,10 +35,7 @@ public class SwiftDemanglerAnalyzer extends AbstractDemanglerAnalyzer { private static final String NAME = "Demangler Swift"; private static final String DESCRIPTION = - "Demangles Swift symbols and applies appropriate datatype and calling conventions where possible. Requires Swift to be installed."; - private static final String OPTION_NAME_SWIFT_DIR = "Swift binary directory"; - private static final String OPTION_DESCRIPTION_SWIFT_DIR = - "Path to the Swift installation binary directory, if not on PATH"; + "Demangles Swift symbols and applies appropriate datatype and calling conventions where possible. Requires Swift to be on the PATH."; private static final String OPTION_NAME_INCOMPLETE_PREFIX = "Use incomplete demangle label prefix (%s)" @@ -54,7 +50,6 @@ public class SwiftDemanglerAnalyzer extends AbstractDemanglerAnalyzer { "Prefix unsupported demangled labels with '%s'" .formatted(SwiftDemanglerOptions.UNSUPPORTED_PREFIX); - private File swiftDir; private boolean useIncompletePrefix = true; private boolean useUnsupportedPrefix = true; @@ -94,8 +89,6 @@ protected DemangledObject doDemangle(MangledContext mangledContext, MessageLog l @Override public void registerOptions(Options options, Program program) { HelpLocation help = new HelpLocation("AutoAnalysisPlugin", "Demangler_Analyzer"); - options.registerOption(OPTION_NAME_SWIFT_DIR, OptionType.FILE_TYPE, swiftDir, help, - OPTION_DESCRIPTION_SWIFT_DIR); options.registerOption(OPTION_NAME_INCOMPLETE_PREFIX, OptionType.BOOLEAN_TYPE, useIncompletePrefix, help, OPTION_DESCRIPTION_INCOMPLETE_PREFIX); options.registerOption(OPTION_NAME_UNSUPPORTED_PREFIX, OptionType.BOOLEAN_TYPE, @@ -104,9 +97,9 @@ public void registerOptions(Options options, Program program) { @Override protected boolean validateOptions(DemanglerOptions options, MessageLog log) { - if (options instanceof SwiftDemanglerOptions swiftDemanglerOptions) { + if (options instanceof SwiftDemanglerOptions) { try { - new SwiftNativeDemangler(swiftDemanglerOptions.getSwiftDir()); + new SwiftNativeDemangler(); return true; } catch (IOException e) { @@ -120,7 +113,6 @@ protected boolean validateOptions(DemanglerOptions options, MessageLog log) { @Override public void optionsChanged(Options options, Program program) { - swiftDir = options.getFile(OPTION_NAME_SWIFT_DIR, swiftDir); useIncompletePrefix = options.getBoolean(OPTION_NAME_INCOMPLETE_PREFIX, useIncompletePrefix); useUnsupportedPrefix = @@ -130,7 +122,6 @@ public void optionsChanged(Options options, Program program) { @Override protected DemanglerOptions getOptions() { SwiftDemanglerOptions swiftDemanglerOptions = new SwiftDemanglerOptions(); - swiftDemanglerOptions.setSwiftDir(swiftDir); swiftDemanglerOptions.setIncompletePrefix(useIncompletePrefix); swiftDemanglerOptions.setUnsupportedPrefix(useUnsupportedPrefix); return swiftDemanglerOptions; diff --git a/Ghidra/Features/SwiftDemangler/src/main/java/ghidra/app/util/demangler/swift/SwiftDemangler.java b/Ghidra/Features/SwiftDemangler/src/main/java/ghidra/app/util/demangler/swift/SwiftDemangler.java index d49cf4eb58e..589fbb3f55d 100644 --- a/Ghidra/Features/SwiftDemangler/src/main/java/ghidra/app/util/demangler/swift/SwiftDemangler.java +++ b/Ghidra/Features/SwiftDemangler/src/main/java/ghidra/app/util/demangler/swift/SwiftDemangler.java @@ -189,7 +189,7 @@ public SwiftDemanglerOptions getSwiftDemanglerOptions(DemanglerOptions opt) private void setSwiftNativeDemangler(SwiftDemanglerOptions options) throws DemangledException { if (nativeDemangler == null) { try { - nativeDemangler = new SwiftNativeDemangler(options.getSwiftDir()); + nativeDemangler = new SwiftNativeDemangler(); } catch (IOException e) { throw new DemangledException(e); diff --git a/Ghidra/Features/SwiftDemangler/src/main/java/ghidra/app/util/demangler/swift/SwiftDemanglerOptions.java b/Ghidra/Features/SwiftDemangler/src/main/java/ghidra/app/util/demangler/swift/SwiftDemanglerOptions.java index 0f1ecff644f..be919119441 100644 --- a/Ghidra/Features/SwiftDemangler/src/main/java/ghidra/app/util/demangler/swift/SwiftDemanglerOptions.java +++ b/Ghidra/Features/SwiftDemangler/src/main/java/ghidra/app/util/demangler/swift/SwiftDemanglerOptions.java @@ -4,9 +4,9 @@ * 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. @@ -15,8 +15,6 @@ */ package ghidra.app.util.demangler.swift; -import java.io.File; - import ghidra.app.util.demangler.DemanglerOptions; /** @@ -27,33 +25,9 @@ public class SwiftDemanglerOptions extends DemanglerOptions { public static final String INCOMPLETE_PREFIX = "$"; public static final String UNSUPPORTED_PREFIX = "$$"; - private File swiftDir; private boolean useIncompletePrefix; private boolean useUnsupportedPrefix; - /** - * Gets the Swift directory - *

    - * If the Swift directory is on the PATH environment variable, this may return null - * - * @return The Swift directory - */ - public File getSwiftDir() { - return swiftDir; - } - - /** - * Sets the Swift directory - *

    - * If the Swift directory is on the PATH environment variable, it is fine to set this to - * null - * - * @param swiftDir The Swift directory - */ - public void setSwiftDir(File swiftDir) { - this.swiftDir = swiftDir; - } - /** * {@return the "incomplete prefix" character to use in label names} */ diff --git a/Ghidra/Features/SwiftDemangler/src/main/java/ghidra/app/util/demangler/swift/SwiftNativeDemangler.java b/Ghidra/Features/SwiftDemangler/src/main/java/ghidra/app/util/demangler/swift/SwiftNativeDemangler.java index f964e9a0b23..1fe4e40e362 100644 --- a/Ghidra/Features/SwiftDemangler/src/main/java/ghidra/app/util/demangler/swift/SwiftNativeDemangler.java +++ b/Ghidra/Features/SwiftDemangler/src/main/java/ghidra/app/util/demangler/swift/SwiftNativeDemangler.java @@ -4,9 +4,9 @@ * 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. @@ -34,7 +34,7 @@ */ public class SwiftNativeDemangler { - private String nativeDemanglerPath; + private String nativeDemanglerCmd; private boolean standaloneDemanglerBinary; /** @@ -54,25 +54,20 @@ public String toString() { /** * Creates a new {@link SwiftNativeDemangler} * - * @param swiftDir The Swift directory * @throws IOException if there was a problem finding or running the Swift native demangler */ - public SwiftNativeDemangler(File swiftDir) throws IOException { + public SwiftNativeDemangler() throws IOException { List demanglerNames = List.of("swift-demangle", "swift"); IOException ioe = null; for (String demanglerName : demanglerNames) { - nativeDemanglerPath = demanglerName; - if (swiftDir != null) { - nativeDemanglerPath = swiftDir + File.separator + nativeDemanglerPath; - } + nativeDemanglerCmd = demanglerName; // expect swift demangler to be on the PATH try { int exitCode = - new ProcessBuilder(List.of(nativeDemanglerPath, "--version")).start() - .waitFor(); + new ProcessBuilder(List.of(nativeDemanglerCmd, "--version")).start().waitFor(); if (exitCode == 0) { ioe = null; standaloneDemanglerBinary = - new File(nativeDemanglerPath).getName().contains("-demangle"); + new File(nativeDemanglerCmd).getName().contains("-demangle"); break; } ioe = new IOException("Native Swift demangler exited with code: " + exitCode); @@ -144,7 +139,7 @@ public SwiftNativeDemangledOutput demangle(String mangled) throws IOException { */ private BufferedReader demangle(String mangled, List options) throws IOException { List command = new ArrayList<>(); - command.add(nativeDemanglerPath); + command.add(nativeDemanglerCmd); if (!standaloneDemanglerBinary) { command.add("demangle"); } diff --git a/Ghidra/Features/SwiftDemangler/src/test/java/ghidra/app/util/demangler/swift/SwiftDemanglerTest.java b/Ghidra/Features/SwiftDemangler/src/test/java/ghidra/app/util/demangler/swift/SwiftDemanglerTest.java index 7ad9f33d952..a5e66b0a9d7 100644 --- a/Ghidra/Features/SwiftDemangler/src/test/java/ghidra/app/util/demangler/swift/SwiftDemanglerTest.java +++ b/Ghidra/Features/SwiftDemangler/src/test/java/ghidra/app/util/demangler/swift/SwiftDemanglerTest.java @@ -43,7 +43,7 @@ public void setUp() throws Exception { // Ghidra does not ship the native Swift demangler binary, so it may not be present to run // these tests. In this scenario, we just want these tests skipped (as opposed to failing). try { - new SwiftNativeDemangler(new SwiftDemanglerOptions().getSwiftDir()); + new SwiftNativeDemangler(); } catch (IOException e) { assumeNoException(e); // skip test, don't fail From 214c1fba9ba5977dd6752058414f980f8bb8e947 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Tue, 7 Jul 2026 14:00:56 -0400 Subject: [PATCH 063/111] Fixed test focus issue when typing into text fields on FlatLaf --- .../docking/test/AbstractDockingTest.java | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/Ghidra/Framework/Docking/src/main/java/docking/test/AbstractDockingTest.java b/Ghidra/Framework/Docking/src/main/java/docking/test/AbstractDockingTest.java index d4c7d15e526..bc2b4587973 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/test/AbstractDockingTest.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/test/AbstractDockingTest.java @@ -1515,9 +1515,24 @@ public static void triggerActionKey(Component c, int modifiers, int keyCode) { */ private static void forceTextComponentFocus(JTextComponent tc) { - Object contextKey = getInstanceField("FOCUSED_COMPONENT", tc); - AppContext context = AppContext.getAppContext(); - context.put(contextKey, tc); + runSwing(() -> { + + // Update Swing's notion of the focused component + Object contextKey = getInstanceField("FOCUSED_COMPONENT", tc); + AppContext context = AppContext.getAppContext(); + context.put(contextKey, tc); + + /* + The FlatLaf will select all text in a text field when it gains focus. This will + break how we send key events to text fields. For text handling to work correctly, + we need to ensure that the given field has focus. If it gains focus in FlatLaf and + then selects the text, the next key event will overwrite the current text, which we + do not want. + + See FlatClientProperties.SELECT_ALL_ON_FOCUS_POLICY + */ + tc.putClientProperty("JTextField.selectAllOnFocusPolicy", "never"); + }); } /** From 80c61dc32bfa53fed47bf4a9bc08bd2043c86d62 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Tue, 7 Jul 2026 15:12:01 -0400 Subject: [PATCH 064/111] GP-0: Adding -Dsun.awt.disablegrab=true to Ghidra.launch to prevent system hang on breakpoints --- Ghidra/Features/Base/.launch/Ghidra.launch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ghidra/Features/Base/.launch/Ghidra.launch b/Ghidra/Features/Base/.launch/Ghidra.launch index 55365e41560..59308a9fc63 100644 --- a/Ghidra/Features/Base/.launch/Ghidra.launch +++ b/Ghidra/Features/Base/.launch/Ghidra.launch @@ -31,5 +31,5 @@ - + From 108b101bed018fb234f7038079aa2080319fc03b Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Wed, 8 Jul 2026 15:12:06 -0400 Subject: [PATCH 065/111] GP-7049 ensure repository ACL excludes users not defined on server --- .../main/java/ghidra/server/Repository.java | 60 +++++++++++++------ .../java/ghidra/server/RepositoryManager.java | 16 +++-- .../main/java/ghidra/server/ServerAdmin.java | 26 +++++--- .../main/java/ghidra/server/UserManager.java | 18 +++++- 4 files changed, 87 insertions(+), 33 deletions(-) diff --git a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/Repository.java b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/Repository.java index 95b0602692c..6a77e75acaf 100644 --- a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/Repository.java +++ b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/Repository.java @@ -17,6 +17,7 @@ import java.io.*; import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -351,7 +352,7 @@ public void setUserList(String currentUser, User[] users, boolean allowAnonymous validate(); validateAdminPrivilege(currentUser); - Set allUsers = Set.of(mgr.getAllUsers(currentUser)); + Set allUsers = getAllServerUsers(); Set updatedUsers = new HashSet<>(); LinkedHashMap newUserMap = new LinkedHashMap<>(); @@ -574,17 +575,20 @@ void delete(String currentUser) throws IOException, UserAccessException { * Generate formatted list of user access permissions to the specified repository. * This is intended to be used with the svrAdmin console command * @param repositoryDir repository directory + * @param allUsers set of all valid users known to server * @param pad padding string to be prefixed to each output line * @return formatted list of user access permissions */ - static String getFormattedUserPermissions(File repositoryDir, String pad) { + static String getFormattedUserPermissions(File repositoryDir, Set allUsers, + String pad) { StringBuilder buf = new StringBuilder(); File userAccessFile = new File(repositoryDir, ACCESS_CONTROL_FILENAME); try { List list = new ArrayList<>(); - boolean anonymousAccessAllowed = readAccessFile(userAccessFile, list); + AtomicBoolean anonymousAccessAllowed = new AtomicBoolean(); + readAccessFile(userAccessFile, allUsers, anonymousAccessAllowed, list); Collections.sort(list); - if (anonymousAccessAllowed) { + if (anonymousAccessAllowed.get()) { buf.append(pad + "* Anonymous read-only access permitted *\n"); } for (User user : list) { @@ -592,7 +596,7 @@ static String getFormattedUserPermissions(File repositoryDir, String pad) { } } catch (IOException e) { - System.out.println(pad + "Failed to read repository access file: " + e.getMessage()); + System.err.println(pad + "Failed to read repository access file: " + e.getMessage()); } return buf.toString(); } @@ -602,17 +606,19 @@ static String getFormattedUserPermissions(File repositoryDir, String pad) { * restricted to user names contained within listUserAccess. * This is intended to be used with the svrAdmin console command * @param repositoryDir repository directory + * @param allUsers set of all valid users known to server * @param pad padding string to be prefixed to each output line * @param listUserAccess set of user names of interest * @return formatted list of user access permissions or null if no users of interest found */ - static String getFormattedUserPermissions(File repositoryDir, String pad, + static String getFormattedUserPermissions(File repositoryDir, Set allUsers, String pad, Set listUserAccess) { StringBuilder buf = null; File userAccessFile = new File(repositoryDir, ACCESS_CONTROL_FILENAME); try { + AtomicBoolean anonymousAccessAllowed = new AtomicBoolean(); ArrayList list = new ArrayList<>(); - readAccessFile(userAccessFile, list); + readAccessFile(userAccessFile, allUsers, anonymousAccessAllowed, list); Collections.sort(list); for (User user : list) { if (!listUserAccess.contains(user.getName())) { @@ -625,11 +631,15 @@ static String getFormattedUserPermissions(File repositoryDir, String pad, } } catch (IOException e) { - System.out.println(pad + "Failed to read repository access file: " + e.getMessage()); + System.err.println(pad + "Failed to read repository access file: " + e.getMessage()); } return buf != null ? buf.toString() : null; } + private Set getAllServerUsers() { + return Set.of(mgr.getUserManager().getUsers()); + } + /** * Read user access list from local file. * @throws IOException if an IO error occurs @@ -639,9 +649,12 @@ private void readAccessFile() throws IOException { return; } + AtomicBoolean anonymousAccess = new AtomicBoolean(); ArrayList list = new ArrayList<>(); - anonymousAccessAllowed = - readAccessFile(userAccessFile, list) && mgr.anonymousAccessAllowed(); + boolean modified = + readAccessFile(userAccessFile, getAllServerUsers(), anonymousAccess, list) && + mgr.anonymousAccessAllowed(); + anonymousAccessAllowed = mgr.anonymousAccessAllowed() & anonymousAccess.get(); LinkedHashMap newUserMap = new LinkedHashMap<>(); boolean hasAdmin = false; @@ -654,19 +667,27 @@ private void readAccessFile() throws IOException { .info("WARNING: Repository '" + name + "' does not have an assigned Admin"); } userMap = newUserMap; + + if (modified) { + writeUserList(userMap, anonymousAccessAllowed); + } } /** * Read list of user permissions from userAccessFile and determine if anonymous read-only * access is permitted * @param userAccessFile repository user access file + * @param allUsers set of all valid users known to server + * @param allowAnonymous which conveys the anonymous permission state read from the file * @param users list to be populated with user permissions defined by userAccessFile - * @return true if anonymous read-only access is permitted, else false + * @return true if one of more users were removed from the stored list * @throws IOException if an IO error occurs */ - private static boolean readAccessFile(File userAccessFile, List users) + private static boolean readAccessFile(File userAccessFile, Set allUsers, + AtomicBoolean allowAnonymous, List users) throws IOException { - boolean allowAnonymous = false; + boolean userRemoved = false; + allowAnonymous.set(false); try (BufferedReader reader = new BufferedReader(new FileReader(userAccessFile))) { String line = ""; while (true) { @@ -679,16 +700,21 @@ private static boolean readAccessFile(File userAccessFile, List users) } line = line.trim(); if (ANONYMOUS_STR.equals(line)) { - allowAnonymous = true; + allowAnonymous.set(true); continue; } User user = processAccessLine(line); if (user != null) { - users.add(user); + if (allUsers.contains(user.getName())) { + users.add(user); + } + else { + userRemoved = true; + } } } } - return allowAnonymous; + return userRemoved; } /** @@ -986,7 +1012,7 @@ static boolean markRepositoryForIndexMigration(File serverDir, String repository int indexVersion = IndexedLocalFileSystem.readIndexVersion(rootPath); if (indexVersion >= IndexedLocalFileSystem.LATEST_INDEX_VERSION) { if (!silent) { - System.err + System.out .println("Repository '" + repositoryName + "' is already indexed!"); } return false; diff --git a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/RepositoryManager.java b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/RepositoryManager.java index e0faae56931..d5fd7ed411f 100644 --- a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/RepositoryManager.java +++ b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/RepositoryManager.java @@ -459,8 +459,10 @@ static void log(String repositoryName, String path, String msg) { * @param repositoriesRootDir repositories root directory * @param includeUserAccessDetails if true additional user access details will displayed * for each repository + * @param allUsers set of all valid users known to server */ - static void listRepositories(File repositoriesRootDir, boolean includeUserAccessDetails) { + static void listRepositories(File repositoriesRootDir, boolean includeUserAccessDetails, + Set allUsers) { String[] names = RepositoryManager.getRepositoryNames(repositoriesRootDir); System.out.println("\nRepositories:"); if (names.length == 0) { @@ -495,7 +497,7 @@ static void listRepositories(File repositoriesRootDir, boolean includeUserAccess System.out.println(" " + name + (type == null ? "" : (" - uses " + type))); if (includeUserAccessDetails) { - System.out.print(Repository.getFormattedUserPermissions(repoDir, " ")); + System.out.print(Repository.getFormattedUserPermissions(repoDir, allUsers, " ")); } } } @@ -505,8 +507,10 @@ static void listRepositories(File repositoriesRootDir, boolean includeUserAccess * This is intended to be used with the svrAdmin console command * @param repositoriesRootDir repositories root directory * @param usernameSet set of users whose details should be displayed + * @param allUsers set of all valid users known to server */ - static void listRepositories(File repositoriesRootDir, Set usernameSet) { + static void listRepositories(File repositoriesRootDir, Set usernameSet, + Set allUsers) { String[] names = RepositoryManager.getRepositoryNames(repositoriesRootDir); if (names.length == 0) { System.out.println(" "); @@ -518,7 +522,7 @@ static void listRepositories(File repositoriesRootDir, Set usernameSet) File repoDir = new File(repositoriesRootDir, NamingUtilities.mangle(name)); String formattedAccessList = - Repository.getFormattedUserPermissions(repoDir, " ", usernameSet); + Repository.getFormattedUserPermissions(repoDir, allUsers, " ", usernameSet); if (formattedAccessList != null) { if (outputHeader) { System.out.println("\nRepositories:"); @@ -562,8 +566,8 @@ static void markAllRepositoriesForIndexMigration(File serverDir) { * @throws IOException if error occured while updating repository access lists. */ void userRemoved(String username) throws IOException { - for (String repName : getRepositoryNames()) { - getRepository(repName).removeUser(username); + for (Repository repo : repositoryMap.values()) { + repo.removeUser(username); } } diff --git a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/ServerAdmin.java b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/ServerAdmin.java index 2526b304672..2edbc46cf06 100644 --- a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/ServerAdmin.java +++ b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/ServerAdmin.java @@ -26,7 +26,8 @@ import ghidra.GhidraLaunchable; import ghidra.framework.Application; import ghidra.framework.ApplicationConfiguration; -import ghidra.util.*; +import ghidra.util.Msg; +import ghidra.util.NamingUtilities; public class ServerAdmin implements GhidraLaunchable { @@ -238,11 +239,18 @@ public void execute(String[] args) { UserManager.listUsers(serverRootDir); } if (listRepositories) { - if (listUsernameSet.isEmpty()) { - RepositoryManager.listRepositories(serverRootDir, listAllUserPermissions); + try { + Set users = UserManager.getUsers(serverRootDir); + if (listUsernameSet.isEmpty()) { + RepositoryManager.listRepositories(serverRootDir, listAllUserPermissions, + users); + } + else { + RepositoryManager.listRepositories(serverRootDir, listUsernameSet, users); + } } - else { - RepositoryManager.listRepositories(serverRootDir, listUsernameSet); + catch (IOException e) { + System.err.println("\nFailed to read user file: " + e.getMessage()); } } System.out.println(); @@ -477,7 +485,7 @@ private File getServerDirFromConfig(String configFilePath) { File configFile = new File(configFilePath); if (!configFile.exists()) { - System.out.println("Config file not found: " + configFile.getAbsolutePath()); + System.err.println("Config file not found: " + configFile.getAbsolutePath()); return null; } @@ -495,7 +503,7 @@ private File getServerDirFromConfig(String configFilePath) { config.load(in); } catch (IOException e) { - System.out.println("Failed to read " + configFile.getName() + ": " + e.getMessage()); + System.err.println("Failed to read " + configFile.getName() + ": " + e.getMessage()); } finally { if (in != null) { @@ -510,7 +518,7 @@ private File getServerDirFromConfig(String configFilePath) { String p = config.getProperty(SERVER_DIR_CONFIG_PROPERTY); if (p == null) { - System.out.println("Failed to find property: " + SERVER_DIR_CONFIG_PROPERTY); + System.err.println("Failed to find property: " + SERVER_DIR_CONFIG_PROPERTY); return null; } File dir = new File(p); @@ -518,7 +526,7 @@ private File getServerDirFromConfig(String configFilePath) { // Make relative repositories dir relative to installation root ResourceFile installRoot = Application.getInstallationDirectory(); if (installRoot == null || installRoot.getFile(false) == null) { - System.out.println("Failed to resolve installation root directory!"); + System.err.println("Failed to resolve installation root directory!"); return null; } dir = new File(installRoot.getFile(false), p); diff --git a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/UserManager.java b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/UserManager.java index a64090f1f69..a57d8ad983d 100644 --- a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/UserManager.java +++ b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/UserManager.java @@ -554,10 +554,26 @@ static void listUsers(File repositoriesRootDir) { } } catch (IOException e) { - System.out.println("\nFailed to read user file: " + e.getMessage()); + System.err.println("\nFailed to read user file: " + e.getMessage()); } } + /** + * Get list of all users known to server. + * @param repositoriesRootDir repositories root directory + * @return list of known users + * @throws IOException if error occurs while reading passwd file + */ + static Set getUsers(File repositoriesRootDir) throws IOException { + File userFile = new File(repositoriesRootDir, USER_PASSWORD_FILE); + + LinkedHashMap list = new LinkedHashMap<>(); + HashMap lookupMap = new HashMap<>(); + + readUserList(userFile, list, lookupMap); + return list.keySet(); + } + private static void readUserList(File file, Map usersIndexByName, Map x500LookupMap) throws IOException { try (BufferedReader br = new BufferedReader(new FileReader(file))) { From 97780f36c013971131e119c7f23195156f198582 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Wed, 8 Jul 2026 19:16:29 -0400 Subject: [PATCH 066/111] GP-7050 - Fixed exceptions seen on the Mac when using the Column Filter Dialog --- .../widgets/table/constraint/ColumnTypeMapper.java | 3 +-- .../table/constraint/MappedColumnConstraint.java | 3 +-- .../table/constraint/dialog/ColumnFilterData.java | 12 +----------- .../constraint/dialog/DialogFilterCondition.java | 8 +------- .../constraint/dialog/DialogFilterConditionSet.java | 8 +------- .../table/constraint/dialog/DialogFilterRow.java | 11 +++-------- 6 files changed, 8 insertions(+), 37 deletions(-) diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/ColumnTypeMapper.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/ColumnTypeMapper.java index ee7afd82b5b..93c8cbfcd3c 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/ColumnTypeMapper.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/ColumnTypeMapper.java @@ -19,7 +19,6 @@ import java.util.Objects; import docking.widgets.table.constraint.provider.NumberColumnConstraintProvider; -import generic.json.Json; import ghidra.util.classfinder.ExtensionPoint; import utilities.util.reflection.ReflectionUtilities; @@ -62,7 +61,7 @@ protected ColumnTypeMapper(Class sourceType, Class destinationType) { @Override public String toString() { - return Json.toString(this); + return "[source type=%s, destination type=%s]".formatted(sourceType, destinationType); } @Override diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/MappedColumnConstraint.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/MappedColumnConstraint.java index 76c7b5ba621..c9208cd8e0b 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/MappedColumnConstraint.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/MappedColumnConstraint.java @@ -17,7 +17,6 @@ import docking.widgets.table.constrainteditor.ColumnConstraintEditor; import docking.widgets.table.constrainteditor.MappedColumnConstraintEditor; -import generic.json.Json; import ghidra.util.SystemUtilities; /** @@ -103,7 +102,7 @@ public ColumnConstraint getDelegate() { @Override public String toString() { - return Json.toString(this); + return delegate.toString(); } @Override diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/ColumnFilterData.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/ColumnFilterData.java index 3f35ec71389..23f005153f4 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/ColumnFilterData.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/ColumnFilterData.java @@ -17,8 +17,6 @@ import java.util.*; -import org.apache.commons.collections4.CollectionUtils; - import docking.widgets.table.*; import docking.widgets.table.constraint.ColumnConstraint; import docking.widgets.table.constraint.ColumnTypeMapper; @@ -168,15 +166,7 @@ public String getName() { @Override public String toString() { - //@formatter:off - return "{\n" + - "\tname: " + name + ",\n" + - "\tmodelColumn: " + modelIndex + ",\n" + - "\tviewColumn: " + viewIndex + ",\n" + - "\tconstraints: " + - CollectionUtils.collect(applicableConstraints, c -> c.asString()) +"\n" + - "}"; - //@formatter:on + return "[name=%s, model col=%s, view col=%s]".formatted(name, modelIndex, viewIndex); } /** diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/DialogFilterCondition.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/DialogFilterCondition.java index cda6ca16ecf..6fe466dfd68 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/DialogFilterCondition.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/DialogFilterCondition.java @@ -162,13 +162,7 @@ public void setValue(String valueString, Object dataSource) { @Override public String toString() { - //@formatter:off - return "{\n" + - "\tname: " + constraintName + ",\n" + - "\teditor: " + editor + "\n" + -// "\tparent: " + parent + "\n" + // stack overflow when DialogFilterConditionSet.toString() is called - "}"; - //@formatter:on + return "[name=%s, editor=%s]".formatted(constraintName, editor); } private ColumnConstraintEditor buildDummyEditor() { diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/DialogFilterConditionSet.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/DialogFilterConditionSet.java index 2af1564c98f..a73cbfafa89 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/DialogFilterConditionSet.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/DialogFilterConditionSet.java @@ -168,13 +168,7 @@ private ColumnFilterData getColumnFilterData(int columnModelIndex) { @Override public String toString() { - //@formatter:off - return "{\n" + -// "\tfilterRow: " + filterRow + ",\n" + // stack overflow when DialogFilterRow.toString() is called - "\tdata: " + columnFilterData + ",\n" + - "\tconditions: " + conditionSet +"\n" + - "}"; - //@formatter:on + return "[data=%s, conditions=%s]".formatted(columnFilterData, conditionSet); } } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/DialogFilterRow.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/DialogFilterRow.java index d4dcde5a0ef..cea858e4ebd 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/DialogFilterRow.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/DialogFilterRow.java @@ -4,9 +4,9 @@ * 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. @@ -160,11 +160,6 @@ void delete() { @Override public String toString() { - //@formatter:off - return "{\n" + - "\toperation: " + logicOperation + ",\n" + - "\tconditions: " + columnConditionSet +"\n" + - "}"; - //@formatter:on + return "[operations=%s, conditions=%s]".formatted(logicOperation, columnConditionSet); } } From 1f1a5dc33c20508a7e7a5b17c7eddaef823d5437 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Thu, 9 Jul 2026 12:33:20 -0400 Subject: [PATCH 067/111] GP-7051 - Fixed deadlock seen when saving a program --- .../util/PersistentOpenCloseManager.java | 51 ++++++++++++++----- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/util/PersistentOpenCloseManager.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/util/PersistentOpenCloseManager.java index 21c0af5e542..1be8c37d50b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/util/PersistentOpenCloseManager.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/util/PersistentOpenCloseManager.java @@ -26,7 +26,6 @@ */ public class PersistentOpenCloseManager implements OpenCloseManager { private boolean openByDefault = true; - private VoidPropertyMap booleanProperty; private ProgramUserData programUserData; // Often, isOpen will be called on the same function address many times in a row so cache @@ -35,32 +34,53 @@ public class PersistentOpenCloseManager implements OpenCloseManager { private boolean cachedResult; private String defaultOpenClosePropertyname; + private String owner; + private String propertyName; + private VoidPropertyMap cachedPropertyMap; + public PersistentOpenCloseManager(ProgramUserData data, String owner, String propertyName) { + this.owner = owner; + this.propertyName = propertyName; this.defaultOpenClosePropertyname = propertyName + "Default"; programUserData = data; - int tx = programUserData.startTransaction(); - try { - booleanProperty = - programUserData.getBooleanProperty(owner, propertyName, true); - } - finally { - programUserData.endTransaction(tx); - } - // Get the default open state. Only addresses different from default have properties stored. String functionState = programUserData.getStringProperty(defaultOpenClosePropertyname, "Open"); openByDefault = functionState.equals("Open"); } + private VoidPropertyMap getExistingProperty() { + if (cachedPropertyMap != null) { + return cachedPropertyMap; + } + + cachedPropertyMap = programUserData.getBooleanProperty(owner, propertyName, false); + return cachedPropertyMap; + } + + private VoidPropertyMap getOrCreatePropertyMap() { + if (cachedPropertyMap != null) { + return cachedPropertyMap; + } + + cachedPropertyMap = programUserData.getBooleanProperty(owner, propertyName, true); + return cachedPropertyMap; + } + @Override public boolean isOpen(Address address) { + VoidPropertyMap propertyMap = getExistingProperty(); + if (propertyMap == null) { + return openByDefault; + } + if (address.equals(cachedAddress)) { return cachedResult; } + cachedAddress = address; - boolean contains = booleanProperty.hasProperty(address); + boolean contains = propertyMap.hasProperty(address); cachedResult = openByDefault ? !contains : contains; return cachedResult; } @@ -111,7 +131,8 @@ public void closeAll() { private void addAddressProperty(Address address) { int tx = programUserData.startTransaction(); try { - booleanProperty.add(address); + VoidPropertyMap propertyMap = getOrCreatePropertyMap(); + propertyMap.add(address); } finally { programUserData.endTransaction(tx); @@ -121,7 +142,8 @@ private void addAddressProperty(Address address) { private void removeAddressProperty(Address address) { int tx = programUserData.startTransaction(); try { - booleanProperty.remove(address); + VoidPropertyMap propertyMap = getOrCreatePropertyMap(); + propertyMap.remove(address); } finally { programUserData.endTransaction(tx); @@ -131,7 +153,8 @@ private void removeAddressProperty(Address address) { private void clearProperties() { int tx = programUserData.startTransaction(); try { - booleanProperty.clear(); + VoidPropertyMap propertyMap = getOrCreatePropertyMap(); + propertyMap.clear(); } finally { programUserData.endTransaction(tx); From f3d634968ad75930ac0bfde5e26fbf989dce1061 Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Fri, 10 Jul 2026 09:50:14 -0400 Subject: [PATCH 068/111] GP-0 Corrected server test utility to comply with Ghidra Server ACL restrictions from GP-7049 --- .../ghidra/server/remote/ServerTestUtil.java | 82 ++++++++++--------- 1 file changed, 44 insertions(+), 38 deletions(-) diff --git a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/server/remote/ServerTestUtil.java b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/server/remote/ServerTestUtil.java index 0f4bb425198..3e331d7e04a 100644 --- a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/server/remote/ServerTestUtil.java +++ b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/server/remote/ServerTestUtil.java @@ -823,13 +823,45 @@ public static void createRepositoryItem(LocalFileSystem repoFilesystem, String n } /** - * Create and populate server test repositories "Test" and "Test1" with the specified - * users added. The ADMIN_USER "test" is added by default. + * Add a new user to an existing local Ghidra Test Server using the ServerAdmin class. + * @param serverRoot server's repositories root directory + * @param name user name + * @param dn DN or null (applies to PKI authentication only) + * @throws Exception + */ + public static void addUser(File serverRoot, String name, String dn) throws Exception { + ServerAdmin serverAdmin = new ServerAdmin(); + if (dn != null) { + serverAdmin.execute(new String[] { serverRoot.getAbsolutePath(), "-dn", name, dn }); + } + else { + serverAdmin.execute(new String[] { serverRoot.getAbsolutePath(), "-add", name }); + } + } + + /** + * Grant an existing user access to a repository for an existing local Ghidra Test Server + * using the ServerAdmin class. + * @param serverRoot server's repositories root directory + * @param name user name + * @param repoName existing repository name + * @param access an access string: "+r", "+w", "+a" + * @throws Exception + */ + public static void setUserAccess(File serverRoot, String name, String repoName, String access) + throws Exception { + ServerAdmin serverAdmin = new ServerAdmin(); + serverAdmin.execute( + new String[] { serverRoot.getAbsolutePath(), "-grant", name, access, repoName }); + } + + /** + * Create and populate server test repositories "Test" and "Test1". The ADMIN_USER "test" + * is added by default to both repositories. * @param dirPath server root - * @param users optional inclusion of USER_A and/or USER_B to be added with no authentication required * @throws Exception */ - public static void createPopulatedTestServer(String dirPath, String... users) throws Exception { + public static void createPopulatedTestServer(String dirPath) throws Exception { Msg.info(ServerTestUtil.class, "Constructing Ghidra Server for testing: " + dirPath); @@ -837,16 +869,12 @@ public static void createPopulatedTestServer(String dirPath, String... users) th FileUtilities.deleteDir(rootDir); FileUtilities.mkdirs(rootDir); - String[] userArray = new String[users.length + 1]; - userArray[0] = ADMIN_USER; - System.arraycopy(users, 0, userArray, 1, users.length); - createUsers(dirPath, userArray); + createUsers(dirPath, new String[] { ADMIN_USER }); String keys[] = SSHKeyUtil.generateSSHRSAKeys(); addSSHKeys(dirPath, keys[0], "test.key", keys[1], "test.pub"); - LocalFileSystem repoFilesystem = createRepository(dirPath, "Test", ADMIN_USER + "=ADMIN", - USER_A + "=READ_ONLY", USER_B + "=WRITE"); + LocalFileSystem repoFilesystem = createRepository(dirPath, "Test", ADMIN_USER + "=ADMIN"); try { createRepositoryItem(repoFilesystem, "foo", "/", 0); createRepositoryItem(repoFilesystem, "notepad", "/", 0); @@ -857,7 +885,7 @@ public static void createPopulatedTestServer(String dirPath, String... users) th } repoFilesystem = createRepository(dirPath, "Test1", "=ANONYMOUS_ALLOWED", - ADMIN_USER + "=ADMIN", USER_A + "=WRITE"); + ADMIN_USER + "=ADMIN"); try { createRepositoryItem(repoFilesystem, "foo1", "/", 0); createRepositoryItem(repoFilesystem, "notepad1", "/", 0); @@ -870,17 +898,16 @@ public static void createPopulatedTestServer(String dirPath, String... users) th } /** - * Create and populate server test repositories "Test" and "Test1" with the specified - * users added. The ADMIN_USER "test" is added by default. + * Create and populate server test repositories "Test" and "Test1". The ADMIN_USER "test" + * is added by default to both repositories. * @param dirPath server root * @param repoName repository name * @param contentProvider repository content provider callback * (use {@link #createRepositoryItem(LocalFileSystem, String, String, Program)} to add content. - * @param users optional inclusion of USER_A and/or USER_B to be added with no authentication required * @throws Exception */ public static void createPopulatedTestServer(String dirPath, String repoName, - Consumer contentProvider, String... users) throws Exception { + Consumer contentProvider) throws Exception { Msg.info(ServerTestUtil.class, "Constructing Ghidra Server for testing: " + dirPath); @@ -888,16 +915,12 @@ public static void createPopulatedTestServer(String dirPath, String repoName, FileUtilities.deleteDir(rootDir); FileUtilities.mkdirs(rootDir); - String[] userArray = new String[users.length + 1]; - userArray[0] = ADMIN_USER; - System.arraycopy(users, 0, userArray, 1, users.length); - createUsers(dirPath, userArray); + createUsers(dirPath, new String[] { ADMIN_USER }); String keys[] = SSHKeyUtil.generateSSHRSAKeys(); addSSHKeys(dirPath, keys[0], "test.key", keys[1], "test.pub"); - LocalFileSystem repoFilesystem = createRepository(dirPath, repoName, ADMIN_USER + "=ADMIN", - USER_A + "=READ_ONLY", USER_B + "=WRITE"); + LocalFileSystem repoFilesystem = createRepository(dirPath, repoName, ADMIN_USER + "=ADMIN"); try { contentProvider.accept(repoFilesystem); } @@ -987,21 +1010,4 @@ private static Collection getLocalHostnames() throws SocketException { return altNames; } - /** - * Add PKI user to server - * @param serverRoot - * @param userName - * @param dn - * @throws Exception - */ - public static void addPKIUser(File serverRoot, String userName, String dn) throws Exception { - ServerAdmin serverAdmin = new ServerAdmin(); - if (dn != null) { - serverAdmin.execute(new String[] { serverRoot.getAbsolutePath(), "-dn", userName, dn }); - } - else { - serverAdmin.execute(new String[] { serverRoot.getAbsolutePath(), "-add", userName }); - } - } - } From 08a1765da8616b4d90ad5b7d0a0233acc15d64e6 Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Fri, 10 Jul 2026 10:38:54 -0400 Subject: [PATCH 069/111] GP-1 Revised server command processing to address testing issue --- .../main/java/ghidra/server/CommandProcessor.java | 14 +++++++------- .../main/java/ghidra/server/CommandWatcher.java | 6 +++--- .../src/main/java/ghidra/server/ServerAdmin.java | 6 +----- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/CommandProcessor.java b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/CommandProcessor.java index 93c9f414280..edff61a2f8d 100644 --- a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/CommandProcessor.java +++ b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/CommandProcessor.java @@ -224,12 +224,12 @@ static int parsePermission(String permissionStr) { return -1; } - static File getCommandDir(File serverRootDir) { - return new File(serverRootDir, ADMIN_CMD_DIR); - } - - static File getOrCreateCommandDir(RepositoryManager repositoryMgr) { - File cmdDir = getCommandDir(repositoryMgr.getRootDir()); + static File getOrCreateCommandDir(File serverRootDir) { + if (!serverRootDir.isDirectory() || !serverRootDir.canWrite()) { + System.err.println("Insufficient privilege or server not started!"); + System.exit(-1); + } + File cmdDir = new File(serverRootDir, ADMIN_CMD_DIR); if (!cmdDir.exists()) { // ensure process owner creates queued command directory cmdDir.mkdir(); @@ -243,7 +243,7 @@ static File getOrCreateCommandDir(RepositoryManager repositoryMgr) { * @throws IOException */ static void processCommands(RepositoryManager repositoryMgr) throws IOException { - File cmdDir = getOrCreateCommandDir(repositoryMgr); + File cmdDir = getOrCreateCommandDir(repositoryMgr.getRootDir()); File[] files = cmdDir.listFiles(CMD_FILE_FILTER); if (files == null) { log.error("Failed to access command queue " + cmdDir.getAbsolutePath() + diff --git a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/CommandWatcher.java b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/CommandWatcher.java index e3b4ffbe1cf..fd235b23ba4 100644 --- a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/CommandWatcher.java +++ b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/CommandWatcher.java @@ -4,9 +4,9 @@ * 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. @@ -37,7 +37,7 @@ public class CommandWatcher implements Runnable { this.repositoryMgr = repositoryMgr; watcher = FileSystems.getDefault().newWatchService(); - cmdDirPath = CommandProcessor.getOrCreateCommandDir(repositoryMgr).toPath(); + cmdDirPath = CommandProcessor.getOrCreateCommandDir(repositoryMgr.getRootDir()).toPath(); cmdDirPath.register(watcher, StandardWatchEventKinds.ENTRY_CREATE); } diff --git a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/ServerAdmin.java b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/ServerAdmin.java index 2edbc46cf06..fe0a217f84d 100644 --- a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/ServerAdmin.java +++ b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/ServerAdmin.java @@ -111,11 +111,7 @@ public void execute(String[] args) { System.exit(-1); } - File cmdDir = CommandProcessor.getCommandDir(serverRootDir); - if (!cmdDir.isDirectory() || !cmdDir.canWrite()) { - System.err.println("Insufficient privilege or server not started!"); - System.exit(-1); - } + File cmdDir = CommandProcessor.getOrCreateCommandDir(serverRootDir); // Process command line boolean listRepositories = false; From 88d689258cf9740e6120b8fdb9272082395808c5 Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Fri, 10 Jul 2026 11:09:07 -0400 Subject: [PATCH 070/111] GP-7056 Corrected PLTGOT markup issue that could skip last PLT entry --- .../ghidra/app/util/bin/format/elf/ElfDefaultGotPltMarkup.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfDefaultGotPltMarkup.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfDefaultGotPltMarkup.java index 1f2f48aff9f..f5cc6d399bb 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfDefaultGotPltMarkup.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfDefaultGotPltMarkup.java @@ -339,7 +339,7 @@ private void processDynamicPLTGOT(ElfDynamicType pltGotType, ElfDynamicType pltG return; // failed to identify first PLT entry - skip PLT processing } - Address pltEnd = firstPltEntryAddr.add(pltSpacing * (pltEntryCount - 1)); + Address pltEnd = firstPltEntryAddr.add((pltSpacing * pltEntryCount) - 1); processLinkageTable("PLT", firstPltEntryAddr, pltEnd, monitor); } catch (Exception e) { From 2834bc63629ab5ef3b528be76066f608d2ad0f65 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Fri, 10 Jul 2026 11:57:02 -0400 Subject: [PATCH 071/111] GP7055 - Fixed exception when choosing Copy Special --- .../clipboard/CodeBrowserClipboardProvider.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java index a0ba1c466f6..04a0441d0b9 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java @@ -232,12 +232,22 @@ private ClipboardType getGhidraUrlClipboardType() { if (domainFile == null) { return null; } - if (domainFile.getLocalProjectURL(null) != null) { - return GHIDRA_LOCAL_URL_TYPE; + + try { + if (domainFile.getLocalProjectURL(null) != null) { + return GHIDRA_LOCAL_URL_TYPE; + } } + catch (IllegalArgumentException e) { + // this can happen if the filename has characters the GhidraURL doesn't like + Msg.debug(this, "Can't create GhidraURL for " + domainFile.getName()); + return null; + } + if (domainFile.getSharedProjectURL(null) != null) { return GHIDRA_SHARED_URL_TYPE; } + return null; } From 1ea863e5ec36263a0a21d1f4fdb15c893bbd4a74 Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Fri, 10 Jul 2026 13:09:40 -0400 Subject: [PATCH 072/111] GP-7057 Revised ElfSymbol.isExternal() method --- .../java/ghidra/app/util/bin/format/elf/ElfSymbol.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbol.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbol.java index 70540bff280..dab7751e356 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbol.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbol.java @@ -4,9 +4,9 @@ * 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. @@ -303,8 +303,7 @@ public boolean isWeak() { * @return true if this is an external symbol */ public boolean isExternal() { - return (isGlobal() || isWeak()) && getValue() == 0 && getSize() == 0 && - getType() == STT_NOTYPE && + return (isGlobal() || isWeak()) && getSectionHeaderIndex() == ElfSectionHeaderConstants.SHN_UNDEF; } From 50315536955f02d01e818c94fe2a7931c4fc690d Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Mon, 13 Jul 2026 11:23:48 -0400 Subject: [PATCH 073/111] GP-7061 Corrected ELF Import regression related to dynamic GNU Hashtable and symbol table processing --- .../ghidra/app/util/bin/format/elf/ElfHeader.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfHeader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfHeader.java index 1d78f42dfe2..8e23f00d9ff 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfHeader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfHeader.java @@ -992,6 +992,10 @@ else if (dynamicHashType == ElfDynamicType.DT_GNU_XHASH) { symCount = reader.readInt(symbolHashTableOffset + 4); // nchain from DT_HASH } + if (symCount == 0) { + return null; + } + // NOTE: When parsed from dynamic table and not found via section header parse // it is assumed that the extended symbol section table is not used. @@ -1006,7 +1010,7 @@ else if (dynamicHashType == ElfDynamicType.DT_GNU_XHASH) { /** * Walk DT_GNU_HASH table to determine dynamic symbol count * @param gnuHashTableOffset DT_GNU_HASH table file offset - * @return dynamic symbol count + * @return dynamic symbol count (0 may be returned when processing error occurs) * @throws IOException file read error */ private int deriveGnuHashDynamicSymbolCount(long gnuHashTableOffset) throws IOException { @@ -1059,22 +1063,21 @@ private int deriveGnuHashDynamicSymbolCount(long gnuHashTableOffset) throws IOEx } private long getMaxOffsetForLoadedRegionContaining(long offset, long minSize) { - long maxOffset = -1; if (e_shnum != 0) { ElfSectionHeader sectionContaining = getSectionHeaderContainingFileRange(offset, minSize); if (sectionContaining != null) { - maxOffset = sectionContaining.getOffset() + sectionContaining.getSize() - 1; + return sectionContaining.getOffset() + sectionContaining.getSize() - 1; } } - else { + if (e_phnum != 0) { ElfProgramHeader containingSegment = getProgramLoadHeaderContainingFileOffset(offset); if (containingSegment != null) { - maxOffset = containingSegment.getOffset() + containingSegment.getFileSize() - 1; + return containingSegment.getOffset() + containingSegment.getFileSize() - 1; } } - return maxOffset; + return -1; } /** From 87d10fc6ee241b417de41acd0fb82967ec67176f Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Tue, 14 Jul 2026 05:04:31 -0400 Subject: [PATCH 074/111] GP-7064: Fixing XmlLoader path traversal --- .../java/ghidra/app/util/xml/MemoryMapXmlMgr.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/MemoryMapXmlMgr.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/MemoryMapXmlMgr.java index eb5ea454b87..dad67fc21df 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/MemoryMapXmlMgr.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/MemoryMapXmlMgr.java @@ -4,9 +4,9 @@ * 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. @@ -32,6 +32,7 @@ import ghidra.util.xml.*; import ghidra.xml.XmlElement; import ghidra.xml.XmlPullParser; +import utilities.util.FileUtilities; class MemoryMapXmlMgr { @@ -190,7 +191,12 @@ else if (element.getName().equals("BYTE_MAPPED")) { private void setData(byte[] bytes, int offset, String directory, String fileName, int fileOffset, int length, MessageLog log) throws IOException { - File f = new File(directory, fileName); + File dir = new File(directory); + File f = new File(dir, fileName); + if (!FileUtilities.isPathContainedWithin(dir, f)) { + throw new FileNotFoundException( + "FILE_NAME entry escapes target directory: " + fileName); + } RandomAccessFile binfile = new RandomAccessFile(f, "r"); //binfile.seek(fileOffset); try { From f18269b0eb079165df3627063f6c2e1d6bbbb3b2 Mon Sep 17 00:00:00 2001 From: p-mikeg Date: Tue, 14 Jul 2026 00:53:15 +0300 Subject: [PATCH 075/111] Fix sev.w arm encoding. Unlike the other hints, sev.w op0 missed the 0x in the beginning which led to incorrect parsing. The encoding should be 0xf3af8004 (https://developer.arm.com/documentation/ddi0403/latest/, sev encoding T2). --- Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc b/Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc index a56103c476a..26a34b46306 100644 --- a/Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc +++ b/Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc @@ -4358,7 +4358,7 @@ thumbEndianNess: "BE" is op0=0xb658 { export 1:1; } build ItCond; } -:sev^ItCond^".w" is TMode=1 & ItCond & op0=0xf3af; op0=8004 +:sev^ItCond^".w" is TMode=1 & ItCond & op0=0xf3af; op0=0x8004 { build ItCond; } From ce37accf24dd26d493c966a85c953279ac22b2c9 Mon Sep 17 00:00:00 2001 From: Nicolas Iooss Date: Tue, 14 Jul 2026 16:16:37 +0200 Subject: [PATCH 076/111] Do not normalize build_exe in pcodetests definitions In pcodetests definition, build_exe is an integer set to 1 when an executable may be built. Contrary to other *_exe fields, it is not the name of a command and therefore should not be normalized with exec_dir. Fixes: 71cd33572c87 ("GP-6007: Updated NDS32 analyzer and elf relocation handler and test fixups") --- Ghidra/Extensions/SleighDevTools/pcodetest/pcodetest.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Ghidra/Extensions/SleighDevTools/pcodetest/pcodetest.py b/Ghidra/Extensions/SleighDevTools/pcodetest/pcodetest.py index 42e0604168f..33f9287d6de 100644 --- a/Ghidra/Extensions/SleighDevTools/pcodetest/pcodetest.py +++ b/Ghidra/Extensions/SleighDevTools/pcodetest/pcodetest.py @@ -91,7 +91,6 @@ def main(self): # make sure compiler exists and runnable self.config.compile_exe = self.config.exec_dir + self.config.exec_prefix + self.config.compile_exe - self.config.build_exe = self.config.exec_dir + str(self.config.exec_prefix) + str(self.config.build_exe) self.config.strip_exe = self.config.exec_dir + str(self.config.exec_prefix) + str(self.config.strip_exe) self.config.objdump_exe = self.config.exec_dir + str(self.config.exec_prefix) + str(self.config.objdump_exe) self.config.readelf_exe = self.config.exec_dir + str(self.config.exec_prefix) + str(self.config.readelf_exe) From 730dd972bec5bf91928e5c6e7a2910ce4c9efd2d Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Wed, 15 Jul 2026 09:59:23 -0400 Subject: [PATCH 077/111] GP-7070 Allow DBHandle.isChanged() to consider uncommitted changes --- .../DB/src/main/java/db/DBHandle.java | 18 +++++++--- .../Framework/DB/src/test/java/db/DBTest.java | 35 +++++++++++++++++-- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/Ghidra/Framework/DB/src/main/java/db/DBHandle.java b/Ghidra/Framework/DB/src/main/java/db/DBHandle.java index 6f86d7eea29..b75a2a545ad 100644 --- a/Ghidra/Framework/DB/src/main/java/db/DBHandle.java +++ b/Ghidra/Framework/DB/src/main/java/db/DBHandle.java @@ -46,6 +46,7 @@ public class DBHandle { private long lastTransactionID; private volatile boolean txStarted = false; + private volatile long txStartingModCount; private boolean waitingForNewTransaction = false; private boolean reloadInProgress = false; @@ -472,6 +473,7 @@ public synchronized long startTransaction() { } waitingForNewTransaction = false; txStarted = true; + txStartingModCount = getModCount(); return ++lastTransactionID; } @@ -509,7 +511,7 @@ public boolean endTransaction(long id, boolean commit) throws IOException { */ private synchronized boolean doEndTransaction(long id, boolean commit) throws DBRollbackException, IOException { - if (id != lastTransactionID) { + if (!txStarted || id != lastTransactionID) { throw new IllegalStateException("Transaction id is not active"); } try { @@ -530,8 +532,10 @@ private synchronized boolean doEndTransaction(long id, boolean commit) } } finally { + if (commit) { + cachedChangedState = isChanged(); + } txStarted = false; - cacheChangedState(); } return false; } @@ -762,11 +766,17 @@ public synchronized void close(boolean keepRecoveryData) { /** * Determine if the underlying database has changed. - * NOTE: The returned value reflects a cached state assuming all underlaying database - * transactions, saving, etc. are facilitated by this handle object. + *

    + * While a transaction is active this value will reflect changes made during the transaction + * which could ultimately never get committed. When a transaction is not active it is a + * reflection of the committed state. + * * @return true if unsaved changes have been made. */ public boolean isChanged() { + if (txStarted) { + return cachedChangedState || txStartingModCount != getModCount(); + } return cachedChangedState; } diff --git a/Ghidra/Framework/DB/src/test/java/db/DBTest.java b/Ghidra/Framework/DB/src/test/java/db/DBTest.java index d3f0a619b37..a59d75ca865 100644 --- a/Ghidra/Framework/DB/src/test/java/db/DBTest.java +++ b/Ghidra/Framework/DB/src/test/java/db/DBTest.java @@ -4,9 +4,9 @@ * 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. @@ -552,6 +552,37 @@ public void testTableWithIndexRecreateUndo() throws IOException { } + @Test + public void testIsChanged() throws IOException { + + assertFalse(dbh.isChanged()); + + long txId = dbh.startTransaction(); + try { + assertFalse(dbh.isChanged()); + } + finally { + dbh.endTransaction(txId, true); + } + + assertFalse(dbh.isChanged()); + + txId = dbh.startTransaction(); + try { + assertFalse(dbh.isChanged()); + + DBTestUtils.createLongKeyTable(dbh, "TABLE", DBTestUtils.SINGLE_LONG, false, false); + assertEquals(1, dbh.getTableCount()); + + assertTrue(dbh.isChanged()); + } + finally { + dbh.endTransaction(txId, true); + } + + assertTrue(dbh.isChanged()); + } + @Test public void testEvents() throws IOException { From 9b15f9060f4e4010878104021d4d71c2908848cd Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Wed, 15 Jul 2026 18:39:42 -0400 Subject: [PATCH 078/111] GP-7072 - Fixed an exception trying to find references to a global variable without an address --- .../FindReferencesToHighSymbolAction.java | 37 ++++++++++++++----- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FindReferencesToHighSymbolAction.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FindReferencesToHighSymbolAction.java index 866fc659bb3..3e50bcd77d3 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FindReferencesToHighSymbolAction.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FindReferencesToHighSymbolAction.java @@ -4,9 +4,9 @@ * 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. @@ -21,7 +21,9 @@ import ghidra.app.plugin.core.decompile.DecompilerProvider; import ghidra.app.plugin.core.navigation.locationreferences.LocationReferencesService; import ghidra.app.util.HelpTopics; -import ghidra.program.model.listing.Function; +import ghidra.program.model.address.Address; +import ghidra.program.model.listing.*; +import ghidra.program.model.pcode.HighFunction; import ghidra.program.model.pcode.HighSymbol; import ghidra.program.model.symbol.Symbol; import ghidra.program.util.LabelFieldLocation; @@ -61,16 +63,27 @@ protected boolean isEnabledForDecompilerContext(DecompilerActionContext context) updateMenuName(function.getName()); return true; } + ClangToken token = context.getTokenAtCursor(); if (token == null) { return false; } + HighSymbol highSymbol = token.getHighSymbol(context.getHighFunction()); + if (highSymbol == null) { + return false; + } - if (highSymbol == null || highSymbol.getStorage().isBadStorage() || - !highSymbol.isGlobal()) { + if (highSymbol.getStorage().isBadStorage() || !highSymbol.isGlobal()) { return false; } + + VariableStorage storage = highSymbol.getStorage(); + Address addr = storage.getMinAddress(); + if (addr == null) { + return false; + } + updateMenuName(highSymbol.getName()); return true; } @@ -85,17 +98,23 @@ protected void decompilerActionPerformed(DecompilerActionContext context) { "Please add the plugin implementing this service."); return; } + LabelFieldLocation location = null; Function function = getFunction(context); if (function != null && !(function instanceof UndefinedFunction)) { location = new LabelFieldLocation(function.getSymbol()); } else { - HighSymbol highSymbol = - context.getTokenAtCursor().getHighSymbol(context.getHighFunction()); - location = new LabelFieldLocation(context.getProgram(), - highSymbol.getStorage().getMinAddress(), highSymbol.getName()); + ClangToken token = context.getTokenAtCursor(); + HighFunction highFunction = context.getHighFunction(); + HighSymbol highSymbol = token.getHighSymbol(highFunction); + Program program = context.getProgram(); + VariableStorage storage = highSymbol.getStorage(); + Address minAddress = storage.getMinAddress(); + String symbolName = highSymbol.getName(); + location = new LabelFieldLocation(program, minAddress, symbolName); } + DecompilerProvider provider = context.getComponentProvider(); service.showReferencesToLocation(location, provider); } From b3381bb52635ce898e9bbe5aa9d814575f731e5d Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Thu, 16 Jul 2026 14:08:02 -0400 Subject: [PATCH 079/111] GP-1 Corrected regrerssion failure --- .../DB/src/main/java/db/DBHandle.java | 34 +++++-------------- 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/Ghidra/Framework/DB/src/main/java/db/DBHandle.java b/Ghidra/Framework/DB/src/main/java/db/DBHandle.java index b75a2a545ad..be6eaddc38b 100644 --- a/Ghidra/Framework/DB/src/main/java/db/DBHandle.java +++ b/Ghidra/Framework/DB/src/main/java/db/DBHandle.java @@ -519,6 +519,7 @@ private synchronized boolean doEndTransaction(long id, boolean commit) if (commit) { masterTable.flush(); if (bufferMgr.checkpoint()) { + cachedChangedState = isChanged(); ++checkpointNum; return true; } @@ -532,15 +533,13 @@ private synchronized boolean doEndTransaction(long id, boolean commit) } } finally { - if (commit) { - cachedChangedState = isChanged(); - } txStarted = false; } return false; } private void cacheChangedState() { + // Must be invoked from within a synchronized block when no transaction is active cachedChangedState = bufferMgr != null && bufferMgr.isChanged(); } @@ -550,7 +549,10 @@ private void cacheChangedState() { * * @return current modification count */ - public long getModCount() { + public synchronized long getModCount() { + if (bufferMgr == null) { + return txStartingModCount; // ballpark value (database has been closed) + } return bufferMgr.getModCount(); } @@ -715,26 +717,6 @@ public int getTableCount() { return tables.size(); } - /** - * Revert the current database version to an older version. - * @param oldVersion - * @param monitor - * @return boolean - * @throws IllegalStateException if the database has modified prior to - * invoking this method. - * @throws IllegalArgumentException if this method is invoked more than - * once or the version file(s) are corrupt. - */ -// boolean revert(int oldVersion, TaskMonitor monitor) throws IOException { -// for (int v = (version-1); v >= oldVersion; --v) { -// monitor.setMessage("Processing Version " + v); -// bufferMgr.applyVersionFile(db.getVersionFile(v), monitor); -// if (monitor.isCancelled()) -// return false; -// } -// return true; -// } - /** * Close the database and dispose of the underlying buffer manager. * Any existing recovery data will be discarded. @@ -773,8 +755,8 @@ public synchronized void close(boolean keepRecoveryData) { * * @return true if unsaved changes have been made. */ - public boolean isChanged() { - if (txStarted) { + public synchronized boolean isChanged() { + if (bufferMgr != null && txStarted) { return cachedChangedState || txStartingModCount != getModCount(); } return cachedChangedState; From db839765545caf825cb7ca73f4664312e7287256 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Fri, 17 Jul 2026 08:38:44 -0400 Subject: [PATCH 080/111] GP-7071: Fixing potential infinite loop in the PefLoader, and some other PEF/OMF parsing fixes --- .../app/util/bin/format/omf/Omf2or4.java | 37 +++---------------- .../app/util/bin/format/omf/OmfUtils.java | 2 +- .../bin/format/omf/omf/OmfIteratedData.java | 18 +++++---- .../util/bin/format/pef/ContainerHeader.java | 12 ++++-- .../util/bin/format/pef/SectionHeader.java | 14 ++++--- .../ghidra/app/util/opinion/PefLoader.java | 8 ++++ 6 files changed, 43 insertions(+), 48 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/omf/Omf2or4.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/omf/Omf2or4.java index f21d076560d..a12709c95ad 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/omf/Omf2or4.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/omf/Omf2or4.java @@ -4,9 +4,9 @@ * 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. @@ -23,36 +23,11 @@ /** * An OMF value that is either 2 or 4 bytes + * + * @param length 2 or 4 + * @param value The 2 or 4 byte value */ -public class Omf2or4 implements StructConverter { - - private int length; - private long value; - - /** - * Creates a new {@link Omf2or4} - * - * @param length 2 or 4 - * @param value The 2 or 4 byte value - */ - public Omf2or4(int length, long value) { - this.length = length; - this.value = value; - } - - /** - * {@return the length of the value (2 or 4)} - */ - public int length() { - return length; - } - - /** - * {@return the value} - */ - public long value() { - return value; - } +public record Omf2or4(int length, long value) implements StructConverter { @Override public DataType toDataType() throws DuplicateNameException, IOException { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/omf/OmfUtils.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/omf/OmfUtils.java index a93cff8ed9c..6b227b9c68e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/omf/OmfUtils.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/omf/OmfUtils.java @@ -35,7 +35,7 @@ public class OmfUtils { public static final String CATEGORY_PATH = "/OMF"; public static Omf2or4 readInt2Or4(BinaryReader reader, boolean isBig) throws IOException { - return isBig ? new Omf2or4(4, reader.readNextInt()) + return isBig ? new Omf2or4(4, reader.readNextUnsignedInt()) : new Omf2or4(2, reader.readNextUnsignedShort()); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/omf/omf/OmfIteratedData.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/omf/omf/OmfIteratedData.java index f6a221ea9c1..faf9f03c492 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/omf/omf/OmfIteratedData.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/omf/omf/OmfIteratedData.java @@ -4,9 +4,9 @@ * 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. @@ -19,7 +19,8 @@ import java.util.ArrayList; import ghidra.app.util.bin.BinaryReader; -import ghidra.app.util.bin.format.omf.*; +import ghidra.app.util.bin.format.omf.OmfException; +import ghidra.app.util.bin.format.omf.OmfUtils; import ghidra.program.model.data.DataType; import ghidra.util.exception.DuplicateNameException; @@ -83,14 +84,17 @@ public byte[] getByteArray(BinaryReader reader) throws IOException { * Contain the definition of one part of a datablock with possible recursion */ public static class DataBlock { - private Omf2or4 repeatCount; + private int repeatCount; private int blockCount; private byte[] simpleBlock = null; private DataBlock[] nestedBlock = null; public static DataBlock read(BinaryReader reader, boolean hasBigFields) throws IOException { DataBlock subblock = new DataBlock(); - subblock.repeatCount = OmfUtils.readInt2Or4(reader, hasBigFields); + subblock.repeatCount = (int) OmfUtils.readInt2Or4(reader, hasBigFields).value(); + if (subblock.repeatCount < 0) { + throw new IOException("Iterated block has negative repeat count"); + } subblock.blockCount = reader.readNextUnsignedShort(); if (subblock.blockCount == 0) { int size = reader.readNextByte() & 0xff; @@ -115,7 +119,7 @@ public static DataBlock read(BinaryReader reader, boolean hasBigFields) throws I * @return The position after the block */ public int fillBuffer(byte[] buffer, int pos) { - for (int i = 0; i < (int) repeatCount.value(); ++i) { + for (int i = 0; i < repeatCount; ++i) { if (simpleBlock != null) { for (byte element : simpleBlock) { buffer[pos] = element; @@ -144,7 +148,7 @@ else if (nestedBlock != null) { length += block.getLength(); } } - return length * (int) repeatCount.value(); + return length * repeatCount; } /** diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pef/ContainerHeader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pef/ContainerHeader.java index 511fab80d8b..d13813089db 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pef/ContainerHeader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pef/ContainerHeader.java @@ -15,14 +15,14 @@ */ package ghidra.app.util.bin.format.pef; -import ghidra.app.util.bin.*; -import ghidra.program.model.data.*; -import ghidra.util.exception.DuplicateNameException; - import java.io.IOException; import java.util.ArrayList; import java.util.List; +import ghidra.app.util.bin.*; +import ghidra.program.model.data.*; +import ghidra.util.exception.DuplicateNameException; + /** * See Apple's -- PEFBinaryFormat.h *

    @@ -103,6 +103,10 @@ public void parse() throws IOException, PefException {
     			}
     			_sections.add(section);
     		}
    +
    +		if (_loader == null) {
    +			throw new PefException("Loader section not found!");
    +		}
     	}
     
     	/**
    diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pef/SectionHeader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pef/SectionHeader.java
    index 858d4e287d4..d1ed148306f 100644
    --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pef/SectionHeader.java
    +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pef/SectionHeader.java
    @@ -4,9 +4,9 @@
      * 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.
    @@ -113,8 +113,9 @@ public InputStream getData() throws IOException {
     	 * @param monitor the task monitor
     	 * @return the unpacked data
     	 * @throws IOException if an i/o error occurs or the section is not packed.
    +	 * @throws IllegalStateException an an unexpected state occurs
     	 */
    -	public byte[] getUnpackedData(TaskMonitor monitor) throws IOException {
    +	public byte[] getUnpackedData(TaskMonitor monitor) throws IOException, IllegalStateException {
     		if (getSectionKind() != SectionKind.PackedData) {
     			throw new IOException("Attempt to unpack a section that is not packed.");
     		}
    @@ -127,7 +128,7 @@ public byte[] getUnpackedData(TaskMonitor monitor) throws IOException {
     				}
     				int value = input.read();
     				if (value == -1) {
    -					throw new IllegalStateException();
    +					throw new IllegalStateException("Unexpectedly reached end-of-file");
     				}
     				int count = value & 0x1f;//count is the lower 5 bits...
     				if (count == 0) {
    @@ -218,11 +219,14 @@ else if (opcode == PackedDataOpcodes.kPEFPkDataRepeatZero) {
     		}
     	}
     
    -	private int unpackNextValue(InputStream input) throws IOException {
    +	private int unpackNextValue(InputStream input) throws IOException, IllegalStateException {
     		int unpacked = 0;
     		while (true) {
     			unpacked <<= 7;
     			int value = input.read();
    +			if (value == -1) {
    +				throw new IllegalStateException("Unexpectedly reached end-of-file");
    +			}
     			unpacked += (value & 0x7f);
     			if ((value & 0x80) == 0x00) {
     				break;
    diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/PefLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/PefLoader.java
    index 3d274bc7e2c..7b3dde1bd79 100644
    --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/PefLoader.java
    +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/PefLoader.java
    @@ -35,6 +35,14 @@
     import ghidra.util.exception.CancelledException;
     import ghidra.util.task.TaskMonitor;
     
    +/**
    + * A {@link Loader} for Preferred Executable Format (PEF) files.
    + * 

    + * PEF was developed by Apple for use in its classic Mac OS operating system. BeOS on PowerPC + * systems also uses PEF. + * + * @see PEF Structure + */ public class PefLoader extends AbstractProgramWrapperLoader { public final static String PEF_NAME = "Preferred Executable Format (PEF)"; From fe841ab92d04e564268c32319d758357b02c956b Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Mon, 20 Jul 2026 11:31:01 -0400 Subject: [PATCH 081/111] GP-7079: Handling missing LC_SYMTAB better (Closes #9399) --- .../util/bin/format/macho/commands/SymbolTableCommand.java | 4 ++-- .../java/ghidra/app/util/opinion/MachoProgramBuilder.java | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/SymbolTableCommand.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/SymbolTableCommand.java index f1ccd62e75f..48c466a8779 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/SymbolTableCommand.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/SymbolTableCommand.java @@ -42,7 +42,7 @@ public class SymbolTableCommand extends LoadCommand { private long stroff; private long strsize; - private List symbols = new ArrayList(); + private List symbols = new ArrayList<>(); /** * Creates and parses a new {@link SymbolTableCommand} @@ -144,7 +144,7 @@ public NList getSymbolAt(int index) { (index & DynamicSymbolTableConstants.INDIRECT_SYMBOL_ABS) != 0) { return null; } - if (index > symbols.size()) { + if (index >= symbols.size()) { return null; } return symbols.get(index); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoProgramBuilder.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoProgramBuilder.java index 2916eaeda88..0051b07db3c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoProgramBuilder.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoProgramBuilder.java @@ -692,7 +692,8 @@ protected void processStubs() throws Exception { for (int i = indirectSymbolTableIndex; i < indirectSymbolTableIndex + nSymbols; ++i) { monitor.increment(); int symbolIndex = indirectSymbols.get(i); - NList symbol = symbolTableCommand.getSymbolAt(symbolIndex); + NList symbol = + symbolTableCommand != null ? symbolTableCommand.getSymbolAt(symbolIndex) : null; String name = null; if (symbol != null && !symbol.getString().isBlank()) { name = SymbolUtilities.replaceInvalidChars(symbol.getString(), true); From ca4603ad14324ef45e72650b7843f07aab1d07f0 Mon Sep 17 00:00:00 2001 From: ghidragon <106987263+ghidragon@users.noreply.github.com> Date: Mon, 20 Jul 2026 14:41:21 -0400 Subject: [PATCH 082/111] GP-7048 fixed stack trace in AccessibleFieldPanel --- .../docking/widgets/fieldpanel/AccessibleField.java | 8 +++++--- .../fieldpanel/AccessibleFieldPanelDelegate.java | 12 +++++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/AccessibleField.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/AccessibleField.java index 298384c14f5..cb6f2ec9a0d 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/AccessibleField.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/AccessibleField.java @@ -4,9 +4,9 @@ * 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. @@ -19,6 +19,7 @@ import java.awt.event.FocusListener; import java.text.BreakIterator; import java.util.Locale; +import java.util.Objects; import javax.accessibility.*; import javax.swing.JComponent; @@ -49,11 +50,12 @@ public class AccessibleField extends AccessibleContext * @param bounds the bounds of the field relative to the field panel. */ public AccessibleField(Field field, JComponent parent, int indexInParent, Rectangle bounds) { + Objects.requireNonNull(field); this.field = field; this.parent = parent; this.indexInParent = indexInParent; this.locale = parent.getLocale(); - this.boundsInParent = bounds; + this.boundsInParent = bounds != null ? bounds : new Rectangle(0, 0, 0, 0); setAccessibleName("Field"); } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/AccessibleFieldPanelDelegate.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/AccessibleFieldPanelDelegate.java index 10b471cd516..303bfb2da86 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/AccessibleFieldPanelDelegate.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/fieldpanel/AccessibleFieldPanelDelegate.java @@ -27,6 +27,7 @@ import docking.widgets.EventTrigger; import docking.widgets.fieldpanel.field.Field; import docking.widgets.fieldpanel.support.*; +import ghidra.util.Msg; /** * Contains all the code for implementing the AccessibleFieldPanel which is an inner class in @@ -217,8 +218,9 @@ public AccessibleField getAccessibleField(int fieldNum) { */ public AccessibleField getAccessibleField(FieldLocation loc) { AccessibleLayout accessibleLayout = getAccessibleLayout(loc.getIndex()); + int fieldNum = loc.getFieldNum(); if (accessibleLayout != null) { - return getAccessibleField(accessibleLayout.getStartingFieldNum() + loc.getFieldNum()); + return getAccessibleField(accessibleLayout.getStartingFieldNum() + fieldNum); } LayoutModel layoutModel = panel.getLayoutModel(); @@ -226,8 +228,12 @@ public AccessibleField getAccessibleField(FieldLocation loc) { if (layout == null) { return null; } - Field field = layout.getField(loc.getFieldNum()); - return new AccessibleField(field, panel, loc.getFieldNum(), null); + Field field = layout.getField(fieldNum); + if (field == null) { + Msg.warn(this, "Can't find field for given FieldLocation, loc = " + loc); + return null; + } + return new AccessibleField(field, panel, fieldNum, null); } private AccessibleLayout getAccessibleLayout(BigInteger index) { From 683b8dae88074c629ee2d8a7b69e1c2994d6d0ef Mon Sep 17 00:00:00 2001 From: Fereydoun Memarzanjany Date: Mon, 20 Jul 2026 00:45:01 -0600 Subject: [PATCH 083/111] 9396: Fix unsigned PE export ordinal-table indexes The PE Export Ordinal Table stores unsigned 16-bit indexes into the Export Address Table. Reading these values with readShort() sign-extends entries from 0x8000 through 0xffff, preventing them from matching the nonnegative function index and causing their export names to be lost. --- .../java/ghidra/app/util/bin/format/pe/ExportDataDirectory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/ExportDataDirectory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/ExportDataDirectory.java index 54d14c39cf1..01bb7df9068 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/ExportDataDirectory.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/ExportDataDirectory.java @@ -314,7 +314,7 @@ public boolean parse() throws IOException { // See if this function has an associated name exported for it. for (int j = 0; j < numberOfNames; ++j) { - int jthOrdinalVal = reader.readShort(pointerToOrdinals + (j * 2)); + int jthOrdinalVal = reader.readUnsignedShort(pointerToOrdinals + (j * 2)); if (jthOrdinalVal == i) { int jthNameRVA = reader.readInt(pointerToNames + (j * 4)); int jthNamePtr = ntHeader.rvaToPointer(jthNameRVA); From ebb5497940fbf63c1f4b9c8b2466928bd8b583a2 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Tue, 21 Jul 2026 15:30:12 -0400 Subject: [PATCH 084/111] GP-7087: Improved the handling of JDOM attribute errors in the PE LibraryLookupTable (Closes #6288) --- .../app/util/opinion/AbstractOrdinalSupportLoader.java | 3 ++- .../ghidra/app/util/opinion/LibraryLookupTable.java | 10 +++++++++- .../ghidra/app/util/opinion/LibrarySymbolTable.java | 9 +++------ 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/AbstractOrdinalSupportLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/AbstractOrdinalSupportLoader.java index 5e950ebf8ca..021feb2bea6 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/AbstractOrdinalSupportLoader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/AbstractOrdinalSupportLoader.java @@ -94,7 +94,8 @@ protected void processLibrary(Program lib, String libName, FSRL libFsrl, log.appendMsg("Created exports file: " + newExportsFile); } catch (IOException e) { - log.appendMsg("Unable to create exports file for " + libFsrl); + log.appendMsg( + "Unable to create exports file for %s: %s".formatted(libFsrl, e.getMessage())); } } else { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/LibraryLookupTable.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/LibraryLookupTable.java index 13cc9933c1f..01e1a6a089e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/LibraryLookupTable.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/LibraryLookupTable.java @@ -19,6 +19,9 @@ import java.io.IOException; import java.util.*; +import org.jdom2.IllegalDataException; +import org.jdom2.IllegalNameException; + import generic.jar.ResourceFile; import ghidra.app.util.bin.format.pe.ResourceDataDirectory; import ghidra.app.util.importer.MessageLog; @@ -173,7 +176,12 @@ public synchronized static ResourceFile createFile(Program program, boolean over Msg.warn(LibraryLookupTable.class, "Can't write to installation directory"); } else { - symTab.write(f, new File(program.getExecutablePath()), version); + try { + symTab.write(f, new File(program.getExecutablePath()), version); + } + catch (IllegalNameException | IllegalDataException e) { + throw new IOException(e); + } } return file; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/LibrarySymbolTable.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/LibrarySymbolTable.java index c26cc0ba5b5..256b4a7e02c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/LibrarySymbolTable.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/LibrarySymbolTable.java @@ -485,7 +485,8 @@ private void read(ResourceFile file, int size) throws IOException { //} } - void write(File output, File input, String lversion) throws IOException { + void write(File output, File input, String lversion) + throws IOException, IllegalNameException, IllegalDataException { Element root = new Element("LIBRARY"); root.setAttribute("NAME", tableName); @@ -515,16 +516,12 @@ void write(File output, File input, String lversion) throws IOException { root.addContent(export); } - FileOutputStream fos = new FileOutputStream(output); - try { + try (FileOutputStream fos = new FileOutputStream(output)) { Document doc = new Document(root); XMLOutputter xmlout = GenericXMLOutputter.getInstance(); xmlout.output(doc, fos); } - finally { - fos.close(); - } //StringBuffer buffer = new StringBuffer(); //Iterator iter = exportList.iterator(); From 3101600853b76db6fbf699805a96c5fd98efb4eb Mon Sep 17 00:00:00 2001 From: Meow Date: Wed, 22 Jul 2026 01:01:17 +0200 Subject: [PATCH 085/111] fix: missing implementation for IMAGE_REL_ARM64_ADDR64 --- .../coff/relocation/AARCH64_CoffRelocationHandler.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Ghidra/Processors/AARCH64/src/main/java/ghidra/app/util/bin/formatt/coff/relocation/AARCH64_CoffRelocationHandler.java b/Ghidra/Processors/AARCH64/src/main/java/ghidra/app/util/bin/formatt/coff/relocation/AARCH64_CoffRelocationHandler.java index 99974f48e08..eee6c08f6a9 100644 --- a/Ghidra/Processors/AARCH64/src/main/java/ghidra/app/util/bin/formatt/coff/relocation/AARCH64_CoffRelocationHandler.java +++ b/Ghidra/Processors/AARCH64/src/main/java/ghidra/app/util/bin/formatt/coff/relocation/AARCH64_CoffRelocationHandler.java @@ -187,6 +187,11 @@ public RelocationResult relocate(Address address, CoffRelocation relocation, mem.setInt(address, bytesToAdjust); break; + case IMAGE_REL_ARM64_ADDR64: + mem.setLong(address, symbolAddr.getOffset()); + byteLength = 8; + break; + default: { return RelocationResult.UNSUPPORTED; } From 10b2f530c6872b147adc971bd5dfbc930b9f36df Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Wed, 22 Jul 2026 17:14:15 -0400 Subject: [PATCH 086/111] GP-7019: Fixed pslld count operand --- Ghidra/Processors/x86/data/languages/ia.sinc | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Ghidra/Processors/x86/data/languages/ia.sinc b/Ghidra/Processors/x86/data/languages/ia.sinc index 7763d811f92..cffcdf28c95 100644 --- a/Ghidra/Processors/x86/data/languages/ia.sinc +++ b/Ghidra/Processors/x86/data/languages/ia.sinc @@ -9065,14 +9065,15 @@ define pcodeop psllw; :PSLLW mmxreg2, imm8 is vexMode=0 & mandover=0 & byte=0x0F; byte=0x71; mod = 0b11 & reg_opcode=6 & mmxreg2; imm8 { mmxreg2 = psllw(mmxreg2, imm8:8); } :PSLLD mmxreg, m64 is vexMode=0 & mandover=0 & byte=0x0F; byte=0xF2; mmxreg ... & m64 ... { - local m:8 = m64; - mmxreg[0,32] = mmxreg[0,32] << m[0,32]; - mmxreg[32,32] = mmxreg[32,32] << m[32,32]; + local count = m64; + mmxreg[0,32] = mmxreg[0,32] << count; + mmxreg[32,32] = mmxreg[32,32] << count; } :PSLLD mmxreg1, mmxreg2 is vexMode=0 & mandover=0 & byte=0x0F; byte=0xF2; mmxmod = 3 & mmxreg1 & mmxreg2 { - mmxreg1[0,32] = mmxreg1[0,32] << mmxreg2[0,32]; - mmxreg1[32,32] = mmxreg1[32,32] << mmxreg2[32,32]; + local count = mmxreg2; + mmxreg1[0,32] = mmxreg1[0,32] << count; + mmxreg1[32,32] = mmxreg1[32,32] << count; } :PSLLD mmxreg2, imm8 is vexMode=0 & mandover=0 & byte=0x0F; byte=0x72; mod = 0b11 & reg_opcode=6 & mmxreg2; imm8 { @@ -9090,7 +9091,7 @@ define pcodeop psllw; :PSLLD XmmReg, m128 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0xF2; XmmReg ... & m128 ... { local m:16 = m128; - local count:4 = m[0,32]; + local count:8 = m(0); XmmReg[0,32] = XmmReg[0,32] << count; XmmReg[32,32] = XmmReg[32,32] << count; XmmReg[64,32] = XmmReg[64,32] << count; @@ -9098,7 +9099,7 @@ define pcodeop psllw; } :PSLLD XmmReg1, XmmReg2 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0xF2; xmmmod = 3 & XmmReg1 & XmmReg2 { - local count:4 = XmmReg2[0,32]; + local count = XmmReg2[0,64]; XmmReg1[0,32] = XmmReg1[0,32] << count; XmmReg1[32,32] = XmmReg1[32,32] << count; XmmReg1[64,32] = XmmReg1[64,32] << count; From efaddf9a09e526ec3dcc95886dc2c770602fa08c Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Tue, 7 Jul 2026 15:04:11 -0400 Subject: [PATCH 087/111] GP-7046: Safer parsing of dyld_shared_cache files --- .../macho/commands/SymbolTableCommand.java | 2 +- .../codesignature/CodeSignatureSuperBlob.java | 4 +- .../macho/dyld/DyldCacheAccelerateInfo.java | 8 +- .../format/macho/dyld/DyldCacheHeader.java | 112 +++++++----------- .../macho/dyld/DyldCacheLocalSymbolsInfo.java | 30 ++--- 5 files changed, 61 insertions(+), 95 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/SymbolTableCommand.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/SymbolTableCommand.java index 48c466a8779..3a5762bcdbf 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/SymbolTableCommand.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/SymbolTableCommand.java @@ -63,7 +63,7 @@ public SymbolTableCommand(BinaryReader loadCommandReader, BinaryReader dataReade stroff = loadCommandReader.readNextUnsignedInt(); strsize = loadCommandReader.readNextUnsignedInt(); - List nlistList = new ArrayList<>((int) nsyms); + List nlistList = new ArrayList<>(); dataReader.setPointerIndex(header.getStartIndex() + symoff); for (int i = 0; i < nsyms; ++i) { nlistList.add(new NList(dataReader, header.is32bit())); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/codesignature/CodeSignatureSuperBlob.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/codesignature/CodeSignatureSuperBlob.java index 2cd6311632c..b87ee43e62b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/codesignature/CodeSignatureSuperBlob.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/codesignature/CodeSignatureSuperBlob.java @@ -54,12 +54,12 @@ public CodeSignatureSuperBlob(BinaryReader reader) throws IOException { super(reader); count = reader.readNextInt(); - indexList = new ArrayList<>(count); + indexList = new ArrayList<>(); for (int i = 0; i < count; i++) { indexList.add(new CodeSignatureBlobIndex(reader)); } - indexBlobs = new ArrayList<>(count); + indexBlobs = new ArrayList<>(); for (CodeSignatureBlobIndex blobIndex : indexList) { reader.setPointerIndex(base + blobIndex.getOffset()); indexBlobs.add(CodeSignatureBlobParser.parse(reader)); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldCacheAccelerateInfo.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldCacheAccelerateInfo.java index baa0206c6eb..385c2f87677 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldCacheAccelerateInfo.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldCacheAccelerateInfo.java @@ -92,10 +92,10 @@ public DyldCacheAccelerateInfo(BinaryReader reader) throws IOException { rangeTableCount = reader.readNextInt(); dyldSectionAddr = reader.readNextLong(); - imageInfoExtraList = new ArrayList<>(imageExtrasCount); - acceleratorInitializerList = new ArrayList<>(initializersCount); - acceleratorDofList = new ArrayList<>(dofSectionsCount); - rangeEntryList = new ArrayList<>(rangeTableCount); + imageInfoExtraList = new ArrayList<>(); + acceleratorInitializerList = new ArrayList<>(); + acceleratorDofList = new ArrayList<>(); + rangeEntryList = new ArrayList<>(); } /** diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldCacheHeader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldCacheHeader.java index 075aa381742..c91837409fe 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldCacheHeader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldCacheHeader.java @@ -380,11 +380,11 @@ public DyldCacheHeader(BinaryReader reader) throws IOException { baseAddress = reader.readLong(mappingOffset); architecture = DyldArchitecture.getArchitecture(new String(magic).trim()); - mappingInfoList = new ArrayList<>(mappingCount); - cacheMappingAndSlideInfoList = new ArrayList<>(mappingWithSlideCount); + mappingInfoList = new ArrayList<>(); + cacheMappingAndSlideInfoList = new ArrayList<>(); slideInfoList = new ArrayList<>(); - imageInfoList = new ArrayList<>(imagesCountOld); - branchPoolList = new ArrayList<>(branchPoolsCount); + imageInfoList = new ArrayList<>(); + branchPoolList = new ArrayList<>(); imageTextInfoList = new ArrayList<>(); subcacheEntryList = new ArrayList<>(); } @@ -448,9 +448,8 @@ private void parseCacheMappingSlideInfo(MessageLog log, TaskMonitor monitor) } reader.setPointerIndex(mappingWithSlideOffset); for (int i = 0; i < mappingWithSlideCount; ++i) { + monitor.increment(); cacheMappingAndSlideInfoList.add(new DyldCacheMappingAndSlideInfo(reader)); - monitor.checkCancelled(); - monitor.incrementProgress(1); } } catch (IOException e) { @@ -1087,72 +1086,66 @@ public long getBaseAddress() { } /** - * Gets the {@link List} of {@link DyldCacheMappingInfo}s. Requires header to have been parsed. - * - * @return The {@link List} of {@link DyldCacheMappingInfo}s + * {@return the {@link List} of {@link DyldCacheMappingInfo}s} + *

    + * Requires header to have been parsed. */ public List getMappingInfos() { return mappingInfoList; } /** - * Gets the {@link List} of {@link DyldCacheImageInfo}s. Requires header to have been parsed. - * - * @return The {@link List} of {@link DyldCacheImageInfo}s + * {@return the {@link List} of {@link DyldCacheImageInfo}s} + *

    + * Requires header to have been parsed. */ public List getImageInfos() { return imageInfoList; } /** - * Gets the {@link List} of {@link DyldSubcacheEntry}s. Requires header to have been parsed. - * - * @return The {@link List} of {@link DyldSubcacheEntry}s + * {@return the {@link List} of {@link DyldSubcacheEntry}s} + *

    + * Requires header to have been parsed. */ public List getSubcacheEntries() { return subcacheEntryList; } /** - * Gets the {@link List} of {@link DyldCacheMappingAndSlideInfo}s. Requires header to have been parsed. - * - * @return The {@link List} of {@link DyldCacheMappingAndSlideInfo}s + * {@return the {@link List} of {@link DyldCacheMappingAndSlideInfo}s} + *

    + * Requires header to have been parsed. */ public List getCacheMappingAndSlideInfos() { return cacheMappingAndSlideInfoList; } /** - * Gets the {@link DyldCacheLocalSymbolsInfo}. - * - * @return The {@link DyldCacheLocalSymbolsInfo}. Could be null if it didn't parse. + * {@return the {@link DyldCacheLocalSymbolsInfo}, or {@code null} if it didn't parse} */ public DyldCacheLocalSymbolsInfo getLocalSymbolsInfo() { return localSymbolsInfo; } /** - * Gets the {@link List} of {@link DyldCacheSlideInfoCommon}s. - * - * @return the {@link List} of {@link DyldCacheSlideInfoCommon}s. + * {@return the {@link List} of {@link DyldCacheSlideInfoCommon}s} */ public List getSlideInfos() { return slideInfoList; } /** - * Gets the {@link List} of branch pool address. Requires header to have been parsed. - * - * @return The {@link List} of branch pool address + * {@return the {@link List} of branch pool address} + *

    + * Requires header to have been parsed. */ public List getBranchPoolAddresses() { return branchPoolList; } /** - * Gets architecture information. - * - * @return architecture information + * {@return architecture information} */ public DyldArchitecture getArchitecture() { return architecture; @@ -1266,8 +1259,7 @@ private void parseMappingInfo(MessageLog log, TaskMonitor monitor) throws Cancel reader.setPointerIndex(mappingOffset); for (int i = 0; i < mappingCount; ++i) { mappingInfoList.add(new DyldCacheMappingInfo(reader)); - monitor.checkCancelled(); - monitor.incrementProgress(1); + monitor.increment(); } } catch (IOException e) { @@ -1288,8 +1280,7 @@ private void parseImageInfo(MessageLog log, TaskMonitor monitor) throws Cancelle reader.setPointerIndex(offset); for (int i = 0; i < count; ++i) { imageInfoList.add(new DyldCacheImageInfo(reader)); - monitor.checkCancelled(); - monitor.incrementProgress(1); + monitor.increment(); } } catch (IOException e) { @@ -1328,8 +1319,7 @@ private void parseBranchPools(MessageLog log, TaskMonitor monitor) throws Cancel reader.setPointerIndex(branchPoolsOffset); for (int i = 0; i < branchPoolsCount; ++i) { branchPoolList.add(reader.readNextLong()); - monitor.checkCancelled(); - monitor.incrementProgress(1); + monitor.increment(); } } catch (IOException e) { @@ -1347,8 +1337,7 @@ private void parseImageTextInfo(MessageLog log, TaskMonitor monitor) throws Canc reader.setPointerIndex(imagesTextOffset); for (int i = 0; i < imagesTextCount; ++i) { imageTextInfoList.add(new DyldCacheImageTextInfo(reader)); - monitor.checkCancelled(); - monitor.incrementProgress(1); + monitor.increment(); } } catch (IOException e) { @@ -1367,8 +1356,7 @@ private void parseSubcaches(MessageLog log, TaskMonitor monitor) throws Cancelle reader.setPointerIndex(subCacheArrayOffset); for (int i = 0; i < subCacheArrayCount; ++i) { subcacheEntryList.add(new DyldSubcacheEntry(reader)); - monitor.checkCancelled(); - monitor.incrementProgress(1); + monitor.increment(); } } catch (IOException e) { @@ -1420,11 +1408,10 @@ private void markupMappingInfo(Program program, AddressSpace space, TaskMonitor try { Address addr = fileOffsetToAddr(mappingOffset, program, space); for (DyldCacheMappingInfo mappingInfo : mappingInfoList) { + monitor.increment(); Data d = DataUtilities.createData(program, addr, mappingInfo.toDataType(), -1, DataUtilities.ClearDataMode.CHECK_FOR_SPACE); addr = addr.add(d.getLength()); - monitor.checkCancelled(); - monitor.incrementProgress(1); } } catch (CodeUnitInsertionException | DuplicateNameException | IOException e) { @@ -1440,11 +1427,10 @@ private void markupCacheMappingSlideInfo(Program program, AddressSpace space, Me try { Address addr = fileOffsetToAddr(mappingWithSlideOffset, program, space); for (DyldCacheMappingAndSlideInfo mappingInfo : cacheMappingAndSlideInfoList) { + monitor.increment(); Data d = DataUtilities.createData(program, addr, mappingInfo.toDataType(), -1, DataUtilities.ClearDataMode.CHECK_FOR_SPACE); addr = addr.add(d.getLength()); - monitor.checkCancelled(); - monitor.incrementProgress(1); } } catch (CodeUnitInsertionException | DuplicateNameException | IOException e) { @@ -1461,12 +1447,11 @@ private void markupImageInfo(Program program, AddressSpace space, TaskMonitor mo Address addr = fileOffsetToAddr(imagesOffset != 0 ? imagesOffset : imagesOffsetOld, program, space); for (DyldCacheImageInfo imageInfo : imageInfoList) { + monitor.increment(); Data d = DataUtilities.createData(program, addr, imageInfo.toDataType(), -1, DataUtilities.ClearDataMode.CHECK_FOR_SPACE); program.getListing().setComment(addr, CommentType.EOL, imageInfo.getPath()); addr = addr.add(d.getLength()); - monitor.checkCancelled(); - monitor.incrementProgress(1); } } catch (CodeUnitInsertionException | DuplicateNameException | IOException e) { @@ -1541,12 +1526,11 @@ private void markupBranchPools(Program program, AddressSpace space, TaskMonitor try { Address addr = fileOffsetToAddr(branchPoolsOffset, program, space); for (int i = 0; i < branchPoolList.size(); i++) { + monitor.increment(); Data d = DataUtilities.createData(program, addr, Pointer64DataType.dataType, Pointer64DataType.dataType.getLength(), DataUtilities.ClearDataMode.CHECK_FOR_SPACE); addr = addr.add(d.getLength()); - monitor.checkCancelled(); - monitor.incrementProgress(1); } } catch (CodeUnitInsertionException e) { @@ -1581,12 +1565,11 @@ private void markupImageTextInfo(Program program, AddressSpace space, TaskMonito try { Address addr = fileOffsetToAddr(imagesTextOffset, program, space); for (DyldCacheImageTextInfo imageTextInfo : imageTextInfoList) { + monitor.increment(); Data d = DataUtilities.createData(program, addr, imageTextInfo.toDataType(), -1, DataUtilities.ClearDataMode.CHECK_FOR_SPACE); program.getListing().setComment(addr, CommentType.EOL, imageTextInfo.getPath()); addr = addr.add(d.getLength()); - monitor.checkCancelled(); - monitor.incrementProgress(1); } } catch (CodeUnitInsertionException | DuplicateNameException | IOException e) { @@ -1602,11 +1585,10 @@ private void markupSubcacheEntries(Program program, AddressSpace space, TaskMoni try { Address addr = fileOffsetToAddr(subCacheArrayOffset, program, space); for (DyldSubcacheEntry subcacheEntry : subcacheEntryList) { + monitor.increment(); Data d = DataUtilities.createData(program, addr, subcacheEntry.toDataType(), -1, DataUtilities.ClearDataMode.CHECK_FOR_SPACE); addr = addr.add(d.getLength()); - monitor.checkCancelled(); - monitor.incrementProgress(1); } } catch (CodeUnitInsertionException | DuplicateNameException | IOException e) { @@ -1625,13 +1607,12 @@ public void setFileBlock(MemoryBlock block) { } /** - * Gets the given file offset's corresponding memory address. + * {@return the given file offset's corresponding memory address, or {@code null} if it doesn't + * have one} * * @param offset The file offset * @param program The {@link Program} * @param space The {@link AddressSpace} - * @return The given file offset's corresponding memory address. Could be null if it doesn't - * have one. */ private Address fileOffsetToAddr(long offset, Program program, AddressSpace space) { @@ -1660,9 +1641,7 @@ private Address fileOffsetToAddr(long offset, Program program, AddressSpace spac } /** - * Checks to see if any slide info exists - * - * @return True if any slide info exists; otherwise, false + * {@return whether or not any slide info exists} */ public boolean hasSlideInfo() { if (slideInfoSize != 0) { @@ -1678,28 +1657,25 @@ public boolean hasSlideInfo() { } /** - * Get the original unslid load address. This is found in the first mapping infos. - * - * @return the original unslid load address + * {@return the original unslid load address} + *

    + * This is found in the first mapping infos. */ public long unslidLoadAddress() { return mappingInfoList.get(0).getAddress(); } /** - * Checks to see whether or not this is a subcache - * - * @return True if this is a subcache; otherwise, false if it's a base cache + * {@return whether or not this is a subcache} */ public boolean isSubcache() { return subCacheArrayCount != null && subCacheArrayCount == 0 && symbolFileUUID == null; } /** - * Checks to see whether or not the old accelerate info fields are being used - * - * @return True if the old accelerate info fields are being used; otherwise, false if the new - * dyldInCache fields are being used + * {@return whether or not the old accelerate info fields are being used} + *

    + * If they aren't being used, then the new {@code dyldInCache} fields are being used. */ public boolean hasAccelerateInfo() { return cacheSubType == null; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldCacheLocalSymbolsInfo.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldCacheLocalSymbolsInfo.java index 8fda44c08db..0732915b092 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldCacheLocalSymbolsInfo.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/dyld/DyldCacheLocalSymbolsInfo.java @@ -79,8 +79,8 @@ public DyldCacheLocalSymbolsInfo(BinaryReader reader, DyldArchitecture architect entriesOffset = reader.readNextInt(); entriesCount = reader.readNextInt(); - nlistList = new ArrayList<>(nlistCount); - localSymbolsEntryList = new ArrayList<>(entriesCount); + nlistList = new ArrayList<>(); + localSymbolsEntryList = new ArrayList<>(); is32bit = !(architecture.getCpuType() == CpuTypes.CPU_TYPE_ARM_64 || architecture.getCpuType() == CpuTypes.CPU_TYPE_X86_64); @@ -116,28 +116,23 @@ public void markup(Program program, Address localSymbolsInfoAddr, TaskMonitor mo } /** - * Gets the {@link List} of {@link DyldCacheLocalSymbolsEntry}s. - * - * @return The {@link List} of {@link DyldCacheLocalSymbolsEntry} + * {@return the {@link List} of {@link DyldCacheLocalSymbolsEntry}s} */ public List getLocalSymbolsEntries() { return localSymbolsEntryList; } /** - * Gets the {@link List} of {@link NList}. - * - * @return The {@link List} of {@link NList} + * {@return the {@link List} of {@link NList}s} */ public List getNList() { return nlistList; } /** - * Gets the {@link List} of {@link NList} for the given dylib offset. + * {@return the {@link List} of {@link NList}s for the given dylib offset} * * @param dylibOffset The offset of dylib in the DYLD Cache - * @return The {@link List} of {@link NList} for the given dylib offset */ public List getNList(long dylibOffset) { for (DyldCacheLocalSymbolsEntry entry : localSymbolsEntryList) { @@ -175,8 +170,7 @@ private void parseNList(MessageLog log, TaskMonitor monitor) throws CancelledExc for (int i = 0; i < nlistCount; ++i) { nlistList.add(new NList(nListReader, is32bit)); - monitor.checkCancelled(); - monitor.incrementProgress(1); + monitor.increment(); } // sort the entries by the index in the string table, so don't jump around reading List sortedList = nlistList.stream() @@ -187,8 +181,7 @@ private void parseNList(MessageLog log, TaskMonitor monitor) throws CancelledExc // initialize the NList strings from string table long stringTableOffset = startIndex + stringsOffset; for (NList nList : sortedList) { - monitor.checkCancelled(); - monitor.incrementProgress(1); + monitor.increment(); nList.initString(nListReader, stringTableOffset); } } @@ -205,8 +198,7 @@ private void parseLocalSymbols(MessageLog log, TaskMonitor monitor) try { for (int i = 0; i < entriesCount; ++i) { localSymbolsEntryList.add(new DyldCacheLocalSymbolsEntry(reader, use64bitOffsets)); - monitor.checkCancelled(); - monitor.incrementProgress(1); + monitor.increment(); } } catch (IOException e) { @@ -224,8 +216,7 @@ private void markupNList(Program program, Address localSymbolsInfoAddr, TaskMoni for (NList nlist : nlistList) { Data d = program.getListing().createData(addr, nlist.toDataType()); addr = addr.add(d.getLength()); - monitor.checkCancelled(); - monitor.incrementProgress(1); + monitor.increment(); } } catch (CodeUnitInsertionException | DuplicateNameException | IOException e) { @@ -242,8 +233,7 @@ private void markupLocalSymbols(Program program, Address localSymbolsInfoAddr, for (DyldCacheLocalSymbolsEntry localSymbolsEntry : localSymbolsEntryList) { Data d = program.getListing().createData(addr, localSymbolsEntry.toDataType()); addr = addr.add(d.getLength()); - monitor.checkCancelled(); - monitor.incrementProgress(1); + monitor.increment(); } } catch (CodeUnitInsertionException | DuplicateNameException | IOException e) { From b855a9164ffa57b8213fa86cf5c2a7c0dde93c36 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Fri, 24 Jul 2026 08:32:00 -0400 Subject: [PATCH 088/111] GP-0: Upping gradle wrapper to 9.6.1 --- .../Common/support/gradle/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ghidra/RuntimeScripts/Common/support/gradle/gradle-wrapper.properties b/Ghidra/RuntimeScripts/Common/support/gradle/gradle-wrapper.properties index 5dd3c0121b3..a351597e62a 100644 --- a/Ghidra/RuntimeScripts/Common/support/gradle/gradle-wrapper.properties +++ b/Ghidra/RuntimeScripts/Common/support/gradle/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From a16770a969bc90bb171ab11e68b7d88f3118418f Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Mon, 27 Jul 2026 14:40:39 -0400 Subject: [PATCH 089/111] GP-7096 - Prevent headless analyzer from updating last opened project --- .../app/util/headless/HeadlessAnalyzer.java | 22 ++++++++++++++++++- .../framework/model/DefaultLaunchMode.java | 14 ++++++------ .../project/DefaultProjectManager.java | 2 +- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/headless/HeadlessAnalyzer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/headless/HeadlessAnalyzer.java index 8048bacdbd6..7c8552d6648 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/headless/HeadlessAnalyzer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/headless/HeadlessAnalyzer.java @@ -1859,7 +1859,27 @@ private static class HeadlessProject extends DefaultProject { } } + /** + * A headless version of the {@link DefaultProjectManager} that does not update the project's + * preferences. This prevents the headless environment from overwriting settings GUI + * installations. + */ private static class HeadlessGhidraProjectManager extends DefaultProjectManager { - // this exists just to allow access to the constructor + + @Override + public void setLastOpenedProject(ProjectLocator projectLocator) { + // No need to save this for headless. We also do not want to affect the GUI by saving + // this value. + } + + @Override + public ProjectLocator getLastOpenedProject() { + return null; + } + + @Override + protected void updatePreferences() { + // nothing to save + } } } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/model/DefaultLaunchMode.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/model/DefaultLaunchMode.java index f8cbbc18840..3a0ced246ca 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/model/DefaultLaunchMode.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/model/DefaultLaunchMode.java @@ -4,9 +4,9 @@ * 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. @@ -23,20 +23,20 @@ */ public enum DefaultLaunchMode { - REUSE_TOOL("Reuse acceptable running tool"), - NEW_TOOL("Launch new default tool"); + REUSE_TOOL("Reuse Tool"), + NEW_TOOL("New Tool"); public static DefaultLaunchMode DEFAULT = NEW_TOOL; - private String str; + private String description; private DefaultLaunchMode(String str) { - this.str = str; + this.description = str; } @Override public String toString() { - return str; + return description; } } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/project/DefaultProjectManager.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/project/DefaultProjectManager.java index 5a8071f01aa..fdee732bb25 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/project/DefaultProjectManager.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/project/DefaultProjectManager.java @@ -568,7 +568,7 @@ private void populateProjectURLList(List list, String propertyName) { /** * Update preferences file with list of known projects. */ - void updatePreferences() { + protected void updatePreferences() { setProjectLocatorProperty(recentlyOpenedProjectsList, RECENT_PROJECTS); setProjectURLProperty(recentlyViewedProjectsList, VIEWED_PROJECTS); From bc253d3ff132fc36fad89e86c0164de127106af2 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Tue, 28 Jul 2026 18:53:29 -0400 Subject: [PATCH 090/111] GP-7094 - Fixed bad tooltips when using fixed cell width; fixed clipping on some LaFs --- .../Docking/data/docking.theme.properties | 6 ++++ .../filechooser/FileListCellRenderer.java | 32 ++++++++++++----- .../widgets/list/GListCellRenderer.java | 35 +++++++++++++++---- 3 files changed, 58 insertions(+), 15 deletions(-) diff --git a/Ghidra/Framework/Docking/data/docking.theme.properties b/Ghidra/Framework/Docking/data/docking.theme.properties index a8837843458..fcda9ff118f 100644 --- a/Ghidra/Framework/Docking/data/docking.theme.properties +++ b/Ghidra/Framework/Docking/data/docking.theme.properties @@ -108,6 +108,7 @@ icon.help.navigation.aid.enabled = software-update-available.png icon.filechooser.default.directory = icon.folder.closed icon.filechooser.default.file = [icon]laf.icon.FileView.fileIcon + icon.filechooser.places.my.computer = computer.png icon.filechooser.places.desktop = desktop.png icon.filechooser.places.home = user-home.png @@ -214,3 +215,8 @@ color.bg.widget.tabs.selected.inactive = #696969 // dimgray color.border.button.focused = [color]laf.color.TabbedPane.focus +[Nimbus] + +// The Nimbus LaF makes a key for laf.icon.FileView.fileIcon, but we are not correctly finding it +icon.filechooser.default.file = [icon]laf.icon.FileChooser.fileIcon + diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/filechooser/FileListCellRenderer.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/filechooser/FileListCellRenderer.java index 0cf7e290fc7..df23d6d4238 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/filechooser/FileListCellRenderer.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/filechooser/FileListCellRenderer.java @@ -21,10 +21,7 @@ import javax.swing.JList; -import org.bouncycastle.crypto.generators.DHBasicKeyPairGenerator; - import docking.widgets.list.GListCellRenderer; -import ghidra.util.Msg; import ghidra.util.filechooser.GhidraFileChooserModel; class FileListCellRenderer extends GListCellRenderer { @@ -43,26 +40,43 @@ protected String getItemText(File file) { return chooser.getDisplayName(file); } + @Override + public Dimension getPreferredSize() { + /* + The preferred size is used by the UI to pre-calculate the list's cell width to use while + rendering. The default preferred size does not account for the border insets. Some LaFs + appreciably change border size when focused. If the size of the cell is pre-calculated + using the smaller border size, then when the cell is focused text may be clipped, as the + cell size does not get updated when the border is changed. Start with the biggest known + border size to prevent clipping. + */ + Dimension d = super.getPreferredSize(); + int borderWidth = getMaxBorderWidth(); + d.width += borderWidth; + return d; + } + @Override public Component getListCellRendererComponent(JList list, File file, int index, boolean isSelected, boolean cellHasFocus) { super.getListCellRendererComponent(list, file, index, isSelected, cellHasFocus); + setIcon(model.getIcon(file)); - // The file chooser's list will sometimes set a fixed width. When that happens, the text - // may get clipped. When we get clipped text, add a tooltip to show the full text. + setToolTipText(null); // clear out previous cell's tool tip + + // As a performance tweak, the file chooser's list will get set to a fixed width when the + // number of directory items is large. (Clients may also choose to set a fixed width value.) + // Setting a fixed width may cause a cell's text to get clipped. When we get clipped text, + // add a tooltip to show the full text. int fixedWidth = list.getFixedCellWidth(); if (fixedWidth > 0) { Dimension d = getPreferredSize(); if (d.getWidth() > fixedWidth) { setToolTipText(getText()); - } - else { - setToolTipText(null); } } - return this; } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/list/GListCellRenderer.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/list/GListCellRenderer.java index 03f5ddddb70..c274b285900 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/list/GListCellRenderer.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/list/GListCellRenderer.java @@ -15,8 +15,7 @@ */ package docking.widgets.list; -import java.awt.Color; -import java.awt.Component; +import java.awt.*; import java.util.function.Function; import javax.swing.*; @@ -38,7 +37,7 @@ public class GListCellRenderer extends AbstractGCellRenderer implements ListC private static final Color LIST_BACKGROUND_COLOR = new GColor("color.bg.list.row"); /** - * Returns a new ListCellRenderer that maps the list's data instance to a string used in the cell. + * Returns a new renderer that maps the list's data instance to a string used in the cell. *

    * Use this if you only need to provide a way to get the string value from the type being shown * in the list. @@ -56,20 +55,25 @@ protected String getItemText(E value) { }; } - /** - * Constructs a new GListCellRenderer. - */ public GListCellRenderer() { // lists don't need alternation for rows, as they don't use long columnar data setShouldAlternateRowBackgroundColors(false); + } + protected void initBorders() { // Base our borders on those used by the list. ComboBoxes do not change the list borders in // the Look and Feel. noFocusBorder = getBorder("List.noFocusBorder"); focusBorder = getBorder("List.focusCellHighlightBorder"); } + @Override + public void updateUI() { + super.updateUI(); + initBorders(); + } + private Border getBorder(String id) { Border border = UIManager.getBorder(id); if (border == null) { @@ -79,6 +83,25 @@ private Border getBorder(String id) { return border; } + /** + * Gets the max border size for the default borders used by this renderer. If any subclass or + * client uses borders other than 'noFocusBorder' or 'focusBorder', then they will need to + * override this method if any of their borders have bigger insets than the default borders of + * this class. + * @return the largest known border width + */ + protected int getMaxBorderWidth() { + Insets insets = noFocusBorder.getBorderInsets(this); + int left = insets.left; + int right = insets.right; + int width = left + right; + + insets = focusBorder.getBorderInsets(this); + left = Math.max(left, insets.left); + right = Math.max(right, insets.right); + return Math.max(width, left + right); + } + // overridden to return the list-specific background color @Override protected Color getDefaultBackgroundColor() { From 237d83af4c45da34d9a40e115d33e38a01483510 Mon Sep 17 00:00:00 2001 From: ghidravision Date: Fri, 31 Jul 2026 11:07:51 +0000 Subject: [PATCH 091/111] Updated handling of unions with bitfields. Cleaned up code. SQUASHED --- .../DecompileDebugDataTypeManager.java | 77 ++++++++++++++++--- .../opinion/DecompileDebugXmlLoaderTest.java | 5 +- .../app/util/opinion/decompile_debug_test.xml | 3 + 3 files changed, 73 insertions(+), 12 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/DecompileDebugDataTypeManager.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/DecompileDebugDataTypeManager.java index e91fdb9ddfd..46c779fc275 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/DecompileDebugDataTypeManager.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/DecompileDebugDataTypeManager.java @@ -226,14 +226,33 @@ private DataType parseUnion(XmlPullParser parser, XmlMessageLog log) { return unionDT; } - while (parser.peek().getName().equals("field")) { - XmlElement fieldElement = parser.start("field"); - DataType fieldDT = parseDataTypeTag(parser, log); - unionDT.add(fieldDT, fieldDT.getLength(), key.name(), ""); - parser.end(fieldElement); + while (parser.peek().getName().contains("field")) { + String fieldType = parser.peek().getName(); + if (fieldType.equals("field")) { + XmlElement fieldElement = parser.start("field"); + DataType fieldDT = parseDataTypeTag(parser, log); + unionDT.add(fieldDT, fieldDT.getLength(), key.name(), ""); + parser.end(fieldElement); + } + else if (fieldType.equals("bitfield")) { + XmlElement bitFieldElement = parser.start("bitfield"); + int bitFieldSize = + SpecXmlUtils.decodeInt(bitFieldElement.getAttribute(ATTRIB_SIZE.name())); + String componentName = bitFieldElement.getAttribute(ATTRIB_NAME.name()); + DataType fieldDT = parseDataTypeTag(parser, log); + + try { + unionDT.addBitField(fieldDT, bitFieldSize, componentName, null); + } + catch (InvalidDataTypeException e) { + log.appendException(e); + } + parser.end(bitFieldElement); + } } parser.end(unionElement); return unionDT; + } /** @@ -295,8 +314,9 @@ private DataType parsePointerRelative(XmlPullParser parser, XmlMessageLog log) { DataType baseType = parseDataTypeTag(parser, log); PointerTypedef relPointerDT = new PointerTypedef(baseType.getName(), baseType, size, programDataManager, offset); - - DataType resolved = resolveAndMapDataType(new DataTypeKey(baseType.getName()+"relptr", idHolder), relPointerDT); + + DataType resolved = resolveAndMapDataType( + new DataTypeKey(baseType.getName() + "relptr", idHolder), relPointerDT); parser.end(pointerRelElement); return resolved; @@ -331,7 +351,25 @@ private DataType parseStruct(XmlPullParser parser, XmlMessageLog log) { return createdStruct; } - while (parser.peek().getName().equals("field")) { + while (parser.peek().getName().contains("field")) { + handleStructFieldType(parser, createdStruct, log); + } + parser.end(structElement); + + return createdStruct; + + } + + /** + * Parse and populate field and bit field types for created structs. + * + * @param parser XmlPullParser + * @param createdStruct Structure + * @param log XmlMessageLog + */ + private void handleStructFieldType(XmlPullParser parser, Structure createdStruct, + XmlMessageLog log) { + if (parser.peek().getName().equals("field")) { XmlElement fieldElement = parser.start("field"); int fieldOffset = SpecXmlUtils.decodeInt(fieldElement.getAttribute(ATTRIB_OFFSET.name())); @@ -341,10 +379,27 @@ private DataType parseStruct(XmlPullParser parser, XmlMessageLog log) { fieldElement.getAttribute(ATTRIB_NAME.name()), ""); parser.end(fieldElement); } - parser.end(structElement); - - return createdStruct; + else if (parser.peek().getName().equals("bitfield")) { + XmlElement bitFieldElement = parser.start("bitfield"); + int bitFieldSize = + SpecXmlUtils.decodeInt(bitFieldElement.getAttribute(ATTRIB_SIZE.name())); + String componentName = bitFieldElement.getAttribute(ATTRIB_NAME.name()); + int byteOffset = + SpecXmlUtils.decodeInt(bitFieldElement.getAttribute(ATTRIB_OFFSET.name())); + int bitOffset = + SpecXmlUtils.decodeInt(bitFieldElement.getAttribute(ATTRIB_FIRST.name())); + int byteWidth = Math.ceilDiv((bitOffset + bitFieldSize), 8); + DataType fieldDT = parseDataTypeTag(parser, log); + try { + createdStruct.insertBitFieldAt(byteOffset, byteWidth, bitOffset, fieldDT, + bitFieldSize, componentName, null); + } + catch (InvalidDataTypeException e) { + log.appendException(e); + } + parser.end(bitFieldElement); + } } /** diff --git a/Ghidra/Features/Base/src/test/java/ghidra/app/util/opinion/DecompileDebugXmlLoaderTest.java b/Ghidra/Features/Base/src/test/java/ghidra/app/util/opinion/DecompileDebugXmlLoaderTest.java index 6a9290b0e7b..8c11d8a3b25 100644 --- a/Ghidra/Features/Base/src/test/java/ghidra/app/util/opinion/DecompileDebugXmlLoaderTest.java +++ b/Ghidra/Features/Base/src/test/java/ghidra/app/util/opinion/DecompileDebugXmlLoaderTest.java @@ -123,11 +123,14 @@ public void testVerifyLoadedProgramDataTypes() throws Exception { Iterator structures = dtm.getAllStructures(); Structure struct = structures.next(); // there is only 1 struct in the example XML dump - assertEquals("Component count didn't match.", 20, struct.getNumComponents()); + assertEquals("Component count didn't match.", 22, struct.getNumComponents()); assertEquals("Struct name is incorrect", "IMAGE_DOS_HEADER", struct.getName()); DataTypeComponent array = struct.getComponentAt(0); // the first component is an array assertEquals("Array component name doesn't match", "e_magic", array.getFieldName()); assertEquals("Array wasn't sized right", 2, array.getLength()); + DataTypeComponent bitField = struct.getComponentAt(65); // last component is a bitfield + assertEquals("Bitfield name doesn't match", "low_nibble", bitField.getFieldName()); + assertEquals("Bitfield length doesn't match", "1", bitField.getLength() + ""); } finally { program.release(this); diff --git a/Ghidra/Features/Base/src/test/resources/ghidra/app/util/opinion/decompile_debug_test.xml b/Ghidra/Features/Base/src/test/resources/ghidra/app/util/opinion/decompile_debug_test.xml index ac6ce650362..61b0f0f8929 100644 --- a/Ghidra/Features/Base/src/test/resources/ghidra/app/util/opinion/decompile_debug_test.xml +++ b/Ghidra/Features/Base/src/test/resources/ghidra/app/util/opinion/decompile_debug_test.xml @@ -167,6 +167,9 @@ c4305fc3b907000000e8be03000090b9 + + + From ece613805df56dbb1f6d8410fbf53d7d38cf53f5 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Fri, 31 Jul 2026 13:33:04 -0400 Subject: [PATCH 092/111] GP-7105: Upgraded the PostgreSQL JDBC Driver from 42.7.11 to 42.7.13 --- Ghidra/Features/BSim/Module.manifest | 2 +- Ghidra/Features/BSim/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Ghidra/Features/BSim/Module.manifest b/Ghidra/Features/BSim/Module.manifest index 9e49351711f..f61ef6b59eb 100755 --- a/Ghidra/Features/BSim/Module.manifest +++ b/Ghidra/Features/BSim/Module.manifest @@ -1,6 +1,6 @@ ##MODULE IP: Oxygen Icons - LGPL 3.0 MODULE FILE LICENSE: postgresql-15.13.tar.gz Postgresql License -MODULE FILE LICENSE: lib/postgresql-42.7.11.jar PostgresqlJDBC License +MODULE FILE LICENSE: lib/postgresql-42.7.13.jar PostgresqlJDBC License MODULE FILE LICENSE: lib/commons-dbcp2-2.9.0.jar Apache License 2.0 MODULE FILE LICENSE: lib/commons-pool2-2.11.1.jar Apache License 2.0 MODULE FILE LICENSE: lib/commons-logging-1.2.jar Apache License 2.0 diff --git a/Ghidra/Features/BSim/build.gradle b/Ghidra/Features/BSim/build.gradle index 35a1edd6d69..660f26cb0e5 100755 --- a/Ghidra/Features/BSim/build.gradle +++ b/Ghidra/Features/BSim/build.gradle @@ -32,7 +32,7 @@ dependencies { api project(":Decompiler") api project(":CodeCompare") - api "org.postgresql:postgresql:42.7.11" + api "org.postgresql:postgresql:42.7.13" api "org.apache.commons:commons-dbcp2:2.9.0" api "org.apache.commons:commons-pool2:2.11.1" api "commons-logging:commons-logging:1.2" From 1b1c821076315e3577d9a00fd27b58ba574c21d2 Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Tue, 4 Aug 2026 18:47:45 -0400 Subject: [PATCH 093/111] GP-7113 Corrected ContentHandle.getChangeSet version handling --- .../db/buffers/LocalManagedBufferFile.java | 72 +++++++++++-------- 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/Ghidra/Framework/DB/src/main/java/db/buffers/LocalManagedBufferFile.java b/Ghidra/Framework/DB/src/main/java/db/buffers/LocalManagedBufferFile.java index 1d1251e2a01..682e0f92e67 100644 --- a/Ghidra/Framework/DB/src/main/java/db/buffers/LocalManagedBufferFile.java +++ b/Ghidra/Framework/DB/src/main/java/db/buffers/LocalManagedBufferFile.java @@ -93,10 +93,11 @@ public class LocalManagedBufferFile extends LocalBufferFile implements ManagedBu /** * bfMgr manages the various files associated with this buffer * file. When working with versioned files or when Save support is - * required bfMgr must be set. The bufMgr will be null for - * a read-only non-updateable file. + * required bfMgr must be set. The openForUpdate will be false + * for a read-only non-updateable file. */ private BufferFileManager bfMgr; + private boolean openForUpdate = false; /** * checkinId is the checkin ID needed by bfMgr when a new @@ -174,6 +175,7 @@ public LocalManagedBufferFile(int bufferSize, BufferFileManager bfManager, long } this.version = 1; this.bfMgr = bfManager; + this.openForUpdate = true; this.checkinId = checkinId; } @@ -191,6 +193,7 @@ public LocalManagedBufferFile(BufferFileManager bfManager, boolean versionUpdate int minChangeDataVer, long checkinId) throws IOException { super(bfManager.getBufferFile(bfManager.getCurrentVersion()), true); this.bfMgr = bfManager; + this.openForUpdate = true; this.version = bfManager.getCurrentVersion(); this.minChangeDataVer = minChangeDataVer; this.checkinId = checkinId; @@ -200,7 +203,7 @@ public LocalManagedBufferFile(BufferFileManager bfManager, boolean versionUpdate } /** - * Open an older version of an existing buffer file as read-only and NOT UPDATEABLE (bfMgr remains null). + * Open an older version of an existing buffer file as read-only and NOT UPDATEABLE (openForUpdate remains false). * Version files must exist for all versions starting with the requested version. * These version files will be used in conjunction with the current buffer file * to emulate an older version buffer file. @@ -214,6 +217,7 @@ public LocalManagedBufferFile(BufferFileManager bfManager, boolean versionUpdate public LocalManagedBufferFile(BufferFileManager bfManager, int version, int minChangeDataVer) throws IOException { super(bfManager.getBufferFile(bfManager.getCurrentVersion()), true); + this.bfMgr = bfManager; this.version = version; this.minChangeDataVer = minChangeDataVer; int curVer = bfManager.getCurrentVersion(); @@ -243,9 +247,6 @@ private LocalManagedBufferFile(File presaveFile, int bufferSize) throws IOExcept @Override public BufferFile getNextChangeDataFile(boolean getFirst) throws IOException { - if (bfMgr == null) { - return null; - } if (getFirst || nextChangeDataVer == -1) { nextChangeDataVer = minChangeDataVer != -1 ? minChangeDataVer : (version - 1); } @@ -291,9 +292,10 @@ public void setVersionComment(String comment) { @Override public synchronized DataBuffer get(DataBuffer buf, int index) throws IOException { - if (index > getBufferCount()) + if (index > getBufferCount()) { throw new EOFException( "Buffer index too large (" + index + " > " + getBufferCount() + ")"); + } if (versionFileHandler != null) { DataBuffer vbuf = versionFileHandler.getOldBuffer(buf, index); @@ -312,10 +314,12 @@ public synchronized DataBuffer get(DataBuffer buf, int index) throws IOException @Override public synchronized void put(DataBuffer buf, int index) throws IOException { - if (isReadOnly()) + if (isReadOnly()) { throw new IOException("File is read-only"); - if (index > MAX_BUFFER_INDEX) + } + if (index > MAX_BUFFER_INDEX) { throw new EOFException("Buffer index too large, exceeds max-int"); + } versionBufferIfNeeded(index); @@ -355,8 +359,9 @@ private void versionBufferIfNeeded(int index) throws IOException { @Override public synchronized boolean setReadOnly() throws IOException { - if (!flush()) + if (!flush()) { return false; + } if (versionOutFile != null) { versionOutFile.close(); @@ -369,8 +374,8 @@ public synchronized boolean setReadOnly() throws IOException { super.setReadOnly(); - if (bfMgr != null) { -// TODO: This seems very hidden! + if (openForUpdate) { + openForUpdate = false; bfMgr.versionCreated(version, comment, checkinId); startPreSave(); } @@ -380,8 +385,9 @@ public synchronized boolean setReadOnly() throws IOException { @Override public synchronized void close() throws IOException { - if (isClosed()) + if (isClosed()) { return; + } stopPreSave(true); @@ -406,7 +412,8 @@ public synchronized void close() throws IOException { // NOTE: the above close will delete non-read-only files which were not committed } finally { - if (bfMgr != null) { + if (openForUpdate) { + openForUpdate = false; if (comit) { bfMgr.versionCreated(version, comment, checkinId); } @@ -427,8 +434,9 @@ public synchronized void close() throws IOException { @Override public synchronized boolean delete() { - if (isClosed() || isReadOnly()) + if (isClosed() || isReadOnly()) { return false; + } boolean success = false; try { @@ -448,7 +456,8 @@ public synchronized boolean delete() { } } finally { - if (bfMgr != null) { + if (openForUpdate) { + openForUpdate = false; bfMgr.updateEnded(checkinId); } } @@ -456,9 +465,6 @@ public synchronized boolean delete() { } private byte[] getForwardModMapData() throws IOException { - if (bfMgr == null) { - return null; - } File mf = bfMgr.getChangeMapFile(); if (mf == null || !mf.exists()) { return null; @@ -474,9 +480,6 @@ private byte[] getForwardModMapData() throws IOException { @Override public byte[] getForwardModMapData(int oldVersion) throws IOException { - if (bfMgr == null) { - return null; - } if (oldVersion < 1 || oldVersion >= version) { throw new IOException("Invalid mod-map version requested: " + oldVersion); } @@ -694,6 +697,7 @@ public synchronized void saveCompleted(boolean commit) throws IOException { if (saveFile.renameFile(newFile)) { saveFile.version = newVersion; saveFile.bfMgr = bfMgr; + saveFile.openForUpdate = true; saveFile.checkinId = checkinId; if (saveChangeFile != null) { @@ -712,6 +716,7 @@ public synchronized void saveCompleted(boolean commit) throws IOException { if (!success) { saveFile.delete(); } + saveFile = null; saveChangeFile = null; } @@ -771,7 +776,7 @@ private void stopPreSave(boolean endUpdate) { synchronized (this) { // If preSaveFile is null and !preSaveFailed - we were unsuccessful at terminating the pre-save - if (endUpdate && bfMgr != null && (preSaveFailed || preSaveFile != null)) { + if (endUpdate && openForUpdate && (preSaveFailed || preSaveFile != null)) { // Update is ended when we can no longer perform a save bfMgr.updateEnded(checkinId); @@ -1066,15 +1071,20 @@ public synchronized void updateFrom(ManagedBufferFile versionedBufferFile, int o success = true; } finally { - saveCompleted(success); - if (!success) { - bfMgr.updateEnded(checkinId); + try { + saveCompleted(success); + } + finally { + bf.dispose(); + if (!success) { + bfMgr.updateEnded(checkinId); + } +// else { +// // VERIFY RESULT FILE +// System.err.println("Update check: " + file); +// checkSameContent(versionedBufferFile, bf); +// } } -// else { -// // VERIFY RESULT FILE -// System.err.println("Update check: " + file); -// checkSameContent(versionedBufferFile, bf); -// } } } From 9734de71f94e01dd04646b129f151e07121cd530 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Wed, 5 Aug 2026 14:23:57 -0400 Subject: [PATCH 094/111] GP-7118 - Updated Structure Editor to reloaded when the description is changed outside of the editor --- .../app/plugin/core/compositeeditor/CompEditorModel.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompEditorModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompEditorModel.java index aafe6c4d5c2..0f5dc935aca 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompEditorModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompEditorModel.java @@ -57,7 +57,7 @@ public boolean hasChanges() { public void load(T dataType) { if (dataType.isDeleted()) { - // This can occur when mayny events get lumped together and a change event triggers + // This can occur when many events get lumped together and a change event triggers // a delayed reload prior to datatype removal and its event if (dataType == originalComposite) { // Re-route to dataTypeRemoved callback after restoring listener. @@ -884,7 +884,7 @@ protected final int getNumUndefinedBytesAfter(DataTypeComponent dtc) { throw new UnsupportedOperationException(); } - // TODO: May need special logic if dtc is zero-length component + // Note: May need special logic if dtc is zero-length component int length = getLength(); int nextCompOffset = dtc.getEndOffset() + 1; if (nextCompOffset >= length) { @@ -1513,8 +1513,7 @@ public void dataTypeChanged(DataTypeManager dtm, DataTypePath path) { } else { Composite changedComposite = getOriginalComposite(); - if ((changedComposite != null) && - !viewComposite.isEquivalent(changedComposite)) { + if (changedComposite != null) { originalDTM.removeDataTypeManagerListener(this); originalDTM.flushEvents(); Swing.runLater(() -> load(getOriginalComposite())); From 6d7ace559f2206ef3f72446a5e45734194ba0483 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Thu, 6 Aug 2026 11:18:42 -0400 Subject: [PATCH 095/111] GP-7124: MotorolaHexLoader parsing improvement --- .../main/java/ghidra/app/util/opinion/MotorolaHexLoader.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MotorolaHexLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MotorolaHexLoader.java index 3a8bb35ee5c..c5073500331 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MotorolaHexLoader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MotorolaHexLoader.java @@ -77,10 +77,12 @@ public Collection findSupportedLoadSpecs(ByteProvider provider) throws } static boolean isPossibleHexFile(ByteProvider provider) { + final int MAX_BLANK_LINES = 100; try (BoundedBufferedReader reader = new BoundedBufferedReader(new InputStreamReader(provider.getInputStream(0)))) { + int i = 0; String line = reader.readLine(); - while (line.matches("^\\s*$")) { + while (i++ < MAX_BLANK_LINES && line.isBlank()) { line = reader.readLine(); } return line.matches("^[S:][0-9a-fA-F]+$"); From 36cf4956db662afbe060044031731398d75849ed Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Thu, 6 Aug 2026 11:29:21 -0400 Subject: [PATCH 096/111] GP-7123: SomLoader parsing improvement --- .../app/util/bin/format/som/SomException.java | 42 +++++++++++++ .../app/util/bin/format/som/SomHeader.java | 60 ++++++++++--------- .../ghidra/app/util/opinion/SomLoader.java | 18 +++--- 3 files changed, 83 insertions(+), 37 deletions(-) create mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/som/SomException.java diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/som/SomException.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/som/SomException.java new file mode 100644 index 00000000000..97b4eb19eac --- /dev/null +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/som/SomException.java @@ -0,0 +1,42 @@ +/* ### + * 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.util.bin.format.som; + +/** + * An exception class to handle encountering invalid SOM headers + */ +public class SomException extends Exception { + + /** + * Constructs a new exception with the specified detail message + * + * @param message the detail message + */ + public SomException(String message) { + super(message); + } + + /** + * Constructs a new exception with the specified cause and a detail message + * + * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} + * method (a {@code null} value is permitted, and indicates that the cause is nonexistent + * or unknown). + */ + public SomException(Exception cause) { + super(cause); + } +} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/som/SomHeader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/som/SomHeader.java index 8eab52fc09b..5b2a08be4fa 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/som/SomHeader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/som/SomHeader.java @@ -84,12 +84,18 @@ public class SomHeader implements StructConverter { * Creates a new {@link SomHeader} * * @param reader A {@link BinaryReader} positioned at the start of the header + * @throws SomException if the header is invalid * @throws IOException if there was an IO-related error */ - public SomHeader(BinaryReader reader) throws IOException { + public SomHeader(BinaryReader reader) throws SomException, IOException { systemId = reader.readNextUnsignedShort(); magic = reader.readNextUnsignedShort(); versionId = reader.readNextUnsignedInt(); + + if (!hasValidMagic() || !hasValidVersionId()) { + throw new SomException("Invalid SOM header"); + } + fileTime = new SomSysClock(reader); entrySpace = reader.readNextUnsignedInt(); entrySubspace = reader.readNextUnsignedInt(); @@ -173,25 +179,6 @@ public int getMagic() { return magic; } - /** - * {@return true if this {@link SomHeader} has a valid magic number; otherwise false} - */ - public boolean hasValidMagic() { - return switch (magic) { - case MAGIC_LIBRARY: - case MAGIC_RELOCATABLE: - case MAGIC_NON_SHAREABLE_EXE: - case MAGIC_SHAREABLE_EXE: - case MAGIC_SHARABLE_DEMAND_LOADABLE_EXE: - case MAGIC_DYNAMIC_LOAD_LIBRARY: - case MAGIC_SHARED_LIBRARY: - case MAGIC_RELOCATABLE_LIBRARY: - yield true; - default: - yield false; - }; - } - /** * {@return the version ID} */ @@ -199,13 +186,6 @@ public long getVersionId() { return versionId; } - /** - * {@return true if this {@link SomHeader} has a valid version ID; otherwise false} - */ - public boolean hasValidVersionId() { - return versionId == 85082112 || versionId == 87102412; - } - /** * {@return the file time} */ @@ -558,6 +538,32 @@ public void markup(Program program, Address headerAddr, TaskMonitor monitor) thr } } + /** + * {@return true if this {@link SomHeader} has a valid magic number; otherwise false} + */ + private boolean hasValidMagic() { + return switch (magic) { + case MAGIC_LIBRARY: + case MAGIC_RELOCATABLE: + case MAGIC_NON_SHAREABLE_EXE: + case MAGIC_SHAREABLE_EXE: + case MAGIC_SHARABLE_DEMAND_LOADABLE_EXE: + case MAGIC_DYNAMIC_LOAD_LIBRARY: + case MAGIC_SHARED_LIBRARY: + case MAGIC_RELOCATABLE_LIBRARY: + yield true; + default: + yield false; + }; + } + + /** + * {@return true if this {@link SomHeader} has a valid version ID; otherwise false} + */ + private boolean hasValidVersionId() { + return versionId == 85082112 || versionId == 87102412; + } + @Override public DataType toDataType() throws DuplicateNameException, IOException { StructureDataType struct = new StructureDataType("header", SIZE); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/SomLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/SomLoader.java index 362d73c2eb2..93514833518 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/SomLoader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/SomLoader.java @@ -50,18 +50,16 @@ public Collection findSupportedLoadSpecs(ByteProvider provider) throws try { SomHeader header = new SomHeader(new BinaryReader(provider, false)); - if (header.hasValidMagic() && header.hasValidVersionId()) { - List results = QueryOpinionService.query(getName(), - Integer.toString(header.getSystemId()), null); - for (QueryResult result : results) { - loadSpecs.add(new LoadSpec(this, 0, result)); - } - if (loadSpecs.isEmpty()) { - loadSpecs.add(new LoadSpec(this, 0, true)); - } + List results = QueryOpinionService.query(getName(), + Integer.toString(header.getSystemId()), null); + for (QueryResult result : results) { + loadSpecs.add(new LoadSpec(this, 0, result)); + } + if (loadSpecs.isEmpty()) { + loadSpecs.add(new LoadSpec(this, 0, true)); } } - catch (IOException e) { + catch (SomException | IOException e) { // that's ok, not a System Object Model } return loadSpecs; From c09c05643814099b8f28048157f1cc2bb6ebf5e1 Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Tue, 4 Aug 2026 18:47:45 -0400 Subject: [PATCH 097/111] GP-7113 Corrected missing bug fix --- .../DB/src/main/java/db/buffers/LocalManagedBufferFile.java | 1 - .../java/ghidra/framework/store/local/LocalFolderItem.java | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Ghidra/Framework/DB/src/main/java/db/buffers/LocalManagedBufferFile.java b/Ghidra/Framework/DB/src/main/java/db/buffers/LocalManagedBufferFile.java index 682e0f92e67..c22add90bf7 100644 --- a/Ghidra/Framework/DB/src/main/java/db/buffers/LocalManagedBufferFile.java +++ b/Ghidra/Framework/DB/src/main/java/db/buffers/LocalManagedBufferFile.java @@ -375,7 +375,6 @@ public synchronized boolean setReadOnly() throws IOException { super.setReadOnly(); if (openForUpdate) { - openForUpdate = false; bfMgr.versionCreated(version, comment, checkinId); startPreSave(); } diff --git a/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/store/local/LocalFolderItem.java b/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/store/local/LocalFolderItem.java index 2a3f4195e2c..42d398519b9 100644 --- a/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/store/local/LocalFolderItem.java +++ b/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/store/local/LocalFolderItem.java @@ -250,7 +250,7 @@ void beginCheckin(long checkoutId) throws FileInUseException { throw new FileInUseException("Another checkin is in progress" + byMsg); } checkinId = checkoutId; -//Log.put("Check-in started: " + checkinId); + //log.info("Check-in started: " + checkinId); } } @@ -262,7 +262,7 @@ void endCheckin(long itemCheckinId) { synchronized (fileSystem) { if (this.checkinId == itemCheckinId) { this.checkinId = DEFAULT_CHECKOUT_ID; -//Log.put("Check-in ended: " + checkinId); + //log.info("Check-in ended: " + itemCheckinId); } } } From 1f7a1b350b6c6883f90306d71de811c91ba4d079 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Mon, 10 Aug 2026 04:57:38 -0400 Subject: [PATCH 098/111] GP-0: Fixing NullPointerException importing an x64 PE with a zeroed UnwindInfoAddress in .pdata (Closing #9491) --- .../app/util/bin/format/pe/ImageRuntimeFunctionEntries_X86.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/ImageRuntimeFunctionEntries_X86.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/ImageRuntimeFunctionEntries_X86.java index 7c9f13d0133..b6d12f98b39 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/ImageRuntimeFunctionEntries_X86.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/ImageRuntimeFunctionEntries_X86.java @@ -139,7 +139,7 @@ record ImageRuntimeFunctionEntry_X86(long beginAddress, long endAddress, public void markup(Program program, MessageLog log) throws DuplicateNameException, IOException { - if (beginAddress != 0 && !unwindInfo.hasChainedUnwindInfo()) { + if (beginAddress != 0 && (unwindInfo == null || !unwindInfo.hasChainedUnwindInfo())) { AbstractProgramLoader.markAsFunction(program, null, program.getImageBase().add(beginAddress)); } From d08e8acff10747511c4132c87ab80ef437f20d64 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Mon, 10 Aug 2026 05:33:15 -0400 Subject: [PATCH 099/111] GP-0: Fixing a potential NullPointerException when parsing PE DebugMisc structures (Closes #9486) --- .../util/bin/format/pe/debug/DebugMisc.java | 40 ++++++++----------- .../util/opinion/AbstractPeDebugLoader.java | 4 ++ 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/debug/DebugMisc.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/debug/DebugMisc.java index ddaad89ca02..03a7e5ce8ce 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/debug/DebugMisc.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/debug/DebugMisc.java @@ -16,6 +16,7 @@ package ghidra.app.util.bin.format.pe.debug; import java.io.IOException; +import java.util.Objects; import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.StructConverter; @@ -56,10 +57,12 @@ public class DebugMisc implements StructConverter { private String actualData; /** - * Constructor + * Creates a new {@link DebugMisc} + * * @param reader the binary reader * @param debugDir the debug directory associated to this MISC debug - * @param ntHeader + * @param validator the {@link OffsetValidator} + * @throws IOException if an IO-related exception occurred */ DebugMisc(BinaryReader reader, DebugDirectory debugDir, OffsetValidator validator) throws IOException { @@ -69,7 +72,7 @@ public class DebugMisc implements StructConverter { long index = Integer.toUnsignedLong(debugDir.getPointerToRawData()); if (!validator.checkPointer(index)) { - Msg.error(this, "Invalid file index " + Long.toHexString(index)); + Msg.error(this, "Invalid file index 0x%x".formatted(index)); return; } reader.setPointerIndex(index); @@ -86,81 +89,70 @@ else if (length == 0 && !unicode) { actualData = reader.readNextAsciiString(); // NB: should be a multiple of 4 per winnt.h // 13 = len(start of struct) + null - length = (int) Math.ceil((actualData.length() + 13)/4.0)*4; + length = (int) Math.ceil((actualData.length() + 13) / 4.0) * 4; if (length > DebugDirectory.IMAGE_SIZEOF_DEBUG_DIRECTORY) { length = DebugDirectory.IMAGE_SIZEOF_DEBUG_DIRECTORY; } Msg.warn(this, "Zero length structure - defaulting to " + Integer.toHexString(length)); } else { - Msg.error(this, "Bad structure length " + Integer.toHexString(length)); + Msg.error(this, "Bad structure length: 0x%x".formatted(length)); } reader.setPointerIndex(oldIndex); } /** - * Returns the data type of this misc debug. - * @return the data type of this misc debug + *{@return the data type of this misc debug} */ public int getDataType() { return dataType; } /** - * Returns the length of this misc debug. - * @return the length of this misc debug + * {@return the length of this misc debug} */ public int getLength() { return length; } /** - * Returns true if this misc debug is unicode. - * @return true if this misc debug is unicode + * {@return true if this misc debug is unicode} */ public boolean isUnicode() { return unicode; } /** - * Returns the array of reserved bytes. - * @return the array of reserved bytes + * {@return the array of reserved bytes} */ public byte[] getReserved() { return reserved; } /** - * Returns a string equivalent of the actual misc debug data. - * @return a string equivalent of the actual misc debug data + * {@return a string equivalent of the actual misc debug data, or {@code null} if this structure + * is invalid} */ public String getActualData() { return actualData; } - /** - * @see java.lang.Object#toString() - */ @Override public String toString() { if (getDataType() == DebugMisc.IMAGE_DEBUG_MISC_EXENAME) { - return "Misc Debug Information: " + getActualData(); + return "Misc Debug Information: " + Objects.toString(actualData, ""); } return "Unknown Misc Debug Information Type: " + getDataType(); } /** - * Returns the debug directory associated with this misc debug. - * @return the debug directory associated with this misc debug + * {@return the debug directory associated with this misc debug} */ public DebugDirectory getDebugDirectory() { return debugDir; } - /** - * @see ghidra.app.util.bin.StructConverter#toDataType() - */ @Override public DataType toDataType() throws DuplicateNameException { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/AbstractPeDebugLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/AbstractPeDebugLoader.java index 62a218195f2..e0e84bf6bb2 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/AbstractPeDebugLoader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/AbstractPeDebugLoader.java @@ -474,6 +474,10 @@ private void processDebugMisc(Program program, DebugMisc dm) { } String actualData = dm.getActualData(); + if (actualData == null) { + return; + } + int datatype = dm.getDataType(); DebugDirectory dd = dm.getDebugDirectory(); From 19afcc1c499d8aa0998632f23591e78cf5561b2d Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Mon, 10 Aug 2026 06:43:01 -0400 Subject: [PATCH 100/111] GP-7071: Another OMF fix --- .../ghidra/app/util/bin/format/omf/omf/OmfIteratedData.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/omf/omf/OmfIteratedData.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/omf/omf/OmfIteratedData.java index faf9f03c492..9d079a1a4e4 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/omf/omf/OmfIteratedData.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/omf/omf/OmfIteratedData.java @@ -148,7 +148,11 @@ else if (nestedBlock != null) { length += block.getLength(); } } - return length * repeatCount; + long total = (long) length * (long) repeatCount; + if (total < 0 || total > OmfIteratedData.MAX_ITERATED_FILL) { + throw new IllegalArgumentException("Iterated block length out of range: " + total); + } + return (int) total; } /** From fe7e95f3ebfdd3f9f1b488f67531bd54b493a62a Mon Sep 17 00:00:00 2001 From: James <49045138+ghidracadabra@users.noreply.github.com> Date: Mon, 10 Aug 2026 06:57:10 -0400 Subject: [PATCH 101/111] GP-7107 update postgres version --- Ghidra/Features/BSim/Module.manifest | 4 ++-- Ghidra/Features/BSim/build.gradle | 2 +- Ghidra/Features/BSim/support/make-postgres.sh | 6 +++--- gradle/support/fetchDependencies.gradle | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Ghidra/Features/BSim/Module.manifest b/Ghidra/Features/BSim/Module.manifest index f61ef6b59eb..a98c965931b 100755 --- a/Ghidra/Features/BSim/Module.manifest +++ b/Ghidra/Features/BSim/Module.manifest @@ -1,7 +1,7 @@ ##MODULE IP: Oxygen Icons - LGPL 3.0 -MODULE FILE LICENSE: postgresql-15.13.tar.gz Postgresql License +MODULE FILE LICENSE: postgresql-15.18.tar.gz Postgresql License MODULE FILE LICENSE: lib/postgresql-42.7.13.jar PostgresqlJDBC License MODULE FILE LICENSE: lib/commons-dbcp2-2.9.0.jar Apache License 2.0 MODULE FILE LICENSE: lib/commons-pool2-2.11.1.jar Apache License 2.0 MODULE FILE LICENSE: lib/commons-logging-1.2.jar Apache License 2.0 -MODULE FILE LICENSE: lib/h2-2.2.220.jar H2 Mozilla License 2.0 \ No newline at end of file +MODULE FILE LICENSE: lib/h2-2.2.220.jar H2 Mozilla License 2.0 diff --git a/Ghidra/Features/BSim/build.gradle b/Ghidra/Features/BSim/build.gradle index 660f26cb0e5..15bd8ff8110 100755 --- a/Ghidra/Features/BSim/build.gradle +++ b/Ghidra/Features/BSim/build.gradle @@ -26,7 +26,7 @@ eclipse.project.name = 'Features BSim' import java.nio.file.Files // NOTE: fetchDependencies.gradle must be updated if postgresql version changes -def postgresql_distro = "postgresql-15.13.tar.gz" +def postgresql_distro = "postgresql-15.18.tar.gz" dependencies { api project(":Decompiler") diff --git a/Ghidra/Features/BSim/support/make-postgres.sh b/Ghidra/Features/BSim/support/make-postgres.sh index 5ab6cec265c..d20c35dd6de 100755 --- a/Ghidra/Features/BSim/support/make-postgres.sh +++ b/Ghidra/Features/BSim/support/make-postgres.sh @@ -18,11 +18,11 @@ # This script builds the postgresql server and BSim extension within a # GHIDRA installation. # -# The PostgreSQL source distribution file postgresql-15.13.tar.gz must +# The PostgreSQL source distribution file postgresql-15.18.tar.gz must # be placed in the BSim module directory prior to running this script. # This file can be downloaded directly from the PostgreSQL website at: # -# https://www.postgresql.org/ftp/source/v15.13 +# https://www.postgresql.org/ftp/source/v15.18 # # Within development environments, this script will first check the # ghidra.bin repo for this source file. @@ -46,7 +46,7 @@ # # -POSTGRES=postgresql-15.13 +POSTGRES=postgresql-15.18 POSTGRES_GZ=${POSTGRES}.tar.gz POSTGRES_CONFIG_OPTIONS="--disable-rpath --with-openssl" diff --git a/gradle/support/fetchDependencies.gradle b/gradle/support/fetchDependencies.gradle index 322b2c9b152..54d4560a6ca 100644 --- a/gradle/support/fetchDependencies.gradle +++ b/gradle/support/fetchDependencies.gradle @@ -96,9 +96,9 @@ ext.deps = [ destination: file("${DEPS_DIR}/GhidraServer") ], [ - name: "postgresql-15.13.tar.gz", - url: "https://ftp.postgresql.org/pub/source/v15.13/postgresql-15.13.tar.gz", - sha256: "afdc22b0a6e5bec7b65723756b90d44ea911e61b2f7b01c4dc5524ab813b4d89", + name: "postgresql-15.18.tar.gz", + url: "https://ftp.postgresql.org/pub/source/v15.18/postgresql-15.18.tar.gz", + sha256: "d32a533516edc688ebbb96ae221b605be2712edd94d7428b42a4af5644250943", destination: file("${DEPS_DIR}/BSim") ], [ From da55ff5bc21f15b47d3251574b18bbd1ad2b1295 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20V=C3=A1zquez=20Blanco?= Date: Mon, 20 Jul 2026 10:48:26 +0200 Subject: [PATCH 102/111] Fix radix mismatch in GenericAddress sub-word offset display --- .../java/ghidra/program/model/address/GenericAddress.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/GenericAddress.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/GenericAddress.java index c5fe598eade..441bb768260 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/GenericAddress.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/GenericAddress.java @@ -274,7 +274,7 @@ else if (showAddressSpace) { } long mod = 0; if (unitSize > 1) { - mod = displayOffset % unitSize; + mod = Long.remainderUnsigned(displayOffset, unitSize); displayOffset = addrSpace.getAddressableWordOffset(displayOffset); } @@ -287,7 +287,7 @@ else if (showAddressSpace) { buf.append(addressString); if (mod != 0) { buf.append('.'); - buf.append(mod); + buf.append(Long.toHexString(mod)); } if (stackFormat) { buf.append(STACK_ADDRESS_SUFFIX); From d0650fa0ef4a1a3fd5a02385f06be2b385c1e4de Mon Sep 17 00:00:00 2001 From: Sleigh-InSPECtor Date: Tue, 30 Apr 2024 15:05:50 +0930 Subject: [PATCH 103/111] AA64: fix stlrb and stlrh store sizes --- Ghidra/Processors/AARCH64/data/languages/AARCH64base.sinc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Ghidra/Processors/AARCH64/data/languages/AARCH64base.sinc b/Ghidra/Processors/AARCH64/data/languages/AARCH64base.sinc index 2811de5d481..a3d57128eda 100644 --- a/Ghidra/Processors/AARCH64/data/languages/AARCH64base.sinc +++ b/Ghidra/Processors/AARCH64/data/languages/AARCH64base.sinc @@ -5659,7 +5659,7 @@ is size.ldstr=2 & b_2429=0x8 & b_23=1 & L=0 & b_21=0 & b_15=1 & addrReg & Rt_GPR :stlrb Rt_GPR32, addrReg is size.ldstr=0 & b_2429=0x8 & b_23=1 & L=0 & b_21=0 & b_15=1 & addrReg & Rt_GPR32 { - *addrReg = Rt_GPR32; + *:1 addrReg = Rt_GPR32:1; } # C6.2.312 STLRH page C6-1849 line 108967 MATCH x48808000/mask=xffe08000 @@ -5670,7 +5670,7 @@ is size.ldstr=0 & b_2429=0x8 & b_23=1 & L=0 & b_21=0 & b_15=1 & addrReg & Rt_GPR :stlrh Rt_GPR32, addrReg is size.ldstr=1 & b_2429=0x8 & b_23=1 & L=0 & b_21=0 & b_15=1 & addrReg & Rt_GPR32 { - *addrReg = Rt_GPR32; + *:2 addrReg = Rt_GPR32:2; } # C6.2.313 STLUR page C6-1850 line 109030 MATCH x99000000/mask=xbfe00c00 From acf4fc7c781f144704f89ed849199b35badde89a Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Mon, 10 Aug 2026 14:59:01 -0400 Subject: [PATCH 104/111] GP-7133: Fixed MIPS 16e variant ldef entries --- Ghidra/Processors/MIPS/data/languages/mips.ldefs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Ghidra/Processors/MIPS/data/languages/mips.ldefs b/Ghidra/Processors/MIPS/data/languages/mips.ldefs index cc6190b54eb..59dc5bba942 100644 --- a/Ghidra/Processors/MIPS/data/languages/mips.ldefs +++ b/Ghidra/Processors/MIPS/data/languages/mips.ldefs @@ -132,7 +132,7 @@ Date: Mon, 10 Aug 2026 16:56:11 -0400 Subject: [PATCH 105/111] GP_6767: Corrected OF flag for x86 shift/rotate instructions --- Ghidra/Processors/x86/data/languages/ia.sinc | 256 +++++++++---------- 1 file changed, 128 insertions(+), 128 deletions(-) diff --git a/Ghidra/Processors/x86/data/languages/ia.sinc b/Ghidra/Processors/x86/data/languages/ia.sinc index 7763d811f92..972db6df20c 100644 --- a/Ghidra/Processors/x86/data/languages/ia.sinc +++ b/Ghidra/Processors/x86/data/languages/ia.sinc @@ -2188,68 +2188,33 @@ macro multflags(highhalf) { } macro rolflags(result,count) { - - local notzero = (count != 0); - local newCF = ((result & 1) != 0); - CF = (!notzero & CF) | (notzero & newCF); - - local one = (count == 1); - local newOF = CF ^ (result s< 0); - OF = (!one & OF) | (one & newOF); + conditionalAssign(CF, count==0, CF, (result & 1) != 0); + conditionalAssign(OF, count==1, CF ^ (result s< 0), OF); } macro rorflags(result,count) { - - local notzero = (count != 0); - local newCF = (result s< 0); - CF = (!notzero & CF) | (notzero & newCF); - - local one = (count == 1); - local newOF = (result s< 0) ^ ((result << 1) s< 0); - OF = (!one & OF) | (one & newOF); + conditionalAssign(CF, count==0, CF, (result s< 0)); + conditionalAssign(OF, count==1, CF ^ ((result << 1) s< 0), OF); } macro shlflags(op1,result,count) { # works for shld also - - local notzero = (count != 0); - local newCF = ( (op1 << (count - 1)) s< 0 ); - CF = (!notzero & CF) | (notzero & newCF); - - local one = (count == 1); - local newOF = CF ^ (result s< 0); - OF = (!one & OF) | (one & newOF); + conditionalAssign(CF, count==0, CF, (op1 << (count - 1)) s< 0); + conditionalAssign(OF, count==1, CF ^ (result s< 0), OF); } macro sarflags(op1,result,count) { - - local notzero = (count != 0); - local newCF = ( ( (op1 s>> (count - 1)) & 1 ) != 0 ); - CF = (!notzero & CF) | (notzero & newCF); - - local one = (count == 1); - OF = (!one & OF); + conditionalAssign(CF, count==0, CF, ( (op1 s>> (count - 1)) & 1 ) != 0 ); + conditionalAssign(OF, count==1, 0, OF); } macro shrflags(op1,result,count) { - - local notzero = (count != 0); - local newCF = ( ( (op1 >> (count - 1)) & 1 ) != 0 ); - CF = (!notzero & CF) | (notzero & newCF); - - local one = (count == 1); - local newOF = (op1 s< 0); - OF = (!one & OF) | (one & newOF); + conditionalAssign(CF, count==0, CF, ( (op1 >> (count - 1)) & 1 ) != 0 ); + conditionalAssign(OF, count==1, 0, (op1 s< 0)); } macro shrdflags(op1,result,count) { - - local notzero = (count != 0); - local newCF = ( ( (op1 >> (count - 1)) & 1 ) != 0 ); - CF = (!notzero & CF) | (notzero & newCF); - - local one = (count == 1); - local newOF = ((op1 s< 0) ^ (result s< 0)); - OF = (!one & OF) | (one & newOF); + conditionalAssign(CF, count==0, CF, ( (op1 >> (count - 1)) & 1 ) != 0 ); + conditionalAssign(OF, count==1, 0, ((op1 s< 0) ^ (result s< 0))); } macro fdec() { @@ -4426,82 +4391,117 @@ define pcodeop ptwrite; :PUSHFQ is $(LONGMODE_ON) & vexMode=0 & byte=0x9c { packflags(rflags); packeflags(rflags); push88(rflags); } @endif -:RCL rm8,n1 is vexMode=0 & byte=0xD0; rm8 & n1 & reg_opcode=2 ... { local tmpCF = CF; CF = rm8 s< 0; rm8 = (rm8 << 1) | tmpCF; OF = CF ^ (rm8 s< 0); } -:RCL rm8,CL is vexMode=0 & byte=0xD2; CL & rm8 & reg_opcode=2 ... { local cnt=(CL&0x1f)%9; tmp:2=(zext(CF)<<8)|zext(rm8); tmp=(tmp<>(9-cnt));rm8=tmp(0); CF=(tmp&0x100)!=0; } -:RCL rm8,imm8 is vexMode=0 & byte=0xC0; rm8 & reg_opcode=2 ... ; imm8 { local cnt=(imm8&0x1f)%9; tmp:2=(zext(CF)<<8)|zext(rm8); tmp=(tmp<>(9-cnt)); rm8=tmp(0); CF=(tmp&0x100)!=0; } -:RCL rm16,n1 is vexMode=0 & opsize=0 & byte=0xD1; rm16 & n1 & reg_opcode=2 ... { local tmpCF = CF; CF = rm16 s< 0; rm16 = (rm16 << 1) | zext(tmpCF); OF = CF ^ (rm16 s< 0);} -:RCL rm16,CL is vexMode=0 & opsize=0 & byte=0xD3; CL & rm16 & reg_opcode=2 ... {local cnt=(CL&0x1f)%17; tmp:4=(zext(CF)<<16)|zext(rm16); tmp=(tmp<>(17-cnt)); rm16=tmp(0); CF=(tmp&0x10000)!=0; } -:RCL rm16,imm8 is vexMode=0 & opsize=0 & byte=0xC1; rm16 & reg_opcode=2 ... ; imm8 { local cnt=(imm8&0x1f)%17; tmp:4=(zext(CF)<<16)|zext(rm16); tmp=(tmp<>(17-cnt)); rm16=tmp(0); CF=(tmp&0x10000)!=0; } -:RCL rm32,n1 is vexMode=0 & opsize=1 & byte=0xD1; rm32 & n1 & check_rm32_dest ... & reg_opcode=2 ... { local tmpCF=CF; CF=rm32 s< 0; rm32=(rm32<<1)|zext(tmpCF); OF=CF^(rm32 s< 0); build check_rm32_dest; } -:RCL rm32,CL is vexMode=0 & opsize=1 & byte=0xD3; CL & rm32 & check_rm32_dest ... & reg_opcode=2 ... { local cnt=CL&0x1f; tmp:8=(zext(CF)<<32)|zext(rm32); tmp=(tmp<>(33-cnt)); rm32=tmp(0); CF=(tmp&0x100000000)!=0; build check_rm32_dest; } -:RCL rm32,imm8 is vexMode=0 & opsize=1 & byte=0xC1; rm32 & check_rm32_dest ... & reg_opcode=2 ... ; imm8 { local cnt=imm8&0x1f; tmp:8=(zext(CF)<<32)|zext(rm32); tmp=(tmp<>(33-cnt)); rm32=tmp(0); CF=(tmp&0x100000000)!=0; build check_rm32_dest; } -@ifdef IA64 -:RCL rm64,n1 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0xD1; rm64 & n1 & reg_opcode=2 ... { local tmpCF=CF; CF=rm64 s< 0; rm64=(rm64<<1)|zext(tmpCF); OF=CF^(rm64 s< 0);} - -:RCL rm64,CL is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0xD3; CL & rm64 & reg_opcode=2 ... -{ - local cnt:1=CL&0x3f; - local rm64_copy:8 = rm64; - local CF_copy:1 = CF; - rotated:8 = rm64_copy << cnt; - rotated = rotated | (rm64_copy >> (65 -cnt)); - local CF_bit:8 = zext(CF_copy) << cnt-1; - rotated = rotated | CF_bit; - conditionalAssign(CF, cnt == 0:1, CF_copy, ((1:8<<(64-cnt)) & rm64_copy) != 0); - rm64 = rotated; -} - -:RCL rm64,imm8 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0xC1; rm64 & reg_opcode=2 ... ; imm8 -{ - local cnt:1=imm8&0x3f; - local rm64_copy:8 = rm64; - local CF_copy:1 = CF; - rotated:8 = rm64_copy << cnt; - rotated = rotated | (rm64_copy >> (65 -cnt)); - local CF_bit:8 = zext(CF_copy) << cnt-1; - rotated = rotated | CF_bit; - conditionalAssign(CF, cnt == 0:1, CF_copy, ((1:8<<(64-cnt)) & rm64_copy) != 0); - rm64 = rotated; -} -@endif - -:RCR rm8,n1 is vexMode=0 & byte=0xD0; rm8 & n1 & reg_opcode=3 ... { local tmpCF=CF; OF=rm8 s< 0; CF=(rm8&1)!=0; rm8=(rm8>>1)|(tmpCF<<7); OF=OF^(rm8 s< 0); } -:RCR rm8,CL is vexMode=0 & byte=0xD2; CL & rm8 & reg_opcode=3 ... { local cnt=(CL&0x1f)%9; tmp:2=(zext(CF)<<8)|zext(rm8); tmp=(tmp>>cnt)|(tmp<<(9-cnt)); rm8=tmp(0); CF=(tmp&0x100)!=0; } -:RCR rm8,imm8 is vexMode=0 & byte=0xC0; rm8 & reg_opcode=3 ... ; imm8 { local cnt=(imm8&0x1f)%9; tmp:2=(zext(CF)<<8)|zext(rm8); tmp=(tmp>>cnt)|(tmp<<(9-cnt)); rm8=tmp(0); CF=(tmp&0x100)!=0; } -:RCR rm16,n1 is vexMode=0 & opsize=0 & byte=0xD1; rm16 & n1 & reg_opcode=3 ... { local tmpCF=CF; OF=rm16 s< 0; CF=(rm16&1)!=0; rm16=(rm16>>1)|(zext(tmpCF)<<15); OF=OF^(rm16 s< 0); } -:RCR rm16,CL is vexMode=0 & opsize=0 & byte=0xD3; CL & rm16 & reg_opcode=3 ... { local cnt=(CL&0x1f)%17; tmp:4=(zext(CF)<<16)|zext(rm16); tmp=(tmp>>cnt)|(tmp<<(17-cnt)); rm16=tmp(0); CF=(tmp&0x10000)!=0; } -:RCR rm16,imm8 is vexMode=0 & opsize=0 & byte=0xC1; rm16 & reg_opcode=3 ... ; imm8 { local cnt=(imm8&0x1f)%17; tmp:4=(zext(CF)<<16)|zext(rm16); tmp=(tmp>>cnt)|(tmp<<(17-cnt)); rm16=tmp(0); CF=(tmp&0x10000)!=0; } -:RCR rm32,n1 is vexMode=0 & opsize=1 & byte=0xD1; rm32 & n1 & check_rm32_dest ... & reg_opcode=3 ... { local tmpCF=CF; OF=rm32 s< 0; CF=(rm32&1)!=0; rm32=(rm32>>1)|(zext(tmpCF)<<31); OF=OF^(rm32 s< 0); build check_rm32_dest; } -:RCR rm32,CL is vexMode=0 & opsize=1 & byte=0xD3; CL & rm32 & check_rm32_dest ... & reg_opcode=3 ... { local cnt=CL&0x1f; tmp:8=(zext(CF)<<32)|zext(rm32); tmp=(tmp>>cnt)|(tmp<<(33-cnt)); rm32=tmp(0); CF=(tmp&0x100000000)!=0; build check_rm32_dest; } -:RCR rm32,imm8 is vexMode=0 & opsize=1 & byte=0xC1; rm32 & check_rm32_dest ... & reg_opcode=3 ... ; imm8 { local cnt=imm8&0x1f; tmp:8=(zext(CF)<<32)|zext(rm32); tmp=(tmp>>cnt)|(tmp<<(33-cnt)); rm32=tmp(0); CF=(tmp&0x100000000)!=0; build check_rm32_dest; } -@ifdef IA64 -:RCR rm64,n1 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0xD1; rm64 & n1 & reg_opcode=3 ... { local tmpCF=CF; OF=rm64 s< 0; CF=(rm64&1)!=0; rm64=(rm64>>1)|(zext(tmpCF)<<63); OF=OF^(rm64 s< 0); } - -:RCR rm64,CL is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0xD3; CL & rm64 & reg_opcode=3 ... -{ - local cnt:1=CL&0x3f; - local rm64_copy:8 = rm64; - local CF_copy:1 = CF; - rotated:8 = rm64_copy >> cnt; - rotated = rotated | (rm64_copy << (65 -cnt)); - local CF_bit:8 = zext(CF_copy) << 64-cnt; - rotated = rotated | CF_bit; - conditionalAssign(CF, cnt == 0:1, CF_copy, ((1:8<<(cnt-1)) & rm64_copy) != 0); - rm64 = rotated; - } +macro rcl8(dest, rotate_count) { + local cnt:1 = (rotate_count & 0x1f) % 9; + local tmp:2 = (zext(CF) << 8) | zext(dest); + tmp = (tmp << cnt)|(tmp >> (9 - cnt)); + dest = tmp(0); + conditionalAssign(CF, cnt == 0, CF, (tmp & 0x100) != 0); + conditionalAssign(OF, cnt == 1, CF ^ (dest s< 0), OF); +} -:RCR rm64,imm8 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0xC1; rm64 & reg_opcode=3 ... ; imm8 -{ - local cnt:1=imm8&0x3f; - local rm64_copy:8 = rm64; - local CF_copy:1 = CF; - rotated:8 = rm64_copy >> cnt; - rotated = rotated | (rm64_copy << (65 -cnt)); - local CF_bit:8 = zext(CF_copy) << 64-cnt; - rotated = rotated | CF_bit; - conditionalAssign(CF, cnt == 0:1, CF_copy, ((1:8<<(cnt-1)) & rm64_copy) != 0); - rm64 = rotated; - } +:RCL rm8,n1 is vexMode=0 & byte=0xD0; rm8 & n1 & reg_opcode=2 ... { rcl8(rm8, n1:1); } +:RCL rm8,CL is vexMode=0 & byte=0xD2; CL & rm8 & reg_opcode=2 ... { rcl8(rm8, CL); } +:RCL rm8,imm8 is vexMode=0 & byte=0xC0; rm8 & reg_opcode=2 ... ; imm8 { rcl8(rm8, imm8:1); } + +macro rcl16(dest, rotate_count) { + local cnt = (rotate_count & 0x1f) % 17; + local tmp:4 = (zext(CF) << 16) | zext(dest); + tmp = (tmp << cnt) | (tmp >> (17 - cnt)); + dest = tmp(0); + conditionalAssign(CF, cnt==0, CF, (tmp & 0x10000) != 0); + conditionalAssign(OF, cnt==1, CF ^ (dest s< 0), OF); +} + +:RCL rm16,n1 is vexMode=0 & opsize=0 & byte=0xD1; rm16 & n1 & reg_opcode=2 ... { rcl16(rm16, n1:1); } +:RCL rm16,CL is vexMode=0 & opsize=0 & byte=0xD3; CL & rm16 & reg_opcode=2 ... { rcl16(rm16, CL); } +:RCL rm16,imm8 is vexMode=0 & opsize=0 & byte=0xC1; rm16 & reg_opcode=2 ... ; imm8 { rcl16(rm16, imm8:1); } + + +macro rcl32(dest, rotate_count) { + local cnt = rotate_count & 0x1f; + local tmp:8 = (zext(CF) << 32) | zext(dest); + tmp = (tmp << cnt) | (tmp >> (33 - cnt)); + dest = tmp(0); + conditionalAssign(CF, cnt==0, CF, (tmp&0x100000000)!=0); + conditionalAssign(OF, cnt==1, CF ^ (dest s< 0), OF); +} + +:RCL rm32,n1 is vexMode=0 & opsize=1 & byte=0xD1; rm32 & n1 & check_rm32_dest ... & reg_opcode=2 ... { rcl32(rm32, n1:1); build check_rm32_dest; } +:RCL rm32,CL is vexMode=0 & opsize=1 & byte=0xD3; CL & rm32 & check_rm32_dest ... & reg_opcode=2 ... { rcl32(rm32, CL); build check_rm32_dest; } +:RCL rm32,imm8 is vexMode=0 & opsize=1 & byte=0xC1; rm32 & check_rm32_dest ... & reg_opcode=2 ... ; imm8 { rcl32(rm32, imm8:1); build check_rm32_dest; } + +@ifdef IA64 +macro rcl64(dest, rotate_count) { + local cnt:1 = rotate_count & 0x3f; + local rm64_copy:8 = dest; + local CF_copy:1 = CF; + rotated:8 = rm64_copy << cnt; + rotated = rotated | (rm64_copy >> (65 - cnt)); + local CF_bit:8 = zext(CF_copy) << cnt-1; + rotated = rotated | CF_bit; + dest = rotated; + conditionalAssign(CF, cnt == 0, CF_copy, ((1<<(64-cnt)) & rm64_copy) != 0); + conditionalAssign(OF, cnt==1, CF ^ (dest s< 0), OF); +} + +:RCL rm64,n1 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0xD1; rm64 & n1 & reg_opcode=2 ... { rcl64(rm64, n1:1); } +:RCL rm64,CL is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0xD3; CL & rm64 & reg_opcode=2 ... { rcl64(rm64, CL); } +:RCL rm64,imm8 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0xC1; rm64 & reg_opcode=2 ... ; imm8 { rcl64(rm64, imm8:1); } +@endif + +macro rcr8(dest, rotate_count) { + local cnt = (rotate_count & 0x1f) % 9; + conditionalAssign(OF, cnt==1, CF ^ (dest s< 0), OF); + local tmp:2 = (zext(CF) << 8) | zext(dest); tmp = (tmp >> cnt) | (tmp << (9 - cnt)); + dest = tmp(0); + conditionalAssign(CF, cnt == 0, CF, (tmp & 0x100) != 0); +} + +:RCR rm8,n1 is vexMode=0 & byte=0xD0; rm8 & n1 & reg_opcode=3 ... { rcr8(rm8, n1:1); } +:RCR rm8,CL is vexMode=0 & byte=0xD2; CL & rm8 & reg_opcode=3 ... { rcr8(rm8, CL); } +:RCR rm8,imm8 is vexMode=0 & byte=0xC0; rm8 & reg_opcode=3 ... ; imm8 { rcr8(rm8, imm8:1); } + +macro rcr16(dest, rotate_count) { + local cnt=(rotate_count & 0x1f) % 17; + conditionalAssign(OF, cnt==1, CF ^ (dest s< 0), OF); + local tmp:4 = (zext(CF) << 16) | zext(dest); + tmp = (tmp >> cnt) | (tmp << (17 - cnt)); + dest=tmp(0); + conditionalAssign(CF, cnt == 0, CF, (tmp & 0x10000) != 0); +} + +:RCR rm16,n1 is vexMode=0 & opsize=0 & byte=0xD1; rm16 & n1 & reg_opcode=3 ... { rcr16(rm16, n1:1); } +:RCR rm16,CL is vexMode=0 & opsize=0 & byte=0xD3; CL & rm16 & reg_opcode=3 ... { rcr16(rm16, CL); } +:RCR rm16,imm8 is vexMode=0 & opsize=0 & byte=0xC1; rm16 & reg_opcode=3 ... ; imm8 { rcr16(rm16, imm8:1); } + +macro rcr32(dest, rotate_count) { + local cnt = rotate_count & 0x1f; + conditionalAssign(OF, cnt==1, CF ^ (dest s< 0), OF); + local tmp:8 = (zext(CF) << 32) | zext(dest); + tmp = (tmp >> cnt) | (tmp << (33 - cnt)); + dest = tmp(0); + conditionalAssign(CF, cnt == 0, CF, (tmp&0x100000000)!=0); +} + +:RCR rm32,n1 is vexMode=0 & opsize=1 & byte=0xD1; rm32 & n1 & check_rm32_dest ... & reg_opcode=3 ... { rcr32(rm32, n1:1); build check_rm32_dest; } +:RCR rm32,CL is vexMode=0 & opsize=1 & byte=0xD3; CL & rm32 & check_rm32_dest ... & reg_opcode=3 ... { rcr32(rm32, CL); build check_rm32_dest; } +:RCR rm32,imm8 is vexMode=0 & opsize=1 & byte=0xC1; rm32 & check_rm32_dest ... & reg_opcode=3 ... ; imm8 { rcr32(rm32, imm8:1); build check_rm32_dest; } + +@ifdef IA64 +macro rcr64(dest, rotate_count) { + local cnt:1 = rotate_count & 0x3f; + conditionalAssign(OF, cnt==1, CF ^ (dest s< 0), OF); + local tmp:16 = (zext(CF) << 64) | zext(dest); + tmp = (tmp >> cnt) | (tmp << (65 - cnt)); + dest = tmp(0); + local upper:1 = tmp(8) & 0x1; + conditionalAssign(CF, cnt == 0, CF, upper != 0); +} + +:RCR rm64,n1 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0xD1; rm64 & n1 & reg_opcode=3 ... { rcr64(rm64, n1:1); } +:RCR rm64,CL is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0xD3; CL & rm64 & reg_opcode=3 ... { rcr64(rm64, CL); } +:RCR rm64,imm8 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0xC1; rm64 & reg_opcode=3 ... ; imm8 { rcr64(rm64, imm8:1); } @endif @ifdef IA64 @@ -4710,7 +4710,7 @@ define pcodeop serialize; :SHL rm8,n1 is vexMode=0 & byte=0xD0; rm8 & n1 &(reg_opcode=4|reg_opcode=6) ... { CF = rm8 s< 0; rm8 = rm8 << 1; OF = CF ^ (rm8 s< 0); resultflags(rm8); } -:SHL rm8,CL is vexMode=0 & byte=0xD2; CL & rm8 & (reg_opcode=4|reg_opcode=6) ... { local count = CL & 0x1f; local tmp = rm8; rm8 = rm8 << count; +:SHL rm8,CL is vexMode=0 & byte=0xD2; CL & rm8 & (reg_opcode=4|reg_opcode=6) ... { local count = CL & 0x1f; local tmp = rm8; rm8 = rm8 << count; shlflags(tmp, rm8,count); shiftresultflags(rm8,count); } :SHL rm8,imm8 is vexMode=0 & byte=0xC0; rm8 & (reg_opcode=4|reg_opcode=6) ... ; imm8 { local count = imm8 & 0x1f; local tmp = rm8; rm8 = rm8 << count; shlflags(tmp, rm8,count); shiftresultflags(rm8,count); } @@ -4774,23 +4774,23 @@ define pcodeop serialize; shrdflags(tmp,rm64,count); shiftresultflags(rm64,count); } @endif -:SHR rm8,n1 is vexMode=0 & byte=0xD0; rm8 & n1 & reg_opcode=5 ... { OF = (rm8 s< 0); CF = rm8 & 1; rm8 = rm8 >> 1; resultflags(rm8); } -:SHR rm8,CL is vexMode=0 & byte=0xD2; CL & rm8 & reg_opcode=5 ... { local count = CL & 0x1f; local tmp = rm8; rm8 = rm8 >> count; +:SHR rm8,n1 is vexMode=0 & byte=0xD0; rm8 & n1 & reg_opcode=5 ... { CF = rm8 & 1; OF = (rm8 s< 0); rm8 = rm8 >> 1; resultflags(rm8); } +:SHR rm8,CL is vexMode=0 & byte=0xD2; CL & rm8 & reg_opcode=5 ... { local count = CL & 0x1f; local tmp = rm8; rm8 = rm8 >> count; shrflags(tmp, rm8,count); shiftresultflags(rm8,count); } :SHR rm8,imm8 is vexMode=0 & byte=0xC0; rm8 & reg_opcode=5 ... ; imm8 { local count = imm8 & 0x1f; local tmp = rm8; rm8 = rm8 >> count; shrflags(tmp, rm8,count); shiftresultflags(rm8,count); } -:SHR rm16,n1 is vexMode=0 & opsize=0 & byte=0xD1; rm16 & n1 & reg_opcode=5 ... { OF = (rm16 s< 0); CF = (rm16 & 1) != 0; rm16 = rm16 >> 1; resultflags(rm16); } +:SHR rm16,n1 is vexMode=0 & opsize=0 & byte=0xD1; rm16 & n1 & reg_opcode=5 ... { CF = (rm16 & 1) != 0; OF = (rm16 s< 0); rm16 = rm16 >> 1; resultflags(rm16); } :SHR rm16,CL is vexMode=0 & opsize=0 & byte=0xD3; CL & rm16 & reg_opcode=5 ... { local count = CL & 0x1f; local tmp = rm16; rm16 = rm16 >> count; shrflags(tmp, rm16,count); shiftresultflags(rm16,count); } :SHR rm16,imm8 is vexMode=0 & opsize=0 & byte=0xC1; rm16 & reg_opcode=5 ... ; imm8 { local count = imm8 & 0x1f; local tmp = rm16; rm16 = rm16 >> count; shrflags(tmp, rm16,count); shiftresultflags(rm16,count); } -:SHR rm32,n1 is vexMode=0 & opsize=1 & byte=0xD1; rm32 & n1 & check_rm32_dest ... & reg_opcode=5 ... { OF = (rm32 s< 0); CF = (rm32 & 1) != 0; rm32 = rm32 >> 1; build check_rm32_dest; resultflags(rm32); } +:SHR rm32,n1 is vexMode=0 & opsize=1 & byte=0xD1; rm32 & n1 & check_rm32_dest ... & reg_opcode=5 ... { CF = (rm32 & 1) != 0; OF = (rm32 s< 0); rm32 = rm32 >> 1; build check_rm32_dest; resultflags(rm32); } :SHR rm32,CL is vexMode=0 & opsize=1 & byte=0xD3; CL & rm32 & check_rm32_dest ... & reg_opcode=5 ... { local count = CL & 0x1f; local tmp = rm32; rm32 = rm32 >> count; build check_rm32_dest; shrflags(tmp, rm32,count); shiftresultflags(rm32,count); } :SHR rm32,imm8 is vexMode=0 & opsize=1 & byte=0xC1; rm32 & check_rm32_dest ... & reg_opcode=5 ... ; imm8 { local count = imm8 & 0x1f; local tmp = rm32; rm32 = rm32 >> count; build check_rm32_dest; shrflags(tmp, rm32,count); shiftresultflags(rm32,count); } @ifdef IA64 -:SHR rm64,n1 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0xD1; rm64 & n1 ®_opcode=5 ... { OF = (rm64 s< 0); CF = (rm64 & 1) != 0; rm64 = rm64 >> 1; resultflags(rm64); } +:SHR rm64,n1 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0xD1; rm64 & n1 ®_opcode=5 ... { CF = (rm64 & 1) != 0; OF = (rm64 s< 0); rm64 = rm64 >> 1; resultflags(rm64); } :SHR rm64,CL is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0xD3; CL & rm64 & reg_opcode=5 ... { local count = CL & 0x3f; local tmp = rm64; rm64 = rm64 >> count; shrflags(tmp, rm64,count); shiftresultflags(rm64,count); } :SHR rm64,imm8 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0xC1; rm64 & reg_opcode=5 ... ; imm8 { local count = imm8 & 0x3f; local tmp = rm64; rm64 = rm64 >> count; From 8fe0f54f139149832a7916d80128f73cfd31e7e8 Mon Sep 17 00:00:00 2001 From: emteere <47253321+emteere@users.noreply.github.com> Date: Mon, 10 Aug 2026 18:25:06 -0400 Subject: [PATCH 106/111] GP-7023 Fix switch detection code for instructions with internal pcode branching like AARCH64 CSEL instruction. --- .../analysis/DecompilerSwitchAnalyzer.java | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/analysis/DecompilerSwitchAnalyzer.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/analysis/DecompilerSwitchAnalyzer.java index af699b90abf..d632172e4c8 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/analysis/DecompilerSwitchAnalyzer.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/analysis/DecompilerSwitchAnalyzer.java @@ -478,7 +478,8 @@ private boolean resolveComputableFlow(Address location, TaskMonitor monitor, // then it isn't a switch statment // // NOTE: Assumption, we have found all flows leading to the switch that might split the basic block - + // NOTE: This assumption is a problem for internal pcode branching. Need to check for that. + final AtomicInteger foundCount = new AtomicInteger(0); SymbolicPropogator prop = new SymbolicPropogator(program,false); prop.flowConstants(jumpBlockAt.getFirstStartAddress(), jumpBlockAt, @@ -493,6 +494,27 @@ public boolean evaluateReference(VarnodeContext context, Instruction instr, } return false; } + + @Override + public boolean evaluateContextBefore(VarnodeContext context, Instruction instr) { + // There shouldn't be any branching because a branch would split a block + // but there could be internal branches, as the basic block algorithm can't + // detect these cases correctly. + PcodeOp[] pcode = instr.getPcode(); + for (PcodeOp pcodeOp : pcode) { + if (pcodeOp.getOpcode() == PcodeOp.CBRANCH) { + return true; + } + } + return false; + } + + @Override + public boolean followFalseConditionalBranches() { + // There shouldn't be any because a branch would split a block + // but there could be internal branches. + return false; + } }, false, monitor); // only found one reference From cd0d718e488c12ae89740502eaa2b45c31d21f33 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Tue, 11 Aug 2026 11:40:53 -0400 Subject: [PATCH 107/111] GP-7134: Upgrading log4j to 2.26.1 --- Ghidra/Framework/Generic/Module.manifest | 4 ++-- Ghidra/Framework/Generic/build.gradle | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Ghidra/Framework/Generic/Module.manifest b/Ghidra/Framework/Generic/Module.manifest index 37630b5f059..af96a293f19 100644 --- a/Ghidra/Framework/Generic/Module.manifest +++ b/Ghidra/Framework/Generic/Module.manifest @@ -3,8 +3,8 @@ MODULE FILE LICENSE: lib/commons-codec-1.18.0.jar Apache License 2.0 MODULE FILE LICENSE: lib/guava-32.1.3-jre.jar Apache License 2.0 MODULE FILE LICENSE: lib/failureaccess-1.0.1.jar Apache License 2.0 MODULE FILE LICENSE: lib/jdom2-2.0.6.1.jar JDOM License -MODULE FILE LICENSE: lib/log4j-api-2.25.4.jar Apache License 2.0 -MODULE FILE LICENSE: lib/log4j-core-2.25.4.jar Apache License 2.0 +MODULE FILE LICENSE: lib/log4j-api-2.26.1.jar Apache License 2.0 +MODULE FILE LICENSE: lib/log4j-core-2.26.1.jar Apache License 2.0 MODULE FILE LICENSE: lib/commons-collections4-4.1.jar Apache License 2.0 MODULE FILE LICENSE: lib/commons-lang3-3.20.0.jar Apache License 2.0 MODULE FILE LICENSE: lib/commons-io-2.19.0.jar Apache License 2.0 diff --git a/Ghidra/Framework/Generic/build.gradle b/Ghidra/Framework/Generic/build.gradle index ef03caa0565..4fa145d166e 100644 --- a/Ghidra/Framework/Generic/build.gradle +++ b/Ghidra/Framework/Generic/build.gradle @@ -34,8 +34,8 @@ dependencies { } api "com.google.guava:failureaccess:1.0.1" api "org.jdom:jdom2:2.0.6.1" - api "org.apache.logging.log4j:log4j-api:2.25.4" - api "org.apache.logging.log4j:log4j-core:2.25.4" + api "org.apache.logging.log4j:log4j-api:2.26.1" + api "org.apache.logging.log4j:log4j-core:2.26.1" api "org.apache.commons:commons-collections4:4.1" api "org.apache.commons:commons-compress:1.27.1" // requires commons-codec api "commons-codec:commons-codec:1.18.0" From 31ffc98d3b8eabb149009fa99ffa0f0d4c621028 Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Tue, 11 Aug 2026 14:53:25 -0400 Subject: [PATCH 108/111] GP-7017: Fixed masking for several PEXT* and PINS* instructions --- Ghidra/Processors/x86/data/languages/avx.sinc | 54 +++++++++++++------ .../Processors/x86/data/languages/avx512.sinc | 48 ++++++----------- Ghidra/Processors/x86/data/languages/ia.sinc | 4 +- 3 files changed, 56 insertions(+), 50 deletions(-) diff --git a/Ghidra/Processors/x86/data/languages/avx.sinc b/Ghidra/Processors/x86/data/languages/avx.sinc index 59b3dd6f07d..607489e3906 100644 --- a/Ghidra/Processors/x86/data/languages/avx.sinc +++ b/Ghidra/Processors/x86/data/languages/avx.sinc @@ -1832,16 +1832,16 @@ define pcodeop vpcmpistrm_avx ; define pcodeop vpextrb_avx ; :VPEXTRB Rmr32, XmmReg1, imm8 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W0); byte=0x14; mod=3 & XmmReg1 & Rmr32 & check_Rmr32_dest; imm8 { - local tmp8:1 = imm8; - local tmp = XmmReg1 >> (tmp8[0,3]*8); + local tmp8:1 = imm8 & 0xf; + local tmp = XmmReg1 >> (tmp8*8); Rmr32 = zext(tmp[0,8]); build check_Rmr32_dest; } :VPEXTRB m8, XmmReg1, imm8 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W0); byte=0x14; (XmmReg1 ... & m8); imm8 { - local tmp8:1 = imm8; - local tmp = XmmReg1 >> (tmp8[0,3]*8); + local tmp8:1 = imm8 & 0xf; + local tmp = XmmReg1 >> (tmp8*8); m8 = tmp[0,8]; } @@ -1849,39 +1849,52 @@ define pcodeop vpextrb_avx ; define pcodeop vpextrd_avx ; :VPEXTRD Rmr32, XmmReg1, imm8 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W0); byte=0x16; mod=3 & XmmReg1 & Rmr32 & check_Rmr32_dest; imm8 { - local tmp = XmmReg1 >> (imm8*32); + local tmp8:1 = imm8 & 3; + local tmp = XmmReg1 >> (tmp8*32); Rmr32 = tmp(0); build check_Rmr32_dest; } :VPEXTRD m32, XmmReg1, imm8 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W0); byte=0x16; XmmReg1 ... & m32; imm8 { - local tmp = XmmReg1 >> (imm8*32); + local tmp8:1 = imm8 & 3; + local tmp = XmmReg1 >> (tmp8*32); m32 = tmp(0); } # PEXTRB/PEXTRD/PEXTRQ 4-274 PAGE 1394 LINE 72330 -define pcodeop vpextrq_avx ; @ifdef IA64 :VPEXTRQ rm64, XmmReg1, imm8 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1); byte=0x16; XmmReg1 ... & rm64; imm8 { - rm64 = vpextrq_avx( XmmReg1, imm8:1 ); + local tmp8:1 = imm8 & 1; + local tmp = XmmReg1 >> (tmp8*64); + rm64 = tmp(0); } @endif # PEXTRW 4-277 PAGE 1397 LINE 72478 -define pcodeop vpextrw_avx ; -:VPEXTRW Reg32, XmmReg2, imm8 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG); byte=0xC5; Reg32 & (mod=0x3 & XmmReg2); imm8 +:VPEXTRW Reg32, XmmReg2, imm8 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG); byte=0xC5; Reg32 & check_Reg32_dest & (mod=0x3 & XmmReg2); imm8 { - Reg32 = vpextrw_avx( XmmReg2, imm8:1 ); - # TODO Reg64 = zext(Reg32) + local tmp8:1 = imm8 & 7; + local tmp = XmmReg2 >> (tmp8*16); + Reg32 = zext(tmp[0,16]); + build check_Reg32_dest; } # PEXTRW 4-277 PAGE 1397 LINE 72483 -:VPEXTRW Reg32_m16, XmmReg1, imm8 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_WIG); byte=0x15; XmmReg1 ... & Reg32_m16; imm8 +:VPEXTRW Reg32, XmmReg1, imm8 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_WIG); byte=0x15; XmmReg1 & mod=3 & Reg32 & check_Reg32_dest; imm8 { - Reg32_m16 = vpextrw_avx( XmmReg1, imm8:1 ); - # TODO Reg64 = zext(Reg32) + local tmp8:1 = imm8 & 7; + local tmp = XmmReg1 >> (tmp8*16); + Reg32 = zext(tmp[0,16]); + build check_Reg32_dest; +} + +:VPEXTRW m16, XmmReg1, imm8 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_WIG); byte=0x15; XmmReg1 ... & m16; imm8 +{ + local tmp8:1 = imm8 & 7; + local tmp = XmmReg1 >> (tmp8*16); + m16 = tmp[0,16]; } # PHADDW/PHADDD 4-280 PAGE 1400 LINE 72627 @@ -1950,7 +1963,16 @@ define pcodeop vpinsrb_avx ; # PINSRW 4-296 PAGE 1416 LINE 73446 define pcodeop vpinsrw_avx ; -:VPINSRW XmmReg1, vexVVVV_XmmReg, Reg32_m16, imm8 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xC4; (XmmReg1 & ZmmReg1) ... & Reg32_m16; imm8 +@ifdef IA64 +:VPINSRW XmmReg1, vexVVVV_XmmReg, Reg32_m16, imm8 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG) & vexVVVV_XmmReg; byte=0xC4; (XmmReg1 & ZmmReg1) ... & Reg32_m16; imm8 +{ + local tmp:16 = vpinsrw_avx( vexVVVV_XmmReg, Reg32_m16, imm8:1 ); + ZmmReg1 = zext(tmp); +} +@endif + +# Footnote in manual: In 64-bit mode, VEX.W1 is ignored for VPINSRW (similar to legacy REX.W=1 prefix in PINSRW). +:VPINSRW XmmReg1, vexVVVV_XmmReg, Reg32_m16, imm8 is $(LONGMODE_OFF) & $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W0) & vexVVVV_XmmReg; byte=0xC4; (XmmReg1 & ZmmReg1) ... & Reg32_m16; imm8 { local tmp:16 = vpinsrw_avx( vexVVVV_XmmReg, Reg32_m16, imm8:1 ); ZmmReg1 = zext(tmp); diff --git a/Ghidra/Processors/x86/data/languages/avx512.sinc b/Ghidra/Processors/x86/data/languages/avx512.sinc index 97ea239c2bb..5fbec89db3a 100644 --- a/Ghidra/Processors/x86/data/languages/avx512.sinc +++ b/Ghidra/Processors/x86/data/languages/avx512.sinc @@ -3146,30 +3146,27 @@ define pcodeop vpcmpgtq_avx512f ; } # PEXTRB/PEXTRD/PEXTRQ 4-274 PAGE 1394 LINE 72334 -@ifdef IA64 -:VPEXTRB Reg32, XmmReg1, imm8 is $(LONGMODE_ON) & $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_WIG); byte=0x14; XmmReg1 & mod=3 & Reg32 & Reg64; imm8 -{ - local tmp = XmmReg1 >> (imm8*8); - Reg64 = zext(tmp[0,8]); -} -@endif - -:VPEXTRB Reg32, XmmReg1, imm8 is $(LONGMODE_OFF) & $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_WIG); byte=0x14; XmmReg1 & mod=3 & Reg32; imm8 +:VPEXTRB Reg32, XmmReg1, imm8 is $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_WIG); byte=0x14; XmmReg1 & mod=3 & Reg32 & check_Reg32_dest; imm8 { - local tmp = XmmReg1 >> (imm8*8); + local tmp8:1 = imm8 & 0xf; + local tmp = XmmReg1 >> (tmp8*8); Reg32 = zext(tmp[0,8]); + build check_Reg32_dest; } + :VPEXTRB m8, XmmReg1, imm8 is $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_WIG); byte=0x14; XmmReg1 ... & m8; imm8 { - local tmp = XmmReg1 >> (imm8*8); + local tmp8:1 = imm8 & 0xf; + local tmp = XmmReg1 >> (tmp8*8); m8 = tmp[0,8]; } # PEXTRB/PEXTRD/PEXTRQ 4-274 PAGE 1394 LINE 72339 :VPEXTRD rm32, XmmReg1, imm8 is $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W0); byte=0x16; XmmReg1 ... & rm32; imm8 { - local tmp = XmmReg1 >> (imm8*32); + local tmp8:1 = imm8 & 0x3; + local tmp = XmmReg1 >> (tmp8*32); rm32 = tmp[0,32]; } @@ -3177,42 +3174,29 @@ define pcodeop vpcmpgtq_avx512f ; @ifdef IA64 :VPEXTRQ rm64, XmmReg1, imm8 is $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1); byte=0x16; XmmReg1 ... & rm64; imm8 { - local tmp = XmmReg1 >> (imm8*64); + local tmp8:1 = imm8 & 0x1; + local tmp = XmmReg1 >> (tmp8*64); rm64 = tmp[0,64]; } @endif # PEXTRW 4-277 PAGE 1397 LINE 72488 -@ifdef IA64 -:VPEXTRW Reg32, XmmReg2, imm8 is $(LONGMODE_ON) & $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG); byte=0xC5; Reg32 & Reg64 & (mod=0x3 & XmmReg2); imm8 -{ - local tmp = XmmReg2 >> (imm8*16); - Reg64 = zext(tmp[0,16]); -} -@endif - -:VPEXTRW Reg32, XmmReg2, imm8 is $(LONGMODE_OFF) & $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG); byte=0xC5; Reg32 & (mod=0x3 & XmmReg2); imm8 +:VPEXTRW Reg32, XmmReg2, imm8 is $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG); byte=0xC5; Reg32 & check_Reg32_dest & (mod=0x3 & XmmReg2); imm8 { local tmp = XmmReg2 >> (imm8*16); Reg32 = zext(tmp[0,16]); + build check_Reg32_dest; } -# PEXTRW 4-277 PAGE 1397 LINE 72494 -@ifdef IA64 -:VPEXTRW Reg32, XmmReg1, imm8 is $(LONGMODE_ON) & $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_WIG); byte=0x15; XmmReg1 & mod=3 & Reg32 & Reg64; imm8 -{ - local tmp = XmmReg1 >> (imm8*16); - Reg64 = zext(tmp[0,16]); -} -@endif -:VPEXTRW Reg32, XmmReg1, imm8 is $(LONGMODE_OFF) & $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_WIG); byte=0x15; XmmReg1 & mod=3 & Reg32; imm8 +# PEXTRW 4-277 PAGE 1397 LINE 72494 +:VPEXTRW Reg32, XmmReg1, imm8 is $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_WIG); byte=0x15; XmmReg1 & mod=3 & Reg32 & check_Reg32_dest; imm8 { local tmp = XmmReg1 >> (imm8*16); Reg32 = zext(tmp[0,16]); + build check_Reg32_dest; } - :VPEXTRW m16, XmmReg1, imm8 is $(EVEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_WIG); byte=0x15; XmmReg1 ... & m16; imm8 { local tmp = XmmReg1 >> (imm8*16); diff --git a/Ghidra/Processors/x86/data/languages/ia.sinc b/Ghidra/Processors/x86/data/languages/ia.sinc index bec84c5ba38..9c3482063c7 100644 --- a/Ghidra/Processors/x86/data/languages/ia.sinc +++ b/Ghidra/Processors/x86/data/languages/ia.sinc @@ -8691,7 +8691,7 @@ define pcodeop phsubsw; :PINSRW mmxreg, Rmr32, imm8 is vexMode=0 & mandover=0 & byte=0x0F; byte=0xC4; mmxmod=3 & Rmr32 & mmxreg; imm8 { - local destIndex:1 = (imm8 & 0x7) * 16:1; + local destIndex:1 = (imm8 & 0x3) * 16:1; mmxreg = mmxreg & ~(0xffff:8 << destIndex); local newVal:8 = zext(Rmr32[0,16]); mmxreg = mmxreg | (newVal << destIndex); @@ -8699,7 +8699,7 @@ define pcodeop phsubsw; :PINSRW mmxreg, m16, imm8 is vexMode=0 & mandover=0 & byte=0x0F; byte=0xC4; m16 & mmxreg ... ; imm8 { - local destIndex:1 = (imm8 & 0x7) * 16:1; + local destIndex:1 = (imm8 & 0x3) * 16:1; mmxreg = mmxreg & ~(0xffff:8 << destIndex); local newVal:8 = zext(m16); mmxreg = mmxreg | (newVal << destIndex); From 90015f129cbe0ff67bc5e9481c8cdf3f256fef10 Mon Sep 17 00:00:00 2001 From: ghidorahrex Date: Wed, 12 Aug 2026 08:36:10 -0400 Subject: [PATCH 109/111] GP-7017: Upped x86 version number --- Ghidra/Processors/x86/data/languages/x86.ldefs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Ghidra/Processors/x86/data/languages/x86.ldefs b/Ghidra/Processors/x86/data/languages/x86.ldefs index 43b1ecf864f..089bee449a8 100644 --- a/Ghidra/Processors/x86/data/languages/x86.ldefs +++ b/Ghidra/Processors/x86/data/languages/x86.ldefs @@ -5,7 +5,7 @@ endian="little" size="32" variant="default" - version="4.7" + version="4.8" slafile="x86.sla" processorspec="x86.pspec" manualindexfile="../manuals/x86.idx" @@ -37,7 +37,7 @@ endian="little" size="32" variant="System Management Mode" - version="4.7" + version="4.8" slafile="x86.sla" processorspec="x86-16.pspec" manualindexfile="../manuals/x86.idx" @@ -50,7 +50,7 @@ endian="little" size="16" variant="Real Mode" - version="4.7" + version="4.8" slafile="x86.sla" processorspec="x86-16-real.pspec" manualindexfile="../manuals/x86.idx" @@ -70,7 +70,7 @@ endian="little" size="16" variant="Protected Mode" - version="4.7" + version="4.8" slafile="x86.sla" processorspec="x86-16.pspec" manualindexfile="../manuals/x86.idx" @@ -85,7 +85,7 @@ endian="little" size="64" variant="default" - version="4.7" + version="4.8" slafile="x86-64.sla" processorspec="x86-64.pspec" manualindexfile="../manuals/x86.idx" @@ -108,7 +108,7 @@ endian="little" size="64" variant="compat32" - version="4.7" + version="4.8" slafile="x86-64.sla" processorspec="x86-64-compat32.pspec" manualindexfile="../manuals/x86.idx" From c8c09e57ca85d83b7ade0752a02924ea8285ba60 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Wed, 12 Aug 2026 11:17:27 -0400 Subject: [PATCH 110/111] GP-0: Adding ChangeHistory for 12.1.3 --- .../src/global/docs/ChangeHistory.md | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/Ghidra/Configurations/Public_Release/src/global/docs/ChangeHistory.md b/Ghidra/Configurations/Public_Release/src/global/docs/ChangeHistory.md index a0814cb4f76..8e83034bedd 100644 --- a/Ghidra/Configurations/Public_Release/src/global/docs/ChangeHistory.md +++ b/Ghidra/Configurations/Public_Release/src/global/docs/ChangeHistory.md @@ -1,3 +1,82 @@ +# Ghidra 12.1.3 Change History (August 2026) + +### Improvements +* _Basic Infrastructure_. Added stricter filtering to characters used for symbol names. (GP-6843, Issue #9165, #9172, #9206) +* _BSim_. Improved escaping in `BSimControlLaunchable`. (GP-6977) +* _BSim_. Upgraded the PostgreSQL JDBC Driver from 42.7.11 to 42.7.13. (GP-7105) +* _BSim_. Upgraded postgresql for BSim to 15.18. (GP-7107) +* _Demangler_. The Swift Demangler Analyzer no longer accepts a user-specified path to the Swift binary directory. Instead, the Demangler expects Swift to be on the `PATH`. (GP-7045) +* _Exporter_. Added packed Debugger Trace import/export using `*.gzt` files. (GP-6891) +* _GUI_. Updated the Headless Analyzer to not write to the user's preferences. (GP-7096, Issue #9414) +* _Importer:COFF_. Implemented the COFF `IMAGE_REL_ARM64_ADDR64` relocation. (GP-7088, Issue #9408) +* _Importer:Mach-O_. Provided safer parsing of `dyld_shared_cache` files. (GP-7046) +* _Logging_. Upgraded log4j to version 2.26.1. (GP-7134) +* _Multi-User_. Corrected potential network performance issue related to Ghidra Server use. Full benefit requires update of both Ghidra Server installation and Ghidra client software. (GP-7012, Issue #2752, #9316) +* _Processors_. Made SparcV9 register display formatting more consistent. (GP-941) +* _Scripting_. Updated the Structure Editor to perform a structure reload when the structure's description is changed outside of the editor. (GP-7118, Issue #9461) +* _Search_. Updated __Find Uses of__ for FunctionDefinitions to find references inside of functions and function parameters. (GP-7044, Issue #9342) + +### Bugs +* _Analysis_. Fixed failure to recover switch instructions if the switch is computed with an instruction with internal pcode branching such as the AARCH64 `csel` instruction. (GP-7023) +* _BSim_. Improved `GhidraURL.toURL` to handle Ghidra URLs previously stored by BSim where proper URL encoding was never performed. (GP-6970, Issue #9275) +* _Data Types_. Corrected BuiltIn GUID datatype alignment to be 4 bytes instead of 8 bytes. Packed structures containing this datatype will need to be re-packed to pick up on this change. (GP-6953, Issue #9200) +* _DB_. Corrected Ghidra database problem which could prevent analysis times from getting properly saved to a program. (GP-7070, Issue #9346) +* _DB_. Corrected internal method behavior for `ContentHandler.getChangeSet` which could return an empty change set if the version range does not include the latest version. (GP-7113, Issue #9415) +* _Debugger:Agents_. Now applying proper argument quoting and metacharacter escaping to prevent `ShellUtils` command injection. (GP-6934, Issue #9283) +* _Debugger:Time_. Fixed PC column in Time panel when emulating from a live target. (GP-6841) +* _Debugger:Trace_. Fixed a potential OOM exception in `ObjectStorageStreamAdapter` used by Trace database. (GP-6886) +* _Decompiler_. Added Decompiler support for memory accesses that wrap from high to low addresses. (GP-6936) +* _FileSystems_. Fixed a potential path-traversal vulnerability in `AndroidProjectCreator`. (GP-6885) +* _GUI_. Fixed bugs in the Column Filter Dialog that caused `NullPointerExceptions` on some Mac systems. (GP-7050) +* _GUI_. Fixed a deadlock seen when saving a program. (GP-7051, Issue #9358) +* _GUI_. Fixed incorrect tool tips in the File Chooser that are sometimes seen when filenames are clipped. (GP-7094) +* _Importer_. Fixed a potential path-traversal vulnerability when importing XML `*.bytes` files. (GP-7064) +* _Importer_. Fixed a potential infinite loop in the PEF loader and made improvements to OMF parsing. (GP-7071) +* _Importer_. Providing more efficient parsing of System Object Model (SOM) binaries. (GP-7123) +* _Importer_. Providing more efficient parsing of Motorola Hex files. (GP-7124) +* _Importer:ELF_. Corrected an issue found with ELF dynamic PLTGOT processing, in the absence of section headers, which could cause the last PLT to be skipped. (GP-7056) +* _Importer:ELF_. Corrected ELF Importer regression with Ghidra 12.1.2 which could fail when processing dynamic GNU Hashtable and symbol table. (GP-7061, Issue #9369) +* _Importer:Mach-O_. Fixed an `IndexOutOfBoundsException` in the Mach-O loader that could occur when importing a binary with a `LC_DYSYMTAB` load command but having a missing or empty `LC_SYMTAB` load command. (GP-7079, Issue #9399) +* _Importer:PE_. Fixed unsigned PE export ordinal-table indexes. (GP-7085, Issue #9396, #9397) +* _Importer:PE_. Improved the handling of JDOM attribute errors in the PE `LibraryLookupTable`. (GP-7087, Issue #6288) +* _Listing_. Fixed an `IllegalArgumentException` that occurred when trying to perform __Copy Special__ in the Listing with a program name that contains the exclamation mark (`!`) character. (GP-7055, Issue #9362) +* _PDB_. Fixed a memory-consumption issue that could occur with a malformed PDB directory stream. (GP-6971) +* _Processors_. Added support for RH850G3 instructions in the V850 language module. (GP-2907, Issue #4788) +* _Processors_. Fixed register operand for ARM M-profile `msr apsr` instruction operand encoding. (GP-5206, Issue #6597, #6598) +* _Processors_. Added several missing x86 instructions. (GP-5780) +* _Processors_. Added semantics for several x86 AVX instructions. (GP-6061, Issue #9184, #9197) +* _Processors_. Added CPU32 variant for the M68000 processor module. (GP-6186, Issue #1244, #2617, #8463, #9084) +* _Processors_. Corrected operand sizes for AARCH64 `stlrb` and `stlrh` instructions. (GP-6620, Issue #6468, #9043) +* _Processors_. Corrected disassembly of HCS12 `BRN` instruction. (GP-6642, Issue #9001) +* _Processors_. Fixed an issue with a missing return address for the SuperH4 `bsr` instruction. (GP-6699) +* _Processors_. Corrected x86 logic for setting the `OF` flag for `SHR`, `RCL`, and `RCR` instructions. (GP-6767, Issue #9330) +* _Processors_. Corrected Tricore `subc` carry flag usage. (GP-6769) +* _Processors_. Corrected carry flag calculation for the MCS-96 `CMPL` instruction. (GP-6770) +* _Processors_. Added missing x86 GFNI instructions. (GP-6818) +* _Processors_. Corrected handling of RISC-V 16-bit operands. (GP-6876) +* _Processors_. Fixed RISC-V emulation of `div` and `rem` instructions when divisor is 0. (GP-6909, Issue #6508, #9225, #9235) +* _Processors_. Added PowerPC v3.0B, v3.0C instructions. (GP-6914) +* _Processors_. Corrected interrupt mask size in ARM `mrs` for the `IPSR` system status register. (GP-6931, Issue #9251, #9252) +* _Processors_. Fixed an issue with x86 legacy instructions using a `REX` prefix to read AVX-512 registers. (GP-6937, Issue #9256) +* _Processors_. Added instruction index file for the SuperH processor. (GP-6964, Issue #9278) +* _Processors_. Fixed stack parameter offset for e500mc default calling convention. (GP-6968, Issue #9089) +* _Processors_. Fixed an issue with the M68000 `movem.w` instruction incrementing by 4 instead of 2. (GP-6983, Issue #8824) +* _Processors_. Corrected x86 `rex chg eax, eax` to correctly disassemble to `nop`. (GP-7015, Issue #9327) +* _Processors_. Corrected x86 `vpextrw` to correctly disassemble when `VEX.W=1`. (GP-7016, Issue #9323) +* _Processors_. Corrected x86 `PINSRW`, `VPEXTRB`, and `VPEXTRD` intructions to use the correct masking of immediate byte for masks. (GP-7017, Issue #9328) +* _Processors_. Corrected x86 `MOV` instruction to use 32-bit register operands when moving from segment registers. (GP-7018, Issue #9326) +* _Processors_. Corrected x86 `pslld` instruction to use correct shift count for upper word. (GP-7019, Issue #9329) +* _Processors_. Corrected AARCH64 NEON instructions which did not correctly zero-extend scalar results. (GP-7040, Issue #9277) +* _Processors_. Corrected encoding for ARM `sev.w` instruction. (GP-7065, Issue #9371) +* _Processors_. Corrected MIPS 16e language variants to use the correct `variant` tag in the ldefs file. (GP-7133, Issue #9432) +* _Testing_. Fixed pcodetest framework to correctly honor the `build_exe` config option. (GP-7067, Issue #9374) +* _Tests_. Patched the pcodetest builder to remove the use of `os.system()`. (GP-7007, Issue #9309) + +### Notable API Changes +* _Debugger:Agents_. (GP-6934) `ShellUtils.generateLine` now requires a `Shell` argument, identifying the applicable shell. `ShellUtils.generateArgument` has been replaced by `Shell.generateArgument`. +* _Decompiler_. (GP-6892) Added `Encoder.writeOpcode` method, specifically for opcode ordinals. +* _Importer:ELF_. (GP-7057) Revised `ElfSymbol.isExternal() ` to disregard symbol type, `st_value`, and `st_size`, which were previously being considered. + # Ghidra 12.1.2 Change History (June 2026) ### Improvements From 8b4c91d4d5bd1549622bfbade0df199585b98365 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Fri, 14 Aug 2026 14:02:49 -0400 Subject: [PATCH 111/111] GP-0: Preserve file timestamps in Gradle --- build.gradle | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/build.gradle b/build.gradle index d460f7143e7..706d97f3e49 100644 --- a/build.gradle +++ b/build.gradle @@ -73,6 +73,15 @@ allprojects { } } +/********************************************************************************* + * Gradle 9+ by default gives every archived file a timestamp of Feb 1 1980. + * We prefer to preserve the real timestamp of each file in the release. + **********************************************************************************/ +allprojects { + tasks.withType(AbstractArchiveTask).configureEach { + preserveFileTimestamps = true + } +} /********************************************************************************* * Use flat directory-style repository if flatRepo directory is present.