diff --git a/Cargo.lock b/Cargo.lock index 57e14bf..91a54df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,15 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "ansi_term" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -dependencies = [ - "winapi", -] - [[package]] name = "atty" version = "0.2.14" @@ -24,9 +15,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "bincode" @@ -51,24 +42,24 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "2.33.3" +version = "3.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +checksum = "71c47df61d9e16dc010b55dba1952a57d8c215dbb533fd13cdd13369aac73b1c" dependencies = [ - "ansi_term", "atty", "bitflags", + "indexmap", + "os_str_bytes", "strsim", + "termcolor", "textwrap", - "unicode-width", - "vec_map", ] [[package]] name = "ctor" -version = "0.1.20" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e98e2ad1a782e33928b96fc3948e7c355e5af34ba4de7670fe8bac2a3b2006d" +checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c" dependencies = [ "quote", "syn", @@ -91,15 +82,15 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "fixedbitset" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "398ea4fabe40b9b0d885340a2a991a44c8a645624075ad966d21f88688e2b69e" +checksum = "279fb028e20b3c4c320317955b77c5e0c9701f05a1d309905d6fc702cdc5053e" [[package]] name = "getrandom" -version = "0.1.16" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" dependencies = [ "cfg-if", "libc", @@ -134,9 +125,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" +checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" dependencies = [ "autocfg", "hashbrown", @@ -144,82 +135,69 @@ dependencies = [ [[package]] name = "indoc" -version = "0.3.6" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47741a8bc60fb26eb8d6e0238bbb26d8575ff623fdc97b1a2c00c050b9684ed8" +checksum = "e7906a9fababaeacb774f72410e497a1d18de916322e33797bb2cd29baa23c9e" dependencies = [ - "indoc-impl", - "proc-macro-hack", -] - -[[package]] -name = "indoc-impl" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce046d161f000fffde5f432a0d034d0341dc152643b2598ed5bfce44c4f3a8f0" -dependencies = [ - "proc-macro-hack", - "proc-macro2", - "quote", - "syn", "unindent", ] [[package]] name = "instant" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ "cfg-if", ] [[package]] name = "inventory" -version = "0.1.10" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f0f7efb804ec95e33db9ad49e4252f049e37e8b0a4652e3cd61f7999f2eff7f" +checksum = "ce6b5d8c669bfbad811d95ddd7a1c6cf9cfdbf2777e59928b6f3fa8ff54f72a0" dependencies = [ "ctor", "ghost", - "inventory-impl", -] - -[[package]] -name = "inventory-impl" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75c094e94816723ab936484666968f5b58060492e880f3c8d00489a1e244fa51" -dependencies = [ - "proc-macro2", - "quote", - "syn", ] [[package]] name = "itertools" -version = "0.10.1" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" dependencies = [ "either", ] [[package]] name = "libc" -version = "0.2.99" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765" +checksum = "ec647867e2bf0772e28c8bcde4f0d19a9216916e890543b5a03ed8ef27b8f259" + +[[package]] +name = "linked-hash-map" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" [[package]] name = "lock_api" -version = "0.4.4" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb" +checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" dependencies = [ + "autocfg", "scopeguard", ] +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + [[package]] name = "num-traits" version = "0.2.14" @@ -231,9 +209,9 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ "hermit-abi", "libc", @@ -241,15 +219,24 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" +checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" + +[[package]] +name = "os_str_bytes" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" +dependencies = [ + "memchr", +] [[package]] name = "parking_lot" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", @@ -258,9 +245,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" dependencies = [ "cfg-if", "instant", @@ -272,32 +259,13 @@ dependencies = [ [[package]] name = "parse_int" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15f96500577cfa0a3bad8a88a3c4daa66684828af2e7d349012fa7fc3c725f0c" +checksum = "2d695b79916a2c08bcff7be7647ab60d1402885265005a6658ffe6d763553c5a" dependencies = [ "num-traits", ] -[[package]] -name = "paste" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880" -dependencies = [ - "paste-impl", - "proc-macro-hack", -] - -[[package]] -name = "paste-impl" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6" -dependencies = [ - "proc-macro-hack", -] - [[package]] name = "petgraph" version = "0.6.0" @@ -310,15 +278,15 @@ dependencies = [ [[package]] name = "ppc750cl" -version = "0.1.1" +version = "0.2.0" dependencies = [ "num-traits", - "ppc750cl-macros", + "serde", ] [[package]] name = "ppc750cl-flow-graph" -version = "0.1.1" +version = "0.2.0" dependencies = [ "clap", "dol", @@ -330,24 +298,27 @@ dependencies = [ [[package]] name = "ppc750cl-fuzz" -version = "0.1.1" +version = "0.2.0" dependencies = [ "num_cpus", "ppc750cl", ] [[package]] -name = "ppc750cl-macros" -version = "0.1.1" +name = "ppc750cl-genisa" +version = "0.2.0" dependencies = [ + "itertools", "proc-macro2", "quote", + "serde", + "serde_yaml", "syn", ] [[package]] name = "ppc750cl-py" -version = "0.1.1" +version = "0.2.0" dependencies = [ "ppc750cl", "pyo3", @@ -355,7 +326,7 @@ dependencies = [ [[package]] name = "ppc750cl-rand" -version = "0.1.1" +version = "0.2.0" dependencies = [ "ppc750cl", "rand_core", @@ -364,57 +335,63 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.10" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" - -[[package]] -name = "proc-macro-hack" -version = "0.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "proc-macro2" -version = "1.0.28" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612" +checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" dependencies = [ "unicode-xid", ] [[package]] name = "pyo3" -version = "0.14.2" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af205762ba65eec9f27a2fa1a57a40644e8e3368784b8c8b2f2de48f6e8ddd96" +checksum = "6b3e99c4c3e790e4fc365b42b70c1f7801f42eadc4ea648fa327e6f5ca29f215" dependencies = [ "cfg-if", "indoc", "inventory", "libc", "parking_lot", - "paste", "pyo3-build-config", + "pyo3-ffi", "pyo3-macros", "unindent", ] [[package]] name = "pyo3-build-config" -version = "0.14.2" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "755944027ce803c7238e59c5a18e59c1d0a4553db50b23e9ba209a568353028d" +checksum = "2486b96281859ff0a3929ba6467b13751627b974f7137362db38e2bed14b2094" dependencies = [ "once_cell", + "target-lexicon", +] + +[[package]] +name = "pyo3-ffi" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd9de1d94557751599f8bd321f10e6c1ef2801067acb58c91138deef2ae83a17" +dependencies = [ + "libc", + "pyo3-build-config", ] [[package]] name = "pyo3-macros" -version = "0.14.2" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd31b36bccfd902c78804bd96c28ea93eac6fa0ca311f9d21ef2230b6665b29a" +checksum = "0b9584049129b1cfb615243391a6345c726690271ae195ffd6aa3766177296aa" dependencies = [ + "proc-macro2", "pyo3-macros-backend", "quote", "syn", @@ -422,43 +399,40 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.14.2" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c21c59ba36db9c823e931c662766b0dd01a030b1d96585b67d8857a96a56b972" +checksum = "b6c4717e6a55c51a9958eda1f5481ff7f62cccd21f45309c10e4731cb7198dbc" dependencies = [ "proc-macro2", - "pyo3-build-config", "quote", "syn", ] [[package]] name = "quote" -version = "1.0.9" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58" dependencies = [ "proc-macro2", ] [[package]] name = "rand" -version = "0.7.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "getrandom", "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] name = "rand_chacha" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", "rand_core", @@ -466,31 +440,28 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.5.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core", -] - [[package]] name = "redox_syscall" -version = "0.2.10" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" dependencies = [ "bitflags", ] +[[package]] +name = "ryu" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" + [[package]] name = "scopeguard" version = "1.1.0" @@ -499,18 +470,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "serde" -version = "1.0.128" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1056a0db1978e9dbf0f6e4fca677f6f9143dc1c19de346f22cac23e422196834" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.128" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13af2fbb8b60a8950d6c72a56d2095c28870367cc8e10c55e9745bac4995a2c4" +checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" dependencies = [ "proc-macro2", "quote", @@ -518,10 +489,22 @@ dependencies = [ ] [[package]] -name = "sfmt" -version = "0.6.0" +name = "serde_yaml" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "269239cd28e19133d5dc0179d060b00b0b95ce1224792ea5b7c075241d4ee309" +checksum = "a4a521f2940385c165a24ee286aa8599633d162077a54bdcae2a6fd5a7bfa7a0" +dependencies = [ + "indexmap", + "ryu", + "serde", + "yaml-rust", +] + +[[package]] +name = "sfmt" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e389a3c1536438f85612667cd992dfb7169f60784252342278458e90d37c7565" dependencies = [ "rand", "rand_core", @@ -529,21 +512,21 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" [[package]] name = "strsim" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.74" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c" +checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d" dependencies = [ "proc-macro2", "quote", @@ -551,40 +534,46 @@ dependencies = [ ] [[package]] -name = "textwrap" -version = "0.11.0" +name = "target-lexicon" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +checksum = "d7fa7e55043acb85fca6b3c01485a2eeb6b69c5d21002e273c79e465f43b7ac1" + +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ - "unicode-width", + "winapi-util", ] [[package]] -name = "thiserror" -version = "1.0.26" +name = "textwrap" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" + +[[package]] +name = "thiserror" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.26" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" dependencies = [ "proc-macro2", "quote", "syn", ] -[[package]] -name = "unicode-width" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" - [[package]] name = "unicode-xid" version = "0.2.2" @@ -593,21 +582,15 @@ checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" [[package]] name = "unindent" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f14ee04d9415b52b3aeab06258a3f07093182b88ba0f9b8d203f211a7a7d41c7" - -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +checksum = "514672a55d7380da379785a4d70ca8386c8883ff7eaae877be4d2081cebe73d8" [[package]] name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" +version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "winapi" @@ -625,8 +608,26 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] diff --git a/Cargo.toml b/Cargo.toml index f70da3f..71aa117 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,8 +3,8 @@ members = [ "disasm", "disasm-py", "dol", - "macros", "fuzz", + "genisa", "flow-graph", "rand", ] diff --git a/README.md b/README.md index 92a2819..f406afa 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,15 @@ Rust tools for working with the PowerPC 750CL family of processors. -### Python module +### Rust crates -Build instructions: +```shell +rustup components add rustfmt +cargo run --package ppc750cl-genisa +cargo build --release +``` + +### Python module ```shell python -m venv env @@ -12,3 +18,21 @@ source ./env/bin/activate pip install maturin maturin build -m ./disasm-py/Cargo.toml ``` + +### Instruction Set + +For those unfamiliar with PowerPC, here are some basics. +- PowerPC 7xx is a family of RISC CPUs produced from 1997 to 2012. + - They operate with 32-bit words and every instruction is 32-bits wide. +- This project focuses (only) on compatibility with the PowerPC 750CL. + - This chip is famously packaged as codename "Broadway" for the Nintendo Wii. + - Its predecessor PowerPC 750CXe is used in the Nintendo GameCube. + - It adds a "paired-singles" SIMD unit and a bunch of other instructions. + +### isa.yaml + +The file [isa.yaml](./isa.yaml) contains a full definition of the PowerPC 750CL instruction set. + +It powers the disassembler, assembler, and Rust/Python bindings code analysis tools. + +Similarly to LLVM TableGen, the program `ppc750cl-genisa` generates a Rust file implementing an instruction decoder. diff --git a/codegen/.gitignore b/codegen/.gitignore deleted file mode 100644 index f4e465b..0000000 --- a/codegen/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -masks.txt -__pycache__ diff --git a/codegen/gen_masks.py b/codegen/gen_masks.py deleted file mode 100644 index 5ffa043..0000000 --- a/codegen/gen_masks.py +++ /dev/null @@ -1,38 +0,0 @@ -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( - "../disasm/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 deleted file mode 100644 index 07b5e3e..0000000 --- a/codegen/patterns.txt +++ /dev/null @@ -1,222 +0,0 @@ -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/disasm-py/Cargo.toml b/disasm-py/Cargo.toml index 08b4a9d..a924bc7 100644 --- a/disasm-py/Cargo.toml +++ b/disasm-py/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "ppc750cl-py" -version = "0.1.1" -edition = "2018" +version = "0.2.0" +edition = "2021" authors = ["Richard Patel "] license = "GPL-3.0-or-later" description = "Python bindings for PowerPC 750CL Disassembler" @@ -16,5 +16,5 @@ extension-module = ["pyo3/extension-module"] default = ["extension-module"] [dependencies] -pyo3 = { version = "0.14", features = ["multiple-pymethods"] } -ppc750cl = { version = "0.1.1", path = "../disasm" } +pyo3 = { version = "0.16", features = ["multiple-pymethods"] } +ppc750cl = { version = "0.2.0", path = "../disasm" } diff --git a/disasm-py/src/lib.rs b/disasm-py/src/lib.rs index 5db763c..0288041 100644 --- a/disasm-py/src/lib.rs +++ b/disasm-py/src/lib.rs @@ -1,34 +1,11 @@ use pyo3::prelude::*; use pyo3::types::PyBytes; -use pyo3::{PyIterProtocol, PyObjectProtocol}; + +use ppc750cl::formatter::FormattedIns; #[pyclass] struct Ins(ppc750cl::Ins); -macro_rules! ins_ufield { - ($name:ident) => { - #[pymethods] - impl Ins { - #[getter] - fn $name(&self) -> PyResult { - Ok(self.0.$name() as u32) - } - } - }; -} - -macro_rules! ins_ifield { - ($name:ident) => { - #[pymethods] - impl Ins { - #[getter] - fn $name(&self) -> PyResult { - Ok(self.0.$name() as i32) - } - } - }; -} - #[pymethods] impl Ins { #[new] @@ -45,41 +22,11 @@ impl Ins { fn addr(&self) -> PyResult { Ok(self.0.addr) } -} -ins_ufield!(rc); -ins_ufield!(aa); -ins_ufield!(lk); -ins_ufield!(l); -ins_ufield!(oe); -ins_ufield!(w); -ins_ufield!(s); -ins_ufield!(d); -ins_ufield!(a); -ins_ufield!(b); -ins_ufield!(c); -ins_ufield!(crb_d); -ins_ufield!(crb_a); -ins_ufield!(crb_b); -ins_ufield!(crm); -ins_ufield!(sr); -ins_ufield!(spr); -ins_ufield!(fm); -ins_ufield!(crf_d); -ins_ufield!(crf_s); -ins_ifield!(simm); -ins_ufield!(uimm); -ins_ufield!(bo); -ins_ufield!(bi); -ins_ufield!(sh); -ins_ufield!(mb); -ins_ufield!(me); -ins_ufield!(me_31sub); -ins_ifield!(bd); -ins_ifield!(li); -ins_ufield!(to); -ins_ufield!(ps_l); -ins_ifield!(ps_d); + fn __str__(&self) -> String { + FormattedIns(self.0.clone()).to_string() + } +} impl From for Ins { fn from(ins: ppc750cl::Ins) -> Self { @@ -87,13 +34,6 @@ impl From for Ins { } } -#[pyproto] -impl<'a> PyObjectProtocol<'a> for Ins { - fn __str__(&self) -> String { - self.0.to_string() - } -} - #[pyclass] struct DisasmIterator { bytes: Py, @@ -102,8 +42,8 @@ struct DisasmIterator { left: usize, } -#[pyproto] -impl PyIterProtocol for DisasmIterator { +#[pymethods] +impl DisasmIterator { fn __iter__(slf: PyRef) -> PyRef { slf } diff --git a/disasm/Cargo.toml b/disasm/Cargo.toml index 1f139ba..a8030fa 100644 --- a/disasm/Cargo.toml +++ b/disasm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "ppc750cl" -version = "0.1.1" -edition = "2018" +version = "0.2.0" +edition = "2021" authors = ["Richard Patel "] license = "GPL-3.0-or-later" description = "Disassembler for PowerPC 750CL" @@ -9,5 +9,5 @@ keywords = ["powerpc", "wii", "gamecube"] repository = "https://github.com/terorie/ppc750cl" [dependencies] -num-traits = "0.2.14" -ppc750cl-macros = { path = "../macros", version = "0.1.1" } +num-traits = "0.2" +serde = "1.0" diff --git a/disasm/src/formatter.rs b/disasm/src/formatter.rs index 3456c46..3e2ca3c 100644 --- a/disasm/src/formatter.rs +++ b/disasm/src/formatter.rs @@ -1,251 +1,33 @@ -use std::fmt::{Display, LowerHex, UpperHex}; -use std::io::Write; +use std::fmt::{Display, Formatter}; -use num_traits::PrimInt; +use crate::prelude::*; -use crate::Ins; +pub struct FormattedIns(pub Ins); -type IOResult = std::io::Result<()>; - -pub trait AsmFormatter -where - W: Write, -{ - /// Returns the underlying writer. - fn writer(&mut self) -> &mut W; - - /// Callback for custom styling before writing an instruction. - fn before_instruction(&mut self, _: &Ins) -> IOResult { - Ok(()) - } - /// Callback for custom styling after writing an instruction. - fn after_instruction(&mut self, _: &Ins) -> IOResult { - Ok(()) - } - - /// Writes the instruction mnemonic. - fn write_mnemonic(&mut self, name: &str) -> IOResult { - write!(self.writer(), "{}", name) - } - - /// Separates the instruction mnemonic and arguments. - fn write_opcode_separator(&mut self) -> IOResult { - write!(self.writer(), " ") - } - - /// Separates two instruction arguments (e.g. registers). - fn write_operand_separator(&mut self) -> IOResult { - write!(self.writer(), ", ") - } - - /// Writes a general-purpose register argument. - fn write_gpr(&mut self, reg: u8) -> IOResult { - write!(self.writer(), "r{}", reg) - } - - /// Writes a nullable general-purpose register argument. - fn write_gpr0(&mut self, reg: u8) -> IOResult { - if reg != 0 { - self.write_gpr(reg) - } else { - write!(self.writer(), "0") - } - } - - /// Writes a floating point register argument. - fn write_fpr(&mut self, reg: u8) -> IOResult { - write!(self.writer(), "f{}", reg) - } - - /// Writes a condition register argument. - fn write_cr(&mut self, reg: u8) -> IOResult { - write!(self.writer(), "cr{}", reg) - } - - /// Writes a paired-singles quantization register argument. - fn write_qr(&mut self, reg: u8) -> IOResult { - write!(self.writer(), "qr{}", reg) - } - - fn write_sr(&mut self, reg: u8) -> IOResult { - write!(self.writer(), "{}", reg) - } - - /// Sets the mnemonic 'o' suffix. - fn write_oe(&mut self, oe: u8) -> IOResult { - if oe != 0 { - write!(self.writer(), "o")?; +impl Display for FormattedIns { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let simple = self.0.clone().simplified(); + write!(f, "{}{}", simple.mnemonic, simple.ins.suffix())?; + let mut writing_offset = false; + for (i, arg) in simple.args.iter().enumerate() { + if i == 0 { + write!(f, " ")?; + } + if i > 0 && !writing_offset { + write!(f, ", ")?; + } + if let Argument::Offset(val) = arg { + write!(f, "{}(", val)?; + writing_offset = true; + continue; + } else { + write!(f, "{}", arg)?; + } + if writing_offset { + write!(f, ")")?; + writing_offset = false; + } } Ok(()) } - - /// Sets the mnemonic 'a' suffix. - fn write_aa(&mut self, aa: u8) -> IOResult { - if aa != 0 { - write!(self.writer(), "a")?; - } - Ok(()) - } - - /// Sets the mnemonic 'l' suffix. - fn write_lk(&mut self, lk: u8) -> IOResult { - if lk != 0 { - write!(self.writer(), "l")?; - } - Ok(()) - } - - /// Sets the mnemonic '.' suffix. - fn write_rc(&mut self, rc: u8) -> IOResult { - if rc != 0 { - write!(self.writer(), ".")?; - } - Ok(()) - } - - /// Writes an unsigned immediate. - fn write_uimm>(&mut self, uimm: T) -> IOResult { - let uimm = uimm.into(); - if uimm < 16 { - write!(self.writer(), "{}", uimm) - } else { - write!(self.writer(), "{:#x}", uimm) - } - } - - /// Writes a signed immediate. - fn write_simm + Display>(&mut self, simm: T) -> IOResult { - let simm: i32 = simm.into(); - if simm < 8 { - write!(self.writer(), "{}", simm) - } else { - write!(self.writer(), "{:#x}", ReallySigned(simm)) - } - } - - /// Writes an instruction-specific field like the compare mode. - fn write_mode(&mut self, mode: P) -> IOResult { - write!(self.writer(), "{}", mode) - } - - fn write_fm(&mut self, fm: u16) -> IOResult { - write!(self.writer(), "{}", fm) - } - - fn write_offset_unsigned_open>(&mut self, offset: T) -> IOResult { - let offset = offset.into(); - if offset < 15 { - write!(self.writer(), "{}(", offset) - } else { - write!(self.writer(), "{:#x}(", offset) - } - } - - /// Writes an offset prefix. - /// - /// The next write calls that follow should be: - /// - An operand (almost always a general-purpose register) - /// - `write_offset_close()` - fn write_offset_open>(&mut self, offset: T) -> IOResult { - let offset = offset.into(); - if -9 < offset && offset < 10 { - write!(self.writer(), "{}(", offset) - } else { - write!(self.writer(), "{:#x}(", ReallySigned(offset)) - } - } - - /// Closes an offset prefix. - fn write_offset_close(&mut self) -> IOResult { - write!(self.writer(), ")") - } - - /// Writes a branch target given the jump offset and current program counter. - fn write_branch_target(&mut self, offset: i32, _: u32) -> IOResult { - write!(self.writer(), "{:#x}", ReallySigned(offset)) - } -} - -pub struct SimpleFormatter { - pub writer: W, -} - -impl SimpleFormatter { - pub fn new(writer: W) -> Self { - Self { writer } - } -} - -impl AsmFormatter for SimpleFormatter { - fn writer(&mut self) -> &mut W { - &mut self.writer - } -} - -pub struct DoldecompFormatter { - pub writer: W, -} - -impl DoldecompFormatter { - pub fn new(writer: W) -> Self { - Self { writer } - } -} - -impl AsmFormatter for DoldecompFormatter { - fn writer(&mut self) -> &mut W { - &mut self.writer - } - - fn before_instruction(&mut self, ins: &Ins) -> IOResult { - write!( - &mut self.writer, - "/* {:0>8X} {:0>2X} {:0>2X} {:0>2X} {:0>2X} */\t", - ins.addr, - (ins.code >> 24) as u8, - (ins.code >> 16) as u8, - (ins.code >> 8) as u8, - ins.code as u8 - ) - } -} - -// https://stackoverflow.com/questions/44711012/how-do-i-format-a-signed-integer-to-a-sign-aware-hexadecimal-representation -struct ReallySigned(N); - -impl LowerHex for ReallySigned { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - let num = self.0.to_i32().unwrap(); - let prefix = if f.alternate() { "0x" } else { "" }; - let bare_hex = format!("{:x}", num.abs()); - f.pad_integral(num >= 0, prefix, &bare_hex) - } -} - -impl UpperHex for ReallySigned { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - let num = self.0.to_i32().unwrap(); - let prefix = if f.alternate() { "0x" } else { "" }; - let bare_hex = format!("{:X}", num.abs()); - f.pad_integral(num >= 0, prefix, &bare_hex) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_doldecomp_formatter() { - let buf = Vec::::new(); - let mut formatter = DoldecompFormatter::new(buf); - - let ins = Ins::new(0x48000007, 6); - ins.write_string(&mut formatter).unwrap(); - - assert_eq!( - String::from_utf8(formatter.writer).unwrap(), - "/* 00000006 48 00 00 07 */\tbla 0x4" - ); - } } diff --git a/disasm/src/generated.rs b/disasm/src/generated.rs new file mode 100644 index 0000000..f4e7393 --- /dev/null +++ b/disasm/src/generated.rs @@ -0,0 +1,5855 @@ +use crate::prelude::*; +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub enum Opcode { + Illegal = -1, + Add, + Addc, + Adde, + Addi, + Addic, + Addic_, + Addis, + Addme, + Addze, + And, + Andc, + Andi_, + Andis_, + B, + Bc, + Bcctr, + Bclr, + Cmp, + Cmpi, + Cmpl, + Cmpli, + Cntlzw, + Crand, + Crandc, + Creqv, + Crnand, + Crnor, + Cror, + Crorc, + Crxor, + Dcbf, + Dcbi, + Dcbst, + Dcbt, + Dcbtst, + Dcbz, + DcbzL, + Divw, + Divwu, + Eciwx, + Ecowx, + Eieio, + Eqv, + Extsb, + Extsh, + Fabs, + Fadd, + Fadds, + Fcmpo, + Fcmpu, + Fctiw, + Fctiwz, + Fdiv, + Fdivs, + Fmadd, + Fmadds, + Fmr, + Fmsub, + Fmsubs, + Fmul, + Fmuls, + Fnabs, + Fneg, + Fnmadd, + Fnmadds, + Fnmsub, + Fnmsubs, + Fres, + Frsp, + Frsqrte, + Fsel, + Fsub, + Fsubs, + Icbi, + Isync, + Lbz, + Lbzu, + Lbzux, + Lbzx, + Lfd, + Lfdu, + Lfdux, + Lfdx, + Lfs, + Lfsu, + Lfsux, + Lfsx, + Lha, + Lhau, + Lhaux, + Lhax, + Lhbrx, + Lhz, + Lhzu, + Lhzux, + Lhzx, + Lmw, + Lswi, + Lswx, + Lwarx, + Lwbrx, + Lwz, + Lwzu, + Lwzux, + Lwzx, + Mcrf, + Mcrfs, + Mcrxr, + Mfcr, + Mffs, + Mfmsr, + Mfspr, + Mfsr, + Mfsrin, + Mftb, + Mtcrf, + Mtfsb0, + Mtfsb1, + Mtfsf, + Mtfsfi, + Mtmsr, + Mtspr, + Mtsr, + Mtsrin, + Mulhw, + Mulhwu, + Mulli, + Mullw, + Nand, + Neg, + Nor, + Or, + Orc, + Ori, + Oris, + PsqL, + PsqLu, + PsqLux, + PsqLx, + PsqSt, + PsqStu, + PsqStux, + PsqStx, + PsAbs, + PsAdd, + PsCmpo0, + PsCmpo1, + PsCmpu0, + PsCmpu1, + PsDiv, + PsMadd, + PsMadds0, + PsMadds1, + PsMerge00, + PsMerge01, + PsMerge10, + PsMerge11, + PsMr, + PsMsub, + PsMul, + PsMuls0, + PsMuls1, + PsNabs, + PsNeg, + PsNmadd, + PsNmsub, + PsRes, + PsRsqrte, + PsSel, + PsSub, + PsSum0, + PsSum1, + Rfi, + Rlwimi, + Rlwinm, + Rlwnm, + Sc, + Slw, + Sraw, + Srawi, + Srw, + Stb, + Stbu, + Stbux, + Stbx, + Stfd, + Stfdu, + Stfdux, + Stfdx, + Stfiwx, + Stfs, + Stfsu, + Stfsux, + Stfsx, + Sth, + Sthbrx, + Sthu, + Sthux, + Sthx, + Stmw, + Stswi, + Stswx, + Stw, + Stwbrx, + Stwcx_, + Stwu, + Stwux, + Stwx, + Subf, + Subfc, + Subfe, + Subfic, + Subfme, + Subfze, + Sync, + Tlbie, + Tlbsync, + Tw, + Twi, + Xor, + Xori, + Xoris, +} +#[allow(clippy::all)] +impl Opcode { + pub(crate) fn _mnemonic(self) -> &'static str { + match self { + Opcode::Illegal => "", + Opcode::Add => "add", + Opcode::Addc => "addc", + Opcode::Adde => "adde", + Opcode::Addi => "addi", + Opcode::Addic => "addic", + Opcode::Addic_ => "addic.", + Opcode::Addis => "addis", + Opcode::Addme => "addme", + Opcode::Addze => "addze", + Opcode::And => "and", + Opcode::Andc => "andc", + Opcode::Andi_ => "andi.", + Opcode::Andis_ => "andis.", + Opcode::B => "b", + Opcode::Bc => "bc", + Opcode::Bcctr => "bcctr", + Opcode::Bclr => "bclr", + Opcode::Cmp => "cmp", + Opcode::Cmpi => "cmpi", + Opcode::Cmpl => "cmpl", + Opcode::Cmpli => "cmpli", + Opcode::Cntlzw => "cntlzw", + Opcode::Crand => "crand", + Opcode::Crandc => "crandc", + Opcode::Creqv => "creqv", + Opcode::Crnand => "crnand", + Opcode::Crnor => "crnor", + Opcode::Cror => "cror", + Opcode::Crorc => "crorc", + Opcode::Crxor => "crxor", + Opcode::Dcbf => "dcbf", + Opcode::Dcbi => "dcbi", + Opcode::Dcbst => "dcbst", + Opcode::Dcbt => "dcbt", + Opcode::Dcbtst => "dcbtst", + Opcode::Dcbz => "dcbz", + Opcode::DcbzL => "dcbz_l", + Opcode::Divw => "divw", + Opcode::Divwu => "divwu", + Opcode::Eciwx => "eciwx", + Opcode::Ecowx => "ecowx", + Opcode::Eieio => "eieio", + Opcode::Eqv => "eqv", + Opcode::Extsb => "extsb", + Opcode::Extsh => "extsh", + Opcode::Fabs => "fabs", + Opcode::Fadd => "fadd", + Opcode::Fadds => "fadds", + Opcode::Fcmpo => "fcmpo", + Opcode::Fcmpu => "fcmpu", + Opcode::Fctiw => "fctiw", + Opcode::Fctiwz => "fctiwz", + Opcode::Fdiv => "fdiv", + Opcode::Fdivs => "fdivs", + Opcode::Fmadd => "fmadd", + Opcode::Fmadds => "fmadds", + Opcode::Fmr => "fmr", + Opcode::Fmsub => "fmsub", + Opcode::Fmsubs => "fmsubs", + Opcode::Fmul => "fmul", + Opcode::Fmuls => "fmuls", + Opcode::Fnabs => "fnabs", + Opcode::Fneg => "fneg", + Opcode::Fnmadd => "fnmadd", + Opcode::Fnmadds => "fnmadds", + Opcode::Fnmsub => "fnmsub", + Opcode::Fnmsubs => "fnmsubs", + Opcode::Fres => "fres", + Opcode::Frsp => "frsp", + Opcode::Frsqrte => "frsqrte", + Opcode::Fsel => "fsel", + Opcode::Fsub => "fsub", + Opcode::Fsubs => "fsubs", + Opcode::Icbi => "icbi", + Opcode::Isync => "isync", + Opcode::Lbz => "lbz", + Opcode::Lbzu => "lbzu", + Opcode::Lbzux => "lbzux", + Opcode::Lbzx => "lbzx", + Opcode::Lfd => "lfd", + Opcode::Lfdu => "lfdu", + Opcode::Lfdux => "lfdux", + Opcode::Lfdx => "lfdx", + Opcode::Lfs => "lfs", + Opcode::Lfsu => "lfsu", + Opcode::Lfsux => "lfsux", + Opcode::Lfsx => "lfsx", + Opcode::Lha => "lha", + Opcode::Lhau => "lhau", + Opcode::Lhaux => "lhaux", + Opcode::Lhax => "lhax", + Opcode::Lhbrx => "lhbrx", + Opcode::Lhz => "lhz", + Opcode::Lhzu => "lhzu", + Opcode::Lhzux => "lhzux", + Opcode::Lhzx => "lhzx", + Opcode::Lmw => "lmw", + Opcode::Lswi => "lswi", + Opcode::Lswx => "lswx", + Opcode::Lwarx => "lwarx", + Opcode::Lwbrx => "lwbrx", + Opcode::Lwz => "lwz", + Opcode::Lwzu => "lwzu", + Opcode::Lwzux => "lwzux", + Opcode::Lwzx => "lwzx", + Opcode::Mcrf => "mcrf", + Opcode::Mcrfs => "mcrfs", + Opcode::Mcrxr => "mcrxr", + Opcode::Mfcr => "mfcr", + Opcode::Mffs => "mffs", + Opcode::Mfmsr => "mfmsr", + Opcode::Mfspr => "mfspr", + Opcode::Mfsr => "mfsr", + Opcode::Mfsrin => "mfsrin", + Opcode::Mftb => "mftb", + Opcode::Mtcrf => "mtcrf", + Opcode::Mtfsb0 => "mtfsb0", + Opcode::Mtfsb1 => "mtfsb1", + Opcode::Mtfsf => "mtfsf", + Opcode::Mtfsfi => "mtfsfi", + Opcode::Mtmsr => "mtmsr", + Opcode::Mtspr => "mtspr", + Opcode::Mtsr => "mtsr", + Opcode::Mtsrin => "mtsrin", + Opcode::Mulhw => "mulhw", + Opcode::Mulhwu => "mulhwu", + Opcode::Mulli => "mulli", + Opcode::Mullw => "mullw", + Opcode::Nand => "nand", + Opcode::Neg => "neg", + Opcode::Nor => "nor", + Opcode::Or => "or", + Opcode::Orc => "orc", + Opcode::Ori => "ori", + Opcode::Oris => "oris", + Opcode::PsqL => "psq_l", + Opcode::PsqLu => "psq_lu", + Opcode::PsqLux => "psq_lux", + Opcode::PsqLx => "psq_lx", + Opcode::PsqSt => "psq_st", + Opcode::PsqStu => "psq_stu", + Opcode::PsqStux => "psq_stux", + Opcode::PsqStx => "psq_stx", + Opcode::PsAbs => "ps_abs", + Opcode::PsAdd => "ps_add", + Opcode::PsCmpo0 => "ps_cmpo0", + Opcode::PsCmpo1 => "ps_cmpo1", + Opcode::PsCmpu0 => "ps_cmpu0", + Opcode::PsCmpu1 => "ps_cmpu1", + Opcode::PsDiv => "ps_div", + Opcode::PsMadd => "ps_madd", + Opcode::PsMadds0 => "ps_madds0", + Opcode::PsMadds1 => "ps_madds1", + Opcode::PsMerge00 => "ps_merge00", + Opcode::PsMerge01 => "ps_merge01", + Opcode::PsMerge10 => "ps_merge10", + Opcode::PsMerge11 => "ps_merge11", + Opcode::PsMr => "ps_mr", + Opcode::PsMsub => "ps_msub", + Opcode::PsMul => "ps_mul", + Opcode::PsMuls0 => "ps_muls0", + Opcode::PsMuls1 => "ps_muls1", + Opcode::PsNabs => "ps_nabs", + Opcode::PsNeg => "ps_neg", + Opcode::PsNmadd => "ps_nmadd", + Opcode::PsNmsub => "ps_nmsub", + Opcode::PsRes => "ps_res", + Opcode::PsRsqrte => "ps_rsqrte", + Opcode::PsSel => "ps_sel", + Opcode::PsSub => "ps_sub", + Opcode::PsSum0 => "ps_sum0", + Opcode::PsSum1 => "ps_sum1", + Opcode::Rfi => "rfi", + Opcode::Rlwimi => "rlwimi", + Opcode::Rlwinm => "rlwinm", + Opcode::Rlwnm => "rlwnm", + Opcode::Sc => "sc", + Opcode::Slw => "slw", + Opcode::Sraw => "sraw", + Opcode::Srawi => "srawi", + Opcode::Srw => "srw", + Opcode::Stb => "stb", + Opcode::Stbu => "stbu", + Opcode::Stbux => "stbux", + Opcode::Stbx => "stbx", + Opcode::Stfd => "stfd", + Opcode::Stfdu => "stfdu", + Opcode::Stfdux => "stfdux", + Opcode::Stfdx => "stfdx", + Opcode::Stfiwx => "stfiwx", + Opcode::Stfs => "stfs", + Opcode::Stfsu => "stfsu", + Opcode::Stfsux => "stfsux", + Opcode::Stfsx => "stfsx", + Opcode::Sth => "sth", + Opcode::Sthbrx => "sthbrx", + Opcode::Sthu => "sthu", + Opcode::Sthux => "sthux", + Opcode::Sthx => "sthx", + Opcode::Stmw => "stmw", + Opcode::Stswi => "stswi", + Opcode::Stswx => "stswx", + Opcode::Stw => "stw", + Opcode::Stwbrx => "stwbrx", + Opcode::Stwcx_ => "stwcx.", + Opcode::Stwu => "stwu", + Opcode::Stwux => "stwux", + Opcode::Stwx => "stwx", + Opcode::Subf => "subf", + Opcode::Subfc => "subfc", + Opcode::Subfe => "subfe", + Opcode::Subfic => "subfic", + Opcode::Subfme => "subfme", + Opcode::Subfze => "subfze", + Opcode::Sync => "sync", + Opcode::Tlbie => "tlbie", + Opcode::Tlbsync => "tlbsync", + Opcode::Tw => "tw", + Opcode::Twi => "twi", + Opcode::Xor => "xor", + Opcode::Xori => "xori", + Opcode::Xoris => "xoris", + } + } + pub(crate) fn _detect(code: u32) -> Self { + if code & 0xfc0007fe == 0x7c000214 { + return Opcode::Add; + } + if code & 0xfc0007fe == 0x7c000014 { + return Opcode::Addc; + } + if code & 0xfc0007fe == 0x7c000114 { + return Opcode::Adde; + } + if code & 0xfc000000 == 0x38000000 { + return Opcode::Addi; + } + if code & 0xfc000000 == 0x30000000 { + return Opcode::Addic; + } + if code & 0xfc000000 == 0x34000000 { + return Opcode::Addic_; + } + if code & 0xfc000000 == 0x3c000000 { + return Opcode::Addis; + } + if code & 0xfc00fbfe == 0x7c0001d4 { + return Opcode::Addme; + } + if code & 0xfc00fbfe == 0x7c000194 { + return Opcode::Addze; + } + if code & 0xfc0007fe == 0x7c000038 { + return Opcode::And; + } + if code & 0xfc0007fe == 0x7c000078 { + return Opcode::Andc; + } + if code & 0xfc000000 == 0x70000000 { + return Opcode::Andi_; + } + if code & 0xfc000000 == 0x74000000 { + return Opcode::Andis_; + } + if code & 0xfc000000 == 0x48000000 { + return Opcode::B; + } + if code & 0xfc000000 == 0x40000000 { + return Opcode::Bc; + } + if code & 0xfc007ffe == 0x4c000420 { + return Opcode::Bcctr; + } + if code & 0xfc007ffe == 0x4c000020 { + return Opcode::Bclr; + } + if code & 0xfc4007ff == 0x7c000000 { + return Opcode::Cmp; + } + if code & 0xfc400000 == 0x2c000000 { + return Opcode::Cmpi; + } + if code & 0xfc4007ff == 0x7c000040 { + return Opcode::Cmpl; + } + if code & 0xfc400000 == 0x28000000 { + return Opcode::Cmpli; + } + if code & 0xfc00fffe == 0x7c000034 { + return Opcode::Cntlzw; + } + if code & 0xfc0007ff == 0x4c000202 { + return Opcode::Crand; + } + if code & 0xfc0007ff == 0x4c000102 { + return Opcode::Crandc; + } + if code & 0xfc0007ff == 0x4c000242 { + return Opcode::Creqv; + } + if code & 0xfc0007ff == 0x4c0001c2 { + return Opcode::Crnand; + } + if code & 0xfc0007ff == 0x4c000042 { + return Opcode::Crnor; + } + if code & 0xfc0007ff == 0x4c000382 { + return Opcode::Cror; + } + if code & 0xfc0007ff == 0x4c000342 { + return Opcode::Crorc; + } + if code & 0xfc0007ff == 0x4c000182 { + return Opcode::Crxor; + } + if code & 0xffe007ff == 0x7c0000ac { + return Opcode::Dcbf; + } + if code & 0xffe007ff == 0x7c0003ac { + return Opcode::Dcbi; + } + if code & 0xffe007ff == 0x7c00006c { + return Opcode::Dcbst; + } + if code & 0xffe007ff == 0x7c00022c { + return Opcode::Dcbt; + } + if code & 0xffe007ff == 0x7c0001ec { + return Opcode::Dcbtst; + } + if code & 0xffe007ff == 0x7c0007ec { + return Opcode::Dcbz; + } + if code & 0xffe007ff == 0x100007ec { + return Opcode::DcbzL; + } + if code & 0xfc0003fe == 0x7c0003d6 { + return Opcode::Divw; + } + if code & 0xfc0003fe == 0x7c000396 { + return Opcode::Divwu; + } + if code & 0xfc0003ff == 0x7c00026c { + return Opcode::Eciwx; + } + if code & 0xfc0003ff == 0x7c00036c { + return Opcode::Ecowx; + } + if code & 0xffffffff == 0x7c0006ac { + return Opcode::Eieio; + } + if code & 0xfc0003fe == 0x7c000238 { + return Opcode::Eqv; + } + if code & 0xfc00fffe == 0x7c000774 { + return Opcode::Extsb; + } + if code & 0xfc00fffe == 0x7c000734 { + return Opcode::Extsh; + } + if code & 0xfc1f07fe == 0xfc000210 { + return Opcode::Fabs; + } + if code & 0xfc0007fe == 0xfc00002a { + return Opcode::Fadd; + } + if code & 0xfc0007fe == 0xec00002a { + return Opcode::Fadds; + } + if code & 0xfc6007ff == 0xfc000040 { + return Opcode::Fcmpo; + } + if code & 0xfc6007ff == 0xfc000000 { + return Opcode::Fcmpu; + } + if code & 0xfc1f07fe == 0xfc00001c { + return Opcode::Fctiw; + } + if code & 0xfc1f07fe == 0xfc00001e { + return Opcode::Fctiwz; + } + if code & 0xfc0007fe == 0xfc000024 { + return Opcode::Fdiv; + } + if code & 0xfc0007fe == 0xec000024 { + return Opcode::Fdivs; + } + if code & 0xfc00003e == 0xfc00003a { + return Opcode::Fmadd; + } + if code & 0xfc00003e == 0xec00003a { + return Opcode::Fmadds; + } + if code & 0xfc1f07fe == 0xfc000090 { + return Opcode::Fmr; + } + if code & 0xfc00003e == 0xfc000038 { + return Opcode::Fmsub; + } + if code & 0xfc00003e == 0xec000038 { + return Opcode::Fmsubs; + } + if code & 0xfc00f83e == 0xfc000032 { + return Opcode::Fmul; + } + if code & 0xfc00f83e == 0xec000032 { + return Opcode::Fmuls; + } + if code & 0xfc1f07fe == 0xfc000110 { + return Opcode::Fnabs; + } + if code & 0xfc1f07fe == 0xfc000050 { + return Opcode::Fneg; + } + if code & 0xfc00003e == 0xfc00003e { + return Opcode::Fnmadd; + } + if code & 0xfc00003e == 0xec00003e { + return Opcode::Fnmadds; + } + if code & 0xfc00003e == 0xfc00003c { + return Opcode::Fnmsub; + } + if code & 0xfc00003e == 0xec00003c { + return Opcode::Fnmsubs; + } + if code & 0xfc1f07fe == 0xec000030 { + return Opcode::Fres; + } + if code & 0xfc1f07fe == 0xfc000018 { + return Opcode::Frsp; + } + if code & 0xfc1f07fe == 0xfc000034 { + return Opcode::Frsqrte; + } + if code & 0xfc00003e == 0xfc00002e { + return Opcode::Fsel; + } + if code & 0xfc0007fe == 0xfc000028 { + return Opcode::Fsub; + } + if code & 0xfc0007fe == 0xec000028 { + return Opcode::Fsubs; + } + if code & 0xffe007ff == 0x7c0007ac { + return Opcode::Icbi; + } + if code & 0xffffffff == 0x4c00012c { + return Opcode::Isync; + } + if code & 0xfc000000 == 0x88000000 { + return Opcode::Lbz; + } + if code & 0xfc000000 == 0x8c000000 { + return Opcode::Lbzu; + } + if code & 0xfc0007ff == 0x7c0000ee { + return Opcode::Lbzux; + } + if code & 0xfc0007ff == 0x7c0000ae { + return Opcode::Lbzx; + } + if code & 0xfc000000 == 0xc8000000 { + return Opcode::Lfd; + } + if code & 0xfc000000 == 0xcc000000 { + return Opcode::Lfdu; + } + if code & 0xfc0007ff == 0x7c0004ee { + return Opcode::Lfdux; + } + if code & 0xfc0007ff == 0x7c0004ae { + return Opcode::Lfdx; + } + if code & 0xfc000000 == 0xc0000000 { + return Opcode::Lfs; + } + if code & 0xfc000000 == 0xc4000000 { + return Opcode::Lfsu; + } + if code & 0xfc0007ff == 0x7c00046e { + return Opcode::Lfsux; + } + if code & 0xfc0007ff == 0x7c00042e { + return Opcode::Lfsx; + } + if code & 0xfc000000 == 0xa8000000 { + return Opcode::Lha; + } + if code & 0xfc000000 == 0xac000000 { + return Opcode::Lhau; + } + if code & 0xfc0007ff == 0x7c0002ee { + return Opcode::Lhaux; + } + if code & 0xfc0007ff == 0x7c0002ae { + return Opcode::Lhax; + } + if code & 0xfc0007ff == 0x7c00062c { + return Opcode::Lhbrx; + } + if code & 0xfc000000 == 0xa0000000 { + return Opcode::Lhz; + } + if code & 0xfc000000 == 0xa4000000 { + return Opcode::Lhzu; + } + if code & 0xfc0007ff == 0x7c00026e { + return Opcode::Lhzux; + } + if code & 0xfc0007ff == 0x7c00022e { + return Opcode::Lhzx; + } + if code & 0xfc000000 == 0xb8000000 { + return Opcode::Lmw; + } + if code & 0xfc0007ff == 0x7c0004aa { + return Opcode::Lswi; + } + if code & 0xfc0007ff == 0x7c00042a { + return Opcode::Lswx; + } + if code & 0xfc0007ff == 0x7c000028 { + return Opcode::Lwarx; + } + if code & 0xfc0007ff == 0x7c00042c { + return Opcode::Lwbrx; + } + if code & 0xfc000000 == 0x80000000 { + return Opcode::Lwz; + } + if code & 0xfc000000 == 0x84000000 { + return Opcode::Lwzu; + } + if code & 0xfc0007ff == 0x7c00006e { + return Opcode::Lwzux; + } + if code & 0xfc0007ff == 0x7c00002e { + return Opcode::Lwzx; + } + if code & 0xfc300fff == 0x4c000000 { + return Opcode::Mcrf; + } + if code & 0xfc30ffff == 0xfc000080 { + return Opcode::Mcrfs; + } + if code & 0xfc30ffff == 0x7c000400 { + return Opcode::Mcrxr; + } + if code & 0xfc1fffff == 0x7c000026 { + return Opcode::Mfcr; + } + if code & 0xfc1ffffe == 0xfc00048e { + return Opcode::Mffs; + } + if code & 0xfc1fffff == 0x7c0000a6 { + return Opcode::Mfmsr; + } + if code & 0xfc0007ff == 0x7c0002a6 { + return Opcode::Mfspr; + } + if code & 0xfc10ffff == 0x7c0004a6 { + return Opcode::Mfsr; + } + if code & 0xfc1f07ff == 0x7c000526 { + return Opcode::Mfsrin; + } + if code & 0xfc0007ff == 0x7c0002e6 { + return Opcode::Mftb; + } + if code & 0xfc100fff == 0x7c000120 { + return Opcode::Mtcrf; + } + if code & 0xfc1ffffe == 0xfc00008c { + return Opcode::Mtfsb0; + } + if code & 0xfc1ffffe == 0xfc00004c { + return Opcode::Mtfsb1; + } + if code & 0xfe0107fe == 0xfc00058e { + return Opcode::Mtfsf; + } + if code & 0xfc7f0ffe == 0xfc00010c { + return Opcode::Mtfsfi; + } + if code & 0xfc1fffff == 0x7c000124 { + return Opcode::Mtmsr; + } + if code & 0xfc0007ff == 0x7c0003a6 { + return Opcode::Mtspr; + } + if code & 0xfc10ffff == 0x7c0001a4 { + return Opcode::Mtsr; + } + if code & 0xfc1f07ff == 0x7c0001e4 { + return Opcode::Mtsrin; + } + if code & 0xfc0007fe == 0x7c000096 { + return Opcode::Mulhw; + } + if code & 0xfc0007fe == 0x7c000016 { + return Opcode::Mulhwu; + } + if code & 0xfc000000 == 0x1c000000 { + return Opcode::Mulli; + } + if code & 0xfc0003fe == 0x7c0001d6 { + return Opcode::Mullw; + } + if code & 0xfc0007fe == 0x7c0003b8 { + return Opcode::Nand; + } + if code & 0xfc00fffe == 0x7c0000d0 { + return Opcode::Neg; + } + if code & 0xfc0007fe == 0x7c0000f8 { + return Opcode::Nor; + } + if code & 0xfc0007fe == 0x7c000378 { + return Opcode::Or; + } + if code & 0xfc0007fe == 0x7c000338 { + return Opcode::Orc; + } + if code & 0xfc000000 == 0x60000000 { + return Opcode::Ori; + } + if code & 0xfc000000 == 0x64000000 { + return Opcode::Oris; + } + if code & 0xfc000000 == 0xe0000000 { + return Opcode::PsqL; + } + if code & 0xfc000000 == 0xe4000000 { + return Opcode::PsqLu; + } + if code & 0xfc00007f == 0x1000004c { + return Opcode::PsqLux; + } + if code & 0xfc00007f == 0x1000000c { + return Opcode::PsqLx; + } + if code & 0xfc000000 == 0xf0000000 { + return Opcode::PsqSt; + } + if code & 0xfc000000 == 0xf4000000 { + return Opcode::PsqStu; + } + if code & 0xfc00007f == 0x1000004e { + return Opcode::PsqStux; + } + if code & 0xfc00007f == 0x1000000e { + return Opcode::PsqStx; + } + if code & 0xfc1f07fe == 0x10000210 { + return Opcode::PsAbs; + } + if code & 0xfc0007fe == 0x1000002a { + return Opcode::PsAdd; + } + if code & 0xfc6007ff == 0x10000040 { + return Opcode::PsCmpo0; + } + if code & 0xfc6007ff == 0x100000c0 { + return Opcode::PsCmpo1; + } + if code & 0xfc6007ff == 0x10000000 { + return Opcode::PsCmpu0; + } + if code & 0xfc6007ff == 0x10000080 { + return Opcode::PsCmpu1; + } + if code & 0xfc0007fe == 0x10000024 { + return Opcode::PsDiv; + } + if code & 0xfc00003e == 0x1000003a { + return Opcode::PsMadd; + } + if code & 0xfc00003e == 0x1000001c { + return Opcode::PsMadds0; + } + if code & 0xfc00003e == 0x1000001e { + return Opcode::PsMadds1; + } + if code & 0xfc0007fe == 0x10000420 { + return Opcode::PsMerge00; + } + if code & 0xfc0007fe == 0x10000460 { + return Opcode::PsMerge01; + } + if code & 0xfc0007fe == 0x100004a0 { + return Opcode::PsMerge10; + } + if code & 0xfc0007fe == 0x100004e0 { + return Opcode::PsMerge11; + } + if code & 0xfc1f07fe == 0x10000090 { + return Opcode::PsMr; + } + if code & 0xfc00003e == 0x10000038 { + return Opcode::PsMsub; + } + if code & 0xfc00f83e == 0x10000032 { + return Opcode::PsMul; + } + if code & 0xfc00f83e == 0x10000018 { + return Opcode::PsMuls0; + } + if code & 0xfc00f83e == 0x1000001a { + return Opcode::PsMuls1; + } + if code & 0xfc1f07fe == 0x10000110 { + return Opcode::PsNabs; + } + if code & 0xfc1f07fe == 0x10000050 { + return Opcode::PsNeg; + } + if code & 0xfc00003e == 0x1000003e { + return Opcode::PsNmadd; + } + if code & 0xfc00003e == 0x1000003c { + return Opcode::PsNmsub; + } + if code & 0xfc1f07fe == 0x10000030 { + return Opcode::PsRes; + } + if code & 0xfc1f07fe == 0x10000034 { + return Opcode::PsRsqrte; + } + if code & 0xfc00003e == 0x1000002e { + return Opcode::PsSel; + } + if code & 0xfc0007fe == 0x10000028 { + return Opcode::PsSub; + } + if code & 0xfc00003e == 0x10000014 { + return Opcode::PsSum0; + } + if code & 0xfc00003e == 0x10000016 { + return Opcode::PsSum1; + } + if code & 0xfffff801 == 0x4c000000 { + return Opcode::Rfi; + } + if code & 0xfc000000 == 0x50000000 { + return Opcode::Rlwimi; + } + if code & 0xfc000000 == 0x54000000 { + return Opcode::Rlwinm; + } + if code & 0xfc000000 == 0x5c000000 { + return Opcode::Rlwnm; + } + if code & 0xffffffff == 0x44000002 { + return Opcode::Sc; + } + if code & 0xfc0007fe == 0x7c000030 { + return Opcode::Slw; + } + if code & 0xfc0007fe == 0x7c000630 { + return Opcode::Sraw; + } + if code & 0xfc0007fe == 0x7c000670 { + return Opcode::Srawi; + } + if code & 0xfc0007fe == 0x7c000430 { + return Opcode::Srw; + } + if code & 0xfc000000 == 0x98000000 { + return Opcode::Stb; + } + if code & 0xfc000000 == 0x9c000000 { + return Opcode::Stbu; + } + if code & 0xfc0003ff == 0x7c0001ee { + return Opcode::Stbux; + } + if code & 0xfc0003ff == 0x7c0001ae { + return Opcode::Stbx; + } + if code & 0xfc000000 == 0xd8000000 { + return Opcode::Stfd; + } + if code & 0xfc000000 == 0xdc000000 { + return Opcode::Stfdu; + } + if code & 0xfc0007ff == 0x7c0005ee { + return Opcode::Stfdux; + } + if code & 0xfc0007ff == 0x7c0005ae { + return Opcode::Stfdx; + } + if code & 0xfc0007ff == 0x7c0007ae { + return Opcode::Stfiwx; + } + if code & 0xfc000000 == 0xd0000000 { + return Opcode::Stfs; + } + if code & 0xfc000000 == 0xd4000000 { + return Opcode::Stfsu; + } + if code & 0xfc0007ff == 0x7c00056e { + return Opcode::Stfsux; + } + if code & 0xfc0007ff == 0x7c00052e { + return Opcode::Stfsx; + } + if code & 0xfc000000 == 0xb0000000 { + return Opcode::Sth; + } + if code & 0xfc0007ff == 0x7c00072c { + return Opcode::Sthbrx; + } + if code & 0xfc000000 == 0xb4000000 { + return Opcode::Sthu; + } + if code & 0xfc0007ff == 0x7c00036e { + return Opcode::Sthux; + } + if code & 0xfc0007ff == 0x7c00032e { + return Opcode::Sthx; + } + if code & 0xfc000000 == 0xbc000000 { + return Opcode::Stmw; + } + if code & 0xfc0007ff == 0x7c0005aa { + return Opcode::Stswi; + } + if code & 0xfc0007ff == 0x7c00052a { + return Opcode::Stswx; + } + if code & 0xfc000000 == 0x90000000 { + return Opcode::Stw; + } + if code & 0xfc0007ff == 0x7c00052c { + return Opcode::Stwbrx; + } + if code & 0xfc0007ff == 0x7c00012d { + return Opcode::Stwcx_; + } + if code & 0xfc000000 == 0x94000000 { + return Opcode::Stwu; + } + if code & 0xfc0007ff == 0x7c00016e { + return Opcode::Stwux; + } + if code & 0xfc0007ff == 0x7c00012e { + return Opcode::Stwx; + } + if code & 0xfc0003fe == 0x7c000050 { + return Opcode::Subf; + } + if code & 0xfc0003fe == 0x7c000010 { + return Opcode::Subfc; + } + if code & 0xfc0003fe == 0x7c000110 { + return Opcode::Subfe; + } + if code & 0xfc000000 == 0x20000000 { + return Opcode::Subfic; + } + if code & 0xfc00fbfe == 0x7c0001d0 { + return Opcode::Subfme; + } + if code & 0xfc00fbfe == 0x7c000190 { + return Opcode::Subfze; + } + if code & 0xffffffff == 0x7c0004ac { + return Opcode::Sync; + } + if code & 0xffff07ff == 0x7c000264 { + return Opcode::Tlbie; + } + if code & 0xffffffff == 0x7c00046c { + return Opcode::Tlbsync; + } + if code & 0xfc0007ff == 0x7c000008 { + return Opcode::Tw; + } + if code & 0xfc000000 == 0xc0000000 { + return Opcode::Twi; + } + if code & 0xfc0007fe == 0x7c000278 { + return Opcode::Xor; + } + if code & 0xfc000000 == 0x68000000 { + return Opcode::Xori; + } + if code & 0xfc000000 == 0x6c000000 { + return Opcode::Xoris; + } + Opcode::Illegal + } +} +#[allow(non_camel_case_types)] +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub enum Field { + simm(Simm), + uimm(Uimm), + offset(Offset), + BO(OpaqueU), + BI(OpaqueU), + BD(BranchDest), + LI(BranchDest), + SH(OpaqueU), + MB(OpaqueU), + ME(OpaqueU), + rS(GPR), + rD(GPR), + rA(GPR), + rB(GPR), + rC(GPR), + sr(SR), + spr(SPR), + frS(FPR), + frD(FPR), + frA(FPR), + frB(FPR), + frC(FPR), + crbD(CRField), + crbA(CRField), + crbB(CRField), + crfD(CRBit), + crfS(CRBit), + crm(OpaqueU), + ps_l(GQR), + ps_W(OpaqueU), + NB(OpaqueU), + tbr(OpaqueU), + mtfsf_FM(OpaqueU), + mtfsf_IMM(OpaqueU), + TO(OpaqueU), + xer, + ctr, + lr, +} +#[allow(clippy::all, unused_mut)] +impl Ins { + pub(crate) fn _fields(&self) -> Vec { + match self.op { + Opcode::Illegal => vec![], + Opcode::Add => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Addc => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Adde => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Addi => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::simm(Simm( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + ], + Opcode::Addic => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::simm(Simm( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + ], + Opcode::Addic_ => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::simm(Simm( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + ], + Opcode::Addis => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::uimm(Uimm((self.code & 0xffff) as _)), + ], + Opcode::Addme => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Addze => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::And => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Andc => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Andi_ => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::uimm(Uimm((self.code & 0xffff) as _)), + ], + Opcode::Andis_ => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::uimm(Uimm((self.code & 0xffff) as _)), + ], + Opcode::B => vec![Field::LI(BranchDest( + (((((self.code >> 2u8) & 0xffffff) ^ 0x800000).wrapping_sub(0x800000)) << 2u8) as _, + ))], + Opcode::Bc => vec![ + Field::BO(OpaqueU(((self.code >> 21u8) & 0x1f) as _)), + Field::BI(OpaqueU(((self.code >> 16u8) & 0x1f) as _)), + Field::BD(BranchDest( + (((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) << 2u8) as _, + )), + ], + Opcode::Bcctr => vec![ + Field::BO(OpaqueU(((self.code >> 21u8) & 0x1f) as _)), + Field::BI(OpaqueU(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Bclr => vec![ + Field::BO(OpaqueU(((self.code >> 21u8) & 0x1f) as _)), + Field::BI(OpaqueU(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Cmp => vec![ + Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Cmpi => vec![ + Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::simm(Simm( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + ], + Opcode::Cmpl => vec![ + Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Cmpli => vec![ + Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::uimm(Uimm((self.code & 0xffff) as _)), + ], + Opcode::Cntlzw => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + ], + Opcode::Crand => vec![ + Field::crbD(CRField(((self.code >> 21u8) & 0x1f) as _)), + Field::crbA(CRField(((self.code >> 16u8) & 0x1f) as _)), + Field::crbB(CRField(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Crandc => vec![ + Field::crbD(CRField(((self.code >> 21u8) & 0x1f) as _)), + Field::crbA(CRField(((self.code >> 16u8) & 0x1f) as _)), + Field::crbB(CRField(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Creqv => vec![ + Field::crbD(CRField(((self.code >> 21u8) & 0x1f) as _)), + Field::crbA(CRField(((self.code >> 16u8) & 0x1f) as _)), + Field::crbB(CRField(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Crnand => vec![ + Field::crbD(CRField(((self.code >> 21u8) & 0x1f) as _)), + Field::crbA(CRField(((self.code >> 16u8) & 0x1f) as _)), + Field::crbB(CRField(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Crnor => vec![ + Field::crbD(CRField(((self.code >> 21u8) & 0x1f) as _)), + Field::crbA(CRField(((self.code >> 16u8) & 0x1f) as _)), + Field::crbB(CRField(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Cror => vec![ + Field::crbD(CRField(((self.code >> 21u8) & 0x1f) as _)), + Field::crbA(CRField(((self.code >> 16u8) & 0x1f) as _)), + Field::crbB(CRField(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Crorc => vec![ + Field::crbD(CRField(((self.code >> 21u8) & 0x1f) as _)), + Field::crbA(CRField(((self.code >> 16u8) & 0x1f) as _)), + Field::crbB(CRField(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Crxor => vec![ + Field::crbD(CRField(((self.code >> 21u8) & 0x1f) as _)), + Field::crbA(CRField(((self.code >> 16u8) & 0x1f) as _)), + Field::crbB(CRField(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Dcbf => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Dcbi => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Dcbst => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Dcbt => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Dcbtst => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Dcbz => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::DcbzL => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Divw => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Divwu => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Eciwx => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Ecowx => vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Eieio => vec![], + Opcode::Eqv => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Extsb => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + ], + Opcode::Extsh => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + ], + Opcode::Fabs => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Fadd => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Fadds => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Fcmpo => vec![ + Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Fcmpu => vec![ + Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Fctiw => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Fctiwz => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Fdiv => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Fdivs => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Fmadd => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Fmadds => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Fmr => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Fmsub => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Fmsubs => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Fmul => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + ], + Opcode::Fmuls => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + ], + Opcode::Fnabs => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Fneg => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Fnmadd => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Fnmadds => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Fnmsub => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Fnmsubs => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Fres => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Frsp => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Frsqrte => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Fsel => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Fsub => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Fsubs => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Icbi => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Isync => vec![], + Opcode::Lbz => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Lbzu => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Lbzux => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Lbzx => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Lfd => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Lfdu => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Lfdux => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Lfdx => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Lfs => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Lfsu => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Lfsux => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Lfsx => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Lha => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Lhau => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Lhaux => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Lhax => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Lhbrx => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Lhz => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Lhzu => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Lhzux => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Lhzx => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Lmw => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Lswi => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::NB(OpaqueU(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Lswx => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Lwarx => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Lwbrx => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Lwz => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Lwzu => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Lwzux => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Lwzx => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Mcrf => vec![ + Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _)), + Field::crfS(CRBit(((self.code >> 18u8) & 0x7) as _)), + ], + Opcode::Mcrfs => vec![ + Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _)), + Field::crfS(CRBit(((self.code >> 18u8) & 0x7) as _)), + ], + Opcode::Mcrxr => vec![Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _))], + Opcode::Mfcr => vec![Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _))], + Opcode::Mffs => vec![Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _))], + Opcode::Mfmsr => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Mfspr => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::spr(SPR(((self.code >> 11u8) & 0x3ff) as _)), + ], + Opcode::Mfsr => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::sr(SR(((self.code >> 16u8) & 0xf) as _)), + ], + Opcode::Mfsrin => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Mftb => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::tbr(OpaqueU(((self.code >> 11u8) & 0x3ff) as _)), + ], + Opcode::Mtcrf => vec![ + Field::crm(OpaqueU(((self.code >> 12u8) & 0xff) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + ], + Opcode::Mtfsb0 => vec![Field::crbD(CRField(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Mtfsb1 => vec![Field::crbD(CRField(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Mtfsf => vec![ + Field::mtfsf_FM(OpaqueU(((self.code >> 17u8) & 0xff) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Mtfsfi => vec![ + Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _)), + Field::mtfsf_IMM(OpaqueU(((self.code >> 12u8) & 0xf) as _)), + ], + Opcode::Mtmsr => vec![Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Mtspr => vec![ + Field::spr(SPR(((self.code >> 11u8) & 0x3ff) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + ], + Opcode::Mtsr => vec![ + Field::sr(SR(((self.code >> 16u8) & 0xf) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + ], + Opcode::Mtsrin => vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Mulhw => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Mulhwu => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Mulli => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::simm(Simm( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + ], + Opcode::Mullw => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Nand => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Neg => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Nor => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Or => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Orc => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Ori => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::uimm(Uimm((self.code & 0xffff) as _)), + ], + Opcode::Oris => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::uimm(Uimm((self.code & 0xffff) as _)), + ], + Opcode::PsqL => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::ps_W(OpaqueU(((self.code >> 16u8) & 0x0) as _)), + Field::ps_l(GQR(((self.code >> 12u8) & 0x7) as _)), + ], + Opcode::PsqLu => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::ps_W(OpaqueU(((self.code >> 16u8) & 0x0) as _)), + Field::ps_l(GQR(((self.code >> 12u8) & 0x7) as _)), + ], + Opcode::PsqLux => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + Field::ps_W(OpaqueU(((self.code >> 16u8) & 0x0) as _)), + Field::ps_l(GQR(((self.code >> 12u8) & 0x7) as _)), + ], + Opcode::PsqLx => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + Field::ps_W(OpaqueU(((self.code >> 16u8) & 0x0) as _)), + Field::ps_l(GQR(((self.code >> 12u8) & 0x7) as _)), + ], + Opcode::PsqSt => vec![ + Field::frS(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::ps_W(OpaqueU(((self.code >> 16u8) & 0x0) as _)), + Field::ps_l(GQR(((self.code >> 12u8) & 0x7) as _)), + ], + Opcode::PsqStu => vec![ + Field::frS(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::ps_W(OpaqueU(((self.code >> 16u8) & 0x0) as _)), + Field::ps_l(GQR(((self.code >> 12u8) & 0x7) as _)), + ], + Opcode::PsqStux => vec![ + Field::frS(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + Field::ps_W(OpaqueU(((self.code >> 16u8) & 0x0) as _)), + Field::ps_l(GQR(((self.code >> 12u8) & 0x7) as _)), + ], + Opcode::PsqStx => vec![ + Field::frS(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + Field::ps_W(OpaqueU(((self.code >> 16u8) & 0x0) as _)), + Field::ps_l(GQR(((self.code >> 12u8) & 0x7) as _)), + ], + Opcode::PsAbs => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::PsAdd => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::PsCmpo0 => vec![ + Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::PsCmpo1 => vec![ + Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::PsCmpu0 => vec![ + Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::PsCmpu1 => vec![ + Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::PsDiv => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::PsMadd => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::PsMadds0 => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::PsMadds1 => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::PsMerge00 => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::PsMerge01 => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::PsMerge10 => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::PsMerge11 => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::PsMr => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::PsMsub => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::PsMul => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + ], + Opcode::PsMuls0 => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + ], + Opcode::PsMuls1 => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + ], + Opcode::PsNabs => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::PsNeg => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::PsNmadd => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::PsNmsub => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::PsRes => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::PsRsqrte => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::PsSel => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::PsSub => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::PsSum0 => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::PsSum1 => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Rfi => vec![], + Opcode::Rlwimi => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::SH(OpaqueU(((self.code >> 11u8) & 0x1f) as _)), + Field::MB(OpaqueU(((self.code >> 6u8) & 0x1f) as _)), + Field::ME(OpaqueU(((self.code >> 1u8) & 0x1f) as _)), + ], + Opcode::Rlwinm => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::SH(OpaqueU(((self.code >> 11u8) & 0x1f) as _)), + Field::MB(OpaqueU(((self.code >> 6u8) & 0x1f) as _)), + Field::ME(OpaqueU(((self.code >> 1u8) & 0x1f) as _)), + ], + Opcode::Rlwnm => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + Field::MB(OpaqueU(((self.code >> 6u8) & 0x1f) as _)), + Field::ME(OpaqueU(((self.code >> 1u8) & 0x1f) as _)), + ], + Opcode::Sc => vec![], + Opcode::Slw => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Sraw => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Srawi => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::SH(OpaqueU(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Srw => vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Stb => vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Stbu => vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Stbux => vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Stbx => vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Stfd => vec![ + Field::frS(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Stfdu => vec![ + Field::frS(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Stfdux => vec![ + Field::frS(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Stfdx => vec![ + Field::frS(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Stfiwx => vec![ + Field::frS(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Stfs => vec![ + Field::frS(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Stfsu => vec![ + Field::frS(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Stfsux => vec![ + Field::frS(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Stfsx => vec![ + Field::frS(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Sth => vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Sthbrx => vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Sthu => vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Sthux => vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Sthx => vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Stmw => vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Stswi => vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::NB(OpaqueU(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Stswx => vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Stw => vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Stwbrx => vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Stwcx_ => vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Stwu => vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Stwux => vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Stwx => vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Subf => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Subfc => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Subfe => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Subfic => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::simm(Simm( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + ], + Opcode::Subfme => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Subfze => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Sync => vec![], + Opcode::Tlbie => vec![Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _))], + Opcode::Tlbsync => vec![], + Opcode::Tw => vec![ + Field::TO(OpaqueU(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Twi => vec![ + Field::TO(OpaqueU(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::simm(Simm( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + ], + Opcode::Xor => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + Opcode::Xori => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::uimm(Uimm((self.code & 0xffff) as _)), + ], + Opcode::Xoris => vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::uimm(Uimm((self.code & 0xffff) as _)), + ], + } + } + pub(crate) fn _defs(&self) -> Vec { + match self.op { + Opcode::Illegal => vec![], + Opcode::Add => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Addc => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Adde => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Addi => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Addic => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Addic_ => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Addis => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Addme => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Addze => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::And => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Andc => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Andi_ => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Andis_ => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::B => vec![], + Opcode::Bc => vec![], + Opcode::Bcctr => vec![], + Opcode::Bclr => vec![], + Opcode::Cmp => vec![Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _))], + Opcode::Cmpi => vec![Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _))], + Opcode::Cmpl => vec![Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _))], + Opcode::Cmpli => vec![Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _))], + Opcode::Cntlzw => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Crand => vec![Field::crbD(CRField(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Crandc => vec![Field::crbD(CRField(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Creqv => vec![Field::crbD(CRField(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Crnand => vec![Field::crbD(CRField(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Crnor => vec![Field::crbD(CRField(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Cror => vec![Field::crbD(CRField(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Crorc => vec![Field::crbD(CRField(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Crxor => vec![Field::crbD(CRField(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Dcbf => vec![], + Opcode::Dcbi => vec![], + Opcode::Dcbst => vec![], + Opcode::Dcbt => vec![], + Opcode::Dcbtst => vec![], + Opcode::Dcbz => vec![], + Opcode::DcbzL => vec![], + Opcode::Divw => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Divwu => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Eciwx => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Ecowx => vec![], + Opcode::Eieio => vec![], + Opcode::Eqv => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Extsb => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Extsh => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Fabs => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Fadd => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Fadds => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Fcmpo => vec![Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _))], + Opcode::Fcmpu => vec![Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _))], + Opcode::Fctiw => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Fctiwz => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Fdiv => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Fdivs => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Fmadd => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Fmadds => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Fmr => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Fmsub => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Fmsubs => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Fmul => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Fmuls => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Fnabs => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Fneg => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Fnmadd => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Fnmadds => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Fnmsub => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Fnmsubs => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Fres => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Frsp => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Frsqrte => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Fsel => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Fsub => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Fsubs => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Icbi => vec![], + Opcode::Isync => vec![], + Opcode::Lbz => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Lbzu => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Lbzux => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Lbzx => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Lfd => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Lfdu => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Lfdux => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Lfdx => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Lfs => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Lfsu => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Lfsux => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Lfsx => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Lha => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Lhau => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Lhaux => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Lhax => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Lhbrx => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Lhz => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Lhzu => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Lhzux => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Lhzx => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Lmw => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Lswi => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Lswx => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Lwarx => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Lwbrx => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Lwz => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Lwzu => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Lwzux => vec![ + Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::Lwzx => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Mcrf => vec![Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _))], + Opcode::Mcrfs => vec![Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _))], + Opcode::Mcrxr => vec![ + Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _)), + Field::xer, + ], + Opcode::Mfcr => vec![Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _))], + Opcode::Mffs => vec![Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _))], + Opcode::Mfmsr => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Mfspr => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Mfsr => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Mfsrin => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Mftb => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Mtcrf => vec![], + Opcode::Mtfsb0 => vec![Field::crbD(CRField(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Mtfsb1 => vec![Field::crbD(CRField(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Mtfsf => vec![], + Opcode::Mtfsfi => vec![Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _))], + Opcode::Mtmsr => vec![], + Opcode::Mtspr => vec![], + Opcode::Mtsr => vec![], + Opcode::Mtsrin => vec![], + Opcode::Mulhw => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Mulhwu => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Mulli => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Mullw => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Nand => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Neg => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Nor => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Or => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Orc => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Ori => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Oris => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::PsqL => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::PsqLu => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::PsqLux => vec![ + Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ], + Opcode::PsqLx => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::PsqSt => vec![], + Opcode::PsqStu => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::PsqStux => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::PsqStx => vec![], + Opcode::PsAbs => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::PsAdd => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::PsCmpo0 => vec![Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _))], + Opcode::PsCmpo1 => vec![Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _))], + Opcode::PsCmpu0 => vec![Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _))], + Opcode::PsCmpu1 => vec![Field::crfD(CRBit(((self.code >> 23u8) & 0x7) as _))], + Opcode::PsDiv => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::PsMadd => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::PsMadds0 => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::PsMadds1 => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::PsMerge00 => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::PsMerge01 => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::PsMerge10 => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::PsMerge11 => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::PsMr => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::PsMsub => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::PsMul => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::PsMuls0 => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::PsMuls1 => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::PsNabs => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::PsNeg => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::PsNmadd => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::PsNmsub => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::PsRes => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::PsRsqrte => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::PsSel => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::PsSub => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::PsSum0 => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::PsSum1 => vec![Field::frD(FPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Rfi => vec![], + Opcode::Rlwimi => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Rlwinm => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Rlwnm => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Sc => vec![], + Opcode::Slw => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Sraw => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Srawi => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Srw => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Stb => vec![], + Opcode::Stbu => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Stbux => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Stbx => vec![], + Opcode::Stfd => vec![], + Opcode::Stfdu => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Stfdux => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Stfdx => vec![], + Opcode::Stfiwx => vec![], + Opcode::Stfs => vec![], + Opcode::Stfsu => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Stfsux => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Stfsx => vec![], + Opcode::Sth => vec![], + Opcode::Sthbrx => vec![], + Opcode::Sthu => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Sthux => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Sthx => vec![], + Opcode::Stmw => vec![], + Opcode::Stswi => vec![], + Opcode::Stswx => vec![], + Opcode::Stw => vec![], + Opcode::Stwbrx => vec![], + Opcode::Stwcx_ => vec![], + Opcode::Stwu => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Stwux => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Stwx => vec![], + Opcode::Subf => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Subfc => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Subfe => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Subfic => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Subfme => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Subfze => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], + Opcode::Sync => vec![], + Opcode::Tlbie => vec![], + Opcode::Tlbsync => vec![], + Opcode::Tw => vec![], + Opcode::Twi => vec![], + Opcode::Xor => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Xori => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + Opcode::Xoris => vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))], + } + } + pub(crate) fn _uses(&self) -> Vec { + match self.op { + Opcode::Illegal => vec![], + Opcode::Add => { + let mut uses = vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Addc => { + let mut uses = vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Adde => { + let mut uses = vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Addi => { + let mut uses = vec![]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Addic => { + let mut uses = vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))]; + uses + } + Opcode::Addic_ => { + let mut uses = vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))]; + uses + } + Opcode::Addis => { + let mut uses = vec![]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Addme => { + let mut uses = vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))]; + uses + } + Opcode::Addze => { + let mut uses = vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))]; + uses + } + Opcode::And => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Andc => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Andi_ => { + let mut uses = vec![Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _))]; + uses + } + Opcode::Andis_ => { + let mut uses = vec![Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _))]; + uses + } + Opcode::B => { + let mut uses = vec![]; + uses + } + Opcode::Bc => { + let mut uses = vec![]; + uses + } + Opcode::Bcctr => { + let mut uses = vec![Field::ctr]; + uses + } + Opcode::Bclr => { + let mut uses = vec![Field::lr]; + uses + } + Opcode::Cmp => { + let mut uses = vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Cmpi => { + let mut uses = vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))]; + uses + } + Opcode::Cmpl => { + let mut uses = vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Cmpli => { + let mut uses = vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))]; + uses + } + Opcode::Cntlzw => { + let mut uses = vec![Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _))]; + uses + } + Opcode::Crand => { + let mut uses = vec![ + Field::crbA(CRField(((self.code >> 16u8) & 0x1f) as _)), + Field::crbB(CRField(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Crandc => { + let mut uses = vec![ + Field::crbA(CRField(((self.code >> 16u8) & 0x1f) as _)), + Field::crbB(CRField(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Creqv => { + let mut uses = vec![ + Field::crbA(CRField(((self.code >> 16u8) & 0x1f) as _)), + Field::crbB(CRField(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Crnand => { + let mut uses = vec![ + Field::crbA(CRField(((self.code >> 16u8) & 0x1f) as _)), + Field::crbB(CRField(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Crnor => { + let mut uses = vec![ + Field::crbA(CRField(((self.code >> 16u8) & 0x1f) as _)), + Field::crbB(CRField(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Cror => { + let mut uses = vec![ + Field::crbA(CRField(((self.code >> 16u8) & 0x1f) as _)), + Field::crbB(CRField(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Crorc => { + let mut uses = vec![ + Field::crbA(CRField(((self.code >> 16u8) & 0x1f) as _)), + Field::crbB(CRField(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Crxor => { + let mut uses = vec![ + Field::crbA(CRField(((self.code >> 16u8) & 0x1f) as _)), + Field::crbB(CRField(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Dcbf => { + let mut uses = vec![Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Dcbi => { + let mut uses = vec![Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Dcbst => { + let mut uses = vec![Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Dcbt => { + let mut uses = vec![Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Dcbtst => { + let mut uses = vec![Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Dcbz => { + let mut uses = vec![Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::DcbzL => { + let mut uses = vec![Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Divw => { + let mut uses = vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Divwu => { + let mut uses = vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Eciwx => { + let mut uses = vec![Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Ecowx => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Eieio => { + let mut uses = vec![]; + uses + } + Opcode::Eqv => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Extsb => { + let mut uses = vec![Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _))]; + uses + } + Opcode::Extsh => { + let mut uses = vec![Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _))]; + uses + } + Opcode::Fabs => { + let mut uses = vec![Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _))]; + uses + } + Opcode::Fadd => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Fadds => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Fcmpo => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Fcmpu => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Fctiw => { + let mut uses = vec![Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _))]; + uses + } + Opcode::Fctiwz => { + let mut uses = vec![Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _))]; + uses + } + Opcode::Fdiv => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Fdivs => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Fmadd => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Fmadds => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Fmr => { + let mut uses = vec![Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _))]; + uses + } + Opcode::Fmsub => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Fmsubs => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Fmul => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Fmuls => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Fnabs => { + let mut uses = vec![Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _))]; + uses + } + Opcode::Fneg => { + let mut uses = vec![Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _))]; + uses + } + Opcode::Fnmadd => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Fnmadds => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Fnmsub => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Fnmsubs => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Fres => { + let mut uses = vec![Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _))]; + uses + } + Opcode::Frsp => { + let mut uses = vec![Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _))]; + uses + } + Opcode::Frsqrte => { + let mut uses = vec![Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _))]; + uses + } + Opcode::Fsel => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Fsub => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Fsubs => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Icbi => { + let mut uses = vec![Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Isync => { + let mut uses = vec![]; + uses + } + Opcode::Lbz => { + let mut uses = vec![Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + ))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Lbzu => { + let mut uses = vec![ + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Lbzux => { + let mut uses = vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Lbzx => { + let mut uses = vec![Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Lfd => { + let mut uses = vec![Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + ))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Lfdu => { + let mut uses = vec![ + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Lfdux => { + let mut uses = vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Lfdx => { + let mut uses = vec![Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Lfs => { + let mut uses = vec![Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + ))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Lfsu => { + let mut uses = vec![ + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Lfsux => { + let mut uses = vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Lfsx => { + let mut uses = vec![Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Lha => { + let mut uses = vec![Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + ))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Lhau => { + let mut uses = vec![ + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Lhaux => { + let mut uses = vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Lhax => { + let mut uses = vec![Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Lhbrx => { + let mut uses = vec![Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Lhz => { + let mut uses = vec![Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + ))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Lhzu => { + let mut uses = vec![ + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Lhzux => { + let mut uses = vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Lhzx => { + let mut uses = vec![Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Lmw => { + let mut uses = vec![Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + ))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Lswi => { + let mut uses = vec![]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Lswx => { + let mut uses = vec![Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Lwarx => { + let mut uses = vec![Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Lwbrx => { + let mut uses = vec![Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Lwz => { + let mut uses = vec![Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + ))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Lwzu => { + let mut uses = vec![ + Field::offset(Offset( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Lwzux => { + let mut uses = vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Lwzx => { + let mut uses = vec![Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Mcrf => { + let mut uses = vec![Field::crfS(CRBit(((self.code >> 18u8) & 0x7) as _))]; + uses + } + Opcode::Mcrfs => { + let mut uses = vec![Field::crfS(CRBit(((self.code >> 18u8) & 0x7) as _))]; + uses + } + Opcode::Mcrxr => { + let mut uses = vec![]; + uses + } + Opcode::Mfcr => { + let mut uses = vec![]; + uses + } + Opcode::Mffs => { + let mut uses = vec![]; + uses + } + Opcode::Mfmsr => { + let mut uses = vec![]; + uses + } + Opcode::Mfspr => { + let mut uses = vec![]; + uses + } + Opcode::Mfsr => { + let mut uses = vec![]; + uses + } + Opcode::Mfsrin => { + let mut uses = vec![Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _))]; + uses + } + Opcode::Mftb => { + let mut uses = vec![]; + uses + } + Opcode::Mtcrf => { + let mut uses = vec![Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _))]; + uses + } + Opcode::Mtfsb0 => { + let mut uses = vec![]; + uses + } + Opcode::Mtfsb1 => { + let mut uses = vec![]; + uses + } + Opcode::Mtfsf => { + let mut uses = vec![Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _))]; + uses + } + Opcode::Mtfsfi => { + let mut uses = vec![]; + uses + } + Opcode::Mtmsr => { + let mut uses = vec![Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _))]; + uses + } + Opcode::Mtspr => { + let mut uses = vec![Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _))]; + uses + } + Opcode::Mtsr => { + let mut uses = vec![Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _))]; + uses + } + Opcode::Mtsrin => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Mulhw => { + let mut uses = vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Mulhwu => { + let mut uses = vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Mulli => { + let mut uses = vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))]; + uses + } + Opcode::Mullw => { + let mut uses = vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Nand => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Neg => { + let mut uses = vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))]; + uses + } + Opcode::Nor => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Or => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Orc => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Ori => { + let mut uses = vec![Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _))]; + uses + } + Opcode::Oris => { + let mut uses = vec![Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _))]; + uses + } + Opcode::PsqL => { + let mut uses = vec![]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::PsqLu => { + let mut uses = vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))]; + uses + } + Opcode::PsqLux => { + let mut uses = vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::PsqLx => { + let mut uses = vec![Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::PsqSt => { + let mut uses = vec![Field::frS(FPR(((self.code >> 21u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::PsqStu => { + let mut uses = vec![ + Field::frS(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ]; + uses + } + Opcode::PsqStux => { + let mut uses = vec![ + Field::frS(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::PsqStx => { + let mut uses = vec![ + Field::frS(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::PsAbs => { + let mut uses = vec![Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _))]; + uses + } + Opcode::PsAdd => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::PsCmpo0 => { + let mut uses = vec![Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::PsCmpo1 => { + let mut uses = vec![Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::PsCmpu0 => { + let mut uses = vec![Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::PsCmpu1 => { + let mut uses = vec![Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::PsDiv => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::PsMadd => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::PsMadds0 => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::PsMadds1 => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::PsMerge00 => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::PsMerge01 => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::PsMerge10 => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::PsMerge11 => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::PsMr => { + let mut uses = vec![Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _))]; + uses + } + Opcode::PsMsub => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::PsMul => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + ]; + uses + } + Opcode::PsMuls0 => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + ]; + uses + } + Opcode::PsMuls1 => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + ]; + uses + } + Opcode::PsNabs => { + let mut uses = vec![Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _))]; + uses + } + Opcode::PsNeg => { + let mut uses = vec![Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _))]; + uses + } + Opcode::PsNmadd => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::PsNmsub => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::PsRes => { + let mut uses = vec![Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _))]; + uses + } + Opcode::PsRsqrte => { + let mut uses = vec![Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _))]; + uses + } + Opcode::PsSel => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::PsSub => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::PsSum0 => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::PsSum1 => { + let mut uses = vec![ + Field::frA(FPR(((self.code >> 16u8) & 0x1f) as _)), + Field::frC(FPR(((self.code >> 6u8) & 0x1f) as _)), + Field::frB(FPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Rfi => { + let mut uses = vec![]; + uses + } + Opcode::Rlwimi => { + let mut uses = vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::SH(OpaqueU(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Rlwinm => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::SH(OpaqueU(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Rlwnm => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Sc => { + let mut uses = vec![]; + uses + } + Opcode::Slw => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Sraw => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Srawi => { + let mut uses = vec![Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _))]; + uses + } + Opcode::Srw => { + let mut uses = vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Stb => { + let mut uses = vec![Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Stbu => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Stbux => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Stbx => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Stfd => { + let mut uses = vec![Field::frS(FPR(((self.code >> 21u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Stfdu => { + let mut uses = vec![ + Field::frS(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Stfdux => { + let mut uses = vec![ + Field::frS(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Stfdx => { + let mut uses = vec![ + Field::frS(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Stfiwx => { + let mut uses = vec![ + Field::frS(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Stfs => { + let mut uses = vec![Field::frS(FPR(((self.code >> 21u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Stfsu => { + let mut uses = vec![ + Field::frS(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Stfsux => { + let mut uses = vec![ + Field::frS(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Stfsx => { + let mut uses = vec![ + Field::frS(FPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Sth => { + let mut uses = vec![Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Sthbrx => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Sthu => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Sthux => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Sthx => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Stmw => { + let mut uses = vec![Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Stswi => { + let mut uses = vec![Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Stswx => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Stw => { + let mut uses = vec![Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _))]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Stwbrx => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Stwcx_ => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Stwu => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Stwux => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Stwx => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + if ((self.code >> 16u8) & 0x1f) != 0 { + uses.push(Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))); + } + uses + } + Opcode::Subf => { + let mut uses = vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Subfc => { + let mut uses = vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Subfe => { + let mut uses = vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Subfic => { + let mut uses = vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))]; + uses + } + Opcode::Subfme => { + let mut uses = vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))]; + uses + } + Opcode::Subfze => { + let mut uses = vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))]; + uses + } + Opcode::Sync => { + let mut uses = vec![]; + uses + } + Opcode::Tlbie => { + let mut uses = vec![Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _))]; + uses + } + Opcode::Tlbsync => { + let mut uses = vec![]; + uses + } + Opcode::Tw => { + let mut uses = vec![ + Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Twi => { + let mut uses = vec![Field::rA(GPR(((self.code >> 16u8) & 0x1f) as _))]; + uses + } + Opcode::Xor => { + let mut uses = vec![ + Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), + Field::rB(GPR(((self.code >> 11u8) & 0x1f) as _)), + ]; + uses + } + Opcode::Xori => { + let mut uses = vec![Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _))]; + uses + } + Opcode::Xoris => { + let mut uses = vec![Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _))]; + uses + } + } + } + pub(crate) fn _suffix(&self) -> String { + match self.op { + Opcode::Illegal => String::new(), + Opcode::Add => { + let mut s = String::with_capacity(4); + if self.bit(21usize) { + s.push('o'); + } + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Addc => { + let mut s = String::with_capacity(4); + if self.bit(21usize) { + s.push('o'); + } + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Adde => { + let mut s = String::with_capacity(4); + if self.bit(21usize) { + s.push('o'); + } + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Addi => String::new(), + Opcode::Addic => String::new(), + Opcode::Addic_ => String::new(), + Opcode::Addis => String::new(), + Opcode::Addme => { + let mut s = String::with_capacity(4); + if self.bit(21usize) { + s.push('o'); + } + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Addze => { + let mut s = String::with_capacity(4); + if self.bit(21usize) { + s.push('o'); + } + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::And => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Andc => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Andi_ => String::new(), + Opcode::Andis_ => String::new(), + Opcode::B => { + let mut s = String::with_capacity(4); + if self.bit(30usize) { + s.push('a'); + } + if self.bit(31usize) { + s.push('l'); + } + s + } + Opcode::Bc => { + let mut s = String::with_capacity(4); + if self.bit(30usize) { + s.push('a'); + } + if self.bit(31usize) { + s.push('l'); + } + s + } + Opcode::Bcctr => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + s + } + Opcode::Bclr => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + s + } + Opcode::Cmp => String::new(), + Opcode::Cmpi => String::new(), + Opcode::Cmpl => String::new(), + Opcode::Cmpli => String::new(), + Opcode::Cntlzw => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Crand => String::new(), + Opcode::Crandc => String::new(), + Opcode::Creqv => String::new(), + Opcode::Crnand => String::new(), + Opcode::Crnor => String::new(), + Opcode::Cror => String::new(), + Opcode::Crorc => String::new(), + Opcode::Crxor => String::new(), + Opcode::Dcbf => String::new(), + Opcode::Dcbi => String::new(), + Opcode::Dcbst => String::new(), + Opcode::Dcbt => String::new(), + Opcode::Dcbtst => String::new(), + Opcode::Dcbz => String::new(), + Opcode::DcbzL => String::new(), + Opcode::Divw => { + let mut s = String::with_capacity(4); + if self.bit(21usize) { + s.push('o'); + } + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Divwu => { + let mut s = String::with_capacity(4); + if self.bit(21usize) { + s.push('o'); + } + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Eciwx => String::new(), + Opcode::Ecowx => String::new(), + Opcode::Eieio => String::new(), + Opcode::Eqv => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Extsb => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Extsh => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Fabs => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Fadd => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Fadds => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Fcmpo => String::new(), + Opcode::Fcmpu => String::new(), + Opcode::Fctiw => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Fctiwz => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Fdiv => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Fdivs => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Fmadd => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Fmadds => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Fmr => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Fmsub => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Fmsubs => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Fmul => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Fmuls => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Fnabs => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Fneg => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Fnmadd => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Fnmadds => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Fnmsub => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Fnmsubs => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Fres => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Frsp => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Frsqrte => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Fsel => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Fsub => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Fsubs => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Icbi => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Isync => String::new(), + Opcode::Lbz => String::new(), + Opcode::Lbzu => String::new(), + Opcode::Lbzux => String::new(), + Opcode::Lbzx => String::new(), + Opcode::Lfd => String::new(), + Opcode::Lfdu => String::new(), + Opcode::Lfdux => String::new(), + Opcode::Lfdx => String::new(), + Opcode::Lfs => String::new(), + Opcode::Lfsu => String::new(), + Opcode::Lfsux => String::new(), + Opcode::Lfsx => String::new(), + Opcode::Lha => String::new(), + Opcode::Lhau => String::new(), + Opcode::Lhaux => String::new(), + Opcode::Lhax => String::new(), + Opcode::Lhbrx => String::new(), + Opcode::Lhz => String::new(), + Opcode::Lhzu => String::new(), + Opcode::Lhzux => String::new(), + Opcode::Lhzx => String::new(), + Opcode::Lmw => String::new(), + Opcode::Lswi => String::new(), + Opcode::Lswx => String::new(), + Opcode::Lwarx => String::new(), + Opcode::Lwbrx => String::new(), + Opcode::Lwz => String::new(), + Opcode::Lwzu => String::new(), + Opcode::Lwzux => String::new(), + Opcode::Lwzx => String::new(), + Opcode::Mcrf => String::new(), + Opcode::Mcrfs => String::new(), + Opcode::Mcrxr => String::new(), + Opcode::Mfcr => String::new(), + Opcode::Mffs => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Mfmsr => String::new(), + Opcode::Mfspr => String::new(), + Opcode::Mfsr => String::new(), + Opcode::Mfsrin => String::new(), + Opcode::Mftb => String::new(), + Opcode::Mtcrf => String::new(), + Opcode::Mtfsb0 => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Mtfsb1 => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Mtfsf => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Mtfsfi => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Mtmsr => String::new(), + Opcode::Mtspr => String::new(), + Opcode::Mtsr => String::new(), + Opcode::Mtsrin => String::new(), + Opcode::Mulhw => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Mulhwu => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Mulli => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Mullw => { + let mut s = String::with_capacity(4); + if self.bit(21usize) { + s.push('o'); + } + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Nand => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Neg => { + let mut s = String::with_capacity(4); + if self.bit(21usize) { + s.push('o'); + } + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Nor => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Or => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Orc => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Ori => String::new(), + Opcode::Oris => String::new(), + Opcode::PsqL => String::new(), + Opcode::PsqLu => String::new(), + Opcode::PsqLux => String::new(), + Opcode::PsqLx => String::new(), + Opcode::PsqSt => String::new(), + Opcode::PsqStu => String::new(), + Opcode::PsqStux => String::new(), + Opcode::PsqStx => String::new(), + Opcode::PsAbs => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::PsAdd => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::PsCmpo0 => String::new(), + Opcode::PsCmpo1 => String::new(), + Opcode::PsCmpu0 => String::new(), + Opcode::PsCmpu1 => String::new(), + Opcode::PsDiv => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::PsMadd => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::PsMadds0 => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::PsMadds1 => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::PsMerge00 => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::PsMerge01 => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::PsMerge10 => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::PsMerge11 => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::PsMr => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::PsMsub => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::PsMul => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::PsMuls0 => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::PsMuls1 => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::PsNabs => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::PsNeg => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::PsNmadd => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::PsNmsub => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::PsRes => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::PsRsqrte => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::PsSel => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::PsSub => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::PsSum0 => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::PsSum1 => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Rfi => String::new(), + Opcode::Rlwimi => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Rlwinm => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Rlwnm => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Sc => String::new(), + Opcode::Slw => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Sraw => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Srawi => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Srw => { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Stb => String::new(), + Opcode::Stbu => String::new(), + Opcode::Stbux => String::new(), + Opcode::Stbx => String::new(), + Opcode::Stfd => String::new(), + Opcode::Stfdu => String::new(), + Opcode::Stfdux => String::new(), + Opcode::Stfdx => String::new(), + Opcode::Stfiwx => String::new(), + Opcode::Stfs => String::new(), + Opcode::Stfsu => String::new(), + Opcode::Stfsux => String::new(), + Opcode::Stfsx => String::new(), + Opcode::Sth => String::new(), + Opcode::Sthbrx => String::new(), + Opcode::Sthu => String::new(), + Opcode::Sthux => String::new(), + Opcode::Sthx => String::new(), + Opcode::Stmw => String::new(), + Opcode::Stswi => String::new(), + Opcode::Stswx => String::new(), + Opcode::Stw => String::new(), + Opcode::Stwbrx => String::new(), + Opcode::Stwcx_ => String::new(), + Opcode::Stwu => String::new(), + Opcode::Stwux => String::new(), + Opcode::Stwx => String::new(), + Opcode::Subf => { + let mut s = String::with_capacity(4); + if self.bit(21usize) { + s.push('o'); + } + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Subfc => { + let mut s = String::with_capacity(4); + if self.bit(21usize) { + s.push('o'); + } + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Subfe => { + let mut s = String::with_capacity(4); + if self.bit(21usize) { + s.push('o'); + } + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Subfic => String::new(), + Opcode::Subfme => { + let mut s = String::with_capacity(4); + if self.bit(21usize) { + s.push('o'); + } + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Subfze => { + let mut s = String::with_capacity(4); + if self.bit(21usize) { + s.push('o'); + } + if self.bit(31usize) { + s.push('.'); + } + s + } + Opcode::Sync => String::new(), + Opcode::Tlbie => String::new(), + Opcode::Tlbsync => String::new(), + Opcode::Tw => String::new(), + Opcode::Twi => String::new(), + Opcode::Xor => String::new(), + Opcode::Xori => String::new(), + Opcode::Xoris => String::new(), + } + } + pub(crate) fn _simplified(self) -> SimplifiedIns { + match self.op { + Opcode::Addi => { + if ((self.code >> 16u8) & 0x1f) == 0 { + return SimplifiedIns { + mnemonic: "li", + args: vec![ + Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), + Argument::Simm(Simm( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + ], + ins: self, + }; + } + } + Opcode::Addis => { + if ((self.code >> 16u8) & 0x1f) == 0 { + return SimplifiedIns { + mnemonic: "lis", + args: vec![ + Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), + Argument::Uimm(Uimm((self.code & 0xffff) as _)), + ], + ins: self, + }; + } + } + Opcode::Bc => { + if ((self.code >> 21u8) & 0x1f) == 12 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00 + && ((self.code >> 18u8) & 0x7) == 0 + { + return SimplifiedIns { + mnemonic: "blt", + args: vec![Argument::BranchDest(BranchDest( + (((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) << 2u8) + as _, + ))], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00 + { + return SimplifiedIns { + mnemonic: "blt", + args: vec![ + Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _)), + Argument::BranchDest(BranchDest( + (((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) + << 2u8) as _, + )), + ], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 4 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01 + && ((self.code >> 18u8) & 0x7) == 0 + { + return SimplifiedIns { + mnemonic: "ble", + args: vec![Argument::BranchDest(BranchDest( + (((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) << 2u8) + as _, + ))], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01 + { + return SimplifiedIns { + mnemonic: "ble", + args: vec![ + Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _)), + Argument::BranchDest(BranchDest( + (((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) + << 2u8) as _, + )), + ], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 12 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10 + && ((self.code >> 18u8) & 0x7) == 0 + { + return SimplifiedIns { + mnemonic: "beq", + args: vec![Argument::BranchDest(BranchDest( + (((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) << 2u8) + as _, + ))], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10 + { + return SimplifiedIns { + mnemonic: "beq", + args: vec![ + Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _)), + Argument::BranchDest(BranchDest( + (((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) + << 2u8) as _, + )), + ], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 4 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00 + && ((self.code >> 18u8) & 0x7) == 0 + { + return SimplifiedIns { + mnemonic: "bge", + args: vec![Argument::BranchDest(BranchDest( + (((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) << 2u8) + as _, + ))], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00 + { + return SimplifiedIns { + mnemonic: "bge", + args: vec![ + Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _)), + Argument::BranchDest(BranchDest( + (((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) + << 2u8) as _, + )), + ], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 12 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01 + && ((self.code >> 18u8) & 0x7) == 0 + { + return SimplifiedIns { + mnemonic: "bgt", + args: vec![Argument::BranchDest(BranchDest( + (((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) << 2u8) + as _, + ))], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01 + { + return SimplifiedIns { + mnemonic: "bgt", + args: vec![ + Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _)), + Argument::BranchDest(BranchDest( + (((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) + << 2u8) as _, + )), + ], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 4 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10 + && ((self.code >> 18u8) & 0x7) == 0 + { + return SimplifiedIns { + mnemonic: "bne", + args: vec![Argument::BranchDest(BranchDest( + (((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) << 2u8) + as _, + ))], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10 + { + return SimplifiedIns { + mnemonic: "bne", + args: vec![ + Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _)), + Argument::BranchDest(BranchDest( + (((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) + << 2u8) as _, + )), + ], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 12 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11 + && ((self.code >> 18u8) & 0x7) == 0 + { + return SimplifiedIns { + mnemonic: "bso", + args: vec![Argument::BranchDest(BranchDest( + (((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) << 2u8) + as _, + ))], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11 + { + return SimplifiedIns { + mnemonic: "bso", + args: vec![ + Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _)), + Argument::BranchDest(BranchDest( + (((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) + << 2u8) as _, + )), + ], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 4 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11 + && ((self.code >> 18u8) & 0x7) == 0 + { + return SimplifiedIns { + mnemonic: "bns", + args: vec![Argument::BranchDest(BranchDest( + (((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) << 2u8) + as _, + ))], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11 + { + return SimplifiedIns { + mnemonic: "bns", + args: vec![ + Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _)), + Argument::BranchDest(BranchDest( + (((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) + << 2u8) as _, + )), + ], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 16 && ((self.code >> 16u8) & 0x1f) == 0 { + return SimplifiedIns { + mnemonic: "bdnz", + args: vec![Argument::BranchDest(BranchDest( + (((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) << 2u8) + as _, + ))], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 18 && ((self.code >> 16u8) & 0x1f) == 0 { + return SimplifiedIns { + mnemonic: "bdz", + args: vec![Argument::BranchDest(BranchDest( + (((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) << 2u8) + as _, + ))], + ins: self, + }; + } + } + Opcode::Bcctr => { + if ((self.code >> 21u8) & 0x1f) == 20 && ((self.code >> 16u8) & 0x1f) == 0 { + return SimplifiedIns { + mnemonic: "bctr", + args: vec![], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 12 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00 + && ((self.code >> 18u8) & 0x7) == 0 + { + return SimplifiedIns { + mnemonic: "bltctr", + args: vec![], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00 + { + return SimplifiedIns { + mnemonic: "bltctr", + args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 4 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01 + && ((self.code >> 18u8) & 0x7) == 0 + { + return SimplifiedIns { + mnemonic: "blectr", + args: vec![], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01 + { + return SimplifiedIns { + mnemonic: "blectr", + args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 12 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10 + && ((self.code >> 18u8) & 0x7) == 0 + { + return SimplifiedIns { + mnemonic: "beqctr", + args: vec![], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10 + { + return SimplifiedIns { + mnemonic: "beqctr", + args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 4 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00 + && ((self.code >> 18u8) & 0x7) == 0 + { + return SimplifiedIns { + mnemonic: "bgectr", + args: vec![], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00 + { + return SimplifiedIns { + mnemonic: "bgectr", + args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 12 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01 + && ((self.code >> 18u8) & 0x7) == 0 + { + return SimplifiedIns { + mnemonic: "bgtctr", + args: vec![], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01 + { + return SimplifiedIns { + mnemonic: "bgtctr", + args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 4 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10 + && ((self.code >> 18u8) & 0x7) == 0 + { + return SimplifiedIns { + mnemonic: "bnectr", + args: vec![], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10 + { + return SimplifiedIns { + mnemonic: "bnectr", + args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 12 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11 + && ((self.code >> 18u8) & 0x7) == 0 + { + return SimplifiedIns { + mnemonic: "bsoctr", + args: vec![], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11 + { + return SimplifiedIns { + mnemonic: "bsoctr", + args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 4 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11 + && ((self.code >> 18u8) & 0x7) == 0 + { + return SimplifiedIns { + mnemonic: "bnsctr", + args: vec![], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11 + { + return SimplifiedIns { + mnemonic: "bnsctr", + args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))], + ins: self, + }; + } + } + Opcode::Bclr => { + if ((self.code >> 21u8) & 0x1f) == 20 && ((self.code >> 16u8) & 0x1f) == 0 { + return SimplifiedIns { + mnemonic: "blr", + args: vec![], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 12 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00 + && ((self.code >> 18u8) & 0x7) == 0 + { + return SimplifiedIns { + mnemonic: "bltlr", + args: vec![], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00 + { + return SimplifiedIns { + mnemonic: "bltlr", + args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 4 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01 + && ((self.code >> 18u8) & 0x7) == 0 + { + return SimplifiedIns { + mnemonic: "blelr", + args: vec![], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01 + { + return SimplifiedIns { + mnemonic: "blelr", + args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 12 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10 + && ((self.code >> 18u8) & 0x7) == 0 + { + return SimplifiedIns { + mnemonic: "beqlr", + args: vec![], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10 + { + return SimplifiedIns { + mnemonic: "beqlr", + args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 4 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00 + && ((self.code >> 18u8) & 0x7) == 0 + { + return SimplifiedIns { + mnemonic: "bgelr", + args: vec![], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00 + { + return SimplifiedIns { + mnemonic: "bgelr", + args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 12 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01 + && ((self.code >> 18u8) & 0x7) == 0 + { + return SimplifiedIns { + mnemonic: "bgtlr", + args: vec![], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01 + { + return SimplifiedIns { + mnemonic: "bgtlr", + args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 4 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10 + && ((self.code >> 18u8) & 0x7) == 0 + { + return SimplifiedIns { + mnemonic: "bnelr", + args: vec![], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10 + { + return SimplifiedIns { + mnemonic: "bnelr", + args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 12 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11 + && ((self.code >> 18u8) & 0x7) == 0 + { + return SimplifiedIns { + mnemonic: "bsolr", + args: vec![], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11 + { + return SimplifiedIns { + mnemonic: "bsolr", + args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 4 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11 + && ((self.code >> 18u8) & 0x7) == 0 + { + return SimplifiedIns { + mnemonic: "bnslr", + args: vec![], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11 + { + return SimplifiedIns { + mnemonic: "bnslr", + args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))], + ins: self, + }; + } + } + Opcode::Cmp => { + if ((self.code >> 23u8) & 0x7) == 0 { + return SimplifiedIns { + mnemonic: "cmpw", + args: vec![ + Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), + Argument::GPR(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + ins: self, + }; + } + } + Opcode::Cmpi => { + if ((self.code >> 23u8) & 0x7) == 0 { + return SimplifiedIns { + mnemonic: "cmpwi", + args: vec![ + Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), + Argument::Simm(Simm( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + ], + ins: self, + }; + } + if ((self.code >> 23u8) & 0x7) == 0 { + return SimplifiedIns { + mnemonic: "cmpwi", + args: vec![ + Argument::CRBit(CRBit(((self.code >> 23u8) & 0x7) as _)), + Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), + Argument::Simm(Simm( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + ], + ins: self, + }; + } + } + Opcode::Cmpl => { + if ((self.code >> 23u8) & 0x7) == 0 { + return SimplifiedIns { + mnemonic: "cmplw", + args: vec![ + Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), + Argument::GPR(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + ins: self, + }; + } + } + Opcode::Cmpli => { + if ((self.code >> 23u8) & 0x7) == 0 { + return SimplifiedIns { + mnemonic: "cmplwi", + args: vec![ + Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), + Argument::Uimm(Uimm((self.code & 0xffff) as _)), + ], + ins: self, + }; + } + if ((self.code >> 23u8) & 0x7) == 0 { + return SimplifiedIns { + mnemonic: "cmplwi", + args: vec![ + Argument::CRBit(CRBit(((self.code >> 23u8) & 0x7) as _)), + Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), + Argument::Uimm(Uimm((self.code & 0xffff) as _)), + ], + ins: self, + }; + } + } + Opcode::Mfspr => { + if ((self.code >> 11u8) & 0x3ff) == 1 { + return SimplifiedIns { + mnemonic: "mfxer", + args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + ins: self, + }; + } + if ((self.code >> 11u8) & 0x3ff) == 8 { + return SimplifiedIns { + mnemonic: "mflr", + args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + ins: self, + }; + } + if ((self.code >> 11u8) & 0x3ff) == 9 { + return SimplifiedIns { + mnemonic: "mfctr", + args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + ins: self, + }; + } + if ((self.code >> 11u8) & 0x3ff) == 18 { + return SimplifiedIns { + mnemonic: "mfdsisr", + args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + ins: self, + }; + } + if ((self.code >> 11u8) & 0x3ff) == 397 { + return SimplifiedIns { + mnemonic: "mfdbatu", + args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + ins: self, + }; + } + if ((self.code >> 11u8) & 0x3ff) == 571 { + return SimplifiedIns { + mnemonic: "mftdu", + args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + ins: self, + }; + } + } + Opcode::Mtspr => { + if ((self.code >> 11u8) & 0x3ff) == 1 { + return SimplifiedIns { + mnemonic: "mtxer", + args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + ins: self, + }; + } + if ((self.code >> 11u8) & 0x3ff) == 8 { + return SimplifiedIns { + mnemonic: "mtlr", + args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + ins: self, + }; + } + if ((self.code >> 11u8) & 0x3ff) == 9 { + return SimplifiedIns { + mnemonic: "mtctr", + args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + ins: self, + }; + } + if ((self.code >> 11u8) & 0x3ff) == 18 { + return SimplifiedIns { + mnemonic: "mtdsisr", + args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + ins: self, + }; + } + if ((self.code >> 11u8) & 0x3ff) == 397 { + return SimplifiedIns { + mnemonic: "mtdbatu", + args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + ins: self, + }; + } + if ((self.code >> 11u8) & 0x3ff) == 571 { + return SimplifiedIns { + mnemonic: "mttdu", + args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + ins: self, + }; + } + } + Opcode::Or => { + if ((self.code >> 21u8) & 0x1f) == ((self.code >> 11u8) & 0x1f) { + return SimplifiedIns { + mnemonic: "mr", + args: vec![ + Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), + Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), + ], + ins: self, + }; + } + } + Opcode::Ori => { + if ((self.code >> 16u8) & 0x1f) == 0 + && ((self.code >> 21u8) & 0x1f) == 0 + && (self.code & 0xffff) == 0 + { + return SimplifiedIns { + mnemonic: "nop", + args: vec![], + ins: self, + }; + } + } + Opcode::Rlwinm => { + if ((self.code >> 11u8) & 0x1f) == 0 && ((self.code >> 1u8) & 0x1f) == 31 { + return SimplifiedIns { + mnemonic: "clrlwi", + args: vec![ + Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), + Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), + Argument::OpaqueU(OpaqueU(((self.code >> 6u8) & 0x1f) as _)), + ], + ins: self, + }; + } + if ((self.code >> 6u8) & 0x1f) == 0 && ((self.code >> 1u8) & 0x1f) == 31 { + return SimplifiedIns { + mnemonic: "rotlwi", + args: vec![ + Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), + Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), + Argument::OpaqueU(OpaqueU(((self.code >> 11u8) & 0x1f) as _)), + ], + ins: self, + }; + } + if ((self.code >> 6u8) & 0x1f) == 0 + && 31 - ((self.code >> 11u8) & 0x1f) == ((self.code >> 1u8) & 0x1f) + { + return SimplifiedIns { + mnemonic: "slwi", + args: vec![ + Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), + Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), + Argument::OpaqueU(OpaqueU(((self.code >> 1u8) & 0x1f) as _)), + ], + ins: self, + }; + } + if ((self.code >> 1u8) & 0x1f) == 31 + && 32 - ((self.code >> 6u8) & 0x1f) == ((self.code >> 11u8) & 0x1f) + { + return SimplifiedIns { + mnemonic: "srwi", + args: vec![ + Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), + Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), + Argument::OpaqueU(OpaqueU(((self.code >> 6u8) & 0x1f) as _)), + ], + ins: self, + }; + } + } + Opcode::Twi => { + if ((self.code >> 21u8) & 0x1f) == 8 { + return SimplifiedIns { + mnemonic: "twgti", + args: vec![ + Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), + Argument::Simm(Simm( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + ], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) == 6 { + return SimplifiedIns { + mnemonic: "twllei", + args: vec![ + Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), + Argument::Simm(Simm( + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _, + )), + ], + ins: self, + }; + } + } + _ => {} + } + SimplifiedIns::basic_form(self) + } +} +#[allow(clippy::all, non_snake_case)] +impl Ins { + #[inline(always)] + pub fn field_simm(&self) -> isize { + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _ + } + #[inline(always)] + pub fn field_uimm(&self) -> usize { + (self.code & 0xffff) as _ + } + #[inline(always)] + pub fn field_offset(&self) -> isize { + (((self.code & 0xffff) ^ 0x8000).wrapping_sub(0x8000)) as _ + } + #[inline(always)] + pub fn field_BO(&self) -> usize { + ((self.code >> 21u8) & 0x1f) as _ + } + #[inline(always)] + pub fn field_BI(&self) -> usize { + ((self.code >> 16u8) & 0x1f) as _ + } + #[inline(always)] + pub fn field_BD(&self) -> isize { + (((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) << 2u8) as _ + } + #[inline(always)] + pub fn field_LI(&self) -> isize { + (((((self.code >> 2u8) & 0xffffff) ^ 0x800000).wrapping_sub(0x800000)) << 2u8) as _ + } + #[inline(always)] + pub fn field_SH(&self) -> usize { + ((self.code >> 11u8) & 0x1f) as _ + } + #[inline(always)] + pub fn field_MB(&self) -> usize { + ((self.code >> 6u8) & 0x1f) as _ + } + #[inline(always)] + pub fn field_ME(&self) -> usize { + ((self.code >> 1u8) & 0x1f) as _ + } + #[inline(always)] + pub fn field_rS(&self) -> usize { + ((self.code >> 21u8) & 0x1f) as _ + } + #[inline(always)] + pub fn field_rD(&self) -> usize { + ((self.code >> 21u8) & 0x1f) as _ + } + #[inline(always)] + pub fn field_rA(&self) -> usize { + ((self.code >> 16u8) & 0x1f) as _ + } + #[inline(always)] + pub fn field_rB(&self) -> usize { + ((self.code >> 11u8) & 0x1f) as _ + } + #[inline(always)] + pub fn field_rC(&self) -> usize { + ((self.code >> 6u8) & 0x1f) as _ + } + #[inline(always)] + pub fn field_sr(&self) -> usize { + ((self.code >> 16u8) & 0xf) as _ + } + #[inline(always)] + pub fn field_spr(&self) -> usize { + ((self.code >> 11u8) & 0x3ff) as _ + } + #[inline(always)] + pub fn field_frS(&self) -> usize { + ((self.code >> 21u8) & 0x1f) as _ + } + #[inline(always)] + pub fn field_frD(&self) -> usize { + ((self.code >> 21u8) & 0x1f) as _ + } + #[inline(always)] + pub fn field_frA(&self) -> usize { + ((self.code >> 16u8) & 0x1f) as _ + } + #[inline(always)] + pub fn field_frB(&self) -> usize { + ((self.code >> 11u8) & 0x1f) as _ + } + #[inline(always)] + pub fn field_frC(&self) -> usize { + ((self.code >> 6u8) & 0x1f) as _ + } + #[inline(always)] + pub fn field_crbD(&self) -> usize { + ((self.code >> 21u8) & 0x1f) as _ + } + #[inline(always)] + pub fn field_crbA(&self) -> usize { + ((self.code >> 16u8) & 0x1f) as _ + } + #[inline(always)] + pub fn field_crbB(&self) -> usize { + ((self.code >> 11u8) & 0x1f) as _ + } + #[inline(always)] + pub fn field_crfD(&self) -> usize { + ((self.code >> 23u8) & 0x7) as _ + } + #[inline(always)] + pub fn field_crfS(&self) -> usize { + ((self.code >> 18u8) & 0x7) as _ + } + #[inline(always)] + pub fn field_crm(&self) -> usize { + ((self.code >> 12u8) & 0xff) as _ + } + #[inline(always)] + pub fn field_ps_l(&self) -> usize { + ((self.code >> 12u8) & 0x7) as _ + } + #[inline(always)] + pub fn field_ps_W(&self) -> usize { + ((self.code >> 16u8) & 0x0) as _ + } + #[inline(always)] + pub fn field_NB(&self) -> usize { + ((self.code >> 11u8) & 0x1f) as _ + } + #[inline(always)] + pub fn field_tbr(&self) -> usize { + ((self.code >> 11u8) & 0x3ff) as _ + } + #[inline(always)] + pub fn field_mtfsf_FM(&self) -> usize { + ((self.code >> 17u8) & 0xff) as _ + } + #[inline(always)] + pub fn field_mtfsf_IMM(&self) -> usize { + ((self.code >> 12u8) & 0xf) as _ + } + #[inline(always)] + pub fn field_TO(&self) -> usize { + ((self.code >> 21u8) & 0x1f) as _ + } + #[inline(always)] + pub fn field_OE(&self) -> bool { + self.bit(21usize) + } + #[inline(always)] + pub fn field_Rc(&self) -> bool { + self.bit(31usize) + } + #[inline(always)] + pub fn field_LK(&self) -> bool { + self.bit(31usize) + } + #[inline(always)] + pub fn field_AA(&self) -> bool { + self.bit(30usize) + } +} diff --git a/disasm/src/isa.rs b/disasm/src/isa.rs deleted file mode 100644 index dd646a7..0000000 --- a/disasm/src/isa.rs +++ /dev/null @@ -1,570 +0,0 @@ -#![allow(clippy::bad_bit_mask)] - -use crate::{bit, bits}; -use ppc750cl_macros::isa; - -isa! { - "add" & 0xfc0007fe == 0x7c000214; - //"addc" & 0xfc0007fe == 0x7c00002a; - "addc" & 0x0 == 0x0; - "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; - "bc" & 0x0 == 0x0; // TODO - //"bcctr" & 0xfc00ffff == 0x4c000210; - "bcctr" & 0x0 == 0x0; // TODO - "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; - "fabs" & 0x0 == 0x0; // TODO - "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; - "fneg" & 0x0 == 0x0; // TODO - "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; - "lfdx" & 0x0 == 0x0; - "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; - "mffs" & 0x0 == 0x0; // TODO - "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; - "mulhw" & 0x0 == 0x0; - //"mulhwu" & 0xfc0007fe == 0x7c000016; - "mulhwu" & 0x0 == 0x0; - "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; -} - -impl Opcode { - pub const BLR: u32 = 0x4c000020; - - pub fn from_code(x: u32) -> Self { - let op = match bits(x, 0..6) { - 0b000011 => Opcode::Twi, - 0b000100 => Self::from_code_cl_ext(x), - 0b000111..=0b001111 => Self::from_code_basic1(x), - 0b010000 => Opcode::Bc, - 0b010001 => Opcode::Sc, - 0b010010 => Opcode::B, - 0b010011 => Self::from_code_010011(x), - 0b010100..=0b011101 => Self::from_code_basic2(x), - 0b011111 => Self::from_code_011111(x), - 0b100000..=0b110111 => Self::from_code_basic3(x), - 0b111000..=0b111001 => Self::from_code_psq(x), - 0b111011 => Self::from_code_111011(x), - 0b111100..=0b111101 => Self::from_code_psq(x), - 0b111111 => Self::from_code_111111(x), - _ => Opcode::Illegal, - }; - if !op.is_valid(x) { - return Opcode::Illegal; - } - op - } - - fn from_code_cl_ext(x: u32) -> Self { - match bits(x, 26..31) { - 0b00000 => match bits(x, 21..26) { - 0b00000 => Opcode::PsCmpu0, - 0b00001 => Opcode::PsCmpo0, - 0b00010 => Opcode::PsCmpu1, - 0b00011 => Opcode::PsCmpo1, - _ => Opcode::Illegal, - }, - 0b00110 => { - if bit(x, 25) == 0 { - Opcode::PsqLx - } else { - 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, 21..26) { - 0b00001 => Opcode::PsNeg, - 0b00010 => Opcode::PsMr, - 0b00100 => Opcode::PsNabs, - 0b01000 => Opcode::PsAbs, - _ => Opcode::Illegal, - }, - 0b10000 => match bits(x, 21..26) { - 0b10000 => Opcode::PsMerge00, - 0b10001 => Opcode::PsMerge01, - 0b10010 => Opcode::PsMerge10, - 0b10011 => Opcode::PsMerge11, - _ => Opcode::Illegal, - }, - 0b10110 => Opcode::DcbzL, - // Unknown paired-singles key. - _ => Opcode::Illegal, - } - } - - fn from_code_basic1(x: u32) -> Self { - 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, - } - } - - fn from_code_010011(x: u32) -> Self { - 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, - } - } - - fn from_code_basic2(x: u32) -> Self { - match bits(x, 0..6) { - 0b10100 => Opcode::Rlwimi, - 0b10101 => Opcode::Rlwinm, - 0b10111 => Opcode::Rlwnm, - 0b11000 => Opcode::Ori, - 0b11001 => Opcode::Oris, - 0b11010 => Opcode::Xori, - 0b11011 => Opcode::Xoris, - 0b11100 => Opcode::Andi_, - 0b11101 => Opcode::Andis_, - _ => Opcode::Illegal, - } - } - - fn from_code_011111(x: u32) -> Self { - 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_1011 => 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_0001_0110 => Opcode::Dcbt, - 0b01_0001_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_1110_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, - } - } - - fn from_code_basic3(x: u32) -> Self { - match bits(x, 0..6) { - 0b100000 => Opcode::Lwz, - 0b100001 => Opcode::Lwzu, - 0b100010 => Opcode::Lbz, - 0b100011 => Opcode::Lbzu, - 0b100100 => Opcode::Stw, - 0b100101 => Opcode::Stwu, - 0b100110 => Opcode::Stb, - 0b100111 => Opcode::Stbu, - 0b101000 => Opcode::Lhz, - 0b101001 => Opcode::Lhzu, - 0b101010 => Opcode::Lha, - 0b101011 => Opcode::Lhau, - 0b101100 => Opcode::Sth, - 0b101101 => Opcode::Sthu, - 0b101110 => Opcode::Lmw, - 0b101111 => Opcode::Stmw, - 0b110000 => Opcode::Lfs, - 0b110001 => Opcode::Lfsu, - 0b110010 => Opcode::Lfd, - 0b110011 => Opcode::Lfdu, - 0b110100 => Opcode::Stfs, - 0b110101 => Opcode::Stfsu, - 0b110110 => Opcode::Stfd, - 0b110111 => Opcode::Stfdu, - _ => disasm_unreachable!(x), - } - } - - fn from_code_psq(x: u32) -> Self { - match bits(x, 0..6) { - 0b111000 => Opcode::PsqL, - 0b111001 => Opcode::PsqLu, - 0b111100 => Opcode::PsqSt, - 0b111101 => Opcode::PsqStu, - _ => disasm_unreachable!(x), - } - } - - fn from_code_111011(x: u32) -> Self { - 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, - } - } - - fn from_code_111111(x: u32) -> Self { - match bits::(x, 26..31) { - 0b00000 => match bits(x, 24..26) { - 0b00 => Opcode::Fcmpu, - 0b01 => Opcode::Fcmpo, - 0b10 => Opcode::Mcrfs, - _ => Opcode::Illegal, - }, - 0b00110 => match bits(x, 23..26) { - 0b001 => Opcode::Mtfsb1, - 0b010 => Opcode::Mtfsb0, - 0b100 => Opcode::Mtfsfi, - _ => Opcode::Illegal, - }, - 0b00111 => match bits(x, 21..26) { - 0b10010 => Opcode::Mffs, - 0b10110 => Opcode::Mtfsf, - _ => Opcode::Illegal, - }, - 0b01000 => match bits(x, 22..26) { - 0b0001 => Opcode::Fneg, - 0b0010 => Opcode::Fmr, - 0b0100 => Opcode::Fnabs, - 0b1000 => Opcode::Fabs, - _ => 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, - } - } -} diff --git a/disasm/src/lib.rs b/disasm/src/lib.rs index b373b39..7f14e1e 100644 --- a/disasm/src/lib.rs +++ b/disasm/src/lib.rs @@ -1,33 +1,69 @@ -#![allow(clippy::unusual_byte_groupings)] - -use std::io::Write; +use std::fmt::{Display, Formatter, LowerHex, UpperHex, Write}; use std::ops::Range; -use num_traits::AsPrimitive; +use num_traits::{AsPrimitive, PrimInt}; -use ppc750cl_macros::write_asm; - -#[macro_use] -mod macros; -pub mod formatter; -mod isa; -mod iter; - -pub use crate::formatter::AsmFormatter; -use crate::formatter::SimpleFormatter; -pub use crate::isa::Opcode; pub use crate::iter::{disasm_iter, DisasmIterator}; -#[derive(Default, Clone)] -pub struct Ins { - pub code: u32, - pub addr: u32, - pub op: Opcode, +pub mod formatter; +mod generated; +mod iter; +pub use generated::*; + +pub mod prelude { + pub use crate::formatter::FormattedIns; + pub use crate::Argument; + pub use crate::Field::*; + pub use crate::Ins; + pub use crate::Opcode::*; + pub use crate::SimplifiedIns; + pub use crate::{ + Bit, BranchDest, CRBit, CRField, Offset, OpaqueU, Simm, Uimm, FPR, GPR, GQR, SPR, SR, + }; +} + +macro_rules! field_arg_no_display { + ($name:ident, $typ:ident) => { + #[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)] + pub struct $name(pub $typ); + impl std::convert::From<$name> for Argument { + fn from(x: $name) -> Argument { + Argument::$name(x) + } + } + }; +} + +macro_rules! field_arg { + ($name:ident, $typ:ident) => { + field_arg_no_display!($name, $typ); + impl Display for $name { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } + } + }; + ($name:ident, $typ:ident, $format:literal) => { + field_arg_no_display!($name, $typ); + impl Display for $name { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, $format, self.0) + } + } + }; + ($name:ident, $typ:ident, $format:literal, $format_arg:expr) => { + field_arg_no_display!($name, $typ); + impl Display for $name { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, $format, $format_arg(self.0)) + } + } + }; } #[inline(always)] -fn bit(x: u32, idx: usize) -> u8 { - ((x >> (32 - idx - 1)) & 1) as u8 +fn bit(x: u32, idx: usize) -> bool { + ((x >> (32 - idx - 1)) & 1) == 1 } #[inline(always)] @@ -40,122 +76,221 @@ where masked.as_() } -macro_rules! ins_bit { - ($func:ident, $idx:expr) => { - #[inline(always)] - pub fn $func(&self) -> u8 { - bit(self.code, $idx) - } - }; +// https://stackoverflow.com/questions/44711012/how-do-i-format-a-signed-integer-to-a-sign-aware-hexadecimal-representation +struct ReallySigned(N); + +impl LowerHex for ReallySigned { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let num = self.0.to_i32().unwrap(); + let prefix = if f.alternate() { "0x" } else { "" }; + let bare_hex = format!("{:x}", num.abs()); + f.pad_integral(num >= 0, prefix, &bare_hex) + } } -macro_rules! ins_ufield { - ($func:ident, $return_type:ident, $range:expr) => { - #[inline(always)] - pub fn $func(&self) -> $return_type { - debug_assert!( - ($range).len() / 8 <= (std::mem::size_of::<$return_type>()), - "{:?} does not fit in {}", - $range, - stringify!($return_type) - ); - bits(self.code, $range) - } - }; +impl UpperHex for ReallySigned { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let num = self.0.to_i32().unwrap(); + let prefix = if f.alternate() { "0x" } else { "" }; + let bare_hex = format!("{:X}", num.abs()); + f.pad_integral(num >= 0, prefix, &bare_hex) + } } -macro_rules! ins_ifield { - ($func:ident, $range:expr) => { - #[inline(always)] - pub fn $func(&self) -> i32 { - debug_assert!( - ($range).len() / 8 <= (std::mem::size_of::()), - "{:?} does not fit in {}", - $range, - stringify!(i32) - ); - let mut x = bits::(self.code, $range); - if x >> (($range).len() - 1) == 1 { - x = (x ^ ((1 << ($range).len()) - 1)) + 1; - return -(x as i32); - } - x as i32 +// General-purpose register. +field_arg!(GPR, u8, "r{}"); +// Floating-point register (direct or paired-singles mode). +field_arg!(FPR, u8, "f{}"); +// Segment register. +field_arg!(SR, u8); +// Special-purpose register. +field_arg!(SPR, u16); +// Condition register field. +field_arg!(CRField, u8, "crb{}"); +// Condition register bit (index + condition case). +field_arg!(CRBit, u8, "cr{}"); +// Paired-single graphics quantization register +field_arg!(GQR, u8, "qr{}"); +// Unsigned immediate. +field_arg!(Uimm, u16, "{:#x}"); +// Signed immediate. +field_arg!(Simm, i16, "{:#x}", ReallySigned); +// Offset for indirect memory reference. +field_arg!(Offset, i16, "{:#x}", ReallySigned); +// Branch destination. +field_arg!(BranchDest, i32, "{:#x}", ReallySigned); +// Opaque zero or one argument. +field_arg_no_display!(Bit, bool); +impl Display for Bit { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.write_char(if self.0 { '1' } else { '0' }) + } +} +// Unsigned opaque argument. +field_arg!(OpaqueU, u32); + +#[derive(Debug, Clone)] +pub enum Argument { + GPR(GPR), + FPR(FPR), + SR(SR), + SPR(SPR), + CRField(CRField), + CRBit(CRBit), + GQR(GQR), + Uimm(Uimm), + Simm(Simm), + Offset(Offset), + BranchDest(BranchDest), + Bit(Bit), + OpaqueU(OpaqueU), +} + +impl Display for Argument { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + Argument::GPR(x) => x.fmt(f), + Argument::FPR(x) => x.fmt(f), + Argument::SR(x) => x.fmt(f), + Argument::SPR(x) => x.fmt(f), + Argument::CRField(x) => x.fmt(f), + Argument::CRBit(x) => x.fmt(f), + Argument::GQR(x) => x.fmt(f), + Argument::Uimm(x) => x.fmt(f), + Argument::Simm(x) => x.fmt(f), + Argument::Offset(x) => x.fmt(f), + Argument::BranchDest(x) => x.fmt(f), + Argument::Bit(x) => x.fmt(f), + Argument::OpaqueU(x) => x.fmt(f), } - }; - ($func:ident, $range:expr, $shift:literal) => { - #[inline(always)] - pub fn $func(&self) -> i32 { - debug_assert!( - ($range).len() / 8 <= (std::mem::size_of::()), - "{:?} does not fit in {}", - $range, - stringify!(i32) - ); - let mut x = bits::(self.code, $range); - if x >> (($range).len() - 1) == 1 { - x = (x ^ ((1 << ($range).len()) - 1)) + 1; - return -((x << $shift) as i32); - } - (x << $shift) as i32 + } +} + +impl Field { + pub fn argument(&self) -> Option { + match self { + Field::simm(x) => Some(Argument::Simm(*x)), + Field::uimm(x) => Some(Argument::Uimm(*x)), + Field::offset(x) => Some(Argument::Offset(*x)), + Field::BO(x) => Some(Argument::OpaqueU(*x)), + Field::BI(x) => Some(Argument::OpaqueU(*x)), + Field::BD(x) => Some(Argument::BranchDest(*x)), + Field::LI(x) => Some(Argument::BranchDest(*x)), + Field::SH(x) => Some(Argument::OpaqueU(*x)), + Field::MB(x) => Some(Argument::OpaqueU(*x)), + Field::ME(x) => Some(Argument::OpaqueU(*x)), + Field::rS(x) => Some(Argument::GPR(*x)), + Field::rD(x) => Some(Argument::GPR(*x)), + Field::rA(x) => Some(Argument::GPR(*x)), + Field::rB(x) => Some(Argument::GPR(*x)), + Field::rC(x) => Some(Argument::GPR(*x)), + Field::sr(x) => Some(Argument::SR(*x)), + Field::spr(x) => Some(Argument::SPR(*x)), + Field::frS(x) => Some(Argument::FPR(*x)), + Field::frD(x) => Some(Argument::FPR(*x)), + Field::frA(x) => Some(Argument::FPR(*x)), + Field::frB(x) => Some(Argument::FPR(*x)), + Field::frC(x) => Some(Argument::FPR(*x)), + Field::crbD(x) => Some(Argument::CRField(*x)), + Field::crbA(x) => Some(Argument::CRField(*x)), + Field::crbB(x) => Some(Argument::CRField(*x)), + Field::crfD(x) => Some(Argument::CRBit(*x)), + Field::crfS(x) => Some(Argument::CRBit(*x)), + Field::crm(x) => Some(Argument::OpaqueU(*x)), + Field::ps_l(x) => Some(Argument::GQR(*x)), + Field::ps_W(x) => Some(Argument::OpaqueU(*x)), + Field::NB(x) => Some(Argument::OpaqueU(*x)), + Field::tbr(x) => Some(Argument::OpaqueU(*x)), + Field::mtfsf_FM(x) => Some(Argument::OpaqueU(*x)), + Field::mtfsf_IMM(x) => Some(Argument::OpaqueU(*x)), + Field::TO(x) => Some(Argument::OpaqueU(*x)), + _ => None, } - }; + } +} + +impl Opcode { + /// Detects the opcode of a machine code instruction. + pub fn detect(code: u32) -> Self { + Self::_detect(code) // auto-generated + } + + /// Prints the basic mnemonic of an opcode. + pub fn mnemonic(self) -> &'static str { + self._mnemonic() // auto-generated + } +} + +impl Default for Opcode { + fn default() -> Self { + Opcode::Illegal + } +} + +impl std::string::ToString for Opcode { + fn to_string(&self) -> String { + let mnemonic = self.mnemonic(); + mnemonic.to_owned() + } +} + +/// A PowerPC 750CL instruction. +#[derive(Default, Clone, Debug, Eq, PartialEq)] +pub struct Ins { + pub code: u32, + pub addr: u32, + pub op: Opcode, } impl Ins { - /// Reads an instruction given a machine code and its address. + /// Constructs an instruction from the given machine code and address. pub fn new(code: u32, addr: u32) -> Self { - let op = Opcode::from_code(code); - Self { code, addr, op } + Self { + code, + addr, + op: Opcode::detect(code), + } } - //ins_bit!(w, 21); - ins_bit!(rc, 31); - ins_bit!(aa, 30); - ins_bit!(lk, 31); - ins_bit!(l, 10); - ins_bit!(oe, 21); - ins_bit!(w, 16); - - // Registers - ins_ufield!(s, u8, 6..11); - ins_ufield!(d, u8, 6..11); - ins_ufield!(a, u8, 11..16); - ins_ufield!(b, u8, 16..21); - ins_ufield!(c, u8, 21..26); - // Condition registers - ins_ufield!(crb_d, u8, 6..11); - ins_ufield!(crb_a, u8, 11..16); - ins_ufield!(crb_b, u8, 16..21); - - ins_ufield!(crm, u8, 12..20); - ins_ufield!(sr, u8, 12..16); - pub fn spr(&self) -> u16 { - bits::(self.code, 11..16) | (bits::(self.code, 16..21) << 5) + /// Returns the simplified representation of an instruction. + pub fn simplified(self) -> SimplifiedIns { + self._simplified() // auto-generated } - ins_ufield!(fm, u16, 7..15); - ins_ufield!(crf_d, u8, 6..9); - ins_ufield!(crf_s, u8, 11..14); - ins_ifield!(simm, 16..32); - ins_ufield!(uimm, u16, 16..32); - ins_ufield!(bo, u8, 6..11); - ins_ufield!(bi, u8, 11..16); - ins_ufield!(sh, u8, 16..21); - ins_ufield!(mb, u8, 21..26); - ins_ufield!(me, u8, 26..31); - pub fn me_31sub(&self) -> u8 { - 31 - self.me() + + /// Gets the fields of an instruction. + pub fn fields(&self) -> Vec { + self._fields() // auto-generated + } + + /// Gets the suffix of an instruction mnemonic. + pub fn suffix(&self) -> String { + self._suffix() // auto-generated + } + + /// Gets the defs of an instruction. + pub fn defs(&self) -> Vec { + self._defs() // auto-generated + } + + /// Gets the uses of an instruction. + pub fn uses(&self) -> Vec { + self._uses() // auto-generated + } + + /// Gets the given bit from the machine code instruction. + pub fn bit(&self, idx: usize) -> bool { + bit(self.code, idx) + } + + /// Gets the given range of btis from the machine code instruction. + pub fn bits(&self, range: Range) -> u32 { + bits(self.code, range) } - ins_ifield!(bd, 16..30, 2); - ins_ifield!(li, 6..30, 2); - ins_ufield!(to, u8, 6..11); - // Paired-single fields. - ins_ufield!(ps_l, u8, 17..20); - ins_ifield!(ps_d, 20..32); pub fn branch_offset(&self) -> Option { match self.op { - Opcode::B => Some(self.li()), - Opcode::Bc | Opcode::Bcctr | Opcode::Bclr => Some(self.bd()), + Opcode::B => Some(self.field_LI() as i32), + Opcode::Bc | Opcode::Bcctr | Opcode::Bclr => Some(self.field_BD() as i32), _ => None, } } @@ -169,1735 +304,48 @@ impl Ins { } }) } +} - fn write_asm_mtfsfi(&self, out: &mut F) -> std::io::Result<()> - where - F: AsmFormatter, - W: Write, - { - out.write_mnemonic(self.op.mnemonic())?; - out.write_opcode_separator()?; - out.write_cr(self.crf_d())?; - out.write_operand_separator()?; - write!(out.writer(), "{}", bits::(self.code, 16..20))?; - Ok(()) - } +/// A simplified PowerPC 750CL instruction. +pub struct SimplifiedIns { + pub ins: Ins, + pub mnemonic: &'static str, + pub args: Vec, +} - // Ported from - // https://github.com/dolphin-emu/dolphin/blob/master/Source/Core/Common/GekkoDisassembler.cpp - #[inline(always)] - fn write_asm_branch(&self, out: &mut F, bname: &str) -> std::io::Result<()> - where - F: AsmFormatter, - W: Write, - { - if self.bo() & 4 != 0 { - if self.bo() & 16 != 0 { - return if self.bi() == 0 { - out.write_mnemonic(&("b".to_owned() + bname))?; - out.write_lk(self.lk())?; - out.write_aa(self.aa())?; - Ok(()) - } else { - write_asm!(out, self => { - (op.mnemonic, lk, aa): mnemonic; - bo: mode; - bi: mode; - bd: branch_target; - }) - }; - } else { - let condition = (bit(self.code, 7) << 2) | (bits::(self.code, 14..16)); - let mnemonic_base = match condition { - 0 => "bge", - 1 => "ble", - 2 => "bne", - 3 => "bns", - 4 => "blt", - 5 => "bgt", - 6 => "beq", - _ => { - return write_asm!(out, self => { - (op.mnemonic, lk, aa): mnemonic; - bo: mode; - bi: mode; - bd: branch_target; - }) - } - }; - // TODO avoid string concatenation - out.write_mnemonic(&(mnemonic_base.to_owned() + bname))?; - out.write_lk(self.lk())?; - out.write_aa(self.aa())?; - if bname.is_empty() { - out.write_opcode_separator()?; - if self.crf_s() != 0 { - out.write_cr(self.bi() >> 2)?; - out.write_operand_separator()?; - } - out.write_branch_target(self.bd(), self.addr)?; - } else if self.crf_s() != 0 { - out.write_opcode_separator()?; - out.write_cr(self.bi() >> 2)?; - } +impl Display for SimplifiedIns { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}{} ", self.mnemonic, self.ins.suffix())?; + let mut writing_offset = false; + for (i, argument) in self.args.iter().enumerate() { + write!(f, "{}", argument)?; + if let Argument::Offset(_) = argument { + write!(f, "(")?; + writing_offset = true; + continue; } - } else { - let mnemonic_base = match self.bo() >> 1 { - 0 => "bdnzf", - 1 => "bdnf", - 4 => "bdnzt", - 5 => "bdzt", - 8 | 12 => "bdnz", - 9 | 13 => "bdz", - _ => { - return write_asm!(out, self => { - (op.mnemonic, lk, aa): mnemonic; - bo: mode; - bi: mode; - bd: branch_target; - }) - } - }; - // TODO avoid string concatenation - out.write_mnemonic(&(mnemonic_base.to_owned() + bname))?; - out.write_lk(self.lk())?; - out.write_aa(self.aa())?; - if bname.is_empty() { - out.write_opcode_separator()?; - if (self.bo() & 16) == 0 { - out.write_mode(self.bi())?; - out.write_operand_separator()?; - } - out.write_branch_target(self.bd(), self.addr)?; - } else if (self.bo() & 16) == 0 { - out.write_opcode_separator()?; - out.write_mode(self.bi())?; + if writing_offset { + write!(f, ")")?; + writing_offset = false; + } + if i != self.args.len() - 1 { + write!(f, ", ")?; } } Ok(()) } - - fn write_asm_cmp(&self, out: &mut F) -> std::io::Result<()> - where - F: AsmFormatter, - W: Write, - { - match (self.op, self.crf_d(), self.l()) { - (Opcode::Cmp, 0, 0) => { - return write_asm!(out, self => { - "cmpw": mnemonic; - a: gpr; - b: gpr; - }) - } - (Opcode::Cmp, _, 0) => { - return write_asm!(out, self => { - "cmpw": mnemonic; - crf_d: cr; - a: gpr; - b: gpr; - }) - } - (Opcode::Cmpl, 0, 0) => { - return write_asm!(out, self => { - "cmplw": mnemonic; - a: gpr; - b: gpr; - }) - } - (Opcode::Cmpl, _, 0) => { - return write_asm!(out, self => { - "cmplw": mnemonic; - crf_d: cr; - a: gpr; - b: gpr; - }) - } - _ => (), - } - write_asm!(out, self => { - (op.mnemonic): mnemonic; - crf_d: cr; - l: mode; - a: gpr; - b: gpr; - }) - } - - fn write_asm_cmp_simm(&self, out: &mut F) -> std::io::Result<()> - where - F: AsmFormatter, - W: Write, - { - match (self.op, self.crf_d(), self.l()) { - (Opcode::Cmpi, 0, 0) => { - return write_asm!(out, self => { - "cmpwi": mnemonic; - a: gpr; - simm: simm; - }) - } - (Opcode::Cmpi, _, 0) => { - return write_asm!(out, self => { - "cmpwi": mnemonic; - crf_d: cr; - a: gpr; - simm: simm; - }) - } - _ => (), - } - write_asm!(out, self => { - (op.mnemonic): mnemonic; - crf_d: cr; - l: mode; - a: gpr; - simm: simm; - }) - } - - fn write_asm_cmp_uimm(&self, out: &mut F) -> std::io::Result<()> - where - F: AsmFormatter, - W: Write, - { - match (self.op, self.crf_d(), self.l()) { - (Opcode::Cmpli, 0, 0) => { - return write_asm!(out, self => { - "cmplwi": mnemonic; - a: gpr; - uimm: uimm; - }) - } - (Opcode::Cmpli, _, 0) => { - return write_asm!(out, self => { - "cmplwi": mnemonic; - crf_d: cr; - a: gpr; - uimm: uimm; - }) - } - _ => (), - } - write_asm!(out, self => { - (op.mnemonic): mnemonic; - crf_d: cr; - l: mode; - a: gpr; - uimm: uimm; - }) - } - - fn write_asm_form_reg1_spr(&self, out: &mut F) -> std::io::Result<()> - where - F: AsmFormatter, - W: Write, - { - if self.op == Opcode::Mfspr { - match self.spr() { - 1 => return write_asm!(out, self => { "mfxer": mnemonic; s: gpr }), - 8 => return write_asm!(out, self => { "mflr": mnemonic; s: gpr }), - 9 => return write_asm!(out, self => { "mfctr": mnemonic; s: gpr }), - 18 => return write_asm!(out, self => { "mfdsisr": mnemonic; s: gpr }), - 397 => return write_asm!(out, self => { "mfdbatu": mnemonic; s: gpr }), - 571 => return write_asm!(out, self => { "mftdu": mnemonic; s: gpr }), - _ => (), - }; - } - out.write_mnemonic(self.op.mnemonic())?; - out.write_opcode_separator()?; - out.write_gpr(self.d())?; - out.write_operand_separator()?; - write!(out.writer(), "{:#x}", self.spr())?; - Ok(()) - } - - fn write_asm_form_spr_reg1(&self, out: &mut F) -> std::io::Result<()> - where - F: AsmFormatter, - W: Write, - { - if self.op == Opcode::Mtspr { - match self.spr() { - 1 => return write_asm!(out, self => { "mtxer": mnemonic; s: gpr }), - 8 => return write_asm!(out, self => { "mtlr": mnemonic; s: gpr }), - 9 => return write_asm!(out, self => { "mtctr": mnemonic; s: gpr }), - 18 => return write_asm!(out, self => { "mtdsisr": mnemonic; s: gpr }), - 397 => return write_asm!(out, self => { "mtdbatu": mnemonic; s: gpr }), - 571 => return write_asm!(out, self => { "mttdu": mnemonic; s: gpr }), - _ => (), - }; - } - out.write_mnemonic(self.op.mnemonic())?; - out.write_opcode_separator()?; - write!(out.writer(), "{:#x}", self.spr())?; - out.write_operand_separator()?; - out.write_gpr(self.s())?; - Ok(()) - } - - pub fn write_string(&self, out: &mut F) -> std::io::Result<()> - where - F: AsmFormatter, - W: Write, - { - out.before_instruction(self)?; - self.write_string_inner(out)?; - out.after_instruction(self)?; - Ok(()) - } - - fn write_string_inner(&self, out: &mut F) -> std::io::Result<()> - where - F: AsmFormatter, - W: Write, - { - // Simplified mnemonic. - if self.op == Opcode::Or && self.s() == self.b() { - return write_asm!(out, self => { - "mr": mnemonic; - a: gpr; - s: gpr; - }); - } - if self.op == Opcode::Rlwinm && self.sh() == 0 && self.me() == 31 { - return write_asm!(out, self => { - ("clrlwi", rc): mnemonic; - a: gpr; - s: gpr; - mb: uimm; - }); - } - if self.op == Opcode::Rlwinm && self.mb() == 0 && self.me() == 31 { - return write_asm!(out, self => { - ("rotlwi", rc): mnemonic; - a: gpr; - s: gpr; - sh: uimm; - }); - } - if self.op == Opcode::Rlwinm && self.mb() == 0 && 31 - self.sh() == self.me() { - return write_asm!(out, self => { - ("slwi", rc): mnemonic; - a: gpr; - s: gpr; - me_31sub: uimm; - }); - } - if self.op == Opcode::Rlwinm && self.me() == 31 && 32 - self.mb() == self.sh() { - return write_asm!(out, self => { - ("srwi", rc): mnemonic; - a: gpr; - s: gpr; - mb: uimm; - }); - } - if self.op == Opcode::Twi && self.to() == 31 { - return write_asm!(out, self => { - "twui": mnemonic; - a: gpr; - simm: simm; - }); - } - if self.op == Opcode::Ori && self.a() == 0 && self.s() == 0 && self.uimm() == 0 { - return write_asm!(out, self => { "nop": mnemonic }); - } - if self.op == Opcode::Addis && self.a() == 0 { - return write_asm!(out, self => { - "lis": mnemonic; - d: gpr; - uimm: uimm; - }); - } - if self.op == Opcode::Addi && self.a() == 0 { - return write_asm!(out, self => { - "li": mnemonic; - d: gpr; - simm: simm; - }); - } - if self.op == Opcode::Addis && self.a() == 0 { - return write_asm!(out, self => { - "lis": mnemonic; - d: gpr; - simm: simm; - }); - } - // Generic. - match self.op { - Opcode::Illegal => write!(out.writer(), ""), - - // Standalone instructions - Opcode::Eieio - | Opcode::Isync - | Opcode::Rfi - | Opcode::Sc - | Opcode::Sync - | Opcode::Tlbsync => out.write_mnemonic(self.op.mnemonic()), - - // General purpose register only - Opcode::Mfcr | Opcode::Mfmsr | Opcode::Mtmsr | Opcode::Tlbie => { - write_asm!(out, self => { - (op.mnemonic): mnemonic; - d: gpr; - }) - } - Opcode::Addme | Opcode::Addze | Opcode::Neg | Opcode::Subfme | Opcode::Subfze => { - write_asm!(out, self => { - (op.mnemonic, oe, rc): mnemonic; - d: gpr; - a: gpr; - }) - } - Opcode::Mfsrin | Opcode::Mtsrin => write_asm!(out, self => { - (op.mnemonic): mnemonic; - d: gpr; - b: gpr; - }), - Opcode::Cntlzw | Opcode::Extsb | Opcode::Extsh => write_asm!(out, self => { - (op.mnemonic, rc): mnemonic; - a: gpr; - s: gpr; - }), - Opcode::Dcbf - | Opcode::Dcbi - | Opcode::Dcbst - | Opcode::Dcbt - | Opcode::Dcbtst - | Opcode::Dcbz - | Opcode::DcbzL - | Opcode::Icbi => write_asm!(out, self => { - (op.mnemonic): mnemonic; - a: gpr0; - b: gpr0; - }), - Opcode::Eciwx - | Opcode::Ecowx - | Opcode::Lhaux - | Opcode::Lhax - | Opcode::Lbzux - | Opcode::Lbzx - | Opcode::Lhbrx - | Opcode::Lhzux - | Opcode::Lhzx - | Opcode::Lswx - | Opcode::Lwarx - | Opcode::Lwbrx - | Opcode::Lwzux - | Opcode::Lwzx - | Opcode::Stbx - | Opcode::Stbux - | Opcode::Sthbrx - | Opcode::Sthx - | Opcode::Sthux - | Opcode::Stswx - | Opcode::Stwbrx - | Opcode::Stwcx_ - | Opcode::Stwx - | Opcode::Stwux => write_asm!(out, self => { - (op.mnemonic): mnemonic; - d: gpr; - a: gpr0; - b: gpr; - }), - Opcode::Mulhw | Opcode::Mulhwu => write_asm!(out, self => { - (op.mnemonic, rc): mnemonic; - d: gpr; - a: gpr; - b: gpr; - }), - Opcode::Add - | Opcode::Addc - | Opcode::Adde - | Opcode::Divw - | Opcode::Divwu - | Opcode::Mullw - | Opcode::Subf - | Opcode::Subfc - | Opcode::Subfe => write_asm!(out, self => { - (op.mnemonic, oe, rc): mnemonic; - d: gpr; - a: gpr; - b: gpr; - }), - Opcode::Eqv - | Opcode::Nand - | Opcode::Nor - | Opcode::Or - | Opcode::Orc - | Opcode::Slw - | Opcode::Sraw - | Opcode::Srw - | Opcode::Xor - | Opcode::And - | Opcode::Andc => write_asm!(out, self => { - (op.mnemonic, rc): mnemonic; - a: gpr; - s: gpr; - b: gpr; - }), - - // General purpose shifts - Opcode::Rlwimi | Opcode::Rlwinm => write_asm!(out, self => { - (op.mnemonic, rc): mnemonic; - a: gpr; - s: gpr; - sh: mode; - mb: uimm; - me: uimm; - }), - Opcode::Rlwnm => write_asm!(out, self => { - (op.mnemonic, rc): mnemonic; - a: gpr; - s: gpr; - b: gpr; - mb: uimm; - me: uimm; - }), - - // General purpose register misc - Opcode::Addi | Opcode::Addic | Opcode::Addic_ | Opcode::Mulli | Opcode::Subfic => { - write_asm!(out, self => { - (op.mnemonic): mnemonic; - d: gpr; - a: gpr; - simm: simm; - }) - } - Opcode::Addis => write_asm!(out, self => { - (op.mnemonic): mnemonic; - d: gpr; - a: gpr; - uimm: uimm; - }), - Opcode::Andi_ - | Opcode::Andis_ - | Opcode::Ori - | Opcode::Oris - | Opcode::Xori - | Opcode::Xoris => write_asm!(out, self => { - (op.mnemonic): mnemonic; - a: gpr; - s: gpr; - uimm: uimm; - }), - Opcode::Lbz - | Opcode::Lbzu - | Opcode::Lha - | Opcode::Lhau - | Opcode::Lhz - | Opcode::Lhzu - | Opcode::Lmw - | Opcode::Lwz - | Opcode::Lwzu - | Opcode::Stb - | Opcode::Stbu - | Opcode::Sth - | Opcode::Sthu - | Opcode::Stmw - | Opcode::Stw - | Opcode::Stwu => write_asm!(out, self => { - (op.mnemonic): mnemonic; - d: gpr; - simm: offset; - a: gpr0; - }), - Opcode::Lswi | Opcode::Stswi => write_asm!(out, self => { - (op.mnemonic): mnemonic; - d: gpr; - a: gpr; - b: mode; - }), - Opcode::Mfspr | Opcode::Mftb => self.write_asm_form_reg1_spr(out), - Opcode::Mtspr => self.write_asm_form_spr_reg1(out), - Opcode::Mfsr => write_asm!(out, self => { - (op.mnemonic): mnemonic; - d: gpr; - sr: mode; - }), - Opcode::Mtsr => write_asm!(out, self => { - (op.mnemonic): mnemonic; - sr: uimm; - s: gpr; - }), - Opcode::Mtcrf => write_asm!(out, self => { - (op.mnemonic): mnemonic; - crm: mode; - s: gpr; - }), - Opcode::Srawi => write_asm!(out, self => { - (op.mnemonic, rc): mnemonic; - a: gpr; - s: gpr; - sh: uimm; - }), - Opcode::Tw => write_asm!(out, self => { - (op.mnemonic): mnemonic; - to: mode; - a: gpr; - b: gpr; - }), - Opcode::Twi => write_asm!(out, self => { - (op.mnemonic): mnemonic; - to: mode; - a: gpr; - simm: simm; - }), - - // Branch instructions - Opcode::B => write_asm!(out, self => { - (op.mnemonic, lk, aa): mnemonic; - li: branch_target; - }), - Opcode::Bc => self.write_asm_branch(out, ""), - Opcode::Bcctr => self.write_asm_branch(out, "ctr"), - Opcode::Bclr => self.write_asm_branch(out, "lr"), - - // Compare instructions - Opcode::Cmp | Opcode::Cmpl => self.write_asm_cmp(out), - Opcode::Cmpi => self.write_asm_cmp_simm(out), - Opcode::Cmpli => self.write_asm_cmp_uimm(out), - - // Floating point register only instructions - Opcode::Mffs => write_asm!(out, self => { - (op.mnemonic, rc): mnemonic; - d: fpr; - }), - Opcode::Fabs - | Opcode::Fmr - | Opcode::Fnabs - | Opcode::Fneg - | Opcode::Fres - | Opcode::Frsp - | Opcode::Frsqrte - | Opcode::Fctiwz - | Opcode::PsAbs - | Opcode::PsMr - | Opcode::PsNabs - | Opcode::PsNeg - | Opcode::PsRes - | Opcode::PsRsqrte => write_asm!(out, self => { - (op.mnemonic, rc): mnemonic; - d: fpr; - b: fpr; - }), - Opcode::Fadd - | Opcode::Fadds - | Opcode::Fdiv - | Opcode::Fdivs - | Opcode::Fsub - | Opcode::Fsubs - | Opcode::PsAdd - | Opcode::PsDiv - | Opcode::PsMerge00 - | Opcode::PsMerge01 - | Opcode::PsMerge10 - | Opcode::PsMerge11 - | Opcode::PsSub => write_asm!(out, self => { - (op.mnemonic, rc): mnemonic; - d: fpr; - a: fpr; - b: fpr; - }), - Opcode::Fmul | Opcode::Fmuls | Opcode::PsMul | Opcode::PsMuls0 | Opcode::PsMuls1 => { - write_asm!(out, self => { - (op.mnemonic, rc): mnemonic; - d: fpr; - a: fpr; - c: fpr; - }) - } - Opcode::Fmadd - | Opcode::Fmadds - | Opcode::Fmsub - | Opcode::Fmsubs - | Opcode::Fnmadd - | Opcode::Fnmadds - | Opcode::Fnmsub - | Opcode::Fnmsubs - | Opcode::Fsel - | Opcode::PsMadd - | Opcode::PsMadds0 - | Opcode::PsMadds1 - | Opcode::PsMsub - | Opcode::PsNmadd - | Opcode::PsNmsub - | Opcode::PsSel - | Opcode::PsSum0 - | Opcode::PsSum1 => write_asm!(out, self => { - (op.mnemonic, rc): mnemonic; - d: fpr; - a: fpr; - c: fpr; - b: fpr; - }), - - // Floating point register misc instructions - Opcode::Fctiw => write_asm!(out, self => { - (op.mnemonic, rc): mnemonic; - crf_d: cr; - d: fpr; - b: fpr; - }), - Opcode::Fcmpo - | Opcode::Fcmpu - | Opcode::PsCmpo0 - | Opcode::PsCmpo1 - | Opcode::PsCmpu0 - | Opcode::PsCmpu1 => write_asm!(out, self => { - (op.mnemonic): mnemonic; - crf_d: cr; - a: fpr; - b: fpr; - }), - Opcode::Lfd - | Opcode::Lfdu - | Opcode::Lfs - | Opcode::Lfsu - | Opcode::Stfd - | Opcode::Stfdu - | Opcode::Stfs - | Opcode::Stfsu => write_asm!(out, self => { - (op.mnemonic): mnemonic; - d: fpr; - simm: offset; - a: gpr; - }), - Opcode::Lfdux - | Opcode::Lfdx - | Opcode::Lfsux - | Opcode::Lfsx - | Opcode::Stfdux - | Opcode::Stfdx - | Opcode::Stfiwx - | Opcode::Stfsux - | Opcode::Stfsx => write_asm!(out, self => { - (op.mnemonic): mnemonic; - d: fpr; - a: gpr; - b: gpr; - }), - Opcode::Mtfsf => write_asm!(out, self => { - (op.mnemonic): mnemonic; - fm: fm; - b: fpr; - }), - - // Condition register only - Opcode::Mcrxr => write_asm!(out, self => { - (op.mnemonic): mnemonic; - crf_d: cr; - }), - Opcode::Mtfsb0 | Opcode::Mtfsb1 => write_asm!(out, self => { - (op.mnemonic, rc): mnemonic; - crf_d: cr; - }), - Opcode::Mcrf | Opcode::Mcrfs => write_asm!(out, self => { - (op.mnemonic): mnemonic; - crf_d: cr; - crf_s: cr; - }), - Opcode::Crand - | Opcode::Crandc - | Opcode::Creqv - | Opcode::Crnand - | Opcode::Crnor - | Opcode::Cror - | Opcode::Crorc - | Opcode::Crxor => write_asm!(out, self => { - (op.mnemonic): mnemonic; - crb_d: cr; - crb_a: cr; - crb_b: cr; - }), - - // Condition register misc - Opcode::Mtfsfi => self.write_asm_mtfsfi(out), - - // Paired-single instructions - Opcode::PsqL | Opcode::PsqLu | Opcode::PsqSt | Opcode::PsqStu => { - write_asm!(out, self => { - (op.mnemonic): mnemonic; - d: fpr; - ps_d: offset; - a: gpr; - w: mode; - ps_l: qr; - }) - } - Opcode::PsqLx | Opcode::PsqLux | Opcode::PsqStx | Opcode::PsqStux => { - write_asm!(out, self => { - (op.mnemonic): mnemonic; - d: fpr; - a: gpr; - b: gpr; - w: mode; - ps_l: qr; - }) - } - } - } } -impl ToString for Ins { - fn to_string(&self) -> String { - let buf = Vec::::new(); - let mut formatter = SimpleFormatter::new(buf); - self.write_string(&mut formatter).unwrap(); - unsafe { String::from_utf8_unchecked(formatter.writer) } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_bits() { - assert_eq!( - bits::(0b00000101100000000000000000000000u32, 5..9), - 0b1011u32 - ); - assert_eq!(bit(0b00000101100000000000000000000000u32, 5), 1); - } - - macro_rules! assert_asm { - ($code:expr, $disasm:expr) => {{ - assert_eq!(Ins::new($code, 0x8000_0000u32).to_string(), $disasm) - }}; - } - - #[test] - fn test_ins_addc() { - assert_asm!(0x7c002014, "addc r0, r0, r4"); - } - - #[test] - fn test_ins_adde() { - assert_asm!(0x7c006114, "adde r0, r0, r12"); - } - - #[test] - fn test_ins_addi() { - assert_asm!(0x38010008, "addi r0, r1, 0x8"); - assert_asm!(0x38010010, "addi r0, r1, 0x10"); - assert_asm!(0x38010018, "addi r0, r1, 0x18"); - assert_asm!(0x38010140, "addi r0, r1, 0x140"); - assert_asm!(0x38049000, "addi r0, r4, -28672"); - assert_asm!(0x38a00000, "li r5, 0"); - } - - #[test] - fn test_ins_addic() { - assert_asm!(0x3060ffff, "addic r3, r0, -1"); - assert_asm!(0x30840800, "addic r4, r4, 0x800"); - assert_asm!(0x30a50008, "addic r5, r5, 0x8"); - assert_asm!(0x37DF001C, "addic. r30, r31, 0x1c"); - assert_asm!(0x37E06278, "addic. r31, r0, 0x6278"); - assert_asm!(0x37E3FFFF, "addic. r31, r3, -1"); - } - - #[test] - fn test_ins_addic_() { - assert_asm!(0x341D001C, "addic. r0, r29, 0x1c"); - } - - #[test] - fn test_ins_addis() { - assert_asm!(0x3C030000, "addis r0, r3, 0"); - assert_asm!(0x3C038000, "addis r0, r3, 0x8000"); - assert_asm!(0x3D00EFCE, "lis r8, 0xefce"); - } - - #[test] - fn test_ins_addze() { - assert_asm!(0x7C000194, "addze r0, r0"); - } - - #[test] - fn test_ins_and() { - assert_asm!(0x7C001838, "and r0, r0, r3"); - assert_asm!(0x7C001839, "and. r0, r0, r3"); - } - - #[test] - fn test_ins_andc() { - assert_asm!(0x7C001878, "andc r0, r0, r3"); - } - - #[test] - fn test_ins_andi_() { - assert_asm!(0x70000009, "andi. r0, r0, 9"); - } - - #[test] - fn test_ins_andis_() { - assert_asm!(0x77c802ff, "andis. r8, r30, 0x2ff"); - } - - #[test] - fn test_ins_b() { - assert_asm!(0x48000000, "b 0x0"); - assert_asm!(0x48000004, "b 0x4"); - assert_asm!(0x4800A5C9, "bl 0xa5c8"); - assert_asm!(0x4823B4D9, "bl 0x23b4d8"); - assert_asm!(0x4BE03C99, "bl -0x1fc368"); - assert_asm!(0x4BDC1A59, "bl -0x23e5a8"); - } - - #[test] - fn test_ins_bc() { - assert_asm!(0x40800008, "bge 0x8"); - assert_asm!(0x40802350, "bge 0x2350"); - assert_asm!(0x4080FC7C, "bge -0x384"); - assert_asm!(0x408100AC, "ble 0xac"); - assert_asm!(0x4081F788, "ble -0x878"); - assert_asm!(0x40821BA0, "bne 0x1ba0"); - assert_asm!(0x4082E3C4, "bne -0x1c3c"); - assert_asm!(0x408600D8, "bne cr1, 0xd8"); - assert_asm!(0x4086FECC, "bne cr1, -0x134"); - assert_asm!(0x409C000C, "bge cr7, 0xc"); - // assert_asm!(0x40A10010, "ble+ 0x10"); - assert_asm!(0x4180000C, "blt 0xc"); - assert_asm!(0x4180F9C0, "blt -0x640"); - assert_asm!(0x4181021C, "bgt 0x21c"); - assert_asm!(0x4181FD80, "bgt -0x280"); - assert_asm!(0x41822304, "beq 0x2304"); - assert_asm!(0x4182FE3C, "beq -0x1c4"); - assert_asm!(0x418401AC, "blt cr1, 0x1ac"); - assert_asm!(0x4184FCE4, "blt cr1, -0x31c"); - assert_asm!(0x418500C0, "bgt cr1, 0xc0"); - assert_asm!(0x418502E4, "bgt cr1, 0x2e4"); - assert_asm!(0x419A0138, "beq cr6, 0x138"); - assert_asm!(0x419C0008, "blt cr7, 0x8"); - assert_asm!(0x4200F560, "bdnz -0xaa0"); - } - - #[test] - fn test_ins_bcctr() { - assert_asm!(0x4E800420, "bctr"); - assert_asm!(0x4E800421, "bctrl"); - } - - #[test] - fn test_ins_bclr() { - assert_asm!(0x4C800020, "bgelr"); - assert_asm!(0x4C810020, "blelr"); - assert_asm!(0x4C820020, "bnelr"); - assert_asm!(0x4C9E0020, "bnelr cr7"); - assert_asm!(0x4D800020, "bltlr"); - assert_asm!(0x4D810020, "bgtlr"); - assert_asm!(0x4D820020, "beqlr"); - assert_asm!(0x4D860020, "beqlr cr1"); - assert_asm!(0x4E800020, "blr"); - assert_asm!(0x4E800021, "blrl"); - } - - #[test] - fn test_ins_cmp() { - assert_asm!(0x7C030000, "cmpw r3, r0"); - } - - #[test] - fn test_ins_cmpi() { - assert_asm!(0x2C050D00, "cmpwi r5, 0xd00"); - assert_asm!(0x2F1F0000, "cmpwi cr6, r31, 0"); - } - - #[test] - fn test_ins_cmpl() { - assert_asm!(0x7C9A2040, "cmplw cr1, r26, r4"); - } - - #[test] - fn test_ins_cmpli() { - assert_asm!(0x2803FFF3, "cmplwi r3, 0xfff3"); - assert_asm!(0x2884F8F0, "cmplwi cr1, r4, 0xf8f0"); - } - - #[test] - fn test_ins_cntlzw() { - assert_asm!(0x7C030034, "cntlzw r3, r0"); - } - - #[test] - fn test_ins_cror() { - assert_asm!(0x4C411382, "cror cr2, cr1, cr2"); - } - - #[test] - fn test_ins_dcbf() { - assert_asm!(0x7C0028AC, "dcbf 0, r5"); - } - - #[test] - fn test_ins_dcbi() { - assert_asm!(0x7C001BAC, "dcbi 0, r3"); - } - - #[test] - fn test_ins_dcbst() { - assert_asm!(0x7C00286C, "dcbst 0, r5"); - } - - #[test] - fn test_ins_dcbt() { - assert_asm!(0x7C001A2C, "dcbt 0, r3"); - } - - #[test] - fn test_ins_dcbz() { - assert_asm!(0x7C001FEC, "dcbz 0, r3"); - } - - #[test] - fn test_ins_dcbz_l() { - assert_asm!(0x10061FEC, "dcbz_l r6, r3"); - } - - #[test] - fn test_ins_divw() { - assert_asm!(0x7C8073D6, "divw r4, r0, r14"); - } - - #[test] - fn test_ins_divwu() { - assert_asm!(0x7C69E396, "divwu r3, r9, r28"); - } - - #[test] - fn test_ins_extsb() { - assert_asm!(0x7C650774, "extsb r5, r3"); - assert_asm!(0x7C650775, "extsb. r5, r3"); - } - - #[test] - fn test_ins_extsh() { - assert_asm!(0x7C000734, "extsh r0, r0"); - assert_asm!(0x7C000735, "extsh. r0, r0"); - } - - #[test] - fn test_ins_fabs() { - assert_asm!(0xFC000A10, "fabs f0, f1"); - } - - #[test] - fn test_ins_fadd() { - assert_asm!(0xFC00282A, "fadd f0, f0, f5"); - } - - #[test] - fn test_ins_fadds() { - assert_asm!(0xEC41602A, "fadds f2, f1, f12"); - } - - #[test] - fn test_ins_fcmpo() { - assert_asm!(0xFC00C840, "fcmpo cr0, f0, f25"); - } - - #[test] - fn test_ins_fcmpu() { - assert_asm!(0xFC00D000, "fcmpu cr0, f0, f26"); - } - - #[test] - fn test_ins_fctiwz() { - assert_asm!(0xFC20001E, "fctiwz f1, f0"); - } - - #[test] - fn test_ins_fdiv() { - assert_asm!(0xFC200024, "fdiv f1, f0, f0"); - } - - #[test] - fn test_ins_fdivs() { - assert_asm!(0xEC01F824, "fdivs f0, f1, f31"); - } - - #[test] - fn test_ins_fmadds() { - assert_asm!(0xEC0200FA, "fmadds f0, f2, f3, f0"); - } - - #[test] - fn test_ins_fmsub() { - assert_asm!(0xFC000028, "fsub f0, f0, f0"); - } - - #[test] - fn test_ins_fmsubs() { - assert_asm!(0xEC00B828, "fsubs f0, f0, f23"); - } - - #[test] - fn test_ins_fmul() { - assert_asm!(0xFC0000B2, "fmul f0, f0, f2"); - assert_asm!(0xFC0000F2, "fmul f0, f0, f3"); - } - - #[test] - fn test_ins_fmuls() { - assert_asm!(0xEC0007B2, "fmuls f0, f0, f30"); - } - - #[test] - fn test_ins_fneg() { - assert_asm!(0xFCE00050, "fneg f7, f0"); - } - - #[test] - fn test_ins_fnmsub() { - assert_asm!(0xFCC640BC, "fnmsub f6, f6, f2, f8"); - } - - #[test] - fn test_ins_fnmsubs() { - assert_asm!(0xEC022B3C, "fnmsubs f0, f2, f12, f5"); - } - - #[test] - fn test_ins_fres() { - assert_asm!(0xEC000830, "fres f0, f1"); - } - - #[test] - fn test_ins_frsp() { - assert_asm!(0xFC000018, "frsp f0, f0"); - } - - #[test] - fn test_ins_frsqrte() { - assert_asm!(0xFC000834, "frsqrte f0, f1"); - } - - #[test] - fn test_ins_fsel() { - assert_asm!(0xFC01F82E, "fsel f0, f1, f0, f31"); - } - - #[test] - fn test_ins_fsub() { - assert_asm!(0xFC000828, "fsub f0, f0, f1"); - } - - #[test] - fn test_ins_fsubs() { - assert_asm!(0xEC000828, "fsubs f0, f0, f1"); - } - - #[test] - fn test_ins_icbi() { - assert_asm!(0x7C001FAC, "icbi 0, r3"); - } - - #[test] - fn test_ins_isync() { - assert_asm!(0x4C00012C, "isync"); - } - - #[test] - fn test_ins_lbz() { - assert_asm!(0x880104CC, "lbz r0, 0x4cc(r1)"); - assert_asm!(0x8802801B, "lbz r0, -0x7fe5(r2)"); - } - - #[test] - fn test_ins_lbzu() { - assert_asm!(0x8D9DCA10, "lbzu r12, -0x35f0(r29)"); - assert_asm!(0x8E3053EC, "lbzu r17, 0x53ec(r16)"); - } - - #[test] - fn test_ins_lbzux() { - assert_asm!(0x7C0400EE, "lbzux r0, r4, r0"); - } - - #[test] - fn test_ins_lbzx() { - assert_asm!(0x7C0300AE, "lbzx r0, r3, r0"); - } - - #[test] - fn test_ins_lfd() { - assert_asm!(0xC80140C8, "lfd f0, 0x40c8(r1)"); - assert_asm!(0xC8028090, "lfd f0, -0x7f70(r2)"); - } - - #[test] - fn test_ins_lfdu() { - assert_asm!(0xCC03FFC0, "lfdu f0, -0x40(r3)"); - } - - #[test] - fn test_ins_lfdx() { - assert_asm!(0x7C0404AE, "lfdx f0, r4, r0"); - } - - #[test] - fn test_ins_lfs() { - assert_asm!(0xC001027C, "lfs f0, 0x27c(r1)"); - assert_asm!(0xC0028000, "lfs f0, -0x8000(r2)"); - } - - #[test] - fn test_ins_lfsu() { - assert_asm!(0xC404FFF4, "lfsu f0, -0xc(r4)"); - assert_asm!(0xC4170084, "lfsu f0, 0x84(r23)"); - } - - #[test] - fn test_ins_lfsux() { - assert_asm!(0x7C03846E, "lfsux f0, r3, r16"); - } - - #[test] - fn test_ins_lfsx() { - assert_asm!(0x7C03042E, "lfsx f0, r3, r0"); - } - - #[test] - fn test_ins_lha() { - assert_asm!(0xA861000E, "lha r3, 0xe(r1)"); - assert_asm!(0xA80D9F64, "lha r0, -0x609c(r13)"); - } - - #[test] - fn test_ins_lhau() { - assert_asm!(0xAC060006, "lhau r0, 6(r6)"); - assert_asm!(0xAC06FFFA, "lhau r0, -6(r6)"); - } - - #[test] - fn test_ins_lhax() { - assert_asm!(0x7C0402AE, "lhax r0, r4, r0"); - } - - #[test] - fn test_ins_lhz() { - assert_asm!(0xA00104D6, "lhz r0, 0x4d6(r1)"); - assert_asm!(0xA00296DA, "lhz r0, -0x6926(r2)"); - } - - #[test] - fn test_ins_lhzu() { - assert_asm!(0xA40A0004, "lhzu r0, 4(r10)"); - } - - #[test] - fn test_ins_lhzux() { - assert_asm!(0x7C04026E, "lhzux r0, r4, r0"); - } - - #[test] - fn test_ins_lhzx() { - assert_asm!(0x7C03022E, "lhzx r0, r3, r0"); - } - - #[test] - fn test_ins_lmw() { - assert_asm!(0xBB210444, "lmw r25, 0x444(r1)"); - } - - #[test] - fn test_ins_lwbrx() { - assert_asm!(0x7D80242C, "lwbrx r12, 0, r4"); - } - - #[test] - fn test_ins_lwz() { - assert_asm!(0x800294F4, "lwz r0, -0x6b0c(r2)"); - assert_asm!(0x80011254, "lwz r0, 0x1254(r1)"); - } - - #[test] - fn test_ins_lwzu() { - assert_asm!(0x84038608, "lwzu r0, -0x79f8(r3)"); - assert_asm!(0x873E5058, "lwzu r25, 0x5058(r30)"); - } - - #[test] - fn test_ins_lwzux() { - assert_asm!(0x7C03006E, "lwzux r0, r3, r0"); - } - - #[test] - fn test_ins_lwzx() { - assert_asm!(0x7C03002E, "lwzx r0, r3, r0"); - } - - #[test] - fn test_ins_mfcr() { - assert_asm!(0x7C000026, "mfcr r0"); - } - - #[test] - fn test_ins_mffs() { - assert_asm!(0xFC00048E, "mffs f0"); - } - - #[test] - fn test_ins_mfmsr() { - assert_asm!(0x7C0000A6, "mfmsr r0"); - } - - #[test] - fn test_ins_mfspr() { - assert_asm!(0x7E1A02A6, "mfspr r16, 0x1a"); - } - - #[test] - fn test_ins_mfsr() { - assert_asm!(0x7E0004A6, "mfsr r16, 0"); - } - - #[test] - fn test_ins_mftb() { - assert_asm!(0x7C8C42E6, "mftb r4, 0x10c"); - } - - #[test] - fn test_ins_mtcrf() { - assert_asm!(0x7C6FF120, "mtcrf 255, r3"); - } - - /* - #[test] - fn test_ins_mtfsb0() {} - - #[test] - fn test_ins_mtfsb1() { - assert_asm!(0xFFA0004C, "mtfsb1 0x1d"); - } - */ - - #[test] - fn test_ins_mtfsf() { - assert_asm!(0xFDFE058E, "mtfsf 255, f0"); - assert_asm!(0xFDFEFD8E, "mtfsf 255, f31"); - } - - #[test] - fn test_ins_mtmsr() { - assert_asm!(0x7C000124, "mtmsr r0"); - } - - #[test] - fn test_ins_mtspr() { - assert_asm!(0x7E75FBA6, "mtspr 0x3f5, r19"); - } - - #[test] - fn test_ins_mtsr() { - assert_asm!(0x7E0001A4, "mtsr 0, r16"); - } - - #[test] - fn test_ins_mulhw() { - assert_asm!(0x7C7F2096, "mulhw r3, r31, r4"); - } - - #[test] - fn test_ins_mulhwu() { - assert_asm!(0x7C7D0016, "mulhwu r3, r29, r0"); - } - - #[test] - fn test_ins_mulli() { - assert_asm!(0x1C001880, "mulli r0, r0, 0x1880"); - assert_asm!(0x1FBD0030, "mulli r29, r29, 0x30"); - } - - #[test] - fn test_ins_mullw() { - assert_asm!(0x7C7D01D6, "mullw r3, r29, r0"); - } - - #[test] - fn test_ins_nand() { - assert_asm!(0x7C7D03B8, "nand r29, r3, r0"); - } - - #[test] - fn test_ins_neg() { - assert_asm!(0x7C0600D0, "neg r0, r6"); - } - - #[test] - fn test_ins_nor() { - assert_asm!(0x7C0500F8, "nor r5, r0, r0"); - } - - #[test] - fn test_ins_or() { - assert_asm!(0x7C04DB78, "or r4, r0, r27"); - } - - #[test] - fn test_ins_orc() { - assert_asm!(0x7C042338, "orc r4, r0, r4"); - } - - #[test] - fn test_ins_ori() { - assert_asm!(0x60002204, "ori r0, r0, 0x2204"); - } - - #[test] - fn test_ins_oris() { - assert_asm!(0x67A06800, "oris r0, r29, 0x6800"); - } - - #[test] - fn test_ins_psq_l() { - assert_asm!(0xE02500AC, "psq_l f1, 0xac(r5), 0, qr0"); - } - - #[test] - fn test_ins_psq_lu() { - assert_asm!(0xE5435010, "psq_lu f10, 0x10(r3), 0, qr5"); - } - - #[test] - fn test_ins_psq_lx() { - assert_asm!(0x1000000C, "psq_lx f0, r0, r0, 0, qr0"); - } - - #[test] - fn test_ins_psq_st() { - assert_asm!(0xF1230210, "psq_st f9, 0x210(r3), 0, qr0"); - assert_asm!(0xF1238008, "psq_st f9, 8(r3), 1, qr0"); - } - - #[test] - fn test_ins_psq_stu() { - assert_asm!(0xF40A0020, "psq_stu f0, 0x20(r10), 0, qr0"); - } - - #[test] - fn test_ins_psq_stx() { - assert_asm!(0x13E1000E, "psq_stx f31, r1, r0, 0, qr0"); - } - - #[test] - fn test_ins_ps_abs() { - assert_asm!(0x10A03210, "ps_abs f5, f6"); - } - - #[test] - fn test_ins_ps_add() { - assert_asm!(0x1006382A, "ps_add f0, f6, f7"); - } - - #[test] - fn test_ins_ps_cmpo0() { - assert_asm!(0x10070840, "ps_cmpo0 cr0, f7, f1"); - } - - #[test] - fn test_ins_ps_cmpu0() { - assert_asm!(0x10003000, "ps_cmpu0 cr0, f0, f6"); - } - - #[test] - fn test_ins_ps_cmpu1() { - assert_asm!(0x10003080, "ps_cmpu1 cr0, f0, f6"); - } - - #[test] - fn test_ins_ps_madd() { - assert_asm!(0x112141FA, "ps_madd f9, f1, f7, f8"); - } - - #[test] - fn test_ins_ps_madds0() { - assert_asm!(0x10AC299C, "ps_madds0 f5, f12, f6, f5"); - } - - #[test] - fn test_ins_ps_madds1() { - assert_asm!(0x110640DE, "ps_madds1 f8, f6, f3, f8"); - } - - #[test] - fn test_ins_ps_merge00() { - assert_asm!(0x10400420, "ps_merge00 f2, f0, f0"); - } - - #[test] - fn test_ins_ps_merge01() { - assert_asm!(0x10400C60, "ps_merge01 f2, f0, f1"); - } - - #[test] - fn test_ins_ps_merge10() { - assert_asm!(0x104004A0, "ps_merge10 f2, f0, f0"); - } - - #[test] - fn test_ins_ps_merge11() { - assert_asm!(0x10AA14E0, "ps_merge11 f5, f10, f2"); - } - - #[test] - fn test_ins_ps_msub() { - assert_asm!(0x10A53778, "ps_msub f5, f5, f29, f6"); - } - - #[test] - fn test_ins_ps_mul() { - assert_asm!(0x10000032, "ps_mul f0, f0, f0"); - } - - #[test] - fn test_ins_ps_muls0() { - assert_asm!(0x100002D8, "ps_muls0 f0, f0, f11"); - } - - #[test] - fn test_ins_ps_muls1() { - assert_asm!(0x10A2005A, "ps_muls1 f5, f2, f1"); - } - - #[test] - fn test_ins_ps_nabs() { - assert_asm!(0x10803210, "ps_abs f4, f6"); - } - - #[test] - fn test_ins_ps_neg() { - assert_asm!(0x10E03850, "ps_neg f7, f7"); - } - - #[test] - fn test_ins_ps_nmadd() { - assert_asm!(0x10CB30FE, "ps_nmadd f6, f11, f3, f6"); - } - - #[test] - fn test_ins_ps_nmsub() { - assert_asm!(0x107E083C, "ps_nmsub f3, f30, f0, f1"); - } - - #[test] - fn test_ins_ps_sel() { - assert_asm!(0x106428EE, "ps_sel f3, f4, f3, f5"); - } - - #[test] - fn test_ins_ps_sub() { - assert_asm!(0x10A92828, "ps_sub f5, f9, f5"); - } - - #[test] - fn test_ins_ps_sum0() { - assert_asm!(0x10230854, "ps_sum0 f1, f3, f1, f1"); - } - - #[test] - fn test_ins_ps_sum1() { - assert_asm!(0x10A12956, "ps_sum1 f5, f1, f5, f5"); - } - - #[test] - fn test_ins_rfi() { - assert_asm!(0x4C000064, "rfi"); - } - - #[test] - fn test_ins_rlwimi() { - assert_asm!(0x500306FE, "rlwimi r3, r0, 0, 0x1b, 0x1f"); - assert_asm!(0x50032D74, "rlwimi r3, r0, 5, 0x15, 0x1a"); - } - - #[test] - fn test_ins_rlwinm() { - assert_asm!(0x54000423, "rlwinm. r0, r0, 0, 0x10, 0x11"); - assert_asm!(0x54000432, "rlwinm r0, r0, 0, 0x10, 0x19"); - } - - #[test] - fn test_ins_rlwnm() { - assert_asm!(0x5D6A67FE, "rlwnm r10, r11, r12, 0x1f, 0x1f"); - assert_asm!(0x5FC52EFE, "rlwnm r5, r30, r5, 0x1b, 0x1f"); - } - - #[test] - fn test_ins_sc() { - assert_asm!(0x44000002, "sc"); - } - - #[test] - fn test_ins_slw() { - assert_asm!(0x7C042830, "slw r4, r0, r5"); - } - - #[test] - fn test_ins_sraw() { - assert_asm!(0x7C043E30, "sraw r4, r0, r7"); - } - - #[test] - fn test_ins_srawi() { - assert_asm!(0x7C000E70, "srawi r0, r0, 1"); - assert_asm!(0x7C001670, "srawi r0, r0, 2"); - } - - #[test] - fn test_ins_srw() { - assert_asm!(0x7C001C30, "srw r0, r0, r3"); - } - - #[test] - fn test_ins_stb() { - assert_asm!(0x980105EC, "stb r0, 0x5ec(r1)"); - assert_asm!(0x98030000, "stb r0, 0(r3)"); - } - - #[test] - fn test_ins_stbu() { - assert_asm!(0x9D2A7428, "stbu r9, 0x7428(r10)"); - assert_asm!(0x9D66FFFF, "stbu r11, -1(r6)"); - } - - #[test] - fn test_ins_stbux() { - assert_asm!(0x7C08F9EE, "stbux r0, r8, r31"); - } - - #[test] - fn test_ins_stbx() { - assert_asm!(0x7C03F9AE, "stbx r0, r3, r31"); - } - - #[test] - fn test_ins_stfd() { - assert_asm!(0xD80D97B0, "stfd f0, -0x6850(r13)"); - assert_asm!(0xD8050090, "stfd f0, 0x90(r5)"); - } - - #[test] - fn test_ins_stfdu() { - assert_asm!(0xDC24FFC0, "stfdu f1, -0x40(r4)"); - } - - #[test] - fn test_ins_stfdx() { - assert_asm!(0x7C4405AE, "stfdx f2, r4, r0"); - } - - #[test] - fn test_ins_stfs() { - assert_asm!(0xD003086C, "stfs f0, 0x86c(r3)"); - assert_asm!(0xD0038000, "stfs f0, -0x8000(r3)"); - } - - #[test] - fn test_ins_stfsx() { - assert_asm!(0x7C465D2E, "stfsx f2, r6, r11"); - } - - #[test] - fn test_ins_sth() { - assert_asm!(0xB0038A7C, "sth r0, -0x7584(r3)"); - assert_asm!(0xB0035036, "sth r0, 0x5036(r3)"); - } - - #[test] - fn test_ins_sthbrx() { - assert_asm!(0x7C60072C, "sthbrx r3, 0, r0"); - } - - #[test] - fn test_ins_sthu() { - assert_asm!(0xB4055B88, "sthu r0, 0x5b88(r5)"); - } - - #[test] - fn test_ins_sthux() { - assert_asm!(0x7C03236E, "sthux r0, r3, r4"); - } - - #[test] - fn test_ins_sthx() { - assert_asm!(0x7C1C2B2E, "sthx r0, r28, r5"); - } - - #[test] - fn test_ins_stmw() { - assert_asm!(0xBFA202A4, "stmw r29, 0x2a4(r2)"); - } - - #[test] - fn test_ins_stw() { - assert_asm!(0x900140CC, "stw r0, 0x40cc(r1)"); - assert_asm!(0x9003FFBC, "stw r0, -0x44(r3)"); - } - - #[test] - fn test_ins_stwbrx() { - assert_asm!(0x7C00FD2C, "stwbrx r0, 0, r31"); - } - - #[test] - fn test_ins_stwu() { - assert_asm!(0x9421EBC0, "stwu r1, -0x1440(r1)"); - } - - #[test] - fn test_ins_stwux() { - assert_asm!(0x7C01B96E, "stwux r0, r1, r23"); - } - - #[test] - fn test_ins_stwx() { - assert_asm!(0x7C03212E, "stwx r0, r3, r4"); - } - - #[test] - fn test_ins_subf() { - assert_asm!(0x7C051850, "subf r0, r5, r3"); - assert_asm!(0x7C051851, "subf. r0, r5, r3"); - } - - #[test] - fn test_ins_subfc() { - assert_asm!(0x7C040010, "subfc r0, r4, r0"); - } - - #[test] - fn test_ins_subfe() { - assert_asm!(0x7C030110, "subfe r0, r3, r0"); - } - - #[test] - fn test_ins_subfic() { - assert_asm!(0x200602FF, "subfic r0, r6, 0x2ff"); - } - - #[test] - fn test_ins_subfze() { - assert_asm!(0x7C000190, "subfze r0, r0"); - } - - #[test] - fn test_ins_sync() { - assert_asm!(0x7C0004AC, "sync"); - } - - #[test] - fn test_ins_xor() { - assert_asm!(0x7C052A78, "xor r5, r0, r5"); - } - - #[test] - fn test_ins_xori() { - assert_asm!(0x68E71021, "xori r7, r7, 0x1021"); - } - #[test] - fn test_ins_xoris() { - assert_asm!(0x6E3D8000, "xoris r29, r17, 0x8000"); +impl SimplifiedIns { + pub(crate) fn basic_form(ins: Ins) -> Self { + Self { + mnemonic: ins.op.mnemonic(), + args: ins + .fields() + .iter() + .flat_map(|field| field.argument()) + .collect(), + ins, + } } } diff --git a/disasm/src/macros.rs b/disasm/src/macros.rs deleted file mode 100644 index 60718d2..0000000 --- a/disasm/src/macros.rs +++ /dev/null @@ -1,8 +0,0 @@ -macro_rules! disasm_unreachable { - ($msg:expr $(,)?) => {{ - panic!( - "internal error: entered unreachable code disassembling instruction 0x{:08x}", - $msg - ) - }}; -} diff --git a/disasm/tests/test_disasm.rs b/disasm/tests/test_disasm.rs new file mode 100644 index 0000000..07391d8 --- /dev/null +++ b/disasm/tests/test_disasm.rs @@ -0,0 +1,980 @@ +use ppc750cl::prelude::*; + +macro_rules! assert_asm { + ($ins:ident, $disasm:literal) => {{ + assert_eq!(format!("{}", FormattedIns($ins)), $disasm) + }}; + ($code:literal, $disasm:literal) => {{ + let ins = Ins::new($code, 0x8000_0000); + assert_eq!(format!("{}", FormattedIns(ins)), $disasm) + }}; +} + +#[test] +fn test_ins_addc() { + let ins = Ins::new(0x7c002014, 0x8000_0000u32); + assert_eq!(ins.op, Addc); + assert_eq!(ins.fields(), vec![rD(GPR(0)), rA(GPR(0)), rB(GPR(4))]); + assert_asm!(ins, "addc r0, r0, r4"); +} + +#[test] +fn test_ins_addi() { + let ins = Ins::new(0x38010140, 0x8000_0000u32); + assert_eq!(ins.op, Addi); + assert_eq!( + ins.fields(), + vec![rD(GPR(0)), rA(GPR(1)), simm(Simm(0x140))] + ); + assert_eq!(ins.defs(), vec![rD(GPR(0))]); + assert_eq!(ins.uses(), vec![rA(GPR(1))]); + assert_asm!(ins, "addi r0, r1, 0x140"); + + assert_asm!(0x38010008, "addi r0, r1, 0x8"); + assert_asm!(0x38010010, "addi r0, r1, 0x10"); + assert_asm!(0x38010018, "addi r0, r1, 0x18"); + assert_asm!(0x38010140, "addi r0, r1, 0x140"); + assert_asm!(0x38049000, "addi r0, r4, -0x7000"); + assert_asm!(0x38a00000, "li r5, 0x0"); +} + +#[test] +fn test_ins_adde() { + assert_asm!(0x7c006114, "adde r0, r0, r12"); +} + +#[test] +fn test_ins_addic() { + assert_asm!(0x3060ffff, "addic r3, r0, -0x1"); + assert_asm!(0x30840800, "addic r4, r4, 0x800"); + assert_asm!(0x30a50008, "addic r5, r5, 0x8"); + assert_asm!(0x37DF001C, "addic. r30, r31, 0x1c"); + assert_asm!(0x37E06278, "addic. r31, r0, 0x6278"); + assert_asm!(0x37E3FFFF, "addic. r31, r3, -0x1"); +} + +#[test] +fn test_ins_addis() { + assert_asm!(0x3C030000, "addis r0, r3, 0x0"); + assert_asm!(0x3C038000, "addis r0, r3, 0x8000"); + assert_asm!(0x3D00EFCE, "lis r8, 0xefce"); +} + +#[test] +fn test_ins_addze() { + assert_asm!(0x7C000194, "addze r0, r0"); +} + +#[test] +fn test_ins_and() { + assert_asm!(0x7C001838, "and r0, r0, r3"); + assert_asm!(0x7C001839, "and. r0, r0, r3"); +} + +#[test] +fn test_ins_andc() { + assert_asm!(0x7C001878, "andc r0, r0, r3"); +} + +#[test] +fn test_ins_andi_() { + assert_asm!(0x70000009, "andi. r0, r0, 0x9"); +} + +#[test] +fn test_ins_andis_() { + assert_asm!(0x77c802ff, "andis. r8, r30, 0x2ff"); +} + +#[test] +fn test_ins_b() { + assert_asm!(0x48000000, "b 0x0"); + assert_asm!(0x48000004, "b 0x4"); + assert_asm!(0x4800A5C9, "bl 0xa5c8"); + assert_asm!(0x4823B4D9, "bl 0x23b4d8"); + assert_asm!(0x4BE03C99, "bl -0x1fc368"); + assert_asm!(0x4BDC1A59, "bl -0x23e5a8"); +} + +#[test] +fn test_ins_bc() { + assert_asm!(0x40800008, "bge 0x8"); + assert_asm!(0x40802350, "bge 0x2350"); + assert_asm!(0x4080FC7C, "bge -0x384"); + assert_asm!(0x408100AC, "ble 0xac"); + assert_asm!(0x4081F788, "ble -0x878"); + assert_asm!(0x40821BA0, "bne 0x1ba0"); + assert_asm!(0x4082E3C4, "bne -0x1c3c"); + assert_asm!(0x408600D8, "bne cr1, 0xd8"); + assert_asm!(0x4086FECC, "bne cr1, -0x134"); + assert_asm!(0x409C000C, "bge cr7, 0xc"); + assert_asm!(0x4180000C, "blt 0xc"); + assert_asm!(0x4180F9C0, "blt -0x640"); + assert_asm!(0x4181021C, "bgt 0x21c"); + assert_asm!(0x4181FD80, "bgt -0x280"); + assert_asm!(0x41822304, "beq 0x2304"); + assert_asm!(0x4182FE3C, "beq -0x1c4"); + assert_asm!(0x418401AC, "blt cr1, 0x1ac"); + assert_asm!(0x4184FCE4, "blt cr1, -0x31c"); + assert_asm!(0x418500C0, "bgt cr1, 0xc0"); + assert_asm!(0x418502E4, "bgt cr1, 0x2e4"); + assert_asm!(0x419A0138, "beq cr6, 0x138"); + assert_asm!(0x419C0008, "blt cr7, 0x8"); + assert_asm!(0x4200F560, "bdnz -0xaa0"); +} + +#[test] +fn test_ins_bcctr() { + assert_asm!(0x4E800420, "bctr"); + assert_asm!(0x4E800421, "bctrl"); +} + +#[test] +fn test_ins_bclr() { + assert_asm!(0x4C800020, "bgelr"); + assert_asm!(0x4C810020, "blelr"); + assert_asm!(0x4C820020, "bnelr"); + assert_asm!(0x4C9E0020, "bnelr cr7"); + assert_asm!(0x4D800020, "bltlr"); + assert_asm!(0x4D810020, "bgtlr"); + assert_asm!(0x4D820020, "beqlr"); + assert_asm!(0x4D860020, "beqlr cr1"); + assert_asm!(0x4E800020, "blr"); + assert_asm!(0x4E800021, "blrl"); +} + +#[test] +fn test_ins_cmp() { + assert_asm!(0x7C030000, "cmpw r3, r0"); +} + +/* +#[test] +fn test_ins_cmpi() { + assert_asm!(0x2C050D00, "cmpwi r5, 0xd00"); + assert_asm!(0x2F1F0000, "cmpwi cr6, r31, 0"); +} + +#[test] +fn test_ins_cmpl() { + assert_asm!(0x7C9A2040, "cmplw cr1, r26, r4"); +} + +#[test] +fn test_ins_cmpli() { + assert_asm!(0x2803FFF3, "cmplwi r3, 0xfff3"); + assert_asm!(0x2884F8F0, "cmplwi cr1, r4, 0xf8f0"); +} +*/ + +#[test] +fn test_ins_cntlzw() { + assert_asm!(0x7C030034, "cntlzw r3, r0"); +} + +/* +#[test] +fn test_ins_cror() { + assert_asm!(0x4C411382, "cror cr2, cr1, cr2"); +} + */ + +#[test] +fn test_ins_dcbf() { + assert_asm!(0x7C0028AC, "dcbf r0, r5"); +} + +#[test] +fn test_ins_dcbi() { + assert_asm!(0x7C001BAC, "dcbi r0, r3"); +} + +#[test] +fn test_ins_dcbst() { + assert_asm!(0x7C00286C, "dcbst r0, r5"); +} + +#[test] +fn test_ins_dcbt() { + assert_asm!(0x7C001A2C, "dcbt r0, r3"); +} + +#[test] +fn test_ins_dcbz() { + assert_asm!(0x7C001FEC, "dcbz r0, r3"); +} + +#[test] +fn test_ins_dcbz_l() { + assert_asm!(0x10061FEC, "dcbz_l r6, r3"); +} + +#[test] +fn test_ins_divw() { + assert_asm!(0x7C8073D6, "divw r4, r0, r14"); +} + +#[test] +fn test_ins_divwu() { + assert_asm!(0x7C69E396, "divwu r3, r9, r28"); +} + +#[test] +fn test_ins_extsb() { + assert_asm!(0x7C650774, "extsb r5, r3"); + assert_asm!(0x7C650775, "extsb. r5, r3"); +} + +#[test] +fn test_ins_extsh() { + assert_asm!(0x7C000734, "extsh r0, r0"); + assert_asm!(0x7C000735, "extsh. r0, r0"); +} + +#[test] +fn test_ins_fabs() { + assert_asm!(0xFC000A10, "fabs f0, f1"); +} + +#[test] +fn test_ins_fadd() { + assert_asm!(0xFC00282A, "fadd f0, f0, f5"); +} + +#[test] +fn test_ins_fadds() { + assert_asm!(0xEC41602A, "fadds f2, f1, f12"); +} + +#[test] +fn test_ins_fcmpo() { + assert_asm!(0xFC00C840, "fcmpo cr0, f0, f25"); +} + +#[test] +fn test_ins_fcmpu() { + assert_asm!(0xFC00D000, "fcmpu cr0, f0, f26"); +} + +#[test] +fn test_ins_fctiwz() { + assert_asm!(0xFC20001E, "fctiwz f1, f0"); +} + +#[test] +fn test_ins_fdiv() { + assert_asm!(0xFC200024, "fdiv f1, f0, f0"); +} + +#[test] +fn test_ins_fdivs() { + assert_asm!(0xEC01F824, "fdivs f0, f1, f31"); +} + +#[test] +fn test_ins_fmadds() { + assert_asm!(0xEC0200FA, "fmadds f0, f2, f3, f0"); +} + +#[test] +fn test_ins_fmsub() { + assert_asm!(0xFC000028, "fsub f0, f0, f0"); +} + +#[test] +fn test_ins_fmsubs() { + assert_asm!(0xEC00B828, "fsubs f0, f0, f23"); +} + +#[test] +fn test_ins_fmul() { + assert_asm!(0xFC0000B2, "fmul f0, f0, f2"); + assert_asm!(0xFC0000F2, "fmul f0, f0, f3"); +} + +#[test] +fn test_ins_fmuls() { + assert_asm!(0xEC0007B2, "fmuls f0, f0, f30"); +} + +#[test] +fn test_ins_fneg() { + assert_asm!(0xFCE00050, "fneg f7, f0"); +} + +#[test] +fn test_ins_fnmsub() { + assert_asm!(0xFCC640BC, "fnmsub f6, f6, f2, f8"); +} + +#[test] +fn test_ins_fnmsubs() { + assert_asm!(0xEC022B3C, "fnmsubs f0, f2, f12, f5"); +} + +#[test] +fn test_ins_fres() { + assert_asm!(0xEC000830, "fres f0, f1"); +} + +#[test] +fn test_ins_frsp() { + assert_asm!(0xFC000018, "frsp f0, f0"); +} + +#[test] +fn test_ins_frsqrte() { + assert_asm!(0xFC000834, "frsqrte f0, f1"); +} + +#[test] +fn test_ins_fsel() { + assert_asm!(0xFC01F82E, "fsel f0, f1, f0, f31"); +} + +#[test] +fn test_ins_fsub() { + assert_asm!(0xFC000828, "fsub f0, f0, f1"); +} + +#[test] +fn test_ins_fsubs() { + assert_asm!(0xEC000828, "fsubs f0, f0, f1"); +} + +#[test] +fn test_ins_icbi() { + assert_asm!(0x7C001FAC, "icbi r0, r3"); +} + +#[test] +fn test_ins_isync() { + assert_asm!(0x4C00012C, "isync"); +} + +#[test] +fn test_ins_lbz() { + assert_asm!(0x880104CC, "lbz r0, 0x4cc(r1)"); + assert_asm!(0x8802801B, "lbz r0, -0x7fe5(r2)"); +} + +#[test] +fn test_ins_lbzu() { + assert_asm!(0x8D9DCA10, "lbzu r12, -0x35f0(r29)"); + assert_asm!(0x8E3053EC, "lbzu r17, 0x53ec(r16)"); +} + +#[test] +fn test_ins_lbzux() { + assert_asm!(0x7C0400EE, "lbzux r0, r4, r0"); +} + +#[test] +fn test_ins_lbzx() { + assert_asm!(0x7C0300AE, "lbzx r0, r3, r0"); +} + +#[test] +fn test_ins_lfd() { + assert_asm!(0xC80140C8, "lfd f0, 0x40c8(r1)"); + assert_asm!(0xC8028090, "lfd f0, -0x7f70(r2)"); +} + +#[test] +fn test_ins_lfdu() { + assert_asm!(0xCC03FFC0, "lfdu f0, -0x40(r3)"); +} + +#[test] +fn test_ins_lfdx() { + assert_asm!(0x7C0404AE, "lfdx f0, r4, r0"); +} + +#[test] +fn test_ins_lfs() { + assert_asm!(0xC001027C, "lfs f0, 0x27c(r1)"); + assert_asm!(0xC0028000, "lfs f0, -0x8000(r2)"); +} + +#[test] +fn test_ins_lfsu() { + assert_asm!(0xC404FFF4, "lfsu f0, -0xc(r4)"); + assert_asm!(0xC4170084, "lfsu f0, 0x84(r23)"); +} + +#[test] +fn test_ins_lfsux() { + assert_asm!(0x7C03846E, "lfsux f0, r3, r16"); +} + +#[test] +fn test_ins_lfsx() { + assert_asm!(0x7C03042E, "lfsx f0, r3, r0"); +} + +#[test] +fn test_ins_lha() { + assert_asm!(0xA861000E, "lha r3, 0xe(r1)"); + assert_asm!(0xA80D9F64, "lha r0, -0x609c(r13)"); +} + +#[test] +fn test_ins_lhau() { + assert_asm!(0xAC060006, "lhau r0, 0x6(r6)"); + assert_asm!(0xAC06FFFA, "lhau r0, -0x6(r6)"); +} + +#[test] +fn test_ins_lhax() { + assert_asm!(0x7C0402AE, "lhax r0, r4, r0"); +} + +#[test] +fn test_ins_lhz() { + assert_asm!(0xA00104D6, "lhz r0, 0x4d6(r1)"); + assert_asm!(0xA00296DA, "lhz r0, -0x6926(r2)"); +} + +#[test] +fn test_ins_lhzu() { + assert_asm!(0xA40A0004, "lhzu r0, 0x4(r10)"); +} + +#[test] +fn test_ins_lhzux() { + assert_asm!(0x7C04026E, "lhzux r0, r4, r0"); +} + +#[test] +fn test_ins_lhzx() { + assert_asm!(0x7C03022E, "lhzx r0, r3, r0"); +} + +#[test] +fn test_ins_lmw() { + assert_asm!(0xBB210444, "lmw r25, 0x444(r1)"); +} + +#[test] +fn test_ins_lwbrx() { + assert_asm!(0x7D80242C, "lwbrx r12, r0, r4"); +} + +#[test] +fn test_ins_lwz() { + assert_asm!(0x800294F4, "lwz r0, -0x6b0c(r2)"); + assert_asm!(0x80011254, "lwz r0, 0x1254(r1)"); +} + +#[test] +fn test_ins_lwzu() { + assert_asm!(0x84038608, "lwzu r0, -0x79f8(r3)"); + assert_asm!(0x873E5058, "lwzu r25, 0x5058(r30)"); +} + +#[test] +fn test_ins_lwzux() { + assert_asm!(0x7C03006E, "lwzux r0, r3, r0"); +} + +#[test] +fn test_ins_lwzx() { + assert_asm!(0x7C03002E, "lwzx r0, r3, r0"); +} + +#[test] +fn test_ins_mfcr() { + assert_asm!(0x7C000026, "mfcr cr0"); +} + +/* +#[test] +fn test_ins_mffs() { + assert_asm!(0xFC00048E, "mffs f0"); +} + */ + +#[test] +fn test_ins_mfmsr() { + assert_asm!(0x7C0000A6, "mfmsr r0"); +} + +#[test] +fn test_ins_mfspr() { + assert_asm!(0x7E1A02A6, "mfspr r16, 832"); +} + +#[test] +fn test_ins_mfsr() { + assert_asm!(0x7E0004A6, "mfsr r16, 0"); +} + +#[test] +fn test_ins_mftb() { + assert_asm!(0x7C8C42E6, "mftb r4, 392"); +} + +#[test] +fn test_ins_mtcrf() { + assert_asm!(0x7C6FF120, "mtcrf 255, r3"); +} + +/* +#[test] +fn test_ins_mtfsb0() {} + +#[test] +fn test_ins_mtfsb1() { + assert_asm!(0xFFA0004C, "mtfsb1 0x1d"); +} +*/ + +#[test] +fn test_ins_mtfsf() { + assert_asm!(0xFDFE058E, "mtfsf 255, f0"); + assert_asm!(0xFDFEFD8E, "mtfsf 255, f31"); +} + +#[test] +fn test_ins_mtmsr() { + assert_asm!(0x7C000124, "mtmsr r0"); +} + +#[test] +fn test_ins_mtspr() { + assert_asm!(0x7E75FBA6, "mtspr 703, r19"); +} + +#[test] +fn test_ins_mtsr() { + assert_asm!(0x7E0001A4, "mtsr 0, r16"); +} + +#[test] +fn test_ins_mulhw() { + assert_asm!(0x7C7F2096, "mulhw r3, r31, r4"); +} + +#[test] +fn test_ins_mulhwu() { + assert_asm!(0x7C7D0016, "mulhwu r3, r29, r0"); +} + +#[test] +fn test_ins_mulli() { + assert_asm!(0x1C001880, "mulli r0, r0, 0x1880"); + assert_asm!(0x1FBD0030, "mulli r29, r29, 0x30"); +} + +#[test] +fn test_ins_mullw() { + assert_asm!(0x7C7D01D6, "mullw r3, r29, r0"); +} + +#[test] +fn test_ins_nand() { + assert_asm!(0x7C7D03B8, "nand r29, r3, r0"); +} + +#[test] +fn test_ins_neg() { + assert_asm!(0x7C0600D0, "neg r0, r6"); +} + +#[test] +fn test_ins_nor() { + assert_asm!(0x7C0500F8, "nor r5, r0, r0"); +} + +#[test] +fn test_ins_or() { + assert_asm!(0x7C04DB78, "or r4, r0, r27"); +} + +#[test] +fn test_ins_orc() { + assert_asm!(0x7C042338, "orc r4, r0, r4"); +} + +#[test] +fn test_ins_ori() { + assert_asm!(0x60002204, "ori r0, r0, 0x2204"); +} + +#[test] +fn test_ins_oris() { + assert_asm!(0x67A06800, "oris r0, r29, 0x6800"); +} + +#[test] +fn test_ins_psq_l() { + assert_asm!(0xE02500AC, "psq_l f1, 0xac(r5), 0, qr0"); +} + +/* +#[test] +fn test_ins_psq_lu() { + assert_asm!(0xE5435010, "psq_lu f10, 0x10(r3), 0, qr5"); +} + */ + +#[test] +fn test_ins_psq_lx() { + let ins = Ins::new(0x1000000C, 0x8000_0000u32); + assert_eq!(ins.op, PsqLx); + assert_eq!( + ins.fields(), + vec![ + frD(FPR(0)), + rA(GPR(0)), + rB(GPR(0)), + ps_W(OpaqueU(0)), + ps_l(GQR(0)) + ] + ); + assert_eq!(ins.defs(), vec![frD(FPR(0))]); + assert_eq!(ins.uses(), vec![rB(GPR(0))]); + + assert_asm!(0x1000000C, "psq_lx f0, r0, r0, 0, qr0"); +} + +/* +#[test] +fn test_ins_psq_st() { + assert_asm!(0xF1230210, "psq_st f9, 0x210(r3), 0, qr0"); + assert_asm!(0xF1238008, "psq_st f9, 8(r3), 1, qr0"); +} + */ + +#[test] +fn test_ins_psq_stu() { + assert_asm!(0xF40A0020, "psq_stu f0, 0x20(r10), 0, qr0"); +} + +#[test] +fn test_ins_psq_stx() { + assert_asm!(0x13E1000E, "psq_stx f31, r1, r0, 0, qr0"); +} + +#[test] +fn test_ins_ps_abs() { + assert_asm!(0x10A03210, "ps_abs f5, f6"); +} + +#[test] +fn test_ins_ps_add() { + assert_asm!(0x1006382A, "ps_add f0, f6, f7"); +} + +#[test] +fn test_ins_ps_cmpo0() { + assert_asm!(0x10070840, "ps_cmpo0 cr0, f7, f1"); +} + +#[test] +fn test_ins_ps_cmpu0() { + assert_asm!(0x10003000, "ps_cmpu0 cr0, f0, f6"); +} + +#[test] +fn test_ins_ps_cmpu1() { + assert_asm!(0x10003080, "ps_cmpu1 cr0, f0, f6"); +} + +#[test] +fn test_ins_ps_madd() { + assert_asm!(0x112141FA, "ps_madd f9, f1, f7, f8"); +} + +#[test] +fn test_ins_ps_madds0() { + assert_asm!(0x10AC299C, "ps_madds0 f5, f12, f6, f5"); +} + +#[test] +fn test_ins_ps_madds1() { + assert_asm!(0x110640DE, "ps_madds1 f8, f6, f3, f8"); +} + +#[test] +fn test_ins_ps_merge00() { + assert_asm!(0x10400420, "ps_merge00 f2, f0, f0"); +} + +#[test] +fn test_ins_ps_merge01() { + assert_asm!(0x10400C60, "ps_merge01 f2, f0, f1"); +} + +#[test] +fn test_ins_ps_merge10() { + assert_asm!(0x104004A0, "ps_merge10 f2, f0, f0"); +} + +#[test] +fn test_ins_ps_merge11() { + assert_asm!(0x10AA14E0, "ps_merge11 f5, f10, f2"); +} + +#[test] +fn test_ins_ps_msub() { + assert_asm!(0x10A53778, "ps_msub f5, f5, f29, f6"); +} + +#[test] +fn test_ins_ps_mul() { + assert_asm!(0x10000032, "ps_mul f0, f0, f0"); +} + +#[test] +fn test_ins_ps_muls0() { + assert_asm!(0x100002D8, "ps_muls0 f0, f0, f11"); +} + +#[test] +fn test_ins_ps_muls1() { + assert_asm!(0x10A2005A, "ps_muls1 f5, f2, f1"); +} + +#[test] +fn test_ins_ps_nabs() { + assert_asm!(0x10803210, "ps_abs f4, f6"); +} + +#[test] +fn test_ins_ps_neg() { + assert_asm!(0x10E03850, "ps_neg f7, f7"); +} + +#[test] +fn test_ins_ps_nmadd() { + assert_asm!(0x10CB30FE, "ps_nmadd f6, f11, f3, f6"); +} + +#[test] +fn test_ins_ps_nmsub() { + assert_asm!(0x107E083C, "ps_nmsub f3, f30, f0, f1"); +} + +#[test] +fn test_ins_ps_sel() { + assert_asm!(0x106428EE, "ps_sel f3, f4, f3, f5"); +} + +#[test] +fn test_ins_ps_sub() { + assert_asm!(0x10A92828, "ps_sub f5, f9, f5"); +} + +#[test] +fn test_ins_ps_sum0() { + assert_asm!(0x10230854, "ps_sum0 f1, f3, f1, f1"); +} + +#[test] +fn test_ins_ps_sum1() { + assert_asm!(0x10A12956, "ps_sum1 f5, f1, f5, f5"); +} + +#[test] +fn test_ins_rfi() { + assert_asm!(0x4C000064, "rfi"); +} + +#[test] +fn test_ins_rlwimi() { + assert_asm!(0x500306FE, "rlwimi r3, r0, 0, 27, 31"); + assert_asm!(0x50032D74, "rlwimi r3, r0, 5, 21, 26"); +} + +#[test] +fn test_ins_rlwinm() { + assert_asm!(0x54000423, "rlwinm. r0, r0, 0, 16, 17"); + assert_asm!(0x54000432, "rlwinm r0, r0, 0, 16, 25"); +} + +#[test] +fn test_ins_rlwnm() { + assert_asm!(0x5D6A67FE, "rlwnm r10, r11, r12, 31, 31"); + assert_asm!(0x5FC52EFE, "rlwnm r5, r30, r5, 27, 31"); +} + +#[test] +fn test_ins_sc() { + assert_asm!(0x44000002, "sc"); +} + +#[test] +fn test_ins_slw() { + assert_asm!(0x7C042830, "slw r4, r0, r5"); +} + +#[test] +fn test_ins_sraw() { + assert_asm!(0x7C043E30, "sraw r4, r0, r7"); +} + +#[test] +fn test_ins_srawi() { + assert_asm!(0x7C000E70, "srawi r0, r0, 1"); + assert_asm!(0x7C001670, "srawi r0, r0, 2"); +} + +#[test] +fn test_ins_srw() { + assert_asm!(0x7C001C30, "srw r0, r0, r3"); +} + +#[test] +fn test_ins_stb() { + assert_asm!(0x980105EC, "stb r0, 0x5ec(r1)"); + assert_asm!(0x98030000, "stb r0, 0x0(r3)"); +} + +#[test] +fn test_ins_stbu() { + assert_asm!(0x9D2A7428, "stbu r9, 0x7428(r10)"); + assert_asm!(0x9D66FFFF, "stbu r11, -0x1(r6)"); +} + +#[test] +fn test_ins_stbux() { + assert_asm!(0x7C08F9EE, "stbux r0, r8, r31"); +} + +#[test] +fn test_ins_stbx() { + assert_asm!(0x7C03F9AE, "stbx r0, r3, r31"); +} + +#[test] +fn test_ins_stfd() { + assert_asm!(0xD80D97B0, "stfd f0, -0x6850(r13)"); + assert_asm!(0xD8050090, "stfd f0, 0x90(r5)"); +} + +#[test] +fn test_ins_stfdu() { + assert_asm!(0xDC24FFC0, "stfdu f1, -0x40(r4)"); +} + +/* +#[test] +fn test_ins_stfdx() { + assert_asm!(0x7C4405AE, "stfdx f2, r4, r0"); +} + */ + +#[test] +fn test_ins_stfs() { + assert_asm!(0xD003086C, "stfs f0, 0x86c(r3)"); + assert_asm!(0xD0038000, "stfs f0, -0x8000(r3)"); +} + +#[test] +fn test_ins_stfsx() { + assert_asm!(0x7C465D2E, "stfsx f2, r6, r11"); +} + +#[test] +fn test_ins_sth() { + assert_asm!(0xB0038A7C, "sth r0, -0x7584(r3)"); + assert_asm!(0xB0035036, "sth r0, 0x5036(r3)"); +} + +#[test] +fn test_ins_sthbrx() { + assert_asm!(0x7C60072C, "sthbrx r3, r0, r0"); +} + +#[test] +fn test_ins_sthu() { + assert_asm!(0xB4055B88, "sthu r0, 0x5b88(r5)"); +} + +#[test] +fn test_ins_sthux() { + assert_asm!(0x7C03236E, "sthux r0, r3, r4"); +} + +#[test] +fn test_ins_sthx() { + assert_asm!(0x7C1C2B2E, "sthx r0, r28, r5"); +} + +#[test] +fn test_ins_stmw() { + assert_asm!(0xBFA202A4, "stmw r29, 0x2a4(r2)"); +} + +#[test] +fn test_ins_stw() { + assert_asm!(0x900140CC, "stw r0, 0x40cc(r1)"); + assert_asm!(0x9003FFBC, "stw r0, -0x44(r3)"); +} + +#[test] +fn test_ins_stwbrx() { + assert_asm!(0x7C00FD2C, "stwbrx r0, r0, r31"); +} + +#[test] +fn test_ins_stwu() { + assert_asm!(0x9421EBC0, "stwu r1, -0x1440(r1)"); +} + +#[test] +fn test_ins_stwux() { + assert_asm!(0x7C01B96E, "stwux r0, r1, r23"); +} + +#[test] +fn test_ins_stwx() { + assert_asm!(0x7C03212E, "stwx r0, r3, r4"); +} + +#[test] +fn test_ins_subf() { + assert_asm!(0x7C051850, "subf r0, r5, r3"); + assert_asm!(0x7C051851, "subf. r0, r5, r3"); +} + +#[test] +fn test_ins_subfc() { + assert_asm!(0x7C040010, "subfc r0, r4, r0"); +} + +#[test] +fn test_ins_subfe() { + assert_asm!(0x7C030110, "subfe r0, r3, r0"); +} + +#[test] +fn test_ins_subfic() { + assert_asm!(0x200602FF, "subfic r0, r6, 0x2ff"); +} + +#[test] +fn test_ins_subfze() { + assert_asm!(0x7C000190, "subfze r0, r0"); +} + +#[test] +fn test_ins_sync() { + assert_asm!(0x7C0004AC, "sync"); +} + +#[test] +fn test_ins_xor() { + assert_asm!(0x7C052A78, "xor r5, r0, r5"); +} + +#[test] +fn test_ins_xori() { + assert_asm!(0x68E71021, "xori r7, r7, 0x1021"); +} + +#[test] +fn test_ins_xoris() { + assert_asm!(0x6E3D8000, "xoris r29, r17, 0x8000"); +} diff --git a/dol/Cargo.toml b/dol/Cargo.toml index 195d6a4..5b3a995 100644 --- a/dol/Cargo.toml +++ b/dol/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "dol" version = "0.1.0" -edition = "2018" +edition = "2021" authors = ["Richard Patel "] license = "GPL-3.0-or-later" description = "Deserializer for the DOL executable format" diff --git a/dol/src/lib.rs b/dol/src/lib.rs index 0b3bb05..4d53b44 100644 --- a/dol/src/lib.rs +++ b/dol/src/lib.rs @@ -121,7 +121,7 @@ pub enum DolSectionType { Bss, } -#[derive()] +#[derive(Debug, Clone)] pub struct DolSection { pub kind: DolSectionType, pub index: usize, diff --git a/flow-graph/Cargo.toml b/flow-graph/Cargo.toml index 0afa423..6c6092a 100644 --- a/flow-graph/Cargo.toml +++ b/flow-graph/Cargo.toml @@ -1,16 +1,16 @@ [package] name = "ppc750cl-flow-graph" -version = "0.1.1" -edition = "2018" +version = "0.2.0" +edition = "2021" authors = ["riidefi ", "Richard Patel "] license = "GPL-3.0-or-later" description = "Control flow graph analysis for PowerPC 750CL" repository = "https://github.com/terorie/ppc750cl" [dependencies] -clap = "2.33" +clap = "3" dol = { version = "0.1.0", path = "../dol" } itertools = "0.10" -parse_int = "0.5" +parse_int = "0.6" petgraph = "0.6" -ppc750cl = { version = "0.1.1", path = "../disasm" } +ppc750cl = { version = "0.2.0", path = "../disasm" } diff --git a/flow-graph/src/flow.rs b/flow-graph/src/flow.rs index 1c4d81b..8ded08f 100644 --- a/flow-graph/src/flow.rs +++ b/flow-graph/src/flow.rs @@ -8,6 +8,7 @@ use petgraph::algo::dominators::Dominators; use petgraph::graph::{DefaultIx, NodeIndex}; use petgraph::Graph; +use ppc750cl::formatter::FormattedIns; use ppc750cl::{Ins, Opcode}; use crate::slices::{BasicSlices, CodeIdx}; @@ -53,18 +54,21 @@ impl<'a> BasicBlock<'a> { for ins in code { match ins.op { Opcode::Addis => { - if ins.a() == 0 { + if ins.field_rA() == 0 { // lis - defs.insert(ins.d(), ins.uimm()); + defs.insert(ins.field_rD() as u8, ins.field_uimm() as u16); } else { - defs.remove(&ins.d()); + defs.remove(&(ins.field_rD() as u8)); } } Opcode::Addi => { - if let Some(hi) = defs.get(&ins.a()) { - data_refs.insert(ins.addr / 4, ((*hi as u32) << 16) + (ins.uimm() as u32)); + if let Some(hi) = defs.get(&(ins.field_rA() as u8)) { + data_refs.insert( + ins.addr / 4, + ((*hi as u32) << 16) + (ins.field_uimm() as u32), + ); } - defs.remove(&ins.d()); + defs.remove(&(ins.field_rD() as u8)); } _ => (), } @@ -88,7 +92,7 @@ impl<'a> Debug for BasicBlock<'a> { self.range.end * 4 )?; for ins in self.code { - writeln!(f, "{}", ins.to_string())?; + writeln!(f, "{}", FormattedIns(ins.clone()))?; if let Some(addr) = self.data_refs.get(&(ins.addr / 4)) { writeln!(f, " ref: {:0>#8x}", addr)?; } @@ -151,8 +155,8 @@ impl<'a> FlowGraph<'a> { // Get last instruction of left block. // Unless it's an unconditional branch, we can connect the blocks. let last_ins = &src_block.code.last().unwrap(); - if last_ins.code == Opcode::BLR - || (last_ins.op == Opcode::B && last_ins.bo() == 0b10100) + if last_ins.code == 0x4E800020 + || (last_ins.op == Opcode::B && last_ins.field_BO() == 0b10100) { continue; } diff --git a/flow-graph/src/main.rs b/flow-graph/src/main.rs index 20b3f6b..de2c5cd 100644 --- a/flow-graph/src/main.rs +++ b/flow-graph/src/main.rs @@ -1,4 +1,3 @@ -use clap::clap_app; use petgraph::dot::{Config as DotConfig, Dot}; use ppc750cl::{disasm_iter, Ins}; @@ -11,14 +10,29 @@ use crate::slices::BasicSlices; use dol::Dol; fn main() { - let matches = clap_app!(myapp => - (version: "1.0") - (about: "Control flow graph analysis for PowerPC 750CL") - (@arg START: --start +required +takes_value "Start address") - (@arg STOP: --stop +required +takes_value "Stop address") - (@arg INPUT: +required "Binary input file") - ) - .get_matches(); + let matches = clap::Command::new("ppc750cl-flow-graph") + .version("0.2.0") + .about("Control flow graph analysis for PowerPC 750CL") + .arg( + clap::Arg::new("START") + .long("--start") + .required(true) + .takes_value(true) + .help("Start address"), + ) + .arg( + clap::Arg::new("STOP") + .long("--stop") + .required(true) + .takes_value(true) + .help("Stop address"), + ) + .arg( + clap::Arg::new("INPUT") + .required(true) + .help("Binary input file"), + ) + .get_matches(); let start_addr = matches.value_of("START").unwrap(); let start_addr: u32 = ::parse_int::parse(start_addr).expect("Invalid address flag"); diff --git a/flow-graph/src/slices.rs b/flow-graph/src/slices.rs index 368ae2b..6b62759 100644 --- a/flow-graph/src/slices.rs +++ b/flow-graph/src/slices.rs @@ -24,7 +24,7 @@ impl BasicSlices { let is_control_flow_ins = match ins.op { // Direct branches are control flow instructions if they don't save the link register. // If they do, we encountered a function call. - Opcode::B | Opcode::Bc => ins.lk() == 0, + Opcode::B | Opcode::Bc => !ins.field_LK(), // Switch table Opcode::Bcctr => panic!("jump tables not supported yet"), _ => false, @@ -33,7 +33,7 @@ impl BasicSlices { continue; } // We encountered some kind of control flow instruction. - if ins.code != Opcode::BLR { + if ins.field_BO() == 20 && ins.field_BI() == 0 { // There's a possibility that branch can be taken. // Branch destinations are always the first instruction of a block. // Thus, we also found the end of another block. @@ -58,5 +58,5 @@ fn is_conditional_branch(ins: &Ins) -> bool { _ => return false, }; // Check whether bits "branch always". - ins.bo() & 0b10100 != 0b10100 + ins.field_BO() & 0b10100 != 0b10100 } diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index fdcb8d7..5b846dc 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "ppc750cl-fuzz" -version = "0.1.1" -edition = "2018" +version = "0.2.0" +edition = "2021" authors = ["Richard Patel "] license = "GPL-3.0-or-later" description = "Complete fuzzer for ppc750cl" @@ -9,4 +9,4 @@ repository = "https://github.com/terorie/ppc750cl" [dependencies] num_cpus = "1.13" -ppc750cl = { path = "../disasm", version = "0.1.1" } +ppc750cl = { path = "../disasm", version = "0.2.0" } diff --git a/fuzz/src/main.rs b/fuzz/src/main.rs index e4d1d84..be0840b 100644 --- a/fuzz/src/main.rs +++ b/fuzz/src/main.rs @@ -1,10 +1,11 @@ +use std::io::Write; +use std::ops::Range; use std::sync::atomic::{AtomicU32, Ordering}; use std::sync::Arc; use std::time::{Duration, Instant}; -use ppc750cl::formatter::SimpleFormatter; +use ppc750cl::formatter::FormattedIns; use ppc750cl::Ins; -use std::ops::Range; fn main() { let start = Instant::now(); @@ -62,7 +63,6 @@ impl MultiFuzzer { // for most of the time. handle.join().expect("thread panicked"); } - disasm(0xFFFF_FFFF); } } @@ -81,11 +81,14 @@ impl Fuzzer { } fn dispatch(&self) -> std::thread::JoinHandle<()> { + let mut devnull = DevNull; + let counter = Arc::clone(&self.counter); let range = self.range.clone(); std::thread::spawn(move || { for x in range.clone() { - disasm(x); + let ins = Ins::new(x, 0x8000_0000); + writeln!(&mut devnull, "{}", FormattedIns(ins)).unwrap(); if x % (1 << 19) == 0 { counter.store(x, Ordering::Relaxed); } @@ -95,13 +98,6 @@ impl Fuzzer { } } -fn disasm(x: u32) { - let devnull = DevNull; - let mut formatter = SimpleFormatter { writer: devnull }; - let ins = Ins::new(x, 0x8000_0000u32); - ins.write_string(&mut formatter).unwrap(); -} - struct DevNull; impl std::io::Write for DevNull { diff --git a/genisa/Cargo.toml b/genisa/Cargo.toml new file mode 100644 index 0000000..625e8b8 --- /dev/null +++ b/genisa/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "ppc750cl-genisa" +version = "0.2.0" +edition = "2021" +authors = ["Richard Patel "] +license = "GPL-3.0-or-later" +description = "Rust code generator for ppc750cl" +repository = "https://github.com/terorie/ppc750cl" + + +[dependencies] +itertools = "0.10" +proc-macro2 = "1.0" +quote = "1.0" +syn = "1.0" +serde = { version = "1.0", features = ["derive"] } +serde_yaml = "0.8" diff --git a/genisa/src/main.rs b/genisa/src/main.rs new file mode 100644 index 0000000..8aad187 --- /dev/null +++ b/genisa/src/main.rs @@ -0,0 +1,693 @@ +use std::collections::HashMap; +use std::fs::File; +use std::io::Write; +use std::ops::Range; +use std::process::{Command, Stdio}; +use std::str::FromStr; + +use itertools::Itertools; +use proc_macro2::{Ident, Literal, Span, TokenStream, TokenTree}; +use quote::quote; +use serde::{Deserialize, Deserializer}; +use syn::{LitChar, LitInt, LitStr}; + +macro_rules! token_stream { + ($stream:ident) => { + TokenStream::from_iter($stream.into_iter()) + }; +} + +fn main() { + if let Err(err) = _main() { + eprintln!("{}", err); + std::process::exit(1); + } +} + +type Error = Box; +type Result = std::result::Result; + +fn _main() -> Result<()> { + let isa = load_isa()?; + + let mut unformatted_code = Vec::::new(); + writeln!( + &mut unformatted_code, + "{}", + quote! { + use crate::prelude::*; + } + )?; + writeln!(&mut unformatted_code, "{}", isa.gen_opcode_enum()?)?; + writeln!(&mut unformatted_code, "{}", isa.gen_field_enum()?)?; + writeln!(&mut unformatted_code, "{}", isa.gen_ins_impl()?)?; + + let formatted_code = rustfmt(unformatted_code); + File::create("./disasm/src/generated.rs")?.write_all(&formatted_code)?; + + Ok(()) +} + +fn rustfmt(code: Vec) -> Vec { + let mut rustfmt = Command::new("rustfmt") + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .expect("failed to spawn rustfmt"); + + let mut stdin = rustfmt.stdin.take().unwrap(); + std::thread::spawn(move || { + let _ = stdin.write_all(&code); + }); + + let rustfmt_res = rustfmt.wait_with_output().expect("failed to run rustfmt"); + if !rustfmt_res.status.success() { + panic!("rustfmt failed"); + } + + rustfmt_res.stdout +} + +#[derive(Default)] +pub(crate) struct BitRange(Range); + +impl<'de> Deserialize<'de> for BitRange { + fn deserialize(deserializer: D) -> std::result::Result + where + D: Deserializer<'de>, + { + let range_str: String = Deserialize::deserialize(deserializer)?; + if let Some((start_str, stop_str)) = range_str.split_once("..") { + let start = start_str.parse::().map_err(serde::de::Error::custom)?; + let stop = stop_str.parse::().map_err(serde::de::Error::custom)?; + Ok(Self(start..stop)) + } else { + let bit_idx = range_str.parse::().map_err(serde::de::Error::custom)?; + Ok(Self(bit_idx..bit_idx)) + } + } +} + +#[derive(Deserialize, Default)] +#[serde(default)] +pub(crate) struct Field { + name: String, + desc: String, + bits: BitRange, + signed: bool, + split: bool, + arg: Option, + shift_left: u8, +} + +impl Field { + fn variant_identifier(&self) -> Option { + self.identifier("") + } + + fn identifier(&self, prefix: &str) -> Option { + if self.name.strip_suffix(".nz").is_none() { + Some(to_rust_ident(prefix, &self.name)) + } else { + None + } + } + + fn express_value(&self, code: TokenStream) -> TokenStream { + let mut val = quote!(#code); + + let shift = 32 - self.bits.0.end; + if shift > 0 { + val = quote!((#val >> #shift)); + } + + let mask = (1u32 << self.bits.0.len()) - 1; + if mask != 0xFFFF_FFFF { + let mask = LitInt::new(&format!("0x{:x}", mask), Span::call_site()); + val = quote!((#val & #mask)); + } + + // https://graphics.stanford.edu/~seander/bithacks.html#VariableSignExtend + if self.signed { + let mask2 = 1u32 << (self.bits.0.len() - 1); + let mask2 = LitInt::new(&format!("0x{:x}", mask2), Span::call_site()); + val = quote!(((#val ^ #mask2).wrapping_sub(#mask2))) + } + + let val_shift = self.shift_left; + if val_shift > 0 { + val = quote!((#val << #val_shift)); + } + + val + } + + fn express_value_self(&self) -> TokenStream { + self.express_value(quote!(self.code)) + } + + fn enum_variant_definition(&self) -> Option { + let ident = self.variant_identifier()?; + Some(if let Some(arg) = &self.arg { + let arg = TokenTree::Ident(Ident::new(arg, Span::call_site())); + quote! { + #ident(#arg), + } + } else { + quote! { + #ident, + } + }) + } + + fn construct_variant(&self, code: TokenStream) -> TokenStream { + let field_variant = self.variant_identifier(); + if let Some(arg) = &self.arg { + let field_arg = TokenTree::Ident(Ident::new(arg, Span::call_site())); + let value = self.express_value(code); + quote! { + Field::#field_variant(#field_arg(#value as _)) + } + } else { + quote! { + Field::#field_variant + } + } + } + + fn construct_variant_self(&self) -> TokenStream { + self.construct_variant(quote!(self.code)) + } + + fn construct_accessor(&self) -> TokenStream { + let field_variant = match self.identifier("field_") { + Some(v) => v, + None => return TokenStream::new(), + }; + if self.arg.is_none() { + return TokenStream::new(); + } + let value = self.express_value_self(); + let ret_type = if self.signed { + quote!(isize) + } else { + quote!(usize) + }; + quote! { + #[inline(always)] + pub fn #field_variant(&self) -> #ret_type { + #value as _ + } + } + } +} + +#[derive(Deserialize, Default)] +#[serde(default)] +pub(crate) struct Opcode { + name: String, + desc: String, + bitmask: u32, + pattern: u32, + modifiers: Vec, + side_effects: Vec, + args: Vec, + defs: Vec, + uses: Vec, +} + +impl Opcode { + fn variant_identifier(&self) -> Result { + to_rust_variant(&self.name) + } +} + +#[derive(Deserialize, Default)] +#[serde(default)] +pub(crate) struct Mnemonic { + name: String, + opcode: String, + modifiers: Vec, + args: Vec, + condition: String, +} + +#[derive(Deserialize, Default)] +#[serde(default)] +pub(crate) struct Modifier { + name: String, + suffix: char, + bit: u8, +} + +impl Modifier { + fn express_value_self(&self) -> TokenStream { + let modifier_bit = self.bit as usize; + quote!(self.bit(#modifier_bit)) + } + + fn construct_accessor(&self) -> TokenStream { + let field_variant = to_rust_ident("field_", &self.name); + let value = self.express_value_self(); + quote! { + #[inline(always)] + pub fn #field_variant(&self) -> bool { + #value + } + } + } +} + +#[derive(Deserialize, Default)] +#[serde(default)] +pub(crate) struct Isa { + fields: Vec, + modifiers: Vec, + opcodes: Vec, + mnemonics: Vec, +} + +fn load_isa() -> Result { + let yaml_file = File::open("isa.yaml")?; + let isa: Isa = serde_yaml::from_reader(yaml_file)?; + Ok(isa) +} + +impl Isa { + fn gen_opcode_enum(&self) -> Result { + // Create enum variants. + let enum_variants = self + .opcodes + .iter() + .map(|opcode| -> Result { + let ident = opcode.variant_identifier()?; + Ok(quote! { + #ident, + }) + }) + .try_collect::, Error>()?; + let enum_variants = token_stream!(enum_variants); + + // Create functions. + let mnemonic_fn = self.gen_mnemonic_fn()?; + let detect_fn = self.gen_opcode_detect()?; + + // Create final enum. + let opcode_enum = quote! { + #[derive(Debug, Copy, Clone, Eq, PartialEq)] + pub enum Opcode { + Illegal = -1, + #enum_variants + } + #[allow(clippy::all)] + impl Opcode { + #mnemonic_fn + #detect_fn + } + }; + Ok(opcode_enum) + } + + fn gen_mnemonic_fn(&self) -> Result { + // Create match arms. + let match_arms = self + .opcodes + .iter() + .map(|opcode| { + let variant = opcode.variant_identifier()?; + let literal = Literal::string(&opcode.name); + Ok(quote! { + Opcode::#variant => #literal, + }) + }) + .try_collect::, Error>()?; + let match_arms = token_stream!(match_arms); + // Create final function. + let mnemonic_fn = quote! { + pub(crate) fn _mnemonic(self) -> &'static str { + match self { + Opcode::Illegal => "", + #match_arms + } + } + }; + Ok(mnemonic_fn) + } + + pub(crate) fn gen_opcode_detect(&self) -> Result { + // Generate if chain. + let if_chain = self + .opcodes + .iter() + .map(|opcode| { + let bitmask_str = format!("{:>#8x}", opcode.bitmask); + let bitmask = LitInt::new(&bitmask_str, Span::call_site()); + let pattern_str = format!("{:>#8x}", opcode.pattern); + let pattern = LitInt::new(&pattern_str, Span::call_site()); + let identifier = opcode.variant_identifier()?; + Ok(quote! { + if code & #bitmask == #pattern { + return Opcode::#identifier; + } + }) + }) + .try_collect::, Error>()?; + let if_chain = token_stream!(if_chain); + // Generate function. + let func = quote! { + pub(crate) fn _detect(code: u32) -> Self { + #if_chain + Opcode::Illegal + } + }; + Ok(func) + } + + pub(crate) fn gen_field_enum(&self) -> Result { + // Create enum variants. + let mut enum_variants = Vec::new(); + for field in &self.fields { + if let Some(field) = field.enum_variant_definition() { + enum_variants.push(field); + } + } + let enum_variants = token_stream!(enum_variants); + + // Create final enum. + let field_enum = quote! { + #[allow(non_camel_case_types)] + #[derive(Debug, Copy, Clone, Eq, PartialEq)] + pub enum Field { + #enum_variants + } + }; + Ok(field_enum) + } + + pub(crate) fn gen_ins_impl(&self) -> Result { + // Map fields by name. + let mut field_by_name = HashMap::::new(); + for field in &self.fields { + field_by_name.insert(field.name.clone(), field); + } + let mut modifier_by_name = HashMap::::new(); + for modifier in &self.modifiers { + modifier_by_name.insert(modifier.name.clone(), modifier); + } + // Map mnemonics by opcode. + let mut mnemonics_by_opcode = HashMap::<&String, Vec<&Mnemonic>>::new(); + for simple in &self.mnemonics { + mnemonics_by_opcode + .entry(&simple.opcode) + .or_insert_with(Vec::new) + .push(simple) + } + // Generate match arms for each opcode. + let mut field_match_arms = Vec::new(); + let mut def_match_arms = Vec::new(); + let mut use_match_arms = Vec::new(); + let mut suffix_match_arms = Vec::new(); + let mut simplified_ins_match_arms = Vec::new(); + for opcode in &self.opcodes { + // Generate fields of opcode. + let mut fields = Vec::new(); + for arg in &opcode.args { + let field: &Field = field_by_name + .get(arg) + .ok_or_else(|| Error::from(format!("undefined field {}", arg)))?; + let variant = field.construct_variant_self(); + fields.extend(quote! { #variant, }) + } + let fields = token_stream!(fields); + // Emit match arm. + let ident = opcode.variant_identifier()?; + field_match_arms.push(quote! { + Opcode::#ident => vec![#fields], + }); + + // Generate modifiers. + let suffix = express_suffix(&modifier_by_name, opcode)?; + suffix_match_arms.push(quote! { + Opcode::#ident => #suffix, + }); + + // Generate defs. + let mut defs = Vec::new(); + for arg in &opcode.defs { + let field: &Field = field_by_name.get(arg).ok_or_else(|| { + syn::Error::new(Span::call_site(), format!("undefined field {}", arg)) + })?; + let variant = field.construct_variant_self(); + defs.extend(quote! { #variant, }) + } + let defs = token_stream!(defs); + let ident = opcode.variant_identifier()?; + def_match_arms.push(quote! { + Opcode::#ident => vec![#defs], + }); + + // Generate uses. + let mut uses = Vec::new(); + let mut special_uses = Vec::new(); + for arg in &opcode.uses { + // Detect non-zero modifier. + let mut arg = arg.as_str(); + let mut non_zero = false; + if let Some(substr) = arg.strip_suffix(".nz") { + non_zero = true; + arg = substr; + } + // Get underlying field. + let field: &Field = field_by_name.get(arg).ok_or_else(|| { + syn::Error::new(Span::call_site(), format!("undefined field {}", arg)) + })?; + let variant = field.construct_variant_self(); + if non_zero { + let value = field.express_value_self(); + special_uses.extend(quote! { + if (#value) != 0 { + uses.push(#variant); + } + }) + } else { + uses.extend(quote! { + #variant, + }) + } + } + let uses = token_stream!(uses); + let ident = opcode.variant_identifier()?; + let special_uses = token_stream!(special_uses); + use_match_arms.push(quote! { + Opcode::#ident => { + let mut uses = vec![#uses]; + #special_uses + uses + }, + }); + + // Generate instruction simplification. + if let Some(mnemonics) = mnemonics_by_opcode.get(&opcode.name) { + let mut simplified_conditions = Vec::new(); + for mnemonic in mnemonics { + if mnemonic.condition.is_empty() { + continue; // TODO else branch + } + simplified_conditions.push(quote!(if)); + simplified_conditions.push(compile_mnemonic_condition( + &field_by_name, + &mnemonic.condition, + )?); + // Emit branch. + let mnemonic_lit = LitStr::new(&mnemonic.name, Span::call_site()); + // Extract arguments. + let mut args = Vec::new(); + for arg in &mnemonic.args { + let field = field_by_name + .get(arg) + .unwrap_or_else(|| panic!("field not found: {}", arg)); + let variant = Ident::new(field.arg.as_ref().unwrap(), Span::call_site()); + let value = field.express_value_self(); + args.push(quote!(Argument::#variant(#variant(#value as _)),)); + } + let args = token_stream!(args); + simplified_conditions.push(quote! { + { + return SimplifiedIns { + mnemonic: #mnemonic_lit, + args: vec![#args], + ins: self, + }; + } + }); + } + let simplified_conditions = token_stream!(simplified_conditions); + simplified_ins_match_arms.push(quote! { + Opcode::#ident => { + #simplified_conditions + }, + }); + } + } + let field_match_arms = token_stream!(field_match_arms); + let def_match_arms = token_stream!(def_match_arms); + let use_match_arms = token_stream!(use_match_arms); + let suffix_match_arms = token_stream!(suffix_match_arms); + let simplified_ins_match_arms = token_stream!(simplified_ins_match_arms); + let field_accessors = self + .fields + .iter() + .map(|field| field.construct_accessor()) + .collect::>(); + let field_accessors = token_stream!(field_accessors); + let modifier_accessors = self + .modifiers + .iter() + .map(|modifier| modifier.construct_accessor()) + .collect::>(); + let modifier_accessors = token_stream!(modifier_accessors); + // Generate final fields function. + let ins_impl = quote! { + #[allow(clippy::all, unused_mut)] + impl Ins { + pub(crate) fn _fields(&self) -> Vec { + match self.op { + Opcode::Illegal => vec![], + #field_match_arms + } + } + + pub(crate) fn _defs(&self) -> Vec { + match self.op { + Opcode::Illegal => vec![], + #def_match_arms + } + } + + pub(crate) fn _uses(&self) -> Vec { + match self.op { + Opcode::Illegal => vec![], + #use_match_arms + } + } + + pub(crate) fn _suffix(&self) -> String { + match self.op { + Opcode::Illegal => String::new(), + #suffix_match_arms + } + } + + pub(crate) fn _simplified(self) -> SimplifiedIns { + match self.op { + #simplified_ins_match_arms + _ => {} + } + SimplifiedIns::basic_form(self) + } + } + #[allow(clippy::all, non_snake_case)] + impl Ins { + #field_accessors + #modifier_accessors + } + }; + Ok(ins_impl) + } +} + +/// Converts the given key into an identifier. +fn to_rust_ident(prefix: &str, key: &str) -> TokenTree { + TokenTree::Ident(Ident::new( + &(prefix.to_owned() + &key.replace('.', "_")), + Span::call_site(), + )) +} + +/// Converts the given key into an enum variant key. +fn to_rust_variant(key: &str) -> Result { + Ok(TokenTree::Ident(Ident::new( + &to_rust_variant_str(key)?, + Span::call_site(), + ))) +} + +fn to_rust_variant_str(key: &str) -> Result { + let mut s = String::new(); + let mut chars = key.chars(); + loop { + // Make first char uppercase. + let c = match chars.next() { + None => return Ok(s), + Some(c) => c, + }; + s.push(match c { + 'a'..='z' => c.to_ascii_uppercase(), + 'A'..='Z' => c, + _ => return Err(format!("invalid identifier: {}", key).into()), + }); + loop { + let c = match chars.next() { + None => return Ok(s), + Some(c) => c, + }; + match c.to_ascii_lowercase() { + '0'..='9' | 'a'..='z' => s.push(c), + '_' => break, + '.' => { + s.push('_'); + break; + } + _ => return Err(format!("invalid character in opcode name: {}", key).into()), + } + } + } +} + +/// Compiles conditions such as `S == B` into valid Rust expressions on a PowerPC instruction. +fn compile_mnemonic_condition( + field_by_name: &HashMap, + code: &str, +) -> Result { + let src_stream = TokenStream::from_str(code)?; + let token_iter = src_stream.into_iter().flat_map(|token| { + if let TokenTree::Ident(ref ident) = token { + if let Some(field) = field_by_name.get(&ident.to_string()) { + return field.express_value_self(); + } + } + token.into() + }); + Ok(TokenStream::from_iter(token_iter)) +} + +fn express_suffix( + modifier_by_name: &HashMap, + opcode: &Opcode, +) -> Result { + Ok(if opcode.modifiers.is_empty() { + quote!(String::new()) + } else { + let mut chars = Vec::new(); + for mod_name in &opcode.modifiers { + let modifier: &Modifier = modifier_by_name + .get(mod_name) + .ok_or_else(|| Error::from(format!("undefined modifier {}", mod_name)))?; + let lit_char = LitChar::new(modifier.suffix, Span::call_site()); + let modifier_bit = modifier.express_value_self(); + chars.push(quote! { + if #modifier_bit { + s.push(#lit_char); + } + }); + } + let chars = token_stream!(chars); + quote!({ + { + let mut s = String::with_capacity(4); + #chars + s + } + }) + }) +} diff --git a/isa.yaml b/isa.yaml new file mode 100644 index 0000000..9f196ba --- /dev/null +++ b/isa.yaml @@ -0,0 +1,2368 @@ +fields: + # Immediates + - name: simm + arg: Simm + bits: 16..32 + signed: true + - name: uimm + arg: Uimm + bits: 16..32 + - name: offset + arg: Offset + bits: 16..32 + signed: true + # Branch fields + - name: BO + arg: OpaqueU + bits: 6..11 + - name: BI + arg: OpaqueU + bits: 11..16 + - name: BD + arg: BranchDest + bits: 16..30 + shift_left: 2 + signed: true + - name: LI + arg: BranchDest + bits: 6..30 + signed: true + shift_left: 2 + # Shift/rotate type fields + - name: SH + arg: OpaqueU + desc: Shift + bits: 16..21 + - name: MB + arg: OpaqueU + desc: Mask start + bits: 21..26 + - name: ME + arg: OpaqueU + desc: Mask stop + bits: 26..31 + # Registers + - name: rS + arg: GPR + bits: 6..11 + - name: rD + arg: GPR + bits: 6..11 + - name: rA + arg: GPR + bits: 11..16 + - name: rA.nz + arg: GPR + bits: 11..16 + - name: rB + arg: GPR + bits: 16..21 + - name: rC + arg: GPR + bits: 21..26 + - name: sr + arg: SR + bits: 12..16 + - name: spr + arg: SPR + bits: 11..21 + split: true + # Floating-point registers + - name: frS + arg: FPR + bits: 6..11 + - name: frD + arg: FPR + bits: 6..11 + - name: frA + arg: FPR + bits: 11..16 + - name: frB + arg: FPR + bits: 16..21 + - name: frC + arg: FPR + bits: 21..26 + # Condition registers + # TODO This looks swapped the wrong way around + - name: crbD + arg: CRField + bits: 6..11 + - name: crbA + arg: CRField + bits: 11..16 + - name: crbB + arg: CRField + bits: 16..21 + # Condition register fields + - name: crfD + arg: CRBit + bits: 6..9 + - name: crfS + arg: CRBit + bits: 11..14 + # Condition register misc + - name: crm + arg: OpaqueU + bits: 12..20 + # Paired single fields + - name: ps_l + arg: GQR + bits: 17..20 + - name: ps_W + arg: OpaqueU + bits: 16 + # Misc + - name: NB + arg: OpaqueU + bits: 16..21 + - name: tbr + arg: OpaqueU + desc: Time Base + bits: 11..21 + split: true + - name: mtfsf_FM + arg: OpaqueU + desc: Field Mask for mtfsf + bits: 7..15 + - name: mtfsf_IMM + arg: OpaqueU + desc: Immediate for mtfsfi + bits: 16..20 + - name: TO + arg: OpaqueU + desc: Bitset for tw and twi + bits: 6..11 + - name: xer + - name: ctr + - name: lr + +# TODO Add defs/uses for modifiers. +modifiers: + - name: OE + suffix: o + bit: 21 + - name: Rc + suffix: . + bit: 31 + - name: LK + suffix: l + bit: 31 + - name: AA + suffix: a + bit: 30 + +opcodes: + - name: add + desc: Add + bitmask: 0xfc0007fe + pattern: 0x7c000214 + modifiers: [ OE, Rc ] + args: [ rD, rA, rB ] + defs: [ rD ] + uses: [ rA, rB ] + + - name: addc + desc: Add Carrying + bitmask: 0xfc0007fe + pattern: 0x7c000014 + modifiers: [ OE, Rc ] + args: [ rD, rA, rB ] + defs: [ rD ] + uses: [ rA, rB ] + + - name: adde + desc: Add Extended + bitmask: 0xfc0007fe + pattern: 0x7c000114 + modifiers: [ OE, Rc ] + args: [ rD, rA, rB ] + defs: [ rD ] + uses: [ rA, rB ] + + - name: addi + desc: Add Immediate + bitmask: 0xfc000000 + pattern: 0x38000000 + args: [ rD, rA, simm ] + defs: [ rD ] + uses: [ rA.nz ] + + - name: addic + desc: Add Immediate Carrying + bitmask: 0xfc000000 + pattern: 0x30000000 + args: [ rD, rA, simm ] + defs: [ rD ] + uses: [ rA ] + + - name: addic. + desc: Add Immediate Carrying and Record + bitmask: 0xfc000000 + pattern: 0x34000000 + args: [ rD, rA, simm ] + side_effects: [ Rc ] + defs: [ rD ] + uses: [ rA ] + + - name: addis + desc: Add Immediate Shifted + bitmask: 0xfc000000 + pattern: 0x3c000000 + args: [ rD, rA, uimm ] + defs: [ rD ] + uses: [ rA.nz ] + + - name: addme + desc: Add to Minus One Extended + bitmask: 0xfc00fbfe + pattern: 0x7c0001d4 + modifiers: [ OE, Rc ] + args: [ rD, rA ] + defs: [ rD ] + uses: [ rA ] + + - name: addze + desc: Add to Zero Extended + bitmask: 0xfc00fbfe + pattern: 0x7c000194 + modifiers: [ OE, Rc ] + args: [ rD, rA ] + defs: [ rD ] + uses: [ rA ] + + - name: and + desc: AND + bitmask: 0xfc0007fe + pattern: 0x7c000038 + modifiers: [ Rc ] + args: [ rA, rS, rB ] + defs: [ rA ] + uses: [ rS, rB ] + + - name: andc + desc: AND with Complement + bitmask: 0xfc0007fe + pattern: 0x7c000078 + modifiers: [ Rc ] + args: [ rA, rS, rB ] + defs: [ rA ] + uses: [ rS, rB ] + + - name: andi. + desc: AND Immediate + bitmask: 0xfc000000 + pattern: 0x70000000 + side_effects: [ Rc ] + args: [ rA, rS, uimm ] + defs: [ rA ] + uses: [ rB ] + + - name: andis. + desc: AND Immediate Shifted + bitmask: 0xfc000000 + pattern: 0x74000000 + side_effects: [ Rc ] + args: [ rA, rS, uimm ] + defs: [ rA ] + uses: [ rB ] + + - name: b + desc: Branch + bitmask: 0xfc000000 + pattern: 0x48000000 + modifiers: [ AA, LK ] + args: [ LI ] + + - name: bc + desc: Branch Conditional + bitmask: 0xfc000000 + pattern: 0x40000000 + modifiers: [ AA, LK ] + args: [ BO, BI, BD ] + + - name: bcctr + desc: Branch Conditional to Count Register + bitmask: 0xfc007ffe + pattern: 0x4c000420 + modifiers: [ LK ] + args: [ BO, BI ] + uses: [ ctr ] + + - name: bclr + desc: Branch Conditional to Link Register + bitmask: 0xfc007ffe + pattern: 0x4c000020 + modifiers: [ LK ] + args: [ BO, BI ] + uses: [ lr ] + + - name: cmp + desc: Compare + bitmask: 0xfc4007ff + pattern: 0x7c000000 + args: [ crfD, rA, rB ] + defs: [ crfD ] + uses: [ rA, rB ] + + - name: cmpi + desc: Compare Immediate + bitmask: 0xfc400000 + pattern: 0x2c000000 + args: [ crfD, rA, simm ] + defs: [ crfD ] + uses: [ rA ] + + - name: cmpl + desc: Compare Logical + bitmask: 0xfc4007ff + pattern: 0x7c000040 + args: [ crfD, rA, rB ] + defs: [ crfD ] + uses: [ rA, rB ] + + - name: cmpli + desc: Compare Logical Immediate + bitmask: 0xfc400000 + pattern: 0x28000000 + args: [ crfD, rA, uimm ] + defs: [ crfD ] + uses: [ rA ] + + - name: cntlzw + desc: Count Leading Zeros Word + bitmask: 0xfc00fffe + pattern: 0x7c000034 + modifiers: [ Rc ] + args: [ rA, rS ] + defs: [ rA ] + uses: [ rS ] + + - name: crand + desc: Condition Register AND + bitmask: 0xfc0007ff + pattern: 0x4c000202 + args: [ crbD, crbA, crbB ] + defs: [ crbD ] + uses: [ crbA, crbB ] + + - name: crandc + desc: Condition Register AND with Complement + bitmask: 0xfc0007ff + pattern: 0x4c000102 + args: [ crbD, crbA, crbB ] + defs: [ crbD ] + uses: [ crbA, crbB ] + + - name: creqv + desc: Condition Register Equivalent + bitmask: 0xfc0007ff + pattern: 0x4c000242 + args: [ crbD, crbA, crbB ] + defs: [ crbD ] + uses: [ crbA, crbB ] + + - name: crnand + desc: Condition Register NAND + bitmask: 0xfc0007ff + pattern: 0x4c0001c2 + args: [ crbD, crbA, crbB ] + defs: [ crbD ] + uses: [ crbA, crbB ] + + - name: crnor + desc: Condition Register NOR + bitmask: 0xfc0007ff + pattern: 0x4c000042 + args: [ crbD, crbA, crbB ] + defs: [ crbD ] + uses: [ crbA, crbB ] + + - name: cror + desc: Condition Register OR + bitmask: 0xfc0007ff + pattern: 0x4c000382 + args: [ crbD, crbA, crbB ] + defs: [ crbD ] + uses: [ crbA, crbB ] + + - name: crorc + desc: Condition Register OR with Complement + bitmask: 0xfc0007ff + pattern: 0x4c000342 + args: [ crbD, crbA, crbB ] + defs: [ crbD ] + uses: [ crbA, crbB ] + + - name: crxor + desc: Condition Register XOR + bitmask: 0xfc0007ff + pattern: 0x4c000182 + args: [ crbD, crbA, crbB ] + defs: [ crbD ] + uses: [ crbA, crbB ] + + - name: dcbf + desc: Data Cache Block Flush + bitmask: 0xffe007ff + pattern: 0x7c0000ac + args: [ rA, rB ] + uses: [ rA.nz, rB ] + + - name: dcbi + desc: Data Cache Block Invalidate + bitmask: 0xffe007ff + pattern: 0x7c0003ac + args: [ rA, rB ] + uses: [ rA.nz, rB ] + + - name: dcbst + desc: Data Cache Block Store + bitmask: 0xffe007ff + pattern: 0x7c00006c + args: [ rA, rB ] + uses: [ rA.nz, rB ] + + - name: dcbt + desc: Data Cache Block Touch + bitmask: 0xffe007ff + pattern: 0x7c00022c + args: [ rA, rB ] + uses: [ rA.nz, rB ] + + - name: dcbtst + desc: Data Cache Block Touch for Store + bitmask: 0xffe007ff + pattern: 0x7c0001ec + args: [ rA, rB ] + uses: [ rA.nz, rB ] + + - name: dcbz + desc: Data Cache Block Clear to Zero + bitmask: 0xffe007ff + pattern: 0x7c0007ec + args: [ rA, rB ] + uses: [ rA.nz, rB ] + + - name: dcbz_l + desc: Data Cache Block Set to Zero Locked + bitmask: 0xffe007ff + pattern: 0x100007ec + args: [ rA, rB ] + uses: [ rA.nz, rB ] + + - name: divw + desc: Divide Word + bitmask: 0xfc0003fe + pattern: 0x7c0003d6 + modifiers: [ OE, Rc ] + args: [ rD, rA, rB ] + defs: [ rD ] + uses: [ rA, rB ] + + - name: divwu + desc: Divide Word Unsigned + bitmask: 0xfc0003fe + pattern: 0x7c000396 + modifiers: [ OE, Rc ] + args: [ rD, rA, rB ] + defs: [ rD ] + uses: [ rA, rB ] + + - name: eciwx + desc: External Control In Word Indexed + bitmask: 0xfc0003ff + pattern: 0x7c00026c + args: [ rD, rA, rB ] + defs: [ rD ] + uses: [ rA.nz, rB ] + + - name: ecowx + desc: External Control Out Word Indexed + bitmask: 0xfc0003ff + pattern: 0x7c00036c + args: [ rS, rA, rB ] + uses: [ rS, rA.nz, rB ] + + - name: eieio + desc: Enforce In-Order Execution of I/O + bitmask: 0xffffffff + pattern: 0x7c0006ac + + - name: eqv + desc: Equivalent + bitmask: 0xfc0003fe + pattern: 0x7c000238 + modifiers: [ Rc ] + args: [ rA, rS, rB ] + defs: [ rA ] + uses: [ rS, rB ] + + - name: extsb + desc: Extend Sign Byte + bitmask: 0xfc00fffe + pattern: 0x7c000774 + modifiers: [ Rc ] + args: [ rA, rS ] + defs: [ rA ] + uses: [ rS ] + + - name: extsh + desc: Extend Sign Half Word + bitmask: 0xfc00fffe + pattern: 0x7c000734 + modifiers: [ Rc ] + args: [ rA, rS ] + defs: [ rA ] + uses: [ rS ] + + - name: fabs + desc: Floating Absolute Value + bitmask: 0xfc1f07fe + pattern: 0xfc000210 + modifiers: [ Rc ] + args: [ frD, frB ] + defs: [ frD ] + uses: [ frB ] + + - name: fadd + desc: Floating Add (Double-Precision) + bitmask: 0xfc0007fe + pattern: 0xfc00002a + modifiers: [ Rc ] + args: [ frD, frA, frB ] + defs: [ frD ] + uses: [ frA, frB ] + + - name: fadds + desc: Floating Add (Single-Precision) + bitmask: 0xfc0007fe + pattern: 0xec00002a + modifiers: [ Rc ] + args: [ frD, frA, frB ] + defs: [ frD ] + uses: [ frA, frB ] + + - name: fcmpo + desc: Floating Compare Ordered + bitmask: 0xfc6007ff + pattern: 0xfc000040 + args: [ crfD, frA, frB ] + defs: [ crfD ] + uses: [ frA, frB ] + + - name: fcmpu + desc: Floating Compare Unordered + bitmask: 0xfc6007ff + pattern: 0xfc000000 + args: [ crfD, frA, frB ] + defs: [ crfD ] + uses: [ frA, frB ] + + - name: fctiw + desc: Floating Convert to Integer Word + bitmask: 0xfc1f07fe + pattern: 0xfc00001c + modifiers: [ Rc ] + args: [ frD, frB ] + defs: [ frD ] + uses: [ frB ] + + - name: fctiwz + desc: Floating Convert to Integer Word with Round toward Zero + bitmask: 0xfc1f07fe + pattern: 0xfc00001e + modifiers: [ Rc ] + args: [ frD, frB ] + defs: [ frD ] + uses: [ frB ] + + - name: fdiv + desc: Floating Divide (Double-Precision) + bitmask: 0xfc0007fe + pattern: 0xfc000024 + modifiers: [ Rc ] + args: [ frD, frA, frB ] + defs: [ frD ] + uses: [ frA, frB ] + + - name: fdivs + desc: Floating Divide (Single-Precision) + bitmask: 0xfc0007fe + pattern: 0xec000024 + modifiers: [ Rc ] + args: [ frD, frA, frB ] + defs: [ frD ] + uses: [ frA, frB ] + + - name: fmadd + desc: Floating Multiply-Add (Double-Precision) + bitmask: 0xfc00003e + pattern: 0xfc00003a + modifiers: [ Rc ] + args: [ frD, frA, frC, frB ] + defs: [ frD ] + uses: [ frA, frC, frB ] + + - name: fmadds + desc: Floating Multiply-Add (Single-Precision) + bitmask: 0xfc00003e + pattern: 0xec00003a + modifiers: [ Rc ] + args: [ frD, frA, frC, frB ] + defs: [ frD ] + uses: [ frA, frC, frB ] + + - name: fmr + desc: Floating Move Register (Double-Precision) + bitmask: 0xfc1f07fe + pattern: 0xfc000090 + modifiers: [ Rc ] + args: [ frD, frB ] + defs: [ frD ] + uses: [ frB ] + + - name: fmsub + desc: Floating Multiply-Subtract (Double-Precision) + bitmask: 0xfc00003e + pattern: 0xfc000038 + modifiers: [ Rc ] + args: [ frD, frA, frC, frB ] + defs: [ frD ] + uses: [ frA, frC, frB ] + + - name: fmsubs + desc: Floating Multiply-Subtract (Single-Precision) + bitmask: 0xfc00003e + pattern: 0xec000038 + modifiers: [ Rc ] + args: [ frD, frA, frC, frB ] + defs: [ frD ] + uses: [ frA, frC, frB ] + + - name: fmul + desc: Floating Multiply (Double-Precision) + bitmask: 0xfc00f83e + pattern: 0xfc000032 + modifiers: [ Rc ] + args: [ frD, frA, frC ] + defs: [ frD ] + uses: [ frA, frC ] + + - name: fmuls + desc: Floating Multiply (Single-Precision) + bitmask: 0xfc00f83e + pattern: 0xec000032 + modifiers: [ Rc ] + args: [ frD, frA, frC ] + defs: [ frD ] + uses: [ frA, frC ] + + - name: fnabs + desc: Floating Negative Absolute Value + bitmask: 0xfc1f07fe + pattern: 0xfc000110 + modifiers: [ Rc ] + args: [ frD, frB ] + defs: [ frD ] + uses: [ frB ] + + - name: fneg + desc: Floating Negate + bitmask: 0xfc1f07fe + pattern: 0xfc000050 + modifiers: [ Rc ] + args: [ frD, frB ] + defs: [ frD ] + uses: [ frB ] + + - name: fnmadd + desc: Floating Negative Multiply-Add (Double-Precision) + bitmask: 0xfc00003e + pattern: 0xfc00003e + modifiers: [ Rc ] + args: [ frD, frA, frC, frB ] + defs: [ frD ] + uses: [ frA, frC, frB ] + + - name: fnmadds + desc: Floating Negative Multiply-Add (Single-Precision) + bitmask: 0xfc00003e + pattern: 0xec00003e + modifiers: [ Rc ] + args: [ frD, frA, frC, frB ] + defs: [ frD ] + uses: [ frA, frC, frB ] + + - name: fnmsub + desc: Floating Negative Multiply-Subtract (Double-Precision) + bitmask: 0xfc00003e + pattern: 0xfc00003c + modifiers: [ Rc ] + args: [ frD, frA, frC, frB ] + defs: [ frD ] + uses: [ frA, frC, frB ] + + - name: fnmsubs + desc: Floating Negative Multiply-Subtract (Single-Precision) + bitmask: 0xfc00003e + pattern: 0xec00003c + modifiers: [ Rc ] + args: [ frD, frA, frC, frB ] + defs: [ frD ] + uses: [ frA, frC, frB ] + + - name: fres + desc: Floating Reciprocal Estimate Single + bitmask: 0xfc1f07fe + pattern: 0xec000030 + modifiers: [ Rc ] + args: [ frD, frB ] + defs: [ frD ] + uses: [ frB ] + + - name: frsp + desc: Floating Round to Single + bitmask: 0xfc1f07fe + pattern: 0xfc000018 + modifiers: [ Rc ] + args: [ frD, frB ] + defs: [ frD ] + uses: [ frB ] + + - name: frsqrte + desc: Floating Reciprocal Square Root Estimate + bitmask: 0xfc1f07fe + pattern: 0xfc000034 + modifiers: [ Rc ] + args: [ frD, frB ] + defs: [ frD ] + uses: [ frB ] + + - name: fsel + desc: Floating Select + bitmask: 0xfc00003e + pattern: 0xfc00002e + modifiers: [ Rc ] + args: [ frD, frA, frC, frB ] + defs: [ frD ] + uses: [ frA, frC, frB ] + + - name: fsub + desc: Floating Subtract (Double-Precision) + bitmask: 0xfc0007fe + pattern: 0xfc000028 + modifiers: [ Rc ] + args: [ frD, frA, frB ] + defs: [ frD ] + uses: [ frA, frB ] + + - name: fsubs + desc: Floating Subtract (Single-Precision) + bitmask: 0xfc0007fe + pattern: 0xec000028 + modifiers: [ Rc ] + args: [ frD, frA, frB ] + defs: [ frD ] + uses: [ frA, frB ] + + - name: icbi + desc: Instruction Cache Block Invalidate + bitmask: 0xffe007ff + pattern: 0x7c0007ac + modifiers: [ Rc ] + args: [ rA, rB ] + uses: [ rA.nz, rB ] + + - name: isync + desc: Instruction Synchronize + bitmask: 0xffffffff + pattern: 0x4c00012c + + - name: lbz + desc: Load Byte and Zero + bitmask: 0xfc000000 + pattern: 0x88000000 + args: [ rD, offset, rA ] + defs: [ rD ] + uses: [ offset, rA.nz ] + + - name: lbzu + desc: Load Byte and Zero with Update + bitmask: 0xfc000000 + pattern: 0x8c000000 + args: [ rD, offset, rA ] + defs: [ rD, rA ] + uses: [ offset, rA ] + + - name: lbzux + desc: Load Byte and Zero with Update Indexed + bitmask: 0xfc0007ff + pattern: 0x7c0000ee + args: [ rD, rA, rB ] + defs: [ rD, rA ] + uses: [ rA, rB ] + + - name: lbzx + desc: Load Byte and Zero Indexed + bitmask: 0xfc0007ff + pattern: 0x7c0000ae + args: [ rD, rA, rB ] + defs: [ rD ] + uses: [ rA.nz, rB ] + + - name: lfd + desc: Load Floating-Point Double + bitmask: 0xfc000000 + pattern: 0xc8000000 + args: [ frD, offset, rA ] + defs: [ frD ] + uses: [ offset, rA.nz ] + + - name: lfdu + desc: Load Floating-Point Double with Update + bitmask: 0xfc000000 + pattern: 0xcc000000 + args: [ frD, offset, rA ] + defs: [ frD, rA ] + uses: [ offset, rA ] + + - name: lfdux + desc: Load Floating-Point Double with Update Indexed + bitmask: 0xfc0007ff + pattern: 0x7c0004ee + args: [ frD, rA, rB ] + defs: [ frD, rA ] + uses: [ rA, rB ] + + - name: lfdx + desc: Load Floating-Point Double Indexed + bitmask: 0xfc0007ff + pattern: 0x7c0004ae + args: [ frD, rA, rB ] + defs: [ frD ] + uses: [ rA.nz, rB ] + + - name: lfs + desc: Load Floating-Point Single + bitmask: 0xfc000000 + pattern: 0xc0000000 + args: [ frD, offset, rA ] + defs: [ frD ] + uses: [ offset, rA.nz ] + + - name: lfsu + desc: Load Floating-Point Single with Update + bitmask: 0xfc000000 + pattern: 0xc4000000 + args: [ frD, offset, rA ] + defs: [ frD, rA ] + uses: [ offset, rA ] + + - name: lfsux + desc: Load Floating-Point Single with Update Indexed + bitmask: 0xfc0007ff + pattern: 0x7c00046e + args: [ frD, rA, rB ] + defs: [ frD, rA ] + uses: [ rA, rB ] + + - name: lfsx + desc: Load Floating-Point Single Indexed + bitmask: 0xfc0007ff + pattern: 0x7c00042e + args: [ frD, rA, rB ] + defs: [ frD ] + uses: [ rA.nz, rB ] + + - name: lha + desc: Load Half Word Algebraic + bitmask: 0xfc000000 + pattern: 0xa8000000 + args: [ rD, offset, rA ] + defs: [ rD ] + uses: [ offset, rA.nz ] + + - name: lhau + desc: Load Half Word Algebraic with Update + bitmask: 0xfc000000 + pattern: 0xac000000 + args: [ rD, offset, rA ] + defs: [ rD, rA ] + uses: [ offset, rA ] + + - name: lhaux + desc: Load Half Word Algebraic with Update Indexed + bitmask: 0xfc0007ff + pattern: 0x7c0002ee + args: [ rD, rA, rB ] + defs: [ rD, rA ] + uses: [ rA, rB ] + + - name: lhax + desc: Load Half Word Algebraic Indexed + bitmask: 0xfc0007ff + pattern: 0x7c0002ae + args: [ rD, rA, rB ] + defs: [ rD ] + uses: [ rA.nz, rB ] + + - name: lhbrx + desc: Load Half Word Byte-Reverse Indexed + bitmask: 0xfc0007ff + pattern: 0x7c00062c + args: [ rD, rA, rB ] + defs: [ rD ] + uses: [ rA.nz, rB ] + + - name: lhz + desc: Load Half Word and Zero + bitmask: 0xfc000000 + pattern: 0xa0000000 + args: [ rD, offset, rA ] + defs: [ rD ] + uses: [ offset, rA.nz ] + + - name: lhzu + desc: Load Half Word and Zero with Update + bitmask: 0xfc000000 + pattern: 0xa4000000 + args: [ rD, offset, rA ] + defs: [ rD, rA ] + uses: [ offset, rA ] + + - name: lhzux + desc: Load Half Word and Zero with Update Indexed + bitmask: 0xfc0007ff + pattern: 0x7c00026e + args: [ rD, rA, rB ] + defs: [ rD, rA ] + uses: [ rA, rB ] + + - name: lhzx + desc: Load Half Word and Zero Indexed + bitmask: 0xfc0007ff + pattern: 0x7c00022e + args: [ rD, rA, rB ] + defs: [ rD ] + uses: [ rA.nz, rB ] + + # TODO lmw has much more defs + - name: lmw + desc: Load Multiple Word + bitmask: 0xfc000000 + pattern: 0xb8000000 + args: [ rD, offset, rA ] + defs: [ rD ] + uses: [ offset, rA.nz ] + + - name: lswi + desc: Load String Word Immediate + bitmask: 0xfc0007ff + pattern: 0x7c0004aa + args: [ rD, rA, NB ] + defs: [ rD ] + uses: [ rA.nz ] + + - name: lswx + desc: Load String Word Indexed + bitmask: 0xfc0007ff + pattern: 0x7c00042a + args: [ rD, rA, rB ] + defs: [ rD ] + uses: [ rA.nz, rB ] + + - name: lwarx + desc: Load String Word and Reverse Indexed + bitmask: 0xfc0007ff + pattern: 0x7c000028 + args: [ rD, rA, rB ] + defs: [ rD ] + uses: [ rA.nz, rB ] + + - name: lwbrx + desc: Load String Word and Byte-Reverse Indexed + bitmask: 0xfc0007ff + pattern: 0x7c00042c + args: [ rD, rA, rB ] + defs: [ rD ] + uses: [ rA.nz, rB ] + + - name: lwz + desc: Load Word and Zero + bitmask: 0xfc000000 + pattern: 0x80000000 + args: [ rD, offset, rA ] + defs: [ rD ] + uses: [ offset, rA.nz ] + + - name: lwzu + desc: Load Word and Zero with Update + bitmask: 0xfc000000 + pattern: 0x84000000 + args: [ rD, offset, rA ] + defs: [ rD, rA ] + uses: [ offset, rA ] + + - name: lwzux + desc: Load Word and Zero with Update Indexed + bitmask: 0xfc0007ff + pattern: 0x7c00006e + args: [ rD, rA, rB ] + defs: [ rD, rA ] + uses: [ rA, rB ] + + - name: lwzx + desc: Load Word and Zero Indexed + bitmask: 0xfc0007ff + pattern: 0x7c00002e + args: [ rD, rA, rB ] + defs: [ rD ] + uses: [ rA.nz, rB ] + + - name: mcrf + desc: Move Condition Register Field + bitmask: 0xfc300fff + pattern: 0x4c000000 + args: [ crfD, crfS ] + defs: [ crfD ] + uses: [ crfS ] + + - name: mcrfs + desc: Move to Condition Register from FPSCR + bitmask: 0xfc30ffff + pattern: 0xfc000080 + args: [ crfD, crfS ] + defs: [ crfD ] + uses: [ crfS ] + + - name: mcrxr + desc: Move to Condition Register from XER + bitmask: 0xfc30ffff + pattern: 0x7c000400 + args: [ crfD ] + defs: [ crfD, xer ] + + - name: mfcr + desc: Move from Condition Register + bitmask: 0xfc1fffff + pattern: 0x7c000026 + args: [ crfD ] + defs: [ crfD ] + + - name: mffs + desc: Move from FPSCR + bitmask: 0xfc1ffffe + pattern: 0xfc00048e + modifiers: [ Rc ] + args: [ crfD ] + defs: [ crfD ] + + - name: mfmsr + desc: Move from Machine State Register + bitmask: 0xfc1fffff + pattern: 0x7c0000a6 + args: [ rD ] + defs: [ rD ] + + - name: mfspr + desc: Move from Special-Purpose Register + bitmask: 0xfc0007ff + pattern: 0x7c0002a6 + args: [ rD, spr ] + defs: [ rD ] + + - name: mfsr + desc: Move from Segment Register + bitmask: 0xfc10ffff + pattern: 0x7c0004a6 + args: [ rD, sr ] + defs: [ rD ] + + - name: mfsrin + desc: Move from Segment Register Indirect + bitmask: 0xfc1f07ff + pattern: 0x7c000526 + args: [ rD, rB ] + defs: [ rD ] + uses: [ rB ] + + - name: mftb + desc: Move from Time Base + bitmask: 0xfc0007ff + pattern: 0x7c0002e6 + args: [ rD, tbr ] + defs: [ rD ] + + - name: mtcrf + desc: Move to Condition Register Fields + bitmask: 0xfc100fff + pattern: 0x7c000120 + args: [ crm, rS ] + uses: [ rS ] + + - name: mtfsb0 + desc: Move to FPSCR Bit 0 + bitmask: 0xfc1ffffe + pattern: 0xfc00008c + modifiers: [ Rc ] + args: [ crbD ] + defs: [ crbD ] + + - name: mtfsb1 + desc: Move to FPSCR Bit 1 + bitmask: 0xfc1ffffe + pattern: 0xfc00004c + modifiers: [ Rc ] + args: [ crbD ] + defs: [ crbD ] + + - name: mtfsf + desc: Move to FPSCR Fields + bitmask: 0xfe0107fe + pattern: 0xfc00058e + modifiers: [ Rc ] + args: [ mtfsf_FM, frB ] + uses: [ frB ] + + - name: mtfsfi + desc: Move to FPSCR Field Immediate + bitmask: 0xfc7f0ffe + pattern: 0xfc00010c + modifiers: [ Rc ] + args: [ crfD, mtfsf_IMM ] + defs: [ crfD ] + + - name: mtmsr + desc: Move to Machine State Register + bitmask: 0xfc1fffff + pattern: 0x7c000124 + args: [ rS ] + uses: [ rS ] + + - name: mtspr + desc: Move to Special-Purpose Register + bitmask: 0xfc0007ff + pattern: 0x7c0003a6 + args: [ spr, rS ] + uses: [ rS ] + + - name: mtsr + desc: Move to Segment Register + bitmask: 0xfc10ffff + pattern: 0x7c0001a4 + args: [ sr, rS ] + uses: [ rS ] + + - name: mtsrin + desc: Move to Segment Register Indirect + bitmask: 0xfc1f07ff + pattern: 0x7c0001e4 + args: [ rS, rB ] + uses: [ rS, rB ] + + - name: mulhw + desc: Multiply High Word + bitmask: 0xfc0007fe + pattern: 0x7c000096 + modifiers: [ Rc ] + args: [ rD, rA, rB ] + defs: [ rD ] + uses: [ rA, rB ] + + - name: mulhwu + desc: Multiply High Word Unsigned + bitmask: 0xfc0007fe + pattern: 0x7c000016 + modifiers: [ Rc ] + args: [ rD, rA, rB ] + defs: [ rD ] + uses: [ rA, rB ] + + - name: mulli + desc: Multiply Low Immediate + bitmask: 0xfc000000 + pattern: 0x1c000000 + modifiers: [ Rc ] + args: [ rD, rA, simm ] + defs: [ rD ] + uses: [ rA ] + + - name: mullw + desc: Multiply Low Word + bitmask: 0xfc0003fe + pattern: 0x7c0001d6 + modifiers: [ OE, Rc ] + args: [ rD, rA, rB ] + defs: [ rD ] + uses: [ rA, rB ] + + - name: nand + desc: NAND + bitmask: 0xfc0007fe + pattern: 0x7c0003b8 + modifiers: [ Rc ] + args: [ rA, rS, rB ] + defs: [ rA ] + uses: [ rS, rB ] + + - name: neg + desc: Negate + bitmask: 0xfc00fffe + pattern: 0x7c0000d0 + modifiers: [ OE, Rc ] + args: [ rD, rA ] + defs: [ rD ] + uses: [ rA ] + + - name: nor + desc: NOR + bitmask: 0xfc0007fe + pattern: 0x7c0000f8 + modifiers: [ Rc ] + args: [ rA, rS, rB ] + defs: [ rA ] + uses: [ rS, rB ] + + - name: or + desc: OR + bitmask: 0xfc0007fe + pattern: 0x7c000378 + modifiers: [ Rc ] + args: [ rA, rS, rB ] + defs: [ rA ] + uses: [ rS, rB ] + + - name: orc + desc: OR with Complement + bitmask: 0xfc0007fe + pattern: 0x7c000338 + modifiers: [ Rc ] + args: [ rA, rS, rB ] + defs: [ rA ] + uses: [ rS, rB ] + + - name: ori + desc: OR Immediate + bitmask: 0xfc000000 + pattern: 0x60000000 + args: [ rA, rS, uimm ] + defs: [ rA ] + uses: [ rS ] + + - name: oris + desc: OR Immediate Shifted + bitmask: 0xfc000000 + pattern: 0x64000000 + args: [ rA, rS, uimm ] + defs: [ rA ] + uses: [ rS ] + + - name: psq_l + desc: Paired Single Quantized Load + bitmask: 0xfc000000 + pattern: 0xe0000000 + args: [ frD, offset, rA, ps_W, ps_l ] + defs: [ frD ] + uses: [ rA.nz ] + + - name: psq_lu + desc: Paired Single Quantized Load with Update + bitmask: 0xfc000000 + pattern: 0xe4000000 + args: [ frD, offset, rA, ps_W, ps_l ] + defs: [ frD, rA ] + uses: [ rA ] + + - name: psq_lux + desc: Paired Single Quantized Load with Update Indexed + bitmask: 0xfc00007f + pattern: 0x1000004c + args: [ frD, rA, rB, ps_W, ps_l ] + defs: [ frD, rA ] + uses: [ rA, rB ] + + - name: psq_lx + desc: Paired Single Quantized Load Indexed + bitmask: 0xfc00007f + pattern: 0x1000000c + args: [ frD, rA, rB, ps_W, ps_l ] + defs: [ frD ] + uses: [ rA.nz, rB ] + + - name: psq_st + desc: Paired Single Quantized Store + bitmask: 0xfc000000 + pattern: 0xf0000000 + args: [ frS, offset, rA, ps_W, ps_l ] + uses: [ frS, rA.nz ] + + - name: psq_stu + desc: Paired Single Quantized Store with Update + bitmask: 0xfc000000 + pattern: 0xf4000000 + args: [ frS, offset, rA, ps_W, ps_l ] + defs: [ rA ] + uses: [ frS, rA ] + + - name: psq_stux + desc: Paired Single Quantized Store with Update Indexed + bitmask: 0xfc00007f + pattern: 0x1000004e + args: [ frS, rA, rB, ps_W, ps_l ] + defs: [ rA ] + uses: [ frS, rA, rB ] + + - name: psq_stx + desc: Paired Single Quantized Store Indexed + bitmask: 0xfc00007f + pattern: 0x1000000e + args: [ frS, rA, rB, ps_W, ps_l ] + uses: [ frS, rA.nz, rB ] + + - name: ps_abs + desc: Paired Single Absolute Value + bitmask: 0xfc1f07fe + pattern: 0x10000210 + modifiers: [ Rc ] + args: [ frD, frB ] + defs: [ frD ] + uses: [ frB ] + + - name: ps_add + desc: Paired Single Add + bitmask: 0xfc0007fe + pattern: 0x1000002a + modifiers: [ Rc ] + args: [ frD, frA, frB ] + defs: [ frD ] + uses: [ frA, frB ] + + - name: ps_cmpo0 + desc: Paired Singles Compare Ordered High + bitmask: 0xfc6007ff + pattern: 0x10000040 + args: [ crfD, frA, frB ] + defs: [ crfD ] + uses: [ frA.nz, frB ] + + - name: ps_cmpo1 + desc: Paired Singles Compare Ordered Low + bitmask: 0xfc6007ff + pattern: 0x100000c0 + args: [ crfD, frA, frB ] + defs: [ crfD ] + uses: [ frA.nz, frB ] + + - name: ps_cmpu0 + desc: Paired Singles Compare Unordered High + bitmask: 0xfc6007ff + pattern: 0x10000000 + args: [ crfD, frA, frB ] + defs: [ crfD ] + uses: [ frA.nz, frB ] + + - name: ps_cmpu1 + desc: Paired Singles Compare Unordered Low + bitmask: 0xfc6007ff + pattern: 0x10000080 + args: [ crfD, frA, frB ] + defs: [ crfD ] + uses: [ frA.nz, frB ] + + - name: ps_div + desc: Paired Single Divide + bitmask: 0xfc0007fe + pattern: 0x10000024 + modifiers: [ Rc ] + args: [ frD, frA, frB ] + defs: [ frD ] + uses: [ frA, frB ] + + - name: ps_madd + desc: Paired Single Multiply-Add + bitmask: 0xfc00003e + pattern: 0x1000003a + modifiers: [ Rc ] + args: [ frD, frA, frC, frB ] + defs: [ frD ] + uses: [ frA, frC, frB ] + + - name: ps_madds0 + desc: Paired Single Multiply-Add Scalar high + bitmask: 0xfc00003e + pattern: 0x1000001c + modifiers: [ Rc ] + args: [ frD, frA, frC, frB ] + defs: [ frD ] + uses: [ frA, frC, frB ] + + - name: ps_madds1 + desc: Paired Single Multiply-Add Scalar low + bitmask: 0xfc00003e + pattern: 0x1000001e + modifiers: [ Rc ] + args: [ frD, frA, frC, frB ] + defs: [ frD ] + uses: [ frA, frC, frB ] + + - name: ps_merge00 + desc: Paired Single MERGE high + bitmask: 0xfc0007fe + pattern: 0x10000420 + modifiers: [ Rc ] + args: [ frD, frA, frB ] + defs: [ frD ] + uses: [ frA, frB ] + + - name: ps_merge01 + desc: Paired Single MERGE direct + bitmask: 0xfc0007fe + pattern: 0x10000460 + modifiers: [ Rc ] + args: [ frD, frA, frB ] + defs: [ frD ] + uses: [ frA, frB ] + + - name: ps_merge10 + desc: Paired Single MERGE swapped + bitmask: 0xfc0007fe + pattern: 0x100004a0 + modifiers: [ Rc ] + args: [ frD, frA, frB ] + defs: [ frD ] + uses: [ frA, frB ] + + - name: ps_merge11 + desc: Paired Single MERGE low + bitmask: 0xfc0007fe + pattern: 0x100004e0 + modifiers: [ Rc ] + args: [ frD, frA, frB ] + defs: [ frD ] + uses: [ frA, frB ] + + - name: ps_mr + desc: Paired Single Move Register + bitmask: 0xfc1f07fe + pattern: 0x10000090 + modifiers: [ Rc ] + args: [ frD, frA, frB ] + defs: [ frD ] + uses: [ frB ] + + - name: ps_msub + desc: Paired Single Multiply-Subtract + bitmask: 0xfc00003e + pattern: 0x10000038 + modifiers: [ Rc ] + args: [ frD, frA, frC, frB ] + defs: [ frD ] + uses: [ frA, frC, frB ] + + - name: ps_mul + desc: Paired Single Multiply + bitmask: 0xfc00f83e + pattern: 0x10000032 + modifiers: [ Rc ] + args: [ frD, frA, frC ] + defs: [ frD ] + uses: [ frA, frC ] + + - name: ps_muls0 + desc: Paired Single Multiply Scalar high + bitmask: 0xfc00f83e + pattern: 0x10000018 + modifiers: [ Rc ] + args: [ frD, frA, frC ] + defs: [ frD ] + uses: [ frA, frC ] + + - name: ps_muls1 + desc: Paired Single Multiply Scalar low + bitmask: 0xfc00f83e + pattern: 0x1000001a + modifiers: [ Rc ] + args: [ frD, frA, frC ] + defs: [ frD ] + uses: [ frA, frC ] + + - name: ps_nabs + desc: Paired Single Negative Absolute Value + bitmask: 0xfc1f07fe + pattern: 0x10000110 + modifiers: [ Rc ] + args: [ frD, frB ] + defs: [ frD ] + uses: [ frB ] + + - name: ps_neg + desc: Paired Single Negate + bitmask: 0xfc1f07fe + pattern: 0x10000050 + modifiers: [ Rc ] + args: [ frD, frB ] + defs: [ frD ] + uses: [ frB ] + + - name: ps_nmadd + desc: Paired Single Negative Multiply-Add + bitmask: 0xfc00003e + pattern: 0x1000003e + modifiers: [ Rc ] + args: [ frD, frA, frC, frB ] + defs: [ frD ] + uses: [ frA, frC, frB ] + + - name: ps_nmsub + desc: Paired Single Negative Multiply-Subtract + bitmask: 0xfc00003e + pattern: 0x1000003c + modifiers: [ Rc ] + args: [ frD, frA, frC, frB ] + defs: [ frD ] + uses: [ frA, frC, frB ] + + - name: ps_res + desc: Paired Single Reciprocal Estimate + bitmask: 0xfc1f07fe + pattern: 0x10000030 + modifiers: [ Rc ] + args: [ frD, frB ] + defs: [ frD ] + uses: [ frB ] + + - name: ps_rsqrte + desc: Paired Single Reciprocal Square Root Estimate + bitmask: 0xfc1f07fe + pattern: 0x10000034 + modifiers: [ Rc ] + args: [ frD, frB ] + defs: [ frD ] + uses: [ frB ] + + - name: ps_sel + desc: Paired Single Select + bitmask: 0xfc00003e + pattern: 0x1000002e + modifiers: [ Rc ] + args: [ frD, frA, frC, frB ] + defs: [ frD ] + uses: [ frA, frC, frB ] + + - name: ps_sub + desc: Paired Single Subtract + bitmask: 0xfc0007fe + pattern: 0x10000028 + modifiers: [ Rc ] + args: [ frD, frA, frB ] + defs: [ frD ] + uses: [ frA, frB ] + + - name: ps_sum0 + desc: Paired Single vector SUM high + bitmask: 0xfc00003e + pattern: 0x10000014 + modifiers: [ Rc ] + args: [ frD, frA, frC, frB ] + defs: [ frD ] + uses: [ frA, frC, frB ] + + - name: ps_sum1 + desc: Paired Single vector SUM low + bitmask: 0xfc00003e + pattern: 0x10000016 + modifiers: [ Rc ] + args: [ frD, frA, frC, frB ] + defs: [ frD ] + uses: [ frA, frC, frB ] + + - name: rfi + desc: Return from Interrupt + bitmask: 0xfffff801 + pattern: 0x4c000000 + + - name: rlwimi + desc: Rotate Left Word Immediate then Mask Insert + bitmask: 0xfc000000 + pattern: 0x50000000 + modifiers: [ Rc ] + args: [ rA, rS, SH, MB, ME ] + defs: [ rA ] + uses: [ rA, rS, SH ] + + - name: rlwinm + desc: Rotate Left Word Immediate then AND with Mask + bitmask: 0xfc000000 + pattern: 0x54000000 + modifiers: [ Rc ] + args: [ rA, rS, SH, MB, ME ] + defs: [ rA ] + uses: [ rS, SH ] + + - name: rlwnm + desc: Rotate Left Word then AND with Mask + bitmask: 0xfc000000 + pattern: 0x5c000000 + modifiers: [ Rc ] + args: [ rA, rS, rB, MB, ME ] + defs: [ rA ] + uses: [ rS, rB ] + + - name: sc + desc: System Call + bitmask: 0xffffffff + pattern: 0x44000002 + + - name: slw + desc: Shift Left Word + bitmask: 0xfc0007fe + pattern: 0x7c000030 + modifiers: [ Rc ] + args: [ rA, rS, rB ] + defs: [ rA ] + uses: [ rS, rB ] + + - name: sraw + desc: Shift Right Algebraic Word + bitmask: 0xfc0007fe + pattern: 0x7c000630 + modifiers: [ Rc ] + args: [ rA, rS, rB ] + defs: [ rA ] + uses: [ rS, rB ] + + - name: srawi + desc: Shift Right Algebraic Word Immediate + bitmask: 0xfc0007fe + pattern: 0x7c000670 + modifiers: [ Rc ] + args: [ rA, rS, SH ] + defs: [ rA ] + uses: [ rS ] + + - name: srw + desc: Shift Right Word + bitmask: 0xfc0007fe + pattern: 0x7c000430 + modifiers: [ Rc ] + args: [ rS, rA, rB ] + defs: [ rA ] + uses: [ rA, rB ] + + - name: stb + desc: Store Byte + bitmask: 0xfc000000 + pattern: 0x98000000 + args: [ rS, offset, rA ] + uses: [ rS, rA.nz ] + + - name: stbu + desc: Store Byte with Update + bitmask: 0xfc000000 + pattern: 0x9c000000 + args: [ rS, offset, rA ] + defs: [ rA ] + uses: [ rS, rA ] + + - name: stbux + desc: Store Byte with Update Indexed + bitmask: 0xfc0003ff + pattern: 0x7c0001ee + args: [ rS, rA, rB ] + defs: [ rA ] + uses: [ rS, rA, rB ] + + - name: stbx + desc: Store Byte Indexed + bitmask: 0xfc0003ff + pattern: 0x7c0001ae + args: [ rS, rA, rB ] + uses: [ rS, rA.nz, rB ] + + - name: stfd + desc: Store Floating-Point Double + bitmask: 0xfc000000 + pattern: 0xd8000000 + args: [ frS, offset, rA ] + uses: [ frS, rA.nz ] + + - name: stfdu + desc: Store Floating-Point Double with Update + bitmask: 0xfc000000 + pattern: 0xdc000000 + args: [ frS, offset, rA ] + defs: [ rA ] + uses: [ frS, rA ] + + - name: stfdux + desc: Store Floating-Point Double with Update Indexed + bitmask: 0xfc0007ff + pattern: 0x7c0005ee + args: [ frS, rA, rB ] + defs: [ rA ] + uses: [ frS, rA, rB ] + + - name: stfdx + desc: Store Floating-Point Double Indexed + bitmask: 0xfc0007ff + pattern: 0x7c0005ae + args: [ frS, rA, rB ] + uses: [ frS, rA.nz, rB ] + + - name: stfiwx + desc: Store Floating-Point as Integer Word Indexed + bitmask: 0xfc0007ff + pattern: 0x7c0007ae + args: [ frS, rA, rB ] + uses: [ frS, rA.nz, rB ] + + - name: stfs + desc: Store Floating-Point Single + bitmask: 0xfc000000 + pattern: 0xd0000000 + args: [ frS, offset, rA ] + uses: [ frS, rA.nz ] + + - name: stfsu + desc: Store Floating-Point Single with Update + bitmask: 0xfc000000 + pattern: 0xd4000000 + args: [ frS, offset, rA ] + defs: [ rA ] + uses: [ frS, rA ] + + - name: stfsux + desc: Store Floating-Point Single with Update Indexed + bitmask: 0xfc0007ff + pattern: 0x7c00056e + args: [ frS, rA, rB ] + defs: [ rA ] + uses: [ frS, rA, rB ] + + - name: stfsx + desc: Store Floating-Point Single Indexed + bitmask: 0xfc0007ff + pattern: 0x7c00052e + args: [ frS, rA, rB ] + uses: [ frS, rA.nz, rB ] + + - name: sth + desc: Store Half Word + bitmask: 0xfc000000 + pattern: 0xb0000000 + args: [ rS, offset, rA ] + uses: [ rS, rA.nz ] + + - name: sthbrx + desc: Store Half Word Byte-Reverse Indexed + bitmask: 0xfc0007ff + pattern: 0x7c00072c + args: [ rS, rA, rB ] + uses: [ rS, rA.nz, rB ] + + - name: sthu + desc: Store Half Word with Update + bitmask: 0xfc000000 + pattern: 0xb4000000 + args: [ rS, offset, rA ] + defs: [ rA ] + uses: [ rS, rA ] + + - name: sthux + desc: Store Half Word with Update Indexed + bitmask: 0xfc0007ff + pattern: 0x7c00036e + args: [ rS, rA, rB ] + defs: [ rA ] + uses: [ rS, rA, rB ] + + - name: sthx + desc: Store Half Word Indexed + bitmask: 0xfc0007ff + pattern: 0x7c00032e + args: [ rS, rA, rB ] + uses: [ rS, rA.nz, rB ] + + - name: stmw + desc: Store Multiple Word + bitmask: 0xfc000000 + pattern: 0xbc000000 + args: [ rS, offset, rA ] + uses: [ rS, rA.nz ] + + - name: stswi + desc: Store String Word Immediate + bitmask: 0xfc0007ff + pattern: 0x7c0005aa + args: [ rS, rA, NB ] + uses: [ rS, rA.nz ] + + - name: stswx + desc: Store String Word Indexed + bitmask: 0xfc0007ff + pattern: 0x7c00052a + args: [ rS, rA, rB ] + uses: [ rS, rA.nz, rB ] + + - name: stw + desc: Store Word + bitmask: 0xfc000000 + pattern: 0x90000000 + args: [ rS, offset, rA ] + uses: [ rS, rA.nz ] + + - name: stwbrx + desc: Store Word Byte-Reverse Indexed + bitmask: 0xfc0007ff + pattern: 0x7c00052c + args: [ rS, rA, rB ] + uses: [ rS, rA.nz, rB ] + + - name: stwcx. + desc: Store Word Conditional Indexed + bitmask: 0xfc0007ff + pattern: 0x7c00012d + args: [ rS, rA, rB ] + uses: [ rS, rA.nz, rB ] + + - name: stwu + desc: Store Word with Update + bitmask: 0xfc000000 + pattern: 0x94000000 + args: [ rS, offset, rA ] + defs: [ rA ] + uses: [ rS, rA ] + + - name: stwux + desc: Store Word Indexed + bitmask: 0xfc0007ff + pattern: 0x7c00016e + args: [ rS, rA, rB ] + defs: [ rA ] + uses: [ rS, rA, rB ] + + - name: stwx + desc: Store Word Indexed + bitmask: 0xfc0007ff + pattern: 0x7c00012e + args: [ rS, rA, rB ] + uses: [ rS, rA.nz, rB ] + + - name: subf + desc: Subtract From Carrying + bitmask: 0xfc0003fe + pattern: 0x7c000050 + modifiers: [ OE, Rc ] + args: [ rD, rA, rB ] + defs: [ rD ] + uses: [ rA, rB ] + + - name: subfc + desc: Subtract from Carrying + bitmask: 0xfc0003fe + pattern: 0x7c000010 + modifiers: [ OE, Rc ] + args: [ rD, rA, rB ] + defs: [ rD ] + uses: [ rA, rB ] + + - name: subfe + desc: Subtract from Extended + bitmask: 0xfc0003fe + pattern: 0x7c000110 + modifiers: [ OE, Rc ] + args: [ rD, rA, rB ] + defs: [ rD ] + uses: [ rA, rB ] + + - name: subfic + desc: Subtract from Immediate Carrying + bitmask: 0xfc000000 + pattern: 0x20000000 + args: [ rD, rA, simm ] + defs: [ rD ] + uses: [ rA ] + + - name: subfme + desc: Subtract from Minus One Extended + bitmask: 0xfc00fbfe + pattern: 0x7c0001d0 + modifiers: [ OE, Rc ] + args: [ rD, rA ] + defs: [ rD ] + uses: [ rA ] + + - name: subfze + desc: Subtract from Zero Extended + bitmask: 0xfc00fbfe + pattern: 0x7c000190 + modifiers: [ OE, Rc ] + args: [ rD, rA ] + defs: [ rD ] + uses: [ rA ] + + - name: sync + desc: Synchronize + bitmask: 0xffffffff + pattern: 0x7c0004ac + + - name: tlbie + desc: Translation Lookaside Buffer Invalidate Entry + bitmask: 0xffff07ff + pattern: 0x7c000264 + args: [ rB ] + uses: [ rB ] + + - name: tlbsync + desc: TLB Synchronize + bitmask: 0xffffffff + pattern: 0x7c00046c + + - name: tw + desc: Trap Word + bitmask: 0xfc0007ff + pattern: 0x7c000008 + args: [ TO, rA, rB ] + uses: [ rA, rB ] + + - name: twi + desc: Trap Word Immediate + bitmask: 0xfc000000 + pattern: 0xc0000000 + args: [ TO, rA, simm ] + uses: [ rA ] + + - name: xor + desc: XOR + bitmask: 0xfc0007fe + pattern: 0x7c000278 + args: [ rA, rS, rB ] + defs: [ rA ] + uses: [ rS, rB ] + + - name: xori + desc: XOR Immediate + bitmask: 0xfc000000 + pattern: 0x68000000 + args: [ rA, rS, uimm ] + defs: [ rA ] + uses: [ rS ] + + - name: xoris + desc: XOR Immediate Shifted + bitmask: 0xfc000000 + pattern: 0x6c000000 + args: [ rA, rS, uimm ] + defs: [ rA ] + uses: [ rS ] + +mnemonics: + # Arithmetic + - name: lis + opcode: addis + args: [ rD, uimm ] + condition: rA == 0 + - name: li + opcode: addi + args: [ rD, simm ] + condition: rA == 0 + - name: mr + opcode: or + args: [ rA, rS ] + condition: rS == rB + - name: nop + opcode: ori + condition: rA == 0 && rS == 0 && uimm == 0 + + # Rotates/Shifts + - name: clrlwi + opcode: rlwinm + args: [ rA, rS, MB ] + condition: SH == 0 && ME == 31 + - name: rotlwi + opcode: rlwinm + args: [ rA, rS, SH ] + condition: MB == 0 && ME == 31 + - name: slwi + opcode: rlwinm + args: [ rA, rS, ME ] + condition: MB == 0 && 31 - SH == ME + - name: srwi + opcode: rlwinm + args: [ rA, rS, MB ] + condition: ME == 31 && 32 - MB == SH + + # Compares + - name: cmpw + opcode: cmp + args: [ rA, rB ] + condition: crfD == 0 + - name: cmpw + opcode: cmp + args: [ crfD, rA, rB ] + - name: cmplw + opcode: cmpl + args: [ rA, rB ] + condition: crfD == 0 + - name: cmplw + opcode: cmpl + args: [ crfD, rA, rB ] + - name: cmpwi + opcode: cmpi + args: [ rA, simm ] + condition: crfD == 0 + - name: cmpwi + opcode: cmpi + args: [ crfD, rA, simm ] + condition: crfD == 0 + - name: cmplwi + opcode: cmpli + args: [ rA, uimm ] + condition: crfD == 0 + - name: cmplwi + opcode: cmpli + args: [ crfD, rA, uimm ] + condition: crfD == 0 + + # Misc + - name: twgti + opcode: twi + args: [ rA, simm ] + condition: TO == 8 + - name: twllei + opcode: twi + args: [ rA, simm ] + condition: TO == 6 + - name: twui + args: [ rA, simm ] + condition: TO == 31 + + # Move to special-purpose register + - name: mtxer + opcode: mtspr + args: [ rS ] + condition: spr == 1 + - name: mtlr + opcode: mtspr + args: [ rS ] + condition: spr == 8 + - name: mtctr + opcode: mtspr + args: [ rS ] + condition: spr == 9 + - name: mtdsisr + opcode: mtspr + args: [ rS ] + condition: spr == 18 + - name: mtdbatu + opcode: mtspr + args: [ rS ] + condition: spr == 397 + - name: mttdu + opcode: mtspr + args: [ rS ] + condition: spr == 571 + + # Move from special-purpose register + - name: mfxer + opcode: mfspr + args: [ rD ] + condition: spr == 1 + - name: mflr + opcode: mfspr + args: [ rD ] + condition: spr == 8 + - name: mfctr + opcode: mfspr + args: [ rD ] + condition: spr == 9 + - name: mfdsisr + opcode: mfspr + args: [ rD ] + condition: spr == 18 + - name: mfdbatu + opcode: mfspr + args: [ rD ] + condition: spr == 397 + - name: mftdu + opcode: mfspr + args: [ rD ] + condition: spr == 571 + + # Branch Conditional + # bc branch if negative + - name: blt + opcode: bc + modifiers: [ AA, LK ] + args: [ BD ] + condition: BO == 12 && BI & 0b11 == 0b00 && crfS == 0 + - name: blt + opcode: bc + modifiers: [ AA, LK ] + args: [ crfS, BD ] + condition: BO == 12 && BI & 0b11 == 0b00 + # bc branch if not positive + - name: ble + opcode: bc + modifiers: [ AA, LK ] + args: [ BD ] + condition: BO == 4 && BI & 0b11 == 0b01 && crfS == 0 + - name: ble + opcode: bc + modifiers: [ AA, LK ] + args: [ crfS, BD ] + condition: BO == 4 && BI & 0b11 == 0b01 + # bc branch if zero + - name: beq + opcode: bc + modifiers: [ AA, LK ] + args: [ BD ] + condition: BO == 12 && BI & 0b11 == 0b10 && crfS == 0 + - name: beq + opcode: bc + modifiers: [ AA, LK ] + args: [ crfS, BD ] + condition: BO == 12 && BI & 0b11 == 0b10 + # bc branch if not negative + - name: bge + opcode: bc + modifiers: [ AA, LK ] + args: [ BD ] + condition: BO == 4 && BI & 0b11 == 0b00 && crfS == 0 + - name: bge + opcode: bc + modifiers: [ AA, LK ] + args: [ crfS, BD ] + condition: BO == 4 && BI & 0b11 == 0b00 + # bc branch if positive + - name: bgt + opcode: bc + modifiers: [ AA, LK ] + args: [ BD ] + condition: BO == 12 && BI & 0b11 == 0b01 && crfS == 0 + - name: bgt + opcode: bc + modifiers: [ AA, LK ] + args: [ crfS, BD ] + condition: BO == 12 && BI & 0b11 == 0b01 + # bc branch if not zero + - name: bne + opcode: bc + modifiers: [ AA, LK ] + args: [ BD ] + condition: BO == 4 && BI & 0b11 == 0b10 && crfS == 0 + - name: bne + opcode: bc + modifiers: [ AA, LK ] + args: [ crfS, BD ] + condition: BO == 4 && BI & 0b11 == 0b10 + # bc branch if summary overflow + - name: bso + opcode: bc + modifiers: [ AA, LK ] + args: [ BD ] + condition: BO == 12 && BI & 0b11 == 0b11 && crfS == 0 + - name: bso + opcode: bc + modifiers: [ AA, LK ] + args: [ crfS, BD ] + condition: BO == 12 && BI & 0b11 == 0b11 + # bc branch if not summary overflow + - name: bns + opcode: bc + modifiers: [ AA, LK ] + args: [ BD ] + condition: BO == 4 && BI & 0b11 == 0b11 && crfS == 0 + - name: bns + opcode: bc + modifiers: [ AA, LK ] + args: [ crfS, BD ] + condition: BO == 4 && BI & 0b11 == 0b11 + + - name: bdnz + opcode: bc + modifiers: [ AA, LK ] + args: [ BD ] + condition: BO == 16 && BI == 0 + - name: bdz + opcode: bc + modifiers: [ AA, LK ] + args: [ BD ] + condition: BO == 18 && BI == 0 + # TODO support conditional bd... + + # Branch Conditional to Count Register + # bcctr branch always + - name: bctr + opcode: bcctr + modifiers: [ LK ] + condition: BO == 20 && BI == 0 + # bcctr branch if negative + - name: bltctr + opcode: bcctr + modifiers: [ LK ] + condition: BO == 12 && BI & 0b11 == 0b00 && crfS == 0 + - name: bltctr + opcode: bcctr + modifiers: [ LK ] + args: [ crfS ] + condition: BO == 12 && BI & 0b11 == 0b00 + # bcctr branch if not positive + - name: blectr + opcode: bcctr + modifiers: [ LK ] + condition: BO == 4 && BI & 0b11 == 0b01 && crfS == 0 + - name: blectr + opcode: bcctr + modifiers: [ LK ] + args: [ crfS ] + condition: BO == 4 && BI & 0b11 == 0b01 + # bcctr branch if zero + - name: beqctr + opcode: bcctr + modifiers: [ LK ] + condition: BO == 12 && BI & 0b11 == 0b10 && crfS == 0 + - name: beqctr + opcode: bcctr + modifiers: [ LK ] + args: [ crfS ] + condition: BO == 12 && BI & 0b11 == 0b10 + # bcctr branch if not negative + - name: bgectr + opcode: bcctr + modifiers: [ LK ] + condition: BO == 4 && BI & 0b11 == 0b00 && crfS == 0 + - name: bgectr + opcode: bcctr + modifiers: [ LK ] + args: [ crfS ] + condition: BO == 4 && BI & 0b11 == 0b00 + # bcctr branch if positive + - name: bgtctr + opcode: bcctr + modifiers: [ LK ] + condition: BO == 12 && BI & 0b11 == 0b01 && crfS == 0 + - name: bgtctr + opcode: bcctr + modifiers: [ LK ] + args: [ crfS ] + condition: BO == 12 && BI & 0b11 == 0b01 + # bcctr branch if not zero + - name: bnectr + opcode: bcctr + modifiers: [ LK ] + condition: BO == 4 && BI & 0b11 == 0b10 && crfS == 0 + - name: bnectr + opcode: bcctr + modifiers: [ LK ] + args: [ crfS ] + condition: BO == 4 && BI & 0b11 == 0b10 + # bcctr branch if summary overflow + - name: bsoctr + opcode: bcctr + modifiers: [ LK ] + condition: BO == 12 && BI & 0b11 == 0b11 && crfS == 0 + - name: bsoctr + opcode: bcctr + modifiers: [ LK ] + args: [ crfS ] + condition: BO == 12 && BI & 0b11 == 0b11 + # bcctr branch if not summary overflow + - name: bnsctr + opcode: bcctr + modifiers: [ LK ] + condition: BO == 4 && BI & 0b11 == 0b11 && crfS == 0 + - name: bnsctr + opcode: bcctr + modifiers: [ LK ] + args: [ crfS ] + condition: BO == 4 && BI & 0b11 == 0b11 + + # Branch Conditional to Link Register + + # bclr branch always + - name: blr + opcode: bclr + modifiers: [ LK ] + condition: BO == 20 && BI == 0 + # bclr branch if negative + - name: bltlr + opcode: bclr + modifiers: [ LK ] + condition: BO == 12 && BI & 0b11 == 0b00 && crfS == 0 + - name: bltlr + opcode: bclr + modifiers: [ LK ] + args: [ crfS ] + condition: BO == 12 && BI & 0b11 == 0b00 + # bclr branch if not positive + - name: blelr + opcode: bclr + modifiers: [ LK ] + condition: BO == 4 && BI & 0b11 == 0b01 && crfS == 0 + - name: blelr + opcode: bclr + modifiers: [ LK ] + args: [ crfS ] + condition: BO == 4 && BI & 0b11 == 0b01 + # bclr branch if zero + - name: beqlr + opcode: bclr + modifiers: [ LK ] + condition: BO == 12 && BI & 0b11 == 0b10 && crfS == 0 + - name: beqlr + opcode: bclr + modifiers: [ LK ] + args: [ crfS ] + condition: BO == 12 && BI & 0b11 == 0b10 + # bclr branch if not negative + - name: bgelr + opcode: bclr + modifiers: [ LK ] + condition: BO == 4 && BI & 0b11 == 0b00 && crfS == 0 + - name: bgelr + opcode: bclr + modifiers: [ LK ] + args: [ crfS ] + condition: BO == 4 && BI & 0b11 == 0b00 + # bclr branch if positive + - name: bgtlr + opcode: bclr + modifiers: [ LK ] + condition: BO == 12 && BI & 0b11 == 0b01 && crfS == 0 + - name: bgtlr + opcode: bclr + modifiers: [ LK ] + args: [ crfS ] + condition: BO == 12 && BI & 0b11 == 0b01 + # bclr branch if not zero + - name: bnelr + opcode: bclr + modifiers: [ LK ] + condition: BO == 4 && BI & 0b11 == 0b10 && crfS == 0 + - name: bnelr + opcode: bclr + modifiers: [ LK ] + args: [ crfS ] + condition: BO == 4 && BI & 0b11 == 0b10 + # bclr branch if summary overflow + - name: bsolr + opcode: bclr + modifiers: [ LK ] + condition: BO == 12 && BI & 0b11 == 0b11 && crfS == 0 + - name: bsolr + opcode: bclr + modifiers: [ LK ] + args: [ crfS ] + condition: BO == 12 && BI & 0b11 == 0b11 + # bclr branch if not summary overflow + - name: bnslr + opcode: bclr + modifiers: [ LK ] + condition: BO == 4 && BI & 0b11 == 0b11 && crfS == 0 + - name: bnslr + opcode: bclr + modifiers: [ LK ] + args: [ crfS ] + condition: BO == 4 && BI & 0b11 == 0b11 diff --git a/macros/Cargo.toml b/macros/Cargo.toml deleted file mode 100644 index 51288b3..0000000 --- a/macros/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "ppc750cl-macros" -version = "0.1.1" -edition = "2018" -authors = ["Richard Patel "] -license = "GPL-3.0-or-later" -description = "Procedural macros for powerpc750cl" -repository = "https://github.com/terorie/ppc750cl" - -[lib] -proc-macro = true - -[dependencies] -proc-macro2 = "1.0.28" -quote = "1.0.9" -syn = { version = "1.0.74", features = ["full", "parsing"] } diff --git a/macros/src/isa.rs b/macros/src/isa.rs deleted file mode 100644 index 2b089fc..0000000 --- a/macros/src/isa.rs +++ /dev/null @@ -1,215 +0,0 @@ -use std::iter::FromIterator; - -use proc_macro2::{Delimiter, Group, Ident, Literal, Span, TokenStream, TokenTree}; -use quote::quote; -use syn::parse::{Parse, ParseStream}; -use syn::punctuated::Punctuated; -use syn::token::{And, EqEq, Semi}; -use syn::{LitInt, LitStr}; - -struct Opcodes { - opcodes: Punctuated, -} - -impl Parse for Opcodes { - fn parse(input: ParseStream) -> syn::Result { - Ok(Self { - opcodes: Punctuated::parse_terminated(input)?, - }) - } -} - -#[derive(Debug)] -struct Opcode { - name: String, - variant_name: String, - mask: u32, - bits: u32, -} - -impl Parse for Opcode { - fn parse(input: ParseStream) -> syn::Result { - let name = input.parse::()?; - input.parse::()?; - let mask = input.parse::()?; - input.parse::()?; - let bits = input.parse::()?; - Ok(Self { - name: name.value(), - variant_name: opcode_to_variant_name(&name)?, - mask: hex_from_lit_int(&mask)?, - bits: hex_from_lit_int(&bits)?, - }) - } -} - -fn hex_from_lit_int(int: &LitInt) -> syn::Result { - let str = int.to_string(); - let hex = match str.strip_prefix("0x") { - None => return Err(syn::Error::new(int.span(), "not a hex integer")), - Some(x) => x, - }; - u32::from_str_radix(hex, 16).map_err(|e| syn::Error::new(int.span(), e)) -} - -fn opcode_to_variant_name(opcode: &LitStr) -> syn::Result { - let mut s = String::new(); - let opcode_value = opcode.value(); - let mut chars = opcode_value.chars(); - loop { - // Make first char uppercase. - let c = match chars.next() { - None => return Ok(s), - Some(c) => c, - }; - match c { - 'a'..='z' => s.push(c.to_ascii_uppercase()), - _ => return Err(syn::Error::new(opcode.span(), "invalid opcode name")), - } - loop { - let c = match chars.next() { - None => return Ok(s), - Some(c) => c, - }; - match c { - '0'..='9' | 'a'..='z' => s.push(c), - '_' => break, - '.' => { - s.push('_'); - break; - } - _ => { - return Err(syn::Error::new( - opcode.span(), - "invalid character in opcode name", - )) - } - } - } - } -} - -fn gen_is_valid_fn(tokens: &mut Vec, opcodes: &Opcodes) { - tokens.extend(quote!(pub fn is_valid(self, code: u32) -> bool)); - - let mut parts = Vec::::new(); - parts.extend(quote!(match self)); - - let mut match_parts = Vec::::new(); - match_parts.extend(quote!(Opcode::Illegal => false,)); - - for opcode in &opcodes.opcodes { - match_parts.extend(quote!(Opcode::)); - match_parts.push(TokenTree::Ident(Ident::new( - &opcode.variant_name, - Span::call_site(), - ))); - match_parts.extend(quote!(=> code &)); - match_parts.push(TokenTree::Literal(Literal::u32_suffixed(opcode.mask))); - match_parts.extend(quote!(==)); - match_parts.push(TokenTree::Literal(Literal::u32_suffixed(opcode.bits))); - match_parts.extend(quote!(,)); - } - 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)); - tokens.push(TokenTree::Group(body)); -} - -fn gen_mnemonic_fn(tokens: &mut Vec, opcodes: &Opcodes) { - tokens.extend(quote!(pub fn mnemonic(self) -> &'static str)); - - let mut parts = Vec::::new(); - parts.extend(quote!(match self)); - - let mut match_parts = Vec::::new(); - match_parts.extend(quote!(Opcode::Illegal => "",)); - for opcode in &opcodes.opcodes { - match_parts.extend(quote!(Opcode::)); - match_parts.push(TokenTree::Ident(Ident::new( - &opcode.variant_name, - Span::call_site(), - ))); - match_parts.extend(quote!(=>)); - match_parts.push(TokenTree::Literal(Literal::string(&opcode.name))); - match_parts.extend(quote!(,)); - } - - 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)); - tokens.push(TokenTree::Group(body)); -} - -pub(crate) fn isa(input: TokenStream) -> syn::Result { - let opcodes: Opcodes = syn::parse2(input)?; - - // Assemble root stream. - let mut root = Vec::::new(); - - // Define enum derives and header. - root.extend(quote!(#[derive(Debug, Copy, Clone, Eq, PartialEq)])); - root.extend(quote!(pub enum Opcode)); - - // Create entries. - // First entry is going to be the illegal entry. - let mut enum_entries = Vec::::new(); - enum_entries.extend(quote!(Illegal = -1,)); - // Append the actual opcodes. - for opcode in &opcodes.opcodes { - enum_entries.push(TokenTree::Ident(Ident::new( - &opcode.variant_name, - Span::call_site(), - ))); - enum_entries.extend(quote!(,)); - } - - // Create body. - let enum_body = Group::new(Delimiter::Brace, TokenStream::from_iter(enum_entries)); - root.push(TokenTree::Group(enum_body)); - - // impl Opcode block. - root.extend(quote!(impl Opcode)); - let mut impl_opcode_body_parts = Vec::::new(); - gen_is_valid_fn(&mut impl_opcode_body_parts, &opcodes); - gen_mnemonic_fn(&mut impl_opcode_body_parts, &opcodes); - let impl_opcode_body = Group::new( - Delimiter::Brace, - TokenStream::from_iter(impl_opcode_body_parts), - ); - root.push(TokenTree::Group(impl_opcode_body)); - - // Extra code. - root.extend(quote! { - impl Default for Opcode { - fn default() -> Self { - Opcode::Illegal - } - } - - impl std::string::ToString for Opcode { - fn to_string(&self) -> String { - let mnemonic = self.mnemonic(); - mnemonic.to_owned() - } - } - }); - - Ok(TokenStream::from_iter(root)) -} - -#[cfg(test)] -mod tests { - use super::*; - - fn _opcode_to_variant_name(input: &str) -> String { - opcode_to_variant_name(&LitStr::new(input, proc_macro2::Span::call_site())).unwrap() - } - - #[test] - fn test_opcode_to_variant_name() { - assert_eq!(_opcode_to_variant_name("lol_lel."), "LolLel_"); - assert_eq!(_opcode_to_variant_name("ps_nmsub"), "PsNmsub"); - } -} diff --git a/macros/src/lib.rs b/macros/src/lib.rs deleted file mode 100644 index 64339b0..0000000 --- a/macros/src/lib.rs +++ /dev/null @@ -1,22 +0,0 @@ -mod isa; -mod writer; - -#[proc_macro] -pub fn isa(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let input = proc_macro2::TokenStream::from(input); - let output = match crate::isa::isa(input) { - Ok(v) => v, - Err(err) => return proc_macro::TokenStream::from(err.to_compile_error()), - }; - proc_macro::TokenStream::from(output) -} - -#[proc_macro] -pub fn write_asm(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let input = proc_macro2::TokenStream::from(input); - let output = match crate::writer::write_asm(input) { - Ok(v) => v, - Err(err) => return proc_macro::TokenStream::from(err.to_compile_error()), - }; - proc_macro::TokenStream::from(output) -} diff --git a/macros/src/writer.rs b/macros/src/writer.rs deleted file mode 100644 index dc96c3f..0000000 --- a/macros/src/writer.rs +++ /dev/null @@ -1,170 +0,0 @@ -use std::iter::FromIterator; -use std::string::ToString; - -use proc_macro2::{Delimiter, Group, TokenStream}; -use quote::quote; -use quote::ToTokens; -use syn::parse::{Parse, ParseStream}; -use syn::punctuated::Punctuated; -use syn::spanned::Spanned; -use syn::{Expr, ExprLit, ExprPath, Ident}; - -struct Arguments { - formatter: Expr, - ins: Expr, - args: Punctuated, -} - -impl Parse for Arguments { - fn parse(input: ParseStream) -> syn::Result { - let formatter = input.parse()?; - input.parse::()?; - let ins = input.parse()?; - input.parse::()?; - let content; - syn::braced!(content in input); - let args = Punctuated::parse_terminated(&content)?; - Ok(Self { - formatter, - ins, - args, - }) - } -} - -/// A single part of an instruction. -/// -/// Examples: -/// ```ignore -/// (op.mnemonic, rc, oe) -> mnemonic; -/// d -> fpr; -/// ``` -struct Argument { - sources: Vec, - target: Ident, -} - -impl Parse for Argument { - fn parse(input: ParseStream) -> syn::Result { - // Parse source part. - let lookahead = input.lookahead1(); - let sources; - if lookahead.peek(syn::token::Paren) { - // Parse multiple if we found a parenthesis. - let content; - syn::parenthesized!(content in input); - sources = content - .parse_terminated::(Expr::parse)? - .into_iter() - .collect(); - } else if lookahead.peek(syn::LitStr) || lookahead.peek(syn::LitInt) { - let expr = input.parse::()?.into(); - sources = vec![expr]; - } else { - let expr = input.parse::()?.into(); - sources = vec![expr]; - } - input.parse::()?; - let target = input.parse()?; - Ok(Self { sources, target }) - } -} - -impl Arguments { - fn format_mnemonic(&self) -> Vec { - let arg = &self.args[0]; - assert!(!arg.sources.is_empty()); - // Print the mnemonic. - let mut calls = vec![self.format_call(&arg.target, self.ins_call(&arg.sources[0]))]; - // Print any mnemonic suffixes. - for src in arg.sources.iter().skip(1) { - calls.push(self.format_call( - &Ident::new(&src.into_token_stream().to_string(), src.span()), - self.ins_call(src), - )); - } - calls - } - - fn format_call(&self, method_arg: &Ident, args: TokenStream) -> TokenStream { - let arg_str = method_arg.to_string(); - let method_name = format!("write_{}", arg_str); - let method_name = Ident::new(&method_name, method_arg.span()); - let formatter = &self.formatter; - if arg_str == "branch_target" { - quote!(#formatter.write_branch_target(#args, self.addr)?) - } else { - quote!(#formatter.#method_name(#args)?) - } - } - - fn ins_call(&self, call: &Expr) -> TokenStream { - match call { - Expr::Lit(_) => call.to_token_stream(), - _ => { - let ins = &self.ins; - quote!(#ins.#call()) - } - } - } -} - -pub(crate) fn write_asm(input: TokenStream) -> syn::Result { - let arguments: Arguments = syn::parse2(input)?; - assert!(!arguments.args.is_empty()); - - // Create a list of calls to execute. - let mut calls = Vec::::new(); - calls.extend(arguments.format_mnemonic()); - let mut offset_open = false; - for (i, arg) in arguments.args.iter().enumerate().skip(1) { - // Separate operands from one another unless the last one was an offset. - if !offset_open { - if i == 1 { - calls.push( - arguments - .format_call(&Ident::new("opcode_separator", arg.target.span()), quote!()), - ); - } else { - calls.push(arguments.format_call( - &Ident::new("operand_separator", arg.target.span()), - quote!(), - )); - } - } - // Arguments to out.write_x(...); - let format_args = arg.sources.iter().map(|src| arguments.ins_call(src)); - let format_args_punct: Punctuated = - Punctuated::from_iter(format_args); - // Create call. - if arg.target.to_string().starts_with("offset") { - // Offsets are a special case since we need to call close afterwards. - if offset_open { - return Err(syn::Error::new( - arg.target.span(), - "two consecutive offset arguments", - )); - } - calls.push(arguments.format_call( - &Ident::new(&(arg.target.to_string() + "_open"), arg.target.span()), - format_args_punct.to_token_stream(), - )); - offset_open = true; - } else { - calls.push(arguments.format_call(&arg.target, format_args_punct.to_token_stream())); - if offset_open { - calls.push( - arguments.format_call(&Ident::new("offset_close", arg.target.span()), quote!()), - ); - offset_open = false; - } - } - } - - // Wrap calls in a block returning Ok(()). - calls.push(quote!(std::io::Result::Ok(()))); - let statements = Punctuated::::from_iter(calls); - let tokens = Group::new(Delimiter::Brace, statements.to_token_stream()); - - Ok(tokens.to_token_stream()) -} diff --git a/rand/Cargo.toml b/rand/Cargo.toml index 1002969..8f96880 100644 --- a/rand/Cargo.toml +++ b/rand/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "ppc750cl-rand" -version = "0.1.1" -edition = "2018" +version = "0.2.0" +edition = "2021" authors = ["Richard Patel "] license = "GPL-3.0-or-later" description = "Generate random PowerPC 750CL instructions" repository = "https://github.com/terorie/ppc750cl" [dependencies] -ppc750cl = { path = "../disasm", version = "0.1.1" } -rand_core = "0.5" -sfmt = "0.6" +ppc750cl = { path = "../disasm", version = "0.2.0" } +rand_core = "0.6" +sfmt = "0.7" diff --git a/rand/src/main.rs b/rand/src/main.rs index eefd5c1..99a75dd 100644 --- a/rand/src/main.rs +++ b/rand/src/main.rs @@ -1,26 +1,16 @@ use rand_core::{RngCore, SeedableRng}; use sfmt::SFMT; -use ppc750cl::formatter::SimpleFormatter; +use ppc750cl::formatter::FormattedIns; use ppc750cl::{Ins, Opcode}; -use std::io::{BufWriter, Write}; fn main() { let mut rng = SFMT::seed_from_u64(42); - let stdout = std::io::stdout(); - let stdout_lock = stdout.lock(); - let stream = BufWriter::with_capacity(1_000_000, stdout_lock); - let mut formatter = SimpleFormatter { writer: stream }; loop { let ins = Ins::new(rng.next_u32(), 0); if ins.op == Opcode::Illegal { continue; } - if ins.write_string(&mut formatter).is_err() { - return; - } - if formatter.writer.write_all("\n".as_ref()).is_err() { - return; - } + println!("{}", FormattedIns(ins)); } }