diff --git a/.gitignore b/.gitignore index c403c34..807922d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target .idea/ +.DS_Store diff --git a/codegen/.gitignore b/codegen/.gitignore new file mode 100644 index 0000000..f4e465b --- /dev/null +++ b/codegen/.gitignore @@ -0,0 +1,2 @@ +masks.txt +__pycache__ diff --git a/codegen/gen_masks.py b/codegen/gen_masks.py new file mode 100644 index 0000000..eefb857 --- /dev/null +++ b/codegen/gen_masks.py @@ -0,0 +1,38 @@ +import sys + + +def apply_pattern(pattern, mask, bits): + start, stop, value = map(int, pattern.split(",")) + bit_count = stop - start + 1 + shift = 31 - stop + mask |= ((1 << bit_count) - 1) << shift + bits |= value << shift + return mask, bits + + +def dump_mask(line): + parts = line.split(" ") + opcode = parts[0] + patterns = parts[1:] + assert len(patterns) > 0 + mask, bits = 0, 0 + for pattern in patterns: + mask, bits = apply_pattern(pattern, mask, bits) + print(f' "{opcode}" & {hex(mask)} == {hex(bits)};') + + +def main(): + with open("patterns.txt", "r") as patterns, open( + "../lib/src/isa.rs", "w" + ) as isa_file: + sys.stdout = isa_file + print("use ppc750cl_macros::isa;") + print() + print("isa! {") + for line in patterns.readlines(): + dump_mask(line) + print("}") + + +if __name__ == "__main__": + main() diff --git a/codegen/patterns.txt b/codegen/patterns.txt new file mode 100644 index 0000000..07b5e3e --- /dev/null +++ b/codegen/patterns.txt @@ -0,0 +1,222 @@ +add 0,5,31 21,30,266 +addc 0,5,31 21,30,21 +adde 0,5,31 21,30,138 +addi 0,5,14 +addic 0,5,12 +addic. 0,5,13 +addis 0,5,15 +addme 0,5,31 16,20,0 22,30,234 +addze 0,5,31 16,20,0 22,30,202 +and 0,5,31 21,30,28 +andc 0,5,31 21,30,60 +andi. 0,5,28 +andis. 0,5,29 +b 0,5,18 +bc 0,5,16 +bcctr 0,5,19 16,20,0 21,31,528 +bclr 0,5,19 16,20,0 21,30,16 +cmp 0,5,31 9,9,0 21,31,0 +cmpi 0,5,11 9,9,0 +cmpl 0,5,31 9,9,0 21,30,32 31,31,0 +cmpli 0,5,10 9,9,0 +cntlzw 0,5,31 16,20,0 21,30,26 +crand 0,5,19 21,30,257 31,31,0 +crandc 0,5,19 21,30,129 31,31,0 +creqv 0,5,19 21,30,289 31,31,0 +crnand 0,5,19 21,30,225 31,31,0 +crnor 0,5,19 21,30,33 31,31,0 +cror 0,5,19 21,30,449 31,31,0 +crorc 0,5,19 21,30,417 31,31,0 +crxor 0,5,19 21,30,193 31,31,0 +dcbf 0,5,31 6,10,0 21,30,86 31,31,0 +dcbi 0,5,31 6,10,0 21,30,470 31,31,0 +dcbst 0,5,31 6,10,0 21,30,54 31,31,0 +dcbt 0,5,31 6,10,0 21,30,278 31,31,0 +dcbtst 0,5,31 6,10,0 21,30,246 31,31,0 +dcbz 0,5,31 6,10,0 21,30,1014 31,31,0 +dcbz_l 0,5,4 6,10,0 21,30,1014 31,31,0 +divw 0,5,31 22,30,491 +divwu 0,5,31 22,30,459 +eciwx 0,5,31 22,30,310 31,31,0 +ecowx 0,5,31 22,30,438 31,31,0 +eieio 0,5,31 6,20,0 21,30,854 31,31,0 +eqv 0,5,31 22,30,284 +extsb 0,5,31 16,20,0 21,30,954 +extsh 0,5,31 16,20,0 21,30,922 +fabs 0,5,63 11,15,0 21,30,922 +fadd 0,5,63 21,25,0 26,30,21 +fadds 0,5,59 21,25,0 26,30,21 +fcmpo 0,5,63 9,10,0 21,30,32 31,31,0 +fcmpu 0,5,63 9,10,0 21,30,0 31,31,0 +fctiw 0,5,63 11,15,0 21,30,14 +fctiwz 0,5,63 11,15,0 21,30,15 +fdiv 0,5,63 21,25,0 26,30,18 +fdivs 0,5,59 21,25,0 26,30,18 +fmadd 0,5,63 26,30,29 +fmadds 0,5,59 26,30,29 +fmr 0,5,63 11,15,0 21,30,72 +fmsub 0,5,63 26,30,28 +fmsubs 0,5,59 26,30,28 +fmul 0,5,63 16,20,0 26,30,25 +fmuls 0,5,59 16,20,0 26,30,25 +fnabs 0,5,63 11,15,0 21,30,136 +fneg 0,5,63 11,15,0 21,30,40 +fnmadd 0,5,63 26,30,31 +fnmadds 0,5,59 26,30,31 +fnmsub 0,5,63 26,30,30 +fnmsubs 0,5,59 26,30,30 +fres 0,5,59 11,15,0 21,25,0 26,30,24 +frsp 0,5,63 11,15,0 21,30,12 +frsqrte 0,5,63 11,15,0 21,25,0 26,30,26 +fsel 0,5,63 26,30,23 +fsub 0,5,63 21,25,0 26,30,20 +fsubs 0,5,59 21,25,0 26,30,20 +icbi 0,5,31 6,10,0 21,30,982 31,31,0 +isync 0,5,19 6,20,0 21,30,150 31,31,0 +lbz 0,5,34 +lbzu 0,5,35 +lbzux 0,5,31 21,30,119 31,31,0 +lbzx 0,5,31 21,30,87 31,31,0 +lfd 0,5,50 +lfdu 0,5,51 +lfdux 0,5,31 21,30,631 31,31,0 +lfdx 0,5,31 21,30,559 31,31,0 +lfs 0,5,48 +lfsu 0,5,49 +lfsux 0,5,31 21,30,567 31,31,0 +lfsx 0,5,31 21,30,535 31,31,0 +lha 0,5,42 +lhau 0,5,43 +lhaux 0,5,31 21,30,375 31,31,0 +lhax 0,5,31 21,30,343 31,31,0 +lhbrx 0,5,31 21,30,790 31,31,0 +lhz 0,5,40 +lhzu 0,5,41 +lhzux 0,5,31 21,30,311 31,31,0 +lhzx 0,5,31 21,30,279 31,31,0 +lmw 0,5,46 +lswi 0,5,31 21,30,597 31,31,0 +lswx 0,5,31 21,30,533 31,31,0 +lwarx 0,5,31 21,30,20 31,31,0 +lwbrx 0,5,31 21,30,534 31,31,0 +lwz 0,5,32 +lwzu 0,5,33 +lwzux 0,5,31 21,30,55 31,31,0 +lwzx 0,5,31 21,30,23 31,31,0 +mcrf 0,5,19 10,11,0 20,31,0 +mcrfs 0,5,63 10,11,0 16,24,0 25,30,64 31,31,0 +mcrxr 0,5,31 10,11,0 16,24,0 25,30,512 31,31,0 +mfcr 0,5,31 11,20,0 21,30,19 31,31,0 +mffs 0,5,31 11,20,0 21,30,583 +mfmsr 0,5,31 11,20,0 21,30,83 31,31,0 +mfspr 0,5,31 21,30,339 31,31,0 +mfsr 0,5,31 11,11,0 16,20,0 21,30,595 31,31,0 +mfsrin 0,5,31 11,15,0 21,30,659 31,31,0 +mftb 0,5,31 21,30,371 31,31,0 +mtcrf 0,5,31 11,11,0 20,20,0 21,30,144 31,31,0 +mtfsb0 0,5,63 11,20,0 21,30,70 +mtfsb1 0,5,63 11,20,0 21,30,38 +mtfsf 0,5,63 6,6,0 15,15,0 21,30,711 +mtfsfi 0,5,63 9,15,0 20,20,0 21,30,134 +mtmsr 0,5,31 11,20,0 21,30,146 31,31,0 +mtspr 0,5,31 21,30,467 31,31,0 +mtsr 0,5,31 11,11,0 16,20,0 21,30,210 31,31,0 +mtsrin 0,5,31 11,15,0 21,30,242 31,31,0 +mulhw 0,5,31 21,21,0 22,30,75 +mulhwu 0,5,31 21,21,0 22,30,11 +mulli 0,5,7 +mullw 0,5,31 22,30,235 +nand 0,5,31 21,30,476 +neg 0,5,31 16,20,0 21,30,104 +nor 0,5,31 21,30,124 +or 0,5,31 21,30,444 +orc 0,5,31 21,30,412 +ori 0,5,24 +oris 0,5,25 +psq_l 0,5,56 +psq_lu 0,5,57 +psq_lux 0,5,4 25,30,38 31,31,0 +psq_lx 0,5,4 25,30,6 31,31,0 +psq_st 0,5,60 +psq_stu 0,5,61 +psq_stux 0,5,4 25,30,39 31,31,0 +psq_stx 0,5,4 25,30,7 31,31,0 +ps_abs 0,5,4 11,15,0 21,30,264 +ps_add 0,5,4 21,25,0 26,30,21 +ps_cmpo0 0,5,4 9,10,0 21,30,32 31,31,0 +ps_cmpo1 0,5,4 9,10,0 21,30,96 31,31,0 +ps_cmpu0 0,5,4 9,10,0 21,30,0 31,31,0 +ps_cmpu1 0,5,4 9,10,0 21,30,64 31,31,0 +ps_div 0,5,4 21,25,0 26,30,18 +ps_madd 0,5,4 26,30,29 +ps_madds0 0,5,4 26,30,14 +ps_madds1 0,5,4 26,30,15 +ps_merge00 0,5,4 21,30,528 +ps_merge01 0,5,4 21,30,560 +ps_merge10 0,5,4 21,30,592 +ps_merge11 0,5,4 21,30,624 +ps_mr 0,5,4 11,15,0 21,30,72 +ps_msub 0,5,4 26,30,28 +ps_mul 0,5,4 16,20,0 26,30,25 +ps_muls0 0,5,4 16,20,0 26,30,12 +ps_muls1 0,5,4 16,20,0 26,30,13 +ps_nabs 0,5,4 11,15,0 21,30,136 +ps_neg 0,5,4 11,15,0 21,30,40 +ps_nmadd 0,5,4 26,30,31 +ps_nmsub 0,5,4 26,30,30 +ps_res 0,5,4 11,15,0 21,25,0 26,30,24 +ps_rsqrte 0,5,4 11,15,0 21,25,0 26,30,26 +ps_sel 0,5,4 26,30,23 +ps_sub 0,5,4 21,25,0 26,30,20 +ps_sum0 0,5,4 26,30,10 +ps_sum1 0,5,4 26,30,11 +rfi 0,5,19 6,20,0 31,31,0 +rlwimi 0,5,20 +rlwinm 0,5,21 +rlwnm 0,5,23 +sc 0,5,17 6,29,0 30,30,1 31,31,0 +slw 0,5,31 21,30,24 +sraw 0,5,31 21,30,792 +srawi 0,5,31 21,30,824 +srw 0,5,31 21,30,536 +stb 0,5,38 +stbu 0,5,39 +stbux 0,5,31 22,30,247 31,31,0 +stbx 0,5,31 22,30,215 31,31,0 +stfd 0,5,54 +stfdu 0,5,55 +stfdux 0,5,31 21,30,759 31,31,0 +stfdx 0,5,31 21,30,727 31,31,0 +stfiwx 0,5,31 21,30,983 31,31,0 +stfs 0,5,52 +stfsu 0,5,53 +stfsux 0,5,31 21,30,695 31,31,0 +stfsx 0,5,31 21,30,663 31,31,0 +sth 0,5,44 +sthbrx 0,5,31 21,30,918 31,31,0 +sthu 0,5,45 +sthux 0,5,31 21,30,439 31,31,0 +sthx 0,5,31 21,30,407 31,31,0 +stmw 0,5,47 +stswi 0,5,31 21,30,725 31,31,0 +stswx 0,5,31 21,30,661 31,31,0 +stw 0,5,36 +stwbrx 0,5,31 21,30,662 31,31,0 +stwcx. 0,5,31 21,30,150 31,31,1 +stwu 0,5,37 +stwux 0,5,31 21,30,183 31,31,0 +stwx 0,5,31 21,30,151 31,31,0 +subf 0,5,31 22,30,40 +subfc 0,5,31 22,30,8 +subfe 0,5,31 22,30,136 +subfic 0,5,8 +subfme 0,5,31 16,20,0 22,30,232 +subfze 0,5,31 16,20,0 22,30,200 +sync 0,5,31 6,20,0 21,30,598 31,31,0 +tlbie 0,5,31 6,15,0 21,30,306 31,31,0 +tlbsync 0,5,31 6,20,0 21,30,566 31,31,0 +tw 0,5,31 21,30,4 31,31,0 +twi 0,5,3 +xor 0,5,31 21,30,316 +xori 0,5,26 +xoris 0,5,27 diff --git a/lib/src/isa.rs b/lib/src/isa.rs new file mode 100644 index 0000000..ea6a61d --- /dev/null +++ b/lib/src/isa.rs @@ -0,0 +1,226 @@ +use ppc750cl_macros::isa; + +isa! { + "add" & 0xfc0007fe == 0x7c000214; + "addc" & 0xfc0007fe == 0x7c00002a; + "adde" & 0xfc0007fe == 0x7c000114; + "addi" & 0xfc000000 == 0x38000000; + "addic" & 0xfc000000 == 0x30000000; + "addic." & 0xfc000000 == 0x34000000; + "addis" & 0xfc000000 == 0x3c000000; + "addme" & 0xfc00fbfe == 0x7c0001d4; + "addze" & 0xfc00fbfe == 0x7c000194; + "and" & 0xfc0007fe == 0x7c000038; + "andc" & 0xfc0007fe == 0x7c000078; + "andi." & 0xfc000000 == 0x70000000; + "andis." & 0xfc000000 == 0x74000000; + "b" & 0xfc000000 == 0x48000000; + "bc" & 0xfc000000 == 0x40000000; + "bcctr" & 0xfc00ffff == 0x4c000210; + "bclr" & 0xfc00fffe == 0x4c000020; + "cmp" & 0xfc4007ff == 0x7c000000; + "cmpi" & 0xfc400000 == 0x2c000000; + "cmpl" & 0xfc4007ff == 0x7c000040; + "cmpli" & 0xfc400000 == 0x28000000; + "cntlzw" & 0xfc00fffe == 0x7c000034; + "crand" & 0xfc0007ff == 0x4c000202; + "crandc" & 0xfc0007ff == 0x4c000102; + "creqv" & 0xfc0007ff == 0x4c000242; + "crnand" & 0xfc0007ff == 0x4c0001c2; + "crnor" & 0xfc0007ff == 0x4c000042; + "cror" & 0xfc0007ff == 0x4c000382; + "crorc" & 0xfc0007ff == 0x4c000342; + "crxor" & 0xfc0007ff == 0x4c000182; + "dcbf" & 0xffe007ff == 0x7c0000ac; + "dcbi" & 0xffe007ff == 0x7c0003ac; + "dcbst" & 0xffe007ff == 0x7c00006c; + "dcbt" & 0xffe007ff == 0x7c00022c; + "dcbtst" & 0xffe007ff == 0x7c0001ec; + "dcbz" & 0xffe007ff == 0x7c0007ec; + "dcbz_l" & 0xffe007ff == 0x100007ec; + "divw" & 0xfc0003fe == 0x7c0003d6; + "divwu" & 0xfc0003fe == 0x7c000396; + "eciwx" & 0xfc0003ff == 0x7c00026c; + "ecowx" & 0xfc0003ff == 0x7c00036c; + "eieio" & 0xffffffff == 0x7c0006ac; + "eqv" & 0xfc0003fe == 0x7c000238; + "extsb" & 0xfc00fffe == 0x7c000774; + "extsh" & 0xfc00fffe == 0x7c000734; + "fabs" & 0xfc1f07fe == 0xfc000734; + "fadd" & 0xfc0007fe == 0xfc00002a; + "fadds" & 0xfc0007fe == 0xec00002a; + "fcmpo" & 0xfc6007ff == 0xfc000040; + "fcmpu" & 0xfc6007ff == 0xfc000000; + "fctiw" & 0xfc1f07fe == 0xfc00001c; + "fctiwz" & 0xfc1f07fe == 0xfc00001e; + "fdiv" & 0xfc0007fe == 0xfc000024; + "fdivs" & 0xfc0007fe == 0xec000024; + "fmadd" & 0xfc00003e == 0xfc00003a; + "fmadds" & 0xfc00003e == 0xec00003a; + "fmr" & 0xfc1f07fe == 0xfc000090; + "fmsub" & 0xfc00003e == 0xfc000038; + "fmsubs" & 0xfc00003e == 0xec000038; + "fmul" & 0xfc00f83e == 0xfc000032; + "fmuls" & 0xfc00f83e == 0xec000032; + "fnabs" & 0xfc1f07fe == 0xfc000110; + "fneg" & 0xfc1f07fe == 0xfc000050; + "fnmadd" & 0xfc00003e == 0xfc00003e; + "fnmadds" & 0xfc00003e == 0xec00003e; + "fnmsub" & 0xfc00003e == 0xfc00003c; + "fnmsubs" & 0xfc00003e == 0xec00003c; + "fres" & 0xfc1f07fe == 0xec000030; + "frsp" & 0xfc1f07fe == 0xfc000018; + "frsqrte" & 0xfc1f07fe == 0xfc000034; + "fsel" & 0xfc00003e == 0xfc00002e; + "fsub" & 0xfc0007fe == 0xfc000028; + "fsubs" & 0xfc0007fe == 0xec000028; + "icbi" & 0xffe007ff == 0x7c0007ac; + "isync" & 0xffffffff == 0x4c00012c; + "lbz" & 0xfc000000 == 0x88000000; + "lbzu" & 0xfc000000 == 0x8c000000; + "lbzux" & 0xfc0007ff == 0x7c0000ee; + "lbzx" & 0xfc0007ff == 0x7c0000ae; + "lfd" & 0xfc000000 == 0xc8000000; + "lfdu" & 0xfc000000 == 0xcc000000; + "lfdux" & 0xfc0007ff == 0x7c0004ee; + "lfdx" & 0xfc0007ff == 0x7c00045e; + "lfs" & 0xfc000000 == 0xc0000000; + "lfsu" & 0xfc000000 == 0xc4000000; + "lfsux" & 0xfc0007ff == 0x7c00046e; + "lfsx" & 0xfc0007ff == 0x7c00042e; + "lha" & 0xfc000000 == 0xa8000000; + "lhau" & 0xfc000000 == 0xac000000; + "lhaux" & 0xfc0007ff == 0x7c0002ee; + "lhax" & 0xfc0007ff == 0x7c0002ae; + "lhbrx" & 0xfc0007ff == 0x7c00062c; + "lhz" & 0xfc000000 == 0xa0000000; + "lhzu" & 0xfc000000 == 0xa4000000; + "lhzux" & 0xfc0007ff == 0x7c00026e; + "lhzx" & 0xfc0007ff == 0x7c00022e; + "lmw" & 0xfc000000 == 0xb8000000; + "lswi" & 0xfc0007ff == 0x7c0004aa; + "lswx" & 0xfc0007ff == 0x7c00042a; + "lwarx" & 0xfc0007ff == 0x7c000028; + "lwbrx" & 0xfc0007ff == 0x7c00042c; + "lwz" & 0xfc000000 == 0x80000000; + "lwzu" & 0xfc000000 == 0x84000000; + "lwzux" & 0xfc0007ff == 0x7c00006e; + "lwzx" & 0xfc0007ff == 0x7c00002e; + "mcrf" & 0xfc300fff == 0x4c000000; + "mcrfs" & 0xfc30ffff == 0xfc000080; + "mcrxr" & 0xfc30ffff == 0x7c000400; + "mfcr" & 0xfc1fffff == 0x7c000026; + "mffs" & 0xfc1ffffe == 0x7c00048e; + "mfmsr" & 0xfc1fffff == 0x7c0000a6; + "mfspr" & 0xfc0007ff == 0x7c0002a6; + "mfsr" & 0xfc10ffff == 0x7c0004a6; + "mfsrin" & 0xfc1f07ff == 0x7c000526; + "mftb" & 0xfc0007ff == 0x7c0002e6; + "mtcrf" & 0xfc100fff == 0x7c000120; + "mtfsb0" & 0xfc1ffffe == 0xfc00008c; + "mtfsb1" & 0xfc1ffffe == 0xfc00004c; + "mtfsf" & 0xfe0107fe == 0xfc00058e; + "mtfsfi" & 0xfc7f0ffe == 0xfc00010c; + "mtmsr" & 0xfc1fffff == 0x7c000124; + "mtspr" & 0xfc0007ff == 0x7c0003a6; + "mtsr" & 0xfc10ffff == 0x7c0001a4; + "mtsrin" & 0xfc1f07ff == 0x7c0001e4; + "mulhw" & 0xfc0007fe == 0x7c000096; + "mulhwu" & 0xfc0007fe == 0x7c000016; + "mulli" & 0xfc000000 == 0x1c000000; + "mullw" & 0xfc0003fe == 0x7c0001d6; + "nand" & 0xfc0007fe == 0x7c0003b8; + "neg" & 0xfc00fffe == 0x7c0000d0; + "nor" & 0xfc0007fe == 0x7c0000f8; + "or" & 0xfc0007fe == 0x7c000378; + "orc" & 0xfc0007fe == 0x7c000338; + "ori" & 0xfc000000 == 0x60000000; + "oris" & 0xfc000000 == 0x64000000; + "psq_l" & 0xfc000000 == 0xe0000000; + "psq_lu" & 0xfc000000 == 0xe4000000; + "psq_lux" & 0xfc00007f == 0x1000004c; + "psq_lx" & 0xfc00007f == 0x1000000c; + "psq_st" & 0xfc000000 == 0xf0000000; + "psq_stu" & 0xfc000000 == 0xf4000000; + "psq_stux" & 0xfc00007f == 0x1000004e; + "psq_stx" & 0xfc00007f == 0x1000000e; + "ps_abs" & 0xfc1f07fe == 0x10000210; + "ps_add" & 0xfc0007fe == 0x1000002a; + "ps_cmpo0" & 0xfc6007ff == 0x10000040; + "ps_cmpo1" & 0xfc6007ff == 0x100000c0; + "ps_cmpu0" & 0xfc6007ff == 0x10000000; + "ps_cmpu1" & 0xfc6007ff == 0x10000080; + "ps_div" & 0xfc0007fe == 0x10000024; + "ps_madd" & 0xfc00003e == 0x1000003a; + "ps_madds0" & 0xfc00003e == 0x1000001c; + "ps_madds1" & 0xfc00003e == 0x1000001e; + "ps_merge00" & 0xfc0007fe == 0x10000420; + "ps_merge01" & 0xfc0007fe == 0x10000460; + "ps_merge10" & 0xfc0007fe == 0x100004a0; + "ps_merge11" & 0xfc0007fe == 0x100004e0; + "ps_mr" & 0xfc1f07fe == 0x10000090; + "ps_msub" & 0xfc00003e == 0x10000038; + "ps_mul" & 0xfc00f83e == 0x10000032; + "ps_muls0" & 0xfc00f83e == 0x10000018; + "ps_muls1" & 0xfc00f83e == 0x1000001a; + "ps_nabs" & 0xfc1f07fe == 0x10000110; + "ps_neg" & 0xfc1f07fe == 0x10000050; + "ps_nmadd" & 0xfc00003e == 0x1000003e; + "ps_nmsub" & 0xfc00003e == 0x1000003c; + "ps_res" & 0xfc1f07fe == 0x10000030; + "ps_rsqrte" & 0xfc1f07fe == 0x10000034; + "ps_sel" & 0xfc00003e == 0x1000002e; + "ps_sub" & 0xfc0007fe == 0x10000028; + "ps_sum0" & 0xfc00003e == 0x10000014; + "ps_sum1" & 0xfc00003e == 0x10000016; + "rfi" & 0xfffff801 == 0x4c000000; + "rlwimi" & 0xfc000000 == 0x50000000; + "rlwinm" & 0xfc000000 == 0x54000000; + "rlwnm" & 0xfc000000 == 0x5c000000; + "sc" & 0xffffffff == 0x44000002; + "slw" & 0xfc0007fe == 0x7c000030; + "sraw" & 0xfc0007fe == 0x7c000630; + "srawi" & 0xfc0007fe == 0x7c000670; + "srw" & 0xfc0007fe == 0x7c000430; + "stb" & 0xfc000000 == 0x98000000; + "stbu" & 0xfc000000 == 0x9c000000; + "stbux" & 0xfc0003ff == 0x7c0001ee; + "stbx" & 0xfc0003ff == 0x7c0001ae; + "stfd" & 0xfc000000 == 0xd8000000; + "stfdu" & 0xfc000000 == 0xdc000000; + "stfdux" & 0xfc0007ff == 0x7c0005ee; + "stfdx" & 0xfc0007ff == 0x7c0005ae; + "stfiwx" & 0xfc0007ff == 0x7c0007ae; + "stfs" & 0xfc000000 == 0xd0000000; + "stfsu" & 0xfc000000 == 0xd4000000; + "stfsux" & 0xfc0007ff == 0x7c00056e; + "stfsx" & 0xfc0007ff == 0x7c00052e; + "sth" & 0xfc000000 == 0xb0000000; + "sthbrx" & 0xfc0007ff == 0x7c00072c; + "sthu" & 0xfc000000 == 0xb4000000; + "sthux" & 0xfc0007ff == 0x7c00036e; + "sthx" & 0xfc0007ff == 0x7c00032e; + "stmw" & 0xfc000000 == 0xbc000000; + "stswi" & 0xfc0007ff == 0x7c0005aa; + "stswx" & 0xfc0007ff == 0x7c00052a; + "stw" & 0xfc000000 == 0x90000000; + "stwbrx" & 0xfc0007ff == 0x7c00052c; + "stwcx." & 0xfc0007ff == 0x7c00012d; + "stwu" & 0xfc000000 == 0x94000000; + "stwux" & 0xfc0007ff == 0x7c00016e; + "stwx" & 0xfc0007ff == 0x7c00012e; + "subf" & 0xfc0003fe == 0x7c000050; + "subfc" & 0xfc0003fe == 0x7c000010; + "subfe" & 0xfc0003fe == 0x7c000110; + "subfic" & 0xfc000000 == 0x20000000; + "subfme" & 0xfc00fbfe == 0x7c0001d0; + "subfze" & 0xfc00fbfe == 0x7c000190; + "sync" & 0xffffffff == 0x7c0004ac; + "tlbie" & 0xffff07ff == 0x7c000264; + "tlbsync" & 0xffffffff == 0x7c00046c; + "tw" & 0xfc0007ff == 0x7c000008; + "twi" & 0xfc000000 == 0xc000000; + "xor" & 0xfc0007fe == 0x7c000278; + "xori" & 0xfc000000 == 0x68000000; + "xoris" & 0xfc000000 == 0x6c000000; +} diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 5e8ec3e..6ef6dd1 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -5,232 +5,8 @@ use std::ops::Range; use num_traits::AsPrimitive; -use ppc750cl_macros::isa; - -isa! { - "add" & 0xfc0007fe == 0x7c000214; - "addc" & 0xfc0007fe == 0x7c00002a; - "adde" & 0xfc0007fe == 0x7c000114; - "addi" & 0xfc000000 == 0x38000000; - "addic" & 0xfc000000 == 0x30000000; - "addic." & 0xfc000000 == 0x34000000; - "addis" & 0xfc000000 == 0x3c000000; - "addme" & 0xfc00fbfe == 0x7c0001d4; - "addze" & 0xfc00fbfe == 0x7c000194; - "and" & 0xfc0007fe == 0x7c000038; - "andc" & 0xfc0007fe == 0x7c000078; - "andi." & 0xfc000000 == 0x70000000; - "andis." & 0xfc000000 == 0x74000000; - "b" & 0xfc000000 == 0x48000000; - "bc" & 0xfc000000 == 0x40000000; - "bcctr" & 0xfc00ffff == 0x4c000210; - "bclr" & 0xfc00fffe == 0x4c000020; - "cmp" & 0xfc4007ff == 0x7c000000; - "cmpi" & 0xfc400000 == 0x2c000000; - "cmpl" & 0xfc4007ff == 0x7c000040; - "cmpli" & 0xfc400000 == 0x28000000; - "cntlzw" & 0xfc00fffe == 0x7c000034; - "crand" & 0xfc0007ff == 0x4c000202; - "crandc" & 0xfc0007ff == 0x4c000102; - "creqv" & 0xfc0007ff == 0x4c000242; - "crnand" & 0xfc0007ff == 0x4c0001c2; - "crnor" & 0xfc0007ff == 0x4c000042; - "cror" & 0xfc0007ff == 0x4c000382; - "crorc" & 0xfc0007ff == 0x4c000342; - "crxor" & 0xfc0007ff == 0x4c000182; - "dcbf" & 0xffe007ff == 0x7c0000ac; - "dcbi" & 0xffe007ff == 0x7c0003ac; - "dcbst" & 0xffe007ff == 0x7c00006c; - "dcbt" & 0xffe007ff == 0x7c00022c; - "dcbtst" & 0xffe007ff == 0x7c0001ec; - "dcbz" & 0xffe007ff == 0x7c0007ec; - "dcbz_l" & 0xffe007ff == 0x100007ec; - "divw" & 0xfc0003fe == 0x7c0003d6; - "divwu" & 0xfc0003fe == 0x7c000396; - "eciwx" & 0xfc0003ff == 0x7c00026c; - "ecowx" & 0xfc0003ff == 0x7c00036c; - "eieio" & 0xffffffff == 0x7c0006ac; - "eqv" & 0xfc0003fe == 0x7c000238; - "extsb" & 0xfc00fffe == 0x7c000774; - "extsh" & 0xfc00fffe == 0x7c000734; - "fabs" & 0xfc1f07fe == 0xfc000734; - "fadd" & 0xfc0007fe == 0xfc00002a; - "fadds" & 0xfc0007fe == 0xec00002a; - "fcmpo" & 0xfc6007ff == 0xfc000040; - "fcmpu" & 0xfc6007ff == 0xfc000000; - "fctiw" & 0xfc1f07fe == 0xfc00001c; - "fctiwz" & 0xfc1f07fe == 0xfc00001e; - "fdiv" & 0xfc0007fe == 0xfc000024; - "fdivs" & 0xfc0007fe == 0xec000024; - "fmadd" & 0xfc00003e == 0xfc00003a; - "fmadds" & 0xfc00003e == 0xec00003a; - "fmr" & 0xfc1f07fe == 0xfc000090; - "fmsub" & 0xfc00003e == 0xfc000038; - "fmsubs" & 0xfc00003e == 0xec000038; - "fmul" & 0xfc00f83e == 0xfc000032; - "fmuls" & 0xfc00f83e == 0xec000032; - "fnabs" & 0xfc1f07fe == 0xfc000110; - "fneg" & 0xfc1f07fe == 0xfc000050; - "fnmadd" & 0xfc00003e == 0xfc00003e; - "fnmadds" & 0xfc00003e == 0xec00003e; - "fnmsub" & 0xfc00003e == 0xfc00003c; - "fnmsubs" & 0xfc00003e == 0xec00003c; - "fres" & 0xfc1f07fe == 0xec000030; - "frsp" & 0xfc1f07fe == 0xfc000018; - "frsqrte" & 0xfc1f07fe == 0xfc000034; - "fsel" & 0xfc00003e == 0xfc00002e; - "fsub" & 0xfc0007fe == 0xfc000028; - "fsubs" & 0xfc0007fe == 0xec000028; - "icbi" & 0xffe007ff == 0x7c0007ac; - "isync" & 0xffffffff == 0x4c00012c; - "lbz" & 0xfc000000 == 0x88000000; - "lbzu" & 0xfc000000 == 0x8c000000; - "lbzux" & 0xfc0007ff == 0x7c0000ee; - "lbzx" & 0xfc0007ff == 0x7c0000ae; - "lfd" & 0xfc000000 == 0xc8000000; - "lfdu" & 0xfc000000 == 0xcc000000; - "lfdux" & 0xfc0007ff == 0x7c0004ee; - "lfdx" & 0xfc0007ff == 0x7c00045e; - "lfs" & 0xfc000000 == 0xc0000000; - "lfsu" & 0xfc000000 == 0xc4000000; - "lfsux" & 0xfc0007ff == 0x7c00046e; - "lfsx" & 0xfc0007ff == 0x7c00042e; - "lha" & 0xfc000000 == 0xa8000000; - "lhau" & 0xfc000000 == 0xac000000; - "lhaux" & 0xfc0007ff == 0x7c0002ee; - "lhax" & 0xfc0007ff == 0x7c0002ae; - "lhbrx" & 0xfc0007ff == 0x7c00062c; - "lhz" & 0xfc000000 == 0xa0000000; - "lhzu" & 0xfc000000 == 0xa4000000; - "lhzux" & 0xfc0007ff == 0x7c00026e; - "lhzx" & 0xfc0007ff == 0x7c00022e; - "lmw" & 0xfc000000 == 0xb8000000; - "lswi" & 0xfc0007ff == 0x7c0004aa; - "lswx" & 0xfc0007ff == 0x7c00042a; - "lwarx" & 0xfc0007ff == 0x7c000028; - "lwbrx" & 0xfc0007ff == 0x7c00042c; - "lwz" & 0xfc000000 == 0x80000000; - "lwzu" & 0xfc000000 == 0x84000000; - "lwzux" & 0xfc0007ff == 0x7c00006e; - "lwzx" & 0xfc0007ff == 0x7c00002e; - "mcrf" & 0xfc300fff == 0x4c000000; - "mcrfs" & 0xfc30ffff == 0xfc000080; - "mcrxr" & 0xfc30ffff == 0x7c000400; - "mfcr" & 0xfc1fffff == 0x7c000026; - "mffs" & 0xfc1ffffe == 0x7c00048e; - "mfmsr" & 0xfc1fffff == 0x7c0000a6; - "mfspr" & 0xfc0007ff == 0x7c0002a6; - "mfsr" & 0xfc10ffff == 0x7c0004a6; - "mfsrin" & 0xfc1f07ff == 0x7c000526; - "mftb" & 0xfc0007ff == 0x7c0002e6; - "mtcrf" & 0xfc100fff == 0x7c000120; - "mtfsb0" & 0xfc1ffffe == 0xfc00008c; - "mtfsb1" & 0xfc1ffffe == 0xfc00004c; - "mtfsf" & 0xfe0107fe == 0xfc00058e; - "mtfsfi" & 0xfc7f0ffe == 0xfc00010c; - "mtmsr" & 0xfc1fffff == 0x7c000124; - "mtspr" & 0xfc0007ff == 0x7c0003a6; - "mtsr" & 0xfc10ffff == 0x7c0001a4; - "mtsrin" & 0xfc1f07ff == 0x7c0001e4; - "mulhw" & 0xfc0007fe == 0x7c000096; - "mulhwu" & 0xfc0007fe == 0x7c000016; - "mulli" & 0xfc000000 == 0x1c000000; - "mullw" & 0xfc0003fe == 0x7c0001d6; - "nand" & 0xfc0007fe == 0x7c0003b8; - "neg" & 0xfc00fffe == 0x7c0000d0; - "nor" & 0xfc0007fe == 0x7c0000f8; - "or" & 0xfc0007fe == 0x7c000378; - "orc" & 0xfc0007fe == 0x7c000338; - "ori" & 0xfc000000 == 0x60000000; - "oris" & 0xfc000000 == 0x64000000; - "psq_l" & 0xfc000000 == 0xe0000000; - "psq_lu" & 0xfc000000 == 0xe4000000; - "psq_lux" & 0xfc00007f == 0x1000004c; - "psq_lx" & 0xfc00007f == 0x1000000c; - "psq_st" & 0xfc000000 == 0xf0000000; - "psq_stu" & 0xfc000000 == 0xf4000000; - "psq_stux" & 0xfc00007f == 0x1000004e; - "psq_stx" & 0xfc00007f == 0x1000000e; - "ps_abs" & 0xfc1f07fe == 0x10000210; - "ps_add" & 0xfc0007fe == 0x1000002a; - "ps_cmpo0" & 0xfc6007ff == 0x10000040; - "ps_cmpo1" & 0xfc6007ff == 0x100000c0; - "ps_cmpu0" & 0xfc6007ff == 0x10000000; - "ps_cmpu1" & 0xfc6007ff == 0x10000080; - "ps_div" & 0xfc0007fe == 0x10000024; - "ps_madd" & 0xfc00003e == 0x1000003a; - "ps_madds0" & 0xfc00003e == 0x1000001c; - "ps_madds1" & 0xfc00003e == 0x1000001e; - "ps_merge00" & 0xfc0007fe == 0x10000420; - "ps_merge01" & 0xfc0007fe == 0x10000460; - "ps_merge10" & 0xfc0007fe == 0x100004a0; - "ps_merge11" & 0xfc0007fe == 0x100004e0; - "ps_mr" & 0xfc1f07fe == 0x10000090; - "ps_msub" & 0xfc00003e == 0x10000038; - "ps_mul" & 0xfc00f83e == 0x10000032; - "ps_muls0" & 0xfc00f83e == 0x10000018; - "ps_muls1" & 0xfc00f83e == 0x1000001a; - "ps_nabs" & 0xfc1f07fe == 0x10000110; - "ps_neg" & 0xfc1f07fe == 0x10000050; - "ps_nmadd" & 0xfc00003e == 0x1000003e; - "ps_nmsub" & 0xfc00003e == 0x1000003c; - "ps_res" & 0xfc1f07fe == 0x10000030; - "ps_rsqrte" & 0xfc1f07fe == 0x10000034; - "ps_sel" & 0xfc00003e == 0x1000002e; - "ps_sub" & 0xfc0007fe == 0x10000028; - "ps_sum0" & 0xfc00003e == 0x10000014; - "ps_sum1" & 0xfc00003e == 0x10000016; - "rfi" & 0xfffff801 == 0x4c000000; - "rlwimi" & 0xfc000000 == 0x50000000; - "rlwinm" & 0xfc000000 == 0x54000000; - "rlwnm" & 0xfc000000 == 0x5c000000; - "sc" & 0xffffffff == 0x44000002; - "slw" & 0xfc0007fe == 0x7c000030; - "sraw" & 0xfc0007fe == 0x7c000630; - "srawi" & 0xfc0007fe == 0x7c000670; - "srw" & 0xfc0007fe == 0x7c000430; - "stb" & 0xfc000000 == 0x98000000; - "stbu" & 0xfc000000 == 0x9c000000; - "stbux" & 0xfc0003ff == 0x7c0001ee; - "stbx" & 0xfc0003ff == 0x7c0001ae; - "stfd" & 0xfc000000 == 0xd8000000; - "stfdu" & 0xfc000000 == 0xdc000000; - "stfdux" & 0xfc0003ff == 0x7c0005ee; - "stfdx" & 0xfc0003ff == 0x7c0005ae; - "stfiwx" & 0xfc0007ff == 0x7c0007ae; - "stfs" & 0xfc000000 == 0xd0000000; - "stfsu" & 0xfc000000 == 0xd4000000; - "stfsux" & 0xfc0003ff == 0x7c00056e; - "stfsx" & 0xfc0003ff == 0x7c00052e; - "sth" & 0xfc000000 == 0xb0000000; - "sthbrx" & 0xfc0007ff == 0x7c00072c; - "sthu" & 0xfc000000 == 0xb4000000; - "sthux" & 0xfc0003ff == 0x7c00036e; - "sthx" & 0xfc0003ff == 0x7c00032e; - "stmw" & 0xfc000000 == 0xbc000000; - "stswi" & 0xfc0007ff == 0x7c0005aa; - "stswx" & 0xfc0007ff == 0x7c00052a; - "stw" & 0xfc000000 == 0x90000000; - "stwbrx" & 0xfc0007ff == 0x7c00052c; - "stwcx." & 0xfc0007ff == 0x7c00012d; - "stwu" & 0xfc000000 == 0x94000000; - "stwux" & 0xfc0003ff == 0x7c00016e; - "stwx" & 0xfc0003ff == 0x7c00012e; - "subf" & 0xfc0003fe == 0x7c000050; - "subfc" & 0xfc0003fe == 0x7c000010; - "subfe" & 0xfc0003fe == 0x7c000110; - "subfic" & 0xfc000000 == 0x20000000; - "subfme" & 0xfc00fbfe == 0x7c0001d0; - "subfze" & 0xfc00fbfe == 0x7c000190; - "sync" & 0xffffffff == 0x7c0004ac; - "tlbie" & 0xffff07ff == 0x7c000264; - "tlbsync" & 0xffffffff == 0x7c00046c; - "tw" & 0xfc0007ff == 0x7c000008; - "twi" & 0xfc000000 == 0xc000000; - "xor" & 0xfc0007fe == 0x7c000278; - "xori" & 0xfc000000 == 0x68000000; - "xoris" & 0xfc000000 == 0x6c000000; -} +mod isa; +pub use crate::isa::Opcode; #[derive(Default, Clone)] pub struct Ins { @@ -253,11 +29,6 @@ where masked.as_() } -#[inline(always)] -fn zero_bits(x: u32, range: Range) -> bool { - bits::(x, range) == 0 -} - macro_rules! disasm_unreachable { ($msg:expr $(,)?) => {{ panic!( @@ -290,11 +61,8 @@ macro_rules! ins_field { } impl Ins { - fn new(code: u32) -> Self { - Ins { - code, - ..Default::default() - } + fn new(code: u32, op: Opcode) -> Self { + Ins { code, op } } fn illegal() -> Self { @@ -344,17 +112,13 @@ impl Ins { pub fn disasm(x: u32) -> Self { let family = bits(x, 0..6); - match family { - 0b000011 => { - let mut ins = Ins::new(x); - ins.op = Opcode::Twi; - ins - } + let mut ins = match family { + 0b000011 => Ins::new(x, Opcode::Twi), 0b000100 => Self::disasm_cl_ext(x), 0b000111..=0b001111 => Self::disasm_basic1(x), - 0b010000 => Self::disasm_bc(x), - 0b010001 => Self::disasm_sc(x), - 0b010010 => Self::disasm_b(x), + 0b010000 => Ins::new(x, Opcode::Bc), + 0b010001 => Ins::new(x, Opcode::Sc), + 0b010010 => Ins::new(x, Opcode::B), 0b010011 => Self::disasm_010011(x), 0b010100..=0b011101 => Self::disasm_basic2(x), 0b011111 => Self::disasm_011111(x), @@ -364,238 +128,111 @@ impl Ins { 0b111100..=0b111101 => Self::disasm_psq(x), 0b111111 => Self::disasm_111111(x), _ => Self::illegal(), - } - } - - fn disasm_cl_ext(x: u32) -> Self { - let mut ins = Ins::new(x); - let key: u8 = bits(x, 26..31); - match key { - // AB cmp form - 0b00000 => { - ins.op = match bits(x, 26..31) { - 0b00000 => Opcode::PsCmpu0, - 0b00001 => Opcode::PsCmpo0, - 0b00010 => Opcode::PsCmpu1, - 0b00011 => Opcode::PsCmpo1, - _ => Opcode::Illegal, - }; - if !zero_bits(x, 9..11) || bit(x, 31) == 1 { - ins.op = Opcode::Illegal; - } - } - // ABwi form - 0b00110 | 0b00111 => { - if bit(x, 25) == 0 { - ins.op = match key { - 0b00110 => Opcode::PsqLx, - 0b00111 => Opcode::PsqStx, - _ => Opcode::Illegal, - }; - } else { - ins.op = match key { - 0b00110 => Opcode::PsqLux, - 0b00111 => Opcode::PsqStux, - _ => Opcode::Illegal, - }; - } - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - // ABC form - 0b01010 | 0b01011 | 0b01110 | 0b01111 | 0b11100..=0b11111 => { - ins.op = match key { - 0b01010 => Opcode::PsSum0, - 0b01011 => Opcode::PsSum1, - 0b01110 => Opcode::PsMadds0, - 0b01111 => Opcode::PsMadds1, - 0b10111 => Opcode::PsSel, - 0b11100 => Opcode::PsMsub, - 0b11101 => Opcode::PsMadd, - 0b11110 => Opcode::PsNmsub, - 0b11111 => Opcode::PsNmadd, - _ => disasm_unreachable!(x), - }; - } - // AC form - 0b01100 | 0b01101 | 0b11001 => { - ins.op = match key { - 0b01100 => Opcode::PsMuls0, - 0b01101 => Opcode::PsMuls1, - 0b11001 => Opcode::PsMul, - _ => disasm_unreachable!(x), - }; - if bits::(x, 21..26) != 0 { - ins.op = Opcode::Illegal; - } - } - // AB form - 0b10010 | 0b10100 | 0b10101 => { - ins.op = match key { - 0b10010 => Opcode::PsDiv, - 0b10100 => Opcode::PsSub, - 0b10101 => Opcode::PsAdd, - _ => disasm_unreachable!(x), - }; - if bits::(x, 26..31) != 0 { - ins.op = Opcode::Illegal; - } - } - // B form - 0b11000 | 0b11010 => { - ins.op = match key { - 0b11000 => Opcode::PsRes, - 0b11010 => Opcode::PsRsqrte, - _ => disasm_unreachable!(x), - }; - if bits::(x, 16..21) != 0 || bits::(x, 26..31) != 0 { - ins.op = Opcode::Illegal; - } - } - // B alt form - 0b01000 => { - ins.op = match bits(x, 26..31) { - 0b00001 => Opcode::PsNeg, - 0b00010 => Opcode::PsMr, - 0b00100 => Opcode::PsNabs, - 0b01000 => Opcode::PsAbs, - _ => Opcode::Illegal, - }; - } - // AB alt form - 0b10000 => { - ins.op = match bits(x, 26..31) { - 0b10000 => Opcode::PsMerge00, - 0b10001 => Opcode::PsMerge01, - 0b10010 => Opcode::PsMerge10, // violates IBM user guide - 0b10011 => Opcode::PsMerge11, - _ => Opcode::Illegal, - } - } - // dcbz_l - 0b10110 => { - ins.op = Opcode::DcbzL; - if bits::(x, 11..16) != 0 { - ins.op = Opcode::Illegal; // reserved - } - } - // Unknown paired-singles key. - _ => ins.op = Opcode::Illegal, + }; + if !ins.op.is_valid(x) { + ins.op = Opcode::Illegal; } ins } - fn disasm_basic1(x: u32) -> Self { - let mut ins = Ins::new(x); - let key = bits(x, 0..6); - ins.op = match key { - 0b000111 => Opcode::Mulli, - 0b001000 => Opcode::Subfic, - 0b001010 | 0b001011 => { - if bit(x, 9) != 0 { - Opcode::Illegal // reserved - } else if key == 0b001010 { - Opcode::Cmpli - } else if key == 0b001011 { - Opcode::Cmpi + fn disasm_cl_ext(x: u32) -> Self { + let op = match bits(x, 26..31) { + 0b00000 => match bits(x, 26..31) { + 0b00000 => Opcode::PsCmpu0, + 0b00001 => Opcode::PsCmpo0, + 0b00010 => Opcode::PsCmpu1, + 0b00011 => Opcode::PsCmpo1, + _ => Opcode::Illegal, + }, + 0b00110 => { + if bit(x, 25) == 0 { + Opcode::PsqLx } else { - disasm_unreachable!(x) + Opcode::PsqLux } } + 0b00111 => { + if bit(x, 25) == 0 { + Opcode::PsqStx + } else { + Opcode::PsqStux + } + } + 0b01010 => Opcode::PsSum0, + 0b01011 => Opcode::PsSum1, + 0b01110 => Opcode::PsMadds0, + 0b01111 => Opcode::PsMadds1, + 0b10111 => Opcode::PsSel, + 0b11100 => Opcode::PsMsub, + 0b11101 => Opcode::PsMadd, + 0b11110 => Opcode::PsNmsub, + 0b11111 => Opcode::PsNmadd, + 0b01100 => Opcode::PsMuls0, + 0b01101 => Opcode::PsMuls1, + 0b11001 => Opcode::PsMul, + 0b10010 => Opcode::PsDiv, + 0b10100 => Opcode::PsSub, + 0b10101 => Opcode::PsAdd, + 0b11000 => Opcode::PsRes, + 0b11010 => Opcode::PsRsqrte, + 0b01000 => match bits(x, 26..31) { + 0b00001 => Opcode::PsNeg, + 0b00010 => Opcode::PsMr, + 0b00100 => Opcode::PsNabs, + 0b01000 => Opcode::PsAbs, + _ => Opcode::Illegal, + }, + 0b10000 => match bits(x, 26..31) { + 0b10000 => Opcode::PsMerge00, + 0b10001 => Opcode::PsMerge01, + 0b10010 => Opcode::PsMerge10, + 0b10011 => Opcode::PsMerge11, + _ => Opcode::Illegal, + }, + 0b10110 => Opcode::DcbzL, + // Unknown paired-singles key. + _ => Opcode::Illegal, + }; + Ins::new(x, op) + } + + fn disasm_basic1(x: u32) -> Self { + let op = match bits(x, 0..6) { + 0b000111 => Opcode::Mulli, + 0b001000 => Opcode::Subfic, + 0b001010 => Opcode::Cmpli, + 0b001011 => Opcode::Cmpi, 0b001100 => Opcode::Addic, 0b001101 => Opcode::Addic_, 0b001110 => Opcode::Addi, 0b001111 => Opcode::Addis, _ => Opcode::Illegal, }; - ins - } - - fn disasm_bc(x: u32) -> Self { - let mut ins = Ins::new(x); - ins.op = Opcode::Bc; - ins - } - - fn disasm_sc(x: u32) -> Self { - let mut ins = Ins::new(x); - ins.op = Opcode::Sc; - if bits::(x, 6..32) != 0b10 { - ins.op = Opcode::Illegal; - } - ins - } - - fn disasm_b(x: u32) -> Self { - let mut ins = Ins::new(x); - ins.op = Opcode::B; - ins + Ins::new(x, op) } fn disasm_010011(x: u32) -> Self { - let mut ins = Ins::new(x); - let key = bits(x, 21..27); - let key2 = bits::(x, 27..31); - match key { - // mcrf - 0b000000 => { - ins.op = Opcode::Mcrf; - if ins.code & 0b11111_000_11_000_11_11111_1111111111_1 - != 0b10011_000_00_000_00_00000_0000000000_0 - { - ins.op = Opcode::Illegal; - } - } - // DA form - 0b000001 | 0b100001 => { - ins.op = match key { - 0b000001 => Opcode::Bclr, - 0b100001 => Opcode::Bcctr, - _ => disasm_unreachable!(x), - }; - if ins.code & 0b00000000_00000000_11111_000_00000000 != 0 { - ins.op = Opcode::Illegal; - } - } - 0b000011 => { - ins.op = Opcode::Rfi; - if !zero_bits(x, 6..21) || bits::(x, 27..31) != 0b0010 || bit(x, 31) == 0 { - ins.op = Opcode::Illegal; - } - } - 0b001001 => { - ins.op = Opcode::Isync; - if !zero_bits(x, 6..21) || bits::(x, 27..31) != 0b0110 || bit(x, 31) == 0 { - ins.op = Opcode::Illegal; - } - } - // DAB form - 0b000010 | 0b001000 | 0b001100..=0b011100 => { - ins.op = match key { - 0b000010 => Opcode::Crnor, - 0b001000 => Opcode::Crandc, - 0b001100 => Opcode::Crxor, - 0b001110 => Opcode::Crnand, - 0b010000 => Opcode::Crand, - 0b010010 => Opcode::Creqv, - 0b011010 => Opcode::Crorc, - 0b011100 => Opcode::Cror, - _ => Opcode::Illegal, - }; - if key2 != 0b0001 || bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - _ => (), - } - ins + let op = match bits(x, 21..27) { + 0b000000 => Opcode::Mcrf, + 0b000001 => Opcode::Bclr, + 0b100001 => Opcode::Bcctr, + 0b000011 => Opcode::Rfi, + 0b001001 => Opcode::Isync, + 0b000010 => Opcode::Crnor, + 0b001000 => Opcode::Crandc, + 0b001100 => Opcode::Crxor, + 0b001110 => Opcode::Crnand, + 0b010000 => Opcode::Crand, + 0b010010 => Opcode::Creqv, + 0b011010 => Opcode::Crorc, + 0b011100 => Opcode::Cror, + _ => Opcode::Illegal, + }; + Ins::new(x, op) } fn disasm_basic2(x: u32) -> Self { - let mut ins = Ins::new(x); - let key = bits(x, 0..6); - ins.op = match key { + let op = match bits(x, 0..6) { 0b10100 => Opcode::Rlwimi, 0b10101 => Opcode::Rlwinm, 0b10111 => Opcode::Rlwnm, @@ -607,471 +244,110 @@ impl Ins { 0b11101 => Opcode::Andis_, _ => Opcode::Illegal, }; - ins + Ins::new(x, op) } fn disasm_011111(x: u32) -> Self { - let mut ins = Ins::new(x); - let key = bits::(x, 21..31); - // Super ugly switch statement. - // Plenty to clean up here. - match key { - 0b00_0000_0000 | 0b00_0010_0000 => { - ins.op = match key { - 0b00_0000_0000 => Opcode::Cmp, - 0b00_0010_0000 => Opcode::Cmpl, - _ => disasm_unreachable!(x), - }; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b00_0000_0100 => { - ins.op = Opcode::Tw; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b00_0000_1000 => ins.op = Opcode::Subfc, - 0b00_0000_1010 => ins.op = Opcode::Addc, - 0b00_0000_1011 => ins.op = Opcode::Mulhwu, - 0b00_0001_0011 => { - ins.op = Opcode::Mfcr; - if bits::(x, 16..21) != 0 || bits::(x, 21..26) != 0 || bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b00_0001_0100 => { - ins.op = Opcode::Lwarx; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b00_0001_0111 => { - ins.op = Opcode::Lwzx; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b00_0001_1000 => ins.op = Opcode::Slw, - 0b00_0001_1010 => { - ins.op = Opcode::Cntlzw; - if bits::(x, 21..26) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b00_0001_1100 => ins.op = Opcode::And, - 0b00_0010_1000 => ins.op = Opcode::Subf, - 0b00_0011_0110 => { - ins.op = Opcode::Dcbst; - if bits::(x, 11..16) != 0 || bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b00_0011_0111 => { - ins.op = Opcode::Lwzux; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b00_0011_1100 => ins.op = Opcode::Andc, - 0b00_0100_1101 => ins.op = Opcode::Mulhw, - 0b00_0101_0011 => { - ins.op = Opcode::Mfmsr; - if bits::(x, 16..21) != 0 || bits::(x, 21..26) != 0 || bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b00_0101_0110 => { - ins.op = Opcode::Dcbf; - if bits::(x, 11..16) != 0 || bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b00_0101_0111 => { - ins.op = Opcode::Lbzx; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b00_0110_1000 => { - ins.op = Opcode::Neg; - if bits::(x, 21..26) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b00_0111_0111 => { - ins.op = Opcode::Lbzux; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b00_0111_1100 => ins.op = Opcode::Nor, - 0b00_1000_1000 => ins.op = Opcode::Subfe, - 0b00_1000_1010 => ins.op = Opcode::Adde, - 0b00_1001_0000 => { - ins.op = Opcode::Mtcrf; - if bit(x, 11) != 0 || bit(x, 20) != 0 || bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b00_1001_0010 => { - ins.op = Opcode::Mtmsr; - if bits::(x, 16..21) != 0 || bits::(x, 21..26) != 0 || bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b00_1001_0110 => { - ins.op = Opcode::Stwcx_; - if bit(x, 31) == 0 { - ins.op = Opcode::Illegal; - } - } - 0b00_1001_0111 => { - ins.op = Opcode::Stwx; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b00_1011_0111 => { - ins.op = Opcode::Stwux; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b00_1100_1000 => { - ins.op = Opcode::Subfze; - if bits::(x, 21..26) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b00_1100_1010 => { - ins.op = Opcode::Addze; - if bits::(x, 21..26) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b00_1101_0010 => { - ins.op = Opcode::Mtsr; - if bit(x, 11) != 0 || bits::(x, 21..26) != 0 || bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b00_1101_0111 => { - ins.op = Opcode::Stbx; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b00_1110_1000 => { - ins.op = Opcode::Subfme; - if bits::(x, 21..26) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b00_1110_1010 => { - ins.op = Opcode::Addme; - if bits::(x, 21..26) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b00_1110_1011 => ins.op = Opcode::Mullw, - 0b00_1111_0010 => { - ins.op = Opcode::Mtsrin; - if bits::(x, 16..21) != 0 || bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b00_1111_0110 => { - ins.op = Opcode::Dcbtst; - if bits::(x, 11..16) != 0 || bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b00_1111_0111 => { - ins.op = Opcode::Stbux; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b01_0000_1010 => ins.op = Opcode::Add, - 0b01_0000_0110 => { - ins.op = Opcode::Dcbt; - if bits::(x, 11..16) != 0 || bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b01_0000_0111 => { - ins.op = Opcode::Lhzx; - if bits::(x, 11..16) != 0 || bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b01_0001_1100 => ins.op = Opcode::Eqv, - 0b01_0011_0010 => { - ins.op = Opcode::Tlbie; - if bits::(x, 11..16) != 0 || bits::(x, 16..21) != 0 || bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b01_0011_0110 => { - ins.op = Opcode::Eciwx; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b01_0011_0111 => { - ins.op = Opcode::Lhzux; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b01_0011_1100 => ins.op = Opcode::Xor, - 0b01_0101_0011 => { - ins.op = Opcode::Mfspr; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b01_0101_0111 => { - ins.op = Opcode::Lhax; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b01_0111_0011 => { - ins.op = Opcode::Mftb; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b01_0111_0111 => { - ins.op = Opcode::Lhaux; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b01_1001_0111 => { - ins.op = Opcode::Sthx; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b01_1001_1100 => ins.op = Opcode::Orc, - 0b01_1011_0110 => { - ins.op = Opcode::Ecowx; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b01_1011_0111 => { - ins.op = Opcode::Sthux; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b01_1011_1100 => ins.op = Opcode::Or, - 0b01_1100_1011 => ins.op = Opcode::Divwu, - 0b01_1101_0011 => { - ins.op = Opcode::Mtspr; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b01_1101_0110 => { - ins.op = Opcode::Dcbi; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b01_1101_1100 => ins.op = Opcode::Nand, - 0b01_1111_1011 => ins.op = Opcode::Divw, - 0b10_0000_0000 => { - ins.op = Opcode::Mcrxr; - if !zero_bits(x, 9..21) || bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b10_0001_0101 => { - ins.op = Opcode::Lswx; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b10_0001_0110 => { - ins.op = Opcode::Lwbrx; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b10_0001_0111 => { - ins.op = Opcode::Lfsx; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b10_0001_1000 => ins.op = Opcode::Srw, - 0b10_0011_0110 => { - ins.op = Opcode::Tlbsync; - if bits::(x, 11..16) != 0 - || bits::(x, 16..21) != 0 - || bits::(x, 21..26) != 0 - || bit(x, 31) != 0 - { - ins.op = Opcode::Illegal; - } - } - 0b10_0011_0111 => { - ins.op = Opcode::Lfsux; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b10_0101_0011 => { - ins.op = Opcode::Mfsr; - if bit(x, 11) != 0 || bits::(x, 21..26) != 0 || bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b10_0101_0101 => { - ins.op = Opcode::Lswi; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b10_0101_0110 => { - ins.op = Opcode::Sync; - if bits::(x, 11..16) != 0 - || bits::(x, 16..21) != 0 - || bits::(x, 21..26) != 0 - || bit(x, 31) != 0 - { - ins.op = Opcode::Illegal; - } - } - 0b10_0101_0111 => { - ins.op = Opcode::Lfdx; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b10_0111_0111 => { - ins.op = Opcode::Lfdux; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b10_1001_0011 => { - ins.op = Opcode::Mfsrin; - if bits::(x, 16..21) != 0 || bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b10_1001_0101 => { - ins.op = Opcode::Stswx; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b10_1001_0110 => { - ins.op = Opcode::Stwbrx; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b10_1001_0111 => { - ins.op = Opcode::Stfsx; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b10_1011_0111 => { - ins.op = Opcode::Stfsux; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b10_1101_0101 => { - ins.op = Opcode::Stswi; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b10_1101_0111 => { - ins.op = Opcode::Stfdx; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b10_1111_0111 => { - ins.op = Opcode::Stfdux; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b11_0001_0110 => { - ins.op = Opcode::Lhbrx; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b11_0001_1000 => ins.op = Opcode::Sraw, - 0b11_0011_1000 => ins.op = Opcode::Srawi, - 0b11_0101_0110 => { - ins.op = Opcode::Eieio; - if bits::(x, 16..21) != 0 - || bits::(x, 21..26) != 0 - || bits::(x, 26..31) != 0 - || bit(x, 31) != 0 - { - ins.op = Opcode::Illegal; - } - } - 0b11_1001_0110 => { - ins.op = Opcode::Sthbrx; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b11_1001_1010 => { - ins.op = Opcode::Extsh; - if bits::(x, 21..26) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b11_1011_1010 => { - ins.op = Opcode::Extsb; - if bits::(x, 21..26) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b11_1101_0110 => { - ins.op = Opcode::Icbi; - if bits::(x, 11..16) != 0 || bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b11_1101_0111 => { - ins.op = Opcode::Stfiwx; - if bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b11_1111_0110 => { - ins.op = Opcode::Dcbz; - if bits::(x, 11..16) != 0 || bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - _ => ins.op = Opcode::Illegal, - } - ins + let op = match bits::(x, 21..31) { + 0b00_0000_0000 => Opcode::Cmp, + 0b00_0010_0000 => Opcode::Cmpl, + 0b00_0000_0100 => Opcode::Tw, + 0b00_0000_1000 => Opcode::Subfc, + 0b00_0000_1010 => Opcode::Addc, + 0b00_0000_1011 => Opcode::Mulhwu, + 0b00_0001_0011 => Opcode::Mfcr, + 0b00_0001_0100 => Opcode::Lwarx, + 0b00_0001_0111 => Opcode::Lwzx, + 0b00_0001_1000 => Opcode::Slw, + 0b00_0001_1010 => Opcode::Cntlzw, + 0b00_0001_1100 => Opcode::And, + 0b00_0010_1000 => Opcode::Subf, + 0b00_0011_0110 => Opcode::Dcbst, + 0b00_0011_0111 => Opcode::Lwzux, + 0b00_0011_1100 => Opcode::Andc, + 0b00_0100_1101 => Opcode::Mulhw, + 0b00_0101_0011 => Opcode::Mfmsr, + 0b00_0101_0110 => Opcode::Dcbf, + 0b00_0101_0111 => Opcode::Lbzx, + 0b00_0110_1000 => Opcode::Neg, + 0b00_0111_0111 => Opcode::Lbzux, + 0b00_0111_1100 => Opcode::Nor, + 0b00_1000_1000 => Opcode::Subfe, + 0b00_1000_1010 => Opcode::Adde, + 0b00_1001_0000 => Opcode::Mtcrf, + 0b00_1001_0010 => Opcode::Mtmsr, + 0b00_1001_0110 => Opcode::Stwcx_, + 0b00_1001_0111 => Opcode::Stwx, + 0b00_1011_0111 => Opcode::Stwux, + 0b00_1100_1000 => Opcode::Subfze, + 0b00_1100_1010 => Opcode::Addze, + 0b00_1101_0010 => Opcode::Mtsr, + 0b00_1101_0111 => Opcode::Stbx, + 0b00_1110_1000 => Opcode::Subfme, + 0b00_1110_1010 => Opcode::Addme, + 0b00_1110_1011 => Opcode::Mullw, + 0b00_1111_0010 => Opcode::Mtsrin, + 0b00_1111_0110 => Opcode::Dcbtst, + 0b00_1111_0111 => Opcode::Stbux, + 0b01_0000_1010 => Opcode::Add, + 0b01_0000_0110 => Opcode::Dcbt, + 0b01_0000_0111 => Opcode::Lhzx, + 0b01_0001_1100 => Opcode::Eqv, + 0b01_0011_0010 => Opcode::Tlbie, + 0b01_0011_0110 => Opcode::Eciwx, + 0b01_0011_0111 => Opcode::Lhzux, + 0b01_0011_1100 => Opcode::Xor, + 0b01_0101_0011 => Opcode::Mfspr, + 0b01_0101_0111 => Opcode::Lhax, + 0b01_0111_0011 => Opcode::Mftb, + 0b01_0111_0111 => Opcode::Lhaux, + 0b01_1001_0111 => Opcode::Sthx, + 0b01_1001_1100 => Opcode::Orc, + 0b01_1011_0110 => Opcode::Ecowx, + 0b01_1011_0111 => Opcode::Sthux, + 0b01_1011_1100 => Opcode::Or, + 0b01_1100_1011 => Opcode::Divwu, + 0b01_1101_0011 => Opcode::Mtspr, + 0b01_1101_0110 => Opcode::Dcbi, + 0b01_1101_1100 => Opcode::Nand, + 0b01_1111_1011 => Opcode::Divw, + 0b10_0000_0000 => Opcode::Mcrxr, + 0b10_0001_0101 => Opcode::Lswx, + 0b10_0001_0110 => Opcode::Lwbrx, + 0b10_0001_0111 => Opcode::Lfsx, + 0b10_0001_1000 => Opcode::Srw, + 0b10_0011_0110 => Opcode::Tlbsync, + 0b10_0011_0111 => Opcode::Lfsux, + 0b10_0101_0011 => Opcode::Mfsr, + 0b10_0101_0101 => Opcode::Lswi, + 0b10_0101_0110 => Opcode::Sync, + 0b10_0101_0111 => Opcode::Lfdx, + 0b10_0111_0111 => Opcode::Lfdux, + 0b10_1001_0011 => Opcode::Mfsrin, + 0b10_1001_0101 => Opcode::Stswx, + 0b10_1001_0110 => Opcode::Stwbrx, + 0b10_1001_0111 => Opcode::Stfsx, + 0b10_1011_0111 => Opcode::Stfsux, + 0b10_1101_0101 => Opcode::Stswi, + 0b10_1101_0111 => Opcode::Stfdx, + 0b10_1111_0111 => Opcode::Stfdux, + 0b11_0001_0110 => Opcode::Lhbrx, + 0b11_0001_1000 => Opcode::Sraw, + 0b11_0011_1000 => Opcode::Srawi, + 0b11_0101_0110 => Opcode::Eieio, + 0b11_1001_0110 => Opcode::Sthbrx, + 0b11_1001_1010 => Opcode::Extsh, + 0b11_1011_1010 => Opcode::Extsb, + 0b11_1101_0110 => Opcode::Icbi, + 0b11_1101_0111 => Opcode::Stfiwx, + 0b11_1111_0110 => Opcode::Dcbz, + _ => Opcode::Illegal, + }; + Ins::new(x, op) } fn disasm_basic3(x: u32) -> Self { - let mut ins = Ins::new(x); - let key = bits(x, 0..6); - ins.op = match key { + let op = match bits(x, 0..6) { 0b100000 => Opcode::Lwz, 0b100001 => Opcode::Lwzu, 0b100010 => Opcode::Lbz, @@ -1098,196 +374,78 @@ impl Ins { 0b110111 => Opcode::Stfdu, _ => disasm_unreachable!(x), }; - ins + Ins::new(x, op) } fn disasm_psq(x: u32) -> Self { - let mut ins = Ins::new(x); - let key = bits(x, 0..6); - ins.op = match key { + let op = match bits(x, 0..6) { 0b111000 => Opcode::PsqL, 0b111001 => Opcode::PsqLu, 0b111100 => Opcode::PsqSt, 0b111101 => Opcode::PsqStu, _ => disasm_unreachable!(x), }; - ins + Ins::new(x, op) } fn disasm_111011(x: u32) -> Self { - let mut ins = Ins::new(x); - let key = bits(x, 26..31); - match key { - 0b10010 => { - ins.op = Opcode::Fdivs; - if bits::(x, 21..26) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b10100 => { - ins.op = Opcode::Fsubs; - if bits::(x, 21..26) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b10101 => { - ins.op = Opcode::Fadds; - if bits::(x, 21..26) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b11000 => { - ins.op = Opcode::Fres; - if bits::(x, 16..26) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b11001 => { - ins.op = Opcode::Fmuls; - if bits::(x, 16..21) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b11100 => ins.op = Opcode::Fmsubs, - 0b11101 => ins.op = Opcode::Fmadds, - 0b11110 => ins.op = Opcode::Fnmsubs, - 0b11111 => ins.op = Opcode::Fnmadds, - _ => (), - } - ins + let op = match bits(x, 26..31) { + 0b10010 => Opcode::Fdivs, + 0b10100 => Opcode::Fsubs, + 0b10101 => Opcode::Fadds, + 0b11000 => Opcode::Fres, + 0b11001 => Opcode::Fmuls, + 0b11100 => Opcode::Fmsubs, + 0b11101 => Opcode::Fmadds, + 0b11110 => Opcode::Fnmsubs, + 0b11111 => Opcode::Fnmadds, + _ => Opcode::Illegal, + }; + Ins::new(x, op) } fn disasm_111111(x: u32) -> Self { - let mut ins = Ins::new(x); - let key = bits::(x, 26..31); - match key { + let op = match bits::(x, 26..31) { 0b00000 => match bits(x, 26..31) { - 0b00 => { - ins.op = Opcode::Fcmpu; - if !zero_bits(x, 9..11) || bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b01 => { - ins.op = Opcode::Fcmpo; - if !zero_bits(x, 9..11) || bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b10 => { - ins.op = Opcode::Mcrfs; - if !zero_bits(x, 9..11) || !zero_bits(x, 14..16) || bit(x, 31) != 0 { - ins.op = Opcode::Illegal; - } - } - _ => (), + 0b00 => Opcode::Fcmpu, + 0b01 => Opcode::Fcmpo, + 0b10 => Opcode::Mcrfs, + _ => Opcode::Illegal, + }, + 0b00110 => match bits(x, 26..31) { + 0b001 => Opcode::Mtfsb1, + 0b010 => Opcode::Mtfsb0, + 0b100 => Opcode::Mtfsfi, + _ => Opcode::Illegal, }, - 0b00110 => { - match bits(x, 26..31) { - 0b001 => { - ins.op = Opcode::Mtfsb1; - if bits::(x, 16..21) != 0 || bits::(x, 21..26) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b010 => { - ins.op = Opcode::Mtfsb0; - if bits::(x, 16..21) != 0 || bits::(x, 21..26) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b100 => { - ins.op = Opcode::Mtfsfi; - if !zero_bits(x, 9..16) || bit(x, 20) != 0 { - ins.op = Opcode::Illegal; - } - } - _ => (), - }; - } 0b00111 => match bits(x, 26..31) { - 0b10010 => { - ins.op = Opcode::Mffs; - if bits::(x, 16..21) != 0 || bits::(x, 21..26) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b10110 => { - ins.op = Opcode::Mtfsf; - if bit(x, 6) != 0 || bit(x, 16) != 0 { - ins.op = Opcode::Illegal; - } - } - _ => (), + 0b10010 => Opcode::Mffs, + 0b10110 => Opcode::Mtfsf, + _ => Opcode::Illegal, }, - 0b01000 => { - ins.op = match bits(x, 26..31) { - 0b0001 => Opcode::Fneg, - 0b0010 => Opcode::Fabs, - 0b0100 => Opcode::Fnabs, - 0b1000 => Opcode::Fmr, - _ => Opcode::Illegal, - }; - if bits::(x, 11..16) != 0 { - ins.op = Opcode::Illegal - } - } - 0b01100 => { - ins.op = Opcode::Frsp; - if bits::(x, 11..16) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b01110 => { - ins.op = Opcode::Fctiw; - if bits::(x, 11..16) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b01111 => { - ins.op = Opcode::Fctiwz; - if bits::(x, 11..16) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b10010 => { - ins.op = Opcode::Fdiv; - if bits::(x, 26..31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b10100 => { - ins.op = Opcode::Fsub; - if bits::(x, 26..31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b10101 => { - ins.op = Opcode::Fadd; - if bits::(x, 26..31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b10111 => ins.op = Opcode::Fsel, - 0b11001 => { - ins.op = Opcode::Fmul; - if bits::(x, 21..26) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b11010 => { - ins.op = Opcode::Frsqrte; - if bits::(x, 16..21) != 0 || bits::(x, 26..31) != 0 { - ins.op = Opcode::Illegal; - } - } - 0b11100 => ins.op = Opcode::Fmsub, - 0b11101 => ins.op = Opcode::Fmadd, - 0b11110 => ins.op = Opcode::Fnmsub, - 0b11111 => ins.op = Opcode::Fnmadd, - _ => (), - } - ins + 0b01000 => match bits(x, 26..31) { + 0b0001 => Opcode::Fneg, + 0b0010 => Opcode::Fabs, + 0b0100 => Opcode::Fnabs, + 0b1000 => Opcode::Fmr, + _ => Opcode::Illegal, + }, + 0b01100 => Opcode::Frsp, + 0b01110 => Opcode::Fctiw, + 0b01111 => Opcode::Fctiwz, + 0b10010 => Opcode::Fdiv, + 0b10100 => Opcode::Fsub, + 0b10101 => Opcode::Fadd, + 0b10111 => Opcode::Fsel, + 0b11001 => Opcode::Fmul, + 0b11010 => Opcode::Frsqrte, + 0b11100 => Opcode::Fmsub, + 0b11101 => Opcode::Fmadd, + 0b11110 => Opcode::Fnmsub, + 0b11111 => Opcode::Fnmadd, + _ => Opcode::Illegal, + }; + Ins::new(x, op) } fn write_string_form_reg123(&self, out: &mut W) -> std::io::Result<()> { diff --git a/macros/src/lib.rs b/macros/src/lib.rs index 890d2dc..525fab7 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -1,4 +1,4 @@ -use proc_macro::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree, Literal}; +use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; use std::iter::FromIterator; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; @@ -88,14 +88,22 @@ fn opcode_to_variant_name(opcode: &LitStr) -> syn::Result { } fn gen_is_valid_fn(tokens: &mut Vec, opcodes: &Opcodes) { - let header: TokenStream = "fn is_valid(&self, code: u32) -> bool".parse().unwrap(); + let header: TokenStream = "pub fn is_valid(self, code: u32) -> bool".parse().unwrap(); tokens.append(&mut header.into_iter().collect()); let mut parts = Vec::::new(); let match_header: TokenStream = "match self".parse().unwrap(); parts.append(&mut match_header.into_iter().collect()); let mut match_parts = Vec::::new(); + let illegal_match: TokenStream = "Opcode::Illegal => false,".parse().unwrap(); + match_parts.append(&mut illegal_match.into_iter().collect()); for opcode in &opcodes.opcodes { - match_parts.push(TokenTree::Ident(Ident::new(&opcode.variant_name, Span::call_site()))); + match_parts.push(TokenTree::Ident(Ident::new("Opcode", Span::call_site()))); + match_parts.push(TokenTree::Punct(Punct::new(':', Spacing::Joint))); + match_parts.push(TokenTree::Punct(Punct::new(':', Spacing::Alone))); + match_parts.push(TokenTree::Ident(Ident::new( + &opcode.variant_name, + Span::call_site(), + ))); match_parts.push(TokenTree::Punct(Punct::new('=', Spacing::Joint))); match_parts.push(TokenTree::Punct(Punct::new('>', Spacing::Alone))); match_parts.push(TokenTree::Ident(Ident::new("code", Span::call_site()))); @@ -106,15 +114,9 @@ fn gen_is_valid_fn(tokens: &mut Vec, opcodes: &Opcodes) { match_parts.push(TokenTree::Literal(Literal::u32_suffixed(opcode.bits))); match_parts.push(TokenTree::Punct(Punct::new(',', Spacing::Alone))); } - let match_body = Group::new( - Delimiter::Brace, - TokenStream::from_iter(match_parts), - ); + let match_body = Group::new(Delimiter::Brace, TokenStream::from_iter(match_parts)); parts.push(TokenTree::Group(match_body)); - let body = Group::new( - Delimiter::Brace, - TokenStream::from_iter(parts), - ); + let body = Group::new(Delimiter::Brace, TokenStream::from_iter(parts)); tokens.push(TokenTree::Group(body)); }