diff --git a/Ghidra/Processors/MIPS/certification.manifest b/Ghidra/Processors/MIPS/certification.manifest index 1152c9daf4..868762feaf 100644 --- a/Ghidra/Processors/MIPS/certification.manifest +++ b/Ghidra/Processors/MIPS/certification.manifest @@ -26,6 +26,8 @@ data/languages/mips64_32_o64.cspec||GHIDRA||||END| data/languages/mips64be.slaspec||GHIDRA||||END| data/languages/mips64le.slaspec||GHIDRA||||END| data/languages/mips64micro.pspec||GHIDRA||||END| +data/languages/mips_dsp.sinc||GHIDRA||||END| +data/languages/mips_mt.sinc||GHIDRA||||END| data/languages/mipsfloat.sinc||GHIDRA||||END| data/languages/mipsmicro.sinc||GHIDRA||||END| data/manuals/MIPS.idx||GHIDRA||||END| diff --git a/Ghidra/Processors/MIPS/data/languages/mips.ldefs b/Ghidra/Processors/MIPS/data/languages/mips.ldefs index 28e6355658..ca56e04ca9 100644 --- a/Ghidra/Processors/MIPS/data/languages/mips.ldefs +++ b/Ghidra/Processors/MIPS/data/languages/mips.ldefs @@ -4,7 +4,7 @@ endian="big" size="32" variant="default" - version="1.6" + version="1.7" slafile="mips32be.sla" processorspec="mips32.pspec" manualindexfile="../manuals/mipsM16.idx" @@ -20,7 +20,7 @@ endian="little" size="32" variant="default" - version="1.6" + version="1.7" slafile="mips32le.sla" processorspec="mips32.pspec" manualindexfile="../manuals/mipsM16.idx" @@ -36,7 +36,7 @@ endian="big" size="32" variant="R6" - version="1.6" + version="1.7" slafile="mips32R6be.sla" processorspec="mips32R6.pspec" manualindexfile="../manuals/mipsMic.idx" @@ -50,7 +50,7 @@ endian="little" size="32" variant="R6" - version="1.6" + version="1.7" slafile="mips32R6le.sla" processorspec="mips32R6.pspec" manualindexfile="../manuals/mipsMic.idx" @@ -64,7 +64,7 @@ endian="big" size="64" variant="default" - version="1.6" + version="1.7" slafile="mips64be.sla" processorspec="mips64.pspec" manualindexfile="../manuals/mipsM16.idx" @@ -80,7 +80,7 @@ endian="little" size="64" variant="default" - version="1.6" + version="1.7" slafile="mips64le.sla" processorspec="mips64.pspec" manualindexfile="../manuals/mipsM16.idx" @@ -97,7 +97,7 @@ endian="big" size="64" variant="micro" - version="1.6" + version="1.7" slafile="mips64be.sla" processorspec="mips64micro.pspec" manualindexfile="../manuals/mipsMic.idx" @@ -112,7 +112,7 @@ endian="little" size="64" variant="micro" - version="1.6" + version="1.7" slafile="mips64le.sla" processorspec="mips64micro.pspec" manualindexfile="../manuals/mipsMic.idx" @@ -128,7 +128,7 @@ endian="big" size="64" variant="R6" - version="1.6" + version="1.7" slafile="mips64be.sla" processorspec="mips64R6.pspec" manualindexfile="../manuals/mipsMic.idx" @@ -143,7 +143,7 @@ endian="little" size="64" variant="R6" - version="1.6" + version="1.7" slafile="mips64le.sla" processorspec="mips64R6.pspec" manualindexfile="../manuals/mipsMic.idx" @@ -159,7 +159,7 @@ endian="big" size="32" variant="64-32addr" - version="1.6" + version="1.7" slafile="mips64be.sla" processorspec="mips64.pspec" manualindexfile="../manuals/mipsM16.idx" @@ -179,7 +179,7 @@ endian="little" size="32" variant="64-32addr" - version="1.6" + version="1.7" slafile="mips64le.sla" processorspec="mips64.pspec" manualindexfile="../manuals/mipsM16.idx" @@ -200,7 +200,7 @@ endian="little" size="32" variant="64-32addr-micro" - version="1.6" + version="1.7" slafile="mips64le.sla" processorspec="mips64micro.pspec" manualindexfile="../manuals/mipsMic.idx" @@ -220,7 +220,7 @@ endian="big" size="32" variant="64-32addr-micro" - version="1.6" + version="1.7" slafile="mips64be.sla" processorspec="mips64micro.pspec" manualindexfile="../manuals/mipsMic.idx" @@ -239,7 +239,7 @@ endian="big" size="32" variant="64-32addr-R6" - version="1.6" + version="1.7" slafile="mips64be.sla" processorspec="mips64R6.pspec" manualindexfile="../manuals/mipsMic.idx" @@ -258,7 +258,7 @@ endian="little" size="32" variant="64-32addr-R6" - version="1.6" + version="1.7" slafile="mips64le.sla" processorspec="mips64R6.pspec" manualindexfile="../manuals/mipsMic.idx" @@ -278,7 +278,7 @@ endian="big" size="32" variant="micro" - version="1.6" + version="1.7" slafile="mips32be.sla" processorspec="mips32micro.pspec" manualindexfile="../manuals/mipsMic.idx" @@ -293,7 +293,7 @@ endian="little" size="32" variant="micro" - version="1.6" + version="1.7" slafile="mips32le.sla" processorspec="mips32micro.pspec" manualindexfile="../manuals/mipsMic.idx" diff --git a/Ghidra/Processors/MIPS/data/languages/mips.sinc b/Ghidra/Processors/MIPS/data/languages/mips.sinc index d30d348c80..6d80485cf7 100755 --- a/Ghidra/Processors/MIPS/data/languages/mips.sinc +++ b/Ghidra/Processors/MIPS/data/languages/mips.sinc @@ -142,6 +142,7 @@ @define REGSIZE "8" # General purpose register size (8 or 4) @define FREGSIZE "8" # Floating point register size (8 or 4) @define ADDRSIZE "4" # Memory address size (8 or 4, virtual and physical) +@define DREGSIZE "16" # 2x REGSIZE used for accumulators @define SIZETO4 "4" # In 32-bit mode, no truncation needed @define ADDRCAST ":4" # need to down cast to pointer size @define NEEDCAST "1" @@ -151,6 +152,7 @@ @define REGSIZE "8" # General purpose register size (8 or 4) @define FREGSIZE "8" # Floating point register size (8 or 4) @define ADDRSIZE "8" # Memory address size (8 or 4, virtual and physical) +@define DREGSIZE "16" # 2x REGSIZE used for accumulators @define SIZETO4 "4" # In 64-bit mode, use when need to do 32-bit operation @define ADDRCAST "" # no need to down cast to pointer size @@ -162,6 +164,8 @@ @define REGSIZE "4" # General purpose register size (8 or 4) # FREGSIZE for mips32 is set in slaspec file @define ADDRSIZE "4" # Memory address size (8 or 4, virtual and physical) +@define DOUBLE "8" # 2x REGSIZE used for accumulators +@define DREGSIZE "8" @define SIZETO4 "4" @define ADDRCAST "" # no need to down cast to pointer size @@ -320,7 +324,7 @@ define register offset=0x2400 size=$(REGSIZE) [ # COP-0 control registers, sel=5 define register offset=0x2500 size=$(REGSIZE) [ - cop0_reg0.5 VPESchedule TCContext cop0_reg3.5 + cop0_reg0.5 VPESchedule TCContext cop0_reg3.5 cop0_reg4.5 cop0_reg5.5 SRSConf4 cop0_reg7.5 cop0_reg8.5 cop0_reg9.5 cop0_reg10.5 cop0_reg11.5 cop0_reg12.5 cop0_reg13.5 cop0_reg14.5 cop0_reg15.5 @@ -355,8 +359,19 @@ define register offset=0x2700 size=$(REGSIZE) [ ]; # Some other internal registers -define register offset=0x3000 size=$(REGSIZE) [ hi lo hi1 lo1 hi2 lo2 hi3 lo3 tsp ]; +define register offset=0x3000 size=$(REGSIZE) [ +@if ENDIAN == "big" + hi lo hi1 lo1 hi2 lo2 hi3 lo3 +@else + lo hi lo1 hi1 lo2 hi2 lo3 hi3 +@endif # ENDIAN + tsp +]; +# MIPS dsp lo/hi combined registers +define register offset=0x3000 size=$(DREGSIZE) [ ac0 ac1 ac2 ac3 ]; + +define register offset=0x3100 size=$(REGSIZE) [ DSPControl ]; define register offset=0x3200 size=$(REGSIZE) [ HW_CPUNUM HW_SYNCI_STEP HW_CC HW_CCRe @@ -373,6 +388,24 @@ define register offset=0x3200 size=$(REGSIZE) [ define register offset=0x3F00 size=1 [ ISAModeSwitch ]; @endif +# Dummy registers for multi-threading +define register offset=0x3300 size=$(REGSIZE) [ + thread_zero thread_at thread_v0 thread_v1 thread_a0 thread_a1 thread_a2 thread_a3 + thread_t0 thread_t1 thread_t2 thread_t3 thread_t4 thread_t5 thread_t6 thread_t7 + thread_s0 thread_s1 thread_s2 thread_s3 thread_s4 thread_s5 thread_s6 thread_s7 + thread_t8 thread_t9 thread_k0 thread_k1 thread_gp thread_sp thread_s8 thread_ra + + thread_f0 thread_f1 thread_f2 thread_f3 thread_f4 thread_f5 thread_f6 thread_f7 + thread_f8 thread_f9 thread_f10 thread_f11 thread_f12 thread_f13 thread_f14 thread_f15 + thread_f16 thread_f17 thread_f18 thread_f19 thread_f20 thread_f21 thread_f22 thread_f23 + thread_f24 thread_f25 thread_f26 thread_f27 thread_f28 thread_f29 thread_f30 thread_f31 + + thread_lo0 thread_hi0 thread_acx0 _ thread_lo1 thread_hi1 thread_acx1 _ + thread_lo2 thread_hi2 thread_acx2 _ thread_lo3 thread_hi3 thread_acx3 _ + + thread_fir thread_fccr thread_fexr thread_fenr thread_fcsr +]; + # Define context bits define register offset=0x4000 size=4 contextreg; define context contextreg @@ -455,6 +488,7 @@ define context contextreg define token instr(32) prime = (26,31) bit25 = (25,25) + zero2425 = (24,25) zero2325 = (23,25) zero1 = (22,25) rs32 = (21,25) @@ -465,41 +499,59 @@ define token instr(32) format = (21,25) copop = (21,25) mfmc0 = (21,25) - zero21 = (21,25) - jsub = (21,25) + zero21 = (21,25) + jsub = (21,25) + sa_dsp2 = (21,25) + shift21 = (21,25) + sz = (21,25) + + acf = (21,22) acflo = (21,22) acfhi = (21,22) + shift20 = (20,25) breakcode = (6,25) off26 = (0,25) signed # 26 bit signed offset, e.g. balc, bc ind26 = (0,25) # 26 bit unsigned index, e.g. jal copfill = (6,24) cofun = (0,24) - off21 = (0,20) signed # 21 bit signed offset in conditional branch/link - off16 = (0,15) signed # 16 bit signed offset in conditional branch/link + off21 = (0,20) signed # 21 bit signed offset in conditional branch/link + off16 = (0,15) signed # 16 bit signed offset in conditional branch/link bit21 = (21,21) - bitz19 = (19,20) - pcrel = (19,20) - pcrel2 = (18,20) + bitz19 = (19,20) + pcrel = (19,20) + pcrel2 = (18,20) cc = (18,20) + immed1625 = (16,25) signed + immed1623 = (16,23) signed rt32 = (16,20) rt = (16,20) + rtmtdsp = (16,20) + RT0thread = (16,20) + RTthread = (16,20) + FTthread = (16,20) + FCTthread = (16,20) ftD = (16,20) ft = (16,20) index = (16,20) hint = (16,20) cop1code = (16,20) - synci = (16,20) + synci = (16,20) cond = (16,20) op = (16,20) zero1620 = (16,20) + + zero1619 = (16,19) + lohiacx = (16,19) nd = (17,17) tf = (16,16) zero1320 = (13,20) zero1315 = (13,15) szero = (11,25) - baser6 = (11,15) + mask = (11,20) + baser6 = (11,15) rd32 = (11,15) rd = (11,15) + rdmtdsp = (11,15) rd0_0 = (11,15) rd0_1 = (11,15) rd0_2 = (11,15) @@ -519,18 +571,27 @@ define token instr(32) cp2cprSel7 = (11,15) fsD = (11,15) fs = (11,15) - fs_unk = (11,15) - fs_fcr = (11,15) + RD0thread = (11,15) + RDthread = (11,15) + FDthread = (11,15) + FCRthread = (16,20) + sa_dsp = (11,15) + fs_unk = (11,15) + fs_fcr = (11,15) zero4 = (11,15) msbd = (11,15) + + lohiacx2 = (11,14) aclo = (11,12) achi = (11,12) - code = (6,15) + ac = (11,12) + bp = (11,12) bit10 = (10,10) - spec2 = (9,10) - spec3 = (8,10) - simmed9 = (7,15) + spec2 = (9,10) + spec3 = (8,10) + simmed9 = (7,15) zero2 = (7,10) + code = (6,15) fdD = (6,10) fd = (6,10) stype = (6,10) @@ -539,10 +600,11 @@ define token instr(32) fct2 = (6,10) zero5 = (6,10) wsbh = (6,10) - bp3 = (6,8) + + bp3 = (6,8) sel_0608 = (6,8) - sa2 = (6,7) - bp2 = (6,7) + sa2 = (6,7) + bp2 = (6,7) zero6 = (3,10) bigfunct = (0,10) fct = (0,5) @@ -550,22 +612,24 @@ define token instr(32) bit6 = (6,6) zero3 = (0,4) bit5 = (5,5) + h = (4,4) op4 = (3,5) + bit3 = (3,3) sel = (0,2) format1X = (0,2) - simmed19 = (0,18) signed - simmed18 = (0,17) signed + simmed19 = (0,18) signed + simmed18 = (0,17) signed immed = (0,15) simmed = (0,15) signed - simmseq = (6,15) signed - simmed11 = (0,10) + simmseq = (6,15) signed + simmed11 = (0,10) ; attach variables [ rs rt rd base index baser6 ] [ zero at v0 v1 a0 a1 a2 a3 t0 t1 t2 t3 t4 t5 t6 t7 s0 s1 s2 s3 s4 s5 s6 s7 - t8 t9 k0 k1 gp sp s8 ra + t8 t9 k0 k1 gp sp s8 ra ]; attach variables [ rd_hw ] [ @@ -714,6 +778,7 @@ attach variables [ rd0_7 ] [ attach variables [ aclo acflo ] [ lo lo1 lo2 lo3 ]; attach variables [ achi acfhi ] [ hi hi1 hi2 hi3 ]; +attach variables [ ac acf ] [ ac0 ac1 ac2 ac3 ]; attach names hint [ "load" "store" "hint2" "hint3" "load_streamed" "store_streamed" "load_retained" "store_retained" @@ -721,6 +786,32 @@ attach names hint [ "hint16" "hint17" "hint18" "hint19" "hint20" "hint21" "hint22" "hint23" "hint24" "writeback_invalidate" "hint26" "hint27" "hint28" "hint29" "PrepareForStore" "hint31" ]; +attach variables [RTthread RDthread] [ + thread_zero thread_at thread_v0 thread_v1 thread_a0 thread_a1 thread_a2 thread_a3 + thread_t0 thread_t1 thread_t2 thread_t3 thread_t4 thread_t5 thread_t6 thread_t7 + thread_s0 thread_s1 thread_s2 thread_s3 thread_s4 thread_s5 thread_s6 thread_s7 + thread_t8 thread_t9 thread_k0 thread_k1 thread_gp thread_sp thread_s8 thread_ra +]; + +attach variables [ FTthread FDthread ] [ + thread_f0 thread_f1 thread_f2 thread_f3 thread_f4 thread_f5 thread_f6 thread_f7 + thread_f8 thread_f9 thread_f10 thread_f11 thread_f12 thread_f13 thread_f14 thread_f15 + thread_f16 thread_f17 thread_f18 thread_f19 thread_f20 thread_f21 thread_f22 thread_f23 + thread_f24 thread_f25 thread_f26 thread_f27 thread_f28 thread_f29 thread_f30 thread_f31 +]; + +attach variables [ rtmtdsp rdmtdsp ] [ + thread_lo0 thread_hi0 thread_acx0 _ thread_lo1 thread_hi1 thread_acx1 _ + thread_lo2 thread_hi2 thread_acx2 _ thread_lo3 thread_hi3 thread_acx3 _ + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ +]; + +attach variables [ FCTthread FCRthread ] [ + thread_fir _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ + _ thread_fccr thread_fexr _ thread_fenr _ _ thread_fcsr +]; # Subconstructors RD0: rd0_0 is rd0_0 & sel=0 { export rd0_0; } diff --git a/Ghidra/Processors/MIPS/data/languages/mips32Instructions.sinc b/Ghidra/Processors/MIPS/data/languages/mips32Instructions.sinc index 85b5b8918d..d2b91afd67 100644 --- a/Ghidra/Processors/MIPS/data/languages/mips32Instructions.sinc +++ b/Ghidra/Processors/MIPS/data/languages/mips32Instructions.sinc @@ -407,32 +407,11 @@ define pcodeop special2; RD = sext(*[ram]:1 INDEX_BASE); } -:lbux RD, INDEX_BASE is $(AMODE) & prime=0x1F & RD & fct=10 & fct2=6 & INDEX_BASE { - RD = zext(*[ram]:1 INDEX_BASE); -} - -@ifdef MIPS64 -:ldx RD, INDEX_BASE is $(AMODE) & prime=0x1F & RD & fct=10 & fct2=8 & INDEX_BASE { - RD = *[ram]:8 INDEX_BASE; -} -@endif - -:lhx RD, INDEX_BASE is $(AMODE) & prime=0x1F & RD & fct=10 & fct2=4 & INDEX_BASE { - RD = sext(*[ram]:2 INDEX_BASE); -} :lhux RD, INDEX_BASE is $(AMODE) & prime=0x1F & RD & fct=10 & fct2=20 & INDEX_BASE { RD = zext(*[ram]:2 INDEX_BASE); } -:lwx RD, INDEX_BASE is $(AMODE) & prime=0x1F & RD & fct=10 & fct2=0 & INDEX_BASE { -@ifdef MIPS64 - RD = sext(*[ram]:4 INDEX_BASE); -@else - RD = *[ram]:4 INDEX_BASE; -@endif -} - @ifdef MIPS64 :lwux RD, INDEX_BASE is $(AMODE) & prime=0x1F & RD & fct=10 & fct2=16 & INDEX_BASE { RD = zext(*[ram]:4 INDEX_BASE); @@ -1140,7 +1119,7 @@ define pcodeop SYNC; @endif # 0111 00ss ssst tttt 000a a000 0000 0000 -:madd RS32src, RT32src is $(AMODE) & REL6=0 & prime=0x1C & zero1315=0x0 & fct2=0x0 & fct=0x0 & RS32src & RT32src & achi & aclo { +:madd RS32src, RT32src is $(AMODE) & REL6=0 & prime=0x1C & zero1315=0x0 & fct2=0x0 & fct=0x0 & RS32src & RT32src & ac=0 & achi & aclo { tmp1:8 = sext(RS32src); tmp2:8 = sext(RT32src); prod:8 = tmp1 * tmp2; @@ -1152,7 +1131,7 @@ define pcodeop SYNC; } # 0111 00ss ssst tttt 000a a000 0000 0001 -:maddu RS32src, RT32src is $(AMODE) & REL6=0 & prime=0x1C & zero1315=0x0 & fct2=0x0 & fct=0x01 & RS32src & RT32src & achi & aclo { +:maddu RS32src, RT32src is $(AMODE) & REL6=0 & prime=0x1C & zero1315=0x0 & fct2=0x0 & fct=0x01 & RS32src & RT32src & ac=0 & achi & aclo { tmp1:8 = zext(RS32src); tmp2:8 = zext(RT32src); prod:8 = tmp1 * tmp2; @@ -1164,12 +1143,12 @@ define pcodeop SYNC; } # 0000 0000 0aa0 0000 dddd d000 0001 0000 -:mfhi RD is $(AMODE) & REL6=0 & prime=0 & fct=0x10 & RD & zero5=0 & zero1620=0 & zero2325=0 & acfhi { +:mfhi RD is $(AMODE) & REL6=0 & prime=0 & fct=0x10 & RD & zero5=0 & zero1620=0 & zero2325=0 & acf=0 & acfhi { RD = acfhi; } # 0000 0000 0aa0 0000 dddd d000 0001 0010 -:mflo RD is $(AMODE) & REL6=0 & prime=0 & fct=0x12 & RD & zero5=0 & zero1620=0 & zero2325=0 & acflo { +:mflo RD is $(AMODE) & REL6=0 & prime=0 & fct=0x12 & RD & zero5=0 & zero1620=0 & zero2325=0 & acf=0 & acflo { RD = acflo; } @@ -1201,7 +1180,7 @@ define pcodeop SYNC; } # 0111 00ss ssst tttt 000a a000 0000 0101 -:msubu RS32src, RT32src is $(AMODE) & REL6=0 & prime=0x1C & fct2=0 & fct=0x05 & RS32src & RT32src & zero1315=0 & aclo & achi { +:msubu RS32src, RT32src is $(AMODE) & REL6=0 & prime=0x1C & fct2=0 & fct=0x05 & RS32src & RT32src & zero1315=0 & ac=0 & aclo & achi { tmp1:8 = zext(RS32src); tmp2:8 = zext(RT32src); prod:8 = tmp1 * tmp2; @@ -1213,12 +1192,12 @@ define pcodeop SYNC; } # 0000 00ss sss0 0000 000a a000 0001 0001 -:mthi RSsrc is $(AMODE) & REL6=0 & prime=0 & fct=0x11 & RSsrc & zero5=0 & zero1320=0 & achi { +:mthi RSsrc is $(AMODE) & REL6=0 & prime=0 & fct=0x11 & RSsrc & zero5=0 & zero1320=0 & ac=0 & achi { achi = RSsrc; } # 0000 00ss sss0 0000 000a a000 0001 0011 -:mtlo RSsrc is $(AMODE) & REL6=0 & prime=0 & fct=0x13 & RSsrc & zero5=0 & zero1320=0 & aclo { +:mtlo RSsrc is $(AMODE) & REL6=0 & prime=0 & fct=0x13 & RSsrc & zero5=0 & zero1320=0 & ac=0 & aclo { aclo = RSsrc; } diff --git a/Ghidra/Processors/MIPS/data/languages/mips32R6be.slaspec b/Ghidra/Processors/MIPS/data/languages/mips32R6be.slaspec index c3cf7b3411..bb06d7017d 100644 --- a/Ghidra/Processors/MIPS/data/languages/mips32R6be.slaspec +++ b/Ghidra/Processors/MIPS/data/languages/mips32R6be.slaspec @@ -1,11 +1,11 @@ # SLA specification file for MIPS32 big endian @define ENDIAN "big" -@define FREGSIZE "8" +@define FREGSIZE "8" @define ISA_VARIANT "" @include "mips.sinc" @include "mips32Instructions.sinc" @include "mips16.sinc" @include "mipsmicro.sinc" - +@include "mips_dsp.sinc" diff --git a/Ghidra/Processors/MIPS/data/languages/mips32R6le.slaspec b/Ghidra/Processors/MIPS/data/languages/mips32R6le.slaspec index e06db5d8b5..5355fd4b63 100644 --- a/Ghidra/Processors/MIPS/data/languages/mips32R6le.slaspec +++ b/Ghidra/Processors/MIPS/data/languages/mips32R6le.slaspec @@ -1,10 +1,11 @@ # SLA specification file for MIPS32 little endian @define ENDIAN "little" -@define FREGSIZE "8" +@define FREGSIZE "8" @define ISA_VARIANT "" @include "mips.sinc" @include "mips32Instructions.sinc" @include "mips16.sinc" @include "mipsmicro.sinc" +@include "mips_dsp.sinc" \ No newline at end of file diff --git a/Ghidra/Processors/MIPS/data/languages/mips32be.slaspec b/Ghidra/Processors/MIPS/data/languages/mips32be.slaspec index cac287b84f..76b9077086 100644 --- a/Ghidra/Processors/MIPS/data/languages/mips32be.slaspec +++ b/Ghidra/Processors/MIPS/data/languages/mips32be.slaspec @@ -8,4 +8,5 @@ @include "mips32Instructions.sinc" @include "mips16.sinc" @include "mipsmicro.sinc" - +@include "mips_mt.sinc" +@include "mips_dsp.sinc" diff --git a/Ghidra/Processors/MIPS/data/languages/mips32le.slaspec b/Ghidra/Processors/MIPS/data/languages/mips32le.slaspec index d0fbd4c6a3..3620d20236 100644 --- a/Ghidra/Processors/MIPS/data/languages/mips32le.slaspec +++ b/Ghidra/Processors/MIPS/data/languages/mips32le.slaspec @@ -8,3 +8,5 @@ @include "mips32Instructions.sinc" @include "mips16.sinc" @include "mipsmicro.sinc" +@include "mips_mt.sinc" +@include "mips_dsp.sinc" diff --git a/Ghidra/Processors/MIPS/data/languages/mips64be.slaspec b/Ghidra/Processors/MIPS/data/languages/mips64be.slaspec index 7f51c41d40..5bf0368c53 100644 --- a/Ghidra/Processors/MIPS/data/languages/mips64be.slaspec +++ b/Ghidra/Processors/MIPS/data/languages/mips64be.slaspec @@ -9,3 +9,4 @@ @include "mips16.sinc" @include "mipsmicro.sinc" @include "mips64Instructions.sinc" +@include "mips_dsp.sinc" diff --git a/Ghidra/Processors/MIPS/data/languages/mips64le.slaspec b/Ghidra/Processors/MIPS/data/languages/mips64le.slaspec index 0bb47bb436..abce05d12d 100644 --- a/Ghidra/Processors/MIPS/data/languages/mips64le.slaspec +++ b/Ghidra/Processors/MIPS/data/languages/mips64le.slaspec @@ -9,3 +9,5 @@ @include "mips16.sinc" @include "mipsmicro.sinc" @include "mips64Instructions.sinc" +@include "mips_dsp.sinc" + diff --git a/Ghidra/Processors/MIPS/data/languages/mips_dsp.sinc b/Ghidra/Processors/MIPS/data/languages/mips_dsp.sinc new file mode 100644 index 0000000000..e4c183515c --- /dev/null +++ b/Ghidra/Processors/MIPS/data/languages/mips_dsp.sinc @@ -0,0 +1,1242 @@ + +define pcodeop ABSQ_S.PH; +define pcodeop ABSQ_S.QB; +define pcodeop ABSQ_S.W; +define pcodeop ADDQ.PH; +define pcodeop ADDQ_S.W; +define pcodeop ADDQH.PH; +define pcodeop ADDQH.W; +define pcodeop ADDSC; +define pcodeop ADDU.PH; +define pcodeop ADDU.QB; +define pcodeop ADDWC; +define pcodeop ADDUH.QB; +define pcodeop BITREV; +define pcodeop DPA.W.PH; +define pcodeop DPAQ_S.W.PH; +define pcodeop DPAQ_SA.L.W; +define pcodeop DPAQX_S.W.PH; +define pcodeop DPAQX_SA.W.PH; +define pcodeop DPAU.H.QBL; +define pcodeop DPAU.H.QBR; +define pcodeop DPAX.W.PH; +define pcodeop DPS.W.PH; +define pcodeop DPSQ_S.W.PH; +define pcodeop DPSQ_SA.L.W; +define pcodeop DPSQX_S.W.PH; +define pcodeop DPSQX_SA.W.PH; +define pcodeop DPSU.H.QBL; +define pcodeop DPSU.H.QBR; +define pcodeop DPSX.W.PH; +define pcodeop EXTP; +define pcodeop EXTPDP; +define pcodeop EXTPDPV; +define pcodeop EXTPV; +define pcodeop EXTR.W; +define pcodeop EXTR_S.H; +define pcodeop EXTRV.W; +define pcodeop EXTRV_S.H; +define pcodeop INSV; +define pcodeop MAQ_S.W.PHL; +define pcodeop MAQ_S.W.PHR; +define pcodeop MUL.PH; +define pcodeop MULEQ_S.W.PHL; +define pcodeop MULEQ_S.W.PHR; +define pcodeop MULEU_S.PH.QBL; +define pcodeop MULEU_S.PH.QBR; +define pcodeop MULQ_RS.PH; +define pcodeop MULQ_RS.W; +define pcodeop MULQ_S.PH; +define pcodeop MULQ_S.W; +define pcodeop MULSA.W.PH; +define pcodeop MULSAQ_S.W.PH; +define pcodeop PRECEQ.W.PHL; +define pcodeop PRECEQ.W.PHR; +define pcodeop PRECEQU.PH.QBL; +define pcodeop PRECEQU.PH.QBLA; +define pcodeop PRECEQU.PH.QBR; +define pcodeop PRECEQU.PH.QBRA; +define pcodeop PRECEU.PH.QBL; +define pcodeop PRECEU.PH.QBLA; +define pcodeop PRECEU.PH.QBR; +define pcodeop PRECEU.PH.QBRA; +define pcodeop PRECR.QB.PH; +define pcodeop PRECR_SRA.PH.W; +define pcodeop PRECRQ.PH.W; +define pcodeop PRECRQ.QB.PH; +define pcodeop PRECRQU_S.QB.PH; +define pcodeop PRECRQ_RS.PH.W; +define pcodeop RADDU.W.QB; +define pcodeop REPLV.PH; +define pcodeop REPLV.QB; +define pcodeop SHLL.PH; +define pcodeop SHLL.QB; +define pcodeop SHLLV.PH; +define pcodeop SHLLV.QB; +define pcodeop SHLLV_S.W; +define pcodeop SHLL_S.W; +define pcodeop SHRA.QB; +define pcodeop SHRA.PH; +define pcodeop SHRAV.PH; +define pcodeop SHRAV.QB; +define pcodeop SHRAV_R.W; +define pcodeop SHRA_R.W; +define pcodeop SHRL.PH; +define pcodeop SHRL.QB; +define pcodeop SHRLV.PH; +define pcodeop SHRLV.QB; +define pcodeop SUBQ.PH; +define pcodeop SUBQ_S.W; +define pcodeop SUBQH.PH; +define pcodeop SUBQH.W; +define pcodeop SUBU.PH; +define pcodeop SUBU.QB; +define pcodeop SUBUH.QB; + + +# ABSQ_S.PH Purpose: Find Absolute Value of Two Fractional Halfwords +:absq_s.ph RD, RTsrc is $(AMODE) & prime=0x1f & zero21=0x0 & RTsrc & RD & fct2=0x9 & fct=0x12 { + RD = ABSQ_S.PH(RTsrc); +} + + +# ABSQ_S.QB Purpose: Find Absolute Value of Four Fractional Byte Values +:absq_s.qb RD, RTsrc is $(AMODE) & prime=0x1f & zero21=0x0 & RTsrc & RD & fct2=0x1 & fct=0x12 { + RD = ABSQ_S.QB(RTsrc); +} + + +# ABSQ_S.W Purpose: Find Absolute Value of Fractional Word +:absq_s.w RD, RTsrc is $(AMODE) & prime=0x1f & zero21=0x0 & RTsrc & RD & fct2=0x11 & fct=0x12 { + RD = ABSQ_S.W(RTsrc); +} + + +# ADDQ[_S].PH Purpose: Add Fractional Halfword Vectors +:addq.ph RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0xa & fct=0x10 { + RD = ADDQ.PH(RSsrc, RTsrc); +} + +:addq_s.ph RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0xe & fct=0x10 { + RD = ADDQ.PH(RSsrc, RTsrc); +} + + +# ADDQ_S.W Purpose: Add Fractional Words +:addq_s.w RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x16 & fct=0x10 { + RD = ADDQ_S.W(RSsrc, RTsrc); +} + + +# ADDQH[_R].PH Purpose: Add Fractional Halfword Vectors And Shift Right to Halve Results +:addqh.ph RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x8 & fct=0x18 { + RD = ADDQH.PH(RSsrc, RTsrc); +} + +:addqh_r.ph RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0xa & fct=0x18 { + RD = ADDQH.PH(RSsrc, RTsrc); +} + + +# ADDQH[_R].W Purpose: Add Fractional Words And Shift Right to Halve Results +:addqh.w RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x10 & fct=0x18 { + RD = ADDQH.W(RSsrc, RTsrc); +} + +:addqh_r.w RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x12 & fct=0x18 { + RD = ADDQH.W(RSsrc, RTsrc); +} + + +# ADDSC Purpose: Add Signed Word and Set Carry Bit +:addsc RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x10 & fct=0x10 { + RD = ADDSC(RSsrc, RTsrc); +} + + +# ADDU[_S].PH Purpose: Unsigned Add Integer Halfwords +:addu.ph RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x8 & fct=0x10 { + RD = ADDU.PH(RSsrc, RTsrc); +} + +:addu_s.ph RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0xc & fct=0x10 { + RD = ADDU.PH(RSsrc, RTsrc); +} + + +# ADDU[_S].QB Purpose: Unsigned Add Quad Byte Vectors +:addu.qb RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x0 & fct=0x10 { + RD = ADDU.QB(RSsrc, RTsrc); +} + +:addu_s.qb RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x4 & fct=0x10 { + RD = ADDU.QB(RSsrc, RTsrc); +} + + +# ADDWC Purpose: Add Word with Carry Bit +:addwc RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x11 & fct=0x10 { + RD = ADDWC(RSsrc, RTsrc); +} + + +# ADDUH[_R].QB Purpose: Unsigned Add Vector Quad-Bytes And Right Shift to Halve Results +:adduh.qb RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x0 & fct=0x18 { + RD = ADDUH.QB(RSsrc, RTsrc); +} + +:adduh_r.qb RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x2 & fct=0x18 { + RD = ADDUH.QB(RSsrc, RTsrc); +} + + +# APPEND Purpose: Left Shift and Append Bits to the LSB +:append RTsrc, RSsrc, sa_dsp is $(AMODE) & prime=0x1f & RSsrc & RTsrc & sa_dsp & fct2=0x0 & fct=0x31 { + RSval:$(REGSIZE) = RSsrc & (2^sa_dsp-1); + RTsrc = (RTsrc << sa_dsp) | (RSval); +} + + +# BALIGN Purpose: Byte Align Contents from Two Registers +:balign RTsrc, RSsrc, bp is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero1315=0x0 & bp & fct2=0x10 & fct=0x31 { + RTsrc = (RTsrc << 8*bp) | (RSsrc >> 8*(4-bp)); +} + + +# BITREV Purpose: Bit-Reverse Halfword +:bitrev RD, RTsrc is $(AMODE) & prime=0x1f & zero21=0x0 & RTsrc & RD & fct2=0x1b & fct=0x12 { + RD = BITREV(RTsrc); +} + + +# BPOSGE32 Purpose: Branch on Greater Than or Equal To Value 32 in DSPControl Pos Field +:bposge32 Rel16 is $(AMODE) & prime=0x1 & zero21=0x0 & op=0x1c & Rel16 { + dsp_pos:$(REGSIZE) = DSPControl & 0x1f; + if (dsp_pos < 32) goto inst_next; + delayslot(1); + goto Rel16; +} + +# BPOSGE32C Purpose: Branch on Greater Than or Equal To Value 32 in DSPControl Pos Field Compact +# no branch delay +:bposge32c Rel16 is $(AMODE) & prime=0x1 & zero21=0x0 & op=0x1a & Rel16 { + dsp_pos:$(REGSIZE) = DSPControl & 0x1f; + if (dsp_pos < 32) goto inst_next; + goto Rel16; +} + +# CMP.cond.PH Purpose: Compare Vectors of Signed Integer Halfword Values +:cmp.eq.ph RSsrc, RTsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero4=0x0 & fct2=0x8 & fct=0x11 { + tmp_rs:2 = RSsrc(0) & 0xffff; + tmp_rt:2 = RTsrc(0) & 0xffff; + cca:1 = (tmp_rs == tmp_rt); + tmp_rs = RSsrc(2) & 0xffff; + tmp_rt = RTsrc(2) & 0xffff; + ccb:1 = (tmp_rs == tmp_rt); + flags:$(REGSIZE) = 0xfcffffff; + DSPControl = (DSPControl & flags) | zext(cca << 24) | zext(ccb << 25); +} + +:cmp.lt.ph RSsrc, RTsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero4=0x0 & fct2=0x9 & fct=0x11 { + tmp_rs:2 = RSsrc(0) & 0xffff; + tmp_rt:2 = RTsrc(0) & 0xffff; + cca:1 = (tmp_rs s< tmp_rt); + tmp_rs = RSsrc(2) & 0xffff; + tmp_rt = RTsrc(2) & 0xffff; + ccb:1 = (tmp_rs s< tmp_rt); + flags:$(REGSIZE) = 0xfcffffff; + DSPControl = (DSPControl & flags) | zext(cca << 24) | zext(ccb << 25); +} + +:cmp.le.ph RSsrc, RTsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero4=0x0 & fct2=0xa & fct=0x11 { + tmp_rs:2 = RSsrc(0) & 0xffff; + tmp_rt:2 = RTsrc(0) & 0xffff; + cca:1 = (tmp_rs s<= tmp_rt); + tmp_rs = RSsrc(2) & 0xffff; + tmp_rt = RTsrc(2) & 0xffff; + ccb:1 = (tmp_rs s<= tmp_rt); + flags:$(REGSIZE) = 0xfcffffff; + DSPControl = (DSPControl & flags) | zext(cca << 24) | zext(ccb << 25); +} + + +# CMPGDU.cond.QB Purpose: Compare Unsigned Vector of Four Bytes and Write Result to GPR and DSPControl +:cmpgdu.eq.qb RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x18 & fct=0x11 { + tmp_rs:1 = RSsrc(0) & 0xff; + tmp_rt:1 = RTsrc(0) & 0xff; + cca:$(REGSIZE) = zext(tmp_rs == tmp_rt); + tmp_rs = RSsrc(1) & 0xff; + tmp_rt = RTsrc(1) & 0xff; + ccb:$(REGSIZE) = zext(tmp_rs == tmp_rt); + tmp_rs = RSsrc(2) & 0xff; + tmp_rt = RTsrc(2) & 0xff; + ccc:$(REGSIZE) = zext(tmp_rs == tmp_rt); + tmp_rs = RSsrc(3) & 0xff; + tmp_rt = RTsrc(3) & 0xff; + ccd:$(REGSIZE) = zext(tmp_rs == tmp_rt); + flags:$(REGSIZE) = 0xf0ffffff; + DSPControl = (DSPControl & flags) | (ccd << 27) | (ccc << 26) | (ccb << 25) | (cca << 24); + RD = (ccd << 3) | (ccc << 2) | (ccb << 1) | (cca); +} + +:cmpgdu.lt.qb RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x19 & fct=0x11 { + tmp_rs:1 = RSsrc(0) & 0xff; + tmp_rt:1 = RTsrc(0) & 0xff; + cca:$(REGSIZE) = zext(tmp_rs < tmp_rt); + tmp_rs = RSsrc(1) & 0xff; + tmp_rt = RTsrc(1) & 0xff; + ccb:$(REGSIZE) = zext(tmp_rs < tmp_rt); + tmp_rs = RSsrc(2) & 0xff; + tmp_rt = RTsrc(2) & 0xff; + ccc:$(REGSIZE) = zext(tmp_rs < tmp_rt); + tmp_rs = RSsrc(3) & 0xff; + tmp_rt = RTsrc(3) & 0xff; + ccd:$(REGSIZE) = zext(tmp_rs < tmp_rt); + flags:$(REGSIZE) = 0xf0ffffff; + DSPControl = (DSPControl & flags) | (cca << 24) | (ccb << 25) | (ccc << 26) | (ccd << 27); + RD = (cca) | (ccb << 1) | (ccc << 2) | (ccd << 3); +} + +:cmpgdu.le.qb RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x1a & fct=0x11 { + tmp_rs:1 = RSsrc(0) & 0xff; + tmp_rt:1 = RTsrc(0) & 0xff; + cca:$(REGSIZE) = zext(tmp_rs <= tmp_rt); + tmp_rs = RSsrc(1) & 0xff; + tmp_rt = RTsrc(1) & 0xff; + ccb:$(REGSIZE) = zext(tmp_rs <= tmp_rt); + tmp_rs = RSsrc(2) & 0xff; + tmp_rt = RTsrc(2) & 0xff; + ccc:$(REGSIZE) = zext(tmp_rs <= tmp_rt); + tmp_rs = RSsrc(3) & 0xff; + tmp_rt = RTsrc(3) & 0xff; + ccd:$(REGSIZE) = zext(tmp_rs <= tmp_rt); + flags:$(REGSIZE) = 0xf0ffffff; + DSPControl = (DSPControl & flags) | (cca << 24) | (ccb << 25) | (ccc << 26) | (ccd << 27); + RD = (cca) | (ccb << 1) | (ccc << 2) | (ccd << 3); +} + + +# CMPGU.cond.QB Purpose: Compare Vectors of Unsigned Byte Values and Write Results to a GPR +:cmpgu.eq.qb RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x4 & fct=0x11 { + tmp_rs:1 = RSsrc(0) & 0xff; + tmp_rt:1 = RTsrc(0) & 0xff; + cca:1 = (tmp_rs == tmp_rt); + tmp_rs = RSsrc(1) & 0xff; + tmp_rt = RTsrc(1) & 0xff; + ccb:1 = (tmp_rs == tmp_rt); + tmp_rs = RSsrc(2) & 0xff; + tmp_rt = RTsrc(2) & 0xff; + ccc:1 = (tmp_rs == tmp_rt); + tmp_rs = RSsrc(3) & 0xff; + tmp_rt = RTsrc(3) & 0xff; + ccd:1 = (tmp_rs == tmp_rt); + RD = zext(cca) | zext(ccb << 1) | zext(ccc << 2) | zext(ccd << 3); +} + +:cmpgu.lt.qb RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x5 & fct=0x11 { + tmp_rs:1 = RSsrc(0) & 0xff; + tmp_rt:1 = RTsrc(0) & 0xff; + cca:1 = (tmp_rs < tmp_rt); + tmp_rs = RSsrc(1) & 0xff; + tmp_rt = RTsrc(1) & 0xff; + ccb:1 = (tmp_rs < tmp_rt); + tmp_rs = RSsrc(2) & 0xff; + tmp_rt = RTsrc(2) & 0xff; + ccc:1 = (tmp_rs < tmp_rt); + tmp_rs = RSsrc(3) & 0xff; + tmp_rt = RTsrc(3) & 0xff; + ccd:1 = (tmp_rs < tmp_rt); + RD = zext(cca) | zext(ccb << 1) | zext(ccc << 2) | zext(ccd << 3); +} + +:cmpgu.le.qb RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x6 & fct=0x11 { + tmp_rs:1 = RSsrc(0) & 0xff; + tmp_rt:1 = RTsrc(0) & 0xff; + cca:1 = (tmp_rs <= tmp_rt); + tmp_rs = RSsrc(1) & 0xff; + tmp_rt = RTsrc(1) & 0xff; + ccb:1 = (tmp_rs <= tmp_rt); + tmp_rs = RSsrc(2) & 0xff; + tmp_rt = RTsrc(2) & 0xff; + ccc:1 = (tmp_rs <= tmp_rt); + tmp_rs = RSsrc(3) & 0xff; + tmp_rt = RTsrc(3) & 0xff; + ccd:1 = (tmp_rs <= tmp_rt); + RD = zext(cca) | zext(ccb << 1) | zext(ccc << 2) | zext(ccd << 3); +} + + +# CMPU.cond.QB Purpose: Compare Vectors of Unsigned Byte Values +:cmpu.eq.qb RSsrc, RTsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero4=0x0 & fct2=0x0 & fct=0x11 { + tmp_rs:1 = RSsrc(0) & 0xff; + tmp_rt:1 = RTsrc(0) & 0xff; + cca:1 = (tmp_rs == tmp_rt); + tmp_rs = RSsrc(1) & 0xff; + tmp_rt = RTsrc(1) & 0xff; + ccb:1 = (tmp_rs == tmp_rt); + tmp_rs = RSsrc(2) & 0xff; + tmp_rt = RTsrc(2) & 0xff; + ccc:1 = (tmp_rs == tmp_rt); + tmp_rs = RSsrc(3) & 0xff; + tmp_rt = RTsrc(3) & 0xff; + ccd:1 = (tmp_rs == tmp_rt); + flags:$(REGSIZE) = 0xf0ffffff; + DSPControl = (DSPControl & flags) | zext(cca << 24) | zext(ccb << 25) | zext(ccc << 26) | zext(ccd << 27); +} + +:cmpu.lt.qb RSsrc, RTsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero4=0x0 & fct2=0x1 & fct=0x11 { + tmp_rs:1 = RSsrc(0) & 0xff; + tmp_rt:1 = RTsrc(0) & 0xff; + cca:1 = (tmp_rs < tmp_rt); + tmp_rs = RSsrc(1) & 0xff; + tmp_rt = RTsrc(1) & 0xff; + ccb:1 = (tmp_rs < tmp_rt); + tmp_rs = RSsrc(2) & 0xff; + tmp_rt = RTsrc(2) & 0xff; + ccc:1 = (tmp_rs < tmp_rt); + tmp_rs = RSsrc(3) & 0xff; + tmp_rt = RTsrc(3) & 0xff; + ccd:1 = (tmp_rs < tmp_rt); + flags:$(REGSIZE) = 0xf0ffffff; + DSPControl = (DSPControl & flags) | zext(cca << 24) | zext(ccb << 25) | zext(ccc << 26) | zext(ccd << 27); +} + +:cmpu.le.qb RSsrc, RTsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero4=0x0 & fct2=0x2 & fct=0x11 { + tmp_rs:1 = RSsrc(0) & 0xff; + tmp_rt:1 = RTsrc(0) & 0xff; + cca:1 = (tmp_rs <= tmp_rt); + tmp_rs = RSsrc(1) & 0xff; + tmp_rt = RTsrc(1) & 0xff; + ccb:1 = (tmp_rs <= tmp_rt); + tmp_rs = RSsrc(2) & 0xff; + tmp_rt = RTsrc(2) & 0xff; + ccc:1 = (tmp_rs <= tmp_rt); + tmp_rs = RSsrc(3) & 0xff; + tmp_rt = RTsrc(3) & 0xff; + ccd:1 = (tmp_rs <= tmp_rt); + flags:$(REGSIZE) = 0xf0ffffff; + DSPControl = (DSPControl & flags) | zext(cca << 24) | zext(ccb << 25) | zext(ccc << 26) | zext(ccd << 27); +} + + +# DPA.W.PH Purpose: Dot Product with Accumulate on Vector Integer Halfword Elements +:dpa.w.ph ac, RSsrc, RTsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero1315=0x0 & ac & fct2=0x0 & fct=0x30 { + ac = DPA.W.PH(ac, RSsrc, RTsrc); +} + + +# DPAQ_S.W.PH Purpose: Dot Product with Accumulation on Fractional Halfword Elements +:dpaq_s.w.ph ac, RSsrc, RTsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero1315=0x0 & ac & fct2=0x4 & fct=0x30 { + ac = DPAQ_S.W.PH(ac, RSsrc, RTsrc); +} + + +# DPAQ_SA.L.W Purpose: Dot Product with Accumulate on Fractional Word Element +:dpaq_sa.l.w ac, RSsrc, RTsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero1315=0x0 & ac & fct2=0xc & fct=0x30 { + ac = DPAQ_SA.L.W(ac, RSsrc, RTsrc); +} + + +# DPAQX_S.W.PH Purpose: Cross Dot Product with Accumulation on Fractional Halfword Elements +:dpaqx_s.w.ph ac, RSsrc, RTsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero1315=0x0 & ac & fct2=0x18 & fct=0x30 { + ac = DPAQX_S.W.PH(ac, RSsrc, RTsrc); +} + + +# DPAQX_SA.W.PH Purpose: Cross Dot Product with Accumulation on Fractional Halfword Elements +:dpaqx_sa.w.ph ac, RSsrc, RTsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero1315=0x0 & ac & fct2=0x1a & fct=0x30 { + ac = DPAQX_SA.W.PH(ac, RSsrc, RTsrc); +} + + +# DPAU.H.QBL Purpose: Dot Product with Accumulate on Vector Unsigned Byte Elements +:dpau.h.qbl ac, RSsrc, RTsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero1315=0x0 & ac & fct2=0x3 & fct=0x30 { + ac = DPAU.H.QBL(ac, RSsrc, RTsrc); +} + + +# DPAU.H.QBR Purpose: Dot Product with Accumulate on Vector Unsigned Byte Elements +:dpau.h.qbr ac, RSsrc, RTsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero1315=0x0 & ac & fct2=0x7 & fct=0x30 { + ac = DPAU.H.QBR(ac, RSsrc, RTsrc); +} + + +# DPAX.W.PH Purpose: Cross Dot Product with Accumulate on Vector Integer Halfword Elements +:dpax.w.ph ac, RSsrc, RTsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero1315=0x0 & ac & fct2=0x8 & fct=0x30 { + ac = DPAX.W.PH(ac, RSsrc, RTsrc); +} + + +# DPS.W.PH Purpose: Dot Product with Subtract on Vector Integer Half-Word Elements +:dps.w.ph ac, RSsrc, RTsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero1315=0x0 & ac & fct2=0x1 & fct=0x30 { + ac = DPS.W.PH(ac, RSsrc, RTsrc); +} + + +# DPSQ_S.W.PH Purpose: Dot Product with Subtraction on Fractional Halfword Elements +:dpsq_s.w.ph ac, RSsrc, RTsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero1315=0x0 & ac & fct2=0x5 & fct=0x30 { + ac = DPSQ_S.W.PH(ac, RSsrc, RTsrc); +} + + +# DPSQ_SA.L.W Purpose: Dot Product with Subtraction on Fractional Word Element +:dpsq_sa.l.w ac, RSsrc, RTsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero1315=0x0 & ac & fct2=0xd & fct=0x30 { + ac = DPSQ_SA.L.W(ac, RSsrc, RTsrc); +} + + +# DPSQX_S.W.PH Purpose: Cross Dot Product with Subtraction on Fractional Halfword Elements +:dpsqx_s.w.ph ac, RSsrc, RTsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero1315=0x0 & ac & fct2=0x19 & fct=0x30 { + ac = DPSQX_S.W.PH(ac, RSsrc, RTsrc); +} + + +# DPSQX_SA.W.PH Purpose: Cross Dot Product with Subtraction on Fractional Halfword Elements +:dpsqx_sa.w.ph ac, RSsrc, RTsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero1315=0x0 & ac & fct2=0x1b & fct=0x30 { + ac = DPSQX_SA.W.PH(ac, RSsrc, RTsrc); +} + + +# DPSU.H.QBL Purpose: Dot Product with Subtraction on Vector Unsigned Byte Elements +:dpsu.h.qbl ac, RSsrc, RTsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero1315=0x0 & ac & fct2=0xb & fct=0x30 { + ac = DPSU.H.QBL(ac, RSsrc, RTsrc); +} + + +# DPSU.H.QBR Purpose: Dot Product with Subtraction on Vector Unsigned Byte Elements +:dpsu.h.qbr ac, RSsrc, RTsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero1315=0x0 & ac & fct2=0xf & fct=0x30 { + ac = DPSU.H.QBR(ac, RSsrc, RTsrc); +} + + +# DPSX.W.PH Purpose: Cross Dot Product with Subtract on Vector Integer Halfword Elements +:dpsx.w.ph ac, RSsrc, RTsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero1315=0x0 & ac & fct2=0x9 & fct=0x30 { + ac = DPSX.W.PH(ac, RSsrc, RTsrc); +} + + +# EXTP Purpose: Extract Fixed Bitfield From Arbitrary Position in Accumulator to GPR +:extp RT, ac, sz is $(AMODE) & prime=0x1f & sz & RT & zero1315=0x0 & ac & fct2=0x2 & fct=0x38 { + RT = EXTP(ac, sz:1); +} + + +# EXTPDP Purpose: Extract Fixed Bitfield From Arbitrary Position in Accumulator to GPR and Decrement Pos +:extpdp RT, ac, sz is $(AMODE) & prime=0x1f & sz & RT & zero1315=0x0 & ac & fct2=0xa & fct=0x38 { + RT = EXTPDP(ac, sz:1); +} + + +# EXTPDPV Purpose: Extract Variable Bitfield From Arbitrary Position in Accumulator to GPR and Decrement Pos +:extpdpv RT, ac, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RT & zero1315=0x0 & ac & fct2=0xb & fct=0x38 { + RT = EXTPDPV(ac, RSsrc); +} + + +# EXTPV Purpose: Extract Variable Bitfield From Arbitrary Position in Accumulator to GPR +:extpv RT, ac, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RT & zero1315=0x0 & ac & fct2=0x3 & fct=0x38 { + RT = EXTPV(ac, RSsrc); +} + + +# EXTR[_RS].W Purpose: Extract Word Value With Right Shift From Accumulator to GPR +:extr.w RT, ac, shift21 is $(AMODE) & prime=0x1f & shift21 & RT & zero1315=0x0 & ac & fct2=0x0 & fct=0x38 { + val:$(DREGSIZE) = ac >> shift21:1; + result:4 = val(0); + RT = zext(result); +} + +:extr_r.w RT, ac, shift21 is $(AMODE) & prime=0x1f & shift21 & RT & zero1315=0x0 & ac & fct2=0x4 & fct=0x38 { + val:$(DREGSIZE) = ac >> shift21:1; + result:4 = val(0); + RT = EXTR.W(result, 1:1); +} + +:extr_rs.w RT, ac, shift21 is $(AMODE) & prime=0x1f & shift21 & RT & zero1315=0x0 & ac & fct2=0x6 & fct=0x38 { + val:$(DREGSIZE) = ac >> shift21:1; + result:4 = val(0); + RT = EXTR.W(result, 2:1); +} + + +# EXTR_S.H Purpose: Extract Halfword Value From Accumulator to GPR With Right Shift and Saturate +:extr_s.h RT, ac, shift21 is $(AMODE) & prime=0x1f & shift21 & RT & zero1315=0x0 & ac & fct2=0xe & fct=0x38 { + val:$(DREGSIZE) = ac >> shift21:1; + result:2 = val(0); + RT = EXTR_S.H(result); +} + + +# EXTRV[_RS].W Purpose: Extract Word Value With Variable Right Shift From Accumulator to GPR +:extrv.w RT, ac, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RT & zero1315=0x0 & ac & fct2=0x1 & fct=0x38 { + shift:1 = RSsrc(0) & 0x3f; + val:$(DREGSIZE) = ac >> shift; + result:4 = val(0); + RT = EXTRV.W(result, 0:1); +} + +:extrv_r.w RT, ac, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RT & zero1315=0x0 & ac & fct2=0x5 & fct=0x38 { + shift:1 = RSsrc(0) & 0x3f; + val:$(DREGSIZE) = ac >> shift; + result:4 = val(0); + RT = EXTRV.W(result, 1:1); +} + +:extrv_rs.w RT, ac, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RT & zero1315=0x0 & ac & fct2=0x7 & fct=0x38 { + shift:1 = RSsrc(0) & 0x3f; + val:$(DREGSIZE) = ac >> shift; + result:4 = val(0); + RT = EXTRV.W(result, 2:1); +} + + +# EXTRV_S.H Purpose: Extract Halfword Value Variable From Accumulator to GPR With Right Shift and Saturate +:extrv_s.h RT, ac, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RT & zero1315=0x0 & ac & fct2=0xf & fct=0x38 { + shift:1 = RSsrc(0) & 0x3f; + val:$(DREGSIZE) = ac >> shift; + result:2 = val(0); + RT = EXTR_S.H(result); +} + + +# INSV Purpose: Insert Bit Field Variable +:insv RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero4=0x0 & fct2=0x0 & fct=0xc { + RTsrc = INSV(RTsrc, RSsrc); +} + + +# LBUX Purpose: Load Unsigned Byte Indexed +:lbux RD, INDEX_BASE is $(AMODE) & prime=0x1f & INDEX_BASE & RD & fct2=0x6 & fct=0xa { + RD = zext(*[ram]:1 INDEX_BASE); +} + +@ifdef MIPS64 +# LDX Load Doubleword Indexed +:ldx RD, INDEX_BASE is $(AMODE) & prime=0x1F & RD & fct=10 & fct2=8 & INDEX_BASE { + RD = *[ram]:8 INDEX_BASE; +} +@endif + +# LHX Purpose: Load Halfword Indexed +:lhx RD, INDEX_BASE is $(AMODE) & prime=0x1f & INDEX_BASE & RD & fct2=0x4 & fct=0xa { + RD = sext(*[ram]:2 INDEX_BASE); +} + + +# LWX Purpose: Load Word Indexed +:lwx RD, INDEX_BASE is $(AMODE) & prime=0x1f & INDEX_BASE & RD & fct2=0x0 & fct=0xa { +@ifdef MIPS64 + RD = sext(*[ram]:4 INDEX_BASE); +@else + RD = *[ram]:4 INDEX_BASE; +@endif +} + +# MADD Purpose: Multiply Word and Add to Accumulator +:madd ac, RS32src, RT32src is $(AMODE) & prime=0x1c & RS32src & RT32src & zero1315=0x0 & ac & fct2=0x0 & fct=0x0 { + tmp1:$(DREGSIZE) = zext(RS32src); + tmp2:$(DREGSIZE) = zext(RT32src); + prod:$(DREGSIZE) = tmp1 * tmp2; + ac = ac + prod; +} + + +# MADDU Purpose: Multiply Unsigned Word and Add to Accumulator +:maddu ac, RS32src, RT32src is $(AMODE) & prime=0x1c & RS32src & RT32src & zero1315=0x0 & ac & fct2=0x0 & fct=0x1 { + tmp1:$(DREGSIZE) = zext(RS32src); + tmp2:$(DREGSIZE) = zext(RT32src); + prod:$(DREGSIZE) = tmp1 * tmp2; + ac = ac + prod; + +} + + +# MAQ_S[A].W.PHL Purpose: Multiply with Accumulate Single Vector Fractional Halfword Element +:maq_s.w.phl ac, RSsrc, RTsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero1315=0x0 & ac & fct2=0x14 & fct=0x30 { + ac = MAQ_S.W.PHL(RSsrc, RTsrc); +} + +:maq_sa.w.phl ac, RSsrc, RTsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero1315=0x0 & ac & fct2=0x10 & fct=0x30 { + ac = MAQ_S.W.PHL(RSsrc, RTsrc); +} + + +# MAQ_S[A].W.PHR Purpose: Multiply with Accumulate Single Vector Fractional Halfword Element +:maq_s.w.phr ac, RSsrc, RTsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero1315=0x0 & ac & fct2=0x16 & fct=0x30 { + ac = MAQ_S.W.PHR(RSsrc, RTsrc); +} + +:maq_sa.w.phr ac, RSsrc, RTsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero1315=0x0 & ac & fct2=0x12 & fct=0x30 { + ac = MAQ_S.W.PHR(RSsrc, RTsrc); +} + + +# MFHI Purpose: Move from HI register +:mfhi RD, acfhi is $(AMODE) & prime=0x0 & zero2325=0x0 & acfhi & zero1620=0x0 & RD & fct2=0x0 & fct=0x10 { + RD = acfhi; +} + + +# MFLO Purpose: Move from LO register +:mflo RD, acflo is $(AMODE) & prime=0x0 & zero2325=0x0 & acflo & zero1620=0x0 & RD & fct2=0x0 & fct=0x12 { + RD = acflo; +} + + +# MODSUB Purpose: Modular Subtraction on an Index Value +:modsub RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x12 & fct=0x10 { + decr:1 = RTsrc(0); + lastIdx:2 = RTsrc(1); + equals:1 = (RSsrc == 0); + RD = (zext(equals) * zext(lastIdx)) + (zext(!equals) * (RSsrc - zext(decr))); +} + + +# MSUB Purpose: Multiply Word and Subtract from Accumulator +:msub ac, RS32src, RT32src is $(AMODE) & prime=0x1c & RS32src & RT32src & zero1315=0x0 & ac & aclo & achi & fct2=0x0 & fct=0x4 { + tmp1:$(DREGSIZE) = sext(RS32src); + tmp2:$(DREGSIZE) = sext(RT32src); + prod:$(DREGSIZE) = tmp1 * tmp2; + ac = ac - prod; +} + + +# MSUBU Purpose: Multiply Unsigned Word and Add to Accumulator + +:msubu ac, RS32src, RT32src is $(AMODE) & prime=0x1c & RS32src & RT32src & zero1315=0x0 & ac & fct2=0x0 & fct=0x5 { + tmp1:$(DREGSIZE) = zext(RS32src); + tmp2:$(DREGSIZE) = zext(RT32src); + prod:$(DREGSIZE) = tmp1 * tmp2; + ac = ac - prod; +} + + +# MTHI Purpose: Move to HI register +:mthi RS, achi is $(AMODE) & prime=0x0 & RS & zero1320=0x0 & achi & fct2=0x0 & fct=0x11 { + RS = achi; +} + + +# MTHLIP Purpose: Copy LO to HI and a GPR to LO and Increment Pos by 32 +:mthlip RS, ac is $(AMODE) & prime=0x1f & RS & zero1320=0x0 & ac & aclo & achi & fct2=0x1f & fct=0x38 { + achi = aclo; + aclo = RS; + # increment DSPControl pos field by 32 +} + + +# MTLO Purpose: Move to LO register +:mtlo RS, aclo is $(AMODE) & prime=0x0 & RS & zero1320=0x0 & aclo & fct2=0x0 & fct=0x13 { + RS=aclo; +} + + +# MUL[_S].PH Purpose: Multiply Vector Integer HalfWords to Same Size Products +:mul.ph RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0xc & fct=0x18 { + RD = MUL.PH(RSsrc, RTsrc); +} + +:mul_s.ph RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0xe & fct=0x18 { + RD = MUL.PH(RSsrc, RTsrc); +} + + +# MULEQ_S.W.PHL Purpose: Multiply Vector Fractional Left Halfwords to Expanded Width Products +:muleq_s.w.phl RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x1c & fct=0x10 { + RD = MULEQ_S.W.PHL(RSsrc, RTsrc); +} + + +# MULEQ_S.W.PHR Purpose: Multiply Vector Fractional Right Halfwords to Expanded Width Products +:muleq_s.w.phr RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x1d & fct=0x10 { + RD = MULEQ_S.W.PHR(RSsrc, RTsrc); +} + + +# MULEU_S.PH.QBL Purpose: Multiply Unsigned Vector Left Bytes by Halfwords to Halfword Products +:muleu_s.ph.qbl RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x6 & fct=0x10 { + RD = MULEU_S.PH.QBL(RSsrc, RTsrc); +} + + +# MULEU_S.PH.QBR Purpose: Multiply Unsigned Vector Right Bytes with halfwords to Half Word Products +:muleu_s.ph.qbr RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x7 & fct=0x10 { + RD = MULEU_S.PH.QBR(RSsrc, RTsrc); +} + + +# MULQ_RS.PH Purpose: Multiply Vector Fractional Halfwords to Fractional Halfword Products +:mulq_rs.ph RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x1f & fct=0x10 { + RD = MULQ_RS.PH(RSsrc, RTsrc); +} + + +# MULQ_RS.W Purpose: Multiply Fractional Words to Same Size Product with Saturation and Rounding +:mulq_rs.w RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x17 & fct=0x18 { + RD = MULQ_RS.W(RSsrc, RTsrc); +} + + +# MULQ_S.PH Purpose: Multiply Vector Fractional Half-Words to Same Size Products +:mulq_s.ph RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x1e & fct=0x10 { + RD = MULQ_S.PH(RSsrc, RTsrc); +} + + +# MULQ_S.W Purpose: Multiply Fractional Words to Same Size Product with Saturation +:mulq_s.w RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x16 & fct=0x18 { + RD = MULQ_S.W(RSsrc, RTsrc); +} + + +# MULSA.W.PH Purpose: Multiply and Subtract Vector Integer Halfword Elements and Accumulate +:mulsa.w.ph ac, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero1315=0x0 & ac & fct2=0x2 & fct=0x30 { + ac = MULSA.W.PH(RSsrc, RTsrc); +} + + +# MULSAQ_S.W.PH Purpose: Multiply And Subtract Vector Fractional Halfwords And Accumulate +:mulsaq_s.w.ph ac, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & zero1315=0x0 & ac & fct2=0x6 & fct=0x30 { + ac = MULSAQ_S.W.PH(RSsrc, RTsrc); +} + + +# MULT Purpose: Multiply Word +:mult ac, RS32src, RT32src is $(AMODE) & prime=0x0 & RS32src & RT32src & zero1315=0x0 & ac & fct2=0x0 & fct=0x18 { + tmp1:$(DREGSIZE) = sext( RS32src ); + tmp2:$(DREGSIZE) = sext( RT32src ); + ac = tmp1 * tmp2; +} + + +# MULTU Purpose: Multiply Unsigned Word +:multu ac, RS32src, RT32src is $(AMODE) & prime=0x0 & RS32src & RT32src & zero1315=0x0 & ac & fct2=0x0 & fct=0x19 { + tmp1:$(DREGSIZE) = zext( RS32src ); + tmp2:$(DREGSIZE) = zext( RT32src ); + ac = tmp1 * tmp2; +} + + +# PACKRL.PH Purpose: Pack a Vector of Halfwords from Vector Halfword Sources +:packrl.ph RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0xe & fct=0x11 { + src1:2 = RSsrc(0); + src2:2 = RTsrc(2); + RD = zext(src1 << 16) + zext(src2); +} + + +# PICK.PH Purpose: Pick a Vector of Halfword Values Based on Condition Code Bits +:pick.ph RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0xb & fct=0x11 { + cc24:1 = DSPControl[24,1]; + cc25:1 = DSPControl[25,1]; + + val1:2 = RSsrc(0); + val2:2 = RTsrc(0); + tmp1:2 = (zext(cc24 == 1) * val1) + ((zext(cc24==0)) * val2); + + val1 = RSsrc(2); + val2 = RTsrc(2); + tmp2:2 = (zext(cc25 == 1) * val1) + ((zext(cc25==0)) * val2); + + RD = zext(tmp1) + zext(tmp2 << 16); +} + + +# PICK.QB Purpose: Pick a Vector of Byte Values Based on Condition Code Bits +:pick.qb RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x3 & fct=0x11 { + local cc1:1 = DSPControl[24,1]; + local cc2:1 = DSPControl[25,1]; + local cc3:1 = DSPControl[26,1]; + local cc4:1 = DSPControl[27,1]; + + local val1:1 = RSsrc(0); + local val2:1 = RTsrc(0); + local tmp1:1 = ((cc1 == 1) * val1) + (((cc1==0)) * val2); + + val1 = RSsrc(1); + val2 = RTsrc(1); + local tmp2:1 = ((cc2 == 1) * val1) + (((cc2==0)) * val2); + + val1 = RSsrc(2); + val2 = RTsrc(2); + local tmp3:1 = ((cc3 == 1) * val1) + (((cc3==0)) * val2); + + val1 = RSsrc(3); + val2 = RTsrc(3); + local tmp4:1 = ((cc4 == 1) * val1) + (((cc4==0)) * val2); + + RD = zext(tmp1) + zext(tmp2 << 8) + zext(tmp3 << 16) + zext(tmp4 << 24); +} + + +# PRECEQ.W.PHL Purpose: Precision Expand Fractional Halfword to Fractional Word Value +:preceq.w.phl RD, RTsrc is $(AMODE) & prime=0x1f & zero21=0x0 & RTsrc & RD & fct2=0xc & fct=0x12 { + RD = PRECEQ.W.PHL(RTsrc); +} + + +# PRECEQ.W.PHR Purpose: Precision Expand Fractional Halfword to Fractional Word Value +:preceq.w.phr RD, RTsrc is $(AMODE) & prime=0x1f & zero21=0x0 & RTsrc & RD & fct2=0xd & fct=0x12 { + RD = PRECEQ.W.PHR(RTsrc); +} + + +# PRECEQU.PH.QBL Purpose: Precision Expand two Unsigned Bytes to Fractional Halfword Values +:precequ.ph.qbl RD, RTsrc is $(AMODE) & prime=0x1f & zero21=0x0 & RTsrc & RD & fct2=0x4 & fct=0x12 { + RD = PRECEQU.PH.QBL(RTsrc); +} + + +# PRECEQU.PH.QBLA Purpose: Precision Expand two Unsigned Bytes to Fractional Halfword Values +:precequ.ph.qbla RD, RTsrc is $(AMODE) & prime=0x1f & zero21=0x0 & RTsrc & RD & fct2=0x6 & fct=0x12 { + RD = PRECEQU.PH.QBLA(RTsrc); +} + + +# PRECEQU.PH.QBR Purpose: Precision Expand two Unsigned Bytes to Fractional Halfword Values +:precequ.ph.qbr RD, RTsrc is $(AMODE) & prime=0x1f & zero21=0x0 & RTsrc & RD & fct2=0x5 & fct=0x12 { + RD = PRECEQU.PH.QBR(RTsrc); +} + + +# PRECEQU.PH.QBRA Purpose: Precision Expand two Unsigned Bytes to Fractional Halfword Values +:precequ.ph.qbra RD, RTsrc is $(AMODE) & prime=0x1f & zero21=0x0 & RTsrc & RD & fct2=0x7 & fct=0x12 { + RD = PRECEQU.PH.QBRA(RTsrc); +} + + +# PRECEU.PH.QBL Purpose: Precision Expand Two Unsigned Bytes to Unsigned Halfword Values +:preceu.ph.qbl RD, RTsrc is $(AMODE) & prime=0x1f & zero21=0x0 & RTsrc & RD & fct2=0x1c & fct=0x12 { + RD = PRECEU.PH.QBL(RTsrc); +} + + +# PRECEU.PH.QBLA Purpose: Precision Expand Two Unsigned Bytes to Unsigned Halfword Values +:preceu.ph.qbla RD, RTsrc is $(AMODE) & prime=0x1f & zero21=0x0 & RTsrc & RD & fct2=0x1e & fct=0x12 { + RD = PRECEU.PH.QBLA(RTsrc); +} + + +# PRECEU.PH.QBR Purpose: Precision Expand two Unsigned Bytes to Unsigned Halfword Values +:preceu.ph.qbr RD, RTsrc is $(AMODE) & prime=0x1f & zero21=0x0 & RTsrc & RD & fct2=0x1d & fct=0x12 { + RD = PRECEU.PH.QBR(RTsrc); +} + + +# PRECEU.PH.QBRA Purpose: Precision Expand Two Unsigned Bytes to Unsigned Halfword Values +:preceu.ph.qbra RD, RTsrc is $(AMODE) & prime=0x1f & zero21=0x0 & RTsrc & RD & fct2=0x1f & fct=0x12 { + RD = PRECEU.PH.QBRA(RTsrc); +} + + +# PRECR.QB.PH Purpose: Precision Reduce Four Integer Halfwords to Four Bytes +:precr.qb.ph RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0xd & fct=0x11 { + RD = PRECR.QB.PH(RSsrc, RTsrc); +} + + +# PRECR_SRA[_R].PH.W Purpose: Precision Reduce Two Integer Words to Halfwords after a Right Shift +:precr_sra.ph.w rt, rs, sa_dsp is $(AMODE) & prime=0x1f & rs & rt & sa_dsp & fct2=0x1e & fct=0x11 { + PRECR_SRA.PH.W(); +} + +:precr_sra_r.ph.w rt, rs, sa_dsp is $(AMODE) & prime=0x1f & rs & rt & sa_dsp & fct2=0x1f & fct=0x11 { + PRECR_SRA.PH.W(); +} + + +# PRECRQ.PH.W Purpose: Precision Reduce Fractional Words to Fractional Halfwords +:precrq.ph.w RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x14 & fct=0x11 { + RD = PRECRQ.PH.W(RSsrc, RTsrc); +} + + +# PRECRQ.QB.PH Purpose: Precision Reduce Four Fractional Halfwords to Four Bytes +:precrq.qb.ph RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0xc & fct=0x11 { + RD = PRECRQ.QB.PH(RSsrc, RTsrc); +} + + +# PRECRQU_S.QB.PH Purpose: Precision Reduce Fractional Halfwords to Unsigned Bytes With Saturation +:precrqu_s.qb.ph RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0xf & fct=0x11 { + RD = PRECRQU_S.QB.PH(RSsrc, RTsrc); +} + + +# PRECRQ_RS.PH.W Purpose: Precision Reduce Fractional Words to Halfwords With Rounding and Saturation +:precrq_rs.ph.w RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x15 & fct=0x11 { + RD = PRECRQ_RS.PH.W(RSsrc, RTsrc); +} + + +# PREPEND Purpose: Right Shift and Prepend Bits to the MSB +:prepend RT, RSsrc, sa_dsp is $(AMODE) & prime=0x1f & RSsrc & RT & sa_dsp & fct2=0x1 & fct=0x31 { + shift_val:1 = sa_dsp; + trunc_val:1 = ($(REGSIZE) * 8) - shift_val; + temp:$(REGSIZE) = (RSsrc << shift_val) + (RT >> trunc_val); + RT = (zext(shift_val == 0) * RT) + (zext(shift_val != 0) * temp); +} + + +# RADDU.W.QB Purpose: Unsigned Reduction Add Vector Quad Bytes +:raddu.w.qb RD, RSsrc is $(AMODE) & prime=0x1f & RSsrc & zero1620=0x0 & RD & fct2=0x14 & fct=0x10 { + RD = RADDU.W.QB(RSsrc); +} + + +# RDDSP Purpose: Read DSPControl Register Fields to a GPR +:rddsp RD, immed1625 is $(AMODE) & prime=0x1f & immed1625 & RD & fct2=0x12 & fct=0x38 { + RD = DSPControl & immed1625:$(REGSIZE); +} + +:rddsp RD is $(AMODE) & prime=0x1f & immed1625=0x1f & RD & fct2=0x12 & fct=0x38 { + RD = DSPControl; +} + + +# REPL.PH Purpose: Replicate Immediate Integer into all Vector Element Positions +:repl.ph RD, immed1625 is $(AMODE) & prime=0x1f & immed1625 & RD & fct2=0xa & fct=0x12 { + val:2 = immed1625; + repl:$(REGSIZE) = sext(val) << 16 | zext(val); + RD = repl; +} + + +# REPL.QB Purpose: Replicate Immediate Integer into all Vector Element Positions +:repl.qb RD, immed1623 is $(AMODE) & prime=0x1f & zero2425=0x0 & immed1623 & RD & fct2=0x2 & fct=0x12 { + byte:1 = immed1623; + RD = sext((byte << 24) | (byte << 16) | (byte << 8) | (byte)); +} + + +# REPLV.PH Purpose: Replicate a Halfword into all Vector Element Positions +:replv.ph RD, RTsrc is $(AMODE) & prime=0x1f & zero21=0x0 & RTsrc & RD & fct2=0xb & fct=0x12 { + RD = REPLV.PH(RTsrc); +} + + +# REPLV.QB Purpose: Replicate Byte into all Vector Element Positions +:replv.qb RD, RTsrc is $(AMODE) & prime=0x1f & zero21=0x0 & RTsrc & RD & fct2=0x3 & fct=0x12 { + RD = REPLV.QB(RTsrc); +} + + +# SHILO Purpose: Shift an Accumulator Value Leaving the Result in the Same Accumulator +:shilo ac, shift20 is $(AMODE) & prime=0x1f & shift20 & zero1619=0x0 & zero1315=0x0 & ac & fct2=0x1a & fct=0x38 { + shift_val:1 = shift20; + ac = (zext(shift_val s>= 0) * (ac >> shift_val)) + (zext(shift_val s< 0) * (ac << (-shift_val))); +} + + +# SHILOV Purpose: Variable Shift of Accumulator Value Leaving the Result in the Same Accumulator +:shilov ac, RSsrc is $(AMODE) & prime=0x1f & RSsrc & zero1620=0x0 & zero1315=0x0 & ac & fct2=0x1b & fct=0x38 { + shift_val:1 = RSsrc(1) & 0x7f; + ac = (zext(shift_val s>= 0) * (ac >> shift_val)) + (zext(shift_val s< 0) * (ac << (-shift_val))); +} + + +# SHLL[_S].PH Purpose: Shift Left Logical Vector Pair Halfwords +:shll.ph RD, RTsrc, sa_dsp2 is $(AMODE) & prime=0x1f & bit25=0x0 & sa_dsp2 & RTsrc & RD & fct2=0x8 & fct=0x13 { + shift_val:1 = sa_dsp2; + RD = SHLL.PH(RTsrc, shift_val); +} + +:shll_s.ph RD, RTsrc, sa_dsp2 is $(AMODE) & prime=0x1f & bit25=0x0 & sa_dsp2 & RTsrc & RD & fct2=0xc & fct=0x13 { + shift_val:1 = sa_dsp2; + RD= SHLL.PH(RTsrc, shift_val); +} + + +# SHLL.QB Purpose: Shift Left Logical Vector Quad Bytes +:shll.qb RD, RTsrc, sa_dsp2 is $(AMODE) & prime=0x1f & sa_dsp2 & RTsrc & RD & fct2=0x0 & fct=0x13 { + shift_val:1 = sa_dsp2; + RD = SHLL.QB(RTsrc, shift_val); +} + + +# SHLLV[_S].PH Purpose: Shift Left Logical Variable Vector Pair Halfwords +:shllv.ph RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0xa & fct=0x13 { + RD = SHLLV.PH(RTsrc, RSsrc); +} + +:shllv_s.ph RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0xe & fct=0x13 { + RD = SHLLV.PH(RTsrc, RSsrc); +} + + +# SHLLV.QB Purpose: Shift Left Logical Variable Vector Quad Bytes +:shllv.qb RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x2 & fct=0x13 { + RD = SHLLV.QB(RTsrc, RSsrc); +} + + +# SHLLV_S.W Purpose: Shift Left Logical Variable Vector Word +:shllv_s.w RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x16 & fct=0x13 { + RD = SHLLV_S.W(RTsrc, RSsrc); +} + + +# SHLL_S.W Purpose: Shift Left Logical Word with Saturation +:shll_s.w RD, RTsrc, sa_dsp2 is $(AMODE) & prime=0x1f & sa_dsp2 & RTsrc & RD & fct2=0x14 & fct=0x13 { + shift_val:1 = sa_dsp2; + RD = SHLL_S.W(RTsrc, shift_val); +} + + +# SHRA[_R].QB Purpose: Shift Right Arithmetic Vector of Four Bytes +:shra.qb RD, RTsrc, sa_dsp2 is $(AMODE) & prime=0x1f & sa_dsp2 & RTsrc & RD & fct2=0x4 & fct=0x13 { + shift_val:1 = sa_dsp2; + RD = SHRA.QB(RTsrc, shift_val); +} + +:shra_r.qb RD, RTsrc, sa_dsp2 is $(AMODE) & prime=0x1f & sa_dsp2 & RTsrc & RD & fct2=0x5 & fct=0x13 { + shift_val:1 = sa_dsp2; + RD = SHRA.QB(RTsrc, shift_val); +} + + +# SHRA[_R].PH Purpose: Shift Right Arithmetic Vector Pair Halfwords +:shra.ph RD, RTsrc, sa_dsp2 is $(AMODE) & prime=0x1f & bit25=0x0 & sa_dsp2 & RTsrc & RD & fct2=0x9 & fct=0x13 { + shift_val:1 = sa_dsp2; + RD = SHRA.PH(RTsrc, shift_val); +} + +:shra_r.ph RD, RTsrc, sa_dsp2 is $(AMODE) & prime=0x1f & bit25=0x0 & sa_dsp2 & RTsrc & RD & fct2=0xd & fct=0x13 { + shift_val:1 = sa_dsp2; + RD = SHRA.PH(RTsrc, shift_val); +} + + +# SHRAV[_R].PH Purpose: Shift Right Arithmetic Variable Vector Pair Halfwords +:shrav.ph RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0xb & fct=0x13 { + RD = SHRAV.PH(RTsrc, RSsrc); +} + +:shrav_r.ph RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0xf & fct=0x13 { + RD = SHRAV.PH(RTsrc, RSsrc); +} + + +# SHRAV[_R].QB Purpose: Shift Right Arithmetic Variable Vector of Four Bytes +:shrav.qb RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x6 & fct=0x13 { + RD = SHRAV.QB(RTsrc, RSsrc); +} + +:shrav_r.qb RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x7 & fct=0x13 { + RD = SHRAV.QB(RTsrc, RSsrc); +} + + +# SHRAV_R.W Purpose: Shift Right Arithmetic Variable Word with Rounding +:shrav_r.w RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x17 & fct=0x13 { + RD = SHRAV_R.W(RTsrc, RSsrc); +} + + +# SHRA_R.W Purpose: Shift Right Arithmetic Word with Rounding +:shra_r.w RD, RTsrc, sa_dsp2 is $(AMODE) & prime=0x1f & sa_dsp2 & RTsrc & RD & fct2=0x15 & fct=0x13 { + shift_val:1 = sa_dsp2; + RD = SHRA_R.W(RTsrc, shift_val); +} + + +# SHRL.PH Purpose: Shift Right Logical Two Halfwords +:shrl.ph RD, RTsrc, sa_dsp2 is $(AMODE) & prime=0x1f & bit25=0x0 & sa_dsp2 & RTsrc & RD & fct2=0x19 & fct=0x13 { + shift_val:1 = sa_dsp2; + RD = SHRL.PH(RTsrc, shift_val); +} + + +# SHRL.QB Purpose: Shift Right Logical Vector Quad Bytes +:shrl.qb RD, RTsrc, sa_dsp2 is $(AMODE) & prime=0x1f & sa_dsp2 & RTsrc & RD & fct2=0x1 & fct=0x13 { + shift_val:1 = sa_dsp2; + RD = SHRL.QB(RTsrc, shift_val); +} + + +# SHRLV.PH Purpose: Shift Variable Right Logical Pair of Halfwords +:shrlv.ph RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x1b & fct=0x13 { + RD = SHRLV.PH(RTsrc, RSsrc); +} + + +# SHRLV.QB Purpose: Shift Right Logical Variable Vector Quad Bytes +:shrlv.qb RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x3 & fct=0x13 { + RD = SHRLV.QB(RTsrc, RSsrc); +} + + +# SUBQ[_S].PH Purpose: Subtract Fractional Halfword Vector +:subq.ph RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0xb & fct=0x10 { + RD = SUBQ.PH(RSsrc, RTsrc); +} + +:subq_s.ph RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0xf & fct=0x10 { + RD = SUBQ.PH(RSsrc, RTsrc); +} + + +# SUBQ_S.W Purpose: Subtract Fractional Word +:subq_s.w RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x17 & fct=0x10 { + RD = SUBQ_S.W(RSsrc, RTsrc); +} + + +# SUBQH[_R].PH Purpose: Subtract Fractional Halfword Vectors And Shift Right to Halve Results +:subqh.ph RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x9 & fct=0x18 { + RD = SUBQH.PH(RSsrc, RTsrc); +} + +:subqh_r.ph RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0xb & fct=0x18 { + RD = SUBQH.PH(RSsrc, RTsrc); +} + + +# SUBQH[_R].W Purpose: Subtract Fractional Words And Shift Right to Halve Results +:subqh.w RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x11 & fct=0x18 { + RD = SUBQH.W(RSsrc, RTsrc); +} + +:subqh_r.w RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x13 & fct=0x18 { + RD = SUBQH.W(RSsrc, RTsrc); +} + + +# SUBU[_S].PH Purpose: Subtract Unsigned Integer Halfwords +:subu.ph RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x9 & fct=0x10 { + RD = SUBU.PH(RSsrc, RTsrc); +} + +:subu_s.ph RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0xd & fct=0x10 { + RD = SUBU.PH(RSsrc, RTsrc); +} + + +# SUBU[_S].QB Purpose: Subtract Unsigned Quad Byte Vector +:subu.qb RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x1 & fct=0x10 { + RD = SUBU.QB(RSsrc, RTsrc); +} + +:subu_s.qb RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x5 & fct=0x10 { + RD = SUBU.QB(RSsrc, RTsrc); +} + + +# SUBUH[_R].QB Purpose: Subtract Unsigned Bytes And Right Shift to Halve Results +:subuh.qb RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x1 & fct=0x18 { + RD = SUBUH.QB(RSsrc, RTsrc); +} + +:subuh_r.qb RD, RTsrc, RSsrc is $(AMODE) & prime=0x1f & RSsrc & RTsrc & RD & fct2=0x3 & fct=0x18 { + RD = SUBUH.QB(RSsrc, RTsrc); +} + + +# WRDSP Purpose: Write Fields to DSPControl Register from a GPR +:wrdsp RSsrc, mask is $(AMODE) & prime=0x1f & RSsrc & mask & fct2=0x13 & fct=0x38 { + DSPControl = (RSsrc & mask); +} + +:wrdsp RSsrc is $(AMODE) & prime=0x1f & RSsrc & mask=0x1f & fct2=0x13 & fct=0x38 { + DSPControl = RSsrc; +} diff --git a/Ghidra/Processors/MIPS/data/languages/mips_mt.sinc b/Ghidra/Processors/MIPS/data/languages/mips_mt.sinc new file mode 100644 index 0000000000..b1d4c144b4 --- /dev/null +++ b/Ghidra/Processors/MIPS/data/languages/mips_mt.sinc @@ -0,0 +1,152 @@ +define pcodeop fork; +define pcodeop move_from_thread_context; +define pcodeop move_from_thread_cp0; +define pcodeop move_from_thread_gpr; +define pcodeop move_from_thread_dsp; +define pcodeop move_from_thread_fpr; +define pcodeop move_from_thread_fpcr; +define pcodeop move_from_thread_cop2_data; +define pcodeop move_from_thread_cop2_control; +define pcodeop move_to_thread_context; +define pcodeop move_to_thread_cp0; +define pcodeop move_to_thread_gpr; +define pcodeop move_to_thread_dsp; +define pcodeop move_to_thread_fpr; +define pcodeop move_to_thread_fpcr; +define pcodeop move_to_thread_cop2_data; +define pcodeop move_to_thread_cop2_control; +define pcodeop yield; + +# Disable multi-threaded execution. Returns VPEControl +:dmt RT is $(AMODE) & REL6=0 & prime=0x10 & mfmc0=0xB & rd32=0x1 & zero5=0xF & fct=0x1 & RT { + # Clear VPEControl IE bit (bit 15) + RT = VPEControl; VPEControl = VPEControl & ~0x8000; #VPEControl[15,1] = 0; +} + +# Disable Virtual Processor Execution. Returns VPEControl +:dvpe RT is $(AMODE) & REL6=0 & prime=0x10 & mfmc0=0xB & rd32=0x0 & zero5=0x0 & fct=0x1 & RT { + # Clear MVPControl EVP bit (bit 0) + RT = MVPControl; MVPControl = MVPControl & ~0x1; +} + +# Enable multi-threaded execution. Returns VPEControl +:emt RT is $(AMODE) & REL6=0 & prime=0x10 & mfmc0=0xB & rd32=0x1 & zero5=0xF & fct=0x21 & RT { + # Set VPEControl TE bit (bit 15) + RT = VPEControl; VPEControl = VPEControl | 0x8000; # VPEControl[15,1] = 1; +} + +# Enable Virtual Processor Execution. Returns VPEControl +:evpe RT is $(AMODE) & REL6=0 & prime=0x10 & mfmc0=0xB & rd32=0x0 & zero5=0x0 & fct=0x21 & RT { +# Set MVPControl EVP bit (bit 0)h + RT = MVPControl; + MVPControl = MVPControl | 0x1; +} + +:fork "Thread_GPR["^RDsrc^"]", RSsrc, RTsrc is $(AMODE) & REL6=0 & prime=0x1F & zero5=0x0 & fct=0x8 & RDsrc & RSsrc & RTsrc { + fork(RDsrc, RSsrc, RTsrc); +} + +# Move From Thread Context +# MFTR general instruction +:mftr RD, RTsrc, bit5, sel, h is $(AMODE) & REL6=0 & prime=0x10 & mfmc0=0x8 & bit5 & h & bit3=0 & sel & RD & RTsrc { + tmp:$(REGSIZE) = move_from_thread_context(RTsrc, bit5:1, sel:1, h:1); + RD = tmp; +} + +# MFTR instructions have many idioms for sub-decodings +# Move from coprocessor 0 register rt, sel=sel +:mftc0 RD, "Thread_Co0["^RT0thread^"]", sel is $(AMODE) & REL6=0 & prime=0x10 & mfmc0=0x8 & bit5=0 & bit3=0 & RD & RT0thread & sel { + RD = move_from_thread_cp0(RT0thread:1, sel:1); +} + +:mftc0 RD, "Thread_Co0["^RT0thread^"]" is $(AMODE) & REL6=0 & prime=0x10 & mfmc0=0x8 & bit5=0 & bit3=0 & RD & RT0thread & sel=0 { + RD = move_from_thread_cp0(RT0thread:1, 0:1); +} + +# Move from GPR[rt] +:mftgpr RD, "Thread_GPR["^RTthread^"]" is $(AMODE) & REL6=0 & prime=0x10 & mfmc0=0x8 & bit5=1 & bit3=0 & sel=0x0 & RD & RTthread { + RD = move_from_thread_gpr(RTthread); +} + +RtDSP: "lo" is lohiacx=0 { } +RtDSP: "hi" is lohiacx=1 { } +RtDSP: "acx" is lohiacx=2 { } +RtDSP: "dsp" is rtmtdsp=16 { } + + +:mft^RtDSP RD, rtmtdsp is $(AMODE) & REL6=0 & prime=0x10 & mfmc0=0x8 & bit5=1 & bit3=0 & sel=0x1 & RD & RtDSP & rtmtdsp { + RD = move_from_thread_dsp(rtmtdsp); +} + +# Move from FPR[rt] +:mftc1 RD, "Thread_FPR["^FTthread^"]" is $(AMODE) & REL6=0 & prime=0x10 & mfmc0=0x8 & bit5=1 & h=0 & bit3=0 & sel=0x2 & RD & FTthread { + RD = move_from_thread_fpr(FTthread, 0:1); +} + +:mfthc1 RD, "Thread_FPR["^FTthread^"]" is $(AMODE) & REL6=0 & prime=0x10 & mfmc0=0x8 & bit5=1 & h=1 & bit3=0 & sel=0x2 & RD & FTthread { + RD = move_from_thread_fpr(FTthread, 1:1); +} + +# Move from FPCR[rt] +:cftc1 RD, "Thread_FPCR["^FCTthread^"]" is $(AMODE) & REL6=0 & prime=0x10 & mfmc0=0x8 & bit5=1 & bit3=0 & sel=0x3 & RD & FCTthread { + RD = move_from_thread_fpcr(FCTthread); +} + +# Skipping for now: MFTR for C0P2 Data and C0P2 Control (bit5=1, sel=4/5) + +# Move to Thread Context +# MTTR general instruction +:mttr RDsrc, RTsrc, bit5, sel, h is $(AMODE) & REL6=0 & prime=0x10 & mfmc0=0xc & bit5 & h & bit3=0 & sel & RDsrc & RTsrc { + move_to_thread_context(RDsrc, RTsrc, bit5:1, sel:1, h:1); +} + +# MTTR instructions have many idioms for sub-decodings +# Move rt to coprocessor 0 register rd, sel=sel +:mttc0 RTsrc, "Thread_Co0["^RD0thread^"]", sel is $(AMODE) & REL6=0 & prime=0x10 & mfmc0=0xc & bit5=0 & bit3=0 & RTsrc & RD0thread & sel { + move_to_thread_cp0(RD0thread:1, RTsrc, sel:1); +} + +:mttc0 RTsrc, "Thread_Co0["^RD0thread^"]" is $(AMODE) & REL6=0 & prime=0x10 & mfmc0=0xc & bit5=0 & bit3=0 & RTsrc & RD0thread & sel=0 { + move_to_thread_cp0(RD0thread:1, RTsrc, 0:1); +} + +# Move to GPR[rd] +:mttgpr RTsrc, "Thread_GPR["^RDthread^"]" is $(AMODE) & REL6=0 & prime=0x10 & mfmc0=0xc & bit5=1 & bit3=0 & sel=0x0 & RTsrc & RDthread { + move_to_thread_gpr(RDthread, RTsrc); +} + +RdDSP: "lo" is lohiacx2=0 { } +RdDSP: "hi" is lohiacx2=1 { } +RdDSP: "acx" is lohiacx2=2 { } +RdDSP: "dsp" is rdmtdsp=16 { } + +# Move to DSP[rd] +:mtt^RdDSP RTsrc, rdmtdsp is $(AMODE) & REL6=0 & prime=0x10 & mfmc0=0xc & bit5=1 & bit3=0 & sel=0x1 & RTsrc & RdDSP & rdmtdsp { + move_to_thread_dsp(rdmtdsp, RTsrc); +} + +# Move to FPR[rd] +:mttc1 RTsrc, "Thread_FPR["^FDthread^"]" is $(AMODE) & REL6=0 & prime=0x10 & mfmc0=0xC & bit5=1 & h=0 & bit3=0 & sel=0x2 & RTsrc & FDthread { + move_to_thread_fpr(FDthread, RTsrc, 0:1); +} + +:mtthc1 RTsrc, "Thread_FPR["^FDthread^"]" is $(AMODE) & REL6=0 & prime=0x10 & mfmc0=0xC & bit5=1 & h=1 & bit3=0 & sel=0x2 & RTsrc & FDthread { + move_to_thread_fpr(FDthread, RTsrc, 1:1); +} + +# Move to FPCR[rd] +:cttc1 RTsrc, "Thread_FPCR["^FCRthread^"]" is $(AMODE) & REL6=0 & prime=0x10 & mfmc0=0xC & bit5=1 & bit3=0 & sel=0x3 & RTsrc & FCRthread { + move_to_thread_fpcr(FCRthread, RTsrc); +} + +# Skipping for now: MTTR for C0P2 Data and C0P2 control (bit5=1, sel=4/5) + +# Conditionally Deschedule or Deallocate the Current Thread +:yield RD, RSsrc is $(AMODE) & REL6=0 & prime=0x1F & op=0 & zero5=0x0 & fct=0x9 & RD & RSsrc { + yield(RSsrc); + RD = RSsrc & YQMask; +} + +:yield RSsrc is $(AMODE) & REL6=0 & prime=0x1F & op=0 & zero5=0x0 & fct=0x9 & rd=0 & RSsrc { + yield(RSsrc); +}