diff --git a/Ghidra/Extensions/SleighDevTools/certification.manifest b/Ghidra/Extensions/SleighDevTools/certification.manifest index 8c9c5acfcf..d82fb5b166 100644 --- a/Ghidra/Extensions/SleighDevTools/certification.manifest +++ b/Ghidra/Extensions/SleighDevTools/certification.manifest @@ -23,5 +23,6 @@ pcodetest/c_src/ParameterPassing2.test||GHIDRA||||END| pcodetest/c_src/ParameterPassing3.test||GHIDRA||||END| pcodetest/c_src/PointerManipulation.test||GHIDRA||||END| pcodetest/c_src/StructUnionManipulation.test||GHIDRA||||END| +pcodetest/c_src/arm/arm.test||GHIDRA||||END| pcodetest/c_src/misc.test||GHIDRA||||END| pcodetest/c_src/msp430x.ld||GHIDRA||||END| diff --git a/Ghidra/Extensions/SleighDevTools/pcodetest/build.py b/Ghidra/Extensions/SleighDevTools/pcodetest/build.py index ee663bb3ea..eb6adba116 100644 --- a/Ghidra/Extensions/SleighDevTools/pcodetest/build.py +++ b/Ghidra/Extensions/SleighDevTools/pcodetest/build.py @@ -112,10 +112,8 @@ class BuildUtil(object): try: if not os.path.isdir(dname): self.makedirs(dname) - if os.path.isfile(fname): + else: self.copy(fname, dname, verbose=True) - elif os.path.isdir(fname): - self.copy(fname, dname, dir=True, verbose=True) except IOError as e: self.log_err('Error occurred exporting %s to %s' % (fname, dname)) self.log_err("Unexpected error: %s" % str(e)) @@ -129,9 +127,9 @@ class BuildUtil(object): try: os.makedirs(dir) except: pass - # copy a file to a directory - def copy(self, fname, dname, verbose=True, dir=False): - if not dir: + # copy a file/directory to a directory + def copy(self, fname, dname, verbose=True): + if not os.path.isdir(fname): if verbose: self.log_info('cp -av %s %s' % (fname, dname)) shutil.copy(fname, dname) else: diff --git a/Ghidra/Extensions/SleighDevTools/pcodetest/c_src/arm/arm.test b/Ghidra/Extensions/SleighDevTools/pcodetest/c_src/arm/arm.test new file mode 100644 index 0000000000..d659d7c86a --- /dev/null +++ b/Ghidra/Extensions/SleighDevTools/pcodetest/c_src/arm/arm.test @@ -0,0 +1,43 @@ +#include "pcode_test.h" + +/* This test checks the correct carry flag handling for adc instructions */ +TEST arm_adc_Main() +{ + extern u4 u4_adc_carry(u4 a, u4 b, u1 carry); + extern u4 u4_adc_overflow(u4 a, u4 b, u1 carry); + ASSERTU1(u4_adc_carry(0xffffffff, 0, 1), 1); + ASSERTU1(u4_adc_carry(0, 0xffffffff, 1), 1); + ASSERTU1(u4_adc_carry(1, 0xffffffff, 1), 1); + ASSERTU1(u4_adc_carry(0xffffffff, 1, 1), 1); + ASSERTU1(u4_adc_carry(1, 0xfffffffe, 1), 1); + ASSERTU1(u4_adc_carry(0xfffffffe, 1, 1), 1); + ASSERTU1(u4_adc_carry(0xffffffff, 0, 0), 0); + ASSERTU1(u4_adc_carry(0, 0xffffffff, 0), 0); + ASSERTU1(u4_adc_carry(1, 0xffffffff, 0), 1); + ASSERTU1(u4_adc_carry(0xffffffff, 1, 0), 1); + ASSERTU1(u4_adc_carry(1, 0xfffffffe, 0), 0); + ASSERTU1(u4_adc_carry(0xfffffffe, 1, 0), 0); + ASSERTU1(u4_adc_overflow(0x80000000, 0xffffffff, 1), 0); +} + +/* This test checks the correct carry flag handling for sbc instructions */ +TEST arm_sbc_Main() +{ + extern u4 u4_sbc_carry(i4 a, i4 b, u1 carry); + ASSERTU1(u4_sbc_carry(-1, 0, 0), 1); + ASSERTU1(u4_sbc_carry(0, 0x7fffffff, 0), 0); + ASSERTU1(u4_sbc_carry(-1, 0x7fffffff, 0), 1); + ASSERTU1(u4_sbc_carry(-1, 1, 1), 1); + ASSERTU1(u4_sbc_carry(1, 1, 1), 1); + ASSERTU1(u4_sbc_carry(-1, 1, 1), 1); + + extern i4 i4_sbc(i4 a, i4 b, u1 carry); + ASSERTU1(i4_sbc(0, 0, 0), -1); + ASSERTU1(i4_sbc(-1, 0, 0), -2); + ASSERTU1(i4_sbc(0, 0, 1), 0); + ASSERTU1(i4_sbc(0, 1, 1), -1); + ASSERTU1(i4_sbc(2, 1, 0), 0); +} + + +MAIN asm_main() { } \ No newline at end of file diff --git a/Ghidra/Extensions/SleighDevTools/pcodetest/c_src/arm/arm_BODY.c b/Ghidra/Extensions/SleighDevTools/pcodetest/c_src/arm/arm_BODY.c new file mode 100644 index 0000000000..35c5c44803 --- /dev/null +++ b/Ghidra/Extensions/SleighDevTools/pcodetest/c_src/arm/arm_BODY.c @@ -0,0 +1,149 @@ +/* ### + * 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. + */ +#include "pcode_test.h" + +u4 u4_adc_carry(u4 a, u4 b, u1 carry) +{ + u4 res = 0; + u4 x = 0xffffffff; + u4 y = 1; + if (carry == 1) { + __asm__( + ".syntax unified\n" + "adds %[x_res],%[x],%[y]\n" /* set the carry flag */ + : [x_res] "=r" (x) + : [x] "r" (x), [y] "r" (y) + ); + } else { + __asm__( + ".syntax unified\n" + "adds %[x_res],%[y],%[y]\n" /* clear the carry flag */ + : [x_res] "=r" (x) + : [y] "r" (y) + ); + } + __asm__( + ".syntax unified\n" + "adcs %[input_a],%[input_a],%[input_b]\n" + "bcc adc_nocarry\n" + "ldr %[result], =0x1\n" + "b adc_end\n" + "adc_nocarry:\n" + "ldr %[result], =0x0\n" + "adc_end:\n" + : [result] "=r" (res) + : [input_a] "r" (a), [input_b] "r" (b) + ); + return res; +} + +u4 u4_adc_overflow(u4 a, u4 b, u1 carry) +{ + u4 res = 0; + u4 x = 0xffffffff; + u4 y = 1; + if (carry == 1) { + __asm__( + ".syntax unified\n" + "adds %[x_res],%[x],%[y]\n" /* set the carry flag */ + : [x_res] "=r" (x) + : [x] "r" (x), [y] "r" (y) + ); + } else { + __asm__( + ".syntax unified\n" + "adds %[x_res],%[y],%[y]\n" /* clear the carry flag */ + : [x_res] "=r" (x) + : [y] "r" (y) + ); + } + __asm__( + ".syntax unified\n" + "adcs %[input_a],%[input_a],%[input_b], lsr #1\n" + "bvc adc_noover\n" + "ldr %[result], =0x1\n" + "b adc_o_end\n" + "adc_noover:\n" + "ldr %[result], =0x0\n" + "adc_o_end:\n" + : [result] "=r" (res) + : [input_a] "r" (a), [input_b] "r" (b) + ); + return res; +} + +u4 u4_sbc_carry(i4 a, i4 b, u1 carry) +{ + u4 res = 0; + u4 x = 0xffffffff; + u4 y = 1; + if (carry == 1) { + __asm__( + ".syntax unified\n" + "adds %[x_res],%[x],%[y]\n" /* set the carry flag */ + : [x_res] "=r" (x) + : [x] "r" (x), [y] "r" (y) + ); + } else { + __asm__( + ".syntax unified\n" + "adds %[x_res],%[y],%[y]\n" /* clear the carry flag */ + : [x_res] "=r" (x) + : [y] "r" (y) + ); + } + __asm__( + ".syntax unified\n" + "sbcs %[input_a],%[input_a],%[input_b]\n" + "bcc sbc_nocarry\n" + "ldr %[result], =0x1\n" + "b sbc_end\n" + "sbc_nocarry:\n" + "ldr %[result], =0x0\n" + "sbc_end:\n" + : [result] "=r" (res) + : [input_a] "r" (a), [input_b] "r" (b) + ); + return res; +} + +i4 i4_sbc(i4 a, i4 b, u1 carry) +{ + u4 res = 0; + u4 x = 0xffffffff; + u4 y = 1; + if (carry == 1) { + __asm__( + ".syntax unified\n" + "adds %[x_res],%[x],%[y]\n" /* set the carry flag */ + : [x_res] "=r" (x) + : [x] "r" (x), [y] "r" (y) + ); + } else { + __asm__( + ".syntax unified\n" + "adds %[x_res],%[y],%[y]\n" /* clear the carry flag */ + : [x_res] "=r" (x) + : [y] "r" (y) + ); + } + __asm__( + "sbc %[result],%[input_a],%[input_b]\n" + : [result] "=r" (res) + : [input_a] "r" (a), [input_b] "r" (b) + ); + return res; +} diff --git a/Ghidra/Extensions/SleighDevTools/pcodetest/defaults.py b/Ghidra/Extensions/SleighDevTools/pcodetest/defaults.py index 1505aa8e20..8bc78ab34e 100644 --- a/Ghidra/Extensions/SleighDevTools/pcodetest/defaults.py +++ b/Ghidra/Extensions/SleighDevTools/pcodetest/defaults.py @@ -49,4 +49,5 @@ PCodeTest.defaults.readelf_exe = 'bin/readelf' PCodeTest.defaults.nm_exe = 'bin/nm' PCodeTest.defaults.strip_exe = 'bin/strip' PCodeTest.defaults.variants = {'O0': '-O0', 'O3': '-O3'} +PCodeTest.defaults.proc_test = '' diff --git a/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py b/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py index e061547313..ca300da20c 100644 --- a/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py +++ b/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py @@ -24,6 +24,7 @@ PCodeTest({ 'toolchain': 'ARM/arm-eabi', 'language_id': 'ARM:LE:32:v7', 'ccflags': '-L %(toolchain_dir)s/lib/gcc/arm-eabi/%(gcc_version)s -lgcc', + 'proc_test': 'arm', }) PCodeTest({ @@ -34,6 +35,7 @@ PCodeTest({ 'toolchain': 'ARM/armbe-eabi', 'language_id': 'ARM:BE:32:v7', 'ccflags': '-mbig-endian -L %(toolchain_dir)s/lib/gcc/arm-eabi/%(gcc_version)s -lgcc', + 'proc_test': 'arm', 'has_float': 0, 'has_double': 0, 'has_longlong': 0, @@ -45,6 +47,7 @@ PCodeTest({ 'toolchain': 'ARM/arm-eabi', 'ccflags': '-mcpu=arm2 -L %(toolchain_dir)s/lib/gcc/arm-eabi/%(gcc_version)s -lgcc', 'language_id': 'ARM:LE:32:v7', + 'proc_test': 'arm', }) PCodeTest({ @@ -62,6 +65,7 @@ PCodeTest({ 'toolchain': 'ARM/arm-eabi', 'ccflags': '-mcpu=arm7 -L %(toolchain_dir)s/lib/gcc/arm-eabi/%(gcc_version)s -lgcc', 'language_id': 'ARM:LE:32:v7', + 'proc_test': 'arm', }) PCodeTest({ @@ -69,6 +73,7 @@ PCodeTest({ 'toolchain': 'ARM/arm-eabi', 'ccflags': '-mcpu=arm8 -L %(toolchain_dir)s/lib/gcc/arm-eabi/%(gcc_version)s -lgcc', 'language_id': 'ARM:LE:32:v7', + 'proc_test': 'arm', }) PCodeTest({ @@ -76,6 +81,7 @@ PCodeTest({ 'toolchain': 'ARM/arm-eabi', 'ccflags': '-mcpu=arm9 -L %(toolchain_dir)s/lib/gcc/arm-eabi/%(gcc_version)s -lgcc', 'language_id': 'ARM:LE:32:v7', + 'proc_test': 'arm', }) PCodeTest({ @@ -86,6 +92,7 @@ PCodeTest({ 'toolchain': 'ARM/arm-eabi', 'ccflags': '-mcpu=arm10e -L %(toolchain_dir)s/lib/gcc/arm-eabi/%(gcc_version)s -lgcc', 'language_id': 'ARM:LE:32:v7', + 'proc_test': 'arm', }) PCodeTest({ @@ -96,6 +103,7 @@ PCodeTest({ 'toolchain': 'ARM/arm-eabi', 'ccflags': '-mthumb -L %(toolchain_dir)s/lib/gcc/arm-eabi/%(gcc_version)s/thumb -lgcc', 'language_id': 'ARM:LE:32:v7', + 'proc_test': 'arm', }) PCodeTest({ @@ -104,6 +112,7 @@ PCodeTest({ 'toolchain': 'ARM/armbe-eabi', 'ccflags': '-mthumb -mbig-endian -L %(toolchain_dir)s/lib/gcc/armbe-eabi/%(gcc_version)s/thumb -lgcc', 'language_id': 'ARM:BE:32:v7', + 'proc_test': 'arm', 'has_float': 0, 'has_double': 0, 'has_longlong': 0, @@ -117,6 +126,7 @@ PCodeTest({ 'toolchain': 'ARM/arm-eabi', 'ccflags': '-mthumb -mcpu=cortex-a8 -mfloat-abi=softfp -L %(toolchain_dir)s/lib/gcc/arm-eabi/%(gcc_version)s/thumb -lgcc', 'language_id': 'ARM:LE:32:v7', + 'proc_test': 'arm', }) PCodeTest({ diff --git a/Ghidra/Extensions/SleighDevTools/pcodetest/pcodetest.py b/Ghidra/Extensions/SleighDevTools/pcodetest/pcodetest.py index 628a8759a4..d3409e212d 100644 --- a/Ghidra/Extensions/SleighDevTools/pcodetest/pcodetest.py +++ b/Ghidra/Extensions/SleighDevTools/pcodetest/pcodetest.py @@ -103,7 +103,10 @@ class PCodeTestBuild(BuildUtil): # Get a list of strings to filter input files available_files = sorted(glob.glob(self.config.format('%(pcodetest_src)s/*'))) - + if self.config.proc_test: + available_files.extend(sorted(glob.glob(self.config.format('%(pcodetest_src)s/%(proc_test)s/*')))) + + available_files = [x for x in available_files if not os.path.isdir(x) ] # skip any? skip_files = self.config.skip_files if len(skip_files) > 0: diff --git a/Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc b/Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc index bb4ff1c9ea..e68be097dc 100644 --- a/Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc +++ b/Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc @@ -213,14 +213,14 @@ macro th_addflags(op1,op2) { tmpOV = scarry(op1,op2); } -#See Section 2-13, "Overflow Detection", of Hacker's Delight (2nd ed) +#See ARM Architecture reference section "Pseudocode details of addition and subtraction" macro th_add_with_carry_flags(op1,op2){ - tmpCY = ((CY == 0) && carry(op1,op2)) || ((CY == 1) && (op1 >= op1 + op2 + 1:4)); - local total= op1 + op2 + zext(CY); - local sign_total = (total >> 31) != 0; - local sign_op1 = (op1 >> 31) != 0; - local sign_op2 = (op2 >> 31) != 0; - tmpOV = (sign_op1 == sign_op2) && (sign_total != sign_op1); +local CYz = zext(CY); +local CYa = carry( op1, op2 ); +local OVa = scarry( op1, op2 ); +local result = op1 + op2; +tmpCY = CYa || carry( result, CYz ); +tmpOV = OVa ^^ scarry( result, CYz ); } macro th_test_flags(result){ diff --git a/Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc b/Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc index 9b467f9089..138f30ccd3 100644 --- a/Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc +++ b/Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc @@ -1876,14 +1876,14 @@ SetMode: "#"^31 is c0004=0x1f { setSystemMode(); } # ################################################# -#See Section 2-13, "Overflow Detection", of Hacker's Delight (2nd ed) +#See ARM Architecture reference section "Pseudocode details of addition and subtraction" macro add_with_carry_flags(op1,op2){ - tmpCY = ((CY == 0) && carry(op1,op2)) || ((CY == 1) && (op1 >= op1 + op2 + 1:4)); - local total= op1 + op2 + zext(CY); - local sign_total = (total >> 31) != 0; - local sign_op1 = (op1 >> 31) != 0; - local sign_op2 = (op2 >> 31) != 0; - tmpOV = (sign_op1 == sign_op2) && (sign_total != sign_op1); +local CYz = zext(CY); +local CYa = carry( op1, op2 ); +local OVa = scarry( op1, op2 ); +local result = op1 + op2; +tmpCY = CYa || carry( result, CYz ); +tmpOV = OVa ^^ scarry( result, CYz ); } :adc^COND^SBIT_CZNO Rd,rn,shift1 is $(AMODE) & COND & c2124=5 & SBIT_CZNO & rn & Rd & c2627=0 & shift1