From 1e82a772c5aea41d333904a3e5e0640b5af825a4 Mon Sep 17 00:00:00 2001 From: James <49045138+ghidracadabra@users.noreply.github.com> Date: Thu, 28 Dec 2023 13:57:10 +0000 Subject: [PATCH] GP-4152 msp430 improvements --- .../SleighDevTools/pcodetest/pcode_defs.py | 24 ++- .../java/ghidra/program/model/mem/Memory.java | 6 +- Ghidra/Processors/TI_MSP430/build.gradle | 7 +- .../TI_MSP430/data/languages/TI430X.sinc | 138 ++++++++----- .../TI_MSP430/data/languages/TI_MSP430.ldefs | 4 +- .../data/languages/ti_msp430.opinion | 6 +- .../TI_MSP430X_ElfRelocationConstants.java | 53 +++++ .../TI_MSP430X_ElfRelocationHandler.java | 185 ++++++++++++++++++ .../TI_MSP430_ElfRelocationConstants.java | 35 ++++ .../TI_MSP430_ElfRelocationHandler.java | 104 ++++++++++ .../processors/MSP430X_O0_EmulatorTest.java | 49 +++++ .../processors/MSP430X_O3_EmulatorTest.java | 49 +++++ .../processors/MSP430_O0_EmulatorTest.java | 49 +++++ .../processors/MSP430_O3_EmulatorTest.java | 49 +++++ 14 files changed, 692 insertions(+), 66 deletions(-) create mode 100644 Ghidra/Processors/TI_MSP430/src/main/java/ghidra/app/util/bin/format/elf/relocation/TI_MSP430X_ElfRelocationConstants.java create mode 100644 Ghidra/Processors/TI_MSP430/src/main/java/ghidra/app/util/bin/format/elf/relocation/TI_MSP430X_ElfRelocationHandler.java create mode 100644 Ghidra/Processors/TI_MSP430/src/main/java/ghidra/app/util/bin/format/elf/relocation/TI_MSP430_ElfRelocationConstants.java create mode 100644 Ghidra/Processors/TI_MSP430/src/main/java/ghidra/app/util/bin/format/elf/relocation/TI_MSP430_ElfRelocationHandler.java create mode 100644 Ghidra/Processors/TI_MSP430/src/test.processors/java/ghidra/test/processors/MSP430X_O0_EmulatorTest.java create mode 100644 Ghidra/Processors/TI_MSP430/src/test.processors/java/ghidra/test/processors/MSP430X_O3_EmulatorTest.java create mode 100644 Ghidra/Processors/TI_MSP430/src/test.processors/java/ghidra/test/processors/MSP430_O0_EmulatorTest.java create mode 100644 Ghidra/Processors/TI_MSP430/src/test.processors/java/ghidra/test/processors/MSP430_O3_EmulatorTest.java diff --git a/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py b/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py index b15ac99879..dd5dc2db57 100644 --- a/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py +++ b/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py @@ -460,16 +460,30 @@ PCodeTest({ PCodeTest({ 'name': 'msp430x', 'build_all': 1, - 'toolchain': 'TI/msp430-elf', - 'ccflags': '-g -mmcu=msp430x -mlarge -mhwmult=none -fno-builtin -Wl,-T,msp430x.ld -L %(toolchain_dir)s/lib/gcc/msp430-elf/%(gcc_version)s/large/ -lgcc -lmul_none', + 'toolchain': 'TI/msp430-gcc-9.3.1.11_linux64', + 'ccflags': '-g -mcpu=msp430x -mlarge -mhwmult=none -fno-builtin -Wl,-T,msp430x.ld -L %(toolchain_dir)s/lib/gcc/msp430-elf/%(gcc_version)s/large/ -lgcc -lmul_none', 'language_id': 'TI_MSP430X:LE:32:default', 'processor': 'TI', 'architecture_test': 'MSP430X', - 'has_float': 0, - 'has_double': 0, + 'has_float': 1, + 'has_double': 1, + 'has_longlong': 0, + 'small_build': 1, + 'skip_files': ['PointerManipulation.test', 'misc.out'], +}) + +PCodeTest({ + 'name': 'msp430', + 'build_all': 1, + 'toolchain': 'TI/msp430-gcc-9.3.1.11_linux64', + 'ccflags': '-g -mcpu=msp430 -fno-builtin -mhwmult=none -lgcc -lmul_none', + 'language_id': 'TI_MSP430:LE:16:default', + 'processor': 'TI', + 'architecture_test': 'MSP430', + 'has_float': 1, + 'has_double': 1, 'has_longlong': 0, 'small_build': 1, - 'skip_files': ['PointerManipulation.test', 'misc.test'], }) PCodeTest({ diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/Memory.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/Memory.java index 7037ba94fa..bbb4afc6f7 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/Memory.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/Memory.java @@ -836,7 +836,7 @@ public interface Memory extends AddressSetView { throws MemoryAccessException; /** - * Write short at addr in big endian order. + * Write short at addr in default endian order. * * @param addr the Address of the short. * @param value the data to write. @@ -857,7 +857,7 @@ public interface Memory extends AddressSetView { public void setShort(Address addr, short value, boolean bigEndian) throws MemoryAccessException; /** - * Write int at addr. + * Write int at addr in the default endian order. * * @param addr the Address of the int. * @param value the data to write. @@ -879,7 +879,7 @@ public interface Memory extends AddressSetView { public void setInt(Address addr, int value, boolean bigEndian) throws MemoryAccessException; /** - * Write long at addr. + * Write long at addr in the default endian order. * * @param addr the Address of the long. * @param value the data to write. diff --git a/Ghidra/Processors/TI_MSP430/build.gradle b/Ghidra/Processors/TI_MSP430/build.gradle index 27bb5d2cbe..0b91772e57 100644 --- a/Ghidra/Processors/TI_MSP430/build.gradle +++ b/Ghidra/Processors/TI_MSP430/build.gradle @@ -14,8 +14,13 @@ * limitations under the License. */ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" +apply from: "$rootProject.projectDir/gradle/javaProject.gradle" +apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" +apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle" apply from: "$rootProject.projectDir/gradle/processorProject.gradle" apply plugin: 'eclipse' - eclipse.project.name = 'Processors TI_MSP430' +dependencies { + api project(':Base') +} diff --git a/Ghidra/Processors/TI_MSP430/data/languages/TI430X.sinc b/Ghidra/Processors/TI_MSP430/data/languages/TI430X.sinc index bcfb538249..80054727b0 100644 --- a/Ghidra/Processors/TI_MSP430/data/languages/TI430X.sinc +++ b/Ghidra/Processors/TI_MSP430/data/languages/TI430X.sinc @@ -5,7 +5,8 @@ # The original way of using sub-tables to breakout the addressing modes does not # work for these instructions -:^instruction is opext_11_5=0x3 & ctx_haveext=0 & dest_0_4 & src_ext & al & zc & ad; instruction [ ctx_haveext=1; ctx_ctregdest=dest_0_4; ctx_regsrc=src_ext; ctx_al=al; ctx_num=ad; ] {$(CARRY)=$(CARRY) * (zc:1 == 0); build instruction;} +#constructor recognizing the presence of an extension word +:^instruction is opext_11_5=0x3 & ctx_haveext=0 & dest_0_4 & src_ext & al & zc & ad; instruction [ ctx_haveext=1; ctx_ctregdest=dest_0_4; ctx_regsrc=src_ext; ctx_al=al; ctx_num=ad; ctx_zc=zc;] { build instruction;} #:^instruction is ctx_haveext=1 & instruction & as=1 & src_8_4=3 [ctx_haveext=2;] {build instruction;} @@ -291,6 +292,17 @@ XDEST_A_AD: "&"^val is dest=0x2 & ad=0x1 & bow=0x1 & as=0x1 & ((src16_8_ XDEST_A_AD: "&"^val is dest=0x2 & ad=0x1 & bow=0x1 & as=0x3 & src16_8_4=0x0 ; indexExtWord16_0_16 ; indexExt2Word16_0_16 [val=(ctx_ctregdest << 16) | indexExt2Word16_0_16; ] {export *:$(REG_SIZE) val; } # Absolute +#Use repeat_carry with a build directive at the beginning of a RPT loop + +#use existing value of carry bit +repeat_carry: is ctx_zc = 0 {} + +#in this case the repeated instruction uses 0 as the value of the carry bit +#after repeated instruction executes, value of carry bit is defined by the result of +#last operation, so building this constructor at the beginning of RPT loop can accurately +#model the semantics +repeat_carry: is ctx_zc = 1 {$(CARRY) = 0;} + macro setaddflags(ans, in1, in2) { tmp1:$(REG_SIZE) = zext(in1[0,20]); @@ -310,7 +322,6 @@ macro setsubflags(ans, in1, in2) $(OVERFLOW) = ((in1 s< 0) & (in2 s>= 0) & (ans s< 0)) | ((in1 s>= 0) & (in2 s< 0) & (ans s>= 0)); $(SIGN) = (ans s< 0); $(ZERO) = (ans == 0); - } ################# @@ -1115,7 +1126,7 @@ POPWR0: is ctx_mreg=0x0 & POPWR1 [ctx_count=ctx_count-1; ctx_mreg=ctx_mreg+ call [PC]; } -:CALLA imms_0_16^"(PC)" is ctx_haveext=0 & op16_8_8=0x13 & op16_4_4=0x9 & imms_0_16 { +:CALLA imms_0_16^"(PC)" is ctx_haveext=0 & op16_8_8=0x13 & op16_4_4=0x9 ; imms_0_16 { SP = SP - 0x4; *:4 SP = inst_next; tmp:$(REG_SIZE) = inst_start + sext(imms_0_16:2); @@ -1275,8 +1286,9 @@ macro wzero(full, word) # ############################# # Repeat enabled -:ADCX.B DST8_0_4 is ctx_haveext=4 & op16_12_4=0x6 & src16_8_4=0x3 & as=0x0 & bow=1 & ctx_al=1 & postIncrementStore & DST8_0_4 & reg_Direct16_0_4 { +:ADCX.B DST8_0_4 is ctx_haveext=4 & op16_12_4=0x6 & src16_8_4=0x3 & as=0x0 & bow=1 & ctx_al=1 & postIncrementStore & DST8_0_4 & reg_Direct16_0_4 & repeat_carry { + build repeat_carry; # Operation Flags... tmp_carry:1 = carry(DST8_0_4,$(CARRY)); #C Flag $(OVERFLOW) = scarry(DST8_0_4,$(CARRY)); #V Flag @@ -1293,8 +1305,9 @@ macro wzero(full, word) goto ; } -:ADCX.W DST16_0_4 is ctx_haveext=4 & op16_12_4=0x6 & src16_8_4=0x3 & as=0x0 & bow=0 & ctx_al=1 & postIncrementStore & DST16_0_4 & reg_Direct16_0_4 { +:ADCX.W DST16_0_4 is ctx_haveext=4 & op16_12_4=0x6 & src16_8_4=0x3 & as=0x0 & bow=0 & ctx_al=1 & postIncrementStore & DST16_0_4 & reg_Direct16_0_4 & repeat_carry { + build repeat_carry; # Operation Flags... tmp_carry:1 = carry(DST16_0_4,zext($(CARRY))); #C Flag $(OVERFLOW) = scarry(DST16_0_4,zext($(CARRY))); #V Flag @@ -1311,8 +1324,9 @@ macro wzero(full, word) goto ; } -:ADCX.A dest_0_4 is ctx_haveext=4 & op16_12_4=0x6 & src16_8_4=0x3 & as=0x0 & bow=1 & ctx_al=0 & postIncrementStore & dest_0_4 { +:ADCX.A dest_0_4 is ctx_haveext=4 & op16_12_4=0x6 & src16_8_4=0x3 & as=0x0 & bow=1 & ctx_al=0 & postIncrementStore & dest_0_4 & repeat_carry { + build repeat_carry; tmpd:$(REG_SIZE) = dest_0_4; tmpc:$(REG_SIZE) = zext($(CARRY)); tmp:$(REG_SIZE) = tmpc + dest_0_4; @@ -1372,8 +1386,9 @@ macro wzero(full, word) goto ; } -:ADDCX.B XRSRC_B_AS, DST8_0_4 is ctx_haveext=4 & op16_12_4=0x6 & bow=1 & ctx_al=1 & postIncrementStore & XRSRC_B_AS & DST8_0_4 & reg_Direct16_0_4 { +:ADDCX.B XRSRC_B_AS, DST8_0_4 is ctx_haveext=4 & op16_12_4=0x6 & bow=1 & ctx_al=1 & postIncrementStore & XRSRC_B_AS & DST8_0_4 & reg_Direct16_0_4 & repeat_carry { + build repeat_carry; # Operation Flags... tmp_carry:1 = (carry(XRSRC_B_AS, $(CARRY)) || carry(DST8_0_4,XRSRC_B_AS + $(CARRY))); #C Flag $(OVERFLOW) = (scarry(XRSRC_B_AS, $(CARRY)) || scarry(DST8_0_4,XRSRC_B_AS + $(CARRY))); #V Flag @@ -1390,8 +1405,9 @@ macro wzero(full, word) goto ; } -:ADDCX.W XRSRC_W_AS, DST16_0_4 is ctx_haveext=4 & op16_12_4=0x6 & bow=0 & ctx_al=1 & postIncrementStore & XRSRC_W_AS & DST16_0_4 & reg_Direct16_0_4 { +:ADDCX.W XRSRC_W_AS, DST16_0_4 is ctx_haveext=4 & op16_12_4=0x6 & bow=0 & ctx_al=1 & postIncrementStore & XRSRC_W_AS & DST16_0_4 & reg_Direct16_0_4 & repeat_carry { + build repeat_carry; # Operation Flags... tmp_carry:1 = (carry(XRSRC_W_AS,zext($(CARRY))) || carry(DST16_0_4,XRSRC_W_AS + zext($(CARRY)))); #C Flag $(OVERFLOW) = (scarry(XRSRC_W_AS,zext($(CARRY))) || scarry(DST16_0_4,XRSRC_W_AS + zext($(CARRY)))); #V Flag @@ -1408,8 +1424,9 @@ macro wzero(full, word) goto ; } -:ADDCX.A XRSRC_A_AS, dest_0_4 is ctx_haveext=4 & op16_12_4=0x6 & bow=1 & ctx_al=0 & postIncrementStore & XRSRC_A_AS & dest_0_4 { +:ADDCX.A XRSRC_A_AS, dest_0_4 is ctx_haveext=4 & op16_12_4=0x6 & bow=1 & ctx_al=0 & postIncrementStore & XRSRC_A_AS & dest_0_4 & repeat_carry { + build repeat_carry; tmpd:$(REG_SIZE) = dest_0_4; tmps:$(REG_SIZE) = XRSRC_A_AS + zext($(CARRY)); tmp:$(REG_SIZE) = tmps + dest_0_4; @@ -1661,12 +1678,12 @@ macro wzero(full, word) goto ; } -:DADCX.B DST8_0_4 is ctx_haveext=4 & op16_12_4=0xA & src16_8_4=0x3 & as=0x0 & bow=1 & ctx_al=1 & postIncrementStore & DST8_0_4 & reg_Direct16_0_4 { +:DADCX.B DST8_0_4 is ctx_haveext=4 & op16_12_4=0xA & src16_8_4=0x3 & as=0x0 & bow=1 & ctx_al=1 & postIncrementStore & DST8_0_4 & reg_Direct16_0_4 & repeat_carry { - # Operation Flags... - $(CARRY) = 0; # This should be overflow - # Operation... - DST8_0_4 = bcd_add(DST8_0_4); + build repeat_carry; + local temp:4 = zext(DST8_0_4); + DST8_0_4 = bcd_add(temp, $(CARRY)); + $(CARRY) = temp >= 0x99; bzero(reg_Direct16_0_4,DST8_0_4); # Result Flags... $(SIGN) = (DST8_0_4 s< 0x0); # S Flag @@ -1677,12 +1694,12 @@ macro wzero(full, word) goto ; } -:DADCX.W DST16_0_4 is ctx_haveext=4 & op16_12_4=0xA & src16_8_4=0x3 & as=0x0 & bow=0 & ctx_al=1 & postIncrementStore & DST16_0_4 & reg_Direct16_0_4 { +:DADCX.W DST16_0_4 is ctx_haveext=4 & op16_12_4=0xA & src16_8_4=0x3 & as=0x0 & bow=0 & ctx_al=1 & postIncrementStore & DST16_0_4 & reg_Direct16_0_4 & repeat_carry { - # Operation Flags... - $(CARRY) = 0; # Don't currently have BCD overflow op - # Operation... - DST16_0_4 = bcd_add(DST16_0_4); + build repeat_carry; + local temp:4 = zext(DST16_0_4); + DST16_0_4 = bcd_add(temp, $(CARRY)); + $(CARRY) = temp >= 0x9999; wzero(reg_Direct16_0_4,DST16_0_4); # Result Flags... $(SIGN) = (DST16_0_4 s< 0x0); # S Flag @@ -1693,12 +1710,12 @@ macro wzero(full, word) goto ; } -:DADCX.A dest_0_4 is ctx_haveext=4 & op16_12_4=0xA & src16_8_4=0x3 & as=0x0 & bow=1 & ctx_al=0 & postIncrementStore & dest_0_4 { +:DADCX.A dest_0_4 is ctx_haveext=4 & op16_12_4=0xA & src16_8_4=0x3 & as=0x0 & bow=1 & ctx_al=0 & postIncrementStore & dest_0_4 & repeat_carry { - # Operation Flags... - $(CARRY) = 0; # Don't currently have BCD overflow op - # Operation... - dest_0_4 = bcd_add(dest_0_4); + build repeat_carry; + local temp:4 = zext(dest_0_4); + dest_0_4 = bcd_add(temp, $(CARRY)); + $(CARRY) = temp >= 0x99999; dest_0_4 = sext(dest_0_4[0,20]); # Result Flags... $(SIGN) = (dest_0_4 s< 0x0); # S Flag @@ -1709,48 +1726,54 @@ macro wzero(full, word) goto ; } -:DADDX.B XRSRC_B_AS, DST8_0_4 is ctx_haveext=4 & op16_12_4=0xA & bow=1 & ctx_al=1 & postIncrementStore & XRSRC_B_AS & DST8_0_4 & reg_Direct16_0_4 { +:DADDX.B XRSRC_B_AS, DST8_0_4 is ctx_haveext=4 & op16_12_4=0xA & bow=1 & ctx_al=1 & postIncrementStore & XRSRC_B_AS & DST8_0_4 & reg_Direct16_0_4 & repeat_carry { - # Operation Flags... - $(CARRY) = 0; # This should be overflow - # Operation... - DST8_0_4 = bcd_add(XRSRC_B_AS,DST8_0_4); + build repeat_carry; + local temp_src:4 = zext(XRSRC_B_AS); + local temp_dest:4 = zext(DST8_0_4); + local temp_carry:4 = zext($(CARRY)); + DST8_0_4 = bcd_add(temp_src,temp_dest, temp_carry); bzero(reg_Direct16_0_4,DST8_0_4); # Result Flags... $(SIGN) = (DST8_0_4 s< 0x0); # S Flag $(ZERO) = (DST8_0_4 == 0x0); # Z Flag + $(CARRY) = (temp_src + temp_dest + temp_carry) > 0x99; build postIncrementStore; if (CNT == 0) goto inst_next; CNT = CNT - 1; goto ; } -:DADDX.W XRSRC_W_AS, DST16_0_4 is ctx_haveext=4 & op16_12_4=0xA & bow=0 & ctx_al=1 & postIncrementStore & XRSRC_W_AS & DST16_0_4 & reg_Direct16_0_4 { +:DADDX.W XRSRC_W_AS, DST16_0_4 is ctx_haveext=4 & op16_12_4=0xA & bow=0 & ctx_al=1 & postIncrementStore & XRSRC_W_AS & DST16_0_4 & reg_Direct16_0_4 & repeat_carry { - # Operation Flags... - $(CARRY) = 0; # Don't currently have BCD overflow op - # Operation... - DST16_0_4 = bcd_add(XRSRC_W_AS ,DST16_0_4); + build repeat_carry; + local temp_src:4 = zext(XRSRC_W_AS); + local temp_dest:4 = zext(DST16_0_4); + local temp_carry:4 = zext($(CARRY)); + DST16_0_4 = bcd_add(temp_src, temp_dest, temp_carry); wzero(reg_Direct16_0_4,DST16_0_4); # Result Flags... $(SIGN) = (DST16_0_4 s< 0x0); # S Flag $(ZERO) = (DST16_0_4 == 0x0); # Z Flag + $(CARRY) = (temp_src + temp_dest + temp_carry) > 0x9999; build postIncrementStore; if (CNT == 0) goto inst_next; CNT = CNT - 1; goto ; } -:DADDX.A XRSRC_A_AS, dest_0_4 is ctx_haveext=4 & op16_12_4=0xA & bow=1 & ctx_al=0 & postIncrementStore & XRSRC_A_AS & dest_0_4 { +:DADDX.A XRSRC_A_AS, dest_0_4 is ctx_haveext=4 & op16_12_4=0xA & bow=1 & ctx_al=0 & postIncrementStore & XRSRC_A_AS & dest_0_4 & repeat_carry { - # Operation Flags... - $(CARRY) = 0; # Don't currently have BCD overflow op - # Operation... - dest_0_4 = bcd_add(XRSRC_A_AS ,dest_0_4); + build repeat_carry; + local temp_src:4 = zext(XRSRC_A_AS); + local temp_dest:4 = zext(dest_0_4); + local temp_carry:4 = zext($(CARRY)); + dest_0_4 = bcd_add(temp_src, temp_dest, temp_carry); dest_0_4 = sext(dest_0_4[0,20]); # Result Flags... $(SIGN) = (dest_0_4 s< 0x0); # S Flag $(ZERO) = (dest_0_4 == 0x0); # Z Flag + $(CARRY) = (temp_src + temp_dest + temp_carry) > 0x99999; build postIncrementStore; if (CNT == 0) goto inst_next; CNT = CNT - 1; @@ -2103,8 +2126,9 @@ macro wzero(full, word) goto ; } -:RLCX.B DST8_0_4 is ctx_haveext=4 & op16_12_4=0x6 & bow=1 & ctx_al=1 & src_Direct16_8_4=dest_Direct16_0_4 & postIncrementStore & XRSRC_B_AS & DST8_0_4 & reg_Direct16_0_4 { +:RLCX.B DST8_0_4 is ctx_haveext=4 & op16_12_4=0x6 & bow=1 & ctx_al=1 & src_Direct16_8_4=dest_Direct16_0_4 & postIncrementStore & XRSRC_B_AS & DST8_0_4 & reg_Direct16_0_4 & repeat_carry { + build repeat_carry; # Operation Flags... tmp_carry:1 = (carry(DST8_0_4, $(CARRY)) || carry(DST8_0_4,DST8_0_4 + $(CARRY))); #C Flag $(OVERFLOW) = (scarry(DST8_0_4, $(CARRY)) || scarry(DST8_0_4,DST8_0_4 + $(CARRY))); #V Flag @@ -2121,8 +2145,9 @@ macro wzero(full, word) goto ; } -:RLCX.W DST16_0_4 is ctx_haveext=4 & op16_12_4=0x6 & bow=0 & ctx_al=1 & src_Direct16_8_4=dest_Direct16_0_4 & postIncrementStore & XRSRC_W_AS & DST16_0_4 & reg_Direct16_0_4 { +:RLCX.W DST16_0_4 is ctx_haveext=4 & op16_12_4=0x6 & bow=0 & ctx_al=1 & src_Direct16_8_4=dest_Direct16_0_4 & postIncrementStore & XRSRC_W_AS & DST16_0_4 & reg_Direct16_0_4 & repeat_carry { + build repeat_carry; # Operation Flags... tmp_carry:1 = (carry(DST16_0_4,zext($(CARRY))) || carry(DST16_0_4,DST16_0_4 + zext($(CARRY)))); #C Flag $(OVERFLOW) = (scarry(DST16_0_4,zext($(CARRY))) || scarry(DST16_0_4,DST16_0_4 + zext($(CARRY)))); #V Flag @@ -2139,8 +2164,9 @@ macro wzero(full, word) goto ; } -:RLCX.A dest_0_4 is ctx_haveext=4 & op16_12_4=0x6 & bow=1 & ctx_al=0 & src_Direct16_8_4=dest_Direct16_0_4 & postIncrementStore & XRSRC_A_AS & dest_0_4 { +:RLCX.A dest_0_4 is ctx_haveext=4 & op16_12_4=0x6 & bow=1 & ctx_al=0 & src_Direct16_8_4=dest_Direct16_0_4 & postIncrementStore & XRSRC_A_AS & dest_0_4 & repeat_carry { + build repeat_carry; tmpd:$(REG_SIZE) = dest_0_4; tmps:$(REG_SIZE) = dest_0_4 + zext($(CARRY)); tmp:$(REG_SIZE) = tmps + dest_0_4; @@ -2153,8 +2179,9 @@ macro wzero(full, word) goto ; } -:SBCX.B DST8_0_4 is ctx_haveext=4 & op16_12_4=0x7 & bow=1 & ctx_al=1 & src16_8_4=0x3 & as=0x0 & postIncrementStore & DST8_0_4 & reg_Direct16_0_4 { +:SBCX.B DST8_0_4 is ctx_haveext=4 & op16_12_4=0x7 & bow=1 & ctx_al=1 & src16_8_4=0x3 & as=0x0 & postIncrementStore & DST8_0_4 & reg_Direct16_0_4 & repeat_carry { + build repeat_carry; # Operation Flags... brw:1 = 1 - $(CARRY); $(CARRY) = (brw <= DST8_0_4); # Carry flag is NOT set if there is a borrow @@ -2171,8 +2198,9 @@ macro wzero(full, word) goto ; } -:SBCX.W DST16_0_4 is ctx_haveext=4 & op16_12_4=0x7 & bow=0 & ctx_al=1 & src16_8_4=0x3 & as=0x0 & postIncrementStore & DST16_0_4 & reg_Direct16_0_4 { +:SBCX.W DST16_0_4 is ctx_haveext=4 & op16_12_4=0x7 & bow=0 & ctx_al=1 & src16_8_4=0x3 & as=0x0 & postIncrementStore & DST16_0_4 & reg_Direct16_0_4 & repeat_carry { + build repeat_carry; # Operation Flags... brw:2 = 1 - zext( $(CARRY) ); $(CARRY) = (brw <= DST16_0_4); # Carry flag is NOT set if there is a borrow @@ -2189,8 +2217,9 @@ macro wzero(full, word) goto ; } -:SBCX.A dest_0_4 is ctx_haveext=4 & op16_12_4=0x7 & bow=1 & ctx_al=0 & src16_8_4=0x3 & as=0x0 & postIncrementStore & dest_0_4 { +:SBCX.A dest_0_4 is ctx_haveext=4 & op16_12_4=0x7 & bow=1 & ctx_al=0 & src16_8_4=0x3 & as=0x0 & postIncrementStore & dest_0_4 & repeat_carry { + build repeat_carry; brw:$(REG_SIZE) = 1 - zext( $(CARRY) ); tmpd:$(REG_SIZE) = dest_0_4; tmp:$(REG_SIZE) = dest_0_4 - brw; @@ -2203,8 +2232,9 @@ macro wzero(full, word) goto ; } -:SUBCX.B XRSRC_B_AS, DST8_0_4 is ctx_haveext=4 & op16_12_4=0x7 & bow=1 & ctx_al=1 & postIncrementStore & XRSRC_B_AS & DST8_0_4 & reg_Direct16_0_4 { +:SUBCX.B XRSRC_B_AS, DST8_0_4 is ctx_haveext=4 & op16_12_4=0x7 & bow=1 & ctx_al=1 & postIncrementStore & XRSRC_B_AS & DST8_0_4 & reg_Direct16_0_4 & repeat_carry { + build repeat_carry; # Operation Flags... brw:1 = 1 - $(CARRY); $(CARRY) = ((brw + XRSRC_B_AS) <= DST8_0_4); # Carry flag is NOT set if there is a borrow @@ -2221,8 +2251,9 @@ macro wzero(full, word) goto ; } -:SUBCX.W XRSRC_W_AS, DST16_0_4 is ctx_haveext=4 & op16_12_4=0x7 & bow=0 & ctx_al=1 & postIncrementStore & XRSRC_W_AS & DST16_0_4 & reg_Direct16_0_4 { +:SUBCX.W XRSRC_W_AS, DST16_0_4 is ctx_haveext=4 & op16_12_4=0x7 & bow=0 & ctx_al=1 & postIncrementStore & XRSRC_W_AS & DST16_0_4 & reg_Direct16_0_4 & repeat_carry { + build repeat_carry; # Operation Flags... brw:2 = 1 - zext( $(CARRY) ); $(CARRY) = ((brw + XRSRC_W_AS) <= DST16_0_4); # Carry flag is NOT set if there is a borrow @@ -2239,8 +2270,9 @@ macro wzero(full, word) goto ; } -:SUBCX.A XRSRC_A_AS, dest_0_4 is ctx_haveext=4 & op16_12_4=0x7 & bow=1 & ctx_al=0 & postIncrementStore & XRSRC_A_AS & dest_0_4 { +:SUBCX.A XRSRC_A_AS, dest_0_4 is ctx_haveext=4 & op16_12_4=0x7 & bow=1 & ctx_al=0 & postIncrementStore & XRSRC_A_AS & dest_0_4 & repeat_carry { + build repeat_carry; brw:$(REG_SIZE) = 1 - zext( $(CARRY) ); tmpd:$(REG_SIZE) = dest_0_4; tmps:$(REG_SIZE) = XRSRC_A_AS + brw; @@ -3222,9 +3254,11 @@ macro wzero(full, word) goto ; } -:RRCX.B XRREG_B_AS_DEST is ctx_haveext=4 & ctx_al=1 & op16_12_4=0x1 & op16_8_4=0x0 & bow=0x1 & postRegIncrement & XRREG_B_AS_DEST { +:RRCX.B XRREG_B_AS_DEST is ctx_haveext=4 & ctx_al=1 & ctx_zc & op16_12_4=0x1 & op16_8_4=0x0 & bow=0x1 & postRegIncrement & XRREG_B_AS_DEST & repeat_carry { # Operation Flags... + build repeat_carry; + $(CARRY) = $(CARRY) * ctx_zc; $(OVERFLOW) = ((XRREG_B_AS_DEST != 0x0) && ($(CARRY) == 0x1)); # V Flag # Operation... tmp:1 = $(CARRY); @@ -3239,8 +3273,9 @@ macro wzero(full, word) goto ; } -:RRCX.W XRREG_W_AS_DEST is ctx_haveext=4 & ctx_al=1 & op16_12_4=0x1 & op16_8_4=0x0 & bow=0x0 & postRegIncrement & XRREG_W_AS_DEST { +:RRCX.W XRREG_W_AS_DEST is ctx_haveext=4 & ctx_al=1 & op16_12_4=0x1 & op16_8_4=0x0 & bow=0x0 & postRegIncrement & XRREG_W_AS_DEST & repeat_carry { + build repeat_carry; # Operation Flags... $(OVERFLOW) = ((XRREG_W_AS_DEST != 0x0) && ($(CARRY) == 0x1)); # V Flag # Operation... @@ -3256,8 +3291,9 @@ macro wzero(full, word) goto ; } -:RRCX.A XRREG_A_AS_DEST is ctx_haveext=4 & ctx_al=0 & op16_12_4=0x1 & op16_8_4=0x0 & bow=0x1 & postRegIncrement & XRREG_A_AS_DEST { +:RRCX.A XRREG_A_AS_DEST is ctx_haveext=4 & ctx_al=0 & op16_12_4=0x1 & op16_8_4=0x0 & bow=0x1 & postRegIncrement & XRREG_A_AS_DEST & repeat_carry { + build repeat_carry; # Operation Flags... $(OVERFLOW) = ((XRREG_A_AS_DEST != 0x0) && ($(CARRY) == 0x1)); # V Flag # Operation... diff --git a/Ghidra/Processors/TI_MSP430/data/languages/TI_MSP430.ldefs b/Ghidra/Processors/TI_MSP430/data/languages/TI_MSP430.ldefs index 4f980021f6..30dd447e09 100644 --- a/Ghidra/Processors/TI_MSP430/data/languages/TI_MSP430.ldefs +++ b/Ghidra/Processors/TI_MSP430/data/languages/TI_MSP430.ldefs @@ -5,7 +5,7 @@ endian="little" size="16" variant="default" - version="1.4" + version="1.5" slafile="TI_MSP430.sla" processorspec="TI_MSP430.pspec" manualindexfile="../manuals/MSP430.idx" @@ -20,7 +20,7 @@ endian="little" size="32" variant="default" - version="1.4" + version="1.5" slafile="TI_MSP430X.sla" processorspec="TI_MSP430.pspec" manualindexfile="../manuals/MSP430.idx" diff --git a/Ghidra/Processors/TI_MSP430/data/languages/ti_msp430.opinion b/Ghidra/Processors/TI_MSP430/data/languages/ti_msp430.opinion index 0b73ea9a0e..fe15d33b83 100644 --- a/Ghidra/Processors/TI_MSP430/data/languages/ti_msp430.opinion +++ b/Ghidra/Processors/TI_MSP430/data/languages/ti_msp430.opinion @@ -3,9 +3,7 @@ - - - - + + diff --git a/Ghidra/Processors/TI_MSP430/src/main/java/ghidra/app/util/bin/format/elf/relocation/TI_MSP430X_ElfRelocationConstants.java b/Ghidra/Processors/TI_MSP430/src/main/java/ghidra/app/util/bin/format/elf/relocation/TI_MSP430X_ElfRelocationConstants.java new file mode 100644 index 0000000000..7278758b13 --- /dev/null +++ b/Ghidra/Processors/TI_MSP430/src/main/java/ghidra/app/util/bin/format/elf/relocation/TI_MSP430X_ElfRelocationConstants.java @@ -0,0 +1,53 @@ +/* ### + * 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.relocation; + +/** + * class for elf_msp430x_reloc_type (from binutils source) + */ +public class TI_MSP430X_ElfRelocationConstants { + // Note: some of the msp430x relocation types have "msp430" (without the x) + // in their names + public static final int R_MSP430_NONE = 0; // No calculation + public static final int R_MSP430_ABS32 = 1;// S + A + public static final int R_MSP430_ABS16 = 2; // S + A + public static final int R_MSP430_ABS8 = 3; // S + A + public static final int R_MSP430_PCR16 = 4; // S + A - PC + public static final int R_MSP430X_PCR20_EXT_SRC = 5; // S + A - PC + public static final int R_MSP430X_PCR20_EXT_DST = 6; // S + A - PC + public static final int R_MSP430X_PCR20_EXT_ODST = 7; // S + A - PC + public static final int R_MSP430X_ABS20_EXT_SRC = 8; // S + A + public static final int R_MSP430X_ABS20_EXT_DST = 9; // S + A + public static final int R_MSP430X_ABS20_EXT_ODST = 10; // S + A + public static final int R_MSP430X_ABS20_ADR_SRC = 11; // S + A + public static final int R_MSP430X_ABS20_ADR_DST = 12; // S + A + public static final int R_MSP430X_PCR16 = 13; // S + A - PC + public static final int R_MSP430X_PCR20_CALL = 14; // S + A - PC + public static final int R_MSP430X_ABS16 = 15; // S + A + public static final int R_MSP430_ABS_HI16 = 16; // S + A (Rela only) + public static final int R_MSP430_PREL31 = 17; // S + A - PC + public static final int R_MSP430_EHTYPE = 18; // encodes typeinfo addresses in exception tables + public static final int R_MSP430X_10_PCREL = 19; // Red Hat invention. + public static final int R_MSP430X_2X_PCREL = 20; // Red Hat invention + public static final int R_MSP430X_SYM_DIFF = 21; // Red Hat invention*/ + public static final int R_MSP430X_SET_ULEB128 = 22; // GNU only + public static final int R_MSP430X_SUB_ULEB128 = 23; // GNU only + + private TI_MSP430X_ElfRelocationConstants() { + //class not for instantiation + } + +} diff --git a/Ghidra/Processors/TI_MSP430/src/main/java/ghidra/app/util/bin/format/elf/relocation/TI_MSP430X_ElfRelocationHandler.java b/Ghidra/Processors/TI_MSP430/src/main/java/ghidra/app/util/bin/format/elf/relocation/TI_MSP430X_ElfRelocationHandler.java new file mode 100644 index 0000000000..5eda2e8e3d --- /dev/null +++ b/Ghidra/Processors/TI_MSP430/src/main/java/ghidra/app/util/bin/format/elf/relocation/TI_MSP430X_ElfRelocationHandler.java @@ -0,0 +1,185 @@ +/* ### + * 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.relocation; + +import ghidra.app.util.bin.format.elf.*; +import ghidra.program.model.address.Address; +import ghidra.program.model.listing.Program; +import ghidra.program.model.mem.Memory; +import ghidra.program.model.mem.MemoryAccessException; +import ghidra.program.model.reloc.Relocation.Status; +import ghidra.program.model.reloc.RelocationResult; +import ghidra.util.exception.NotFoundException; + +public class TI_MSP430X_ElfRelocationHandler extends ElfRelocationHandler { + + public static final int E_MSP430_MACH_MSP430X = 45; + + @Override + public boolean canRelocate(ElfHeader elf) { + return (elf.e_machine() == ElfConstants.EM_MSP430) && + ((elf.e_flags() & 0xff) == E_MSP430_MACH_MSP430X); + } + + @Override + public RelocationResult relocate(ElfRelocationContext elfRelocationContext, + ElfRelocation relocation, Address relocationAddress) + throws MemoryAccessException, NotFoundException { + int type = relocation.getType(); + if (type == TI_MSP430X_ElfRelocationConstants.R_MSP430_NONE) { + return RelocationResult.SKIPPED; + } + + Program program = elfRelocationContext.getProgram(); + Memory memory = program.getMemory(); + int symbolIndex = relocation.getSymbolIndex(); + long addend = relocation.getAddend(); // will be 0 for REL case + long offset = relocationAddress.getOffset(); + ElfSymbol sym = elfRelocationContext.getSymbol(symbolIndex); // may be null + String symbolName = elfRelocationContext.getSymbolName(symbolIndex); + long symbolValue = elfRelocationContext.getSymbolValue(sym); + int byteLength = 0; + + switch (type) { + case TI_MSP430X_ElfRelocationConstants.R_MSP430_ABS32: + int newIntValue = (int) (symbolValue + addend); + memory.setInt(relocationAddress, newIntValue); + byteLength = 4; + break; + case TI_MSP430X_ElfRelocationConstants.R_MSP430_ABS16: + case TI_MSP430X_ElfRelocationConstants.R_MSP430X_ABS16: + short newShortValue = (short) (symbolValue + addend); + memory.setShort(relocationAddress, newShortValue); + byteLength = 2; + break; + case TI_MSP430X_ElfRelocationConstants.R_MSP430_ABS8: + byte newByteValue = (byte) (symbolValue + addend); + memory.setByte(relocationAddress, newByteValue); + byteLength = 1; + break; + case TI_MSP430X_ElfRelocationConstants.R_MSP430_PCR16: + case TI_MSP430X_ElfRelocationConstants.R_MSP430X_PCR16: + newShortValue = (short) (symbolValue + addend - offset); + memory.setShort(relocationAddress, newShortValue); + byteLength = 2; + break; + case TI_MSP430X_ElfRelocationConstants.R_MSP430X_PCR20_EXT_SRC: + newIntValue = (int) (symbolValue + addend - offset - 4); + memory.setShort(relocationAddress.add(4), (short) (newIntValue)); + newIntValue >>= 16; + newIntValue &= 0xf0; + short highWord = memory.getShort(relocationAddress); + highWord &= 0xff0f; + highWord |= newIntValue; + memory.setShort(relocationAddress, highWord); + byteLength = 3; + break; + case TI_MSP430X_ElfRelocationConstants.R_MSP430X_PCR20_EXT_DST: + newIntValue = (int) (symbolValue + addend - offset - 4); + memory.setShort(relocationAddress.add(4), (short) (newIntValue)); + newIntValue >>= 16; + newIntValue &= 0xf; + highWord = memory.getShort(relocationAddress); + highWord &= 0xfff0; + highWord |= newIntValue; + memory.setShort(relocationAddress, highWord); + byteLength = 3; + break; + case TI_MSP430X_ElfRelocationConstants.R_MSP430X_PCR20_EXT_ODST: + newIntValue = (int) (symbolValue + addend - offset - 4); + memory.setShort(relocationAddress.add(6), (short) (newIntValue)); + newIntValue >>= 16; + newIntValue &= 0xf; + highWord = memory.getShort(relocationAddress); + highWord &= 0xfff0; + highWord |= newIntValue; + memory.setShort(relocationAddress, highWord); + byteLength = 4; + break; + case TI_MSP430X_ElfRelocationConstants.R_MSP430X_ABS20_EXT_SRC: + newIntValue = (int) (symbolValue + addend); + memory.setShort(relocationAddress.add(4), (short) (newIntValue)); + newIntValue >>= 16; + newIntValue &= 0xf0; + highWord = memory.getShort(relocationAddress); + highWord &= 0xff0f; + highWord |= newIntValue; + memory.setShort(relocationAddress, highWord); + byteLength = 3; + break; + case TI_MSP430X_ElfRelocationConstants.R_MSP430X_ABS20_EXT_DST: + newIntValue = (int) (symbolValue + addend); + memory.setShort(relocationAddress.add(4), (short) (newIntValue)); + newIntValue >>= 16; + newIntValue &= 0xf; + highWord = memory.getShort(relocationAddress); + highWord &= 0xfff0; + highWord |= newIntValue; + memory.setShort(relocationAddress, highWord); + byteLength = 3; + break; + case TI_MSP430X_ElfRelocationConstants.R_MSP430X_ABS20_EXT_ODST: + newIntValue = (int) (symbolValue + addend); + memory.setShort(relocationAddress.add(6), (short) (newIntValue)); + newIntValue >>= 16; + newIntValue &= 0xf; + highWord = memory.getShort(relocationAddress); + highWord &= 0xfff0; + highWord |= newIntValue; + memory.setShort(relocationAddress, highWord); + byteLength = 4; + break; + case TI_MSP430X_ElfRelocationConstants.R_MSP430X_ABS20_ADR_DST: + newIntValue = (int) (symbolValue + addend); + memory.setShort(relocationAddress.add(2), (short) (newIntValue & 0xffff)); + newIntValue >>= 16; + newIntValue &= 0xf; + highWord = memory.getShort(relocationAddress); + highWord &= 0xfff0; + highWord |= newIntValue; + memory.setShort(relocationAddress, highWord); + byteLength = 3; + break; + case TI_MSP430X_ElfRelocationConstants.R_MSP430X_PCR20_CALL: + newIntValue = (int) (symbolValue + addend - offset); + memory.setShort(relocationAddress.add(2), (short) (newIntValue & 0xffff)); + newIntValue >>= 16; + newIntValue &= 0xf; + highWord = memory.getShort(relocationAddress); + highWord &= 0xfff0; + highWord |= newIntValue; + memory.setShort(relocationAddress, highWord); + byteLength = 3; + break; + case TI_MSP430X_ElfRelocationConstants.R_MSP430X_10_PCREL: + short oldShortValue = memory.getShort(relocationAddress); + oldShortValue &= 0xfc00; + newShortValue = (short) (symbolValue + addend - offset - 2); + newShortValue >>= 1; + newShortValue &= 0x3ff; + newShortValue = (short) (oldShortValue | newShortValue); + memory.setShort(relocationAddress, newShortValue); + byteLength = 2; + break; + default: + markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName, + elfRelocationContext.getLog()); + return RelocationResult.UNSUPPORTED; + } + return new RelocationResult(Status.APPLIED, byteLength); + } + +} diff --git a/Ghidra/Processors/TI_MSP430/src/main/java/ghidra/app/util/bin/format/elf/relocation/TI_MSP430_ElfRelocationConstants.java b/Ghidra/Processors/TI_MSP430/src/main/java/ghidra/app/util/bin/format/elf/relocation/TI_MSP430_ElfRelocationConstants.java new file mode 100644 index 0000000000..9864cdf3a4 --- /dev/null +++ b/Ghidra/Processors/TI_MSP430/src/main/java/ghidra/app/util/bin/format/elf/relocation/TI_MSP430_ElfRelocationConstants.java @@ -0,0 +1,35 @@ +/* ### + * 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.relocation; + +/** + * class for elf_msp430_reloc_type (from binutils source) + */ +public class TI_MSP430_ElfRelocationConstants { + public static final int R_MSP430_NONE = 0; + public static final int R_MSP430_32 = 1; + public static final int R_MSP430_10_PCREL = 2; + public static final int R_MSP430_16 = 3; + public static final int R_MSP430_16_PCREL = 4; + public static final int R_MSP430_16_BYTE = 5; + public static final int R_MSP430_16_PCREL_BYTE = 6; + public static final int R_MSP430_2X_PCREL = 7; + public static final int R_MSP430_RL_PCREL = 8; + public static final int R_MSP430_8 = 9; + public static final int R_MSP430_SYM_DIFF = 10; + public static final int R_MSP430_SET_ULEB128 = 11; // GNU only. + public static final int R_MSP430_SUB_ULEB128 = 12; // GNU only +} diff --git a/Ghidra/Processors/TI_MSP430/src/main/java/ghidra/app/util/bin/format/elf/relocation/TI_MSP430_ElfRelocationHandler.java b/Ghidra/Processors/TI_MSP430/src/main/java/ghidra/app/util/bin/format/elf/relocation/TI_MSP430_ElfRelocationHandler.java new file mode 100644 index 0000000000..bf54fbf3cc --- /dev/null +++ b/Ghidra/Processors/TI_MSP430/src/main/java/ghidra/app/util/bin/format/elf/relocation/TI_MSP430_ElfRelocationHandler.java @@ -0,0 +1,104 @@ +/* ### + * 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.relocation; + +import ghidra.app.util.bin.format.elf.*; +import ghidra.program.model.address.Address; +import ghidra.program.model.listing.Program; +import ghidra.program.model.mem.Memory; +import ghidra.program.model.mem.MemoryAccessException; +import ghidra.program.model.reloc.Relocation.Status; +import ghidra.program.model.reloc.RelocationResult; +import ghidra.util.exception.NotFoundException; + +public class TI_MSP430_ElfRelocationHandler extends ElfRelocationHandler { + + @Override + public boolean canRelocate(ElfHeader elf) { + return (elf.e_machine() == ElfConstants.EM_MSP430) && + ((elf.e_flags() & 0xff) != TI_MSP430X_ElfRelocationHandler.E_MSP430_MACH_MSP430X); + } + + @Override + public RelocationResult relocate(ElfRelocationContext elfRelocationContext, + ElfRelocation relocation, Address relocationAddress) + throws MemoryAccessException, NotFoundException { + int type = relocation.getType(); + if (type == TI_MSP430_ElfRelocationConstants.R_MSP430_NONE) { + return RelocationResult.SKIPPED; + } + + Program program = elfRelocationContext.getProgram(); + Memory memory = program.getMemory(); + int symbolIndex = relocation.getSymbolIndex(); + long addend = relocation.getAddend(); // will be 0 for REL case + long offset = relocationAddress.getOffset(); + ElfSymbol sym = elfRelocationContext.getSymbol(symbolIndex); // may be null + String symbolName = elfRelocationContext.getSymbolName(symbolIndex); + long symbolValue = elfRelocationContext.getSymbolValue(sym); + + int byteLength = 0; + + switch (type) { + case TI_MSP430_ElfRelocationConstants.R_MSP430_32: + int newIntValue = (int) (symbolValue + addend); + memory.setInt(relocationAddress, newIntValue); + byteLength = 4; + break; + case TI_MSP430_ElfRelocationConstants.R_MSP430_10_PCREL: + short oldShortValue = memory.getShort(relocationAddress); + oldShortValue &= 0xfc00; + short newShortValue = (short) (symbolValue + addend - offset - 2); + newShortValue >>= 1; + newShortValue &= 0x3ff; + newShortValue = (short) (oldShortValue | newShortValue); + memory.setShort(relocationAddress, newShortValue); + byteLength = 2; + break; + case TI_MSP430_ElfRelocationConstants.R_MSP430_16: + newShortValue = (short) (symbolValue + addend); + memory.setShort(relocationAddress, newShortValue); + byteLength = 2; + break; + //case TI_MSP430_ElfRelocationConstants.R_MSP430_16_PCREL: + case TI_MSP430_ElfRelocationConstants.R_MSP430_16_BYTE: + newShortValue = (short) (symbolValue + addend); + memory.setShort(relocationAddress, newShortValue); + byteLength = 2; + break; + case TI_MSP430_ElfRelocationConstants.R_MSP430_16_PCREL_BYTE: + newShortValue = (short) (symbolValue + addend - offset); + memory.setShort(relocationAddress, newShortValue); + byteLength = 2; + break; + //case TI_MSP430_ElfRelocationConstants.R_MSP430_2X_PCREL: + //case TI_MSP430_ElfRelocationConstants.R_MSP430_RL_PCREL: + case TI_MSP430_ElfRelocationConstants.R_MSP430_8: + byte newByteValue = (byte) (symbolValue + addend); + memory.setByte(relocationAddress, newByteValue); + byteLength = 1; + break; + //case TI_MSP430_ElfRelocationConstants.R_MSP430_SYM_DIFF: + //case TI_MSP430_ElfRelocationConstants.R_MSP430_SET_ULEB128: + //case TI_MSP430_ElfRelocationConstants.R_MSP430_SUB_ULEB128: + default: + markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName, + elfRelocationContext.getLog()); + return RelocationResult.UNSUPPORTED; + } + return new RelocationResult(Status.APPLIED, byteLength); + } +} diff --git a/Ghidra/Processors/TI_MSP430/src/test.processors/java/ghidra/test/processors/MSP430X_O0_EmulatorTest.java b/Ghidra/Processors/TI_MSP430/src/test.processors/java/ghidra/test/processors/MSP430X_O0_EmulatorTest.java new file mode 100644 index 0000000000..45ccf43fa3 --- /dev/null +++ b/Ghidra/Processors/TI_MSP430/src/test.processors/java/ghidra/test/processors/MSP430X_O0_EmulatorTest.java @@ -0,0 +1,49 @@ +/* ### + * 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.program.model.listing.*; +import ghidra.test.processors.support.EmulatorTestRunner; +import ghidra.test.processors.support.ProcessorEmulatorTestAdapter; +import junit.framework.Test; + +public class MSP430X_O0_EmulatorTest extends ProcessorEmulatorTestAdapter { + + private static final String LANGUAGE_ID = "TI_MSP430X:LE:32:default"; + private static final String COMPILER_SPEC_ID = "default"; + + private static final String[] REG_DUMP_SET = new String[] {}; + + public MSP430X_O0_EmulatorTest(String name) throws Exception { + super(name, LANGUAGE_ID, COMPILER_SPEC_ID, REG_DUMP_SET); + } + + @Override + protected String getProcessorDesignator() { + return "MSP430X_GCC_O0"; + } + + @Override + protected void initializeState(EmulatorTestRunner testRunner, Program program) + throws Exception { + super.initializeState(testRunner, program); + testRunner.setRegister("SP", 0xFF80L); + } + + public static Test suite() { + return ProcessorEmulatorTestAdapter.buildEmulatorTestSuite(MSP430X_O0_EmulatorTest.class); + } +} diff --git a/Ghidra/Processors/TI_MSP430/src/test.processors/java/ghidra/test/processors/MSP430X_O3_EmulatorTest.java b/Ghidra/Processors/TI_MSP430/src/test.processors/java/ghidra/test/processors/MSP430X_O3_EmulatorTest.java new file mode 100644 index 0000000000..d66f10d552 --- /dev/null +++ b/Ghidra/Processors/TI_MSP430/src/test.processors/java/ghidra/test/processors/MSP430X_O3_EmulatorTest.java @@ -0,0 +1,49 @@ +/* ### + * 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.program.model.listing.*; +import ghidra.test.processors.support.EmulatorTestRunner; +import ghidra.test.processors.support.ProcessorEmulatorTestAdapter; +import junit.framework.Test; + +public class MSP430X_O3_EmulatorTest extends ProcessorEmulatorTestAdapter { + + private static final String LANGUAGE_ID = "TI_MSP430X:LE:32:default"; + private static final String COMPILER_SPEC_ID = "default"; + + private static final String[] REG_DUMP_SET = new String[] {}; + + public MSP430X_O3_EmulatorTest(String name) throws Exception { + super(name, LANGUAGE_ID, COMPILER_SPEC_ID, REG_DUMP_SET); + } + + @Override + protected String getProcessorDesignator() { + return "MSP430X_GCC_O3"; + } + + @Override + protected void initializeState(EmulatorTestRunner testRunner, Program program) + throws Exception { + super.initializeState(testRunner, program); + testRunner.setRegister("SP", 0xFF80L); + } + + public static Test suite() { + return ProcessorEmulatorTestAdapter.buildEmulatorTestSuite(MSP430X_O3_EmulatorTest.class); + } +} diff --git a/Ghidra/Processors/TI_MSP430/src/test.processors/java/ghidra/test/processors/MSP430_O0_EmulatorTest.java b/Ghidra/Processors/TI_MSP430/src/test.processors/java/ghidra/test/processors/MSP430_O0_EmulatorTest.java new file mode 100644 index 0000000000..d5c4a618ab --- /dev/null +++ b/Ghidra/Processors/TI_MSP430/src/test.processors/java/ghidra/test/processors/MSP430_O0_EmulatorTest.java @@ -0,0 +1,49 @@ +/* ### + * 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.program.model.listing.*; +import ghidra.test.processors.support.EmulatorTestRunner; +import ghidra.test.processors.support.ProcessorEmulatorTestAdapter; +import junit.framework.Test; + +public class MSP430_O0_EmulatorTest extends ProcessorEmulatorTestAdapter { + + private static final String LANGUAGE_ID = "TI_MSP430:LE:16:default"; + private static final String COMPILER_SPEC_ID = "default"; + + private static final String[] REG_DUMP_SET = new String[] {}; + + public MSP430_O0_EmulatorTest(String name) throws Exception { + super(name, LANGUAGE_ID, COMPILER_SPEC_ID, REG_DUMP_SET); + } + + @Override + protected String getProcessorDesignator() { + return "MSP430_GCC_O0"; + } + + @Override + protected void initializeState(EmulatorTestRunner testRunner, Program program) + throws Exception { + super.initializeState(testRunner, program); + testRunner.setRegister("SP", 0xFF80L); + } + + public static Test suite() { + return ProcessorEmulatorTestAdapter.buildEmulatorTestSuite(MSP430_O0_EmulatorTest.class); + } +} diff --git a/Ghidra/Processors/TI_MSP430/src/test.processors/java/ghidra/test/processors/MSP430_O3_EmulatorTest.java b/Ghidra/Processors/TI_MSP430/src/test.processors/java/ghidra/test/processors/MSP430_O3_EmulatorTest.java new file mode 100644 index 0000000000..1e54e93a2d --- /dev/null +++ b/Ghidra/Processors/TI_MSP430/src/test.processors/java/ghidra/test/processors/MSP430_O3_EmulatorTest.java @@ -0,0 +1,49 @@ +/* ### + * 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.program.model.listing.*; +import ghidra.test.processors.support.EmulatorTestRunner; +import ghidra.test.processors.support.ProcessorEmulatorTestAdapter; +import junit.framework.Test; + +public class MSP430_O3_EmulatorTest extends ProcessorEmulatorTestAdapter { + + private static final String LANGUAGE_ID = "TI_MSP430:LE:16:default"; + private static final String COMPILER_SPEC_ID = "default"; + + private static final String[] REG_DUMP_SET = new String[] {}; + + public MSP430_O3_EmulatorTest(String name) throws Exception { + super(name, LANGUAGE_ID, COMPILER_SPEC_ID, REG_DUMP_SET); + } + + @Override + protected String getProcessorDesignator() { + return "MSP430_GCC_O3"; + } + + @Override + protected void initializeState(EmulatorTestRunner testRunner, Program program) + throws Exception { + super.initializeState(testRunner, program); + testRunner.setRegister("SP", 0xFF80L); + } + + public static Test suite() { + return ProcessorEmulatorTestAdapter.buildEmulatorTestSuite(MSP430_O3_EmulatorTest.class); + } +}