diff --git a/Ghidra/Extensions/SleighDevTools/pcodetest/c_src/misc_BODY.c b/Ghidra/Extensions/SleighDevTools/pcodetest/c_src/misc_BODY.c index 131404c87f..4120b125e2 100644 --- a/Ghidra/Extensions/SleighDevTools/pcodetest/c_src/misc_BODY.c +++ b/Ghidra/Extensions/SleighDevTools/pcodetest/c_src/misc_BODY.c @@ -16,6 +16,14 @@ #include "pcode_test.h" #include "big_struct.h" +#ifdef HAS_LIBC +#include +#else +void *memset(void *b, int c, size_t len); +void *memcpy(void *dst, const void *src, size_t n); +int memcmp(const void *s1, const void *s2, size_t n); +#endif + static i4 int_expectedValue; static i4 int_actualValue; diff --git a/Ghidra/Extensions/SleighDevTools/pcodetest/defaults.py b/Ghidra/Extensions/SleighDevTools/pcodetest/defaults.py index 91cd62de33..94f4982b7d 100644 --- a/Ghidra/Extensions/SleighDevTools/pcodetest/defaults.py +++ b/Ghidra/Extensions/SleighDevTools/pcodetest/defaults.py @@ -47,12 +47,14 @@ pcodeTestDefaults.has_vector = 0 pcodeTestDefaults.small_build = 0 pcodeTestDefaults.ld_library_path = '' pcodeTestDefaults.toolchain_type = 'gcc' -pcodeTestDefaults.compile_exe = 'bin/gcc' -pcodeTestDefaults.objdump_exe = 'bin/objdump' +pcodeTestDefaults.compile_exe = 'gcc' +pcodeTestDefaults.objdump_exe = 'objdump' pcodeTestDefaults.objdump_option = '' -pcodeTestDefaults.readelf_exe = 'bin/readelf' -pcodeTestDefaults.nm_exe = 'bin/nm' -pcodeTestDefaults.strip_exe = 'bin/strip' +pcodeTestDefaults.readelf_exe = 'readelf' +pcodeTestDefaults.exec_dir = 'bin/' +pcodeTestDefaults.exec_prefix = '' +pcodeTestDefaults.nm_exe = 'nm' +pcodeTestDefaults.strip_exe = 'strip' pcodeTestDefaults.variants = {'O0': '-O0', 'O3': '-O3'} pcodeTestDefaults.proc_test = '' pcodeTestDefaults.force = False diff --git a/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py b/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py index 6c9ddaa373..0e70268d34 100644 --- a/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py +++ b/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py @@ -436,7 +436,7 @@ PCodeTest({ 'name': 'NDS32BE', 'build_all': 1, 'toolchain': 'NDS32/nds32be-elf', - 'ccflags': '', + 'ccflags': '-mbig-endian', 'cclibs': '-lgcc', 'language_id': 'NDS32:BE:32:default', }) @@ -444,9 +444,20 @@ PCodeTest({ PCodeTest({ 'name': 'NDS32LE', 'build_all': 1, - 'toolchain': 'NDS32/nds32le-elf', + 'toolchain': 'NDS32/nds32le-elf',#'NDS32/nds32le-linux-glibc-v5d', + 'ccflags': '-mlittle-endian -EL', + 'cclibs': '-lgcc', + 'language_id': 'NDS32:LE:32:default', +}) + +PCodeTest({ + 'name': 'NDS32AS', + 'build_all': 1, + 'toolchain': 'NDS32/nds32le-elf-mculib-v3s', + 'exec_prefix': 'nds32le-elf-', 'ccflags': '', 'cclibs': '-lgcc', + 'gcc_version': '12.2.0', 'language_id': 'NDS32:LE:32:default', }) diff --git a/Ghidra/Extensions/SleighDevTools/pcodetest/pcodetest.py b/Ghidra/Extensions/SleighDevTools/pcodetest/pcodetest.py index 76a48ef3ba..1bdde635d8 100644 --- a/Ghidra/Extensions/SleighDevTools/pcodetest/pcodetest.py +++ b/Ghidra/Extensions/SleighDevTools/pcodetest/pcodetest.py @@ -88,7 +88,13 @@ class PCodeTestBuild(BuildUtil): 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) + self.config.nm_exe = self.config.exec_dir + str(self.config.exec_prefix) + str(self.config.nm_exe) + if not self.is_executable_file(self.which('compile_exe')): self.log_err(self.config.format('build the Toolchain before compilation')) return @@ -427,6 +433,7 @@ class PCodeBuildGCC(PCodeTestBuild): self.set_library_path(self.config.ld_library_path) # Construct the compile/link command line and execute it + cmp = self.which('compile_exe') cmd = [cmp] + input_files + self.cflags(output_file) + [opt_cflag, '-B', self.dirname(cmp), '-o', output_file] out, err = self.run(cmd) diff --git a/Ghidra/Processors/NDS32/Module.manifest b/Ghidra/Processors/NDS32/Module.manifest new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Ghidra/Processors/NDS32/build.gradle b/Ghidra/Processors/NDS32/build.gradle new file mode 100644 index 0000000000..801e85ff93 --- /dev/null +++ b/Ghidra/Processors/NDS32/build.gradle @@ -0,0 +1,30 @@ +/* ### + * 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. + */ +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 NDS32' + + +dependencies { + api project(':Base') + // Temporary dependency so that pcodeTests can use the Decompiler switch recovery + api project(':Decompiler') +} + diff --git a/Ghidra/Processors/NDS32/certification.manifest b/Ghidra/Processors/NDS32/certification.manifest new file mode 100644 index 0000000000..cec7eed86b --- /dev/null +++ b/Ghidra/Processors/NDS32/certification.manifest @@ -0,0 +1,13 @@ +##VERSION: 2.0 +Module.manifest||GHIDRA||||END| +data/languages/lsmw.sinc||GHIDRA||||END| +data/languages/nds32.cspec||GHIDRA||||END| +data/languages/nds32.dwarf||GHIDRA||||END| +data/languages/nds32.ldefs||GHIDRA||||END| +data/languages/nds32.opinion||GHIDRA||||END| +data/languages/nds32.pspec||GHIDRA||||END| +data/languages/nds32.sinc||GHIDRA||||END| +data/languages/nds32be.slaspec||GHIDRA||||END| +data/languages/nds32le.slaspec||GHIDRA||||END| +data/patterns/nds32_patterns.xml||GHIDRA||||END| +data/patterns/patternconstraints.xml||GHIDRA||||END| diff --git a/Ghidra/Processors/NDS32/data/languages/lsmw.sinc b/Ghidra/Processors/NDS32/data/languages/lsmw.sinc new file mode 100644 index 0000000000..bff5e75888 --- /dev/null +++ b/Ghidra/Processors/NDS32/data/languages/lsmw.sinc @@ -0,0 +1,125 @@ +Dreg: a0 is a0 & regNum=0 { export a0; } +Dreg: a1 is a1 & regNum=1 { export a1; } +Dreg: a2 is a2 & regNum=2 { export a2; } +Dreg: a3 is a3 & regNum=3 { export a3; } +Dreg: a4 is a4 & regNum=4 { export a4; } +Dreg: a5 is a5 & regNum=5 { export a5; } +Dreg: s0 is s0 & regNum=6 { export s0; } +Dreg: s1 is s1 & regNum=7 { export s1; } +Dreg: s2 is s2 & regNum=8 { export s2; } +Dreg: s3 is s3 & regNum=9 { export s3; } +Dreg: s4 is s4 & regNum=10 { export s4; } +Dreg: s5 is s5 & regNum=11 { export s5; } +Dreg: s6 is s6 & regNum=12 { export s6; } +Dreg: s7 is s7 & regNum=13 { export s7; } +Dreg: s8 is s8 & regNum=14 { export s8; } +Dreg: ta is ta & regNum=15 { export ta; } +Dreg: t0 is t0 & regNum=16 { export t0; } +Dreg: t1 is t1 & regNum=17 { export t1; } +Dreg: t2 is t2 & regNum=18 { export t2; } +Dreg: t3 is t3 & regNum=19 { export t3; } +Dreg: t4 is t4 & regNum=20 { export t4; } +Dreg: t5 is t5 & regNum=21 { export t5; } +Dreg: t6 is t6 & regNum=22 { export t6; } +Dreg: t7 is t7 & regNum=23 { export t7; } +Dreg: t8 is t8 & regNum=24 { export t8; } +Dreg: t9 is t9 & regNum=25 { export t9; } +Dreg: p0 is p0 & regNum=26 { export p0; } +Dreg: p1 is p1 & regNum=27 { export p1; } +Dreg: fp is fp & regNum=28 { export fp; } +Dreg: gp is gp & regNum=29 { export gp; } +Dreg: lp is lp & regNum=30 { export lp; } +Dreg: sp is sp & regNum=31 { export sp; } + +macro Smwad(reg) { + mult_addr = mult_addr - 4; + *mult_addr = reg; +} + +macro LmwOp(reg) { + reg = *mult_addr; +} + +macro SmwOp(reg) { + *mult_addr = reg; +} + +macro MwDec() { mult_addr = mult_addr - 4; } +macro MwInc() { mult_addr = mult_addr + 4; } + +Lsmw_id: is LsmwId=0 { MwInc(); } +Lsmw_id: is LsmwId=1 { MwDec(); } + +Lmw.fp: fp is Lsmw_id & LsmwBa=0 & Enable4_fp=1 & fp { LmwOp(fp); build Lsmw_id; } +Lmw.fp: fp is Lsmw_id & LsmwBa=1 & Enable4_fp=1 & fp { build Lsmw_id; LmwOp(fp); } +Lmw.fp: is Enable4_fp=0 { } +Lmw.gp: gp is Lsmw_id & LsmwBa=0 & Enable4_gp=1 & gp { LmwOp(gp); build Lsmw_id; } +Lmw.gp: gp is Lsmw_id & LsmwBa=1 & Enable4_gp=1 & gp { build Lsmw_id; LmwOp(gp); } +Lmw.gp: is Enable4_gp=0 { } +Lmw.lp: lp is Lsmw_id & LsmwBa=0 & Enable4_lp=1 & lp { LmwOp(lp); build Lsmw_id; } +Lmw.lp: lp is Lsmw_id & LsmwBa=1 & Enable4_lp=1 & lp { build Lsmw_id; LmwOp(lp); } +Lmw.lp: is Enable4_lp=0 { } +Lmw.sp: sp is Lsmw_id & LsmwBa=0 & Enable4_sp=1 & sp { LmwOp(sp); build Lsmw_id; } +Lmw.sp: sp is Lsmw_id & LsmwBa=1 & Enable4_sp=1 & sp { build Lsmw_id; LmwOp(sp); } +Lmw.sp: is Enable4_sp=0 { } + +# Terminating condition +LmwReg: Dreg is LsmwId=0 & LsmwBa=0 & Dreg & counter=1 [regNum=regNum+1;] { build Dreg; LmwOp(Dreg); MwInc(); } +LmwReg: Dreg is LsmwId=1 & LsmwBa=0 & Dreg & counter=1 [regNum=regNum-1;] { build Dreg; LmwOp(Dreg); MwDec(); } + +LmwReg: Dreg is LsmwId=0 & LsmwBa=1 & Dreg & counter=1 [regNum=regNum+1;] { build Dreg; MwInc(); LmwOp(Dreg); } +LmwReg: Dreg is LsmwId=1 & LsmwBa=1 & Dreg & counter=1 [regNum=regNum-1;] { build Dreg; MwDec(); LmwOp(Dreg); } + +LmwReg: Dreg, LmwReg is LsmwId=0 & LsmwBa=0 & Dreg & LmwReg [ counter = counter-1; regNum=regNum+1;] { LmwOp(Dreg); MwInc(); build LmwReg; } +LmwReg: Dreg, LmwReg is LsmwId=1 & LsmwBa=0 & Dreg & LmwReg [ counter = counter-1; regNum=regNum-1;] { LmwOp(Dreg); MwDec(); build LmwReg; } + +LmwReg: Dreg, LmwReg is LsmwId=0 & LsmwBa=1 & Dreg & LmwReg [ counter = counter-1; regNum=regNum+1;] { MwInc(); LmwOp(Dreg); build LmwReg; } +LmwReg: Dreg, LmwReg is LsmwId=1 & LsmwBa=1 & Dreg & LmwReg [ counter = counter-1; regNum=regNum-1;] { MwDec(); LmwOp(Dreg); build LmwReg; } + +# Initial conditions +Lmw.regs: is (LsmwRe_ & LsmwRb_ & LsmwId=0 & Lmw.fp & Lmw.gp & Lmw.lp & Lmw.sp) ... & LmwReg [ regNum=LsmwRb_-1; counter=LsmwRe_-LsmwRb_+1; ] { build LmwReg; build Lmw.fp; build Lmw.gp; build Lmw.lp; build Lmw.sp; } +Lmw.regs: is (LsmwRe_ & LsmwRb_ & LsmwId=1 & Lmw.sp & Lmw.lp & Lmw.gp & Lmw.fp) ... & LmwReg [ regNum=LsmwRe_+1; counter=LsmwRe_-LsmwRb_+1; ] { build Lmw.sp; build Lmw.lp; build Lmw.gp; build Lmw.fp; build LmwReg; } +Lmw.regs: is LsmwRe_=0x1f & LsmwRb_=0x1f & LsmwId=0 & Lmw.fp & Lmw.gp & Lmw.lp & Lmw.sp { build Lmw.fp; build Lmw.gp; build Lmw.lp; build Lmw.sp; } +Lmw.regs: is LsmwRe_=0x1f & LsmwRb_=0x1f & LsmwId=1 & Lmw.sp & Lmw.lp & Lmw.gp & Lmw.fp { build Lmw.sp; build Lmw.lp; build Lmw.gp; build Lmw.fp; } + +Lmwa.regs: is (LsmwRe_ & LsmwRb_ & LsmwId=0 & Lmw.fp & Lmw.gp & Lmw.lp & Lmw.sp) ... & LmwReg [ regNum=LsmwRb_-1; counter=LsmwRe_-LsmwRb_+1; ] { build LmwReg; build Lmw.sp; build Lmw.lp; build Lmw.gp; build Lmw.fp; } +Lmwa.regs: is (LsmwRe_ & LsmwRb_ & LsmwId=1 & Lmw.sp & Lmw.lp & Lmw.gp & Lmw.fp) ... & LmwReg [ regNum=LsmwRe_+1; counter=LsmwRe_-LsmwRb_+1; ] { build Lmw.fp; build Lmw.gp; build Lmw.lp; build Lmw.sp; build LmwReg; } +Lmwa.regs: is LsmwRe_=0x1f & LsmwRb_=0x1f & LsmwId=0 & Lmw.fp & Lmw.gp & Lmw.lp & Lmw.sp { build Lmw.sp; build Lmw.lp; build Lmw.gp; build Lmw.fp; } +Lmwa.regs: is LsmwRe_=0x1f & LsmwRb_=0x1f & LsmwId=1 & Lmw.sp & Lmw.lp & Lmw.gp & Lmw.fp { build Lmw.fp; build Lmw.gp; build Lmw.lp; build Lmw.sp; } + +Smw.fp: fp is Lsmw_id & LsmwBa=0 & Enable4_fp=1 & fp { SmwOp(fp); build Lsmw_id; } +Smw.fp: fp is Lsmw_id & LsmwBa=1 & Enable4_fp=1 & fp { build Lsmw_id; SmwOp(fp); } +Smw.fp: is Enable4_fp=0 { } +Smw.gp: gp is Lsmw_id & LsmwBa=0 & Enable4_gp=1 & gp { SmwOp(gp); build Lsmw_id; } +Smw.gp: gp is Lsmw_id & LsmwBa=1 & Enable4_gp=1 & gp { build Lsmw_id; SmwOp(gp); } +Smw.gp: is Enable4_gp=0 { } +Smw.lp: lp is Lsmw_id & LsmwBa=0 & Enable4_lp=1 & lp { SmwOp(lp); build Lsmw_id; } +Smw.lp: lp is Lsmw_id & LsmwBa=1 & Enable4_lp=1 & lp { build Lsmw_id; SmwOp(lp); } +Smw.lp: is Enable4_lp=0 { } +Smw.sp: sp is Lsmw_id & LsmwBa=0 & Enable4_sp=1 & sp { SmwOp(sp); build Lsmw_id; } +Smw.sp: sp is Lsmw_id & LsmwBa=1 & Enable4_sp=1 & sp { build Lsmw_id; SmwOp(sp); } +Smw.sp: is Enable4_sp=0 { } + +# Terminating condition +SmwReg: Dreg is LsmwId=0 & LsmwBa=0 & Dreg & counter=1 [regNum=regNum+1;] { build Dreg; SmwOp(Dreg); MwInc(); } +SmwReg: Dreg is LsmwId=1 & LsmwBa=0 & Dreg & counter=1 [regNum=regNum-1;] { build Dreg; SmwOp(Dreg); MwDec(); } + +SmwReg: Dreg is LsmwId=0 & LsmwBa=1 & Dreg & counter=1 [regNum=regNum+1;] { build Dreg; MwInc(); SmwOp(Dreg); } +SmwReg: Dreg is LsmwId=1 & LsmwBa=1 & Dreg & counter=1 [regNum=regNum-1;] { build Dreg; MwDec(); SmwOp(Dreg); } + +SmwReg: Dreg, SmwReg is LsmwId=0 & LsmwBa=0 & Dreg & SmwReg [ counter = counter-1; regNum=regNum+1;] { build Dreg; SmwOp(Dreg); MwInc(); build SmwReg; } +SmwReg: Dreg, SmwReg is LsmwId=1 & LsmwBa=0 & Dreg & SmwReg [ counter = counter-1; regNum=regNum-1;] { build Dreg; SmwOp(Dreg); MwDec(); build SmwReg; } + +SmwReg: Dreg, SmwReg is LsmwId=0 & LsmwBa=1 & Dreg & SmwReg [ counter = counter-1; regNum=regNum+1;] { build Dreg; MwInc(); SmwOp(Dreg); build SmwReg; } +SmwReg: Dreg, SmwReg is LsmwId=1 & LsmwBa=1 & Dreg & SmwReg [ counter = counter-1; regNum=regNum-1;] { build Dreg; MwDec(); SmwOp(Dreg); build SmwReg; } + +# Initial conditions +Smw.regs: is (LsmwRe_ & LsmwRb_ & LsmwId=0 & Smw.fp & Smw.gp & Smw.lp & Smw.sp) ... & SmwReg [ regNum=LsmwRb_-1; counter=LsmwRe_-LsmwRb_+1; ] { build SmwReg; build Smw.fp; build Smw.gp; build Smw.lp; build Smw.sp; } +Smw.regs: is (LsmwRe_ & LsmwRb_ & LsmwId=1 & Smw.sp & Smw.lp & Smw.gp & Smw.fp) ... & SmwReg [ regNum=LsmwRe_+1; counter=LsmwRe_-LsmwRb_+1; ] { build Smw.sp; build Smw.lp; build Smw.gp; build Smw.fp; build SmwReg; } +Smw.regs: is LsmwRe_=0x1f & LsmwRb_=0x1f & LsmwId=0 & Smw.fp & Smw.gp & Smw.lp & Smw.sp { build Smw.fp; build Smw.gp; build Smw.lp; build Smw.sp; } +Smw.regs: is LsmwRe_=0x1f & LsmwRb_=0x1f & LsmwId=1 & Smw.sp & Smw.lp & Smw.gp & Smw.fp { build Smw.sp; build Smw.lp; build Smw.gp; build Smw.fp; } + +Smwa.regs: is (LsmwRe_ & LsmwRb_ & LsmwId=0 & Smw.fp & Smw.gp & Smw.lp & Smw.sp) ... & SmwReg [ regNum=LsmwRb_-1; counter=LsmwRe_-LsmwRb_+1; ] { build SmwReg; build Smw.sp; build Smw.lp; build Smw.gp; build Smw.fp; } +Smwa.regs: is (LsmwRe_ & LsmwRb_ & LsmwId=1 & Smw.sp & Smw.lp & Smw.gp & Smw.fp) ... & SmwReg [ regNum=LsmwRe_+1; counter=LsmwRe_-LsmwRb_+1; ] { build Smw.fp; build Smw.gp; build Smw.lp; build Smw.sp; build SmwReg; } +Smwa.regs: is LsmwRe_=0x1f & LsmwRb_=0x1f & LsmwId=0 & Smw.fp & Smw.gp & Smw.lp & Smw.sp { build Smw.sp; build Smw.lp; build Smw.gp; build Smw.fp; } +Smwa.regs: is LsmwRe_=0x1f & LsmwRb_=0x1f & LsmwId=1 & Smw.sp & Smw.lp & Smw.gp & Smw.fp { build Smw.fp; build Smw.gp; build Smw.lp; build Smw.sp; } diff --git a/Ghidra/Processors/NDS32/data/languages/nds32.cspec b/Ghidra/Processors/NDS32/data/languages/nds32.cspec new file mode 100644 index 0000000000..ed3a93b095 --- /dev/null +++ b/Ghidra/Processors/NDS32/data/languages/nds32.cspec @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Ghidra/Processors/NDS32/data/languages/nds32.dwarf b/Ghidra/Processors/NDS32/data/languages/nds32.dwarf new file mode 100644 index 0000000000..b254e363fd --- /dev/null +++ b/Ghidra/Processors/NDS32/data/languages/nds32.dwarf @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/Ghidra/Processors/NDS32/data/languages/nds32.ldefs b/Ghidra/Processors/NDS32/data/languages/nds32.ldefs new file mode 100644 index 0000000000..8ee0ac46ac --- /dev/null +++ b/Ghidra/Processors/NDS32/data/languages/nds32.ldefs @@ -0,0 +1,33 @@ + + + + + NDS32 default processor 32-bit big-endian + + + + + + NDS32 default processor 32-bit little-endian + + + + + + diff --git a/Ghidra/Processors/NDS32/data/languages/nds32.opinion b/Ghidra/Processors/NDS32/data/languages/nds32.opinion new file mode 100644 index 0000000000..bf744db132 --- /dev/null +++ b/Ghidra/Processors/NDS32/data/languages/nds32.opinion @@ -0,0 +1,5 @@ + + + + + diff --git a/Ghidra/Processors/NDS32/data/languages/nds32.pspec b/Ghidra/Processors/NDS32/data/languages/nds32.pspec new file mode 100644 index 0000000000..d70bdf4abd --- /dev/null +++ b/Ghidra/Processors/NDS32/data/languages/nds32.pspec @@ -0,0 +1,155 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Ghidra/Processors/NDS32/data/languages/nds32.sinc b/Ghidra/Processors/NDS32/data/languages/nds32.sinc new file mode 100644 index 0000000000..141183a38d --- /dev/null +++ b/Ghidra/Processors/NDS32/data/languages/nds32.sinc @@ -0,0 +1,1625 @@ +### General ### + +define endian=big; +define alignment=2; +define space ram type=ram_space size=4 wordsize=1 default; +define space register type=register_space size=4; + +define space csreg type=ram_space size=2 wordsize=4; + +@define CSR_REG_START "0x0000" + +define register offset=0 size=4 +[a0 a1 a2 a3 a4 a5 s0 s1 s2 s3 s4 s5 s6 s7 s8 ta t0 t1 t2 t3 t4 t5 t6 t7 t8 t9 p0 p1 fp gp lp sp]; + +define register offset=0x90 size=4 +[pc mult_addr mult_inc]; + +define register offset=0x100 size=8 +[d0 d1]; + +define register offset=0x100 size=4 +[d0.hi d0.lo d1.hi d1.lo]; + +define register offset=0x200 size=4 +[ itb lb lc le ifc_lp + fpcsr fpcfg +]; + +define register offset=0x1000 size=4 +[ fs0 fs1 fs2 fs3 fs4 fs5 fs6 fs7 + fs8 fs9 fs10 fs11 fs12 fs13 fs14 fs15 + fs16 fs17 fs18 fs19 fs20 fs21 fs22 fs23 + fs24 fs25 fs26 fs27 fs28 fs29 fs30 fs31 +]; + +define register offset=0x1000 size=8 +[ fd0 fd1 fd2 fd3 fd4 fd5 fd6 fd7 + fd8 fd9 fd10 fd11 fd12 fd13 fd14 fd15 + fd16 fd17 fd18 fd19 fd20 fd21 fd22 fd23 + fd24 fd25 fd26 fd27 fd28 fd29 fd30 fd31 +]; + +define csreg offset=0x0a9 size=4 +[ + ipc +]; + +define register offset=0x300 size=8 contextreg; +define context contextreg + counter = (22,26) + regNum = (27,31) # register for load/store multiple instructions +; + +define token instr32(32) + OpSz = (31, 31) + Opc = (25, 30) + Rt = (20, 24) + Fst = (20, 24) + Fdt = (20, 24) + Rth = (21, 24) + Rtl = (21, 24) + Ra = (15, 19) + Fsa = (15, 19) + Fda = (15, 19) + Rb = (10, 14) + Fsb = (10, 14) + Fdb = (10, 14) + Rd = (5, 9) + Rs = (5, 9) + Sub5 = (0, 4) + Sub6 = (0, 5) + Sub7 = (0, 6) + Sub8 = (0, 7) + Sub3 = (7, 9) + fop4 = (6, 9) + cop4 = (0, 3) + f2op = (10, 14) + fcnd = (7, 9) + cmpe = (6, 6) + fbi = (7, 7) + cpn = (13, 14) + fsbi = (12, 12) + Imm8u = (7,14) + Imm5u = (10, 14) + Imm5s = (10, 14) signed + Br1t = (14, 14) + Br2t = (16, 19) + Alu2Mod = (6, 9) + Dtl = (22, 24) + Dt = (21, 21) + Dtlow = (21, 21) + Dthigh = (21, 21) + Dtr = (20, 20) + JIt = (24, 24) + Imm19s = (0, 18) signed + Imm18s = (0, 17) signed + Imm17s = (0, 16) signed + Imm16s = (0, 15) signed + Imm14s = (0, 13) signed + Imm15u = (0, 14) + Imm15s = (0, 14) signed + Imm20u = (0, 19) + Imm20s = (0, 19) signed + Imm24s = (0, 23) signed + Imm12s = (0, 11) signed + Imm11s = (8, 18) signed + Imm8s = (0, 7) signed + sv = (8, 9) + SrIdx = (10, 19) + Swid = (5, 19) + + CctlZ = (11, 14) + CctlLevel = (10, 10) + CctlSub = (5, 9) + + MsyncZ = (8, 19) + MsyncSub = (5, 7) + + DtIt = (8, 9) + Jz = (6, 7) + JrHint = (5, 5) + + ToggleL = (21, 24) + Toggle = (20, 20) + + Usr = (15, 19) + Group = (10, 14) + + DprefD = (24, 24) + DprefSub = (20, 23) + + TlbopSub = (5, 9) + + StandbyZ = (7, 9) + StandbySub = (5, 6) + + GpSub1 = (19, 19) + GpSub2 = (18, 19) + GpSub3 = (17, 19) + + sh = (5, 9) + + Bxxc = (19, 19) + + LsmwRa = (15, 19) + LsmwRb = (20, 24) + LsmwRb_ = (20, 24) + LsmwRe = (10, 14) + LsmwRe_ = (10, 14) + Enable4 = (6, 9) + Enable4_fp = (9, 9) + Enable4_gp = (8, 8) + Enable4_lp = (7, 7) + Enable4_sp = (6, 6) + LsmwLs = (5, 5) + LsmwBa = (4, 4) + LsmwId = (3, 3) + LsmwM = (2, 2) + LsmwSub = (0, 1) +; + +attach variables [Rt Rs Ra Rb Rd LsmwRa LsmwRb LsmwRe] [ + a0 a1 a2 a3 a4 a5 s0 s1 s2 s3 s4 s5 s6 s7 s8 ta t0 t1 t2 t3 t4 t5 t6 t7 t8 t9 p0 p1 fp gp lp sp +]; + +attach variables [Rtl] [ + a0 a2 a4 s0 s2 s4 s6 s8 t0 t2 t4 t6 t8 p0 fp lp +]; + +attach variables [Rth] [ + a1 a3 a5 s1 s3 s5 s7 ta t1 t3 t5 t7 t9 p1 gp sp +]; + +attach variables [Dt] [ + d0 d1 +]; + +attach variables [Dtlow] [ + d0.lo d1.lo +]; + +attach variables [Dthigh] [ + d0.hi d1.hi +]; + +attach variables [ Fst Fsa Fsb ] +[ fs0 fs1 fs2 fs3 fs4 fs5 fs6 fs7 + fs8 fs9 fs10 fs11 fs12 fs13 fs14 fs15 + fs16 fs17 fs18 fs19 fs20 fs21 fs22 fs23 + fs24 fs25 fs26 fs27 fs28 fs29 fs30 fs31 +]; + +attach variables [ Fdt Fda Fdb ] +[ fd0 fd1 fd2 fd3 fd4 fd5 fd6 fd7 + fd8 fd9 fd10 fd11 fd12 fd13 fd14 fd15 + fd16 fd17 fd18 fd19 fd20 fd21 fd22 fd23 + fd24 fd25 fd26 fd27 fd28 fd29 fd30 fd31 +]; + +@define I32 "(OpSz=0)" +@define LBGP "(Opc=0b010111)" +@define LWC "(Opc=0b011000)" +@define SWC "(Opc=0b011001)" +@define LDC "(Opc=0b011010)" +@define SDC "(Opc=0b011011)" +@define LSMW "(Opc=0b011101)" +@define MEM "(Opc=0b011100)" +@define HWGP "(Opc=0b011110)" +@define SBGP "(Opc=0b011111)" +@define ALU_1 "(Opc=0b100000)" +@define ALU_2 "(Opc=0b100001)" +@define JI "(Opc=0b100100)" +@define JREG "(Opc=0b100101)" +@define BR1 "(Opc=0b100110)" +@define BR2 "(Opc=0b100111)" +@define BR3 "(Opc=0b101101)" +@define MISC "(Opc=0b110010)" +@define COP "(Opc=0b110101)" +@define SIMD "(Opc=0b111000)" + +@define ALU2Z "(Alu2Mod=0b0000)" +@define GPR "(Alu2Mod=0b0001)" + + +### ALU Instruction with Immediate ### + +:addi Rt, Ra, Imm15s is $(I32) & Opc=0b101000 & Rt & Ra & Imm15s { Rt = Ra + Imm15s; } +:subri Rt, Ra, Imm15s is $(I32) & Opc=0b101001 & Rt & Ra & Imm15s { Rt = Imm15s - Ra; } +:andi Rt, Ra, Imm15u is $(I32) & Opc=0b101010 & Rt & Ra & Imm15u { Rt = Ra & Imm15u; } +:ori Rt, Ra, Imm15u is $(I32) & Opc=0b101100 & Rt & Ra & Imm15u { Rt = Ra | Imm15u; } +:xori Rt, Ra, Imm15u is $(I32) & Opc=0b101011 & Rt & Ra & Imm15u { Rt = Ra ^ Imm15u; } +:slti Rt, Ra, Imm15s is $(I32) & Opc=0b101110 & Rt & Ra & Imm15s { Rt = zext(Ra < Imm15s); } +:sltsi Rt, Ra, Imm15s is $(I32) & Opc=0b101111 & Rt & Ra & Imm15s { Rt = zext(Ra s< Imm15s); } +:movi Rt, Imm20s is $(I32) & Opc=0b100010 & Rt & Imm20s { Rt = Imm20s; } +:sethi Rt, Imm20u is $(I32) & Opc=0b100011 & Rt & Imm20u { Rt = Imm20u << 12;} + + +### ALU Instruction ### + +:add Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b00000 { Rt = Ra + Rb; } +:sub Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b00001 { Rt = Ra - Rb; } +:and Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b00010 { Rt = Ra & Rb; } +:xor Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b00011 { Rt = Ra ^ Rb; } +:or Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b00100 { Rt = Ra | Rb; } +:nor Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b00101 { Rt = ~(Ra | Rb); } +:slt Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b00110 { Rt = zext(Ra < Rb); } +:slts Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b00111 { Rt = zext(Ra s< Rb); } +:sva Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b11000 { Rt = zext(scarry(Ra, Rb)); } +:svs Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b11001 { Rt = zext(sborrow(Ra, Rb)); } +:seb Rt, Ra is $(I32) & $(ALU_1) & Rt & Ra & Rb=0b00000 & Rd=0 & Sub5=0b10000 { local tmp = Ra; Rt = sext(tmp:1); } +:seh Rt, Ra is $(I32) & $(ALU_1) & Rt & Ra & Rb=0b00000 & Rd=0 & Sub5=0b10001 { local tmp = Ra; Rt = sext(tmp:2); } +:zeb Rt, Ra is $(I32) & Opc=0b101010 & Rt & Ra & Imm15u=0xff { local tmp = Ra; Rt = zext(tmp:1); } +:zeh Rt, Ra is $(I32) & $(ALU_1) & Rt & Ra & Rb=0b00000 & Rd=0 & Sub5=0b10011 { local tmp = Ra; Rt = zext(tmp:2); } +:wsbh Rt, Ra is $(I32) & $(ALU_1) & Rt & Ra & Rb=0b00000 & Rd=0 & Sub5=0b10100 +{ + Rt = ((Ra & 0x000000ff) << 8) + | ((Ra & 0x0000ff00) >> 8) + | ((Ra & 0x00ff0000) << 8) + | ((Ra & 0xff000000) >> 8); +} + + +### Shifter Instruction ### + +:slli Rt, Ra, Imm5u is $(I32) & $(ALU_1) & Rt & Ra & Imm5u & Rd=0 & Sub5=0b01000 { Rt = Ra << Imm5u; } +:srli Rt, Ra, Imm5u is $(I32) & $(ALU_1) & Rt & Ra & Imm5u & Rd=0 & Sub5=0b01001 { Rt = Ra >> Imm5u; } +:srai Rt, Ra, Imm5u is $(I32) & $(ALU_1) & Rt & Ra & Imm5u & Rd=0 & Sub5=0b01010 { Rt = Ra s>> Imm5u; } +:rotri Rt, Ra, Imm5u is $(I32) & $(ALU_1) & Rt & Ra & Imm5u & Rd=0 & Sub5=0b01011 { Rt = (Ra >> Imm5u) | (Ra << (32 - Imm5u)); } +:sll Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b01100 { tmp:4 = Rb & 0b11111; Rt = Ra << tmp; } +:srl Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b01101 { tmp:4 = Rb & 0b11111; Rt = Ra >> tmp; } +:sra Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b01110 { tmp:4 = Rb & 0b11111; Rt = Ra s>> tmp; } +:rotr Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b01111 { tmp:4 = Rb & 0b11111; Rt = (Ra >> tmp) | (Ra << (32 - tmp)); } + + +### Multiply Instruction ### + +:mul Rt, Ra, Rb is $(I32) & $(ALU_2) & Rt & Ra & Rb & $(ALU2Z) & Sub6=0b100100 { Rt = Ra * Rb; } +:mults64 Dt, Ra, Rb is $(I32) & $(ALU_2) & Dtl=0 & Dt & Dtr=0 & Ra & Rb & $(ALU2Z) & Sub6=0b101000 { Dt = sext(Ra) * sext(Rb); } +:mult64 Dt, Ra, Rb is $(I32) & $(ALU_2) & Dtl=0 & Dt & Dtr=0 & Ra & Rb & $(ALU2Z) & Sub6=0b101001 { Dt = zext(Ra) * zext(Rb); } +:madds64 Dt, Ra, Rb is $(I32) & $(ALU_2) & Dtl=0 & Dt & Dtr=0 & Ra & Rb & $(ALU2Z) & Sub6=0b101010 { Dt = Dt + (sext(Ra) * sext(Rb)); } +:madd64 Dt, Ra, Rb is $(I32) & $(ALU_2) & Dtl=0 & Dt & Dtr=0 & Ra & Rb & $(ALU2Z) & Sub6=0b101011 { Dt = Dt + (zext(Ra) * zext(Rb)); } +:msubs64 Dt, Ra, Rb is $(I32) & $(ALU_2) & Dtl=0 & Dt & Dtr=0 & Ra & Rb & $(ALU2Z) & Sub6=0b101100 { Dt = Dt - (sext(Ra) * sext(Rb)); } +:msub64 Dt, Ra, Rb is $(I32) & $(ALU_2) & Dtl=0 & Dt & Dtr=0 & Ra & Rb & $(ALU2Z) & Sub6=0b101101 { Dt = Dt - (zext(Ra) * zext(Rb)); } +:mult32 Dtlow, Ra, Rb is $(I32) & $(ALU_2) & Dtl=0 & Dtlow & Dtr=0 & Ra & Rb & $(ALU2Z) & Sub6=0b110001 { Dtlow = Ra * Rb; } +:madd32 Dtlow, Ra, Rb is $(I32) & $(ALU_2) & Dtl=0 & Dtlow & Dtr=0 & Ra & Rb & $(ALU2Z) & Sub6=0b110011 { Dtlow = Dtlow + (Ra * Rb); } +:msub32 Dtlow, Ra, Rb is $(I32) & $(ALU_2) & Dtl=0 & Dtlow & Dtr=0 & Ra & Rb & $(ALU2Z) & Sub6=0b110101 { Dtlow = Dtlow - (Ra * Rb); } + + +# Group 0 +UsrName: d0.lo is Group=0 & Usr=0 & d0.lo { export d0.lo; } +UsrName: d0.hi is Group=0 & Usr=1 & d0.hi { export d0.hi; } +UsrName: d1.lo is Group=0 & Usr=2 & d1.lo { export d1.lo; } +UsrName: d1.hi is Group=0 & Usr=3 & d1.hi { export d1.hi; } +UsrName: lb is Group=0 & Usr=25 & lb { export lb; } +UsrName: le is Group=0 & Usr=26 & le { export le; } +UsrName: lc is Group=0 & Usr=27 & lc { export lc; } +UsrName: itb is Group=0 & Usr=28 & itb { export itb; } +UsrName: ifc_lp is Group=0 & Usr=29 & ifc_lp { export ifc_lp; } +#UsrName: pc is Group=0 & Usr=31 & pc { export pc; } # handled separately + +# Group 1 +UsrName: "dma_cfg" is Group=1 & Usr=0 { tmp:2 = 0x280; export *[csreg]:4 tmp; } +UsrName: "dma_gcsw" is Group=1 & Usr=1 { tmp:2 = 0x288; export *[csreg]:4 tmp; } +UsrName: "dma_chnsel" is Group=1 & Usr=2 { tmp:2 = 0x290; export *[csreg]:4 tmp; } +UsrName: "dma_act" is Group=1 & Usr=3 { tmp:2 = 0x298; export *[csreg]:4 tmp; } +UsrName: "dma_setup" is Group=1 & Usr=4 { tmp:2 = 0x2a0; export *[csreg]:4 tmp; } +UsrName: "dma_isaddr" is Group=1 & Usr=5 { tmp:2 = 0x2a8; export *[csreg]:4 tmp; } +UsrName: "dma_esaddr" is Group=1 & Usr=6 { tmp:2 = 0x2b0; export *[csreg]:4 tmp; } +UsrName: "dma_tcnt" is Group=1 & Usr=7 { tmp:2 = 0x2b8; export *[csreg]:4 tmp; } +UsrName: "dma_status" is Group=1 & Usr=8 { tmp:2 = 0x2c0; export *[csreg]:4 tmp; } +UsrName: "dma_2dset" is Group=1 & Usr=9 { tmp:2 = 0x2c8; export *[csreg]:4 tmp; } +UsrName: "dma_rcnt" is Group=1 & Usr=23 { tmp:2 = 0x2b9; export *[csreg]:4 tmp; } +UsrName: "dma_hstatus" is Group=1 & Usr=24 { tmp:2 = 0x2c1; export *[csreg]:4 tmp; } +UsrName: "dma_2dsctl" is Group=1 & Usr=25 { tmp:2 = 0x2c9; export *[csreg]:4 tmp; } + +# Group 2 +UsrName: "pfmc0" is Group=2 & Usr=0 { tmp:2 = 0x200; export *[csreg]:4 tmp; } +UsrName: "pfmc1" is Group=2 & Usr=1 { tmp:2 = 0x201; export *[csreg]:4 tmp; } +UsrName: "pfmc2" is Group=2 & Usr=2 { tmp:2 = 0x202; export *[csreg]:4 tmp; } +UsrName: "pfm_ctl" is Group=2 & Usr=4 { tmp:2 = 0x208; export *[csreg]:4 tmp; } + + +:mfusr Rt, UsrName is $(I32) & $(ALU_2) & Rt & UsrName & $(ALU2Z) & Sub6=0b100000 { Rt = UsrName; } +:mfusr Rt, pc is $(I32) & $(ALU_2) & Rt & Group=0 & Usr=0b11111 & $(ALU2Z) & Sub6=0b100000 & pc { Rt = inst_next; } +:mtusr Rt, UsrName is $(I32) & $(ALU_2) & Rt & UsrName & $(ALU2Z) & Sub6=0b100001 { UsrName = Rt; } +:mtusr Rt, pc is $(I32) & $(ALU_2) & Rt & Group=0 & Usr=0b11111 & $(ALU2Z) & Sub6=0b100001 & pc { pc = Rt; goto[pc]; } # Not sure this works correctly + + +### Divide Instructions ### + +:div Dt, Ra, Rb is $(I32) & $(ALU_2) & Dtl=0 & Dt & Dtlow & Dthigh & Dtr=0 & Ra & Rb & $(ALU2Z) & Sub6=0b101111 { Dtlow = Ra / Rb; Dthigh = Ra % Rb; } +:divs Dt, Ra, Rb is $(I32) & $(ALU_2) & Dtl=0 & Dt & Dtlow & Dthigh & Dtr=0 & Ra & Rb & $(ALU2Z) & Sub6=0b101110 { Dtlow = Ra s/ Rb; Dthigh = Ra s% Rb; } + + +### Load / Store Instruction (immediate) ### + +ByteOffset: off is Imm15s [ off = Imm15s << 0; ] { export *[const]:4 off; } +HalfOffset: off is Imm15s [ off = Imm15s << 1; ] { export *[const]:4 off; } +WordOffset: off is Imm15s [ off = Imm15s << 2; ] { export *[const]:4 off; } + +AddrByteRaImm15s: [Ra + ByteOffset] is Ra & ByteOffset { addr:4 = Ra + ByteOffset; export addr; } +AddrHalfRaImm15s: [Ra + HalfOffset] is Ra & HalfOffset { addr:4 = Ra + HalfOffset; export addr; } +AddrWordRaImm15s: [Ra + WordOffset] is Ra & WordOffset { addr:4 = Ra + WordOffset; export addr; } + +:lwi Rt, AddrWordRaImm15s is $(I32) & Opc=0b000010 & Rt & AddrWordRaImm15s { Rt = *AddrWordRaImm15s; } +:lhi Rt, AddrHalfRaImm15s is $(I32) & Opc=0b000001 & Rt & AddrHalfRaImm15s { local tmp:2 = *AddrHalfRaImm15s; Rt = zext(tmp); } +:lhsi Rt, AddrHalfRaImm15s is $(I32) & Opc=0b010001 & Rt & AddrHalfRaImm15s { local tmp:2 = *AddrHalfRaImm15s; Rt = sext(tmp); } +:lbi Rt, AddrByteRaImm15s is $(I32) & Opc=0b000000 & Rt & AddrByteRaImm15s { local tmp:1 = *AddrByteRaImm15s; Rt = zext(tmp); } +:lbsi Rt, AddrByteRaImm15s is $(I32) & Opc=0b010000 & Rt & AddrByteRaImm15s { local tmp:1 = *AddrByteRaImm15s; Rt = sext(tmp); } +:swi Rt, AddrWordRaImm15s is $(I32) & Opc=0b001010 & Rt & AddrWordRaImm15s { *AddrWordRaImm15s = Rt; } +:shi Rt, AddrHalfRaImm15s is $(I32) & Opc=0b001001 & Rt & AddrHalfRaImm15s { local tmp = Rt; *AddrHalfRaImm15s = tmp:2; } +:sbi Rt, AddrByteRaImm15s is $(I32) & Opc=0b001000 & Rt & AddrByteRaImm15s { local tmp = Rt; *AddrByteRaImm15s = tmp:1; } + +### Load / Store Instruction (immediate, postincr) ### + +:lwi.bi Rt, [Ra], WordOffset is $(I32) & Opc=0b000110 & Rt & Ra & WordOffset { Rt = *Ra; Ra = Ra + WordOffset; } +:lhi.bi Rt, [Ra], HalfOffset is $(I32) & Opc=0b000101 & Rt & Ra & HalfOffset { local tmp:2 = *Ra; Rt = zext(tmp); Ra = Ra + HalfOffset; } +:lhsi.bi Rt, [Ra], HalfOffset is $(I32) & Opc=0b010101 & Rt & Ra & HalfOffset { local tmp:2 = *Ra; Rt = sext(tmp); Ra = Ra + HalfOffset; } +:lbi.bi Rt, [Ra], ByteOffset is $(I32) & Opc=0b000100 & Rt & Ra & ByteOffset { local tmp:1 = *Ra; Rt = zext(tmp); Ra = Ra + ByteOffset; } +:lbsi.bi Rt, [Ra], ByteOffset is $(I32) & Opc=0b010100 & Rt & Ra & ByteOffset { local tmp:1 = *Ra; Rt = sext(tmp); Ra = Ra + ByteOffset; } +:swi.bi Rt, [Ra], WordOffset is $(I32) & Opc=0b001110 & Rt & Ra & WordOffset { *Ra = Rt; Ra = Ra + WordOffset; } +:shi.bi Rt, [Ra], HalfOffset is $(I32) & Opc=0b001101 & Rt & Ra & HalfOffset { local tmp = Rt; *Ra = tmp:2; Ra = Ra + HalfOffset; } +:sbi.bi Rt, [Ra], ByteOffset is $(I32) & Opc=0b001100 & Rt & Ra & ByteOffset { local tmp = Rt; *Ra = tmp:1; Ra = Ra + ByteOffset; } + + +### Load / Store Instruction (register) ### + +OffsetRbsv: (Rb "<<" sv) is Rb & sv { off:4 = Rb << sv; export off; } +AddrRaRbsv: [Ra + OffsetRbsv] is Ra & OffsetRbsv { addr:4 = Ra + OffsetRbsv; export addr; } + +:lw Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00000010 { Rt = *AddrRaRbsv; } +:lh Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00000001 { local tmp:2 = *AddrRaRbsv; Rt = zext(tmp); } +:lhs Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00010001 { local tmp:2 = *AddrRaRbsv; Rt = sext(tmp); } +:lb Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00000000 { local tmp:1 = *AddrRaRbsv; Rt = zext(tmp); } +:lbs Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00010000 { local tmp:1 = *AddrRaRbsv; Rt = sext(tmp); } +:sw Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00001010 { *AddrRaRbsv = Rt; } +:sh Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00001001 { local tmp = Rt; *AddrRaRbsv = tmp:2; } +:sb Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00001000 { local tmp = Rt; *AddrRaRbsv = tmp:1; } + + +### Load / Store Instruction (register, postincr) ### + +:lw.bi Rt, [Ra], OffsetRbsv is $(I32) & $(MEM) & Rt & Ra & OffsetRbsv & Sub8=0b00000110 { Rt = *Ra; Ra = Ra + OffsetRbsv; } +:lh.bi Rt, [Ra], OffsetRbsv is $(I32) & $(MEM) & Rt & Ra & OffsetRbsv & Sub8=0b00000101 { local tmp:2 = *Ra; Rt = zext(tmp); Ra = Ra + OffsetRbsv; } +:lhs.bi Rt, [Ra], OffsetRbsv is $(I32) & $(MEM) & Rt & Ra & OffsetRbsv & Sub8=0b00010101 { local tmp:2 = *Ra; Rt = sext(tmp); Ra = Ra + OffsetRbsv; } +:lb.bi Rt, [Ra], OffsetRbsv is $(I32) & $(MEM) & Rt & Ra & OffsetRbsv & Sub8=0b00000100 { local tmp:1 = *Ra; Rt = zext(tmp); Ra = Ra + OffsetRbsv; } +:lbs.bi Rt, [Ra], OffsetRbsv is $(I32) & $(MEM) & Rt & Ra & OffsetRbsv & Sub8=0b00010100 { local tmp:1 = *Ra; Rt = sext(tmp); Ra = Ra + OffsetRbsv; } +:sw.bi Rt, [Ra], OffsetRbsv is $(I32) & $(MEM) & Rt & Ra & OffsetRbsv & Sub8=0b00001110 { *Ra = Rt; Ra = Ra + OffsetRbsv; } +:sh.bi Rt, [Ra], OffsetRbsv is $(I32) & $(MEM) & Rt & Ra & OffsetRbsv & Sub8=0b00001101 { local tmp = Rt; *Ra = tmp:2; Ra = Ra + OffsetRbsv; } +:sb.bi Rt, [Ra], OffsetRbsv is $(I32) & $(MEM) & Rt & Ra & OffsetRbsv & Sub8=0b00001100 { local tmp = Rt; *Ra = tmp:1; Ra = Ra + OffsetRbsv; } + + +### Load / Store Multiple Word Instruction ### + + +@include "lsmw.sinc" + +LsmwBa_: "b" is LsmwBa=0 { } +LsmwBa_: "a" is LsmwBa=1 { } + +LsmwId_: "i" is LsmwId=0 { } +LsmwId_: "d" is LsmwId=1 { } + +LsmwM_: "" is LsmwRa & LsmwM=0 { } +LsmwM_: "m" is LsmwRa & LsmwM=1 { LsmwRa = mult_addr; } + + +:lmw.^LsmwBa_^LsmwId_^LsmwM_ LsmwRb, [LsmwRa], LsmwRe, Enable4 is ($(I32) & $(LSMW) & LsmwRb & LsmwRa & LsmwRe & Enable4 & LsmwLs=0 & LsmwBa_ & LsmwId_ & LsmwM_ & LsmwSub=0b00) ... & Lmw.regs +{ + mult_addr = LsmwRa; + build Lmw.regs; + build LsmwM_; +} + +:smw.^LsmwBa_^LsmwId_^LsmwM_ LsmwRb, [LsmwRa], LsmwRe, Enable4 is ($(I32) & $(LSMW) & LsmwRb & LsmwRa & LsmwRe & Enable4 & LsmwLs=1 & LsmwBa_ & LsmwId_ & LsmwM_ & LsmwSub=0b00) ... & Smw.regs +{ + mult_addr = LsmwRa; + build Smw.regs; + build LsmwM_; +} + + +### Load / Store Instruction for Atomic Updates ### + +:llw Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00011000 { Rt = *AddrRaRbsv; } +:scw Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00011001 { *AddrRaRbsv = Rt; } + + +### Load / Store Instructions with User-mode Privilege ### + +# TODO : special constraint (user-mode address translation) + +:lwup Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00100010 { Rt = *AddrRaRbsv; } +:swup Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00101010 { *AddrRaRbsv = Rt; } + + +### Jump Instruction ### + +Rel24: addr is Imm24s [ addr = inst_start + (Imm24s << 1); ] { export *:4 addr; } + +:j Rel24 is $(I32) & $(JI) & JIt=0 & Rel24 { goto Rel24; } +:jal Rel24 is $(I32) & $(JI) & JIt=1 & Rel24 { lp = inst_next; call Rel24; } +:jr Rb is $(I32) & $(JREG) & Rt=0 & Ra=0 & Rb & DtIt=0b00 & Jz=0 & JrHint=0 & Sub5=0b00000 { goto [Rb]; } +:ret Rb is $(I32) & $(JREG) & Rt=0 & Ra=0 & Rb & DtIt=0b00 & Jz=0 & JrHint=1 & Sub5=0b00000 { return [Rb]; } +:jral Rt,Rb is $(I32) & $(JREG) & Rt & Ra=0 & Rb & DtIt=0b00 & Jz=0 & JrHint=0 & Sub5=0b00001 { Rt = inst_next; call [Rb]; } + + +### Branch Instruction ### +Rel14: addr is Imm14s [ addr = inst_start + (Imm14s << 1); ] { export *:4 addr; } +Rel16: addr is Imm16s [ addr = inst_start + (Imm16s << 1); ] { export *:4 addr; } + +:beq Rt, Ra, Rel14 is $(I32) & $(BR1) & Rt & Ra & Br1t=0 & Rel14 { if(Rt == Ra) goto Rel14; } +:bne Rt, Ra, Rel14 is $(I32) & $(BR1) & Rt & Ra & Br1t=1 & Rel14 { if(Rt != Ra) goto Rel14; } +:beqz Rt, Rel16 is $(I32) & $(BR2) & Rt & Br2t=0b0010 & Rel16 { if(Rt == 0) goto Rel16; } +:bnez Rt, Rel16 is $(I32) & $(BR2) & Rt & Br2t=0b0011 & Rel16 { if(Rt != 0) goto Rel16; } +:bgez Rt, Rel16 is $(I32) & $(BR2) & Rt & Br2t=0b0100 & Rel16 { if(Rt s>= 0) goto Rel16; } +:bltz Rt, Rel16 is $(I32) & $(BR2) & Rt & Br2t=0b0101 & Rel16 { if(Rt s< 0) goto Rel16; } +:bgtz Rt, Rel16 is $(I32) & $(BR2) & Rt & Br2t=0b0110 & Rel16 { if(Rt s> 0) goto Rel16; } +:blez Rt, Rel16 is $(I32) & $(BR2) & Rt & Br2t=0b0111 & Rel16 { if(Rt s<= 0) goto Rel16; } + + +### Branch with link Instruction ### + +:bgezal Rt, Rel16 is $(I32) & $(BR2) & Rt & Br2t=0b1100 & Rel16 +{ + lp = inst_next; + if(Rt s>= 0) goto ; + call Rel16; + +} + +:bltzal Rt, Rel16 is $(I32) & $(BR2) & Rt & Br2t=0b1101 & Rel16 +{ + lp = inst_next; + if(Rt s< 0) goto ; + call Rel16; + +} + + +### Read / Write System Registers ### + +# TODO : special instruction, do we create the system registers ? +define pcodeop mfsr; +define pcodeop mtsr; + +csr: csr_reg is SrIdx [ csr_reg = $(CSR_REG_START) + SrIdx; ] { export *[csreg]:4 csr_reg; } + +:mfsr Rt, csr is $(I32) & $(MISC) & Rt & csr & Rd=0 & Sub5=0b00010 { Rt = csr; } +:mtsr Rt, csr is $(I32) & $(MISC) & Rt & csr & Rd=0 & Sub5=0b00011 { csr = Rt; } + + +### Jump Register with System Register Update ### + +# TODO : special constraint (address translation off) + +:jr.itoff Rb is $(I32) & $(JREG) & Rt=0 & Ra=0 & Rb & DtIt=0b01 & Jz=0 & JrHint=0 & Sub5=0b00000 { goto [Rb]; } +:jr.toff Rb is $(I32) & $(JREG) & Rt=0 & Ra=0 & Rb & DtIt=0b11 & Jz=0 & JrHint=0 & Sub5=0b00000 { goto [Rb]; } +:jral.iton Rt,Rb is $(I32) & $(JREG) & Rt & Ra=0 & Rb & DtIt=0b01 & Jz=0 & JrHint=0 & Sub5=0b00001 { Rt = inst_next; call [Rb]; } +:jral.ton Rt,Rb is $(I32) & $(JREG) & Rt & Ra=0 & Rb & DtIt=0b11 & Jz=0 & JrHint=0 & Sub5=0b00001 { Rt = inst_next; call [Rb]; } + + +### MMU Instruction ### + +define pcodeop TLB_TargetRead; +define pcodeop TLB_TargetWrite; +define pcodeop TLB_RWrite; +define pcodeop TLB_RWriteLock; +define pcodeop TLB_Unlock; +define pcodeop TLB_Probe; +define pcodeop TLB_Invalidate; +define pcodeop TLB_FlushAll; + +:tlbop Ra,"TargetRead" is $(I32) & $(MISC) & Rt & Ra & Rb=0 & TlbopSub=0 & Sub5=0b01110 { TLB_TargetRead(Ra:4); } +:tlbop Ra,"TargetWrite" is $(I32) & $(MISC) & Rt & Ra & Rb=0 & TlbopSub=1 & Sub5=0b01110 { TLB_TargetWrite(Ra:4); } +:tlbop Ra,"RWrite" is $(I32) & $(MISC) & Rt & Ra & Rb=0 & TlbopSub=2 & Sub5=0b01110 { TLB_RWrite(Ra:4); } +:tlbop Ra,"RWriteLock" is $(I32) & $(MISC) & Rt & Ra & Rb=0 & TlbopSub=3 & Sub5=0b01110 { TLB_RWriteLock(Ra:4); } +:tlbop Ra,"Unlock" is $(I32) & $(MISC) & Rt & Ra & Rb=0 & TlbopSub=4 & Sub5=0b01110 { TLB_Unlock(Ra:4); } +:tlbop Rt,Ra,"Probe" is $(I32) & $(MISC) & Rt & Ra & Rb=0 & TlbopSub=5 & Sub5=0b01110 { TLB_Probe(Rt:4, Ra:4); } +:tlbop Ra,"Invalidate" is $(I32) & $(MISC) & Rt & Ra & Rb=0 & TlbopSub=6 & Sub5=0b01110 { TLB_Invalidate(Ra:4); } +:tlbop "FlushAll" is $(I32) & $(MISC) & Rt & Ra & Rb=0 & TlbopSub=7 & Sub5=0b01110 { TLB_FlushAll(); } + + +### Conditional Move ### + +:cmovz Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b11010 +{ + if(Rb != 0) goto ; + Rt = Ra; + +} + +:cmovn Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b11011 +{ + if(Rb == 0) goto ; + Rt = Ra; + +} + + +### Synchronization Instruction ### + +# TODO : special function, and subfunctions + +define pcodeop msync; +define pcodeop isync; + +:msync MsyncSub is $(I32) & $(MISC) & Rt=0 & MsyncZ=0 & MsyncSub & Sub5=0b01100 { msync(MsyncSub:1); } +:isync Rt is $(I32) & $(MISC) & Rt & Ra=0 & Rb=0 & Rd=0 & Sub5=0b01101 { isync(Rt:4); } + +### Prefetch Instruction ### + +define pcodeop dpref; + +OffsetRbsv2: (Rb "<<" sv) is Rb & sv { off:4 = Rb << (sv + 1); export off; } +AddrRaRbsv2: [Ra + OffsetRbsv2] is Ra & OffsetRbsv2 { addr:4 = Ra + OffsetRbsv2; export addr; } + +:dpref DprefSub, AddrRaRbsv2 is $(I32) & $(MEM) & DprefD=0 & DprefSub & AddrRaRbsv2 & Sub8=0b00010011 { + dpref(DprefSub:1, AddrRaRbsv2:4); +} + +DprefD_: "w" is DprefD=0 { } +DprefD_: "d" is DprefD=1 { } + +DprefiAddr: [Ra + Offset] is DprefD=0 & Ra & Imm15s [ Offset = Imm15s << 2; ] { export *[const]:4 Offset; } +DprefiAddr: [Ra + Offset] is DprefD=1 & Ra & Imm15s [ Offset = Imm15s << 3; ] { export *[const]:4 Offset; } + +:dprefi.^DprefD_ DprefSub, DprefiAddr is $(I32) & Opc=0b010011 & DprefD_ & DprefSub & DprefiAddr { + dpref(DprefSub:1, DprefiAddr:4); +} + + +### NOP Instruction ### + +:nop is $(I32) & $(ALU_1) & Rt=0 & Ra=0 & Imm5u=0 & Rd=0 & Sub5=0b01001 { } + + +### Serialization Instruction ### + +define pcodeop dsb; +define pcodeop isb; + +:dsb is $(I32) & $(MISC) & Rt=0 & Ra=0 & Rb=0 & Rd=0 & Sub5=0b01000 { dsb(); } +:isb is $(I32) & $(MISC) & Rt=0 & Ra=0 & Rb=0 & Rd=0 & Sub5=0b01001 { isb(); } + + +### Exception Generation Instruction ### + +define pcodeop break; +define pcodeop syscall; +define pcodeop trap; + +:break Swid is $(I32) & $(MISC) & Rt=0 & Swid & Sub5=0b01010 { break(Swid:4); } +:syscall Swid is $(I32) & $(MISC) & Rt=0 & Swid & Sub5=0b01011 { syscall(Swid:4); } +:trap Swid is $(I32) & $(MISC) & Rt=0 & Swid & Sub5=0b00101 { trap(Swid:4); } + +:teqz Rt, Swid is $(I32) & $(MISC) & Rt & Swid & Sub5=0b00110 +{ + if(Rt != 0) goto ; + trap(Swid:4); + +} + +:tnez Rt, Swid is $(I32) & $(MISC) & Rt & Swid & Sub5=0b00111 +{ + if(Rt == 0) goto ; + trap(Swid:4); + +} + + +### Special Return Instruction ### + +:iret is $(I32) & $(MISC) & Rt=0 & Ra=0 & Rb=0 & Rd=0 & Sub5=0b00100 { return [ipc]; } + +# TODO : special constraint (address translation off) +:ret.itoff Rb is $(I32) & $(JREG) & Rt=0 & Ra=0 & Rb & DtIt=0b01 & Jz=0 & JrHint=1 & Sub5=0b00000 { return [Rb]; } +:ret.toff Rb is $(I32) & $(JREG) & Rt=0 & Ra=0 & Rb & DtIt=0b11 & Jz=0 & JrHint=1 & Sub5=0b00000 { return [Rb]; } + + +### Cache Control Instruction ### + +# TODO : special function, with subfunctions +define pcodeop cctl; + +:cctl Rt, Ra, CctlLevel, CctlSub is $(I32) & $(MISC) & Rt & Ra & CctlZ=0 & CctlLevel & CctlSub & Sub5=0b00001 { cctl(Rt:4, Ra:4, CctlLevel:1, CctlSub:1); } + + +# Miscellaneous Instructions (Baseline) + +# TODO : special function. Not sure if we use context or registers for this. + +define pcodeop setgie; + +SetgieEN: "d" is Toggle=0 { setgie(0:1); } +SetgieEN: "e" is Toggle=1 { setgie(1:1); } + +:setgie.^SetgieEN is $(I32) & $(MISC) & ToggleL=0 & SetgieEN & SrIdx=0b0010000000 & Rd=0b00010 & Sub5=0b00011 { } + +define pcodeop setend; + +SetendBE: "l" is Toggle=0 { setend(0:1); } +SetendBE: "b" is Toggle=1 { setend(1:1); } + +:setend.^SetendBE is $(I32) & $(MISC) & ToggleL=0 & SetendBE & SrIdx=0b0010000000 & Rd=0b00001 & Sub5=0b00011 { } + +:standby StandbySub is $(I32) & $(MISC) & Rt=0 & Ra=0 & Rb=0 & StandbyZ=0 & StandbySub & Sub5=0b00000 { goto inst_start; } + + + +### 32-bit Baseline V2 instructions ### + +### ALU Instructions ### + +:addi.gp is $(I32) & $(SBGP) & Rt & GpSub1=0b1 & Imm19s { Rt = gp + Imm19s; } + + +### Multiply and Divide Instructions (V2) ### + +:mulr64 Rt, Ra, Rb is $(I32) & $(ALU_2) & Rt & Ra & Rb & $(GPR) & Sub6=0b101001 & Rtl & Rth +{ + res:8 = zext(Ra) * zext(Rb); + Rtl = res[32,32]; + Rth = res[0,32]; + +} + +:mulsr64 Rt, Ra, Rb is $(I32) & $(ALU_2) & Rt & Ra & Rb & $(GPR) & Sub6=0b101000 & Rtl & Rth +{ + res:8 = sext(Ra) * sext(Rb); + Rtl = res[32,32]; + Rth = res[0,32]; +} + +:maddr32 Rt, Ra, Rb is $(I32) & $(ALU_2) & Rt & Ra & Rb & $(GPR) & Sub6=0b110011 { Rt = Rt + (Ra * Rb); } +:msubr32 Rt, Ra, Rb is $(I32) & $(ALU_2) & Rt & Ra & Rb & $(GPR) & Sub6=0b110101 { Rt = Rt - (Ra * Rb); } +:divr Rt, Rs, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rs & Sub5=0b10111 { local div = Ra / Rb; local mod = Ra % Rb; Rs = mod; Rt = div; } +:divsr Rt, Rs, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rs & Sub5=0b10110 { local div = Ra s/ Rb; local mod = Ra s% Rb; Rs = mod; Rt = div; } + + +### Load/Store Instructions ### + +GpByteAddress: [+ off] is Imm19s [ off = Imm19s << 0; ] { addr:4 = gp + off; export addr; } +GpHalfAddress: [+ off] is Imm18s [ off = Imm18s << 1; ] { addr:4 = gp + off; export addr; } +GpWordAddress: [+ off] is Imm17s [ off = Imm17s << 2; ] { addr:4 = gp + off; export addr; } + +:lbi.gp Rt, GpByteAddress is $(I32) & $(LBGP) & Rt & GpSub1=0b0 & GpByteAddress { local tmp:1 = *GpByteAddress; Rt = zext(tmp); } +:lbsi.gp Rt, GpByteAddress is $(I32) & $(LBGP) & Rt & GpSub1=0b1 & GpByteAddress { local tmp:1 = *GpByteAddress; Rt = sext(tmp); } +:lhi.gp Rt, GpHalfAddress is $(I32) & $(HWGP) & Rt & GpSub2=0b00 & GpHalfAddress { local tmp:2 = *GpHalfAddress; Rt = zext(tmp); } +:lhsi.gp Rt, GpHalfAddress is $(I32) & $(HWGP) & Rt & GpSub2=0b01 & GpHalfAddress { local tmp:2 = *GpHalfAddress; Rt = sext(tmp); } +:lwi.gp Rt, GpWordAddress is $(I32) & $(HWGP) & Rt & GpSub3=0b110 & GpWordAddress { Rt = *GpWordAddress; } +:sbi.gp Rt, GpByteAddress is $(I32) & $(SBGP) & Rt & GpSub1=0b0 & GpByteAddress { local tmp = Rt; *GpByteAddress = tmp:1; } +:shi.gp Rt, GpHalfAddress is $(I32) & $(HWGP) & Rt & GpSub2=0b10 & GpHalfAddress { local tmp = Rt; *GpHalfAddress = tmp:2; } +:swi.gp Rt, GpWordAddress is $(I32) & $(HWGP) & Rt & GpSub3=0b111 & GpWordAddress { *GpWordAddress = Rt; } + + +:lmwa.^LsmwBa_^LsmwId_^LsmwM_ LsmwRb, [LsmwRa], LsmwRe, Enable4 is ($(I32) & $(LSMW) & LsmwRb & LsmwRa & LsmwRe & Enable4 & LsmwLs=0 & LsmwBa_ & LsmwId_ & LsmwM_ & LsmwSub=0b01) ... & Lmwa.regs +{ + mult_addr = LsmwRa; + build Lmwa.regs; + build LsmwM_; +} + +:smwa.^LsmwBa_^LsmwId_^LsmwM_ LsmwRb, [LsmwRa], LsmwRe, Enable4 is ($(I32) & $(LSMW) & LsmwRb & LsmwRa & LsmwRe & Enable4 & LsmwLs=1 & LsmwBa_ & LsmwId_ & LsmwM_ & LsmwSub=0b01) ... & Smwa.regs +{ + mult_addr = LsmwRa; + build Smwa.regs; + build LsmwM_; +} + +:lbup Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00100000 { local tmp:1 = *AddrRaRbsv; Rt = zext(tmp); } +:sbup Rt, AddrRaRbsv is $(I32) & $(MEM) & Rt & AddrRaRbsv & Sub8=0b00101000 { local tmp = Rt; *AddrRaRbsv = tmp:1; } + + + +### 32-bit Baseline V3 instructions ### + +### ALU Instructions with Shift Operation (v3) ### + +:add_slli Rt, Ra, Rb, sh is $(I32) & $(ALU_1) & Rt & Ra & Rb & sh & Sub5=0b00000 { Rt = Ra + (Rb << sh); } +:and_slli Rt, Ra, Rb, sh is $(I32) & $(ALU_1) & Rt & Ra & Rb & sh & Sub5=0b00010 { Rt = Ra & (Rb << sh); } +:or_slli Rt, Ra, Rb, sh is $(I32) & $(ALU_1) & Rt & Ra & Rb & sh & Sub5=0b00100 { Rt = Ra | (Rb << sh); } +:sub_slli Rt, Ra, Rb, sh is $(I32) & $(ALU_1) & Rt & Ra & Rb & sh & Sub5=0b00001 { Rt = Ra - (Rb << sh); } +:xor_slli Rt, Ra, Rb, sh is $(I32) & $(ALU_1) & Rt & Ra & Rb & sh & Sub5=0b00011 { Rt = Ra ^ (Rb << sh); } + +:add_srli Rt, Ra, Rb, sh is $(I32) & $(ALU_1) & Rt & Ra & Rb & sh & Sub5=0b11100 { Rt = Ra + (Rb << sh); } +:and_srli Rt, Ra, Rb, sh is $(I32) & $(ALU_1) & Rt & Ra & Rb & sh & Sub5=0b11110 { Rt = Ra & (Rb << sh); } +:or_srli Rt, Ra, Rb, sh is $(I32) & $(ALU_1) & Rt & Ra & Rb & sh & Sub5=0b10101 { Rt = Ra | (Rb << sh); } +:sub_srli Rt, Ra, Rb, sh is $(I32) & $(ALU_1) & Rt & Ra & Rb & sh & Sub5=0b11101 { Rt = Ra - (Rb << sh); } +:xor_srli Rt, Ra, Rb, sh is $(I32) & $(ALU_1) & Rt & Ra & Rb & sh & Sub5=0b11111 { Rt = Ra ^ (Rb << sh); } + +### Conditional Branch and Jump Instructions (V3) ### + +Rel8: addr is Imm8s [ addr = inst_start + (Imm8s << 1); ] { export *:4 addr; } +:beqc Rt, Imm11s, Rel8 is $(I32) & $(BR3) & Rt & Bxxc=0 & Imm11s & Rel8 { if(Rt == Imm11s) goto Rel8; } +:bnec Rt, Imm11s, Rel8 is $(I32) & $(BR3) & Rt & Bxxc=1 & Imm11s & Rel8 { if(Rt != Imm11s) goto Rel8; } + +:jralnez Rt,Rb is $(I32) & $(JREG) & Rt & Ra=0 & Rb & DtIt=0b00 & Jz=0 & JrHint=0 & Sub5=0b00011 { if(Rb == 0) goto ; Rt = inst_next; call [Rb]; } +:jrnez Rb is $(I32) & $(JREG) & Rt=0 & Ra=0 & Rb & DtIt=0b00 & Jz=0 & JrHint=0 & Sub5=0b00010 { if(Rb == 0) goto ; goto [Rb]; } + +### Bit Manipulation Instructions (V3) ### + +:bitc Rt, Ra, Rb is $(I32) & $(ALU_1) & Rt & Ra & Rb & Rd=0 & Sub5=0b10010 { Rt = Ra & (~Rb); } +:bitci Rt, Ra, Imm15u is $(I32) & Opc=0b110011 & Rt & Ra & Imm15u { Rt = Ra & (~Imm15u); } + +### Cache Control Instruction (V3) ### + +# TODO: Add CCTL L1D_WBALL, level + + +### 32-bit ISA extension ### + +### ALU Instruction (Performance) ### + + +:abs Rt, Ra is $(I32) & $(ALU_2) & Rt & Ra & Rb=0 & $(ALU2Z) & Sub6=0b000011 +{ + gez:4 = zext(Ra s>= 0); + ltz:4 = zext(Ra s< 0); + Rt = (Ra * gez) | ((-Ra) * ltz); +} + +:ave Rt, Ra, Rb is $(I32) & $(ALU_2) & Rt & Ra & Rb & $(ALU2Z) & Sub6=0b000010 +{ + Rt = (Ra + Rb + 1) s>> 2; +} + +:max Rt, Ra, Rb is $(I32) & $(ALU_2) & Rt & Ra & Rb & $(ALU2Z) & Sub6=0b000000 +{ + altb:4 = zext(Ra s< Rb); + ageb:4 = zext(Ra s>= Rb); + Rt = (Ra * ageb) | (Rb * altb); +} + +:min Rt, Ra, Rb is $(I32) & $(ALU_2) & Rt & Ra & Rb & $(ALU2Z) & Sub6=0b000001 +{ + altb:4 = zext(Ra s< Rb); + ageb:4 = zext(Ra s>= Rb); + Rt = (Ra * altb) | (Rb * ageb); +} + +:bset Rt, Ra, Imm5u is $(I32) & $(ALU_2) & Rt & Ra & Imm5u & $(ALU2Z) & Sub6=0b001000 { Rt = Ra | (1 << Imm5u); } +:bclr Rt, Ra, Imm5u is $(I32) & $(ALU_2) & Rt & Ra & Imm5u & $(ALU2Z) & Sub6=0b001001 { Rt = Ra & ~(1 << Imm5u); } +:btgl Rt, Ra, Imm5u is $(I32) & $(ALU_2) & Rt & Ra & Imm5u & $(ALU2Z) & Sub6=0b001010 { Rt = Ra ^ (1 << Imm5u); } +:btst Rt, Ra, Imm5u is $(I32) & $(ALU_2) & Rt & Ra & Imm5u & $(ALU2Z) & Sub6=0b001011 { Rt = (Ra >> Imm5u) & 1; } + +:clips Rt, Ra, Imm5u is $(I32) & $(ALU_2) & Rt & Ra & Imm5u & $(ALU2Z) & Sub6=0b000100 +{ + local upper:4 = (1 << Imm5u) - 1; + local lower:4 = -(1 << Imm5u); + if(Ra s<= upper) goto ; + Rt = upper; + goto ; + + if(Ra s>= lower) goto ; + Rt = lower; + goto ; + + Rt = Ra; + +} +:clip Rt, Ra, Imm5u is $(I32) & $(ALU_2) & Rt & Ra & Imm5u & $(ALU2Z) & Sub6=0b000101 +{ + local upper:4 = (1 << Imm5u) - 1; + if(Ra s<= upper) goto ; + Rt = upper; + goto ; + + if(Ra s>= 0) goto ; + Rt = 0; + goto ; + + Rt = Ra; + +} + +:clz Rt, Ra is $(I32) & $(ALU_2) & Rt & Ra & Imm5u=0 & $(ALU2Z) & Sub6=0b000111 +{ + countTmp:4 = 0; + inputTmp:4 = Ra; + + + if ((inputTmp & 0x80000000) != 0) goto ; + + countTmp = countTmp + 1; + inputTmp = (inputTmp << 1) | 1; + goto ; + + + Rt = countTmp; +} + +:clo Rt, Ra is $(I32) & $(ALU_2) & Rt & Ra & Imm5u=0 & $(ALU2Z) & Sub6=0b000110 +{ + countTmp:4 = 0; + inputTmp:4 = Ra; + + + if ((inputTmp & 0x80000000) == 0) goto ; + + countTmp = countTmp + 1; + inputTmp = (inputTmp << 1) | 1; + goto ; + + + Rt = countTmp; +} + + +### Performance Extension V2 ### + + +# TODO : arithmetic functions: bs* +:bse is $(I32) & $(ALU_2) & Rt & Ra & Rb & $(ALU2Z) & Sub6=0b001100 unimpl +:bsp is $(I32) & $(ALU_2) & Rt & Ra & Rb & $(ALU2Z) & Sub6=0b001101 unimpl + +macro add_abs_diff(dst, src1, src2, shift) +{ + local src1_ = src1 >> shift; + local src2_ = src2 >> shift; + local src1__ = src1_:1; + local src2__ = src2_:1; + local a:1 = src1__ - src2__; + local agez:1 = zext(a s>= 0); + local altz:1 = zext(a s< 0); + local aabs:1 = (a * agez) | ((-a) * altz); + dst = dst + zext(aabs); +} +:pbsad Rt, Ra, Rb is $(I32) & $(SIMD) & Rt & Ra & Rb & Rd=0 & Sub5=0b0000 +{ + Rt = 0; + add_abs_diff(Rt, Ra, Rb, 0); + add_abs_diff(Rt, Ra, Rb, 8); + add_abs_diff(Rt, Ra, Rb, 16); + add_abs_diff(Rt, Ra, Rb, 24); +} +:pbsada Rt, Ra, Rb is $(I32) & $(SIMD) & Rt & Ra & Rb & Rd=0 & Sub5=0b0001 +{ + add_abs_diff(Rt, Ra, Rb, 0); + add_abs_diff(Rt, Ra, Rb, 8); + add_abs_diff(Rt, Ra, Rb, 16); + add_abs_diff(Rt, Ra, Rb, 24); +} + + +# 32-bit String Extension +:ffb Rt, Ra, Rb is $(I32) & $(ALU_2) & Rt & Ra & Rb & Sub3=0 & Sub7=0b0001110 { + match:1 = Rb[0,8]; + m1:1 = (Ra[0,8] == match); + m2:1 = (Ra[8,8] == match); + m3:1 = (Ra[16,8] == match); + m4:1 = (Ra[24,8] == match); + Rt = -4; + if (m1) goto inst_next; + Rt = -3; + if (m2) goto inst_next; + Rt = -2; + if (m3) goto inst_next; + Rt = -1; + if (m4) goto inst_next; + Rt = 0; + # choosery method + # rd = 0 + (zext(m1)*-4) + (zext(m2)*-3) + (zext(m3)*-2) + (zext(m4)*-1); +} + +:ffbi Rt, Ra, Imm8u is $(I32) & $(ALU_2) & Rt & Ra & Imm8u & Sub7=0b1001110 { + match:1 = Imm8u; + m1:1 = (Ra[0,8] == match); + m2:1 = (Ra[8,8] == match); + m3:1 = (Ra[16,8] == match); + m4:1 = (Ra[24,8] == match); + Rt = -4; + if (m1) goto inst_next; + Rt = -3; + if (m2) goto inst_next; + Rt = -2; + if (m3) goto inst_next; + Rt = -1; + if (m4) goto inst_next; + Rt = 0; +} + +:ffmism Rt, Ra, Rb is $(I32) & $(ALU_2) & Rt & Ra & Rb & Sub3=0 & Sub7=0b0001111 { + match:1 = Rb[0,8]; + m1:1 = (Ra[0,8] != Rb[0,8]); + m2:1 = (Ra[8,8] != Rb[8,8]); + m3:1 = (Ra[16,8] != Rb[16,8]); + m4:1 = (Ra[24,8] != Rb[24,8]); +@if ENDIAN == "little" + Rt = -4; + if (m1) goto inst_next; + Rt = -3; + if (m2) goto inst_next; + Rt = -2; + if (m3) goto inst_next; + Rt = -1; + if (m4) goto inst_next; + Rt = 0; + # choosery method + # rd = 0 + (zext(m1)*-4) + (zext(m2)*-3) + (zext(m3)*-2) + (zext(m4)*-1); +@else + Rt = -4; + if (m4) goto inst_next; + Rt = -3; + if (m3) goto inst_next; + Rt = -2; + if (m2) goto inst_next; + Rt = -1; + if (m1) goto inst_next; + Rt = 0; +@endif +} + +:flmism Rt, Ra, Rb is $(I32) & $(ALU_2) & Rt & Ra & Rb & Sub3=0 & Sub7=0b1001111 { + match:1 = Rb[0,8]; + m1:1 = (Ra[0,8] != Rb[0,8]); + m2:1 = (Ra[8,8] != Rb[8,8]); + m3:1 = (Ra[16,8] != Rb[16,8]); + m4:1 = (Ra[24,8] != Rb[24,8]); +@if ENDIAN == "little" + Rt = -1; + if (m4) goto inst_next; + Rt = -2; + if (m3) goto inst_next; + Rt = -3; + if (m2) goto inst_next; + Rt = -4; + if (m1) goto inst_next; + Rt = 0; + # choosery method + # rd = 0 + (zext(m1)*-4) + (zext(m2)*-3) + (zext(m3)*-2) + (zext(m4)*-1); +@else + Rt = -1; + if (m1) goto inst_next; + Rt = -2; + if (m2) goto inst_next; + Rt = -3; + if (m3) goto inst_next; + Rt = -4; + if (m4) goto inst_next; + Rt = 0; +@endif +} + +########### 16b ############ + +define token instr16(16) + opsz = (15, 15) + opc4 = (11, 14) + opc5 = (10, 14) + opc6 = (9, 14) + opc7 = (8, 14) + opc8 = (7, 14) + opc10 = (5, 14) + re2 = (5, 6) + rt5 = (5, 9) + ra4 = (5, 8) + rt4 = (5, 8) + ra5 = (0, 4) + rb5 = (0, 4) + rt5b = (0, 4) + rt3 = (6, 8) + rt3b = (8, 10) + ra3 = (3, 5) + rb3 = (0, 2) + bit5 = (5,5) + bit6 = (6,6) + bit7 = (7,7) + bit8 = (8,8) + imm3u = (0, 2) + imm3ub = (3, 5) + imm4u = (5, 8) + imm5u = (0, 4) + imm5s = (0, 4) signed + imm6u = (0, 5) + imm7u = (0, 6) + imm8s = (0, 7) signed + imm10s = (0, 9) signed + xwi37_ls = (7, 7) + swid9 = (0, 8) + rt5e1 = (4, 7) + rt5e2 = (4, 7) + ra5e1 = (0, 3) + ra5e2 = (0, 3) +; + +attach variables [rt5 ra5 rb5 rt5b] [ + a0 a1 a2 a3 a4 a5 s0 s1 s2 s3 s4 s5 s6 s7 s8 ta t0 t1 t2 t3 t4 t5 t6 t7 t8 t9 p0 p1 fp gp lp sp +]; + +attach variables [ra4 rt4] [ + a0 a1 a2 a3 a4 a5 s0 s1 s2 s3 s4 s5 t0 t1 t2 t3 +]; + +attach variables [rt3 ra3 rt3b rb3] [ + a0 a1 a2 a3 a4 a5 s0 s1 +]; + +attach variables [ra5e1 rt5e1] [ + a0 a2 a4 s0 s2 s4 s6 s8 t0 t2 t4 t6 t8 p0 fp lp +]; +attach variables [ra5e2 rt5e2] [ + a1 a3 a5 s1 s3 s5 s7 ta t1 t3 t5 t7 t9 p1 gp sp +]; + +attach variables [re2] [ + s0 s2 s4 s8 +]; + + +@define I16 "(opsz=1)" +@define BFMI333 "(opc6=0b001011)" +@define XWI37 "(opc4=0b0111)" +@define XWI37SP "(opc4=0b1110)" +@define MISC33 "(opc6=0b111111)" + + +### Move Instruction ### + +:movi55 rt5, imm5s is $(I16) & opc5=0b00001 & rt5 & imm5s { rt5 = imm5s; } +:mov55 rt5, ra5 is $(I16) & opc5=0b00000 & rt5 & ra5 { rt5 = ra5; } + + +### Add/Sub Instruction with Immediate ### + +:addi45 rt4, imm5u is $(I16) & opc6=0b000110 & rt4 & imm5u { rt4 = rt4 + imm5u; } +:addi333 rt3, ra3, imm3u is $(I16) & opc6=0b001110 & rt3 & ra3 & imm3u { rt3 = ra3 + imm3u; } +:subi45 rt4, imm5u is $(I16) & opc6=0b000111 & rt4 & imm5u { rt4 = rt4 - imm5u; } +:subi333 rt3, ra3, imm3u is $(I16) & opc6=0b001111 & rt3 & ra3 & imm3u { rt3 = ra3 - imm3u; } + + +### Add/Sub Instruction ### + +:add45 rt4, rb5 is $(I16) & opc6=0b000100 & rt4 & rb5 { rt4 = rt4 + rb5; } +:add333 rt3, ra3, rb3 is $(I16) & opc6=0b001100 & rt3 & ra3 & rb3 { rt3 = ra3 + rb3; } +:sub45 rt4, rb5 is $(I16) & opc6=0b000101 & rt4 & rb5 { rt4 = rt4 - rb5; } +:sub333 rt3, ra3, rb3 is $(I16) & opc6=0b001101 & rt3 & ra3 & rb3 { rt3 = ra3 - rb3; } + + +### Shift Instruction with Immediate ### + +:srai45 rt4, imm5u is $(I16) & opc6=0b001000 & rt4 & imm5u { rt4 = rt4 s>> imm5u; } +:srli45 rt4, imm5u is $(I16) & opc6=0b001001 & rt4 & imm5u { rt4 = rt4 >> imm5u; } +:slli333 rt3, ra3, imm3u is $(I16) & opc6=0b001010 & rt3 & ra3 & imm3u { rt3 = ra3 << imm3u; } + + +### Bit Field Mask Instruction with Immediate ### + +:zeb33 rt3, ra3 is $(I16) & $(BFMI333) & rt3 & ra3 & imm3u=0b000 { local tmp = ra3; rt3 = zext(tmp:1); } +:zeh33 rt3, ra3 is $(I16) & $(BFMI333) & rt3 & ra3 & imm3u=0b001 { local tmp = ra3; rt3 = zext(tmp:2); } +:seb33 rt3, ra3 is $(I16) & $(BFMI333) & rt3 & ra3 & imm3u=0b010 { local tmp = ra3; rt3 = sext(tmp:1); } +:seh33 rt3, ra3 is $(I16) & $(BFMI333) & rt3 & ra3 & imm3u=0b011 { local tmp = ra3; rt3 = sext(tmp:2); } +:xlsb33 rt3, ra3 is $(I16) & $(BFMI333) & rt3 & ra3 & imm3u=0b100 { rt3 = ra3 & 1; } +:x11b33 rt3, ra3 is $(I16) & $(BFMI333) & rt3 & ra3 & imm3u=0b101 { rt3 = ra3 & 0x7ff; } + + +### Load / Store Instruction ### + +:lwi450 rt4,[ra5] is $(I16) & opc6=0b011010 & rt4 & ra5 { rt4 = *ra5; } + +rel3w: off is imm3u [ off = imm3u << 2; ] { export *[const]:4 off; } +rel3h: off is imm3u [ off = imm3u << 1; ] { export *[const]:4 off; } +rel3b: off is imm3u [ off = imm3u << 0 ; ] { export *[const]:4 off; } +ra3_rel3w: [ra3 + rel3w] is ra3 & rel3w { addr:4 = ra3 + rel3w; export addr; } +ra3_rel3h: [ra3 + rel3h] is ra3 & rel3h { addr:4 = ra3 + rel3h; export addr; } +ra3_rel3b: [ra3 + rel3b] is ra3 & rel3b { addr:4 = ra3 + rel3b; export addr; } + +:lwi333 rt3, ra3_rel3w is $(I16) & opc6=0b010000 & rt3 & ra3_rel3w { rt3 = *ra3_rel3w; } +:lwi333.bi rt3, [ra3], rel3w is $(I16) & opc6=0b010001 & rt3 & ra3 & rel3w { rt3 = *ra3; ra3 = ra3 + rel3w; } +:lhi333 rt3, ra3_rel3h is $(I16) & opc6=0b010010 & rt3 & ra3_rel3h { local tmp:2 = *ra3_rel3h; rt3 = zext(tmp); } +:lbi333 rt3, ra3_rel3b is $(I16) & opc6=0b010011 & rt3 & ra3_rel3b { local tmp:1 = *ra3_rel3b; rt3 = zext(tmp); } +:swi450 rt4, [ra5] is $(I16) & opc6=0b011011 & rt4 & ra5 { *ra5 = rt4; } +:swi333 rt3, ra3_rel3w is $(I16) & opc6=0b010100 & rt3 & ra3_rel3w { *ra3_rel3w = rt3; } +:swi333.bi rt3, [ra3], rel3w is $(I16) & opc6=0b010101 & rt3 & ra3 & rel3w { *ra3 = rt3; ra3 = ra3 + rel3w; } +:shi333 rt3, ra3_rel3h is $(I16) & opc6=0b010110 & rt3 & ra3_rel3h { local tmp = rt3; *ra3_rel3h = tmp:2; } +:sbi333 rt3, ra3_rel3b is $(I16) & opc6=0b010111 & rt3 & ra3_rel3b { local tmp = rt3; *ra3_rel3b = tmp:1; } + + +### Load/Store Instruction with Implied FP ### + +rel7w: off is imm7u [ off = imm7u << 2; ] { export *[const]:4 off; } +fp_rel7w: [fp + rel7w] is fp & rel7w { addr:4 = fp + rel7w; export addr; } + +:lwi37 rt3b, fp_rel7w is $(I16) & rt3b & $(XWI37) & xwi37_ls=0 & fp_rel7w { rt3b = *fp_rel7w; } +:swi37 rt3b, fp_rel7w is $(I16) & rt3b & $(XWI37) & xwi37_ls=1 & fp_rel7w { *fp_rel7w = rt3b; } + + +### Branch and Jump Instruction ### + +rel8: addr is imm8s [ addr = inst_start + (imm8s << 1); ] { export *:4 addr; } + + +:beqs38 rt3b,rel8 is $(I16) & opc4=0b1010 & rt3b & rel8 { if(a5 == rt3b) goto rel8; } +:bnes38 rt3b,rel8 is $(I16) & opc4=0b1011 & rt3b & rel8 { if(a5 != rt3b) goto rel8; } +:beqz38 rt3b,rel8 is $(I16) & opc4=0b1000 & rt3b & rel8 { if(rt3b == 0) goto rel8; } +:bnez38 rt3b,rel8 is $(I16) & opc4=0b1001 & rt3b & rel8 { if(rt3b != 0) goto rel8; } + +:j8 rel8 is $(I16) & opc7=0b1010101 & rel8 { goto rel8; } +:jr5 rb5 is $(I16) & opc10=0b1011101000 & rb5 { goto [rb5]; } +:ret5 rb5 is $(I16) & opc10=0b1011101100 & rb5 { return [rb5]; } +:jral5 rb5 is $(I16) & opc10=0b1011101001 & rb5 { lp = inst_next; call [rb5]; } + + +### Compare and Branch Instruction ### + +:slti45 ra4, imm5u is $(I16) & opc6=0b110011 & ra4 & imm5u { ta = zext(ra4 < imm5u); } +:sltsi45 ra4, imm5u is $(I16) & opc6=0b110010 & ra4 & imm5u { ta = zext(ra4 s< imm5u); } +:slt45 ra4, rb5 is $(I16) & opc6=0b110001 & ra4 & rb5 { ta = zext(ra4 < rb5); } +:slts45 ra4, rb5 is $(I16) & opc6=0b110000 & ra4 & rb5 { ta = zext(ra4 s< rb5); } + +:beqzs8 rel8 is $(I16) & opc7=0b1101000 & rel8 { if(ta == 0) goto rel8; } +:bnezs8 rel8 is $(I16) & opc7=0b1101001 & rel8 { if(ta != 0) goto rel8; } + + +### Misc Instruction ### + +# V3 doesn't allow break16 with SWID greater than 31 +:break16 swid9 is $(I16) & opc6=0b110101 & imm4u=0 & swid9 { break(swid9:4); } +:nop16 is $(I16) & opc6=0b001001 & rt4=0 & imm5u=0 { } + + +### ALU Instructions (V2) ### + +:addi10.sp imm10s is $(I16) & opc5=0b11011 & imm10s { sp = sp + imm10s; } + + +### Load/Store Instruction (V2) ### + +sp_rel7w: [+ rel7w] is rel7w { addr:4 = sp + rel7w; export addr; } + +:lwi37.sp rt3b, sp_rel7w is $(I16) & rt3b & $(XWI37SP) & xwi37_ls=0 & sp_rel7w { rt3b = *sp_rel7w; } +:swi37.sp rt3b, sp_rel7w is $(I16) & rt3b & $(XWI37SP) & xwi37_ls=1 & sp_rel7w { *sp_rel7w = rt3b; } + + + +### 16-bit Baseline V3 instructions ### + +### ALU Instructions (V3 16-bit) ### + +imm6u_: imm8 is imm6u [ imm8 = imm6u << 2; ] { export *[const]:4 imm8; } +:addri36.sp rt3, imm6u_ is $(I16) & opc6=0b011000 & rt3 & imm6u_ { rt3 = sp + imm6u_; } +:add5.pc rt5b is $(I16) & opc10=0b1011101101 & rt5b { rt5b = pc + rt5b; } +:and33 rt3, ra3 is $(I16) & $(MISC33) & rt3 & ra3 & imm3u=0b110 { rt3 = rt3 & ra3; } +:neg33 rt3, ra3 is $(I16) & $(MISC33) & rt3 & ra3 & imm3u=0b010 { rt3 = -ra3; } +:not33 rt3, ra3 is $(I16) & $(MISC33) & rt3 & ra3 & imm3u=0b011 { rt3 = ~ra3; } +:or33 rt3, ra3 is $(I16) & $(MISC33) & rt3 & ra3 & imm3u=0b111 { rt3 = rt3 | ra3; } +:xor33 rt3, ra3 is $(I16) & $(MISC33) & rt3 & ra3 & imm3u=0b101 { rt3 = rt3 ^ ra3; } + +### Bit Manipulation Instructions (V3 16-bit) ### + +:bmski33 rt3, imm3ub is $(I16) & opc6=0b001011 & rt3 & imm3ub & imm3u=0b110 { rt3 = (rt3 >> imm3ub) & 1; } +:fexti33 rt3, imm3ub is $(I16) & opc6=0b001011 & rt3 & imm3ub & imm3u=0b111 { rt3 = rt3 & ((1 << (imm3ub + 1)) - 1); } + +### Misc. Instructions (V3 16-bit) ### + +imm7n: off is imm5u [ off = -((32 - imm5u) << 2); ] { export *[const]:4 off; } +:lwi45.fe rt4, [imm7n] is $(I16) & opc6=0b011001 & rt4 & imm7n { addr:4 = s2 + imm7n; rt4 = *addr; } + +:movd44 rt5e1, ra5e1 is $(I16) & opc7=0b1111101 & rt5e1 & rt5e2 & ra5e1 & ra5e2 { rt5e1 = ra5e1; rt5e2 = ra5e2; } + +imm5u_: imm6 is imm5u [ imm6 = imm5u + 16; ] { export *[const]:4 imm6; } +:movpi45 rt4, imm5u_ is $(I16) & opc6=0b111101 & rt4 & imm5u_ { rt4 = imm5u_; } + +:mul33 rt3, ra3 is $(I16) & $(MISC33) & rt3 & ra3 & imm3u=0b100 { rt3 = rt3 * ra3; } + +# Note: POP25 and PUSH25 are highly untested ! And they just look messy :/ +imm5u__: imm8 is imm5u [ imm8 = imm5u << 3; ] { export *[const]:4 imm8; } + +macro push25_special() { Smwad(lp); Smwad(gp); Smwad(fp); } +macro push25_s0() { Smwad(s0); } +macro push25_s2() { Smwad(s2); Smwad(s1); push25_s0(); } +macro push25_s4() { Smwad(s4); Smwad(s3); push25_s2(); } +macro push25_s8() { Smwad(s8); Smwad(s7); Smwad(s6); Smwad(s5); push25_s4(); } + +push25_re: re2 is re2 & re2=0 { push25_s0(); } +push25_re: re2 is re2 & re2=1 { push25_s2(); } +push25_re: re2 is re2 & re2=2 { push25_s4(); } +push25_re: re2 is re2 & re2=3 { push25_s8(); } + +:push25 push25_re, imm5u__ is $(I16) & opc8=0b11111000 & re2 & push25_re & imm5u__ { + mult_addr = sp; + push25_special(); + build push25_re; + sp = mult_addr - imm5u__; + if(re2 < 1) goto ; + s2 = pc & 0xfffffffc; + +} + +macro pop25_special() { LmwOp(fp); LmwOp(gp); LmwOp(lp); } +macro pop25_s0() { LmwOp(s0); } +macro pop25_s2() { pop25_s0(); LmwOp(s1); LmwOp(s2); } +macro pop25_s4() { pop25_s2(); LmwOp(s3); LmwOp(s4); } +macro pop25_s8() { pop25_s4(); LmwOp(s5); LmwOp(s6); LmwOp(s7); LmwOp(s8); } + +pop25_re: re2 is re2 & re2=0 { pop25_s0(); } +pop25_re: re2 is re2 & re2=1 { pop25_s2(); } +pop25_re: re2 is re2 & re2=2 { pop25_s4(); } +pop25_re: re2 is re2 & re2=3 { pop25_s8(); } + +:pop25 pop25_re, imm5u__ is $(I16) & opc8=0b11111001 & re2 & pop25_re & imm5u__ { + mult_addr = sp; + build pop25_re; + pop25_special(); + sp = mult_addr + imm5u__; + return [lp]; +} + + +# EX9.IT + +imm9u_: imm9 is imm5u & imm4u [ imm9 = (imm4u << 5) | imm5u; ] { export *[const]:4 imm9; } +define pcodeop ex9; + +# TODO: Depending on the value of ITB.HW the address is either set by hardware or set by ITB.Addr +:ex9.it imm9u_ is $(I16) & opc6=0b110101 & (bit5=1 | bit6=1 | bit7=1 | bit8=1) & imm9u_ { + ex9(imm9u_); +} + +:ex9.it imm5u is $(I16) & opc10=0b1011101010 & imm5u { + ex9(imm5u:4); +} + + +########################## +# Floating Point Extension + +# FPU_FS1 +define pcodeop fadds; +:fadds Fst, Fsa, Fsb is $(I32) & $(COP) & fop4=0x0 & Fst & Fsa & Fsb & cop4=0x0 { + Fst = fadds(Fsa, Fsb); +} + +define pcodeop fsubs; +:fsubs Fst, Fsa, Fsb is $(I32) & $(COP) & fop4=0x1 & Fst & Fsa & Fsb & cop4=0x0 { + Fst = fsubs(Fsa, Fsb); +} + +define pcodeop fcpynss; +:fcpynss Fst, Fsa, Fsb is $(I32) & $(COP) & fop4=0x2 & Fst & Fsa & Fsb & cop4=0x0 { + Fst = fcpynss(Fsa, Fsb); +} + +define pcodeop fcpyss; +:fcpyss Fst, Fsa, Fsb is $(I32) & $(COP) & fop4=0x3 & Fst & Fsa & Fsb & cop4=0x0 { + Fst = fcpyss(Fsa, Fsb); +} + +define pcodeop fmadds; +:fmadds Fst, Fsa, Fsb is $(I32) & $(COP) & fop4=0x4 & Fst & Fsa & Fsb & cop4=0x0 { + Fst = fmadds(Fsa, Fsb); +} + +define pcodeop fmsubs; +:fmsubs Fst, Fsa, Fsb is $(I32) & $(COP) & fop4=0x5 & Fst & Fsa & Fsb & cop4=0x0 { + Fst = fmsubs(Fsa, Fsb); +} + +define pcodeop fcmovns; +:fcmovns Fst, Fsa, Fsb is $(I32) & $(COP) & fop4=0x6 & Fst & Fsa & Fsb & cop4=0x0 { + Fst = fcmovns(Fsa, Fsb); +} + +define pcodeop fcmovzs; +:fcmovzs Fst, Fsa, Fsb is $(I32) & $(COP) & fop4=0x7 & Fst & Fsa & Fsb & cop4=0x0 { + Fst = fcmovzs(Fsa, Fsb); +} + +define pcodeop fnmadds; +:fnmadds Fst, Fsa, Fsb is $(I32) & $(COP) & fop4=0x8 & Fst & Fsa & Fsb & cop4=0x0 { + Fst = fnmadds(Fsa, Fsb); +} + +define pcodeop fnmsubs; +:fnmsubs Fst, Fsa, Fsb is $(I32) & $(COP) & fop4=0x9 & Fst & Fsa & Fsb & cop4=0x0 { + Fst = fnmsubs(Fsa, Fsb); +} + +define pcodeop fmuls; +:fmuls Fst, Fsa, Fsb is $(I32) & $(COP) & fop4=0xa & Fst & Fsa & Fsb & cop4=0x0 { + Fst = fmuls(Fsa, Fsb); +} + +define pcodeop fdivs; +:fdivs Fst, Fsa, Fsb is $(I32) & $(COP) & fop4=0xb & Fst & Fsa & Fsb & cop4=0x0 { + Fst = fdivs(Fsa, Fsb); +} + +# FPU_FS1_F2OP + +define pcodeop fs2d; +:fs2d Fdt, Fsa is $(I32) & $(COP) & fop4=0xf & Fdt & Fsa & f2op=0 & cop4=0x0 { + Fdt = fs2d(Fsa); +} + +define pcodeop fsqrts; +:fsqrts Fst, Fsa is $(I32) & $(COP) & fop4=0xf & Fst & Fsa & f2op=1 & cop4=0x0 { + Fst = fsqrts(Fsa); +} + +define pcodeop fabss; +:fabss Fst, Fsa is $(I32) & $(COP) & fop4=0xf & Fst & Fsa & f2op=0x5 & cop4=0x0 { + Fst = fabss(Fsa); +} + +define pcodeop fui2s; +:fui2s Fst, Fsa is $(I32) & $(COP) & fop4=0xf & Fst & Fsa & f2op=0x8 & cop4=0x0 { + Fst = fui2s(Fsa); +} + +define pcodeop fsi2s; +:fsi2s Fst, Fsa is $(I32) & $(COP) & fop4=0xf & Fst & Fsa & f2op=0xc & cop4=0x0 { + Fst = fsi2s(Fsa); +} + +define pcodeop fs2ui; +:fs2ui Fst, Fsa is $(I32) & $(COP) & fop4=0xf & Fst & Fsa & f2op=0x10 & cop4=0x0 { + Fst = fs2ui(Fsa); +} + +define pcodeop fs2ui.z; +:fs2ui.z Fst, Fsa is $(I32) & $(COP) & fop4=0xf & Fst & Fsa & f2op=0x14 & cop4=0x0 { + Fst = fs2ui.z(Fsa); +} + +define pcodeop fs2si; +:fs2si Fst, Fsa is $(I32) & $(COP) & fop4=0xf & Fst & Fsa & f2op=0x18 & cop4=0x0 { + Fst = fs2si(Fsa); +} + +define pcodeop fs2si.z; +:fs2si.z Fst, Fsa is $(I32) & $(COP) & fop4=0xf & Fst & Fsa & f2op=0x1c & cop4=0x0 { + Fst = fs2si.z(Fsa); +} + +# FPU_FS2 +fcond: "eq" is fcnd=0 { local tmp:1 = 0; export *[const]:1 tmp; } +fcond: "lt" is fcnd=1 { local tmp:1 = 1; export *[const]:1 tmp; } +fcond: "le" is fcnd=2 { local tmp:1 = 2; export *[const]:1 tmp; } +fcond: "un" is fcnd=3 { local tmp:1 = 3; export *[const]:1 tmp; } + +fcmpe: "" is cmpe=0 { local tmp:1 = 0; export *[const]:1 tmp; } +fcmpe: ".e" is cmpe=1 { local tmp:1 = 1; export *[const]:1 tmp; } +define pcodeop fcmps; +:fcmp^fcond^"s"^fcmpe Fst, Fsa, Fsb is $(I32) & $(COP) & Fst & Fsa & Fsb & cop4=0x4 & fcond & fcmpe { + Fst = fcmps(Fsa, Fsb, fcond, fcmpe); +} + +# FPU_FD1 + +define pcodeop faddd; +:faddd Fdt, Fda, Fdb is $(I32) & $(COP) & fop4=0x0 & Fdt & Fda & Fdb & cop4=0x8 { + Fdt = faddd(Fda, Fdb); +} + +define pcodeop fsubd; +:fsubd Fdt, Fda, Fdb is $(I32) & $(COP) & fop4=0x1 & Fdt & Fda & Fdb & cop4=0x8 { + Fdt = fsubd(Fda, Fdb); +} + +define pcodeop fcpynsd; +:fcpynsd Fdt, Fda, Fdb is $(I32) & $(COP) & fop4=0x2 & Fdt & Fda & Fdb & cop4=0x8 { + Fdt = fcpynsd(Fda, Fdb); +} + +define pcodeop fcpysd; +:fcpysd Fdt, Fda, Fdb is $(I32) & $(COP) & fop4=0x3 & Fdt & Fda & Fdb & cop4=0x8 { + Fdt = fcpysd(Fda, Fdb); +} + +define pcodeop fmaddd; +:fmaddd Fdt, Fda, Fdb is $(I32) & $(COP) & fop4=0x4 & Fdt & Fda & Fdb & cop4=0x8 { + Fdt = fmaddd(Fda, Fdb); +} + +define pcodeop fmsubd; +:fmsubd Fdt, Fda, Fdb is $(I32) & $(COP) & fop4=0x5 & Fdt & Fda & Fdb & cop4=0x8 { + Fdt = fmsubd(Fda, Fdb); +} + +define pcodeop fcmovnd; +:fcmovnd Fdt, Fda, Fdb is $(I32) & $(COP) & fop4=0x6 & Fdt & Fda & Fdb & cop4=0x8 { + Fdt = fcmovnd(Fda, Fdb); +} + +define pcodeop fcmovzd; +:fcmovzd Fdt, Fda, Fdb is $(I32) & $(COP) & fop4=0x7 & Fdt & Fda & Fdb & cop4=0x8 { + Fdt = fcmovzd(Fda, Fdb); +} + +define pcodeop fnmaddd; +:fnmaddd Fdt, Fda, Fdb is $(I32) & $(COP) & fop4=0x8 & Fdt & Fda & Fdb & cop4=0x8 { + Fdt = fnmaddd(Fda, Fdb); +} + +define pcodeop fnmsubd; +:fnmsubd Fdt, Fda, Fdb is $(I32) & $(COP) & fop4=0x9 & Fdt & Fda & Fdb & cop4=0x8 { + Fdt = fnmsubd(Fda, Fdb); +} + +define pcodeop fmuld; +:fmuld Fdt, Fda, Fdb is $(I32) & $(COP) & fop4=0xa & Fdt & Fda & Fdb & cop4=0x8 { + Fdt = fmuld(Fda, Fdb); +} + +define pcodeop fdivd; +:fdivd Fdt, Fda, Fdb is $(I32) & $(COP) & fop4=0xb & Fdt & Fda & Fdb & cop4=0x8 { + Fdt = fdivd(Fda, Fdb); +} + +# FPU_FD1_F2OP +define pcodeop fd2s; +:fd2s Fst, Fda is $(I32) & $(COP) & fop4=0xf & Fst & Fda & f2op=0 & cop4=0x8 { + Fst = fd2s(Fda); +} + +define pcodeop fsqrtd; +:fsqrtd Fdt, Fda is $(I32) & $(COP) & fop4=0xf & Fdt & Fda & f2op=1 & cop4=0x8 { + Fdt = fsqrtd(Fda); +} + +define pcodeop fabsd; +:fabsd Fdt, Fda is $(I32) & $(COP) & fop4=0xf & Fdt & Fda & f2op=0x5 & cop4=0x8 { + Fdt = fabsd(Fda); +} + +define pcodeop fui2d; +:fui2d Fdt, Fsa is $(I32) & $(COP) & fop4=0xf & Fdt & Fsa & f2op=0x8 & cop4=0x8 { + Fdt = fui2d(Fsa); +} + +define pcodeop fsi2d; +:fsi2d Fdt, Fsa is $(I32) & $(COP) & fop4=0xf & Fdt & Fsa & f2op=0xc & cop4=0x8 { + Fdt = fsi2d(Fsa); +} + +define pcodeop fd2ui; +:fd2ui Fst, Fda is $(I32) & $(COP) & fop4=0xf & Fst & Fda & f2op=0x10 & cop4=0x8 { + Fst = fd2ui(Fda); +} + +define pcodeop fd2ui.z; +:fd2ui.z Fst, Fda is $(I32) & $(COP) & fop4=0xf & Fst & Fda & f2op=0x14 & cop4=0x8 { + Fst = fs2ui.z(Fda); +} + +define pcodeop fd2si; +:fd2si Fst, Fda is $(I32) & $(COP) & fop4=0xf & Fst & Fda & f2op=0x18 & cop4=0x8 { + Fst = fd2si(Fda); +} + +define pcodeop fd2si.z; +:fd2si.z Fst, Fda is $(I32) & $(COP) & fop4=0xf & Fst & Fda & f2op=0x1c & cop4=0x8 { + Fst = fs2si.z(Fda); +} + +# FPU_FS2 +define pcodeop fcmpd; +:fcmp^fcond^"d"^fcmpe Fst, Fda, Fdb is $(I32) & $(COP) & Fst & Fda & Fdb & cop4=0xc & fcond & fcmpe { + Fst = fcmpd(Fda, Fdb, fcond, fcmpe); +} + +# FPU_MFCP +define pcodeop fmfsr; +:fmfsr Rt, Fsa is $(I32) & $(COP) & fop4=0x0 & Rt & Fsa & f2op=0x0 & cop4=0x1 { + Rt = fmfsr(Fsa); +} + +define pcodeop fmfdr; +:fmfdr Rt, Fda is $(I32) & $(COP) & fop4=0x1 & Rt & Fda & f2op=0x0 & cop4=0x1 { + Rt = fmfdr(Fda); +} + +# FPU_MTCP +define pcodeop fmtsr; +:fmtsr Rt, Fsa is $(I32) & $(COP) & fop4=0x0 & Rt & Fsa & f2op=0x0 & cop4=0x9 { + Fsa = fmtsr(Rt); +} + +define pcodeop fmtdr; +:fmtdr Rt, Fda is $(I32) & $(COP) & fop4=0x1 & Rt & Fda & f2op=0x0 & cop4=0x9 { + Fda = fmtdr(Rt); +} + +# FPU_FLS + +:fls Fst, AddrRaRbsv is $(I32) & $(COP) & Fst & AddrRaRbsv & fbi=0 & cop4=0x2 { + Fst = *AddrRaRbsv; +} + +:fls.bi Fst [Ra], OffsetRbsv is $(I32) & $(COP) & Fst & Ra & OffsetRbsv & fbi=1 & cop4=2 { + Fst = *Ra; + Ra = Ra + OffsetRbsv; +} + +# FPU_FLD + +:fld Fdt, AddrRaRbsv is $(I32) & $(COP) & Fdt & AddrRaRbsv & fbi=0 & cop4=0x3 { + Fdt = *AddrRaRbsv; +} + +:fld.bi Fdt [Ra], OffsetRbsv is $(I32) & $(COP) & Fdt & Ra & OffsetRbsv & fbi=1 & cop4=3 { + Fdt = *Ra; + Ra = Ra + OffsetRbsv; +} + +# FPU_FSS + +:fss Fst, AddrRaRbsv is $(I32) & $(COP) & Fst & AddrRaRbsv & fbi=0 & cop4=0xa { + *AddrRaRbsv = Fst; +} + +:fss.bi Fst [Ra], OffsetRbsv is $(I32) & $(COP) & Fst & Ra & OffsetRbsv & fbi=1 & cop4=0xa { + *Ra = Fst; + Ra = Ra + OffsetRbsv; +} + +# FPU_FSD +:fsd Fdt, AddrRaRbsv is $(I32) & $(COP) & Fdt & AddrRaRbsv & fbi=0 & cop4=0xb { + *AddrRaRbsv = Fdt; +} + +:fsd.bi Fdt [Ra], OffsetRbsv is $(I32) & $(COP) & Fdt & Ra & OffsetRbsv & fbi=1 & cop4=0xb { + *Ra = Fdt; + Ra = Ra + OffsetRbsv; +} + + +# LWC0 +AddrRaImm12s: [Ra + offs] is Ra & Imm12s [ offs = Imm12s << 2; ] { addr:4 = Ra + offs; export addr; } +OffImm12s: (offs) is Imm12s [ offs = Imm12s << 2; ] { export *[const]:4 offs; } + +:flsi Fst, AddrRaImm12s is $(I32) & $(LWC) & Fst & cpn=0 & fsbi=0 & AddrRaImm12s { + Fst = *AddrRaImm12s; +} + +:flsi.bi Fst [Ra], OffImm12s is $(I32) & $(LWC) & Fst & Ra & cpn=0 & fsbi=1 & OffImm12s { + Fst = *Ra; + Ra = Ra + OffImm12s; +} + +# LDC0 + +:fldi Fdt, AddrRaImm12s is $(I32) & $(LDC) & Fdt & cpn=0 & fsbi=0 & AddrRaImm12s { + Fdt = *AddrRaImm12s; +} + +:fldi.bi Fdt [Ra], OffImm12s is $(I32) & $(LDC) & Fdt & Ra & cpn=0 & fsbi=1 & OffImm12s { + Fdt = *Ra; + Ra = Ra + OffImm12s; +} + +# SWC0 + +:fssi Fst, AddrRaImm12s is $(I32) & $(SWC) & Fst & cpn=0 & fsbi=0 & AddrRaImm12s { + *AddrRaImm12s = Fst; +} + +:fssi.bi Fst [Ra], OffImm12s is $(I32) & $(SWC) & Fst & Ra & cpn=0 & fsbi=1 & OffImm12s { + *Ra = Fst; + Ra = Ra + OffImm12s; +} + +# SDC0 +:fsdi Fdt, AddrRaImm12s is $(I32) & $(SDC) & Fdt & cpn=0 & fsbi=0 & AddrRaImm12s { + *AddrRaImm12s = Fdt; +} + +:fsdi.bi Fdt [Ra], OffImm12s is $(I32) & $(SDC) & Fdt & Ra & cpn=0 & fsbi=1 & OffImm12s { + *Ra = Fdt; + Ra = Ra + OffImm12s; +} + +:fmfcfg Rt is $(I32) & $(COP) & fop4=0xc & Rt & f2op=0x0 & cop4=0x1 { + Rt = fpcfg; +} + +:fmfcsr Rt is $(I32) & $(COP) & fop4=0xc & Rt & f2op=0x1 & cop4=0x1 { + Rt = fpcsr; +} + +:fmtcsr Rt is $(I32) & $(COP) & fop4=0xc & Rt & Fsa & f2op=0x1 & cop4=0x9 { + fpcsr = Rt; +} + diff --git a/Ghidra/Processors/NDS32/data/languages/nds32be.slaspec b/Ghidra/Processors/NDS32/data/languages/nds32be.slaspec new file mode 100644 index 0000000000..244364229b --- /dev/null +++ b/Ghidra/Processors/NDS32/data/languages/nds32be.slaspec @@ -0,0 +1,3 @@ +@define ENDIAN "big" + +@include "nds32.sinc" diff --git a/Ghidra/Processors/NDS32/data/languages/nds32le.slaspec b/Ghidra/Processors/NDS32/data/languages/nds32le.slaspec new file mode 100644 index 0000000000..d6d998cd97 --- /dev/null +++ b/Ghidra/Processors/NDS32/data/languages/nds32le.slaspec @@ -0,0 +1,3 @@ +@define ENDIAN "little" + +@include "nds32.sinc" diff --git a/Ghidra/Processors/NDS32/data/patterns/nds32_patterns.xml b/Ghidra/Processors/NDS32/data/patterns/nds32_patterns.xml new file mode 100644 index 0000000000..802d6307b7 --- /dev/null +++ b/Ghidra/Processors/NDS32/data/patterns/nds32_patterns.xml @@ -0,0 +1,12 @@ + + + + 0xfc 1....... + 0xdd 0x9e + + + 0xfc 0....... + + + + \ No newline at end of file diff --git a/Ghidra/Processors/NDS32/data/patterns/patternconstraints.xml b/Ghidra/Processors/NDS32/data/patterns/patternconstraints.xml new file mode 100644 index 0000000000..735a59bec2 --- /dev/null +++ b/Ghidra/Processors/NDS32/data/patterns/patternconstraints.xml @@ -0,0 +1,5 @@ + + + nds32_patterns.xml + + diff --git a/Ghidra/Processors/NDS32/src/main/java/ghidra/app/plugin/core/analysis/NDS32Analyzer.java b/Ghidra/Processors/NDS32/src/main/java/ghidra/app/plugin/core/analysis/NDS32Analyzer.java new file mode 100644 index 0000000000..fa50a11cd7 --- /dev/null +++ b/Ghidra/Processors/NDS32/src/main/java/ghidra/app/plugin/core/analysis/NDS32Analyzer.java @@ -0,0 +1,172 @@ +/* ### + * 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.analysis; + +import java.math.BigInteger; + +import ghidra.app.util.importer.MessageLog; +import ghidra.framework.options.Options; +import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressSet; +import ghidra.program.model.address.AddressSetView; +import ghidra.program.model.lang.Processor; +import ghidra.program.model.lang.Register; +import ghidra.program.model.lang.RegisterValue; +import ghidra.program.model.listing.ContextChangeException; +import ghidra.program.model.listing.Function; +import ghidra.program.model.listing.Instruction; +import ghidra.program.model.listing.Program; +import ghidra.program.model.listing.ProgramContext; +import ghidra.program.model.symbol.FlowType; +import ghidra.program.model.symbol.Symbol; +import ghidra.program.model.symbol.SymbolUtilities; +import ghidra.program.util.ContextEvaluator; +import ghidra.program.util.SymbolicPropogator; +import ghidra.program.util.VarnodeContext; +import ghidra.util.Msg; +import ghidra.util.exception.AssertException; +import ghidra.util.exception.CancelledException; +import ghidra.util.task.TaskMonitor; + +public class NDS32Analyzer extends ConstantPropagationAnalyzer { + private final static String PROCESSOR_NAME = "NDS32"; + + private static final String RECOVER_GP_OPTION_NAME = "Recover global GP register writes"; + private static final String RECOVER_GP_OPTION_DESCRIPTION = "Reads the global GP value from the symbol _SDA_BASE_"; + private static final boolean RECOVER_GP_OPTION_DEFAULT_VALUE = true; + + + //private boolean recoverSwitchTables = SWITCH_OPTION_DEFAULT_VALUE; + private boolean recoverGp = RECOVER_GP_OPTION_DEFAULT_VALUE; + + private Address gpAssumptionValue = null; + + private Register gp; + + public NDS32Analyzer() { + super(PROCESSOR_NAME); + } + + @Override + public boolean canAnalyze(Program program) { + boolean canAnalyze = program.getLanguage().getProcessor().equals( + Processor.findOrPossiblyCreateProcessor(PROCESSOR_NAME)); + + if (!canAnalyze) { + return false; + } + + gp = program.getRegister("gp"); + + return true; + } + + @Override + public void optionsChanged(Options options, Program program) { + super.optionsChanged(options, program); + + options.registerOption(RECOVER_GP_OPTION_NAME, recoverGp, null, + RECOVER_GP_OPTION_DESCRIPTION); + recoverGp = options.getBoolean(RECOVER_GP_OPTION_NAME, recoverGp); + } + + @Override + public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log) + throws CancelledException { + gpAssumptionValue = null; + + checkForGlobalGP(program, set, monitor); + + return super.added(program, set, monitor, log); + } + + /** + * Check for a global GP register symbol or discovered symbol + * @param program + * @param set + * @param monitor + */ + private void checkForGlobalGP(Program program, AddressSetView set, TaskMonitor monitor) { + if (!recoverGp) { + return; + } + + Symbol symbol = SymbolUtilities.getLabelOrFunctionSymbol(program, "_SDA_BASE_", + err -> Msg.error(this, err)); + if (symbol != null) { + gpAssumptionValue = symbol.getAddress(); + return; + } + + // TODO : if the symbol doesn't exist, check manually... somewhere else + + return; + } + + @Override + public AddressSetView flowConstants(final Program program, Address flowStart, + AddressSetView flowSet, final SymbolicPropogator symEval, final TaskMonitor monitor) + throws CancelledException { + + // get the function body + final Function func = program.getFunctionManager().getFunctionContaining(flowStart); + + final AddressSet coveredSet = new AddressSet(); + + Address currentGPAssumptionValue = gpAssumptionValue; + + // TODO : copypaste more code from MipsAddressAnalyzer to see if gp is written and act accordingly + if (func != null) { + flowStart = func.getEntryPoint(); + if (currentGPAssumptionValue != null) { + ProgramContext programContext = program.getProgramContext(); + RegisterValue gpVal = programContext.getRegisterValue(gp, flowStart); + if (gpVal == null || !gpVal.hasValue()) { + gpVal = new RegisterValue(gp, + BigInteger.valueOf(currentGPAssumptionValue.getOffset())); + try { + program.getProgramContext().setRegisterValue(func.getEntryPoint(), + func.getEntryPoint(), gpVal); + } + catch (ContextChangeException e) { + throw new AssertException("unexpected", e); // only happens for context register + } + } + } + } + + ContextEvaluator eval = new ConstantPropagationContextEvaluator(monitor, trustWriteMemOption) { + @Override + public boolean evaluateDestination(VarnodeContext context, Instruction instruction) { + FlowType flowtype = instruction.getFlowType(); + if (!flowtype.isJump()) { + return false; + } + + return false; + } + }; + + AddressSet resultSet = symEval.flowConstants(flowStart, null, eval, true, monitor); + + // Add in any addresses we should assume got covered + // These addresses are put on because we had to stop analysis due to an unknown register value + resultSet.add(coveredSet); + + return resultSet; + } + +} diff --git a/Ghidra/Processors/NDS32/src/main/java/ghidra/app/util/bin/format/elf/relocation/NDS32_ElfRelocationHandler.java b/Ghidra/Processors/NDS32/src/main/java/ghidra/app/util/bin/format/elf/relocation/NDS32_ElfRelocationHandler.java new file mode 100644 index 0000000000..4bac0c4d4f --- /dev/null +++ b/Ghidra/Processors/NDS32/src/main/java/ghidra/app/util/bin/format/elf/relocation/NDS32_ElfRelocationHandler.java @@ -0,0 +1,96 @@ +/* ### + * 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 java.util.Map; + +import ghidra.app.util.bin.format.elf.*; +import ghidra.app.util.importer.MessageLog; +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.RelocationResult; +import ghidra.program.model.reloc.Relocation.Status; + +public class NDS32_ElfRelocationHandler extends AbstractElfRelocationHandler> { + + public NDS32_ElfRelocationHandler() { + super(NDS32_ElfRelocationType.class); + } + + + @Override + public boolean canRelocate(ElfHeader elf) { + return elf.e_machine() == ElfConstants.EM_NDS32; + } + + @Override + public int getRelrRelocationType() { + return NDS32_ElfRelocationType.R_NDS32_RELATIVE.typeId; + } + + @Override + protected RelocationResult relocate(ElfRelocationContext elfRelocationContext, + ElfRelocation relocation, NDS32_ElfRelocationType type, Address relocationAddress, + ElfSymbol sym, Address symbolAddr, long symbolValue, String symbolName) + throws MemoryAccessException { + + ElfRelocationContext nds32RelocationContext = elfRelocationContext; + + int symbolIndex = relocation.getSymbolIndex(); + return doRelocate(nds32RelocationContext, type, symbolIndex, relocation, relocationAddress); + + } + + private RelocationResult doRelocate(ElfRelocationContext nds32RelocationContext, NDS32_ElfRelocationType type, + int symbolIndex, ElfRelocation relocation, Address relocationAddress) + throws MemoryAccessException { + Program program = nds32RelocationContext.getProgram(); + Memory memory = program.getMemory(); + MessageLog log = nds32RelocationContext.getLog(); + ElfSymbol elfSymbol = nds32RelocationContext.getSymbol(symbolIndex); + long symbolValue = nds32RelocationContext.getSymbolValue(elfSymbol); + String symbolName = elfSymbol.getNameAsString(); + + // Read instruction as big endian + int oldValue = memory.getInt(relocationAddress, true); + + long addend = 0; + if(relocation.hasAddend()) { + addend = relocation.getAddend(); + } + + int value = 0; + int newValue = 0; + int byteLength = 4; + + switch(type) { + case R_NDS32_HI20_RELA: + value = (int)(symbolValue + addend); + newValue = (oldValue & 0xfff00000) | (value >> 12); + memory.setInt(relocationAddress, newValue, true); + return new RelocationResult(Status.APPLIED, byteLength); + case R_NDS32_LO12S0_RELA: + value = (int)(symbolValue + addend); + newValue = (oldValue & 0xfffff000) | (value & 0xfff); + memory.setInt(relocationAddress, newValue, true); + return new RelocationResult(Status.APPLIED, byteLength); + default: + return RelocationResult.UNSUPPORTED; + } + } +} diff --git a/Ghidra/Processors/NDS32/src/main/java/ghidra/app/util/bin/format/elf/relocation/NDS32_ElfRelocationType.java b/Ghidra/Processors/NDS32/src/main/java/ghidra/app/util/bin/format/elf/relocation/NDS32_ElfRelocationType.java new file mode 100644 index 0000000000..e255cad300 --- /dev/null +++ b/Ghidra/Processors/NDS32/src/main/java/ghidra/app/util/bin/format/elf/relocation/NDS32_ElfRelocationType.java @@ -0,0 +1,195 @@ +/* ### + * 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; + +public enum NDS32_ElfRelocationType implements ElfRelocationType { + /* REL relocations. */ + R_NDS32_16(1), + R_NDS32_32(2), + R_NDS32_20(3), + R_NDS32_9_PCREL(4), + R_NDS32_15_PCREL(5), + R_NDS32_17_PCREL(6), + R_NDS32_25_PCREL(7), + R_NDS32_HI20(8), + R_NDS32_LO12S3(9), + R_NDS32_LO12S2(10), + R_NDS32_LO12S1(11), + R_NDS32_LO12S0(12), + R_NDS32_SDA15S3(13), + R_NDS32_SDA15S2(14), + R_NDS32_SDA15S1(15), + R_NDS32_SDA15S0(16), + R_NDS32_GNU_VTINHERIT(17), + R_NDS32_GNU_VTENTRY(18), + /* RELA relocations. */ + R_NDS32_16_RELA(19), + R_NDS32_32_RELA(20), + R_NDS32_20_RELA(21), + R_NDS32_9_PCREL_RELA(22), + R_NDS32_15_PCREL_RELA(23), + R_NDS32_17_PCREL_RELA(24), + R_NDS32_25_PCREL_RELA(25), + R_NDS32_HI20_RELA(26), + R_NDS32_LO12S3_RELA(27), + R_NDS32_LO12S2_RELA(28), + R_NDS32_LO12S1_RELA(29), + R_NDS32_LO12S0_RELA(30), + R_NDS32_SDA15S3_RELA(31), + R_NDS32_SDA15S2_RELA(32), + R_NDS32_SDA15S1_RELA(33), + R_NDS32_SDA15S0_RELA(34), + R_NDS32_RELA_GNU_VTINHERIT(35), + R_NDS32_RELA_GNU_VTENTRY(36), + /* GOT and PLT. */ + R_NDS32_GOT20(37), + R_NDS32_25_PLTREL(38), + R_NDS32_COPY(39), + R_NDS32_GLOB_DAT(40), + R_NDS32_JMP_SLOT(41), + R_NDS32_RELATIVE(42), + R_NDS32_GOTOFF(43), + R_NDS32_GOTPC20(44), + R_NDS32_GOT_HI20(45), + R_NDS32_GOT_LO12(46), + R_NDS32_GOTPC_HI20(47), + R_NDS32_GOTPC_LO12(48), + R_NDS32_GOTOFF_HI20(49), + R_NDS32_GOTOFF_LO12(50), + /* 32_to_16 relaxations. */ + R_NDS32_INSN16(51), + /* Alignment tag. */ + R_NDS32_LABEL(52), + R_NDS32_LONGCALL1(53), /* This is obsoleted. */ + R_NDS32_LONGCALL2(54), /* This is obsoleted. */ + R_NDS32_LONGCALL3(55), /* This is obsoleted. */ + R_NDS32_LONGJUMP1(56), /* This is obsoleted. */ + R_NDS32_LONGJUMP2(57), /* This is obsoleted. */ + R_NDS32_LONGJUMP3(58), /* This is obsoleted. */ + R_NDS32_LOADSTORE(59), /* This is obsoleted. */ + R_NDS32_9_FIXED_RELA(60), + R_NDS32_15_FIXED_RELA(61), + R_NDS32_17_FIXED_RELA(62), + R_NDS32_25_FIXED_RELA(63), + R_NDS32_PLTREL_HI20(64), /* This is obsoleted. */ + R_NDS32_PLTREL_LO12(65), /* This is obsoleted. */ + R_NDS32_PLT_GOTREL_HI20(66), + R_NDS32_PLT_GOTREL_LO12(67), + R_NDS32_SDA12S2_DP_RELA(68), + R_NDS32_SDA12S2_SP_RELA(69), + R_NDS32_LO12S2_DP_RELA(70), + R_NDS32_LO12S2_SP_RELA(71), + R_NDS32_LO12S0_ORI_RELA(72), + R_NDS32_SDA16S3_RELA(73), + R_NDS32_SDA17S2_RELA(74), + R_NDS32_SDA18S1_RELA(75), + R_NDS32_SDA19S0_RELA(76), + R_NDS32_DWARF2_OP1_RELA(77), /* This is obsoleted. */ + R_NDS32_DWARF2_OP2_RELA(78), /* This is obsoleted. */ + R_NDS32_DWARF2_LEB_RELA(79), /* This is obsoleted. */ + R_NDS32_UPDATE_TA_RELA(80), /* This is obsoleted. */ + R_NDS32_9_PLTREL(81), + R_NDS32_PLT_GOTREL_LO20(82), + R_NDS32_PLT_GOTREL_LO15(83), + R_NDS32_PLT_GOTREL_LO19(84), + R_NDS32_GOT_LO15(85), + R_NDS32_GOT_LO19(86), + R_NDS32_GOTOFF_LO15(87), + R_NDS32_GOTOFF_LO19(88), + R_NDS32_GOT15S2_RELA(89), + R_NDS32_GOT17S2_RELA(90), + R_NDS32_5_RELA(91), + R_NDS32_10_UPCREL_RELA(92), /* This is obsoleted. */ + R_NDS32_SDA_FP7U2_RELA(93), + R_NDS32_WORD_9_PCREL_RELA(94), + R_NDS32_25_ABS_RELA(95), + R_NDS32_17IFC_PCREL_RELA(96), /* This is obsoleted. */ + R_NDS32_10IFCU_PCREL_RELA(97), /* This is obsoleted. */ + /* TLS support. */ + R_NDS32_TLS_LE_HI20(98), + R_NDS32_TLS_LE_LO12(99), + R_NDS32_TLS_IE_HI20(100), + R_NDS32_TLS_IE_LO12S2(101), + R_NDS32_TLS_TPOFF(102), + R_NDS32_TLS_LE_20(103), + R_NDS32_TLS_LE_15S0(104), + R_NDS32_TLS_LE_15S1(105), + R_NDS32_TLS_LE_15S2(106), + R_NDS32_LONGCALL4(107), + R_NDS32_LONGCALL5(108), + R_NDS32_LONGCALL6(109), + R_NDS32_LONGJUMP4(110), + R_NDS32_LONGJUMP5(111), + R_NDS32_LONGJUMP6(112), + R_NDS32_LONGJUMP7(113), + /* Reserved numbers: 114. */ + /* TLS support */ + R_NDS32_TLS_IE_LO12(115), + R_NDS32_TLS_IEGP_HI20(116), + R_NDS32_TLS_IEGP_LO12(117), + R_NDS32_TLS_IEGP_LO12S2(118), + R_NDS32_TLS_DESC(119), + R_NDS32_TLS_DESC_HI20(120), + R_NDS32_TLS_DESC_LO12(121), + R_NDS32_TLS_DESC_20(122), + R_NDS32_TLS_DESC_SDA17S2(123), + /* Reserved numbers: 124-191. */ + + /* These used only for relaxations */ + R_NDS32_RELAX_ENTRY(192), + R_NDS32_GOT_SUFF(193), + R_NDS32_GOTOFF_SUFF(194), + R_NDS32_PLT_GOT_SUFF(195), + R_NDS32_MULCALL_SUFF(196), /* This is obsoleted. */ + R_NDS32_PTR(197), + R_NDS32_PTR_COUNT(198), + R_NDS32_PTR_RESOLVED(199), + R_NDS32_PLTBLOCK(200), /* This is obsoleted. */ + R_NDS32_RELAX_REGION_BEGIN(201), + R_NDS32_RELAX_REGION_END(202), + R_NDS32_MINUEND(203), + R_NDS32_SUBTRAHEND(204), + R_NDS32_DIFF8(205), + R_NDS32_DIFF16(206), + R_NDS32_DIFF32(207), + R_NDS32_DIFF_ULEB128(208), + R_NDS32_DATA(209), + R_NDS32_TRAN(210), + /* TLS support */ + R_NDS32_TLS_LE_ADD(211), + R_NDS32_TLS_LE_LS(212), + R_NDS32_EMPTY(213), + R_NDS32_TLS_DESC_ADD(214), + R_NDS32_TLS_DESC_FUNC(215), + R_NDS32_TLS_DESC_CALL(216), + R_NDS32_TLS_DESC_MEM(217), + R_NDS32_RELAX_REMOVE(218), + R_NDS32_RELAX_GROUP(219), + R_NDS32_TLS_IEGP_LW(220), + R_NDS32_LSI(221), + R_NDS32_RELA_NOP_MAX(255); + + public final int typeId; + + private NDS32_ElfRelocationType(int typeId) { + this.typeId = typeId; + } + + @Override + public int typeId() { + return typeId; + } +} diff --git a/Ghidra/Processors/NDS32/src/test.processors/java/ghidra/test/processors/NDS32_BE_O0_EmulatorTest.java b/Ghidra/Processors/NDS32/src/test.processors/java/ghidra/test/processors/NDS32_BE_O0_EmulatorTest.java new file mode 100644 index 0000000000..b08df6306d --- /dev/null +++ b/Ghidra/Processors/NDS32/src/test.processors/java/ghidra/test/processors/NDS32_BE_O0_EmulatorTest.java @@ -0,0 +1,41 @@ +/* ### + * 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 NDS32_BE_O0_EmulatorTest extends ProcessorEmulatorTestAdapter { + + private static final String LANGUAGE_ID = "NDS32:BE:32:default"; + private static final String COMPILER_SPEC_ID = "default"; + + private static final String[] REG_DUMP_SET = new String[] {}; + + public NDS32_BE_O0_EmulatorTest(String name) throws Exception { + super(name, LANGUAGE_ID, COMPILER_SPEC_ID, REG_DUMP_SET); + } + + @Override + protected String getProcessorDesignator() { + return "NDS32BE_GCC_O0"; + } + + public static Test suite() { + return ProcessorEmulatorTestAdapter.buildEmulatorTestSuite(NDS32_BE_O0_EmulatorTest.class); + } +} diff --git a/Ghidra/Processors/NDS32/src/test.processors/java/ghidra/test/processors/NDS32_BE_O3_EmulatorTest.java b/Ghidra/Processors/NDS32/src/test.processors/java/ghidra/test/processors/NDS32_BE_O3_EmulatorTest.java new file mode 100644 index 0000000000..c8136ce919 --- /dev/null +++ b/Ghidra/Processors/NDS32/src/test.processors/java/ghidra/test/processors/NDS32_BE_O3_EmulatorTest.java @@ -0,0 +1,41 @@ +/* ### + * 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 NDS32_BE_O3_EmulatorTest extends ProcessorEmulatorTestAdapter { + + private static final String LANGUAGE_ID = "NDS32:BE:32:default"; + private static final String COMPILER_SPEC_ID = "default"; + + private static final String[] REG_DUMP_SET = new String[] {}; + + public NDS32_BE_O3_EmulatorTest(String name) throws Exception { + super(name, LANGUAGE_ID, COMPILER_SPEC_ID, REG_DUMP_SET); + } + + @Override + protected String getProcessorDesignator() { + return "NDS32BE_GCC_O3"; + } + + public static Test suite() { + return ProcessorEmulatorTestAdapter.buildEmulatorTestSuite(NDS32_BE_O3_EmulatorTest.class); + } +} diff --git a/Ghidra/Processors/NDS32/src/test.processors/java/ghidra/test/processors/NDS32_LE_O0_EmulatorTest.java b/Ghidra/Processors/NDS32/src/test.processors/java/ghidra/test/processors/NDS32_LE_O0_EmulatorTest.java new file mode 100644 index 0000000000..3799bdeeeb --- /dev/null +++ b/Ghidra/Processors/NDS32/src/test.processors/java/ghidra/test/processors/NDS32_LE_O0_EmulatorTest.java @@ -0,0 +1,41 @@ +/* ### + * 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 NDS32_LE_O0_EmulatorTest extends ProcessorEmulatorTestAdapter { + + private static final String LANGUAGE_ID = "NDS32:LE:32:default"; + private static final String COMPILER_SPEC_ID = "default"; + + private static final String[] REG_DUMP_SET = new String[] {}; + + public NDS32_LE_O0_EmulatorTest(String name) throws Exception { + super(name, LANGUAGE_ID, COMPILER_SPEC_ID, REG_DUMP_SET); + } + + @Override + protected String getProcessorDesignator() { + return "NDS32LE_GCC_O0"; + } + + public static Test suite() { + return ProcessorEmulatorTestAdapter.buildEmulatorTestSuite(NDS32_LE_O0_EmulatorTest.class); + } +} diff --git a/Ghidra/Processors/NDS32/src/test.processors/java/ghidra/test/processors/NDS32_LE_O3_EmulatorTest.java b/Ghidra/Processors/NDS32/src/test.processors/java/ghidra/test/processors/NDS32_LE_O3_EmulatorTest.java new file mode 100644 index 0000000000..5343e5a272 --- /dev/null +++ b/Ghidra/Processors/NDS32/src/test.processors/java/ghidra/test/processors/NDS32_LE_O3_EmulatorTest.java @@ -0,0 +1,41 @@ +/* ### + * 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 NDS32_LE_O3_EmulatorTest extends ProcessorEmulatorTestAdapter { + + private static final String LANGUAGE_ID = "NDS32:LE:32:default"; + private static final String COMPILER_SPEC_ID = "default"; + + private static final String[] REG_DUMP_SET = new String[] {}; + + public NDS32_LE_O3_EmulatorTest(String name) throws Exception { + super(name, LANGUAGE_ID, COMPILER_SPEC_ID, REG_DUMP_SET); + } + + @Override + protected String getProcessorDesignator() { + return "NDS32LE_GCC_O3"; + } + + public static Test suite() { + return ProcessorEmulatorTestAdapter.buildEmulatorTestSuite(NDS32_LE_O3_EmulatorTest.class); + } +} diff --git a/Ghidra/Processors/RISCV/data/languages/andestar_v5.instr.sinc b/Ghidra/Processors/RISCV/data/languages/andestar_v5.instr.sinc index bb30a6333a..c629881233 100644 --- a/Ghidra/Processors/RISCV/data/languages/andestar_v5.instr.sinc +++ b/Ghidra/Processors/RISCV/data/languages/andestar_v5.instr.sinc @@ -20,7 +20,8 @@ simm18_lh: val is sop3131 & op1516 & op1719 & op2020 & op2130 [ val = (sop3131<< export *[const]:$(XLEN) val; } -simm18_lw: val is sop3131 & op1516 & op1719 & op2020 & op2130 [ val = (sop3131<<18) | (op1516<<16) | (op1719<<13) | (op2020<<12) | (op2130<<2); ] { +#simm18_lw: val is sop3131 & op1516 & op1719 & op2020 & op2130 [ val = (sop3131<<18) | (op1516<<16) | (op1719<<13) | (op2020<<12) | (op2130<<2); ] { +simm18_lw: val is sop3131 & op2121 & op1516 & op1719 & op2020 & op2230 [ val = (sop3131<<18) | (op2121 << 17) | (op1516<<15) | (op1719<<12) | (op2020<<11) | (op2230<<2); ] { export *[const]:$(XLEN) val; } diff --git a/Ghidra/Processors/RISCV/data/languages/riscv.reg.sinc b/Ghidra/Processors/RISCV/data/languages/riscv.reg.sinc index 91ede6e4ae..ecd02ef3cc 100644 --- a/Ghidra/Processors/RISCV/data/languages/riscv.reg.sinc +++ b/Ghidra/Processors/RISCV/data/languages/riscv.reg.sinc @@ -1231,6 +1231,7 @@ define token instr (32) op2122=(21,22) op2130=(21,30) op2222=(22,22) + op2230=(22,30) op2323=(23,23) op2324=(23,24) op2330=(23,30)