From 87b90dc701bd03442dbd6107a4182c1ab94e57a4 Mon Sep 17 00:00:00 2001 From: geos_one Date: Sun, 10 Oct 2010 08:02:11 +0000 Subject: [PATCH] app-emulation/qemu: Bump git-svn-id: https://svn.disconnected-by-peer.at/svn/linamh/trunk/vmware@2501 6952d904-891a-0410-993b-d76249ca496b --- app-emulation/qemu/ChangeLog | 19 + app-emulation/qemu/Manifest | 22 +- .../files/0.12.4/0001-qemu-0.7.0-amd64.patch | 37 + .../0.12.4/0002-qemu-0.9.0.cvs-binfmt.patch | 85 + .../0.12.4/0003-qemu-cvs-alsa_bitfield.patch | 83 + .../0.12.4/0004-qemu-cvs-alsa_ioctl.patch | 3626 ++++++++ .../0.12.4/0005-qemu-cvs-alsa_mmap.patch | 47 + .../0.12.4/0006-qemu-cvs-gettimeofday.patch | 26 + .../0.12.4/0007-qemu-cvs-ioctl_debug.patch | 33 + .../0008-qemu-cvs-ioctl_nodirection.patch | 42 + .../0009-qemu-cvs-sched_getaffinity.patch | 56 + .../0.12.4/0010-qemu-cvs-mmap-amd64.patch | 41 + .../0.12.4/0011-qemu-img-vmdk-scsi.patch | 142 + .../0.12.4/0012-qemu-nonvoid_return.patch | 40 + .../0013-i386-linux-user-NPTL-support.patch | 64 + .../0014-qemu-0.11-git-ioctl_mount.patch | 25 + ...mu-0.11-git-user-linux-ppc-uid16_fix.patch | 116 + .../files/0.12.4/0016-S-390-support.patch | 7699 +++++++++++++++++ app-emulation/qemu/qemu-0.11.1.ebuild | 8 +- app-emulation/qemu/qemu-0.12.5.ebuild | 155 + 20 files changed, 12360 insertions(+), 6 deletions(-) create mode 100644 app-emulation/qemu/files/0.12.4/0001-qemu-0.7.0-amd64.patch create mode 100644 app-emulation/qemu/files/0.12.4/0002-qemu-0.9.0.cvs-binfmt.patch create mode 100644 app-emulation/qemu/files/0.12.4/0003-qemu-cvs-alsa_bitfield.patch create mode 100644 app-emulation/qemu/files/0.12.4/0004-qemu-cvs-alsa_ioctl.patch create mode 100644 app-emulation/qemu/files/0.12.4/0005-qemu-cvs-alsa_mmap.patch create mode 100644 app-emulation/qemu/files/0.12.4/0006-qemu-cvs-gettimeofday.patch create mode 100644 app-emulation/qemu/files/0.12.4/0007-qemu-cvs-ioctl_debug.patch create mode 100644 app-emulation/qemu/files/0.12.4/0008-qemu-cvs-ioctl_nodirection.patch create mode 100644 app-emulation/qemu/files/0.12.4/0009-qemu-cvs-sched_getaffinity.patch create mode 100644 app-emulation/qemu/files/0.12.4/0010-qemu-cvs-mmap-amd64.patch create mode 100644 app-emulation/qemu/files/0.12.4/0011-qemu-img-vmdk-scsi.patch create mode 100644 app-emulation/qemu/files/0.12.4/0012-qemu-nonvoid_return.patch create mode 100644 app-emulation/qemu/files/0.12.4/0013-i386-linux-user-NPTL-support.patch create mode 100644 app-emulation/qemu/files/0.12.4/0014-qemu-0.11-git-ioctl_mount.patch create mode 100644 app-emulation/qemu/files/0.12.4/0015-qemu-0.11-git-user-linux-ppc-uid16_fix.patch create mode 100644 app-emulation/qemu/files/0.12.4/0016-S-390-support.patch create mode 100644 app-emulation/qemu/qemu-0.12.5.ebuild diff --git a/app-emulation/qemu/ChangeLog b/app-emulation/qemu/ChangeLog index a4ec535..7646010 100644 --- a/app-emulation/qemu/ChangeLog +++ b/app-emulation/qemu/ChangeLog @@ -2,6 +2,25 @@ # Copyright 1999-2010 Gentoo Foundation; Distributed under the GPL v2 # $Header: /var/cvsroot/gentoo-x86/app-emulation/qemu/ChangeLog,v 1.77 2010/01/05 23:58:40 flameeyes Exp $ + 10 Oct 2010; Mario Fetka +files/0.12.4, + +files/0.12.4/0005-qemu-cvs-alsa_mmap.patch, + +files/0.12.4/0001-qemu-0.7.0-amd64.patch, + +files/0.12.4/0006-qemu-cvs-gettimeofday.patch, + +files/0.12.4/0002-qemu-0.9.0.cvs-binfmt.patch, + +files/0.12.4/0003-qemu-cvs-alsa_bitfield.patch, + +files/0.12.4/0004-qemu-cvs-alsa_ioctl.patch, + +files/0.12.4/0007-qemu-cvs-ioctl_debug.patch, + +files/0.12.4/0009-qemu-cvs-sched_getaffinity.patch, + +files/0.12.4/0010-qemu-cvs-mmap-amd64.patch, + +files/0.12.4/0011-qemu-img-vmdk-scsi.patch, + +files/0.12.4/0014-qemu-0.11-git-ioctl_mount.patch, + +files/0.12.4/0015-qemu-0.11-git-user-linux-ppc-uid16_fix.patch, + +files/0.12.4/0008-qemu-cvs-ioctl_nodirection.patch, qemu-0.11.1.ebuild, + +files/0.12.4/0012-qemu-nonvoid_return.patch, + +files/0.12.4/0013-i386-linux-user-NPTL-support.patch, + +qemu-0.12.5.ebuild, +files/0.12.4/0016-S-390-support.patch: + Bump + 08 Feb 2010; Mario Fetka ChangeLog: add suse patches mainly for sched_getaffinity diff --git a/app-emulation/qemu/Manifest b/app-emulation/qemu/Manifest index 9cbace9..0144e6b 100644 --- a/app-emulation/qemu/Manifest +++ b/app-emulation/qemu/Manifest @@ -27,6 +27,22 @@ AUX 0.11.0/0030-linux-user-getpriority-errno-fix.patch 1024 RMD160 515cd8127329b AUX 0.11.0/0031-linux-user-fadvise64-implementation.patch 1528 RMD160 9085b0ab2b3134d99fc14951ee1f654dc9b2acf8 SHA1 0a87be8db93a9b4695867c16102cd0c435b192a0 SHA256 e06b25ca222f8c0c1bca915f04237f5a3d3ff98260f6f77678bd31bba711593e AUX 0.11.0/0032-linux-user-zero-fstat-buffer-to-initialize-nsec-fie.patch 1241 RMD160 d6d8149d8df578f860c952c30b8de256ecb7670a SHA1 fec06450adf94327076c810ee527782c54b4feb5 SHA256 98fc97662b8360502fe46f747ec46ed5d24f1355184df6d3935338b831344bc3 AUX 0.11.0/0033-dup3-check-fallocate-check-fixed.patch 2241 RMD160 0c191ae3fdf37213175063b3f5a38045939af03d SHA1 a281a4c19cfc2ea938c9b2b4ab9e86cc42826764 SHA256 a9efd4690b840b4c87d9e6a7be15e29381024e8ec7c0811653b4073e9802d6d2 +AUX 0.12.4/0001-qemu-0.7.0-amd64.patch 1431 RMD160 0988e7640747d4ed1b004ef498a0d6da15d216dd SHA1 25d6ff8638ee6a79a8fc686941b14d0222fa1111 SHA256 3e4fdf208e5a746600057d85bca832977afa09a7db022f9fe147ad1a29ad3fa1 +AUX 0.12.4/0002-qemu-0.9.0.cvs-binfmt.patch 7525 RMD160 784b85657ea7ca2f3978b4ddcd0e039b50401793 SHA1 d908545eb963a30465e0e92fbc073cafffa4a37b SHA256 953203c86055b0b83d389ed00fd63629af7f221817da9e0017e931f2c07b1ca4 +AUX 0.12.4/0003-qemu-cvs-alsa_bitfield.patch 2463 RMD160 141d23417fcf2a79ee499d6433859b0ff59cbfbc SHA1 7dd07e6c2fcb29b9f859a365a5dee6580938263a SHA256 bfb3c320ac80dd69187d453e2bdcdc9932e613000dd46a5333ae14a202218780 +AUX 0.12.4/0004-qemu-cvs-alsa_ioctl.patch 134019 RMD160 a6d116925c15a175162273b06d2da67887fdeeab SHA1 397b0e87ee7ea9e00edd882443082f9fd73f7a0f SHA256 defeb75f644661c9f947068759513a775a3055a6cbce2c07d6836c5be5f3bec1 +AUX 0.12.4/0005-qemu-cvs-alsa_mmap.patch 1559 RMD160 1bdba386e31612c392b9672bdd4e4dc47f02e234 SHA1 dae6f96eb16ce9bfa924f66b503fec2016d41201 SHA256 7d0f5aa3fffa980960c4fccf5f77e621216f8292ac7985e16a985b961160c7b2 +AUX 0.12.4/0006-qemu-cvs-gettimeofday.patch 825 RMD160 303366820fd2771ee24c9c5dfd55d29e9b55a8ca SHA1 de26d00e2c920682cc38fd138572f76c41fee853 SHA256 336a0ad0178289cea1bc16825bb425d6fbb8472fc5a5b39eb6f4d71903502ed7 +AUX 0.12.4/0007-qemu-cvs-ioctl_debug.patch 1434 RMD160 bc9d1705d725637f2f8b5d498b9739e851d0593d SHA1 0d20791711fe171f635a5708799c49810207f792 SHA256 0c9830d62edd3a03b8132d9aedc82b12bc934a676b7b3e5d1499ac58d59648fc +AUX 0.12.4/0008-qemu-cvs-ioctl_nodirection.patch 1603 RMD160 4a3549dc1276ae18e7b62ca23a1a693060582c75 SHA1 b56d63d3dde9382759a84554a763e11c48ead551 SHA256 d95cbed88bd560d1c74da8a4e9c47ed180d1718bdcee25652345a035f7e28ea2 +AUX 0.12.4/0009-qemu-cvs-sched_getaffinity.patch 1985 RMD160 2b4f2b59d5d3d73c17ce74f1860cc0d853ac8bf5 SHA1 6a3e6e115e1f50934c01d96e115a45fd59f173f3 SHA256 e251b73c0c21279786343f09884da76147e6fdc08287ec706882d900ed73022a +AUX 0.12.4/0010-qemu-cvs-mmap-amd64.patch 1213 RMD160 0b97ff141f22158ce4593b761185c23269447757 SHA1 19f8e0d97ea8442ae3f1972f33d04dabfc54242e SHA256 ac77e087f64f6aa901355aa7ce261396db68cb52648b9ee0d276fc670de07616 +AUX 0.12.4/0011-qemu-img-vmdk-scsi.patch 4807 RMD160 6ea88da1e2f4d2d3fa2ccefebe24603e6d300504 SHA1 9e9d4120bc9524c5375afb3cd16be781c0bf0ae0 SHA256 70c628853830e5c5c073873d3c305bf0e5b8c174782e89912c1bd074104df7ad +AUX 0.12.4/0012-qemu-nonvoid_return.patch 1125 RMD160 9131a27f9da7ac3f92e6f826a28eea70992cd126 SHA1 24450b33ead5168b2e8327cf08542ab2ef5d6914 SHA256 f906e1e8f9718c38d3927eacd11a65b0abe2178fb15f65e14aa007b392d41425 +AUX 0.12.4/0013-i386-linux-user-NPTL-support.patch 2097 RMD160 c0894f7a112c5ad4f29ab0539a0c333fd6f6d1fd SHA1 df971ecc7f3819fce132d00a524390b2b330b8cc SHA256 15be0654302f9941e9563ea02ef22b72b64aef5359343d6935aa46c90fb9750e +AUX 0.12.4/0014-qemu-0.11-git-ioctl_mount.patch 893 RMD160 b0dbf5ff9912905dc3a536189f1ca9ee621bccb8 SHA1 b1cdcc0c00cae4ede9fa76ad99103324a408b273 SHA256 8523965fb8781e35f5c6852b72c1f80c3fba859bf600075e11b71d2a4ce719ab +AUX 0.12.4/0015-qemu-0.11-git-user-linux-ppc-uid16_fix.patch 4886 RMD160 f054c87a28c786687f14a9d7936d29c5f4ebf923 SHA1 e5a8e5ce368eec9da5069ff45cecf7826d71fccd SHA256 198bb2e440d5ac53cf065b7eb634528d0725b3c66fd5be3306046bf4994e9e59 +AUX 0.12.4/0016-S-390-support.patch 248902 RMD160 a8691de62f77db5a1764adbe82e50de47ac1b8a3 SHA1 f7cf8c6c0bdfead8d2ad73ce6a49b6586ded1743 SHA256 c951f19784d126230ac563ad0c9ebb9ad96b6260f5ac53e43dc469e374f635f1 AUX qemu-0.10.3-nopl-fix.patch 1118 RMD160 849e4b88ca7985dc3faae0a225181205043f0265 SHA1 70cf0727a7cbdd79243ae6768f34c07c6e9c5aec SHA256 24656137f1f38aed2c2661ebd20d9a6d86eaf9768c3e239b971f01418b396028 AUX qemu-0.11.0-mips64-user-fix.patch 313 RMD160 db016e0a48990a435dd6cf6e807145b33ada4908 SHA1 2ea913b1bcd29734a6d4011794bdb4aa3599a184 SHA256 b4173fc177bd0d0ba67f5551a3512047a19a9b2c0a122f968e32fbd834848d2f AUX qemu-arm-eabi-0.10.5.patch 21422 RMD160 a2ab6384938b08764324a4239fc30718161a3977 SHA1 2c7cec113b02e9f91226887257b393a3dfba2234 SHA256 b47327d7eab124617941e5403c5d4d0af2b21ce2278d5524677c521be462aa57 @@ -35,7 +51,9 @@ AUX qemu-ifdown 478 RMD160 2187fbf352e6b84686f0cf0e9e9ebe5d26359858 SHA1 1daccb4 AUX qemu-ifup 554 RMD160 9769d79ab6456bdd7e3e689005f629e2a67b858d SHA1 dde2b27acabe6fe23ca40f90ff6950bb12a4b506 SHA256 eae9b50680442acc29c65a245a2d26a63756ad4cb894e08cb5ea249686801f1d DIST qemu-0.10.6.tar.gz 3664559 RMD160 1321a10777d2e0c6b53887d0525a28cc1b36ec9b SHA1 9432738ba513e07c981097468945b2e3ad9cb81e SHA256 8725298d4fd937ae41d942d0dd4a22fc02561d8c57a9fdcdbfa56427915757c7 DIST qemu-0.11.1.tar.gz 3830070 RMD160 4da00fa6c01d7ff6af0ee781bc9260da577ea7d3 SHA1 7b983cd18f44c6e7627532b662f010389d3bcdff SHA256 2ecd2fc0af2ce5d96067ae82cc98a08275c596de53fc929484bedee1d6e7893a +DIST qemu-0.12.5.tar.gz 4291741 RMD160 c4eba2e649b428e8dd432718443e986057e692d7 SHA1 596a673f3a6697ea8fd90f4f23981241cc13bdc3 SHA256 a6a7b30b53591e160b5c7fd9319985673174e9ea47b182dbe63bc99357741f58 EBUILD qemu-0.10.6.ebuild 5000 RMD160 093eeeda7f4872bddeb83688daba67623eb26d01 SHA1 e5c5abf287914b222483cb32853bbcd658fa8fb6 SHA256 117e429849e1f55c17dd76837cb11c974ffccc19eba1b6ae5f33996a18c463c7 -EBUILD qemu-0.11.1.ebuild 5085 RMD160 8087ae228f75201f05e62ee034f552f529a44199 SHA1 b7bc2dd15b3c0d70722911c52176855cdedb33ab SHA256 10a7c4c25766209a80b18dbd360fedc3fd9fe6d79c2e37f3007870df6335ec19 -MISC ChangeLog 10331 RMD160 ff0ab9d98d85c4c46d37aaab5904c5d691be92a6 SHA1 ef40ad6b3c5cde2867f18e63af15a1335c3a3b96 SHA256 e03743f4235a6bc4030280b8e5e40136b0b317a059ef585d539bef9f289b6387 +EBUILD qemu-0.11.1.ebuild 5090 RMD160 9889a49d89c968b9710a159004c0467a82e711f7 SHA1 f3389454f0508c9c9b903d35b2472d429a85a954 SHA256 6963ebb2f42ef4bee899e5c9554eb4b91de11e798c4f632111ae9b6850d801da +EBUILD qemu-0.12.5.ebuild 5128 RMD160 7f1ca4fe533772771d753fdb45565cc62b1e1031 SHA1 bb9960710ea99fb224a5381aec95d11f0b3a4f8c SHA256 b097d506303e4856cb5819642f113162a17644fbc46ae3c483ed1b4fb297b632 +MISC ChangeLog 11259 RMD160 6e119249ab4ffddf3dc6ef8da9fce0949fc91ad2 SHA1 0914e40152b37c48c175db6b9079eb7990814237 SHA256 db076339aadcd5266d3998d3314a1e1fb54cea58457f5c43cea5a40f3fe4999c MISC metadata.xml 910 RMD160 da1d7ba61d401bb22fc22be931b27be432d6d103 SHA1 6ffb7c25e19589933bd016d80a16284ae8df436c SHA256 6a27d48cbcc5a90f1464e302252ea10813317ddcb7bdd2e1e5cb927760a5640d diff --git a/app-emulation/qemu/files/0.12.4/0001-qemu-0.7.0-amd64.patch b/app-emulation/qemu/files/0.12.4/0001-qemu-0.7.0-amd64.patch new file mode 100644 index 0000000..daa0e3b --- /dev/null +++ b/app-emulation/qemu/files/0.12.4/0001-qemu-0.7.0-amd64.patch @@ -0,0 +1,37 @@ +From 8c7a6ec1220237db1e270244b1f1d90dd3d54204 Mon Sep 17 00:00:00 2001 +From: Ulrich Hecht +Date: Tue, 14 Apr 2009 16:17:39 +0200 +Subject: [PATCH 01/16] qemu-0.7.0-amd64 + +No clue why this is necessary or useful, nothing found in any changelogs. +--- + x86_64.ld | 6 ++---- + 1 files changed, 2 insertions(+), 4 deletions(-) + +diff --git a/x86_64.ld b/x86_64.ld +index 24ea77d..52a696e 100644 +--- a/x86_64.ld ++++ b/x86_64.ld +@@ -58,8 +58,6 @@ SECTIONS + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .eh_frame_hdr : { *(.eh_frame_hdr) } +- .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } +- .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN (0x100000) - ((0x100000 - .) & (0x100000 - 1)); . = DATA_SEGMENT_ALIGN (0x100000, 0x1000); +@@ -85,8 +83,8 @@ SECTIONS + .data1 : { *(.data1) } + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } +- .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } +- .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table) } ++ .eh_frame : { KEEP (*(.eh_frame)) } ++ .gcc_except_table : { *(.gcc_except_table) } + .dynamic : { *(.dynamic) } + .ctors : + { +-- +1.6.4.2 + diff --git a/app-emulation/qemu/files/0.12.4/0002-qemu-0.9.0.cvs-binfmt.patch b/app-emulation/qemu/files/0.12.4/0002-qemu-0.9.0.cvs-binfmt.patch new file mode 100644 index 0000000..5593022 --- /dev/null +++ b/app-emulation/qemu/files/0.12.4/0002-qemu-0.9.0.cvs-binfmt.patch @@ -0,0 +1,85 @@ +From af10e52cdaf296681cf093f9269acf3080a01f5c Mon Sep 17 00:00:00 2001 +From: Ulrich Hecht +Date: Tue, 14 Apr 2009 16:18:44 +0200 +Subject: [PATCH 02/16] qemu-0.9.0.cvs-binfmt + +Fixes binfmt_misc setup script: +- x86_64 is i386-compatible +- m68k signature fixed +- path to QEMU + +Signed-off-by: Ulrich Hecht +--- + qemu-binfmt-conf.sh | 33 ++++++++++++++++++--------------- + 1 files changed, 18 insertions(+), 15 deletions(-) + +diff --git a/qemu-binfmt-conf.sh b/qemu-binfmt-conf.sh +index 941f0cf..67d6728 100644 +--- a/qemu-binfmt-conf.sh ++++ b/qemu-binfmt-conf.sh +@@ -12,7 +12,7 @@ fi + # probe cpu type + cpu=`uname -m` + case "$cpu" in +- i386|i486|i586|i686|i86pc|BePC) ++ i386|i486|i586|i686|i86pc|BePC|x86_64) + cpu="i386" + ;; + m68k) +@@ -24,36 +24,39 @@ case "$cpu" in + "Power Macintosh"|ppc|ppc64) + cpu="ppc" + ;; +- armv4l) ++ armv[4-9]*l) + cpu="arm" + ;; ++ sparc*) ++ cpu="sparc" ++ ;; + esac + + # register the interpreter for each cpu except for the native one + if [ $cpu != "i386" ] ; then +- echo ':i386:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-i386:' > /proc/sys/fs/binfmt_misc/register +- echo ':i486:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x06\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-i386:' > /proc/sys/fs/binfmt_misc/register ++ echo ':i386:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-i386:' > /proc/sys/fs/binfmt_misc/register ++ echo ':i486:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x06\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-i386:' > /proc/sys/fs/binfmt_misc/register + fi + if [ $cpu != "arm" ] ; then +- echo ':arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-arm:' > /proc/sys/fs/binfmt_misc/register +- echo ':armeb:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-armeb:' > /proc/sys/fs/binfmt_misc/register ++ echo ':arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-arm:' > /proc/sys/fs/binfmt_misc/register ++ echo ':armeb:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-armeb:' > /proc/sys/fs/binfmt_misc/register + fi + if [ $cpu != "sparc" ] ; then +- echo ':sparc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-sparc:' > /proc/sys/fs/binfmt_misc/register ++ echo ':sparc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-sparc:' > /proc/sys/fs/binfmt_misc/register + fi + if [ $cpu != "ppc" ] ; then +- echo ':ppc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x14:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-ppc:' > /proc/sys/fs/binfmt_misc/register ++ echo ':ppc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x14:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-ppc:' > /proc/sys/fs/binfmt_misc/register + fi + if [ $cpu != "m68k" ] ; then + echo 'Please check cpu value and header information for m68k!' +- echo ':m68k:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x04:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-m68k:' > /proc/sys/fs/binfmt_misc/register ++ echo ':m68k:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-m68k:' > /proc/sys/fs/binfmt_misc/register + fi + if [ $cpu != "mips" ] ; then + # FIXME: We could use the other endianness on a MIPS host. +- echo ':mips:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-mips:' > /proc/sys/fs/binfmt_misc/register +- echo ':mipsel:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-mipsel:' > /proc/sys/fs/binfmt_misc/register +- echo ':mipsn32:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-mipsn32:' > /proc/sys/fs/binfmt_misc/register +- echo ':mipsn32el:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-mipsn32el:' > /proc/sys/fs/binfmt_misc/register +- echo ':mips64:M::\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-mips64:' > /proc/sys/fs/binfmt_misc/register +- echo ':mips64el:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-mips64el:' > /proc/sys/fs/binfmt_misc/register ++ echo ':mips:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-mips:' > /proc/sys/fs/binfmt_misc/register ++ echo ':mipsel:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-mipsel:' > /proc/sys/fs/binfmt_misc/register ++ echo ':mipsn32:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-mipsn32:' > /proc/sys/fs/binfmt_misc/register ++ echo ':mipsn32el:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-mipsn32el:' > /proc/sys/fs/binfmt_misc/register ++ echo ':mips64:M::\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-mips64:' > /proc/sys/fs/binfmt_misc/register ++ echo ':mips64el:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-mips64el:' > /proc/sys/fs/binfmt_misc/register + fi +-- +1.6.4.2 + diff --git a/app-emulation/qemu/files/0.12.4/0003-qemu-cvs-alsa_bitfield.patch b/app-emulation/qemu/files/0.12.4/0003-qemu-cvs-alsa_bitfield.patch new file mode 100644 index 0000000..12757e1 --- /dev/null +++ b/app-emulation/qemu/files/0.12.4/0003-qemu-cvs-alsa_bitfield.patch @@ -0,0 +1,83 @@ +From d4ec93547c43a157b88b923b612653c9527ec2a6 Mon Sep 17 00:00:00 2001 +From: Ulrich Hecht +Date: Tue, 14 Apr 2009 16:20:50 +0200 +Subject: [PATCH 03/16] qemu-cvs-alsa_bitfield + +Implements TYPE_INTBITFIELD partially. (required for ALSA support) + +Signed-off-by: Ulrich Hecht +--- + thunk.c | 21 +++++++++++++++++++++ + thunk.h | 3 +++ + 2 files changed, 24 insertions(+), 0 deletions(-) + +diff --git a/thunk.c b/thunk.c +index 0657188..5638b2c 100644 +--- a/thunk.c ++++ b/thunk.c +@@ -41,6 +41,7 @@ static inline const argtype *thunk_type_next(const argtype *type_ptr) + case TYPE_CHAR: + case TYPE_SHORT: + case TYPE_INT: ++ case TYPE_INTBITFIELD: + case TYPE_LONGLONG: + case TYPE_ULONGLONG: + case TYPE_LONG: +@@ -139,6 +140,26 @@ const argtype *thunk_convert(void *dst, const void *src, + case TYPE_INT: + *(uint32_t *)dst = tswap32(*(uint32_t *)src); + break; ++ case TYPE_INTBITFIELD: ++#if defined(TARGET_I386) && defined(__powerpc__) ++ /* powerpc uses the MSB, whereas i386 uses the LSB ++ * to store the first bit in a field */ ++ { ++ unsigned char byte = *(uint8_t *)src; ++ *(uint8_t *)dst = ((byte >> 7) & 1) ++ | ((byte >> 5) & 2) ++ | ((byte >> 3) & 4) ++ | ((byte >> 1) & 8) ++ | ((byte << 1) & 16) ++ | ((byte << 3) & 32) ++ | ((byte << 5) & 64) ++ | ((byte << 7) & 128); ++ /* FIXME: implement for bitfields > 1 byte and other archs */ ++ } ++#else ++ *(uint32_t *)dst = tswap32(*(uint32_t *)src); ++#endif ++ break; + case TYPE_LONGLONG: + case TYPE_ULONGLONG: + *(uint64_t *)dst = tswap64(*(uint64_t *)src); +diff --git a/thunk.h b/thunk.h +index 109c541..55890f3 100644 +--- a/thunk.h ++++ b/thunk.h +@@ -37,6 +37,7 @@ typedef enum argtype { + TYPE_PTR, + TYPE_ARRAY, + TYPE_STRUCT, ++ TYPE_INTBITFIELD, + } argtype; + + #define MK_PTR(type) TYPE_PTR, type +@@ -90,6 +91,7 @@ static inline int thunk_type_size(const argtype *type_ptr, int is_host) + case TYPE_SHORT: + return 2; + case TYPE_INT: ++ case TYPE_INTBITFIELD: + return 4; + case TYPE_LONGLONG: + case TYPE_ULONGLONG: +@@ -127,6 +129,7 @@ static inline int thunk_type_align(const argtype *type_ptr, int is_host) + case TYPE_SHORT: + return 2; + case TYPE_INT: ++ case TYPE_INTBITFIELD: + return 4; + case TYPE_LONGLONG: + case TYPE_ULONGLONG: +-- +1.6.4.2 + diff --git a/app-emulation/qemu/files/0.12.4/0004-qemu-cvs-alsa_ioctl.patch b/app-emulation/qemu/files/0.12.4/0004-qemu-cvs-alsa_ioctl.patch new file mode 100644 index 0000000..53d8473 --- /dev/null +++ b/app-emulation/qemu/files/0.12.4/0004-qemu-cvs-alsa_ioctl.patch @@ -0,0 +1,3626 @@ +From 91d6aa16e2794b006ac997ccebd2c7c7da671f32 Mon Sep 17 00:00:00 2001 +From: Ulrich Hecht +Date: Tue, 14 Apr 2009 16:23:27 +0200 +Subject: [PATCH 04/16] qemu-cvs-alsa_ioctl + +Implements ALSA ioctls on PPC hosts. + +Signed-off-by: Ulrich Hecht +--- + linux-user/ioctls.h | 5 + + linux-user/ioctls_alsa.h | 467 ++++++++++ + linux-user/ioctls_alsa_structs.h | 1740 ++++++++++++++++++++++++++++++++++++++ + linux-user/syscall_defs.h | 1 + + linux-user/syscall_types.h | 5 + + linux-user/syscall_types_alsa.h | 1337 +++++++++++++++++++++++++++++ + 6 files changed, 3555 insertions(+), 0 deletions(-) + create mode 100644 linux-user/ioctls_alsa.h + create mode 100644 linux-user/ioctls_alsa_structs.h + create mode 100644 linux-user/syscall_types_alsa.h + +diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h +index 769e1bc..fca824c 100644 +--- a/linux-user/ioctls.h ++++ b/linux-user/ioctls.h +@@ -304,6 +304,11 @@ + IOCTL(VFAT_IOCTL_READDIR_BOTH, IOC_R, MK_PTR(MK_ARRAY(MK_STRUCT(STRUCT_dirent), 2))) + IOCTL(VFAT_IOCTL_READDIR_SHORT, IOC_R, MK_PTR(MK_ARRAY(MK_STRUCT(STRUCT_dirent), 2))) + ++/* FIXME: including these on x86 / x86_64 breaks qemu-i386 */ ++#ifdef __powerpc__ ++#include "ioctls_alsa.h" ++#endif ++ + IOCTL(LOOP_SET_FD, 0, TYPE_INT) + IOCTL(LOOP_CLR_FD, 0, TYPE_INT) + IOCTL(LOOP_SET_STATUS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info))) +diff --git a/linux-user/ioctls_alsa.h b/linux-user/ioctls_alsa.h +new file mode 100644 +index 0000000..c2aa542 +--- /dev/null ++++ b/linux-user/ioctls_alsa.h +@@ -0,0 +1,467 @@ ++#define SNDRV_SEQ_IOCTL_PVERSION _IOR ('S', 0x00, int) ++#define SNDRV_SEQ_IOCTL_CLIENT_ID _IOR ('S', 0x01, int) ++#define SNDRV_SEQ_IOCTL_SYSTEM_INFO _IOWR('S', 0x02, struct sndrv_seq_system_info) ++#define SNDRV_SEQ_IOCTL_RUNNING_MODE _IOWR('S', 0x03, struct sndrv_seq_running_info) ++#define SNDRV_SEQ_IOCTL_GET_CLIENT_INFO _IOWR('S', 0x10, struct sndrv_seq_client_info) ++#define SNDRV_SEQ_IOCTL_SET_CLIENT_INFO _IOW ('S', 0x11, struct sndrv_seq_client_info) ++#define SNDRV_SEQ_IOCTL_CREATE_PORT _IOWR('S', 0x20, struct sndrv_seq_port_info) ++#define SNDRV_SEQ_IOCTL_DELETE_PORT _IOW ('S', 0x21, struct sndrv_seq_port_info) ++#define SNDRV_SEQ_IOCTL_GET_PORT_INFO _IOWR('S', 0x22, struct sndrv_seq_port_info) ++#define SNDRV_SEQ_IOCTL_SET_PORT_INFO _IOW ('S', 0x23, struct sndrv_seq_port_info) ++#define SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT _IOW ('S', 0x30, struct sndrv_seq_port_subscribe) ++#define SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT _IOW ('S', 0x31, struct sndrv_seq_port_subscribe) ++#define SNDRV_SEQ_IOCTL_CREATE_QUEUE _IOWR('S', 0x32, struct sndrv_seq_queue_info) ++#define SNDRV_SEQ_IOCTL_DELETE_QUEUE _IOW ('S', 0x33, struct sndrv_seq_queue_info) ++#define SNDRV_SEQ_IOCTL_GET_QUEUE_INFO _IOWR('S', 0x34, struct sndrv_seq_queue_info) ++#define SNDRV_SEQ_IOCTL_SET_QUEUE_INFO _IOWR('S', 0x35, struct sndrv_seq_queue_info) ++#define SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE _IOWR('S', 0x36, struct sndrv_seq_queue_info) ++#define SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS _IOWR('S', 0x40, struct sndrv_seq_queue_status) ++#define SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO _IOWR('S', 0x41, struct sndrv_seq_queue_tempo) ++#define SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO _IOW ('S', 0x42, struct sndrv_seq_queue_tempo) ++#define SNDRV_SEQ_IOCTL_GET_QUEUE_OWNER _IOWR('S', 0x43, struct sndrv_seq_queue_owner) ++#define SNDRV_SEQ_IOCTL_SET_QUEUE_OWNER _IOW ('S', 0x44, struct sndrv_seq_queue_owner) ++#define SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER _IOWR('S', 0x45, struct sndrv_seq_queue_timer) ++#define SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER _IOW ('S', 0x46, struct sndrv_seq_queue_timer) ++#define SNDRV_SEQ_IOCTL_GET_QUEUE_SYNC _IOWR('S', 0x53, struct sndrv_seq_queue_sync) ++#define SNDRV_SEQ_IOCTL_SET_QUEUE_SYNC _IOW ('S', 0x54, struct sndrv_seq_queue_sync) ++#define SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT _IOWR('S', 0x49, struct sndrv_seq_queue_client) ++#define SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT _IOW ('S', 0x4a, struct sndrv_seq_queue_client) ++#define SNDRV_SEQ_IOCTL_GET_CLIENT_POOL _IOWR('S', 0x4b, struct sndrv_seq_client_pool) ++#define SNDRV_SEQ_IOCTL_SET_CLIENT_POOL _IOW ('S', 0x4c, struct sndrv_seq_client_pool) ++#define SNDRV_SEQ_IOCTL_REMOVE_EVENTS _IOW ('S', 0x4e, struct sndrv_seq_remove_events) ++#define SNDRV_SEQ_IOCTL_QUERY_SUBS _IOWR('S', 0x4f, struct sndrv_seq_query_subs) ++#define SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION _IOWR('S', 0x50, struct sndrv_seq_port_subscribe) ++#define SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT _IOWR('S', 0x51, struct sndrv_seq_client_info) ++#define SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT _IOWR('S', 0x52, struct sndrv_seq_port_info) ++#define SNDRV_DM_FM_IOCTL_INFO _IOR('H', 0x20, snd_dm_fm_info_t) ++#define SNDRV_DM_FM_IOCTL_RESET _IO ('H', 0x21) ++#define SNDRV_DM_FM_IOCTL_PLAY_NOTE _IOW('H', 0x22, snd_dm_fm_note_t) ++#define SNDRV_DM_FM_IOCTL_SET_VOICE _IOW('H', 0x23, snd_dm_fm_voice_t) ++#define SNDRV_DM_FM_IOCTL_SET_PARAMS _IOW('H', 0x24, snd_dm_fm_params_t) ++#define SNDRV_DM_FM_IOCTL_SET_MODE _IOW('H', 0x25, int) ++#define SNDRV_DM_FM_IOCTL_SET_CONNECTION _IOW('H', 0x26, int) ++#define SNDRV_DM_FM_OSS_IOCTL_RESET 0x20 ++#define SNDRV_DM_FM_OSS_IOCTL_PLAY_NOTE 0x21 ++#define SNDRV_DM_FM_OSS_IOCTL_SET_VOICE 0x22 ++#define SNDRV_DM_FM_OSS_IOCTL_SET_PARAMS 0x23 ++#define SNDRV_DM_FM_OSS_IOCTL_SET_MODE 0x24 ++#define SNDRV_DM_FM_OSS_IOCTL_SET_OPL 0x25 ++#define SNDRV_HWDEP_IOCTL_PVERSION _IOR ('H', 0x00, int) ++#define SNDRV_HWDEP_IOCTL_INFO _IOR ('H', 0x01, struct sndrv_hwdep_info) ++#define SNDRV_HWDEP_IOCTL_DSP_STATUS _IOR('H', 0x02, struct sndrv_hwdep_dsp_status) ++#define SNDRV_HWDEP_IOCTL_DSP_LOAD _IOW('H', 0x03, struct sndrv_hwdep_dsp_image) ++#define SNDRV_PCM_IOCTL_PVERSION _IOR('A', 0x00, int) ++#define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct sndrv_pcm_info) ++#define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int) ++#define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct sndrv_pcm_hw_params) ++#define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct sndrv_pcm_hw_params) ++#define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12) ++#define SNDRV_PCM_IOCTL_SW_PARAMS _IOWR('A', 0x13, struct sndrv_pcm_sw_params) ++#define SNDRV_PCM_IOCTL_STATUS _IOR('A', 0x20, struct sndrv_pcm_status) ++#define SNDRV_PCM_IOCTL_DELAY _IOR('A', 0x21, sndrv_pcm_sframes_t) ++#define SNDRV_PCM_IOCTL_HWSYNC _IO('A', 0x22) ++#define SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct sndrv_pcm_sync_ptr) ++#define SNDRV_PCM_IOCTL_CHANNEL_INFO _IOR('A', 0x32, struct sndrv_pcm_channel_info) ++#define SNDRV_PCM_IOCTL_PREPARE _IO('A', 0x40) ++#define SNDRV_PCM_IOCTL_RESET _IO('A', 0x41) ++#define SNDRV_PCM_IOCTL_START _IO('A', 0x42) ++#define SNDRV_PCM_IOCTL_DROP _IO('A', 0x43) ++#define SNDRV_PCM_IOCTL_DRAIN _IO('A', 0x44) ++#define SNDRV_PCM_IOCTL_PAUSE _IOW('A', 0x45, int) ++#define SNDRV_PCM_IOCTL_REWIND _IOW('A', 0x46, sndrv_pcm_uframes_t) ++#define SNDRV_PCM_IOCTL_RESUME _IO('A', 0x47) ++#define SNDRV_PCM_IOCTL_XRUN _IO('A', 0x48) ++#define SNDRV_PCM_IOCTL_FORWARD _IOW('A', 0x49, sndrv_pcm_uframes_t) ++#define SNDRV_PCM_IOCTL_WRITEI_FRAMES _IOW('A', 0x50, struct sndrv_xferi) ++#define SNDRV_PCM_IOCTL_READI_FRAMES _IOR('A', 0x51, struct sndrv_xferi) ++#define SNDRV_PCM_IOCTL_WRITEN_FRAMES _IOW('A', 0x52, struct sndrv_xfern) ++#define SNDRV_PCM_IOCTL_READN_FRAMES _IOR('A', 0x53, struct sndrv_xfern) ++#define SNDRV_PCM_IOCTL_LINK _IOW('A', 0x60, int) ++#define SNDRV_PCM_IOCTL_UNLINK _IO('A', 0x61) ++#define SNDRV_RAWMIDI_IOCTL_PVERSION _IOR('W', 0x00, int) ++#define SNDRV_RAWMIDI_IOCTL_INFO _IOR('W', 0x01, struct sndrv_rawmidi_info) ++#define SNDRV_RAWMIDI_IOCTL_PARAMS _IOWR('W', 0x10, struct sndrv_rawmidi_params) ++#define SNDRV_RAWMIDI_IOCTL_STATUS _IOWR('W', 0x20, struct sndrv_rawmidi_status) ++#define SNDRV_RAWMIDI_IOCTL_DROP _IOW('W', 0x30, int) ++#define SNDRV_RAWMIDI_IOCTL_DRAIN _IOW('W', 0x31, int) ++#define SNDRV_TIMER_IOCTL_PVERSION _IOR('T', 0x00, int) ++#define SNDRV_TIMER_IOCTL_NEXT_DEVICE _IOWR('T', 0x01, struct sndrv_timer_id) ++#define SNDRV_TIMER_IOCTL_TREAD _IOW('T', 0x02, int) ++#define SNDRV_TIMER_IOCTL_GINFO _IOWR('T', 0x03, struct sndrv_timer_ginfo) ++#define SNDRV_TIMER_IOCTL_GPARAMS _IOW('T', 0x04, struct sndrv_timer_gparams) ++#define SNDRV_TIMER_IOCTL_GSTATUS _IOWR('T', 0x05, struct sndrv_timer_gstatus) ++#define SNDRV_TIMER_IOCTL_SELECT _IOW('T', 0x10, struct sndrv_timer_select) ++#define SNDRV_TIMER_IOCTL_INFO _IOR('T', 0x11, struct sndrv_timer_info) ++#define SNDRV_TIMER_IOCTL_PARAMS _IOW('T', 0x12, struct sndrv_timer_params) ++#define SNDRV_TIMER_IOCTL_STATUS _IOR('T', 0x14, struct sndrv_timer_status) ++#define SNDRV_TIMER_IOCTL_START _IO('T', 0xa0) ++#define SNDRV_TIMER_IOCTL_STOP _IO('T', 0xa1) ++#define SNDRV_TIMER_IOCTL_CONTINUE _IO('T', 0xa2) ++#define SNDRV_TIMER_IOCTL_PAUSE _IO('T', 0xa3) ++#define SNDRV_CTL_IOCTL_PVERSION _IOR('U', 0x00, int) ++#define SNDRV_CTL_IOCTL_CARD_INFO _IOR('U', 0x01, struct sndrv_ctl_card_info) ++#define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct sndrv_ctl_elem_list) ++#define SNDRV_CTL_IOCTL_ELEM_INFO _IOWR('U', 0x11, struct sndrv_ctl_elem_info) ++#define SNDRV_CTL_IOCTL_ELEM_READ _IOWR('U', 0x12, struct sndrv_ctl_elem_value) ++#define SNDRV_CTL_IOCTL_ELEM_WRITE _IOWR('U', 0x13, struct sndrv_ctl_elem_value) ++#define SNDRV_CTL_IOCTL_ELEM_LOCK _IOW('U', 0x14, struct sndrv_ctl_elem_id) ++#define SNDRV_CTL_IOCTL_ELEM_UNLOCK _IOW('U', 0x15, struct sndrv_ctl_elem_id) ++#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int) ++#define SNDRV_CTL_IOCTL_ELEM_ADD _IOWR('U', 0x17, struct sndrv_ctl_elem_info) ++#define SNDRV_CTL_IOCTL_ELEM_REPLACE _IOWR('U', 0x18, struct sndrv_ctl_elem_info) ++#define SNDRV_CTL_IOCTL_ELEM_REMOVE _IOWR('U', 0x19, struct sndrv_ctl_elem_id) ++#define SNDRV_CTL_IOCTL_TLV_READ _IOWR('U', 0x1a, struct sndrv_ctl_tlv) ++#define SNDRV_CTL_IOCTL_TLV_WRITE _IOWR('U', 0x1b, struct sndrv_ctl_tlv) ++#define SNDRV_CTL_IOCTL_TLV_COMMAND _IOWR('U', 0x1c, struct sndrv_ctl_tlv) ++#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int) ++#define SNDRV_CTL_IOCTL_HWDEP_INFO _IOR('U', 0x21, struct sndrv_hwdep_info) ++#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE _IOR('U', 0x30, int) ++#define SNDRV_CTL_IOCTL_PCM_INFO _IOWR('U', 0x31, struct sndrv_pcm_info) ++#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int) ++#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int) ++#define SNDRV_CTL_IOCTL_RAWMIDI_INFO _IOWR('U', 0x41, struct sndrv_rawmidi_info) ++#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int) ++#define SNDRV_CTL_IOCTL_POWER _IOWR('U', 0xd0, int) ++#define SNDRV_CTL_IOCTL_POWER_STATE _IOR('U', 0xd1, int) ++#define SNDRV_IOCTL_READV _IOW('K', 0x00, struct sndrv_xferv) ++#define SNDRV_IOCTL_WRITEV _IOW('K', 0x01, struct sndrv_xferv) ++#define SNDRV_EMU10K1_IOCTL_INFO _IOR ('H', 0x10, emu10k1_fx8010_info_t) ++#define SNDRV_EMU10K1_IOCTL_CODE_POKE _IOW ('H', 0x11, emu10k1_fx8010_code_t) ++#define SNDRV_EMU10K1_IOCTL_CODE_PEEK _IOWR('H', 0x12, emu10k1_fx8010_code_t) ++#define SNDRV_EMU10K1_IOCTL_TRAM_SETUP _IOW ('H', 0x20, int) ++#define SNDRV_EMU10K1_IOCTL_TRAM_POKE _IOW ('H', 0x21, emu10k1_fx8010_tram_t) ++#define SNDRV_EMU10K1_IOCTL_TRAM_PEEK _IOWR('H', 0x22, emu10k1_fx8010_tram_t) ++#define SNDRV_EMU10K1_IOCTL_PCM_POKE _IOW ('H', 0x30, emu10k1_fx8010_pcm_t) ++#define SNDRV_EMU10K1_IOCTL_PCM_PEEK _IOWR('H', 0x31, emu10k1_fx8010_pcm_t) ++#define SNDRV_EMU10K1_IOCTL_PVERSION _IOR ('H', 0x40, int) ++#define SNDRV_EMU10K1_IOCTL_STOP _IO ('H', 0x80) ++#define SNDRV_EMU10K1_IOCTL_CONTINUE _IO ('H', 0x81) ++#define SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER _IO ('H', 0x82) ++#define SNDRV_EMU10K1_IOCTL_SINGLE_STEP _IOW ('H', 0x83, int) ++#define SNDRV_EMU10K1_IOCTL_DBG_READ _IOR ('H', 0x84, int) ++#define SNDRV_HDSP_IOCTL_GET_PEAK_RMS _IOR('H', 0x40, hdsp_peak_rms_t) ++#define SNDRV_HDSP_IOCTL_GET_CONFIG_INFO _IOR('H', 0x41, hdsp_config_info_t) ++#define SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE _IOW('H', 0x42, hdsp_firmware_t) ++#define SNDRV_HDSP_IOCTL_GET_VERSION _IOR('H', 0x43, hdsp_version_t) ++#define SNDRV_HDSP_IOCTL_GET_MIXER _IOR('H', 0x44, hdsp_mixer_t) ++#define SNDRV_HDSP_IOCTL_GET_9632_AEB _IOR('H', 0x45, hdsp_9632_aeb_t) ++#define SNDRV_SB_CSP_IOCTL_INFO _IOR('H', 0x10, snd_sb_csp_info_t) ++#define SNDRV_SB_CSP_IOCTL_LOAD_CODE _IOW('H', 0x11, snd_sb_csp_microcode_t) ++#define SNDRV_SB_CSP_IOCTL_UNLOAD_CODE _IO('H', 0x12) ++#define SNDRV_SB_CSP_IOCTL_START _IOW('H', 0x13, snd_sb_csp_start_t) ++#define SNDRV_SB_CSP_IOCTL_STOP _IO('H', 0x14) ++#define SNDRV_SB_CSP_IOCTL_PAUSE _IO('H', 0x15) ++#define SNDRV_SB_CSP_IOCTL_RESTART _IO('H', 0x16) ++#define SND_SSCAPE_LOAD_BOOTB _IOWR('P', 100, struct sscape_bootblock) ++#define SND_SSCAPE_LOAD_MCODE _IOW ('P', 101, struct sscape_microcode) ++ ++ ++#define TARGET_SNDRV_SEQ_IOCTL_PVERSION TARGET_IOR ('S', 0x00, int) ++#define TARGET_SNDRV_SEQ_IOCTL_CLIENT_ID TARGET_IOR ('S', 0x01, int) ++#define TARGET_SNDRV_SEQ_IOCTL_SYSTEM_INFO TARGET_IOWRU('S', 0x02) ++#define TARGET_SNDRV_SEQ_IOCTL_RUNNING_MODE TARGET_IOWRU('S', 0x03) ++#define TARGET_SNDRV_SEQ_IOCTL_GET_CLIENT_INFO TARGET_IOWRU('S', 0x10) ++#define TARGET_SNDRV_SEQ_IOCTL_SET_CLIENT_INFO TARGET_IOWU ('S', 0x11) ++#define TARGET_SNDRV_SEQ_IOCTL_CREATE_PORT TARGET_IOWRU('S', 0x20) ++#define TARGET_SNDRV_SEQ_IOCTL_DELETE_PORT TARGET_IOWU ('S', 0x21) ++#define TARGET_SNDRV_SEQ_IOCTL_GET_PORT_INFO TARGET_IOWRU('S', 0x22) ++#define TARGET_SNDRV_SEQ_IOCTL_SET_PORT_INFO TARGET_IOWU ('S', 0x23) ++#define TARGET_SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT TARGET_IOWU ('S', 0x30) ++#define TARGET_SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT TARGET_IOWU ('S', 0x31) ++#define TARGET_SNDRV_SEQ_IOCTL_CREATE_QUEUE TARGET_IOWRU('S', 0x32) ++#define TARGET_SNDRV_SEQ_IOCTL_DELETE_QUEUE TARGET_IOWU ('S', 0x33) ++#define TARGET_SNDRV_SEQ_IOCTL_GET_QUEUE_INFO TARGET_IOWRU('S', 0x34) ++#define TARGET_SNDRV_SEQ_IOCTL_SET_QUEUE_INFO TARGET_IOWRU('S', 0x35) ++#define TARGET_SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE TARGET_IOWRU('S', 0x36) ++#define TARGET_SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS TARGET_IOWRU('S', 0x40) ++#define TARGET_SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO TARGET_IOWRU('S', 0x41) ++#define TARGET_SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO TARGET_IOWU ('S', 0x42) ++#define TARGET_SNDRV_SEQ_IOCTL_GET_QUEUE_OWNER TARGET_IOWRU('S', 0x43) ++#define TARGET_SNDRV_SEQ_IOCTL_SET_QUEUE_OWNER TARGET_IOWU ('S', 0x44) ++#define TARGET_SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER TARGET_IOWRU('S', 0x45) ++#define TARGET_SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER TARGET_IOWU ('S', 0x46) ++#define TARGET_SNDRV_SEQ_IOCTL_GET_QUEUE_SYNC TARGET_IOWRU('S', 0x53) ++#define TARGET_SNDRV_SEQ_IOCTL_SET_QUEUE_SYNC TARGET_IOWU ('S', 0x54) ++#define TARGET_SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT TARGET_IOWRU('S', 0x49) ++#define TARGET_SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT TARGET_IOWU ('S', 0x4a) ++#define TARGET_SNDRV_SEQ_IOCTL_GET_CLIENT_POOL TARGET_IOWRU('S', 0x4b) ++#define TARGET_SNDRV_SEQ_IOCTL_SET_CLIENT_POOL TARGET_IOWU ('S', 0x4c) ++#define TARGET_SNDRV_SEQ_IOCTL_REMOVE_EVENTS TARGET_IOWU ('S', 0x4e) ++#define TARGET_SNDRV_SEQ_IOCTL_QUERY_SUBS TARGET_IOWRU('S', 0x4f) ++#define TARGET_SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION TARGET_IOWRU('S', 0x50) ++#define TARGET_SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT TARGET_IOWRU('S', 0x51) ++#define TARGET_SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT TARGET_IOWRU('S', 0x52) ++#define TARGET_SNDRV_DM_FM_IOCTL_INFO TARGET_IORU('H', 0x20) ++#define TARGET_SNDRV_DM_FM_IOCTL_RESET TARGET_IO ('H', 0x21) ++#define TARGET_SNDRV_DM_FM_IOCTL_PLAY_NOTE TARGET_IOWU('H', 0x22) ++#define TARGET_SNDRV_DM_FM_IOCTL_SET_VOICE TARGET_IOWU('H', 0x23) ++#define TARGET_SNDRV_DM_FM_IOCTL_SET_PARAMS TARGET_IOWU('H', 0x24) ++#define TARGET_SNDRV_DM_FM_IOCTL_SET_MODE TARGET_IOW('H', 0x25, int) ++#define TARGET_SNDRV_DM_FM_IOCTL_SET_CONNECTION TARGET_IOW('H', 0x26, int) ++#define TARGET_SNDRV_DM_FM_OSS_IOCTL_RESET 0x20 ++#define TARGET_SNDRV_DM_FM_OSS_IOCTL_PLAY_NOTE 0x21 ++#define TARGET_SNDRV_DM_FM_OSS_IOCTL_SET_VOICE 0x22 ++#define TARGET_SNDRV_DM_FM_OSS_IOCTL_SET_PARAMS 0x23 ++#define TARGET_SNDRV_DM_FM_OSS_IOCTL_SET_MODE 0x24 ++#define TARGET_SNDRV_DM_FM_OSS_IOCTL_SET_OPL 0x25 ++#define TARGET_SNDRV_HWDEP_IOCTL_PVERSION TARGET_IOR ('H', 0x00, int) ++#define TARGET_SNDRV_HWDEP_IOCTL_INFO TARGET_IORU ('H', 0x01) ++#define TARGET_SNDRV_HWDEP_IOCTL_DSP_STATUS TARGET_IORU('H', 0x02) ++#define TARGET_SNDRV_HWDEP_IOCTL_DSP_LOAD TARGET_IOWU('H', 0x03) ++#define TARGET_SNDRV_PCM_IOCTL_PVERSION TARGET_IOR('A', 0x00, int) ++#define TARGET_SNDRV_PCM_IOCTL_INFO TARGET_IORU('A', 0x01) ++#define TARGET_SNDRV_PCM_IOCTL_TSTAMP TARGET_IOW('A', 0x02, int) ++#define TARGET_SNDRV_PCM_IOCTL_HW_REFINE TARGET_IOWRU('A', 0x10) ++#define TARGET_SNDRV_PCM_IOCTL_HW_PARAMS TARGET_IOWRU('A', 0x11) ++#define TARGET_SNDRV_PCM_IOCTL_HW_FREE TARGET_IO('A', 0x12) ++#define TARGET_SNDRV_PCM_IOCTL_SW_PARAMS TARGET_IOWRU('A', 0x13) ++#define TARGET_SNDRV_PCM_IOCTL_STATUS TARGET_IORU('A', 0x20) ++#define TARGET_SNDRV_PCM_IOCTL_DELAY TARGET_IORU('A', 0x21) ++#define TARGET_SNDRV_PCM_IOCTL_HWSYNC TARGET_IO('A', 0x22) ++#define TARGET_SNDRV_PCM_IOCTL_SYNC_PTR TARGET_IOWRU('A', 0x23) ++#define TARGET_SNDRV_PCM_IOCTL_CHANNEL_INFO TARGET_IORU('A', 0x32) ++#define TARGET_SNDRV_PCM_IOCTL_PREPARE TARGET_IO('A', 0x40) ++#define TARGET_SNDRV_PCM_IOCTL_RESET TARGET_IO('A', 0x41) ++#define TARGET_SNDRV_PCM_IOCTL_START TARGET_IO('A', 0x42) ++#define TARGET_SNDRV_PCM_IOCTL_DROP TARGET_IO('A', 0x43) ++#define TARGET_SNDRV_PCM_IOCTL_DRAIN TARGET_IO('A', 0x44) ++#define TARGET_SNDRV_PCM_IOCTL_PAUSE TARGET_IOW('A', 0x45, int) ++#define TARGET_SNDRV_PCM_IOCTL_REWIND TARGET_IOWU('A', 0x46) ++#define TARGET_SNDRV_PCM_IOCTL_RESUME TARGET_IO('A', 0x47) ++#define TARGET_SNDRV_PCM_IOCTL_XRUN TARGET_IO('A', 0x48) ++#define TARGET_SNDRV_PCM_IOCTL_FORWARD TARGET_IOWU('A', 0x49) ++#define TARGET_SNDRV_PCM_IOCTL_WRITEI_FRAMES TARGET_IOWU('A', 0x50) ++#define TARGET_SNDRV_PCM_IOCTL_READI_FRAMES TARGET_IORU('A', 0x51) ++#define TARGET_SNDRV_PCM_IOCTL_WRITEN_FRAMES TARGET_IOWU('A', 0x52) ++#define TARGET_SNDRV_PCM_IOCTL_READN_FRAMES TARGET_IORU('A', 0x53) ++#define TARGET_SNDRV_PCM_IOCTL_LINK TARGET_IOW('A', 0x60, int) ++#define TARGET_SNDRV_PCM_IOCTL_UNLINK TARGET_IO('A', 0x61) ++#define TARGET_SNDRV_RAWMIDI_IOCTL_PVERSION TARGET_IOR('W', 0x00, int) ++#define TARGET_SNDRV_RAWMIDI_IOCTL_INFO TARGET_IORU('W', 0x01) ++#define TARGET_SNDRV_RAWMIDI_IOCTL_PARAMS TARGET_IOWRU('W', 0x10) ++#define TARGET_SNDRV_RAWMIDI_IOCTL_STATUS TARGET_IOWRU('W', 0x20) ++#define TARGET_SNDRV_RAWMIDI_IOCTL_DROP TARGET_IOW('W', 0x30, int) ++#define TARGET_SNDRV_RAWMIDI_IOCTL_DRAIN TARGET_IOW('W', 0x31, int) ++#define TARGET_SNDRV_TIMER_IOCTL_PVERSION TARGET_IOR('T', 0x00, int) ++#define TARGET_SNDRV_TIMER_IOCTL_NEXT_DEVICE TARGET_IOWRU('T', 0x01) ++#define TARGET_SNDRV_TIMER_IOCTL_TREAD TARGET_IOW('T', 0x02, int) ++#define TARGET_SNDRV_TIMER_IOCTL_GINFO TARGET_IOWRU('T', 0x03) ++#define TARGET_SNDRV_TIMER_IOCTL_GPARAMS TARGET_IOWU('T', 0x04) ++#define TARGET_SNDRV_TIMER_IOCTL_GSTATUS TARGET_IOWRU('T', 0x05) ++#define TARGET_SNDRV_TIMER_IOCTL_SELECT TARGET_IOWU('T', 0x10) ++#define TARGET_SNDRV_TIMER_IOCTL_INFO TARGET_IORU('T', 0x11) ++#define TARGET_SNDRV_TIMER_IOCTL_PARAMS TARGET_IOWU('T', 0x12) ++#define TARGET_SNDRV_TIMER_IOCTL_STATUS TARGET_IORU('T', 0x14) ++#define TARGET_SNDRV_TIMER_IOCTL_START TARGET_IO('T', 0xa0) ++#define TARGET_SNDRV_TIMER_IOCTL_STOP TARGET_IO('T', 0xa1) ++#define TARGET_SNDRV_TIMER_IOCTL_CONTINUE TARGET_IO('T', 0xa2) ++#define TARGET_SNDRV_TIMER_IOCTL_PAUSE TARGET_IO('T', 0xa3) ++#define TARGET_SNDRV_CTL_IOCTL_PVERSION TARGET_IOR('U', 0x00, int) ++#define TARGET_SNDRV_CTL_IOCTL_CARD_INFO TARGET_IORU('U', 0x01) ++#define TARGET_SNDRV_CTL_IOCTL_ELEM_LIST TARGET_IOWRU('U', 0x10) ++#define TARGET_SNDRV_CTL_IOCTL_ELEM_INFO TARGET_IOWRU('U', 0x11) ++#define TARGET_SNDRV_CTL_IOCTL_ELEM_READ TARGET_IOWRU('U', 0x12) ++#define TARGET_SNDRV_CTL_IOCTL_ELEM_WRITE TARGET_IOWRU('U', 0x13) ++#define TARGET_SNDRV_CTL_IOCTL_ELEM_LOCK TARGET_IOWU('U', 0x14) ++#define TARGET_SNDRV_CTL_IOCTL_ELEM_UNLOCK TARGET_IOWU('U', 0x15) ++#define TARGET_SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS TARGET_IOWR('U', 0x16, int) ++#define TARGET_SNDRV_CTL_IOCTL_ELEM_ADD TARGET_IOWRU('U', 0x17) ++#define TARGET_SNDRV_CTL_IOCTL_ELEM_REPLACE TARGET_IOWRU('U', 0x18) ++#define TARGET_SNDRV_CTL_IOCTL_ELEM_REMOVE TARGET_IOWRU('U', 0x19) ++#define TARGET_SNDRV_CTL_IOCTL_TLV_READ TARGET_IOWRU('U', 0x1a) ++#define TARGET_SNDRV_CTL_IOCTL_TLV_WRITE TARGET_IOWRU('U', 0x1b) ++#define TARGET_SNDRV_CTL_IOCTL_TLV_COMMAND TARGET_IOWRU('U', 0x1c) ++#define TARGET_SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE TARGET_IOWR('U', 0x20, int) ++#define TARGET_SNDRV_CTL_IOCTL_HWDEP_INFO TARGET_IORU('U', 0x21) ++#define TARGET_SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE TARGET_IOR('U', 0x30, int) ++#define TARGET_SNDRV_CTL_IOCTL_PCM_INFO TARGET_IOWRU('U', 0x31) ++#define TARGET_SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE TARGET_IOW('U', 0x32, int) ++#define TARGET_SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE TARGET_IOWR('U', 0x40, int) ++#define TARGET_SNDRV_CTL_IOCTL_RAWMIDI_INFO TARGET_IOWRU('U', 0x41) ++#define TARGET_SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE TARGET_IOW('U', 0x42, int) ++#define TARGET_SNDRV_CTL_IOCTL_POWER TARGET_IOWR('U', 0xd0, int) ++#define TARGET_SNDRV_CTL_IOCTL_POWER_STATE TARGET_IOR('U', 0xd1, int) ++#define TARGET_SNDRV_IOCTL_READV TARGET_IOWU('K', 0x00) ++#define TARGET_SNDRV_IOCTL_WRITEV TARGET_IOWU('K', 0x01) ++#define TARGET_SNDRV_EMU10K1_IOCTL_INFO TARGET_IORU ('H', 0x10) ++#define TARGET_SNDRV_EMU10K1_IOCTL_CODE_POKE TARGET_IOWU ('H', 0x11) ++#define TARGET_SNDRV_EMU10K1_IOCTL_CODE_PEEK TARGET_IOWRU('H', 0x12) ++#define TARGET_SNDRV_EMU10K1_IOCTL_TRAM_SETUP TARGET_IOW ('H', 0x20, int) ++#define TARGET_SNDRV_EMU10K1_IOCTL_TRAM_POKE TARGET_IOWU ('H', 0x21) ++#define TARGET_SNDRV_EMU10K1_IOCTL_TRAM_PEEK TARGET_IOWRU('H', 0x22) ++#define TARGET_SNDRV_EMU10K1_IOCTL_PCM_POKE TARGET_IOWU ('H', 0x30) ++#define TARGET_SNDRV_EMU10K1_IOCTL_PCM_PEEK TARGET_IOWRU('H', 0x31) ++#define TARGET_SNDRV_EMU10K1_IOCTL_PVERSION TARGET_IOR ('H', 0x40, int) ++#define TARGET_SNDRV_EMU10K1_IOCTL_STOP TARGET_IO ('H', 0x80) ++#define TARGET_SNDRV_EMU10K1_IOCTL_CONTINUE TARGET_IO ('H', 0x81) ++#define TARGET_SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER TARGET_IO ('H', 0x82) ++#define TARGET_SNDRV_EMU10K1_IOCTL_SINGLE_STEP TARGET_IOW ('H', 0x83, int) ++#define TARGET_SNDRV_EMU10K1_IOCTL_DBG_READ TARGET_IOR ('H', 0x84, int) ++#define TARGET_SNDRV_HDSP_IOCTL_GET_PEAK_RMS TARGET_IORU('H', 0x40) ++#define TARGET_SNDRV_HDSP_IOCTL_GET_CONFIG_INFO TARGET_IORU('H', 0x41) ++#define TARGET_SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE TARGET_IOWU('H', 0x42) ++#define TARGET_SNDRV_HDSP_IOCTL_GET_VERSION TARGET_IORU('H', 0x43) ++#define TARGET_SNDRV_HDSP_IOCTL_GET_MIXER TARGET_IORU('H', 0x44) ++#define TARGET_SNDRV_HDSP_IOCTL_GET_9632_AEB TARGET_IORU('H', 0x45) ++#define TARGET_SNDRV_SB_CSP_IOCTL_INFO TARGET_IORU('H', 0x10) ++#define TARGET_SNDRV_SB_CSP_IOCTL_LOAD_CODE TARGET_IOWU('H', 0x11) ++#define TARGET_SNDRV_SB_CSP_IOCTL_UNLOAD_CODE TARGET_IO('H', 0x12) ++#define TARGET_SNDRV_SB_CSP_IOCTL_START TARGET_IOWU('H', 0x13) ++#define TARGET_SNDRV_SB_CSP_IOCTL_STOP TARGET_IO('H', 0x14) ++#define TARGET_SNDRV_SB_CSP_IOCTL_PAUSE TARGET_IO('H', 0x15) ++#define TARGET_SNDRV_SB_CSP_IOCTL_RESTART TARGET_IO('H', 0x16) ++#define TARGET_SND_SSCAPE_LOAD_BOOTB TARGET_IOWRU('P', 100) ++#define TARGET_SND_SSCAPE_LOAD_MCODE TARGET_IOWU ('P', 101) ++ ++IOCTL( SNDRV_SEQ_IOCTL_PVERSION , IOC_R, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_SEQ_IOCTL_CLIENT_ID , IOC_R, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_SEQ_IOCTL_SYSTEM_INFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_system_info)) ) ++IOCTL( SNDRV_SEQ_IOCTL_RUNNING_MODE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_running_info)) ) ++IOCTL( SNDRV_SEQ_IOCTL_GET_CLIENT_INFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_client_info)) ) ++IOCTL( SNDRV_SEQ_IOCTL_SET_CLIENT_INFO , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_client_info)) ) ++IOCTL( SNDRV_SEQ_IOCTL_CREATE_PORT , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_port_info)) ) ++IOCTL( SNDRV_SEQ_IOCTL_DELETE_PORT , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_port_info)) ) ++IOCTL( SNDRV_SEQ_IOCTL_GET_PORT_INFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_port_info)) ) ++IOCTL( SNDRV_SEQ_IOCTL_SET_PORT_INFO , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_port_info)) ) ++IOCTL( SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_port_subscribe)) ) ++IOCTL( SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_port_subscribe)) ) ++IOCTL( SNDRV_SEQ_IOCTL_CREATE_QUEUE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_info)) ) ++IOCTL( SNDRV_SEQ_IOCTL_DELETE_QUEUE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_info)) ) ++IOCTL( SNDRV_SEQ_IOCTL_GET_QUEUE_INFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_info)) ) ++IOCTL( SNDRV_SEQ_IOCTL_SET_QUEUE_INFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_info)) ) ++IOCTL( SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_info)) ) ++IOCTL( SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_status)) ) ++IOCTL( SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_tempo)) ) ++IOCTL( SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_tempo)) ) ++//IOCTL( SNDRV_SEQ_IOCTL_GET_QUEUE_OWNER , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_owner)) ) ++//IOCTL( SNDRV_SEQ_IOCTL_SET_QUEUE_OWNER , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_owner)) ) ++IOCTL( SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_timer)) ) ++IOCTL( SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_timer)) ) ++//IOCTL( SNDRV_SEQ_IOCTL_GET_QUEUE_SYNC , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_sync)) ) ++//IOCTL( SNDRV_SEQ_IOCTL_SET_QUEUE_SYNC , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_sync)) ) ++IOCTL( SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_client)) ) ++IOCTL( SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_client)) ) ++IOCTL( SNDRV_SEQ_IOCTL_GET_CLIENT_POOL , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_client_pool)) ) ++IOCTL( SNDRV_SEQ_IOCTL_SET_CLIENT_POOL , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_client_pool)) ) ++IOCTL( SNDRV_SEQ_IOCTL_REMOVE_EVENTS , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_remove_events)) ) ++IOCTL( SNDRV_SEQ_IOCTL_QUERY_SUBS , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_query_subs)) ) ++IOCTL( SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_port_subscribe)) ) ++IOCTL( SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_client_info)) ) ++IOCTL( SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_port_info)) ) ++IOCTL( SNDRV_DM_FM_IOCTL_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_snd_dm_fm_info)) ) ++IOCTL( SNDRV_DM_FM_IOCTL_RESET , 0, TYPE_NULL ) ++IOCTL( SNDRV_DM_FM_IOCTL_PLAY_NOTE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_snd_dm_fm_note)) ) ++IOCTL( SNDRV_DM_FM_IOCTL_SET_VOICE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_snd_dm_fm_voice)) ) ++IOCTL( SNDRV_DM_FM_IOCTL_SET_PARAMS , IOC_W, MK_PTR(MK_STRUCT(STRUCT_snd_dm_fm_params)) ) ++IOCTL( SNDRV_DM_FM_IOCTL_SET_MODE , IOC_W, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_DM_FM_IOCTL_SET_CONNECTION , IOC_W, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_HWDEP_IOCTL_PVERSION , IOC_R, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_HWDEP_IOCTL_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_hwdep_info)) ) ++IOCTL( SNDRV_HWDEP_IOCTL_DSP_STATUS , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_hwdep_dsp_status)) ) ++IOCTL( SNDRV_HWDEP_IOCTL_DSP_LOAD , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_hwdep_dsp_image)) ) ++IOCTL( SNDRV_PCM_IOCTL_PVERSION , IOC_R, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_PCM_IOCTL_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_info)) ) ++IOCTL( SNDRV_PCM_IOCTL_TSTAMP , IOC_W, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_PCM_IOCTL_HW_REFINE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_hw_params)) ) ++IOCTL( SNDRV_PCM_IOCTL_HW_PARAMS , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_hw_params)) ) ++IOCTL( SNDRV_PCM_IOCTL_HW_FREE , 0, TYPE_NULL ) ++IOCTL( SNDRV_PCM_IOCTL_SW_PARAMS , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_sw_params)) ) ++IOCTL( SNDRV_PCM_IOCTL_STATUS , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_status)) ) ++IOCTL( SNDRV_PCM_IOCTL_DELAY , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_sframes)) ) ++IOCTL( SNDRV_PCM_IOCTL_HWSYNC , 0, TYPE_NULL ) ++IOCTL( SNDRV_PCM_IOCTL_SYNC_PTR , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_sync_ptr)) ) ++IOCTL( SNDRV_PCM_IOCTL_CHANNEL_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_channel_info)) ) ++IOCTL( SNDRV_PCM_IOCTL_PREPARE , 0, TYPE_NULL ) ++IOCTL( SNDRV_PCM_IOCTL_RESET , 0, TYPE_NULL ) ++IOCTL( SNDRV_PCM_IOCTL_START , 0, TYPE_NULL ) ++IOCTL( SNDRV_PCM_IOCTL_DROP , 0, TYPE_NULL ) ++IOCTL( SNDRV_PCM_IOCTL_DRAIN , 0, TYPE_NULL ) ++IOCTL( SNDRV_PCM_IOCTL_PAUSE , IOC_W, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_PCM_IOCTL_REWIND , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_uframes)) ) ++IOCTL( SNDRV_PCM_IOCTL_RESUME , 0, TYPE_NULL ) ++IOCTL( SNDRV_PCM_IOCTL_XRUN , 0, TYPE_NULL ) ++IOCTL( SNDRV_PCM_IOCTL_FORWARD , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_uframes)) ) ++IOCTL( SNDRV_PCM_IOCTL_WRITEI_FRAMES , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_xferi)) ) ++IOCTL( SNDRV_PCM_IOCTL_READI_FRAMES , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_xferi)) ) ++IOCTL( SNDRV_PCM_IOCTL_WRITEN_FRAMES , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_xfern)) ) ++IOCTL( SNDRV_PCM_IOCTL_READN_FRAMES , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_xfern)) ) ++IOCTL( SNDRV_PCM_IOCTL_LINK , IOC_W, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_PCM_IOCTL_UNLINK , 0, TYPE_NULL ) ++IOCTL( SNDRV_RAWMIDI_IOCTL_PVERSION , IOC_R, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_RAWMIDI_IOCTL_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_rawmidi_info)) ) ++IOCTL( SNDRV_RAWMIDI_IOCTL_PARAMS , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_rawmidi_params)) ) ++IOCTL( SNDRV_RAWMIDI_IOCTL_STATUS , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_rawmidi_status)) ) ++IOCTL( SNDRV_RAWMIDI_IOCTL_DROP , IOC_W, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_RAWMIDI_IOCTL_DRAIN , IOC_W, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_TIMER_IOCTL_PVERSION , IOC_R, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_TIMER_IOCTL_NEXT_DEVICE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_timer_id)) ) ++IOCTL( SNDRV_TIMER_IOCTL_TREAD , IOC_W, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_TIMER_IOCTL_GINFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_timer_ginfo)) ) ++IOCTL( SNDRV_TIMER_IOCTL_GPARAMS , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_timer_gparams)) ) ++IOCTL( SNDRV_TIMER_IOCTL_GSTATUS , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_timer_gstatus)) ) ++IOCTL( SNDRV_TIMER_IOCTL_SELECT , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_timer_select)) ) ++IOCTL( SNDRV_TIMER_IOCTL_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_timer_info)) ) ++IOCTL( SNDRV_TIMER_IOCTL_PARAMS , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_timer_params)) ) ++IOCTL( SNDRV_TIMER_IOCTL_STATUS , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_timer_status)) ) ++IOCTL( SNDRV_TIMER_IOCTL_START , 0, TYPE_NULL ) ++IOCTL( SNDRV_TIMER_IOCTL_STOP , 0, TYPE_NULL ) ++IOCTL( SNDRV_TIMER_IOCTL_CONTINUE , 0, TYPE_NULL ) ++IOCTL( SNDRV_TIMER_IOCTL_PAUSE , 0, TYPE_NULL ) ++IOCTL( SNDRV_CTL_IOCTL_PVERSION , IOC_R, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_CTL_IOCTL_CARD_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_card_info)) ) ++IOCTL( SNDRV_CTL_IOCTL_ELEM_LIST , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_list)) ) ++IOCTL( SNDRV_CTL_IOCTL_ELEM_INFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_info)) ) ++IOCTL( SNDRV_CTL_IOCTL_ELEM_READ , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_value)) ) ++IOCTL( SNDRV_CTL_IOCTL_ELEM_WRITE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_value)) ) ++IOCTL( SNDRV_CTL_IOCTL_ELEM_LOCK , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_id)) ) ++IOCTL( SNDRV_CTL_IOCTL_ELEM_UNLOCK , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_id)) ) ++IOCTL( SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS , IOC_RW, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_CTL_IOCTL_ELEM_ADD , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_info)) ) ++IOCTL( SNDRV_CTL_IOCTL_ELEM_REPLACE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_info)) ) ++IOCTL( SNDRV_CTL_IOCTL_ELEM_REMOVE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_id)) ) ++IOCTL( SNDRV_CTL_IOCTL_TLV_READ , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_tlv)) ) ++IOCTL( SNDRV_CTL_IOCTL_TLV_WRITE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_tlv)) ) ++IOCTL( SNDRV_CTL_IOCTL_TLV_COMMAND , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_tlv)) ) ++IOCTL( SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE , IOC_RW, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_CTL_IOCTL_HWDEP_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_hwdep_info)) ) ++IOCTL( SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE , IOC_R, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_CTL_IOCTL_PCM_INFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_info)) ) ++IOCTL( SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE , IOC_W, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE , IOC_RW, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_CTL_IOCTL_RAWMIDI_INFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_rawmidi_info)) ) ++IOCTL( SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE , IOC_W, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_CTL_IOCTL_POWER , IOC_RW, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_CTL_IOCTL_POWER_STATE , IOC_R, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_IOCTL_READV , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_xferv)) ) ++IOCTL( SNDRV_IOCTL_WRITEV , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_xferv)) ) ++IOCTL( SNDRV_EMU10K1_IOCTL_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_emu10k1_fx8010_info)) ) ++IOCTL( SNDRV_EMU10K1_IOCTL_CODE_POKE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_emu10k1_fx8010_code)) ) ++IOCTL( SNDRV_EMU10K1_IOCTL_CODE_PEEK , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_emu10k1_fx8010_code)) ) ++IOCTL( SNDRV_EMU10K1_IOCTL_TRAM_SETUP , IOC_W, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_EMU10K1_IOCTL_TRAM_POKE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_emu10k1_fx8010_tram)) ) ++IOCTL( SNDRV_EMU10K1_IOCTL_TRAM_PEEK , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_emu10k1_fx8010_tram)) ) ++IOCTL( SNDRV_EMU10K1_IOCTL_PCM_POKE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_emu10k1_fx8010_pcm)) ) ++IOCTL( SNDRV_EMU10K1_IOCTL_PCM_PEEK , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_emu10k1_fx8010_pcm)) ) ++IOCTL( SNDRV_EMU10K1_IOCTL_PVERSION , IOC_R, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_EMU10K1_IOCTL_STOP , 0, TYPE_NULL ) ++IOCTL( SNDRV_EMU10K1_IOCTL_CONTINUE , 0, TYPE_NULL ) ++IOCTL( SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER , 0, TYPE_NULL ) ++IOCTL( SNDRV_EMU10K1_IOCTL_SINGLE_STEP , IOC_W, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_EMU10K1_IOCTL_DBG_READ , IOC_R, MK_PTR(TYPE_INT) ) ++IOCTL( SNDRV_HDSP_IOCTL_GET_PEAK_RMS , IOC_R, MK_PTR(MK_STRUCT(STRUCT_hdsp_peak_rms)) ) ++IOCTL( SNDRV_HDSP_IOCTL_GET_CONFIG_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_hdsp_config_info)) ) ++IOCTL( SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_hdsp_firmware)) ) ++IOCTL( SNDRV_HDSP_IOCTL_GET_VERSION , IOC_R, MK_PTR(MK_STRUCT(STRUCT_hdsp_version)) ) ++IOCTL( SNDRV_HDSP_IOCTL_GET_MIXER , IOC_R, MK_PTR(MK_STRUCT(STRUCT_hdsp_mixer)) ) ++IOCTL( SNDRV_HDSP_IOCTL_GET_9632_AEB , IOC_R, MK_PTR(MK_STRUCT(STRUCT_hdsp_9632_aeb)) ) ++IOCTL( SNDRV_SB_CSP_IOCTL_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_snd_sb_csp_info)) ) ++#if _IOC_SIZEBITS > 13 ++IOCTL( SNDRV_SB_CSP_IOCTL_LOAD_CODE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_snd_sb_csp_microcode)) ) ++#endif ++IOCTL( SNDRV_SB_CSP_IOCTL_UNLOAD_CODE , 0, TYPE_NULL ) ++IOCTL( SNDRV_SB_CSP_IOCTL_START , IOC_W, MK_PTR(MK_STRUCT(STRUCT_snd_sb_csp_start)) ) ++IOCTL( SNDRV_SB_CSP_IOCTL_STOP , 0, TYPE_NULL ) ++IOCTL( SNDRV_SB_CSP_IOCTL_PAUSE , 0, TYPE_NULL ) ++IOCTL( SNDRV_SB_CSP_IOCTL_RESTART , 0, TYPE_NULL ) ++IOCTL( SND_SSCAPE_LOAD_BOOTB , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sscape_bootblock)) ) ++IOCTL( SND_SSCAPE_LOAD_MCODE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sscape_microcode)) ) +diff --git a/linux-user/ioctls_alsa_structs.h b/linux-user/ioctls_alsa_structs.h +new file mode 100644 +index 0000000..3de8614 +--- /dev/null ++++ b/linux-user/ioctls_alsa_structs.h +@@ -0,0 +1,1740 @@ ++/* ++ * Advanced Linux Sound Architecture ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ */ ++ ++#ifndef __u8 ++#define __u8 uint8_t ++#define __u16 uint16_t ++#define __u32 uint32_t ++#define __s8 int8_t ++#define __s16 int16_t ++#define __s32 int32_t ++#endif ++ ++#define SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE 0x3000 ++#define HDSP_MATRIX_MIXER_SIZE 2048 ++#define SNDRV_MASK_MAX 256 ++ ++typedef struct fm_operator { ++ unsigned char am_vib; ++ unsigned char ksl_level; ++ unsigned char attack_decay; ++ unsigned char sustain_release; ++ unsigned char wave_select; ++} fm_operator_t; ++ ++typedef struct { ++ unsigned int share_id[4]; /* share id - zero = no sharing */ ++ unsigned char type; /* instrument type */ ++ ++ fm_operator_t op[4]; ++ unsigned char feedback_connection[2]; ++ ++ unsigned char echo_delay; ++ unsigned char echo_atten; ++ unsigned char chorus_spread; ++ unsigned char trnsps; ++ unsigned char fix_dur; ++ unsigned char modes; ++ unsigned char fix_key; ++} fm_instrument_t; ++ ++typedef struct fm_xoperator { ++ __u8 am_vib; ++ __u8 ksl_level; ++ __u8 attack_decay; ++ __u8 sustain_release; ++ __u8 wave_select; ++} fm_xoperator_t; ++ ++typedef struct fm_xinstrument { ++ __u32 stype; /* structure type */ ++ ++ __u32 share_id[4]; /* share id - zero = no sharing */ ++ __u8 type; /* instrument type */ ++ ++ fm_xoperator_t op[4]; /* fm operators */ ++ __u8 feedback_connection[2]; ++ ++ __u8 echo_delay; ++ __u8 echo_atten; ++ __u8 chorus_spread; ++ __u8 trnsps; ++ __u8 fix_dur; ++ __u8 modes; ++ __u8 fix_key; ++} fm_xinstrument_t; ++ ++typedef struct gf1_wave { ++ unsigned int share_id[4]; /* share id - zero = no sharing */ ++ unsigned int format; /* wave format */ ++ ++ struct { ++ unsigned int number; /* some other ID for this instrument */ ++ unsigned int memory; /* begin of waveform in onboard memory */ ++ unsigned char *ptr; /* pointer to waveform in system memory */ ++ } address; ++ ++ unsigned int size; /* size of waveform in samples */ ++ unsigned int start; /* start offset in samples * 16 (lowest 4 bits - fraction) */ ++ unsigned int loop_start; /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */ ++ unsigned int loop_end; /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ ++ unsigned short loop_repeat; /* loop repeat - 0 = forever */ ++ ++ unsigned char flags; /* GF1 patch flags */ ++ unsigned char pad; ++ unsigned int sample_rate; /* sample rate in Hz */ ++ unsigned int low_frequency; /* low frequency range */ ++ unsigned int high_frequency; /* high frequency range */ ++ unsigned int root_frequency; /* root frequency range */ ++ signed short tune; ++ unsigned char balance; ++ unsigned char envelope_rate[6]; ++ unsigned char envelope_offset[6]; ++ unsigned char tremolo_sweep; ++ unsigned char tremolo_rate; ++ unsigned char tremolo_depth; ++ unsigned char vibrato_sweep; ++ unsigned char vibrato_rate; ++ unsigned char vibrato_depth; ++ unsigned short scale_frequency; ++ unsigned short scale_factor; /* 0-2048 or 0-2 */ ++ ++ struct gf1_wave *next; ++} gf1_wave_t; ++ ++typedef struct { ++ unsigned short exclusion; ++ unsigned short exclusion_group; /* 0 - none, 1-65535 */ ++ ++ unsigned char effect1; /* effect 1 */ ++ unsigned char effect1_depth; /* 0-127 */ ++ unsigned char effect2; /* effect 2 */ ++ unsigned char effect2_depth; /* 0-127 */ ++ ++ gf1_wave_t *wave; /* first waveform */ ++} gf1_instrument_t; ++ ++typedef struct gf1_xwave { ++ __u32 stype; /* structure type */ ++ ++ __u32 share_id[4]; /* share id - zero = no sharing */ ++ __u32 format; /* wave format */ ++ ++ __u32 size; /* size of waveform in samples */ ++ __u32 start; /* start offset in samples * 16 (lowest 4 bits - fraction) */ ++ __u32 loop_start; /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */ ++ __u32 loop_end; /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ ++ __u16 loop_repeat; /* loop repeat - 0 = forever */ ++ ++ __u8 flags; /* GF1 patch flags */ ++ __u8 pad; ++ __u32 sample_rate; /* sample rate in Hz */ ++ __u32 low_frequency; /* low frequency range */ ++ __u32 high_frequency; /* high frequency range */ ++ __u32 root_frequency; /* root frequency range */ ++ __s16 tune; ++ __u8 balance; ++ __u8 envelope_rate[6]; ++ __u8 envelope_offset[6]; ++ __u8 tremolo_sweep; ++ __u8 tremolo_rate; ++ __u8 tremolo_depth; ++ __u8 vibrato_sweep; ++ __u8 vibrato_rate; ++ __u8 vibrato_depth; ++ __u16 scale_frequency; ++ __u16 scale_factor; /* 0-2048 or 0-2 */ ++} gf1_xwave_t; ++ ++typedef struct gf1_xinstrument { ++ __u32 stype; ++ ++ __u16 exclusion; ++ __u16 exclusion_group; /* 0 - none, 1-65535 */ ++ ++ __u8 effect1; /* effect 1 */ ++ __u8 effect1_depth; /* 0-127 */ ++ __u8 effect2; /* effect 2 */ ++ __u8 effect2_depth; /* 0-127 */ ++} gf1_xinstrument_t; ++ ++typedef struct gf1_info { ++ unsigned char flags; /* supported wave flags */ ++ unsigned char pad[3]; ++ unsigned int features; /* supported features */ ++ unsigned int max8_len; /* maximum 8-bit wave length */ ++ unsigned int max16_len; /* maximum 16-bit wave length */ ++} gf1_info_t; ++ ++typedef struct iwffff_wave { ++ unsigned int share_id[4]; /* share id - zero = no sharing */ ++ unsigned int format; /* wave format */ ++ ++ struct { ++ unsigned int number; /* some other ID for this wave */ ++ unsigned int memory; /* begin of waveform in onboard memory */ ++ unsigned char *ptr; /* pointer to waveform in system memory */ ++ } address; ++ ++ unsigned int size; /* size of waveform in samples */ ++ unsigned int start; /* start offset in samples * 16 (lowest 4 bits - fraction) */ ++ unsigned int loop_start; /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */ ++ unsigned int loop_end; /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ ++ unsigned short loop_repeat; /* loop repeat - 0 = forever */ ++ unsigned int sample_ratio; /* sample ratio (44100 * 1024 / rate) */ ++ unsigned char attenuation; /* 0 - 127 (no corresponding midi controller) */ ++ unsigned char low_note; /* lower frequency range for this waveform */ ++ unsigned char high_note; /* higher frequency range for this waveform */ ++ unsigned char pad; ++ ++ struct iwffff_wave *next; ++} iwffff_wave_t; ++ ++typedef struct iwffff_lfo { ++ unsigned short freq; /* (0-2047) 0.01Hz - 21.5Hz */ ++ signed short depth; /* volume +- (0-255) 0.48675dB/step */ ++ signed short sweep; /* 0 - 950 deciseconds */ ++ unsigned char shape; /* see to IWFFFF_LFO_SHAPE_XXXX */ ++ unsigned char delay; /* 0 - 255 deciseconds */ ++} iwffff_lfo_t; ++ ++typedef struct iwffff_env_point { ++ unsigned short offset; ++ unsigned short rate; ++} iwffff_env_point_t; ++ ++typedef struct iwffff_env_record { ++ unsigned short nattack; ++ unsigned short nrelease; ++ unsigned short sustain_offset; ++ unsigned short sustain_rate; ++ unsigned short release_rate; ++ unsigned char hirange; ++ unsigned char pad; ++ struct iwffff_env_record *next; ++ /* points are stored here */ ++ /* count of points = nattack + nrelease */ ++} iwffff_env_record_t; ++ ++typedef struct iwffff_env { ++ unsigned char flags; ++ unsigned char mode; ++ unsigned char index; ++ unsigned char pad; ++ struct iwffff_env_record *record; ++} iwffff_env_t; ++ ++typedef struct iwffff_layer { ++ unsigned char flags; ++ unsigned char velocity_mode; ++ unsigned char layer_event; ++ unsigned char low_range; /* range for layer based */ ++ unsigned char high_range; /* on either velocity or frequency */ ++ unsigned char pan; /* pan offset from CC1 (0 left - 127 right) */ ++ unsigned char pan_freq_scale; /* position based on frequency (0-127) */ ++ unsigned char attenuation; /* 0-127 (no corresponding midi controller) */ ++ iwffff_lfo_t tremolo; /* tremolo effect */ ++ iwffff_lfo_t vibrato; /* vibrato effect */ ++ unsigned short freq_scale; /* 0-2048, 1024 is equal to semitone scaling */ ++ unsigned char freq_center; /* center for keyboard frequency scaling */ ++ unsigned char pad; ++ iwffff_env_t penv; /* pitch envelope */ ++ iwffff_env_t venv; /* volume envelope */ ++ ++ iwffff_wave_t *wave; ++ struct iwffff_layer *next; ++} iwffff_layer_t; ++ ++typedef struct { ++ unsigned short exclusion; ++ unsigned short layer_type; ++ unsigned short exclusion_group; /* 0 - none, 1-65535 */ ++ ++ unsigned char effect1; /* effect 1 */ ++ unsigned char effect1_depth; /* 0-127 */ ++ unsigned char effect2; /* effect 2 */ ++ unsigned char effect2_depth; /* 0-127 */ ++ ++ iwffff_layer_t *layer; /* first layer */ ++} iwffff_instrument_t; ++ ++typedef struct iwffff_xwave { ++ __u32 stype; /* structure type */ ++ ++ __u32 share_id[4]; /* share id - zero = no sharing */ ++ ++ __u32 format; /* wave format */ ++ __u32 offset; /* offset to ROM (address) */ ++ ++ __u32 size; /* size of waveform in samples */ ++ __u32 start; /* start offset in samples * 16 (lowest 4 bits - fraction) */ ++ __u32 loop_start; /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */ ++ __u32 loop_end; /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ ++ __u16 loop_repeat; /* loop repeat - 0 = forever */ ++ __u32 sample_ratio; /* sample ratio (44100 * 1024 / rate) */ ++ __u8 attenuation; /* 0 - 127 (no corresponding midi controller) */ ++ __u8 low_note; /* lower frequency range for this waveform */ ++ __u8 high_note; /* higher frequency range for this waveform */ ++ __u8 pad; ++} iwffff_xwave_t; ++ ++typedef struct iwffff_xlfo { ++ __u16 freq; /* (0-2047) 0.01Hz - 21.5Hz */ ++ __s16 depth; /* volume +- (0-255) 0.48675dB/step */ ++ __s16 sweep; /* 0 - 950 deciseconds */ ++ __u8 shape; /* see to ULTRA_IW_LFO_SHAPE_XXXX */ ++ __u8 delay; /* 0 - 255 deciseconds */ ++} iwffff_xlfo_t; ++ ++typedef struct iwffff_xenv_point { ++ __u16 offset; ++ __u16 rate; ++} iwffff_xenv_point_t; ++ ++typedef struct iwffff_xenv_record { ++ __u32 stype; ++ __u16 nattack; ++ __u16 nrelease; ++ __u16 sustain_offset; ++ __u16 sustain_rate; ++ __u16 release_rate; ++ __u8 hirange; ++ __u8 pad; ++ /* points are stored here.. */ ++ /* count of points = nattack + nrelease */ ++} iwffff_xenv_record_t; ++ ++typedef struct iwffff_xenv { ++ __u8 flags; ++ __u8 mode; ++ __u8 index; ++ __u8 pad; ++} iwffff_xenv_t; ++ ++typedef struct iwffff_xlayer { ++ __u32 stype; ++ __u8 flags; ++ __u8 velocity_mode; ++ __u8 layer_event; ++ __u8 low_range; /* range for layer based */ ++ __u8 high_range; /* on either velocity or frequency */ ++ __u8 pan; /* pan offset from CC1 (0 left - 127 right) */ ++ __u8 pan_freq_scale; /* position based on frequency (0-127) */ ++ __u8 attenuation; /* 0-127 (no corresponding midi controller) */ ++ iwffff_xlfo_t tremolo; /* tremolo effect */ ++ iwffff_xlfo_t vibrato; /* vibrato effect */ ++ __u16 freq_scale; /* 0-2048, 1024 is equal to semitone scaling */ ++ __u8 freq_center; /* center for keyboard frequency scaling */ ++ __u8 pad; ++ iwffff_xenv_t penv; /* pitch envelope */ ++ iwffff_xenv_t venv; /* volume envelope */ ++} iwffff_xlayer_t; ++ ++typedef struct iwffff_xinstrument { ++ __u32 stype; ++ ++ __u16 exclusion; ++ __u16 layer_type; ++ __u16 exclusion_group; /* 0 - none, 1-65535 */ ++ ++ __u8 effect1; /* effect 1 */ ++ __u8 effect1_depth; /* 0-127 */ ++ __u8 effect2; /* effect 2 */ ++ __u8 effect2_depth; /* 0-127 */ ++} iwffff_xinstrument_t; ++ ++typedef struct { ++ __u8 iwave[8]; ++ __u8 revision; ++ __u8 series_number; ++ __u8 series_name[16]; ++ __u8 date[10]; ++ __u16 vendor_revision_major; ++ __u16 vendor_revision_minor; ++ __u32 rom_size; ++ __u8 copyright[128]; ++ __u8 vendor_name[64]; ++ __u8 description[128]; ++} iwffff_rom_header_t; ++ ++typedef struct iwffff_info { ++ unsigned int format; /* supported format bits */ ++ unsigned int effects; /* supported effects (1 << IWFFFF_EFFECT*) */ ++ unsigned int lfos; /* LFO effects */ ++ unsigned int max8_len; /* maximum 8-bit wave length */ ++ unsigned int max16_len; /* maximum 16-bit wave length */ ++} iwffff_info_t; ++ ++typedef struct simple_instrument_info { ++ unsigned int format; /* supported format bits */ ++ unsigned int effects; /* supported effects (1 << SIMPLE_EFFECT_*) */ ++ unsigned int max8_len; /* maximum 8-bit wave length */ ++ unsigned int max16_len; /* maximum 16-bit wave length */ ++} simple_instrument_info_t; ++ ++typedef struct { ++ unsigned int share_id[4]; /* share id - zero = no sharing */ ++ unsigned int format; /* wave format */ ++ ++ struct { ++ unsigned int number; /* some other ID for this instrument */ ++ unsigned int memory; /* begin of waveform in onboard memory */ ++ unsigned char *ptr; /* pointer to waveform in system memory */ ++ } address; ++ ++ unsigned int size; /* size of waveform in samples */ ++ unsigned int start; /* start offset in samples * 16 (lowest 4 bits - fraction) */ ++ unsigned int loop_start; /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ ++ unsigned int loop_end; /* loop end offset in samples * 16 (lowest 4 bits - fraction) */ ++ unsigned short loop_repeat; /* loop repeat - 0 = forever */ ++ ++ unsigned char effect1; /* effect 1 */ ++ unsigned char effect1_depth; /* 0-127 */ ++ unsigned char effect2; /* effect 2 */ ++ unsigned char effect2_depth; /* 0-127 */ ++} simple_instrument_t; ++ ++typedef struct simple_xinstrument { ++ __u32 stype; ++ ++ __u32 share_id[4]; /* share id - zero = no sharing */ ++ __u32 format; /* wave format */ ++ ++ __u32 size; /* size of waveform in samples */ ++ __u32 start; /* start offset in samples * 16 (lowest 4 bits - fraction) */ ++ __u32 loop_start; /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */ ++ __u32 loop_end; /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ ++ __u16 loop_repeat; /* loop repeat - 0 = forever */ ++ ++ __u8 effect1; /* effect 1 */ ++ __u8 effect1_depth; /* 0-127 */ ++ __u8 effect2; /* effect 2 */ ++ __u8 effect2_depth; /* 0-127 */ ++} simple_xinstrument_t; ++ ++typedef unsigned char sndrv_seq_event_type_t; ++ ++/** event address */ ++struct sndrv_seq_addr { ++ unsigned char client; /**< Client number: 0..255, 255 = broadcast to all clients */ ++ unsigned char port; /**< Port within client: 0..255, 255 = broadcast to all ports */ ++}; ++ ++/** port connection */ ++struct sndrv_seq_connect { ++ struct sndrv_seq_addr sender; ++ struct sndrv_seq_addr dest; ++}; ++ ++struct sndrv_seq_ev_note { ++ unsigned char channel; ++ unsigned char note; ++ unsigned char velocity; ++ unsigned char off_velocity; /* only for SNDRV_SEQ_EVENT_NOTE */ ++ unsigned int duration; /* only for SNDRV_SEQ_EVENT_NOTE */ ++}; ++ ++ /* controller event */ ++struct sndrv_seq_ev_ctrl { ++ unsigned char channel; ++ unsigned char unused1, unused2, unused3; /* pad */ ++ unsigned int param; ++ signed int value; ++}; ++ ++ /* generic set of bytes (12x8 bit) */ ++struct sndrv_seq_ev_raw8 { ++ unsigned char d[12]; /* 8 bit value */ ++}; ++ ++ /* generic set of integers (3x32 bit) */ ++struct sndrv_seq_ev_raw32 { ++ unsigned int d[3]; /* 32 bit value */ ++}; ++ ++ /* external stored data */ ++struct sndrv_seq_ev_ext { ++ unsigned int len; /* length of data */ ++ void *ptr; /* pointer to data (note: maybe 64-bit) */ ++} __attribute__((packed)); ++ ++/* Instrument cluster type */ ++typedef unsigned int sndrv_seq_instr_cluster_t; ++ ++/* Instrument type */ ++struct sndrv_seq_instr { ++ sndrv_seq_instr_cluster_t cluster; ++ unsigned int std; /* the upper byte means a private instrument (owner - client #) */ ++ unsigned short bank; ++ unsigned short prg; ++}; ++ ++ /* sample number */ ++struct sndrv_seq_ev_sample { ++ unsigned int std; ++ unsigned short bank; ++ unsigned short prg; ++}; ++ ++ /* sample cluster */ ++struct sndrv_seq_ev_cluster { ++ sndrv_seq_instr_cluster_t cluster; ++}; ++ ++ /* sample position */ ++typedef unsigned int sndrv_seq_position_t; /* playback position (in samples) * 16 */ ++ ++ /* sample stop mode */ ++enum sndrv_seq_stop_mode { ++ SAMPLE_STOP_IMMEDIATELY = 0, /* terminate playing immediately */ ++ SAMPLE_STOP_VENVELOPE = 1, /* finish volume envelope */ ++ SAMPLE_STOP_LOOP = 2 /* terminate loop and finish wave */ ++}; ++ ++ /* sample frequency */ ++typedef int sndrv_seq_frequency_t; /* playback frequency in HZ * 16 */ ++ ++ /* sample volume control; if any value is set to -1 == do not change */ ++struct sndrv_seq_ev_volume { ++ signed short volume; /* range: 0-16383 */ ++ signed short lr; /* left-right balance; range: 0-16383 */ ++ signed short fr; /* front-rear balance; range: 0-16383 */ ++ signed short du; /* down-up balance; range: 0-16383 */ ++}; ++ ++ /* simple loop redefinition */ ++struct sndrv_seq_ev_loop { ++ unsigned int start; /* loop start (in samples) * 16 */ ++ unsigned int end; /* loop end (in samples) * 16 */ ++}; ++ ++struct sndrv_seq_ev_sample_control { ++ unsigned char channel; ++ unsigned char unused1, unused2, unused3; /* pad */ ++ union { ++ struct sndrv_seq_ev_sample sample; ++ struct sndrv_seq_ev_cluster cluster; ++ sndrv_seq_position_t position; ++ int stop_mode; ++ sndrv_seq_frequency_t frequency; ++ struct sndrv_seq_ev_volume volume; ++ struct sndrv_seq_ev_loop loop; ++ unsigned char raw8[8]; ++ } param; ++}; ++ ++ ++ ++/* INSTR_BEGIN event */ ++struct sndrv_seq_ev_instr_begin { ++ int timeout; /* zero = forever, otherwise timeout in ms */ ++}; ++ ++struct sndrv_seq_result { ++ int event; /* processed event type */ ++ int result; ++}; ++ ++ ++struct sndrv_seq_real_time { ++ unsigned int tv_sec; /* seconds */ ++ unsigned int tv_nsec; /* nanoseconds */ ++}; ++ ++typedef unsigned int sndrv_seq_tick_time_t; /* midi ticks */ ++ ++union sndrv_seq_timestamp { ++ sndrv_seq_tick_time_t tick; ++ struct sndrv_seq_real_time time; ++}; ++ ++struct sndrv_seq_queue_skew { ++ unsigned int value; ++ unsigned int base; ++}; ++ ++ /* queue timer control */ ++struct sndrv_seq_ev_queue_control { ++ unsigned char queue; /* affected queue */ ++ unsigned char pad[3]; /* reserved */ ++ union { ++ signed int value; /* affected value (e.g. tempo) */ ++ union sndrv_seq_timestamp time; /* time */ ++ unsigned int position; /* sync position */ ++ struct sndrv_seq_queue_skew skew; ++ unsigned int d32[2]; ++ unsigned char d8[8]; ++ } param; ++}; ++ ++ /* quoted event - inside the kernel only */ ++struct sndrv_seq_ev_quote { ++ struct sndrv_seq_addr origin; /* original sender */ ++ unsigned short value; /* optional data */ ++ struct sndrv_seq_event *event; /* quoted event */ ++} __attribute__((packed)); ++ ++ ++ /* sequencer event */ ++struct sndrv_seq_event { ++ sndrv_seq_event_type_t type; /* event type */ ++ unsigned char flags; /* event flags */ ++ char tag; ++ ++ unsigned char queue; /* schedule queue */ ++ union sndrv_seq_timestamp time; /* schedule time */ ++ ++ ++ struct sndrv_seq_addr source; /* source address */ ++ struct sndrv_seq_addr dest; /* destination address */ ++ ++ union { /* event data... */ ++ struct sndrv_seq_ev_note note; ++ struct sndrv_seq_ev_ctrl control; ++ struct sndrv_seq_ev_raw8 raw8; ++ struct sndrv_seq_ev_raw32 raw32; ++ struct sndrv_seq_ev_ext ext; ++ struct sndrv_seq_ev_queue_control queue; ++ union sndrv_seq_timestamp time; ++ struct sndrv_seq_addr addr; ++ struct sndrv_seq_connect connect; ++ struct sndrv_seq_result result; ++ struct sndrv_seq_ev_instr_begin instr_begin; ++ struct sndrv_seq_ev_sample_control sample; ++ struct sndrv_seq_ev_quote quote; ++ } data; ++}; ++ ++ ++/* ++ * bounce event - stored as variable size data ++ */ ++struct sndrv_seq_event_bounce { ++ int err; ++ struct sndrv_seq_event event; ++ /* external data follows here. */ ++}; ++ ++struct sndrv_seq_system_info { ++ int queues; /* maximum queues count */ ++ int clients; /* maximum clients count */ ++ int ports; /* maximum ports per client */ ++ int channels; /* maximum channels per port */ ++ int cur_clients; /* current clients */ ++ int cur_queues; /* current queues */ ++ char reserved[24]; ++}; ++ ++struct sndrv_seq_running_info { ++ unsigned char client; /* client id */ ++ unsigned char big_endian; /* 1 = big-endian */ ++ unsigned char cpu_mode; /* 4 = 32bit, 8 = 64bit */ ++ unsigned char pad; /* reserved */ ++ unsigned char reserved[12]; ++}; ++ ++enum sndrv_seq_client_type { ++ NO_CLIENT = 0, ++ USER_CLIENT = 1, ++ KERNEL_CLIENT = 2 ++}; ++ ++struct sndrv_seq_client_info { ++ int client; /* client number to inquire */ ++ int type; /* client type */ ++ char name[64]; /* client name */ ++ unsigned int filter; /* filter flags */ ++ unsigned char multicast_filter[8]; /* multicast filter bitmap */ ++ unsigned char event_filter[32]; /* event filter bitmap */ ++ int num_ports; /* RO: number of ports */ ++ int event_lost; /* number of lost events */ ++ char reserved[64]; /* for future use */ ++}; ++ ++struct sndrv_seq_client_pool { ++ int client; /* client number to inquire */ ++ int output_pool; /* outgoing (write) pool size */ ++ int input_pool; /* incoming (read) pool size */ ++ int output_room; /* minimum free pool size for select/blocking mode */ ++ int output_free; /* unused size */ ++ int input_free; /* unused size */ ++ char reserved[64]; ++}; ++ ++struct sndrv_seq_remove_events { ++ unsigned int remove_mode; /* Flags that determine what gets removed */ ++ ++ union sndrv_seq_timestamp time; ++ ++ unsigned char queue; /* Queue for REMOVE_DEST */ ++ struct sndrv_seq_addr dest; /* Address for REMOVE_DEST */ ++ unsigned char channel; /* Channel for REMOVE_DEST */ ++ ++ int type; /* For REMOVE_EVENT_TYPE */ ++ char tag; /* Tag for REMOVE_TAG */ ++ ++ int reserved[10]; /* To allow for future binary compatibility */ ++ ++}; ++ ++struct sndrv_seq_port_info { ++ struct sndrv_seq_addr addr; /* client/port numbers */ ++ char name[64]; /* port name */ ++ ++ unsigned int capability; /* port capability bits */ ++ unsigned int type; /* port type bits */ ++ int midi_channels; /* channels per MIDI port */ ++ int midi_voices; /* voices per MIDI port */ ++ int synth_voices; /* voices per SYNTH port */ ++ ++ int read_use; /* R/O: subscribers for output (from this port) */ ++ int write_use; /* R/O: subscribers for input (to this port) */ ++ ++ void *kernel; /* reserved for kernel use (must be NULL) */ ++ unsigned int flags; /* misc. conditioning */ ++ unsigned char time_queue; /* queue # for timestamping */ ++ char reserved[59]; /* for future use */ ++}; ++ ++struct sndrv_seq_queue_info { ++ int queue; /* queue id */ ++ ++ /* ++ * security settings, only owner of this queue can start/stop timer ++ * etc. if the queue is locked for other clients ++ */ ++ int owner; /* client id for owner of the queue */ ++ int locked:1; /* timing queue locked for other queues */ ++ char name[64]; /* name of this queue */ ++ unsigned int flags; /* flags */ ++ char reserved[60]; /* for future use */ ++ ++}; ++ ++struct sndrv_seq_queue_status { ++ int queue; /* queue id */ ++ int events; /* read-only - queue size */ ++ sndrv_seq_tick_time_t tick; /* current tick */ ++ struct sndrv_seq_real_time time; /* current time */ ++ int running; /* running state of queue */ ++ int flags; /* various flags */ ++ char reserved[64]; /* for the future */ ++}; ++ ++struct sndrv_seq_queue_tempo { ++ int queue; /* sequencer queue */ ++ unsigned int tempo; /* current tempo, us/tick */ ++ int ppq; /* time resolution, ticks/quarter */ ++ unsigned int skew_value; /* queue skew */ ++ unsigned int skew_base; /* queue skew base */ ++ char reserved[24]; /* for the future */ ++}; ++ ++struct sndrv_timer_id { ++ int dev_class; ++ int dev_sclass; ++ int card; ++ int device; ++ int subdevice; ++}; ++ ++struct sndrv_seq_queue_timer { ++ int queue; /* sequencer queue */ ++ int type; /* source timer type */ ++ union { ++ struct { ++ struct sndrv_timer_id id; /* ALSA's timer ID */ ++ unsigned int resolution; /* resolution in Hz */ ++ } alsa; ++ } u; ++ char reserved[64]; /* for the future use */ ++}; ++ ++struct sndrv_seq_queue_client { ++ int queue; /* sequencer queue */ ++ int client; /* sequencer client */ ++ int used; /* queue is used with this client ++ (must be set for accepting events) */ ++ /* per client watermarks */ ++ char reserved[64]; /* for future use */ ++}; ++ ++struct sndrv_seq_port_subscribe { ++ struct sndrv_seq_addr sender; /* sender address */ ++ struct sndrv_seq_addr dest; /* destination address */ ++ unsigned int voices; /* number of voices to be allocated (0 = don't care) */ ++ unsigned int flags; /* modes */ ++ unsigned char queue; /* input time-stamp queue (optional) */ ++ unsigned char pad[3]; /* reserved */ ++ char reserved[64]; ++}; ++ ++struct sndrv_seq_query_subs { ++ struct sndrv_seq_addr root; /* client/port id to be searched */ ++ int type; /* READ or WRITE */ ++ int index; /* 0..N-1 */ ++ int num_subs; /* R/O: number of subscriptions on this port */ ++ struct sndrv_seq_addr addr; /* R/O: result */ ++ unsigned char queue; /* R/O: result */ ++ unsigned int flags; /* R/O: result */ ++ char reserved[64]; /* for future use */ ++}; ++ ++/* size of ROM/RAM */ ++typedef unsigned int sndrv_seq_instr_size_t; ++ ++struct sndrv_seq_instr_info { ++ int result; /* operation result */ ++ unsigned int formats[8]; /* bitmap of supported formats */ ++ int ram_count; /* count of RAM banks */ ++ sndrv_seq_instr_size_t ram_sizes[16]; /* size of RAM banks */ ++ int rom_count; /* count of ROM banks */ ++ sndrv_seq_instr_size_t rom_sizes[8]; /* size of ROM banks */ ++ char reserved[128]; ++}; ++ ++struct sndrv_seq_instr_status { ++ int result; /* operation result */ ++ sndrv_seq_instr_size_t free_ram[16]; /* free RAM in banks */ ++ int instrument_count; /* count of downloaded instruments */ ++ char reserved[128]; ++}; ++ ++struct sndrv_seq_instr_format_info { ++ char format[16]; /* format identifier - SNDRV_SEQ_INSTR_ID_* */ ++ unsigned int len; /* max data length (without this structure) */ ++}; ++ ++struct sndrv_seq_instr_format_info_result { ++ int result; /* operation result */ ++ char format[16]; /* format identifier */ ++ unsigned int len; /* filled data length (without this structure) */ ++}; ++ ++struct sndrv_seq_instr_data { ++ char name[32]; /* instrument name */ ++ char reserved[16]; /* for the future use */ ++ int type; /* instrument type */ ++ union { ++ char format[16]; /* format identifier */ ++ struct sndrv_seq_instr alias; ++ } data; ++}; ++ ++struct sndrv_seq_instr_header { ++ union { ++ struct sndrv_seq_instr instr; ++ sndrv_seq_instr_cluster_t cluster; ++ } id; /* instrument identifier */ ++ unsigned int cmd; /* get/put/free command */ ++ unsigned int flags; /* query flags (only for get) */ ++ unsigned int len; /* real instrument data length (without header) */ ++ int result; /* operation result */ ++ char reserved[16]; /* for the future */ ++ struct sndrv_seq_instr_data data; /* instrument data (for put/get result) */ ++}; ++ ++struct sndrv_seq_instr_cluster_set { ++ sndrv_seq_instr_cluster_t cluster; /* cluster identifier */ ++ char name[32]; /* cluster name */ ++ int priority; /* cluster priority */ ++ char reserved[64]; /* for the future use */ ++}; ++ ++struct sndrv_seq_instr_cluster_get { ++ sndrv_seq_instr_cluster_t cluster; /* cluster identifier */ ++ char name[32]; /* cluster name */ ++ int priority; /* cluster priority */ ++ char reserved[64]; /* for the future use */ ++}; ++ ++typedef struct snd_dm_fm_info { ++ unsigned char fm_mode; /* OPL mode, see SNDRV_DM_FM_MODE_XXX */ ++ unsigned char rhythm; /* percussion mode flag */ ++} snd_dm_fm_info_t; ++ ++typedef struct snd_dm_fm_voice { ++ unsigned char op; /* operator cell (0 or 1) */ ++ unsigned char voice; /* FM voice (0 to 17) */ ++ ++ unsigned char am; /* amplitude modulation */ ++ unsigned char vibrato; /* vibrato effect */ ++ unsigned char do_sustain; /* sustain phase */ ++ unsigned char kbd_scale; /* keyboard scaling */ ++ unsigned char harmonic; /* 4 bits: harmonic and multiplier */ ++ unsigned char scale_level; /* 2 bits: decrease output freq rises */ ++ unsigned char volume; /* 6 bits: volume */ ++ ++ unsigned char attack; /* 4 bits: attack rate */ ++ unsigned char decay; /* 4 bits: decay rate */ ++ unsigned char sustain; /* 4 bits: sustain level */ ++ unsigned char release; /* 4 bits: release rate */ ++ ++ unsigned char feedback; /* 3 bits: feedback for op0 */ ++ unsigned char connection; /* 0 for serial, 1 for parallel */ ++ unsigned char left; /* stereo left */ ++ unsigned char right; /* stereo right */ ++ unsigned char waveform; /* 3 bits: waveform shape */ ++} snd_dm_fm_voice_t; ++ ++typedef struct snd_dm_fm_note { ++ unsigned char voice; /* 0-17 voice channel */ ++ unsigned char octave; /* 3 bits: what octave to play */ ++ unsigned int fnum; /* 10 bits: frequency number */ ++ unsigned char key_on; /* set for active, clear for silent */ ++} snd_dm_fm_note_t; ++ ++typedef struct snd_dm_fm_params { ++ unsigned char am_depth; /* amplitude modulation depth (1=hi) */ ++ unsigned char vib_depth; /* vibrato depth (1=hi) */ ++ unsigned char kbd_split; /* keyboard split */ ++ unsigned char rhythm; /* percussion mode select */ ++ ++ /* This block is the percussion instrument data */ ++ unsigned char bass; ++ unsigned char snare; ++ unsigned char tomtom; ++ unsigned char cymbal; ++ unsigned char hihat; ++} snd_dm_fm_params_t; ++ ++#include ++#if __BYTE_ORDER == __LITTLE_ENDIAN ++#define SNDRV_LITTLE_ENDIAN ++#elif __BYTE_ORDER == __BIG_ENDIAN ++#define SNDRV_BIG_ENDIAN ++#else ++#error "Unsupported endian..." ++#endif ++ ++#include ++#include ++ ++struct sndrv_aes_iec958 { ++ unsigned char status[24]; /* AES/IEC958 channel status bits */ ++ unsigned char subcode[147]; /* AES/IEC958 subcode bits */ ++ unsigned char pad; /* nothing */ ++ unsigned char dig_subframe[4]; /* AES/IEC958 subframe bits */ ++}; ++ ++enum sndrv_hwdep_iface { ++ SNDRV_HWDEP_IFACE_OPL2 = 0, ++ SNDRV_HWDEP_IFACE_OPL3, ++ SNDRV_HWDEP_IFACE_OPL4, ++ SNDRV_HWDEP_IFACE_SB16CSP, /* Creative Signal Processor */ ++ SNDRV_HWDEP_IFACE_EMU10K1, /* FX8010 processor in EMU10K1 chip */ ++ SNDRV_HWDEP_IFACE_YSS225, /* Yamaha FX processor */ ++ SNDRV_HWDEP_IFACE_ICS2115, /* Wavetable synth */ ++ SNDRV_HWDEP_IFACE_SSCAPE, /* Ensoniq SoundScape ISA card (MC68EC000) */ ++ SNDRV_HWDEP_IFACE_VX, /* Digigram VX cards */ ++ SNDRV_HWDEP_IFACE_MIXART, /* Digigram miXart cards */ ++ SNDRV_HWDEP_IFACE_USX2Y, /* Tascam US122, US224 & US428 usb */ ++ SNDRV_HWDEP_IFACE_EMUX_WAVETABLE, /* EmuX wavetable */ ++ SNDRV_HWDEP_IFACE_BLUETOOTH, /* Bluetooth audio */ ++ SNDRV_HWDEP_IFACE_USX2Y_PCM, /* Tascam US122, US224 & US428 rawusb pcm */ ++ SNDRV_HWDEP_IFACE_PCXHR, /* Digigram PCXHR */ ++ SNDRV_HWDEP_IFACE_SB_RC, /* SB Extigy/Audigy2NX remote control */ ++ ++ /* Don't forget to change the following: */ ++ SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_SB_RC ++}; ++ ++struct sndrv_hwdep_info { ++ unsigned int device; /* WR: device number */ ++ int card; /* R: card number */ ++ unsigned char id[64]; /* ID (user selectable) */ ++ unsigned char name[80]; /* hwdep name */ ++ int iface; /* hwdep interface */ ++ unsigned char reserved[64]; /* reserved for future */ ++}; ++ ++/* generic DSP loader */ ++struct sndrv_hwdep_dsp_status { ++ unsigned int version; /* R: driver-specific version */ ++ unsigned char id[32]; /* R: driver-specific ID string */ ++ unsigned int num_dsps; /* R: number of DSP images to transfer */ ++ unsigned int dsp_loaded; /* R: bit flags indicating the loaded DSPs */ ++ unsigned int chip_ready; /* R: 1 = initialization finished */ ++ unsigned char reserved[16]; /* reserved for future use */ ++}; ++ ++struct sndrv_hwdep_dsp_image { ++ unsigned int index; /* W: DSP index */ ++ unsigned char name[64]; /* W: ID (e.g. file name) */ ++ unsigned char *image; /* W: binary image */ ++ size_t length; /* W: size of image in bytes */ ++ unsigned long driver_data; /* W: driver-specific data */ ++}; ++ ++typedef unsigned long sndrv_pcm_uframes_t; ++typedef long sndrv_pcm_sframes_t; ++ ++enum sndrv_pcm_class { ++ SNDRV_PCM_CLASS_GENERIC = 0, /* standard mono or stereo device */ ++ SNDRV_PCM_CLASS_MULTI, /* multichannel device */ ++ SNDRV_PCM_CLASS_MODEM, /* software modem class */ ++ SNDRV_PCM_CLASS_DIGITIZER, /* digitizer class */ ++ /* Don't forget to change the following: */ ++ SNDRV_PCM_CLASS_LAST = SNDRV_PCM_CLASS_DIGITIZER, ++}; ++ ++enum sndrv_pcm_subclass { ++ SNDRV_PCM_SUBCLASS_GENERIC_MIX = 0, /* mono or stereo subdevices are mixed together */ ++ SNDRV_PCM_SUBCLASS_MULTI_MIX, /* multichannel subdevices are mixed together */ ++ /* Don't forget to change the following: */ ++ SNDRV_PCM_SUBCLASS_LAST = SNDRV_PCM_SUBCLASS_MULTI_MIX, ++}; ++ ++enum sndrv_pcm_stream { ++ SNDRV_PCM_STREAM_PLAYBACK = 0, ++ SNDRV_PCM_STREAM_CAPTURE, ++ SNDRV_PCM_STREAM_LAST = SNDRV_PCM_STREAM_CAPTURE, ++}; ++ ++enum sndrv_pcm_access { ++ SNDRV_PCM_ACCESS_MMAP_INTERLEAVED = 0, /* interleaved mmap */ ++ SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED, /* noninterleaved mmap */ ++ SNDRV_PCM_ACCESS_MMAP_COMPLEX, /* complex mmap */ ++ SNDRV_PCM_ACCESS_RW_INTERLEAVED, /* readi/writei */ ++ SNDRV_PCM_ACCESS_RW_NONINTERLEAVED, /* readn/writen */ ++ SNDRV_PCM_ACCESS_LAST = SNDRV_PCM_ACCESS_RW_NONINTERLEAVED, ++}; ++ ++enum sndrv_pcm_format { ++ SNDRV_PCM_FORMAT_S8 = 0, ++ SNDRV_PCM_FORMAT_U8, ++ SNDRV_PCM_FORMAT_S16_LE, ++ SNDRV_PCM_FORMAT_S16_BE, ++ SNDRV_PCM_FORMAT_U16_LE, ++ SNDRV_PCM_FORMAT_U16_BE, ++ SNDRV_PCM_FORMAT_S24_LE, /* low three bytes */ ++ SNDRV_PCM_FORMAT_S24_BE, /* low three bytes */ ++ SNDRV_PCM_FORMAT_U24_LE, /* low three bytes */ ++ SNDRV_PCM_FORMAT_U24_BE, /* low three bytes */ ++ SNDRV_PCM_FORMAT_S32_LE, ++ SNDRV_PCM_FORMAT_S32_BE, ++ SNDRV_PCM_FORMAT_U32_LE, ++ SNDRV_PCM_FORMAT_U32_BE, ++ SNDRV_PCM_FORMAT_FLOAT_LE, /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */ ++ SNDRV_PCM_FORMAT_FLOAT_BE, /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */ ++ SNDRV_PCM_FORMAT_FLOAT64_LE, /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */ ++ SNDRV_PCM_FORMAT_FLOAT64_BE, /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */ ++ SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE, /* IEC-958 subframe, Little Endian */ ++ SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE, /* IEC-958 subframe, Big Endian */ ++ SNDRV_PCM_FORMAT_MU_LAW, ++ SNDRV_PCM_FORMAT_A_LAW, ++ SNDRV_PCM_FORMAT_IMA_ADPCM, ++ SNDRV_PCM_FORMAT_MPEG, ++ SNDRV_PCM_FORMAT_GSM, ++ SNDRV_PCM_FORMAT_SPECIAL = 31, ++ SNDRV_PCM_FORMAT_S24_3LE = 32, /* in three bytes */ ++ SNDRV_PCM_FORMAT_S24_3BE, /* in three bytes */ ++ SNDRV_PCM_FORMAT_U24_3LE, /* in three bytes */ ++ SNDRV_PCM_FORMAT_U24_3BE, /* in three bytes */ ++ SNDRV_PCM_FORMAT_S20_3LE, /* in three bytes */ ++ SNDRV_PCM_FORMAT_S20_3BE, /* in three bytes */ ++ SNDRV_PCM_FORMAT_U20_3LE, /* in three bytes */ ++ SNDRV_PCM_FORMAT_U20_3BE, /* in three bytes */ ++ SNDRV_PCM_FORMAT_S18_3LE, /* in three bytes */ ++ SNDRV_PCM_FORMAT_S18_3BE, /* in three bytes */ ++ SNDRV_PCM_FORMAT_U18_3LE, /* in three bytes */ ++ SNDRV_PCM_FORMAT_U18_3BE, /* in three bytes */ ++ SNDRV_PCM_FORMAT_LAST = SNDRV_PCM_FORMAT_U18_3BE, ++ ++#ifdef SNDRV_LITTLE_ENDIAN ++ SNDRV_PCM_FORMAT_S16 = SNDRV_PCM_FORMAT_S16_LE, ++ SNDRV_PCM_FORMAT_U16 = SNDRV_PCM_FORMAT_U16_LE, ++ SNDRV_PCM_FORMAT_S24 = SNDRV_PCM_FORMAT_S24_LE, ++ SNDRV_PCM_FORMAT_U24 = SNDRV_PCM_FORMAT_U24_LE, ++ SNDRV_PCM_FORMAT_S32 = SNDRV_PCM_FORMAT_S32_LE, ++ SNDRV_PCM_FORMAT_U32 = SNDRV_PCM_FORMAT_U32_LE, ++ SNDRV_PCM_FORMAT_FLOAT = SNDRV_PCM_FORMAT_FLOAT_LE, ++ SNDRV_PCM_FORMAT_FLOAT64 = SNDRV_PCM_FORMAT_FLOAT64_LE, ++ SNDRV_PCM_FORMAT_IEC958_SUBFRAME = SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE, ++#endif ++#ifdef SNDRV_BIG_ENDIAN ++ SNDRV_PCM_FORMAT_S16 = SNDRV_PCM_FORMAT_S16_BE, ++ SNDRV_PCM_FORMAT_U16 = SNDRV_PCM_FORMAT_U16_BE, ++ SNDRV_PCM_FORMAT_S24 = SNDRV_PCM_FORMAT_S24_BE, ++ SNDRV_PCM_FORMAT_U24 = SNDRV_PCM_FORMAT_U24_BE, ++ SNDRV_PCM_FORMAT_S32 = SNDRV_PCM_FORMAT_S32_BE, ++ SNDRV_PCM_FORMAT_U32 = SNDRV_PCM_FORMAT_U32_BE, ++ SNDRV_PCM_FORMAT_FLOAT = SNDRV_PCM_FORMAT_FLOAT_BE, ++ SNDRV_PCM_FORMAT_FLOAT64 = SNDRV_PCM_FORMAT_FLOAT64_BE, ++ SNDRV_PCM_FORMAT_IEC958_SUBFRAME = SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE, ++#endif ++}; ++ ++enum sndrv_pcm_subformat { ++ SNDRV_PCM_SUBFORMAT_STD = 0, ++ SNDRV_PCM_SUBFORMAT_LAST = SNDRV_PCM_SUBFORMAT_STD, ++}; ++ ++enum sndrv_pcm_state { ++ SNDRV_PCM_STATE_OPEN = 0, /* stream is open */ ++ SNDRV_PCM_STATE_SETUP, /* stream has a setup */ ++ SNDRV_PCM_STATE_PREPARED, /* stream is ready to start */ ++ SNDRV_PCM_STATE_RUNNING, /* stream is running */ ++ SNDRV_PCM_STATE_XRUN, /* stream reached an xrun */ ++ SNDRV_PCM_STATE_DRAINING, /* stream is draining */ ++ SNDRV_PCM_STATE_PAUSED, /* stream is paused */ ++ SNDRV_PCM_STATE_SUSPENDED, /* hardware is suspended */ ++ SNDRV_PCM_STATE_DISCONNECTED, /* hardware is disconnected */ ++ SNDRV_PCM_STATE_LAST = SNDRV_PCM_STATE_DISCONNECTED, ++}; ++ ++enum { ++ SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000, ++ SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000, ++ SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000, ++}; ++ ++union sndrv_pcm_sync_id { ++ unsigned char id[16]; ++ unsigned short id16[8]; ++ unsigned int id32[4]; ++}; ++ ++struct sndrv_pcm_info { ++ unsigned int device; /* RO/WR (control): device number */ ++ unsigned int subdevice; /* RO/WR (control): subdevice number */ ++ int stream; /* RO/WR (control): stream number */ ++ int card; /* R: card number */ ++ unsigned char id[64]; /* ID (user selectable) */ ++ unsigned char name[80]; /* name of this device */ ++ unsigned char subname[32]; /* subdevice name */ ++ int dev_class; /* SNDRV_PCM_CLASS_* */ ++ int dev_subclass; /* SNDRV_PCM_SUBCLASS_* */ ++ unsigned int subdevices_count; ++ unsigned int subdevices_avail; ++ union sndrv_pcm_sync_id sync; /* hardware synchronization ID */ ++ unsigned char reserved[64]; /* reserved for future... */ ++}; ++ ++enum sndrv_pcm_hw_param { ++ SNDRV_PCM_HW_PARAM_ACCESS = 0, /* Access type */ ++ SNDRV_PCM_HW_PARAM_FIRST_MASK = SNDRV_PCM_HW_PARAM_ACCESS, ++ SNDRV_PCM_HW_PARAM_FORMAT, /* Format */ ++ SNDRV_PCM_HW_PARAM_SUBFORMAT, /* Subformat */ ++ SNDRV_PCM_HW_PARAM_LAST_MASK = SNDRV_PCM_HW_PARAM_SUBFORMAT, ++ ++ SNDRV_PCM_HW_PARAM_SAMPLE_BITS = 8, /* Bits per sample */ ++ SNDRV_PCM_HW_PARAM_FIRST_INTERVAL = SNDRV_PCM_HW_PARAM_SAMPLE_BITS, ++ SNDRV_PCM_HW_PARAM_FRAME_BITS, /* Bits per frame */ ++ SNDRV_PCM_HW_PARAM_CHANNELS, /* Channels */ ++ SNDRV_PCM_HW_PARAM_RATE, /* Approx rate */ ++ SNDRV_PCM_HW_PARAM_PERIOD_TIME, /* Approx distance between interrupts ++ in us */ ++ SNDRV_PCM_HW_PARAM_PERIOD_SIZE, /* Approx frames between interrupts */ ++ SNDRV_PCM_HW_PARAM_PERIOD_BYTES, /* Approx bytes between interrupts */ ++ SNDRV_PCM_HW_PARAM_PERIODS, /* Approx interrupts per buffer */ ++ SNDRV_PCM_HW_PARAM_BUFFER_TIME, /* Approx duration of buffer in us */ ++ SNDRV_PCM_HW_PARAM_BUFFER_SIZE, /* Size of buffer in frames */ ++ SNDRV_PCM_HW_PARAM_BUFFER_BYTES, /* Size of buffer in bytes */ ++ SNDRV_PCM_HW_PARAM_TICK_TIME, /* Approx tick duration in us */ ++ SNDRV_PCM_HW_PARAM_LAST_INTERVAL = SNDRV_PCM_HW_PARAM_TICK_TIME ++}; ++ ++struct sndrv_interval { ++ unsigned int min, max; ++ unsigned int openmin:1, ++ openmax:1, ++ integer:1, ++ empty:1; ++}; ++ ++struct sndrv_mask { ++ u_int32_t bits[(SNDRV_MASK_MAX+31)/32]; ++}; ++ ++struct sndrv_pcm_hw_params { ++ unsigned int flags; ++ struct sndrv_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - ++ SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; ++ struct sndrv_mask mres[5]; /* reserved masks */ ++ struct sndrv_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - ++ SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1]; ++ struct sndrv_interval ires[9]; /* reserved intervals */ ++ unsigned int rmask; /* W: requested masks */ ++ unsigned int cmask; /* R: changed masks */ ++ unsigned int info; /* R: Info flags for returned setup */ ++ unsigned int msbits; /* R: used most significant bits */ ++ unsigned int rate_num; /* R: rate numerator */ ++ unsigned int rate_den; /* R: rate denominator */ ++ sndrv_pcm_uframes_t fifo_size; /* R: chip FIFO size in frames */ ++ unsigned char reserved[64]; /* reserved for future */ ++}; ++ ++enum sndrv_pcm_tstamp { ++ SNDRV_PCM_TSTAMP_NONE = 0, ++ SNDRV_PCM_TSTAMP_MMAP, ++ SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_MMAP, ++}; ++ ++struct sndrv_pcm_sw_params { ++ int tstamp_mode; /* timestamp mode */ ++ unsigned int period_step; ++ unsigned int sleep_min; /* min ticks to sleep */ ++ sndrv_pcm_uframes_t avail_min; /* min avail frames for wakeup */ ++ sndrv_pcm_uframes_t xfer_align; /* xfer size need to be a multiple */ ++ sndrv_pcm_uframes_t start_threshold; /* min hw_avail frames for automatic start */ ++ sndrv_pcm_uframes_t stop_threshold; /* min avail frames for automatic stop */ ++ sndrv_pcm_uframes_t silence_threshold; /* min distance from noise for silence filling */ ++ sndrv_pcm_uframes_t silence_size; /* silence block size */ ++ sndrv_pcm_uframes_t boundary; /* pointers wrap point */ ++ unsigned char reserved[64]; /* reserved for future */ ++}; ++ ++struct sndrv_pcm_channel_info { ++ unsigned int channel; ++ long int offset; /* mmap offset */ ++ unsigned int first; /* offset to first sample in bits */ ++ unsigned int step; /* samples distance in bits */ ++}; ++ ++struct sndrv_pcm_status { ++ int state; /* stream state */ ++ struct timespec trigger_tstamp; /* time when stream was started/stopped/paused */ ++ struct timespec tstamp; /* reference timestamp */ ++ sndrv_pcm_uframes_t appl_ptr; /* appl ptr */ ++ sndrv_pcm_uframes_t hw_ptr; /* hw ptr */ ++ sndrv_pcm_sframes_t delay; /* current delay in frames */ ++ sndrv_pcm_uframes_t avail; /* number of frames available */ ++ sndrv_pcm_uframes_t avail_max; /* max frames available on hw since last status */ ++ sndrv_pcm_uframes_t overrange; /* count of ADC (capture) overrange detections from last status */ ++ int suspended_state; /* suspended stream state */ ++ unsigned char reserved[60]; /* must be filled with zero */ ++}; ++ ++struct sndrv_pcm_mmap_status { ++ int state; /* RO: state - SNDRV_PCM_STATE_XXXX */ ++ int pad1; /* Needed for 64 bit alignment */ ++ sndrv_pcm_uframes_t hw_ptr; /* RO: hw ptr (0...boundary-1) */ ++ struct timespec tstamp; /* Timestamp */ ++ int suspended_state; /* RO: suspended stream state */ ++}; ++ ++struct sndrv_pcm_mmap_control { ++ sndrv_pcm_uframes_t appl_ptr; /* RW: appl ptr (0...boundary-1) */ ++ sndrv_pcm_uframes_t avail_min; /* RW: min available frames for wakeup */ ++}; ++ ++struct sndrv_pcm_sync_ptr { ++ unsigned int flags; ++ union { ++ struct sndrv_pcm_mmap_status status; ++ unsigned char reserved[64]; ++ } s; ++ union { ++ struct sndrv_pcm_mmap_control control; ++ unsigned char reserved[64]; ++ } c; ++}; ++ ++struct sndrv_xferi { ++ sndrv_pcm_sframes_t result; ++ void *buf; ++ sndrv_pcm_uframes_t frames; ++}; ++ ++struct sndrv_xfern { ++ sndrv_pcm_sframes_t result; ++ void **bufs; ++ sndrv_pcm_uframes_t frames; ++}; ++ ++enum sndrv_rawmidi_stream { ++ SNDRV_RAWMIDI_STREAM_OUTPUT = 0, ++ SNDRV_RAWMIDI_STREAM_INPUT, ++ SNDRV_RAWMIDI_STREAM_LAST = SNDRV_RAWMIDI_STREAM_INPUT, ++}; ++ ++struct sndrv_rawmidi_info { ++ unsigned int device; /* RO/WR (control): device number */ ++ unsigned int subdevice; /* RO/WR (control): subdevice number */ ++ int stream; /* WR: stream */ ++ int card; /* R: card number */ ++ unsigned int flags; /* SNDRV_RAWMIDI_INFO_XXXX */ ++ unsigned char id[64]; /* ID (user selectable) */ ++ unsigned char name[80]; /* name of device */ ++ unsigned char subname[32]; /* name of active or selected subdevice */ ++ unsigned int subdevices_count; ++ unsigned int subdevices_avail; ++ unsigned char reserved[64]; /* reserved for future use */ ++}; ++ ++struct sndrv_rawmidi_params { ++ int stream; ++ size_t buffer_size; /* queue size in bytes */ ++ size_t avail_min; /* minimum avail bytes for wakeup */ ++ unsigned int no_active_sensing: 1; /* do not send active sensing byte in close() */ ++ unsigned char reserved[16]; /* reserved for future use */ ++}; ++ ++struct sndrv_rawmidi_status { ++ int stream; ++ struct timespec tstamp; /* Timestamp */ ++ size_t avail; /* available bytes */ ++ size_t xruns; /* count of overruns since last status (in bytes) */ ++ unsigned char reserved[16]; /* reserved for future use */ ++}; ++ ++enum sndrv_timer_class { ++ SNDRV_TIMER_CLASS_NONE = -1, ++ SNDRV_TIMER_CLASS_SLAVE = 0, ++ SNDRV_TIMER_CLASS_GLOBAL, ++ SNDRV_TIMER_CLASS_CARD, ++ SNDRV_TIMER_CLASS_PCM, ++ SNDRV_TIMER_CLASS_LAST = SNDRV_TIMER_CLASS_PCM, ++}; ++ ++/* slave timer classes */ ++enum sndrv_timer_slave_class { ++ SNDRV_TIMER_SCLASS_NONE = 0, ++ SNDRV_TIMER_SCLASS_APPLICATION, ++ SNDRV_TIMER_SCLASS_SEQUENCER, /* alias */ ++ SNDRV_TIMER_SCLASS_OSS_SEQUENCER, /* alias */ ++ SNDRV_TIMER_SCLASS_LAST = SNDRV_TIMER_SCLASS_OSS_SEQUENCER, ++}; ++ ++struct sndrv_timer_ginfo { ++ struct sndrv_timer_id tid; /* requested timer ID */ ++ unsigned int flags; /* timer flags - SNDRV_TIMER_FLG_* */ ++ int card; /* card number */ ++ unsigned char id[64]; /* timer identification */ ++ unsigned char name[80]; /* timer name */ ++ unsigned long reserved0; /* reserved for future use */ ++ unsigned long resolution; /* average period resolution in ns */ ++ unsigned long resolution_min; /* minimal period resolution in ns */ ++ unsigned long resolution_max; /* maximal period resolution in ns */ ++ unsigned int clients; /* active timer clients */ ++ unsigned char reserved[32]; ++}; ++ ++struct sndrv_timer_gparams { ++ struct sndrv_timer_id tid; /* requested timer ID */ ++ unsigned long period_num; /* requested precise period duration (in seconds) - numerator */ ++ unsigned long period_den; /* requested precise period duration (in seconds) - denominator */ ++ unsigned char reserved[32]; ++}; ++ ++struct sndrv_timer_gstatus { ++ struct sndrv_timer_id tid; /* requested timer ID */ ++ unsigned long resolution; /* current period resolution in ns */ ++ unsigned long resolution_num; /* precise current period resolution (in seconds) - numerator */ ++ unsigned long resolution_den; /* precise current period resolution (in seconds) - denominator */ ++ unsigned char reserved[32]; ++}; ++ ++struct sndrv_timer_select { ++ struct sndrv_timer_id id; /* bind to timer ID */ ++ unsigned char reserved[32]; /* reserved */ ++}; ++ ++struct sndrv_timer_info { ++ unsigned int flags; /* timer flags - SNDRV_TIMER_FLG_* */ ++ int card; /* card number */ ++ unsigned char id[64]; /* timer identificator */ ++ unsigned char name[80]; /* timer name */ ++ unsigned long reserved0; /* reserved for future use */ ++ unsigned long resolution; /* average period resolution in ns */ ++ unsigned char reserved[64]; /* reserved */ ++}; ++ ++struct sndrv_timer_params { ++ unsigned int flags; /* flags - SNDRV_MIXER_PSFLG_* */ ++ unsigned int ticks; /* requested resolution in ticks */ ++ unsigned int queue_size; /* total size of queue (32-1024) */ ++ unsigned int reserved0; /* reserved, was: failure locations */ ++ unsigned int filter; /* event filter (bitmask of SNDRV_TIMER_EVENT_*) */ ++ unsigned char reserved[60]; /* reserved */ ++}; ++ ++struct sndrv_timer_status { ++ struct timespec tstamp; /* Timestamp - last update */ ++ unsigned int resolution; /* current period resolution in ns */ ++ unsigned int lost; /* counter of master tick lost */ ++ unsigned int overrun; /* count of read queue overruns */ ++ unsigned int queue; /* used queue size */ ++ unsigned char reserved[64]; /* reserved */ ++}; ++ ++struct sndrv_timer_read { ++ unsigned int resolution; ++ unsigned int ticks; ++}; ++ ++enum sndrv_timer_event { ++ SNDRV_TIMER_EVENT_RESOLUTION = 0, /* val = resolution in ns */ ++ SNDRV_TIMER_EVENT_TICK, /* val = ticks */ ++ SNDRV_TIMER_EVENT_START, /* val = resolution in ns */ ++ SNDRV_TIMER_EVENT_STOP, /* val = 0 */ ++ SNDRV_TIMER_EVENT_CONTINUE, /* val = resolution in ns */ ++ SNDRV_TIMER_EVENT_PAUSE, /* val = 0 */ ++ SNDRV_TIMER_EVENT_EARLY, /* val = 0, early event */ ++ SNDRV_TIMER_EVENT_SUSPEND, /* val = 0 */ ++ SNDRV_TIMER_EVENT_RESUME, /* val = resolution in ns */ ++ /* master timer events for slave timer instances */ ++ SNDRV_TIMER_EVENT_MSTART = SNDRV_TIMER_EVENT_START + 10, ++ SNDRV_TIMER_EVENT_MSTOP = SNDRV_TIMER_EVENT_STOP + 10, ++ SNDRV_TIMER_EVENT_MCONTINUE = SNDRV_TIMER_EVENT_CONTINUE + 10, ++ SNDRV_TIMER_EVENT_MPAUSE = SNDRV_TIMER_EVENT_PAUSE + 10, ++ SNDRV_TIMER_EVENT_MSUSPEND = SNDRV_TIMER_EVENT_SUSPEND + 10, ++ SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10, ++}; ++ ++struct sndrv_timer_tread { ++ int event; ++ struct timespec tstamp; ++ unsigned int val; ++}; ++ ++struct sndrv_ctl_card_info { ++ int card; /* card number */ ++ int pad; /* reserved for future (was type) */ ++ unsigned char id[16]; /* ID of card (user selectable) */ ++ unsigned char driver[16]; /* Driver name */ ++ unsigned char name[32]; /* Short name of soundcard */ ++ unsigned char longname[80]; /* name + info text about soundcard */ ++ unsigned char reserved_[16]; /* reserved for future (was ID of mixer) */ ++ unsigned char mixername[80]; /* visual mixer identification */ ++ unsigned char components[80]; /* card components / fine identification, delimited with one space (AC97 etc..) */ ++ unsigned char reserved[48]; /* reserved for future */ ++}; ++ ++enum sndrv_ctl_elem_type { ++ SNDRV_CTL_ELEM_TYPE_NONE = 0, /* invalid */ ++ SNDRV_CTL_ELEM_TYPE_BOOLEAN, /* boolean type */ ++ SNDRV_CTL_ELEM_TYPE_INTEGER, /* integer type */ ++ SNDRV_CTL_ELEM_TYPE_ENUMERATED, /* enumerated type */ ++ SNDRV_CTL_ELEM_TYPE_BYTES, /* byte array */ ++ SNDRV_CTL_ELEM_TYPE_IEC958, /* IEC958 (S/PDIF) setup */ ++ SNDRV_CTL_ELEM_TYPE_INTEGER64, /* 64-bit integer type */ ++ SNDRV_CTL_ELEM_TYPE_LAST = SNDRV_CTL_ELEM_TYPE_INTEGER64, ++}; ++ ++enum sndrv_ctl_elem_iface { ++ SNDRV_CTL_ELEM_IFACE_CARD = 0, /* global control */ ++ SNDRV_CTL_ELEM_IFACE_HWDEP, /* hardware dependent device */ ++ SNDRV_CTL_ELEM_IFACE_MIXER, /* virtual mixer device */ ++ SNDRV_CTL_ELEM_IFACE_PCM, /* PCM device */ ++ SNDRV_CTL_ELEM_IFACE_RAWMIDI, /* RawMidi device */ ++ SNDRV_CTL_ELEM_IFACE_TIMER, /* timer device */ ++ SNDRV_CTL_ELEM_IFACE_SEQUENCER, /* sequencer client */ ++ SNDRV_CTL_ELEM_IFACE_LAST = SNDRV_CTL_ELEM_IFACE_SEQUENCER, ++}; ++ ++struct sndrv_ctl_elem_id { ++ unsigned int numid; /* numeric identifier, zero = invalid */ ++ int iface; /* interface identifier */ ++ unsigned int device; /* device/client number */ ++ unsigned int subdevice; /* subdevice (substream) number */ ++ unsigned char name[44]; /* ASCII name of item */ ++ unsigned int index; /* index of item */ ++}; ++ ++struct sndrv_ctl_elem_list { ++ unsigned int offset; /* W: first element ID to get */ ++ unsigned int space; /* W: count of element IDs to get */ ++ unsigned int used; /* R: count of element IDs set */ ++ unsigned int count; /* R: count of all elements */ ++ struct sndrv_ctl_elem_id *pids; /* R: IDs */ ++ unsigned char reserved[50]; ++}; ++ ++struct sndrv_ctl_elem_info { ++ struct sndrv_ctl_elem_id id; /* W: element ID */ ++ int type; /* R: value type - SNDRV_CTL_ELEM_TYPE_* */ ++ unsigned int access; /* R: value access (bitmask) - SNDRV_CTL_ELEM_ACCESS_* */ ++ unsigned int count; /* count of values */ ++ pid_t owner; /* owner's PID of this control */ ++ union { ++ struct { ++ long min; /* R: minimum value */ ++ long max; /* R: maximum value */ ++ long step; /* R: step (0 variable) */ ++ } integer; ++ struct { ++ long long min; /* R: minimum value */ ++ long long max; /* R: maximum value */ ++ long long step; /* R: step (0 variable) */ ++ } integer64; ++ struct { ++ unsigned int items; /* R: number of items */ ++ unsigned int item; /* W: item number */ ++ char name[64]; /* R: value name */ ++ } enumerated; ++ unsigned char reserved[128]; ++ } value; ++ union { ++ unsigned short d[4]; /* dimensions */ ++ unsigned short *d_ptr; /* indirect */ ++ } dimen; ++ unsigned char reserved[64-4*sizeof(unsigned short)]; ++}; ++ ++struct sndrv_ctl_elem_value { ++ struct sndrv_ctl_elem_id id; /* W: element ID */ ++ unsigned int indirect: 1; /* W: use indirect pointer (xxx_ptr member) */ ++ union { ++ union { ++ long value[128]; ++ long *value_ptr; ++ } integer; ++ union { ++ long long value[64]; ++ long long *value_ptr; ++ } integer64; ++ union { ++ unsigned int item[128]; ++ unsigned int *item_ptr; ++ } enumerated; ++ union { ++ unsigned char data[512]; ++ unsigned char *data_ptr; ++ } bytes; ++ struct sndrv_aes_iec958 iec958; ++ } value; /* RO */ ++ struct timespec tstamp; ++ unsigned char reserved[128-sizeof(struct timespec)]; ++}; ++ ++struct sndrv_ctl_tlv { ++ unsigned int numid; /* control element numeric identification */ ++ unsigned int length; /* in bytes aligned to 4 */ ++ unsigned int tlv[0]; /* first TLV */ ++}; ++ ++enum sndrv_ctl_event_type { ++ SNDRV_CTL_EVENT_ELEM = 0, ++ SNDRV_CTL_EVENT_LAST = SNDRV_CTL_EVENT_ELEM, ++}; ++ ++struct sndrv_ctl_event { ++ int type; /* event type - SNDRV_CTL_EVENT_* */ ++ union { ++ struct { ++ unsigned int mask; ++ struct sndrv_ctl_elem_id id; ++ } elem; ++ unsigned char data8[60]; ++ } data; ++}; ++ ++struct sndrv_xferv { ++ const struct iovec *vector; ++ unsigned long count; ++}; ++ ++typedef struct { ++ unsigned int internal_tram_size; /* in samples */ ++ unsigned int external_tram_size; /* in samples */ ++ char fxbus_names[16][32]; /* names of FXBUSes */ ++ char extin_names[16][32]; /* names of external inputs */ ++ char extout_names[32][32]; /* names of external outputs */ ++ unsigned int gpr_controls; /* count of GPR controls */ ++} emu10k1_fx8010_info_t; ++ ++enum emu10k1_ctl_elem_iface { ++ EMU10K1_CTL_ELEM_IFACE_MIXER = 2, /* virtual mixer device */ ++ EMU10K1_CTL_ELEM_IFACE_PCM = 3, /* PCM device */ ++}; ++ ++typedef struct { ++ unsigned int pad; /* don't use */ ++ int iface; /* interface identifier */ ++ unsigned int device; /* device/client number */ ++ unsigned int subdevice; /* subdevice (substream) number */ ++ unsigned char name[44]; /* ASCII name of item */ ++ unsigned int index; /* index of item */ ++} emu10k1_ctl_elem_id_t; ++ ++typedef struct { ++ emu10k1_ctl_elem_id_t id; /* full control ID definition */ ++ unsigned int vcount; /* visible count */ ++ unsigned int count; /* count of GPR (1..16) */ ++ unsigned short gpr[32]; /* GPR number(s) */ ++ unsigned int value[32]; /* initial values */ ++ unsigned int min; /* minimum range */ ++ unsigned int max; /* maximum range */ ++ unsigned int translation; /* translation type (EMU10K1_GPR_TRANSLATION*) */ ++ unsigned int *tlv; ++} emu10k1_fx8010_control_gpr_t; ++ ++typedef struct { ++ char name[128]; ++ ++ unsigned long gpr_valid[0x200/(sizeof(unsigned long)*8)]; /* bitmask of valid initializers */ ++ uint32_t *gpr_map; /* initializers */ ++ ++ unsigned int gpr_add_control_count; /* count of GPR controls to add/replace */ ++ emu10k1_fx8010_control_gpr_t *gpr_add_controls; /* GPR controls to add/replace */ ++ ++ unsigned int gpr_del_control_count; /* count of GPR controls to remove */ ++ emu10k1_ctl_elem_id_t *gpr_del_controls; /* IDs of GPR controls to remove */ ++ ++ unsigned int gpr_list_control_count; /* count of GPR controls to list */ ++ unsigned int gpr_list_control_total; /* total count of GPR controls */ ++ emu10k1_fx8010_control_gpr_t *gpr_list_controls; /* listed GPR controls */ ++ ++ unsigned long tram_valid[0x100/(sizeof(unsigned long)*8)]; /* bitmask of valid initializers */ ++ uint32_t *tram_data_map; /* data initializers */ ++ uint32_t *tram_addr_map; /* map initializers */ ++ ++ unsigned long code_valid[1024/(sizeof(unsigned long)*8)]; /* bitmask of valid instructions */ ++ uint32_t *code; /* one instruction - 64 bits */ ++} emu10k1_fx8010_code_t; ++ ++typedef struct { ++ unsigned int address; /* 31.bit == 1 -> external TRAM */ ++ unsigned int size; /* size in samples (4 bytes) */ ++ unsigned int *samples; /* pointer to samples (20-bit) */ ++ /* NULL->clear memory */ ++} emu10k1_fx8010_tram_t; ++ ++typedef struct { ++ unsigned int substream; /* substream number */ ++ unsigned int res1; /* reserved */ ++ unsigned int channels; /* 16-bit channels count, zero = remove this substream */ ++ unsigned int tram_start; /* ring buffer position in TRAM (in samples) */ ++ unsigned int buffer_size; /* count of buffered samples */ ++ unsigned short gpr_size; /* GPR containing size of ringbuffer in samples (host) */ ++ unsigned short gpr_ptr; /* GPR containing current pointer in the ring buffer (host = reset, FX8010) */ ++ unsigned short gpr_count; /* GPR containing count of samples between two interrupts (host) */ ++ unsigned short gpr_tmpcount; /* GPR containing current count of samples to interrupt (host = set, FX8010) */ ++ unsigned short gpr_trigger; /* GPR containing trigger (activate) information (host) */ ++ unsigned short gpr_running; /* GPR containing info if PCM is running (FX8010) */ ++ unsigned char pad; /* reserved */ ++ unsigned char etram[32]; /* external TRAM address & data (one per channel) */ ++ unsigned int res2; /* reserved */ ++} emu10k1_fx8010_pcm_t; ++ ++typedef enum { ++ Digiface, ++ Multiface, ++ H9652, ++ H9632, ++ Undefined, ++} HDSP_IO_Type; ++ ++typedef struct _snd_hdsp_peak_rms hdsp_peak_rms_t; ++ ++struct _snd_hdsp_peak_rms { ++ uint32_t input_peaks[26]; ++ uint32_t playback_peaks[26]; ++ uint32_t output_peaks[28]; ++ uint64_t input_rms[26]; ++ uint64_t playback_rms[26]; ++ /* These are only used for H96xx cards */ ++ uint64_t output_rms[26]; ++}; ++ ++typedef struct _snd_hdsp_config_info hdsp_config_info_t; ++ ++struct _snd_hdsp_config_info { ++ unsigned char pref_sync_ref; ++ unsigned char wordclock_sync_check; ++ unsigned char spdif_sync_check; ++ unsigned char adatsync_sync_check; ++ unsigned char adat_sync_check[3]; ++ unsigned char spdif_in; ++ unsigned char spdif_out; ++ unsigned char spdif_professional; ++ unsigned char spdif_emphasis; ++ unsigned char spdif_nonaudio; ++ unsigned int spdif_sample_rate; ++ unsigned int system_sample_rate; ++ unsigned int autosync_sample_rate; ++ unsigned char system_clock_mode; ++ unsigned char clock_source; ++ unsigned char autosync_ref; ++ unsigned char line_out; ++ unsigned char passthru; ++ unsigned char da_gain; ++ unsigned char ad_gain; ++ unsigned char phone_gain; ++ unsigned char xlr_breakout_cable; ++ unsigned char analog_extension_board; ++}; ++ ++typedef struct _snd_hdsp_firmware hdsp_firmware_t; ++ ++struct _snd_hdsp_firmware { ++ void *firmware_data; /* 24413 x 4 bytes */ ++}; ++ ++typedef struct _snd_hdsp_version hdsp_version_t; ++ ++struct _snd_hdsp_version { ++ HDSP_IO_Type io_type; ++ unsigned short firmware_rev; ++}; ++ ++typedef struct _snd_hdsp_mixer hdsp_mixer_t; ++ ++struct _snd_hdsp_mixer { ++ unsigned short matrix[HDSP_MATRIX_MIXER_SIZE]; ++}; ++ ++typedef struct _snd_hdsp_9632_aeb hdsp_9632_aeb_t; ++ ++struct _snd_hdsp_9632_aeb { ++ int aebi; ++ int aebo; ++}; ++ ++typedef struct snd_sb_csp_mc_header { ++ char codec_name[16]; /* id name of codec */ ++ unsigned short func_req; /* requested function */ ++} snd_sb_csp_mc_header_t; ++ ++typedef struct snd_sb_csp_microcode { ++ snd_sb_csp_mc_header_t info; ++ unsigned char data[SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE]; ++} snd_sb_csp_microcode_t; ++ ++typedef struct snd_sb_csp_start { ++ int sample_width; /* sample width, look above */ ++ int channels; /* channels, look above */ ++} snd_sb_csp_start_t; ++ ++typedef struct snd_sb_csp_info { ++ char codec_name[16]; /* id name of codec */ ++ unsigned short func_nr; /* function number */ ++ unsigned int acc_format; /* accepted PCM formats */ ++ unsigned short acc_channels; /* accepted channels */ ++ unsigned short acc_width; /* accepted sample width */ ++ unsigned short acc_rates; /* accepted sample rates */ ++ unsigned short csp_mode; /* CSP mode, see above */ ++ unsigned short run_channels; /* current channels */ ++ unsigned short run_width; /* current sample width */ ++ unsigned short version; /* version id: 0x10 - 0x1f */ ++ unsigned short state; /* state bits */ ++} snd_sb_csp_info_t; ++ ++struct sscape_bootblock ++{ ++ unsigned char code[256]; ++ unsigned version; ++}; ++ ++struct sscape_microcode ++{ ++ unsigned char *code; ++}; +diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h +index 2d45753..77ae416 100644 +--- a/linux-user/syscall_defs.h ++++ b/linux-user/syscall_defs.h +@@ -2161,3 +2161,4 @@ struct target_mq_attr { + #define FUTEX_CLOCK_REALTIME 256 + #define FUTEX_CMD_MASK ~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME) + ++#include "ioctls_alsa_structs.h" +diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h +index 340dbd3..1b92423 100644 +--- a/linux-user/syscall_types.h ++++ b/linux-user/syscall_types.h +@@ -80,6 +80,11 @@ STRUCT(count_info, + STRUCT(mixer_info, + MK_ARRAY(TYPE_CHAR, 16), MK_ARRAY(TYPE_CHAR, 32), TYPE_INT, MK_ARRAY(TYPE_INT, 10)) + ++/* FIXME: including these on x86 / x86_64 breaks qemu-i386 */ ++#ifdef __powerpc__ ++#include "syscall_types_alsa.h" ++#endif ++ + /* loop device ioctls */ + STRUCT(loop_info, + TYPE_INT, /* lo_number */ +diff --git a/linux-user/syscall_types_alsa.h b/linux-user/syscall_types_alsa.h +new file mode 100644 +index 0000000..6dbc964 +--- /dev/null ++++ b/linux-user/syscall_types_alsa.h +@@ -0,0 +1,1337 @@ ++/* ++ * Advanced Linux Sound Architecture ++ * ++ * This program is free software, you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY, without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * aTYPE_LONG, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ */ ++ ++STRUCT (sndrv_pcm_sframes, TYPE_LONG) ++STRUCT (sndrv_seq_event_type, TYPE_CHAR) ++STRUCT (sndrv_seq_instr_cluster, TYPE_INT) ++STRUCT (sndrv_seq_position, TYPE_INT) ++STRUCT (sndrv_seq_frequency, TYPE_INT) ++STRUCT (sndrv_seq_tick_time, TYPE_INT) ++STRUCT (sndrv_seq_instr_size, TYPE_INT) ++STRUCT (sndrv_pcm_uframes, TYPE_ULONG) ++ ++ ++STRUCT (timespec, ++ TYPE_LONG, ++ TYPE_LONG ++ ) ++ ++STRUCT( fm_operator, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR ++) ++ ++STRUCT(fm_instrument, ++ MK_ARRAY(TYPE_INT, 4), /* share id - zero = no sharing */ ++ TYPE_CHAR, /* instrument type */ ++ ++ MK_ARRAY(MK_STRUCT(STRUCT_fm_operator), 4), ++ MK_ARRAY(TYPE_CHAR, 2), ++ ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR ++) ++ ++STRUCT( fm_xoperator, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR ++) ++ ++STRUCT( fm_xinstrument, ++ TYPE_INT, /* structure type */ ++ ++ MK_ARRAY(TYPE_INT, 4), /* share id - zero = no sharing */ ++ TYPE_CHAR, /* instrument type */ ++ ++ MK_ARRAY(MK_STRUCT(STRUCT_fm_xoperator), 4), /* fm operators */ ++ MK_ARRAY(TYPE_CHAR, 2), ++ ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR ++) ++ ++STRUCT( gf1_wave, ++ MK_ARRAY(TYPE_INT, 4), /* share id - zero = no sharing */ ++ TYPE_INT, /* wave format */ ++ ++ TYPE_INT, /* some other ID for this instrument */ ++ TYPE_INT, /* begin of waveform in onboard memory */ ++ TYPE_PTRVOID, /* poTYPE_INTer to waveform in system memory */ ++ ++ TYPE_INT, /* size of waveform in samples */ ++ TYPE_INT, /* start offset in samples * 16 (lowest 4 bits - fraction) */ ++ TYPE_INT, /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */ ++ TYPE_INT, /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ ++ TYPE_SHORT, /* loop repeat - 0 = forever */ ++ ++ TYPE_CHAR, /* GF1 patch flags */ ++ TYPE_CHAR, ++ TYPE_INT, /* sample rate in Hz */ ++ TYPE_INT, /* low frequency range */ ++ TYPE_INT, /* high frequency range */ ++ TYPE_INT, /* root frequency range */ ++ TYPE_SHORT, ++ TYPE_CHAR, ++ MK_ARRAY(TYPE_CHAR, 6), ++ MK_ARRAY(TYPE_CHAR, 6), ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_SHORT, ++ TYPE_SHORT, /* 0-2048 or 0-2 */ ++ ++ TYPE_PTRVOID ++) ++ ++STRUCT(gf1_instrument, ++ TYPE_SHORT, ++ TYPE_SHORT, /* 0 - none, 1-65535 */ ++ ++ TYPE_CHAR, /* effect 1 */ ++ TYPE_CHAR, /* 0-127 */ ++ TYPE_CHAR, /* effect 2 */ ++ TYPE_CHAR, /* 0-127 */ ++ ++ TYPE_PTRVOID /* first waveform */ ++) ++ ++STRUCT( gf1_xwave, ++ TYPE_INT, /* structure type */ ++ ++ MK_ARRAY(TYPE_INT, 4), /* share id - zero = no sharing */ ++ TYPE_INT, /* wave format */ ++ ++ TYPE_INT, /* size of waveform in samples */ ++ TYPE_INT, /* start offset in samples * 16 (lowest 4 bits - fraction) */ ++ TYPE_INT, /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */ ++ TYPE_INT, /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ ++ TYPE_SHORT, /* loop repeat - 0 = forever */ ++ ++ TYPE_CHAR, /* GF1 patch flags */ ++ TYPE_CHAR, ++ TYPE_INT, /* sample rate in Hz */ ++ TYPE_INT, /* low frequency range */ ++ TYPE_INT, /* high frequency range */ ++ TYPE_INT, /* root frequency range */ ++ TYPE_SHORT, ++ TYPE_CHAR, ++ MK_ARRAY(TYPE_CHAR, 6), ++ MK_ARRAY(TYPE_CHAR, 6), ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_SHORT, ++ TYPE_SHORT /* 0-2048 or 0-2 */ ++) ++ ++STRUCT( gf1_xinstrument, ++ TYPE_INT, ++ ++ TYPE_SHORT, ++ TYPE_SHORT, /* 0 - none, 1-65535 */ ++ ++ TYPE_CHAR, /* effect 1 */ ++ TYPE_CHAR, /* 0-127 */ ++ TYPE_CHAR, /* effect 2 */ ++ TYPE_CHAR /* 0-127 */ ++) ++ ++STRUCT( gf1_info, ++ TYPE_CHAR, /* supported wave flags */ ++ MK_ARRAY(TYPE_CHAR, 3), ++ TYPE_INT, /* supported features */ ++ TYPE_INT, /* maximum 8-bit wave length */ ++ TYPE_INT /* maximum 16-bit wave length */ ++) ++ ++STRUCT( iwffff_wave, ++ MK_ARRAY(TYPE_INT, 4), /* share id - zero = no sharing */ ++ TYPE_INT, /* wave format */ ++ ++ TYPE_INT, /* some other ID for this wave */ ++ TYPE_INT, /* begin of waveform in onboard memory */ ++ TYPE_PTRVOID, /* poTYPE_INTer to waveform in system memory */ ++ ++ TYPE_INT, /* size of waveform in samples */ ++ TYPE_INT, /* start offset in samples * 16 (lowest 4 bits - fraction) */ ++ TYPE_INT, /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */ ++ TYPE_INT, /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ ++ TYPE_SHORT, /* loop repeat - 0 = forever */ ++ TYPE_INT, /* sample ratio (44100 * 1024 / rate) */ ++ TYPE_CHAR, /* 0 - 127 (no corresponding midi controller) */ ++ TYPE_CHAR, /* lower frequency range for this waveform */ ++ TYPE_CHAR, /* higher frequency range for this waveform */ ++ TYPE_CHAR, ++ ++ TYPE_PTRVOID ++) ++ ++STRUCT( iwffff_lfo, ++ TYPE_SHORT, /* (0-2047) 0.01Hz - 21.5Hz */ ++ TYPE_SHORT, /* volume +- (0-255) 0.48675dB/step */ ++ TYPE_SHORT, /* 0 - 950 deciseconds */ ++ TYPE_CHAR, /* see to IWFFFF_LFO_SHAPE_XXXX */ ++ TYPE_CHAR /* 0 - 255 deciseconds */ ++) ++ ++STRUCT( iwffff_env_point, ++ TYPE_SHORT, ++ TYPE_SHORT ++) ++ ++STRUCT( iwffff_env_record, ++ TYPE_SHORT, ++ TYPE_SHORT, ++ TYPE_SHORT, ++ TYPE_SHORT, ++ TYPE_SHORT, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_PTRVOID ++) ++ ++STRUCT( iwffff_env, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_PTRVOID // MK_STRUCT(STRUCT_iwffff_env_record) ++) ++ ++STRUCT( iwffff_layer, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, /* range for layer based */ ++ TYPE_CHAR, /* on either velocity or frequency */ ++ TYPE_CHAR, /* pan offset from CC1 (0 left - 127 right) */ ++ TYPE_CHAR, /* position based on frequency (0-127) */ ++ TYPE_CHAR, /* 0-127 (no corresponding midi controller) */ ++ MK_STRUCT(STRUCT_iwffff_lfo), /* tremolo effect */ ++ MK_STRUCT(STRUCT_iwffff_lfo), /* vibrato effect */ ++ TYPE_SHORT, /* 0-2048, 1024 is equal to semitone scaling */ ++ TYPE_CHAR, /* center for keyboard frequency scaling */ ++ TYPE_CHAR, ++ MK_STRUCT(STRUCT_iwffff_env), /* pitch envelope */ ++ MK_STRUCT(STRUCT_iwffff_env), /* volume envelope */ ++ ++ TYPE_PTRVOID, // iwffff_wave_t *wave, ++ TYPE_PTRVOID // MK_STRUCT(STRUCT_iwffff_layer) ++) ++ ++STRUCT(iwffff_instrument, ++ TYPE_SHORT, ++ TYPE_SHORT, ++ TYPE_SHORT, /* 0 - none, 1-65535 */ ++ ++ TYPE_CHAR, /* effect 1 */ ++ TYPE_CHAR, /* 0-127 */ ++ TYPE_CHAR, /* effect 2 */ ++ TYPE_CHAR, /* 0-127 */ ++ ++ TYPE_PTRVOID // iwffff_layer_t *layer, /* first layer */ ++) ++ ++STRUCT( iwffff_xwave, ++ TYPE_INT, /* structure type */ ++ ++ MK_ARRAY(TYPE_INT, 4), /* share id - zero = no sharing */ ++ ++ TYPE_INT, /* wave format */ ++ TYPE_INT, /* offset to ROM (address) */ ++ ++ TYPE_INT, /* size of waveform in samples */ ++ TYPE_INT, /* start offset in samples * 16 (lowest 4 bits - fraction) */ ++ TYPE_INT, /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */ ++ TYPE_INT, /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ ++ TYPE_SHORT, /* loop repeat - 0 = forever */ ++ TYPE_INT, /* sample ratio (44100 * 1024 / rate) */ ++ TYPE_CHAR, /* 0 - 127 (no corresponding midi controller) */ ++ TYPE_CHAR, /* lower frequency range for this waveform */ ++ TYPE_CHAR, /* higher frequency range for this waveform */ ++ TYPE_CHAR ++) ++ ++STRUCT( iwffff_xlfo, ++ TYPE_SHORT, /* (0-2047) 0.01Hz - 21.5Hz */ ++ TYPE_SHORT, /* volume +- (0-255) 0.48675dB/step */ ++ TYPE_SHORT, /* 0 - 950 deciseconds */ ++ TYPE_CHAR, /* see to ULTRA_IW_LFO_SHAPE_XXXX */ ++ TYPE_CHAR /* 0 - 255 deciseconds */ ++) ++ ++STRUCT( iwffff_xenv_point, ++ TYPE_SHORT, ++ TYPE_SHORT ++) ++ ++STRUCT( iwffff_xenv_record, ++ TYPE_INT, ++ TYPE_SHORT, ++ TYPE_SHORT, ++ TYPE_SHORT, ++ TYPE_SHORT, ++ TYPE_SHORT, ++ TYPE_CHAR, ++ TYPE_CHAR ++) ++ ++STRUCT( iwffff_xenv, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR ++) ++ ++STRUCT( iwffff_xlayer, ++ TYPE_INT, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, /* range for layer based */ ++ TYPE_CHAR, /* on either velocity or frequency */ ++ TYPE_CHAR, /* pan offset from CC1 (0 left - 127 right) */ ++ TYPE_CHAR, /* position based on frequency (0-127) */ ++ TYPE_CHAR, /* 0-127 (no corresponding midi controller) */ ++ MK_STRUCT(STRUCT_iwffff_xlfo), /* tremolo effect */ ++ MK_STRUCT(STRUCT_iwffff_xlfo), /* vibrato effect */ ++ TYPE_SHORT, /* 0-2048, 1024 is equal to semitone scaling */ ++ TYPE_CHAR, /* center for keyboard frequency scaling */ ++ TYPE_CHAR, ++ MK_STRUCT(STRUCT_iwffff_xenv), /* pitch envelope */ ++ MK_STRUCT(STRUCT_iwffff_xenv) /* volume envelope */ ++) ++ ++STRUCT( iwffff_xinstrument, ++ TYPE_INT, ++ ++ TYPE_SHORT, ++ TYPE_SHORT, ++ TYPE_SHORT, /* 0 - none, 1-65535 */ ++ ++ TYPE_CHAR, /* effect 1 */ ++ TYPE_CHAR, /* 0-127 */ ++ TYPE_CHAR, /* effect 2 */ ++ TYPE_CHAR /* 0-127 */ ++) ++ ++STRUCT(iwffff_rom_header, ++ MK_ARRAY(TYPE_CHAR, 8), ++ TYPE_CHAR, ++ TYPE_CHAR, ++ MK_ARRAY(TYPE_CHAR, 16), ++ MK_ARRAY(TYPE_CHAR, 10), ++ TYPE_SHORT, ++ TYPE_SHORT, ++ TYPE_INT, ++ MK_ARRAY(TYPE_CHAR, 128), ++ MK_ARRAY(TYPE_CHAR, 64), ++ MK_ARRAY(TYPE_CHAR, 128) ++) ++ ++STRUCT( iwffff_info, ++ TYPE_INT, /* supported format bits */ ++ TYPE_INT, /* supported effects (1 << IWFFFF_EFFECT*) */ ++ TYPE_INT, /* LFO effects */ ++ TYPE_INT, /* maximum 8-bit wave length */ ++ TYPE_INT /* maximum 16-bit wave length */ ++) ++ ++STRUCT( simple_instrument_info, ++ TYPE_INT, /* supported format bits */ ++ TYPE_INT, /* supported effects (1 << SIMPLE_EFFECT_*) */ ++ TYPE_INT, /* maximum 8-bit wave length */ ++ TYPE_INT /* maximum 16-bit wave length */ ++) ++ ++STRUCT(simple_instrument, ++ MK_ARRAY(TYPE_INT, 4), /* share id - zero = no sharing */ ++ TYPE_INT, /* wave format */ ++ ++ TYPE_INT, /* some other ID for this instrument */ ++ TYPE_INT, /* begin of waveform in onboard memory */ ++ TYPE_PTRVOID, /* poTYPE_INTer to waveform in system memory */ ++ ++ TYPE_INT, /* size of waveform in samples */ ++ TYPE_INT, /* start offset in samples * 16 (lowest 4 bits - fraction) */ ++ TYPE_INT, /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ ++ TYPE_INT, /* loop end offset in samples * 16 (lowest 4 bits - fraction) */ ++ TYPE_SHORT, /* loop repeat - 0 = forever */ ++ ++ TYPE_CHAR, /* effect 1 */ ++ TYPE_CHAR, /* 0-127 */ ++ TYPE_CHAR, /* effect 2 */ ++ TYPE_CHAR /* 0-127 */ ++) ++ ++STRUCT( simple_xinstrument, ++ TYPE_INT, ++ ++ MK_ARRAY(TYPE_INT, 4), /* share id - zero = no sharing */ ++ TYPE_INT, /* wave format */ ++ ++ TYPE_INT, /* size of waveform in samples */ ++ TYPE_INT, /* start offset in samples * 16 (lowest 4 bits - fraction) */ ++ TYPE_INT, /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */ ++ TYPE_INT, /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ ++ TYPE_SHORT, /* loop repeat - 0 = forever */ ++ ++ TYPE_CHAR, /* effect 1 */ ++ TYPE_CHAR, /* 0-127 */ ++ TYPE_CHAR, /* effect 2 */ ++ TYPE_CHAR /* 0-127 */ ++) ++ ++/** event address */ ++STRUCT( sndrv_seq_addr, ++ TYPE_CHAR, /**< Client number: 0..255, 255 = broadcast to all clients */ ++ TYPE_CHAR /**< Port within client: 0..255, 255 = broadcast to all ports */ ++) ++ ++/** port connection */ ++STRUCT( sndrv_seq_connect, ++ MK_STRUCT(STRUCT_sndrv_seq_addr), ++ MK_STRUCT(STRUCT_sndrv_seq_addr) ++) ++ ++STRUCT( sndrv_seq_ev_note, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, /* only for SNDRV_SEQ_EVENT_NOTE */ ++ TYPE_INT /* only for SNDRV_SEQ_EVENT_NOTE */ ++) ++ ++ /* controller event */ ++STRUCT( sndrv_seq_ev_ctrl, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, /* pad */ ++ TYPE_INT, ++ TYPE_INT ++) ++ ++ /* generic set of bytes (12x8 bit) */ ++STRUCT( sndrv_seq_ev_raw8, ++ MK_ARRAY(TYPE_CHAR, 12) /* 8 bit value */ ++) ++ ++ /* generic set of TYPE_INTegers (3x32 bit) */ ++STRUCT( sndrv_seq_ev_raw32, ++ MK_ARRAY(TYPE_INT, 3) /* 32 bit value */ ++) ++ ++ /* external stored data */ ++STRUCT( sndrv_seq_ev_ext, ++ TYPE_INT, /* length of data */ ++ TYPE_PTRVOID /* poTYPE_INTer to data (note: maybe 64-bit) */ ++) ++ ++/* Instrument type */ ++STRUCT( sndrv_seq_instr, ++ TYPE_INT, ++ TYPE_INT, /* the upper byte means a private instrument (owner - client #) */ ++ TYPE_SHORT, ++ TYPE_SHORT ++) ++ ++ /* sample number */ ++STRUCT( sndrv_seq_ev_sample, ++ TYPE_INT, ++ TYPE_SHORT, ++ TYPE_SHORT ++) ++ ++ /* sample cluster */ ++STRUCT( sndrv_seq_ev_cluster, ++ TYPE_INT ++) ++ ++ /* sample volume control, if any value is set to -1 == do not change */ ++STRUCT( sndrv_seq_ev_volume, ++ TYPE_SHORT, /* range: 0-16383 */ ++ TYPE_SHORT, /* left-right balance, range: 0-16383 */ ++ TYPE_SHORT, /* front-rear balance, range: 0-16383 */ ++ TYPE_SHORT /* down-up balance, range: 0-16383 */ ++) ++ ++ /* simple loop redefinition */ ++STRUCT( sndrv_seq_ev_loop, ++ TYPE_INT, /* loop start (in samples) * 16 */ ++ TYPE_INT /* loop end (in samples) * 16 */ ++) ++ ++STRUCT( sndrv_seq_ev_sample_control, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, /* pad */ ++ MK_ARRAY(TYPE_INT, 2) ++) ++ ++ ++ ++/* INSTR_BEGIN event */ ++STRUCT( sndrv_seq_ev_instr_begin, ++ TYPE_INT ++) ++ ++STRUCT( sndrv_seq_result, ++ TYPE_INT, ++ TYPE_INT ++) ++ ++ ++STRUCT( sndrv_seq_real_time, ++ TYPE_INT, ++ TYPE_INT ++) ++ ++STRUCT( sndrv_seq_queue_skew, ++ TYPE_INT, ++ TYPE_INT ++) ++ ++ /* queue timer control */ ++STRUCT( sndrv_seq_ev_queue_control, ++ TYPE_CHAR, /* affected queue */ ++ MK_ARRAY(TYPE_CHAR, 3), /* reserved */ ++ MK_ARRAY(TYPE_INT, 2) ++) ++ ++ /* quoted event - inside the kernel only */ ++STRUCT( sndrv_seq_ev_quote, ++ MK_STRUCT(STRUCT_sndrv_seq_addr), /* original sender */ ++ TYPE_SHORT, /* optional data */ ++ MK_STRUCT(STRUCT_sndrv_seq_event) /* quoted event */ ++) ++ ++ ++ /* sequencer event */ ++STRUCT( sndrv_seq_event, ++ TYPE_CHAR, /* event type */ ++ TYPE_CHAR, /* event flags */ ++ TYPE_CHAR, ++ ++ TYPE_CHAR, /* schedule queue */ ++ MK_STRUCT(STRUCT_sndrv_seq_real_time), /* schedule time */ ++ ++ ++ MK_STRUCT(STRUCT_sndrv_seq_addr), /* source address */ ++ MK_STRUCT(STRUCT_sndrv_seq_addr), /* destination address */ ++ ++ MK_ARRAY(TYPE_INT,3) ++) ++ ++ ++/* ++ * bounce event - stored as variable size data ++ */ ++STRUCT( sndrv_seq_event_bounce, ++ TYPE_INT, ++ MK_STRUCT(STRUCT_sndrv_seq_event) ++ /* external data follows here. */ ++) ++ ++STRUCT( sndrv_seq_system_info, ++ TYPE_INT, /* maximum queues count */ ++ TYPE_INT, /* maximum clients count */ ++ TYPE_INT, /* maximum ports per client */ ++ TYPE_INT, /* maximum channels per port */ ++ TYPE_INT, /* current clients */ ++ TYPE_INT, /* current queues */ ++ MK_ARRAY(TYPE_CHAR, 24) ++) ++ ++STRUCT( sndrv_seq_running_info, ++ TYPE_CHAR, /* client id */ ++ TYPE_CHAR, /* 1 = big-endian */ ++ TYPE_CHAR, ++ TYPE_CHAR, /* reserved */ ++ MK_ARRAY(TYPE_CHAR, 12) ++) ++ ++STRUCT( sndrv_seq_client_info, ++ TYPE_INT, /* client number to inquire */ ++ TYPE_INT, /* client type */ ++ MK_ARRAY(TYPE_CHAR, 64), /* client name */ ++ TYPE_INT, /* filter flags */ ++ MK_ARRAY(TYPE_CHAR, 8), /* multicast filter bitmap */ ++ MK_ARRAY(TYPE_CHAR, 32), /* event filter bitmap */ ++ TYPE_INT, /* RO: number of ports */ ++ TYPE_INT, /* number of lost events */ ++ MK_ARRAY(TYPE_CHAR, 64) /* for future use */ ++) ++ ++STRUCT( sndrv_seq_client_pool, ++ TYPE_INT, /* client number to inquire */ ++ TYPE_INT, /* outgoing (write) pool size */ ++ TYPE_INT, /* incoming (read) pool size */ ++ TYPE_INT, /* minimum free pool size for select/blocking mode */ ++ TYPE_INT, /* unused size */ ++ TYPE_INT, /* unused size */ ++ MK_ARRAY(TYPE_CHAR, 64) ++) ++ ++STRUCT( sndrv_seq_remove_events, ++ TYPE_INT, /* Flags that determine what gets removed */ ++ ++ MK_STRUCT(STRUCT_sndrv_seq_real_time), ++ ++ TYPE_CHAR, /* Queue for REMOVE_DEST */ ++ MK_STRUCT(STRUCT_sndrv_seq_addr), /* Address for REMOVE_DEST */ ++ TYPE_CHAR, /* Channel for REMOVE_DEST */ ++ ++ TYPE_INT, /* For REMOVE_EVENT_TYPE */ ++ TYPE_CHAR, /* Tag for REMOVE_TAG */ ++ ++ MK_ARRAY(TYPE_INT, 10) /* To allow for future binary compatibility */ ++ ++) ++ ++STRUCT( sndrv_seq_port_info, ++ MK_STRUCT(STRUCT_sndrv_seq_addr), /* client/port numbers */ ++ MK_ARRAY(TYPE_CHAR, 64), /* port name */ ++ ++ TYPE_INT, /* port capability bits */ ++ TYPE_INT, /* port type bits */ ++ TYPE_INT, /* channels per MIDI port */ ++ TYPE_INT, /* voices per MIDI port */ ++ TYPE_INT, /* voices per SYNTH port */ ++ ++ TYPE_INT, /* R/O: subscribers for output (from this port) */ ++ TYPE_INT, /* R/O: subscribers for input (to this port) */ ++ ++ TYPE_PTRVOID, /* reserved for kernel use (must be NULL) */ ++ TYPE_INT, /* misc. conditioning */ ++ TYPE_CHAR, /* queue # for timestamping */ ++ MK_ARRAY(TYPE_CHAR, 59) /* for future use */ ++) ++ ++STRUCT( sndrv_seq_queue_info, ++ TYPE_INT, /* queue id */ ++ ++ /* ++ * security settings, only owner of this queue can start/stop timer ++ * etc. if the queue is locked for other clients ++ */ ++ TYPE_INT, /* client id for owner of the queue */ ++ TYPE_INT, /* timing queue locked for other queues */ ++ MK_ARRAY(TYPE_CHAR, 64), /* name of this queue */ ++ TYPE_INT, /* flags */ ++ MK_ARRAY(TYPE_CHAR, 60) /* for future use */ ++ ++) ++ ++STRUCT( sndrv_seq_queue_status, ++ TYPE_INT, /* queue id */ ++ TYPE_INT, /* read-only - queue size */ ++ TYPE_INT, /* current tick */ ++ MK_STRUCT(STRUCT_sndrv_seq_real_time), /* current time */ ++ TYPE_INT, /* running state of queue */ ++ TYPE_INT, /* various flags */ ++ MK_ARRAY(TYPE_CHAR, 64) /* for the future */ ++) ++ ++STRUCT( sndrv_seq_queue_tempo, ++ TYPE_INT, /* sequencer queue */ ++ TYPE_INT, ++ TYPE_INT, ++ TYPE_INT, /* queue skew */ ++ TYPE_INT, /* queue skew base */ ++ MK_ARRAY(TYPE_CHAR, 24) /* for the future */ ++) ++ ++STRUCT( sndrv_timer_id, ++ TYPE_INT, ++ TYPE_INT, ++ TYPE_INT, ++ TYPE_INT, ++ TYPE_INT ++) ++ ++STRUCT( sndrv_seq_queue_timer, ++ TYPE_INT, /* sequencer queue */ ++ TYPE_INT, /* source timer type */ ++ MK_STRUCT(STRUCT_sndrv_timer_id), /* ALSA's timer ID */ ++ TYPE_INT, /* resolution in Hz */ ++ MK_ARRAY(TYPE_CHAR, 64) /* for the future use */ ++) ++ ++STRUCT( sndrv_seq_queue_client, ++ TYPE_INT, /* sequencer queue */ ++ TYPE_INT, /* sequencer client */ ++ TYPE_INT, /* queue is used with this client ++ (must be set for accepting events) */ ++ /* per client watermarks */ ++ MK_ARRAY(TYPE_CHAR, 64) /* for future use */ ++) ++ ++STRUCT( sndrv_seq_port_subscribe, ++ MK_STRUCT(STRUCT_sndrv_seq_addr), /* sender address */ ++ MK_STRUCT(STRUCT_sndrv_seq_addr), /* destination address */ ++ TYPE_INT, /* number of voices to be allocated (0 = don't care) */ ++ TYPE_INT, /* modes */ ++ TYPE_CHAR, /* input time-stamp queue (optional) */ ++ MK_ARRAY(TYPE_CHAR, 3), /* reserved */ ++ MK_ARRAY(TYPE_CHAR, 64) ++) ++ ++STRUCT( sndrv_seq_query_subs, ++ MK_STRUCT(STRUCT_sndrv_seq_addr), /* client/port id to be searched */ ++ TYPE_INT, /* READ or WRITE */ ++ TYPE_INT, /* 0..N-1 */ ++ TYPE_INT, /* R/O: number of subscriptions on this port */ ++ MK_STRUCT(STRUCT_sndrv_seq_addr), /* R/O: result */ ++ TYPE_CHAR, /* R/O: result */ ++ TYPE_INT, /* R/O: result */ ++ MK_ARRAY(TYPE_CHAR, 64) /* for future use */ ++) ++ ++STRUCT( sndrv_seq_instr_info, ++ TYPE_INT, /* operation result */ ++ MK_ARRAY(TYPE_INT, 8), /* bitmap of supported formats */ ++ TYPE_INT, /* count of RAM banks */ ++ MK_ARRAY(TYPE_INT, 16), /* size of RAM banks */ ++ TYPE_INT, /* count of ROM banks */ ++ MK_ARRAY(TYPE_INT, 8), /* size of ROM banks */ ++ MK_ARRAY(TYPE_CHAR, 128) ++) ++ ++STRUCT( sndrv_seq_instr_status, ++ TYPE_INT, /* operation result */ ++ MK_ARRAY(TYPE_INT, 16), /* free RAM in banks */ ++ TYPE_INT, /* count of downloaded instruments */ ++ MK_ARRAY(TYPE_CHAR, 128) ++) ++ ++STRUCT( sndrv_seq_instr_format_info, ++ MK_ARRAY(TYPE_CHAR, 16), /* format identifier - SNDRV_SEQ_INSTR_ID_* */ ++ TYPE_INT /* max data length (without this structure) */ ++) ++ ++STRUCT( sndrv_seq_instr_format_info_result, ++ TYPE_INT, /* operation result */ ++ MK_ARRAY(TYPE_CHAR, 16), /* format identifier */ ++ TYPE_INT /* filled data length (without this structure) */ ++) ++ ++STRUCT( sndrv_seq_instr_data, ++ MK_ARRAY(TYPE_CHAR, 32), /* instrument name */ ++ MK_ARRAY(TYPE_CHAR, 16), /* for the future use */ ++ TYPE_INT, /* instrument type */ ++ MK_STRUCT(STRUCT_sndrv_seq_instr), ++ MK_ARRAY(TYPE_CHAR, 4) /* fillup */ ++) ++ ++STRUCT( sndrv_seq_instr_header, ++ MK_STRUCT(STRUCT_sndrv_seq_instr), ++ TYPE_INT, /* get/put/free command */ ++ TYPE_INT, /* query flags (only for get) */ ++ TYPE_INT, /* real instrument data length (without header) */ ++ TYPE_INT, /* operation result */ ++ MK_ARRAY(TYPE_CHAR, 16), /* for the future */ ++ MK_STRUCT(STRUCT_sndrv_seq_instr_data) /* instrument data (for put/get result) */ ++) ++ ++STRUCT( sndrv_seq_instr_cluster_set, ++ TYPE_INT, /* cluster identifier */ ++ MK_ARRAY(TYPE_CHAR, 32), /* cluster name */ ++ TYPE_INT, /* cluster priority */ ++ MK_ARRAY(TYPE_CHAR, 64) /* for the future use */ ++) ++ ++STRUCT( sndrv_seq_instr_cluster_get, ++ TYPE_INT, /* cluster identifier */ ++ MK_ARRAY(TYPE_CHAR, 32), /* cluster name */ ++ TYPE_INT, /* cluster priority */ ++ MK_ARRAY(TYPE_CHAR, 64) /* for the future use */ ++) ++ ++STRUCT( snd_dm_fm_info, ++ TYPE_CHAR, ++ TYPE_CHAR ++) ++ ++STRUCT( snd_dm_fm_voice, ++ TYPE_CHAR, /* operator cell (0 or 1) */ ++ TYPE_CHAR, /* FM voice (0 to 17) */ ++ ++ TYPE_CHAR, /* amplitude modulation */ ++ TYPE_CHAR, /* vibrato effect */ ++ TYPE_CHAR, /* sustain phase */ ++ TYPE_CHAR, /* keyboard scaling */ ++ TYPE_CHAR, /* 4 bits: harmonic and multiplier */ ++ TYPE_CHAR, /* 2 bits: decrease output freq rises */ ++ TYPE_CHAR, /* 6 bits: volume */ ++ ++ TYPE_CHAR, /* 4 bits: attack rate */ ++ TYPE_CHAR, /* 4 bits: decay rate */ ++ TYPE_CHAR, /* 4 bits: sustain level */ ++ TYPE_CHAR, /* 4 bits: release rate */ ++ ++ TYPE_CHAR, /* 3 bits: feedback for op0 */ ++ TYPE_CHAR, ++ TYPE_CHAR, /* stereo left */ ++ TYPE_CHAR, /* stereo right */ ++ TYPE_CHAR /* 3 bits: waveform shape */ ++) ++ ++STRUCT( snd_dm_fm_note, ++ TYPE_CHAR, /* 0-17 voice channel */ ++ TYPE_CHAR, /* 3 bits: what octave to play */ ++ TYPE_INT, /* 10 bits: frequency number */ ++ TYPE_CHAR ++) ++ ++STRUCT( snd_dm_fm_params, ++ TYPE_CHAR, /* amplitude modulation depth (1=hi) */ ++ TYPE_CHAR, /* vibrato depth (1=hi) */ ++ TYPE_CHAR, /* keyboard split */ ++ TYPE_CHAR, /* percussion mode select */ ++ ++ /* This block is the percussion instrument data */ ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR ++) ++ ++STRUCT( sndrv_aes_iec958, ++ MK_ARRAY(TYPE_CHAR, 24), /* AES/IEC958 channel status bits */ ++ MK_ARRAY(TYPE_CHAR, 147), /* AES/IEC958 subcode bits */ ++ TYPE_CHAR, /* nothing */ ++ MK_ARRAY(TYPE_CHAR, 4) /* AES/IEC958 subframe bits */ ++) ++ ++STRUCT( sndrv_hwdep_info, ++ TYPE_INT, /* WR: device number */ ++ TYPE_INT, /* R: card number */ ++ MK_ARRAY(TYPE_CHAR, 64), /* ID (user selectable) */ ++ MK_ARRAY(TYPE_CHAR, 80), /* hwdep name */ ++ TYPE_INT, /* hwdep interface */ ++ MK_ARRAY(TYPE_CHAR, 64) /* reserved for future */ ++) ++ ++/* generic DSP loader */ ++STRUCT( sndrv_hwdep_dsp_status, ++ TYPE_INT, /* R: driver-specific version */ ++ MK_ARRAY(TYPE_CHAR, 32), /* R: driver-specific ID string */ ++ TYPE_INT, /* R: number of DSP images to transfer */ ++ TYPE_INT, /* R: bit flags indicating the loaded DSPs */ ++ TYPE_INT, /* R: 1 = initialization finished */ ++ MK_ARRAY(TYPE_CHAR, 16) /* reserved for future use */ ++) ++ ++STRUCT( sndrv_hwdep_dsp_image, ++ TYPE_INT, /* W: DSP index */ ++ MK_ARRAY(TYPE_CHAR, 64), /* W: ID (e.g. file name) */ ++ TYPE_CHAR, /* W: binary image */ ++ TYPE_LONG, /* W: size of image in bytes */ ++ TYPE_LONG /* W: driver-specific data */ ++) ++ ++STRUCT( sndrv_pcm_info, ++ TYPE_INT, /* RO/WR (control): device number */ ++ TYPE_INT, /* RO/WR (control): subdevice number */ ++ TYPE_INT, /* RO/WR (control): stream number */ ++ TYPE_INT, /* R: card number */ ++ MK_ARRAY(TYPE_CHAR, 64), /* ID (user selectable) */ ++ MK_ARRAY(TYPE_CHAR, 80), /* name of this device */ ++ MK_ARRAY(TYPE_CHAR, 32), /* subdevice name */ ++ TYPE_INT, /* SNDRV_PCM_CLASS_* */ ++ TYPE_INT, /* SNDRV_PCM_SUBCLASS_* */ ++ TYPE_INT, ++ TYPE_INT, ++ MK_ARRAY(TYPE_INT, 4), ++ ++ MK_ARRAY(TYPE_CHAR, 64) /* reserved for future... */ ++) ++ ++STRUCT( sndrv_interval, ++ TYPE_INT, ++ TYPE_INT, ++ TYPE_INTBITFIELD ++) ++ ++STRUCT( sndrv_mask, ++ MK_ARRAY(TYPE_INT, (SNDRV_MASK_MAX+31)/32) ++) ++ ++STRUCT( sndrv_pcm_hw_params, ++ TYPE_INT, ++ MK_ARRAY(MK_STRUCT(STRUCT_sndrv_mask),SNDRV_PCM_HW_PARAM_LAST_MASK - SNDRV_PCM_HW_PARAM_FIRST_MASK + 1), ++ MK_ARRAY(MK_STRUCT(STRUCT_sndrv_mask), 5), /* reserved masks */ ++ MK_ARRAY(MK_STRUCT(STRUCT_sndrv_interval), SNDRV_PCM_HW_PARAM_LAST_INTERVAL - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1), ++ MK_ARRAY(MK_STRUCT(STRUCT_sndrv_interval), 9), /* reserved intervals */ ++ TYPE_INT, /* W: requested masks */ ++ TYPE_INT, /* R: changed masks */ ++ TYPE_INT, /* R: Info flags for returned setup */ ++ TYPE_INT, /* R: used most significant bits */ ++ TYPE_INT, /* R: rate numerator */ ++ TYPE_INT, /* R: rate denominator */ ++ TYPE_LONG, /* R: chip FIFO size in frames */ ++ MK_ARRAY(TYPE_CHAR, 64) /* reserved for future */ ++) ++ ++STRUCT( sndrv_pcm_sw_params, ++ TYPE_INT, /* timestamp mode */ ++ TYPE_INT, ++ TYPE_INT, /* min ticks to sleep */ ++ TYPE_LONG, /* min avail frames for wakeup */ ++ TYPE_LONG, /* xfer size need to be a multiple */ ++ TYPE_LONG, /* min hw_avail frames for automatic start */ ++ TYPE_LONG, /* min avail frames for automatic stop */ ++ TYPE_LONG, /* min distance from noise for silence filling */ ++ TYPE_LONG, /* silence block size */ ++ TYPE_LONG, /* poTYPE_INTers wrap point */ ++ MK_ARRAY(TYPE_CHAR, 64) /* reserved for future */ ++) ++ ++STRUCT( sndrv_pcm_channel_info, ++ TYPE_INT, ++ TYPE_LONG, /* mmap offset (FIXME) */ ++ TYPE_INT, /* offset to first sample in bits */ ++ TYPE_INT /* samples distance in bits */ ++) ++ ++ ++STRUCT( sndrv_pcm_status, ++ TYPE_INT, /* stream state */ ++ MK_STRUCT(STRUCT_timespec), /* time when stream was started/stopped/paused */ ++ MK_STRUCT(STRUCT_timespec), /* reference timestamp */ ++ TYPE_LONG, /* appl ptr */ ++ TYPE_LONG, /* hw ptr */ ++ TYPE_LONG, /* current delay in frames */ ++ TYPE_LONG, /* number of frames available */ ++ TYPE_LONG, /* max frames available on hw since last status */ ++ TYPE_LONG, /* count of ADC (capture) overrange detections from last status */ ++ TYPE_INT, /* suspended stream state */ ++ MK_ARRAY(TYPE_CHAR, 60) /* must be filled with zero */ ++) ++ ++STRUCT( sndrv_pcm_mmap_status, ++ TYPE_INT, /* RO: state - SNDRV_PCM_STATE_XXXX */ ++ TYPE_INT, /* Needed for 64 bit alignment */ ++ TYPE_LONG, /* RO: hw ptr (0...boundary-1) */ ++ MK_STRUCT(STRUCT_timespec), /* Timestamp */ ++ TYPE_INT /* RO: suspended stream state */ ++) ++ ++STRUCT( sndrv_pcm_mmap_control, ++ TYPE_LONG, /* RW: appl ptr (0...boundary-1) */ ++ TYPE_LONG /* RW: min available frames for wakeup */ ++) ++ ++STRUCT( sndrv_pcm_sync_ptr, ++ TYPE_INT, ++ // FIXME: does not work with 64-bit target ++ MK_STRUCT(STRUCT_sndrv_pcm_mmap_status), // 28 bytes on 32-bit target ++ MK_ARRAY(TYPE_CHAR, 64 - 24), // so we pad to 64 bytes (was a union) ++ ++ MK_STRUCT(STRUCT_sndrv_pcm_mmap_control), // 8 bytes on 32-bit target ++ MK_ARRAY(TYPE_CHAR, 64 - 8) // so we pad to 64 bytes (was a union)) ++) ++ ++STRUCT( sndrv_xferi, ++ TYPE_LONG, ++ TYPE_PTRVOID, ++ TYPE_LONG ++) ++ ++STRUCT( sndrv_xfern, ++ TYPE_LONG, ++ TYPE_PTRVOID, ++ TYPE_LONG ++) ++ ++STRUCT( sndrv_rawmidi_info, ++ TYPE_INT, /* RO/WR (control): device number */ ++ TYPE_INT, /* RO/WR (control): subdevice number */ ++ TYPE_INT, /* WR: stream */ ++ TYPE_INT, /* R: card number */ ++ TYPE_INT, /* SNDRV_RAWMIDI_INFO_XXXX */ ++ MK_ARRAY(TYPE_CHAR, 64), /* ID (user selectable) */ ++ MK_ARRAY(TYPE_CHAR, 80), /* name of device */ ++ MK_ARRAY(TYPE_CHAR, 32), /* name of active or selected subdevice */ ++ TYPE_INT, ++ TYPE_INT, ++ MK_ARRAY(TYPE_CHAR, 64) /* reserved for future use */ ++) ++ ++STRUCT( sndrv_rawmidi_params, ++ TYPE_INT, ++ TYPE_LONG, /* queue size in bytes */ ++ TYPE_LONG, /* minimum avail bytes for wakeup */ ++ TYPE_INT, /* do not send active sensing byte in close() */ ++ MK_ARRAY(TYPE_CHAR, 16) /* reserved for future use */ ++) ++ ++STRUCT( sndrv_rawmidi_status, ++ TYPE_INT, ++ MK_STRUCT(STRUCT_timespec), /* Timestamp */ ++ TYPE_LONG, /* available bytes */ ++ TYPE_LONG, /* count of overruns since last status (in bytes) */ ++ MK_ARRAY(TYPE_CHAR, 16) /* reserved for future use */ ++) ++ ++STRUCT( sndrv_timer_ginfo, ++ MK_STRUCT(STRUCT_sndrv_timer_id), /* requested timer ID */ ++ TYPE_INT, /* timer flags - SNDRV_TIMER_FLG_* */ ++ TYPE_INT, /* card number */ ++ MK_ARRAY(TYPE_CHAR, 64), /* timer identification */ ++ MK_ARRAY(TYPE_CHAR, 80), /* timer name */ ++ TYPE_LONG, /* reserved for future use */ ++ TYPE_LONG, /* average period resolution in ns */ ++ TYPE_LONG, /* minimal period resolution in ns */ ++ TYPE_LONG, /* maximal period resolution in ns */ ++ TYPE_INT, /* active timer clients */ ++ MK_ARRAY(TYPE_CHAR, 32) ++) ++ ++STRUCT( sndrv_timer_gparams, ++ MK_STRUCT(STRUCT_sndrv_timer_id), /* requested timer ID */ ++ TYPE_LONG, /* requested precise period duration (in seconds) - numerator */ ++ TYPE_LONG, /* requested precise period duration (in seconds) - denominator */ ++ MK_ARRAY(TYPE_CHAR, 32) ++) ++ ++STRUCT( sndrv_timer_gstatus, ++ MK_STRUCT(STRUCT_sndrv_timer_id), /* requested timer ID */ ++ TYPE_LONG, /* current period resolution in ns */ ++ TYPE_LONG, /* precise current period resolution (in seconds) - numerator */ ++ TYPE_LONG, /* precise current period resolution (in seconds) - denominator */ ++ MK_ARRAY(TYPE_CHAR, 32) ++) ++ ++STRUCT( sndrv_timer_select, ++ MK_STRUCT(STRUCT_sndrv_timer_id), /* bind to timer ID */ ++ MK_ARRAY(TYPE_CHAR, 32) /* reserved */ ++) ++ ++STRUCT( sndrv_timer_info, ++ TYPE_INT, /* timer flags - SNDRV_TIMER_FLG_* */ ++ TYPE_INT, /* card number */ ++ MK_ARRAY(TYPE_CHAR, 64), /* timer identificator */ ++ MK_ARRAY(TYPE_CHAR, 80), /* timer name */ ++ TYPE_LONG, /* reserved for future use */ ++ TYPE_LONG, /* average period resolution in ns */ ++ MK_ARRAY(TYPE_CHAR, 64) /* reserved */ ++) ++ ++STRUCT( sndrv_timer_params, ++ TYPE_INT, /* flags - SNDRV_MIXER_PSFLG_* */ ++ TYPE_INT, /* requested resolution in ticks */ ++ TYPE_INT, /* total size of queue (32-1024) */ ++ TYPE_INT, ++ TYPE_INT, /* event filter (bitmask of SNDRV_TIMER_EVENT_*) */ ++ MK_ARRAY(TYPE_CHAR, 60) /* reserved */ ++) ++ ++STRUCT( sndrv_timer_status, ++ MK_STRUCT(STRUCT_timespec), /* Timestamp - last update */ ++ TYPE_INT, /* current period resolution in ns */ ++ TYPE_INT, /* counter of master tick lost */ ++ TYPE_INT, /* count of read queue overruns */ ++ TYPE_INT, /* used queue size */ ++ MK_ARRAY(TYPE_CHAR, 64) /* reserved */ ++) ++ ++STRUCT( sndrv_timer_read, ++ TYPE_INT, ++ TYPE_INT ++) ++ ++STRUCT( sndrv_timer_tread, ++ TYPE_INT, ++ MK_STRUCT(STRUCT_timespec), ++ TYPE_INT ++) ++ ++STRUCT( sndrv_ctl_card_info, ++ TYPE_INT, /* card number */ ++ TYPE_INT, /* reserved for future (was type) */ ++ MK_ARRAY(TYPE_CHAR, 16), /* ID of card (user selectable) */ ++ MK_ARRAY(TYPE_CHAR, 16), /* Driver name */ ++ MK_ARRAY(TYPE_CHAR, 32), /* Short name of soundcard */ ++ MK_ARRAY(TYPE_CHAR, 80), /* name + info text about soundcard */ ++ MK_ARRAY(TYPE_CHAR, 16), /* reserved for future (was ID of mixer) */ ++ MK_ARRAY(TYPE_CHAR, 80), /* visual mixer identification */ ++ MK_ARRAY(TYPE_CHAR, 80), /* card components / fine identification, delimited with one space (AC97 etc..) */ ++ MK_ARRAY(TYPE_CHAR, 48) /* reserved for future */ ++) ++ ++STRUCT( sndrv_ctl_elem_id, ++ TYPE_INT, ++ TYPE_INT, /* interface identifier */ ++ TYPE_INT, /* device/client number */ ++ TYPE_INT, /* subdevice (substream) number */ ++ MK_ARRAY(TYPE_CHAR, 44), /* ASCII name of item */ ++ TYPE_INT /* index of item */ ++) ++ ++STRUCT( sndrv_ctl_elem_list, ++ TYPE_INT, /* W: first element ID to get */ ++ TYPE_INT, /* W: count of element IDs to get */ ++ TYPE_INT, /* R: count of element IDs set */ ++ TYPE_INT, /* R: count of all elements */ ++ MK_STRUCT(STRUCT_sndrv_ctl_elem_id), /* R: IDs */ ++ MK_ARRAY(TYPE_CHAR, 50) ++) ++ ++STRUCT( sndrv_ctl_elem_info, ++ MK_STRUCT(STRUCT_sndrv_ctl_elem_id), /* W: element ID */ ++ TYPE_INT, /* R: value type - SNDRV_CTL_ELEM_TYPE_* */ ++ TYPE_INT, /* R: value access (bitmask) - SNDRV_CTL_ELEM_ACCESS_* */ ++ TYPE_INT, /* count of values */ ++ TYPE_INT, /* owner's PID of this control */ ++ MK_ARRAY(TYPE_CHAR, 128), // FIXME: prone to break (was union) ++ MK_ARRAY(TYPE_SHORT, 4), /* dimensions */ ++ MK_ARRAY(TYPE_CHAR, 64-4*sizeof(unsigned short)) ++) ++ ++STRUCT( sndrv_ctl_elem_value, ++ MK_STRUCT(STRUCT_sndrv_ctl_elem_id), /* W: element ID */ ++ TYPE_INT, /* W: use indirect pointer (xxx_ptr member) */ ++ MK_ARRAY(TYPE_INT, 128), ++ MK_STRUCT(STRUCT_timespec), ++ MK_ARRAY(TYPE_CHAR, 128-sizeof(struct timespec)) // FIXME: breaks on 64-bit host ++) ++ ++STRUCT( sndrv_ctl_tlv, ++ TYPE_INT, /* control element numeric identification */ ++ TYPE_INT, /* in bytes aligned to 4 */ ++ MK_ARRAY(TYPE_INT, 0) /* first TLV */ // FIXME: what is this supposed to become? ++) ++ ++STRUCT( sndrv_ctl_event, ++ TYPE_INT, /* event type - SNDRV_CTL_EVENT_* */ ++ TYPE_INT, ++ MK_STRUCT(STRUCT_sndrv_ctl_elem_id) // 64 bytes ++) ++ ++STRUCT( iovec, ++ TYPE_PTRVOID, ++ TYPE_LONG ++ ) ++ ++ ++STRUCT( sndrv_xferv, ++ MK_STRUCT(STRUCT_iovec), ++ TYPE_LONG ++) ++ ++STRUCT(emu10k1_fx8010_info, ++ TYPE_INT, /* in samples */ ++ TYPE_INT, /* in samples */ ++ MK_ARRAY(MK_ARRAY(TYPE_CHAR, 32), 16), /* names of FXBUSes */ ++ MK_ARRAY(MK_ARRAY(TYPE_CHAR, 32), 16), /* names of external inputs */ ++ MK_ARRAY(MK_ARRAY(TYPE_CHAR, 32), 32), /* names of external outputs */ ++ TYPE_INT /* count of GPR controls */ ++) ++ ++STRUCT(emu10k1_ctl_elem_id, ++ TYPE_INT, /* don't use */ ++ TYPE_INT, /* interface identifier */ ++ TYPE_INT, /* device/client number */ ++ TYPE_INT, /* subdevice (substream) number */ ++ MK_ARRAY(TYPE_CHAR, 44), /* ASCII name of item */ ++ TYPE_INT /* index of item */ ++) ++ ++STRUCT(emu10k1_fx8010_control_gpr, ++ MK_STRUCT(STRUCT_emu10k1_ctl_elem_id), /* full control ID definition */ ++ TYPE_INT, /* visible count */ ++ TYPE_INT, /* count of GPR (1..16) */ ++ MK_ARRAY(TYPE_SHORT, 32), /* GPR number(s) */ ++ MK_ARRAY(TYPE_INT, 32), /* initial values */ ++ TYPE_INT, /* minimum range */ ++ TYPE_INT, /* maximum range */ ++ TYPE_INT, /* translation type (EMU10K1_GPR_TRANSLATION*) */ ++ TYPE_INT ++) ++ ++#ifndef TARGET_LONG_SIZE ++#define TARGET_LONG_SIZE 4 ++#endif ++ ++STRUCT(emu10k1_fx8010_code, ++ MK_ARRAY(TYPE_CHAR, 128), ++ ++ MK_ARRAY(TYPE_LONG, 0x200/(TARGET_LONG_SIZE*8)), /* bitmask of valid initializers */ ++ TYPE_PTRVOID, /* initializers */ ++ ++ TYPE_INT, /* count of GPR controls to add/replace */ ++ MK_STRUCT(STRUCT_emu10k1_fx8010_control_gpr), /* GPR controls to add/replace */ ++ ++ TYPE_INT, /* count of GPR controls to remove */ ++ MK_STRUCT(STRUCT_emu10k1_ctl_elem_id), /* IDs of GPR controls to remove */ ++ ++ TYPE_INT, /* count of GPR controls to list */ ++ TYPE_INT, /* total count of GPR controls */ ++ MK_STRUCT(STRUCT_emu10k1_fx8010_control_gpr), /* listed GPR controls */ ++ ++ MK_ARRAY(TYPE_LONG, 0x100/(TARGET_LONG_SIZE*8)), /* bitmask of valid initializers */ ++ TYPE_PTRVOID, /* data initializers */ ++ TYPE_PTRVOID, /* map initializers */ ++ ++ MK_ARRAY(TYPE_LONG, 1024/(TARGET_LONG_SIZE*8)), /* bitmask of valid instructions */ ++ TYPE_PTRVOID /* one instruction - 64 bits */ ++) ++ ++STRUCT(emu10k1_fx8010_tram, ++ TYPE_INT, /* 31.bit == 1 -> external TRAM */ ++ TYPE_INT, /* size in samples (4 bytes) */ ++ TYPE_INT /* pointer to samples (20-bit) */ ++ /* NULL->clear memory */ ++) ++ ++STRUCT(emu10k1_fx8010_pcm, ++ TYPE_INT, /* substream number */ ++ TYPE_INT, /* reserved */ ++ TYPE_INT, ++ TYPE_INT, /* ring buffer position in TRAM (in samples) */ ++ TYPE_INT, /* count of buffered samples */ ++ TYPE_SHORT, /* GPR containing size of ringbuffer in samples (host) */ ++ TYPE_SHORT, ++ TYPE_SHORT, /* GPR containing count of samples between two TYPE_INTerrupts (host) */ ++ TYPE_SHORT, ++ TYPE_SHORT, /* GPR containing trigger (activate) information (host) */ ++ TYPE_SHORT, /* GPR containing info if PCM is running (FX8010) */ ++ TYPE_CHAR, /* reserved */ ++ MK_ARRAY(TYPE_CHAR, 32), /* external TRAM address & data (one per channel) */ ++ TYPE_INT /* reserved */ ++) ++ ++STRUCT( hdsp_peak_rms, ++ MK_ARRAY(TYPE_INT, 26), ++ MK_ARRAY(TYPE_INT, 26), ++ MK_ARRAY(TYPE_INT, 28), ++ MK_ARRAY(TYPE_LONGLONG, 26), ++ MK_ARRAY(TYPE_LONGLONG, 26), ++ /* These are only used for H96xx cards */ ++ MK_ARRAY(TYPE_LONGLONG, 26) ++) ++ ++STRUCT( hdsp_config_info, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ MK_ARRAY(TYPE_CHAR, 3), ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_INT, ++ TYPE_INT, ++ TYPE_INT, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR, ++ TYPE_CHAR ++) ++ ++STRUCT( hdsp_firmware, ++ TYPE_PTRVOID /* 24413 x 4 bytes */ ++) ++ ++STRUCT( hdsp_version, ++ TYPE_INT, ++ TYPE_SHORT ++) ++ ++STRUCT( hdsp_mixer, ++ MK_ARRAY(TYPE_SHORT, HDSP_MATRIX_MIXER_SIZE) ++) ++ ++STRUCT( hdsp_9632_aeb, ++ TYPE_INT, ++ TYPE_INT ++) ++ ++STRUCT( snd_sb_csp_mc_header, ++ MK_ARRAY(TYPE_CHAR, 16), /* id name of codec */ ++ TYPE_SHORT /* requested function */ ++) ++ ++STRUCT( snd_sb_csp_microcode, ++ MK_STRUCT(STRUCT_snd_sb_csp_mc_header), ++ MK_ARRAY(TYPE_CHAR, SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE) ++) ++ ++STRUCT( snd_sb_csp_start, ++ TYPE_INT, ++ TYPE_INT ++) ++ ++STRUCT( snd_sb_csp_info, ++ MK_ARRAY(TYPE_CHAR, 16), /* id name of codec */ ++ TYPE_SHORT, /* function number */ ++ TYPE_INT, /* accepted PCM formats */ ++ TYPE_SHORT, /* accepted channels */ ++ TYPE_SHORT, /* accepted sample width */ ++ TYPE_SHORT, /* accepted sample rates */ ++ TYPE_SHORT, ++ TYPE_SHORT, /* current channels */ ++ TYPE_SHORT, /* current sample width */ ++ TYPE_SHORT, /* version id: 0x10 - 0x1f */ ++ TYPE_SHORT /* state bits */ ++) ++ ++STRUCT( sscape_bootblock, ++ MK_ARRAY(TYPE_CHAR, 256), ++ TYPE_INT ++) ++ ++STRUCT( sscape_microcode, ++ TYPE_PTRVOID ++) ++ +-- +1.6.4.2 + diff --git a/app-emulation/qemu/files/0.12.4/0005-qemu-cvs-alsa_mmap.patch b/app-emulation/qemu/files/0.12.4/0005-qemu-cvs-alsa_mmap.patch new file mode 100644 index 0000000..720d07b --- /dev/null +++ b/app-emulation/qemu/files/0.12.4/0005-qemu-cvs-alsa_mmap.patch @@ -0,0 +1,47 @@ +From 8dc126f05ef5f8d0105d5d1b77493a27df8b4e30 Mon Sep 17 00:00:00 2001 +From: Ulrich Hecht +Date: Tue, 14 Apr 2009 16:24:15 +0200 +Subject: [PATCH 05/16] qemu-cvs-alsa_mmap + +Hack to prevent ALSA from using mmap() interface to simplify emulation. + +Signed-off-by: Ulrich Hecht +--- + linux-user/mmap.c | 14 ++++++++++++++ + 1 files changed, 14 insertions(+), 0 deletions(-) + +diff --git a/linux-user/mmap.c b/linux-user/mmap.c +index 144fb7c..1ea202b 100644 +--- a/linux-user/mmap.c ++++ b/linux-user/mmap.c +@@ -328,6 +328,9 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size) + return h2g(ptr); + } + ++#define SNDRV_PCM_MMAP_OFFSET_STATUS 0x80000000 ++#define SNDRV_PCM_MMAP_OFFSET_CONTROL 0x81000000 ++ + /* NOTE: all the constants are the HOST ones */ + abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, + int flags, int fd, abi_ulong offset) +@@ -363,6 +366,17 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, + } + #endif + ++ /* Alsa tries to communcate with the kernel via mmap. This usually ++ * is a good idea when user- and kernelspace are running on the ++ * same architecture but does not work out when not. To make alsa ++ * not to use mmap, we can just have it fail on the mmap calls that ++ * would initiate this. ++ */ ++ if(offset == SNDRV_PCM_MMAP_OFFSET_STATUS || offset == SNDRV_PCM_MMAP_OFFSET_CONTROL) { ++ errno = EINVAL; ++ return -1; ++ } ++ + if (offset & ~TARGET_PAGE_MASK) { + errno = EINVAL; + goto fail; +-- +1.6.4.2 + diff --git a/app-emulation/qemu/files/0.12.4/0006-qemu-cvs-gettimeofday.patch b/app-emulation/qemu/files/0.12.4/0006-qemu-cvs-gettimeofday.patch new file mode 100644 index 0000000..165b2b1 --- /dev/null +++ b/app-emulation/qemu/files/0.12.4/0006-qemu-cvs-gettimeofday.patch @@ -0,0 +1,26 @@ +From fdeb1b8a61335d7c8537725cd1d7997053ce1d27 Mon Sep 17 00:00:00 2001 +From: Ulrich Hecht +Date: Tue, 14 Apr 2009 16:25:41 +0200 +Subject: [PATCH 06/16] qemu-cvs-gettimeofday + +No clue what this is for. +--- + linux-user/syscall.c | 2 ++ + 1 files changed, 2 insertions(+), 0 deletions(-) + +diff --git a/linux-user/syscall.c b/linux-user/syscall.c +index e38552c..63eef34 100644 +--- a/linux-user/syscall.c ++++ b/linux-user/syscall.c +@@ -5101,6 +5101,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, + case TARGET_NR_gettimeofday: + { + struct timeval tv; ++ if(copy_from_user_timeval(&tv, arg1)) ++ goto efault; + ret = get_errno(gettimeofday(&tv, NULL)); + if (!is_error(ret)) { + if (copy_to_user_timeval(arg1, &tv)) +-- +1.6.4.2 + diff --git a/app-emulation/qemu/files/0.12.4/0007-qemu-cvs-ioctl_debug.patch b/app-emulation/qemu/files/0.12.4/0007-qemu-cvs-ioctl_debug.patch new file mode 100644 index 0000000..3e3183c --- /dev/null +++ b/app-emulation/qemu/files/0.12.4/0007-qemu-cvs-ioctl_debug.patch @@ -0,0 +1,33 @@ +From 6d88562dea1c1e0ae1367b89353a546c0e725513 Mon Sep 17 00:00:00 2001 +From: Ulrich Hecht +Date: Tue, 14 Apr 2009 16:26:33 +0200 +Subject: [PATCH 07/16] qemu-cvs-ioctl_debug + +Extends unsupported ioctl debug output. + +Signed-off-by: Ulrich Hecht +--- + linux-user/syscall.c | 7 ++++++- + 1 files changed, 6 insertions(+), 1 deletions(-) + +diff --git a/linux-user/syscall.c b/linux-user/syscall.c +index 63eef34..1540e77 100644 +--- a/linux-user/syscall.c ++++ b/linux-user/syscall.c +@@ -2896,7 +2896,12 @@ static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg) + ie = ioctl_entries; + for(;;) { + if (ie->target_cmd == 0) { +- gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd); ++ int i; ++ gemu_log("Unsupported ioctl: cmd=0x%04lx (%x)\n", (unsigned long)cmd, (unsigned int)(cmd & (TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) >> TARGET_IOC_SIZESHIFT); ++ for(i=0;ioctl_entries[i].target_cmd;i++) { ++ if((ioctl_entries[i].target_cmd & ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) == (cmd & ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT))) ++ gemu_log("%p\t->\t%s (%x)\n", (void *)(unsigned long)ioctl_entries[i].host_cmd, ioctl_entries[i].name, (ioctl_entries[i].target_cmd & (TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) >> TARGET_IOC_SIZESHIFT); ++ } + return -TARGET_ENOSYS; + } + if (ie->target_cmd == cmd) +-- +1.6.4.2 + diff --git a/app-emulation/qemu/files/0.12.4/0008-qemu-cvs-ioctl_nodirection.patch b/app-emulation/qemu/files/0.12.4/0008-qemu-cvs-ioctl_nodirection.patch new file mode 100644 index 0000000..ba9d475 --- /dev/null +++ b/app-emulation/qemu/files/0.12.4/0008-qemu-cvs-ioctl_nodirection.patch @@ -0,0 +1,42 @@ +From 8fdbbf0d63c4de94c308c165283d7ea57f1cbf60 Mon Sep 17 00:00:00 2001 +From: Ulrich Hecht +Date: Tue, 14 Apr 2009 16:27:36 +0200 +Subject: [PATCH 08/16] qemu-cvs-ioctl_nodirection + +the direction given in the ioctl should be correct so we can assume the +communication is uni-directional. The alsa developers did not like this +concept though and declared ioctls IOC_R and IOC_W even though they were +IOC_RW. + +Signed-off-by: Ulrich Hecht +--- + linux-user/syscall.c | 6 ++++++ + 1 files changed, 6 insertions(+), 0 deletions(-) + +diff --git a/linux-user/syscall.c b/linux-user/syscall.c +index 1540e77..3f810c3 100644 +--- a/linux-user/syscall.c ++++ b/linux-user/syscall.c +@@ -2926,6 +2926,11 @@ static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg) + arg_type++; + target_size = thunk_type_size(arg_type, 0); + switch(ie->access) { ++ /* FIXME: actually the direction given in the ioctl should be ++ * correct so we can assume the communication is uni-directional. ++ * The alsa developers did not like this concept though and ++ * declared ioctls IOC_R and IOC_W even though they were IOC_RW.*/ ++/* + case IOC_R: + ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); + if (!is_error(ret)) { +@@ -2944,6 +2949,7 @@ static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg) + unlock_user(argptr, arg, 0); + ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); + break; ++*/ + default: + case IOC_RW: + argptr = lock_user(VERIFY_READ, arg, target_size, 1); +-- +1.6.4.2 + diff --git a/app-emulation/qemu/files/0.12.4/0009-qemu-cvs-sched_getaffinity.patch b/app-emulation/qemu/files/0.12.4/0009-qemu-cvs-sched_getaffinity.patch new file mode 100644 index 0000000..1ac5cad --- /dev/null +++ b/app-emulation/qemu/files/0.12.4/0009-qemu-cvs-sched_getaffinity.patch @@ -0,0 +1,56 @@ +From a6f58c0e024cda6f06d788f6d03b699c8c736fdf Mon Sep 17 00:00:00 2001 +From: Ulrich Hecht +Date: Tue, 14 Apr 2009 16:30:16 +0200 +Subject: [PATCH 09/16] qemu-cvs-sched_getaffinity + +Implements sched_getaffinity syscall. + +Signed-off-by: Ulrich Hecht +--- + linux-user/syscall.c | 16 ++++++++++++++++ + 1 files changed, 16 insertions(+), 0 deletions(-) + +diff --git a/linux-user/syscall.c b/linux-user/syscall.c +index 3f810c3..a74869e 100644 +--- a/linux-user/syscall.c ++++ b/linux-user/syscall.c +@@ -156,6 +156,7 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \ + } + + ++#define __NR_sys_sched_getaffinity __NR_sched_getaffinity + #define __NR_sys_uname __NR_uname + #define __NR_sys_faccessat __NR_faccessat + #define __NR_sys_fchmodat __NR_fchmodat +@@ -215,6 +216,9 @@ _syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig) + #if defined(TARGET_NR_tkill) && defined(__NR_tkill) + _syscall2(int,sys_tkill,int,tid,int,sig) + #endif ++#ifdef __NR_sys_sched_getaffinity ++_syscall3(int,sys_sched_getaffinity,pid_t,pid,unsigned int,cpusetsize,void*,mask) ++#endif + #ifdef __NR_exit_group + _syscall1(int,exit_group,int,error_code) + #endif +@@ -7045,6 +7049,18 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, + ret = get_errno(fallocate(arg1, arg2, arg3, arg4)); + break; + #endif ++ ++#ifdef TARGET_NR_sched_getaffinity ++ case TARGET_NR_sched_getaffinity: ++ { ++ cpu_set_t *mask; ++ lock_user_struct(VERIFY_READ, mask, arg3, 1); ++ ret = get_errno(sys_sched_getaffinity((pid_t)arg1, (unsigned int)arg2, mask)); ++ unlock_user_struct(mask, arg3, 0); ++ break; ++ } ++#endif ++ + default: + unimplemented: + gemu_log("qemu: Unsupported syscall: %d\n", num); +-- +1.6.4.2 + diff --git a/app-emulation/qemu/files/0.12.4/0010-qemu-cvs-mmap-amd64.patch b/app-emulation/qemu/files/0.12.4/0010-qemu-cvs-mmap-amd64.patch new file mode 100644 index 0000000..d42952e --- /dev/null +++ b/app-emulation/qemu/files/0.12.4/0010-qemu-cvs-mmap-amd64.patch @@ -0,0 +1,41 @@ +From b22d5f62f9765ec734d7b14886d7aed5b61acf8b Mon Sep 17 00:00:00 2001 +From: Ulrich Hecht +Date: Tue, 14 Apr 2009 16:34:05 +0200 +Subject: [PATCH 10/16] qemu-cvs-mmap-amd64 + +Map stuff to address space < 4GB on AMD64. This patch got continually smaller +as most cases were this was an issue were dealt with in other ways. May +already be fully obsolete. + +Signed-off-by: Ulrich Hecht +--- + linux-user/mmap.c | 6 +++++- + 1 files changed, 5 insertions(+), 1 deletions(-) + +diff --git a/linux-user/mmap.c b/linux-user/mmap.c +index 1ea202b..74b0d4b 100644 +--- a/linux-user/mmap.c ++++ b/linux-user/mmap.c +@@ -31,6 +31,10 @@ + #include "qemu.h" + #include "qemu-common.h" + ++#if !defined(MAP_32BIT) ++#define MAP_32BIT 0 ++#endif ++ + //#define DEBUG_MMAP + + #if defined(CONFIG_USE_NPTL) +@@ -230,7 +234,7 @@ static int mmap_frag(abi_ulong real_start, + if (prot1 == 0) { + /* no page was there, so we allocate one */ + void *p = mmap(host_start, qemu_host_page_size, prot, +- flags | MAP_ANONYMOUS, -1, 0); ++ flags | MAP_ANONYMOUS | MAP_32BIT, -1, 0); + if (p == MAP_FAILED) + return -1; + prot1 = prot; +-- +1.6.4.2 + diff --git a/app-emulation/qemu/files/0.12.4/0011-qemu-img-vmdk-scsi.patch b/app-emulation/qemu/files/0.12.4/0011-qemu-img-vmdk-scsi.patch new file mode 100644 index 0000000..098d76f --- /dev/null +++ b/app-emulation/qemu/files/0.12.4/0011-qemu-img-vmdk-scsi.patch @@ -0,0 +1,142 @@ +From afdac5e4c878653b9f4a038bebdcf98a01397a39 Mon Sep 17 00:00:00 2001 +From: Ulrich Hecht +Date: Tue, 14 Apr 2009 16:37:42 +0200 +Subject: [PATCH 11/16] qemu-img-vmdk-scsi + +Support creation of SCSI VMDK images in qemu-img. + +Signed-off-by: Ulrich Hecht +--- + block/vmdk.c | 5 +++-- + block_int.h | 1 + + qemu-img-cmds.hx | 8 ++++---- + qemu-img.c | 15 +++++++++++++-- + 4 files changed, 21 insertions(+), 8 deletions(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index 4e48622..b7a15c7 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -710,7 +710,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options) + "ddb.geometry.cylinders = \"%" PRId64 "\"\n" + "ddb.geometry.heads = \"16\"\n" + "ddb.geometry.sectors = \"63\"\n" +- "ddb.adapterType = \"ide\"\n"; ++ "ddb.adapterType = \"%s\"\n"; + char desc[1024]; + const char *real_filename, *temp_str; + int64_t total_size = 0; +@@ -800,7 +800,8 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options) + snprintf(desc, sizeof(desc), desc_template, (unsigned int)time(NULL), + total_size, real_filename, + (flags & BLOCK_FLAG_COMPAT6 ? 6 : 4), +- total_size / (int64_t)(63 * 16)); ++ total_size / (int64_t)(63 * 16), ++ flags & BLOCK_FLAG_SCSI ? "lsilogic" : "ide"); + + /* write the descriptor */ + lseek(fd, le64_to_cpu(header.desc_offset) << 9, SEEK_SET); +diff --git a/block_int.h b/block_int.h +index 9a3b2e0..85e8a72 100644 +--- a/block_int.h ++++ b/block_int.h +@@ -30,6 +30,7 @@ + #define BLOCK_FLAG_ENCRYPT 1 + #define BLOCK_FLAG_COMPRESS 2 + #define BLOCK_FLAG_COMPAT6 4 ++#define BLOCK_FLAG_SCSI 8 + + #define BLOCK_OPT_SIZE "size" + #define BLOCK_OPT_ENCRYPT "encryption" +diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx +index 641bd87..949ae97 100644 +--- a/qemu-img-cmds.hx ++++ b/qemu-img-cmds.hx +@@ -16,9 +16,9 @@ STEXI + ETEXI + + DEF("create", img_create, +- "create [-f fmt] [-o options] filename [size]") ++ "create [-s] [-f fmt] [-o options] filename [size]") + STEXI +-@item create [-f @var{fmt}] [-o @var{options}] @var{filename} [@var{size}] ++@item create [-s] [-f @var{fmt}] [-o @var{options}] @var{filename} [@var{size}] + ETEXI + + DEF("commit", img_commit, +@@ -28,9 +28,9 @@ STEXI + ETEXI + + DEF("convert", img_convert, +- "convert [-c] [-f fmt] [-O output_fmt] [-o options] filename [filename2 [...]] output_filename") ++ "convert [-c] [-s] [-f fmt] [-O output_fmt] [-o options] filename [filename2 [...]] output_filename") + STEXI +-@item convert [-c] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] @var{filename} [@var{filename2} [...]] @var{output_filename} ++@item convert [-c] [-s] [-f @var{fmt}] [-O @var{output_fmt}] [-o @var{options}] @var{filename} [@var{filename2} [...]] @var{output_filename} + ETEXI + + DEF("info", img_info, +diff --git a/qemu-img.c b/qemu-img.c +index 2824178..4b6663f 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -253,7 +253,7 @@ static int img_create(int argc, char **argv) + + flags = 0; + for(;;) { +- c = getopt(argc, argv, "F:b:f:he6o:"); ++ c = getopt(argc, argv, "F:b:f:hes6o:"); + if (c == -1) + break; + switch(c) { +@@ -272,6 +272,9 @@ static int img_create(int argc, char **argv) + case 'e': + flags |= BLOCK_FLAG_ENCRYPT; + break; ++ case 's': ++ flags |= BLOCK_FLAG_SCSI; ++ break; + case '6': + flags |= BLOCK_FLAG_COMPAT6; + break; +@@ -354,6 +357,8 @@ static int img_create(int argc, char **argv) + + printf("Formatting '%s', fmt=%s ", filename, fmt); + print_option_parameters(param); ++ if (flags & BLOCK_FLAG_SCSI) ++ printf(", SCSI"); + puts(""); + + ret = bdrv_create(drv, filename, param); +@@ -548,7 +553,7 @@ static int img_convert(int argc, char **argv) + out_baseimg = NULL; + flags = 0; + for(;;) { +- c = getopt(argc, argv, "f:O:B:hce6o:"); ++ c = getopt(argc, argv, "f:O:B:hces6o:"); + if (c == -1) + break; + switch(c) { +@@ -570,6 +575,9 @@ static int img_convert(int argc, char **argv) + case 'e': + flags |= BLOCK_FLAG_ENCRYPT; + break; ++ case 's': ++ flags |= BLOCK_FLAG_SCSI; ++ break; + case '6': + flags |= BLOCK_FLAG_COMPAT6; + break; +@@ -637,6 +645,9 @@ static int img_convert(int argc, char **argv) + } + } + ++ if (flags & BLOCK_FLAG_SCSI && strcmp(drv->format_name, "vmdk")) ++ error("SCSI devices not supported for this file format"); ++ + /* Create the new image */ + ret = bdrv_create(drv, out_filename, param); + free_option_parameters(param); +-- +1.6.4.2 + diff --git a/app-emulation/qemu/files/0.12.4/0012-qemu-nonvoid_return.patch b/app-emulation/qemu/files/0.12.4/0012-qemu-nonvoid_return.patch new file mode 100644 index 0000000..e515257 --- /dev/null +++ b/app-emulation/qemu/files/0.12.4/0012-qemu-nonvoid_return.patch @@ -0,0 +1,40 @@ +From 44ce0d8cef307cd7b6e82242f896559916886f30 Mon Sep 17 00:00:00 2001 +From: Ulrich Hecht +Date: Tue, 14 Apr 2009 16:38:20 +0200 +Subject: [PATCH 12/16] qemu-nonvoid_return + +Squelches GCC warnings about undefined return values. + +Signed-off-by: Ulrich Hecht +--- + hw/mpcore.c | 1 + + target-m68k/translate.c | 1 + + 2 files changed, 2 insertions(+), 0 deletions(-) + +diff --git a/hw/mpcore.c b/hw/mpcore.c +index b4db191..ef0c705 100644 +--- a/hw/mpcore.c ++++ b/hw/mpcore.c +@@ -104,6 +104,7 @@ static uint32_t mpcore_timer_read(mpcore_timer_state *s, int offset) + default: + return 0; + } ++ return 0; + } + + static void mpcore_timer_write(mpcore_timer_state *s, int offset, +diff --git a/target-m68k/translate.c b/target-m68k/translate.c +index 99cf6dd..18875d9 100644 +--- a/target-m68k/translate.c ++++ b/target-m68k/translate.c +@@ -440,6 +440,7 @@ static inline int opsize_bytes(int opsize) + qemu_assert(0, "bad operand size"); + return 0; + } ++ return 0; + } + + /* Assign value to a register. If the width is less than the register width +-- +1.6.4.2 + diff --git a/app-emulation/qemu/files/0.12.4/0013-i386-linux-user-NPTL-support.patch b/app-emulation/qemu/files/0.12.4/0013-i386-linux-user-NPTL-support.patch new file mode 100644 index 0000000..43fea05 --- /dev/null +++ b/app-emulation/qemu/files/0.12.4/0013-i386-linux-user-NPTL-support.patch @@ -0,0 +1,64 @@ +From b7c83887c1c86140ffaab86d4d1fca5a81e86c2d Mon Sep 17 00:00:00 2001 +From: Ulrich Hecht +Date: Thu, 16 Apr 2009 15:14:12 +0200 +Subject: [PATCH 13/16] i386-linux-user NPTL support + +Makes NPTL binaries run by implementing TLS. + +Signed-off-by: Ulrich Hecht +--- + configure | 1 + + linux-user/syscall.c | 16 ++++++++++++++-- + 2 files changed, 15 insertions(+), 2 deletions(-) + +diff --git a/configure b/configure +index 5f463b0..0ec7ff0 100755 +--- a/configure ++++ b/configure +@@ -2283,6 +2283,7 @@ TARGET_ABI_DIR="" + case "$target_arch2" in + i386) + target_phys_bits=32 ++ target_nptl="yes" + ;; + x86_64) + TARGET_BASE_ARCH=i386 +diff --git a/linux-user/syscall.c b/linux-user/syscall.c +index a74869e..ec67a14 100644 +--- a/linux-user/syscall.c ++++ b/linux-user/syscall.c +@@ -3584,8 +3584,14 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp, + ts->child_tidptr = child_tidptr; + } + +- if (nptl_flags & CLONE_SETTLS) ++ if (nptl_flags & CLONE_SETTLS) { ++#if defined(TARGET_I386) && defined(TARGET_ABI32) ++ do_set_thread_area(new_env, newtls); ++ cpu_x86_load_seg(new_env, R_GS, new_env->segs[R_GS].selector); ++#else + cpu_set_tls (new_env, newtls); ++#endif ++ } + + /* Grab a mutex so that thread setup appears atomic. */ + pthread_mutex_lock(&clone_lock); +@@ -3657,8 +3663,14 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp, + if (flags & CLONE_PARENT_SETTID) + put_user_u32(gettid(), parent_tidptr); + ts = (TaskState *)env->opaque; +- if (flags & CLONE_SETTLS) ++ if (flags & CLONE_SETTLS) { ++#if defined(TARGET_I386) && defined(TARGET_ABI32) ++ do_set_thread_area(env, newtls); ++ cpu_x86_load_seg(env, R_GS, env->segs[R_GS].selector); ++#else + cpu_set_tls (env, newtls); ++#endif ++ } + if (flags & CLONE_CHILD_CLEARTID) + ts->child_tidptr = child_tidptr; + #endif +-- +1.6.4.2 + diff --git a/app-emulation/qemu/files/0.12.4/0014-qemu-0.11-git-ioctl_mount.patch b/app-emulation/qemu/files/0.12.4/0014-qemu-0.11-git-ioctl_mount.patch new file mode 100644 index 0000000..b43f7be --- /dev/null +++ b/app-emulation/qemu/files/0.12.4/0014-qemu-0.11-git-ioctl_mount.patch @@ -0,0 +1,25 @@ +From 7c670471903f85dfbcbfce2a7b7829bd08559c3c Mon Sep 17 00:00:00 2001 +From: Ulrich Hecht +Date: Wed, 17 Jun 2009 14:54:48 +0200 +Subject: [PATCH 14/16] qemu-0.11-git-ioctl_mount + +--- + linux-user/ioctls.h | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h +index fca824c..2cec892 100644 +--- a/linux-user/ioctls.h ++++ b/linux-user/ioctls.h +@@ -313,7 +313,7 @@ + IOCTL(LOOP_CLR_FD, 0, TYPE_INT) + IOCTL(LOOP_SET_STATUS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info))) + IOCTL(LOOP_GET_STATUS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info))) +-#if 0 /* These have some problems - not fully tested */ ++#if 1 /* These have some problems - not fully tested */ + IOCTL(LOOP_SET_STATUS64, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info64))) + IOCTL(LOOP_GET_STATUS64, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info64))) + #endif +-- +1.6.4.2 + diff --git a/app-emulation/qemu/files/0.12.4/0015-qemu-0.11-git-user-linux-ppc-uid16_fix.patch b/app-emulation/qemu/files/0.12.4/0015-qemu-0.11-git-user-linux-ppc-uid16_fix.patch new file mode 100644 index 0000000..7dcda49 --- /dev/null +++ b/app-emulation/qemu/files/0.12.4/0015-qemu-0.11-git-user-linux-ppc-uid16_fix.patch @@ -0,0 +1,116 @@ +From 7871becde1196cc4d89b1e27de4e03858ef8f265 Mon Sep 17 00:00:00 2001 +From: Ulrich Hecht +Date: Wed, 17 Jun 2009 15:08:38 +0200 +Subject: [PATCH 15/16] qemu-0.11-git-user-linux-ppc-uid16_fix + +--- + linux-user/ppc/syscall_nr.h | 30 +++++++++++++++--------------- + linux-user/syscall_defs.h | 2 +- + 2 files changed, 16 insertions(+), 16 deletions(-) + +diff --git a/linux-user/ppc/syscall_nr.h b/linux-user/ppc/syscall_nr.h +index f54276b..cc84a4c 100644 +--- a/linux-user/ppc/syscall_nr.h ++++ b/linux-user/ppc/syscall_nr.h +@@ -17,15 +17,15 @@ + #define TARGET_NR_time 13 + #define TARGET_NR_mknod 14 + #define TARGET_NR_chmod 15 +-#define TARGET_NR_lchown32 16 ++#define TARGET_NR_lchown 16 + #define TARGET_NR_break 17 + #define TARGET_NR_oldstat 18 + #define TARGET_NR_lseek 19 + #define TARGET_NR_getpid 20 + #define TARGET_NR_mount 21 + #define TARGET_NR_umount 22 +-#define TARGET_NR_setuid32 23 +-#define TARGET_NR_getuid32 24 ++#define TARGET_NR_setuid 23 ++#define TARGET_NR_getuid 24 + #define TARGET_NR_stime 25 + #define TARGET_NR_ptrace 26 + #define TARGET_NR_alarm 27 +@@ -47,11 +47,11 @@ + #define TARGET_NR_times 43 + #define TARGET_NR_prof 44 + #define TARGET_NR_brk 45 +-#define TARGET_NR_setgid32 46 +-#define TARGET_NR_getgid32 47 ++#define TARGET_NR_setgid 46 ++#define TARGET_NR_getgid 47 + #define TARGET_NR_signal 48 +-#define TARGET_NR_geteuid32 49 +-#define TARGET_NR_getegid32 50 ++#define TARGET_NR_geteuid 49 ++#define TARGET_NR_getegid 50 + #define TARGET_NR_acct 51 + #define TARGET_NR_umount2 52 + #define TARGET_NR_lock 53 +@@ -71,8 +71,8 @@ + #define TARGET_NR_sigaction 67 + #define TARGET_NR_sgetmask 68 + #define TARGET_NR_ssetmask 69 +-#define TARGET_NR_setreuid32 70 +-#define TARGET_NR_setregid32 71 ++#define TARGET_NR_setreuid 70 ++#define TARGET_NR_setregid 71 + #define TARGET_NR_sigsuspend 72 + #define TARGET_NR_sigpending 73 + #define TARGET_NR_sethostname 74 +@@ -81,8 +81,8 @@ + #define TARGET_NR_getrusage 77 + #define TARGET_NR_gettimeofday 78 + #define TARGET_NR_settimeofday 79 +-#define TARGET_NR_getgroups32 80 +-#define TARGET_NR_setgroups32 81 ++#define TARGET_NR_getgroups 80 ++#define TARGET_NR_setgroups 81 + #define TARGET_NR_select 82 + #define TARGET_NR_symlink 83 + #define TARGET_NR_oldlstat 84 +@@ -96,7 +96,7 @@ + #define TARGET_NR_truncate 92 + #define TARGET_NR_ftruncate 93 + #define TARGET_NR_fchmod 94 +-#define TARGET_NR_fchown32 95 ++#define TARGET_NR_fchown 95 + #define TARGET_NR_getpriority 96 + #define TARGET_NR_setpriority 97 + #define TARGET_NR_profil 98 +@@ -139,8 +139,8 @@ + #define TARGET_NR_sysfs 135 + #define TARGET_NR_personality 136 + #define TARGET_NR_afs_syscall 137 /* Syscall for Andrew File System */ +-#define TARGET_NR_setfsuid32 138 +-#define TARGET_NR_setfsgid32 139 ++#define TARGET_NR_setfsuid 138 ++#define TARGET_NR_setfsgid 139 + #define TARGET_NR__llseek 140 + #define TARGET_NR_getdents 141 + #define TARGET_NR__newselect 142 +@@ -182,7 +182,7 @@ + #define TARGET_NR_rt_sigsuspend 178 + #define TARGET_NR_pread64 179 + #define TARGET_NR_pwrite64 180 +-#define TARGET_NR_chown32 181 ++#define TARGET_NR_chown 181 + #define TARGET_NR_getcwd 182 + #define TARGET_NR_capget 183 + #define TARGET_NR_capset 184 +diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h +index 77ae416..e734fec 100644 +--- a/linux-user/syscall_defs.h ++++ b/linux-user/syscall_defs.h +@@ -49,7 +49,7 @@ + #define TARGET_IOC_TYPEBITS 8 + + #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \ +- || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS) ++ || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS) || defined(TARGET_PPC) + /* 16 bit uid wrappers emulation */ + #define USE_UID16 + #endif +-- +1.6.4.2 + diff --git a/app-emulation/qemu/files/0.12.4/0016-S-390-support.patch b/app-emulation/qemu/files/0.12.4/0016-S-390-support.patch new file mode 100644 index 0000000..5e27a2d --- /dev/null +++ b/app-emulation/qemu/files/0.12.4/0016-S-390-support.patch @@ -0,0 +1,7699 @@ +From 92f6fc08eaf4f9b0873c5442b0536df36323b868 Mon Sep 17 00:00:00 2001 +From: Ulrich Hecht +Date: Tue, 25 May 2010 16:38:22 +0200 +Subject: [PATCH 16/16] S/390 support + +--- + configure | 2 + + cpu-all.h | 2 +- + cpu-defs.h | 8 + + cpu-exec.c | 14 +- + default-configs/s390x-linux-user.mak | 1 + + disas.c | 3 + + exec.c | 2 + + linux-user/elfload.c | 18 + + linux-user/main.c | 89 ++ + linux-user/s390x/syscall.h | 25 + + linux-user/s390x/syscall_nr.h | 348 +++++ + linux-user/s390x/target_signal.h | 26 + + linux-user/s390x/termbits.h | 283 ++++ + linux-user/signal.c | 314 ++++ + linux-user/syscall.c | 144 ++- + linux-user/syscall_defs.h | 56 +- + qemu-binfmt-conf.sh | 5 +- + s390-dis.c | 4 +- + target-s390x/cpu.h | 31 +- + target-s390x/exec.h | 2 +- + target-s390x/helper.c | 24 + + target-s390x/helpers.h | 128 ++ + target-s390x/op_helper.c | 1620 ++++++++++++++++++++ + target-s390x/translate.c | 2760 ++++++++++++++++++++++++++++++++++ + tcg/s390/tcg-target.c | 1070 +++++++++++++- + tcg/s390/tcg-target.h | 9 + + tcg/tcg-op.h | 12 + + tcg/tcg-opc.h | 2 + + tcg/tcg.c | 6 + + 29 files changed, 6947 insertions(+), 61 deletions(-) + create mode 100644 default-configs/s390x-linux-user.mak + create mode 100644 linux-user/s390x/syscall.h + create mode 100644 linux-user/s390x/syscall_nr.h + create mode 100644 linux-user/s390x/target_signal.h + create mode 100644 linux-user/s390x/termbits.h + create mode 100644 target-s390x/helpers.h + +diff --git a/configure b/configure +index 0ec7ff0..bf2aae0 100755 +--- a/configure ++++ b/configure +@@ -830,6 +830,7 @@ sh4eb-linux-user \ + sparc-linux-user \ + sparc64-linux-user \ + sparc32plus-linux-user \ ++s390x-linux-user \ + " + fi + # the following are Darwin specific +@@ -2379,6 +2380,7 @@ case "$target_arch2" in + target_phys_bits=64 + ;; + s390x) ++ target_nptl="yes" + target_phys_bits=64 + ;; + *) +diff --git a/cpu-all.h b/cpu-all.h +index 57b69f8..c500cb8 100644 +--- a/cpu-all.h ++++ b/cpu-all.h +@@ -138,7 +138,7 @@ typedef union { + uint64_t ll; + } CPU_DoubleU; + +-#ifdef TARGET_SPARC ++#if defined(TARGET_SPARC) || defined(TARGET_S390X) + typedef union { + float128 q; + #if defined(HOST_WORDS_BIGENDIAN) \ +diff --git a/cpu-defs.h b/cpu-defs.h +index 95068b5..c50c59e 100644 +--- a/cpu-defs.h ++++ b/cpu-defs.h +@@ -135,6 +135,13 @@ typedef struct CPUWatchpoint { + } CPUWatchpoint; + + #define CPU_TEMP_BUF_NLONGS 128 ++ ++#ifdef CONFIG_USER_ONLY ++#define MULTITHREAD uint32_t multithreaded; ++#else ++#define MULTITHREAD ++#endif ++ + #define CPU_COMMON \ + struct TranslationBlock *current_tb; /* currently executing TB */ \ + /* soft mmu support */ \ +@@ -149,6 +156,7 @@ typedef struct CPUWatchpoint { + uint32_t stop; /* Stop request */ \ + uint32_t stopped; /* Artificially stopped */ \ + uint32_t interrupt_request; \ ++ MULTITHREAD /* needs locking when accessing TBs */ \ + volatile sig_atomic_t exit_request; \ + /* The meaning of the MMU modes is defined in the target code. */ \ + CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \ +diff --git a/cpu-exec.c b/cpu-exec.c +index 3246c9e..b5b5a1f 100644 +--- a/cpu-exec.c ++++ b/cpu-exec.c +@@ -219,6 +219,9 @@ int cpu_exec(CPUState *env1) + TranslationBlock *tb; + uint8_t *tc_ptr; + unsigned long next_tb; ++#ifdef CONFIG_USER_ONLY ++ uint32_t multithreaded; ++#endif + + if (cpu_halted(env1) == EXCP_HALTED) + return EXCP_HALTED; +@@ -578,7 +581,11 @@ int cpu_exec(CPUState *env1) + #endif + } + #endif +- spin_lock(&tb_lock); ++#ifdef CONFIG_USER_ONLY ++ multithreaded = env->multithreaded; ++ if (multithreaded) ++#endif ++ spin_lock(&tb_lock); + tb = tb_find_fast(); + /* Note: we do it here to avoid a gcc bug on Mac OS X when + doing it in tb_find_slow */ +@@ -602,7 +609,10 @@ int cpu_exec(CPUState *env1) + tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb); + } + } +- spin_unlock(&tb_lock); ++#ifdef CONFIG_USER_ONLY ++ if (multithreaded) ++#endif ++ spin_unlock(&tb_lock); + env->current_tb = tb; + + /* cpu_interrupt might be called while translating the +diff --git a/default-configs/s390x-linux-user.mak b/default-configs/s390x-linux-user.mak +new file mode 100644 +index 0000000..a243c99 +--- /dev/null ++++ b/default-configs/s390x-linux-user.mak +@@ -0,0 +1 @@ ++# Default configuration for s390x-linux-user +diff --git a/disas.c b/disas.c +index f7bcce7..4267e67 100644 +--- a/disas.c ++++ b/disas.c +@@ -195,6 +195,9 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags) + #elif defined(TARGET_CRIS) + disasm_info.mach = bfd_mach_cris_v32; + print_insn = print_insn_crisv32; ++#elif defined(TARGET_S390X) ++ disasm_info.mach = bfd_mach_s390_64; ++ print_insn = print_insn_s390; + #elif defined(TARGET_MICROBLAZE) + disasm_info.mach = bfd_arch_microblaze; + print_insn = print_insn_microblaze; +diff --git a/exec.c b/exec.c +index 5969eb2..d51c8ce 100644 +--- a/exec.c ++++ b/exec.c +@@ -74,6 +74,8 @@ + #define TARGET_PHYS_ADDR_SPACE_BITS 42 + #elif defined(TARGET_I386) + #define TARGET_PHYS_ADDR_SPACE_BITS 36 ++#elif defined(TARGET_S390X) ++#define TARGET_PHYS_ADDR_SPACE_BITS 42 + #else + #define TARGET_PHYS_ADDR_SPACE_BITS 32 + #endif +diff --git a/linux-user/elfload.c b/linux-user/elfload.c +index 682a813..899fe59 100644 +--- a/linux-user/elfload.c ++++ b/linux-user/elfload.c +@@ -686,6 +686,24 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i + + #endif /* TARGET_ALPHA */ + ++#ifdef TARGET_S390X ++ ++#define ELF_START_MMAP (0x20000000000ULL) ++ ++#define elf_check_arch(x) ( (x) == ELF_ARCH ) ++ ++#define ELF_CLASS ELFCLASS64 ++#define ELF_DATA ELFDATA2MSB ++#define ELF_ARCH EM_S390 ++ ++static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) ++{ ++ regs->psw.addr = infop->entry; ++ regs->gprs[15] = infop->start_stack; ++} ++ ++#endif /* TARGET_S390X */ ++ + #ifndef ELF_PLATFORM + #define ELF_PLATFORM (NULL) + #endif +diff --git a/linux-user/main.c b/linux-user/main.c +index 802bd88..be9d8a2 100644 +--- a/linux-user/main.c ++++ b/linux-user/main.c +@@ -2433,6 +2433,86 @@ void cpu_loop (CPUState *env) + } + #endif /* TARGET_ALPHA */ + ++#ifdef TARGET_S390X ++void cpu_loop(CPUS390XState *env) ++{ ++ int trapnr; ++ target_siginfo_t info; ++ ++ while (1) { ++ trapnr = cpu_s390x_exec (env); ++ ++ if ((trapnr & 0xffff0000) == EXCP_EXECUTE_SVC) { ++ int n = trapnr & 0xffff; ++ env->regs[2] = do_syscall(env, n, ++ env->regs[2], ++ env->regs[3], ++ env->regs[4], ++ env->regs[5], ++ env->regs[6], ++ env->regs[7]); ++ } ++ else switch (trapnr) { ++ case EXCP_INTERRUPT: ++ /* just indicate that signals should be handled asap */ ++ break; ++ case EXCP_DEBUG: ++ { ++ int sig; ++ ++ sig = gdb_handlesig (env, TARGET_SIGTRAP); ++ if (sig) { ++ info.si_signo = sig; ++ info.si_errno = 0; ++ info.si_code = TARGET_TRAP_BRKPT; ++ queue_signal(env, info.si_signo, &info); ++ } ++ } ++ break; ++ case EXCP_SVC: ++ { ++ int n = ldub(env->psw.addr - 1); ++ if (!n) n = env->regs[1]; /* syscalls > 255 */ ++ env->regs[2] = do_syscall(env, n, ++ env->regs[2], ++ env->regs[3], ++ env->regs[4], ++ env->regs[5], ++ env->regs[6], ++ env->regs[7]); ++ } ++ break; ++ case EXCP_ADDR: ++ { ++ info.si_signo = SIGSEGV; ++ info.si_errno = 0; ++ /* XXX: check env->error_code */ ++ info.si_code = TARGET_SEGV_MAPERR; ++ info._sifields._sigfault._addr = env->__excp_addr; ++ queue_signal(env, info.si_signo, &info); ++ } ++ break; ++ case EXCP_SPEC: ++ { ++ fprintf(stderr,"specification exception insn 0x%08x%04x\n", ldl(env->psw.addr), lduw(env->psw.addr + 4)); ++ info.si_signo = SIGILL; ++ info.si_errno = 0; ++ info.si_code = TARGET_ILL_ILLOPC; ++ info._sifields._sigfault._addr = env->__excp_addr; ++ queue_signal(env, info.si_signo, &info); ++ } ++ break; ++ default: ++ printf ("Unhandled trap: 0x%x\n", trapnr); ++ cpu_dump_state(env, stderr, fprintf, 0); ++ exit (1); ++ } ++ process_pending_signals (env); ++ } ++} ++ ++#endif /* TARGET_S390X */ ++ + static void usage(void) + { + printf("qemu-" TARGET_ARCH " version " QEMU_VERSION QEMU_PKGVERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n" +@@ -3073,6 +3153,15 @@ int main(int argc, char **argv, char **envp) + env->regs[15] = regs->acr; + env->pc = regs->erp; + } ++#elif defined(TARGET_S390X) ++ { ++ int i; ++ for (i = 0; i < 16; i++) { ++ env->regs[i] = regs->gprs[i]; ++ } ++ env->psw.mask = regs->psw.mask; ++ env->psw.addr = regs->psw.addr; ++ } + #else + #error unsupported target CPU + #endif +diff --git a/linux-user/s390x/syscall.h b/linux-user/s390x/syscall.h +new file mode 100644 +index 0000000..a3812a8 +--- /dev/null ++++ b/linux-user/s390x/syscall.h +@@ -0,0 +1,25 @@ ++/* this typedef defines how a Program Status Word looks like */ ++typedef struct ++{ ++ abi_ulong mask; ++ abi_ulong addr; ++} __attribute__ ((aligned(8))) target_psw_t; ++ ++/* ++ * The pt_regs struct defines the way the registers are stored on ++ * the stack during a system call. ++ */ ++ ++#define TARGET_NUM_GPRS 16 ++ ++struct target_pt_regs ++{ ++ abi_ulong args[1]; ++ target_psw_t psw; ++ abi_ulong gprs[TARGET_NUM_GPRS]; ++ abi_ulong orig_gpr2; ++ unsigned short ilc; ++ unsigned short trap; ++}; ++ ++#define UNAME_MACHINE "s390x" +diff --git a/linux-user/s390x/syscall_nr.h b/linux-user/s390x/syscall_nr.h +new file mode 100644 +index 0000000..4a60b9a +--- /dev/null ++++ b/linux-user/s390x/syscall_nr.h +@@ -0,0 +1,348 @@ ++/* ++ * This file contains the system call numbers. ++ */ ++ ++#define TARGET_NR_exit 1 ++#define TARGET_NR_fork 2 ++#define TARGET_NR_read 3 ++#define TARGET_NR_write 4 ++#define TARGET_NR_open 5 ++#define TARGET_NR_close 6 ++#define TARGET_NR_restart_syscall 7 ++#define TARGET_NR_creat 8 ++#define TARGET_NR_link 9 ++#define TARGET_NR_unlink 10 ++#define TARGET_NR_execve 11 ++#define TARGET_NR_chdir 12 ++#define TARGET_NR_mknod 14 ++#define TARGET_NR_chmod 15 ++#define TARGET_NR_lseek 19 ++#define TARGET_NR_getpid 20 ++#define TARGET_NR_mount 21 ++#define TARGET_NR_umount 22 ++#define TARGET_NR_ptrace 26 ++#define TARGET_NR_alarm 27 ++#define TARGET_NR_pause 29 ++#define TARGET_NR_utime 30 ++#define TARGET_NR_access 33 ++#define TARGET_NR_nice 34 ++#define TARGET_NR_sync 36 ++#define TARGET_NR_kill 37 ++#define TARGET_NR_rename 38 ++#define TARGET_NR_mkdir 39 ++#define TARGET_NR_rmdir 40 ++#define TARGET_NR_dup 41 ++#define TARGET_NR_pipe 42 ++#define TARGET_NR_times 43 ++#define TARGET_NR_brk 45 ++#define TARGET_NR_signal 48 ++#define TARGET_NR_acct 51 ++#define TARGET_NR_umount2 52 ++#define TARGET_NR_ioctl 54 ++#define TARGET_NR_fcntl 55 ++#define TARGET_NR_setpgid 57 ++#define TARGET_NR_umask 60 ++#define TARGET_NR_chroot 61 ++#define TARGET_NR_ustat 62 ++#define TARGET_NR_dup2 63 ++#define TARGET_NR_getppid 64 ++#define TARGET_NR_getpgrp 65 ++#define TARGET_NR_setsid 66 ++#define TARGET_NR_sigaction 67 ++#define TARGET_NR_sigsuspend 72 ++#define TARGET_NR_sigpending 73 ++#define TARGET_NR_sethostname 74 ++#define TARGET_NR_setrlimit 75 ++#define TARGET_NR_getrusage 77 ++#define TARGET_NR_gettimeofday 78 ++#define TARGET_NR_settimeofday 79 ++#define TARGET_NR_symlink 83 ++#define TARGET_NR_readlink 85 ++#define TARGET_NR_uselib 86 ++#define TARGET_NR_swapon 87 ++#define TARGET_NR_reboot 88 ++#define TARGET_NR_readdir 89 ++#define TARGET_NR_mmap 90 ++#define TARGET_NR_munmap 91 ++#define TARGET_NR_truncate 92 ++#define TARGET_NR_ftruncate 93 ++#define TARGET_NR_fchmod 94 ++#define TARGET_NR_getpriority 96 ++#define TARGET_NR_setpriority 97 ++#define TARGET_NR_statfs 99 ++#define TARGET_NR_fstatfs 100 ++#define TARGET_NR_socketcall 102 ++#define TARGET_NR_syslog 103 ++#define TARGET_NR_setitimer 104 ++#define TARGET_NR_getitimer 105 ++#define TARGET_NR_stat 106 ++#define TARGET_NR_lstat 107 ++#define TARGET_NR_fstat 108 ++#define TARGET_NR_lookup_dcookie 110 ++#define TARGET_NR_vhangup 111 ++#define TARGET_NR_idle 112 ++#define TARGET_NR_wait4 114 ++#define TARGET_NR_swapoff 115 ++#define TARGET_NR_sysinfo 116 ++#define TARGET_NR_ipc 117 ++#define TARGET_NR_fsync 118 ++#define TARGET_NR_sigreturn 119 ++#define TARGET_NR_clone 120 ++#define TARGET_NR_setdomainname 121 ++#define TARGET_NR_uname 122 ++#define TARGET_NR_adjtimex 124 ++#define TARGET_NR_mprotect 125 ++#define TARGET_NR_sigprocmask 126 ++#define TARGET_NR_create_module 127 ++#define TARGET_NR_init_module 128 ++#define TARGET_NR_delete_module 129 ++#define TARGET_NR_get_kernel_syms 130 ++#define TARGET_NR_quotactl 131 ++#define TARGET_NR_getpgid 132 ++#define TARGET_NR_fchdir 133 ++#define TARGET_NR_bdflush 134 ++#define TARGET_NR_sysfs 135 ++#define TARGET_NR_personality 136 ++#define TARGET_NR_afs_syscall 137 /* Syscall for Andrew File System */ ++#define TARGET_NR_getdents 141 ++#define TARGET_NR_flock 143 ++#define TARGET_NR_msync 144 ++#define TARGET_NR_readv 145 ++#define TARGET_NR_writev 146 ++#define TARGET_NR_getsid 147 ++#define TARGET_NR_fdatasync 148 ++#define TARGET_NR__sysctl 149 ++#define TARGET_NR_mlock 150 ++#define TARGET_NR_munlock 151 ++#define TARGET_NR_mlockall 152 ++#define TARGET_NR_munlockall 153 ++#define TARGET_NR_sched_setparam 154 ++#define TARGET_NR_sched_getparam 155 ++#define TARGET_NR_sched_setscheduler 156 ++#define TARGET_NR_sched_getscheduler 157 ++#define TARGET_NR_sched_yield 158 ++#define TARGET_NR_sched_get_priority_max 159 ++#define TARGET_NR_sched_get_priority_min 160 ++#define TARGET_NR_sched_rr_get_interval 161 ++#define TARGET_NR_nanosleep 162 ++#define TARGET_NR_mremap 163 ++#define TARGET_NR_query_module 167 ++#define TARGET_NR_poll 168 ++#define TARGET_NR_nfsservctl 169 ++#define TARGET_NR_prctl 172 ++#define TARGET_NR_rt_sigreturn 173 ++#define TARGET_NR_rt_sigaction 174 ++#define TARGET_NR_rt_sigprocmask 175 ++#define TARGET_NR_rt_sigpending 176 ++#define TARGET_NR_rt_sigtimedwait 177 ++#define TARGET_NR_rt_sigqueueinfo 178 ++#define TARGET_NR_rt_sigsuspend 179 ++#define TARGET_NR_pread64 180 ++#define TARGET_NR_pwrite64 181 ++#define TARGET_NR_getcwd 183 ++#define TARGET_NR_capget 184 ++#define TARGET_NR_capset 185 ++#define TARGET_NR_sigaltstack 186 ++#define TARGET_NR_sendfile 187 ++#define TARGET_NR_getpmsg 188 ++#define TARGET_NR_putpmsg 189 ++#define TARGET_NR_vfork 190 ++#define TARGET_NR_pivot_root 217 ++#define TARGET_NR_mincore 218 ++#define TARGET_NR_madvise 219 ++#define TARGET_NR_getdents64 220 ++#define TARGET_NR_readahead 222 ++#define TARGET_NR_setxattr 224 ++#define TARGET_NR_lsetxattr 225 ++#define TARGET_NR_fsetxattr 226 ++#define TARGET_NR_getxattr 227 ++#define TARGET_NR_lgetxattr 228 ++#define TARGET_NR_fgetxattr 229 ++#define TARGET_NR_listxattr 230 ++#define TARGET_NR_llistxattr 231 ++#define TARGET_NR_flistxattr 232 ++#define TARGET_NR_removexattr 233 ++#define TARGET_NR_lremovexattr 234 ++#define TARGET_NR_fremovexattr 235 ++#define TARGET_NR_gettid 236 ++#define TARGET_NR_tkill 237 ++#define TARGET_NR_futex 238 ++#define TARGET_NR_sched_setaffinity 239 ++#define TARGET_NR_sched_getaffinity 240 ++#define TARGET_NR_tgkill 241 ++/* Number 242 is reserved for tux */ ++#define TARGET_NR_io_setup 243 ++#define TARGET_NR_io_destroy 244 ++#define TARGET_NR_io_getevents 245 ++#define TARGET_NR_io_submit 246 ++#define TARGET_NR_io_cancel 247 ++#define TARGET_NR_exit_group 248 ++#define TARGET_NR_epoll_create 249 ++#define TARGET_NR_epoll_ctl 250 ++#define TARGET_NR_epoll_wait 251 ++#define TARGET_NR_set_tid_address 252 ++#define TARGET_NR_fadvise64 253 ++#define TARGET_NR_timer_create 254 ++#define TARGET_NR_timer_settime (TARGET_NR_timer_create+1) ++#define TARGET_NR_timer_gettime (TARGET_NR_timer_create+2) ++#define TARGET_NR_timer_getoverrun (TARGET_NR_timer_create+3) ++#define TARGET_NR_timer_delete (TARGET_NR_timer_create+4) ++#define TARGET_NR_clock_settime (TARGET_NR_timer_create+5) ++#define TARGET_NR_clock_gettime (TARGET_NR_timer_create+6) ++#define TARGET_NR_clock_getres (TARGET_NR_timer_create+7) ++#define TARGET_NR_clock_nanosleep (TARGET_NR_timer_create+8) ++/* Number 263 is reserved for vserver */ ++#define TARGET_NR_statfs64 265 ++#define TARGET_NR_fstatfs64 266 ++#define TARGET_NR_remap_file_pages 267 ++/* Number 268 is reserved for new sys_mbind */ ++/* Number 269 is reserved for new sys_get_mempolicy */ ++/* Number 270 is reserved for new sys_set_mempolicy */ ++#define TARGET_NR_mq_open 271 ++#define TARGET_NR_mq_unlink 272 ++#define TARGET_NR_mq_timedsend 273 ++#define TARGET_NR_mq_timedreceive 274 ++#define TARGET_NR_mq_notify 275 ++#define TARGET_NR_mq_getsetattr 276 ++#define TARGET_NR_kexec_load 277 ++#define TARGET_NR_add_key 278 ++#define TARGET_NR_request_key 279 ++#define TARGET_NR_keyctl 280 ++#define TARGET_NR_waitid 281 ++#define TARGET_NR_ioprio_set 282 ++#define TARGET_NR_ioprio_get 283 ++#define TARGET_NR_inotify_init 284 ++#define TARGET_NR_inotify_add_watch 285 ++#define TARGET_NR_inotify_rm_watch 286 ++/* Number 287 is reserved for new sys_migrate_pages */ ++#define TARGET_NR_openat 288 ++#define TARGET_NR_mkdirat 289 ++#define TARGET_NR_mknodat 290 ++#define TARGET_NR_fchownat 291 ++#define TARGET_NR_futimesat 292 ++#define TARGET_NR_unlinkat 294 ++#define TARGET_NR_renameat 295 ++#define TARGET_NR_linkat 296 ++#define TARGET_NR_symlinkat 297 ++#define TARGET_NR_readlinkat 298 ++#define TARGET_NR_fchmodat 299 ++#define TARGET_NR_faccessat 300 ++#define TARGET_NR_pselect6 301 ++#define TARGET_NR_ppoll 302 ++#define TARGET_NR_unshare 303 ++#define TARGET_NR_set_robust_list 304 ++#define TARGET_NR_get_robust_list 305 ++#define TARGET_NR_splice 306 ++#define TARGET_NR_sync_file_range 307 ++#define TARGET_NR_tee 308 ++#define TARGET_NR_vmsplice 309 ++/* Number 310 is reserved for new sys_move_pages */ ++#define TARGET_NR_getcpu 311 ++#define TARGET_NR_epoll_pwait 312 ++#define TARGET_NR_utimes 313 ++#define TARGET_NR_fallocate 314 ++#define TARGET_NR_utimensat 315 ++#define TARGET_NR_signalfd 316 ++#define TARGET_NR_timerfd 317 ++#define TARGET_NR_eventfd 318 ++#define TARGET_NR_timerfd_create 319 ++#define TARGET_NR_timerfd_settime 320 ++#define TARGET_NR_timerfd_gettime 321 ++#define TARGET_NR_signalfd4 322 ++#define TARGET_NR_eventfd2 323 ++#define TARGET_NR_inotify_init1 324 ++#define TARGET_NR_pipe2 325 ++#define TARGET_NR_dup3 326 ++#define TARGET_NR_epoll_create1 327 ++#define NR_syscalls 328 ++ ++/* ++ * There are some system calls that are not present on 64 bit, some ++ * have a different name although they do the same (e.g. TARGET_NR_chown32 ++ * is TARGET_NR_chown on 64 bit). ++ */ ++#ifndef TARGET_S390X ++ ++#define TARGET_NR_time 13 ++#define TARGET_NR_lchown 16 ++#define TARGET_NR_setuid 23 ++#define TARGET_NR_getuid 24 ++#define TARGET_NR_stime 25 ++#define TARGET_NR_setgid 46 ++#define TARGET_NR_getgid 47 ++#define TARGET_NR_geteuid 49 ++#define TARGET_NR_getegid 50 ++#define TARGET_NR_setreuid 70 ++#define TARGET_NR_setregid 71 ++#define TARGET_NR_getrlimit 76 ++#define TARGET_NR_getgroups 80 ++#define TARGET_NR_setgroups 81 ++#define TARGET_NR_fchown 95 ++#define TARGET_NR_ioperm 101 ++#define TARGET_NR_setfsuid 138 ++#define TARGET_NR_setfsgid 139 ++#define TARGET_NR__llseek 140 ++#define TARGET_NR__newselect 142 ++#define TARGET_NR_setresuid 164 ++#define TARGET_NR_getresuid 165 ++#define TARGET_NR_setresgid 170 ++#define TARGET_NR_getresgid 171 ++#define TARGET_NR_chown 182 ++#define TARGET_NR_ugetrlimit 191 /* SuS compliant getrlimit */ ++#define TARGET_NR_mmap2 192 ++#define TARGET_NR_truncate64 193 ++#define TARGET_NR_ftruncate64 194 ++#define TARGET_NR_stat64 195 ++#define TARGET_NR_lstat64 196 ++#define TARGET_NR_fstat64 197 ++#define TARGET_NR_lchown32 198 ++#define TARGET_NR_getuid32 199 ++#define TARGET_NR_getgid32 200 ++#define TARGET_NR_geteuid32 201 ++#define TARGET_NR_getegid32 202 ++#define TARGET_NR_setreuid32 203 ++#define TARGET_NR_setregid32 204 ++#define TARGET_NR_getgroups32 205 ++#define TARGET_NR_setgroups32 206 ++#define TARGET_NR_fchown32 207 ++#define TARGET_NR_setresuid32 208 ++#define TARGET_NR_getresuid32 209 ++#define TARGET_NR_setresgid32 210 ++#define TARGET_NR_getresgid32 211 ++#define TARGET_NR_chown32 212 ++#define TARGET_NR_setuid32 213 ++#define TARGET_NR_setgid32 214 ++#define TARGET_NR_setfsuid32 215 ++#define TARGET_NR_setfsgid32 216 ++#define TARGET_NR_fcntl64 221 ++#define TARGET_NR_sendfile64 223 ++#define TARGET_NR_fadvise64_64 264 ++#define TARGET_NR_fstatat64 293 ++ ++#else ++ ++#define TARGET_NR_select 142 ++#define TARGET_NR_getrlimit 191 /* SuS compliant getrlimit */ ++#define TARGET_NR_lchown 198 ++#define TARGET_NR_getuid 199 ++#define TARGET_NR_getgid 200 ++#define TARGET_NR_geteuid 201 ++#define TARGET_NR_getegid 202 ++#define TARGET_NR_setreuid 203 ++#define TARGET_NR_setregid 204 ++#define TARGET_NR_getgroups 205 ++#define TARGET_NR_setgroups 206 ++#define TARGET_NR_fchown 207 ++#define TARGET_NR_setresuid 208 ++#define TARGET_NR_getresuid 209 ++#define TARGET_NR_setresgid 210 ++#define TARGET_NR_getresgid 211 ++#define TARGET_NR_chown 212 ++#define TARGET_NR_setuid 213 ++#define TARGET_NR_setgid 214 ++#define TARGET_NR_setfsuid 215 ++#define TARGET_NR_setfsgid 216 ++#define TARGET_NR_newfstatat 293 ++ ++#endif ++ +diff --git a/linux-user/s390x/target_signal.h b/linux-user/s390x/target_signal.h +new file mode 100644 +index 0000000..b4816b0 +--- /dev/null ++++ b/linux-user/s390x/target_signal.h +@@ -0,0 +1,26 @@ ++#ifndef TARGET_SIGNAL_H ++#define TARGET_SIGNAL_H ++ ++#include "cpu.h" ++ ++typedef struct target_sigaltstack { ++ abi_ulong ss_sp; ++ int ss_flags; ++ abi_ulong ss_size; ++} target_stack_t; ++ ++/* ++ * sigaltstack controls ++ */ ++#define TARGET_SS_ONSTACK 1 ++#define TARGET_SS_DISABLE 2 ++ ++#define TARGET_MINSIGSTKSZ 2048 ++#define TARGET_SIGSTKSZ 8192 ++ ++static inline abi_ulong get_sp_from_cpustate(CPUS390XState *state) ++{ ++ return state->regs[15]; ++} ++ ++#endif /* TARGET_SIGNAL_H */ +diff --git a/linux-user/s390x/termbits.h b/linux-user/s390x/termbits.h +new file mode 100644 +index 0000000..2a78a05 +--- /dev/null ++++ b/linux-user/s390x/termbits.h +@@ -0,0 +1,283 @@ ++/* ++ * include/asm-s390/termbits.h ++ * ++ * S390 version ++ * ++ * Derived from "include/asm-i386/termbits.h" ++ */ ++ ++#define TARGET_NCCS 19 ++struct target_termios { ++ unsigned int c_iflag; /* input mode flags */ ++ unsigned int c_oflag; /* output mode flags */ ++ unsigned int c_cflag; /* control mode flags */ ++ unsigned int c_lflag; /* local mode flags */ ++ unsigned char c_line; /* line discipline */ ++ unsigned char c_cc[TARGET_NCCS]; /* control characters */ ++}; ++ ++struct target_termios2 { ++ unsigned int c_iflag; /* input mode flags */ ++ unsigned int c_oflag; /* output mode flags */ ++ unsigned int c_cflag; /* control mode flags */ ++ unsigned int c_lflag; /* local mode flags */ ++ unsigned char c_line; /* line discipline */ ++ unsigned char c_cc[TARGET_NCCS]; /* control characters */ ++ unsigned int c_ispeed; /* input speed */ ++ unsigned int c_ospeed; /* output speed */ ++}; ++ ++struct target_ktermios { ++ unsigned int c_iflag; /* input mode flags */ ++ unsigned int c_oflag; /* output mode flags */ ++ unsigned int c_cflag; /* control mode flags */ ++ unsigned int c_lflag; /* local mode flags */ ++ unsigned char c_line; /* line discipline */ ++ unsigned char c_cc[TARGET_NCCS]; /* control characters */ ++ unsigned int c_ispeed; /* input speed */ ++ unsigned int c_ospeed; /* output speed */ ++}; ++ ++/* c_cc characters */ ++#define TARGET_VINTR 0 ++#define TARGET_VQUIT 1 ++#define TARGET_VERASE 2 ++#define TARGET_VKILL 3 ++#define TARGET_VEOF 4 ++#define TARGET_VTIME 5 ++#define TARGET_VMIN 6 ++#define TARGET_VSWTC 7 ++#define TARGET_VSTART 8 ++#define TARGET_VSTOP 9 ++#define TARGET_VSUSP 10 ++#define TARGET_VEOL 11 ++#define TARGET_VREPRINT 12 ++#define TARGET_VDISCARD 13 ++#define TARGET_VWERASE 14 ++#define TARGET_VLNEXT 15 ++#define TARGET_VEOL2 16 ++ ++/* c_iflag bits */ ++#define TARGET_IGNBRK 0000001 ++#define TARGET_BRKINT 0000002 ++#define TARGET_IGNPAR 0000004 ++#define TARGET_PARMRK 0000010 ++#define TARGET_INPCK 0000020 ++#define TARGET_ISTRIP 0000040 ++#define TARGET_INLCR 0000100 ++#define TARGET_IGNCR 0000200 ++#define TARGET_ICRNL 0000400 ++#define TARGET_IUCLC 0001000 ++#define TARGET_IXON 0002000 ++#define TARGET_IXANY 0004000 ++#define TARGET_IXOFF 0010000 ++#define TARGET_IMAXBEL 0020000 ++#define TARGET_IUTF8 0040000 ++ ++/* c_oflag bits */ ++#define TARGET_OPOST 0000001 ++#define TARGET_OLCUC 0000002 ++#define TARGET_ONLCR 0000004 ++#define TARGET_OCRNL 0000010 ++#define TARGET_ONOCR 0000020 ++#define TARGET_ONLRET 0000040 ++#define TARGET_OFILL 0000100 ++#define TARGET_OFDEL 0000200 ++#define TARGET_NLDLY 0000400 ++#define TARGET_NL0 0000000 ++#define TARGET_NL1 0000400 ++#define TARGET_CRDLY 0003000 ++#define TARGET_CR0 0000000 ++#define TARGET_CR1 0001000 ++#define TARGET_CR2 0002000 ++#define TARGET_CR3 0003000 ++#define TARGET_TABDLY 0014000 ++#define TARGET_TAB0 0000000 ++#define TARGET_TAB1 0004000 ++#define TARGET_TAB2 0010000 ++#define TARGET_TAB3 0014000 ++#define TARGET_XTABS 0014000 ++#define TARGET_BSDLY 0020000 ++#define TARGET_BS0 0000000 ++#define TARGET_BS1 0020000 ++#define TARGET_VTDLY 0040000 ++#define TARGET_VT0 0000000 ++#define TARGET_VT1 0040000 ++#define TARGET_FFDLY 0100000 ++#define TARGET_FF0 0000000 ++#define TARGET_FF1 0100000 ++ ++/* c_cflag bit meaning */ ++#define TARGET_CBAUD 0010017 ++#define TARGET_B0 0000000 /* hang up */ ++#define TARGET_B50 0000001 ++#define TARGET_B75 0000002 ++#define TARGET_B110 0000003 ++#define TARGET_B134 0000004 ++#define TARGET_B150 0000005 ++#define TARGET_B200 0000006 ++#define TARGET_B300 0000007 ++#define TARGET_B600 0000010 ++#define TARGET_B1200 0000011 ++#define TARGET_B1800 0000012 ++#define TARGET_B2400 0000013 ++#define TARGET_B4800 0000014 ++#define TARGET_B9600 0000015 ++#define TARGET_B19200 0000016 ++#define TARGET_B38400 0000017 ++#define TARGET_EXTA B19200 ++#define TARGET_EXTB B38400 ++#define TARGET_CSIZE 0000060 ++#define TARGET_CS5 0000000 ++#define TARGET_CS6 0000020 ++#define TARGET_CS7 0000040 ++#define TARGET_CS8 0000060 ++#define TARGET_CSTOPB 0000100 ++#define TARGET_CREAD 0000200 ++#define TARGET_PARENB 0000400 ++#define TARGET_PARODD 0001000 ++#define TARGET_HUPCL 0002000 ++#define TARGET_CLOCAL 0004000 ++#define TARGET_CBAUDEX 0010000 ++#define TARGET_BOTHER 0010000 ++#define TARGET_B57600 0010001 ++#define TARGET_B115200 0010002 ++#define TARGET_B230400 0010003 ++#define TARGET_B460800 0010004 ++#define TARGET_B500000 0010005 ++#define TARGET_B576000 0010006 ++#define TARGET_B921600 0010007 ++#define TARGET_B1000000 0010010 ++#define TARGET_B1152000 0010011 ++#define TARGET_B1500000 0010012 ++#define TARGET_B2000000 0010013 ++#define TARGET_B2500000 0010014 ++#define TARGET_B3000000 0010015 ++#define TARGET_B3500000 0010016 ++#define TARGET_B4000000 0010017 ++#define TARGET_CIBAUD 002003600000 /* input baud rate */ ++#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */ ++#define TARGET_CRTSCTS 020000000000 /* flow control */ ++ ++#define TARGET_IBSHIFT 16 /* Shift from CBAUD to CIBAUD */ ++ ++/* c_lflag bits */ ++#define TARGET_ISIG 0000001 ++#define TARGET_ICANON 0000002 ++#define TARGET_XCASE 0000004 ++#define TARGET_ECHO 0000010 ++#define TARGET_ECHOE 0000020 ++#define TARGET_ECHOK 0000040 ++#define TARGET_ECHONL 0000100 ++#define TARGET_NOFLSH 0000200 ++#define TARGET_TOSTOP 0000400 ++#define TARGET_ECHOCTL 0001000 ++#define TARGET_ECHOPRT 0002000 ++#define TARGET_ECHOKE 0004000 ++#define TARGET_FLUSHO 0010000 ++#define TARGET_PENDIN 0040000 ++#define TARGET_IEXTEN 0100000 ++ ++/* tcflow() and TCXONC use these */ ++#define TARGET_TCOOFF 0 ++#define TARGET_TCOON 1 ++#define TARGET_TCIOFF 2 ++#define TARGET_TCION 3 ++ ++/* tcflush() and TCFLSH use these */ ++#define TARGET_TCIFLUSH 0 ++#define TARGET_TCOFLUSH 1 ++#define TARGET_TCIOFLUSH 2 ++ ++/* tcsetattr uses these */ ++#define TARGET_TCSANOW 0 ++#define TARGET_TCSADRAIN 1 ++#define TARGET_TCSAFLUSH 2 ++ ++/* ++ * include/asm-s390/ioctls.h ++ * ++ * S390 version ++ * ++ * Derived from "include/asm-i386/ioctls.h" ++ */ ++ ++/* 0x54 is just a magic number to make these relatively unique ('T') */ ++ ++#define TARGET_TCGETS 0x5401 ++#define TARGET_TCSETS 0x5402 ++#define TARGET_TCSETSW 0x5403 ++#define TARGET_TCSETSF 0x5404 ++#define TARGET_TCGETA 0x5405 ++#define TARGET_TCSETA 0x5406 ++#define TARGET_TCSETAW 0x5407 ++#define TARGET_TCSETAF 0x5408 ++#define TARGET_TCSBRK 0x5409 ++#define TARGET_TCXONC 0x540A ++#define TARGET_TCFLSH 0x540B ++#define TARGET_TIOCEXCL 0x540C ++#define TARGET_TIOCNXCL 0x540D ++#define TARGET_TIOCSCTTY 0x540E ++#define TARGET_TIOCGPGRP 0x540F ++#define TARGET_TIOCSPGRP 0x5410 ++#define TARGET_TIOCOUTQ 0x5411 ++#define TARGET_TIOCSTI 0x5412 ++#define TARGET_TIOCGWINSZ 0x5413 ++#define TARGET_TIOCSWINSZ 0x5414 ++#define TARGET_TIOCMGET 0x5415 ++#define TARGET_TIOCMBIS 0x5416 ++#define TARGET_TIOCMBIC 0x5417 ++#define TARGET_TIOCMSET 0x5418 ++#define TARGET_TIOCGSOFTCAR 0x5419 ++#define TARGET_TIOCSSOFTCAR 0x541A ++#define TARGET_FIONREAD 0x541B ++#define TARGET_TIOCINQ FIONREAD ++#define TARGET_TIOCLINUX 0x541C ++#define TARGET_TIOCCONS 0x541D ++#define TARGET_TIOCGSERIAL 0x541E ++#define TARGET_TIOCSSERIAL 0x541F ++#define TARGET_TIOCPKT 0x5420 ++#define TARGET_FIONBIO 0x5421 ++#define TARGET_TIOCNOTTY 0x5422 ++#define TARGET_TIOCSETD 0x5423 ++#define TARGET_TIOCGETD 0x5424 ++#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ ++#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */ ++#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */ ++#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */ ++#define TARGET_TCGETS2 _IOR('T',0x2A, struct termios2) ++#define TARGET_TCSETS2 _IOW('T',0x2B, struct termios2) ++#define TARGET_TCSETSW2 _IOW('T',0x2C, struct termios2) ++#define TARGET_TCSETSF2 _IOW('T',0x2D, struct termios2) ++#define TARGET_TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ ++#define TARGET_TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ ++#define TARGET_TIOCGDEV _IOR('T',0x32, unsigned int) /* Get real dev no below /dev/console */ ++ ++#define TARGET_FIONCLEX 0x5450 /* these numbers need to be adjusted. */ ++#define TARGET_FIOCLEX 0x5451 ++#define TARGET_FIOASYNC 0x5452 ++#define TARGET_TIOCSERCONFIG 0x5453 ++#define TARGET_TIOCSERGWILD 0x5454 ++#define TARGET_TIOCSERSWILD 0x5455 ++#define TARGET_TIOCGLCKTRMIOS 0x5456 ++#define TARGET_TIOCSLCKTRMIOS 0x5457 ++#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */ ++#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */ ++#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */ ++#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ ++ ++#define TARGET_TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ ++#define TARGET_TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ ++#define TARGET_FIOQSIZE 0x545E ++ ++/* Used for packet mode */ ++#define TARGET_TIOCPKT_DATA 0 ++#define TARGET_TIOCPKT_FLUSHREAD 1 ++#define TARGET_TIOCPKT_FLUSHWRITE 2 ++#define TARGET_TIOCPKT_STOP 4 ++#define TARGET_TIOCPKT_START 8 ++#define TARGET_TIOCPKT_NOSTOP 16 ++#define TARGET_TIOCPKT_DOSTOP 32 ++ ++#define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */ ++ +diff --git a/linux-user/signal.c b/linux-user/signal.c +index df189c3..c66cf85 100644 +--- a/linux-user/signal.c ++++ b/linux-user/signal.c +@@ -3432,6 +3432,320 @@ long do_rt_sigreturn(CPUState *env) + return -TARGET_ENOSYS; + } + ++#elif defined(TARGET_S390X) ++ ++#define __NUM_GPRS 16 ++#define __NUM_FPRS 16 ++#define __NUM_ACRS 16 ++ ++#define S390_SYSCALL_SIZE 2 ++#define __SIGNAL_FRAMESIZE 160 /* FIXME: 31-bit mode -> 96 */ ++ ++#define _SIGCONTEXT_NSIG 64 ++#define _SIGCONTEXT_NSIG_BPW 64 /* FIXME: 31-bit mode -> 32 */ ++#define _SIGCONTEXT_NSIG_WORDS (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW) ++#define _SIGMASK_COPY_SIZE (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS) ++#define PSW_ADDR_AMODE 0x0000000000000000UL /* 0x80000000UL for 31-bit */ ++#define S390_SYSCALL_OPCODE ((uint16_t)0x0a00) ++ ++typedef struct ++{ ++ target_psw_t psw; ++ target_ulong gprs[__NUM_GPRS]; ++ unsigned int acrs[__NUM_ACRS]; ++} target_s390_regs_common; ++ ++typedef struct ++{ ++ unsigned int fpc; ++ double fprs[__NUM_FPRS]; ++} target_s390_fp_regs; ++ ++typedef struct ++{ ++ target_s390_regs_common regs; ++ target_s390_fp_regs fpregs; ++} target_sigregs; ++ ++struct target_sigcontext ++{ ++ target_ulong oldmask[_SIGCONTEXT_NSIG_WORDS]; ++ target_sigregs *sregs; ++}; ++ ++typedef struct ++{ ++ uint8_t callee_used_stack[__SIGNAL_FRAMESIZE]; ++ struct target_sigcontext sc; ++ target_sigregs sregs; ++ int signo; ++ uint8_t retcode[S390_SYSCALL_SIZE]; ++} sigframe; ++ ++struct target_ucontext { ++ target_ulong uc_flags; ++ struct target_ucontext *uc_link; ++ target_stack_t uc_stack; ++ target_sigregs uc_mcontext; ++ target_sigset_t uc_sigmask; /* mask last for extensibility */ ++}; ++ ++typedef struct ++{ ++ uint8_t callee_used_stack[__SIGNAL_FRAMESIZE]; ++ uint8_t retcode[S390_SYSCALL_SIZE]; ++ struct target_siginfo info; ++ struct target_ucontext uc; ++} rt_sigframe; ++ ++static inline abi_ulong ++get_sigframe(struct target_sigaction *ka, CPUState *env, size_t frame_size) ++{ ++ abi_ulong sp; ++ ++ /* Default to using normal stack */ ++ sp = env->regs[15]; ++ ++ /* This is the X/Open sanctioned signal stack switching. */ ++ if (ka->sa_flags & TARGET_SA_ONSTACK) { ++ if (! sas_ss_flags(sp)) ++ sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; ++ } ++ ++ /* This is the legacy signal stack switching. */ ++ else if (/* FIXME !user_mode(regs) */ 0 && ++ !(ka->sa_flags & TARGET_SA_RESTORER) && ++ ka->sa_restorer) { ++ sp = (abi_ulong) ka->sa_restorer; ++ } ++ ++ return (sp - frame_size) & -8ul; ++} ++ ++static void save_sigregs(CPUState *env, target_sigregs *sregs) ++{ ++ int i; ++ //save_access_regs(current->thread.acrs); FIXME ++ ++ /* Copy a 'clean' PSW mask to the user to avoid leaking ++ information about whether PER is currently on. */ ++ __put_user(env->psw.mask, &sregs->regs.psw.mask); ++ __put_user(env->psw.addr, &sregs->regs.psw.addr); ++ for (i = 0; i < 16; i++) ++ __put_user(env->regs[i], &sregs->regs.gprs[i]); ++ for (i = 0; i < 16; i++) ++ __put_user(env->aregs[i], &sregs->regs.acrs[i]); ++ /* ++ * We have to store the fp registers to current->thread.fp_regs ++ * to merge them with the emulated registers. ++ */ ++ //save_fp_regs(¤t->thread.fp_regs); FIXME ++ for (i = 0; i < 16; i++) ++ __put_user(env->fregs[i].ll, &sregs->fpregs.fprs[i]); ++} ++ ++static void setup_frame(int sig, struct target_sigaction *ka, ++ target_sigset_t *set, CPUState *env) ++{ ++ sigframe *frame; ++ abi_ulong frame_addr; ++ ++ frame_addr = get_sigframe(ka, env, sizeof *frame); ++ qemu_log("%s: frame_addr 0x%lx\n", __FUNCTION__, frame_addr); ++ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) ++ goto give_sigsegv; ++ ++ qemu_log("%s: 1\n", __FUNCTION__); ++ if (__put_user(set->sig[0], &frame->sc.oldmask[0])) ++ goto give_sigsegv; ++ ++ save_sigregs(env, &frame->sregs); ++ ++ __put_user((abi_ulong)&frame->sregs, (abi_ulong *)&frame->sc.sregs); ++ ++ /* Set up to return from userspace. If provided, use a stub ++ already in userspace. */ ++ if (ka->sa_flags & TARGET_SA_RESTORER) { ++ env->regs[14] = (unsigned long) ++ ka->sa_restorer | PSW_ADDR_AMODE; ++ } else { ++ env->regs[14] = (unsigned long) ++ frame->retcode | PSW_ADDR_AMODE; ++ if (__put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn, ++ (uint16_t *)(frame->retcode))) ++ goto give_sigsegv; ++ } ++ ++ /* Set up backchain. */ ++ if (__put_user(env->regs[15], (abi_ulong *) frame)) ++ goto give_sigsegv; ++ ++ /* Set up registers for signal handler */ ++ env->regs[15] = (target_ulong) frame; ++ env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE; ++ ++ env->regs[2] = sig; //map_signal(sig); ++ env->regs[3] = (target_ulong) &frame->sc; ++ ++ /* We forgot to include these in the sigcontext. ++ To avoid breaking binary compatibility, they are passed as args. */ ++ env->regs[4] = 0; // FIXME: no clue... current->thread.trap_no; ++ env->regs[5] = 0; // FIXME: no clue... current->thread.prot_addr; ++ ++ /* Place signal number on stack to allow backtrace from handler. */ ++ if (__put_user(env->regs[2], (int *) &frame->signo)) ++ goto give_sigsegv; ++ unlock_user_struct(frame, frame_addr, 1); ++ return; ++ ++give_sigsegv: ++ qemu_log("%s: give_sigsegv\n", __FUNCTION__); ++ unlock_user_struct(frame, frame_addr, 1); ++ force_sig(TARGET_SIGSEGV); ++} ++ ++static void setup_rt_frame(int sig, struct target_sigaction *ka, ++ target_siginfo_t *info, ++ target_sigset_t *set, CPUState *env) ++{ ++ int i; ++ rt_sigframe *frame; ++ abi_ulong frame_addr; ++ ++ frame_addr = get_sigframe(ka, env, sizeof *frame); ++ qemu_log("%s: frame_addr 0x%lx\n", __FUNCTION__, frame_addr); ++ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) ++ goto give_sigsegv; ++ ++ qemu_log("%s: 1\n", __FUNCTION__); ++ if (copy_siginfo_to_user(&frame->info, info)) ++ goto give_sigsegv; ++ ++ /* Create the ucontext. */ ++ __put_user(0, &frame->uc.uc_flags); ++ __put_user((abi_ulong)NULL, (abi_ulong*)&frame->uc.uc_link); ++ __put_user(target_sigaltstack_used.ss_sp, &frame->uc.uc_stack.ss_sp); ++ __put_user(sas_ss_flags(get_sp_from_cpustate(env)), ++ &frame->uc.uc_stack.ss_flags); ++ __put_user(target_sigaltstack_used.ss_size, &frame->uc.uc_stack.ss_size); ++ save_sigregs(env, &frame->uc.uc_mcontext); ++ for(i = 0; i < TARGET_NSIG_WORDS; i++) { ++ __put_user((abi_ulong)set->sig[i], (abi_ulong*)&frame->uc.uc_sigmask.sig[i]); ++ } ++ ++ /* Set up to return from userspace. If provided, use a stub ++ already in userspace. */ ++ if (ka->sa_flags & TARGET_SA_RESTORER) { ++ env->regs[14] = (unsigned long) ++ ka->sa_restorer | PSW_ADDR_AMODE; ++ } else { ++ env->regs[14] = (unsigned long) ++ frame->retcode | PSW_ADDR_AMODE; ++ if (__put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn, ++ (uint16_t *)(frame->retcode))) ++ goto give_sigsegv; ++ } ++ ++ /* Set up backchain. */ ++ if (__put_user(env->regs[15], (abi_ulong *) frame)) ++ goto give_sigsegv; ++ ++ /* Set up registers for signal handler */ ++ env->regs[15] = (target_ulong) frame; ++ env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE; ++ ++ env->regs[2] = sig; //map_signal(sig); ++ env->regs[3] = (target_ulong) &frame->info; ++ env->regs[4] = (target_ulong) &frame->uc; ++ return; ++ ++give_sigsegv: ++ qemu_log("%s: give_sigsegv\n", __FUNCTION__); ++ unlock_user_struct(frame, frame_addr, 1); ++ force_sig(TARGET_SIGSEGV); ++} ++ ++static int ++restore_sigregs(CPUState *env, target_sigregs *sc) ++{ ++ int err = 0; ++ int i; ++ ++ for (i = 0; i < 16; i++) { ++ err |= __get_user(env->regs[i], &sc->regs.gprs[i]); ++ } ++ ++ err |= __get_user(env->psw.mask, &sc->regs.psw.mask); ++ qemu_log("%s: sc->regs.psw.addr 0x%lx env->psw.addr 0x%lx\n", __FUNCTION__, sc->regs.psw.addr, env->psw.addr); ++ err |= __get_user(env->psw.addr, &sc->regs.psw.addr); ++ /* FIXME: 31-bit -> | PSW_ADDR_AMODE */ ++ ++ for (i = 0; i < 16; i++) { ++ err |= __get_user(env->aregs[i], &sc->regs.acrs[i]); ++ } ++ for (i = 0; i < 16; i++) { ++ err |= __get_user(env->fregs[i].ll, &sc->fpregs.fprs[i]); ++ } ++ ++ return err; ++} ++ ++long do_sigreturn(CPUState *env) ++{ ++ sigframe *frame; ++ abi_ulong frame_addr = env->regs[15]; ++ qemu_log("%s: frame_addr 0x%lx\n", __FUNCTION__, frame_addr); ++ target_sigset_t target_set; ++ sigset_t set; ++ ++ if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) ++ goto badframe; ++ if (__get_user(target_set.sig[0], &frame->sc.oldmask[0])) ++ goto badframe; ++ ++ target_to_host_sigset_internal(&set, &target_set); ++ sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */ ++ ++ if (restore_sigregs(env, &frame->sregs)) ++ goto badframe; ++ ++ unlock_user_struct(frame, frame_addr, 0); ++ return env->regs[2]; ++ ++badframe: ++ unlock_user_struct(frame, frame_addr, 0); ++ force_sig(TARGET_SIGSEGV); ++ return 0; ++} ++ ++long do_rt_sigreturn(CPUState *env) ++{ ++ rt_sigframe *frame; ++ abi_ulong frame_addr = env->regs[15]; ++ qemu_log("%s: frame_addr 0x%lx\n", __FUNCTION__, frame_addr); ++ sigset_t set; ++ ++ if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) ++ goto badframe; ++ target_to_host_sigset(&set, &frame->uc.uc_sigmask); ++ ++ sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */ ++ ++ if (restore_sigregs(env, &frame->uc.uc_mcontext)) ++ goto badframe; ++ ++ if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.uc_stack), 0, ++ get_sp_from_cpustate(env)) == -EFAULT) ++ goto badframe; ++ unlock_user_struct(frame, frame_addr, 0); ++ return env->regs[2]; ++ ++badframe: ++ unlock_user_struct(frame, frame_addr, 0); ++ force_sig(TARGET_SIGSEGV); ++ return 0; ++} ++ + #elif defined(TARGET_PPC) && !defined(TARGET_PPC64) + + /* FIXME: Many of the structures are defined for both PPC and PPC64, but +diff --git a/linux-user/syscall.c b/linux-user/syscall.c +index ec67a14..1995ebb 100644 +--- a/linux-user/syscall.c ++++ b/linux-user/syscall.c +@@ -186,7 +186,7 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \ + #define __NR_sys_inotify_add_watch __NR_inotify_add_watch + #define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch + +-#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__) ++#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__) || defined(__s390x__) + #define __NR__llseek __NR_lseek + #endif + +@@ -313,7 +313,7 @@ static int sys_fchmodat(int dirfd, const char *pathname, mode_t mode) + return (fchmodat(dirfd, pathname, mode, 0)); + } + #endif +-#if defined(TARGET_NR_fchownat) && defined(USE_UID16) ++#if defined(TARGET_NR_fchownat) + static int sys_fchownat(int dirfd, const char *pathname, uid_t owner, + gid_t group, int flags) + { +@@ -422,7 +422,7 @@ _syscall3(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode) + #if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat) + _syscall3(int,sys_fchmodat,int,dirfd,const char *,pathname, mode_t,mode) + #endif +-#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat) && defined(USE_UID16) ++#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat) + _syscall5(int,sys_fchownat,int,dirfd,const char *,pathname, + uid_t,owner,gid_t,group,int,flags) + #endif +@@ -3566,6 +3566,7 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp, + ts = qemu_mallocz(sizeof(TaskState) + NEW_STACK_SIZE); + init_task_state(ts); + new_stack = ts->stack; ++ env->multithreaded = 1; + /* we create a new CPU instance. */ + new_env = cpu_copy(env); + #if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC) +@@ -5145,7 +5146,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, + ret = get_errno(settimeofday(&tv, NULL)); + } + break; +-#ifdef TARGET_NR_select ++#if defined(TARGET_NR_select) && !defined(TARGET_S390X) && !defined(TARGET_S390) + case TARGET_NR_select: + { + struct target_sel_arg_struct *sel; +@@ -5252,7 +5253,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, + #endif + #ifdef TARGET_NR_mmap + case TARGET_NR_mmap: +-#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) ++#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || \ ++ defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) \ ++ || defined(TARGET_S390X) + { + abi_ulong *v; + abi_ulong v1, v2, v3, v4, v5, v6; +@@ -5737,6 +5740,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, + ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4)); + #elif defined(TARGET_CRIS) + ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg4, arg5)); ++#elif defined(TARGET_S390X) ++ ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4)); + #else + ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5)); + #endif +@@ -5941,8 +5946,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, + } + break; + #endif /* TARGET_NR_getdents64 */ +-#ifdef TARGET_NR__newselect ++#if defined(TARGET_NR__newselect) || defined(TARGET_S390X) ++#ifdef TARGET_S390X ++ case TARGET_NR_select: ++#else + case TARGET_NR__newselect: ++#endif + ret = do_select(arg1, arg2, arg3, arg4, arg5); + break; + #endif +@@ -6167,7 +6176,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, + case TARGET_NR_sigaltstack: + #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \ + defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA) || \ +- defined(TARGET_M68K) ++ defined(TARGET_M68K) || defined(TARGET_S390X) + ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env)); + break; + #else +@@ -6400,18 +6409,35 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, + case TARGET_NR_setfsgid: + ret = get_errno(setfsgid(arg1)); + break; ++#else /* USE_UID16 */ ++#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat) ++ case TARGET_NR_fchownat: ++ if (!(p = lock_user_string(arg2))) ++ goto efault; ++ ret = get_errno(sys_fchownat(arg1, p, arg3, arg4, arg5)); ++ unlock_user(p, arg2, 0); ++ break; ++#endif + #endif /* USE_UID16 */ + +-#ifdef TARGET_NR_lchown32 ++#if defined(TARGET_NR_lchown32) || !defined(USE_UID16) ++#if defined(TARGET_NR_lchown32) + case TARGET_NR_lchown32: ++#else ++ case TARGET_NR_lchown: ++#endif + if (!(p = lock_user_string(arg1))) + goto efault; + ret = get_errno(lchown(p, arg2, arg3)); + unlock_user(p, arg1, 0); + break; + #endif +-#ifdef TARGET_NR_getuid32 ++#if defined(TARGET_NR_getuid32) || (defined(TARGET_NR_getuid) && !defined(USE_UID16)) ++#if defined(TARGET_NR_getuid32) + case TARGET_NR_getuid32: ++#else ++ case TARGET_NR_getuid: ++#endif + ret = get_errno(getuid()); + break; + #endif +@@ -6439,33 +6465,57 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, + break; + #endif + +-#ifdef TARGET_NR_getgid32 ++#if defined(TARGET_NR_getgid32) || (defined(TARGET_NR_getgid) && !defined(USE_UID16)) ++#if defined(TARGET_NR_getgid32) + case TARGET_NR_getgid32: ++#else ++ case TARGET_NR_getgid: ++#endif + ret = get_errno(getgid()); + break; + #endif +-#ifdef TARGET_NR_geteuid32 ++#if defined(TARGET_NR_geteuid32) || (defined(TARGET_NR_geteuid) && !defined(USE_UID16)) ++#if defined(TARGET_NR_geteuid32) + case TARGET_NR_geteuid32: ++#else ++ case TARGET_NR_geteuid: ++#endif + ret = get_errno(geteuid()); + break; + #endif +-#ifdef TARGET_NR_getegid32 ++#if defined(TARGET_NR_getegid32) || (defined(TARGET_NR_getegid) && !defined(USE_UID16)) ++#if defined(TARGET_NR_getegid32) + case TARGET_NR_getegid32: ++#else ++ case TARGET_NR_getegid: ++#endif + ret = get_errno(getegid()); + break; + #endif +-#ifdef TARGET_NR_setreuid32 ++#if defined(TARGET_NR_setreuid32) || !defined(USE_UID16) ++#if defined(TARGET_NR_setreuid32) + case TARGET_NR_setreuid32: ++#else ++ case TARGET_NR_setreuid: ++#endif + ret = get_errno(setreuid(arg1, arg2)); + break; + #endif +-#ifdef TARGET_NR_setregid32 ++#if defined(TARGET_NR_setregid32) || !defined(USE_UID16) ++#if defined(TARGET_NR_setregid32) + case TARGET_NR_setregid32: ++#else ++ case TARGET_NR_setregid: ++#endif + ret = get_errno(setregid(arg1, arg2)); + break; + #endif +-#ifdef TARGET_NR_getgroups32 ++#if defined(TARGET_NR_getgroups32) || !defined(USE_UID16) ++#if defined(TARGET_NR_getgroups32) + case TARGET_NR_getgroups32: ++#else ++ case TARGET_NR_getgroups: ++#endif + { + int gidsetsize = arg1; + uint32_t *target_grouplist; +@@ -6489,8 +6539,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, + } + break; + #endif +-#ifdef TARGET_NR_setgroups32 ++#if defined(TARGET_NR_setgroups32) || !defined(USE_UID16) ++#if defined(TARGET_NR_setgroups32) + case TARGET_NR_setgroups32: ++#else ++ case TARGET_NR_setgroups: ++#endif + { + int gidsetsize = arg1; + uint32_t *target_grouplist; +@@ -6510,18 +6564,30 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, + } + break; + #endif +-#ifdef TARGET_NR_fchown32 ++#if defined(TARGET_NR_fchown32) || !defined(USE_UID16) ++#if defined(TARGET_NR_fchown32) + case TARGET_NR_fchown32: ++#else ++ case TARGET_NR_fchown: ++#endif + ret = get_errno(fchown(arg1, arg2, arg3)); + break; + #endif +-#ifdef TARGET_NR_setresuid32 ++#if defined(TARGET_NR_setresuid32) || !defined(USE_UID16) ++#if defined(TARGET_NR_setresuid32) + case TARGET_NR_setresuid32: ++#else ++ case TARGET_NR_setresuid: ++#endif + ret = get_errno(setresuid(arg1, arg2, arg3)); + break; + #endif +-#ifdef TARGET_NR_getresuid32 ++#if defined(TARGET_NR_getresuid32) || !defined(USE_UID16) ++#if defined(TARGET_NR_getresuid32) + case TARGET_NR_getresuid32: ++#else ++ case TARGET_NR_getresuid: ++#endif + { + uid_t ruid, euid, suid; + ret = get_errno(getresuid(&ruid, &euid, &suid)); +@@ -6534,13 +6600,21 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, + } + break; + #endif +-#ifdef TARGET_NR_setresgid32 ++#if defined(TARGET_NR_setresgid32) || !defined(USE_UID16) ++#if defined(TARGET_NR_setresgid32) + case TARGET_NR_setresgid32: ++#else ++ case TARGET_NR_setresgid: ++#endif + ret = get_errno(setresgid(arg1, arg2, arg3)); + break; + #endif ++#if defined(TARGET_NR_getresgid32) || !defined(USE_UID16) + #ifdef TARGET_NR_getresgid32 + case TARGET_NR_getresgid32: ++#else ++ case TARGET_NR_getresgid: ++#endif + { + gid_t rgid, egid, sgid; + ret = get_errno(getresgid(&rgid, &egid, &sgid)); +@@ -6553,31 +6627,51 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, + } + break; + #endif +-#ifdef TARGET_NR_chown32 ++#if defined(TARGET_NR_chown32) || !defined(USE_UID16) ++#if defined(TARGET_NR_chown32) + case TARGET_NR_chown32: ++#else ++ case TARGET_NR_chown: ++#endif + if (!(p = lock_user_string(arg1))) + goto efault; + ret = get_errno(chown(p, arg2, arg3)); + unlock_user(p, arg1, 0); + break; + #endif +-#ifdef TARGET_NR_setuid32 ++#if defined(TARGET_NR_setuid32) || !defined(USE_UID16) ++#if defined(TARGET_NR_setuid32) + case TARGET_NR_setuid32: ++#else ++ case TARGET_NR_setuid: ++#endif + ret = get_errno(setuid(arg1)); + break; + #endif +-#ifdef TARGET_NR_setgid32 ++#if defined(TARGET_NR_setgid32) || !defined(USE_UID16) ++#if defined(TARGET_NR_setgid32) + case TARGET_NR_setgid32: ++#else ++ case TARGET_NR_setgid: ++#endif + ret = get_errno(setgid(arg1)); + break; + #endif +-#ifdef TARGET_NR_setfsuid32 ++#if defined(TARGET_NR_setfsuid32) || !defined(USE_UID16) ++#if defined(TARGET_NR_setfsuid32) + case TARGET_NR_setfsuid32: ++#else ++ case TARGET_NR_setfsuid: ++#endif + ret = get_errno(setfsuid(arg1)); + break; + #endif +-#ifdef TARGET_NR_setfsgid32 ++#if defined(TARGET_NR_setfsgid32) || !defined(USE_UID16) ++#if defined(TARGET_NR_setfsgid32) + case TARGET_NR_setfsgid32: ++#else ++ case TARGET_NR_setfsgid: ++#endif + ret = get_errno(setfsgid(arg1)); + break; + #endif +diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h +index e734fec..a703f8e 100644 +--- a/linux-user/syscall_defs.h ++++ b/linux-user/syscall_defs.h +@@ -55,7 +55,7 @@ + #endif + + #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SH4) \ +- || defined(TARGET_M68K) || defined(TARGET_CRIS) ++ || defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_S390X) + + #define TARGET_IOC_SIZEBITS 14 + #define TARGET_IOC_DIRBITS 2 +@@ -315,7 +315,10 @@ struct target_sigaction; + int do_sigaction(int sig, const struct target_sigaction *act, + struct target_sigaction *oact); + +-#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_MIPS) || defined (TARGET_SH4) || defined(TARGET_M68K) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) ++#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) || \ ++ defined(TARGET_PPC) || defined(TARGET_MIPS) || defined (TARGET_SH4) || \ ++ defined(TARGET_M68K) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \ ++ defined(TARGET_MICROBLAZE) || defined(TARGET_S390X) + + #if defined(TARGET_SPARC) + #define TARGET_SA_NOCLDSTOP 8u +@@ -1633,6 +1636,27 @@ struct target_stat { + + abi_long __unused[3]; + }; ++#elif defined(TARGET_S390X) ++struct target_stat { ++ abi_ulong st_dev; ++ abi_ulong st_ino; ++ abi_ulong st_nlink; ++ unsigned int st_mode; ++ unsigned int st_uid; ++ unsigned int st_gid; ++ unsigned int __pad1; ++ abi_ulong st_rdev; ++ abi_ulong st_size; ++ abi_ulong target_st_atime; ++ abi_ulong target_st_atime_nsec; ++ abi_ulong target_st_mtime; ++ abi_ulong target_st_mtime_nsec; ++ abi_ulong target_st_ctime; ++ abi_ulong target_st_ctime_nsec; ++ abi_ulong st_blksize; ++ abi_long st_blocks; ++ abi_ulong __unused[3]; ++}; + #else + #error unsupported CPU + #endif +@@ -1719,6 +1743,34 @@ struct target_statfs64 { + abi_long f_frsize; + abi_long f_spare[5]; + }; ++#elif defined(TARGET_S390X) ++struct target_statfs { ++ int32_t f_type; ++ int32_t f_bsize; ++ abi_long f_blocks; ++ abi_long f_bfree; ++ abi_long f_bavail; ++ abi_long f_files; ++ abi_long f_ffree; ++ kernel_fsid_t f_fsid; ++ int32_t f_namelen; ++ int32_t f_frsize; ++ int32_t f_spare[5]; ++}; ++ ++struct target_statfs64 { ++ int32_t f_type; ++ int32_t f_bsize; ++ abi_long f_blocks; ++ abi_long f_bfree; ++ abi_long f_bavail; ++ abi_long f_files; ++ abi_long f_ffree; ++ kernel_fsid_t f_fsid; ++ int32_t f_namelen; ++ int32_t f_frsize; ++ int32_t f_spare[5]; ++}; + #else + struct target_statfs { + uint32_t f_type; +diff --git a/qemu-binfmt-conf.sh b/qemu-binfmt-conf.sh +index 67d6728..e676f57 100644 +--- a/qemu-binfmt-conf.sh ++++ b/qemu-binfmt-conf.sh +@@ -1,5 +1,5 @@ + #!/bin/sh +-# enable automatic i386/ARM/M68K/MIPS/SPARC/PPC program execution by the kernel ++# enable automatic i386/ARM/M68K/MIPS/SPARC/PPC/s390 program execution by the kernel + + # load the binfmt_misc module + if [ ! -d /proc/sys/fs/binfmt_misc ]; then +@@ -60,3 +60,6 @@ if [ $cpu != "mips" ] ; then + echo ':mips64:M::\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-mips64:' > /proc/sys/fs/binfmt_misc/register + echo ':mips64el:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-mips64el:' > /proc/sys/fs/binfmt_misc/register + fi ++if [ $cpu != "s390x" ] ; then ++ echo ':s390x:M::\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x16:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-s390x:' > /proc/sys/fs/binfmt_misc/register ++fi +diff --git a/s390-dis.c b/s390-dis.c +index 86dd84f..9a73a57 100644 +--- a/s390-dis.c ++++ b/s390-dis.c +@@ -191,10 +191,10 @@ init_disasm (struct disassemble_info *info) + // switch (info->mach) + // { + // case bfd_mach_s390_31: +- current_arch_mask = 1 << S390_OPCODE_ESA; ++// current_arch_mask = 1 << S390_OPCODE_ESA; + // break; + // case bfd_mach_s390_64: +-// current_arch_mask = 1 << S390_OPCODE_ZARCH; ++ current_arch_mask = 1 << S390_OPCODE_ZARCH; + // break; + // default: + // abort (); +diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h +index 0e75e1c..f2578af 100644 +--- a/target-s390x/cpu.h ++++ b/target-s390x/cpu.h +@@ -32,19 +32,9 @@ + + #define NB_MMU_MODES 2 + +-typedef union FPReg { +- struct { +-#ifdef WORDS_BIGENDIAN +- float32 e; +- int32_t __pad; +-#else +- int32_t __pad; +- float32 e; +-#endif +- }; +- float64 d; +- uint64_t i; +-} FPReg; ++#define TARGET_PAGE_BITS 12 ++ ++#include "cpu-all.h" + + typedef struct CPUS390XState { + uint64_t regs[16]; /* GP registers */ +@@ -52,7 +42,7 @@ typedef struct CPUS390XState { + uint32_t aregs[16]; /* access registers */ + + uint32_t fpc; /* floating-point control register */ +- FPReg fregs[16]; /* FP registers */ ++ CPU_DoubleU fregs[16]; /* FP registers */ + float_status fpu_status; /* passed to softfloat lib */ + + struct { +@@ -88,6 +78,8 @@ static inline int cpu_mmu_index (CPUState *env) + CPUS390XState *cpu_s390x_init(const char *cpu_model); + int cpu_s390x_exec(CPUS390XState *s); + void cpu_s390x_close(CPUS390XState *s); ++void s390x_translate_init(void); ++void do_interrupt (CPUState *env); + + /* you can call this signal handler from your SIGBUS and SIGSEGV + signal handlers to inform the virtual CPU of exceptions. non zero +@@ -106,17 +98,26 @@ extern void kvm_s390_virtio_irq(CPUState *env, int config_change, uint64_t token + extern CPUState *s390_cpu_addr2state(uint16_t cpu_addr); + #endif + ++void cpu_lock(void); ++void cpu_unlock(void); ++ ++static inline void cpu_set_tls(CPUS390XState *env, target_ulong newtls) ++{ ++ env->aregs[0] = newtls >> 32; ++ env->aregs[1] = newtls & 0xffffffffULL; ++} + + #define cpu_init cpu_s390x_init + #define cpu_exec cpu_s390x_exec + #define cpu_gen_code cpu_s390x_gen_code ++#define cpu_signal_handler cpu_s390x_signal_handler + +-#include "cpu-all.h" + #include "exec-all.h" + + #define EXCP_OPEX 1 /* operation exception (sigill) */ + #define EXCP_SVC 2 /* supervisor call (syscall) */ + #define EXCP_ADDR 5 /* addressing exception */ ++#define EXCP_SPEC 6 /* specification exception */ + #define EXCP_EXECUTE_SVC 0xff00000 /* supervisor call via execute insn */ + + static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock* tb) +diff --git a/target-s390x/exec.h b/target-s390x/exec.h +index 13dc7dd..e80c69e 100644 +--- a/target-s390x/exec.h ++++ b/target-s390x/exec.h +@@ -32,7 +32,7 @@ register struct CPUS390XState *env asm(AREG0); + + static inline int cpu_has_work(CPUState *env) + { +- return env->interrupt_request & CPU_INTERRUPT_HARD; // guess ++ return env->interrupt_request & CPU_INTERRUPT_HARD; /* guess */ + } + + static inline void regs_to_env(void) +diff --git a/target-s390x/helper.c b/target-s390x/helper.c +index 4c2dc82..ec096c4 100644 +--- a/target-s390x/helper.c ++++ b/target-s390x/helper.c +@@ -39,6 +39,7 @@ CPUS390XState *cpu_s390x_init(const char *cpu_model) + cpu_exec_init(env); + if (!inited) { + inited = 1; ++ s390x_translate_init(); + } + + env->cpu_model_str = cpu_model; +@@ -64,8 +65,31 @@ void cpu_reset(CPUS390XState *env) + tlb_flush(env, 1); + } + ++#if defined(CONFIG_USER_ONLY) ++ ++void do_interrupt (CPUState *env) ++{ ++ env->exception_index = -1; ++} ++ ++int cpu_s390x_handle_mmu_fault (CPUState *env, target_ulong address, int rw, ++ int mmu_idx, int is_softmmu) ++{ ++ /* fprintf(stderr,"%s: address 0x%lx rw %d mmu_idx %d is_softmmu %d\n", __FUNCTION__, address, rw, mmu_idx, is_softmmu); */ ++ env->exception_index = EXCP_ADDR; ++ env->__excp_addr = address; /* FIXME: find out how this works on a real machine */ ++ return 1; ++} ++ ++#endif /* CONFIG_USER_ONLY */ ++ + #ifndef CONFIG_USER_ONLY + ++target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) ++{ ++ return 0; ++} ++ + int cpu_s390x_handle_mmu_fault (CPUState *env, target_ulong address, int rw, + int mmu_idx, int is_softmmu) + { +diff --git a/target-s390x/helpers.h b/target-s390x/helpers.h +new file mode 100644 +index 0000000..0d16760 +--- /dev/null ++++ b/target-s390x/helpers.h +@@ -0,0 +1,128 @@ ++#include "def-helper.h" ++ ++DEF_HELPER_1(exception, void, i32) ++DEF_HELPER_4(nc, i32, i32, i32, i32, i32) ++DEF_HELPER_4(oc, i32, i32, i32, i32, i32) ++DEF_HELPER_4(xc, i32, i32, i32, i32, i32) ++DEF_HELPER_4(mvc, void, i32, i32, i32, i32) ++DEF_HELPER_4(clc, i32, i32, i32, i32, i32) ++DEF_HELPER_4(lmg, void, i32, i32, i32, s32) ++DEF_HELPER_4(stmg, void, i32, i32, i32, s32) ++DEF_HELPER_FLAGS_1(set_cc_s32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32) ++DEF_HELPER_FLAGS_1(set_cc_s64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64) ++DEF_HELPER_FLAGS_1(set_cc_comp_s32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32) ++DEF_HELPER_FLAGS_1(set_cc_comp_s64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64) ++DEF_HELPER_FLAGS_1(set_cc_nz_u32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32) ++DEF_HELPER_FLAGS_1(set_cc_nz_u64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64) ++DEF_HELPER_FLAGS_2(set_cc_icm, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32) ++DEF_HELPER_4(brc, void, i32, i32, i64, s32) ++DEF_HELPER_3(brctg, void, i64, i64, s32) ++DEF_HELPER_3(brct, void, i32, i64, s32) ++DEF_HELPER_4(brcl, void, i32, i32, i64, s64) ++DEF_HELPER_4(bcr, void, i32, i32, i64, i64) ++DEF_HELPER_4(bc, void, i32, i32, i64, i64) ++DEF_HELPER_FLAGS_2(cmp_u64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64) ++DEF_HELPER_FLAGS_2(cmp_u32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32) ++DEF_HELPER_FLAGS_2(cmp_s32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32, s32) ++DEF_HELPER_FLAGS_2(cmp_s64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64, s64) ++DEF_HELPER_3(clm, i32, i32, i32, i64) ++DEF_HELPER_3(stcm, void, i32, i32, i64) ++DEF_HELPER_2(mlg, void, i32, i64) ++DEF_HELPER_2(dlg, void, i32, i64) ++DEF_HELPER_FLAGS_3(set_cc_add64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64, s64, s64) ++DEF_HELPER_FLAGS_3(set_cc_addu64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64) ++DEF_HELPER_FLAGS_3(set_cc_add32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32, s32, s32) ++DEF_HELPER_FLAGS_3(set_cc_addu32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32, i32) ++DEF_HELPER_FLAGS_3(set_cc_sub64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64, s64, s64) ++DEF_HELPER_FLAGS_3(set_cc_subu64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64) ++DEF_HELPER_FLAGS_3(set_cc_sub32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32, s32, s32) ++DEF_HELPER_FLAGS_3(set_cc_subu32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32, i32) ++DEF_HELPER_3(srst, i32, i32, i32, i32) ++DEF_HELPER_3(clst, i32, i32, i32, i32) ++DEF_HELPER_3(mvst, i32, i32, i32, i32) ++DEF_HELPER_3(csg, i32, i32, i64, i32) ++DEF_HELPER_3(cdsg, i32, i32, i64, i32) ++DEF_HELPER_3(cs, i32, i32, i64, i32) ++DEF_HELPER_4(ex, i32, i32, i64, i64, i64) ++DEF_HELPER_FLAGS_2(tm, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32) ++DEF_HELPER_FLAGS_2(tmxx, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i32) ++DEF_HELPER_2(abs_i32, i32, i32, s32) ++DEF_HELPER_2(nabs_i32, i32, i32, s32) ++DEF_HELPER_2(abs_i64, i32, i32, s64) ++DEF_HELPER_2(nabs_i64, i32, i32, s64) ++DEF_HELPER_3(stcmh, i32, i32, i64, i32) ++DEF_HELPER_3(icmh, i32, i32, i64, i32) ++DEF_HELPER_2(ipm, void, i32, i32) ++DEF_HELPER_3(addc_u32, i32, i32, i32, i32) ++DEF_HELPER_FLAGS_3(set_cc_addc_u64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64) ++DEF_HELPER_3(stam, void, i32, i64, i32) ++DEF_HELPER_3(mvcle, i32, i32, i64, i32) ++DEF_HELPER_3(clcle, i32, i32, i64, i32) ++DEF_HELPER_4(slb, i32, i32, i32, i32, i32) ++DEF_HELPER_4(slbg, i32, i32, i32, i64, i64) ++DEF_HELPER_2(cefbr, void, i32, s32) ++DEF_HELPER_2(cdfbr, void, i32, s32) ++DEF_HELPER_2(cxfbr, void, i32, s32) ++DEF_HELPER_2(cegbr, void, i32, s64) ++DEF_HELPER_2(cdgbr, void, i32, s64) ++DEF_HELPER_2(cxgbr, void, i32, s64) ++DEF_HELPER_2(adbr, i32, i32, i32) ++DEF_HELPER_2(aebr, i32, i32, i32) ++DEF_HELPER_2(sebr, i32, i32, i32) ++DEF_HELPER_2(sdbr, i32, i32, i32) ++DEF_HELPER_2(debr, void, i32, i32) ++DEF_HELPER_2(dxbr, void, i32, i32) ++DEF_HELPER_2(mdbr, void, i32, i32) ++DEF_HELPER_2(mxbr, void, i32, i32) ++DEF_HELPER_2(ldebr, void, i32, i32) ++DEF_HELPER_2(ldxbr, void, i32, i32) ++DEF_HELPER_2(lxdbr, void, i32, i32) ++DEF_HELPER_2(ledbr, void, i32, i32) ++DEF_HELPER_2(lexbr, void, i32, i32) ++DEF_HELPER_2(lpebr, i32, i32, i32) ++DEF_HELPER_2(lpdbr, i32, i32, i32) ++DEF_HELPER_2(lpxbr, i32, i32, i32) ++DEF_HELPER_2(ltebr, i32, i32, i32) ++DEF_HELPER_2(ltdbr, i32, i32, i32) ++DEF_HELPER_2(ltxbr, i32, i32, i32) ++DEF_HELPER_2(lcebr, i32, i32, i32) ++DEF_HELPER_2(lcdbr, i32, i32, i32) ++DEF_HELPER_2(lcxbr, i32, i32, i32) ++DEF_HELPER_2(ceb, i32, i32, i32) ++DEF_HELPER_2(aeb, i32, i32, i32) ++DEF_HELPER_2(deb, void, i32, i32) ++DEF_HELPER_2(meeb, void, i32, i32) ++DEF_HELPER_2(cdb, i32, i32, i64) ++DEF_HELPER_2(adb, i32, i32, i64) ++DEF_HELPER_2(seb, i32, i32, i32) ++DEF_HELPER_2(sdb, i32, i32, i64) ++DEF_HELPER_2(mdb, void, i32, i64) ++DEF_HELPER_2(ddb, void, i32, i64) ++DEF_HELPER_FLAGS_2(cebr, TCG_CALL_PURE, i32, i32, i32) ++DEF_HELPER_FLAGS_2(cdbr, TCG_CALL_PURE, i32, i32, i32) ++DEF_HELPER_FLAGS_2(cxbr, TCG_CALL_PURE, i32, i32, i32) ++DEF_HELPER_3(cgebr, i32, i32, i32, i32) ++DEF_HELPER_3(cgdbr, i32, i32, i32, i32) ++DEF_HELPER_3(cgxbr, i32, i32, i32, i32) ++DEF_HELPER_1(lzer, void, i32) ++DEF_HELPER_1(lzdr, void, i32) ++DEF_HELPER_1(lzxr, void, i32) ++DEF_HELPER_3(cfebr, i32, i32, i32, i32) ++DEF_HELPER_3(cfdbr, i32, i32, i32, i32) ++DEF_HELPER_3(cfxbr, i32, i32, i32, i32) ++DEF_HELPER_2(axbr, i32, i32, i32) ++DEF_HELPER_2(sxbr, i32, i32, i32) ++DEF_HELPER_2(meebr, void, i32, i32) ++DEF_HELPER_2(ddbr, void, i32, i32) ++DEF_HELPER_3(madb, void, i32, i64, i32) ++DEF_HELPER_3(maebr, void, i32, i32, i32) ++DEF_HELPER_3(madbr, void, i32, i32, i32) ++DEF_HELPER_3(msdbr, void, i32, i32, i32) ++DEF_HELPER_2(lxdb, void, i32, i64) ++DEF_HELPER_FLAGS_2(tceb, TCG_CALL_PURE, i32, i32, i64) ++DEF_HELPER_FLAGS_2(tcdb, TCG_CALL_PURE, i32, i32, i64) ++DEF_HELPER_FLAGS_2(tcxb, TCG_CALL_PURE, i32, i32, i64) ++DEF_HELPER_2(flogr, i32, i32, i64) ++DEF_HELPER_2(sqdbr, void, i32, i32) ++ ++#include "def-helper.h" +diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c +index e623de9..d523c34 100644 +--- a/target-s390x/op_helper.c ++++ b/target-s390x/op_helper.c +@@ -1,6 +1,7 @@ + /* + * S/390 helper routines + * ++ * Copyright (c) 2009 Ulrich Hecht + * Copyright (c) 2009 Alexander Graf + * + * This library is free software; you can redistribute it and/or +@@ -72,3 +73,1622 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) + } + + #endif ++ ++#include "helpers.h" ++#include ++ ++/* #define DEBUG_HELPER */ ++#ifdef DEBUG_HELPER ++#define HELPER_LOG(x...) qemu_log(x) ++#else ++#define HELPER_LOG(x...) ++#endif ++ ++/* raise an exception */ ++void HELPER(exception)(uint32_t excp) ++{ ++ HELPER_LOG("%s: exception %d\n", __FUNCTION__, excp); ++ env->exception_index = excp; ++ cpu_loop_exit(); ++} ++ ++/* and on array */ ++uint32_t HELPER(nc)(uint32_t l, uint32_t b, uint32_t d1, uint32_t d2) ++{ ++ uint64_t dest = env->regs[b >> 4] + d1; ++ uint64_t src = env->regs[b & 0xf] + d2; ++ int i; ++ unsigned char x; ++ uint32_t cc = 0; ++ HELPER_LOG("%s l %d b 0x%x d1 %d d2 %d\n", __FUNCTION__, l, b, d1, d2); ++ for (i = 0; i <= l; i++) { ++ x = ldub(dest + i) & ldub(src + i); ++ if (x) cc = 1; ++ stb(dest + i, x); ++ } ++ return cc; ++} ++ ++/* xor on array */ ++uint32_t HELPER(xc)(uint32_t l, uint32_t b, uint32_t d1, uint32_t d2) ++{ ++ uint64_t dest = env->regs[b >> 4] + d1; ++ uint64_t src = env->regs[b & 0xf] + d2; ++ int i; ++ unsigned char x; ++ uint32_t cc = 0; ++ HELPER_LOG("%s l %d b 0x%x d1 %d d2 %d\n", __FUNCTION__, l, b, d1, d2); ++ for (i = 0; i <= l; i++) { ++ x = ldub(dest + i) ^ ldub(src + i); ++ if (x) cc = 1; ++ stb(dest + i, x); ++ } ++ return cc; ++} ++ ++/* or on array */ ++uint32_t HELPER(oc)(uint32_t l, uint32_t b, uint32_t d1, uint32_t d2) ++{ ++ uint64_t dest = env->regs[b >> 4] + d1; ++ uint64_t src = env->regs[b & 0xf] + d2; ++ int i; ++ unsigned char x; ++ uint32_t cc = 0; ++ HELPER_LOG("%s l %d b 0x%x d1 %d d2 %d\n", __FUNCTION__, l, b, d1, d2); ++ for (i = 0; i <= l; i++) { ++ x = ldub(dest + i) | ldub(src + i); ++ if (x) cc = 1; ++ stb(dest + i, x); ++ } ++ return cc; ++} ++ ++/* memcopy */ ++void HELPER(mvc)(uint32_t l, uint32_t b, uint32_t d1, uint32_t d2) ++{ ++ uint64_t dest = env->regs[b >> 4] + d1; ++ uint64_t src = env->regs[b & 0xf] + d2; ++ int i; ++ HELPER_LOG("%s l %d b 0x%x d1 %d d2 %d\n", __FUNCTION__, l, b, d1, d2); ++ for (i = 0; i <= l; i++) { ++ stb(dest + i, ldub(src + i)); ++ } ++} ++ ++/* compare unsigned byte arrays */ ++uint32_t HELPER(clc)(uint32_t l, uint32_t b, uint32_t d1, uint32_t d2) ++{ ++ uint64_t s1 = env->regs[b >> 4] + d1; ++ uint64_t s2 = env->regs[b & 0xf] + d2; ++ int i; ++ unsigned char x,y; ++ uint32_t cc; ++ HELPER_LOG("%s l %d b 0x%x d1 %d d2 %d\n", __FUNCTION__, l, b, d1, d2); ++ for (i = 0; i <= l; i++) { ++ x = ldub(s1 + i); ++ y = ldub(s2 + i); ++ HELPER_LOG("%02x (%c)/%02x (%c) ", x, x, y, y); ++ if (x < y) { ++ cc = 1; ++ goto done; ++ } else if (x > y) { ++ cc = 2; ++ goto done; ++ } ++ } ++ cc = 0; ++done: ++ HELPER_LOG("\n"); ++ return cc; ++} ++ ++/* load multiple 64-bit registers from memory */ ++void HELPER(lmg)(uint32_t r1, uint32_t r3, uint32_t b2, int d2) ++{ ++ uint64_t src = env->regs[b2] + d2; ++ for (;;) { ++ env->regs[r1] = ldq(src); ++ src += 8; ++ if (r1 == r3) break; ++ r1 = (r1 + 1) & 15; ++ } ++} ++ ++/* store multiple 64-bit registers to memory */ ++void HELPER(stmg)(uint32_t r1, uint32_t r3, uint32_t b2, int d2) ++{ ++ uint64_t dest = env->regs[b2] + d2; ++ HELPER_LOG("%s: r1 %d r3 %d\n", __FUNCTION__, r1, r3); ++ for (;;) { ++ HELPER_LOG("storing r%d in 0x%lx\n", r1, dest); ++ stq(dest, env->regs[r1]); ++ dest += 8; ++ if (r1 == r3) break; ++ r1 = (r1 + 1) & 15; ++ } ++} ++ ++/* set condition code for signed 32-bit arithmetics */ ++uint32_t HELPER(set_cc_s32)(int32_t v) ++{ ++ if (v < 0) return 1; ++ else if (v > 0) return 2; ++ else return 0; ++} ++ ++/* set condition code for signed 64-bit arithmetics */ ++uint32_t HELPER(set_cc_s64)(int64_t v) ++{ ++ if (v < 0) return 1; ++ else if (v > 0) return 2; ++ else return 0; ++} ++ ++/* set condition code for signed 32-bit two's complement */ ++uint32_t HELPER(set_cc_comp_s32)(int32_t v) ++{ ++ if ((uint32_t)v == 0x80000000UL) return 3; ++ else if (v < 0) return 1; ++ else if (v > 0) return 2; ++ else return 0; ++} ++ ++/* set condition code for signed 64-bit two's complement */ ++uint32_t HELPER(set_cc_comp_s64)(int64_t v) ++{ ++ if ((uint64_t)v == 0x8000000000000000ULL) return 3; ++ else if (v < 0) return 1; ++ else if (v > 0) return 2; ++ else return 0; ++} ++ ++/* set negative/zero condition code for 32-bit logical op */ ++uint32_t HELPER(set_cc_nz_u32)(uint32_t v) ++{ ++ if (v) return 1; ++ else return 0; ++} ++ ++/* set negative/zero condition code for 64-bit logical op */ ++uint32_t HELPER(set_cc_nz_u64)(uint64_t v) ++{ ++ if (v) return 1; ++ else return 0; ++} ++ ++/* set condition code for insert character under mask insn */ ++uint32_t HELPER(set_cc_icm)(uint32_t mask, uint32_t val) ++{ ++ HELPER_LOG("%s: mask 0x%x val %d\n", __FUNCTION__, mask, val); ++ uint32_t cc; ++ if (!val || !mask) cc = 0; ++ else { ++ while (mask != 1) { ++ mask >>= 1; ++ val >>= 8; ++ } ++ if (val & 0x80) cc = 1; ++ else cc = 2; ++ } ++ return cc; ++} ++ ++/* relative conditional branch */ ++void HELPER(brc)(uint32_t cc, uint32_t mask, uint64_t pc, int32_t offset) ++{ ++ if ( mask & ( 1 << (3 - cc) ) ) { ++ env->psw.addr = pc + offset; ++ } ++ else { ++ env->psw.addr = pc + 4; ++ } ++} ++ ++/* branch relative on 64-bit count (condition is computed inline, this only ++ does the branch */ ++void HELPER(brctg)(uint64_t flag, uint64_t pc, int32_t offset) ++{ ++ if (flag) { ++ env->psw.addr = pc + offset; ++ } ++ else { ++ env->psw.addr = pc + 4; ++ } ++ HELPER_LOG("%s: pc 0x%lx flag %ld psw.addr 0x%lx\n", __FUNCTION__, pc, flag, ++ env->psw.addr); ++} ++ ++/* branch relative on 32-bit count (condition is computed inline, this only ++ does the branch */ ++void HELPER(brct)(uint32_t flag, uint64_t pc, int32_t offset) ++{ ++ if (flag) { ++ env->psw.addr = pc + offset; ++ } ++ else { ++ env->psw.addr = pc + 4; ++ } ++ HELPER_LOG("%s: pc 0x%lx flag %d psw.addr 0x%lx\n", __FUNCTION__, pc, flag, ++ env->psw.addr); ++} ++ ++/* relative conditional branch with long displacement */ ++void HELPER(brcl)(uint32_t cc, uint32_t mask, uint64_t pc, int64_t offset) ++{ ++ if ( mask & ( 1 << (3 - cc) ) ) { ++ env->psw.addr = pc + offset; ++ } ++ else { ++ env->psw.addr = pc + 6; ++ } ++ HELPER_LOG("%s: pc 0x%lx psw.addr 0x%lx\n", __FUNCTION__, pc, env->psw.addr); ++} ++ ++/* conditional branch to register (register content is passed as target) */ ++void HELPER(bcr)(uint32_t cc, uint32_t mask, uint64_t target, uint64_t pc) ++{ ++ if ( mask & ( 1 << (3 - cc) ) ) { ++ env->psw.addr = target; ++ } ++ else { ++ env->psw.addr = pc + 2; ++ } ++} ++ ++/* conditional branch to address (address is passed as target) */ ++void HELPER(bc)(uint32_t cc, uint32_t mask, uint64_t target, uint64_t pc) ++{ ++ if ( mask & ( 1 << (3 - cc) ) ) { ++ env->psw.addr = target; ++ } ++ else { ++ env->psw.addr = pc + 4; ++ } ++ HELPER_LOG("%s: pc 0x%lx psw.addr 0x%lx r2 0x%lx r5 0x%lx\n", __FUNCTION__, ++ pc, env->psw.addr, env->regs[2], env->regs[5]); ++} ++ ++/* 64-bit unsigned comparison */ ++uint32_t HELPER(cmp_u64)(uint64_t o1, uint64_t o2) ++{ ++ if (o1 < o2) return 1; ++ else if (o1 > o2) return 2; ++ else return 0; ++} ++ ++/* 32-bit unsigned comparison */ ++uint32_t HELPER(cmp_u32)(uint32_t o1, uint32_t o2) ++{ ++ HELPER_LOG("%s: o1 0x%x o2 0x%x\n", __FUNCTION__, o1, o2); ++ if (o1 < o2) return 1; ++ else if (o1 > o2) return 2; ++ else return 0; ++} ++ ++/* 64-bit signed comparison */ ++uint32_t HELPER(cmp_s64)(int64_t o1, int64_t o2) ++{ ++ HELPER_LOG("%s: o1 %ld o2 %ld\n", __FUNCTION__, o1, o2); ++ if (o1 < o2) return 1; ++ else if (o1 > o2) return 2; ++ else return 0; ++} ++ ++/* 32-bit signed comparison */ ++uint32_t HELPER(cmp_s32)(int32_t o1, int32_t o2) ++{ ++ if (o1 < o2) return 1; ++ else if (o1 > o2) return 2; ++ else return 0; ++} ++ ++/* compare logical under mask */ ++uint32_t HELPER(clm)(uint32_t r1, uint32_t mask, uint64_t addr) ++{ ++ uint8_t r,d; ++ uint32_t cc; ++ HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%lx\n",__FUNCTION__,r1,mask,addr); ++ cc = 0; ++ while (mask) { ++ if (mask & 8) { ++ d = ldub(addr); ++ r = (r1 & 0xff000000UL) >> 24; ++ HELPER_LOG("mask 0x%x %02x/%02x (0x%lx) ", mask, r, d, addr); ++ if (r < d) { ++ cc = 1; ++ break; ++ } ++ else if (r > d) { ++ cc = 2; ++ break; ++ } ++ addr++; ++ } ++ mask = (mask << 1) & 0xf; ++ r1 <<= 8; ++ } ++ HELPER_LOG("\n"); ++ return cc; ++} ++ ++/* store character under mask */ ++void HELPER(stcm)(uint32_t r1, uint32_t mask, uint64_t addr) ++{ ++ uint8_t r; ++ HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%lx\n",__FUNCTION__,r1,mask,addr); ++ while (mask) { ++ if (mask & 8) { ++ r = (r1 & 0xff000000UL) >> 24; ++ stb(addr, r); ++ HELPER_LOG("mask 0x%x %02x (0x%lx) ", mask, r, addr); ++ addr++; ++ } ++ mask = (mask << 1) & 0xf; ++ r1 <<= 8; ++ } ++ HELPER_LOG("\n"); ++} ++ ++/* 64/64 -> 128 unsigned multiplication */ ++void HELPER(mlg)(uint32_t r1, uint64_t v2) ++{ ++#if TARGET_LONG_BITS == 64 && defined(__GNUC__) /* assuming 64-bit hosts have __uint128_t */ ++ __uint128_t res = (__uint128_t)env->regs[r1 + 1]; ++ res *= (__uint128_t)v2; ++ env->regs[r1] = (uint64_t)(res >> 64); ++ env->regs[r1 + 1] = (uint64_t)res; ++#else ++ mulu64(&env->regs[r1 + 1], &env->regs[r1], env->regs[r1 + 1], v2); ++#endif ++} ++ ++/* 128 -> 64/64 unsigned division */ ++void HELPER(dlg)(uint32_t r1, uint64_t v2) ++{ ++#if TARGET_LONG_BITS == 64 && defined(__GNUC__) /* assuming 64-bit hosts have __uint128_t */ ++ __uint128_t dividend = (((__uint128_t)env->regs[r1]) << 64) | ++ (env->regs[r1+1]); ++ uint64_t divisor = v2; ++ __uint128_t quotient = dividend / divisor; ++ env->regs[r1+1] = quotient; ++ __uint128_t remainder = dividend % divisor; ++ env->regs[r1] = remainder; ++ HELPER_LOG("%s: dividend 0x%016lx%016lx divisor 0x%lx quotient 0x%lx rem 0x%lx\n", ++ __FUNCTION__, (uint64_t)(dividend >> 64), (uint64_t)dividend, ++ divisor, (uint64_t)quotient, (uint64_t)remainder); ++#else ++ cpu_abort(env, "128 -> 64/64 division not implemented on this system\n"); ++#endif ++} ++ ++/* set condition code for 64-bit signed addition */ ++uint32_t HELPER(set_cc_add64)(int64_t a1, int64_t a2, int64_t ar) ++{ ++ if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) { ++ return 3; /* overflow */ ++ } else { ++ if (ar < 0) return 1; ++ else if (ar > 0) return 2; ++ else return 0; ++ } ++} ++ ++/* set condition code for 64-bit unsigned addition */ ++uint32_t HELPER(set_cc_addu64)(uint64_t a1, uint64_t a2, uint64_t ar) ++{ ++ if (ar == 0) { ++ if (a1) return 2; ++ else return 0; ++ } else { ++ if (ar < a1 || ar < a2) { ++ return 3; ++ } else { ++ return 1; ++ } ++ } ++} ++ ++/* set condition code for 32-bit signed addition */ ++uint32_t HELPER(set_cc_add32)(int32_t a1, int32_t a2, int32_t ar) ++{ ++ if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) { ++ return 3; /* overflow */ ++ } else { ++ if (ar < 0) return 1; ++ else if (ar > 0) return 2; ++ else return 0; ++ } ++} ++ ++/* set condition code for 32-bit unsigned addition */ ++uint32_t HELPER(set_cc_addu32)(uint32_t a1, uint32_t a2, uint32_t ar) ++{ ++ if (ar == 0) { ++ if (a1) return 2; ++ else return 0; ++ } else { ++ if (ar < a1 || ar < a2) { ++ return 3; ++ } else { ++ return 1; ++ } ++ } ++} ++ ++/* set condition code for 64-bit signed subtraction */ ++uint32_t HELPER(set_cc_sub64)(int64_t s1, int64_t s2, int64_t sr) ++{ ++ if ((s1 > 0 && s2 < 0 && sr < 0) || (s1 < 0 && s2 > 0 && sr > 0)) { ++ return 3; /* overflow */ ++ } else { ++ if (sr < 0) return 1; ++ else if (sr > 0) return 2; ++ else return 0; ++ } ++} ++ ++/* set condition code for 32-bit signed subtraction */ ++uint32_t HELPER(set_cc_sub32)(int32_t s1, int32_t s2, int32_t sr) ++{ ++ if ((s1 > 0 && s2 < 0 && sr < 0) || (s1 < 0 && s2 > 0 && sr > 0)) { ++ return 3; /* overflow */ ++ } else { ++ if (sr < 0) return 1; ++ else if (sr > 0) return 2; ++ else return 0; ++ } ++} ++ ++/* set condition code for 32-bit unsigned subtraction */ ++uint32_t HELPER(set_cc_subu32)(uint32_t s1, uint32_t s2, uint32_t sr) ++{ ++ if (sr == 0) return 2; ++ else { ++ if (s2 > s1) return 1; ++ else return 3; ++ } ++} ++ ++/* set condition code for 64-bit unsigned subtraction */ ++uint32_t HELPER(set_cc_subu64)(uint64_t s1, uint64_t s2, uint64_t sr) ++{ ++ if (sr == 0) return 2; ++ else { ++ if (s2 > s1) return 1; ++ else return 3; ++ } ++} ++ ++/* search string (c is byte to search, r2 is string, r1 end of string) */ ++uint32_t HELPER(srst)(uint32_t c, uint32_t r1, uint32_t r2) ++{ ++ HELPER_LOG("%s: c %d *r1 0x%lx *r2 0x%lx\n", __FUNCTION__, c, env->regs[r1], ++ env->regs[r2]); ++ uint64_t i; ++ uint32_t cc; ++ for (i = env->regs[r2]; i != env->regs[r1]; i++) { ++ if (ldub(i) == c) { ++ env->regs[r1] = i; ++ cc = 1; ++ return cc; ++ } ++ } ++ cc = 2; ++ return cc; ++} ++ ++/* unsigned string compare (c is string terminator) */ ++uint32_t HELPER(clst)(uint32_t c, uint32_t r1, uint32_t r2) ++{ ++ uint64_t s1 = env->regs[r1]; ++ uint64_t s2 = env->regs[r2]; ++ uint8_t v1, v2; ++ uint32_t cc; ++ c = c & 0xff; ++#ifdef CONFIG_USER_ONLY ++ if (!c) { ++ HELPER_LOG("%s: comparing '%s' and '%s'\n", ++ __FUNCTION__, (char*)s1, (char*)s2); ++ } ++#endif ++ for (;;) { ++ v1 = ldub(s1); ++ v2 = ldub(s2); ++ if (v1 == c || v2 == c) break; ++ if (v1 != v2) break; ++ s1++; s2++; ++ } ++ ++ if (v1 == v2) cc = 0; ++ else { ++ if (v1 < v2) cc = 1; ++ else cc = 2; ++ env->regs[r1] = s1; ++ env->regs[r2] = s2; ++ } ++ return cc; ++} ++ ++/* string copy (c is string terminator) */ ++uint32_t HELPER(mvst)(uint32_t c, uint32_t r1, uint32_t r2) ++{ ++ uint64_t dest = env->regs[r1]; ++ uint64_t src = env->regs[r2]; ++ uint8_t v; ++ c = c & 0xff; ++#ifdef CONFIG_USER_ONLY ++ if (!c) { ++ HELPER_LOG("%s: copying '%s' to 0x%lx\n", __FUNCTION__, (char*)src, dest); ++ } ++#endif ++ for (;;) { ++ v = ldub(src); ++ stb(dest, v); ++ if (v == c) break; ++ src++; dest++; ++ } ++ env->regs[r1] = dest; ++ return 1; ++} ++ ++/* compare and swap 64-bit */ ++uint32_t HELPER(csg)(uint32_t r1, uint64_t a2, uint32_t r3) ++{ ++ /* FIXME: locking? */ ++ uint32_t cc; ++ uint64_t v2 = ldq(a2); ++ if (env->regs[r1] == v2) { ++ cc = 0; ++ stq(a2, env->regs[r3]); ++ } else { ++ cc = 1; ++ env->regs[r1] = v2; ++ } ++ return cc; ++} ++ ++/* compare double and swap 64-bit */ ++uint32_t HELPER(cdsg)(uint32_t r1, uint64_t a2, uint32_t r3) ++{ ++ /* FIXME: locking? */ ++ uint32_t cc; ++ __uint128_t v2 = (((__uint128_t)ldq(a2)) << 64) | (__uint128_t)ldq(a2 + 8); ++ __uint128_t v1 = (((__uint128_t)env->regs[r1]) << 64) | (__uint128_t)env->regs[r1 + 1]; ++ if (v1 == v2) { ++ cc = 0; ++ stq(a2, env->regs[r3]); ++ stq(a2 + 8, env->regs[r3 + 1]); ++ } else { ++ cc = 1; ++ env->regs[r1] = v2 >> 64; ++ env->regs[r1 + 1] = v2 & 0xffffffffffffffffULL; ++ } ++ return cc; ++} ++ ++/* compare and swap 32-bit */ ++uint32_t HELPER(cs)(uint32_t r1, uint64_t a2, uint32_t r3) ++{ ++ /* FIXME: locking? */ ++ uint32_t cc; ++ HELPER_LOG("%s: r1 %d a2 0x%lx r3 %d\n", __FUNCTION__, r1, a2, r3); ++ uint32_t v2 = ldl(a2); ++ if (((uint32_t)env->regs[r1]) == v2) { ++ cc = 0; ++ stl(a2, (uint32_t)env->regs[r3]); ++ } else { ++ cc = 1; ++ env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | v2; ++ } ++ return cc; ++} ++ ++/* execute instruction ++ this instruction executes an insn modified with the contents of r1 ++ it does not change the executed instruction in memory ++ it does not change the program counter ++ in other words: tricky... ++ currently implemented by interpreting the cases it is most commonly used in ++ */ ++uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret) ++{ ++ uint16_t insn = lduw(addr); ++ HELPER_LOG("%s: v1 0x%lx addr 0x%lx insn 0x%x\n", __FUNCTION__, v1, addr, ++ insn); ++ if ((insn & 0xf0ff) == 0xd000) { ++ uint32_t l, insn2, b, d1, d2; ++ l = v1 & 0xff; ++ insn2 = ldl_code(addr + 2); ++ b = (((insn2 >> 28) & 0xf) << 4) | ((insn2 >> 12) & 0xf); ++ d1 = (insn2 >> 16) & 0xfff; ++ d2 = insn2 & 0xfff; ++ switch (insn & 0xf00) { ++ case 0x200: helper_mvc(l, b, d1, d2); return cc; break; ++ case 0x500: return helper_clc(l, b, d1, d2); break; ++ case 0x700: return helper_xc(l, b, d1, d2); break; ++ default: goto abort; break; ++ } ++ } ++ else if ((insn & 0xff00) == 0x0a00) { /* supervisor call */ ++ HELPER_LOG("%s: svc %ld via execute\n", __FUNCTION__, (insn|v1) & 0xff); ++ env->psw.addr = ret; ++ helper_exception(EXCP_EXECUTE_SVC + ((insn | v1) & 0xff)); ++ } ++ else { ++abort: ++ cpu_abort(env, "EXECUTE on instruction prefix 0x%x not implemented\n", insn); ++ } ++ return cc; ++} ++ ++/* set condition code for test under mask */ ++uint32_t HELPER(tm)(uint32_t val, uint32_t mask) ++{ ++ HELPER_LOG("%s: val 0x%x mask 0x%x\n", __FUNCTION__, val, mask); ++ uint16_t r = val & mask; ++ if (r == 0) return 0; ++ else if (r == mask) return 3; ++ else return 1; ++} ++ ++/* set condition code for test under mask */ ++uint32_t HELPER(tmxx)(uint64_t val, uint32_t mask) ++{ ++ uint16_t r = val & mask; ++ HELPER_LOG("%s: val 0x%lx mask 0x%x r 0x%x\n", __FUNCTION__, val, mask, r); ++ if (r == 0) return 0; ++ else if (r == mask) return 3; ++ else { ++ while (!(mask & 0x8000)) { ++ mask <<= 1; ++ val <<= 1; ++ } ++ if (val & 0x8000) return 2; ++ else return 1; ++ } ++} ++ ++/* absolute value 32-bit */ ++uint32_t HELPER(abs_i32)(uint32_t reg, int32_t val) ++{ ++ uint32_t cc; ++ if (val == 0x80000000UL) cc = 3; ++ else if (val) cc = 1; ++ else cc = 0; ++ ++ if (val < 0) { ++ env->regs[reg] = -val; ++ } else { ++ env->regs[reg] = val; ++ } ++ return cc; ++} ++ ++/* negative absolute value 32-bit */ ++uint32_t HELPER(nabs_i32)(uint32_t reg, int32_t val) ++{ ++ uint32_t cc; ++ if (val) cc = 1; ++ else cc = 0; ++ ++ if (val < 0) { ++ env->regs[reg] = (env->regs[reg] & 0xffffffff00000000ULL) | val; ++ } else { ++ env->regs[reg] = (env->regs[reg] & 0xffffffff00000000ULL) | ((uint32_t)-val); ++ } ++ return cc; ++} ++ ++/* absolute value 64-bit */ ++uint32_t HELPER(abs_i64)(uint32_t reg, int64_t val) ++{ ++ uint32_t cc; ++ if (val == 0x8000000000000000ULL) cc = 3; ++ else if (val) cc = 1; ++ else cc = 0; ++ ++ if (val < 0) { ++ env->regs[reg] = -val; ++ } else { ++ env->regs[reg] = val; ++ } ++ return cc; ++} ++ ++/* negative absolute value 64-bit */ ++uint32_t HELPER(nabs_i64)(uint32_t reg, int64_t val) ++{ ++ uint32_t cc; ++ if (val) cc = 1; ++ else cc = 0; ++ ++ if (val < 0) { ++ env->regs[reg] = val; ++ } else { ++ env->regs[reg] = -val; ++ } ++ return cc; ++} ++ ++/* add with carry 32-bit unsigned */ ++uint32_t HELPER(addc_u32)(uint32_t cc, uint32_t r1, uint32_t v2) ++{ ++ uint32_t res; ++ uint32_t v1 = env->regs[r1] & 0xffffffffUL; ++ res = v1 + v2; ++ if (cc & 2) res++; ++ ++ if (res == 0) { ++ if (v1) cc = 2; ++ else cc = 0; ++ } else { ++ if (res < v1 || res < v2) { ++ cc = 3; ++ } else { ++ cc = 1; ++ } ++ } ++ env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | res; ++ return cc; ++} ++ ++/* CC for add with carry 64-bit unsigned (isn't this a duplicate of some other CC function?) */ ++uint32_t HELPER(set_cc_addc_u64)(uint64_t v1, uint64_t v2, uint64_t res) ++{ ++ uint32_t cc; ++ if (res == 0) { ++ if (v1) cc = 2; ++ else cc = 0; ++ } else { ++ if (res < v1 || res < v2) { ++ cc = 3; ++ } else { ++ cc = 1; ++ } ++ } ++ return cc; ++} ++ ++/* store character under mask high ++ operates on the upper half of r1 */ ++uint32_t HELPER(stcmh)(uint32_t r1, uint64_t address, uint32_t mask) ++{ ++ int pos = 56; /* top of the upper half of r1 */ ++ ++ while (mask) { ++ if (mask & 8) { ++ stb(address, (env->regs[r1] >> pos) & 0xff); ++ address++; ++ } ++ mask = (mask << 1) & 0xf; ++ pos -= 8; ++ } ++ return 0; ++} ++ ++/* insert character under mask high ++ same as icm, but operates on the upper half of r1 */ ++uint32_t HELPER(icmh)(uint32_t r1, uint64_t address, uint32_t mask) ++{ ++ int pos = 56; /* top of the upper half of r1 */ ++ uint64_t rmask = 0xff00000000000000ULL; ++ uint8_t val = 0; ++ int ccd = 0; ++ uint32_t cc; ++ ++ cc = 0; ++ ++ while (mask) { ++ if (mask & 8) { ++ env->regs[r1] &= ~rmask; ++ val = ldub(address); ++ if ((val & 0x80) && !ccd) cc = 1; ++ ccd = 1; ++ if (val && cc == 0) cc = 2; ++ env->regs[r1] |= (uint64_t)val << pos; ++ address++; ++ } ++ mask = (mask << 1) & 0xf; ++ pos -= 8; ++ rmask >>= 8; ++ } ++ return cc; ++} ++ ++/* insert psw mask and condition code into r1 */ ++void HELPER(ipm)(uint32_t cc, uint32_t r1) ++{ ++ uint64_t r = env->regs[r1]; ++ r &= 0xffffffff00ffffffULL; ++ r |= (cc << 28) | ( (env->psw.mask >> 40) & 0xf ); ++ env->regs[r1] = r; ++ HELPER_LOG("%s: cc %d psw.mask 0x%lx r1 0x%lx\n", __FUNCTION__, cc, env->psw.mask, r); ++} ++ ++/* store access registers r1 to r3 in memory at a2 */ ++void HELPER(stam)(uint32_t r1, uint64_t a2, uint32_t r3) ++{ ++ int i; ++ for (i = r1; i != ((r3 + 1) & 15); i = (i + 1) & 15) { ++ stl(a2, env->aregs[i]); ++ a2 += 4; ++ } ++} ++ ++/* move long extended ++ another memcopy insn with more bells and whistles */ ++uint32_t HELPER(mvcle)(uint32_t r1, uint64_t a2, uint32_t r3) ++{ ++ uint64_t destlen = env->regs[r1 + 1]; ++ uint64_t dest = env->regs[r1]; ++ uint64_t srclen = env->regs[r3 + 1]; ++ uint64_t src = env->regs[r3]; ++ uint8_t pad = a2 & 0xff; ++ uint8_t v; ++ uint32_t cc; ++ if (destlen == srclen) cc = 0; ++ else if (destlen < srclen) cc = 1; ++ else cc = 2; ++ if (srclen > destlen) srclen = destlen; ++ for(;destlen && srclen;src++,dest++,destlen--,srclen--) { ++ v = ldub(src); ++ stb(dest, v); ++ } ++ for(;destlen;dest++,destlen--) { ++ stb(dest, pad); ++ } ++ env->regs[r1 + 1] = destlen; ++ env->regs[r3 + 1] -= src - env->regs[r3]; /* can't use srclen here, ++ we trunc'ed it */ ++ env->regs[r1] = dest; ++ env->regs[r3] = src; ++ ++ return cc; ++} ++ ++/* compare logical long extended ++ memcompare insn with padding */ ++uint32_t HELPER(clcle)(uint32_t r1, uint64_t a2, uint32_t r3) ++{ ++ uint64_t destlen = env->regs[r1 + 1]; ++ uint64_t dest = env->regs[r1]; ++ uint64_t srclen = env->regs[r3 + 1]; ++ uint64_t src = env->regs[r3]; ++ uint8_t pad = a2 & 0xff; ++ uint8_t v1 = 0,v2 = 0; ++ uint32_t cc = 0; ++ if (!(destlen || srclen)) return cc; ++ if (srclen > destlen) srclen = destlen; ++ for(;destlen || srclen;src++,dest++,destlen--,srclen--) { ++ if (srclen) v1 = ldub(src); ++ else v1 = pad; ++ if (destlen) v2 = ldub(dest); ++ else v2 = pad; ++ if (v1 != v2) break; ++ } ++ ++ env->regs[r1 + 1] = destlen; ++ env->regs[r3 + 1] -= src - env->regs[r3]; /* can't use srclen here, ++ we trunc'ed it */ ++ env->regs[r1] = dest; ++ env->regs[r3] = src; ++ ++ if (v1 < v2) cc = 1; ++ else if (v1 > v2) cc = 2; ++ ++ return cc; ++} ++ ++/* subtract unsigned v2 from v1 with borrow */ ++uint32_t HELPER(slb)(uint32_t cc, uint32_t r1, uint32_t v1, uint32_t v2) ++{ ++ uint32_t res = v1 + (~v2) + (cc >> 1); ++ env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | res; ++ if (cc & 2) { /* borrow */ ++ if (v1) return 1; ++ else return 0; ++ } else { ++ if (v1) return 3; ++ else return 2; ++ } ++} ++ ++/* subtract unsigned v2 from v1 with borrow */ ++uint32_t HELPER(slbg)(uint32_t cc, uint32_t r1, uint64_t v1, uint64_t v2) ++{ ++ uint64_t res = v1 + (~v2) + (cc >> 1); ++ env->regs[r1] = res; ++ if (cc & 2) { /* borrow */ ++ if (v1) return 1; ++ else return 0; ++ } else { ++ if (v1) return 3; ++ else return 2; ++ } ++} ++ ++/* condition codes for binary FP ops */ ++static uint32_t set_cc_f32(float32 v1, float32 v2) ++{ ++ if (float32_is_nan(v1) || float32_is_nan(v2)) return 3; ++ else if (float32_eq(v1, v2, &env->fpu_status)) return 0; ++ else if (float32_lt(v1, v2, &env->fpu_status)) return 1; ++ else return 2; ++} ++ ++static uint32_t set_cc_f64(float64 v1, float64 v2) ++{ ++ if (float64_is_nan(v1) || float64_is_nan(v2)) return 3; ++ else if (float64_eq(v1, v2, &env->fpu_status)) return 0; ++ else if (float64_lt(v1, v2, &env->fpu_status)) return 1; ++ else return 2; ++} ++ ++/* condition codes for unary FP ops */ ++static uint32_t set_cc_nz_f32(float32 v) ++{ ++ if (float32_is_nan(v)) return 3; ++ else if (float32_is_zero(v)) return 0; ++ else if (float32_is_neg(v)) return 1; ++ else return 2; ++} ++ ++static uint32_t set_cc_nz_f64(float64 v) ++{ ++ if (float64_is_nan(v)) return 3; ++ else if (float64_is_zero(v)) return 0; ++ else if (float64_is_neg(v)) return 1; ++ else return 2; ++} ++ ++static uint32_t set_cc_nz_f128(float128 v) ++{ ++ if (float128_is_nan(v)) return 3; ++ else if (float128_is_zero(v)) return 0; ++ else if (float128_is_neg(v)) return 1; ++ else return 2; ++} ++ ++/* convert 32-bit int to 64-bit float */ ++void HELPER(cdfbr)(uint32_t f1, int32_t v2) ++{ ++ HELPER_LOG("%s: converting %d to f%d\n", __FUNCTION__, v2, f1); ++ env->fregs[f1].d = int32_to_float64(v2, &env->fpu_status); ++} ++ ++/* convert 32-bit int to 128-bit float */ ++void HELPER(cxfbr)(uint32_t f1, int32_t v2) ++{ ++ CPU_QuadU v1; ++ v1.q = int32_to_float128(v2, &env->fpu_status); ++ env->fregs[f1].ll = v1.ll.upper; ++ env->fregs[f1 + 2].ll = v1.ll.lower; ++} ++ ++/* convert 64-bit int to 32-bit float */ ++void HELPER(cegbr)(uint32_t f1, int64_t v2) ++{ ++ HELPER_LOG("%s: converting %ld to f%d\n", __FUNCTION__, v2, f1); ++ env->fregs[f1].l.upper = int64_to_float32(v2, &env->fpu_status); ++} ++ ++/* convert 64-bit int to 64-bit float */ ++void HELPER(cdgbr)(uint32_t f1, int64_t v2) ++{ ++ HELPER_LOG("%s: converting %ld to f%d\n", __FUNCTION__, v2, f1); ++ env->fregs[f1].d = int64_to_float64(v2, &env->fpu_status); ++} ++ ++/* convert 64-bit int to 128-bit float */ ++void HELPER(cxgbr)(uint32_t f1, int64_t v2) ++{ ++ CPU_QuadU x1; ++ x1.q = int64_to_float128(v2, &env->fpu_status); ++ HELPER_LOG("%s: converted %ld to 0x%lx and 0x%lx\n", __FUNCTION__, v2, x1.ll.upper, x1.l); ++ env->fregs[f1].ll = x1.ll.upper; ++ env->fregs[f1 + 2].ll = x1.ll.lower; ++} ++ ++/* convert 32-bit int to 32-bit float */ ++void HELPER(cefbr)(uint32_t f1, int32_t v2) ++{ ++ env->fregs[f1].l.upper = int32_to_float32(v2, &env->fpu_status); ++ HELPER_LOG("%s: converting %d to 0x%d in f%d\n", __FUNCTION__, v2, env->fregs[f1].l.upper, f1); ++} ++ ++/* 32-bit FP addition RR */ ++uint32_t HELPER(aebr)(uint32_t f1, uint32_t f2) ++{ ++ env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper, env->fregs[f2].l.upper, &env->fpu_status); ++ HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __FUNCTION__, env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1); ++ return set_cc_nz_f32(env->fregs[f1].l.upper); ++} ++ ++/* 64-bit FP addition RR */ ++uint32_t HELPER(adbr)(uint32_t f1, uint32_t f2) ++{ ++ env->fregs[f1].d = float64_add(env->fregs[f1].d, env->fregs[f2].d, &env->fpu_status); ++ HELPER_LOG("%s: adding 0x%ld resulting in 0x%ld in f%d\n", __FUNCTION__, env->fregs[f2].d, env->fregs[f1].d, f1); ++ return set_cc_nz_f64(env->fregs[f1].d); ++} ++ ++/* 32-bit FP subtraction RR */ ++uint32_t HELPER(sebr)(uint32_t f1, uint32_t f2) ++{ ++ env->fregs[f1].l.upper = float32_sub(env->fregs[f1].l.upper, env->fregs[f2].l.upper, &env->fpu_status); ++ HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __FUNCTION__, env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1); ++ return set_cc_nz_f32(env->fregs[f1].l.upper); ++} ++ ++/* 64-bit FP subtraction RR */ ++uint32_t HELPER(sdbr)(uint32_t f1, uint32_t f2) ++{ ++ env->fregs[f1].d = float64_sub(env->fregs[f1].d, env->fregs[f2].d, &env->fpu_status); ++ HELPER_LOG("%s: subtracting 0x%ld resulting in 0x%ld in f%d\n", __FUNCTION__, env->fregs[f2].d, env->fregs[f1].d, f1); ++ return set_cc_nz_f64(env->fregs[f1].d); ++} ++ ++/* 32-bit FP division RR */ ++void HELPER(debr)(uint32_t f1, uint32_t f2) ++{ ++ env->fregs[f1].l.upper = float32_div(env->fregs[f1].l.upper, env->fregs[f2].l.upper, &env->fpu_status); ++} ++ ++/* 128-bit FP division RR */ ++void HELPER(dxbr)(uint32_t f1, uint32_t f2) ++{ ++ CPU_QuadU v1; ++ v1.ll.upper = env->fregs[f1].ll; ++ v1.ll.lower = env->fregs[f1 + 2].ll; ++ CPU_QuadU v2; ++ v2.ll.upper = env->fregs[f2].ll; ++ v2.ll.lower = env->fregs[f2 + 2].ll; ++ CPU_QuadU res; ++ res.q = float128_div(v1.q, v2.q, &env->fpu_status); ++ env->fregs[f1].ll = res.ll.upper; ++ env->fregs[f1 + 2].ll = res.ll.lower; ++} ++ ++/* 64-bit FP multiplication RR */ ++void HELPER(mdbr)(uint32_t f1, uint32_t f2) ++{ ++ env->fregs[f1].d = float64_mul(env->fregs[f1].d, env->fregs[f2].d, &env->fpu_status); ++} ++ ++/* 128-bit FP multiplication RR */ ++void HELPER(mxbr)(uint32_t f1, uint32_t f2) ++{ ++ CPU_QuadU v1; ++ v1.ll.upper = env->fregs[f1].ll; ++ v1.ll.lower = env->fregs[f1 + 2].ll; ++ CPU_QuadU v2; ++ v2.ll.upper = env->fregs[f2].ll; ++ v2.ll.lower = env->fregs[f2 + 2].ll; ++ CPU_QuadU res; ++ res.q = float128_mul(v1.q, v2.q, &env->fpu_status); ++ env->fregs[f1].ll = res.ll.upper; ++ env->fregs[f1 + 2].ll = res.ll.lower; ++} ++ ++/* convert 32-bit float to 64-bit float */ ++void HELPER(ldebr)(uint32_t r1, uint32_t r2) ++{ ++ env->fregs[r1].d = float32_to_float64(env->fregs[r2].l.upper, &env->fpu_status); ++} ++ ++/* convert 128-bit float to 64-bit float */ ++void HELPER(ldxbr)(uint32_t f1, uint32_t f2) ++{ ++ CPU_QuadU x2; ++ x2.ll.upper = env->fregs[f2].ll; ++ x2.ll.lower = env->fregs[f2 + 2].ll; ++ env->fregs[f1].d = float128_to_float64(x2.q, &env->fpu_status); ++ HELPER_LOG("%s: to 0x%ld\n", __FUNCTION__, env->fregs[f1].d); ++} ++ ++/* convert 64-bit float to 128-bit float */ ++void HELPER(lxdbr)(uint32_t f1, uint32_t f2) ++{ ++ CPU_QuadU res; ++ res.q = float64_to_float128(env->fregs[f2].d, &env->fpu_status); ++ env->fregs[f1].ll = res.ll.upper; ++ env->fregs[f1 + 2].ll = res.ll.lower; ++} ++ ++/* convert 64-bit float to 32-bit float */ ++void HELPER(ledbr)(uint32_t f1, uint32_t f2) ++{ ++ float64 d2 = env->fregs[f2].d; ++ env->fregs[f1].l.upper = float64_to_float32(d2, &env->fpu_status); ++} ++ ++/* convert 128-bit float to 32-bit float */ ++void HELPER(lexbr)(uint32_t f1, uint32_t f2) ++{ ++ CPU_QuadU x2; ++ x2.ll.upper = env->fregs[f2].ll; ++ x2.ll.lower = env->fregs[f2 + 2].ll; ++ env->fregs[f1].l.upper = float128_to_float32(x2.q, &env->fpu_status); ++ HELPER_LOG("%s: to 0x%d\n", __FUNCTION__, env->fregs[f1].l.upper); ++} ++ ++/* absolute value of 32-bit float */ ++uint32_t HELPER(lpebr)(uint32_t f1, uint32_t f2) ++{ ++ float32 v1; ++ float32 v2 = env->fregs[f2].d; ++ v1 = float32_abs(v2); ++ env->fregs[f1].d = v1; ++ return set_cc_nz_f32(v1); ++} ++ ++/* absolute value of 64-bit float */ ++uint32_t HELPER(lpdbr)(uint32_t f1, uint32_t f2) ++{ ++ float64 v1; ++ float64 v2 = env->fregs[f2].d; ++ v1 = float64_abs(v2); ++ env->fregs[f1].d = v1; ++ return set_cc_nz_f64(v1); ++} ++ ++/* absolute value of 128-bit float */ ++uint32_t HELPER(lpxbr)(uint32_t f1, uint32_t f2) ++{ ++ CPU_QuadU v1; ++ CPU_QuadU v2; ++ v2.ll.upper = env->fregs[f2].ll; ++ v2.ll.lower = env->fregs[f2 + 2].ll; ++ v1.q = float128_abs(v2.q); ++ env->fregs[f1].ll = v1.ll.upper; ++ env->fregs[f1 + 2].ll = v1.ll.lower; ++ return set_cc_nz_f128(v1.q); ++} ++ ++/* load and test 64-bit float */ ++uint32_t HELPER(ltdbr)(uint32_t f1, uint32_t f2) ++{ ++ env->fregs[f1].d = env->fregs[f2].d; ++ return set_cc_nz_f64(env->fregs[f1].d); ++} ++ ++/* load and test 32-bit float */ ++uint32_t HELPER(ltebr)(uint32_t f1, uint32_t f2) ++{ ++ env->fregs[f1].l.upper = env->fregs[f2].l.upper; ++ return set_cc_nz_f32(env->fregs[f1].l.upper); ++} ++ ++/* load and test 128-bit float */ ++uint32_t HELPER(ltxbr)(uint32_t f1, uint32_t f2) ++{ ++ CPU_QuadU x; ++ x.ll.upper = env->fregs[f2].ll; ++ x.ll.lower = env->fregs[f2 + 2].ll; ++ env->fregs[f1].ll = x.ll.upper; ++ env->fregs[f1 + 2].ll = x.ll.lower; ++ return set_cc_nz_f128(x.q); ++} ++ ++/* negative absolute of 32-bit float */ ++uint32_t HELPER(lcebr)(uint32_t f1, uint32_t f2) ++{ ++ env->fregs[f1].l.upper = float32_sub(float32_zero, env->fregs[f2].l.upper, &env->fpu_status); ++ return set_cc_nz_f32(env->fregs[f1].l.upper); ++} ++ ++/* negative absolute of 64-bit float */ ++uint32_t HELPER(lcdbr)(uint32_t f1, uint32_t f2) ++{ ++ env->fregs[f1].d = float64_sub(float64_zero, env->fregs[f2].d, &env->fpu_status); ++ return set_cc_nz_f64(env->fregs[f1].d); ++} ++ ++/* convert 64-bit float to 128-bit float */ ++uint32_t HELPER(lcxbr)(uint32_t f1, uint32_t f2) ++{ ++ CPU_QuadU x1, x2; ++ x2.ll.upper = env->fregs[f2].ll; ++ x2.ll.lower = env->fregs[f2 + 2].ll; ++ x1.q = float128_sub(float64_to_float128(float64_zero, &env->fpu_status), x2.q, &env->fpu_status); ++ env->fregs[f1].ll = x1.ll.upper; ++ env->fregs[f1 + 2].ll = x1.ll.lower; ++ return set_cc_nz_f128(x1.q); ++} ++ ++/* 32-bit FP compare RM */ ++uint32_t HELPER(ceb)(uint32_t f1, uint32_t val) ++{ ++ float32 v1 = env->fregs[f1].l.upper; ++ CPU_FloatU v2; ++ v2.l = val; ++ HELPER_LOG("%s: comparing 0x%d from f%d and 0x%d\n", __FUNCTION__, v1, f1, v2.f); ++ return set_cc_f32(v1, v2.f); ++} ++ ++/* 32-bit FP addition RM */ ++uint32_t HELPER(aeb)(uint32_t f1, uint32_t val) ++{ ++ float32 v1 = env->fregs[f1].l.upper; ++ CPU_FloatU v2; ++ v2.l = val; ++ HELPER_LOG("%s: adding 0x%d from f%d and 0x%d\n", __FUNCTION__, v1, f1, v2.f); ++ env->fregs[f1].l.upper = float32_add(v1, v2.f, &env->fpu_status); ++ return set_cc_nz_f32(env->fregs[f1].l.upper); ++} ++ ++/* 32-bit FP division RM */ ++void HELPER(deb)(uint32_t f1, uint32_t val) ++{ ++ float32 v1 = env->fregs[f1].l.upper; ++ CPU_FloatU v2; ++ v2.l = val; ++ HELPER_LOG("%s: dividing 0x%d from f%d by 0x%d\n", __FUNCTION__, v1, f1, v2.f); ++ env->fregs[f1].l.upper = float32_div(v1, v2.f, &env->fpu_status); ++} ++ ++/* 32-bit FP multiplication RM */ ++void HELPER(meeb)(uint32_t f1, uint32_t val) ++{ ++ float32 v1 = env->fregs[f1].l.upper; ++ CPU_FloatU v2; ++ v2.l = val; ++ HELPER_LOG("%s: multiplying 0x%d from f%d and 0x%d\n", __FUNCTION__, v1, f1, v2.f); ++ env->fregs[f1].l.upper = float32_mul(v1, v2.f, &env->fpu_status); ++} ++ ++/* 32-bit FP compare RR */ ++uint32_t HELPER(cebr)(uint32_t f1, uint32_t f2) ++{ ++ float32 v1 = env->fregs[f1].l.upper; ++ float32 v2 = env->fregs[f2].l.upper;; ++ HELPER_LOG("%s: comparing 0x%d from f%d and 0x%d\n", __FUNCTION__, v1, f1, v2); ++ return set_cc_f32(v1, v2); ++} ++ ++/* 64-bit FP compare RR */ ++uint32_t HELPER(cdbr)(uint32_t f1, uint32_t f2) ++{ ++ float64 v1 = env->fregs[f1].d; ++ float64 v2 = env->fregs[f2].d;; ++ HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%ld\n", __FUNCTION__, v1, f1, v2); ++ return set_cc_f64(v1, v2); ++} ++ ++/* 128-bit FP compare RR */ ++uint32_t HELPER(cxbr)(uint32_t f1, uint32_t f2) ++{ ++ CPU_QuadU v1; ++ v1.ll.upper = env->fregs[f1].ll; ++ v1.ll.lower = env->fregs[f1 + 2].ll; ++ CPU_QuadU v2; ++ v2.ll.upper = env->fregs[f2].ll; ++ v2.ll.lower = env->fregs[f2 + 2].ll; ++ if (float128_is_nan(v1.q) || float128_is_nan(v2.q)) return 3; ++ else if (float128_eq(v1.q, v2.q, &env->fpu_status)) return 0; ++ else if (float128_lt(v1.q, v2.q, &env->fpu_status)) return 1; ++ else return 2; ++} ++ ++/* 64-bit FP compare RM */ ++uint32_t HELPER(cdb)(uint32_t f1, uint64_t a2) ++{ ++ float64 v1 = env->fregs[f1].d; ++ CPU_DoubleU v2; ++ v2.ll = ldq(a2); ++ HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%lx\n", __FUNCTION__, v1, f1, v2.d); ++ return set_cc_f64(v1, v2.d); ++} ++ ++/* 64-bit FP addition RM */ ++uint32_t HELPER(adb)(uint32_t f1, uint64_t a2) ++{ ++ float64 v1 = env->fregs[f1].d; ++ CPU_DoubleU v2; ++ v2.ll = ldq(a2); ++ HELPER_LOG("%s: adding 0x%lx from f%d and 0x%lx\n", __FUNCTION__, v1, f1, v2.d); ++ env->fregs[f1].d = v1 = float64_add(v1, v2.d, &env->fpu_status); ++ return set_cc_nz_f64(v1); ++} ++ ++/* 32-bit FP subtraction RM */ ++uint32_t HELPER(seb)(uint32_t f1, uint32_t val) ++{ ++ float32 v1 = env->fregs[f1].l.upper; ++ CPU_FloatU v2; ++ v2.l = val; ++ env->fregs[f1].l.upper = v1 = float32_sub(v1, v2.f, &env->fpu_status); ++ return set_cc_nz_f32(v1); ++} ++ ++/* 64-bit FP subtraction RM */ ++uint32_t HELPER(sdb)(uint32_t f1, uint64_t a2) ++{ ++ float64 v1 = env->fregs[f1].d; ++ CPU_DoubleU v2; ++ v2.ll = ldq(a2); ++ env->fregs[f1].d = v1 = float64_sub(v1, v2.d, &env->fpu_status); ++ return set_cc_nz_f64(v1); ++} ++ ++/* 64-bit FP multiplication RM */ ++void HELPER(mdb)(uint32_t f1, uint64_t a2) ++{ ++ float64 v1 = env->fregs[f1].d; ++ CPU_DoubleU v2; ++ v2.ll = ldq(a2); ++ HELPER_LOG("%s: multiplying 0x%lx from f%d and 0x%ld\n", __FUNCTION__, v1, f1, v2.d); ++ env->fregs[f1].d = float64_mul(v1, v2.d, &env->fpu_status); ++} ++ ++/* 64-bit FP division RM */ ++void HELPER(ddb)(uint32_t f1, uint64_t a2) ++{ ++ float64 v1 = env->fregs[f1].d; ++ CPU_DoubleU v2; ++ v2.ll = ldq(a2); ++ HELPER_LOG("%s: dividing 0x%lx from f%d by 0x%ld\n", __FUNCTION__, v1, f1, v2.d); ++ env->fregs[f1].d = float64_div(v1, v2.d, &env->fpu_status); ++} ++ ++static void set_round_mode(int m3) ++{ ++ switch (m3) { ++ case 0: break; /* current mode */ ++ case 1: /* biased round no nearest */ ++ case 4: /* round to nearest */ ++ set_float_rounding_mode(float_round_nearest_even, &env->fpu_status); ++ break; ++ case 5: /* round to zero */ ++ set_float_rounding_mode(float_round_to_zero, &env->fpu_status); ++ break; ++ case 6: /* round to +inf */ ++ set_float_rounding_mode(float_round_up, &env->fpu_status); ++ break; ++ case 7: /* round to -inf */ ++ set_float_rounding_mode(float_round_down, &env->fpu_status); ++ break; ++ } ++} ++ ++/* convert 32-bit float to 64-bit int */ ++uint32_t HELPER(cgebr)(uint32_t r1, uint32_t f2, uint32_t m3) ++{ ++ float32 v2 = env->fregs[f2].l.upper; ++ set_round_mode(m3); ++ env->regs[r1] = float32_to_int64(v2, &env->fpu_status); ++ return set_cc_nz_f32(v2); ++} ++ ++/* convert 64-bit float to 64-bit int */ ++uint32_t HELPER(cgdbr)(uint32_t r1, uint32_t f2, uint32_t m3) ++{ ++ float64 v2 = env->fregs[f2].d; ++ set_round_mode(m3); ++ env->regs[r1] = float64_to_int64(v2, &env->fpu_status); ++ return set_cc_nz_f64(v2); ++} ++ ++/* convert 128-bit float to 64-bit int */ ++uint32_t HELPER(cgxbr)(uint32_t r1, uint32_t f2, uint32_t m3) ++{ ++ CPU_QuadU v2; ++ v2.ll.upper = env->fregs[f2].ll; ++ v2.ll.lower = env->fregs[f2 + 2].ll; ++ set_round_mode(m3); ++ env->regs[r1] = float128_to_int64(v2.q, &env->fpu_status); ++ if (float128_is_nan(v2.q)) return 3; ++ else if (float128_is_zero(v2.q)) return 0; ++ else if (float128_is_neg(v2.q)) return 1; ++ else return 2; ++} ++ ++/* convert 32-bit float to 32-bit int */ ++uint32_t HELPER(cfebr)(uint32_t r1, uint32_t f2, uint32_t m3) ++{ ++ float32 v2 = env->fregs[f2].l.upper; ++ set_round_mode(m3); ++ env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | float32_to_int32(v2, &env->fpu_status); ++ return set_cc_nz_f32(v2); ++} ++ ++/* convert 64-bit float to 32-bit int */ ++uint32_t HELPER(cfdbr)(uint32_t r1, uint32_t f2, uint32_t m3) ++{ ++ float64 v2 = env->fregs[f2].d; ++ set_round_mode(m3); ++ env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | float64_to_int32(v2, &env->fpu_status); ++ return set_cc_nz_f64(v2); ++} ++ ++/* convert 128-bit float to 32-bit int */ ++uint32_t HELPER(cfxbr)(uint32_t r1, uint32_t f2, uint32_t m3) ++{ ++ CPU_QuadU v2; ++ v2.ll.upper = env->fregs[f2].ll; ++ v2.ll.lower = env->fregs[f2 + 2].ll; ++ env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | float128_to_int32(v2.q, &env->fpu_status); ++ return set_cc_nz_f128(v2.q); ++} ++ ++/* load 32-bit FP zero */ ++void HELPER(lzer)(uint32_t f1) ++{ ++ env->fregs[f1].l.upper = float32_zero; ++} ++ ++/* load 64-bit FP zero */ ++void HELPER(lzdr)(uint32_t f1) ++{ ++ env->fregs[f1].d = float64_zero; ++} ++ ++/* load 128-bit FP zero */ ++void HELPER(lzxr)(uint32_t f1) ++{ ++ CPU_QuadU x; ++ x.q = float64_to_float128(float64_zero, &env->fpu_status); ++ env->fregs[f1].ll = x.ll.upper; ++ env->fregs[f1 + 1].ll = x.ll.lower; ++} ++ ++/* 128-bit FP subtraction RR */ ++uint32_t HELPER(sxbr)(uint32_t f1, uint32_t f2) ++{ ++ CPU_QuadU v1; ++ v1.ll.upper = env->fregs[f1].ll; ++ v1.ll.lower = env->fregs[f1 + 2].ll; ++ CPU_QuadU v2; ++ v2.ll.upper = env->fregs[f2].ll; ++ v2.ll.lower = env->fregs[f2 + 2].ll; ++ CPU_QuadU res; ++ res.q = float128_sub(v1.q, v2.q, &env->fpu_status); ++ env->fregs[f1].ll = res.ll.upper; ++ env->fregs[f1 + 2].ll = res.ll.lower; ++ return set_cc_nz_f128(res.q); ++} ++ ++/* 128-bit FP addition RR */ ++uint32_t HELPER(axbr)(uint32_t f1, uint32_t f2) ++{ ++ CPU_QuadU v1; ++ v1.ll.upper = env->fregs[f1].ll; ++ v1.ll.lower = env->fregs[f1 + 2].ll; ++ CPU_QuadU v2; ++ v2.ll.upper = env->fregs[f2].ll; ++ v2.ll.lower = env->fregs[f2 + 2].ll; ++ CPU_QuadU res; ++ res.q = float128_add(v1.q, v2.q, &env->fpu_status); ++ env->fregs[f1].ll = res.ll.upper; ++ env->fregs[f1 + 2].ll = res.ll.lower; ++ return set_cc_nz_f128(res.q); ++} ++ ++/* 32-bit FP multiplication RR */ ++void HELPER(meebr)(uint32_t f1, uint32_t f2) ++{ ++ env->fregs[f1].l.upper = float32_mul(env->fregs[f1].l.upper, env->fregs[f2].l.upper, &env->fpu_status); ++} ++ ++/* 64-bit FP division RR */ ++void HELPER(ddbr)(uint32_t f1, uint32_t f2) ++{ ++ env->fregs[f1].d = float64_div(env->fregs[f1].d, env->fregs[f2].d, &env->fpu_status); ++} ++ ++/* 64-bit FP multiply and add RM */ ++void HELPER(madb)(uint32_t f1, uint64_t a2, uint32_t f3) ++{ ++ HELPER_LOG("%s: f1 %d a2 0x%lx f3 %d\n", __FUNCTION__, f1, a2, f3); ++ CPU_DoubleU v2; ++ v2.ll = ldq(a2); ++ env->fregs[f1].d = float64_add(env->fregs[f1].d, float64_mul(v2.d, env->fregs[f3].d, &env->fpu_status), &env->fpu_status); ++} ++ ++/* 64-bit FP multiply and add RR */ ++void HELPER(madbr)(uint32_t f1, uint32_t f3, uint32_t f2) ++{ ++ HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __FUNCTION__, f1, f2, f3); ++ env->fregs[f1].d = float64_add(float64_mul(env->fregs[f2].d, env->fregs[f3].d, &env->fpu_status), env->fregs[f1].d, &env->fpu_status); ++} ++ ++/* 64-bit FP multiply and subtract RR */ ++void HELPER(msdbr)(uint32_t f1, uint32_t f3, uint32_t f2) ++{ ++ HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __FUNCTION__, f1, f2, f3); ++ env->fregs[f1].d = float64_sub(float64_mul(env->fregs[f2].d, env->fregs[f3].d, &env->fpu_status), env->fregs[f1].d, &env->fpu_status); ++} ++ ++/* 32-bit FP multiply and add RR */ ++void HELPER(maebr)(uint32_t f1, uint32_t f3, uint32_t f2) ++{ ++ env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper, float32_mul(env->fregs[f2].l.upper, env->fregs[f3].l.upper, &env->fpu_status), &env->fpu_status); ++} ++ ++/* convert 64-bit float to 128-bit float */ ++void HELPER(lxdb)(uint32_t f1, uint64_t a2) ++{ ++ CPU_DoubleU v2; ++ v2.ll = ldq(a2); ++ CPU_QuadU v1; ++ v1.q = float64_to_float128(v2.d, &env->fpu_status); ++ env->fregs[f1].ll = v1.ll.upper; ++ env->fregs[f1 + 2].ll = v1.ll.lower; ++} ++ ++/* test data class 32-bit */ ++uint32_t HELPER(tceb)(uint32_t f1, uint64_t m2) ++{ ++ float32 v1 = env->fregs[f1].l.upper; ++ int neg = float32_is_neg(v1); ++ uint32_t cc = 0; ++ HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __FUNCTION__, v1, m2, neg); ++ if (float32_is_zero(v1) && (m2 & (1 << (11-neg)))) cc = 1; ++ else if (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) cc = 1; ++ else if (float32_is_nan(v1) && (m2 & (1 << (3-neg)))) cc = 1; ++ else if (float32_is_signaling_nan(v1) && (m2 & (1 << (1-neg)))) cc = 1; ++ else /* assume normalized number */ if (m2 & (1 << (9-neg))) cc = 1; ++ /* FIXME: denormalized? */ ++ return cc; ++} ++ ++/* test data class 64-bit */ ++uint32_t HELPER(tcdb)(uint32_t f1, uint64_t m2) ++{ ++ float64 v1 = env->fregs[f1].d; ++ int neg = float64_is_neg(v1); ++ uint32_t cc = 0; ++ HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __FUNCTION__, v1, m2, neg); ++ if (float64_is_zero(v1) && (m2 & (1 << (11-neg)))) cc = 1; ++ else if (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) cc = 1; ++ else if (float64_is_nan(v1) && (m2 & (1 << (3-neg)))) cc = 1; ++ else if (float64_is_signaling_nan(v1) && (m2 & (1 << (1-neg)))) cc = 1; ++ else /* assume normalized number */ if (m2 & (1 << (9-neg))) cc = 1; ++ /* FIXME: denormalized? */ ++ return cc; ++} ++ ++/* test data class 128-bit */ ++uint32_t HELPER(tcxb)(uint32_t f1, uint64_t m2) ++{ ++ CPU_QuadU v1; ++ uint32_t cc = 0; ++ v1.ll.upper = env->fregs[f1].ll; ++ v1.ll.lower = env->fregs[f1 + 2].ll; ++ ++ int neg = float128_is_neg(v1.q); ++ if (float128_is_zero(v1.q) && (m2 & (1 << (11-neg)))) cc = 1; ++ else if (float128_is_infinity(v1.q) && (m2 & (1 << (5-neg)))) cc = 1; ++ else if (float128_is_nan(v1.q) && (m2 & (1 << (3-neg)))) cc = 1; ++ else if (float128_is_signaling_nan(v1.q) && (m2 & (1 << (1-neg)))) cc = 1; ++ else /* assume normalized number */ if (m2 & (1 << (9-neg))) cc = 1; ++ /* FIXME: denormalized? */ ++ return cc; ++} ++ ++/* find leftmost one */ ++uint32_t HELPER(flogr)(uint32_t r1, uint64_t v2) ++{ ++ uint64_t res = 0; ++ uint64_t ov2 = v2; ++ while (!(v2 & 0x8000000000000000ULL) && v2) { ++ v2 <<= 1; ++ res++; ++ } ++ if (!v2) { ++ env->regs[r1] = 64; ++ env->regs[r1 + 1] = 0; ++ return 0; ++ } ++ else { ++ env->regs[r1] = res; ++ env->regs[r1 + 1] = ov2 & ~(0x8000000000000000ULL >> res); ++ return 2; ++ } ++} ++ ++/* square root 64-bit RR */ ++void HELPER(sqdbr)(uint32_t f1, uint32_t f2) ++{ ++ env->fregs[f1].d = float64_sqrt(env->fregs[f2].d, &env->fpu_status); ++} +diff --git a/target-s390x/translate.c b/target-s390x/translate.c +index cde19df..aa50b7d 100644 +--- a/target-s390x/translate.c ++++ b/target-s390x/translate.c +@@ -18,12 +18,43 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA + */ + ++#include ++#include ++#include ++#include ++#include ++ ++#define S390X_DEBUG_DISAS ++#ifdef S390X_DEBUG_DISAS ++# define LOG_DISAS(...) qemu_log(__VA_ARGS__) ++#else ++# define LOG_DISAS(...) do { } while (0) ++#endif ++ + #include "cpu.h" + #include "exec-all.h" + #include "disas.h" + #include "tcg-op.h" + #include "qemu-log.h" + ++/* global register indexes */ ++static TCGv_ptr cpu_env; ++ ++#include "gen-icount.h" ++#include "helpers.h" ++#define GEN_HELPER 1 ++#include "helpers.h" ++ ++typedef struct DisasContext DisasContext; ++struct DisasContext { ++ uint64_t pc; ++ int is_jmp; ++ CPUS390XState *env; ++}; ++ ++#define DISAS_EXCP 4 ++#define DISAS_SVC 5 ++ + void cpu_dump_state(CPUState *env, FILE *f, + int (*cpu_fprintf)(FILE *f, const char *fmt, ...), + int flags) +@@ -48,12 +79,2741 @@ void cpu_dump_state(CPUState *env, FILE *f, + cpu_fprintf(f, "PSW=mask %016lx addr %016lx cc %02x\n", env->psw.mask, env->psw.addr, env->cc); + } + ++#define TCGREGS ++ ++static TCGv global_cc; ++#ifdef TCGREGS ++/* registers stored in TCG variables enhance performance */ ++static TCGv_i64 tcgregs[16]; ++static TCGv_i32 tcgregs32[16]; ++#endif ++static TCGv cc; ++static TCGv psw_addr; ++ ++void s390x_translate_init(void) ++{ ++ cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); ++ global_cc = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, cc), "global_cc"); ++#ifdef TCGREGS ++ int i; ++ char rn[4]; ++ for (i = 0; i < 16; i++) { ++ sprintf(rn, "R%d", i); ++ tcgregs[i] = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUState, regs[i]), strdup(rn)); ++ sprintf(rn, "r%d", i); ++ tcgregs32[i] = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, regs[i]) ++#ifdef HOST_WORDS_BIGENDIAN ++ + 4 ++#endif ++ , strdup(rn)); ++ } ++#endif ++ psw_addr = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUState, psw.addr), "psw_addr"); ++} ++ ++#ifdef TCGREGS ++static inline void sync_reg64(int reg) ++{ ++ tcg_gen_sync_i64(tcgregs[reg]); ++} ++static inline void sync_reg32(int reg) ++{ ++ tcg_gen_sync_i32(tcgregs32[reg]); ++} ++#endif ++ ++static TCGv load_reg(int reg) ++{ ++ TCGv r = tcg_temp_new_i64(); ++#ifdef TCGREGS ++ sync_reg32(reg); ++ tcg_gen_mov_i64(r, tcgregs[reg]); ++ return r; ++#else ++ tcg_gen_ld_i64(r, cpu_env, offsetof(CPUState, regs[reg])); ++ return r; ++#endif ++} ++ ++static TCGv load_freg(int reg) ++{ ++ TCGv r = tcg_temp_new_i64(); ++ tcg_gen_ld_i64(r, cpu_env, offsetof(CPUState, fregs[reg].d)); ++ return r; ++} ++ ++static TCGv_i32 load_freg32(int reg) ++{ ++ TCGv_i32 r = tcg_temp_new_i32(); ++ tcg_gen_ld_i32(r, cpu_env, offsetof(CPUState, fregs[reg].l.upper)); ++ return r; ++} ++ ++static void load_reg32_var(TCGv_i32 r, int reg) ++{ ++#ifdef TCGREGS ++ sync_reg64(reg); ++ tcg_gen_mov_i32(r, tcgregs32[reg]); ++#else ++#ifdef HOST_WORDS_BIGENDIAN ++ tcg_gen_ld_i32(r, cpu_env, offsetof(CPUState, regs[reg]) + 4); ++#else ++ tcg_gen_ld_i32(r, cpu_env, offsetof(CPUState, regs[reg])); ++#endif ++#endif ++} ++ ++static TCGv_i32 load_reg32(int reg) ++{ ++ TCGv_i32 r = tcg_temp_new_i32(); ++ load_reg32_var(r, reg); ++ return r; ++} ++ ++static void store_reg(int reg, TCGv v) ++{ ++#ifdef TCGREGS ++ sync_reg32(reg); ++ tcg_gen_mov_i64(tcgregs[reg], v); ++#else ++ tcg_gen_st_i64(v, cpu_env, offsetof(CPUState, regs[reg])); ++#endif ++} ++ ++static void store_freg(int reg, TCGv v) ++{ ++ tcg_gen_st_i64(v, cpu_env, offsetof(CPUState, fregs[reg].d)); ++} ++ ++static void store_reg32(int reg, TCGv_i32 v) ++{ ++#ifdef TCGREGS ++ sync_reg64(reg); ++ tcg_gen_mov_i32(tcgregs32[reg], v); ++#else ++#ifdef HOST_WORDS_BIGENDIAN ++ tcg_gen_st_i32(v, cpu_env, offsetof(CPUState, regs[reg]) + 4); ++#else ++ tcg_gen_st_i32(v, cpu_env, offsetof(CPUState, regs[reg])); ++#endif ++#endif ++} ++ ++static void store_reg8(int reg, TCGv_i32 v) ++{ ++#ifdef TCGREGS ++ TCGv_i32 tmp = tcg_temp_new_i32(); ++ sync_reg64(reg); ++ tcg_gen_andi_i32(tmp, tcgregs32[reg], 0xffffff00UL); ++ tcg_gen_or_i32(tcgregs32[reg], tmp, v); ++ tcg_temp_free(tmp); ++#else ++#ifdef HOST_WORDS_BIGENDIAN ++ tcg_gen_st8_i32(v, cpu_env, offsetof(CPUState, regs[reg]) + 7); ++#else ++ tcg_gen_st8_i32(v, cpu_env, offsetof(CPUState, regs[reg])); ++#endif ++#endif ++} ++ ++static void store_freg32(int reg, TCGv v) ++{ ++ tcg_gen_st_i32(v, cpu_env, offsetof(CPUState, fregs[reg].l.upper)); ++} ++ ++static void gen_illegal_opcode(DisasContext *s) ++{ ++ TCGv tmp = tcg_const_i64(EXCP_SPEC); ++ gen_helper_exception(tmp); ++ tcg_temp_free(tmp); ++ s->is_jmp = DISAS_EXCP; ++} ++ ++#define DEBUGINSN LOG_DISAS("insn: 0x%lx\n", insn); ++ ++static TCGv get_address(int x2, int b2, int d2) ++{ ++ TCGv tmp = 0, tmp2; ++ if (d2) tmp = tcg_const_i64(d2); ++ if (x2) { ++ if (d2) { ++ tmp2 = load_reg(x2); ++ tcg_gen_add_i64(tmp, tmp, tmp2); ++ tcg_temp_free(tmp2); ++ } ++ else { ++ tmp = load_reg(x2); ++ } ++ } ++ if (b2) { ++ if (d2 || x2) { ++ tmp2 = load_reg(b2); ++ tcg_gen_add_i64(tmp, tmp, tmp2); ++ tcg_temp_free(tmp2); ++ } ++ else { ++ tmp = load_reg(b2); ++ } ++ } ++ ++ if (!(d2 || x2 || b2)) tmp = tcg_const_i64(0); ++ ++ return tmp; ++} ++ ++static inline void set_cc_nz_u32(TCGv val) ++{ ++ gen_helper_set_cc_nz_u32(cc, val); ++} ++ ++static inline void set_cc_nz_u64(TCGv val) ++{ ++ gen_helper_set_cc_nz_u64(cc, val); ++} ++ ++static inline void set_cc_s32(TCGv val) ++{ ++ gen_helper_set_cc_s32(cc, val); ++} ++ ++static inline void set_cc_s64(TCGv val) ++{ ++ gen_helper_set_cc_s64(cc, val); ++} ++ ++static inline void cmp_s32(TCGv v1, TCGv v2) ++{ ++ gen_helper_cmp_s32(cc, v1, v2); ++} ++ ++static inline void cmp_u32(TCGv v1, TCGv v2) ++{ ++ gen_helper_cmp_u32(cc, v1, v2); ++} ++ ++/* this is a hysterical raisin */ ++static inline void cmp_s32c(TCGv v1, int32_t v2) ++{ ++ TCGv_i32 tmp = tcg_const_i32(v2); ++ gen_helper_cmp_s32(cc, v1, tmp); ++ tcg_temp_free(tmp); ++} ++static inline void cmp_u32c(TCGv v1, uint32_t v2) ++{ ++ TCGv_i32 tmp = tcg_const_i32(v2); ++ gen_helper_cmp_u32(cc, v1, tmp); ++ tcg_temp_free(tmp); ++} ++ ++ ++static inline void cmp_s64(TCGv v1, TCGv v2) ++{ ++ gen_helper_cmp_s64(cc, v1, v2); ++} ++ ++static inline void cmp_u64(TCGv v1, TCGv v2) ++{ ++ gen_helper_cmp_u64(cc, v1, v2); ++} ++ ++/* see cmp_[su]32c() */ ++static inline void cmp_s64c(TCGv v1, int64_t v2) ++{ ++ TCGv_i32 tmp = tcg_const_i64(v2); ++ gen_helper_cmp_s64(cc, v1, tmp); ++ tcg_temp_free(tmp); ++} ++static inline void cmp_u64c(TCGv v1, uint64_t v2) ++{ ++ TCGv_i32 tmp = tcg_const_i64(v2); ++ gen_helper_cmp_u64(cc, v1, tmp); ++ tcg_temp_free(tmp); ++} ++ ++static void gen_bcr(uint32_t mask, int tr, uint64_t offset) ++{ ++ TCGv target, o; ++ TCGv_i32 m; ++ if (mask == 0xf) { /* unconditional */ ++ target = load_reg(tr); ++ tcg_gen_mov_i64(psw_addr, target); ++ } ++ else { ++ m = tcg_const_i32(mask); ++ o = tcg_const_i64(offset); ++ gen_helper_bcr(cc, m, (target = load_reg(tr)), o); ++ tcg_temp_free(m); ++ tcg_temp_free(o); ++ } ++ tcg_temp_free(target); ++} ++ ++static void gen_brc(uint32_t mask, uint64_t pc, int32_t offset) ++{ ++ TCGv p; ++ TCGv_i32 m, o; ++ ++ if (mask == 0xf) { /* unconditional */ ++ tcg_gen_movi_i64(psw_addr, pc + offset); ++ } ++ else { ++ m = tcg_const_i32(mask); ++ p = tcg_const_i64(pc); ++ o = tcg_const_i32(offset); ++ gen_helper_brc(cc, m, p, o); ++ tcg_temp_free(m); ++ tcg_temp_free(p); ++ tcg_temp_free(o); ++ } ++} ++ ++static void gen_set_cc_add64(TCGv v1, TCGv v2, TCGv vr) ++{ ++ gen_helper_set_cc_add64(cc, v1, v2, vr); ++} ++ ++static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2) ++{ ++ TCGv tmp, tmp2, tmp3; ++ ++ LOG_DISAS("disas_e3: op 0x%x r1 %d x2 %d b2 %d d2 %d\n", op, r1, x2, b2, d2); ++ tmp = get_address(x2, b2, d2); ++ switch (op) { ++ case 0x2: /* LTG R1,D2(X2,B2) [RXY] */ ++ case 0x4: /* lg r1,d2(x2,b2) */ ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld64(tmp2, tmp, 1); ++ store_reg(r1, tmp2); ++ if (op == 0x2) set_cc_s64(tmp2); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x12: /* LT R1,D2(X2,B2) [RXY] */ ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld32s(tmp2, tmp, 1); ++ store_reg32(r1, tmp2); ++ set_cc_s32(tmp2); ++ tcg_temp_free(tmp2); ++ break; ++ case 0xc: /* MSG R1,D2(X2,B2) [RXY] */ ++ case 0x1c: /* MSGF R1,D2(X2,B2) [RXY] */ ++ tmp2 = tcg_temp_new_i64(); ++ if (op == 0xc) { ++ tcg_gen_qemu_ld64(tmp2, tmp, 1); ++ } ++ else { ++ tcg_gen_qemu_ld32s(tmp2, tmp, 1); ++ } ++ tcg_temp_free(tmp); ++ tmp = load_reg(r1); ++ tcg_gen_mul_i64(tmp, tmp, tmp2); ++ store_reg(r1, tmp); ++ tcg_temp_free(tmp2); ++ break; ++ case 0xd: /* DSG R1,D2(X2,B2) [RXY] */ ++ case 0x1d: /* DSGF R1,D2(X2,B2) [RXY] */ ++ tmp2 = tcg_temp_new_i64(); ++ if (op == 0x1d) { ++ tcg_gen_qemu_ld32s(tmp2, tmp, 1); ++ } ++ else { ++ tcg_gen_qemu_ld64(tmp2, tmp, 1); ++ } ++ tcg_temp_free(tmp); ++ tmp = load_reg(r1 + 1); ++ tmp3 = tcg_temp_new_i64(); ++ tcg_gen_div_i64(tmp3, tmp, tmp2); ++ store_reg(r1 + 1, tmp3); ++ tcg_gen_rem_i64(tmp3, tmp, tmp2); ++ store_reg(r1, tmp3); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x8: /* AG R1,D2(X2,B2) [RXY] */ ++ case 0xa: /* ALG R1,D2(X2,B2) [RXY] */ ++ case 0x18: /* AGF R1,D2(X2,B2) [RXY] */ ++ case 0x1a: /* ALGF R1,D2(X2,B2) [RXY] */ ++ if (op == 0x1a) { ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld32u(tmp2, tmp, 1); ++ } ++ else if (op == 0x18) { ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld32s(tmp2, tmp, 1); ++ } ++ else { ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld64(tmp2, tmp, 1); ++ } ++ tcg_temp_free(tmp); ++ tmp = load_reg(r1); ++ tmp3 = tcg_temp_new_i64(); ++ tcg_gen_add_i64(tmp3, tmp, tmp2); ++ store_reg(r1, tmp3); ++ switch (op) { ++ case 0x8: case 0x18: gen_set_cc_add64(tmp, tmp2, tmp3); break; ++ case 0xa: case 0x1a: gen_helper_set_cc_addu64(cc, tmp, tmp2, tmp3); break; ++ default: tcg_abort(); ++ } ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x9: /* SG R1,D2(X2,B2) [RXY] */ ++ case 0xb: /* SLG R1,D2(X2,B2) [RXY] */ ++ case 0x19: /* SGF R1,D2(X2,B2) [RXY] */ ++ case 0x1b: /* SLGF R1,D2(X2,B2) [RXY] */ ++ tmp2 = tcg_temp_new_i64(); ++ if (op == 0x19) { ++ tcg_gen_qemu_ld32s(tmp2, tmp, 1); ++ } ++ else if (op == 0x1b) { ++ tcg_gen_qemu_ld32u(tmp2, tmp, 1); ++ } ++ else { ++ tcg_gen_qemu_ld64(tmp2, tmp, 1); ++ } ++ tcg_temp_free(tmp); ++ tmp = load_reg(r1); ++ tmp3 = tcg_temp_new_i64(); ++ tcg_gen_sub_i64(tmp3, tmp, tmp2); ++ store_reg(r1, tmp3); ++ switch (op) { ++ case 0x9: case 0x19: gen_helper_set_cc_sub64(cc, tmp, tmp2, tmp3); break; ++ case 0xb: case 0x1b: gen_helper_set_cc_subu64(cc, tmp, tmp2, tmp3); break; ++ default: tcg_abort(); ++ } ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x14: /* LGF R1,D2(X2,B2) [RXY] */ ++ case 0x16: /* LLGF R1,D2(X2,B2) [RXY] */ ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld32u(tmp2, tmp, 1); ++ switch (op) { ++ case 0x14: tcg_gen_ext32s_i64(tmp2, tmp2); break; ++ case 0x16: break; ++ default: tcg_abort(); ++ } ++ store_reg(r1, tmp2); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x15: /* LGH R1,D2(X2,B2) [RXY] */ ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld16s(tmp2, tmp, 1); ++ store_reg(r1, tmp2); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x17: /* LLGT R1,D2(X2,B2) [RXY] */ ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld32u(tmp2, tmp, 1); ++ tcg_gen_andi_i64(tmp2, tmp2, 0x7fffffffULL); ++ store_reg(r1, tmp2); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x1e: /* LRV R1,D2(X2,B2) [RXY] */ ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld32u(tmp2, tmp, 1); ++ tcg_gen_bswap32_i64(tmp2, tmp2); ++ store_reg32(r1, tmp2); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x20: /* CG R1,D2(X2,B2) [RXY] */ ++ case 0x21: /* CLG R1,D2(X2,B2) */ ++ case 0x30: /* CGF R1,D2(X2,B2) [RXY] */ ++ case 0x31: /* CLGF R1,D2(X2,B2) [RXY] */ ++ tmp2 = tcg_temp_new_i64(); ++ switch (op) { ++ case 0x20: ++ case 0x21: ++ tcg_gen_qemu_ld64(tmp2, tmp, 1); ++ break; ++ case 0x30: ++ tcg_gen_qemu_ld32s(tmp2, tmp, 1); ++ break; ++ case 0x31: ++ tcg_gen_qemu_ld32u(tmp2, tmp, 1); ++ break; ++ default: ++ tcg_abort(); ++ } ++ tcg_temp_free(tmp); ++ tmp = load_reg(r1); ++ switch (op) { ++ case 0x20: case 0x30: cmp_s64(tmp, tmp2); break; ++ case 0x21: case 0x31: cmp_u64(tmp, tmp2); break; ++ default: tcg_abort(); ++ } ++ tcg_temp_free(tmp2); ++ break; ++ case 0x24: /* stg r1, d2(x2,b2) */ ++ tmp2 = load_reg(r1); ++ tcg_gen_qemu_st64(tmp2, tmp, 1); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x3e: /* STRV R1,D2(X2,B2) [RXY] */ ++ tmp2 = load_reg32(r1); ++ tcg_gen_bswap32_i32(tmp2, tmp2); ++ tcg_gen_qemu_st32(tmp2, tmp, 1); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x50: /* STY R1,D2(X2,B2) [RXY] */ ++ tmp2 = load_reg32(r1); ++ tcg_gen_qemu_st32(tmp2, tmp, 1); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x57: /* XY R1,D2(X2,B2) [RXY] */ ++ tmp2 = load_reg32(r1); ++ tmp3 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld32u(tmp3, tmp, 1); ++ tcg_gen_xor_i32(tmp, tmp2, tmp3); ++ store_reg32(r1, tmp); ++ set_cc_nz_u32(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x58: /* LY R1,D2(X2,B2) [RXY] */ ++ tmp3 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld32u(tmp3, tmp, 1); ++ store_reg32(r1, tmp3); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x5a: /* AY R1,D2(X2,B2) [RXY] */ ++ case 0x5b: /* SY R1,D2(X2,B2) [RXY] */ ++ tmp2 = load_reg32(r1); ++ tmp3 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld32s(tmp3, tmp, 1); ++ switch (op) { ++ case 0x5a: tcg_gen_add_i32(tmp, tmp2, tmp3); break; ++ case 0x5b: tcg_gen_sub_i32(tmp, tmp2, tmp3); break; ++ default: tcg_abort(); ++ } ++ store_reg32(r1, tmp); ++ switch (op) { ++ case 0x5a: gen_helper_set_cc_add32(cc, tmp2, tmp3, tmp); break; ++ case 0x5b: gen_helper_set_cc_sub32(cc, tmp2, tmp3, tmp); break; ++ default: tcg_abort(); ++ } ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x71: /* LAY R1,D2(X2,B2) [RXY] */ ++ store_reg(r1, tmp); ++ break; ++ case 0x72: /* STCY R1,D2(X2,B2) [RXY] */ ++ tmp2 = load_reg32(r1); ++ tcg_gen_qemu_st8(tmp2, tmp, 1); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x73: /* ICY R1,D2(X2,B2) [RXY] */ ++ tmp3 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld8u(tmp3, tmp, 1); ++ store_reg8(r1, tmp3); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x76: /* LB R1,D2(X2,B2) [RXY] */ ++ case 0x77: /* LGB R1,D2(X2,B2) [RXY] */ ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld8s(tmp2, tmp, 1); ++ switch (op) { ++ case 0x76: ++ tcg_gen_ext8s_i64(tmp2, tmp2); ++ store_reg32(r1, tmp2); ++ break; ++ case 0x77: ++ tcg_gen_ext8s_i64(tmp2, tmp2); ++ store_reg(r1, tmp2); ++ break; ++ default: tcg_abort(); ++ } ++ tcg_temp_free(tmp2); ++ break; ++ case 0x78: /* LHY R1,D2(X2,B2) [RXY] */ ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld16s(tmp2, tmp, 1); ++ store_reg32(r1, tmp2); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x80: /* NG R1,D2(X2,B2) [RXY] */ ++ case 0x81: /* OG R1,D2(X2,B2) [RXY] */ ++ case 0x82: /* XG R1,D2(X2,B2) [RXY] */ ++ tmp2 = load_reg(r1); ++ tmp3 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld64(tmp3, tmp, 1); ++ switch (op) { ++ case 0x80: tcg_gen_and_i64(tmp, tmp2, tmp3); break; ++ case 0x81: tcg_gen_or_i64(tmp, tmp2, tmp3); break; ++ case 0x82: tcg_gen_xor_i64(tmp, tmp2, tmp3); break; ++ default: tcg_abort(); ++ } ++ store_reg(r1, tmp); ++ set_cc_nz_u64(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x86: /* MLG R1,D2(X2,B2) [RXY] */ ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld64(tmp2, tmp, 1); ++ tcg_temp_free(tmp); ++ tmp = tcg_const_i32(r1); ++ gen_helper_mlg(tmp, tmp2); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x87: /* DLG R1,D2(X2,B2) [RXY] */ ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld64(tmp2, tmp, 1); ++ tcg_temp_free(tmp); ++ tmp = tcg_const_i32(r1); ++ gen_helper_dlg(tmp, tmp2); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x88: /* ALCG R1,D2(X2,B2) [RXY] */ ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld64(tmp2, tmp, 1); ++ tcg_temp_free(tmp); ++ tmp = load_reg(r1); ++ tmp3 = tcg_temp_new_i64(); ++ tcg_gen_shri_i64(tmp3, cc, 1); ++ tcg_gen_andi_i64(tmp3, tmp3, 1); ++ tcg_gen_add_i64(tmp3, tmp2, tmp3);; ++ tcg_gen_add_i64(tmp3, tmp, tmp3); ++ store_reg(r1, tmp3); ++ gen_helper_set_cc_addc_u64(cc, tmp, tmp2, tmp3); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x89: /* SLBG R1,D2(X2,B2) [RXY] */ ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld64(tmp2, tmp, 1); ++ tcg_temp_free(tmp); ++ tmp = load_reg(r1); ++ tmp3 = tcg_const_i32(r1); ++ gen_helper_slbg(cc, cc, tmp3, tmp, tmp2); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x90: /* LLGC R1,D2(X2,B2) [RXY] */ ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld8u(tmp2, tmp, 1); ++ store_reg(r1, tmp2); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x91: /* LLGH R1,D2(X2,B2) [RXY] */ ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld16u(tmp2, tmp, 1); ++ store_reg(r1, tmp2); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x94: /* LLC R1,D2(X2,B2) [RXY] */ ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld8u(tmp2, tmp, 1); ++ store_reg32(r1, tmp2); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x95: /* LLH R1,D2(X2,B2) [RXY] */ ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld16u(tmp2, tmp, 1); ++ store_reg32(r1, tmp2); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x98: /* ALC R1,D2(X2,B2) [RXY] */ ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld32u(tmp2, tmp, 1); ++ tcg_temp_free(tmp); ++ tmp = tcg_const_i32(r1); ++ gen_helper_addc_u32(cc, cc, tmp, tmp2); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x99: /* SLB R1,D2(X2,B2) [RXY] */ ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld32u(tmp2, tmp, 1); ++ tcg_temp_free(tmp); ++ tmp = load_reg32(r1); ++ tmp3 = tcg_const_i32(r1); ++ gen_helper_slb(cc, cc, tmp3, tmp, tmp2); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ default: ++ LOG_DISAS("illegal e3 operation 0x%x\n", op); ++ gen_illegal_opcode(s); ++ break; ++ } ++ tcg_temp_free(tmp); ++} ++ ++static void disas_eb(DisasContext *s, int op, int r1, int r3, int b2, int d2) ++{ ++ TCGv tmp, tmp2, tmp3, tmp4; ++ int i; ++ ++ LOG_DISAS("disas_eb: op 0x%x r1 %d r3 %d b2 %d d2 0x%x\n", op, r1, r3, b2, d2); ++ switch (op) { ++ case 0xc: /* SRLG R1,R3,D2(B2) [RSY] */ ++ case 0xd: /* SLLG R1,R3,D2(B2) [RSY] */ ++ case 0xa: /* SRAG R1,R3,D2(B2) [RSY] */ ++ case 0x1c: /* RLLG R1,R3,D2(B2) [RSY] */ ++ if (b2) { ++ tmp = get_address(0, b2, d2); ++ tcg_gen_andi_i64(tmp, tmp, 0x3f); ++ } else { ++ tmp = tcg_const_i64(d2 & 0x3f); ++ } ++ tmp2 = load_reg(r3); ++ tmp3 = tcg_temp_new_i64(); ++ switch (op) { ++ case 0xc: tcg_gen_shr_i64(tmp3, tmp2, tmp); break; ++ case 0xd: tcg_gen_shl_i64(tmp3, tmp2, tmp); break; ++ case 0xa: tcg_gen_sar_i64(tmp3, tmp2, tmp); break; ++ case 0x1c: tcg_gen_rotl_i64(tmp3, tmp2, tmp); break; ++ default: tcg_abort(); break; ++ } ++ store_reg(r1, tmp3); ++ if (op == 0xa) set_cc_s64(tmp3); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x1d: /* RLL R1,R3,D2(B2) [RSY] */ ++ if (b2) { ++ tmp = get_address(0, b2, d2); ++ tcg_gen_andi_i64(tmp, tmp, 0x3f); ++ } else { ++ tmp = tcg_const_i64(d2 & 0x3f); ++ } ++ tmp2 = load_reg32(r3); ++ tmp3 = tcg_temp_new_i32(); ++ switch (op) { ++ case 0x1d: tcg_gen_rotl_i32(tmp3, tmp2, tmp); break; ++ default: tcg_abort(); break; ++ } ++ store_reg32(r1, tmp3); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x4: /* LMG R1,R3,D2(B2) [RSY] */ ++ case 0x24: /* stmg */ ++ /* Apparently, unrolling lmg/stmg of any size gains performance - ++ even for very long ones... */ ++ if (r3 > r1) { ++ tmp = get_address(0, b2, d2); ++ for (i = r1; i <= r3; i++) { ++ if (op == 0x4) { ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld64(tmp2, tmp, 1); ++ store_reg(i, tmp2); ++ /* At least one register is usually read after an lmg ++ (br %rsomething), which is why freeing them is ++ detrimental to performance */ ++ } ++ else { ++ tmp2 = load_reg(i); ++ tcg_gen_qemu_st64(tmp2, tmp, 1); ++ /* R15 is usually read after an stmg; other registers ++ generally aren't and can be free'd */ ++ if (i != 15) tcg_temp_free(tmp2); ++ } ++ tcg_gen_addi_i64(tmp, tmp, 8); ++ } ++ } ++ else { ++ tmp = tcg_const_i32(r1); ++ tmp2 = tcg_const_i32(r3); ++ tmp3 = tcg_const_i32(b2); ++ tmp4 = tcg_const_i32(d2); ++ if (op == 0x4) gen_helper_lmg(tmp, tmp2, tmp3, tmp4); ++ else gen_helper_stmg(tmp, tmp2, tmp3, tmp4); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ tcg_temp_free(tmp4); ++ } ++ tcg_temp_free(tmp); ++ break; ++ case 0x2c: /* STCMH R1,M3,D2(B2) [RSY] */ ++ tmp2 = get_address(0, b2, d2); ++ tmp = tcg_const_i32(r1); ++ tmp3 = tcg_const_i32(r3); ++ gen_helper_stcmh(cc, tmp, tmp2, tmp3); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x30: /* CSG R1,R3,D2(B2) [RSY] */ ++ tmp2 = get_address(0, b2, d2); ++ tmp = tcg_const_i32(r1); ++ tmp3 = tcg_const_i32(r3); ++ gen_helper_csg(cc, tmp, tmp2, tmp3); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x3e: /* CDSG R1,R3,D2(B2) [RSY] */ ++ tmp2 = get_address(0, b2, d2); ++ tmp = tcg_const_i32(r1); ++ tmp3 = tcg_const_i32(r3); ++ gen_helper_cdsg(cc, tmp, tmp2, tmp3); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x51: /* TMY D1(B1),I2 [SIY] */ ++ tmp = get_address(0, b2, d2); /* SIY -> this is the destination */ ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld8u(tmp2, tmp, 1); ++ tcg_temp_free(tmp); ++ tmp = tcg_const_i32((r1 << 4) | r3); ++ gen_helper_tm(cc, tmp2, tmp); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x52: /* MVIY D1(B1),I2 [SIY] */ ++ tmp2 = tcg_const_i32((r1 << 4) | r3); ++ tmp = get_address(0, b2, d2); /* SIY -> this is the destination */ ++ tcg_gen_qemu_st8(tmp2, tmp, 1); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x55: /* CLIY D1(B1),I2 [SIY] */ ++ tmp3 = get_address(0, b2, d2); /* SIY -> this is the 1st operand */ ++ tmp = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld8u(tmp, tmp3, 1); ++ cmp_u32c(tmp, (r1 << 4) | r3); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x80: /* ICMH R1,M3,D2(B2) [RSY] */ ++ tmp2 = get_address(0, b2, d2); ++ tmp = tcg_const_i32(r1); ++ tmp3 = tcg_const_i32(r3); ++ gen_helper_icmh(cc, tmp, tmp2, tmp3); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ default: ++ LOG_DISAS("illegal eb operation 0x%x\n", op); ++ gen_illegal_opcode(s); ++ break; ++ } ++} ++ ++static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2, int r1b) ++{ ++ TCGv_i32 tmp; ++ TCGv tmp2, tmp3; ++ tmp2 = get_address(x2, b2, d2); ++ tmp = tcg_const_i32(r1); ++ switch (op) { ++ case 0x5: /* LXDB R1,D2(X2,B2) [RXE] */ ++ gen_helper_lxdb(tmp, tmp2); ++ break; ++ case 0x9: /* CEB R1,D2(X2,B2) [RXE] */ ++ tmp3 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld32u(tmp3, tmp2, 1); ++ gen_helper_ceb(cc, tmp, tmp3); ++ tcg_temp_free(tmp3); ++ break; ++ case 0xa: /* AEB R1,D2(X2,B2) [RXE] */ ++ tmp3 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld32u(tmp3, tmp2, 1); ++ gen_helper_aeb(cc, tmp, tmp3); ++ tcg_temp_free(tmp3); ++ break; ++ case 0xb: /* SEB R1,D2(X2,B2) [RXE] */ ++ tmp3 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld32u(tmp3, tmp2, 1); ++ gen_helper_seb(cc, tmp, tmp3); ++ tcg_temp_free(tmp3); ++ break; ++ case 0xd: /* DEB R1,D2(X2,B2) [RXE] */ ++ tmp3 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld32u(tmp3, tmp2, 1); ++ gen_helper_deb(tmp, tmp3); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x10: /* TCEB R1,D2(X2,B2) [RXE] */ ++ gen_helper_tceb(cc, tmp, tmp2); ++ break; ++ case 0x11: /* TCDB R1,D2(X2,B2) [RXE] */ ++ gen_helper_tcdb(cc, tmp, tmp2); ++ break; ++ case 0x12: /* TCXB R1,D2(X2,B2) [RXE] */ ++ gen_helper_tcxb(cc, tmp, tmp2); ++ break; ++ case 0x17: /* MEEB R1,D2(X2,B2) [RXE] */ ++ tmp3 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld32u(tmp3, tmp2, 1); ++ gen_helper_meeb(tmp, tmp3); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x19: /* CDB R1,D2(X2,B2) [RXE] */ ++ gen_helper_cdb(cc, tmp, tmp2); ++ break; ++ case 0x1a: /* ADB R1,D2(X2,B2) [RXE] */ ++ gen_helper_adb(cc, tmp, tmp2); ++ break; ++ case 0x1b: /* SDB R1,D2(X2,B2) [RXE] */ ++ gen_helper_sdb(cc, tmp, tmp2); ++ break; ++ case 0x1c: /* MDB R1,D2(X2,B2) [RXE] */ ++ gen_helper_mdb(tmp, tmp2); ++ break; ++ case 0x1d: /* DDB R1,D2(X2,B2) [RXE] */ ++ gen_helper_ddb(tmp, tmp2); ++ break; ++ case 0x1e: /* MADB R1,R3,D2(X2,B2) [RXF] */ ++ /* for RXF insns, r1 is R3 and r1b is R1 */ ++ tmp3 = tcg_const_i32(r1b); ++ gen_helper_madb(tmp3, tmp2, tmp); ++ tcg_temp_free(tmp3); ++ break; ++ default: ++ LOG_DISAS("illegal ed operation 0x%x\n", op); ++ gen_illegal_opcode(s); ++ return; ++ } ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++} ++ ++static void disas_a5(DisasContext *s, int op, int r1, int i2) ++{ ++ TCGv tmp, tmp2; ++ uint64_t vtmp; ++ LOG_DISAS("disas_a5: op 0x%x r1 %d i2 0x%x\n", op, r1, i2); ++ switch (op) { ++ case 0x0: /* IIHH R1,I2 [RI] */ ++ case 0x1: /* IIHL R1,I2 [RI] */ ++ tmp = load_reg(r1); ++ vtmp = i2; ++ switch (op) { ++ case 0x0: tcg_gen_andi_i64(tmp, tmp, 0x0000ffffffffffffULL); vtmp <<= 48; break; ++ case 0x1: tcg_gen_andi_i64(tmp, tmp, 0xffff0000ffffffffULL); vtmp <<= 32; break; ++ default: tcg_abort(); ++ } ++ tcg_gen_ori_i64(tmp, tmp, vtmp); ++ store_reg(r1, tmp); ++ break; ++ case 0x4: /* NIHH R1,I2 [RI] */ ++ case 0x8: /* OIHH R1,I2 [RI] */ ++ tmp = load_reg(r1); ++ switch (op) { ++ case 0x4: ++ tmp2 = tcg_const_i64( (((uint64_t)i2) << 48) | 0x0000ffffffffffffULL); ++ tcg_gen_and_i64(tmp, tmp, tmp2); ++ break; ++ case 0x8: ++ tmp2 = tcg_const_i64(((uint64_t)i2) << 48); ++ tcg_gen_or_i64(tmp, tmp, tmp2); ++ break; ++ default: tcg_abort(); ++ } ++ store_reg(r1, tmp); ++ tcg_gen_shri_i64(tmp2, tmp, 48); ++ tcg_gen_trunc_i64_i32(tmp2, tmp2); ++ set_cc_nz_u32(tmp2); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x5: /* NIHL R1,I2 [RI] */ ++ case 0x9: /* OIHL R1,I2 [RI] */ ++ tmp = load_reg(r1); ++ switch (op) { ++ case 0x5: ++ tmp2 = tcg_const_i64( (((uint64_t)i2) << 32) | 0xffff0000ffffffffULL); ++ tcg_gen_and_i64(tmp, tmp, tmp2); ++ break; ++ case 0x9: ++ tmp2 = tcg_const_i64(((uint64_t)i2) << 32); ++ tcg_gen_or_i64(tmp, tmp, tmp2); ++ break; ++ default: tcg_abort(); ++ } ++ store_reg(r1, tmp); ++ tcg_gen_shri_i64(tmp2, tmp, 32); ++ tcg_gen_trunc_i64_i32(tmp2, tmp2); ++ tcg_gen_andi_i32(tmp2, tmp2, 0xffff); ++ set_cc_nz_u32(tmp2); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x6: /* NILH R1,I2 [RI] */ ++ case 0xa: /* OILH R1,I2 [RI] */ ++ tmp = load_reg(r1); ++ switch (op) { ++ case 0x6: ++ tmp2 = tcg_const_i64( (((uint64_t)i2) << 16) | 0xffffffff0000ffffULL); ++ tcg_gen_and_i64(tmp, tmp, tmp2); ++ break; ++ case 0xa: ++ tmp2 = tcg_const_i64(((uint64_t)i2) << 16); ++ tcg_gen_or_i64(tmp, tmp, tmp2); ++ break; ++ default: tcg_abort(); ++ } ++ store_reg(r1, tmp); ++ tcg_gen_shri_i64(tmp2, tmp, 16); ++ tcg_gen_trunc_i64_i32(tmp2, tmp2); ++ tcg_gen_andi_i32(tmp2, tmp2, 0xffff); ++ set_cc_nz_u32(tmp2); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x7: /* NILL R1,I2 [RI] */ ++ case 0xb: /* OILL R1,I2 [RI] */ ++ tmp = load_reg(r1); ++ switch (op) { ++ case 0x7: ++ tmp2 = tcg_const_i64(i2 | 0xffffffffffff0000ULL); ++ tcg_gen_and_i64(tmp, tmp, tmp2); ++ break; ++ case 0xb: ++ tmp2 = tcg_const_i64(i2); ++ tcg_gen_or_i64(tmp, tmp, tmp2); ++ break; ++ default: tcg_abort(); break; ++ } ++ store_reg(r1, tmp); ++ tcg_gen_trunc_i64_i32(tmp, tmp); ++ tcg_gen_andi_i32(tmp, tmp, 0xffff); ++ set_cc_nz_u32(tmp); /* signedness should not matter here */ ++ tcg_temp_free(tmp2); ++ break; ++ case 0xc: /* LLIHH R1,I2 [RI] */ ++ tmp = tcg_const_i64( ((uint64_t)i2) << 48 ); ++ store_reg(r1, tmp); ++ break; ++ case 0xd: /* LLIHL R1,I2 [RI] */ ++ tmp = tcg_const_i64( ((uint64_t)i2) << 32 ); ++ store_reg(r1, tmp); ++ break; ++ case 0xe: /* LLILH R1,I2 [RI] */ ++ tmp = tcg_const_i64( ((uint64_t)i2) << 16 ); ++ store_reg(r1, tmp); ++ break; ++ case 0xf: /* LLILL R1,I2 [RI] */ ++ tmp = tcg_const_i64(i2); ++ store_reg(r1, tmp); ++ break; ++ default: ++ LOG_DISAS("illegal a5 operation 0x%x\n", op); ++ gen_illegal_opcode(s); ++ return; ++ } ++ tcg_temp_free(tmp); ++} ++ ++static void disas_a7(DisasContext *s, int op, int r1, int i2) ++{ ++ TCGv tmp, tmp2, tmp3; ++ LOG_DISAS("disas_a7: op 0x%x r1 %d i2 0x%x\n", op, r1, i2); ++ switch (op) { ++ case 0x0: /* TMLH or TMH R1,I2 [RI] */ ++ tmp = load_reg(r1); ++ tcg_gen_shri_i64(tmp, tmp, 16); ++ tmp2 = tcg_const_i32((uint16_t)i2); ++ gen_helper_tmxx(cc, tmp, tmp2); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x1: /* TMLL or TML R1,I2 [RI] */ ++ tmp = load_reg(r1); ++ tmp2 = tcg_const_i32((uint16_t)i2); ++ gen_helper_tmxx(cc, tmp, tmp2); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x2: /* TMHH R1,I2 [RI] */ ++ tmp = load_reg(r1); ++ tcg_gen_shri_i64(tmp, tmp, 48); ++ tmp2 = tcg_const_i32((uint16_t)i2); ++ gen_helper_tmxx(cc, tmp, tmp2); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x3: /* TMHL R1,I2 [RI] */ ++ tmp = load_reg(r1); ++ tcg_gen_shri_i64(tmp, tmp, 32); ++ tmp2 = tcg_const_i32((uint16_t)i2); ++ gen_helper_tmxx(cc, tmp, tmp2); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x4: /* brc m1, i2 */ ++ /* FIXME: optimize m1 == 0xf (unconditional) case */ ++ gen_brc(r1, s->pc, i2 * 2); ++ s->is_jmp = DISAS_JUMP; ++ return; ++ case 0x5: /* BRAS R1,I2 [RI] */ ++ tmp = tcg_const_i64(s->pc + 4); ++ store_reg(r1, tmp); ++ tcg_temp_free(tmp); ++ tmp = tcg_const_i64(s->pc + i2 * 2); ++ tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUState, psw.addr)); ++ s->is_jmp = DISAS_JUMP; ++ break; ++ case 0x6: /* BRCT R1,I2 [RI] */ ++ tmp = load_reg32(r1); ++ tcg_gen_subi_i32(tmp, tmp, 1); ++ store_reg32(r1, tmp); ++ tmp2 = tcg_const_i64(s->pc); ++ tmp3 = tcg_const_i32(i2 * 2); ++ gen_helper_brct(tmp, tmp2, tmp3); ++ s->is_jmp = DISAS_JUMP; ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x7: /* BRCTG R1,I2 [RI] */ ++ tmp = load_reg(r1); ++ tcg_gen_subi_i64(tmp, tmp, 1); ++ store_reg(r1, tmp); ++ tmp2 = tcg_const_i64(s->pc); ++ tmp3 = tcg_const_i32(i2 * 2); ++ gen_helper_brctg(tmp, tmp2, tmp3); ++ s->is_jmp = DISAS_JUMP; ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x8: /* lhi r1, i2 */ ++ tmp = tcg_const_i32(i2); ++ store_reg32(r1, tmp); ++ break; ++ case 0x9: /* lghi r1, i2 */ ++ tmp = tcg_const_i64(i2); ++ store_reg(r1, tmp); ++ break; ++ case 0xa: /* AHI R1,I2 [RI] */ ++ tmp = load_reg32(r1); ++ tmp3 = tcg_temp_new_i32(); ++ tcg_gen_addi_i32(tmp3, tmp, i2); ++ store_reg32(r1, tmp3); ++ tmp2 = tcg_const_i32(i2); ++ gen_helper_set_cc_add32(cc, tmp, tmp2, tmp3); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0xb: /* aghi r1, i2 */ ++ tmp = load_reg(r1); ++ tmp3 = tcg_temp_new_i64(); ++ tcg_gen_addi_i64(tmp3, tmp, i2); ++ store_reg(r1, tmp3); ++ tmp2 = tcg_const_i64(i2); ++ gen_set_cc_add64(tmp, tmp2, tmp3); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0xc: /* MHI R1,I2 [RI] */ ++ tmp = load_reg32(r1); ++ tcg_gen_muli_i32(tmp, tmp, i2); ++ store_reg32(r1, tmp); ++ break; ++ case 0xd: /* MGHI R1,I2 [RI] */ ++ tmp = load_reg(r1); ++ tcg_gen_muli_i64(tmp, tmp, i2); ++ store_reg(r1, tmp); ++ break; ++ case 0xe: /* CHI R1,I2 [RI] */ ++ tmp = load_reg32(r1); ++ cmp_s32c(tmp, i2); ++ break; ++ case 0xf: /* CGHI R1,I2 [RI] */ ++ tmp = load_reg(r1); ++ cmp_s64c(tmp, i2); ++ break; ++ default: ++ LOG_DISAS("illegal a7 operation 0x%x\n", op); ++ gen_illegal_opcode(s); ++ return; ++ } ++ tcg_temp_free(tmp); ++} ++ ++static void disas_b2(DisasContext *s, int op, int r1, int r2) ++{ ++ TCGv_i32 tmp, tmp2, tmp3; ++ LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2); ++ switch (op) { ++ case 0x22: /* IPM R1 [RRE] */ ++ tmp = tcg_const_i32(r1); ++ gen_helper_ipm(cc, tmp); ++ break; ++ case 0x4e: /* SAR R1,R2 [RRE] */ ++ tmp = load_reg32(r2); ++ tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, aregs[r1])); ++ break; ++ case 0x4f: /* EAR R1,R2 [RRE] */ ++ tmp = tcg_temp_new_i32(); ++ tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUState, aregs[r2])); ++ store_reg32(r1, tmp); ++ break; ++ case 0x52: /* MSR R1,R2 [RRE] */ ++ tmp = load_reg32(r1); ++ tmp2 = load_reg32(r2); ++ tcg_gen_mul_i32(tmp, tmp, tmp2); ++ store_reg32(r1, tmp); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x55: /* MVST R1,R2 [RRE] */ ++ tmp = load_reg32(0); ++ tmp2 = tcg_const_i32(r1); ++ tmp3 = tcg_const_i32(r2); ++ gen_helper_mvst(cc, tmp, tmp2, tmp3); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x5d: /* CLST R1,R2 [RRE] */ ++ tmp = load_reg32(0); ++ tmp2 = tcg_const_i32(r1); ++ tmp3 = tcg_const_i32(r2); ++ gen_helper_clst(cc, tmp, tmp2, tmp3); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x5e: /* SRST R1,R2 [RRE] */ ++ tmp = load_reg32(0); ++ tmp2 = tcg_const_i32(r1); ++ tmp3 = tcg_const_i32(r2); ++ gen_helper_srst(cc, tmp, tmp2, tmp3); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ default: ++ LOG_DISAS("illegal b2 operation 0x%x\n", op); ++ gen_illegal_opcode(s); ++ return; ++ } ++ tcg_temp_free(tmp); ++} ++ ++static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2) ++{ ++ TCGv_i32 tmp, tmp2, tmp3; ++ LOG_DISAS("disas_b3: op 0x%x m3 0x%x r1 %d r2 %d\n", op, m3, r1, r2); ++#define FP_HELPER(i) \ ++ tmp = tcg_const_i32(r1); \ ++ tmp2 = tcg_const_i32(r2); \ ++ gen_helper_ ## i (tmp, tmp2); \ ++ tcg_temp_free(tmp); \ ++ tcg_temp_free(tmp2); ++ ++#define FP_HELPER_CC(i) \ ++ tmp = tcg_const_i32(r1); \ ++ tmp2 = tcg_const_i32(r2); \ ++ gen_helper_ ## i (cc, tmp, tmp2); \ ++ tcg_temp_free(tmp); \ ++ tcg_temp_free(tmp2); ++ ++ switch (op) { ++ case 0x0: /* LPEBR R1,R2 [RRE] */ ++ FP_HELPER_CC(lpebr); break; ++ case 0x2: /* LTEBR R1,R2 [RRE] */ ++ FP_HELPER_CC(ltebr); break; ++ case 0x3: /* LCEBR R1,R2 [RRE] */ ++ FP_HELPER_CC(lcebr); break; ++ case 0x4: /* LDEBR R1,R2 [RRE] */ ++ FP_HELPER(ldebr); break; ++ case 0x5: /* LXDBR R1,R2 [RRE] */ ++ FP_HELPER(lxdbr); break; ++ case 0x9: /* CEBR R1,R2 [RRE] */ ++ FP_HELPER_CC(cebr); break; ++ case 0xa: /* AEBR R1,R2 [RRE] */ ++ FP_HELPER_CC(aebr); break; ++ case 0xb: /* SEBR R1,R2 [RRE] */ ++ FP_HELPER_CC(sebr); break; ++ case 0xd: /* DEBR R1,R2 [RRE] */ ++ FP_HELPER(debr); break; ++ case 0x10: /* LPDBR R1,R2 [RRE] */ ++ FP_HELPER_CC(lpdbr); break; ++ case 0x12: /* LTDBR R1,R2 [RRE] */ ++ FP_HELPER_CC(ltdbr); break; ++ case 0x13: /* LCDBR R1,R2 [RRE] */ ++ FP_HELPER_CC(lcdbr); break; ++ case 0x15: /* SQBDR R1,R2 [RRE] */ ++ FP_HELPER(sqdbr); break; ++ case 0x17: /* MEEBR R1,R2 [RRE] */ ++ FP_HELPER(meebr); break; ++ case 0x19: /* CDBR R1,R2 [RRE] */ ++ FP_HELPER_CC(cdbr); break; ++ case 0x1a: /* ADBR R1,R2 [RRE] */ ++ FP_HELPER_CC(adbr); break; ++ case 0x1b: /* SDBR R1,R2 [RRE] */ ++ FP_HELPER_CC(sdbr); break; ++ case 0x1c: /* MDBR R1,R2 [RRE] */ ++ FP_HELPER(mdbr); break; ++ case 0x1d: /* DDBR R1,R2 [RRE] */ ++ FP_HELPER(ddbr); break; ++ case 0xe: /* MAEBR R1,R3,R2 [RRF] */ ++ case 0x1e: /* MADBR R1,R3,R2 [RRF] */ ++ case 0x1f: /* MSDBR R1,R3,R2 [RRF] */ ++ /* for RRF insns, m3 is R1, r1 is R3, and r2 is R2 */ ++ tmp = tcg_const_i32(m3); ++ tmp2 = tcg_const_i32(r2); ++ tmp3 = tcg_const_i32(r1); ++ switch (op) { ++ case 0xe: gen_helper_maebr(tmp, tmp3, tmp2); break; ++ case 0x1e: gen_helper_madbr(tmp, tmp3, tmp2); break; ++ case 0x1f: gen_helper_msdbr(tmp, tmp3, tmp2); break; ++ default: tcg_abort(); ++ } ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x40: /* LPXBR R1,R2 [RRE] */ ++ FP_HELPER_CC(lpxbr); break; ++ case 0x42: /* LTXBR R1,R2 [RRE] */ ++ FP_HELPER_CC(ltxbr); break; ++ case 0x43: /* LCXBR R1,R2 [RRE] */ ++ FP_HELPER_CC(lcxbr); break; ++ case 0x44: /* LEDBR R1,R2 [RRE] */ ++ FP_HELPER(ledbr); break; ++ case 0x45: /* LDXBR R1,R2 [RRE] */ ++ FP_HELPER(ldxbr); break; ++ case 0x46: /* LEXBR R1,R2 [RRE] */ ++ FP_HELPER(lexbr); break; ++ case 0x49: /* CXBR R1,R2 [RRE] */ ++ FP_HELPER_CC(cxbr); break; ++ case 0x4a: /* AXBR R1,R2 [RRE] */ ++ FP_HELPER_CC(axbr); break; ++ case 0x4b: /* SXBR R1,R2 [RRE] */ ++ FP_HELPER_CC(sxbr); break; ++ case 0x4c: /* MXBR R1,R2 [RRE] */ ++ FP_HELPER(mxbr); break; ++ case 0x4d: /* DXBR R1,R2 [RRE] */ ++ FP_HELPER(dxbr); break; ++ case 0x65: /* LXR R1,R2 [RRE] */ ++ tmp = load_freg(r2); ++ store_freg(r1, tmp); ++ tcg_temp_free(tmp); ++ tmp = load_freg(r2 + 2); ++ store_freg(r1 + 2, tmp); ++ tcg_temp_free(tmp); ++ break; ++ case 0x74: /* LZER R1 [RRE] */ ++ tmp = tcg_const_i32(r1); ++ gen_helper_lzer(tmp); ++ tcg_temp_free(tmp); ++ break; ++ case 0x75: /* LZDR R1 [RRE] */ ++ tmp = tcg_const_i32(r1); ++ gen_helper_lzdr(tmp); ++ tcg_temp_free(tmp); ++ break; ++ case 0x76: /* LZXR R1 [RRE] */ ++ tmp = tcg_const_i32(r1); ++ gen_helper_lzxr(tmp); ++ tcg_temp_free(tmp); ++ break; ++ case 0x84: /* SFPC R1 [RRE] */ ++ tmp = load_reg32(r1); ++ tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, fpc)); ++ tcg_temp_free(tmp); ++ break; ++ case 0x8c: /* EFPC R1 [RRE] */ ++ tmp = tcg_temp_new_i32(); ++ tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUState, fpc)); ++ store_reg32(r1, tmp); ++ tcg_temp_free(tmp); ++ break; ++ case 0x94: /* CEFBR R1,R2 [RRE] */ ++ case 0x95: /* CDFBR R1,R2 [RRE] */ ++ case 0x96: /* CXFBR R1,R2 [RRE] */ ++ tmp = tcg_const_i32(r1); ++ tmp2 = load_reg32(r2); ++ switch (op) { ++ case 0x94: gen_helper_cefbr(tmp, tmp2); break; ++ case 0x95: gen_helper_cdfbr(tmp, tmp2); break; ++ case 0x96: gen_helper_cxfbr(tmp, tmp2); break; ++ default: tcg_abort(); ++ } ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x98: /* CFEBR R1,R2 [RRE] */ ++ case 0x99: /* CFDBR R1,R2 [RRE] */ ++ case 0x9a: /* CFXBR R1,R2 [RRE] */ ++ tmp = tcg_const_i32(r1); ++ tmp2 = tcg_const_i32(r2); ++ tmp3 = tcg_const_i32(m3); ++ switch (op) { ++ case 0x98: gen_helper_cfebr(cc, tmp, tmp2, tmp3); break; ++ case 0x99: gen_helper_cfdbr(cc, tmp, tmp2, tmp3); break; ++ case 0x9a: gen_helper_cfxbr(cc, tmp, tmp2, tmp3); break; ++ default: tcg_abort(); ++ } ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0xa4: /* CEGBR R1,R2 [RRE] */ ++ case 0xa5: /* CDGBR R1,R2 [RRE] */ ++ tmp = tcg_const_i32(r1); ++ tmp2 = load_reg(r2); ++ switch (op) { ++ case 0xa4: gen_helper_cegbr(tmp, tmp2); break; ++ case 0xa5: gen_helper_cdgbr(tmp, tmp2); break; ++ default: tcg_abort(); ++ } ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ break; ++ case 0xa6: /* CXGBR R1,R2 [RRE] */ ++ tmp = tcg_const_i32(r1); ++ tmp2 = load_reg(r2); ++ gen_helper_cxgbr(tmp, tmp2); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ break; ++ case 0xa8: /* CGEBR R1,R2 [RRE] */ ++ tmp = tcg_const_i32(r1); ++ tmp2 = tcg_const_i32(r2); ++ tmp3 = tcg_const_i32(m3); ++ gen_helper_cgebr(cc, tmp, tmp2, tmp3); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0xa9: /* CGDBR R1,R2 [RRE] */ ++ tmp = tcg_const_i32(r1); ++ tmp2 = tcg_const_i32(r2); ++ tmp3 = tcg_const_i32(m3); ++ gen_helper_cgdbr(cc, tmp, tmp2, tmp3); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0xaa: /* CGXBR R1,R2 [RRE] */ ++ tmp = tcg_const_i32(r1); ++ tmp2 = tcg_const_i32(r2); ++ tmp3 = tcg_const_i32(m3); ++ gen_helper_cgxbr(cc, tmp, tmp2, tmp3); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ default: ++ LOG_DISAS("illegal b3 operation 0x%x\n", op); ++ gen_illegal_opcode(s); ++ break; ++ } ++} ++ ++static void disas_b9(DisasContext *s, int op, int r1, int r2) ++{ ++ TCGv tmp, tmp2, tmp3; ++ LOG_DISAS("disas_b9: op 0x%x r1 %d r2 %d\n", op, r1, r2); ++ switch (op) { ++ case 0: /* LPGR R1,R2 [RRE] */ ++ case 0x10: /* LPGFR R1,R2 [RRE] */ ++ if (op == 0) { ++ tmp2 = load_reg(r2); ++ } ++ else { ++ tmp2 = load_reg32(r2); ++ tcg_gen_ext32s_i64(tmp2, tmp2); ++ } ++ tmp = tcg_const_i32(r1); ++ gen_helper_abs_i64(cc, tmp, tmp2); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ break; ++ case 1: /* LNGR R1,R2 [RRE] */ ++ tmp2 = load_reg(r2); ++ tmp = tcg_const_i32(r1); ++ gen_helper_nabs_i64(cc, tmp, tmp2); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ break; ++ case 2: /* LTGR R1,R2 [RRE] */ ++ tmp = load_reg(r2); ++ if (r1 != r2) store_reg(r1, tmp); ++ set_cc_s64(tmp); ++ tcg_temp_free(tmp); ++ break; ++ case 3: /* LCGR R1,R2 [RRE] */ ++ case 0x13: /* LCGFR R1,R2 [RRE] */ ++ if (op == 0x13) { ++ tmp = load_reg32(r2); ++ tcg_gen_ext32s_i64(tmp, tmp); ++ } ++ else { ++ tmp = load_reg(r2); ++ } ++ tcg_gen_neg_i64(tmp, tmp); ++ store_reg(r1, tmp); ++ gen_helper_set_cc_comp_s64(cc, tmp); ++ tcg_temp_free(tmp); ++ break; ++ case 4: /* LGR R1,R2 [RRE] */ ++ tmp = load_reg(r2); ++ store_reg(r1, tmp); ++ tcg_temp_free(tmp); ++ break; ++ case 0x6: /* LGBR R1,R2 [RRE] */ ++ tmp2 = load_reg(r2); ++ tcg_gen_ext8s_i64(tmp2, tmp2); ++ store_reg(r1, tmp2); ++ tcg_temp_free(tmp2); ++ break; ++ case 8: /* AGR R1,R2 [RRE] */ ++ case 0xa: /* ALGR R1,R2 [RRE] */ ++ tmp = load_reg(r1); ++ tmp2 = load_reg(r2); ++ tmp3 = tcg_temp_new_i64(); ++ tcg_gen_add_i64(tmp3, tmp, tmp2); ++ store_reg(r1, tmp3); ++ switch (op) { ++ case 0x8: gen_set_cc_add64(tmp, tmp2, tmp3); break; ++ case 0xa: gen_helper_set_cc_addu64(cc, tmp, tmp2, tmp3); break; ++ default: tcg_abort(); ++ } ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 9: /* SGR R1,R2 [RRE] */ ++ case 0xb: /* SLGR R1,R2 [RRE] */ ++ case 0x1b: /* SLGFR R1,R2 [RRE] */ ++ case 0x19: /* SGFR R1,R2 [RRE] */ ++ tmp = load_reg(r1); ++ switch (op) { ++ case 0x1b: case 0x19: ++ tmp2 = load_reg32(r2); ++ if (op == 0x19) tcg_gen_ext32s_i64(tmp2, tmp2); ++ else tcg_gen_ext32u_i64(tmp2, tmp2); ++ break; ++ default: ++ tmp2 = load_reg(r2); ++ break; ++ } ++ tmp3 = tcg_temp_new_i64(); ++ tcg_gen_sub_i64(tmp3, tmp, tmp2); ++ store_reg(r1, tmp3); ++ switch (op) { ++ case 9: case 0x19: gen_helper_set_cc_sub64(cc, tmp,tmp2,tmp3); break; ++ case 0xb: case 0x1b: gen_helper_set_cc_subu64(cc, tmp, tmp2, tmp3); break; ++ default: tcg_abort(); ++ } ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0xc: /* MSGR R1,R2 [RRE] */ ++ case 0x1c: /* MSGFR R1,R2 [RRE] */ ++ tmp = load_reg(r1); ++ tmp2 = load_reg(r2); ++ if (op == 0x1c) tcg_gen_ext32s_i64(tmp2, tmp2); ++ tcg_gen_mul_i64(tmp, tmp, tmp2); ++ store_reg(r1, tmp); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ break; ++ case 0xd: /* DSGR R1,R2 [RRE] */ ++ case 0x1d: /* DSGFR R1,R2 [RRE] */ ++ tmp = load_reg(r1 + 1); ++ if (op == 0xd) { ++ tmp2 = load_reg(r2); ++ } ++ else { ++ tmp2 = load_reg32(r2); ++ tcg_gen_ext32s_i64(tmp2, tmp2); ++ } ++ tmp3 = tcg_temp_new_i64(); ++ tcg_gen_div_i64(tmp3, tmp, tmp2); ++ store_reg(r1 + 1, tmp3); ++ tcg_gen_rem_i64(tmp3, tmp, tmp2); ++ store_reg(r1, tmp3); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x14: /* LGFR R1,R2 [RRE] */ ++ tmp = load_reg32(r2); ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_ext32s_i64(tmp2, tmp); ++ store_reg(r1, tmp2); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x16: /* LLGFR R1,R2 [RRE] */ ++ tmp = load_reg32(r2); ++ tcg_gen_ext32u_i64(tmp, tmp); ++ store_reg(r1, tmp); ++ tcg_temp_free(tmp); ++ break; ++ case 0x17: /* LLGTR R1,R2 [RRE] */ ++ tmp = load_reg32(r2); ++ tcg_gen_andi_i64(tmp, tmp, 0x7fffffffUL); ++ tcg_gen_ext32u_i64(tmp, tmp); ++ store_reg(r1, tmp); ++ tcg_temp_free(tmp); ++ break; ++ case 0x18: /* AGFR R1,R2 [RRE] */ ++ case 0x1a: /* ALGFR R1,R2 [RRE] */ ++ tmp2 = load_reg32(r2); ++ switch (op) { ++ case 0x18: tcg_gen_ext32s_i64(tmp2, tmp2); break; ++ case 0x1a: tcg_gen_ext32u_i64(tmp2, tmp2); break; ++ default: tcg_abort(); ++ } ++ tmp = load_reg(r1); ++ tmp3 = tcg_temp_new_i64(); ++ tcg_gen_add_i64(tmp3, tmp, tmp2); ++ store_reg(r1, tmp3); ++ switch (op) { ++ case 0x18: gen_set_cc_add64(tmp, tmp2, tmp3); break; ++ case 0x1a: gen_helper_set_cc_addu64(cc, tmp, tmp2, tmp3); break; ++ default: tcg_abort(); ++ } ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x20: /* CGR R1,R2 [RRE] */ ++ case 0x30: /* CGFR R1,R2 [RRE] */ ++ tmp2 = load_reg(r2); ++ if (op == 0x30) tcg_gen_ext32s_i64(tmp2, tmp2); ++ tmp = load_reg(r1); ++ cmp_s64(tmp, tmp2); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x21: /* CLGR R1,R2 [RRE] */ ++ case 0x31: /* CLGFR R1,R2 [RRE] */ ++ tmp2 = load_reg(r2); ++ if (op == 0x31) tcg_gen_ext32u_i64(tmp2, tmp2); ++ tmp = load_reg(r1); ++ cmp_u64(tmp, tmp2); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x26: /* LBR R1,R2 [RRE] */ ++ tmp2 = load_reg32(r2); ++ tcg_gen_ext8s_i32(tmp2, tmp2); ++ store_reg32(r1, tmp2); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x27: /* LHR R1,R2 [RRE] */ ++ tmp2 = load_reg32(r2); ++ tcg_gen_ext16s_i32(tmp2, tmp2); ++ store_reg32(r1, tmp2); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x80: /* NGR R1,R2 [RRE] */ ++ case 0x81: /* OGR R1,R2 [RRE] */ ++ case 0x82: /* XGR R1,R2 [RRE] */ ++ tmp = load_reg(r1); ++ tmp2 = load_reg(r2); ++ switch (op) { ++ case 0x80: tcg_gen_and_i64(tmp, tmp, tmp2); break; ++ case 0x81: tcg_gen_or_i64(tmp, tmp, tmp2); break; ++ case 0x82: tcg_gen_xor_i64(tmp, tmp, tmp2); break; ++ default: tcg_abort(); ++ } ++ store_reg(r1, tmp); ++ set_cc_nz_u64(tmp); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x83: /* FLOGR R1,R2 [RRE] */ ++ tmp2 = load_reg(r2); ++ tmp = tcg_const_i32(r1); ++ gen_helper_flogr(cc, tmp, tmp2); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x84: /* LLGCR R1,R2 [RRE] */ ++ tmp = load_reg(r2); ++ tcg_gen_andi_i64(tmp, tmp, 0xff); ++ store_reg(r1, tmp); ++ tcg_temp_free(tmp); ++ break; ++ case 0x85: /* LLGHR R1,R2 [RRE] */ ++ tmp = load_reg(r2); ++ tcg_gen_andi_i64(tmp, tmp, 0xffff); ++ store_reg(r1, tmp); ++ tcg_temp_free(tmp); ++ break; ++ case 0x87: /* DLGR R1,R2 [RRE] */ ++ tmp = tcg_const_i32(r1); ++ tmp2 = load_reg(r2); ++ gen_helper_dlg(tmp, tmp2); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x88: /* ALCGR R1,R2 [RRE] */ ++ tmp = load_reg(r1); ++ tmp2 = load_reg(r2); ++ tmp3 = tcg_temp_new_i64(); ++ tcg_gen_shri_i64(tmp3, cc, 1); ++ tcg_gen_andi_i64(tmp3, tmp3, 1); ++ tcg_gen_add_i64(tmp3, tmp2, tmp3); ++ tcg_gen_add_i64(tmp3, tmp, tmp3); ++ store_reg(r1, tmp3); ++ gen_helper_set_cc_addc_u64(cc, tmp, tmp2, tmp3); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x89: /* SLBGR R1,R2 [RRE] */ ++ tmp = load_reg(r1); ++ tmp2 = load_reg(r2); ++ tmp3 = tcg_const_i32(r1); ++ gen_helper_slbg(cc, cc, tmp3, tmp, tmp2); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x94: /* LLCR R1,R2 [RRE] */ ++ tmp = load_reg32(r2); ++ tcg_gen_andi_i32(tmp, tmp, 0xff); ++ store_reg32(r1, tmp); ++ tcg_temp_free(tmp); ++ break; ++ case 0x95: /* LLHR R1,R2 [RRE] */ ++ tmp = load_reg32(r2); ++ tcg_gen_andi_i32(tmp, tmp, 0xffff); ++ store_reg32(r1, tmp); ++ tcg_temp_free(tmp); ++ break; ++ case 0x98: /* ALCR R1,R2 [RRE] */ ++ tmp = tcg_const_i32(r1); ++ tmp2 = load_reg32(r2); ++ gen_helper_addc_u32(cc, cc, tmp, tmp2); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x99: /* SLBR R1,R2 [RRE] */ ++ tmp = load_reg32(r1); ++ tmp2 = load_reg32(r2); ++ tmp3 = tcg_const_i32(r1); ++ gen_helper_slb(cc, cc, tmp3, tmp, tmp2); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ default: ++ LOG_DISAS("illegal b9 operation 0x%x\n", op); ++ gen_illegal_opcode(s); ++ break; ++ } ++} ++ ++static void disas_c0(DisasContext *s, int op, int r1, int i2) ++{ ++ TCGv tmp, tmp2, tmp3; ++ LOG_DISAS("disas_c0: op 0x%x r1 %d i2 %d\n", op, r1, i2); ++ uint64_t target = s->pc + i2 * 2; ++ /* FIXME: huh? */ target &= 0xffffffff; ++ switch (op) { ++ case 0: /* larl r1, i2 */ ++ tmp = tcg_const_i64(target); ++ store_reg(r1, tmp); ++ tcg_temp_free(tmp); ++ break; ++ case 0x1: /* LGFI R1,I2 [RIL] */ ++ tmp = tcg_const_i64((int64_t)i2); ++ store_reg(r1, tmp); ++ tcg_temp_free(tmp); ++ break; ++ case 0x4: /* BRCL M1,I2 [RIL] */ ++ tmp = tcg_const_i32(r1); /* aka m1 */ ++ tmp2 = tcg_const_i64(s->pc); ++ tmp3 = tcg_const_i64(i2 * 2); ++ gen_helper_brcl(cc, tmp, tmp2, tmp3); ++ s->is_jmp = DISAS_JUMP; ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x5: /* brasl r1, i2 */ ++ tmp = tcg_const_i64(s->pc + 6); ++ store_reg(r1, tmp); ++ tmp = tcg_const_i64(target); ++ tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUState, psw.addr)); ++ s->is_jmp = DISAS_JUMP; ++ tcg_temp_free(tmp); ++ break; ++ case 0x7: /* XILF R1,I2 [RIL] */ ++ case 0xb: /* NILF R1,I2 [RIL] */ ++ case 0xd: /* OILF R1,I2 [RIL] */ ++ tmp = load_reg32(r1); ++ switch (op) { ++ case 0x7: tcg_gen_xori_i32(tmp, tmp, (uint32_t)i2); break; ++ case 0xb: tcg_gen_andi_i32(tmp, tmp, (uint32_t)i2); break; ++ case 0xd: tcg_gen_ori_i32(tmp, tmp, (uint32_t)i2); break; ++ default: tcg_abort(); ++ } ++ store_reg32(r1, tmp); ++ tcg_gen_trunc_i64_i32(tmp, tmp); ++ set_cc_nz_u32(tmp); ++ tcg_temp_free(tmp); ++ break; ++ case 0x9: /* IILF R1,I2 [RIL] */ ++ tmp = tcg_const_i32((uint32_t)i2); ++ store_reg32(r1, tmp); ++ tcg_temp_free(tmp); ++ break; ++ case 0xa: /* NIHF R1,I2 [RIL] */ ++ tmp = load_reg(r1); ++ switch (op) { ++ case 0xa: tcg_gen_andi_i64(tmp, tmp, (((uint64_t)((uint32_t)i2)) << 32) | 0xffffffffULL); break; ++ default: tcg_abort(); ++ } ++ store_reg(r1, tmp); ++ tcg_gen_shr_i64(tmp, tmp, 32); ++ tcg_gen_trunc_i64_i32(tmp, tmp); ++ set_cc_nz_u32(tmp); ++ tcg_temp_free(tmp); ++ break; ++ case 0xe: /* LLIHF R1,I2 [RIL] */ ++ tmp = tcg_const_i64(((uint64_t)(uint32_t)i2) << 32); ++ store_reg(r1, tmp); ++ tcg_temp_free(tmp); ++ break; ++ case 0xf: /* LLILF R1,I2 [RIL] */ ++ tmp = tcg_const_i64((uint32_t)i2); ++ store_reg(r1, tmp); ++ tcg_temp_free(tmp); ++ break; ++ default: ++ LOG_DISAS("illegal c0 operation 0x%x\n", op); ++ gen_illegal_opcode(s); ++ break; ++ } ++} ++ ++static void disas_c2(DisasContext *s, int op, int r1, int i2) ++{ ++ TCGv tmp, tmp2, tmp3; ++ switch (op) { ++ case 0x4: /* SLGFI R1,I2 [RIL] */ ++ case 0xa: /* ALGFI R1,I2 [RIL] */ ++ tmp = load_reg(r1); ++ tmp2 = tcg_const_i64((uint64_t)(uint32_t)i2); ++ tmp3 = tcg_temp_new_i64(); ++ switch (op) { ++ case 0x4: ++ tcg_gen_sub_i64(tmp3, tmp, tmp2); ++ gen_helper_set_cc_subu64(cc, tmp, tmp2, tmp3); ++ break; ++ case 0xa: ++ tcg_gen_add_i64(tmp3, tmp, tmp2); ++ gen_helper_set_cc_addu64(cc, tmp, tmp2, tmp3); ++ break; ++ default: tcg_abort(); ++ } ++ store_reg(r1, tmp3); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0x5: /* SLFI R1,I2 [RIL] */ ++ case 0xb: /* ALFI R1,I2 [RIL] */ ++ tmp = load_reg32(r1); ++ tmp2 = tcg_const_i32(i2); ++ tmp3 = tcg_temp_new_i32(); ++ switch (op) { ++ case 0x5: ++ tcg_gen_sub_i32(tmp3, tmp, tmp2); ++ gen_helper_set_cc_subu32(cc, tmp, tmp2, tmp3); ++ break; ++ case 0xb: ++ tcg_gen_add_i32(tmp3, tmp, tmp2); ++ gen_helper_set_cc_addu32(cc, tmp, tmp2, tmp3); ++ break; ++ default: tcg_abort(); ++ } ++ store_reg32(r1, tmp3); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ break; ++ case 0xc: /* CGFI R1,I2 [RIL] */ ++ tmp = load_reg(r1); ++ cmp_s64c(tmp, (int64_t)i2); ++ tcg_temp_free(tmp); ++ break; ++ case 0xe: /* CLGFI R1,I2 [RIL] */ ++ tmp = load_reg(r1); ++ cmp_u64c(tmp, (uint64_t)(uint32_t)i2); ++ tcg_temp_free(tmp); ++ break; ++ case 0xd: /* CFI R1,I2 [RIL] */ ++ case 0xf: /* CLFI R1,I2 [RIL] */ ++ tmp = load_reg32(r1); ++ switch (op) { ++ case 0xd: cmp_s32c(tmp, i2); break; ++ case 0xf: cmp_u32c(tmp, i2); break; ++ default: tcg_abort(); ++ } ++ tcg_temp_free(tmp); ++ break; ++ default: ++ LOG_DISAS("illegal c2 operation 0x%x\n", op); ++ gen_illegal_opcode(s); ++ break; ++ } ++} ++ ++static inline uint64_t ld_code2(uint64_t pc) ++{ ++ return (uint64_t)lduw_code(pc); ++} ++ ++static inline uint64_t ld_code4(uint64_t pc) ++{ ++ return (uint64_t)ldl_code(pc); ++} ++ ++static inline uint64_t ld_code6(uint64_t pc) ++{ ++ uint64_t opc; ++ opc = (uint64_t)lduw_code(pc) << 32; ++ opc |= (uint64_t)(unsigned int)ldl_code(pc+2); ++ return opc; ++} ++ ++static void disas_s390_insn(CPUState *env, DisasContext *s) ++{ ++ TCGv tmp, tmp2, tmp3; ++ unsigned char opc; ++ uint64_t insn; ++ int op, r1, r2, r3, d1, d2, x2, b1, b2, i, i2, r1b; ++ TCGv vl, vd1, vd2, vb; ++ ++ opc = ldub_code(s->pc); ++ LOG_DISAS("opc 0x%x\n", opc); ++ ++#define FETCH_DECODE_RR \ ++ insn = ld_code2(s->pc); \ ++ DEBUGINSN \ ++ r1 = (insn >> 4) & 0xf; \ ++ r2 = insn & 0xf; ++ ++#define FETCH_DECODE_RX \ ++ insn = ld_code4(s->pc); \ ++ DEBUGINSN \ ++ r1 = (insn >> 20) & 0xf; \ ++ x2 = (insn >> 16) & 0xf; \ ++ b2 = (insn >> 12) & 0xf; \ ++ d2 = insn & 0xfff; \ ++ tmp = get_address(x2, b2, d2); ++ ++#define FREE_RX \ ++ tcg_temp_free(tmp); ++ ++#define FETCH_DECODE_RS \ ++ insn = ld_code4(s->pc); \ ++ DEBUGINSN \ ++ r1 = (insn >> 20) & 0xf; \ ++ r3 = (insn >> 16) & 0xf; /* aka m3 */ \ ++ b2 = (insn >> 12) & 0xf; \ ++ d2 = insn & 0xfff; ++ ++#define FETCH_DECODE_SI \ ++ insn = ld_code4(s->pc); \ ++ i2 = (insn >> 16) & 0xff; \ ++ b1 = (insn >> 12) & 0xf; \ ++ d1 = insn & 0xfff; \ ++ tmp = get_address(0, b1, d1); ++ ++#define FREE_SI \ ++ tcg_temp_free(tmp); ++ ++ switch (opc) { ++ case 0x7: /* BCR M1,R2 [RR] */ ++ FETCH_DECODE_RR ++ if (r2) { ++ gen_bcr(r1, r2, s->pc); ++ s->is_jmp = DISAS_JUMP; ++ } ++ else { ++ /* FIXME: "serialization and checkpoint-synchronization function"? */ ++ } ++ s->pc += 2; ++ break; ++ case 0xa: /* SVC I [RR] */ ++ insn = ld_code2(s->pc); ++ DEBUGINSN ++ i = insn & 0xff; ++ tmp = tcg_const_i64(s->pc); ++ tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUState, psw.addr)); ++ tcg_temp_free(tmp); ++ s->is_jmp = DISAS_SVC; ++ s->pc += 2; ++ break; ++ case 0xd: /* BASR R1,R2 [RR] */ ++ FETCH_DECODE_RR ++ tmp = tcg_const_i64(s->pc + 2); ++ store_reg(r1, tmp); ++ if (r2) { ++ tmp2 = load_reg(r2); ++ tcg_gen_st_i64(tmp2, cpu_env, offsetof(CPUState, psw.addr)); ++ tcg_temp_free(tmp2); ++ s->is_jmp = DISAS_JUMP; ++ } ++ tcg_temp_free(tmp); ++ s->pc += 2; ++ break; ++ case 0x10: /* LPR R1,R2 [RR] */ ++ FETCH_DECODE_RR ++ tmp2 = load_reg32(r2); ++ tmp = tcg_const_i32(r1); ++ gen_helper_abs_i32(cc, tmp, tmp2); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ s->pc += 2; ++ break; ++ case 0x11: /* LNR R1,R2 [RR] */ ++ FETCH_DECODE_RR ++ tmp2 = load_reg32(r2); ++ tmp = tcg_const_i32(r1); ++ gen_helper_nabs_i32(cc, tmp, tmp2); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ s->pc += 2; ++ break; ++ case 0x12: /* LTR R1,R2 [RR] */ ++ FETCH_DECODE_RR ++ tmp = load_reg32(r2); ++ if (r1 != r2) store_reg32(r1, tmp); ++ set_cc_s32(tmp); ++ tcg_temp_free(tmp); ++ s->pc += 2; ++ break; ++ case 0x13: /* LCR R1,R2 [RR] */ ++ FETCH_DECODE_RR ++ tmp = load_reg32(r2); ++ tcg_gen_neg_i32(tmp, tmp); ++ store_reg32(r1, tmp); ++ gen_helper_set_cc_comp_s32(cc, tmp); ++ tcg_temp_free(tmp); ++ s->pc += 2; ++ break; ++ case 0x14: /* NR R1,R2 [RR] */ ++ case 0x16: /* OR R1,R2 [RR] */ ++ case 0x17: /* XR R1,R2 [RR] */ ++ FETCH_DECODE_RR ++ tmp2 = load_reg32(r2); ++ tmp = load_reg32(r1); ++ switch (opc) { ++ case 0x14: tcg_gen_and_i32(tmp, tmp, tmp2); break; ++ case 0x16: tcg_gen_or_i32(tmp, tmp, tmp2); break; ++ case 0x17: tcg_gen_xor_i32(tmp, tmp, tmp2); break; ++ default: tcg_abort(); ++ } ++ store_reg32(r1, tmp); ++ set_cc_nz_u32(tmp); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ s->pc += 2; ++ break; ++ case 0x18: /* LR R1,R2 [RR] */ ++ FETCH_DECODE_RR ++ tmp = load_reg32(r2); ++ store_reg32(r1, tmp); ++ tcg_temp_free(tmp); ++ s->pc += 2; ++ break; ++ case 0x15: /* CLR R1,R2 [RR] */ ++ case 0x19: /* CR R1,R2 [RR] */ ++ FETCH_DECODE_RR ++ tmp = load_reg32(r1); ++ tmp2 = load_reg32(r2); ++ switch (opc) { ++ case 0x15: cmp_u32(tmp, tmp2); break; ++ case 0x19: cmp_s32(tmp, tmp2); break; ++ default: tcg_abort(); ++ } ++ s->pc += 2; ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x1a: /* AR R1,R2 [RR] */ ++ case 0x1e: /* ALR R1,R2 [RR] */ ++ FETCH_DECODE_RR ++ tmp = load_reg32(r1); ++ tmp2 = load_reg32(r2); ++ tmp3 = tcg_temp_new_i32(); ++ tcg_gen_add_i32(tmp3, tmp, tmp2); ++ store_reg32(r1, tmp3); ++ switch (opc) { ++ case 0x1a: gen_helper_set_cc_add32(cc, tmp, tmp2, tmp3); break; ++ case 0x1e: gen_helper_set_cc_addu32(cc, tmp, tmp2, tmp3); break; ++ default: tcg_abort(); ++ } ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ s->pc += 2; ++ break; ++ case 0x1b: /* SR R1,R2 [RR] */ ++ case 0x1f: /* SLR R1,R2 [RR] */ ++ FETCH_DECODE_RR ++ tmp = load_reg32(r1); ++ tmp2 = load_reg32(r2); ++ tmp3 = tcg_temp_new_i32(); ++ tcg_gen_sub_i32(tmp3, tmp, tmp2); ++ store_reg32(r1, tmp3); ++ switch (opc) { ++ case 0x1b: gen_helper_set_cc_sub32(cc, tmp, tmp2, tmp3); break; ++ case 0x1f: gen_helper_set_cc_subu32(cc, tmp, tmp2, tmp3); break; ++ default: tcg_abort(); ++ } ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ s->pc += 2; ++ break; ++ case 0x28: /* LDR R1,R2 [RR] */ ++ FETCH_DECODE_RR ++ tmp = load_freg(r2); ++ store_freg(r1, tmp); ++ tcg_temp_free(tmp); ++ s->pc += 2; ++ break; ++ case 0x38: /* LER R1,R2 [RR] */ ++ FETCH_DECODE_RR ++ tmp = load_freg32(r2); ++ store_freg32(r1, tmp); ++ tcg_temp_free(tmp); ++ s->pc += 2; ++ break; ++ case 0x40: /* STH R1,D2(X2,B2) [RX] */ ++ FETCH_DECODE_RX ++ tmp2 = load_reg32(r1); ++ tcg_gen_qemu_st16(tmp2, tmp, 1); ++ FREE_RX ++ tcg_temp_free(tmp2); ++ s->pc += 4; ++ break; ++ case 0x41: /* la */ ++ FETCH_DECODE_RX ++ store_reg(r1, tmp); /* FIXME: 31/24-bit addressing */ ++ FREE_RX ++ s->pc += 4; ++ break; ++ case 0x42: /* STC R1,D2(X2,B2) [RX] */ ++ FETCH_DECODE_RX ++ tmp2 = load_reg32(r1); ++ tcg_gen_qemu_st8(tmp2, tmp, 1); ++ FREE_RX ++ tcg_temp_free(tmp2); ++ s->pc += 4; ++ break; ++ case 0x43: /* IC R1,D2(X2,B2) [RX] */ ++ FETCH_DECODE_RX ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld8u(tmp2, tmp, 1); ++ store_reg8(r1, tmp2); ++ FREE_RX ++ tcg_temp_free(tmp2); ++ s->pc += 4; ++ break; ++ case 0x44: /* EX R1,D2(X2,B2) [RX] */ ++ FETCH_DECODE_RX ++ tmp2 = load_reg(r1); ++ tmp3 = tcg_const_i64(s->pc + 4); ++ gen_helper_ex(cc, cc, tmp2, tmp, tmp3); ++ FREE_RX ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ s->pc += 4; ++ break; ++ case 0x47: /* BC M1,D2(X2,B2) [RX] */ ++ FETCH_DECODE_RX ++ /* FIXME: optimize m1 == 0xf (unconditional) case */ ++ tmp2 = tcg_const_i32(r1); /* aka m1 */ ++ tmp3 = tcg_const_i64(s->pc); ++ gen_helper_bc(cc, tmp2, tmp, tmp3); ++ FREE_RX ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ s->is_jmp = DISAS_JUMP; ++ s->pc += 4; ++ break; ++ case 0x48: /* LH R1,D2(X2,B2) [RX] */ ++ FETCH_DECODE_RX ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld16s(tmp2, tmp, 1); ++ store_reg32(r1, tmp2); ++ FREE_RX ++ tcg_temp_free(tmp2); ++ s->pc += 4; ++ break; ++ case 0x49: /* CH R1,D2(X2,B2) [RX] */ ++ FETCH_DECODE_RX ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld16s(tmp2, tmp, 1); ++ FREE_RX ++ tmp = load_reg32(r1); ++ cmp_s32(tmp, tmp2); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ s->pc += 4; ++ break; ++ case 0x4a: /* AH R1,D2(X2,B2) [RX] */ ++ case 0x4b: /* SH R1,D2(X2,B2) [RX] */ ++ case 0x4c: /* MH R1,D2(X2,B2) [RX] */ ++ FETCH_DECODE_RX ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld16s(tmp2, tmp, 1); ++ FREE_RX ++ tmp = load_reg32(r1); ++ tmp3 = tcg_temp_new_i32(); ++ switch (opc) { ++ case 0x4a: ++ tcg_gen_add_i32(tmp3, tmp, tmp2); ++ gen_helper_set_cc_add32(cc, tmp, tmp2, tmp3); ++ break; ++ case 0x4b: ++ tcg_gen_sub_i32(tmp3, tmp, tmp2); ++ gen_helper_set_cc_sub32(cc, tmp, tmp2, tmp3); ++ break; ++ case 0x4c: ++ tcg_gen_mul_i32(tmp3, tmp, tmp2); ++ break; ++ default: tcg_abort(); ++ } ++ store_reg32(r1, tmp3); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ s->pc += 4; ++ break; ++ case 0x50: /* st r1, d2(x2, b2) */ ++ FETCH_DECODE_RX ++ tmp2 = load_reg32(r1); ++ tcg_gen_qemu_st32(tmp2, tmp, 1); ++ s->pc += 4; ++ FREE_RX ++ tcg_temp_free(tmp2); ++ break; ++ case 0x55: /* CL R1,D2(X2,B2) [RX] */ ++ FETCH_DECODE_RX ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld32u(tmp2, tmp, 1); ++ FREE_RX ++ tmp = load_reg32(r1); ++ cmp_u32(tmp, tmp2); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ s->pc += 4; ++ break; ++ case 0x54: /* N R1,D2(X2,B2) [RX] */ ++ case 0x56: /* O R1,D2(X2,B2) [RX] */ ++ case 0x57: /* X R1,D2(X2,B2) [RX] */ ++ FETCH_DECODE_RX ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld32u(tmp2, tmp, 1); ++ FREE_RX ++ tmp = load_reg32(r1); ++ switch (opc) { ++ case 0x54: tcg_gen_and_i32(tmp, tmp, tmp2); break; ++ case 0x56: tcg_gen_or_i32(tmp, tmp, tmp2); break; ++ case 0x57: tcg_gen_xor_i32(tmp, tmp, tmp2); break; ++ default: tcg_abort(); ++ } ++ store_reg32(r1, tmp); ++ set_cc_nz_u32(tmp); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ s->pc += 4; ++ break; ++ case 0x58: /* l r1, d2(x2, b2) */ ++ FETCH_DECODE_RX ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld32u(tmp2, tmp, 1); ++ store_reg32(r1, tmp2); ++ FREE_RX ++ tcg_temp_free(tmp2); ++ s->pc += 4; ++ break; ++ case 0x59: /* C R1,D2(X2,B2) [RX] */ ++ FETCH_DECODE_RX ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld32s(tmp2, tmp, 1); ++ FREE_RX ++ tmp = load_reg32(r1); ++ cmp_s32(tmp, tmp2); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ s->pc += 4; ++ break; ++ case 0x5a: /* A R1,D2(X2,B2) [RX] */ ++ case 0x5b: /* S R1,D2(X2,B2) [RX] */ ++ case 0x5e: /* AL R1,D2(X2,B2) [RX] */ ++ case 0x5f: /* SL R1,D2(X2,B2) [RX] */ ++ FETCH_DECODE_RX ++ tmp2 = load_reg32(r1); ++ tcg_gen_qemu_ld32s(tmp, tmp, 1); ++ tmp3 = tcg_temp_new_i32(); ++ switch (opc) { ++ case 0x5a: case 0x5e: tcg_gen_add_i32(tmp3, tmp2, tmp); break; ++ case 0x5b: case 0x5f: tcg_gen_sub_i32(tmp3, tmp2, tmp); break; ++ default: tcg_abort(); ++ } ++ store_reg32(r1, tmp3); ++ switch (opc) { ++ case 0x5a: gen_helper_set_cc_add32(cc, tmp2, tmp, tmp3); break; ++ case 0x5e: gen_helper_set_cc_addu32(cc, tmp2, tmp, tmp3); break; ++ case 0x5b: gen_helper_set_cc_sub32(cc, tmp2, tmp, tmp3); break; ++ case 0x5f: gen_helper_set_cc_subu32(cc, tmp2, tmp, tmp3); break; ++ default: tcg_abort(); ++ } ++ FREE_RX ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ s->pc += 4; ++ break; ++ case 0x60: /* STD R1,D2(X2,B2) [RX] */ ++ FETCH_DECODE_RX ++ tmp2 = load_freg(r1); ++ tcg_gen_qemu_st64(tmp2, tmp, 1); ++ FREE_RX ++ tcg_temp_free(tmp2); ++ s->pc += 4; ++ break; ++ case 0x68: /* LD R1,D2(X2,B2) [RX] */ ++ FETCH_DECODE_RX ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld64(tmp2, tmp, 1); ++ store_freg(r1, tmp2); ++ FREE_RX ++ tcg_temp_free(tmp2); ++ s->pc += 4; ++ break; ++ case 0x70: /* STE R1,D2(X2,B2) [RX] */ ++ FETCH_DECODE_RX ++ tmp2 = load_freg32(r1); ++ tcg_gen_qemu_st32(tmp2, tmp, 1); ++ FREE_RX ++ tcg_temp_free(tmp2); ++ s->pc += 4; ++ break; ++ case 0x71: /* MS R1,D2(X2,B2) [RX] */ ++ FETCH_DECODE_RX ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld32s(tmp2, tmp, 1); ++ FREE_RX ++ tmp = load_reg(r1); ++ tcg_gen_mul_i32(tmp, tmp, tmp2); ++ store_reg(r1, tmp); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ s->pc += 4; ++ break; ++ case 0x78: /* LE R1,D2(X2,B2) [RX] */ ++ FETCH_DECODE_RX ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld32u(tmp2, tmp, 1); ++ store_freg32(r1, tmp2); ++ FREE_RX ++ tcg_temp_free(tmp2); ++ s->pc += 4; ++ break; ++ case 0x88: /* SRL R1,D2(B2) [RS] */ ++ case 0x89: /* SLL R1,D2(B2) [RS] */ ++ case 0x8a: /* SRA R1,D2(B2) [RS] */ ++ FETCH_DECODE_RS ++ tmp = get_address(0, b2, d2); ++ tcg_gen_andi_i64(tmp, tmp, 0x3f); ++ tmp2 = load_reg32(r1); ++ switch (opc) { ++ case 0x88: tcg_gen_shr_i32(tmp2, tmp2, tmp); break; ++ case 0x89: tcg_gen_shl_i32(tmp2, tmp2, tmp); break; ++ case 0x8a: tcg_gen_sar_i32(tmp2, tmp2, tmp); break; ++ default: tcg_abort(); ++ } ++ store_reg32(r1, tmp2); ++ if (opc == 0x8a) set_cc_s32(tmp2); ++ s->pc += 4; ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ break; ++ case 0x91: /* TM D1(B1),I2 [SI] */ ++ FETCH_DECODE_SI ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld8u(tmp2, tmp, 1); ++ FREE_SI ++ tmp = tcg_const_i32(i2); ++ gen_helper_tm(cc, tmp2, tmp); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ s->pc += 4; ++ break; ++ case 0x92: /* MVI D1(B1),I2 [SI] */ ++ FETCH_DECODE_SI ++ tmp2 = tcg_const_i32(i2); ++ tcg_gen_qemu_st8(tmp2, tmp, 1); ++ FREE_SI ++ tcg_temp_free(tmp2); ++ s->pc += 4; ++ break; ++ case 0x94: /* NI D1(B1),I2 [SI] */ ++ case 0x96: /* OI D1(B1),I2 [SI] */ ++ case 0x97: /* XI D1(B1),I2 [SI] */ ++ FETCH_DECODE_SI ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld8u(tmp2, tmp, 1); ++ switch (opc) { ++ case 0x94: tcg_gen_andi_i32(tmp2, tmp2, i2); break; ++ case 0x96: tcg_gen_ori_i32(tmp2, tmp2, i2); break; ++ case 0x97: tcg_gen_xori_i32(tmp2, tmp2, i2); break; ++ default: tcg_abort(); ++ } ++ tcg_gen_qemu_st8(tmp2, tmp, 1); ++ set_cc_nz_u32(tmp2); ++ FREE_SI ++ tcg_temp_free(tmp2); ++ s->pc += 4; ++ break; ++ case 0x95: /* CLI D1(B1),I2 [SI] */ ++ FETCH_DECODE_SI ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld8u(tmp2, tmp, 1); ++ cmp_u32c(tmp2, i2); ++ FREE_SI ++ tcg_temp_free(tmp2); ++ s->pc += 4; ++ break; ++ case 0x9b: /* STAM R1,R3,D2(B2) [RS] */ ++ FETCH_DECODE_RS ++ tmp = tcg_const_i32(r1); ++ tmp2 = get_address(0, b2, d2); ++ tmp3 = tcg_const_i32(r3); ++ gen_helper_stam(tmp, tmp2, tmp3); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ s->pc += 4; ++ break; ++ case 0xa5: ++ insn = ld_code4(s->pc); ++ r1 = (insn >> 20) & 0xf; ++ op = (insn >> 16) & 0xf; ++ i2 = insn & 0xffff; ++ disas_a5(s, op, r1, i2); ++ s->pc += 4; ++ break; ++ case 0xa7: ++ insn = ld_code4(s->pc); ++ r1 = (insn >> 20) & 0xf; ++ op = (insn >> 16) & 0xf; ++ i2 = (short)insn; ++ disas_a7(s, op, r1, i2); ++ s->pc += 4; ++ break; ++ case 0xa8: /* MVCLE R1,R3,D2(B2) [RS] */ ++ FETCH_DECODE_RS ++ tmp = tcg_const_i32(r1); ++ tmp3 = tcg_const_i32(r3); ++ tmp2 = get_address(0, b2, d2); ++ gen_helper_mvcle(cc, tmp, tmp2, tmp3); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ s->pc += 4; ++ break; ++ case 0xa9: /* CLCLE R1,R3,D2(B2) [RS] */ ++ FETCH_DECODE_RS ++ tmp = tcg_const_i32(r1); ++ tmp3 = tcg_const_i32(r3); ++ tmp2 = get_address(0, b2, d2); ++ gen_helper_clcle(cc, tmp, tmp2, tmp3); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ s->pc += 4; ++ break; ++ case 0xb2: ++ insn = ld_code4(s->pc); ++ op = (insn >> 16) & 0xff; ++ switch (op) { ++ case 0x9c: /* STFPC D2(B2) [S] */ ++ d2 = insn & 0xfff; ++ b2 = (insn >> 12) & 0xf; ++ tmp = tcg_temp_new_i32(); ++ tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUState, fpc)); ++ tmp2 = get_address(0, b2, d2); ++ tcg_gen_qemu_st32(tmp, tmp2, 1); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ break; ++ default: ++ r1 = (insn >> 4) & 0xf; ++ r2 = insn & 0xf; ++ disas_b2(s, op, r1, r2); ++ break; ++ } ++ s->pc += 4; ++ break; ++ case 0xb3: ++ insn = ld_code4(s->pc); ++ op = (insn >> 16) & 0xff; ++ r3 = (insn >> 12) & 0xf; /* aka m3 */ ++ r1 = (insn >> 4) & 0xf; ++ r2 = insn & 0xf; ++ disas_b3(s, op, r3, r1, r2); ++ s->pc += 4; ++ break; ++ case 0xb9: ++ insn = ld_code4(s->pc); ++ r1 = (insn >> 4) & 0xf; ++ r2 = insn & 0xf; ++ op = (insn >> 16) & 0xff; ++ disas_b9(s, op, r1, r2); ++ s->pc += 4; ++ break; ++ case 0xba: /* CS R1,R3,D2(B2) [RS] */ ++ FETCH_DECODE_RS ++ tmp = tcg_const_i32(r1); ++ tmp2 = get_address(0, b2, d2); ++ tmp3 = tcg_const_i32(r3); ++ gen_helper_cs(cc, tmp, tmp2, tmp3); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ s->pc += 4; ++ break; ++ case 0xbd: /* CLM R1,M3,D2(B2) [RS] */ ++ FETCH_DECODE_RS ++ tmp3 = get_address(0, b2, d2); ++ tmp2 = tcg_const_i32(r3); /* aka m3 */ ++ tmp = load_reg32(r1); ++ gen_helper_clm(cc, tmp, tmp2, tmp3); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ s->pc += 4; ++ break; ++ case 0xbe: /* STCM R1,M3,D2(B2) [RS] */ ++ FETCH_DECODE_RS ++ tmp3 = get_address(0, b2, d2); ++ tmp2 = tcg_const_i32(r3); /* aka m3 */ ++ tmp = load_reg32(r1); ++ gen_helper_stcm(tmp, tmp2, tmp3); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ s->pc += 4; ++ break; ++ case 0xbf: /* ICM R1,M3,D2(B2) [RS] */ ++ FETCH_DECODE_RS ++ if (r3 == 15) { /* effectively a 32-bit load */ ++ tmp = get_address(0, b2, d2); ++ tmp2 = tcg_temp_new_i64(); ++ tcg_gen_qemu_ld32u(tmp2, tmp, 1); ++ store_reg32(r1, tmp2); ++ tcg_temp_free(tmp); ++ tmp = tcg_const_i32(r3); ++ gen_helper_set_cc_icm(cc, tmp, tmp2); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ } ++ else if (r3) { ++ uint32_t mask = 0x00ffffffUL; ++ uint32_t shift = 24; ++ int m3 = r3; ++ tmp3 = load_reg32(r1); ++ tmp = get_address(0, b2, d2); ++ tmp2 = tcg_temp_new_i64(); ++ while (m3) { ++ if (m3 & 8) { ++ tcg_gen_qemu_ld8u(tmp2, tmp, 1); ++ if (shift) tcg_gen_shli_i32(tmp2, tmp2, shift); ++ tcg_gen_andi_i32(tmp3, tmp3, mask); ++ tcg_gen_or_i32(tmp3, tmp3, tmp2); ++ tcg_gen_addi_i64(tmp, tmp, 1); ++ } ++ m3 = (m3 << 1) & 0xf; ++ mask = (mask >> 8) | 0xff000000UL; ++ shift -= 8; ++ } ++ store_reg32(r1, tmp3); ++ tcg_temp_free(tmp); ++ tmp = tcg_const_i32(r3); ++ gen_helper_set_cc_icm(cc, tmp, tmp2); ++ tcg_temp_free(tmp); ++ tcg_temp_free(tmp2); ++ tcg_temp_free(tmp3); ++ } ++ else { ++ tmp = tcg_const_i32(0); ++ gen_helper_set_cc_icm(cc, tmp, tmp); /* i.e. env->cc = 0 */ ++ tcg_temp_free(tmp); ++ } ++ s->pc += 4; ++ break; ++ case 0xc0: ++ case 0xc2: ++ insn = ld_code6(s->pc); ++ r1 = (insn >> 36) & 0xf; ++ op = (insn >> 32) & 0xf; ++ i2 = (int)insn; ++ switch (opc) { ++ case 0xc0: disas_c0(s, op, r1, i2); break; ++ case 0xc2: disas_c2(s, op, r1, i2); break; ++ default: tcg_abort(); ++ } ++ s->pc += 6; ++ break; ++ case 0xd2: /* mvc d1(l, b1), d2(b2) */ ++ case 0xd4: /* NC D1(L,B1),D2(B2) [SS] */ ++ case 0xd5: /* CLC D1(L,B1),D2(B2) [SS] */ ++ case 0xd6: /* OC D1(L,B1),D2(B2) [SS] */ ++ case 0xd7: /* xc d1(l, b1), d2(b2) */ ++ insn = ld_code6(s->pc); ++ vl = tcg_const_i32((insn >> 32) & 0xff); ++ b1 = (insn >> 28) & 0xf; ++ vd1 = tcg_const_i32((insn >> 16) & 0xfff); ++ b2 = (insn >> 12) & 0xf; ++ vd2 = tcg_const_i32(insn & 0xfff); ++ vb = tcg_const_i32((b1 << 4) | b2); ++ switch (opc) { ++ case 0xd2: gen_helper_mvc(vl, vb, vd1, vd2); break; ++ case 0xd4: gen_helper_nc(cc, vl, vb, vd1, vd2); break; ++ case 0xd5: gen_helper_clc(cc, vl, vb, vd1, vd2); break; ++ case 0xd6: gen_helper_oc(cc, vl, vb, vd1, vd2); break; ++ case 0xd7: gen_helper_xc(cc, vl, vb, vd1, vd2); break; ++ default: tcg_abort(); break; ++ } ++ s->pc += 6; ++ break; ++ case 0xe3: ++ insn = ld_code6(s->pc); ++ DEBUGINSN ++ d2 = ( (int) ( (((insn >> 16) & 0xfff) | ((insn << 4) & 0xff000)) << 12 ) ) >> 12; ++ disas_e3(s, /* op */ insn & 0xff, /* r1 */ (insn >> 36) & 0xf, /* x2 */ (insn >> 32) & 0xf, /* b2 */ (insn >> 28) & 0xf, d2 ); ++ s->pc += 6; ++ break; ++ case 0xeb: ++ insn = ld_code6(s->pc); ++ DEBUGINSN ++ op = insn & 0xff; ++ r1 = (insn >> 36) & 0xf; ++ r3 = (insn >> 32) & 0xf; ++ b2 = (insn >> 28) & 0xf; ++ d2 = ( (int) ( (((insn >> 16) & 0xfff) | ((insn << 4) & 0xff000)) << 12 ) ) >> 12; ++ disas_eb(s, op, r1, r3, b2, d2); ++ s->pc += 6; ++ break; ++ case 0xed: ++ insn = ld_code6(s->pc); ++ DEBUGINSN ++ op = insn & 0xff; ++ r1 = (insn >> 36) & 0xf; ++ x2 = (insn >> 32) & 0xf; ++ b2 = (insn >> 28) & 0xf; ++ d2 = (short)((insn >> 16) & 0xfff); ++ r1b = (insn >> 12) & 0xf; ++ disas_ed(s, op, r1, x2, b2, d2, r1b); ++ s->pc += 6; ++ break; ++ default: ++ LOG_DISAS("unimplemented opcode 0x%x\n", opc); ++ gen_illegal_opcode(s); ++ s->pc += 6; ++ break; ++ } ++} ++ ++static inline void gen_intermediate_code_internal (CPUState *env, ++ TranslationBlock *tb, ++ int search_pc) ++{ ++ DisasContext dc; ++ target_ulong pc_start; ++ uint64_t next_page_start; ++ uint16_t *gen_opc_end; ++ int j, lj = -1; ++ int num_insns, max_insns; ++ ++ pc_start = tb->pc; ++ ++ dc.pc = tb->pc; ++ dc.env = env; ++ dc.pc = pc_start; ++ dc.is_jmp = DISAS_NEXT; ++ ++ gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; ++ ++ next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; ++ ++ num_insns = 0; ++ max_insns = tb->cflags & CF_COUNT_MASK; ++ if (max_insns == 0) ++ max_insns = CF_COUNT_MASK; ++ ++ gen_icount_start(); ++#if 1 ++ cc = tcg_temp_local_new_i32(); ++ tcg_gen_mov_i32(cc, global_cc); ++#else ++ cc = global_cc; ++#endif ++ do { ++ if (search_pc) { ++ j = gen_opc_ptr - gen_opc_buf; ++ if (lj < j) { ++ lj++; ++ while (lj < j) ++ gen_opc_instr_start[lj++] = 0; ++ } ++ gen_opc_pc[lj] = dc.pc; ++ gen_opc_instr_start[lj] = 1; ++ gen_opc_icount[lj] = num_insns; ++ } ++ if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) ++ gen_io_start(); ++#if defined S390X_DEBUG_DISAS ++ LOG_DISAS("pc " TARGET_FMT_lx "\n", ++ dc.pc); ++#endif ++ disas_s390_insn(env, &dc); ++ ++ num_insns++; ++ } while (!dc.is_jmp && gen_opc_ptr < gen_opc_end && dc.pc < next_page_start ++ && num_insns < max_insns && !env->singlestep_enabled); ++ tcg_gen_mov_i32(global_cc, cc); ++ tcg_temp_free(cc); ++ ++ if (!dc.is_jmp) { ++ tcg_gen_st_i64(tcg_const_i64(dc.pc), cpu_env, offsetof(CPUState, psw.addr)); ++ } ++ ++ if (dc.is_jmp == DISAS_SVC) { ++ tcg_gen_st_i64(tcg_const_i64(dc.pc), cpu_env, offsetof(CPUState, psw.addr)); ++ TCGv tmp = tcg_const_i32(EXCP_SVC); ++ gen_helper_exception(tmp); ++ } ++ ++ if (tb->cflags & CF_LAST_IO) ++ gen_io_end(); ++ /* Generate the return instruction */ ++ tcg_gen_exit_tb(0); ++ gen_icount_end(tb, num_insns); ++ *gen_opc_ptr = INDEX_op_end; ++ if (search_pc) { ++ j = gen_opc_ptr - gen_opc_buf; ++ lj++; ++ while (lj <= j) ++ gen_opc_instr_start[lj++] = 0; ++ } else { ++ tb->size = dc.pc - pc_start; ++ tb->icount = num_insns; ++ } ++#if defined S390X_DEBUG_DISAS ++ log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0); ++ if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { ++ qemu_log("IN: %s\n", lookup_symbol(pc_start)); ++ log_target_disas(pc_start, dc.pc - pc_start, 1); ++ qemu_log("\n"); ++ } ++#endif ++} ++ + void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb) + { ++ gen_intermediate_code_internal(env, tb, 0); + } + + void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb) + { ++ gen_intermediate_code_internal(env, tb, 1); + } + + void gen_pc_load(CPUState *env, TranslationBlock *tb, +diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c +index 356b1a4..00954c7 100644 +--- a/tcg/s390/tcg-target.c ++++ b/tcg/s390/tcg-target.c +@@ -29,24 +29,109 @@ static const int tcg_target_call_iarg_regs[] = { + }; + + static const int tcg_target_call_oarg_regs[] = { ++#ifndef NDEBUG ++static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { ++ "%r0", ++ "%r1", ++ "%r2", ++ "%r3", ++ "%r4", ++ "%r5", ++ "%r6", ++ "%r7", ++ "%r8", ++ "%r9", ++ "%r10", ++ "%r11", ++ "%r12", ++ "%r13", ++ "%r14", ++ "%r15" ++}; ++#endif ++ ++static const int tcg_target_reg_alloc_order[] = { ++ TCG_REG_R6, ++ TCG_REG_R7, ++ TCG_REG_R8, ++ TCG_REG_R9, ++ TCG_REG_R10, ++ TCG_REG_R11, ++ TCG_REG_R12, ++ TCG_REG_R13, ++ TCG_REG_R14, ++ /* TCG_REG_R0, many insns can't be used with R0, so we better avoid it for now */ ++ TCG_REG_R1, ++ TCG_REG_R2, ++ TCG_REG_R3, ++ TCG_REG_R4, ++ TCG_REG_R5, ++}; ++ ++static const int tcg_target_call_iarg_regs[4] = { ++ TCG_REG_R2, TCG_REG_R3, TCG_REG_R4, TCG_REG_R5 ++}; ++static const int tcg_target_call_oarg_regs[2] = { ++ TCG_REG_R2, TCG_REG_R3 + }; + + static void patch_reloc(uint8_t *code_ptr, int type, + tcg_target_long value, tcg_target_long addend) + { +- tcg_abort(); ++ switch (type) { ++ case R_390_PC32DBL: ++ *(uint32_t*)code_ptr = (value - ((tcg_target_long)code_ptr + addend)) >> 1; ++ break; ++ default: ++ tcg_abort(); ++ break; ++ } + } + ++/* maximum number of register used for input function arguments */ + static inline int tcg_target_get_call_iarg_regs_count(int flags) + { +- tcg_abort(); +- return 0; ++ return 4; + } + ++#define TCG_CT_CONST_S16 0x100 ++#define TCG_CT_CONST_U12 0x200 ++ + /* parse target specific constraints */ + static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) + { +- tcg_abort(); ++ const char *ct_str; ++ ++ ct->ct |= TCG_CT_REG; ++ tcg_regset_set32(ct->u.regs, 0, 0xffff); ++ ct_str = *pct_str; ++ switch (ct_str[0]) { ++ case 'L': /* qemu_ld constraint */ ++ tcg_regset_reset_reg (ct->u.regs, TCG_REG_R2); ++#ifdef CONFIG_SOFTMMU ++ tcg_regset_reset_reg (ct->u.regs, TCG_REG_R3); ++#endif ++ break; ++ case 'S': /* qemu_st constraint */ ++ tcg_regset_reset_reg (ct->u.regs, TCG_REG_R2); ++#ifdef CONFIG_SOFTMMU ++ tcg_regset_reset_reg (ct->u.regs, TCG_REG_R3); ++ tcg_regset_reset_reg (ct->u.regs, TCG_REG_R4); ++#endif ++ break; ++ case 'R': /* not R0 */ ++ tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0); ++ break; ++ case 'I': ++ ct->ct &= ~TCG_CT_REG; ++ ct->ct |= TCG_CT_CONST_S16; ++ break; ++ default: ++ break; ++ } ++ ct_str++; ++ *pct_str = ct_str; ++ + return 0; + } + +@@ -54,49 +139,1010 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) + static inline int tcg_target_const_match(tcg_target_long val, + const TCGArgConstraint *arg_ct) + { +- tcg_abort(); ++ int ct; ++ ct = arg_ct->ct; ++ if (ct & TCG_CT_CONST) ++ return 1; ++ if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val) ++ return 1; ++ if ((ct & TCG_CT_CONST_U12) && val == (val & 0xfff)) ++ return 1; ++ + return 0; + } + ++#ifdef CONFIG_SOFTMMU ++ ++#include "../../softmmu_defs.h" ++ ++static void *qemu_ld_helpers[4] = { ++ __ldb_mmu, ++ __ldw_mmu, ++ __ldl_mmu, ++ __ldq_mmu, ++}; ++ ++static void *qemu_st_helpers[4] = { ++ __stb_mmu, ++ __stw_mmu, ++ __stl_mmu, ++ __stq_mmu, ++}; ++#endif ++ ++static uint8_t *tb_ret_addr; ++ ++/* signed/unsigned is handled by using COMPARE and COMPARE LOGICAL, ++ respectively */ ++static const uint8_t tcg_cond_to_s390_cond[10] = { ++ [TCG_COND_EQ] = 8, ++ [TCG_COND_LT] = 4, ++ [TCG_COND_LTU] = 4, ++ [TCG_COND_LE] = 8 | 4, ++ [TCG_COND_LEU] = 8 | 4, ++ [TCG_COND_GT] = 2, ++ [TCG_COND_GTU] = 2, ++ [TCG_COND_GE] = 8 | 2, ++ [TCG_COND_GEU] = 8 | 2, ++ [TCG_COND_NE] = 4 | 2 | 1, ++}; ++ ++/* emit load/store (and then some) instructions (E3 prefix) */ ++static inline void tcg_out_e3(TCGContext* s, int op, int r1, int r2, int disp) ++{ ++ tcg_out16(s, 0xe300 | (r1 << 4)); ++ tcg_out32(s, op | (r2 << 28) | ((disp & 0xfff) << 16) | ((disp >> 12) << 8)); ++} ++#define E3_LG 0x04 ++#define E3_LRVG 0x0f ++#define E3_LGF 0x14 ++#define E3_LGH 0x15 ++#define E3_LLGF 0x16 ++#define E3_LRV 0x1e ++#define E3_LRVH 0x1f ++#define E3_CG 0x20 ++#define E3_STG 0x24 ++#define E3_STRVG 0x2f ++#define E3_STRV 0x3e ++#define E3_STRVH 0x3f ++#define E3_STHY 0x70 ++#define E3_STCY 0x72 ++#define E3_LGB 0x77 ++#define E3_LLGC 0x90 ++#define E3_LLGH 0x91 ++ ++/* emit 64-bit register/register insns (B9 prefix) */ ++static inline void tcg_out_b9(TCGContext* s, int op, int r1, int r2) ++{ ++ tcg_out32(s, 0xb9000000 | (op << 16) | (r1 << 4) | r2); ++} ++#define B9_LGR 0x04 ++#define B9_AGR 0x08 ++#define B9_SGR 0x09 ++#define B9_MSGR 0x0c ++#define B9_LGFR 0x14 ++#define B9_LLGFR 0x16 ++#define B9_CGR 0x20 ++#define B9_CLGR 0x21 ++#define B9_NGR 0x80 ++#define B9_OGR 0x81 ++#define B9_XGR 0x82 ++#define B9_DLGR 0x87 ++#define B9_DLR 0x97 ++ ++/* emit (mostly) 32-bit register/register insns */ ++static inline void tcg_out_rr(TCGContext* s, int op, int r1, int r2) ++{ ++ tcg_out16(s, (op << 8) | (r1 << 4) | r2); ++} ++#define RR_BASR 0x0d ++#define RR_NR 0x14 ++#define RR_CLR 0x15 ++#define RR_OR 0x16 ++#define RR_XR 0x17 ++#define RR_LR 0x18 ++#define RR_CR 0x19 ++#define RR_AR 0x1a ++#define RR_SR 0x1b ++ ++static inline void tcg_out_a7(TCGContext *s, int op, int r1, int16_t i2) ++{ ++ tcg_out32(s, 0xa7000000UL | (r1 << 20) | (op << 16) | ((uint16_t)i2)); ++} ++#define A7_AHI 0xa ++#define A7_AHGI 0xb ++ ++/* emit 64-bit shifts (EB prefix) */ ++static inline void tcg_out_sh64(TCGContext* s, int op, int r0, int r1, int r2, int imm) ++{ ++ tcg_out16(s, 0xeb00 | (r0 << 4) | r1); ++ tcg_out32(s, op | (r2 << 28) | ((imm & 0xfff) << 16) | ((imm >> 12) << 8)); ++} ++#define SH64_REG_NONE 0 /* use immediate only (not R0!) */ ++#define SH64_SRAG 0x0a ++#define SH64_SRLG 0x0c ++#define SH64_SLLG 0x0d ++ ++/* emit 32-bit shifts */ ++static inline void tcg_out_sh32(TCGContext* s, int op, int r0, int r1, int imm) ++{ ++ tcg_out32(s, 0x80000000 | (op << 24) | (r0 << 20) | (r1 << 12) | imm); ++} ++#define SH32_REG_NONE 0 /* use immediate only (not R0!) */ ++#define SH32_SRL 0x8 ++#define SH32_SLL 0x9 ++#define SH32_SRA 0xa ++ ++/* branch to relative address (long) */ ++static inline void tcg_out_brasl(TCGContext* s, int r, tcg_target_long raddr) ++{ ++ tcg_out16(s, 0xc005 | (r << 4)); ++ tcg_out32(s, raddr >> 1); ++} ++ ++/* store 8/16/32 bits */ ++static inline void tcg_out_store(TCGContext* s, int op, int r0, int r1, int off) ++{ ++ tcg_out32(s, (op << 24) | (r0 << 20) | (r1 << 12) | off); ++} ++#define ST_STH 0x40 ++#define ST_STC 0x42 ++#define ST_ST 0x50 ++ + /* load a register with an immediate value */ + static inline void tcg_out_movi(TCGContext *s, TCGType type, + int ret, tcg_target_long arg) + { +- tcg_abort(); ++ //fprintf(stderr,"tcg_out_movi ret 0x%x arg 0x%lx\n",ret,arg); ++ if (arg >= -0x8000 && arg < 0x8000) { /* signed immediate load */ ++ /* lghi %rret, arg */ ++ tcg_out32(s, 0xa7090000 | (ret << 20) | (arg & 0xffff)); ++ } ++ else if (!(arg & 0xffffffffffff0000UL)) { ++ /* llill %rret, arg */ ++ tcg_out32(s, 0xa50f0000 | (ret << 20) | arg); ++ } ++ else if (!(arg & 0xffffffff00000000UL) || type == TCG_TYPE_I32) { ++ /* llill %rret, arg */ ++ tcg_out32(s, 0xa50f0000 | (ret << 20) | (arg & 0xffff)); ++ /* iilh %rret, arg */ ++ tcg_out32(s, 0xa5020000 | (ret << 20) | ((arg & 0xffffffff) >> 16)); ++ } ++ else { ++ /* branch over constant and store its address in R13 */ ++ tcg_out_brasl(s, TCG_REG_R13, 14); ++ /* 64-bit constant */ ++ tcg_out32(s,arg >> 32); ++ tcg_out32(s,arg); ++ /* load constant to ret */ ++ tcg_out_e3(s, E3_LG, ret, TCG_REG_R13, 0); ++ } + } + + /* load data without address translation or endianness conversion */ + static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg, + int arg1, tcg_target_long arg2) + { +- tcg_abort(); ++ int op; ++ //fprintf(stderr,"tcg_out_ld type %d arg %d arg1 %d arg2 %ld\n",type,arg,arg1,arg2); ++ ++ if (type == TCG_TYPE_I32) op = E3_LLGF; /* 32-bit zero-extended */ ++ else op = E3_LG; /* 64-bit */ ++ ++ if (arg2 < -0x80000 || arg2 > 0x7ffff) { ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, arg2); /* load the displacement */ ++ tcg_out_b9(s, B9_AGR, TCG_REG_R13, arg1); /* add the address */ ++ tcg_out_e3(s, op, arg, TCG_REG_R13, 0); /* load the data */ ++ } ++ else { ++ tcg_out_e3(s, op, arg, arg1, arg2); /* load the data */ ++ } ++} ++ ++/* load data with address translation (if applicable) and endianness conversion */ ++static void tcg_out_qemu_ld(TCGContext* s, const TCGArg* args, int opc) ++{ ++ int addr_reg, data_reg, mem_index, s_bits; ++#if defined(CONFIG_SOFTMMU) ++ uint16_t *label1_ptr, *label2_ptr; ++#endif ++ ++ data_reg = *args++; ++ addr_reg = *args++; ++ mem_index = *args; ++ ++ s_bits = opc & 3; ++ ++ int arg0 = TCG_REG_R2; ++#ifdef CONFIG_SOFTMMU ++ int arg1 = TCG_REG_R3; ++#endif ++ ++ /* fprintf(stderr,"tcg_out_qemu_ld opc %d data_reg %d addr_reg %d mem_index %d s_bits %d\n", ++ opc, data_reg, addr_reg, mem_index, s_bits); */ ++ ++#ifdef CONFIG_SOFTMMU ++ tcg_out_b9(s, B9_LGR, arg1, addr_reg); ++ tcg_out_b9(s, B9_LGR, arg0, addr_reg); ++ ++ tcg_out_sh64(s, SH64_SRLG, arg1, addr_reg, SH64_REG_NONE, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); ++ ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, TARGET_PAGE_MASK | ((1 << s_bits) - 1)); ++ tcg_out_b9(s, B9_NGR, arg0, TCG_REG_R13); ++ ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS); ++ tcg_out_b9(s, B9_NGR, arg1, TCG_REG_R13); ++ ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, offsetof(CPUState, tlb_table[mem_index][0].addr_read)); ++ tcg_out_b9(s, B9_AGR, arg1, TCG_REG_R13); ++ ++ tcg_out_b9(s, B9_AGR, arg1, TCG_AREG0); ++ ++ tcg_out_e3(s, E3_CG, arg0, arg1, 0); ++ ++ label1_ptr = (uint16_t*)s->code_ptr; ++ tcg_out32(s, 0xa7840000); /* je label1 (offset will be patched in later) */ ++ ++ /* call load helper */ ++#if TARGET_LONG_BITS == 32 ++ tcg_out_b9(s, B9_LLGFR, arg0, addr_reg); ++#else ++ tcg_out_b9(s, B9_LGR, arg0, addr_reg); ++#endif ++ tcg_out_movi(s, TCG_TYPE_I32, arg1, mem_index); ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, (tcg_target_ulong)qemu_ld_helpers[s_bits]); ++ tcg_out_rr(s, RR_BASR, TCG_REG_R14, TCG_REG_R13); ++ ++ /* sign extension */ ++ switch (opc) { ++ case 0 | 4: ++ tcg_out_sh64(s, SH64_SLLG, data_reg, arg0, SH64_REG_NONE, 56); ++ tcg_out_sh64(s, SH64_SRAG, data_reg, data_reg, SH64_REG_NONE, 56); ++ break; ++ case 1 | 4: ++ tcg_out_sh64(s, SH64_SLLG, data_reg, arg0, SH64_REG_NONE, 48); ++ tcg_out_sh64(s, SH64_SRAG, data_reg, data_reg, SH64_REG_NONE, 48); ++ break; ++ case 2 | 4: ++ tcg_out_b9(s, B9_LGFR, data_reg, arg0); ++ break; ++ case 0: case 1: case 2: case 3: default: ++ /* unsigned -> just copy */ ++ tcg_out_b9(s, B9_LGR, data_reg, arg0); ++ break; ++ } ++ ++ /* jump to label2 (end) */ ++ label2_ptr = (uint16_t*)s->code_ptr; ++ tcg_out32(s, 0xa7d50000); /* bras %r13, label2 */ ++ ++ /* this is label1, patch branch */ ++ *(label1_ptr + 1) = ((unsigned long)s->code_ptr - (unsigned long)label1_ptr) >> 1; ++ ++ tcg_out_e3(s, E3_LG, arg1, arg1, offsetof(CPUTLBEntry, addend) - offsetof(CPUTLBEntry, addr_read)); ++ ++#if TARGET_LONG_BITS == 32 ++ /* zero upper 32 bits */ ++ tcg_out_b9(s, B9_LLGFR, arg0, addr_reg); ++#else ++ /* just copy */ ++ tcg_out_b9(s, B9_LGR, arg0, addr_reg); ++#endif ++ tcg_out_b9(s, B9_AGR, arg0, arg1); ++ ++#else /* CONFIG_SOFTMMU */ ++ /* user mode, no address translation required */ ++ arg0 = addr_reg; ++#endif ++ ++ switch (opc) { ++ case 0: /* unsigned byte */ ++ tcg_out_e3(s, E3_LLGC, data_reg, arg0, 0); ++ break; ++ case 0 | 4: /* signed byte */ ++ tcg_out_e3(s, E3_LGB, data_reg, arg0, 0); ++ break; ++ case 1: /* unsigned short */ ++#ifdef TARGET_WORDS_BIGENDIAN ++ tcg_out_e3(s, E3_LLGH, data_reg, arg0, 0); ++#else ++ /* swapped unsigned halfword load with upper bits zeroed */ ++ tcg_out_e3(s, E3_LRVH, data_reg, arg0, 0); ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, 0xffffL); ++ tcg_out_b9(s, B9_NGR, data_reg, 13); ++#endif ++ break; ++ case 1 | 4: /* signed short */ ++#ifdef TARGET_WORDS_BIGENDIAN ++ tcg_out_e3(s, E3_LGH, data_reg, arg0, 0); ++#else ++ /* swapped sign-extended halfword load */ ++ tcg_out_e3(s, E3_LRVH, data_reg, arg0, 0); ++ tcg_out_sh64(s, SH64_SLLG, data_reg, data_reg, SH64_REG_NONE, 48); ++ tcg_out_sh64(s, SH64_SRAG, data_reg, data_reg, SH64_REG_NONE, 48); ++#endif ++ break; ++ case 2: /* unsigned int */ ++#ifdef TARGET_WORDS_BIGENDIAN ++ tcg_out_e3(s, E3_LLGF, data_reg, arg0, 0); ++#else ++ /* swapped unsigned int load with upper bits zeroed */ ++ tcg_out_e3(s, E3_LRV, data_reg, arg0, 0); ++ tcg_out_b9(s, B9_LLGFR, data_reg, data_reg); ++#endif ++ break; ++ case 2 | 4: /* signed int */ ++#ifdef TARGET_WORDS_BIGENDIAN ++ tcg_out_e3(s, E3_LGF, data_reg, arg0, 0); ++#else ++ /* swapped sign-extended int load */ ++ tcg_out_e3(s, E3_LRV, data_reg, arg0, 0); ++ tcg_out_b9(s, B9_LGFR, data_reg, data_reg); ++#endif ++ break; ++ case 3: /* long (64 bit) */ ++#ifdef TARGET_WORDS_BIGENDIAN ++ tcg_out_e3(s, E3_LG, data_reg, arg0, 0); ++#else ++ tcg_out_e3(s, E3_LRVG, data_reg, arg0, 0); ++#endif ++ break; ++ default: ++ tcg_abort(); ++ } ++ ++#ifdef CONFIG_SOFTMMU ++ /* this is label2, patch branch */ ++ *(label2_ptr + 1) = ((unsigned long)s->code_ptr - (unsigned long)label2_ptr) >> 1; ++#endif ++} ++ ++static void tcg_out_qemu_st(TCGContext* s, const TCGArg* args, int opc) ++{ ++ int addr_reg, data_reg, mem_index, s_bits; ++#if defined(CONFIG_SOFTMMU) ++ uint16_t *label1_ptr, *label2_ptr; ++#endif ++ ++ data_reg = *args++; ++ addr_reg = *args++; ++ mem_index = *args; ++ ++ s_bits = opc; ++ ++ int arg0 = TCG_REG_R2; ++#ifdef CONFIG_SOFTMMU ++ int arg1 = TCG_REG_R3; ++ int arg2 = TCG_REG_R4; ++#endif ++ ++ /* fprintf(stderr,"tcg_out_qemu_st opc %d data_reg %d addr_reg %d mem_index %d s_bits %d\n", ++ opc, data_reg, addr_reg, mem_index, s_bits); */ ++ ++#ifdef CONFIG_SOFTMMU ++#if TARGET_LONG_BITS == 32 ++ tcg_out_b9(s, B9_LLGFR, arg1, addr_reg); ++ tcg_out_b9(s, B9_LLGFR, arg0, addr_reg); ++#else ++ tcg_out_b9(s, B9_LGR, arg1, addr_reg); ++ tcg_out_b9(s, B9_LGR, arg0, addr_reg); ++#endif ++ ++ tcg_out_sh64(s, SH64_SRLG, arg1, addr_reg, SH64_REG_NONE, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); ++ ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, TARGET_PAGE_MASK | ((1 << s_bits) - 1)); ++ tcg_out_b9(s, B9_NGR, arg0, TCG_REG_R13); ++ ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS); ++ tcg_out_b9(s, B9_NGR, arg1, TCG_REG_R13); ++ ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, offsetof(CPUState, tlb_table[mem_index][0].addr_write)); ++ tcg_out_b9(s, B9_AGR, arg1, TCG_REG_R13); ++ ++ tcg_out_b9(s, B9_AGR, arg1, TCG_AREG0); ++ ++ tcg_out_e3(s, E3_CG, arg0, arg1, 0); ++ ++#if TARGET_LONG_BITS == 32 ++ tcg_out_b9(s, B9_LLGFR, arg0, addr_reg); ++#else ++ tcg_out_b9(s, B9_LGR, arg0, addr_reg); ++#endif ++ ++ /* jump to label1 */ ++ label1_ptr = (uint16_t*)s->code_ptr; ++ tcg_out32(s, 0xa7840000); /* je label1 */ ++ ++ /* call store helper */ ++ tcg_out_b9(s, B9_LGR, arg1, data_reg); ++ tcg_out_movi(s, TCG_TYPE_I32, arg2, mem_index); ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, (tcg_target_ulong)qemu_st_helpers[s_bits]); ++ tcg_out_rr(s, RR_BASR, TCG_REG_R14, TCG_REG_R13); ++ ++ /* jump to label2 (end) */ ++ label2_ptr = (uint16_t*)s->code_ptr; ++ tcg_out32(s, 0xa7d50000); /* bras %r13, label2 */ ++ ++ /* this is label1, patch branch */ ++ *(label1_ptr + 1) = ((unsigned long)s->code_ptr - (unsigned long)label1_ptr) >> 1; ++ ++ tcg_out_e3(s, E3_LG, arg1, arg1, offsetof(CPUTLBEntry, addend) - offsetof(CPUTLBEntry, addr_write)); ++ ++#if TARGET_LONG_BITS == 32 ++ /* zero upper 32 bits */ ++ tcg_out_b9(s, B9_LLGFR, arg0, addr_reg); ++#else ++ /* just copy */ ++ tcg_out_b9(s, B9_LGR, arg0, addr_reg); ++#endif ++ tcg_out_b9(s, B9_AGR, arg0, arg1); ++ ++#else /* CONFIG_SOFTMMU */ ++ /* user mode, no address translation required */ ++ arg0 = addr_reg; ++#endif ++ ++ switch (opc) { ++ case 0: ++ tcg_out_store(s, ST_STC, data_reg, arg0, 0); ++ break; ++ case 1: ++#ifdef TARGET_WORDS_BIGENDIAN ++ tcg_out_store(s, ST_STH, data_reg, arg0, 0); ++#else ++ tcg_out_e3(s, E3_STRVH, data_reg, arg0, 0); ++#endif ++ break; ++ case 2: ++#ifdef TARGET_WORDS_BIGENDIAN ++ tcg_out_store(s, ST_ST, data_reg, arg0, 0); ++#else ++ tcg_out_e3(s, E3_STRV, data_reg, arg0, 0); ++#endif ++ break; ++ case 3: ++#ifdef TARGET_WORDS_BIGENDIAN ++ tcg_out_e3(s, E3_STG, data_reg, arg0, 0); ++#else ++ tcg_out_e3(s, E3_STRVG, data_reg, arg0, 0); ++#endif ++ break; ++ default: ++ tcg_abort(); ++ } ++ ++#ifdef CONFIG_SOFTMMU ++ /* this is label2, patch branch */ ++ *(label2_ptr + 1) = ((unsigned long)s->code_ptr - (unsigned long)label2_ptr) >> 1; ++#endif + } + + static inline void tcg_out_st(TCGContext *s, TCGType type, int arg, + int arg1, tcg_target_long arg2) + { +- tcg_abort(); ++ //fprintf(stderr,"tcg_out_st arg 0x%x arg1 0x%x arg2 0x%lx\n",arg,arg1,arg2); ++ if (type == TCG_TYPE_I32) { ++ if (((long)arg2) < -0x800 || ((long)arg2) > 0x7ff) { ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, arg2); ++ tcg_out_b9(s, B9_AGR, 13, arg1); ++ tcg_out_store(s, ST_ST, arg, TCG_REG_R13, 0); ++ } ++ else tcg_out_store(s, ST_ST, arg, arg1, arg2); ++ } ++ else { ++ if (((long)arg2) < -0x80000 || ((long)arg2) > 0x7ffff) tcg_abort(); ++ tcg_out_e3(s, E3_STG, arg, arg1, arg2); ++ } + } + + static inline void tcg_out_op(TCGContext *s, int opc, + const TCGArg *args, const int *const_args) + { +- tcg_abort(); ++ TCGLabel* l; ++ int op; ++ int op2; ++ //fprintf(stderr,"0x%x\n", INDEX_op_divu_i32); ++ switch (opc) { ++ case INDEX_op_exit_tb: ++ //fprintf(stderr,"op 0x%x exit_tb 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, args[0]); /* return value */ ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, (unsigned long)tb_ret_addr); ++ tcg_out16(s,0x7fd); /* br %r13 */ ++ break; ++ case INDEX_op_goto_tb: ++ //fprintf(stderr,"op 0x%x goto_tb 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ if (s->tb_jmp_offset) { ++ tcg_abort(); ++ } ++ else { ++ tcg_target_long off = ((tcg_target_long)(s->tb_next + args[0]) - (tcg_target_long)s->code_ptr) >> 1; ++ if (off > -0x80000000L && off < 0x7fffffffL) { /* load address relative to PC */ ++ /* larl %r13, off */ ++ tcg_out16(s,0xc0d0); tcg_out32(s,off); ++ } ++ else { /* too far for larl */ ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, (tcg_target_long)(s->tb_next + args[0])); ++ } ++ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R13, TCG_REG_R13, 0); /* load address stored at s->tb_next + args[0] */ ++ tcg_out_rr(s, RR_BASR, TCG_REG_R13, TCG_REG_R13); /* and go there */ ++ } ++ s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf; ++ break; ++ case INDEX_op_call: ++ //fprintf(stderr,"op 0x%x call 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ if (const_args[0]) { ++ tcg_target_long off = (args[0] - (tcg_target_long)s->code_ptr + 4) >> 1; /* FIXME: + 4? Where did that come from? */ ++ if (off > -0x80000000 && off < 0x7fffffff) { /* relative call */ ++ tcg_out_brasl(s, TCG_REG_R14, off << 1); ++ tcg_abort(); // untested ++ } ++ else { /* too far for a relative call, load full address */ ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, args[0]); ++ tcg_out_rr(s, RR_BASR, TCG_REG_R14, TCG_REG_R13); ++ } ++ } ++ else { /* call function in register args[0] */ ++ tcg_out_rr(s, RR_BASR, TCG_REG_R14, args[0]); ++ } ++ break; ++ case INDEX_op_jmp: ++ fprintf(stderr,"op 0x%x jmp 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ tcg_abort(); ++ break; ++ case INDEX_op_ld8u_i32: ++ case INDEX_op_ld8u_i64: ++ //fprintf(stderr,"op 0x%x ld8u_i32 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ if ((long)args[2] > -0x80000 && (long)args[2] < 0x7ffff) { ++ tcg_out_e3(s, E3_LLGC, args[0], args[1], args[2]); ++ } ++ else { /* displacement too large, have to calculate address manually */ ++ tcg_abort(); ++ } ++ break; ++ case INDEX_op_ld8s_i32: ++ fprintf(stderr,"op 0x%x ld8s_i32 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ tcg_abort(); ++ break; ++ case INDEX_op_ld16u_i32: ++ fprintf(stderr,"op 0x%x ld16u_i32 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ if ((long)args[2] > -0x80000 && (long)args[2] < 0x7ffff) { ++ tcg_out_e3(s, E3_LLGH, args[0], args[1], args[2]); ++ } ++ else { /* displacement too large, have to calculate address manually */ ++ tcg_abort(); ++ } ++ break; ++ case INDEX_op_ld16s_i32: ++ fprintf(stderr,"op 0x%x ld16s_i32 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ tcg_abort(); ++ break; ++ case INDEX_op_ld_i32: ++ case INDEX_op_ld32u_i64: ++ tcg_out_ld(s, TCG_TYPE_I32, args[0], args[1], args[2]); ++ break; ++ case INDEX_op_ld32s_i64: ++ if (args[2] < -0x80000 || args[2] > 0x7ffff) { ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, args[2]); /* load the displacement */ ++ tcg_out_b9(s, B9_AGR, TCG_REG_R13, args[1]); /* add the address */ ++ tcg_out_e3(s, E3_LGF, args[0], TCG_REG_R13, 0); /* load the data (sign-extended) */ ++ } ++ else { ++ tcg_out_e3(s, E3_LGF, args[0], args[1], args[2]); /* load the data (sign-extended) */ ++ } ++ break; ++ case INDEX_op_ld_i64: ++ tcg_out_ld(s, TCG_TYPE_I64, args[0], args[1], args[2]); ++ break; ++ case INDEX_op_st8_i32: ++ case INDEX_op_st8_i64: ++ //fprintf(stderr,"op 0x%x st8_i32 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ if (((long)args[2]) >= -0x800 && ((long)args[2]) < 0x800) ++ tcg_out_store(s, ST_STC, args[0], args[1], args[2]); ++ else if (((long)args[2]) >= -0x80000 && ((long)args[2]) < 0x80000) { ++ tcg_out_e3(s, E3_STCY, args[0], args[1], args[2]); /* FIXME: requires long displacement facility */ ++ tcg_abort(); // untested ++ } ++ else tcg_abort(); ++ break; ++ case INDEX_op_st16_i32: ++ case INDEX_op_st16_i64: ++ //fprintf(stderr,"op 0x%x st16_i32 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ if (((long)args[2]) >= -0x800 && ((long)args[2]) < 0x800) ++ tcg_out_store(s, ST_STH, args[0], args[1], args[2]); ++ else if (((long)args[2]) >= -0x80000 && ((long)args[2]) < 0x80000) { ++ tcg_out_e3(s, E3_STHY, args[0], args[1], args[2]); /* FIXME: requires long displacement facility */ ++ tcg_abort(); // untested ++ } ++ else tcg_abort(); ++ break; ++ case INDEX_op_st_i32: ++ case INDEX_op_st32_i64: ++ tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]); ++ break; ++ case INDEX_op_st_i64: ++ tcg_out_st(s, TCG_TYPE_I64, args[0], args[1], args[2]); ++ break; ++ case INDEX_op_mov_i32: ++ fprintf(stderr,"op 0x%x mov_i32 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ tcg_abort(); ++ break; ++ case INDEX_op_movi_i32: ++ fprintf(stderr,"op 0x%x movi_i32 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ tcg_abort(); ++ break; ++ case INDEX_op_add_i32: ++ if (const_args[2]) { ++ if (args[0] == args[1]) tcg_out_a7(s, A7_AHI, args[1], args[2]); ++ else { ++ tcg_out_rr(s, RR_LR, args[0], args[1]); ++ tcg_out_a7(s, A7_AHI, args[0], args[2]); ++ } ++ } ++ else if (args[0] == args[1]) { ++ tcg_out_rr(s, RR_AR, args[1], args[2]); ++ } ++ else if (args[0] == args[2]) { ++ tcg_out_rr(s, RR_AR, args[0], args[1]); ++ } ++ else { ++ tcg_out_rr(s, RR_LR, args[0], args[1]); ++ tcg_out_rr(s, RR_AR, args[0], args[2]); ++ } ++ break; ++ case INDEX_op_sub_i32: ++ //fprintf(stderr,"op 0x%x sub_i32 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ if (args[0] == args[1]) { ++ tcg_out_rr(s, RR_SR, args[1], args[2]); /* sr %ra0/1, %ra2 */ ++ } ++ else if (args[0] == args[2]) { ++ tcg_out_rr(s, RR_LR, TCG_REG_R13, args[2]); /* lr %r13, %raa0/2 */ ++ tcg_out_rr(s, RR_LR, args[0], args[1]); /* lr %ra0/2, %ra1 */ ++ tcg_out_rr(s, RR_SR, args[0], TCG_REG_R13); /* sr %ra0/2, %r13 */ ++ } ++ else { ++ tcg_out_rr(s, RR_LR, args[0], args[1]); /* lr %ra0, %ra1 */ ++ tcg_out_rr(s, RR_SR, args[0], args[2]); /* sr %ra0, %ra2 */ ++ } ++ break; ++ ++ case INDEX_op_sub_i64: ++ //fprintf(stderr,"op 0x%x sub_i64 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ if (args[0] == args[1]) { ++ tcg_out_b9(s, B9_SGR, args[1], args[2]); /* sgr %ra0/1, %ra2 */ ++ } ++ else if (args[0] == args[2]) { ++ tcg_out_b9(s, B9_LGR, TCG_REG_R13, args[2]); /* lgr %r13, %raa0/2 */ ++ tcg_out_b9(s, B9_LGR, args[0], args[1]); /* lgr %ra0/2, %ra1 */ ++ tcg_out_b9(s, B9_SGR, args[0], TCG_REG_R13); /* sgr %ra0/2, %r13 */ ++ } ++ else { ++ tcg_out_b9(s, B9_LGR, args[0], args[1]); /* lgr %ra0, %ra1 */ ++ tcg_out_b9(s, B9_SGR, args[0], args[2]); /* sgr %ra0, %ra2 */ ++ } ++ break; ++ case INDEX_op_add_i64: ++ //fprintf(stderr,"op 0x%x add_i64 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ if (args[0] == args[1]) { ++ tcg_out_b9(s, B9_AGR, args[1], args[2]); ++ } ++ else if (args[0] == args[2]) { ++ tcg_out_b9(s, B9_AGR, args[0], args[1]); ++ } ++ else { ++ tcg_out_b9(s, B9_LGR, args[0], args[1]); ++ tcg_out_b9(s, B9_AGR, args[0], args[2]); ++ } ++ break; ++ ++ case INDEX_op_and_i32: ++ op = RR_NR; ++do_logic_i32: ++ if (args[0] == args[1]) { ++ tcg_out_rr(s, op, args[1], args[2]); /* xr %ra0/1, %ra2 */ ++ } ++ else if (args[0] == args[2]) { ++ tcg_out_rr(s, op, args[0], args[1]); /* xr %ra0/2, %ra1 */ ++ } ++ else { ++ tcg_out_rr(s, RR_LR, args[0], args[1]); /* lr %ra0, %ra1 */ ++ tcg_out_rr(s, op, args[0], args[2]); /* xr %ra0, %ra2 */ ++ } ++ break; ++ case INDEX_op_or_i32: op = RR_OR; goto do_logic_i32; ++ case INDEX_op_xor_i32: op = RR_XR; goto do_logic_i32; ++ ++ case INDEX_op_and_i64: ++ //fprintf(stderr,"op 0x%x and_i64 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ op = B9_NGR; ++do_logic_i64: ++ if (args[0] == args[1]) { ++ tcg_out_b9(s, op, args[0], args[2]); ++ } ++ else if (args[0] == args[2]) { ++ tcg_out_b9(s, op, args[0], args[1]); ++ } ++ else { ++ tcg_out_b9(s, B9_LGR, args[0], args[1]); ++ tcg_out_b9(s, op, args[0], args[2]); ++ } ++ break; ++ case INDEX_op_or_i64: op = B9_OGR; goto do_logic_i64; ++ case INDEX_op_xor_i64: op = B9_XGR; goto do_logic_i64; ++ ++ case INDEX_op_neg_i32: ++ //fprintf(stderr,"op 0x%x neg_i32 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ /* FIXME: optimize args[0] != args[1] case */ ++ tcg_out_rr(s, RR_LR, 13, args[1]); ++ tcg_out32(s, 0xa7090000 | (args[0] << 20)); /* lghi %ra0, 0 */ ++ tcg_out_rr(s, RR_SR, args[0], 13); ++ break; ++ case INDEX_op_neg_i64: ++ //fprintf(stderr,"op 0x%x neg_i64 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ /* FIXME: optimize args[0] != args[1] case */ ++ tcg_out_b9(s, B9_LGR, 13, args[1]); ++ tcg_out32(s, 0xa7090000 | (args[0] << 20)); /* lghi %ra0, 0 */ ++ tcg_out_b9(s, B9_SGR, args[0], 13); ++ break; ++ ++ case INDEX_op_mul_i32: ++ //fprintf(stderr,"op 0x%x mul_i32 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ if (args[0] == args[1]) ++ tcg_out32(s, 0xb2520000 | (args[0] << 4) | args[2]); /* msr %ra0/1, %ra2 */ ++ else if (args[0] == args[2]) ++ tcg_out32(s, 0xb2520000 | (args[0] << 4) | args[1]); /* msr %ra0/2, %ra1 */ ++ else { ++ tcg_out_rr(s, RR_LR, args[0], args[1]); ++ tcg_out32(s, 0xb2520000 | (args[0] << 4) | args[2]); /* msr %ra0, %ra2 */ ++ } ++ break; ++ case INDEX_op_mul_i64: ++ //fprintf(stderr,"op 0x%x mul_i64 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ if (args[0] == args[1]) { ++ tcg_out_b9(s, B9_MSGR, args[0], args[2]); ++ } ++ else if (args[0] == args[2]) { ++ tcg_out_b9(s, B9_MSGR, args[0], args[1]); ++ } ++ else tcg_abort(); ++ break; ++ ++ case INDEX_op_divu_i32: ++ case INDEX_op_remu_i32: ++ //fprintf(stderr,"op 0x%x div/remu_i32 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R12, 0); ++ tcg_out_rr(s, RR_LR, TCG_REG_R13, args[1]); ++ tcg_out_b9(s, B9_DLR, TCG_REG_R12, args[2]); ++ if (opc == INDEX_op_divu_i32) ++ tcg_out_rr(s, RR_LR, args[0], TCG_REG_R13); /* quotient */ ++ else ++ tcg_out_rr(s, RR_LR, args[0], TCG_REG_R12); /* remainder */ ++ break; ++ ++ case INDEX_op_shl_i32: ++ op = SH32_SLL; op2 = SH64_SLLG; ++do_shift32: ++ if (const_args[2]) { ++ if (args[0] == args[1]) { ++ tcg_out_sh32(s, op, args[0], SH32_REG_NONE, args[2]); ++ } ++ else { ++ tcg_out_rr(s, RR_LR, args[0], args[1]); ++ tcg_out_sh32(s, op, args[0], SH32_REG_NONE, args[2]); ++ } ++ } ++ else { ++ if (args[0] == args[1]) { ++ tcg_out_sh32(s, op, args[0], args[2], 0); ++ } ++ else ++ tcg_out_sh64(s, op2, args[0], args[1], args[2], 0); ++ } ++ break; ++ case INDEX_op_shr_i32: op = SH32_SRL; op2 = SH64_SRLG; goto do_shift32; ++ case INDEX_op_sar_i32: op = SH32_SRA; op2 = SH64_SRAG; goto do_shift32; ++ ++ case INDEX_op_shl_i64: ++ op = SH64_SLLG; ++do_shift64: ++ if (const_args[2]) { ++ tcg_out_sh64(s, op, args[0], args[1], SH64_REG_NONE, args[2]); ++ } ++ else { ++ tcg_out_sh64(s, op, args[0], args[1], args[2], 0); ++ } ++ break; ++ case INDEX_op_shr_i64: op = SH64_SRLG; goto do_shift64; ++ case INDEX_op_sar_i64: op = SH64_SRAG; goto do_shift64; ++ ++ case INDEX_op_br: ++ //fprintf(stderr,"op 0x%x br 0x%lx 0x%lx 0x%lx\n",opc,args[0],args[1],args[2]); ++ l = &s->labels[args[0]]; ++ if (l->has_value) { ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, l->u.value); ++ } ++ else { ++ /* larl %r13, ... */ ++ tcg_out16(s, 0xc0d0); ++ tcg_out_reloc(s, s->code_ptr, R_390_PC32DBL, args[0], -2); ++ s->code_ptr += 4; ++ } ++ tcg_out_rr(s, RR_BASR, TCG_REG_R13, TCG_REG_R13); ++ break; ++ case INDEX_op_brcond_i64: ++ //fprintf(stderr,"op 0x%x brcond_i64 0x%lx 0x%lx (c %d) 0x%lx\n",opc,args[0],args[1],const_args[1],args[2]); ++ if (args[2] > TCG_COND_GT) { /* unsigned */ ++ tcg_out_b9(s, B9_CLGR, args[0], args[1]); /* clgr %ra0, %ra1 */ ++ } ++ else { /* signed */ ++ tcg_out_b9(s, B9_CGR, args[0], args[1]); /* cgr %ra0, %ra1 */ ++ } ++ goto do_brcond; ++ case INDEX_op_brcond_i32: ++ //fprintf(stderr,"op 0x%x brcond_i32 0x%lx 0x%lx (c %d) 0x%lx\n",opc,args[0],args[1],const_args[1],args[2]); ++ if (args[2] > TCG_COND_GT) { /* unsigned */ ++ tcg_out_rr(s, RR_CLR, args[0], args[1]); /* clr %ra0, %ra1 */ ++ } ++ else { /* signed */ ++ tcg_out_rr(s, RR_CR, args[0], args[1]); /* cr %ra0, %ra1 */ ++ } ++do_brcond: ++ l = &s->labels[args[3]]; ++ if (l->has_value) { ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, l->u.value); ++ } ++ else { ++ /* larl %r13, ... */ ++ tcg_out16(s, 0xc0d0); ++ tcg_out_reloc(s, s->code_ptr, R_390_PC32DBL, args[3], -2); ++ s->code_ptr += 4; ++ } ++ tcg_out16(s, 0x070d | (tcg_cond_to_s390_cond[args[2]] << 4)); /* bcr cond,%r13 */ ++ break; ++ ++ case INDEX_op_qemu_ld8u: tcg_out_qemu_ld(s, args, 0); break; ++ case INDEX_op_qemu_ld8s: tcg_out_qemu_ld(s, args, 0 | 4); break; ++ case INDEX_op_qemu_ld16u: tcg_out_qemu_ld(s, args, 1); break; ++ case INDEX_op_qemu_ld16s: tcg_out_qemu_ld(s, args, 1 | 4); break; ++ case INDEX_op_qemu_ld32u: tcg_out_qemu_ld(s, args, 2); break; ++ case INDEX_op_qemu_ld32s: tcg_out_qemu_ld(s, args, 2 | 4); break; ++ case INDEX_op_qemu_ld64: tcg_out_qemu_ld(s, args, 3); break; ++ case INDEX_op_qemu_st8: tcg_out_qemu_st(s, args, 0); break; ++ case INDEX_op_qemu_st16: tcg_out_qemu_st(s, args, 1); break; ++ case INDEX_op_qemu_st32: tcg_out_qemu_st(s, args, 2); break; ++ case INDEX_op_qemu_st64: tcg_out_qemu_st(s, args, 3); break; ++ ++ default: ++ fprintf(stderr,"unimplemented opc 0x%x\n",opc); ++ tcg_abort(); ++ } + } + ++static const TCGTargetOpDef s390_op_defs[] = { ++ { INDEX_op_exit_tb, { } }, ++ { INDEX_op_goto_tb, { } }, ++ { INDEX_op_call, { "ri" } }, ++ { INDEX_op_jmp, { "ri" } }, ++ { INDEX_op_br, { } }, ++ ++ { INDEX_op_mov_i32, { "r", "r" } }, ++ { INDEX_op_movi_i32, { "r" } }, ++ ++ { INDEX_op_ld8u_i32, { "r", "r" } }, ++ { INDEX_op_ld8s_i32, { "r", "r" } }, ++ { INDEX_op_ld16u_i32, { "r", "r" } }, ++ { INDEX_op_ld16s_i32, { "r", "r" } }, ++ { INDEX_op_ld_i32, { "r", "r" } }, ++ { INDEX_op_st8_i32, { "r", "r" } }, ++ { INDEX_op_st16_i32, { "r", "r" } }, ++ { INDEX_op_st_i32, { "r", "r" } }, ++ ++ { INDEX_op_add_i32, { "r", "r", "rI" } }, ++ { INDEX_op_sub_i32, { "r", "r", "r" } }, ++ { INDEX_op_mul_i32, { "r", "r", "r" } }, ++ ++ { INDEX_op_div_i32, { "r", "r", "r" } }, ++ { INDEX_op_divu_i32, { "r", "r", "r" } }, ++ { INDEX_op_rem_i32, { "r", "r", "r" } }, ++ { INDEX_op_remu_i32, { "r", "r", "r" } }, ++ ++ { INDEX_op_and_i32, { "r", "r", "r" } }, ++ { INDEX_op_or_i32, { "r", "r", "r" } }, ++ { INDEX_op_xor_i32, { "r", "r", "r" } }, ++ { INDEX_op_neg_i32, { "r", "r" } }, ++ ++ { INDEX_op_shl_i32, { "r", "r", "Ri" } }, ++ { INDEX_op_shr_i32, { "r", "r", "Ri" } }, ++ { INDEX_op_sar_i32, { "r", "r", "Ri" } }, ++ ++ { INDEX_op_brcond_i32, { "r", "r" } }, ++ ++ { INDEX_op_qemu_ld8u, { "r", "L" } }, ++ { INDEX_op_qemu_ld8s, { "r", "L" } }, ++ { INDEX_op_qemu_ld16u, { "r", "L" } }, ++ { INDEX_op_qemu_ld16s, { "r", "L" } }, ++ { INDEX_op_qemu_ld32u, { "r", "L" } }, ++ { INDEX_op_qemu_ld32s, { "r", "L" } }, ++ ++ { INDEX_op_qemu_st8, { "S", "S" } }, ++ { INDEX_op_qemu_st16, { "S", "S" } }, ++ { INDEX_op_qemu_st32, { "S", "S" } }, ++ ++#if defined(__s390x__) ++ { INDEX_op_mov_i64, { "r", "r" } }, ++ { INDEX_op_movi_i64, { "r" } }, ++ ++ { INDEX_op_ld8u_i64, { "r", "r" } }, ++ { INDEX_op_ld8s_i64, { "r", "r" } }, ++ { INDEX_op_ld16u_i64, { "r", "r" } }, ++ { INDEX_op_ld16s_i64, { "r", "r" } }, ++ { INDEX_op_ld32u_i64, { "r", "r" } }, ++ { INDEX_op_ld32s_i64, { "r", "r" } }, ++ { INDEX_op_ld_i64, { "r", "r" } }, ++ ++ { INDEX_op_st8_i64, { "r", "r" } }, ++ { INDEX_op_st16_i64, { "r", "r" } }, ++ { INDEX_op_st32_i64, { "r", "r" } }, ++ { INDEX_op_st_i64, { "r", "r" } }, ++ ++ { INDEX_op_qemu_ld64, { "L", "L" } }, ++ { INDEX_op_qemu_st64, { "S", "S" } }, ++ ++ { INDEX_op_add_i64, { "r", "r", "r" } }, ++ { INDEX_op_mul_i64, { "r", "r", "r" } }, ++ { INDEX_op_sub_i64, { "r", "r", "r" } }, ++ ++ { INDEX_op_and_i64, { "r", "r", "r" } }, ++ { INDEX_op_or_i64, { "r", "r", "r" } }, ++ { INDEX_op_xor_i64, { "r", "r", "r" } }, ++ { INDEX_op_neg_i64, { "r", "r" } }, ++ ++ { INDEX_op_shl_i64, { "r", "r", "Ri" } }, ++ { INDEX_op_shr_i64, { "r", "r", "Ri" } }, ++ { INDEX_op_sar_i64, { "r", "r", "Ri" } }, ++ ++ { INDEX_op_brcond_i64, { "r", "r" } }, ++#endif ++ ++ { -1 }, ++}; ++ + void tcg_target_init(TCGContext *s) + { +- /* gets called with KVM */ ++ /* fail safe */ ++ if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry)) ++ tcg_abort(); ++ ++ tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff); ++ tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffff); ++ tcg_regset_set32(tcg_target_call_clobber_regs, 0, ++ (1 << TCG_REG_R0) | ++ (1 << TCG_REG_R1) | ++ (1 << TCG_REG_R2) | ++ (1 << TCG_REG_R3) | ++ (1 << TCG_REG_R4) | ++ (1 << TCG_REG_R5) | ++ (1 << TCG_REG_R14)); /* link register */ ++ ++ tcg_regset_clear(s->reserved_regs); ++ tcg_regset_set_reg(s->reserved_regs, TCG_REG_R13); /* frequently used as a temporary */ ++ tcg_regset_set_reg(s->reserved_regs, TCG_REG_R12); /* another temporary */ ++ ++ tcg_add_target_add_op_defs(s390_op_defs); + } + + void tcg_target_qemu_prologue(TCGContext *s) + { +- /* gets called with KVM */ ++ tcg_out16(s,0xeb6f);tcg_out32(s,0xf0300024); /* stmg %r6,%r15,48(%r15) (save registers) */ ++ tcg_out32(s, 0xa7fbff60); /* aghi %r15,-160 (stack frame) */ ++ tcg_out16(s,0x7f2); /* br %r2 (go to TB) */ ++ tb_ret_addr = s->code_ptr; ++ tcg_out16(s,0xeb6f);tcg_out32(s, 0xf0d00004); /* lmg %r6,%r15,208(%r15) (restore registers) */ ++ tcg_out16(s,0x7fe); /* br %r14 (return) */ + } + + static inline void tcg_out_mov(TCGContext *s, int ret, int arg) + { +- tcg_abort(); ++ tcg_out_b9(s, B9_LGR, ret, arg); + } + + static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val) +diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h +index 91b931d..6bae3c2 100644 +--- a/tcg/s390/tcg-target.h ++++ b/tcg/s390/tcg-target.h +@@ -25,6 +25,12 @@ + + #define TCG_TARGET_REG_BITS 64 + #define TCG_TARGET_WORDS_BIGENDIAN ++#define TCG_TARGET_HAS_div_i32 ++#undef TCG_TARGET_HAS_div_i64 ++#undef TCG_TARGET_HAS_bswap32_i32 ++#define TCG_TARGET_HAS_neg_i32 ++#define TCG_TARGET_HAS_neg_i64 ++#undef TCG_TARGET_STACK_GROWSUP + + enum { + TCG_REG_R0 = 0, +@@ -67,3 +73,6 @@ static inline void flush_icache_range(unsigned long start, unsigned long stop) + #error not implemented + #endif + } ++ TCG_AREG1 = TCG_REG_R7, ++ TCG_AREG2 = TCG_REG_R8, ++ TCG_AREG3 = TCG_REG_R9, +diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h +index faf2e8b..c1b4710 100644 +--- a/tcg/tcg-op.h ++++ b/tcg/tcg-op.h +@@ -316,6 +316,18 @@ static inline void tcg_gen_br(int label) + tcg_gen_op1i(INDEX_op_br, label); + } + ++static inline void tcg_gen_sync_i32(TCGv_i32 arg) ++{ ++ tcg_gen_op1_i32(INDEX_op_sync_i32, arg); ++} ++ ++#if TCG_TARGET_REG_BITS == 64 ++static inline void tcg_gen_sync_i64(TCGv_i64 arg) ++{ ++ tcg_gen_op1_i64(INDEX_op_sync_i64, arg); ++} ++#endif ++ + static inline void tcg_gen_mov_i32(TCGv_i32 ret, TCGv_i32 arg) + { + if (!TCGV_EQUAL_I32(ret, arg)) +diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h +index b7f3fd7..5dcdeba 100644 +--- a/tcg/tcg-opc.h ++++ b/tcg/tcg-opc.h +@@ -40,6 +40,7 @@ DEF2(call, 0, 1, 2, TCG_OPF_SIDE_EFFECTS) /* variable number of parameters */ + DEF2(jmp, 0, 1, 0, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS) + DEF2(br, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS) + ++DEF2(sync_i32, 0, 1, 0, 0) + DEF2(mov_i32, 1, 1, 0, 0) + DEF2(movi_i32, 1, 0, 1, 0) + /* load/store */ +@@ -109,6 +110,7 @@ DEF2(neg_i32, 1, 1, 0, 0) + #endif + + #if TCG_TARGET_REG_BITS == 64 ++DEF2(sync_i64, 0, 1, 0, 0) + DEF2(mov_i64, 1, 1, 0, 0) + DEF2(movi_i64, 1, 0, 1, 0) + /* load/store */ +diff --git a/tcg/tcg.c b/tcg/tcg.c +index 3c0e296..8eb60f8 100644 +--- a/tcg/tcg.c ++++ b/tcg/tcg.c +@@ -1930,6 +1930,12 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, + // dump_regs(s); + #endif + switch(opc) { ++ case INDEX_op_sync_i32: ++#if TCG_TARGET_REG_BITS == 64 ++ case INDEX_op_sync_i64: ++#endif ++ temp_save(s, args[0], s->reserved_regs); ++ break; + case INDEX_op_mov_i32: + #if TCG_TARGET_REG_BITS == 64 + case INDEX_op_mov_i64: +-- +1.6.4.2 + diff --git a/app-emulation/qemu/qemu-0.11.1.ebuild b/app-emulation/qemu/qemu-0.11.1.ebuild index 2344392..b023619 100644 --- a/app-emulation/qemu/qemu-0.11.1.ebuild +++ b/app-emulation/qemu/qemu-0.11.1.ebuild @@ -13,7 +13,7 @@ SRC_URI="http://download.savannah.gnu.org/releases/qemu/${P}.tar.gz" LICENSE="GPL-2" SLOT="0" KEYWORDS="~amd64 ~ppc ~ppc64 ~x86" -IUSE="alsa bluetooth esd gnutls ncurses pulseaudio sasl +sdl vde kvm static" +IUSE="alsa bluetooth esd gnutls ncurses pulseaudio sasl +sdl vde kvm static kqemu " COMMON_TARGETS="i386 x86_64 arm cris m68k mips mipsel mips64 mips64el ppc ppc64 sh4 sh4eb sparc" @@ -41,8 +41,8 @@ RDEPEND="!app-emulation/qemu-softmmu sdl? ( >=media-libs/libsdl-1.2.11 ) vde? ( net-misc/vde ) kvm? ( >=sys-kernel/linux-headers-2.6.29 ) - bluetooth? ( net-wireless/bluez )" -# kqemu? ( >=app-emulation/kqemu-1.4.0_pre1 ) + bluetooth? ( net-wireless/bluez ) + kqemu? ( >=app-emulation/kqemu-1.4.0_pre1 )" # fdt? ( sys-apps/dtc ) DEPEND="${RDEPEND} @@ -91,7 +91,7 @@ src_configure() { use sdl || conf_opts="$conf_opts --disable-sdl" use vde || conf_opts="$conf_opts --disable-vde" use bluetooth || conf_opts="$conf_opts --disable-bluez" -# use kqemu || conf_opts="$conf_opts --disable-kqemu" + use kqemu || conf_opts="$conf_opts --disable-kqemu" use kvm || conf_opts="$conf_opts --disable-kvm" audio_opts="oss" diff --git a/app-emulation/qemu/qemu-0.12.5.ebuild b/app-emulation/qemu/qemu-0.12.5.ebuild new file mode 100644 index 0000000..4e5054e --- /dev/null +++ b/app-emulation/qemu/qemu-0.12.5.ebuild @@ -0,0 +1,155 @@ +# Copyright 1999-2010 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-x86/app-emulation/qemu/qemu-0.11.1.ebuild,v 1.2 2010/01/05 23:58:40 flameeyes Exp $ + +EAPI="2" + +inherit eutils flag-o-matic toolchain-funcs linux-info + +DESCRIPTION="QEMU emulator and ABI wrapper" +HOMEPAGE="http://www.qemu.org" +SRC_URI="http://download.savannah.gnu.org/releases/qemu/${P}.tar.gz" + +LICENSE="GPL-2" +SLOT="0" +KEYWORDS="~amd64 ~ppc ~ppc64 ~x86" +IUSE="alsa bluetooth esd gnutls ncurses pulseaudio sasl +sdl vde kvm static aio" + +COMMON_TARGETS="i386 x86_64 arm cris m68k mips mipsel mips64 mips64el ppc ppc64 sh4 sh4eb sparc" + +IUSE_SOFTMMU_TARGETS="${COMMON_TARGETS} ppcemb" +IUSE_USER_TARGETS="${COMMON_TARGETS} alpha armeb ppc64abi32 sparc64 sparc32plus" + +for target in ${IUSE_SOFTMMU_TARGETS}; do + IUSE="${IUSE} +qemu_softmmu_targets_${target}" +done + +for target in ${IUSE_USER_TARGETS}; do + IUSE="${IUSE} +qemu_user_targets_${target}" +done + +RDEPEND="!app-emulation/qemu-softmmu + !app-emulation/qemu-user + !=media-libs/alsa-lib-1.0.13 ) + esd? ( media-sound/esound ) + pulseaudio? ( media-sound/pulseaudio ) + gnutls? ( net-libs/gnutls ) + ncurses? ( sys-libs/ncurses ) + sasl? ( dev-libs/cyrus-sasl ) + sdl? ( >=media-libs/libsdl-1.2.11 ) + vde? ( net-misc/vde ) + kvm? ( >=sys-kernel/linux-headers-2.6.29 ) + bluetooth? ( net-wireless/bluez )" +# kqemu? ( >=app-emulation/kqemu-1.4.0_pre1 ) +# fdt? ( sys-apps/dtc )" + +DEPEND="${RDEPEND} + gnutls? ( dev-util/pkgconfig ) + app-text/texi2html" + +src_prepare() { + # avoid fdt till an updated release appears + sed -i -e 's:fdt="yes":fdt="no":' configure + # prevent docs to get automatically installed + sed -i '/$(DESTDIR)$(docdir)/d' Makefile + # Alter target makefiles to accept CFLAGS set via flag-o + sed -i 's/^\(C\|OP_C\|HELPER_C\)FLAGS=/\1FLAGS+=/' \ + Makefile Makefile.target tests/Makefile + [[ -x /sbin/paxctl ]] && \ + sed -i 's/^VL_LDFLAGS=$/VL_LDFLAGS=-Wl,-z,execheap/' \ + Makefile.target + # Append CFLAGS while linking + sed -i 's/$(LDFLAGS)/$(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS)/' rules.mak + epatch "${FILESDIR}/qemu-0.11.0-mips64-user-fix.patch" + epatch "${FILESDIR}/qemu-chroot.patch" + EPATCH_SOURCE="${FILESDIR}/0.12.4" EPATCH_SUFFIX="patch" \ + EPATCH_FORCE="yes" epatch +} + +src_configure() { + local mycc conf_opts audio_opts softmmu_targets user_targets target_list + + for target in ${IUSE_SOFTMMU_TARGETS} ; do + use "qemu_softmmu_targets_${target}" && \ + softmmu_targets="${softmmu_targets} ${target}-softmmu" + done + + for target in ${IUSE_USER_TARGETS} ; do + use "qemu_user_targets_${target}" && \ + user_targets="${user_targets} ${target}-linux-user" + done + + conf_opts="--disable-darwin-user --disable-bsd-user --disable-strip" + + if test ! -z "${softmmu_targets}" ; then + einfo "Building following softmmu targets: ${softmmu_targets}" + use gnutls || conf_opts="$conf_opts --disable-vnc-tls" + use ncurses || conf_opts="$conf_opts --disable-curses" + use sasl || conf_opts="$conf_opts --disable-vnc-sasl" + use sdl || conf_opts="$conf_opts --disable-sdl" + use vde || conf_opts="$conf_opts --disable-vde" + use bluetooth || conf_opts="$conf_opts --disable-bluez" +# use kqemu || conf_opts="$conf_opts --disable-kqemu" + use kvm || conf_opts="$conf_opts --disable-kvm" + + audio_opts="oss" + use alsa && audio_opts="alsa $audio_opts" + use esd && audio_opts="esd $audio_opts" + use pulseaudio && audio_opts="pa $audio_opts" + use sdl && audio_opts="sdl $audio_opts" + else + einfo "Disabling softmmu emulation (no softmmu targets specified)" + conf_opts="$conf_opts --disable-system --disable-vnc-tls \ + --disable-curses --disable-sdl --disable-vde \ + --disable-kvm" + fi + + if test ! -z "${user_targets}" ; then + einfo "Building following user targets: ${user_targets}" + conf_opts="$conf_opts --enable-linux-user" + else + einfo "Disabling usermode emulation (no usermode targets specified)" + conf_opts="$conf_opts --disable-linux-user" + fi + + use fdt || conf_opts="$conf_opts --disable-fdt" + use aio || conf_opts="$conf_opts --disable-linux-aio" + + use static && conf_opts="$conf_opts --static" + conf_opts="$conf_opts --prefix=/usr" + + target_list="${softmmu_targets} ${user_targets}" + + filter-flags -fPIE + + ./configure ${conf_opts} \ + --audio-drv-list="$audio_opts" \ + --cc=$(tc-getCC) --host-cc=$(tc-getCC) \ + --target-list="${target_list}" \ + || die "configure failed" +} + +src_install() { + emake DESTDIR="${D}" install || die "make install failed" + + exeinto /etc/qemu + doexe \ + "${FILESDIR}/qemu-ifup" \ + "${FILESDIR}/qemu-ifdown" \ + || die "qemu interface scripts failed" + + dodoc Changelog MAINTAINERS TODO pci-ids.txt || die + newdoc pc-bios/README README.pc-bios || die + dohtml qemu-doc.html qemu-tech.html || die +} + +pkg_postinst() { + elog "You will need the Universal TUN/TAP driver compiled into your" + elog "kernel or loaded as a module to use the virtual network device" + elog "if using -net tap. You will also need support for 802.1d" + elog "Ethernet Bridging and a configured bridge if using the provided" + elog "qemu-ifup script from /etc/qemu." + echo +}