Compare commits
384 Commits
e2k-v8.1.3
...
e2k-softmm
Author | SHA1 | Date |
---|---|---|
Alibek Omarov | e3304f7219 | |
Alibek Omarov | 030c8c979d | |
Alibek Omarov | 641c6f7e4c | |
Alibek Omarov | b588f7d269 | |
Alibek Omarov | db1f69d6b3 | |
Alibek Omarov | 50a08921e6 | |
Alibek Omarov | 1169f1a46a | |
Alibek Omarov | 818f96d7a5 | |
Alibek Omarov | e57e16c31d | |
Alibek Omarov | 0fbc234be3 | |
Alibek Omarov | 0d8530775e | |
Alibek Omarov | a36b8306ec | |
Alibek Omarov | b0a8c3c70a | |
Alibek Omarov | 3614e16f5c | |
Alibek Omarov | 4d79fff5e6 | |
Alibek Omarov | 5c06474a86 | |
Alibek Omarov | d1adffa508 | |
Alibek Omarov | 4b81eaa930 | |
Alibek Omarov | 2b9db04643 | |
Alibek Omarov | 291dc245dc | |
Alibek Omarov | 0db316ed3c | |
Alibek Omarov | dbc7cacc8d | |
Alibek Omarov | 8de04976c0 | |
Alibek Omarov | d2a1753138 | |
Alibek Omarov | e10bb15d7a | |
Alibek Omarov | 9332082768 | |
Alibek Omarov | f7c2c20661 | |
Alibek Omarov | 1dde9d43a4 | |
Alibek Omarov | bd4ec67ed2 | |
Alibek Omarov | c110f65d09 | |
Alibek Omarov | 10d1009d8a | |
Alibek Omarov | 56ed496823 | |
Alibek Omarov | 85fa254b25 | |
Alibek Omarov | 30e57bf532 | |
Denis Drakhnia | 6d1841f2b4 | |
Alibek Omarov | b960480b6d | |
Alibek Omarov | 1b3e36f3e0 | |
Alibek Omarov | a1af460416 | |
Alibek Omarov | 4670be0fd6 | |
Alibek Omarov | 983e500241 | |
Alibek Omarov | 6cc82042c5 | |
Denis Drakhnia | 1c19a5e42d | |
Alibek Omarov | a2e8e1f726 | |
Alibek Omarov | 332652a264 | |
Denis Drakhnia | 4b74969b55 | |
Denis Drakhnia | 3c683e8842 | |
Denis Drakhnia | fd6b300945 | |
Denis Drakhnia | c85a9d9088 | |
Denis Drakhnia | b05aefc074 | |
Denis Drakhnia | aac549c645 | |
Denis Drakhnia | 452fc964b0 | |
Denis Drakhnia | 7fb91d883b | |
Denis Drakhnia | 652acd6dd9 | |
Denis Drakhnia | 6352dbc284 | |
Denis Drakhnia | 7dcb5fa4c7 | |
Denis Drakhnia | 4277c82910 | |
Denis Drakhnia | 801e422045 | |
Denis Drakhnia | 6f273d2ea4 | |
Denis Drakhnia | 9ca3581380 | |
Denis Drakhnia | 5647e20f76 | |
Denis Drakhnia | 8d7df93656 | |
Denis Drakhnia | a78054bbca | |
Denis Drakhnia | 3a30c5edfd | |
Denis Drakhnia | afc36915fa | |
Denis Drakhnia | 4a4fe9fd52 | |
Denis Drakhnia | 5ac71836f8 | |
Denis Drakhnia | 91b18183de | |
Denis Drakhnia | b59c0ec31e | |
Denis Drakhnia | d89de72255 | |
Denis Drakhnia | e1796eab81 | |
Denis Drakhnia | f7e0eecb9c | |
Denis Drakhnia | 5693b6b04f | |
Alibek Omarov | aa67acded6 | |
Denis Drakhnia | 1ba1a731e8 | |
Denis Drakhnia | 27450f6d57 | |
Denis Drakhnia | a3bd286307 | |
Denis Drakhnia | d0933819e3 | |
Denis Drakhnia | 49c1ea254d | |
Denis Drakhnia | 6f5ad5ee34 | |
Denis Drakhnia | 6ced6a02ea | |
Denis Drakhnia | f5664db54c | |
Denis Drakhnia | 7b12a1a0e4 | |
Denis Drakhnia | 9f48ac64d4 | |
Denis Drakhnia | 9dd2d3dbf6 | |
Denis Drakhnia | d8c92845a7 | |
Denis Drakhnia | d7da680a99 | |
Denis Drakhnia | 4ca7a8e3fe | |
Denis Drakhnia | 19e386d72a | |
Alibek Omarov | 4c8bbd60b5 | |
Denis Drakhnia | b368b67760 | |
Denis Drakhnia | c7cda1f65e | |
Denis Drakhnia | 2c467eee32 | |
Denis Drakhnia | a717098e5f | |
Denis Drakhnia | d9a98c1a39 | |
Denis Drakhnia | aa0d172f6e | |
Denis Drakhnia | fe7ed6b222 | |
Denis Drakhnia | ee81d8da59 | |
Denis Drakhnia | 4227ac3dca | |
Denis Drakhnia | 63011818cd | |
Denis Drakhnia | 687395c535 | |
Denis Drakhnia | d37d06e24d | |
Denis Drakhnia | 74881f8ea7 | |
Denis Drakhnia | ee52b186a9 | |
Alibek Omarov | 4092f92f11 | |
Alibek Omarov | 951b3b142b | |
Denis Drakhnia | b71b381ad9 | |
Denis Drakhnia | 954f026069 | |
Denis Drakhnia | 4a9acdbc7a | |
Denis Drakhnia | 26e5446eaa | |
Denis Drakhnia | 11b07b2033 | |
Denis Drakhnia | 3bc6ba66cb | |
Denis Drakhnia | 41b1894970 | |
Denis Drakhnia | 0cac5fc316 | |
Denis Drakhnia | ca2a301752 | |
Alibek Omarov | ac6a4f007e | |
Alibek Omarov | 62f54e580a | |
Denis Drakhnia | dc3896a3bb | |
Denis Drakhnia | e4ce9097da | |
Denis Drakhnia | 2a783a4c41 | |
Denis Drakhnia | 71fa769902 | |
Denis Drakhnia | c2d5fd78c2 | |
Denis Drakhnia | 3f4ee65a6a | |
Alibek Omarov | 3a3878c337 | |
Denis Drakhnia | 8c3fd2ef2d | |
Denis Drakhnia | 382c861258 | |
Denis Drakhnia | 9b5889f2a3 | |
Alibek Omarov | 07c5bf6dd6 | |
Alibek Omarov | 2c6e75164d | |
Denis Drakhnia | ebf29d0a87 | |
Denis Drakhnia | 2fc5c4f8e3 | |
Denis Drakhnia | 535b0a0616 | |
Denis Drakhnia | 842c990c4c | |
Denis Drakhnia | fd435db566 | |
Denis Drakhnia | 62a6bc54d8 | |
Denis Drakhnia | fbeee5f77a | |
Denis Drakhnia | 034f16d03c | |
Denis Drakhnia | 68c2d77603 | |
Denis Drakhnia | 10f5831153 | |
Denis Drakhnia | 2fa96b18f3 | |
Denis Drakhnia | c0cc80ffba | |
Denis Drakhnia | 135d0824fc | |
Denis Drakhnia | 5846530746 | |
Denis Drakhnia | 3dad8d3fa1 | |
Denis Drakhnia | 2c3600b282 | |
Denis Drakhnia | 333f94693e | |
Denis Drakhnia | ed3ba3fdf9 | |
Denis Drakhnia | 2051e90a5c | |
Denis Drakhnia | 2a54fa6008 | |
Denis Drakhnia | d8a54d6189 | |
Denis Drakhnia | bebca526fb | |
Denis Drakhnia | 39c8f3337c | |
Denis Drakhnia | 012aa4cd9d | |
Denis Drakhnia | 2443e57916 | |
Denis Drakhnia | 6e2130961c | |
Denis Drakhnia | 8d0a6de012 | |
Denis Drakhnia | 6d16038d5f | |
Denis Drakhnia | e6329a2907 | |
Denis Drakhnia | d39cdc07a1 | |
Denis Drakhnia | 219429efcf | |
Denis Drakhnia | 593b6ecc6d | |
Denis Drakhnia | c2afb3a4bf | |
Denis Drakhnia | e6545e53c0 | |
Denis Drakhnia | b7a76b3b03 | |
Alibek Omarov | 62d0ba0ce8 | |
Alibek Omarov | e3cf268a2c | |
Alibek Omarov | a727a050b0 | |
Alibek Omarov | 9d47f0296e | |
Denis Drakhnia | 5c1bfb085e | |
Alibek Omarov | 15a41a9d2b | |
Alibek Omarov | 0b2c48563a | |
Denis Drakhnia | 490916800d | |
Denis Drakhnia | f642e9f4cc | |
Alibek Omarov | 140ff5b26d | |
Denis Drakhnia | 1fa12cd1f8 | |
Denis Drakhnia | 5d7892afaf | |
Denis Drakhnia | 8a9a5186ef | |
Denis Drakhnia | 9ae33eb4ea | |
Denis Drakhnia | 6237724203 | |
Denis Drakhnia | fa11da01cb | |
Alibek Omarov | 4f8db27900 | |
Denis Drakhnia | ed526a6cff | |
Denis Drakhnia | d5cb0fb7fc | |
Alibek Omarov | 82bc772855 | |
Alibek Omarov | 2d776db5d4 | |
Alibek Omarov | 4ae0b676c5 | |
Alibek Omarov | ae835d1ec9 | |
Denis Drakhnia | a4b327f103 | |
Denis Drakhnia | f132f3cace | |
Denis Drakhnia | ca375bc450 | |
Denis Drakhnia | 0ebf9ead7c | |
Denis Drakhnia | 57d2c973ca | |
Denis Drakhnia | 8be1d4a4ff | |
Denis Drakhnia | e614ff56d4 | |
Denis Drakhnia | e0c19f7657 | |
Denis Drakhnia | d4c49d9093 | |
Alibek Omarov | 9e51b8b90b | |
Alibek Omarov | 531275d0b8 | |
Alibek Omarov | fbadcc486a | |
Alibek Omarov | eadbb653fe | |
Alibek Omarov | 66711e6474 | |
Denis Drakhnia | 0a9141271a | |
Denis Drakhnia | 8a29c4873a | |
Denis Drakhnia | 28fb8b3363 | |
Denis Drakhnia | eb74ae2832 | |
Denis Drakhnia | 4c74efa336 | |
Denis Drakhnia | d3e9e9e1cf | |
Denis Drakhnia | ca9777eb47 | |
Denis Drakhnia | d823adeef4 | |
Denis Drakhnia | 50620eb6bf | |
Denis Drakhnia | 53eafebe9e | |
Denis Drakhnia | ad4657fdd5 | |
Denis Drakhnia | 4461945f86 | |
Denis Drakhnia | 9bed8ca071 | |
Denis Drakhnia | a6f51c40d1 | |
Denis Drakhnia | a0f12e586f | |
Denis Drakhnia | 79a04c2476 | |
Denis Drakhnia | 2573f2f59e | |
Denis Drakhnia | 28d1af95ce | |
Denis Drakhnia | 601cb5098e | |
Denis Drakhnia | ef3754013a | |
Denis Drakhnia | 435b7b7b53 | |
Denis Drakhnia | 2c3ccb018a | |
Denis Drakhnia | 489074436c | |
Denis Drakhnia | 1556591a51 | |
Denis Drakhnia | 658ae276ff | |
Denis Drakhnia | 3b7dc608ad | |
Denis Drakhnia | e01c75fcee | |
Denis Drakhnia | 1fe993ba45 | |
Denis Drakhnia | 51828b93a0 | |
Denis Drakhnia | fbe580d688 | |
Denis Drakhnia | dba6891e25 | |
Denis Drakhnia | 80fb7750f9 | |
Denis Drakhnia | b05954919c | |
Denis Drakhnia | 50ea7ffe16 | |
Denis Drakhnia | b1e6863dea | |
Denis Drakhnia | 59bbf4cc32 | |
Denis Drakhnia | 4c367bc7fd | |
Denis Drakhnia | 4efbb14769 | |
Denis Drakhnia | 09c11cc025 | |
Denis Drakhnia | efe2096d99 | |
Denis Drakhnia | 92c450538b | |
Alibek Omarov | b1e0ff07e6 | |
Denis Drakhnia | ae7bdcdaf0 | |
Alibek Omarov | d10c6bb8d3 | |
Denis Drakhnia | c541342e15 | |
Denis Drakhnia | 0b95d2ac84 | |
Denis Drakhnia | 9764860c49 | |
Denis Drakhnia | e6417dbafa | |
Denis Drakhnia | f7e8b88b18 | |
Denis Drakhnia | 3d892bd2e1 | |
Denis Drakhnia | 5e03f648d8 | |
Denis Drakhnia | 57d037c35f | |
Denis Drakhnia | 661f961173 | |
Denis Drakhnia | 168685155c | |
Denis Drakhnia | d4fb3ea77d | |
Denis Drakhnia | c87d09e5c6 | |
Denis Drakhnia | e0aa8d2be7 | |
Denis Drakhnia | 978c71d6f4 | |
Denis Drakhnia | 1973bcaf12 | |
Alibek Omarov | 264053f440 | |
Denis Drakhnia | 9197fb5473 | |
Alibek Omarov | 6ef5bd8c89 | |
Alibek Omarov | d709ccaf02 | |
Denis Drakhnia | 18c3b8e7bf | |
Denis Drakhnia | 44279d5914 | |
Denis Drakhnia | b06832979a | |
Denis Drakhnia | 25538ca72b | |
Denis Drakhnia | 9d82f3ebe9 | |
Denis Drakhnia | 86214b6bb8 | |
Denis Drakhnia | 623b9cf2d7 | |
Denis Drakhnia | 8c6d17d57d | |
Denis Drakhnia | c8e5c64499 | |
Denis Drakhnia | 6129094288 | |
Denis Drakhnia | 1b9422f89d | |
Denis Drakhnia | 41c16b46a1 | |
Denis Drakhnia | f04f7f0106 | |
Alibek Omarov | e5fe02b722 | |
Denis Drakhnia | 2fcc3ba89d | |
Denis Drakhnia | 26d0e12e1e | |
Denis Drakhnia | 205647fbd9 | |
Denis Drakhnia | 284da505ff | |
Denis Drakhnia | 1768bf4cfd | |
Denis Drakhnia | c3f105c132 | |
Denis Drakhnia | 290bff3f3e | |
Denis Drakhnia | 3d1e558b19 | |
Denis Drakhnia | 0153ea9259 | |
Denis Drakhnia | db313e9236 | |
Denis Drakhnia | 1001e16697 | |
Denis Drakhnia | e307182167 | |
Denis Drakhnia | abbe9368e5 | |
Denis Drakhnia | b3e5cd2011 | |
Denis Drakhnia | 72f036b1bf | |
Denis Drakhnia | 11bd8ae0f3 | |
Denis Drakhnia | 23cdc6fc7b | |
Denis Drakhnia | d27d954c75 | |
Denis Drakhnia | fa779edcfb | |
Denis Drakhnia | 3cae4775ad | |
Denis Drakhnia | 0de523f9eb | |
Denis Drakhnia | 71e419504e | |
Denis Drakhnia | eb5c42659d | |
Denis Drakhnia | e11cfa7b90 | |
Denis Drakhnia | 85bdff00a5 | |
Denis Drakhnia | 3e17641dcb | |
Denis Drakhnia | 8da97da7f7 | |
Denis Drakhnia | 8e85dc24f6 | |
Denis Drakhnia | 1368572342 | |
Denis Drakhnia | 5a19b4be08 | |
Denis Drakhnia | cb2d728151 | |
Denis Drakhnia | a0e1a77993 | |
Denis Drakhnia | 81b6220817 | |
Denis Drakhnia | aa3cc78ef1 | |
Denis Drakhnia | 9ea4b04c38 | |
Denis Drakhnia | 505a2a1acd | |
Denis Drakhnia | f1e58bc551 | |
Denis Drakhnia | e7377e2a59 | |
Denis Drakhnia | 078beec8ac | |
Denis Drakhnia | c547c22405 | |
Denis Drakhnia | e1e6588335 | |
Denis Drakhnia | 3ab77d7c10 | |
Denis Drakhnia | 65d7a8646f | |
Alibek Omarov | 28baa0a65d | |
Alibek Omarov | 3708e3489c | |
Denis Drakhnia | 212c121127 | |
Denis Drakhnia | 5b828e999f | |
Denis Drakhnia | 47905d5d35 | |
Denis Drakhnia | dec82b41b6 | |
Denis Drakhnia | d9444952d0 | |
Denis Drakhnia | 45d5039496 | |
Denis Drakhnia | d2c747a497 | |
Denis Drakhnia | 7a24df0762 | |
Denis Drakhnia | 31af59b8d5 | |
Denis Drakhnia | 17d175a2d8 | |
Denis Drakhnia | 8e1c3d2401 | |
Alibek Omarov | 7db0d690b2 | |
Denis Drakhnia | 6184b65812 | |
Denis Drakhnia | a4f18c82f6 | |
Denis Drakhnia | aa84842e3a | |
Denis Drakhnia | e0a0ea5c52 | |
Denis Drakhnia | 320e542ece | |
Alibek Omarov | a793ec50cb | |
Denis Drakhnia | a0b43c510a | |
Denis Drakhnia | 6bcad20ee8 | |
Denis Drakhnia | c88de7df16 | |
Denis Drakhnia | d74f15d1cf | |
Denis Drakhnia | 17b9bc4519 | |
Denis Drakhnia | 959606cda2 | |
Denis Drakhnia | 4b85995458 | |
Denis Drakhnia | 1b382e3498 | |
Denis Drakhnia | 67fb40bbf1 | |
Denis Drakhnia | 6cd1e55a70 | |
Denis Drakhnia | 4f8aec99a5 | |
Denis Drakhnia | c59bd94281 | |
Denis Drakhnia | 905fa26d0f | |
Denis Drakhnia | 368e31db47 | |
Denis Drakhnia | 6cd1b1b708 | |
Denis Drakhnia | 07f2b730fb | |
Denis Drakhnia | 8f5efae8d8 | |
Denis Drakhnia | 5221e50edf | |
Denis Drakhnia | 4a2934f5a0 | |
Denis Drakhnia | 3e3508f9bd | |
Denis Drakhnia | 779fc80db4 | |
Denis Drakhnia | 42cd4b2c56 | |
Denis Drakhnia | 9caeb1a1dd | |
Denis Drakhnia | cf066b7b00 | |
Denis Drakhnia | 7dfb4f0064 | |
Denis Drakhnia | 56c122557d | |
Denis Drakhnia | 4a882f6e23 | |
Denis Drakhnia | f10f86baeb | |
Denis Drakhnia | 2cb98bc101 | |
Denis Drakhnia | a1a62134f9 | |
Denis Drakhnia | 138ef8a409 | |
Denis Drakhnia | 65f0ec0ddb | |
Denis Drakhnia | 1957823609 | |
Alibek Omarov | 734a2c52ca | |
Alibek Omarov | 640e6f5795 | |
Denis Drakhnia | f5f246ce2d | |
Alibek Omarov | 7720349e2b | |
Denis Drakhnia | 42b90e6046 | |
Alibek Omarov | 0d8fe3691c | |
Alibek Omarov | 68e2e890cb | |
Alibek Omarov | 7215f303c1 | |
Alibek Omarov | 4bda3b32bc | |
Alibek Omarov | 3d8eabf29d | |
Alibek Omarov | 0c4d9b8d1c |
|
@ -0,0 +1,13 @@
|
|||
# Default configuration for e2k-softmmu
|
||||
|
||||
# Dev:
|
||||
#
|
||||
CONFIG_APIC=y
|
||||
CONFIG_IOAPIC=y
|
||||
CONFIG_PCI=y
|
||||
CONFIG_ELBRUS_SIM_CONSOLE=y
|
||||
CONFIG_PCI_IOHUB=y
|
||||
CONFIG_VGA_CIRRUS=y
|
||||
CONFIG_VGA_PCI=y
|
||||
CONFIG_ATI_VGA=y
|
||||
CONFIG_ESCC_PCI=y
|
|
@ -0,0 +1,2 @@
|
|||
TARGET_ARCH=e2k
|
||||
TARGET_XML_FILES= gdb-xml/e2k-v1.xml gdb-xml/e2k-v2.xml gdb-xml/e2k-v3.xml gdb-xml/e2k-v5.xml
|
|
@ -0,0 +1,3 @@
|
|||
TARGET_ARCH=e2k
|
||||
TARGET_SUPPORTS_MTTCG=y
|
||||
TARGET_XML_FILES= gdb-xml/e2k-v1.xml gdb-xml/e2k-v2.xml gdb-xml/e2k-v3.xml gdb-xml/e2k-v5.xml
|
|
@ -0,0 +1,5 @@
|
|||
TARGET_ARCH=e2k32
|
||||
TARGET_BASE_ARCH=e2k
|
||||
TARGET_ABI_DIR=e2k
|
||||
TARGET_ABI32=y
|
||||
TARGET_XML_FILES= gdb-xml/e2k-v1.xml gdb-xml/e2k-v2.xml gdb-xml/e2k-v3.xml gdb-xml/e2k-v5.xml
|
2
disas.c
2
disas.c
|
@ -207,6 +207,8 @@ static void initialize_debug_host(CPUDebug *s)
|
|||
s->info.cap_insn_split = 6;
|
||||
#elif defined(__hppa__)
|
||||
s->info.print_insn = print_insn_hppa;
|
||||
#elif defined(__e2k__)
|
||||
s->info.print_insn = print_insn_e2k;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,556 @@
|
|||
|
||||
#include <sys/types.h>
|
||||
|
||||
#define COMMON_PART \
|
||||
const char *name; \
|
||||
int (* parse_args) (char **, const struct e2k_opcode_templ *); \
|
||||
const char * (* merge) (struct e2k_opcode_templ *, const struct e2k_opcode_templ *)
|
||||
|
||||
#define ALOPF1 1
|
||||
#define ALOPF2 2
|
||||
#define ALOPF3 3
|
||||
#define ALOPF7 4
|
||||
#define ALOPF8 5
|
||||
#define ALOPF10 6
|
||||
#define ALOPF11 7
|
||||
#define ALOPF11_LIT8 8
|
||||
#define ALOPF11_MERGE 9
|
||||
#define ALOPF12 10
|
||||
#define ALOPF12_PSHUFH 11
|
||||
#define ALOPF12_IBRANCHD 12
|
||||
#define ALOPF12_ICALLD 13
|
||||
#define ALOPF13 14
|
||||
#define ALOPF15 15
|
||||
#define ALOPF16 16
|
||||
#define ALOPF21 17
|
||||
#define ALOPF21_MERGE 18
|
||||
#define ALOPF22 19
|
||||
#define MERGE 20
|
||||
#define MMURR 21
|
||||
#define MMURW 22
|
||||
#define AAURR 23
|
||||
#define AAURW 24
|
||||
#define ALOPF17 25
|
||||
|
||||
#define ALF_PART \
|
||||
u_int8_t alopf; \
|
||||
int need_mas; \
|
||||
u_int8_t opc; \
|
||||
int allowed_channels[6]
|
||||
|
||||
|
||||
#define MAS 1
|
||||
#define NO_MAS 0
|
||||
|
||||
/* ALES.opc2 values. See B.1.2 in iset.single. */
|
||||
#define EXT 0x1
|
||||
#define EXT1 0x2
|
||||
#define EXT2 0x3
|
||||
#define FLB 0x4
|
||||
#define FLH 0x5
|
||||
#define FLW 0x6
|
||||
#define FLD 0x7
|
||||
#define ICMB0 0x8
|
||||
#define ICMB1 0x9
|
||||
#define ICMB2 0xA
|
||||
#define ICMB3 0xB
|
||||
|
||||
#define FCMB0 0xC
|
||||
#define FCMB1 0xD
|
||||
#define PFCMB0 0XE
|
||||
#define PFCMB1 0xF
|
||||
#define LCMBD0 0x10
|
||||
#define LCMBD1 0x11
|
||||
#define LCMBQ0 0x12
|
||||
#define LCMBQ1 0x13
|
||||
#define QPFCMB0 0x16
|
||||
#define QPFCMB1 0x17
|
||||
|
||||
|
||||
/* ALES.opce values. */
|
||||
#define NONE 0xc0
|
||||
|
||||
|
||||
/* It seems that LAS doesn't support %xr's, that's
|
||||
why everywhere where an x-args is supposed we
|
||||
use a d-one. */
|
||||
typedef enum {
|
||||
SINGLE,
|
||||
DOUBLE,
|
||||
QUAD,
|
||||
QPACKED
|
||||
} e2k_register_format;
|
||||
|
||||
|
||||
#define ARGS_S SINGLE
|
||||
#define ARGS_D DOUBLE
|
||||
#define ARGS_Q QUAD
|
||||
#define ARGS_P QPACKED
|
||||
|
||||
#define ARGS_SS {SINGLE, SINGLE}
|
||||
#define ARGS_SD {SINGLE, DOUBLE}
|
||||
#define ARGS_SQ {SINGLE, QUAD}
|
||||
#define ARGS_DS {DOUBLE, SINGLE}
|
||||
#define ARGS_DD {DOUBLE, DOUBLE}
|
||||
#define ARGS_DQ {DOUBLE, QUAD}
|
||||
#define ARGS_DP {DOUBLE, QPACKED}
|
||||
#define ARGS_QS {QUAD, SINGLE}
|
||||
#define ARGS_PS {QPACKED, SINGLE}
|
||||
#define ARGS_QD {QUAD, DOUBLE}
|
||||
#define ARGS_PD {QPACKED, DOUBLE}
|
||||
#define ARGS_QQ {QUAD, QUAD}
|
||||
#define ARGS_PP {QPACKED, QPACKED}
|
||||
|
||||
#define ARGS_SSS {SINGLE, SINGLE, SINGLE}
|
||||
#define ARGS_SSD {SINGLE, SINGLE, DOUBLE}
|
||||
#define ARGS_SSQ {SINGLE, SINGLE, QUAD}
|
||||
#define ARGS_SSP {SINGLE, SINGLE, QPACKED}
|
||||
#define ARGS_SDD {SINGLE, DOUBLE, DOUBLE}
|
||||
#define ARGS_DSS {DOUBLE, SINGLE, SINGLE}
|
||||
#define ARGS_DSD {DOUBLE, SINGLE, DOUBLE}
|
||||
#define ARGS_DDS {DOUBLE, DOUBLE, SINGLE}
|
||||
#define ARGS_DDD {DOUBLE, DOUBLE, DOUBLE}
|
||||
#define ARGS_DDQ {DOUBLE, DOUBLE, QUAD}
|
||||
#define ARGS_DDP {DOUBLE, DOUBLE, QPACKED}
|
||||
#define ARGS_DQQ {DOUBLE, QUAD, QUAD}
|
||||
#define ARGS_DPP {DOUBLE, QPACKED, QPACKED}
|
||||
#define ARGS_QSS {QUAD, SINGLE, SINGLE}
|
||||
#define ARGS_QSD {QUAD, SINGLE, DOUBLE}
|
||||
#define ARGS_QSQ {QUAD, SINGLE, QUAD}
|
||||
#define ARGS_PSP {QPACKED, SINGLE, QPACKED}
|
||||
#define ARGS_QSP {QUAD, SINGLE, QPACKED}
|
||||
#define ARGS_QDQ {QUAD, DOUBLE, QUAD}
|
||||
#define ARGS_PDP {QPACKED, DOUBLE, QPACKED}
|
||||
#define ARGS_QQD {QUAD, QUAD, DOUBLE}
|
||||
#define ARGS_PPD {QPACKED, QPACKED, DOUBLE}
|
||||
#define ARGS_QQQ {QUAD, QUAD, QUAD}
|
||||
#define ARGS_PPP {QPACKED, QPACKED, QPACKED}
|
||||
|
||||
#define ARGS_SSSS {SINGLE, SINGLE, SINGLE, SINGLE}
|
||||
#define ARGS_DDSD {DOUBLE, DOUBLE, SINGLE, DOUBLE}
|
||||
#define ARGS_DDDD {DOUBLE, DOUBLE, DOUBLE, DOUBLE}
|
||||
#define ARGS_QQQQ {QUAD, QUAD, QUAD, QUAD}
|
||||
#define ARGS_PPPP {QPACKED, QPACKED, QPACKED, QPACKED}
|
||||
|
||||
#define ALL_SINGLE {SINGLE, SINGLE, SINGLE}
|
||||
#define ALL_DOUBLE {DOUBLE, DOUBLE, DOUBLE}
|
||||
|
||||
|
||||
|
||||
typedef struct e2k_opcode_templ
|
||||
{
|
||||
COMMON_PART;
|
||||
} e2k_opcode_templ;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
COMMON_PART;
|
||||
ALF_PART;
|
||||
} e2k_alf_opcode_templ;
|
||||
|
||||
|
||||
|
||||
#define ALF1_PART \
|
||||
e2k_register_format arg_fmt[3]
|
||||
|
||||
typedef struct
|
||||
{
|
||||
COMMON_PART;
|
||||
ALF_PART;
|
||||
ALF1_PART;
|
||||
} e2k_alf1_opcode_templ;
|
||||
|
||||
|
||||
#define ALF2_PART \
|
||||
e2k_register_format arg_fmt[2]; \
|
||||
u_int8_t opce
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
COMMON_PART;
|
||||
ALF_PART;
|
||||
ALF2_PART;
|
||||
} e2k_alf2_opcode_templ;
|
||||
|
||||
|
||||
|
||||
#define ALF3_PART \
|
||||
e2k_register_format arg_fmt[3]
|
||||
|
||||
typedef struct
|
||||
{
|
||||
COMMON_PART;
|
||||
ALF_PART;
|
||||
ALF3_PART;
|
||||
} e2k_alf3_opcode_templ;
|
||||
|
||||
|
||||
#define ALOPF12_PART \
|
||||
e2k_register_format arg_fmt[2]; \
|
||||
u_int8_t opce; \
|
||||
u_int8_t ales_opce; \
|
||||
u_int8_t ales_opc2
|
||||
|
||||
typedef struct
|
||||
{
|
||||
COMMON_PART;
|
||||
ALF_PART;
|
||||
ALOPF12_PART;
|
||||
} e2k_alopf12_opcode_templ;
|
||||
|
||||
|
||||
|
||||
#define ALOPF13_PART \
|
||||
e2k_register_format arg_fmt[3]; \
|
||||
u_int8_t ales_opce; \
|
||||
u_int8_t ales_opc2
|
||||
|
||||
typedef struct
|
||||
{
|
||||
COMMON_PART;
|
||||
ALF_PART;
|
||||
ALOPF13_PART;
|
||||
} e2k_alopf13_opcode_templ;
|
||||
|
||||
|
||||
|
||||
#define ALOPF15_PART \
|
||||
e2k_register_format arg_fmt
|
||||
|
||||
typedef struct
|
||||
{
|
||||
COMMON_PART;
|
||||
ALF_PART;
|
||||
ALOPF15_PART;
|
||||
} e2k_alopf15_opcode_templ;
|
||||
|
||||
typedef e2k_alopf15_opcode_templ e2k_alopf16_opcode_templ;
|
||||
|
||||
#define CMPsb 0x20
|
||||
#define CMPdb 0x21
|
||||
#define CMPANDsb 0x22
|
||||
#define FXCMPxb 0x2b
|
||||
#define FCMPdb 0x2f
|
||||
|
||||
typedef enum {
|
||||
CMPOPCE_0 = 0,
|
||||
CMPOPCE_1,
|
||||
CMPOPCE_2,
|
||||
CMPOPCE_3,
|
||||
CMPOPCE_4,
|
||||
CMPOPCE_5,
|
||||
CMPOPCE_6,
|
||||
CMPOPCE_7
|
||||
} cmpopce_t;
|
||||
|
||||
#define ALF7_PART \
|
||||
e2k_register_format arg_fmt[2]; \
|
||||
cmpopce_t cmpopce; \
|
||||
int implicit_nops;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
COMMON_PART;
|
||||
ALF_PART;
|
||||
ALF7_PART;
|
||||
} e2k_alf7_opcode_templ;
|
||||
|
||||
#define ALF9_PART \
|
||||
e2k_register_format arg_fmt;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
COMMON_PART;
|
||||
ALF_PART;
|
||||
ALF9_PART;
|
||||
} e2k_alf9_opcode_templ;
|
||||
|
||||
|
||||
#define ALF10_PART \
|
||||
e2k_register_format arg_fmt;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
COMMON_PART;
|
||||
ALF_PART;
|
||||
ALF10_PART;
|
||||
} e2k_alf10_opcode_templ;
|
||||
|
||||
|
||||
#define ALF8_PART \
|
||||
e2k_register_format arg_fmt; \
|
||||
cmpopce_t cmpopce
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
COMMON_PART;
|
||||
ALF_PART;
|
||||
ALF8_PART;
|
||||
} e2k_alf8_opcode_templ;
|
||||
|
||||
#define ALOPF11_PART \
|
||||
e2k_register_format arg_fmt[3]; \
|
||||
u_int8_t ales_opce; \
|
||||
u_int8_t ales_opc2[6]; \
|
||||
int explicit_ales25_v4
|
||||
|
||||
typedef struct
|
||||
{
|
||||
COMMON_PART;
|
||||
ALF_PART;
|
||||
ALOPF11_PART;
|
||||
} e2k_alopf11_opcode_templ;
|
||||
|
||||
|
||||
#define ALOPF11_LIT8_PART \
|
||||
u_int8_t max_lit8; \
|
||||
const char *warn
|
||||
|
||||
typedef struct
|
||||
{
|
||||
COMMON_PART;
|
||||
ALF_PART;
|
||||
ALOPF11_PART;
|
||||
ALOPF11_LIT8_PART;
|
||||
} e2k_alopf11_lit8_opcode_templ;
|
||||
|
||||
|
||||
#define ALOPF21_PART \
|
||||
e2k_register_format arg_fmt[4]; \
|
||||
u_int8_t ales_opc2;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
COMMON_PART;
|
||||
ALF_PART;
|
||||
ALOPF21_PART;
|
||||
} e2k_alopf21_opcode_templ;
|
||||
|
||||
|
||||
#define NO_LABEL 0
|
||||
#define EXPECT_LABEL 1
|
||||
|
||||
#define NO_CTPR {0, 0, 0}
|
||||
#define CTPR2 {0, 1, 0}
|
||||
#define CTPR3 {0, 0, 1}
|
||||
#define ALL_CTPRS {1, 1, 1}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
COMMON_PART;
|
||||
u_int8_t ctp_opc;
|
||||
int allowed_ctprs[3];
|
||||
int label_expected;
|
||||
} e2k_copf2_opcode_templ;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
COMMON_PART;
|
||||
unsigned id;
|
||||
} e2k_setcmd_opcode_templ;
|
||||
|
||||
#define MOVA_PART \
|
||||
u_int16_t opc; \
|
||||
e2k_register_format arg_fmt;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
COMMON_PART;
|
||||
MOVA_PART;
|
||||
} e2k_mova_opcode_templ;
|
||||
|
||||
|
||||
|
||||
|
||||
static int parse_alf_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
static int parse_copf2_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
static int parse_pref_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
static int parse_copf4_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
static int parse_nop_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
static int parse_setcmd_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
static int parse_setsft_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
static int parse_wait_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
static int parse_ct_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
static int parse_hcall_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
static int parse_ipd_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
|
||||
static int parse_loop_mode_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
static int parse_alc_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
static int parse_abn_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
static int parse_abp_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
static int parse_abg_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
static int parse_bap_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
static int parse_eap_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
|
||||
|
||||
static int parse_pass_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
static int parse_andp_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
static int parse_landp_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
static int parse_ibranch_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
static int parse_done_hret_glaunch_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
|
||||
static int parse_incr_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
static int parse_mova_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
static int parse_fapb_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
static int parse_movep_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
|
||||
static int parse_flushts_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
|
||||
static int parse_cpl_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
|
||||
static int parse_set_mark_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
static int parse_vfdi_args (char **s, const e2k_opcode_templ *t) { return 0; }
|
||||
|
||||
|
||||
|
||||
extern struct e2k_opcode_templ *e2k_opcode_templs[];
|
||||
extern size_t e2k_num_opcodes;
|
||||
|
||||
|
||||
typedef enum {
|
||||
WINDOW,
|
||||
BASED,
|
||||
GLOBAL,
|
||||
SPECIAL,
|
||||
AASTI
|
||||
} e2k_register_type;
|
||||
|
||||
typedef struct {
|
||||
u_int8_t idx;
|
||||
e2k_register_type type;
|
||||
e2k_register_format fmt;
|
||||
} e2k_generic_register;
|
||||
|
||||
|
||||
typedef enum {
|
||||
LITERAL_4 = -3,
|
||||
LITERAL_5,
|
||||
/* LITERAL_8 should be used exclusively for encoding ALEF2.opce
|
||||
in PSHUF{W,H}. */
|
||||
LITERAL_8,
|
||||
LITERAL_16,
|
||||
LITERAL_32,
|
||||
LITERAL_64
|
||||
} e2k_literal_size;
|
||||
|
||||
typedef struct {
|
||||
e2k_literal_size size;
|
||||
int sgnd;
|
||||
} e2k_literal_format;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int negated;
|
||||
int pred_num;
|
||||
int pred_fld;
|
||||
} e2k_pred;
|
||||
|
||||
/* The maximal possible number of ALCes in the wide instruction. */
|
||||
#define ALS_CHANNELS_NUMBER 6
|
||||
|
||||
#define opc_field \
|
||||
struct { \
|
||||
u_int8_t cop : 7; \
|
||||
u_int8_t spec : 1; \
|
||||
} opc
|
||||
|
||||
#define GENERIC_ALS \
|
||||
/* May be 1, 2, 3, 5, 6, 7, 8, 9, 10 for appropriate ALF's. */ \
|
||||
int fmt; \
|
||||
/* Pointer to a function which will finalize this ALS after all long \
|
||||
literals in the containing wide instruction have been \
|
||||
accommodated. */ \
|
||||
int (* finish) (struct e2k_als *); \
|
||||
/* The value of ALS which should be encoded. */ \
|
||||
union { \
|
||||
struct { \
|
||||
u_int8_t dst, src2, src1; \
|
||||
opc_field; \
|
||||
} alf1; \
|
||||
struct { \
|
||||
u_int8_t dst, src2, opce; \
|
||||
opc_field; \
|
||||
} alf2; \
|
||||
struct { \
|
||||
u_int8_t src3, src2, src1; \
|
||||
opc_field; \
|
||||
} alf3; \
|
||||
struct { \
|
||||
u_int8_t regn, src2, opce; \
|
||||
opc_field; \
|
||||
} alf5; \
|
||||
struct { \
|
||||
u_int8_t dst, none, regn; \
|
||||
opc_field; \
|
||||
} alf6; \
|
||||
struct { \
|
||||
struct { \
|
||||
u_int8_t pdst : 5; \
|
||||
u_int8_t cmpopce : 3; \
|
||||
} dst2; \
|
||||
u_int8_t src2, src1; \
|
||||
opc_field; \
|
||||
} alf7; \
|
||||
struct { \
|
||||
struct { \
|
||||
u_int8_t pdst : 5; \
|
||||
u_int8_t cmpopce : 3; \
|
||||
} dst2; \
|
||||
u_int8_t src2, opce; \
|
||||
opc_field; \
|
||||
} alf8; \
|
||||
struct { \
|
||||
u_int8_t dst; \
|
||||
u_int8_t opce1_lo; \
|
||||
u_int8_t opce1_hi; \
|
||||
opc_field; \
|
||||
} alf9; \
|
||||
struct { \
|
||||
u_int8_t src3; \
|
||||
u_int8_t opce1_lo; \
|
||||
u_int8_t opce1_hi; \
|
||||
opc_field; \
|
||||
} alf10; \
|
||||
u_int32_t val; \
|
||||
} u[2]; \
|
||||
\
|
||||
/* Therse two are used for quad ops occupying two channels. */ \
|
||||
unsigned real_als_nmb; \
|
||||
/* The first element in real_alses will always be the minor \
|
||||
channel number. I want the user to be able to write \
|
||||
stapq,5 instead of stapq,2. */ \
|
||||
unsigned real_alses[6][2]; \
|
||||
\
|
||||
/* This means that ALS{j,k}.src1 should contain the same value \
|
||||
in both channels. This is required to encode LDAPQ and STAPQ \
|
||||
properly. */ \
|
||||
int same_src1_quad; \
|
||||
\
|
||||
/* The number of valid placements. It can be 6 at maximum, which \
|
||||
corresponds to ALC0, . . , ALC5. */ \
|
||||
int plcmnt_nmb; \
|
||||
int pos[ALS_CHANNELS_NUMBER]; \
|
||||
/* The most optimal index in pos[]. */ \
|
||||
int optimal_plcmnt_idx
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
u_int8_t src3;
|
||||
u_int8_t opc2;
|
||||
} alef1;
|
||||
|
||||
struct {
|
||||
u_int8_t opce;
|
||||
u_int8_t opc2;
|
||||
} alef2;
|
||||
|
||||
u_int16_t hword;
|
||||
} e2k_ales;
|
||||
|
||||
|
||||
extern void init_opcode_templs (void);
|
||||
|
||||
extern int mcpu;
|
|
@ -7,6 +7,7 @@ common_ss.add_all(when: 'CONFIG_ARM_A64_DIS', if_true: libvixl_ss)
|
|||
common_ss.add(when: 'CONFIG_ARM_DIS', if_true: files('arm.c'))
|
||||
common_ss.add(when: 'CONFIG_CRIS_DIS', if_true: files('cris.c'))
|
||||
common_ss.add(when: 'CONFIG_HEXAGON_DIS', if_true: files('hexagon.c'))
|
||||
common_ss.add(when: 'CONFIG_E2K_DIS', if_true: files('e2k.c'))
|
||||
common_ss.add(when: 'CONFIG_HPPA_DIS', if_true: files('hppa.c'))
|
||||
common_ss.add(when: 'CONFIG_I386_DIS', if_true: files('i386.c'))
|
||||
common_ss.add(when: 'CONFIG_M68K_DIS', if_true: files('m68k.c'))
|
||||
|
|
|
@ -138,7 +138,7 @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
|
|||
/* !snan_bit_is_one, set all bits */
|
||||
frac = (1ULL << DECOMPOSED_BINARY_POINT) - 1;
|
||||
#elif defined(TARGET_I386) || defined(TARGET_X86_64) \
|
||||
|| defined(TARGET_MICROBLAZE)
|
||||
|| defined(TARGET_MICROBLAZE) || defined(TARGET_E2K)
|
||||
/* !snan_bit_is_one, set sign and msb */
|
||||
frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1);
|
||||
sign = 1;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,6 @@
|
|||
<feature name="org.mcst.gdb.elbrus-v2.linux">
|
||||
|
||||
<!-- 840 -->
|
||||
<reg name="idr" bitsize="64" type="uint64"/>
|
||||
|
||||
</feature>
|
|
@ -0,0 +1,6 @@
|
|||
<feature name="org.mcst.gdb.elbrus-v3.linux">
|
||||
|
||||
<!-- 841 -->
|
||||
<reg name="core_mode" bitsize="64" type="uint64"/>
|
||||
|
||||
</feature>
|
|
@ -0,0 +1,86 @@
|
|||
<feature name="org.mcst.gdb.elbrus-v5.linux">
|
||||
|
||||
<!-- This type seems to be common for %lsr1 and %ilcr1 -->
|
||||
<!-- lsr1 -->
|
||||
<struct id="lsr1_bits" size="8">
|
||||
<field name="lcnt_lo" start="0" end="31"/>
|
||||
<field name="lcnt_hi" start="32" end="63"/>
|
||||
</struct>
|
||||
|
||||
<union id="lsr1">
|
||||
<field name="dword" type="uint64"/>
|
||||
<field name="" type="lsr1_bits"/>
|
||||
</union>
|
||||
|
||||
|
||||
<reg name="lsr1" bitsize="64" type="lsr1"/>
|
||||
<reg name="ilcr1" bitsize="64" type="lsr1"/>
|
||||
|
||||
<reg name="_gext_v5_0" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_1" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_2" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_3" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_4" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_5" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_6" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_7" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_8" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_9" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_10" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_11" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_12" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_13" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_14" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_15" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_16" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_17" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_18" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_19" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_20" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_21" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_22" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_23" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_24" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_25" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_26" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_27" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_28" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_29" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_30" bitsize="16" type="uint64"/>
|
||||
<reg name="_gext_v5_31" bitsize="16" type="uint64"/>
|
||||
|
||||
<reg name="_gtag_v5_0" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_1" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_2" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_3" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_4" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_5" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_6" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_7" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_8" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_9" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_10" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_11" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_12" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_13" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_14" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_15" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_16" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_17" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_18" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_19" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_20" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_21" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_22" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_23" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_24" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_25" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_26" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_27" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_28" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_29" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_30" bitsize="8" type="uint8"/>
|
||||
<reg name="_gtag_v5_31" bitsize="8" type="uint8"/>
|
||||
|
||||
|
||||
</feature>
|
40
gdbstub.c
40
gdbstub.c
|
@ -2178,6 +2178,12 @@ static void handle_query_supported(GArray *params, void *user_ctx)
|
|||
gdbserver_state.multiprocess = true;
|
||||
}
|
||||
|
||||
#ifdef TARGET_E2K
|
||||
// TODO: qXfer:tags:write+
|
||||
// TODO: qXfer:packed_tags:read+
|
||||
g_string_append(gdbserver_state.str_buf, ";qXfer:tags:read+");
|
||||
#endif
|
||||
|
||||
g_string_append(gdbserver_state.str_buf, ";vContSupported+;multiprocess+");
|
||||
put_strbuf();
|
||||
}
|
||||
|
@ -2319,6 +2325,32 @@ static void handle_set_qemu_phy_mem_mode(GArray *params, void *user_ctx)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_E2K
|
||||
static void handle_query_e2k_tags_read(GArray *params, void *user_ctx)
|
||||
{
|
||||
E2KCPU *cpu = E2K_CPU(gdbserver_state.g_cpu);
|
||||
CPUE2KState *env = &cpu->env;
|
||||
target_ulong addr = get_param(params, 0)->val_ull;
|
||||
unsigned long len = get_param(params, 1)->val_ul;
|
||||
unsigned int i;
|
||||
int tags = 0;
|
||||
|
||||
g_string_assign(gdbserver_state.str_buf, "l");
|
||||
if (env->psp.base <= addr && addr < (env->psp.base + env->psp.size)) {
|
||||
target_ulong offset = addr - env->psp.base;
|
||||
tags = cpu_ldub_data(env, env->psp.base_tag + offset / 8);
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
int tag = (tags >> (i * 2)) & 0x3;
|
||||
g_string_append_c(gdbserver_state.str_buf, tag);
|
||||
}
|
||||
|
||||
put_packet_binary(gdbserver_state.str_buf->str,
|
||||
gdbserver_state.str_buf->len, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const GdbCmdParseEntry gdb_gen_query_set_common_table[] = {
|
||||
/* Order is important if has same prefix */
|
||||
{
|
||||
|
@ -2413,6 +2445,14 @@ static const GdbCmdParseEntry gdb_gen_query_table[] = {
|
|||
.cmd = "qemu.PhyMemMode",
|
||||
},
|
||||
#endif
|
||||
#ifdef TARGET_E2K
|
||||
{
|
||||
.handler = handle_query_e2k_tags_read,
|
||||
.cmd = "Xfer:tags:read::",
|
||||
.cmd_startswith = 1,
|
||||
.schema = "L,l0",
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
static const GdbCmdParseEntry gdb_gen_set_table[] = {
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
config ESCC
|
||||
bool
|
||||
|
||||
config ESCC_PCI
|
||||
bool
|
||||
depends on PCI
|
||||
select ESCC
|
||||
|
||||
config HTIF
|
||||
bool
|
||||
|
||||
|
@ -68,3 +73,6 @@ config SIFIVE_UART
|
|||
|
||||
config GOLDFISH_TTY
|
||||
bool
|
||||
|
||||
config ELBRUS_SIM_CONSOLE
|
||||
bool
|
||||
|
|
|
@ -33,6 +33,11 @@
|
|||
#include "ui/console.h"
|
||||
#include "trace.h"
|
||||
|
||||
#define CONFIG_ESCC_PCI0
|
||||
#ifdef CONFIG_ESCC_PCI0
|
||||
#include "hw/pci/pci.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Chipset docs:
|
||||
* "Z80C30/Z85C30/Z80230/Z85230/Z85233 SCC/ESCC User Manual",
|
||||
|
@ -878,9 +883,85 @@ static const TypeInfo escc_info = {
|
|||
.class_init = escc_class_init,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ESCC_PCI0
|
||||
#include "hw/pci/pci_bus.h"
|
||||
|
||||
#define TYPE_ESCC_PCI "escc-pci"
|
||||
struct ESCCPCIState {
|
||||
PCIDevice dev;
|
||||
|
||||
ESCCState escc;
|
||||
};
|
||||
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(ESCCPCIState, ESCC_PCI)
|
||||
|
||||
static void escc_pci_realize(PCIDevice *dev, Error **errp)
|
||||
{
|
||||
ESCCPCIState *pci = ESCC_PCI(dev);
|
||||
ESCCState *s = &pci->escc;
|
||||
|
||||
if (!sysbus_realize(SYS_BUS_DEVICE(s), errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
pci->dev.config[PCI_CLASS_PROG] = 0x02;
|
||||
pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
|
||||
|
||||
pci_register_bar(&pci->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio);
|
||||
|
||||
memory_region_add_subregion(pci_address_space(&pci->dev), 0x1000, &s->mmio);
|
||||
}
|
||||
|
||||
static void escc_pci_exit(PCIDevice *dev)
|
||||
{
|
||||
/*ESCCPCIState *pci = ESCC_PCI(dev);
|
||||
ESCCState *s = &pci->escc;
|
||||
|
||||
sysbus_unrealize(SYS_BUS_DEVICE(s));*/
|
||||
}
|
||||
|
||||
static void escc_pci_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass);
|
||||
pc->realize = escc_pci_realize;
|
||||
pc->exit = escc_pci_exit;
|
||||
pc->vendor_id = 0x1fff;
|
||||
pc->device_id = 0x8019;
|
||||
pc->revision = 1;
|
||||
pc->class_id = PCI_CLASS_COMMUNICATION_SERIAL;
|
||||
/* dc->vmsd = &vmstate_pci_serial; */
|
||||
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
|
||||
}
|
||||
|
||||
static void escc_pci_init(Object *o)
|
||||
{
|
||||
ESCCPCIState *ps = ESCC_PCI(o);
|
||||
|
||||
object_initialize_child(o, "escc", &ps->escc, TYPE_ESCC);
|
||||
|
||||
qdev_alias_all_properties(DEVICE(&ps->escc), o);
|
||||
}
|
||||
|
||||
static const TypeInfo escc_pci_info = {
|
||||
.name = TYPE_ESCC_PCI,
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(ESCCPCIState),
|
||||
.instance_init = escc_pci_init,
|
||||
.class_init = escc_pci_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ INTERFACE_CONVENTIONAL_PCI_DEVICE },
|
||||
{ },
|
||||
},
|
||||
};
|
||||
#endif /* CONFIG_ESCC_PCI */
|
||||
|
||||
static void escc_register_types(void)
|
||||
{
|
||||
type_register_static(&escc_info);
|
||||
#ifdef CONFIG_ESCC_PCI0
|
||||
type_register_static(&escc_pci_info);
|
||||
#endif /* CONFIG_ESCC_PCI */
|
||||
}
|
||||
|
||||
type_init(escc_register_types)
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Alibek Omarov
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2 or later, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "exec/memory.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/qdev-properties-system.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "chardev/char-fe.h"
|
||||
#include "hw/char/lmscon.h"
|
||||
#include "trace.h"
|
||||
|
||||
#define LMS_CONS_DATA_PORT 0x300UL /* On READ - data from keyboard */
|
||||
/* On WRITE - data to debug ouput */
|
||||
/* port (console/journal) */
|
||||
|
||||
#define LMS_CONS_STATUS_PORT 0x301UL /* On READ - data available on 0x300 */
|
||||
/* On WRITE - shift count for 0x304 */
|
||||
|
||||
#define LMS_NSOCK_BADDR_PORT 0x302UL /* On READ - network socket base addr*/
|
||||
/* On WRITE - the same. */
|
||||
|
||||
#define LMS_NSOCK_DATA_PORT 0x303UL /* On READ - data from network socket*/
|
||||
/* On WRITE - data to network socket*/
|
||||
|
||||
#define LMS_TRACE_CNTL_PORT 0x304UL /* On READ - state of the instruction*/
|
||||
/* counter */
|
||||
/* On WRITE - LMS tracer control */
|
||||
/* (1 - start, 0 - stop) */
|
||||
|
||||
#define LMS_TRACE_CNTL_OFF 0
|
||||
#define LMS_TRACE_CNTL_ON 1
|
||||
|
||||
static void lmscon_mem_write(void *opaque, hwaddr addr,
|
||||
uint64_t val, unsigned size)
|
||||
{
|
||||
LMSCONState *s = opaque;
|
||||
|
||||
trace_lmscon_write(addr, val, size);
|
||||
|
||||
if (!qemu_chr_fe_backend_connected(&s->chr))
|
||||
return;
|
||||
|
||||
switch(LMS_CONS_DATA_PORT + addr)
|
||||
{
|
||||
case LMS_CONS_DATA_PORT:
|
||||
if (size == 1) {
|
||||
s->tx = val;
|
||||
qemu_chr_fe_write_all(&s->chr, (uint8_t*)&s->tx, size);
|
||||
} else {
|
||||
qemu_log_mask(LOG_UNIMP, "%s: LMS_CONS_DATA_PORT unknown size %d\n",
|
||||
__func__, size);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_UNIMP, "%s: unimplemented lmscon packet %lx\n",
|
||||
__func__, LMS_CONS_DATA_PORT + addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t lmscon_mem_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
LMSCONState *s = opaque;
|
||||
uint64_t r = 0;
|
||||
|
||||
switch(LMS_CONS_DATA_PORT + addr)
|
||||
{
|
||||
case LMS_CONS_DATA_PORT:
|
||||
if (!qemu_chr_fe_backend_connected(&s->chr))
|
||||
r = 0xFFFFFFFF; /* port disabled */
|
||||
else qemu_chr_fe_read_all(&s->chr, (uint8_t*)&r, size);
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_UNIMP, "%s: unimplemented lmscon packet %lx\n",
|
||||
__func__, LMS_CONS_DATA_PORT + addr);
|
||||
break;
|
||||
}
|
||||
|
||||
trace_lmscon_read(addr, r, size);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static const MemoryRegionOps lmscon_mem_ops = {
|
||||
.read = lmscon_mem_read,
|
||||
.write = lmscon_mem_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.valid = {
|
||||
.min_access_size = 1,
|
||||
.max_access_size = 4,
|
||||
},
|
||||
};
|
||||
|
||||
static void lmscon_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
SysBusDevice *sb = SYS_BUS_DEVICE(dev);
|
||||
LMSCONState *s = LMSCON(dev);
|
||||
const uint64_t size = LMS_TRACE_CNTL_PORT - LMS_CONS_DATA_PORT + 1;
|
||||
|
||||
memory_region_init_io(&s->io, OBJECT(dev), &lmscon_mem_ops, s, "lmscon", size);
|
||||
|
||||
sysbus_add_io(sb, LMS_CONS_DATA_PORT, &s->io);
|
||||
sysbus_init_ioports(sb, LMS_CONS_DATA_PORT, size);
|
||||
}
|
||||
|
||||
static Property lmscon_properties[] = {
|
||||
DEFINE_PROP_CHR("chr", LMSCONState, chr),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void lmscon_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
dc->realize = lmscon_realize;
|
||||
|
||||
device_class_set_props(dc, lmscon_properties);
|
||||
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
|
||||
}
|
||||
|
||||
static TypeInfo lmscon_info = {
|
||||
.name = TYPE_LMSCON,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(LMSCONState),
|
||||
.class_init = lmscon_class_init
|
||||
};
|
||||
|
||||
static void lmscon_register_types(void)
|
||||
{
|
||||
type_register_static(&lmscon_info);
|
||||
}
|
||||
|
||||
type_init(lmscon_register_types)
|
|
@ -32,6 +32,7 @@ softmmu_ss.add(when: 'CONFIG_SIFIVE_UART', if_true: files('sifive_uart.c'))
|
|||
softmmu_ss.add(when: 'CONFIG_SH_SCI', if_true: files('sh_serial.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_STM32F2XX_USART', if_true: files('stm32f2xx_usart.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_MMUART', if_true: files('mchp_pfsoc_mmuart.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_ELBRUS_SIM_CONSOLE', if_true: files('lmscon.c'))
|
||||
|
||||
specific_ss.add(when: 'CONFIG_HTIF', if_true: files('riscv_htif.c'))
|
||||
specific_ss.add(when: 'CONFIG_TERMINAL3270', if_true: files('terminal3270.c'))
|
||||
|
|
|
@ -99,3 +99,7 @@ exynos_uart_rx_timeout(uint32_t channel, uint32_t stat, uint32_t intsp) "UART%d:
|
|||
|
||||
# cadence_uart.c
|
||||
cadence_uart_baudrate(unsigned baudrate) "baudrate %u"
|
||||
|
||||
# lmscon.c
|
||||
lmscon_read(uint64_t addr, uint64_t r, unsigned int size) "addr 0x%" PRIx64 " value 0x%" PRIx64 " size %u"
|
||||
lmscon_write(uint64_t addr, uint64_t val, unsigned int size) "addr 0x%" PRIx64 " value 0x%" PRIx64 " size %u"
|
||||
|
|
|
@ -0,0 +1,322 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Denis Drakhnya
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2 or later, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/datadir.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qapi/error.h"
|
||||
#include "trace.h"
|
||||
|
||||
#include "chardev/char-fe.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/reset.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/loader.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/pci/pci_bridge.h"
|
||||
#include "hw/e2k/e2k.h"
|
||||
#include "hw/e2k/bootinfo.h"
|
||||
#include "target/e2k/cpu.h"
|
||||
#include "elf.h"
|
||||
|
||||
#include "hw/char/escc.h"
|
||||
#include "hw/char/lmscon.h"
|
||||
|
||||
struct
|
||||
{
|
||||
target_ulong loadaddr;
|
||||
} reset_params;
|
||||
|
||||
DeviceState *cpu_get_current_apic(void)
|
||||
{
|
||||
if (current_cpu) {
|
||||
E2KCPU *cpu = E2K_CPU(current_cpu);
|
||||
return cpu->apic_state;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int pci_e2k_map_irq(PCIDevice *pci_dev, int irq_num)
|
||||
{
|
||||
return (irq_num + (pci_dev->devfn >> 3)) & 3;
|
||||
}
|
||||
|
||||
|
||||
static void e2k_cpu_reset(void *opaque)
|
||||
{
|
||||
E2KCPU *cpu = opaque;
|
||||
CPUState *cs = CPU(cpu);
|
||||
|
||||
cpu_reset(cs);
|
||||
|
||||
cpu_set_pc(cs, reset_params.loadaddr);
|
||||
}
|
||||
|
||||
static void cpus_init(E2KMachineState *e2kms)
|
||||
{
|
||||
MachineState *ms = MACHINE(e2kms);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ms->smp.cpus; i++) {
|
||||
Object *cpu = object_new(ms->cpu_type);
|
||||
|
||||
if (!qdev_realize(DEVICE(cpu), NULL, &error_fatal)) {
|
||||
error_report("failed to create cpu");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
qemu_register_reset(e2k_cpu_reset, cpu);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
static void lmscon_init(E2KMachineState *e2kms)
|
||||
{
|
||||
DeviceState *dev;
|
||||
|
||||
dev = qdev_new(TYPE_LMSCON);
|
||||
|
||||
qdev_prop_set_chr(dev, "chr", serial_hd(0));
|
||||
|
||||
if (!sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal)) {
|
||||
error_report("failed to create lmscon");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
static bootblock_struct_t *generate_bootblock(E2KMachineState *e2kms,
|
||||
ram_addr_t kernel_base, long kernel_size)
|
||||
{
|
||||
static bootblock_struct_t bootblock;
|
||||
boot_info_t *const bootinfo = &bootblock.info;
|
||||
MachineState *ms = MACHINE(e2kms);
|
||||
|
||||
memset(&bootblock, 0, sizeof(bootblock));
|
||||
|
||||
/* Set signature */
|
||||
bootinfo->signature = bootblock.x86_marker = X86BOOT_SIGNATURE;
|
||||
bootblock.bootblock_ver = BOOTBLOCK_VER;
|
||||
|
||||
/* Init CPU info */
|
||||
bootinfo->num_of_nodes = 1; /* TODO: numa */
|
||||
bootinfo->nodes_map = 0x1;
|
||||
bootinfo->num_of_cpus = ms->smp.cpus;
|
||||
|
||||
/* Init RAM banks */
|
||||
if(ms->ram_size > E2K_MLO_SIZE) {
|
||||
/* high mem */
|
||||
bootinfo->num_of_banks = 2;
|
||||
bootinfo->nodes_mem[0].banks[0].address = 0;
|
||||
bootinfo->nodes_mem[0].banks[0].size = E2K_MLO_SIZE;
|
||||
|
||||
bootinfo->nodes_mem[0].banks[1].address = E2K_HIMEM_BASE;
|
||||
bootinfo->nodes_mem[0].banks[1].size = ms->ram_size - E2K_MLO_SIZE;
|
||||
} else {
|
||||
/* low mem only */
|
||||
bootinfo->num_of_banks = 1;
|
||||
bootinfo->nodes_mem[0].banks[0].address = 0;
|
||||
bootinfo->nodes_mem[0].banks[0].size = ms->ram_size;
|
||||
}
|
||||
|
||||
bootinfo->kernel_base = kernel_base;
|
||||
bootinfo->kernel_size = kernel_size;
|
||||
|
||||
strncpy(bootinfo->kernel_args_string, ms->kernel_cmdline, sizeof(*bootinfo->kernel_args_string));
|
||||
bootinfo->kernel_args_string[sizeof(*bootinfo->kernel_args_string)] = 0;
|
||||
|
||||
return &bootblock;
|
||||
}
|
||||
|
||||
static bool e2k_kernel_init(E2KMachineState *e2kms, MemoryRegion *rom_memory)
|
||||
{
|
||||
MachineState *ms = MACHINE(e2kms);
|
||||
uint64_t entry, kernel_high;
|
||||
long size;
|
||||
MemoryRegion *kernel;
|
||||
|
||||
if (!ms->kernel_filename)
|
||||
return false;
|
||||
|
||||
/* FIXME: set ip to entry, for now it just equals to FIRMWARE_LOAD_ADDR */
|
||||
size = load_elf(ms->kernel_filename, NULL, NULL, NULL,
|
||||
&entry, NULL, &kernel_high, NULL, 0, EM_MCST_ELBRUS,
|
||||
0, 0);
|
||||
|
||||
if (size <= 0) {
|
||||
error_report("could not load kernel '%s': %s",
|
||||
ms->kernel_filename, load_elf_strerror(size));
|
||||
return false;
|
||||
}
|
||||
|
||||
e2kms->bootblock = generate_bootblock(e2kms, entry, size);
|
||||
|
||||
/* TODO: load initrd */
|
||||
|
||||
kernel = g_malloc(sizeof(*kernel));
|
||||
memory_region_init_ram(kernel, NULL, "e2k.kernel", size, &error_fatal);
|
||||
memory_region_add_subregion(rom_memory, entry, kernel);
|
||||
|
||||
reset_params.loadaddr = entry;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void firmware_init(E2KMachineState *e2kms, const char *default_filename,
|
||||
MemoryRegion *rom_memory)
|
||||
{
|
||||
MachineState *ms = MACHINE(e2kms);
|
||||
const char *firmware_name;
|
||||
char *filename;
|
||||
int size;
|
||||
MemoryRegion *firmware;
|
||||
|
||||
firmware_name = ms->firmware ?: default_filename;
|
||||
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, firmware_name);
|
||||
if (filename == NULL) {
|
||||
error_report("no firmware provided");
|
||||
exit(1);
|
||||
}
|
||||
size = get_image_size(filename);
|
||||
if (size < 0) {
|
||||
error_report("failed to get firmware size '%s'", filename);
|
||||
exit(1);
|
||||
}
|
||||
if (rom_add_file_fixed(firmware_name,
|
||||
E2K_BIOS_AREA_BASE, -1) != 0) {
|
||||
error_report("could not load firmware '%s'", firmware_name);
|
||||
exit(1);
|
||||
}
|
||||
g_free(filename);
|
||||
firmware = g_malloc(sizeof(*firmware));
|
||||
memory_region_init_ram(firmware, NULL, "e2k.firmware",
|
||||
E2K_BIOS_AREA_SIZE, &error_fatal);
|
||||
memory_region_add_subregion(rom_memory,
|
||||
E2K_BIOS_AREA_BASE, firmware);
|
||||
|
||||
reset_params.loadaddr = E2K_BIOS_AREA_BASE;
|
||||
}
|
||||
|
||||
static void e2k_gsi_handler(void *opaque, int n, int level)
|
||||
{
|
||||
GSIState *s = opaque;
|
||||
qemu_set_irq(s->ioapic_irq[n], level);
|
||||
}
|
||||
|
||||
#define ESCC_CLOCK 2457600
|
||||
|
||||
static PCIDevice *pci_init(E2KMachineState *e2kms, qemu_irq *pic)
|
||||
{
|
||||
PCIDevice *d;
|
||||
PCIBridge *br;
|
||||
|
||||
e2kms->bus = iohub_init(TYPE_IOHUB_PCI_HOST_BRIDGE, TYPE_IOHUB_PCI_DEVICE,
|
||||
&e2kms->iohub,
|
||||
get_system_memory(), get_system_io(), pic);
|
||||
|
||||
d = pci_new_multifunction(PCI_DEVFN(0, 0), true, TYPE_IOHUB_PCI_BRIDGE);
|
||||
br = PCI_BRIDGE(d);
|
||||
br->bus_name = "pci";
|
||||
pci_bridge_map_irq(br, TYPE_IOHUB_PCI_BRIDGE, pci_e2k_map_irq);
|
||||
pci_realize_and_unref(d, e2kms->bus, &error_fatal);
|
||||
|
||||
d = pci_new_multifunction(PCI_DEVFN(2, 2), true, "escc-pci");
|
||||
qdev_prop_set_uint32(DEVICE(d), "frequency", ESCC_CLOCK);
|
||||
qdev_prop_set_uint32(DEVICE(d), "it_shift", 0);
|
||||
qdev_prop_set_chr(DEVICE(d), "chrA", serial_hd(0));
|
||||
qdev_prop_set_chr(DEVICE(d), "chrB", serial_hd(1));
|
||||
qdev_prop_set_uint32(DEVICE(d), "chnBtype", escc_serial);
|
||||
qdev_prop_set_uint32(DEVICE(d), "chnAtype", escc_serial);
|
||||
|
||||
pci_realize_and_unref(d, e2kms->bus, &error_fatal);
|
||||
|
||||
return PCI_DEVICE(br);
|
||||
}
|
||||
|
||||
static void e2k_machine_init(MachineState *ms)
|
||||
{
|
||||
E2KMachineState *e2kms = E2K_MACHINE(ms);
|
||||
MemoryRegion *rom_memory;
|
||||
MemoryRegion *ram_below_4g, *ram_above_4g;
|
||||
qemu_irq *pic;
|
||||
|
||||
rom_memory = get_system_memory();
|
||||
|
||||
/* Init RAM banks */
|
||||
if(ms->ram_size > E2K_MLO_SIZE) {
|
||||
e2kms->above_4g_mem_size = ms->ram_size - E2K_MLO_SIZE;
|
||||
e2kms->below_4g_mem_size = E2K_MLO_SIZE;
|
||||
} else {
|
||||
e2kms->above_4g_mem_size = E2K_MLO_BASE;
|
||||
e2kms->below_4g_mem_size = ms->ram_size;
|
||||
}
|
||||
|
||||
ram_below_4g = g_malloc(sizeof(*ram_below_4g));
|
||||
memory_region_init_alias(ram_below_4g, NULL, "ram-below-4g", ms->ram,
|
||||
0, e2kms->below_4g_mem_size);
|
||||
memory_region_add_subregion(rom_memory, 0, ram_below_4g);
|
||||
if(e2kms->above_4g_mem_size > 0) {
|
||||
ram_above_4g = g_malloc(sizeof(*ram_above_4g));
|
||||
memory_region_init_alias(ram_above_4g, NULL, "ram-above-4g",
|
||||
ms->ram,
|
||||
e2kms->below_4g_mem_size,
|
||||
e2kms->above_4g_mem_size);
|
||||
memory_region_add_subregion(rom_memory, E2K_HIMEM_BASE, ram_above_4g);
|
||||
}
|
||||
|
||||
e2kms->ioapic_as = &address_space_memory;
|
||||
|
||||
if (!e2k_kernel_init(e2kms, rom_memory))
|
||||
firmware_init(e2kms, "e2k.bin", rom_memory);
|
||||
|
||||
e2kms->gsi_state = g_new0(GSIState, 1);
|
||||
pic = qemu_allocate_irqs(e2k_gsi_handler, e2kms->gsi_state, IOAPIC_NUM_PINS);
|
||||
|
||||
cpus_init(e2kms);
|
||||
/* lmscon_init(e2kms); */
|
||||
sic_init(e2kms);
|
||||
pci_init(e2kms, pic);
|
||||
}
|
||||
|
||||
static void e2k_machine_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
|
||||
mc->desc = "Generic E2K Machine";
|
||||
mc->init = e2k_machine_init;
|
||||
mc->default_machine_opts = "firmware=e2k.bin";
|
||||
mc->is_default = true;
|
||||
mc->max_cpus = 8;
|
||||
mc->default_cpu_type = "e8c"; // TODO
|
||||
mc->default_ram_id = "e2k.ram";
|
||||
}
|
||||
|
||||
static const TypeInfo e2k_machine_info = {
|
||||
.name = TYPE_E2K_MACHINE,
|
||||
.parent = TYPE_MACHINE,
|
||||
.instance_size = sizeof(E2KMachineState),
|
||||
.class_init = e2k_machine_class_init,
|
||||
};
|
||||
|
||||
static void e2k_machine_register_types(void)
|
||||
{
|
||||
type_register_static(&e2k_machine_info);
|
||||
}
|
||||
|
||||
type_init(e2k_machine_register_types)
|
|
@ -0,0 +1,6 @@
|
|||
e2k_ss = ss.source_set()
|
||||
e2k_ss.add(files('e2k.c', 'sic.c'))
|
||||
|
||||
#e2k_ss.add(when: 'CONFIG_ACPI', if_true: files('acpi-common.c'))
|
||||
|
||||
hw_arch += {'e2k': e2k_ss}
|
|
@ -0,0 +1,461 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Alibek Omarov
|
||||
*
|
||||
* System Interchange Controller emulation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2 or later, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/datadir.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qapi/error.h"
|
||||
#include "trace.h"
|
||||
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/reset.h"
|
||||
#include "hw/loader.h"
|
||||
#include "hw/e2k/e2k.h"
|
||||
#include "target/e2k/cpu.h"
|
||||
#include "elf.h"
|
||||
|
||||
struct SICState *sicregs;
|
||||
|
||||
#define SIC_rt_lcfg0 0x10
|
||||
#define SIC_rt_lcfg1 0x14
|
||||
#define SIC_rt_lcfg2 0x18
|
||||
#define SIC_rt_lcfg3 0x1c
|
||||
|
||||
#define SIC_rt_mhi0 0x20
|
||||
#define SIC_rt_mhi1 0x24
|
||||
#define SIC_rt_mhi2 0x28
|
||||
#define SIC_rt_mhi3 0x2c
|
||||
|
||||
#define SIC_rt_mlo0 0x30
|
||||
#define SIC_rt_mlo1 0x34
|
||||
#define SIC_rt_mlo2 0x38
|
||||
#define SIC_rt_mlo3 0x3c
|
||||
|
||||
#define SIC_rt_msi 0xb0
|
||||
#define SIC_rt_msi_h 0xb4
|
||||
#define SIC_rt_pcim0 0x40
|
||||
#define SIC_rt_pcim1 0x44
|
||||
#define SIC_rt_pcim2 0x48
|
||||
#define SIC_rt_pcim3 0x4c
|
||||
#define SIC_rt_pciio0 0x50
|
||||
#define SIC_rt_pciio1 0x54
|
||||
#define SIC_rt_pciio2 0x58
|
||||
#define SIC_rt_pciio3 0x5c
|
||||
#define SIC_rt_pcimp_b0 0x70
|
||||
#define SIC_rt_pcimp_b1 0x74
|
||||
#define SIC_rt_pcimp_b2 0x78
|
||||
#define SIC_rt_pcimp_b3 0x7c
|
||||
#define SIC_rt_pcimp_e0 0x80
|
||||
#define SIC_rt_pcimp_e1 0x84
|
||||
#define SIC_rt_pcimp_e2 0x88
|
||||
#define SIC_rt_pcimp_e3 0x8c
|
||||
#define SIC_rt_pcicfgb 0x90
|
||||
#define SIC_prepic_ctrl2 0x8030
|
||||
#define SIC_prepic_err_stat 0x8040
|
||||
#define SIC_prepic_err_int 0x8060
|
||||
#define SIC_prepic_linp0 0x8c00
|
||||
#define SIC_prepic_linp1 0x8c04
|
||||
#define SIC_prepic_linp2 0x8c08
|
||||
#define SIC_prepic_linp3 0x8c0c
|
||||
#define SIC_prepic_linp4 0x8c10
|
||||
#define SIC_prepic_linp5 0x8c14
|
||||
#define SIC_iommu_ctrl 0x0380
|
||||
#define SIC_iommu_ba_lo 0x0390
|
||||
#define SIC_iommu_dtba_lo 0x0398
|
||||
#define SIC_iommu_err 0x03b0
|
||||
#define SIC_iommu_err_info_lo 0x03b8
|
||||
|
||||
static uint64_t sic_mem_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
E2KMachineState *ms = opaque;
|
||||
SICState *regs = &ms->sicregs;
|
||||
uint64_t ret;
|
||||
int index;
|
||||
|
||||
index = addr & (E2K_SICREGS_SIZE - 1);
|
||||
switch (index) {
|
||||
case SIC_rt_lcfg0:
|
||||
ret = regs->rt_lcfg0;
|
||||
break;
|
||||
case SIC_rt_lcfg1:
|
||||
ret = regs->rt_lcfg1;
|
||||
break;
|
||||
case SIC_rt_lcfg2:
|
||||
ret = regs->rt_lcfg2;
|
||||
break;
|
||||
case SIC_rt_lcfg3:
|
||||
ret = regs->rt_lcfg3;
|
||||
break;
|
||||
case SIC_rt_mhi0:
|
||||
ret = regs->rt_mhi0.word;
|
||||
break;
|
||||
case SIC_rt_mhi1:
|
||||
ret = regs->rt_mhi1.word;
|
||||
break;
|
||||
case SIC_rt_mhi2:
|
||||
ret = regs->rt_mhi2.word;
|
||||
break;
|
||||
case SIC_rt_mhi3:
|
||||
ret = regs->rt_mhi3.word;
|
||||
break;
|
||||
case SIC_rt_mlo0:
|
||||
ret = regs->rt_mlo0.word;
|
||||
break;
|
||||
case SIC_rt_mlo1:
|
||||
ret = regs->rt_mlo1.word;
|
||||
break;
|
||||
case SIC_rt_mlo2:
|
||||
ret = regs->rt_mlo2.word;
|
||||
break;
|
||||
case SIC_rt_mlo3:
|
||||
ret = regs->rt_mlo3.word;
|
||||
break;
|
||||
case SIC_rt_msi:
|
||||
ret = regs->rt_msi & 0xffffffff;
|
||||
break;
|
||||
case SIC_rt_msi_h:
|
||||
ret = regs->rt_msi >> 32;
|
||||
break;
|
||||
case SIC_rt_pcim0:
|
||||
ret = regs->rt_pcim0.word;
|
||||
break;
|
||||
case SIC_rt_pcim1:
|
||||
ret = regs->rt_pcim1.word;
|
||||
break;
|
||||
case SIC_rt_pcim2:
|
||||
ret = regs->rt_pcim2.word;
|
||||
break;
|
||||
case SIC_rt_pcim3:
|
||||
ret = regs->rt_pcim3.word;
|
||||
break;
|
||||
case SIC_rt_pciio0:
|
||||
ret = regs->rt_pciio0.word;
|
||||
break;
|
||||
case SIC_rt_pciio1:
|
||||
ret = regs->rt_pciio1.word;
|
||||
break;
|
||||
case SIC_rt_pciio2:
|
||||
ret = regs->rt_pciio2.word;
|
||||
break;
|
||||
case SIC_rt_pciio3:
|
||||
ret = regs->rt_pciio3.word;
|
||||
break;
|
||||
case SIC_rt_pcimp_b0:
|
||||
ret = regs->rt_pcimp_b0.addr;
|
||||
break;
|
||||
case SIC_rt_pcimp_b1:
|
||||
ret = regs->rt_pcimp_b1.addr;
|
||||
break;
|
||||
case SIC_rt_pcimp_b2:
|
||||
ret = regs->rt_pcimp_b2.addr;
|
||||
break;
|
||||
case SIC_rt_pcimp_b3:
|
||||
ret = regs->rt_pcimp_b3.addr;
|
||||
break;
|
||||
case SIC_rt_pcimp_e0:
|
||||
ret = regs->rt_pcimp_e0.addr;
|
||||
break;
|
||||
case SIC_rt_pcimp_e1:
|
||||
ret = regs->rt_pcimp_e1.addr;
|
||||
break;
|
||||
case SIC_rt_pcimp_e2:
|
||||
ret = regs->rt_pcimp_e2.addr;
|
||||
break;
|
||||
case SIC_rt_pcimp_e3:
|
||||
ret = regs->rt_pcimp_e3.addr;
|
||||
break;
|
||||
case SIC_rt_pcicfgb:
|
||||
ret = regs->rt_pcicfgb.word;
|
||||
break;
|
||||
case SIC_prepic_ctrl2:
|
||||
ret = regs->prepic_ctrl2;
|
||||
break;
|
||||
case SIC_prepic_err_stat:
|
||||
ret = regs->prepic_err_stat;
|
||||
break;
|
||||
case SIC_prepic_err_int:
|
||||
ret = regs->prepic_err_int;
|
||||
break;
|
||||
case SIC_prepic_linp0:
|
||||
ret = regs->prepic_linp0;
|
||||
break;
|
||||
case SIC_prepic_linp1:
|
||||
ret = regs->prepic_linp1;
|
||||
break;
|
||||
case SIC_prepic_linp2:
|
||||
ret = regs->prepic_linp2;
|
||||
break;
|
||||
case SIC_prepic_linp3:
|
||||
ret = regs->prepic_linp3;
|
||||
break;
|
||||
case SIC_prepic_linp4:
|
||||
ret = regs->prepic_linp4;
|
||||
break;
|
||||
case SIC_prepic_linp5:
|
||||
ret = regs->prepic_linp5;
|
||||
break;
|
||||
case SIC_iommu_err:
|
||||
ret = regs->iommu_err;
|
||||
break;
|
||||
case SIC_iommu_err_info_lo:
|
||||
ret = regs->iommu_err_info;
|
||||
;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_UNIMP, "%s: unknown SIC register 0x%x\n", __func__, index);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
trace_sic_mem_readl(addr, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sic_mem_write(void *opaque, hwaddr addr, uint64_t val,
|
||||
unsigned size)
|
||||
{
|
||||
E2KMachineState *ms = opaque;
|
||||
SICState *regs = &ms->sicregs;
|
||||
int index;
|
||||
|
||||
index = addr & (E2K_SICREGS_SIZE - 1);
|
||||
|
||||
switch (index) {
|
||||
case SIC_rt_msi:
|
||||
regs->rt_msi = (regs->rt_msi & 0xffffffff00000000) | val;
|
||||
break;
|
||||
case SIC_rt_msi_h:
|
||||
regs->rt_msi = (regs->rt_msi & 0x00000000ffffffff) | (val << 32);
|
||||
break;
|
||||
case SIC_rt_mhi0:
|
||||
regs->rt_mhi0.word = val;
|
||||
break;
|
||||
case SIC_rt_mhi1:
|
||||
regs->rt_mhi1.word = val;
|
||||
break;
|
||||
case SIC_rt_mhi2:
|
||||
regs->rt_mhi2.word = val;
|
||||
break;
|
||||
case SIC_rt_mhi3:
|
||||
regs->rt_mhi3.word = val;
|
||||
break;
|
||||
case SIC_rt_mlo0:
|
||||
regs->rt_mlo0.word = val;
|
||||
break;
|
||||
case SIC_rt_mlo1:
|
||||
regs->rt_mlo1.word = val;
|
||||
break;
|
||||
case SIC_rt_mlo2:
|
||||
regs->rt_mlo2.word = val;
|
||||
break;
|
||||
case SIC_rt_mlo3:
|
||||
regs->rt_mlo3.word = val;
|
||||
break;
|
||||
case SIC_rt_pcim0:
|
||||
regs->rt_pcim0.word = val;
|
||||
break;
|
||||
case SIC_rt_pcim1:
|
||||
regs->rt_pcim1.word = val;
|
||||
break;
|
||||
case SIC_rt_pcim2:
|
||||
regs->rt_pcim2.word = val;
|
||||
break;
|
||||
case SIC_rt_pcim3:
|
||||
regs->rt_pcim3.word = val;
|
||||
break;
|
||||
case SIC_rt_pciio0:
|
||||
regs->rt_pciio0.word = val;
|
||||
break;
|
||||
case SIC_rt_pciio1:
|
||||
regs->rt_pciio1.word = val;
|
||||
break;
|
||||
case SIC_rt_pciio2:
|
||||
regs->rt_pciio2.word = val;
|
||||
break;
|
||||
case SIC_rt_pciio3:
|
||||
regs->rt_pciio3.word = val;
|
||||
break;
|
||||
case SIC_rt_pcimp_b0:
|
||||
regs->rt_pcimp_b0.addr = val;
|
||||
break;
|
||||
case SIC_rt_pcimp_b1:
|
||||
regs->rt_pcimp_b1.addr = val;
|
||||
break;
|
||||
case SIC_rt_pcimp_b2:
|
||||
regs->rt_pcimp_b2.addr = val;
|
||||
break;
|
||||
case SIC_rt_pcimp_b3:
|
||||
regs->rt_pcimp_b3.addr = val;
|
||||
break;
|
||||
case SIC_rt_pcimp_e0:
|
||||
regs->rt_pcimp_e0.addr = val;
|
||||
break;
|
||||
case SIC_rt_pcimp_e1:
|
||||
regs->rt_pcimp_e1.addr = val;
|
||||
break;
|
||||
case SIC_rt_pcimp_e2:
|
||||
regs->rt_pcimp_e2.addr = val;
|
||||
break;
|
||||
case SIC_rt_pcimp_e3:
|
||||
regs->rt_pcimp_e3.addr = val;
|
||||
break;
|
||||
case SIC_rt_pcicfgb:
|
||||
regs->rt_pcicfgb.word = val;
|
||||
break;
|
||||
case SIC_prepic_ctrl2:
|
||||
regs->prepic_ctrl2 = val;
|
||||
break;
|
||||
case SIC_prepic_err_stat:
|
||||
regs->prepic_err_stat = val;
|
||||
break;
|
||||
case SIC_prepic_err_int:
|
||||
regs->prepic_err_int = val;
|
||||
break;
|
||||
case SIC_prepic_linp0:
|
||||
regs->prepic_linp0 = val;
|
||||
break;
|
||||
case SIC_prepic_linp1:
|
||||
regs->prepic_linp1 = val;
|
||||
break;
|
||||
case SIC_prepic_linp2:
|
||||
regs->prepic_linp2 = val;
|
||||
break;
|
||||
case SIC_prepic_linp3:
|
||||
regs->prepic_linp3 = val;
|
||||
break;
|
||||
case SIC_prepic_linp4:
|
||||
regs->prepic_linp4 = val;
|
||||
break;
|
||||
case SIC_prepic_linp5:
|
||||
regs->prepic_linp5 = val;
|
||||
break;
|
||||
case SIC_iommu_ctrl:
|
||||
regs->iommu_ctrl = val;
|
||||
break;
|
||||
case SIC_iommu_ba_lo:
|
||||
regs->iommu_ptbar = val;
|
||||
break;
|
||||
case SIC_iommu_dtba_lo:
|
||||
regs->iommu_dtbar = val;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_UNIMP, "%s: unknown SIC register 0x%x\n", __func__, index);
|
||||
break;
|
||||
}
|
||||
|
||||
trace_sic_mem_writel(addr, val);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps sic_io_ops = {
|
||||
.read = sic_mem_read,
|
||||
.write = sic_mem_write,
|
||||
.impl = {
|
||||
.min_access_size = 1,
|
||||
.max_access_size = 4,
|
||||
},
|
||||
.valid = {
|
||||
.min_access_size = 1,
|
||||
.max_access_size = 4,
|
||||
},
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static void sic_reset(SICState *sic)
|
||||
{
|
||||
memset(sic, 0, sizeof(*sic));
|
||||
|
||||
sic->rt_lcfg0 = 0xb; /* BSP node */
|
||||
sic->rt_lcfg1 = 0x30;
|
||||
sic->rt_lcfg2 = 0x30;
|
||||
sic->rt_lcfg3 = 0x30;
|
||||
|
||||
sic->rt_mhi0.E2K_RT_MHI_reg =
|
||||
sic->rt_mhi1.E2K_RT_MHI_reg =
|
||||
sic->rt_mhi2.E2K_RT_MHI_reg =
|
||||
sic->rt_mhi3.E2K_RT_MHI_reg = 0;
|
||||
sic->rt_mhi0.E2K_RT_MHI_bgn =
|
||||
sic->rt_mhi1.E2K_RT_MHI_bgn =
|
||||
sic->rt_mhi2.E2K_RT_MHI_bgn =
|
||||
sic->rt_mhi3.E2K_RT_MHI_bgn = ~0;
|
||||
sic->rt_mhi0.E2K_RT_MHI_end =
|
||||
sic->rt_mhi1.E2K_RT_MHI_end =
|
||||
sic->rt_mhi2.E2K_RT_MHI_end =
|
||||
sic->rt_mhi3.E2K_RT_MHI_end = 0;
|
||||
|
||||
sic->rt_mlo0.E2K_RT_MLO_reg =
|
||||
sic->rt_mlo1.E2K_RT_MLO_reg =
|
||||
sic->rt_mlo2.E2K_RT_MLO_reg =
|
||||
sic->rt_mlo3.E2K_RT_MLO_reg = 0;
|
||||
sic->rt_mlo0.E2K_RT_MLO_bgn =
|
||||
sic->rt_mlo1.E2K_RT_MLO_bgn =
|
||||
sic->rt_mlo2.E2K_RT_MLO_bgn =
|
||||
sic->rt_mlo3.E2K_RT_MLO_bgn = ~0;
|
||||
sic->rt_mlo0.E2K_RT_MLO_end =
|
||||
sic->rt_mlo1.E2K_RT_MLO_end =
|
||||
sic->rt_mlo2.E2K_RT_MLO_end =
|
||||
sic->rt_mlo3.E2K_RT_MLO_end = 0;
|
||||
|
||||
sic->rt_pcim0.E2K_RT_PCIM_reg =
|
||||
sic->rt_pcim1.E2K_RT_PCIM_reg =
|
||||
sic->rt_pcim2.E2K_RT_PCIM_reg =
|
||||
sic->rt_pcim3.E2K_RT_PCIM_reg = 0;
|
||||
sic->rt_pcim0.E2K_RT_PCIM_bgn =
|
||||
sic->rt_pcim1.E2K_RT_PCIM_bgn =
|
||||
sic->rt_pcim2.E2K_RT_PCIM_bgn =
|
||||
sic->rt_pcim3.E2K_RT_PCIM_bgn = ~0;
|
||||
sic->rt_pcim0.E2K_RT_PCIM_end =
|
||||
sic->rt_pcim1.E2K_RT_PCIM_end =
|
||||
sic->rt_pcim2.E2K_RT_PCIM_end =
|
||||
sic->rt_pcim3.E2K_RT_PCIM_end = 0;
|
||||
|
||||
sic->rt_pciio0.E2K_RT_PCIIO_reg =
|
||||
sic->rt_pciio1.E2K_RT_PCIIO_reg =
|
||||
sic->rt_pciio2.E2K_RT_PCIIO_reg =
|
||||
sic->rt_pciio3.E2K_RT_PCIIO_reg = 0;
|
||||
sic->rt_pciio0.E2K_RT_PCIIO_bgn =
|
||||
sic->rt_pciio1.E2K_RT_PCIIO_bgn =
|
||||
sic->rt_pciio2.E2K_RT_PCIIO_bgn =
|
||||
sic->rt_pciio3.E2K_RT_PCIIO_bgn = ~0;
|
||||
sic->rt_pciio0.E2K_RT_PCIIO_end =
|
||||
sic->rt_pciio1.E2K_RT_PCIIO_end =
|
||||
sic->rt_pciio2.E2K_RT_PCIIO_end =
|
||||
sic->rt_pciio3.E2K_RT_PCIIO_end = 0;
|
||||
|
||||
sic->rt_pcimp_b0.E2K_RT_PCIMP_reg =
|
||||
sic->rt_pcimp_b1.E2K_RT_PCIMP_reg =
|
||||
sic->rt_pcimp_b2.E2K_RT_PCIMP_reg =
|
||||
sic->rt_pcimp_b3.E2K_RT_PCIMP_reg = 0;
|
||||
sic->rt_pcimp_b0.E2K_RT_PCIMP_bgn =
|
||||
sic->rt_pcimp_b1.E2K_RT_PCIMP_bgn =
|
||||
sic->rt_pcimp_b2.E2K_RT_PCIMP_bgn =
|
||||
sic->rt_pcimp_b3.E2K_RT_PCIMP_bgn = ~0;
|
||||
|
||||
sic->rt_pcimp_e0.E2K_RT_PCIMP_reg =
|
||||
sic->rt_pcimp_e1.E2K_RT_PCIMP_reg =
|
||||
sic->rt_pcimp_e2.E2K_RT_PCIMP_reg =
|
||||
sic->rt_pcimp_e3.E2K_RT_PCIMP_reg = 0;
|
||||
|
||||
sic->rt_pcicfgb.E2K_RT_PCICFGB_bgn = 0x8; /* see E2K_PCICFG_BASE */
|
||||
}
|
||||
|
||||
void sic_init(E2KMachineState *ms)
|
||||
{
|
||||
sic_reset(&ms->sicregs);
|
||||
memory_region_init_io(&ms->sicregion, OBJECT(ms), &sic_io_ops, ms, "sic-nbsr",
|
||||
E2K_SICREGS_SIZE);
|
||||
memory_region_add_subregion(get_system_memory(), E2K_SICREGS_BASE, &ms->sicregion);
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
# See docs/devel/tracing.txt for syntax documentation.
|
||||
|
||||
# e2k.c
|
||||
e2k_gsi_interrupt(int irqn, int level) "GSI interrupt #%d level:%d"
|
||||
|
||||
sic_mem_readl(uint64_t addr, uint32_t val) "0x%"PRIx64" = 0x%08x"
|
||||
sic_mem_writel(uint64_t addr, uint32_t val) "0x%"PRIx64" = 0x%08x"
|
|
@ -0,0 +1 @@
|
|||
#include "trace/trace-hw_e2k.h"
|
|
@ -18,9 +18,15 @@
|
|||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/thread.h"
|
||||
#include "hw/i386/apic_internal.h"
|
||||
#include "hw/i386/apic.h"
|
||||
#include "hw/i386/ioapic.h"
|
||||
#if defined(TARGET_E2K)
|
||||
# include "hw/e2k/apic_internal.h"
|
||||
# include "hw/e2k/apic.h"
|
||||
# include "hw/e2k/ioapic.h"
|
||||
#else
|
||||
# include "hw/i386/apic_internal.h"
|
||||
# include "hw/i386/apic.h"
|
||||
# include "hw/i386/ioapic.h"
|
||||
#endif
|
||||
#include "hw/intc/i8259.h"
|
||||
#include "hw/pci/msi.h"
|
||||
#include "qemu/host-utils.h"
|
||||
|
@ -497,6 +503,10 @@ static void apic_startup(APICCommonState *s, int vector_num)
|
|||
|
||||
void apic_sipi(DeviceState *dev)
|
||||
{
|
||||
#if defined(TARGET_E2K)
|
||||
/* TODO: e2k */
|
||||
abort();
|
||||
#else
|
||||
APICCommonState *s = APIC(dev);
|
||||
|
||||
cpu_reset_interrupt(CPU(s->cpu), CPU_INTERRUPT_SIPI);
|
||||
|
@ -505,6 +515,7 @@ void apic_sipi(DeviceState *dev)
|
|||
return;
|
||||
cpu_x86_load_seg_cache_sipi(s->cpu, s->sipi_vector);
|
||||
s->wait_for_sipi = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void apic_deliver(DeviceState *dev, uint8_t dest, uint8_t dest_mode,
|
||||
|
@ -653,6 +664,11 @@ static uint64_t apic_mem_read(void *opaque, hwaddr addr, unsigned size)
|
|||
|
||||
index = (addr >> 4) & 0xff;
|
||||
switch(index) {
|
||||
#ifdef TARGET_E2K
|
||||
case 0x01: /* base */
|
||||
val = cpu_get_apic_base(dev);
|
||||
break;
|
||||
#endif
|
||||
case 0x02: /* id */
|
||||
val = s->id << 24;
|
||||
break;
|
||||
|
@ -766,6 +782,11 @@ static void apic_mem_write(void *opaque, hwaddr addr, uint64_t val,
|
|||
trace_apic_mem_writel(addr, val);
|
||||
|
||||
switch(index) {
|
||||
#ifdef TARGET_E2K
|
||||
case 0x01: /* base */
|
||||
cpu_set_apic_base(dev, val);
|
||||
break;
|
||||
#endif
|
||||
case 0x02:
|
||||
s->id = (val >> 24);
|
||||
break;
|
||||
|
|
|
@ -23,8 +23,13 @@
|
|||
#include "qemu/module.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "hw/i386/apic.h"
|
||||
#include "hw/i386/apic_internal.h"
|
||||
#if defined(TARGET_E2K)
|
||||
# include "hw/e2k/apic.h"
|
||||
# include "hw/e2k/apic_internal.h"
|
||||
#else
|
||||
# include "hw/i386/apic.h"
|
||||
# include "hw/i386/apic_internal.h"
|
||||
#endif
|
||||
#include "trace.h"
|
||||
#include "hw/boards.h"
|
||||
#include "sysemu/hax.h"
|
||||
|
@ -117,9 +122,14 @@ void apic_enable_vapic(DeviceState *dev, hwaddr paddr)
|
|||
void apic_handle_tpr_access_report(DeviceState *dev, target_ulong ip,
|
||||
TPRAccess access)
|
||||
{
|
||||
#if defined(TARGET_E2K)
|
||||
/* TODO: e2k */
|
||||
abort();
|
||||
#else
|
||||
APICCommonState *s = APIC_COMMON(dev);
|
||||
|
||||
vapic_report_tpr_access(s->vapic, CPU(s->cpu), ip, access);
|
||||
#endif
|
||||
}
|
||||
|
||||
void apic_report_irq_delivered(int delivered)
|
||||
|
@ -286,7 +296,6 @@ static void apic_common_realize(DeviceState *dev, Error **errp)
|
|||
{
|
||||
APICCommonState *s = APIC_COMMON(dev);
|
||||
APICCommonClass *info;
|
||||
static DeviceState *vapic;
|
||||
uint32_t instance_id = s->initial_apic_id;
|
||||
|
||||
/* Normally initial APIC ID should be no more than hundreds */
|
||||
|
@ -295,6 +304,9 @@ static void apic_common_realize(DeviceState *dev, Error **errp)
|
|||
info = APIC_COMMON_GET_CLASS(s);
|
||||
info->realize(dev, errp);
|
||||
|
||||
#if !defined(TARGET_E2K)
|
||||
static DeviceState *vapic;
|
||||
|
||||
/* Note: We need at least 1M to map the VAPIC option ROM */
|
||||
if (!vapic && s->vapic_control & VAPIC_ENABLE_MASK &&
|
||||
!hax_enabled() && current_machine->ram_size >= 1024 * 1024) {
|
||||
|
@ -310,6 +322,7 @@ static void apic_common_realize(DeviceState *dev, Error **errp)
|
|||
}
|
||||
vmstate_register_with_alias_id(NULL, instance_id, &vmstate_apic_common,
|
||||
s, -1, 0, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void apic_common_unrealize(DeviceState *dev)
|
||||
|
|
|
@ -23,10 +23,17 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "monitor/monitor.h"
|
||||
|
||||
#if defined(TARGET_E2K)
|
||||
#include "hw/e2k/apic.h"
|
||||
#include "hw/e2k/ioapic.h"
|
||||
#include "hw/e2k/e2k.h"
|
||||
#else
|
||||
#include "hw/i386/apic.h"
|
||||
#include "hw/i386/ioapic.h"
|
||||
#include "hw/i386/ioapic_internal.h"
|
||||
#include "hw/i386/x86.h"
|
||||
#endif
|
||||
#include "hw/i386/ioapic_internal.h"
|
||||
#include "hw/intc/i8259.h"
|
||||
#include "hw/pci/msi.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
|
@ -90,7 +97,11 @@ static void ioapic_entry_parse(uint64_t entry, struct ioapic_entry_info *info)
|
|||
|
||||
static void ioapic_service(IOAPICCommonState *s)
|
||||
{
|
||||
#ifdef TARGET_E2K
|
||||
AddressSpace *ioapic_as = E2K_MACHINE(qdev_get_machine())->ioapic_as;
|
||||
#else
|
||||
AddressSpace *ioapic_as = X86_MACHINE(qdev_get_machine())->ioapic_as;
|
||||
#endif
|
||||
struct ioapic_entry_info info;
|
||||
uint8_t i;
|
||||
uint32_t mask;
|
||||
|
|
|
@ -47,6 +47,7 @@ subdir('alpha')
|
|||
subdir('arm')
|
||||
subdir('avr')
|
||||
subdir('cris')
|
||||
subdir('e2k')
|
||||
subdir('hppa')
|
||||
subdir('i386')
|
||||
subdir('m68k')
|
||||
|
|
|
@ -77,3 +77,7 @@ config MV64361
|
|||
bool
|
||||
select PCI
|
||||
select I8259
|
||||
|
||||
config PCI_IOHUB
|
||||
bool
|
||||
select PCI
|
||||
|
|
|
@ -0,0 +1,302 @@
|
|||
/*
|
||||
* QEMU IOHUB PCI Bridge Emulation
|
||||
*
|
||||
* Copyright (c) 2021 Alibek Omarov
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/e2k/e2k.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/pci/pci_host.h"
|
||||
#include "hw/pci/pci_bridge.h"
|
||||
#include "hw/pci-host/iohub.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qom/object.h"
|
||||
#include "trace.h"
|
||||
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(IOHUBState, IOHUB_PCI_HOST_BRIDGE)
|
||||
|
||||
struct IOHUBState {
|
||||
PCIHostState parent_obj;
|
||||
|
||||
qemu_irq *pic;
|
||||
};
|
||||
|
||||
/* PCI config address are 27-bit in length.
|
||||
* bit 20-27: bus number
|
||||
* bit 12-19: devfn
|
||||
* bit 0-11: device register address
|
||||
*/
|
||||
|
||||
#define IOHUB_CONFIG_ADDR_BUS(addr) (((addr) >> 20) & 0xff)
|
||||
#define IOHUB_CONFIG_ADDR_DEVFN(addr) (((addr) >> 12) & 0xff)
|
||||
#define IOHUB_CONFIG_ADDR_REG(addr) (((addr) >> 0) & 0xfff)
|
||||
#define TO_IOHUB_CONFIG_ADDR(bus, devfn, where) ((((bus) & 0xff) << 20) | (((devfn) & 0xff) << 12) | ((where) & 0xfff))
|
||||
#define TO_PCI_CONFIG_ADDR(bus, devfn, reg) ((((bus) & 0xff) << 16) | (((devfn) & 0xff) << 8) | (((reg) & 0xff) << 0))
|
||||
|
||||
static void pci_e2k_set_irq(void *opaque, int irq_num, int level)
|
||||
{
|
||||
IOHUBState *s = opaque;
|
||||
qemu_irq *pic = s->pic;
|
||||
|
||||
int npic = irq_num + ISA_NUM_IRQS - 1;
|
||||
if(npic == 15)
|
||||
{
|
||||
npic = 19;
|
||||
}
|
||||
qemu_set_irq(pic[npic], level);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
iohub_pci_config_addr(hwaddr addr, uint8_t *bus, uint8_t *devfn, uint16_t *reg)
|
||||
{
|
||||
*bus = IOHUB_CONFIG_ADDR_BUS(addr);
|
||||
*devfn = IOHUB_CONFIG_ADDR_DEVFN(addr);
|
||||
*reg = IOHUB_CONFIG_ADDR_REG(addr);
|
||||
|
||||
return TO_PCI_CONFIG_ADDR(*bus, *devfn, *reg);
|
||||
}
|
||||
|
||||
static uint64_t iohub_pci_config_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
uint8_t bus, devfn;
|
||||
uint16_t reg;
|
||||
uint64_t val;
|
||||
hwaddr conf_addr = iohub_pci_config_addr(addr, &bus, &devfn, ®);
|
||||
|
||||
val = pci_data_read(opaque, conf_addr, size);
|
||||
|
||||
trace_iohub_pci_config_read(addr, conf_addr, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), reg, val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void iohub_pci_config_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
|
||||
{
|
||||
uint8_t bus, devfn;
|
||||
uint16_t reg;
|
||||
hwaddr conf_addr = iohub_pci_config_addr(addr, &bus, &devfn, ®);
|
||||
|
||||
trace_iohub_pci_config_write(addr, conf_addr, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), reg, val);
|
||||
|
||||
pci_data_write(opaque, conf_addr, val, size);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps iohub_pci_config_ops = {
|
||||
.read = iohub_pci_config_read,
|
||||
.write = iohub_pci_config_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
PCIBus *iohub_init(const char *host_type, const char *pci_type,
|
||||
PCIIOHUBState **piohub_state,
|
||||
MemoryRegion *address_space_mem,
|
||||
MemoryRegion *address_space_io,
|
||||
qemu_irq *pic)
|
||||
{
|
||||
DeviceState *dev;
|
||||
SysBusDevice *sb;
|
||||
PCIDevice *d;
|
||||
PCIHostState *s;
|
||||
PCIBus *b;
|
||||
PCIIOHUBState *f;
|
||||
MemoryRegion *pci_address_space, *pci_config_as;
|
||||
|
||||
dev = qdev_new(host_type);
|
||||
s = PCI_HOST_BRIDGE(dev);
|
||||
sb = SYS_BUS_DEVICE(dev);
|
||||
IOHUB_PCI_HOST_BRIDGE(dev)->pic = pic;
|
||||
|
||||
pci_address_space = g_malloc(sizeof(*pci_address_space));
|
||||
memory_region_init_io(pci_address_space, OBJECT(dev), NULL, NULL, "pcimem", E2K_PCIMEM_SIZE);
|
||||
memory_region_add_subregion(address_space_mem, E2K_PCIMEM_BASE, pci_address_space);
|
||||
|
||||
s->bus = b = pci_root_bus_new(dev, NULL,
|
||||
pci_address_space,
|
||||
address_space_io,
|
||||
0, TYPE_PCI_BUS);
|
||||
|
||||
pci_bus_irqs(b, pci_e2k_set_irq, pci_e2k_map_irq, pic, 4);
|
||||
|
||||
object_property_add_child(qdev_get_machine(), "iohub", OBJECT(dev));
|
||||
sysbus_realize_and_unref(sb, &error_fatal);
|
||||
|
||||
pci_config_as = g_malloc(sizeof(*pci_config_as));
|
||||
memory_region_init_io(pci_config_as, OBJECT(dev), &iohub_pci_config_ops, s->bus, "pcicfg", E2K_PCICFG_SIZE);
|
||||
sysbus_init_mmio(sb, pci_config_as);
|
||||
sysbus_mmio_map(sb, 0, E2K_PCICFG_BASE);
|
||||
|
||||
d = pci_create_simple(b, PCI_DEVFN(1, 0), pci_type);
|
||||
f = *piohub_state = IOHUB_PCI_DEVICE(d);
|
||||
f->system_memory = address_space_mem;
|
||||
f->pci_address_space = pci_address_space;
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
static void iohub_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(oc);
|
||||
|
||||
k->vendor_id = 0x1fff;
|
||||
k->device_id = 0x8017;
|
||||
k->revision = 0x02;
|
||||
k->class_id = PCI_CLASS_BRIDGE_HOST;
|
||||
dc->desc = "IOHUB Host Bridge";
|
||||
dc->user_creatable = false;
|
||||
dc->hotpluggable = false;
|
||||
}
|
||||
|
||||
static const TypeInfo iohub_info = {
|
||||
.name = TYPE_IOHUB_PCI_DEVICE,
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(PCIIOHUBState),
|
||||
.class_init = iohub_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ INTERFACE_CONVENTIONAL_PCI_DEVICE },
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
static void iohub_pcihost_initfn(Object *obj)
|
||||
{
|
||||
PCIHostState *s = PCI_HOST_BRIDGE(obj);
|
||||
|
||||
memory_region_init_io(&s->conf_mem, obj, &pci_host_conf_le_ops, s,
|
||||
"pci-conf-idx", 4);
|
||||
memory_region_init_io(&s->data_mem, obj, &pci_host_data_le_ops, s,
|
||||
"pci-conf-data", 4);
|
||||
}
|
||||
|
||||
static void iohub_pcihost_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
PCIHostState *s = PCI_HOST_BRIDGE(dev);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
|
||||
sysbus_add_io(sbd, 0xcf8, &s->conf_mem);
|
||||
sysbus_init_ioports(sbd, 0xcf8, 4);
|
||||
|
||||
sysbus_add_io(sbd, 0xcfc, &s->data_mem);
|
||||
sysbus_init_ioports(sbd, 0xcfc, 4);
|
||||
|
||||
/* register iohub 0xcf8 port as coalesced pio */
|
||||
memory_region_set_flush_coalesced(&s->data_mem);
|
||||
memory_region_add_coalescing(&s->conf_mem, 0, 4);
|
||||
}
|
||||
|
||||
static void iohub_pcihost_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
dc->realize = iohub_pcihost_realize;
|
||||
dc->fw_name = "pci";
|
||||
dc->user_creatable = false;
|
||||
}
|
||||
|
||||
static const TypeInfo iohub_pcihost_info = {
|
||||
.name = TYPE_IOHUB_PCI_HOST_BRIDGE,
|
||||
.parent = TYPE_PCI_HOST_BRIDGE,
|
||||
.instance_size = sizeof(IOHUBState),
|
||||
.instance_init = iohub_pcihost_initfn,
|
||||
.class_init = iohub_pcihost_class_init,
|
||||
};
|
||||
|
||||
static void iohub_pcibridge_realize(PCIDevice *dev, Error **errp)
|
||||
{
|
||||
pci_set_word(dev->config + PCI_COMMAND, PCI_COMMAND_MEMORY);
|
||||
pci_bridge_initfn(dev, TYPE_PCI_BUS);
|
||||
|
||||
/*
|
||||
* command register:
|
||||
* According to PCI bridge spec, after reset
|
||||
* bus master bit is off
|
||||
* PCI_COMMAND_MEMORY is ON
|
||||
*/
|
||||
pci_set_word(dev->config + PCI_STATUS,
|
||||
PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
|
||||
PCI_STATUS_DEVSEL_MEDIUM);
|
||||
}
|
||||
|
||||
static uint32_t iohub_pcibridge_read_config(PCIDevice *d, uint32_t addr, int size)
|
||||
{
|
||||
uint8_t bus, devfn;
|
||||
uint16_t reg;
|
||||
uint32_t val;
|
||||
hwaddr conf_addr = iohub_pci_config_addr(addr, &bus, &devfn, ®);
|
||||
|
||||
val = pci_default_read_config(d, conf_addr, size);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void iohub_pcibridge_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int size)
|
||||
{
|
||||
uint8_t bus, devfn;
|
||||
uint16_t reg;
|
||||
hwaddr conf_addr = iohub_pci_config_addr(addr, &bus, &devfn, ®);
|
||||
|
||||
pci_bridge_write_config(d, conf_addr, val, size);
|
||||
}
|
||||
|
||||
static void iohub_pcibridge_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(oc);
|
||||
|
||||
k->realize = iohub_pcibridge_realize;
|
||||
k->exit = pci_bridge_exitfn;
|
||||
k->vendor_id = 0x1fff;
|
||||
k->device_id = 0x8000;
|
||||
k->revision = 0x10;
|
||||
k->class_id = PCI_CLASS_BRIDGE_PCI;
|
||||
k->config_write = iohub_pcibridge_write_config;
|
||||
k->config_read = iohub_pcibridge_read_config;
|
||||
k->is_bridge = true;
|
||||
dc->desc = "IOHUB PCI2PCI Bridge";
|
||||
dc->reset = pci_bridge_reset;
|
||||
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo iohub_pcibridge_info = {
|
||||
.name = TYPE_IOHUB_PCI_BRIDGE,
|
||||
.parent = TYPE_PCI_BRIDGE,
|
||||
.instance_size = sizeof(PCIBridge),
|
||||
.class_init = iohub_pcibridge_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ INTERFACE_CONVENTIONAL_PCI_DEVICE },
|
||||
{ }
|
||||
}
|
||||
};
|
||||
|
||||
static void iohub_register_types(void)
|
||||
{
|
||||
type_register_static(&iohub_info);
|
||||
type_register_static(&iohub_pcihost_info);
|
||||
type_register_static(&iohub_pcibridge_info);
|
||||
}
|
||||
|
||||
type_init(iohub_register_types);
|
|
@ -12,6 +12,9 @@ pci_ss.add(when: 'CONFIG_XEN_IGD_PASSTHROUGH', if_true: files('xen_igd_pt.c'))
|
|||
pci_ss.add(when: 'CONFIG_REMOTE_PCIHOST', if_true: files('remote.c'))
|
||||
pci_ss.add(when: 'CONFIG_SH_PCI', if_true: files('sh_pci.c'))
|
||||
|
||||
# E2K/E90S devices
|
||||
pci_ss.add(when: 'CONFIG_PCI_IOHUB', if_true: files('iohub.c'))
|
||||
|
||||
# PPC devices
|
||||
pci_ss.add(when: 'CONFIG_RAVEN_PCI', if_true: files('raven.c'))
|
||||
pci_ss.add(when: 'CONFIG_GRACKLE_PCI', if_true: files('grackle.c'))
|
||||
|
|
|
@ -6,6 +6,10 @@ bonito_spciconf_small_access(uint64_t addr, unsigned size) "PCI config address i
|
|||
# grackle.c
|
||||
grackle_set_irq(int irq_num, int level) "set_irq num %d level %d"
|
||||
|
||||
# iohub.c
|
||||
iohub_pci_config_write(uint64_t addr, uint64_t confaddr, uint8_t bus, uint8_t slot, uint8_t func, uint16_t reg, uint64_t val) "addr 0x%"PRIx64" 0x%"PRIx64" dev %02x:%02x.%01d reg 0x%x val 0x%"PRIx64
|
||||
iohub_pci_config_read(uint64_t addr, uint64_t confaddr, uint8_t bus, uint8_t slot, uint8_t func, uint16_t reg, uint64_t val) "addr 0x%"PRIx64" 0x%"PRIx64" dev %02x:%02x.%01d reg 0x%x val 0x%"PRIx64
|
||||
|
||||
# mv64361.c
|
||||
mv64361_region_map(const char *name, uint64_t poffs, uint64_t size, uint64_t moffs) "Mapping %s 0x%"PRIx64"+0x%"PRIx64" @ 0x%"PRIx64
|
||||
mv64361_region_enable(const char *op, int num) "Should %s region %d"
|
||||
|
|
|
@ -373,6 +373,8 @@ void pci_bridge_initfn(PCIDevice *dev, const char *typename)
|
|||
if (!br->bus_name && dev->qdev.id && *dev->qdev.id) {
|
||||
br->bus_name = dev->qdev.id;
|
||||
}
|
||||
|
||||
printf("%s\n", br->bus_name);
|
||||
|
||||
qbus_create_inplace(sec_bus, sizeof(br->sec_bus), typename, DEVICE(dev),
|
||||
br->bus_name);
|
||||
|
|
|
@ -241,6 +241,23 @@ enum bfd_architecture
|
|||
#define bfd_mach_cris_v32 32
|
||||
#define bfd_mach_cris_v10_v32 1032
|
||||
bfd_arch_microblaze, /* Xilinx MicroBlaze. */
|
||||
bfd_arch_e2k, /* MCST E2K. */
|
||||
/* It's crucial that the underlying `bfd_mach_e2k*' have the same values as */
|
||||
/* the corresponding `E_E2K_MACH_*'s!!! */
|
||||
#define bfd_mach_e2k_generic 0
|
||||
#define bfd_mach_e2k_ev1 1
|
||||
/* This is interpreted as the common subset of all Elbrus V2 iterations.
|
||||
Currently it is the same as the common subset of all elbrus-2c+. */
|
||||
#define bfd_mach_e2k_ev2 2
|
||||
#define bfd_mach_e2k_ev3 3
|
||||
#define bfd_mach_e2k_ev4 4
|
||||
#define bfd_mach_e2k_ev5 5
|
||||
#define bfd_mach_e2k_ev6 6
|
||||
/* Values 16, 17 and 18 used to be reserved for the first three iterations
|
||||
of `elbrus-v2'. See `include/elf/e2k.h' for why they can't be reused right
|
||||
now. */
|
||||
#define bfd_mach_e2k_8c 19
|
||||
#define bfd_mach_e2k_1cplus 20
|
||||
bfd_arch_moxie, /* The Moxie core. */
|
||||
bfd_arch_ia64, /* HP/Intel ia64 */
|
||||
#define bfd_mach_ia64_elf64 64
|
||||
|
@ -407,6 +424,14 @@ typedef struct disassemble_info {
|
|||
int cap_mode;
|
||||
int cap_insn_unit;
|
||||
int cap_insn_split;
|
||||
|
||||
/* If non-zero then try not disassemble beyond this address, even if
|
||||
there are values left in the buffer. This address is the address
|
||||
of the nearest symbol forwards from the start of the disassembly,
|
||||
and it is assumed that it lies on the boundary between instructions.
|
||||
If an instruction spans this address then this is an error in the
|
||||
file being disassembled. */
|
||||
bfd_vma stop_vma;
|
||||
|
||||
} disassemble_info;
|
||||
|
||||
|
@ -462,6 +487,7 @@ int print_insn_riscv32 (bfd_vma, disassemble_info*);
|
|||
int print_insn_riscv64 (bfd_vma, disassemble_info*);
|
||||
int print_insn_rx(bfd_vma, disassemble_info *);
|
||||
int print_insn_hexagon(bfd_vma, disassemble_info *);
|
||||
int print_insn_e2k (bfd_vma, disassemble_info*);
|
||||
|
||||
#ifdef CONFIG_CAPSTONE
|
||||
bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size);
|
||||
|
|
|
@ -178,6 +178,9 @@ typedef struct mips_elf_abiflags_v0 {
|
|||
|
||||
#define EM_RX 173 /* Renesas RX family */
|
||||
|
||||
#define EM_MCST_ELBRUS 175 /* MCST Elbrus */
|
||||
#define EM_E2K_OLD 49 /* `e_machine' used in old binaries for E2K */
|
||||
|
||||
#define EM_RISCV 243 /* RISC-V */
|
||||
|
||||
#define EM_NANOMIPS 249 /* Wave Computing nanoMIPS */
|
||||
|
@ -1417,6 +1420,82 @@ typedef struct {
|
|||
#define EF_RISCV_RVE 0x0008
|
||||
#define EF_RISCV_TSO 0x0010
|
||||
|
||||
/* E2k specific definitions. */
|
||||
|
||||
/* Values for Elf32/64_Ehdr.e_flags. */
|
||||
|
||||
#define EF_E2K_IPD 3
|
||||
#define EF_E2K_X86APP 4
|
||||
#define EF_E2K_4MB_PAGES 8
|
||||
#define EF_E2K_INCOMPAT 16
|
||||
#define EF_E2K_PM 32
|
||||
#define EF_E2K_BUG_75842 64
|
||||
|
||||
/* E2k relocs. */
|
||||
|
||||
#define R_E2K_32_ABS 0 /* Direct 32 bit */
|
||||
#define R_E2K_32_PC 2 /* PC relative 32 bit */
|
||||
#define R_E2K_32_JMP_SLOT 8 /* Create PLT entry */
|
||||
#define R_E2K_32_COPY 9 /* Copy relocation */
|
||||
#define R_E2K_32_RELATIVE 10 /* Adjust by program base */
|
||||
#define R_E2K_32_IRELATIVE 11
|
||||
#define R_E2K_32_SIZE 12
|
||||
|
||||
#define R_E2K_64_ABS 50 /* Direct 64 bit */
|
||||
#define R_E2K_64_ABS_LIT 51 /* Direct 64 bit for literal */
|
||||
#define R_E2K_64_PC_LIT 54 /* PC relative 64 bit for literal */
|
||||
#define R_E2K_64_JMP_SLOT 63 /* Create PLT entry */
|
||||
#define R_E2K_64_COPY 64 /* Copy relocation */
|
||||
#define R_E2K_64_RELATIVE 65 /* Adjust by program base */
|
||||
#define R_E2K_64_RELATIVE_LIT 66 /* Adjust by program base for literal */
|
||||
#define R_E2K_64_IRELATIVE 67
|
||||
#define R_E2K_64_SIZE 68
|
||||
#define R_E2K_64_GOTOFF 69
|
||||
|
||||
#define R_E2K_TLS_GDMOD 70
|
||||
#define R_E2K_TLS_GDREL 71
|
||||
#define R_E2K_TLS_IE 74
|
||||
#define R_E2K_32_TLS_LE 75
|
||||
#define R_E2K_64_TLS_LE 76
|
||||
#define R_E2K_TLS_32_DTPMOD 80 /* ID of module containing symbol */
|
||||
#define R_E2K_TLS_32_DTPREL 81
|
||||
#define R_E2K_TLS_64_DTPMOD 82 /* ID of module containing symbol */
|
||||
#define R_E2K_TLS_64_DTPREL 83
|
||||
#define R_E2K_TLS_32_TPREL 84
|
||||
#define R_E2K_TLS_64_TPREL 85
|
||||
|
||||
#define R_E2K_AP 100
|
||||
#define R_E2K_PL 101
|
||||
|
||||
#define R_E2K_GOT 108 /* 32 bit GOT entry */
|
||||
#define R_E2K_GOTOFF 109 /* 32 bit offset to GOT */
|
||||
#define R_E2K_DISP 110 /* PC relative 28 bit for DISP */
|
||||
#define R_E2K_PREF 111
|
||||
#define R_E2K_NONE 112 /* No reloc */
|
||||
|
||||
|
||||
/* Legal values for d_tag field of Elf32_Dyn. */
|
||||
|
||||
/* FIXME: find out whether old dynamic tags may be renamed and their names
|
||||
* be used by modern ones or new names should be customized for modern tags.
|
||||
* This concerns DT_E2K_LAZY renamed to DT_E2K_LAZY_DEFECTIVE. */
|
||||
#define DT_E2K_LAZY_DEFECTIVE (DT_LOPROC + 0)
|
||||
#define DT_E2K_LAZY (DT_LOPROC + 1)
|
||||
|
||||
/* This tag will be hopefully used for a limited period of time. `DT_LOPROC + 1'
|
||||
* has already been reserved in glibc-2.16 and binutils-2.23.1 to mark
|
||||
* non-defective lazy binding implementation without this awful Bug #75842 taken
|
||||
* into account. */
|
||||
#define DT_E2K_LAZY_BUG_75842 (DT_LOPROC + 2)
|
||||
#define DT_E2K_LAZY_GOT (DT_LOPROC + 3)
|
||||
|
||||
#define DT_E2K_INIT_GOT (DT_LOPROC + 0x101c)
|
||||
#define DT_E2K_EXPORT_PL (DT_LOPROC + 0x101d)
|
||||
#define DT_E2K_EXPORT_PLSZ (DT_LOPROC + 0x101e)
|
||||
#define DT_E2K_REAL_PLTGOT (DT_LOPROC + 0x101f)
|
||||
|
||||
#define DT_E2K_NUM 0x1020
|
||||
|
||||
typedef struct elf32_rel {
|
||||
Elf32_Addr r_offset;
|
||||
Elf32_Word r_info;
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#pragma GCC poison TARGET_ARM
|
||||
#pragma GCC poison TARGET_CRIS
|
||||
#pragma GCC poison TARGET_HEXAGON
|
||||
#pragma GCC poison TARGET_E2K
|
||||
#pragma GCC poison TARGET_E2K32
|
||||
#pragma GCC poison TARGET_HPPA
|
||||
#pragma GCC poison TARGET_M68K
|
||||
#pragma GCC poison TARGET_MICROBLAZE
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Alibek Omarov
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2 or later, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef HW_LMSCON_H
|
||||
#define HW_LMSCON_H
|
||||
|
||||
#define TYPE_LMSCON "lmscon"
|
||||
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(LMSCONState, LMSCON)
|
||||
|
||||
struct LMSCONState {
|
||||
SysBusDevice parent;
|
||||
|
||||
MemoryRegion io;
|
||||
CharBackend chr;
|
||||
uint8_t tx;
|
||||
};
|
||||
|
||||
|
||||
#endif /* HW_LMSCON_H */
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef APIC_H
|
||||
#define APIC_H
|
||||
|
||||
|
||||
/* apic.c */
|
||||
void apic_deliver_irq(uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode,
|
||||
uint8_t vector_num, uint8_t trigger_mode);
|
||||
int apic_accept_pic_intr(DeviceState *s);
|
||||
void apic_deliver_pic_intr(DeviceState *s, int level);
|
||||
void apic_deliver_nmi(DeviceState *d);
|
||||
int apic_get_interrupt(DeviceState *s);
|
||||
void apic_reset_irq_delivered(void);
|
||||
int apic_get_irq_delivered(void);
|
||||
void cpu_set_apic_base(DeviceState *s, uint64_t val);
|
||||
uint64_t cpu_get_apic_base(DeviceState *s);
|
||||
void cpu_set_apic_tpr(DeviceState *s, uint8_t val);
|
||||
uint8_t cpu_get_apic_tpr(DeviceState *s);
|
||||
void apic_init_reset(DeviceState *s);
|
||||
void apic_sipi(DeviceState *s);
|
||||
void apic_poll_irq(DeviceState *d);
|
||||
void apic_designate_bsp(DeviceState *d, bool bsp);
|
||||
int apic_get_highest_priority_irr(DeviceState *dev);
|
||||
|
||||
/* pc.c */
|
||||
DeviceState *cpu_get_current_apic(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
* APIC support - internal interfaces
|
||||
*
|
||||
* Copyright (c) 2004-2005 Fabrice Bellard
|
||||
* Copyright (c) 2011 Jan Kiszka, Siemens AG
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef QEMU_APIC_INTERNAL_H
|
||||
#define QEMU_APIC_INTERNAL_H
|
||||
|
||||
#include "cpu.h"
|
||||
#include "exec/memory.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "target/e2k/cpu-qom.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
/* APIC Local Vector Table */
|
||||
#define APIC_LVT_TIMER 0
|
||||
#define APIC_LVT_THERMAL 1
|
||||
#define APIC_LVT_PERFORM 2
|
||||
#define APIC_LVT_LINT0 3
|
||||
#define APIC_LVT_LINT1 4
|
||||
#define APIC_LVT_ERROR 5
|
||||
#define APIC_LVT_NB 6
|
||||
|
||||
/* APIC delivery modes */
|
||||
#define APIC_DM_FIXED 0
|
||||
#define APIC_DM_LOWPRI 1
|
||||
#define APIC_DM_SMI 2
|
||||
#define APIC_DM_NMI 4
|
||||
#define APIC_DM_INIT 5
|
||||
#define APIC_DM_SIPI 6
|
||||
#define APIC_DM_EXTINT 7
|
||||
|
||||
/* APIC destination mode */
|
||||
#define APIC_DESTMODE_FLAT 0xf
|
||||
#define APIC_DESTMODE_CLUSTER 1
|
||||
|
||||
#define APIC_TRIGGER_EDGE 0
|
||||
#define APIC_TRIGGER_LEVEL 1
|
||||
|
||||
#define APIC_VECTOR_MASK 0xff
|
||||
#define APIC_DCR_MASK 0xf
|
||||
|
||||
#define APIC_LVT_TIMER_SHIFT 17
|
||||
#define APIC_LVT_MASKED_SHIFT 16
|
||||
#define APIC_LVT_LEVEL_TRIGGER_SHIFT 15
|
||||
#define APIC_LVT_REMOTE_IRR_SHIFT 14
|
||||
#define APIC_LVT_INT_POLARITY_SHIFT 13
|
||||
#define APIC_LVT_DELIV_STS_SHIFT 12
|
||||
#define APIC_LVT_DELIV_MOD_SHIFT 8
|
||||
|
||||
#define APIC_LVT_TIMER_TSCDEADLINE (2 << APIC_LVT_TIMER_SHIFT)
|
||||
#define APIC_LVT_TIMER_PERIODIC (1 << APIC_LVT_TIMER_SHIFT)
|
||||
#define APIC_LVT_MASKED (1 << APIC_LVT_MASKED_SHIFT)
|
||||
#define APIC_LVT_LEVEL_TRIGGER (1 << APIC_LVT_LEVEL_TRIGGER_SHIFT)
|
||||
#define APIC_LVT_REMOTE_IRR (1 << APIC_LVT_REMOTE_IRR_SHIFT)
|
||||
#define APIC_LVT_INT_POLARITY (1 << APIC_LVT_INT_POLARITY_SHIFT)
|
||||
#define APIC_LVT_DELIV_STS (1 << APIC_LVT_DELIV_STS_SHIFT)
|
||||
#define APIC_LVT_DELIV_MOD (7 << APIC_LVT_DELIV_MOD_SHIFT)
|
||||
|
||||
#define APIC_ESR_ILL_ADDRESS_SHIFT 7
|
||||
#define APIC_ESR_RECV_ILL_VECT_SHIFT 6
|
||||
#define APIC_ESR_SEND_ILL_VECT_SHIFT 5
|
||||
#define APIC_ESR_RECV_ACCEPT_SHIFT 3
|
||||
#define APIC_ESR_SEND_ACCEPT_SHIFT 2
|
||||
#define APIC_ESR_RECV_CHECK_SUM_SHIFT 1
|
||||
|
||||
#define APIC_ESR_ILLEGAL_ADDRESS (1 << APIC_ESR_ILL_ADDRESS_SHIFT)
|
||||
#define APIC_ESR_RECV_ILLEGAL_VECT (1 << APIC_ESR_RECV_ILL_VECT_SHIFT)
|
||||
#define APIC_ESR_SEND_ILLEGAL_VECT (1 << APIC_ESR_SEND_ILL_VECT_SHIFT)
|
||||
#define APIC_ESR_RECV_ACCEPT (1 << APIC_ESR_RECV_ACCEPT_SHIFT)
|
||||
#define APIC_ESR_SEND_ACCEPT (1 << APIC_ESR_SEND_ACCEPT_SHIFT)
|
||||
#define APIC_ESR_RECV_CHECK_SUM (1 << APIC_ESR_RECV_CHECK_SUM_SHIFT)
|
||||
#define APIC_ESR_SEND_CHECK_SUM 1
|
||||
|
||||
#define APIC_ICR_DEST_SHIFT 24
|
||||
#define APIC_ICR_DEST_SHORT_SHIFT 18
|
||||
#define APIC_ICR_TRIGGER_MOD_SHIFT 15
|
||||
#define APIC_ICR_LEVEL_SHIFT 14
|
||||
#define APIC_ICR_DELIV_STS_SHIFT 12
|
||||
#define APIC_ICR_DEST_MOD_SHIFT 11
|
||||
#define APIC_ICR_DELIV_MOD_SHIFT 8
|
||||
|
||||
#define APIC_ICR_DEST_SHORT (3 << APIC_ICR_DEST_SHORT_SHIFT)
|
||||
#define APIC_ICR_TRIGGER_MOD (1 << APIC_ICR_TRIGGER_MOD_SHIFT)
|
||||
#define APIC_ICR_LEVEL (1 << APIC_ICR_LEVEL_SHIFT)
|
||||
#define APIC_ICR_DELIV_STS (1 << APIC_ICR_DELIV_STS_SHIFT)
|
||||
#define APIC_ICR_DEST_MOD (1 << APIC_ICR_DEST_MOD_SHIFT)
|
||||
#define APIC_ICR_DELIV_MOD (7 << APIC_ICR_DELIV_MOD_SHIFT)
|
||||
|
||||
#define APIC_PR_CLASS_SHIFT 4
|
||||
#define APIC_PR_SUB_CLASS 0xf
|
||||
|
||||
#define APIC_LOGDEST_XAPIC_SHIFT 4
|
||||
#define APIC_LOGDEST_XAPIC_ID 0xf
|
||||
|
||||
#define APIC_LOGDEST_X2APIC_SHIFT 16
|
||||
#define APIC_LOGDEST_X2APIC_ID 0xffff
|
||||
|
||||
#define APIC_SPURIO_FOCUS_SHIFT 9
|
||||
#define APIC_SPURIO_ENABLED_SHIFT 8
|
||||
|
||||
#define APIC_SPURIO_FOCUS (1 << APIC_SPURIO_FOCUS_SHIFT)
|
||||
#define APIC_SPURIO_ENABLED (1 << APIC_SPURIO_ENABLED_SHIFT)
|
||||
|
||||
#define APIC_SV_DIRECTED_IO (1 << 12)
|
||||
#define APIC_SV_ENABLE (1 << 8)
|
||||
|
||||
#define VAPIC_ENABLE_BIT 0
|
||||
#define VAPIC_ENABLE_MASK (1 << VAPIC_ENABLE_BIT)
|
||||
|
||||
typedef struct APICCommonState APICCommonState;
|
||||
|
||||
#define TYPE_APIC_COMMON "apic-common"
|
||||
typedef struct APICCommonClass APICCommonClass;
|
||||
DECLARE_OBJ_CHECKERS(APICCommonState, APICCommonClass,
|
||||
APIC_COMMON, TYPE_APIC_COMMON)
|
||||
|
||||
struct APICCommonClass {
|
||||
DeviceClass parent_class;
|
||||
|
||||
DeviceRealize realize;
|
||||
DeviceUnrealize unrealize;
|
||||
void (*set_base)(APICCommonState *s, uint64_t val);
|
||||
void (*set_tpr)(APICCommonState *s, uint8_t val);
|
||||
uint8_t (*get_tpr)(APICCommonState *s);
|
||||
void (*enable_tpr_reporting)(APICCommonState *s, bool enable);
|
||||
void (*vapic_base_update)(APICCommonState *s);
|
||||
void (*external_nmi)(APICCommonState *s);
|
||||
void (*pre_save)(APICCommonState *s);
|
||||
void (*post_load)(APICCommonState *s);
|
||||
void (*reset)(APICCommonState *s);
|
||||
/* send_msi emulates an APIC bus and its proper place would be in a new
|
||||
* device, but it's convenient to have it here for now.
|
||||
*/
|
||||
void (*send_msi)(MSIMessage *msi);
|
||||
};
|
||||
|
||||
struct APICCommonState {
|
||||
/*< private >*/
|
||||
DeviceState parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
MemoryRegion io_memory;
|
||||
E2KCPU *cpu;
|
||||
uint32_t apicbase;
|
||||
uint8_t id; /* legacy APIC ID */
|
||||
uint32_t initial_apic_id;
|
||||
uint8_t version;
|
||||
uint8_t arb_id;
|
||||
uint8_t tpr;
|
||||
uint32_t spurious_vec;
|
||||
uint8_t log_dest;
|
||||
uint8_t dest_mode;
|
||||
uint32_t isr[8]; /* in service register */
|
||||
uint32_t tmr[8]; /* trigger mode register */
|
||||
uint32_t irr[8]; /* interrupt request register */
|
||||
uint32_t lvt[APIC_LVT_NB];
|
||||
uint32_t esr; /* error register */
|
||||
uint32_t icr[2];
|
||||
|
||||
uint32_t divide_conf;
|
||||
int count_shift;
|
||||
uint32_t initial_count;
|
||||
int64_t initial_count_load_time;
|
||||
int64_t next_time;
|
||||
QEMUTimer *timer;
|
||||
int64_t timer_expiry;
|
||||
int sipi_vector;
|
||||
int wait_for_sipi;
|
||||
|
||||
uint32_t vapic_control;
|
||||
DeviceState *vapic;
|
||||
hwaddr vapic_paddr; /* note: persistence via kvmvapic */
|
||||
bool legacy_instance_id;
|
||||
};
|
||||
|
||||
typedef struct VAPICState {
|
||||
uint8_t tpr;
|
||||
uint8_t isr;
|
||||
uint8_t zero;
|
||||
uint8_t irr;
|
||||
uint8_t enabled;
|
||||
} QEMU_PACKED VAPICState;
|
||||
|
||||
extern bool apic_report_tpr_access;
|
||||
|
||||
void apic_report_irq_delivered(int delivered);
|
||||
bool apic_next_timer(APICCommonState *s, int64_t current_time);
|
||||
void apic_enable_tpr_access_reporting(DeviceState *d, bool enable);
|
||||
void apic_enable_vapic(DeviceState *d, hwaddr paddr);
|
||||
|
||||
void vapic_report_tpr_access(DeviceState *dev, CPUState *cpu, target_ulong ip,
|
||||
TPRAccess access);
|
||||
|
||||
int apic_get_ppr(APICCommonState *s);
|
||||
uint32_t apic_get_current_count(APICCommonState *s);
|
||||
|
||||
static inline void apic_set_bit(uint32_t *tab, int index)
|
||||
{
|
||||
int i, mask;
|
||||
i = index >> 5;
|
||||
mask = 1 << (index & 0x1f);
|
||||
tab[i] |= mask;
|
||||
}
|
||||
|
||||
static inline int apic_get_bit(uint32_t *tab, int index)
|
||||
{
|
||||
int i, mask;
|
||||
i = index >> 5;
|
||||
mask = 1 << (index & 0x1f);
|
||||
return !!(tab[i] & mask);
|
||||
}
|
||||
|
||||
APICCommonClass *apic_get_class(void);
|
||||
|
||||
#endif /* QEMU_APIC_INTERNAL_H */
|
|
@ -0,0 +1,455 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Alibek Omarov
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2 or later, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef HW_E2K_BOOTINFO
|
||||
#define HW_E2K_BOOTINFO
|
||||
|
||||
/*
|
||||
* Ripped from Linux MCST fork
|
||||
*/
|
||||
|
||||
/*
|
||||
* 0x0:
|
||||
* 0x1: extended command line
|
||||
*/
|
||||
#define BOOTBLOCK_VER 0x1
|
||||
|
||||
#define KSTRMAX_SIZE 128
|
||||
#define KSTRMAX_SIZE_EX 512
|
||||
#define BIOS_INFO_SIGN_SIZE 8
|
||||
#define KERNEL_ARGS_STRING_EX_SIGN_SIZE 22
|
||||
#define BOOT_VER_STR_SIZE 128
|
||||
#define BOOTBLOCK_SIZE 0x1000 /* 1 PAGE_SIZE */
|
||||
#define X86BOOT_SIGNATURE 0x8086
|
||||
#define ROMLOADER_SIGNATURE 0xe200
|
||||
#define KVM_GUEST_SIGNATURE 0x20e2
|
||||
#define BIOS_INFO_SIGNATURE "E2KBIOS"
|
||||
#define KVM_INFO_SIGNATURE "E2KKVM"
|
||||
#define KERNEL_ARGS_STRING_EX_SIGNATURE "KERNEL_ARGS_STRING_EX"
|
||||
#define BOOT_KERNEL_ARGS_STRING_EX_SIGNATURE \
|
||||
boot_va_to_pa(KERNEL_ARGS_STRING_EX_SIGNATURE)
|
||||
|
||||
/*
|
||||
* Below is boot information that comes out of the x86 code of Linux/E2K
|
||||
* loader proto.
|
||||
*/
|
||||
|
||||
/* L_MAX_NODE_PHYS_BANKS = 4 sometimes is not enough, so we increase it to
|
||||
* an arbitary value (8 now). The old L_MAX_NODE_PHYS_BANKS we rename to
|
||||
* L_MAX_NODE_PHYS_BANKS_FUSTY and take in mind for boot_info compatibility.
|
||||
*
|
||||
* L_MAX_NODE_PHYS_BANKS_FUSTY and L_MAX_MEM_NUMNODES describe max size of
|
||||
* array of memory banks on all nodes and should be in accordance with old value
|
||||
* of L_MAX_PHYS_BANKS for compatibility with boot_info old structure (bank)
|
||||
* size, so L_MAX_NODE_PHYS_BANKS_FUSTY * L_MAX_MEM_NUMNODES should be
|
||||
* equal to 32.
|
||||
*/
|
||||
#define L_MAX_NODE_PHYS_BANKS 64 /* max number of memory banks */
|
||||
/* on one node */
|
||||
#define L_MAX_NODE_PHYS_BANKS_FUSTY 4 /* fusty max number of memory */
|
||||
/* banks on one node */
|
||||
#define L_MAX_PHYS_BANKS_EX 64 /* max number of memory banks */
|
||||
/* in banks_ex field of */
|
||||
/* boot_info */
|
||||
#define L_MAX_MEM_NUMNODES 8 /* max number of nodes in the */
|
||||
/* list of memory banks on */
|
||||
/* each node */
|
||||
#define L_MAX_BUSY_AREAS 4 /* max number of busy areas */
|
||||
/* occupied by BIOS and should be */
|
||||
/* kept unchanged by kernel to */
|
||||
/* support recovery mode */
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
typedef struct bank_info {
|
||||
uint64_t address; /* start address of bank */
|
||||
uint64_t size; /* size of bank in bytes */
|
||||
} bank_info_t;
|
||||
|
||||
typedef struct node_banks {
|
||||
bank_info_t banks[L_MAX_NODE_PHYS_BANKS_FUSTY]; /* memory banks array */
|
||||
/* of a node */
|
||||
} node_banks_t;
|
||||
|
||||
typedef struct boot_times {
|
||||
uint64_t arch;
|
||||
uint64_t unpack;
|
||||
uint64_t pci;
|
||||
uint64_t drivers1;
|
||||
uint64_t drivers2;
|
||||
uint64_t menu;
|
||||
uint64_t sm;
|
||||
uint64_t kernel;
|
||||
uint64_t reserved[8];
|
||||
} boot_times_t;
|
||||
|
||||
typedef struct bios_info {
|
||||
uint8_t signature[BIOS_INFO_SIGN_SIZE]; /* signature, */
|
||||
/* 'E2KBIOS' */
|
||||
uint8_t boot_ver[BOOT_VER_STR_SIZE]; /* boot version */
|
||||
uint8_t mb_type; /* mother board type */
|
||||
uint8_t chipset_type; /* chipset type */
|
||||
uint8_t cpu_type; /* cpu type */
|
||||
uint8_t kernel_args_string_ex[KSTRMAX_SIZE_EX]; /* extended command */
|
||||
/* line of kernel */
|
||||
/* used to pass */
|
||||
/* command line */
|
||||
/* from e2k BIOS */
|
||||
uint8_t reserved1; /* reserved1 */
|
||||
uint32_t cache_lines_damaged; /* number of damaged */
|
||||
/* cache lines */
|
||||
uint64_t nodes_mem_slabs_deprecated[52]; /* array of slabs */
|
||||
/* accessible memory */
|
||||
/* on each node */
|
||||
/* accessible memory */
|
||||
/* on each node */
|
||||
bank_info_t banks_ex[L_MAX_PHYS_BANKS_EX]; /* extended array of */
|
||||
/* descriptors of */
|
||||
/* banks of available */
|
||||
/* physical memory */
|
||||
uint64_t devtree; /* devtree pointer */
|
||||
uint32_t bootlog_addr; /* bootlog address */
|
||||
uint32_t bootlog_len; /* bootlog length */
|
||||
uint8_t uuid[16]; /* UUID boot device */
|
||||
} bios_info_t;
|
||||
|
||||
typedef struct boot_info {
|
||||
uint16_t signature; /* signature, 0x8086 */
|
||||
uint8_t target_mdl; /* target cpu model number */
|
||||
uint8_t reserved1; /* reserved1 */
|
||||
uint16_t reserved2; /* reserved2 */
|
||||
uint8_t vga_mode; /* vga mode */
|
||||
uint8_t num_of_banks; /* number of available physical memory banks */
|
||||
/* see below bank array */
|
||||
/* total number on all nodes or 0 */
|
||||
uint64_t kernel_base; /* base address to load kernel image */
|
||||
/* if 0 then BIOS can load at any address */
|
||||
/* but address should be large page size */
|
||||
/* aligned - 4 Mb */
|
||||
uint64_t kernel_size; /* kernel image byte's size */
|
||||
uint64_t ramdisk_base; /* base address to load RAM-disk */
|
||||
/* now not used */
|
||||
uint64_t ramdisk_size; /* RAM-disk byte's size */
|
||||
|
||||
uint16_t num_of_cpus; /* number of started physical CPU(s) */
|
||||
uint16_t mach_flags; /* machine identifacition flags */
|
||||
/* should be set by our romloader and BIOS */
|
||||
uint16_t num_of_busy; /* number of busy areas occupied by BIOS */
|
||||
/* see below busy array */
|
||||
uint16_t num_of_nodes; /* number of nodes on NUMA system */
|
||||
uint64_t mp_table_base; /* MP-table base address */
|
||||
uint64_t serial_base; /* base address of serial port for Am85c30 */
|
||||
/* Used for debugging purpose */
|
||||
uint64_t nodes_map; /* online nodes map */
|
||||
uint64_t mach_serialn; /* serial number of the machine */
|
||||
uint8_t mac_addr[6]; /* base MAC address for ethernet cards */
|
||||
uint16_t reserved3; /* reserved3 */
|
||||
|
||||
char kernel_args_string[KSTRMAX_SIZE]; /* command line of kernel */
|
||||
/* used to pass command line */
|
||||
/* from e2k BIOS */
|
||||
node_banks_t nodes_mem[L_MAX_MEM_NUMNODES]; /* array of */
|
||||
/* descriptors of banks of */
|
||||
/* available physical memory */
|
||||
/* on each node */
|
||||
bank_info_t busy[L_MAX_BUSY_AREAS]; /* descriptors of areas */
|
||||
/* occupied by BIOS, all this */
|
||||
/* shoud be kept in system */
|
||||
/* recovery mode */
|
||||
uint64_t cntp_info_deprecated[32]; /* control points */
|
||||
/* info to save and */
|
||||
/* restore them state */
|
||||
uint64_t dmp_deprecated[20]; /* Info for future work of */
|
||||
/* dump analyzer */
|
||||
uint64_t reserved4[13]; /* reserved4 */
|
||||
uint8_t mb_name[16]; /* Motherboard product name */
|
||||
uint32_t reserved5; /* reserved5 */
|
||||
uint32_t kernel_csum; /* kernel image control sum */
|
||||
bios_info_t bios; /* extended BIOS info */
|
||||
/* SHOULD BE LAST ITEM into this */
|
||||
/* structure */
|
||||
} boot_info_t;
|
||||
|
||||
typedef struct bootblock_struct {
|
||||
boot_info_t info; /* general kernel<->BIOS info */
|
||||
uint8_t /* zip area to make size of */
|
||||
/* bootblock struct - constant */
|
||||
gap[BOOTBLOCK_SIZE -
|
||||
sizeof (boot_info_t) -
|
||||
sizeof (boot_times_t) -
|
||||
1 - /* u8 : bootblock_ver */
|
||||
4 - /* u32 : reserved1 */
|
||||
2 - /* u16 : kernel_flags */
|
||||
1 - /* u8 : reserved2 */
|
||||
5 - /* u8 : number of cnt points */
|
||||
/* u8 : current # of cnt point */
|
||||
/* u8 : number of cnt points */
|
||||
/* ready in the memory */
|
||||
/* u8 : number of cnt points */
|
||||
/* saved on the disk */
|
||||
/* u8 : all control points */
|
||||
/* is created */
|
||||
8 - /* u64 : dump sector */
|
||||
8 - /* u64 : cnt point sector */
|
||||
2 - /* u16 : dump device */
|
||||
2 - /* u16 : cnt point device */
|
||||
2 - /* u16 : boot_flags */
|
||||
2]; /* u16 : x86_marker */
|
||||
uint8_t bootblock_ver; /* bootblock version number */
|
||||
uint32_t reserved1; /* reserved1 */
|
||||
boot_times_t boot_times; /* boot load times */
|
||||
uint16_t kernel_flags; /* kernel flags, boot should */
|
||||
/* not modify it */
|
||||
uint8_t reserved2; /* reserved2 */
|
||||
|
||||
uint8_t cnt_points_num_deprecated; /* number of control points */
|
||||
/* all memory will be devided */
|
||||
/* on this number of parts */
|
||||
uint8_t cur_cnt_point_deprecated; /* current # of active */
|
||||
/* control point (running */
|
||||
/* part) */
|
||||
uint8_t mem_cnt_points_deprecated; /* number of started control */
|
||||
/* points (ready in the memory) */
|
||||
uint8_t disk_cnt_points_deprecated; /* number of control points */
|
||||
/* saved on the disk (ready */
|
||||
/* to be loaded from disk) */
|
||||
uint8_t cnt_points_created_deprecated; /* all control points created */
|
||||
/* in the memory and on disk */
|
||||
uint64_t dump_sector_deprecated; /* start sector # to dump */
|
||||
/* physical memory */
|
||||
uint64_t cnt_point_sector_deprecated; /* start sector # to save */
|
||||
/* restore control points */
|
||||
uint16_t dump_dev_deprecated; /* disk # to dump memory */
|
||||
uint16_t cnt_point_dev_deprecated; /* disk # for save/restore */
|
||||
/* control point */
|
||||
|
||||
uint16_t boot_flags; /* boot flags: if non */
|
||||
/* zero then this structure */
|
||||
/* is recovery info */
|
||||
/* structure instead of boot */
|
||||
/* info structure */
|
||||
uint16_t x86_marker; /* marker of the end of x86 */
|
||||
/* boot block (0xAA55) */
|
||||
} bootblock_struct_t;
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
/*
|
||||
* The mother board types
|
||||
*/
|
||||
|
||||
#define MB_TYPE_MIN 0
|
||||
#define MB_TYPE_E2K_BASE 0x00
|
||||
#define MB_TYPE_ES2_BASE (MB_TYPE_E2K_BASE + 20)
|
||||
#define MB_TYPE_E1CP_BASE (MB_TYPE_E2K_BASE + 50)
|
||||
#define MB_TYPE_ES4_BASE (MB_TYPE_E2K_BASE + 70)
|
||||
#define MB_TYPE_E8C_BASE (MB_TYPE_E2K_BASE + 80)
|
||||
#define MB_TYPE_MAX a0
|
||||
|
||||
#define MB_TYPE_ES2_PLATO1 (MB_TYPE_ES2_BASE + 0)
|
||||
#define MB_TYPE_ES2_BUTTERFLY (MB_TYPE_ES2_BASE + 1)
|
||||
#define MB_TYPE_ES2_RTC_FM33256 (MB_TYPE_ES2_BASE + 2) /* FM332aa56 rtc */
|
||||
#define MB_TYPE_ES2_RTC_CY14B101P (MB_TYPE_ES2_BASE + 3) /* CY14B101P rtc */
|
||||
#define MB_TYPE_ES2_APORIA (MB_TYPE_ES2_BASE + 5) /* APORIA */
|
||||
#define MB_TYPE_ES2_NT (MB_TYPE_ES2_BASE + 6) /* Nosimyi terminal */
|
||||
/* Use this when CLKRs are not synchronized across the system */
|
||||
#define MB_TYPE_ES2_RTC_CY14B101P_MULTICLOCK (MB_TYPE_ES2_BASE + 7)
|
||||
#define MB_TYPE_ES2_CUB_COM (MB_TYPE_ES2_BASE + 8)
|
||||
#define MB_TYPE_ES2_MBCUB_C (MB_TYPE_ES2_BASE + 11)
|
||||
#define MB_TYPE_ES2_MB3S1_C (MB_TYPE_ES2_BUTTERFLY)
|
||||
#define MB_TYPE_ES2_MB3S_C_K (MB_TYPE_ES2_BASE + 14)
|
||||
#define MB_TYPE_ES2_MGA3D (MB_TYPE_ES2_BASE + 15)
|
||||
#define MB_TYPE_ES2_BC_M4211 (MB_TYPE_ES2_BASE + 16)
|
||||
#define MB_TYPE_ES2_EL2S4 (MB_TYPE_ES2_BASE + 17)
|
||||
/* By default all mb_versions > MB_TYPE_ES2_EL2S4
|
||||
* have cy14b101p rt clock. If no - fix is_cy14b101p_exist()
|
||||
* in arch/l/kernel/i2c-spi/core.c
|
||||
*/
|
||||
|
||||
#define MB_TYPE_E1CP_PMC (MB_TYPE_E1CP_BASE + 0) /* E1CP with PMC */
|
||||
#define MB_TYPE_E1CP_IOHUB2_RAZBRAKOVSCHIK /* IOHUB2 razbrakovschik */ \
|
||||
(MB_TYPE_E1CP_BASE + 1)
|
||||
#define MB_TYPE_MBE1C_PC (MB_TYPE_E1CP_BASE + 2) /* E1CP with PMC */
|
||||
|
||||
#define MB_TYPE_ES4_MBE2S_PC (MB_TYPE_ES4_BASE + 0)
|
||||
#define MB_TYPE_ES4_PC401 (MB_TYPE_ES4_BASE + 1)
|
||||
|
||||
#define MB_TYPE_E8C (MB_TYPE_E8C_BASE + 0)
|
||||
|
||||
|
||||
/*
|
||||
* The cpu types
|
||||
*/
|
||||
|
||||
#define CPU_TYPE_E2S 0x03 /* E2S */
|
||||
#define CPU_TYPE_ES2_DSP 0x04 /* E2C+ */
|
||||
#define CPU_TYPE_ES2_RU 0x06 /* E2C Micron */
|
||||
#define CPU_TYPE_E8C 0x07 /* E8C */
|
||||
#define CPU_TYPE_E1CP 0x08 /* E1C+ */
|
||||
#define CPU_TYPE_E8C2 0x09 /* E8C */
|
||||
#define CPU_TYPE_E12C 0xa /* E12C */
|
||||
#define CPU_TYPE_E16C 0xb /* E16C */
|
||||
#define CPU_TYPE_E2C3 0xc /* E2C3 */
|
||||
|
||||
#define CPU_TYPE_SIMUL 0x3e /* simulator */
|
||||
|
||||
#define CPU_TYPE_MASK 0x3f /* mask of CPU type */
|
||||
#define PROC_TYPE_MASK 0xc0 /* mask of MicroProcessor type */
|
||||
|
||||
#define GET_CPU_TYPE(type) (((type) & CPU_TYPE_MASK) >> 0)
|
||||
|
||||
/*
|
||||
* The cpu types names
|
||||
*/
|
||||
|
||||
#define GET_CPU_TYPE_NAME(type_field) \
|
||||
({ \
|
||||
unsigned char type = GET_CPU_TYPE(type_field); \
|
||||
char *name; \
|
||||
\
|
||||
switch (type) { \
|
||||
case CPU_TYPE_E2S: \
|
||||
name = "E2S"; \
|
||||
break; \
|
||||
case CPU_TYPE_ES2_DSP: \
|
||||
name = "E2C+DSP"; \
|
||||
break; \
|
||||
case CPU_TYPE_ES2_RU: \
|
||||
name = "E1C"; \
|
||||
break; \
|
||||
case CPU_TYPE_E8C: \
|
||||
name = "E8C"; \
|
||||
break; \
|
||||
case CPU_TYPE_E1CP: \
|
||||
name = "E1C+"; \
|
||||
break; \
|
||||
case CPU_TYPE_E8C2: \
|
||||
name = "E8C2"; \
|
||||
break; \
|
||||
case CPU_TYPE_E12C: \
|
||||
name = "E12C"; \
|
||||
break; \
|
||||
case CPU_TYPE_E16C: \
|
||||
name = "E16C"; \
|
||||
break; \
|
||||
case CPU_TYPE_E2C3: \
|
||||
name = "E2C3"; \
|
||||
break; \
|
||||
case CPU_TYPE_SIMUL: \
|
||||
name = "SIMUL"; \
|
||||
break; \
|
||||
default: \
|
||||
name = "unknown"; \
|
||||
} \
|
||||
\
|
||||
name; \
|
||||
})
|
||||
|
||||
/*
|
||||
* The mother board types names
|
||||
*/
|
||||
|
||||
#define GET_MB_TYPE_NAME(type) \
|
||||
({ \
|
||||
char *name; \
|
||||
\
|
||||
switch (type) { \
|
||||
case MB_TYPE_ES2_MB3S1_C: \
|
||||
name = "MB3S1/C"; \
|
||||
break; \
|
||||
case MB_TYPE_ES2_MBCUB_C: \
|
||||
case MB_TYPE_ES2_PLATO1: \
|
||||
name = "MBKUB/C"; \
|
||||
break; \
|
||||
case MB_TYPE_ES2_MB3S_C_K: \
|
||||
name = "MB3S/C-K"; \
|
||||
break; \
|
||||
case MB_TYPE_ES2_NT: \
|
||||
name = "NT-ELBRUS-S"; \
|
||||
break; \
|
||||
case MB_TYPE_ES2_CUB_COM: \
|
||||
name = "CUB-COM"; \
|
||||
break; \
|
||||
case MB_TYPE_ES2_RTC_FM33256: \
|
||||
name = "MONOCUB+FM33256"; \
|
||||
break; \
|
||||
case MB_TYPE_ES2_RTC_CY14B101P: \
|
||||
name = "MONOCUB"; \
|
||||
break; \
|
||||
case MB_TYPE_ES2_RTC_CY14B101P_MULTICLOCK: \
|
||||
name = "MP1C1/V"; \
|
||||
break; \
|
||||
case MB_TYPE_ES2_EL2S4: \
|
||||
name = "EL2S4"; \
|
||||
break; \
|
||||
case MB_TYPE_ES2_MGA3D: \
|
||||
name = "MGA3D"; \
|
||||
break; \
|
||||
case MB_TYPE_ES2_BC_M4211: \
|
||||
name = "BC-M4211"; \
|
||||
break; \
|
||||
case MB_TYPE_E1CP_PMC: \
|
||||
name = "E1C+ PMC"; \
|
||||
break; \
|
||||
case MB_TYPE_E1CP_IOHUB2_RAZBRAKOVSCHIK: \
|
||||
name = "IOHUB2 razbrakovschik"; \
|
||||
break; \
|
||||
case MB_TYPE_MBE1C_PC: \
|
||||
name = "MBE1C-PC"; \
|
||||
break; \
|
||||
case MB_TYPE_ES4_MBE2S_PC: \
|
||||
name = "MBE2S-PC"; \
|
||||
break; \
|
||||
case MB_TYPE_ES4_PC401: \
|
||||
name = "PC-401"; \
|
||||
break; \
|
||||
case MB_TYPE_E8C: \
|
||||
name = "E8C"; \
|
||||
break; \
|
||||
default: \
|
||||
name = "unknown"; \
|
||||
} \
|
||||
\
|
||||
name; \
|
||||
})
|
||||
|
||||
#define GET_MB_USED_IN(type) \
|
||||
({ \
|
||||
char *name; \
|
||||
\
|
||||
switch (type) { \
|
||||
case MB_TYPE_ES2_PLATO1: \
|
||||
name = "Plato with softreset error"; \
|
||||
break; \
|
||||
case MB_TYPE_ES2_MBCUB_C: \
|
||||
name = "APM VK-2, APM VK-120, BV632, BV631"; \
|
||||
break; \
|
||||
case MB_TYPE_ES2_MB3S1_C: \
|
||||
name = "ELBRUS-3C-CVS, ELBRUS-3C"; \
|
||||
break; \
|
||||
case MB_TYPE_ES2_RTC_FM33256: \
|
||||
name = "MONOCUB+FM33256"; \
|
||||
break; \
|
||||
case MB_TYPE_ES2_RTC_CY14B101P: \
|
||||
name = "MONOCUB-M, MONOCUB-PC"; \
|
||||
break; \
|
||||
default: \
|
||||
name = NULL; \
|
||||
} \
|
||||
\
|
||||
name; \
|
||||
})
|
||||
|
||||
#endif /* HW_E2K_BOOTINFO */
|
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Denis Drakhnya
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2 or later, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HW_E2K_H
|
||||
#define HW_E2K_H
|
||||
|
||||
#include "qemu-common.h"
|
||||
|
||||
#include "hw/boards.h"
|
||||
#include "qom/object.h"
|
||||
#include "hw/e2k/ioapic.h"
|
||||
#include "hw/e2k/bootinfo.h"
|
||||
#include "hw/e2k/memmap.h"
|
||||
#include "hw/pci-host/iohub.h"
|
||||
|
||||
/*
|
||||
* Read/Write RT_PCIIOj Regs
|
||||
*/
|
||||
typedef unsigned int e2k_rt_pciio_t; /* Read/write pointer (32 bits) */
|
||||
typedef struct e2k_rt_pciio_fields {
|
||||
e2k_rt_pciio_t unused1 : 12; /* [11:0] */
|
||||
e2k_rt_pciio_t bgn : 4; /* [15:12] */
|
||||
e2k_rt_pciio_t unused2 : 12; /* [27:16] */
|
||||
e2k_rt_pciio_t end : 4; /* [31:28] */
|
||||
} e2k_rt_pciio_fields_t;
|
||||
typedef union e2k_rt_pciio_struct { /* Structure of lower word */
|
||||
e2k_rt_pciio_fields_t fields; /* as fields */
|
||||
e2k_rt_pciio_t word; /* as entire register */
|
||||
} e2k_rt_pciio_struct_t;
|
||||
|
||||
#define E2K_SIC_ALIGN_RT_PCIIO 12 /* 4 Kb */
|
||||
#define E2K_SIC_SIZE_RT_PCIIO (1 << E2K_SIC_ALIGN_RT_PCIIO)
|
||||
#define E2K_RT_PCIIO_bgn fields.bgn
|
||||
#define E2K_RT_PCIIO_end fields.end
|
||||
#define E2K_RT_PCIIO_reg word
|
||||
|
||||
/*
|
||||
* Read/Write RT_PCIMj Regs
|
||||
*/
|
||||
typedef unsigned int e2k_rt_pcim_t; /* Read/write pointer (32 bits) */
|
||||
typedef struct e2k_rt_pcim_fields {
|
||||
e2k_rt_pcim_t unused1 : 11; /* [10:0] */
|
||||
e2k_rt_pcim_t bgn : 5; /* [15:11] */
|
||||
e2k_rt_pcim_t unused2 : 11; /* [26:16] */
|
||||
e2k_rt_pcim_t end : 5; /* [31:27] */
|
||||
} e2k_rt_pcim_fields_t;
|
||||
typedef union e2k_rt_pcim_struct { /* Structure of lower word */
|
||||
e2k_rt_pcim_fields_t fields; /* as fields */
|
||||
e2k_rt_pcim_t word; /* as entire register */
|
||||
} e2k_rt_pcim_struct_t;
|
||||
|
||||
#define E2K_SIC_ALIGN_RT_PCIM 27 /* 128 Mb */
|
||||
#define E2K_SIC_SIZE_RT_PCIM (1 << E2K_SIC_ALIGN_RT_PCIM)
|
||||
#define E2K_RT_PCIM_bgn fields.bgn
|
||||
#define E2K_RT_PCIM_end fields.end
|
||||
#define E2K_RT_PCIM_reg word
|
||||
|
||||
/*
|
||||
* Read/Write RT_PCIMPj Regs
|
||||
*/
|
||||
typedef unsigned int e2k_rt_pcimp_t; /* Read/write pointer (32 bits) */
|
||||
typedef struct e2k_rt_pcimp_struct {
|
||||
e2k_rt_pcimp_t addr; /* [PA_MSB: 0] */
|
||||
} e2k_rt_pcimp_struct_t;
|
||||
|
||||
#define E2K_SIC_ALIGN_RT_PCIMP 27 /* 128 Mb */
|
||||
#define E2K_SIC_SIZE_RT_PCIMP (1 << E2K_SIC_ALIGN_RT_PCIMP)
|
||||
#define E2K_RT_PCIMP_bgn addr
|
||||
#define E2K_RT_PCIMP_end addr
|
||||
#define E2K_RT_PCIMP_reg addr
|
||||
|
||||
/*
|
||||
* Read/Write RT_PCICFGB Reg
|
||||
*/
|
||||
typedef unsigned int e2k_rt_pcicfgb_t; /* Read/write pointer (32 bits) */
|
||||
typedef struct e2k_rt_pcicfgb_fields {
|
||||
e2k_rt_pcicfgb_t unused1 : 3; /* [2:0] */
|
||||
e2k_rt_pcicfgb_t bgn : 18; /* [20:3] */
|
||||
e2k_rt_pcicfgb_t unused2 : 11; /* [31:21] */
|
||||
} e2k_rt_pcicfgb_fields_t;
|
||||
typedef union e2k_rt_pcicfgb_struct { /* Structure of lower word */
|
||||
e2k_rt_pcicfgb_fields_t fields; /* as fields */
|
||||
e2k_rt_pcicfgb_t word; /* as entire register */
|
||||
} e2k_rt_pcicfgb_struct_t;
|
||||
|
||||
#define E2K_SIC_ALIGN_RT_PCICFGB 28 /* 256 Mb */
|
||||
#define E2K_SIC_SIZE_RT_PCICFGB (1 << E2K_SIC_ALIGN_RT_PCICFGB)
|
||||
#define E2K_RT_PCICFGB_bgn fields.bgn
|
||||
#define E2K_RT_PCICFGB_reg word
|
||||
#define RT_PCICFGB_NODE_BITS 2 /* 4 nodes */
|
||||
#define RT_PCICFGB_IOLINK_BITS 0 /* 0 IO links per node */
|
||||
|
||||
/*
|
||||
* Read/Write RT_MLOj Regs
|
||||
*/
|
||||
typedef unsigned int e2k_rt_mlo_t; /* Read/write pointer (32 bits) */
|
||||
typedef struct e2k_rt_mlo_fields {
|
||||
e2k_rt_mlo_t unused1 : 11; /* [10:0] */
|
||||
e2k_rt_mlo_t bgn : 5; /* [15:11] */
|
||||
e2k_rt_mlo_t unused2 : 11; /* [26:16] */
|
||||
e2k_rt_mlo_t end : 5; /* [31:27] */
|
||||
} e2k_rt_mlo_fields_t;
|
||||
typedef union e2k_rt_mlo_struct { /* Structure of lower word */
|
||||
e2k_rt_mlo_fields_t fields; /* as fields */
|
||||
e2k_rt_mlo_t word; /* as entire register */
|
||||
} e2k_rt_mlo_struct_t;
|
||||
|
||||
#define E2K_SIC_ALIGN_RT_MLO 27 /* 128 Mb */
|
||||
#define E2K_SIC_SIZE_RT_MLO (1 << E2K_SIC_ALIGN_RT_MLO)
|
||||
#define E2K_RT_MLO_bgn fields.bgn
|
||||
#define E2K_RT_MLO_end fields.end
|
||||
#define E2K_RT_MLO_reg word
|
||||
|
||||
/*
|
||||
* Read/Write RT_MHIj Regs
|
||||
*/
|
||||
typedef unsigned int e2k_rt_mhi_t; /* Read/write pointer (32 bits) */
|
||||
typedef struct e2k_rt_mhi_fields {
|
||||
e2k_rt_mhi_t bgn : 16; /* [15: 0] */
|
||||
e2k_rt_mhi_t end : 16; /* [31:16] */
|
||||
} e2k_rt_mhi_fields_t;
|
||||
typedef union e2k_rt_mhi_struct { /* Structure of lower word */
|
||||
e2k_rt_mhi_fields_t fields; /* as fields */
|
||||
e2k_rt_mhi_t word; /* as entire register */
|
||||
} e2k_rt_mhi_struct_t;
|
||||
|
||||
#define E2K_SIC_ALIGN_RT_MHI 32 /* 4 Gb */
|
||||
#define E2K_SIC_SIZE_RT_MHI (1UL << E2K_SIC_ALIGN_RT_MHI)
|
||||
#define E2K_RT_MHI_bgn fields.bgn
|
||||
#define E2K_RT_MHI_end fields.end
|
||||
#define E2K_RT_MHI_reg word
|
||||
|
||||
|
||||
typedef struct SICState {
|
||||
uint32_t rt_lcfg0;
|
||||
uint32_t rt_lcfg1;
|
||||
uint32_t rt_lcfg2;
|
||||
uint32_t rt_lcfg3;
|
||||
|
||||
e2k_rt_mhi_struct_t rt_mhi0;
|
||||
e2k_rt_mhi_struct_t rt_mhi1;
|
||||
e2k_rt_mhi_struct_t rt_mhi2;
|
||||
e2k_rt_mhi_struct_t rt_mhi3;
|
||||
|
||||
e2k_rt_mlo_struct_t rt_mlo0;
|
||||
e2k_rt_mlo_struct_t rt_mlo1;
|
||||
e2k_rt_mlo_struct_t rt_mlo2;
|
||||
e2k_rt_mlo_struct_t rt_mlo3;
|
||||
|
||||
e2k_rt_pcim_struct_t rt_pcim0;
|
||||
e2k_rt_pcim_struct_t rt_pcim1;
|
||||
e2k_rt_pcim_struct_t rt_pcim2;
|
||||
e2k_rt_pcim_struct_t rt_pcim3;
|
||||
e2k_rt_pciio_struct_t rt_pciio0;
|
||||
e2k_rt_pciio_struct_t rt_pciio1;
|
||||
e2k_rt_pciio_struct_t rt_pciio2;
|
||||
e2k_rt_pciio_struct_t rt_pciio3;
|
||||
e2k_rt_pcimp_struct_t rt_pcimp_b0;
|
||||
e2k_rt_pcimp_struct_t rt_pcimp_b1;
|
||||
e2k_rt_pcimp_struct_t rt_pcimp_b2;
|
||||
e2k_rt_pcimp_struct_t rt_pcimp_b3;
|
||||
e2k_rt_pcimp_struct_t rt_pcimp_e0;
|
||||
e2k_rt_pcimp_struct_t rt_pcimp_e1;
|
||||
e2k_rt_pcimp_struct_t rt_pcimp_e2;
|
||||
e2k_rt_pcimp_struct_t rt_pcimp_e3;
|
||||
e2k_rt_pcicfgb_struct_t rt_pcicfgb;
|
||||
uint64_t rt_msi;
|
||||
uint32_t iommu_ctrl;
|
||||
uint64_t iommu_ptbar;
|
||||
uint64_t iommu_dtbar;
|
||||
uint64_t iommu_err;
|
||||
uint64_t iommu_err_info;
|
||||
uint32_t prepic_ctrl2;
|
||||
uint32_t prepic_err_stat;
|
||||
uint32_t prepic_err_int;
|
||||
uint32_t prepic_linp0;
|
||||
uint32_t prepic_linp1;
|
||||
uint32_t prepic_linp2;
|
||||
uint32_t prepic_linp3;
|
||||
uint32_t prepic_linp4;
|
||||
uint32_t prepic_linp5;
|
||||
} SICState;
|
||||
|
||||
typedef struct GSIState {
|
||||
qemu_irq ioapic_irq[IOAPIC_NUM_PINS];
|
||||
} GSIState;
|
||||
|
||||
struct E2KMachineState {
|
||||
/*< private >*/
|
||||
MachineClass parent;
|
||||
|
||||
/*< public >*/
|
||||
qemu_irq *pic;
|
||||
GSIState *gsi_state;
|
||||
AddressSpace *ioapic_as;
|
||||
|
||||
PCIBus *bus;
|
||||
PCIIOHUBState *iohub;
|
||||
|
||||
MemoryRegion sicregion;
|
||||
struct SICState sicregs;
|
||||
|
||||
ram_addr_t above_4g_mem_size;
|
||||
ram_addr_t below_4g_mem_size;
|
||||
|
||||
bootblock_struct_t *bootblock;
|
||||
};
|
||||
|
||||
|
||||
#define TYPE_E2K_MACHINE MACHINE_TYPE_NAME("e2k")
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(E2KMachineState, E2K_MACHINE)
|
||||
|
||||
void sic_init(E2KMachineState *ms);
|
||||
int pci_e2k_map_irq(PCIDevice *pci_dev, int irq_num);
|
||||
|
||||
#endif /* HW_E2K_H */
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* ioapic.c IOAPIC emulation logic
|
||||
*
|
||||
* Copyright (c) 2011 Jan Kiszka, Siemens AG
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HW_IOAPIC_H
|
||||
#define HW_IOAPIC_H
|
||||
|
||||
#define IOAPIC_NUM_PINS 24
|
||||
#define IO_APIC_DEFAULT_ADDRESS 0xfec00000
|
||||
#define IO_APIC_SECONDARY_ADDRESS (IO_APIC_DEFAULT_ADDRESS + 0x10000)
|
||||
#define IO_APIC_SECONDARY_IRQBASE 24 /* primary 0 -> 23, secondary 24 -> 47 */
|
||||
|
||||
#define TYPE_KVM_IOAPIC "kvm-ioapic"
|
||||
#define TYPE_IOAPIC "ioapic"
|
||||
|
||||
void ioapic_eoi_broadcast(int vector);
|
||||
|
||||
#endif /* HW_IOAPIC_H */
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Alibek Omarov
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2 or later, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HW_E2K_MEMMAP_H
|
||||
#define HW_E2K_MEMMAP_H
|
||||
|
||||
/* Memory map */
|
||||
|
||||
/* may be overriden by VGAMEM, these bytes will be lost */
|
||||
#define E2K_MLO_BASE 0x0
|
||||
#define E2K_MLO_SIZE 0x080000000 /* 2 GiB */
|
||||
|
||||
#define E2K_PCIMEM_BASE 0x080000000
|
||||
#define E2K_PCIMEM_SIZE 0x07ec00000 /* 2028 MiB */
|
||||
|
||||
/* there goes APIC/EPIC, compatible with x86 */
|
||||
|
||||
#define E2K_BIOS_AREA_BASE 0x100000000
|
||||
#define E2K_BIOS_AREA_SIZE 0x001000000 /* 16 MiB */
|
||||
|
||||
#define E2K_IO_AREA_BASE 0x101000000
|
||||
#define E2K_IO_AREA_SIZE 0x000010000 /* 64 KiB */
|
||||
|
||||
#define E2K_SICREGS_BASE 0x110000000
|
||||
#define E2K_SICREGS_SIZE 0x000100000 /* 1 MiB */
|
||||
|
||||
#define E2K_PCICFG_BASE 0x200000000 /* set by SIC_rt_pcicfgb but we hardcode it */
|
||||
#define E2K_PCICFG_SIZE 0x010000000 /* 256 MiB */
|
||||
|
||||
#define E2K_PCIMEMP_BASE 0x210000000 /* Prefetchable MEM */
|
||||
#define E2K_PCIMEMP_SIZE 0x1f0000000 /* 7936 MiB */
|
||||
|
||||
#define E2K_HIMEM_BASE 0x400000000 /* and to the end of address space... */
|
||||
|
||||
#endif /* HW_E2K_MEMMAP_H */
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Alibek Omarov
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HW_PCI_IOHUB_H
|
||||
#define HW_PCI_IOHUB_H
|
||||
|
||||
#include "hw/pci/pci_bus.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#define TYPE_IOHUB_PCI_HOST_BRIDGE "iohub-pcihost"
|
||||
#define TYPE_IOHUB_PCI_BRIDGE "iohub-pcibridge"
|
||||
#define TYPE_IOHUB_PCI_DEVICE "iohub"
|
||||
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(PCIIOHUBState, IOHUB_PCI_DEVICE)
|
||||
|
||||
struct PCIIOHUBState {
|
||||
/*< private >*/
|
||||
PCIDevice parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
MemoryRegion *system_memory;
|
||||
MemoryRegion *pci_address_space;
|
||||
|
||||
qemu_irq *pic;
|
||||
};
|
||||
|
||||
PCIBus *iohub_init(const char *host_type, const char *pci_type,
|
||||
PCIIOHUBState **piohub_state,
|
||||
MemoryRegion *address_space_mem,
|
||||
MemoryRegion *address_space_io,
|
||||
qemu_irq *pic);
|
||||
|
||||
PCIBus *find_iohub(void);
|
||||
|
||||
|
||||
#endif
|
|
@ -23,6 +23,7 @@ enum {
|
|||
QEMU_ARCH_RISCV = (1 << 19),
|
||||
QEMU_ARCH_RX = (1 << 20),
|
||||
QEMU_ARCH_AVR = (1 << 21),
|
||||
QEMU_ARCH_E2K = (1 << 22),
|
||||
|
||||
QEMU_ARCH_NONE = (1 << 31),
|
||||
};
|
||||
|
|
|
@ -276,7 +276,7 @@ typedef struct TCGPool {
|
|||
|
||||
#define TCG_POOL_CHUNK_SIZE 32768
|
||||
|
||||
#define TCG_MAX_TEMPS 512
|
||||
#define TCG_MAX_TEMPS 1024
|
||||
#define TCG_MAX_INSNS 512
|
||||
|
||||
/* when the size of the arguments of a called function is smaller than
|
||||
|
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* qemu user cpu loop
|
||||
*
|
||||
* Copyright (c) 2003-2008 Fabrice Bellard
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu.h"
|
||||
#include "cpu_loop-common.h"
|
||||
#include "target_elf.h"
|
||||
|
||||
static void gen_signal(CPUE2KState *env, int signo, int code, abi_ulong addr)
|
||||
{
|
||||
target_siginfo_t info = {
|
||||
.si_signo = signo,
|
||||
.si_code = code,
|
||||
._sifields._sigfault._addr = addr,
|
||||
// TODO: ._sifields._sigfault._trapno = trapnr
|
||||
};
|
||||
|
||||
queue_signal(env, signo, QEMU_SI_FAULT, &info);
|
||||
}
|
||||
|
||||
static void stack_expand(CPUE2KState *env, E2KPsp *s)
|
||||
{
|
||||
abi_ulong new_size, new_size_tag;
|
||||
abi_long new_base, new_base_tag = 0;
|
||||
|
||||
new_size = s->size * 2;
|
||||
new_size_tag = new_size / 8;
|
||||
new_base = target_mremap(s->base, s->size, new_size, MREMAP_MAYMOVE, 0);
|
||||
if (s->base_tag) {
|
||||
new_base_tag = target_mremap(s->base_tag, s->size / 8, new_size_tag,
|
||||
MREMAP_MAYMOVE, 0);
|
||||
}
|
||||
if (new_base == -1 || new_base_tag == -1) {
|
||||
gen_signal(env, TARGET_SIGSEGV, TARGET_SEGV_MAPERR, env->ip);
|
||||
return;
|
||||
}
|
||||
|
||||
s->base = new_base;
|
||||
s->base_tag = new_base_tag;
|
||||
s->size = new_size;
|
||||
}
|
||||
|
||||
void cpu_loop(CPUE2KState *env)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
int trapnr;
|
||||
|
||||
while (1) {
|
||||
cpu_exec_start(cs);
|
||||
trapnr = cpu_exec(cs);
|
||||
cpu_exec_end(cs);
|
||||
process_queued_cpu_work(cs);
|
||||
|
||||
switch (trapnr) {
|
||||
case EXCP_SYSCALL: {
|
||||
abi_ullong args[E2K_SYSCALL_MAX_ARGS] = { 0 };
|
||||
int i, psize = MIN(E2K_SYSCALL_MAX_ARGS, env->wd.size);
|
||||
abi_ulong ret;
|
||||
|
||||
// TODO: check what happens if env->wd.size is zero
|
||||
for (i = 0; i < psize; i++) {
|
||||
args[i] = env->regs[i].lo;
|
||||
}
|
||||
|
||||
ret = do_syscall(env, args[0], args[1], args[2], args[3],
|
||||
args[4], args[5], args[6], args[7], args[8]);
|
||||
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
/* do not set sysret address and syscall will be restarted */
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN && env->wd.psize > 0) {
|
||||
memset(env->tags, E2K_TAG_NON_NUMBER64,
|
||||
psize * sizeof(env->tags[0]));
|
||||
|
||||
env->regs[0].lo = ret;
|
||||
env->tags[0] = E2K_TAG_NUMBER64;
|
||||
env->ip = E2K_SYSRET_ADDR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EXCP_ILLEGAL_OPCODE:
|
||||
case EXCP_PRIV_ACTION:
|
||||
gen_signal(env, TARGET_SIGILL, TARGET_ILL_ILLOPC, env->ip);
|
||||
break;
|
||||
case EXCP_ILLEGAL_OPERAND:
|
||||
gen_signal(env, TARGET_SIGILL, TARGET_ILL_ILLOPN, env->ip);
|
||||
break;
|
||||
case EXCP_CHAIN_STACK_BOUNDS:
|
||||
stack_expand(env, &env->pcsp);
|
||||
break;
|
||||
case EXCP_PROC_STACK_BOUNDS:
|
||||
stack_expand(env, &env->psp);
|
||||
break;
|
||||
case EXCP_WINDOW_BOUNDS:
|
||||
case EXCP_ARRAY_BOUNDS:
|
||||
case EXCP_DATA_PAGE:
|
||||
gen_signal(env, TARGET_SIGSEGV, TARGET_SEGV_MAPERR, env->ip);
|
||||
break;
|
||||
case EXCP_DIV:
|
||||
gen_signal(env, TARGET_SIGFPE, 0, env->ip);
|
||||
break;
|
||||
/* QEMU common interrupts */
|
||||
case EXCP_INTERRUPT:
|
||||
/* just indicate that signals should be handled asap */
|
||||
break;
|
||||
case EXCP_DEBUG:
|
||||
gen_signal(env, TARGET_SIGTRAP, TARGET_TRAP_BRKPT, 0);
|
||||
break;
|
||||
case EXCP_ATOMIC:
|
||||
cpu_exec_step_atomic(cs);
|
||||
break;
|
||||
case EXCP_HLT:
|
||||
case EXCP_HALTED:
|
||||
case EXCP_YIELD:
|
||||
fprintf(stderr, "Unhandled QEMU trap: 0x%x\n", trapnr);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unhandled trap: 0x%x\n", trapnr);
|
||||
cpu_dump_state(cs, stderr, 0);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
process_pending_signals (env);
|
||||
}
|
||||
}
|
||||
|
||||
void target_cpu_copy_regs(CPUE2KState *env, struct target_pt_regs *regs)
|
||||
{
|
||||
CPUState *cpu = env_cpu(env);
|
||||
TaskState *ts = cpu->opaque;
|
||||
struct image_info *info = ts->info;
|
||||
uint32_t eflags = info->elf_flags;
|
||||
|
||||
env->psr = PSR_NMIE | PSR_SGE | PSR_IE;
|
||||
env->upsr = UPSR_NMIE | UPSR_IE | UPSR_FE;
|
||||
env->ip = regs->ip;
|
||||
env->pcsp = regs->pcsp;
|
||||
env->psp = regs->psp;
|
||||
env->usd.lo = regs->usd_lo;
|
||||
env->usd.hi = regs->usd_hi;
|
||||
env->sbr = regs->sbr;
|
||||
env->elf_flags = info->elf_flags;
|
||||
|
||||
// TODO: set a chain info to return to kernel
|
||||
|
||||
if (eflags & E2K_ELF_PM) {
|
||||
fprintf(stderr, "Protected mode is unsupported\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (eflags & E2K_ELF_X86APP) {
|
||||
fprintf(stderr, "x86 recompiler is unsupported\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
const char *cpu_get_model(uint32_t eflags)
|
||||
{
|
||||
const char *name = "any";
|
||||
uint32_t machine = E2K_ELF_MACH(eflags);
|
||||
|
||||
/* TODO: can't check for EM_E2K_OLD flags because e_machine isn't saved anywhere... */
|
||||
switch(machine) {
|
||||
case E2K_MACH_EV2: name = "e2c+"; break;
|
||||
case E2K_MACH_EV3: name = "e2s"; break;
|
||||
case E2K_MACH_1CPLUS:
|
||||
case E2K_MACH_8C:
|
||||
case E2K_MACH_EV4: name = "e8c"; break;
|
||||
case E2K_MACH_EV5: name = "e8c2"; break;
|
||||
case E2K_MACH_EV6: name = "e16c"; break;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
|
@ -0,0 +1,361 @@
|
|||
/*
|
||||
* Emulation of Linux signals
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
* Copyright (c) 2020 Alibek Omarov
|
||||
* Copyright (c) 2021 Denis Drakhnya
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu.h"
|
||||
#include "signal-common.h"
|
||||
#include "linux-user/trace.h"
|
||||
#include "target/e2k/helper-tcg.h"
|
||||
|
||||
#define MAX_TC_SIZE 10
|
||||
|
||||
#define TIR_NUM 19
|
||||
#define DAM_ENTRIES_NUM 32
|
||||
#define SBBP_ENTRIES_NUM 32
|
||||
|
||||
/* from user.h !!! */
|
||||
#define MLT_NUM (16 * 3) /* common for E3M and E3S */
|
||||
|
||||
struct target_sigcontext {
|
||||
abi_ullong cr0_lo;
|
||||
abi_ullong cr0_hi;
|
||||
abi_ullong cr1_lo;
|
||||
abi_ullong cr1_hi;
|
||||
abi_ullong sbr; /* 21 Stack base register: top of */
|
||||
/* local data (user) stack */
|
||||
abi_ullong usd_lo; /* 22 Local data (user) stack */
|
||||
abi_ullong usd_hi; /* 23 descriptor: base & size */
|
||||
abi_ullong psp_lo; /* 24 Procedure stack pointer: */
|
||||
abi_ullong psp_hi; /* 25 base & index & size */
|
||||
abi_ullong pcsp_lo; /* 26 Procedure chain stack */
|
||||
abi_ullong pcsp_hi; /* 27 pointer: base & index & size */
|
||||
|
||||
/* additional part (for binary compiler) */
|
||||
abi_ullong rpr_hi;
|
||||
abi_ullong rpr_lo;
|
||||
|
||||
abi_ullong nr_TIRs;
|
||||
abi_ullong tir_lo[TIR_NUM];
|
||||
abi_ullong tir_hi[TIR_NUM];
|
||||
abi_ullong trap_cell_addr[MAX_TC_SIZE];
|
||||
abi_ullong trap_cell_val[MAX_TC_SIZE];
|
||||
uint8_t trap_cell_tag[MAX_TC_SIZE];
|
||||
abi_ullong trap_cell_info[MAX_TC_SIZE];
|
||||
|
||||
abi_ullong dam[DAM_ENTRIES_NUM];
|
||||
abi_ullong sbbp[SBBP_ENTRIES_NUM];
|
||||
abi_ullong mlt[MLT_NUM];
|
||||
abi_ullong upsr;
|
||||
};
|
||||
|
||||
/*
|
||||
* This structure is used for compatibility
|
||||
* All new fields must be added in this structure
|
||||
*/
|
||||
struct target_extra_ucontext {
|
||||
abi_int sizeof_extra_uc; /* size of used fields(in bytes) */
|
||||
abi_int curr_cnt; /* current index into trap_celler */
|
||||
abi_int tc_count; /* trap_celler records count */
|
||||
|
||||
/*
|
||||
* For getcontext()
|
||||
*/
|
||||
abi_int fpcr;
|
||||
abi_int fpsr;
|
||||
abi_int pfpfr;
|
||||
|
||||
abi_ullong ctpr1;
|
||||
abi_ullong ctpr2;
|
||||
abi_ullong ctpr3;
|
||||
|
||||
abi_int sc_need_rstrt;
|
||||
};
|
||||
|
||||
struct target_ucontext {
|
||||
abi_ulong uc_flags;
|
||||
struct target_ucontext *uc_link;
|
||||
target_stack_t uc_stack;
|
||||
struct target_sigcontext uc_mcontext;
|
||||
union {
|
||||
target_sigset_t uc_sigmask; /* mask last for extensibility */
|
||||
abi_ullong pad[16];
|
||||
};
|
||||
struct target_extra_ucontext uc_extra; /* for compatibility */
|
||||
};
|
||||
|
||||
struct target_sigframe {
|
||||
target_siginfo_t info;
|
||||
union {
|
||||
struct target_ucontext uc;
|
||||
// TODO: ucontext_prot
|
||||
};
|
||||
|
||||
/* FIXME: move this data to TaskState? */
|
||||
E2KAauState aau;
|
||||
uint64_t lsr;
|
||||
uint64_t lsr_lcnt;
|
||||
uint32_t ilcr;
|
||||
uint64_t ilcr_lcnt;
|
||||
// FIXME: according to ABI only 16-31 must be saved
|
||||
E2KReg gregs[16];
|
||||
uint8_t gtags[16];
|
||||
};
|
||||
|
||||
#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7)))
|
||||
|
||||
static abi_long setup_sigcontext(CPUE2KState *env,
|
||||
struct target_sigcontext *sc, struct target_extra_ucontext *extra)
|
||||
{
|
||||
E2KCrs crs;
|
||||
int i, ret;
|
||||
|
||||
// TODO: save binary compiler state (uspr, rpr, MLT)
|
||||
__put_user(env->upsr, &sc->upsr);
|
||||
|
||||
ret = e2k_copy_from_user_crs(&crs, env->pcsp.base + env->pcsp.index);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
__put_user(crs.cr0_lo, &sc->cr0_lo);
|
||||
__put_user(crs.cr0_hi, &sc->cr0_hi);
|
||||
__put_user(crs.cr1.lo, &sc->cr1_lo);
|
||||
__put_user(crs.cr1.hi, &sc->cr1_hi);
|
||||
|
||||
__put_user(env->sbr, &sc->sbr);
|
||||
__put_user(env->usd.lo, &sc->usd_lo);
|
||||
__put_user(env->usd.hi, &sc->usd_hi);
|
||||
__put_user(env->psp.lo, &sc->psp_lo);
|
||||
__put_user(env->psp.hi, &sc->psp_hi);
|
||||
__put_user(env->pcsp.lo, &sc->pcsp_lo);
|
||||
__put_user(env->pcsp.hi, &sc->pcsp_hi);
|
||||
|
||||
// TODO: save trap state
|
||||
__put_user(0, &sc->nr_TIRs);
|
||||
__put_user(0, &sc->tir_lo[0]);
|
||||
__put_user(0, &sc->tir_hi[0]);
|
||||
__put_user(-1, &extra->curr_cnt);
|
||||
__put_user(0, &extra->tc_count);
|
||||
|
||||
__put_user(sizeof(struct target_extra_ucontext) - sizeof(abi_int),
|
||||
&extra->sizeof_extra_uc);
|
||||
|
||||
__put_user(env->fpcr.raw, &extra->fpcr);
|
||||
__put_user(env->fpsr.raw, &extra->fpsr);
|
||||
__put_user(env->pfpfr.raw, &extra->pfpfr);
|
||||
|
||||
__put_user(env->ctprs[0].raw, &extra->ctpr1);
|
||||
__put_user(env->ctprs[1].raw, &extra->ctpr2);
|
||||
__put_user(env->ctprs[2].raw, &extra->ctpr3);
|
||||
|
||||
for (i = 0; i < DAM_ENTRIES_NUM; i++) {
|
||||
__put_user(env->dam[i].raw, &sc->dam[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static abi_long setup_ucontext(struct target_ucontext *uc, CPUE2KState *env)
|
||||
{
|
||||
__put_user(0, &uc->uc_flags);
|
||||
__put_user(0, &uc->uc_link);
|
||||
|
||||
target_save_altstack(&uc->uc_stack, env);
|
||||
return setup_sigcontext(env, &uc->uc_mcontext, &uc->uc_extra);
|
||||
}
|
||||
|
||||
static abi_ulong get_sigframe(struct target_sigaction *ka, CPUE2KState *env,
|
||||
size_t frame_size)
|
||||
{
|
||||
abi_ulong sp;
|
||||
|
||||
sp = target_sigsp(get_sp_from_cpustate(env), ka);
|
||||
sp = (sp - frame_size) & ~15;
|
||||
|
||||
return sp;
|
||||
}
|
||||
|
||||
static void target_setup_frame(int sig, struct target_sigaction *ka,
|
||||
target_siginfo_t *info, target_sigset_t *set, CPUE2KState *env)
|
||||
{
|
||||
abi_ulong frame_addr;
|
||||
struct target_sigframe *frame;
|
||||
|
||||
if (env->is_bp) {
|
||||
/* numas13 FIXME: I am not sure that it is a good solution but
|
||||
* the way we handle breakpoints requires these steps.
|
||||
* Maybe we need to create more fake kernel frames for breakpoints? */
|
||||
e2k_proc_return(env, true);
|
||||
}
|
||||
|
||||
/* save current frame */
|
||||
e2k_proc_call(env, env->wd.size, env->ip, false);
|
||||
|
||||
frame_addr = get_sigframe(ka, env, sizeof(*frame));
|
||||
trace_user_setup_rt_frame(env, frame_addr);
|
||||
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
|
||||
force_sigsegv(sig);
|
||||
}
|
||||
if (setup_ucontext(&frame->uc, env)) {
|
||||
goto fail;
|
||||
}
|
||||
copy_to_user(frame_addr + offsetof(struct target_sigframe, uc.uc_sigmask),
|
||||
set, sizeof(*set));
|
||||
copy_to_user(frame_addr + offsetof(struct target_sigframe, aau),
|
||||
&env->aau, sizeof(env->aau));
|
||||
__put_user(env_lsr_get(env), &frame->lsr);
|
||||
__put_user(env->lsr_lcnt, &frame->lsr_lcnt);
|
||||
__put_user(env->ilcr, &frame->ilcr);
|
||||
__put_user(env->ilcr_lcnt, &frame->ilcr_lcnt);
|
||||
copy_to_user(frame_addr + offsetof(struct target_sigframe, gregs),
|
||||
&env->regs[E2K_NR_COUNT + 16], 16 * sizeof(E2KReg));
|
||||
copy_to_user(frame_addr + offsetof(struct target_sigframe, gtags),
|
||||
&env->tags[E2K_NR_COUNT + 16], 16);
|
||||
|
||||
if (ka->sa_flags & TARGET_SA_RESTORER) {
|
||||
// TODO: sa_restorer?
|
||||
qemu_log_mask(LOG_UNIMP, "target_setup_frame sa_restorer +\n");
|
||||
} else {
|
||||
// TODO: ignore?
|
||||
}
|
||||
|
||||
/* fake kernel frame */
|
||||
env->wd.size = 0;
|
||||
env->wd.psize = 0;
|
||||
env->usd.size = env->sbr - frame_addr;
|
||||
env->usd.base = frame_addr;
|
||||
e2k_proc_call(env, 0, E2K_SIGRET_ADDR, false);
|
||||
|
||||
env->ip = ka->_sa_handler;
|
||||
env->regs[0].lo = sig;
|
||||
env->tags[0] = E2K_TAG_NUMBER64;
|
||||
env->wd.size = 8;
|
||||
|
||||
if (info && (ka->sa_flags & TARGET_SA_SIGINFO)) {
|
||||
tswap_siginfo(&frame->info, info);
|
||||
env->regs[1].lo = frame_addr + offsetof(struct target_sigframe, info);
|
||||
env->tags[1] = E2K_TAG_NUMBER64;
|
||||
env->regs[2].lo = frame_addr + offsetof(struct target_sigframe, uc);
|
||||
env->tags[2] = E2K_TAG_NUMBER64;
|
||||
}
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 1);
|
||||
return;
|
||||
|
||||
fail:
|
||||
unlock_user_struct(frame, frame_addr, 1);
|
||||
force_sigsegv(sig);
|
||||
}
|
||||
|
||||
static abi_long target_restore_sigframe(CPUE2KState *env,
|
||||
struct target_sigframe *frame)
|
||||
{
|
||||
target_ulong crs_addr = env->pcsp.base + env->pcsp.index;
|
||||
E2KCrs crs, *p;
|
||||
|
||||
if (!lock_user_struct(VERIFY_WRITE, p, crs_addr, 0)) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
__get_user(crs.cr0_hi, &frame->uc.uc_mcontext.cr0_hi);
|
||||
__put_user(crs.cr0_hi, &p->cr0_hi);
|
||||
unlock_user_struct(p, crs_addr, 1);
|
||||
|
||||
__get_user(env->ctprs[0].raw, &frame->uc.uc_extra.ctpr1);
|
||||
__get_user(env->ctprs[1].raw, &frame->uc.uc_extra.ctpr2);
|
||||
__get_user(env->ctprs[2].raw, &frame->uc.uc_extra.ctpr3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setup_frame(int sig, struct target_sigaction *ka,
|
||||
target_sigset_t *set, CPUE2KState *env)
|
||||
{
|
||||
target_setup_frame(sig, ka, 0, set, env);
|
||||
}
|
||||
|
||||
void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
target_siginfo_t *info, target_sigset_t *set, CPUE2KState *env)
|
||||
{
|
||||
target_setup_frame(sig, ka, info, set, env);
|
||||
}
|
||||
|
||||
long do_sigreturn(CPUE2KState *env)
|
||||
{
|
||||
return do_rt_sigreturn(env);
|
||||
}
|
||||
|
||||
long do_rt_sigreturn(CPUE2KState *env)
|
||||
{
|
||||
abi_ulong frame_addr;
|
||||
struct target_sigframe *frame;
|
||||
sigset_t set;
|
||||
|
||||
/* restore fake kernel frame */
|
||||
e2k_proc_return(env, false);
|
||||
frame_addr = env->usd.base;
|
||||
|
||||
trace_user_do_rt_sigreturn(env, frame_addr);
|
||||
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
|
||||
goto badframe;
|
||||
}
|
||||
|
||||
target_to_host_sigset(&set, &frame->uc.uc_sigmask);
|
||||
set_sigmask(&set);
|
||||
|
||||
if (target_restore_sigframe(env, frame)) {
|
||||
goto badframe;
|
||||
}
|
||||
copy_from_user(&env->aau, frame_addr
|
||||
+ offsetof(struct target_sigframe, aau), sizeof(env->aau));
|
||||
__get_user(env->lsr, &frame->lsr);
|
||||
__get_user(env->lsr_lcnt, &frame->lsr_lcnt);
|
||||
__get_user(env->ilcr, &frame->ilcr);
|
||||
__get_user(env->ilcr_lcnt, &frame->ilcr_lcnt);
|
||||
copy_from_user(&env->regs[E2K_NR_COUNT + 16], frame_addr
|
||||
+ offsetof(struct target_sigframe, gregs), 16 * sizeof(E2KReg));
|
||||
copy_from_user(&env->tags[E2K_NR_COUNT + 16], frame_addr
|
||||
+ offsetof(struct target_sigframe, gtags), 16);
|
||||
|
||||
if (do_sigaltstack(frame_addr +
|
||||
offsetof(struct target_sigframe, uc.uc_stack),
|
||||
0, env) == -EFAULT)
|
||||
{
|
||||
goto badframe;
|
||||
}
|
||||
|
||||
/* restore user */
|
||||
e2k_proc_return(env, false);
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
|
||||
badframe:
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
}
|
||||
|
||||
abi_long do_swapcontext(CPUArchState *env, abi_ulong uold_ctx,
|
||||
abi_ulong unew_ctx, abi_long ctx_size)
|
||||
{
|
||||
// TODO: do_swapcontext
|
||||
qemu_log_mask(LOG_UNIMP, "do_swapcontext: not implemented\n");
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
#include "../generic/sockbits.h"
|
|
@ -0,0 +1,457 @@
|
|||
/*
|
||||
* This file contains the system call numbers.
|
||||
*/
|
||||
#ifndef E2K_SYSCALL_NR_H
|
||||
#define E2K_SYSCALL_NR_H
|
||||
|
||||
#define TARGET_NR_restart_syscall 0
|
||||
#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_waitpid 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_time 13
|
||||
#define TARGET_NR_mknod 14
|
||||
#define TARGET_NR_chmod 15
|
||||
#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_setuid 23
|
||||
#define TARGET_NR_getuid 24
|
||||
#define TARGET_NR_stime 25
|
||||
#define TARGET_NR_ptrace 26
|
||||
#define TARGET_NR_alarm 27
|
||||
#define TARGET_NR_oldfstat 28
|
||||
#define TARGET_NR_pause 29
|
||||
#define TARGET_NR_utime 30
|
||||
#define TARGET_NR_stty 31
|
||||
#define TARGET_NR_gtty 32
|
||||
#define TARGET_NR_access 33
|
||||
#define TARGET_NR_nice 34
|
||||
#define TARGET_NR_ftime 35
|
||||
#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_prof 44
|
||||
#define TARGET_NR_brk 45
|
||||
#define TARGET_NR_setgid 46
|
||||
#define TARGET_NR_getgid 47
|
||||
#define TARGET_NR_signal 48
|
||||
#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
|
||||
#define TARGET_NR_ioctl 54
|
||||
#define TARGET_NR_fcntl 55
|
||||
#define TARGET_NR_mpx 56
|
||||
#define TARGET_NR_setpgid 57
|
||||
#define TARGET_NR_ulimit 58
|
||||
#define TARGET_NR_oldolduname 59
|
||||
#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_sgetmask 68
|
||||
#define TARGET_NR_ssetmask 69
|
||||
#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
|
||||
#define TARGET_NR_setrlimit 75
|
||||
#define TARGET_NR_getrlimit 76 /* Back compatible 2Gig limited rlimit */
|
||||
#define TARGET_NR_getrusage 77
|
||||
#define TARGET_NR_gettimeofday 78
|
||||
#define TARGET_NR_settimeofday 79
|
||||
#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
|
||||
#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_fchown 95
|
||||
#define TARGET_NR_getpriority 96
|
||||
#define TARGET_NR_setpriority 97
|
||||
#define TARGET_NR_profil 98
|
||||
#define TARGET_NR_statfs 99
|
||||
#define TARGET_NR_fstatfs 100
|
||||
#define TARGET_NR_ioperm 101
|
||||
#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_olduname 109
|
||||
#define TARGET_NR_iopl 110
|
||||
#define TARGET_NR_vhangup 111
|
||||
#define TARGET_NR_idle 112
|
||||
#define TARGET_NR_vm86old 113
|
||||
#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_modify_ldt 123
|
||||
#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_setfsuid 138
|
||||
#define TARGET_NR_setfsgid 139
|
||||
#define TARGET_NR__llseek 140
|
||||
#define TARGET_NR_getdents 141
|
||||
#define TARGET_NR__newselect 142
|
||||
#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_setresuid 164
|
||||
#define TARGET_NR_getresuid 165
|
||||
#define TARGET_NR_vm86 166
|
||||
#define TARGET_NR_query_module 167
|
||||
#define TARGET_NR_poll 168
|
||||
#define TARGET_NR_nfsservctl 169
|
||||
#define TARGET_NR_setresgid 170
|
||||
#define TARGET_NR_getresgid 171
|
||||
#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_chown 182
|
||||
#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 /* some people actually want streams */
|
||||
#define TARGET_NR_putpmsg 189 /* some people actually want streams */
|
||||
#define TARGET_NR_vfork 190
|
||||
#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_pivot_root 217
|
||||
#define TARGET_NR_mincore 218
|
||||
#define TARGET_NR_madvise 219
|
||||
#define TARGET_NR_madvise1 219 /* delete when C lib stub is removed */
|
||||
#define TARGET_NR_getdents64 220
|
||||
#define TARGET_NR_fcntl64 221
|
||||
#define TARGET_NR_core 222 /* for analys kernel core */
|
||||
#define TARGET_NR_macctl 223 /* MCST trust linux */
|
||||
#define TARGET_NR_newfstatat 224
|
||||
#define TARGET_NR_emergency 225
|
||||
#define TARGET_NR_e2k_sigsetjmp 226 /* setjmp e2k specific */
|
||||
#define TARGET_NR_e2k_longjmp 227 /* longjmp e2k specific */
|
||||
#define TARGET_NR_e2k_syswork 228 /* e2k_syswork */
|
||||
#define TARGET_NR_clone2 229
|
||||
#define TARGET_NR_e2k_longjmp2 230 /* Second Edition */
|
||||
#define TARGET_NR_soft_debug 231
|
||||
#define TARGET_NR_setxattr 232
|
||||
#define TARGET_NR_lsetxattr 233
|
||||
#define TARGET_NR_fsetxattr 234
|
||||
#define TARGET_NR_getxattr 235
|
||||
#define TARGET_NR_lgetxattr 236
|
||||
#define TARGET_NR_fgetxattr 237
|
||||
#define TARGET_NR_listxattr 238
|
||||
#define TARGET_NR_llistxattr 239
|
||||
#define TARGET_NR_flistxattr 240
|
||||
#define TARGET_NR_removexattr 241
|
||||
#define TARGET_NR_lremovexattr 242
|
||||
#define TARGET_NR_fremovexattr 243
|
||||
#define TARGET_NR_gettid 244
|
||||
#define TARGET_NR_readahead 245
|
||||
#define TARGET_NR_tkill 246
|
||||
#define TARGET_NR_sendfile64 247
|
||||
#define TARGET_NR_futex 248
|
||||
#define TARGET_NR_sched_setaffinity 249
|
||||
#define TARGET_NR_sched_getaffinity 250
|
||||
#define TARGET_NR_pipe2 251
|
||||
#define TARGET_NR_set_backtrace 252
|
||||
#define TARGET_NR_get_backtrace 253
|
||||
#define TARGET_NR_access_hw_stacks 254
|
||||
#define TARGET_NR_el_posix 255
|
||||
/*
|
||||
* reserved for update of kernel source codes
|
||||
*/
|
||||
#define TARGET_NR_reserved6 256
|
||||
#define TARGET_NR_reserved7 257
|
||||
#define TARGET_NR_reserved8 258
|
||||
|
||||
#define TARGET_NR_set_tid_address 259
|
||||
#define TARGET_NR_el_binary 260
|
||||
#define TARGET_NR_timer_create 261
|
||||
#define TARGET_NR_timer_settime 262
|
||||
#define TARGET_NR_timer_gettime 263
|
||||
#define TARGET_NR_timer_getoverrun 264
|
||||
#define TARGET_NR_timer_delete 265
|
||||
#define TARGET_NR_clock_settime 266
|
||||
#define TARGET_NR_clock_gettime 267
|
||||
#define TARGET_NR_clock_getres 268
|
||||
#define TARGET_NR_clock_nanosleep 269
|
||||
/*
|
||||
* reserved for update of kernel source codes
|
||||
*/
|
||||
#define TARGET_NR_reserved9 270
|
||||
#define TARGET_NR_reserved10 271
|
||||
#define TARGET_NR_reserved11 272
|
||||
#define TARGET_NR_reserved12 273
|
||||
#define TARGET_NR_reserved13 274
|
||||
#define TARGET_NR_reserved14 275
|
||||
#define TARGET_NR_reserved15 276
|
||||
#define TARGET_NR_reserved16 277
|
||||
#define TARGET_NR_reserved17 278
|
||||
#define TARGET_NR_reserved18 279
|
||||
#define TARGET_NR_reserved19 280
|
||||
#define TARGET_NR_reserved20 281
|
||||
#define TARGET_NR_reserved21 282
|
||||
#define TARGET_NR_reserved22 283
|
||||
#define TARGET_NR_reserved23 284
|
||||
#define TARGET_NR_reserved24 285
|
||||
#define TARGET_NR_reserved25 286
|
||||
|
||||
#define TARGET_NR_sched_setattr 287
|
||||
#define TARGET_NR_sched_getattr 288
|
||||
|
||||
#define TARGET_NR_ioprio_set 289
|
||||
#define TARGET_NR_ioprio_get 290
|
||||
#define TARGET_NR_inotify_init 291
|
||||
#define TARGET_NR_inotify_add_watch 292
|
||||
#define TARGET_NR_inotify_rm_watch 293
|
||||
|
||||
#define TARGET_NR_io_setup 294
|
||||
#define TARGET_NR_io_destroy 295
|
||||
#define TARGET_NR_io_getevents 296
|
||||
#define TARGET_NR_io_submit 297
|
||||
#define TARGET_NR_io_cancel 298
|
||||
#define TARGET_NR_fadvise64 299
|
||||
|
||||
#define TARGET_NR_exit_group 300
|
||||
#define TARGET_NR_lookup_dcookie 301
|
||||
#define TARGET_NR_epoll_create 302
|
||||
#define TARGET_NR_epoll_ctl 303
|
||||
#define TARGET_NR_epoll_wait 304
|
||||
#define TARGET_NR_remap_file_pages 305
|
||||
#define TARGET_NR_statfs64 306
|
||||
#define TARGET_NR_fstatfs64 307
|
||||
#define TARGET_NR_tgkill 308
|
||||
#define TARGET_NR_utimes 309
|
||||
#define TARGET_NR_fadvise64_64 310
|
||||
#define TARGET_NR_vserver 311
|
||||
#define TARGET_NR_mbind 312
|
||||
#define TARGET_NR_get_mempolicy 313
|
||||
#define TARGET_NR_set_mempolicy 314
|
||||
#define TARGET_NR_mq_open 315
|
||||
#define TARGET_NR_mq_unlink (TARGET_NR_mq_open+1)
|
||||
#define TARGET_NR_mq_timedsend (TARGET_NR_mq_open+2)
|
||||
#define TARGET_NR_mq_timedreceive (TARGET_NR_mq_open+3)
|
||||
#define TARGET_NR_mq_notify (TARGET_NR_mq_open+4)
|
||||
#define TARGET_NR_mq_getsetattr (TARGET_NR_mq_open+5)
|
||||
#define TARGET_NR_kexec_load 321
|
||||
#define TARGET_NR_waitid 322
|
||||
#define TARGET_NR_add_key 323
|
||||
#define TARGET_NR_request_key 324
|
||||
#define TARGET_NR_keyctl 325
|
||||
#define TARGET_NR_mcst_rt 326
|
||||
#define TARGET_NR_getcpu 327
|
||||
#define TARGET_NR_move_pages 328
|
||||
#define TARGET_NR_splice 329
|
||||
#define TARGET_NR_vmsplice 330
|
||||
#define TARGET_NR_tee 331
|
||||
#define TARGET_NR_migrate_pages 332
|
||||
#define TARGET_NR_utimensat 333
|
||||
#define TARGET_NR_rt_tgsigqueueinfo 334
|
||||
#define TARGET_NR_openat 335
|
||||
#define TARGET_NR_mkdirat 336
|
||||
#define TARGET_NR_mknodat 337
|
||||
#define TARGET_NR_fchownat 338
|
||||
#define TARGET_NR_unlinkat 339
|
||||
#define TARGET_NR_renameat 340
|
||||
#define TARGET_NR_linkat 341
|
||||
#define TARGET_NR_symlinkat 342
|
||||
#define TARGET_NR_readlinkat 343
|
||||
#define TARGET_NR_fchmodat 344
|
||||
#define TARGET_NR_faccessat 345
|
||||
#define TARGET_NR_epoll_pwait 346
|
||||
#define TARGET_NR_signalfd4 347
|
||||
#define TARGET_NR_eventfd2 348
|
||||
#define TARGET_NR_recvmmsg 349
|
||||
#define TARGET_NR_cnt_point 350
|
||||
#define TARGET_NR_timerfd_create 351
|
||||
#define TARGET_NR_timerfd_settime 352
|
||||
#define TARGET_NR_timerfd_gettime 353
|
||||
#define TARGET_NR_preadv 354
|
||||
#define TARGET_NR_pwritev 355
|
||||
#define TARGET_NR_fallocate 356
|
||||
#define TARGET_NR_sync_file_range 357
|
||||
#define TARGET_NR_dup3 358
|
||||
#define TARGET_NR_inotify_init1 359
|
||||
#define TARGET_NR_epoll_create1 360
|
||||
#define TARGET_NR_fstatat64 361
|
||||
#define TARGET_NR_futimesat 362
|
||||
#define TARGET_NR_perf_event_open 363
|
||||
#define TARGET_NR_unshare 364
|
||||
#define TARGET_NR_get_robust_list 365
|
||||
#define TARGET_NR_set_robust_list 366
|
||||
#define TARGET_NR_pselect6 367
|
||||
#define TARGET_NR_ppoll 368
|
||||
#define TARGET_NR_setcontext 369
|
||||
#define TARGET_NR_makecontext 370
|
||||
#define TARGET_NR_swapcontext 371
|
||||
#define TARGET_NR_freecontext 372
|
||||
#define TARGET_NR_fanotify_init 373
|
||||
#define TARGET_NR_fanotify_mark 374
|
||||
#define TARGET_NR_prlimit64 375
|
||||
#define TARGET_NR_clock_adjtime 376
|
||||
#define TARGET_NR_syncfs 377
|
||||
#define TARGET_NR_sendmmsg 378
|
||||
#define TARGET_NR_setns 379
|
||||
#define TARGET_NR_process_vm_readv 380
|
||||
#define TARGET_NR_process_vm_writev 381
|
||||
#define TARGET_NR_kcmp 382
|
||||
#define TARGET_NR_finit_module 383
|
||||
#define TARGET_NR_renameat2 384
|
||||
#define TARGET_NR_getrandom 385
|
||||
#define TARGET_NR_memfd_create 386
|
||||
#define TARGET_NR_bpf 387
|
||||
#define TARGET_NR_execveat 388
|
||||
#define TARGET_NR_userfaultfd 389
|
||||
#define TARGET_NR_membarrier 390
|
||||
#define TARGET_NR_mlock2 391
|
||||
#define TARGET_NR_seccomp 392
|
||||
#define TARGET_NR_shutdown 393
|
||||
#define TARGET_NR_copy_file_range 394
|
||||
#define TARGET_NR_preadv2 395
|
||||
#define TARGET_NR_pwritev2 396
|
||||
#define TARGET_NR_pkey_mprotect 397
|
||||
#define TARGET_NR_pkey_alloc 398
|
||||
#define TARGET_NR_pkey_free 399
|
||||
#define TARGET_NR_name_to_handle_at 400
|
||||
#define TARGET_NR_open_by_handle_at 401
|
||||
#define TARGET_NR_statx 402
|
||||
/* added for compatibility with x86_64 */
|
||||
#define TARGET_NR_socket 403
|
||||
#define TARGET_NR_connect 404
|
||||
#define TARGET_NR_accept 405
|
||||
#define TARGET_NR_sendto 406
|
||||
#define TARGET_NR_recvfrom 407
|
||||
#define TARGET_NR_sendmsg 408
|
||||
#define TARGET_NR_recvmsg 409
|
||||
#define TARGET_NR_bind 410
|
||||
#define TARGET_NR_listen 411
|
||||
#define TARGET_NR_getsockname 412
|
||||
#define TARGET_NR_getpeername 413
|
||||
#define TARGET_NR_socketpair 414
|
||||
#define TARGET_NR_setsockopt 415
|
||||
#define TARGET_NR_getsockopt 416
|
||||
/* free (unused) entries - reserve 417 - 418 */
|
||||
/* TODO: #define TARGET_NR_arch_prctl 419 */
|
||||
/* added for combability of protected system calls v1-v5 & v6 */
|
||||
#define TARGET_NR_newuselib 420
|
||||
#define TARGET_NR_rt_sigaction_ex 421
|
||||
/* protected Mode specific memory allocation syscall number */
|
||||
#define TARGET_NR_get_mem 422
|
||||
#define TARGET_NR_free_mem 423
|
||||
/* protected mode specific clean memory from old invalid descriptors */
|
||||
#define TARGET_NR_clean_descriptors 424
|
||||
/* protected mode specific unloading module from memory */
|
||||
#define TARGET_NR_unuselib 425
|
||||
#define TARGET_NR_clone3 426
|
||||
#define TARGET_NR_fsopen 427
|
||||
#define TARGET_NR_fsconfig 428
|
||||
#define TARGET_NR_fsmount 429
|
||||
#define TARGET_NR_fspick 430
|
||||
|
||||
#define TARGET_syscalls 431
|
||||
|
||||
#endif /* E2K_SYSCALL_NR_H */
|
|
@ -0,0 +1,87 @@
|
|||
#ifndef E2K_TARGET_CPU_H
|
||||
#define E2K_TARGET_CPU_H
|
||||
|
||||
#include "qemu/log.h"
|
||||
|
||||
abi_long e2k_copy_from_user_crs(E2KCrs *crs, abi_ulong target_crs_addr);
|
||||
abi_long e2k_copy_to_user_crs(abi_ulong target_crs_addr, E2KCrs *crs);
|
||||
|
||||
static inline void cpu_clone_regs_child(CPUE2KState *env, target_ulong newsp,
|
||||
unsigned flags)
|
||||
{
|
||||
if (newsp) {
|
||||
// FIXME: what size must be?
|
||||
env->usd.size = 0x20000;
|
||||
env->usd.base = env->sbr = newsp & ~0xf;
|
||||
env->usd.read = 1;
|
||||
env->usd.write = 1;
|
||||
}
|
||||
|
||||
if (flags & CLONE_VM) {
|
||||
E2KPsp pcs = { 0 };
|
||||
E2KPsp ps = { 0 };
|
||||
E2KCrs crs = { 0 };
|
||||
uint64_t *ps_old, *ps_new;
|
||||
size_t frame_size;
|
||||
target_ulong pcsp = env->pcsp.base + env->pcsp.index;
|
||||
target_ulong ps_base = env->psp.base + env->psp.index;
|
||||
int i;
|
||||
|
||||
e2k_psp_new(&pcs, E2K_DEFAULT_PCS_SIZE, false);
|
||||
e2k_psp_new(&ps, E2K_DEFAULT_PS_SIZE, true);
|
||||
|
||||
// TODO: size checks and a way to report errors
|
||||
// TODO: set a chain info to return to kernel
|
||||
|
||||
pcs.index += sizeof(E2KCrs);
|
||||
if (e2k_copy_from_user_crs(&crs, pcsp)
|
||||
|| e2k_copy_to_user_crs(pcs.base + pcs.index, &crs))
|
||||
{
|
||||
qemu_log("qemu-e2k internal error: failed to copy parent frame\n");
|
||||
env->ip = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
frame_size = crs.cr1.wbs * (crs.cr1.wfx || E2K_FORCE_FX ? 32 : 16);
|
||||
ps_base -= frame_size;
|
||||
ps.index += frame_size;
|
||||
ps_old = lock_user(VERIFY_READ, ps_base, frame_size, 1);
|
||||
ps_new = lock_user(VERIFY_WRITE, ps.base, frame_size, 0);
|
||||
|
||||
for (i = 0; i < frame_size / 8; i++) {
|
||||
uint64_t tmp;
|
||||
__get_user(tmp, &ps_old[i]);
|
||||
__put_user(tmp, &ps_new[i]);
|
||||
}
|
||||
|
||||
unlock_user_struct(ps_new, ps.base, 1);
|
||||
unlock_user_struct(ps_old, ps_base, 0);
|
||||
|
||||
env->ip = E2K_SYSRET_ADDR;
|
||||
env->pcsp = pcs;
|
||||
env->psp = ps;
|
||||
env->regs[0].lo = 0;
|
||||
env->tags[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void cpu_clone_regs_parent(CPUE2KState *env, unsigned flags)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void cpu_set_tls(CPUE2KState *env, target_ulong newtls)
|
||||
{
|
||||
env->regs[E2K_TLS_REG].lo = newtls;
|
||||
}
|
||||
|
||||
static inline target_ulong cpu_get_tls(CPUE2KState *env)
|
||||
{
|
||||
return env->regs[E2K_TLS_REG].lo;
|
||||
}
|
||||
|
||||
static inline abi_ulong get_sp_from_cpustate(CPUE2KState *env)
|
||||
{
|
||||
return env->usd.base;
|
||||
}
|
||||
|
||||
#endif /* E2K_TARGET_CPU_H */
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef E2K_TARGET_ELF_H
|
||||
#define E2K_TARGET_ELF_H
|
||||
|
||||
#define E2K_ELF_IPD_MASK ((1U << 1)|(1U << 0))
|
||||
#define E2K_ELF_X86APP (1U << 2)
|
||||
#define E2K_ELF_4MB_PAGES (1U << 3)
|
||||
#define E2K_ELF_INCOMPAT (1U << 4)
|
||||
#define E2K_ELF_PM (1U << 5)
|
||||
|
||||
#define E2K_ELF_OLD_MACH(x) (((x) >> 28) & 7)
|
||||
#define E2K_ELF_MACH(x) (((x) >> 24) & 255)
|
||||
|
||||
#define E2K_MACH_BASE 0
|
||||
#define E2K_MACH_EV1 1
|
||||
#define E2K_MACH_EV2 2
|
||||
#define E2K_MACH_EV3 3
|
||||
#define E2K_MACH_EV4 4
|
||||
#define E2K_MACH_EV5 5
|
||||
#define E2K_MACH_EV6 6
|
||||
|
||||
/* elbrus-v4 based processors */
|
||||
#define E2K_MACH_8C 19
|
||||
#define E2K_MACH_1CPLUS 20
|
||||
|
||||
const char *cpu_get_model(uint32_t eflags);
|
||||
|
||||
#endif /* E2K_TARGET_ELF_H */
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef E2K_TARGET_ERRNO_DEFS_H
|
||||
#define E2K_TARGET_ERRNO_DEFS_H
|
||||
|
||||
/* Target uses generic errno */
|
||||
#include "../generic/target_errno_defs.h"
|
||||
|
||||
#endif
|
|
@ -0,0 +1,4 @@
|
|||
#ifndef E2K_TARGET_FCNTL_H
|
||||
#define E2K_TARGET_FCNTL_H
|
||||
#include "../generic/fcntl.h"
|
||||
#endif
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef TARGET_SIGNAL_H
|
||||
#define TARGET_SIGNAL_H
|
||||
|
||||
/*
|
||||
* sigaltstack controls
|
||||
*/
|
||||
#define TARGET_SS_ONSTACK 1
|
||||
#define TARGET_SS_DISABLE 2
|
||||
|
||||
#define TARGET_MINSIGSTKSZ 4096
|
||||
#define TARGET_SIGSTKSZ 8192
|
||||
#define TARGET_MCL_CURRENT 1
|
||||
#define TARGET_MCL_FUTURE 2
|
||||
#define TARGET_MCL_ONFAULT 4
|
||||
|
||||
#define TARGET_ARCH_HAS_SETUP_FRAME
|
||||
|
||||
typedef struct target_sigaltstack {
|
||||
abi_ulong ss_sp;
|
||||
abi_int ss_flags;
|
||||
abi_ulong ss_size;
|
||||
} target_stack_t;
|
||||
|
||||
#include "../generic/signal.h"
|
||||
|
||||
#endif /* TARGET_SIGNAL_H */
|
|
@ -0,0 +1,41 @@
|
|||
#ifndef E2K_TARGET_STRUCTS_H
|
||||
#define E2K_TARGET_STRUCTS_H
|
||||
|
||||
struct target_ipc_perm {
|
||||
abi_int __key;
|
||||
abi_uint uid;
|
||||
abi_uint gid;
|
||||
abi_uint cuid;
|
||||
abi_uint cgid;
|
||||
abi_uint mode;
|
||||
abi_ushort __seq;
|
||||
};
|
||||
|
||||
struct target_shmid_ds {
|
||||
struct target_ipc_perm shm_perm;
|
||||
abi_int shm_segsz;
|
||||
abi_long shm_atime;
|
||||
abi_long shm_dtime;
|
||||
abi_long shm_ctime;
|
||||
abi_int shm_cpid;
|
||||
abi_int shm_lpid;
|
||||
abi_ushort shm_nattch;
|
||||
abi_ushort shm_unused;
|
||||
void *shm_unused2;
|
||||
void *shm_unused3;
|
||||
};
|
||||
|
||||
struct target_jmp_info {
|
||||
abi_ullong sigmask;
|
||||
abi_ullong cr0hi;
|
||||
abi_ullong cr1lo;
|
||||
abi_ullong pcsplo;
|
||||
abi_ullong pcsphi;
|
||||
abi_uint pcshtp;
|
||||
abi_uint br;
|
||||
abi_ullong usdlo;
|
||||
abi_ullong wd;
|
||||
abi_ullong reserv1;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,90 @@
|
|||
#ifndef E2K_TARGET_SYSCALL_H
|
||||
#define E2K_TARGET_SYSCALL_H
|
||||
|
||||
#define UNAME_MACHINE "e2k"
|
||||
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
||||
|
||||
#define E2K_MAXNR 128 /* The total number of */
|
||||
/* quad-NRs */
|
||||
#define E2K_MAXGR 16 /* The total number of global */
|
||||
/* quad-NRs */
|
||||
#define E2K_MAXSR (E2K_MAXNR - E2K_MAXGR) /* The total number of stack */
|
||||
/* quad-NRs */
|
||||
#define E2K_MAXNR_d (E2K_MAXNR * 2) /* The total number of */
|
||||
/* double-NRs */
|
||||
#define E2K_MAXGR_d (E2K_MAXGR * 2) /* The total number of global */
|
||||
/* double-NRs */
|
||||
#define E2K_MAXSR_d (E2K_MAXSR * 2) /* The total number of stack */
|
||||
/* double-NRs */
|
||||
|
||||
#define E2K_DEFAULT_PCS_SIZE (TARGET_PAGE_SIZE)
|
||||
#define E2K_DEFAULT_PS_SIZE (TARGET_PAGE_SIZE * 4)
|
||||
|
||||
typedef uint64_t e2k_greg_t; // double word
|
||||
|
||||
struct target_pt_regs {
|
||||
/* special registers */
|
||||
uint64_t wd; // Current window descriptor (WD)
|
||||
|
||||
uint64_t sbr; // User Stack Base Register (USBR/SBR)
|
||||
// SBR - contains the base (top) virtual address of the current User Stack area.
|
||||
|
||||
// uint64_t tr; // current type register
|
||||
|
||||
E2KPsp pcsp;
|
||||
E2KPsp psp;
|
||||
|
||||
uint32_t psr; // Processor State Register (PSR)
|
||||
uint32_t upsr; // User processor status register (UPSR)
|
||||
uint64_t ip; // instruction pointer
|
||||
uint64_t nip; // next instruction pointer
|
||||
|
||||
uint64_t ctpr1; // Control Transfer Preparation Register (CTPR)
|
||||
uint64_t ctpr2;
|
||||
uint64_t ctpr3;
|
||||
|
||||
uint32_t pfpfr; // Packed Floating Point Flag Register (PFPFR)
|
||||
uint32_t fpcr; // Floating point control register (FPCR)
|
||||
uint32_t fpsr; // Floating point state register (FPSR)
|
||||
|
||||
// borrowed from Embox OS
|
||||
uint64_t lsr; // Loop status register (LSR)
|
||||
uint64_t ilcr; // Loop counter register (ILCR)
|
||||
|
||||
uint64_t dr0;
|
||||
|
||||
uint64_t cr0_hi;
|
||||
uint64_t cr1_lo;
|
||||
uint64_t cr1_hi;
|
||||
uint64_t pcsp_hi;
|
||||
uint64_t pcsp_lo;
|
||||
uint64_t usd_lo; // User data
|
||||
uint64_t usd_hi;
|
||||
|
||||
uint64_t gbase[32];
|
||||
uint16_t gext[32];
|
||||
};
|
||||
|
||||
// FIXME: Is it right place for these constants?
|
||||
#if TARGET_LONG_BITS == 64
|
||||
#define TARGET_PAGE_OFFSET 0x0000d00000000000UL
|
||||
#define TARGET_TASK_SIZE TARGET_PAGE_OFFSET
|
||||
#else
|
||||
#define TARGET_TASK_SIZE 0xe0000000UL
|
||||
#endif
|
||||
|
||||
/* modes for sys_access_hw_stacks */
|
||||
enum {
|
||||
READ_CHAIN_STACK,
|
||||
READ_PROCEDURE_STACK,
|
||||
WRITE_PROCEDURE_STACK,
|
||||
GET_CHAIN_STACK_OFFSET,
|
||||
GET_CHAIN_STACK_SIZE,
|
||||
GET_PROCEDURE_STACK_SIZE,
|
||||
READ_CHAIN_STACK_EX,
|
||||
READ_PROCEDURE_STACK_EX,
|
||||
WRITE_PROCEDURE_STACK_EX,
|
||||
WRITE_CHAIN_STACK_EX,
|
||||
};
|
||||
|
||||
#endif /* E2K_TARGET_SYSCALL_H */
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef _E2K_TERMBITS_H_
|
||||
#define _E2K_TERMBITS_H_
|
||||
|
||||
#include "../generic/termbits.h"
|
||||
|
||||
#endif /* _E2K_TERMBITS_H_ */
|
|
@ -1556,6 +1556,73 @@ static inline void init_thread(struct target_pt_regs *regs,
|
|||
|
||||
#endif /* TARGET_HEXAGON */
|
||||
|
||||
#ifdef TARGET_E2K
|
||||
|
||||
#define elf_check_arch(x) ((x) == EM_MCST_ELBRUS || (x) == EM_E2K_OLD)
|
||||
#define ELF_START_MMAP 0x80000000
|
||||
#define ELF_CLASS ELFCLASS64
|
||||
#define ELF_ARCH EM_MCST_ELBRUS
|
||||
#define ELF_EXEC_PAGESIZE 4096
|
||||
#define ELF_NREG 256
|
||||
typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
|
||||
#define USE_ELF_CORE_DUMP
|
||||
|
||||
static abi_ulong e2k_mmap(abi_ulong size)
|
||||
{
|
||||
abi_ulong addr;
|
||||
abi_ulong guard = TARGET_PAGE_SIZE;
|
||||
|
||||
if (size < TARGET_PAGE_SIZE) {
|
||||
size = TARGET_PAGE_SIZE;
|
||||
}
|
||||
if (guard < qemu_real_host_page_size) {
|
||||
guard = qemu_real_host_page_size;
|
||||
}
|
||||
|
||||
addr = target_mmap(0, size + guard, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (addr == -1) {
|
||||
perror("mmap e2k stack");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
target_mprotect(addr + size, guard, PROT_NONE);
|
||||
return addr;
|
||||
}
|
||||
|
||||
void e2k_psp_new(E2KPsp *psp, unsigned int size, bool tags)
|
||||
{
|
||||
psp->is_readable = true;
|
||||
psp->is_writable = true;
|
||||
psp->index = 0;
|
||||
psp->size = size;
|
||||
psp->base = e2k_mmap(size);
|
||||
psp->base_tag = tags ? e2k_mmap(size / 8) : 0;
|
||||
}
|
||||
|
||||
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
|
||||
{
|
||||
abi_ulong start_stack = infop->start_stack & ~0xf;
|
||||
|
||||
regs->ip = infop->entry;
|
||||
|
||||
// FIXME: set real start stack address
|
||||
regs->sbr = infop->arg_strings & ~0xf;
|
||||
regs->usd_lo = (0x1800UL << 48) | start_stack;
|
||||
regs->usd_hi = (regs->sbr - start_stack) << 32;
|
||||
|
||||
e2k_psp_new(®s->pcsp, E2K_DEFAULT_PCS_SIZE, false);
|
||||
e2k_psp_new(®s->psp, E2K_DEFAULT_PS_SIZE, true);
|
||||
}
|
||||
|
||||
static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUE2KState *env)
|
||||
{
|
||||
/* TODO */
|
||||
qemu_log_mask(LOG_UNIMP, "elf_core_copy_regs: not implemented\n");
|
||||
}
|
||||
|
||||
#endif /* TARGET_E2K */
|
||||
|
||||
#ifndef ELF_PLATFORM
|
||||
#define ELF_PLATFORM (NULL)
|
||||
#endif
|
||||
|
|
|
@ -1411,6 +1411,22 @@ UNUSED static struct enums itimer_types[] = {
|
|||
ENUM_END,
|
||||
};
|
||||
|
||||
#ifdef TARGET_E2K
|
||||
UNUSED static struct enums access_hw_stacks_reqs[] = {
|
||||
ENUM_GENERIC(READ_CHAIN_STACK),
|
||||
ENUM_GENERIC(READ_PROCEDURE_STACK),
|
||||
ENUM_GENERIC(WRITE_PROCEDURE_STACK),
|
||||
ENUM_GENERIC(GET_CHAIN_STACK_OFFSET),
|
||||
ENUM_GENERIC(GET_CHAIN_STACK_SIZE),
|
||||
ENUM_GENERIC(GET_PROCEDURE_STACK_SIZE),
|
||||
ENUM_GENERIC(READ_CHAIN_STACK_EX),
|
||||
ENUM_GENERIC(READ_PROCEDURE_STACK_EX),
|
||||
ENUM_GENERIC(WRITE_PROCEDURE_STACK_EX),
|
||||
ENUM_GENERIC(WRITE_CHAIN_STACK_EX),
|
||||
ENUM_END,
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* print_xxx utility functions. These are used to print syscall
|
||||
* parameters in certain format. All of these have parameter
|
||||
|
@ -3758,6 +3774,22 @@ print_ioctl(void *cpu_env, const struct syscallname *name,
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_NR_access_hw_stacks
|
||||
static void
|
||||
print_access_hw_stacks(void *cpu_env, const struct syscallname *name,
|
||||
abi_long arg0, abi_long arg1, abi_long arg2,
|
||||
abi_long arg3, abi_long arg4, abi_long arg5)
|
||||
{
|
||||
print_syscall_prologue(name);
|
||||
print_enums(access_hw_stacks_reqs, arg0, 0);
|
||||
print_pointer(arg1, 0);
|
||||
print_pointer(arg2, 0);
|
||||
print_raw_param("%d", arg3, 0);
|
||||
print_pointer(arg4, 1);
|
||||
print_syscall_epilogue(name);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* An array of all of the syscalls we know about
|
||||
*/
|
||||
|
|
|
@ -126,6 +126,19 @@
|
|||
#ifdef TARGET_NR_dup3
|
||||
{ TARGET_NR_dup3, "dup3" , "%s(%d,%d,%d)", NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_e2k_longjmp2
|
||||
{ TARGET_NR_e2k_longjmp2, "e2k_longjmp2", "%s(%p, %d)", NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_access_hw_stacks
|
||||
{ TARGET_NR_access_hw_stacks, "access_hw_stacks", NULL,
|
||||
print_access_hw_stacks, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_set_backtrace
|
||||
{ TARGET_NR_set_backtrace, "set_backtrace", "%s(%p,%lu,%lu,%lu)", NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_get_backtrace
|
||||
{ TARGET_NR_get_backtrace, "get_backtrace", "%s(%p,%lu,%lu,%lu)", NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_epoll_create
|
||||
{ TARGET_NR_epoll_create, "epoll_create", "%s(%d)", NULL, NULL },
|
||||
#endif
|
||||
|
|
|
@ -6749,6 +6749,526 @@ static inline abi_long copy_to_user_flock64(abi_ulong target_flock_addr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef TARGET_E2K
|
||||
static inline abi_long copy_from_user_jmp_info(struct target_jmp_info *ji,
|
||||
abi_ulong target_jmp_info_addr)
|
||||
{
|
||||
struct target_jmp_info *target_ji;
|
||||
|
||||
if (!lock_user_struct(VERIFY_READ, target_ji, target_jmp_info_addr, 1)) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
__get_user(ji->sigmask, &target_ji->sigmask);
|
||||
__get_user(ji->cr0hi, &target_ji->cr0hi);
|
||||
__get_user(ji->cr1lo, &target_ji->cr1lo);
|
||||
__get_user(ji->pcsplo, &target_ji->pcsplo);
|
||||
__get_user(ji->pcsphi, &target_ji->pcsphi);
|
||||
__get_user(ji->pcshtp, &target_ji->pcshtp);
|
||||
__get_user(ji->br, &target_ji->br);
|
||||
__get_user(ji->usdlo, &target_ji->usdlo);
|
||||
__get_user(ji->wd, &target_ji->wd);
|
||||
__get_user(ji->reserv1, &target_ji->reserv1);
|
||||
unlock_user_struct(target_ji, target_jmp_info_addr, 0);
|
||||
if (ji->cr0hi > TARGET_TASK_SIZE) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
abi_long e2k_copy_from_user_crs(E2KCrs *crs, abi_ulong target_crs_addr)
|
||||
{
|
||||
E2KCrs *target_crs;
|
||||
|
||||
if (!lock_user_struct(VERIFY_READ, target_crs, target_crs_addr, 1)) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
__get_user(crs->cr0_lo, &target_crs->cr0_lo);
|
||||
__get_user(crs->cr0_hi, &target_crs->cr0_hi);
|
||||
__get_user(crs->cr1.lo, &target_crs->cr1.lo);
|
||||
__get_user(crs->cr1.hi, &target_crs->cr1.hi);
|
||||
unlock_user_struct(target_crs, target_crs_addr, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
abi_long e2k_copy_to_user_crs(abi_ulong target_crs_addr, E2KCrs *crs)
|
||||
{
|
||||
E2KCrs *target_crs;
|
||||
|
||||
if (!lock_user_struct(VERIFY_WRITE, target_crs, target_crs_addr, 0)) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
__put_user(crs->cr0_lo, &target_crs->cr0_lo);
|
||||
__put_user(crs->cr0_hi, &target_crs->cr0_hi);
|
||||
__put_user(crs->cr1.lo, &target_crs->cr1.lo);
|
||||
__put_user(crs->cr1.hi, &target_crs->cr1.hi);
|
||||
unlock_user_struct(target_crs, target_crs_addr, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static abi_long do_e2k_longjmp2(CPUE2KState *env, struct target_jmp_info *jmp_info)
|
||||
{
|
||||
E2KPsp jmp_pcsp;
|
||||
E2KCrs crs;
|
||||
int level; /* how many CRs need to restore */
|
||||
int ps_index = env->psp.index;
|
||||
int psize = env->wd.psize;
|
||||
int ret, i;
|
||||
target_ulong pcsp = env->pcsp.base + env->pcsp.index;
|
||||
|
||||
jmp_pcsp.lo = jmp_info->pcsplo;
|
||||
jmp_pcsp.hi = jmp_info->pcsphi;
|
||||
|
||||
level = (env->pcsp.index - jmp_pcsp.index) / CRS_SIZE;
|
||||
for (i = 0; i < level; i++) {
|
||||
ret = e2k_copy_from_user_crs(&crs, pcsp);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
psize = crs.cr1.wpsz * 2;
|
||||
ps_index -= crs.cr1.wbs * E2K_REG_LEN *
|
||||
(crs.cr1.wfx || E2K_FORCE_FX ? 4 : 2);
|
||||
pcsp -= CRS_SIZE;
|
||||
}
|
||||
|
||||
ret = e2k_copy_from_user_crs(&crs, pcsp);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
crs.cr0_hi = jmp_info->cr0hi;
|
||||
crs.cr1.lo = jmp_info->cr1lo;
|
||||
crs.cr1.br = jmp_info->br;
|
||||
crs.cr1.ussz = (env->sbr - extract64(jmp_info->usdlo, 0, 48)) >> 4;
|
||||
|
||||
ret = e2k_copy_to_user_crs(pcsp, &crs);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
env->pcsp.index = pcsp - env->pcsp.base;
|
||||
env->psp.index = ps_index;
|
||||
env->wd.psize = psize;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static abi_long copy_current_chain_stack(abi_ulong dst, abi_ulong src,
|
||||
abi_ulong size)
|
||||
{
|
||||
E2KCrs *from, *to;
|
||||
abi_long ret = 0;
|
||||
int i;
|
||||
|
||||
if (!QEMU_IS_ALIGNED(src, sizeof(*from)) ||
|
||||
!QEMU_IS_ALIGNED(size, sizeof(*from)))
|
||||
{
|
||||
return -TARGET_EINVAL;
|
||||
}
|
||||
|
||||
from = lock_user(VERIFY_READ, src, size, 1);
|
||||
to = lock_user(VERIFY_WRITE, dst, size, 0);
|
||||
if (!to || !from) {
|
||||
ret = -TARGET_EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (i = 0; i < size; i += sizeof(E2KCrs), to++, from++) {
|
||||
E2KCrs crs = *from;
|
||||
target_ulong ip;
|
||||
|
||||
memset(to, 0, sizeof(*to));
|
||||
|
||||
to->cr0_lo = from->cr0_lo;
|
||||
ip = crs.cr0_hi & ~7;
|
||||
if (ip < TARGET_TASK_SIZE) {
|
||||
to->cr0_hi = ip;
|
||||
to->cr1.ussz = from->cr1.ussz;
|
||||
}
|
||||
// FIXME: check what exactly needs to be copied
|
||||
to->cr1 = from->cr1;
|
||||
}
|
||||
|
||||
exit:
|
||||
unlock_user(from, src, size);
|
||||
unlock_user(to, dst, size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static abi_long copy_procedure_stack(CPUE2KState *env, abi_ulong dst,
|
||||
abi_ulong dst_tag, abi_ulong src, abi_ulong size)
|
||||
{
|
||||
abi_ullong *from, *to;
|
||||
uint8_t *to_tag = NULL;
|
||||
abi_long ret = 0;
|
||||
|
||||
from = lock_user(VERIFY_READ, src, size, 1);
|
||||
to = lock_user(VERIFY_WRITE, dst, size, 0);
|
||||
if (!to || !from) {
|
||||
ret = -TARGET_EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (dst_tag) {
|
||||
to_tag = lock_user(VERIFY_WRITE, dst_tag, size / 8, 0);
|
||||
if (!to_tag) {
|
||||
ret = -TARGET_EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// TODO: what to do with tags?
|
||||
memset(to_tag, 0, size / 8);
|
||||
}
|
||||
|
||||
/* v5+ has different stack layout and we need to shuffle registers
|
||||
* for backward compatibility. */
|
||||
if (env->version >= 5) {
|
||||
int i, j;
|
||||
bool to_ps = dst >= env->psp.base
|
||||
&& dst < (env->psp.base + env->psp.size);
|
||||
|
||||
i = ((to_ps ? dst : src) - env->psp.base) / sizeof(abi_ullong);
|
||||
|
||||
if (to_ps) {
|
||||
for (j = 0; j < size / sizeof(abi_ullong); j++, i++) {
|
||||
to[j + ((i & 3) == 1 ? 1 : ((i & 3) == 2 ? -1 : 0))] = from[j];
|
||||
}
|
||||
} else {
|
||||
for (j = 0; j < size / sizeof(abi_ullong); j++, i++) {
|
||||
to[j] = from[j + ((i & 3) == 1 ? 1 : ((i & 3) == 2 ? -1 : 0))];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
memcpy(to, from, size);
|
||||
}
|
||||
|
||||
exit:
|
||||
unlock_user(from, src, size);
|
||||
unlock_user(to_tag, dst_tag, size / 8);
|
||||
unlock_user(to, dst, size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static abi_long do_e2k_access_hw_stacks(CPUState *cpu, abi_ulong arg2,
|
||||
abi_ulong arg3, abi_ulong arg4, abi_ulong arg5, abi_ulong arg6)
|
||||
{
|
||||
E2KCPU *e2k_cpu = E2K_CPU(cpu);
|
||||
CPUE2KState *env = &e2k_cpu->env;
|
||||
abi_ulong mode = arg2;
|
||||
abi_ulong frame_addr = arg3; // __user (abi_ullong *)
|
||||
abi_ulong buf_addr = arg4; // __user (char *)
|
||||
abi_ulong buf_size = arg5;
|
||||
abi_ulong size_addr = arg6; // __user (void *)
|
||||
int ret = 0;
|
||||
|
||||
switch (mode) {
|
||||
case GET_PROCEDURE_STACK_SIZE:
|
||||
ret = put_user(env->psp.index, size_addr, target_ulong);
|
||||
break;
|
||||
case GET_CHAIN_STACK_SIZE:
|
||||
ret = put_user(env->pcsp.index + sizeof(E2KCrs), size_addr, target_ulong);
|
||||
break;
|
||||
case GET_CHAIN_STACK_OFFSET:
|
||||
{
|
||||
abi_ullong frame, pcs_top;
|
||||
|
||||
ret = get_user(frame, frame_addr, abi_ullong);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
pcs_top = env->pcsp.base + env->pcsp.size;
|
||||
if (env->pcsp.base > frame || pcs_top <= frame) {
|
||||
return -TARGET_ESRCH;
|
||||
}
|
||||
ret = put_user(frame - env->pcsp.base, size_addr, target_ulong);
|
||||
break;
|
||||
}
|
||||
case READ_CHAIN_STACK:
|
||||
{
|
||||
abi_ullong frame, pcs_used_top;
|
||||
abi_ulong used_size;
|
||||
|
||||
ret = get_user(frame, frame_addr, abi_ullong);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
pcs_used_top = env->pcsp.base + env->pcsp.index;
|
||||
if (frame < env->pcsp.base || frame > pcs_used_top) {
|
||||
return -TARGET_EINVAL;
|
||||
}
|
||||
used_size = frame - env->pcsp.base;
|
||||
if (size_addr) {
|
||||
ret = put_user(used_size, size_addr, target_ulong);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (used_size > buf_size) {
|
||||
return -TARGET_ENOMEM;
|
||||
}
|
||||
ret = copy_current_chain_stack(buf_addr, env->pcsp.base,
|
||||
used_size);
|
||||
break;
|
||||
}
|
||||
case READ_CHAIN_STACK_EX:
|
||||
case WRITE_CHAIN_STACK_EX:
|
||||
{
|
||||
abi_ullong frame;
|
||||
abi_ulong dst, src;
|
||||
|
||||
ret = get_user(frame, frame_addr, abi_ullong);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
if ((env->pcsp.index + sizeof(E2KCrs)) < (frame + buf_size)) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
if (mode == READ_CHAIN_STACK_EX) {
|
||||
dst = buf_addr;
|
||||
src = env->pcsp.base + frame;
|
||||
} else {
|
||||
dst = env->pcsp.base + frame;
|
||||
src = buf_addr;
|
||||
}
|
||||
ret = copy_current_chain_stack(dst, src, buf_size);
|
||||
break;
|
||||
}
|
||||
case READ_PROCEDURE_STACK:
|
||||
case WRITE_PROCEDURE_STACK:
|
||||
{
|
||||
abi_ullong offset, ps_used_top;
|
||||
abi_ulong used_size, dst, dst_tag, src;
|
||||
|
||||
ret = get_user(offset, frame_addr, abi_ullong);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
ps_used_top = env->psp.base + env->psp.index;
|
||||
if (offset < env->psp.base || offset > ps_used_top) {
|
||||
return -TARGET_EINVAL;
|
||||
}
|
||||
used_size = offset - env->psp.base;
|
||||
if (size_addr) {
|
||||
ret = put_user(used_size, size_addr, target_ulong);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (used_size > buf_size) {
|
||||
return -TARGET_ENOMEM;
|
||||
}
|
||||
if (mode == READ_PROCEDURE_STACK) {
|
||||
dst = buf_addr;
|
||||
dst_tag = 0;
|
||||
src = env->psp.base;
|
||||
} else {
|
||||
dst = env->psp.base;
|
||||
dst_tag = env->psp.base_tag;
|
||||
src = buf_addr;
|
||||
}
|
||||
ret = copy_procedure_stack(env, dst, dst_tag, src, used_size);
|
||||
break;
|
||||
}
|
||||
case READ_PROCEDURE_STACK_EX:
|
||||
case WRITE_PROCEDURE_STACK_EX:
|
||||
{
|
||||
abi_ullong offset;
|
||||
abi_ulong dst, dst_tag, src;
|
||||
|
||||
ret = get_user(offset, frame_addr, abi_ullong);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
if (env->psp.index < (offset + buf_size)) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
if (mode == READ_PROCEDURE_STACK_EX) {
|
||||
dst = buf_addr;
|
||||
dst_tag = 0;
|
||||
src = env->psp.base + offset;
|
||||
} else {
|
||||
dst = env->psp.base + offset;
|
||||
dst_tag = env->psp.base_tag + offset / 8;
|
||||
src = buf_addr;
|
||||
}
|
||||
ret = copy_procedure_stack(env, dst, dst_tag, src, buf_size);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -TARGET_ENOSYS;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool is_privileged_return(target_ulong ip)
|
||||
{
|
||||
return ip == E2K_SYSRET_BACKTRACE_ADDR;
|
||||
}
|
||||
|
||||
static abi_long do_e2k_set_backtrace(CPUState *cpu, abi_ulong buf_addr,
|
||||
abi_ulong count, abi_ulong skip, abi_ulong flags)
|
||||
{
|
||||
E2KCPU *e2k_cpu = E2K_CPU(cpu);
|
||||
CPUE2KState *env = &e2k_cpu->env;
|
||||
E2KCrs *pcs_base, *frame;
|
||||
target_ulong *buf;
|
||||
abi_long ret = 0;
|
||||
int nr_written = 0;
|
||||
uint64_t cr0_hi;
|
||||
E2KCr1 cr1;
|
||||
|
||||
if (flags) {
|
||||
return -TARGET_EINVAL;
|
||||
}
|
||||
|
||||
buf = lock_user(VERIFY_READ, buf_addr, count * sizeof(*buf), 1);
|
||||
pcs_base = lock_user(VERIFY_WRITE, env->pcsp.base, env->pcsp.index, 1);
|
||||
if (!buf || !pcs_base) {
|
||||
ret = -TARGET_EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
frame = pcs_base + env->pcsp.index / sizeof(*frame);
|
||||
|
||||
while (nr_written < count) {
|
||||
target_ulong prev_ip, ip;
|
||||
|
||||
frame -= 1;
|
||||
if (frame < pcs_base) {
|
||||
/* Not an error: we will just return the size */
|
||||
break;
|
||||
}
|
||||
|
||||
__get_user(ip, buf);
|
||||
__get_user(cr0_hi, &frame->cr0_hi);
|
||||
__get_user(cr1.lo, &frame->cr1.lo);
|
||||
|
||||
if (ip == -1) {
|
||||
ip = E2K_SYSRET_BACKTRACE_ADDR;
|
||||
}
|
||||
|
||||
prev_ip = cr0_hi & ~7;
|
||||
|
||||
/* skip fake kernel frames */
|
||||
if (prev_ip >= TARGET_TASK_SIZE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Skip the requested number of frames */
|
||||
if (skip) {
|
||||
--skip;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!is_privileged_return(ip) && !access_ok(cpu, VERIFY_READ, ip, 8)) {
|
||||
ret = -TARGET_EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Forbid changing of special return value into normal
|
||||
* one - to avoid cases when user changes to special and
|
||||
* back to normal function to avoid security checks. */
|
||||
if (is_privileged_return(prev_ip) && !is_privileged_return(ip)) {
|
||||
ret = -TARGET_EPERM;
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: ip/prev_ip page flags checks
|
||||
|
||||
cr0_hi = ip & ~7;
|
||||
|
||||
__put_user(cr0_hi, &frame->cr0_hi);
|
||||
if (is_privileged_return(ip)) {
|
||||
cr1.pm = 1;
|
||||
cr1.ic = 0;
|
||||
__put_user(cr1.lo, &frame->cr1.lo);
|
||||
}
|
||||
|
||||
buf += 1;
|
||||
nr_written += 1;
|
||||
}
|
||||
|
||||
if (nr_written) {
|
||||
ret = nr_written;
|
||||
}
|
||||
|
||||
exit:
|
||||
unlock_user(pcs_base, env->pcsp.base, env->pcsp.index);
|
||||
unlock_user(buf, buf_addr, count * sizeof(buf));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static abi_long do_e2k_get_backtrace(CPUState *cpu, abi_ulong buf_addr,
|
||||
abi_ulong count, abi_ulong skip, abi_ulong flags)
|
||||
{
|
||||
E2KCPU *e2k_cpu = E2K_CPU(cpu);
|
||||
CPUE2KState *env = &e2k_cpu->env;
|
||||
E2KCrs *pcs_base, *frame;
|
||||
target_ulong *buf;
|
||||
abi_long ret = 0;
|
||||
int nr_read = 0;
|
||||
uint64_t cr0_hi;
|
||||
|
||||
if (flags) {
|
||||
return -TARGET_EINVAL;
|
||||
}
|
||||
|
||||
buf = lock_user(VERIFY_WRITE, buf_addr, count * sizeof(*buf), 0);
|
||||
pcs_base = lock_user(VERIFY_READ, env->pcsp.base, env->pcsp.index, 1);
|
||||
if (!buf || !pcs_base) {
|
||||
ret = -TARGET_EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
frame = pcs_base + env->pcsp.index / sizeof(*frame);
|
||||
|
||||
while (nr_read < count) {
|
||||
target_ulong ip;
|
||||
|
||||
frame -= 1;
|
||||
if (frame < pcs_base) {
|
||||
/* Not an error: we will just return the size */
|
||||
break;
|
||||
}
|
||||
|
||||
__get_user(cr0_hi, &frame->cr0_hi);
|
||||
ip = cr0_hi & ~7;
|
||||
|
||||
/* skip fake kernel frames */
|
||||
if (!is_privileged_return(ip) && ip >= TARGET_TASK_SIZE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Skip the requested number of frames */
|
||||
if (skip) {
|
||||
--skip;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!is_privileged_return(ip) && !access_ok(cpu, VERIFY_READ, ip, 8)) {
|
||||
ret = -TARGET_EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Special case of "just return" function */
|
||||
if (is_privileged_return(ip)) {
|
||||
ip = -1;
|
||||
}
|
||||
|
||||
__put_user(ip, buf);
|
||||
|
||||
buf += 1;
|
||||
nr_read += 1;
|
||||
}
|
||||
|
||||
if (nr_read) {
|
||||
ret = nr_read;
|
||||
}
|
||||
|
||||
exit:
|
||||
unlock_user(pcs_base, env->pcsp.base, env->pcsp.index);
|
||||
unlock_user(buf, buf_addr, count * sizeof(buf));
|
||||
return ret;
|
||||
}
|
||||
#endif /* end of TARGET_E2K */
|
||||
|
||||
static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
|
||||
{
|
||||
struct flock64 fl64;
|
||||
|
@ -11839,6 +12359,35 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
|||
#endif
|
||||
return ret;
|
||||
#endif
|
||||
#ifdef TARGET_NR_e2k_longjmp2
|
||||
case TARGET_NR_e2k_longjmp2:
|
||||
{
|
||||
E2KCPU *e2k_cpu = E2K_CPU(cpu);
|
||||
CPUE2KState *env = &e2k_cpu->env;
|
||||
struct target_jmp_info ji;
|
||||
ret = copy_from_user_jmp_info(&ji, arg1);
|
||||
if (ret) {
|
||||
break;
|
||||
}
|
||||
ret = do_e2k_longjmp2(env, &ji);
|
||||
if (ret) {
|
||||
break;
|
||||
}
|
||||
return arg2;
|
||||
}
|
||||
#endif
|
||||
#ifdef TARGET_NR_access_hw_stacks
|
||||
case TARGET_NR_access_hw_stacks:
|
||||
return do_e2k_access_hw_stacks(cpu, arg1, arg2, arg3, arg4, arg5);
|
||||
#endif
|
||||
#ifdef TARGET_NR_set_backtrace
|
||||
case TARGET_NR_set_backtrace:
|
||||
return do_e2k_set_backtrace(cpu, arg1, arg2, arg3, arg4);
|
||||
#endif
|
||||
#ifdef TARGET_NR_get_backtrace
|
||||
case TARGET_NR_get_backtrace:
|
||||
return do_e2k_get_backtrace(cpu, arg1, arg2, arg3, arg4);
|
||||
#endif
|
||||
#ifdef CONFIG_ATTR
|
||||
#ifdef TARGET_NR_setxattr
|
||||
case TARGET_NR_listxattr:
|
||||
|
|
|
@ -74,7 +74,7 @@
|
|||
|| defined(TARGET_M68K) || defined(TARGET_CRIS) \
|
||||
|| defined(TARGET_S390X) || defined(TARGET_OPENRISC) \
|
||||
|| defined(TARGET_NIOS2) || defined(TARGET_RISCV) \
|
||||
|| defined(TARGET_XTENSA)
|
||||
|| defined(TARGET_XTENSA) || defined(TARGET_E2K)
|
||||
|
||||
#define TARGET_IOC_SIZEBITS 14
|
||||
#define TARGET_IOC_DIRBITS 2
|
||||
|
@ -1372,6 +1372,25 @@ struct target_winsize {
|
|||
#define TARGET_MAP_NONBLOCK 0x20000 /* do not block on IO */
|
||||
#define TARGET_MAP_STACK 0x40000
|
||||
#define TARGET_MAP_HUGETLB 0x80000 /* create a huge page mapping */
|
||||
#elif defined(TARGET_E2K)
|
||||
#define TARGET_MAP_ANONYMOUS 0x000010 /* don't use a file */
|
||||
#define TARGET_MAP_FIXED 0x000100 /* Interpret addr exactly */
|
||||
#define TARGET_MAP_DENYWRITE 0x000800 /* ETXTBSY */
|
||||
#define TARGET_MAP_GROWSDOWN 0x001000 /* stack-like segment */
|
||||
#define TARGET_MAP_GROWSUP 0x002000 /* register stack-like segment */
|
||||
#define TARGET_MAP_EXECUTABLE 0x004000 /* mark it as an executable */
|
||||
#define TARGET_MAP_LOCKED 0x008000 /* pages are locked */
|
||||
#define TARGET_MAP_NORESERVE 0x010000 /* don't check for reservations */
|
||||
#define TARGET_MAP_POPULATE 0x020000 /* populate (prefault) pagetables */
|
||||
#define TARGET_MAP_NONBLOCK 0x040000 /* do not block on IO */
|
||||
#define TARGET_MAP_FIRST32 0x080000 /* in protected mode map in */
|
||||
/* first 2 ** 32 area */
|
||||
#define TARGET_MAP_WRITECOMBINED 0x100000 /* Write combine */
|
||||
#define TARGET_MAP_HUGETLB 0x200000 /* create a huge page mapping */
|
||||
#define TARGET_MAP_FIXED_NOREPLACE 0x400000 /* MAP_FIXED which doesn't unmap */
|
||||
/* underlying mapping */
|
||||
#define TARGET_MAP_STACK TARGET_MAP_GROWSDOWN
|
||||
|
||||
#else
|
||||
#define TARGET_MAP_FIXED 0x10 /* Interpret addr exactly */
|
||||
#define TARGET_MAP_ANONYMOUS 0x20 /* don't use a file */
|
||||
|
@ -1597,6 +1616,57 @@ struct target_stat64 {
|
|||
unsigned int __unused2;
|
||||
};
|
||||
|
||||
#elif defined(TARGET_E2K)
|
||||
#define TARGET_STAT_HAVE_NSEC
|
||||
struct target_stat {
|
||||
abi_uint st_dev;
|
||||
abi_ulong st_ino;
|
||||
abi_uint st_mode;
|
||||
abi_uint st_nlink;
|
||||
abi_uint st_uid;
|
||||
abi_uint st_gid;
|
||||
abi_uint st_rdev;
|
||||
abi_long st_size;
|
||||
abi_long st_blksize;
|
||||
abi_long st_blocks;
|
||||
abi_long target_st_atime;
|
||||
abi_ulong target_st_atime_nsec;
|
||||
abi_long target_st_mtime;
|
||||
abi_ulong target_st_mtime_nsec;
|
||||
abi_long target_st_ctime;
|
||||
abi_ulong target_st_ctime_nsec;
|
||||
};
|
||||
|
||||
#define TARGET_HAS_STRUCT_STAT64
|
||||
struct target_stat64 {
|
||||
abi_ullong st_dev;
|
||||
abi_ullong st_ino;
|
||||
abi_uint st_mode;
|
||||
abi_uint st_nlink;
|
||||
abi_uint st_uid;
|
||||
abi_uint st_gid;
|
||||
abi_ullong st_rdev;
|
||||
abi_ullong st_size;
|
||||
abi_uint st_blksize;
|
||||
abi_uint __unused1;
|
||||
abi_ullong st_blocks;
|
||||
#if 0
|
||||
abi_int target_st_atime;
|
||||
abi_uint target_st_atime_nsec;
|
||||
abi_int target_st_mtime;
|
||||
abi_uint target_st_mtime_nsec;
|
||||
abi_int target_st_ctime;
|
||||
abi_uint target_st_ctime_nsec;
|
||||
#else
|
||||
abi_long target_st_atime;
|
||||
abi_ulong target_st_atime_nsec;
|
||||
abi_long target_st_mtime;
|
||||
abi_ulong target_st_mtime_nsec;
|
||||
abi_long target_st_ctime;
|
||||
abi_ulong target_st_ctime_nsec;
|
||||
#endif
|
||||
};
|
||||
|
||||
#elif defined(TARGET_PPC)
|
||||
|
||||
#define TARGET_STAT_HAVE_NSEC
|
||||
|
@ -2388,6 +2458,36 @@ struct target_statfs64 {
|
|||
int32_t f_flags;
|
||||
int32_t f_spare[4];
|
||||
};
|
||||
#elif defined(TARGET_E2K)
|
||||
struct target_statfs {
|
||||
abi_long f_type;
|
||||
abi_long f_bsize;
|
||||
abi_ulong f_blocks;
|
||||
abi_ulong f_bfree;
|
||||
abi_ulong f_bavail;
|
||||
abi_ulong f_files;
|
||||
abi_ulong f_ffree;
|
||||
target_fsid_t f_fsid;
|
||||
abi_long f_namelen;
|
||||
abi_long f_frsize;
|
||||
abi_long f_flags;
|
||||
abi_long f_spare[4];
|
||||
};
|
||||
|
||||
struct target_statfs64 {
|
||||
abi_long f_type;
|
||||
abi_long f_bsize;
|
||||
abi_ullong f_blocks;
|
||||
abi_ullong f_bfree;
|
||||
abi_ullong f_bavail;
|
||||
abi_ullong f_files;
|
||||
abi_ullong f_ffree;
|
||||
target_fsid_t f_fsid;
|
||||
abi_long f_namelen;
|
||||
abi_long f_frsize;
|
||||
abi_long f_flags;
|
||||
abi_long f_spare[4];
|
||||
};
|
||||
#else
|
||||
struct target_statfs {
|
||||
uint32_t f_type;
|
||||
|
|
|
@ -1483,6 +1483,7 @@ disassemblers = {
|
|||
'avr' : ['CONFIG_AVR_DIS'],
|
||||
'cris' : ['CONFIG_CRIS_DIS'],
|
||||
'hexagon' : ['CONFIG_HEXAGON_DIS'],
|
||||
'e2k' : ['CONFIG_E2K_DIS'],
|
||||
'hppa' : ['CONFIG_HPPA_DIS'],
|
||||
'i386' : ['CONFIG_I386_DIS'],
|
||||
'x86_64' : ['CONFIG_I386_DIS'],
|
||||
|
@ -2111,6 +2112,7 @@ if have_system
|
|||
'hw/char',
|
||||
'hw/display',
|
||||
'hw/dma',
|
||||
'hw/e2k',
|
||||
'hw/hppa',
|
||||
'hw/hyperv',
|
||||
'hw/i2c',
|
||||
|
@ -2160,6 +2162,7 @@ if have_system or have_user
|
|||
'accel/tcg',
|
||||
'hw/core',
|
||||
'target/arm',
|
||||
'target/e2k',
|
||||
'target/hppa',
|
||||
'target/i386',
|
||||
'target/i386/kvm',
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
qemu_target_list="i386 i486 alpha arm armeb sparc sparc32plus sparc64 \
|
||||
ppc ppc64 ppc64le m68k mips mipsel mipsn32 mipsn32el mips64 mips64el \
|
||||
sh4 sh4eb s390x aarch64 aarch64_be hppa riscv32 riscv64 xtensa xtensaeb \
|
||||
microblaze microblazeel or1k x86_64 hexagon"
|
||||
microblaze microblazeel or1k x86_64 hexagon e2k e2k_old e2k32 e2k32_old"
|
||||
|
||||
i386_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00'
|
||||
i386_mask='\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
|
||||
|
@ -140,6 +140,22 @@ hexagon_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x
|
|||
hexagon_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
|
||||
hexagon_family=hexagon
|
||||
|
||||
e2k_magic='\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xaf\x00'
|
||||
e2k_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
|
||||
e2k_family=e2k
|
||||
|
||||
e2k_old_magic='\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x31\x00'
|
||||
e2k_old_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
|
||||
e2k_old_family=e2k
|
||||
|
||||
e2k32_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xaf\x00'
|
||||
e2k32_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
|
||||
e2k32_family=e2k
|
||||
|
||||
e2k32_old_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x31\x00'
|
||||
e2k32_old_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
|
||||
e2k32_old_family=e2k
|
||||
|
||||
qemu_get_family() {
|
||||
cpu=${HOST_ARCH:-$(uname -m)}
|
||||
case "$cpu" in
|
||||
|
@ -316,10 +332,12 @@ qemu_set_binfmts() {
|
|||
continue
|
||||
fi
|
||||
|
||||
qemu="$QEMU_PATH/qemu-$cpu"
|
||||
if [ "$cpu" = "i486" ] ; then
|
||||
qemu="$QEMU_PATH/qemu-i386"
|
||||
fi
|
||||
case "$cpu" in
|
||||
"i486" ) qemu="$QEMU_PATH/qemu-i386";;
|
||||
"e2k_old" ) qemu="$QEMU_PATH/qemu-e2k";;
|
||||
"e2k32_old" ) qemu="$QEMU_PATH/qemu-e2k32";;
|
||||
* ) qemu="$QEMU_PATH/qemu-$cpu";;
|
||||
esac
|
||||
|
||||
qemu="$qemu$QEMU_SUFFIX"
|
||||
if [ "$host_family" != "$family" ] ; then
|
||||
|
|
|
@ -84,6 +84,8 @@ int graphic_depth = 32;
|
|||
#define QEMU_ARCH QEMU_ARCH_XTENSA
|
||||
#elif defined(TARGET_AVR)
|
||||
#define QEMU_ARCH QEMU_ARCH_AVR
|
||||
#elif defined(TARGET_E2K)
|
||||
#define QEMU_ARCH QEMU_ARCH_E2K
|
||||
#endif
|
||||
|
||||
const uint32_t arch_type = QEMU_ARCH;
|
||||
|
|
|
@ -2,6 +2,7 @@ source alpha/Kconfig
|
|||
source arm/Kconfig
|
||||
source avr/Kconfig
|
||||
source cris/Kconfig
|
||||
source e2k/Kconfig
|
||||
source hppa/Kconfig
|
||||
source i386/Kconfig
|
||||
source m68k/Kconfig
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
config E2K
|
||||
bool
|
||||
|
||||
config E2K32
|
||||
bool
|
||||
select E2K
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
* e2k CPU dump to file
|
||||
*
|
||||
* Copyright (c) 2021 Denis Drakhnya
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "helper-tcg.h"
|
||||
#include "qemu/qemu-print.h"
|
||||
|
||||
static inline const char *indent(int width, int max_width)
|
||||
{
|
||||
static const char s[] = " ";
|
||||
|
||||
assert(width < sizeof(s) && max_width < sizeof(s));
|
||||
return s + sizeof(s) - 1 - max_width + width;
|
||||
}
|
||||
|
||||
static void dump_psp(FILE *f, int flags, const char *name, E2KPsp *psp,
|
||||
bool newline)
|
||||
{
|
||||
qemu_fprintf(f, "%s %016" PRIx64 " base %016" PRIx64 " index %08" PRIx32
|
||||
" size %08" PRIx32 " %c%c itag=%x%s",
|
||||
name,
|
||||
(uint64_t) psp->base + psp->index,
|
||||
(uint64_t) psp->base,
|
||||
(uint32_t) psp->index,
|
||||
(uint32_t) psp->size,
|
||||
psp->is_readable ? 'R' : ' ',
|
||||
psp->is_writable ? 'W' : ' ',
|
||||
(int) psp->itag,
|
||||
newline ? "\n" : "");
|
||||
}
|
||||
|
||||
static void dump_rwap(FILE *f, int flags, const char *name, E2KRwap *rwap,
|
||||
bool newline)
|
||||
{
|
||||
qemu_fprintf(f, "%s %016" PRIx64 " base %016" PRIx64 " curptr %08" PRIx32
|
||||
" size %08" PRIx32 " %c%c%c%s",
|
||||
name,
|
||||
(uint64_t) rwap->base + rwap->curptr,
|
||||
(uint64_t) rwap->base,
|
||||
(uint32_t) rwap->curptr,
|
||||
(uint32_t) rwap->size,
|
||||
rwap->protected ? 'P' : ' ',
|
||||
rwap->read ? 'R' : ' ',
|
||||
rwap->write ? 'W' : ' ',
|
||||
newline ? "\n" : "");
|
||||
}
|
||||
|
||||
static void dump_lsr(CPUE2KState *env, FILE *f, int flags)
|
||||
{
|
||||
qemu_fprintf(f,
|
||||
" lcnt %016" PRIx64 " pcnt=%02x ecnt=%02x vlc=%d ldmc=%d ldovl=%02x\n"
|
||||
"ilcnt %016" PRIx64 " ipcnt=%02x iecnt=%02x over=%d semc=%d strmd=%02x\n",
|
||||
env->lsr_lcnt,
|
||||
(int) env->lsr_pcnt,
|
||||
(int) env->lsr_ecnt,
|
||||
(int) env->lsr_vlc,
|
||||
(int) extract32(env->lsr, LSR_LDMC_OFF - 32, 1),
|
||||
(int) extract32(env->lsr, LSR_LDOVL_OFF - 32, LSR_LDOVL_LEN),
|
||||
env->ilcr_lcnt,
|
||||
(int) extract32(env->ilcr, LSR_PCNT_OFF - 32, LSR_PCNT_LEN),
|
||||
(int) extract32(env->ilcr, LSR_ECNT_OFF - 32, LSR_ECNT_LEN),
|
||||
(int) env->lsr_over,
|
||||
(int) extract32(env->lsr, LSR_SEMC_OFF - 32, 1),
|
||||
(int) env->lsr_strmd
|
||||
);
|
||||
}
|
||||
|
||||
static void dump_predicate_regs(CPUE2KState *env, FILE *f, int flags)
|
||||
{
|
||||
int i;
|
||||
|
||||
qemu_fprintf(f, "pred");
|
||||
for (i = 0; i < 32; i++) {
|
||||
qemu_fprintf(f, "%s%d", indent(i > 9, 2), i);
|
||||
}
|
||||
qemu_fprintf(f, "\n ");
|
||||
for (i = 0; i < 32; i++) {
|
||||
int index = i < env->bp.size ? (i + env->bp.cur) % env->bp.size : i;
|
||||
int preg = (env->pregs >> (index * 2)) & 3;
|
||||
qemu_fprintf(f, " %c%d", preg >> 1 ? '*' : ' ', preg & 1);
|
||||
}
|
||||
qemu_fprintf(f, "\n");
|
||||
}
|
||||
|
||||
static inline void dump_reg(FILE *f, char mnemonic, int index,
|
||||
uint8_t tag, E2KReg reg)
|
||||
{
|
||||
int width = (index > 9) + (index > 99);
|
||||
const char *prefix = indent(width, 3 - ((index & 3) == 0));
|
||||
uint8_t tag_lo = tag & 3;
|
||||
uint8_t tag_hi = (tag >> 2) & 3;
|
||||
|
||||
qemu_fprintf(f, "%s%c%d <%d%d>%016" PRIx64, prefix, mnemonic, index,
|
||||
tag_hi, tag_lo, reg.lo);
|
||||
if ((index & 3) == 3) {
|
||||
qemu_fprintf(f, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_regs(CPUE2KState *env, FILE *f, int flags)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < env->wd.size; i++) {
|
||||
dump_reg(f, 'r', i, env->tags[i], env->regs[i]);
|
||||
}
|
||||
if (env->wd.size & 3) {
|
||||
qemu_fprintf(f, "\n");
|
||||
}
|
||||
|
||||
if ((env->wd.size - env->bn.base) >= env->bn.size) {
|
||||
for (i = 0; i < env->bn.size; i++) {
|
||||
int index = env->bn.base + (i + env->bn.cur) % env->bn.size;
|
||||
dump_reg(f, 'b', i, env->tags[index], env->regs[index]);
|
||||
}
|
||||
if (env->bn.size & 3) {
|
||||
qemu_fprintf(f, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
int index = E2K_NR_COUNT + i;
|
||||
dump_reg(f, 'g', i, env->tags[index], env->regs[index]);
|
||||
}
|
||||
}
|
||||
|
||||
void e2k_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
||||
{
|
||||
E2KCPU *cpu = E2K_CPU(cs);
|
||||
CPUE2KState *env = &cpu->env;
|
||||
|
||||
|
||||
qemu_fprintf(f,
|
||||
" ip %016" PRIx64 " ctpr1 %016" PRIx64 " ctpr2 %016" PRIx64 " ctpr3 %016" PRIx64 "\n"
|
||||
" sbr %016" PRIx64 " osr0 %016" PRIx64 " psr=%02x upsr=%04x\n",
|
||||
(uint64_t) env->ip,
|
||||
env->ctprs[0].raw,
|
||||
env->ctprs[1].raw,
|
||||
env->ctprs[2].raw,
|
||||
env->sbr,
|
||||
env->osr0,
|
||||
(int) env->psr,
|
||||
(int) env->upsr
|
||||
);
|
||||
dump_rwap(f, flags, " usd", &env->usd, true);
|
||||
dump_psp(f, flags, " pcsp", &env->pcsp, true);
|
||||
dump_psp(f, flags, " psp", &env->psp, true);
|
||||
dump_rwap(f, flags, "oscud", &env->oscud, true);
|
||||
dump_rwap(f, flags, " osgd", &env->osgd, true);
|
||||
dump_rwap(f, flags, " cud", &env->cud, true);
|
||||
dump_rwap(f, flags, " gd", &env->gd, true);
|
||||
dump_lsr(env, f, flags);
|
||||
qemu_fprintf(f, " wsz=%d wbdl=%d rbs=%d rsz=%d rcur=%d psz=%d pcur=%d\n",
|
||||
(int) env->wd.size,
|
||||
(int) env->wdbl,
|
||||
(int) env->bn.base,
|
||||
(int) env->bn.size,
|
||||
(int) env->bn.cur,
|
||||
(int) env->bp.size,
|
||||
(int) env->bp.cur
|
||||
);
|
||||
dump_predicate_regs(env, f, flags);
|
||||
dump_regs(env, f, flags);
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* E2K cpu parameters for qemu.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef E2K_CPU_PARAM_H
|
||||
#define E2K_CPU_PARAM_H 1
|
||||
|
||||
#ifdef TARGET_E2K32
|
||||
# define TARGET_LONG_BITS 32
|
||||
#else
|
||||
# define TARGET_LONG_BITS 64
|
||||
#endif
|
||||
#define TARGET_PAGE_BITS 12 /* 4k */
|
||||
#define TARGET_PHYS_ADDR_SPACE_BITS 40
|
||||
#define TARGET_VIRT_ADDR_SPACE_BITS 48
|
||||
#define NB_MMU_MODES 4
|
||||
|
||||
#endif
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* QEMU E2K CPU
|
||||
*
|
||||
* Copyright (c) 2012 SUSE LINUX Products GmbH
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see
|
||||
* <http://www.gnu.org/licenses/lgpl-2.1.html>
|
||||
*/
|
||||
#ifndef QEMU_E2K_CPU_QOM_H
|
||||
#define QEMU_E2K_CPU_QOM_H
|
||||
|
||||
#include "hw/core/cpu.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#define TYPE_E2K_CPU "e2k-cpu"
|
||||
|
||||
OBJECT_DECLARE_TYPE(E2KCPU, E2KCPUClass,
|
||||
E2K_CPU)
|
||||
|
||||
typedef struct e2k_def_t e2k_def_t;
|
||||
/**
|
||||
* E2KCPUClass:
|
||||
* @parent_realize: The parent class' realize handler.
|
||||
* @parent_reset: The parent class' reset handler.
|
||||
*
|
||||
* A E2K CPU model.
|
||||
*/
|
||||
struct E2KCPUClass {
|
||||
/*< private >*/
|
||||
CPUClass parent_class;
|
||||
/*< public >*/
|
||||
|
||||
DeviceRealize parent_realize;
|
||||
DeviceReset parent_reset;
|
||||
e2k_def_t *cpu_def;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,462 @@
|
|||
/*
|
||||
* Sparc CPU init helpers
|
||||
*
|
||||
* Copyright (c) 2003-2005 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/qemu-print.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "cpu.h"
|
||||
#include "helper-tcg.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/core/tcg-cpu-ops.h"
|
||||
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/tcg.h"
|
||||
#include "sysemu/reset.h"
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
#include "exec/address-spaces.h"
|
||||
#include "hw/e2k/apic_internal.h"
|
||||
#include "hw/boards.h"
|
||||
#endif
|
||||
|
||||
//#define DEBUG_FEATURES
|
||||
|
||||
static void e2k_cpu_reset(DeviceState *dev)
|
||||
{
|
||||
CPUState *cs = CPU(dev);
|
||||
E2KCPU *cpu = E2K_CPU(cs);
|
||||
E2KCPUClass *ecc = E2K_CPU_GET_CLASS(cpu);
|
||||
CPUE2KState *env = &cpu->env;
|
||||
|
||||
ecc->parent_reset(dev);
|
||||
|
||||
memset(env, 0, offsetof(CPUE2KState, end_reset_fields));
|
||||
|
||||
/* must be set by set_pc */
|
||||
/* env->ip = 0x10000; */
|
||||
env->psr = PSR_PM;
|
||||
env->upsr = UPSR_NMIE | UPSR_FE;
|
||||
env->wd.base = 0;
|
||||
env->wd.size = 16;
|
||||
env->wd.psize = 8;
|
||||
env->bn.base = 8;
|
||||
env->bn.size = 8;
|
||||
env->bn.cur = 0;
|
||||
env->aau.incrs[0] = 1; /* always one */
|
||||
env->fpcr._one = 1;
|
||||
env->fpcr.pc = FPCR_PC_XP;
|
||||
env->fpcr.em = FP_EM;
|
||||
env->pfpfr.em = FP_EM;
|
||||
|
||||
e2k_update_fp_status(env);
|
||||
e2k_update_fx_status(env);
|
||||
|
||||
// FIXME: testing
|
||||
env->idr = 0x3a207; /* mimic 8c */
|
||||
|
||||
// FIXME: correct values
|
||||
env->psp.base = 0x810000;
|
||||
env->psp.size = 0x100000;
|
||||
env->pcsp.base = 0x910000;
|
||||
env->pcsp.size = 0xa10000;
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
/* FIXME: default values calculated from E2K E1CP firmware */
|
||||
env->sbr = 0xb000;
|
||||
env->usd.hi = 0x400000000000;
|
||||
env->usd.lo = env->sbr + 0x1800000000000000;
|
||||
|
||||
/* We hard-wire the BSP to the first CPU. */
|
||||
apic_designate_bsp(cpu->apic_state, cs->cpu_index == 0);
|
||||
|
||||
cs->halted = !cpu_is_bsp(cpu);
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool e2k_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
||||
{
|
||||
qemu_log_mask(LOG_UNIMP, "e2k_cpu_exec_interrupt: not implemented\n");
|
||||
if (interrupt_request & CPU_INTERRUPT_HARD) {
|
||||
e2k_cpu_do_interrupt(cs);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void e2k_cpu_do_interrupt(CPUState *cs)
|
||||
{
|
||||
E2KCPU *cpu = E2K_CPU(cs);
|
||||
CPUE2KState *env = &cpu->env;
|
||||
|
||||
qemu_log_mask(LOG_UNIMP, "e2k_cpu_do_interrupt: not implemented %d at " TARGET_FMT_lx "\n",
|
||||
cs->exception_index, env->ip);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void cpu_e2k_disas_set_info(CPUState *cs, disassemble_info *info)
|
||||
{
|
||||
E2KCPU *cpu = E2K_CPU(cs);
|
||||
CPUE2KState *env = &cpu->env;
|
||||
|
||||
info->mach = env->version * 3;
|
||||
info->print_insn = print_insn_e2k;
|
||||
}
|
||||
|
||||
/* https://www.altlinux.org/Модели_процессоров_Эльбрус */
|
||||
#define DEFAULT_CPU_MODEL "e8c"
|
||||
static const struct e2k_def_t e2k_defs[] = {
|
||||
{
|
||||
.name = "e2c+", /* however it may work better */
|
||||
.canonical_name = "MCST Elbrus 2C+ (Monocube)",
|
||||
.gdb_arch = "elbrus-v2",
|
||||
.isa_version = 2,
|
||||
},
|
||||
{
|
||||
.name = "e2s",
|
||||
.canonical_name = "MCST Elbrus 4C",
|
||||
.gdb_arch = "elbrus-v3",
|
||||
.isa_version = 3,
|
||||
},
|
||||
{
|
||||
.name = "e8c", /* default choice for system */
|
||||
.canonical_name = "MCST Elbrus 8C",
|
||||
.gdb_arch = "elbrus-8c",
|
||||
.isa_version = 4,
|
||||
},
|
||||
{
|
||||
.name = "e8c2",
|
||||
.canonical_name = "MCST Elbrus 8CB",
|
||||
.gdb_arch = "elbrus-v5",
|
||||
.isa_version = 5,
|
||||
},
|
||||
{
|
||||
.name = "e16c",
|
||||
.canonical_name = "MCST Elbrus 16C",
|
||||
.gdb_arch = "elbrus-v6",
|
||||
.isa_version = 6,
|
||||
},
|
||||
};
|
||||
|
||||
static bool e2k_get_paging_enabled(const CPUState *cs)
|
||||
{
|
||||
E2KCPU *cpu = E2K_CPU(cs);
|
||||
CPUE2KState *env = &cpu->env;
|
||||
|
||||
return env->mmu.cr & MMU_CR_TLB_EN;
|
||||
}
|
||||
|
||||
static void e2k_cpu_set_pc(CPUState *cs, vaddr value)
|
||||
{
|
||||
E2KCPU *cpu = E2K_CPU(cs);
|
||||
|
||||
cpu->env.ip = value;
|
||||
}
|
||||
|
||||
static void e2k_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb)
|
||||
{
|
||||
E2KCPU *cpu = E2K_CPU(cs);
|
||||
|
||||
cpu->env.ip = tb->pc;
|
||||
}
|
||||
|
||||
static bool e2k_cpu_has_work(CPUState *cs)
|
||||
{
|
||||
// TODO: e2k_cpu_has_work
|
||||
qemu_log_mask(LOG_UNIMP, "e2k_cpu_has_work: not implemented\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
static char *e2k_cpu_type_name(const char *cpu_model)
|
||||
{
|
||||
return g_strdup(cpu_model);
|
||||
}
|
||||
|
||||
static ObjectClass *e2k_cpu_class_by_name(const char *cpu_model)
|
||||
{
|
||||
ObjectClass *oc;
|
||||
char *typename;
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
if (!strcasecmp(cpu_model, "any")) {
|
||||
cpu_model = DEFAULT_CPU_MODEL;
|
||||
}
|
||||
#endif
|
||||
|
||||
typename = e2k_cpu_type_name(cpu_model);
|
||||
oc = object_class_by_name(typename);
|
||||
g_free(typename);
|
||||
return oc;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
bool cpu_is_bsp(E2KCPU *cpu)
|
||||
{
|
||||
return cpu_get_apic_base(cpu->apic_state) & MSR_IA32_APICBASE_BSP;
|
||||
}
|
||||
|
||||
/* TODO: remove me, when reset over QOM tree is implemented */
|
||||
static void e2k_cpu_machine_reset_cb(void *opaque)
|
||||
{
|
||||
E2KCPU *cpu = opaque;
|
||||
cpu_reset(CPU(cpu));
|
||||
}
|
||||
|
||||
void cpu_clear_apic_feature(CPUE2KState *env)
|
||||
{
|
||||
}
|
||||
|
||||
APICCommonClass *apic_get_class(void)
|
||||
{
|
||||
const char *apic_type = "apic";
|
||||
|
||||
/* TODO: kvm */
|
||||
|
||||
return APIC_COMMON_CLASS(object_class_by_name(apic_type));
|
||||
}
|
||||
|
||||
static void e2k_cpu_apic_create(E2KCPU *cpu, Error **errp)
|
||||
{
|
||||
APICCommonState *apic;
|
||||
ObjectClass *apic_class = OBJECT_CLASS(apic_get_class());
|
||||
|
||||
cpu->apic_state = DEVICE(object_new_with_class(apic_class));
|
||||
|
||||
object_property_add_child(OBJECT(cpu), "lapic",
|
||||
OBJECT(cpu->apic_state));
|
||||
object_unref(OBJECT(cpu->apic_state));
|
||||
|
||||
qdev_prop_set_uint32(cpu->apic_state, "id", cpu->apic_id);
|
||||
/* TODO: convert to link<> */
|
||||
apic = APIC_COMMON(cpu->apic_state);
|
||||
apic->cpu = cpu;
|
||||
apic->apicbase = APIC_DEFAULT_ADDRESS | MSR_IA32_APICBASE_ENABLE;
|
||||
}
|
||||
|
||||
static void e2k_cpu_apic_realize(E2KCPU *cpu, Error **errp)
|
||||
{
|
||||
APICCommonState *apic;
|
||||
static bool apic_mmio_map_once;
|
||||
|
||||
if (cpu->apic_state == NULL) {
|
||||
return;
|
||||
}
|
||||
qdev_realize(DEVICE(cpu->apic_state), NULL, errp);
|
||||
|
||||
/* Map APIC MMIO area */
|
||||
apic = APIC_COMMON(cpu->apic_state);
|
||||
if (!apic_mmio_map_once) {
|
||||
memory_region_add_subregion_overlap(get_system_memory(),
|
||||
apic->apicbase &
|
||||
MSR_IA32_APICBASE_BASE,
|
||||
&apic->io_memory,
|
||||
0x1000);
|
||||
apic_mmio_map_once = true;
|
||||
}
|
||||
}
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
static void e2k_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
{
|
||||
CPUState *cs = CPU(dev);
|
||||
E2KCPUClass *ecc = E2K_CPU_GET_CLASS(dev);
|
||||
Error *local_err = NULL;
|
||||
E2KCPU *cpu = E2K_CPU(dev);
|
||||
CPUE2KState *env = &cpu->env;
|
||||
|
||||
env->version = env->def.isa_version;
|
||||
|
||||
cpu_exec_realizefn(cs, &local_err);
|
||||
if (local_err != NULL) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
e2k_cpu_register_gdb_regs_for_features(cs);
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
qemu_register_reset(e2k_cpu_machine_reset_cb, cpu);
|
||||
|
||||
// if (ms->smp.cpus > 1) {
|
||||
e2k_cpu_apic_create(cpu, &local_err);
|
||||
if (local_err != NULL) {
|
||||
goto out;
|
||||
}
|
||||
// }
|
||||
#endif
|
||||
|
||||
qemu_init_vcpu(cs);
|
||||
|
||||
e2k_cpu_apic_realize(cpu, &local_err);
|
||||
if (local_err != NULL) {
|
||||
goto out;
|
||||
}
|
||||
cpu_reset(cs);
|
||||
|
||||
ecc->parent_realize(dev, errp);
|
||||
|
||||
out:
|
||||
if (local_err != NULL) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void e2k_cpu_initfn(Object* obj)
|
||||
{
|
||||
E2KCPU *cpu = E2K_CPU(obj);
|
||||
E2KCPUClass *ecc = E2K_CPU_GET_CLASS(obj);
|
||||
CPUE2KState *env = &cpu->env;
|
||||
|
||||
cpu_set_cpustate_pointers(cpu);
|
||||
|
||||
if (ecc->cpu_def) {
|
||||
env->def = *ecc->cpu_def;
|
||||
}
|
||||
}
|
||||
|
||||
static gchar* e2k_cpu_gdb_arch_name(CPUState *cs)
|
||||
{
|
||||
E2KCPU *cpu = E2K_CPU(cs);
|
||||
CPUE2KState *env = &cpu->env;
|
||||
|
||||
return g_strdup_printf("%s:%d", env->def.gdb_arch, TARGET_LONG_BITS);
|
||||
}
|
||||
|
||||
static struct TCGCPUOps e2k_tcg_ops = {
|
||||
.initialize = e2k_tcg_initialize,
|
||||
.synchronize_from_tb = e2k_cpu_synchronize_from_tb,
|
||||
.cpu_exec_interrupt = e2k_cpu_exec_interrupt,
|
||||
.do_interrupt = e2k_cpu_do_interrupt,
|
||||
.tlb_fill = e2k_cpu_tlb_fill,
|
||||
};
|
||||
|
||||
static Property e2k_cpu_properties[] = {
|
||||
DEFINE_PROP_BOOL("force_save_alc_dst", E2KCPU, env.force_save_alc_dst, false),
|
||||
DEFINE_PROP_BOOL("tags", E2KCPU, env.enable_tags, false),
|
||||
DEFINE_PROP_END_OF_LIST()
|
||||
};
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
#include "hw/core/sysemu-cpu-ops.h"
|
||||
|
||||
static const struct SysemuCPUOps e2k_sysemu_ops = {
|
||||
.get_paging_enabled = e2k_get_paging_enabled,
|
||||
.get_phys_page_attrs_debug = e2k_get_phys_page_attrs_debug,
|
||||
};
|
||||
#endif
|
||||
|
||||
static void e2k_cpu_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
E2KCPUClass *ecc = E2K_CPU_CLASS(oc);
|
||||
CPUClass *cc = CPU_CLASS(oc);
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
device_class_set_parent_realize(dc, e2k_cpu_realizefn,
|
||||
&ecc->parent_realize);
|
||||
device_class_set_props(dc, e2k_cpu_properties);
|
||||
device_class_set_parent_reset(dc, e2k_cpu_reset, &ecc->parent_reset);
|
||||
|
||||
cc->has_work = e2k_cpu_has_work;
|
||||
cc->dump_state = e2k_cpu_dump_state;
|
||||
cc->set_pc = e2k_cpu_set_pc;
|
||||
cc->class_by_name = e2k_cpu_class_by_name;
|
||||
cc->disas_set_info = cpu_e2k_disas_set_info;
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
cc->sysemu_ops = &e2k_sysemu_ops;
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
cc->gdb_core_xml_file = "e2k-v1.xml";
|
||||
cc->gdb_arch_name = e2k_cpu_gdb_arch_name;
|
||||
cc->gdb_read_register = e2k_cpu_gdb_read_register;
|
||||
cc->gdb_write_register = e2k_cpu_gdb_write_register;
|
||||
cc->gdb_num_core_regs = 574;
|
||||
|
||||
cc->tcg_ops = &e2k_tcg_ops;
|
||||
}
|
||||
|
||||
static const TypeInfo e2k_cpu_type_info = {
|
||||
.name = TYPE_E2K_CPU,
|
||||
.parent = TYPE_CPU,
|
||||
.instance_size = sizeof(E2KCPU),
|
||||
.instance_init = e2k_cpu_initfn,
|
||||
.abstract = true,
|
||||
.class_size = sizeof(E2KCPUClass),
|
||||
.class_init = e2k_cpu_class_init,
|
||||
};
|
||||
|
||||
static void e2k_cpu_cpudef_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
E2KCPUClass *ecc = E2K_CPU_CLASS(oc);
|
||||
ecc->cpu_def = data;
|
||||
}
|
||||
|
||||
static void e2k_register_cpudef_type(const struct e2k_def_t *def)
|
||||
{
|
||||
char *typename = e2k_cpu_type_name(def->name);
|
||||
TypeInfo ti = {
|
||||
.name = typename,
|
||||
.parent = TYPE_E2K_CPU,
|
||||
.class_init = e2k_cpu_cpudef_class_init,
|
||||
.class_data = (void *)def,
|
||||
};
|
||||
|
||||
type_register(&ti);
|
||||
g_free(typename);
|
||||
}
|
||||
|
||||
static void e2k_cpu_register_types(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
type_register_static(&e2k_cpu_type_info);
|
||||
for (i = 0; i < ARRAY_SIZE(e2k_defs); i++) {
|
||||
e2k_register_cpudef_type(&e2k_defs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
type_init(e2k_cpu_register_types)
|
||||
|
||||
void e2k_cpu_list(void)
|
||||
{
|
||||
unsigned int i;
|
||||
size_t len = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(e2k_defs); i++) {
|
||||
qemu_printf("%6s (%-30s) ISA version: v%d\n",
|
||||
e2k_defs[i].name,
|
||||
e2k_defs[i].canonical_name,
|
||||
e2k_defs[i].isa_version
|
||||
);
|
||||
}
|
||||
|
||||
qemu_printf("\nFeatures:\n");
|
||||
for (i = 0; i < ARRAY_SIZE(e2k_cpu_properties); i++) {
|
||||
const char *name = e2k_cpu_properties[i].name;
|
||||
size_t l = strlen(name) + 1;
|
||||
if (len + l >= 75) {
|
||||
qemu_printf("\n");
|
||||
len = 0;
|
||||
}
|
||||
qemu_printf("%s%s", len ? " " : " ", name);
|
||||
len += l;
|
||||
}
|
||||
qemu_printf("\n");
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,379 @@
|
|||
/*
|
||||
* Elbrus 2000 gdb server stub
|
||||
*
|
||||
* Copyright (c) 2003-2005 Fabrice Bellard
|
||||
* Copyright (c) 2013 SUSE LINUX Products GmbH
|
||||
* Copyright (c) 2020 Alibek Omarov
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "cpu.h"
|
||||
#include "helper-tcg.h"
|
||||
#include "exec/gdbstub.h"
|
||||
|
||||
/* TODO: reverse engineer e2k-linux-gdb register ids */
|
||||
|
||||
static uint64_t cr_read(CPUState *cs, CPUE2KState *env, size_t offset)
|
||||
{
|
||||
target_ulong addr = env->pcsp.base + env->pcsp.index + offset;
|
||||
uint64_t r;
|
||||
cpu_memory_rw_debug(cs, addr, &r, sizeof(r), false);
|
||||
return r;
|
||||
}
|
||||
|
||||
int e2k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
|
||||
{
|
||||
E2KCPU *cpu = E2K_CPU(cs);
|
||||
// CPUClass *cc = CPU_GET_CLASS(cs);
|
||||
CPUE2KState *env = &cpu->env;
|
||||
|
||||
switch (n) {
|
||||
case 0: return gdb_get_reg64(mem_buf, 0); // unk
|
||||
case 1: return gdb_get_reg64(mem_buf, 0); // b0
|
||||
case 2: return gdb_get_reg64(mem_buf, 0); // b1
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (3 <= n && n < 35) {
|
||||
return gdb_get_reg64(mem_buf, env->regs[E2K_NR_COUNT + n - 3].lo);
|
||||
}
|
||||
|
||||
switch (n) {
|
||||
case 35: return gdb_get_reg64(mem_buf, env->psr); // psr
|
||||
case 36: return gdb_get_reg64(mem_buf, env->upsr); // upsr
|
||||
case 37: return gdb_get_reg64(mem_buf, env->oscud.lo); // oscud_lo
|
||||
case 38: return gdb_get_reg64(mem_buf, env->oscud.hi); // oscud_hi
|
||||
case 39: return gdb_get_reg64(mem_buf, env->osgd.lo); // osgd_lo
|
||||
case 40: return gdb_get_reg64(mem_buf, env->osgd.hi); // osgd_hi
|
||||
case 41: return gdb_get_reg64(mem_buf, 0); // osem
|
||||
case 42: return gdb_get_reg64(mem_buf, env->osr0); // osr0
|
||||
case 43: return gdb_get_reg64(mem_buf, env->pfpfr.raw); // pfpfr
|
||||
case 44: return gdb_get_reg64(mem_buf, env->fpcr.raw); // fpcr
|
||||
case 45: return gdb_get_reg64(mem_buf, env->fpsr.raw); // fpsr
|
||||
case 46: return gdb_get_reg64(mem_buf, 0); // usbr
|
||||
case 47: return gdb_get_reg64(mem_buf, env->usd.lo); // usd_lo
|
||||
case 48: return gdb_get_reg64(mem_buf, env->usd.hi); // usd_hi
|
||||
case 49: return gdb_get_reg64(mem_buf, env->psp.lo); // psp_lo
|
||||
case 50: return gdb_get_reg64(mem_buf, env->psp.hi); // psp_hi
|
||||
case 51: return gdb_get_reg64(mem_buf, 0); // pshtp
|
||||
case 52: return gdb_get_reg64(mem_buf, env->pregs); // pregs
|
||||
case 53: return gdb_get_reg64(mem_buf, env->ip); // ip
|
||||
case 54: { // cr1_lo
|
||||
uint64_t cr1_lo = cr_read(cs, env, offsetof(E2KCrs, cr1.lo));
|
||||
return gdb_get_reg64(mem_buf, cr1_lo);
|
||||
}
|
||||
case 55: { // cr1_hi
|
||||
uint64_t cr1_hi = cr_read(cs, env, offsetof(E2KCrs, cr1.hi));
|
||||
return gdb_get_reg64(mem_buf, cr1_hi);
|
||||
}
|
||||
case 56: return gdb_get_reg64(mem_buf, 0); // cwd
|
||||
case 57: return gdb_get_reg64(mem_buf, env->pcsp.lo); // pcsp_lo
|
||||
case 58: return gdb_get_reg64(mem_buf, env->pcsp.hi); // pcsp_hi
|
||||
case 59: return gdb_get_reg64(mem_buf, 0); // pcshtp
|
||||
case 60: return gdb_get_reg64(mem_buf, env->cud.lo); // cud_lo
|
||||
case 61: return gdb_get_reg64(mem_buf, env->cud.hi); // cud_hi
|
||||
case 62: return gdb_get_reg64(mem_buf, env->gd.lo); // gd_lo
|
||||
case 63: return gdb_get_reg64(mem_buf, env->gd.hi); // gd_hi
|
||||
case 64: return gdb_get_reg64(mem_buf, env->cs.lo); // cs_lo
|
||||
case 65: return gdb_get_reg64(mem_buf, env->cs.hi); // cs_hi
|
||||
case 66: return gdb_get_reg64(mem_buf, env->ds.lo); // ds_lo
|
||||
case 67: return gdb_get_reg64(mem_buf, env->ds.hi); // ds_hi
|
||||
case 68: return gdb_get_reg64(mem_buf, env->es.lo); // es_lo
|
||||
case 69: return gdb_get_reg64(mem_buf, env->es.hi); // es_hi
|
||||
case 70: return gdb_get_reg64(mem_buf, env->fs.lo); // fs_lo
|
||||
case 71: return gdb_get_reg64(mem_buf, env->fs.hi); // fs_hi
|
||||
case 72: return gdb_get_reg64(mem_buf, env->gs.lo); // gs_lo
|
||||
case 73: return gdb_get_reg64(mem_buf, env->gs.hi); // gs_hi
|
||||
case 74: return gdb_get_reg64(mem_buf, env->ss.lo); // ss_lo
|
||||
case 75: return gdb_get_reg64(mem_buf, env->ss.hi); // ss_hi
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (76 <= n && n < 140) {
|
||||
int idx = (n - 76) >> 1;
|
||||
if (n & 1) {
|
||||
return gdb_get_reg64(mem_buf, env->aau.ds[idx].hi); // addN_hi
|
||||
} else {
|
||||
return gdb_get_reg64(mem_buf, env->aau.ds[idx].lo); // addN_lo
|
||||
}
|
||||
}
|
||||
|
||||
if (140 <= n && n < 156) {
|
||||
return gdb_get_reg64(mem_buf, env->aau.inds[n - 140]); // aaindN
|
||||
}
|
||||
|
||||
if (156 <= n && n < 164) {
|
||||
return gdb_get_reg64(mem_buf, env->aau.incrs[n - 156]); // aaincrN
|
||||
}
|
||||
|
||||
if (164 <= n && n < 196) {
|
||||
return gdb_get_reg64(mem_buf, env->aau.pl.area[n - 164].ldi); // aaldiN
|
||||
}
|
||||
|
||||
if (196 <= n && n < 228) {
|
||||
return gdb_get_reg64(mem_buf, env->aau.pr.area[n - 196].ldi); // aaldiN
|
||||
}
|
||||
|
||||
if (n == 228) {
|
||||
return gdb_get_reg64(mem_buf, env->aau.ldv); // aaldv
|
||||
}
|
||||
|
||||
if (229 <= n && n < 293) {
|
||||
return gdb_get_reg64(mem_buf, env->aau.lda[n - 229].raw); // aaldaN
|
||||
}
|
||||
|
||||
switch (n) {
|
||||
case 293: return gdb_get_reg64(mem_buf, env->aau.ldm); // aaldm
|
||||
case 294: return gdb_get_reg64(mem_buf, env->aau.sr.raw); // aasr
|
||||
case 295: return gdb_get_reg64(mem_buf, env->aau.fstr); // aafstr
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (296 <= n && n < 312) {
|
||||
return gdb_get_reg64(mem_buf, env->aau.stis[n - 296]); // aastiN
|
||||
}
|
||||
|
||||
switch (n) {
|
||||
case 312: return gdb_get_reg64(mem_buf, cpu_get_host_ticks()); // clkr
|
||||
case 313: return gdb_get_reg64(mem_buf, 0); // dibcr
|
||||
case 314: return gdb_get_reg64(mem_buf, 0); // ddbcr
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (315 <= n && n < 319) {
|
||||
return gdb_get_reg64(mem_buf, 0); // dibarN
|
||||
}
|
||||
|
||||
if (319 <= n && n < 323) {
|
||||
return gdb_get_reg64(mem_buf, 0); // ddbarN
|
||||
}
|
||||
|
||||
switch (n) {
|
||||
case 323: return gdb_get_reg64(mem_buf, 0); // dimcr
|
||||
case 324: return gdb_get_reg64(mem_buf, 0); // ddmcr
|
||||
case 325: return gdb_get_reg64(mem_buf, 0); // dimar0
|
||||
case 326: return gdb_get_reg64(mem_buf, 0); // dimar1
|
||||
case 327: return gdb_get_reg64(mem_buf, 0); // ddmar0
|
||||
case 328: return gdb_get_reg64(mem_buf, 0); // ddmar1
|
||||
case 329: return gdb_get_reg64(mem_buf, 0); // dibsr
|
||||
case 330: return gdb_get_reg64(mem_buf, 0); // ddbsr
|
||||
case 331: return gdb_get_reg64(mem_buf, 0); // dtcr
|
||||
case 332: return gdb_get_reg64(mem_buf, 0); // dtarf
|
||||
case 333: return gdb_get_reg64(mem_buf, 0); // dtart
|
||||
case 334: return gdb_get_reg64(mem_buf, env_wd_get(env)); // wd
|
||||
case 335: return gdb_get_reg64(mem_buf, 0); // unk
|
||||
case 336: return gdb_get_reg64(mem_buf, env->bgr); // bgr
|
||||
case 337: return gdb_get_reg64(mem_buf, 0); // unk
|
||||
case 338: return gdb_get_reg64(mem_buf, env->nip); // nip
|
||||
case 339: return gdb_get_reg64(mem_buf, env->ctprs[0].raw); // ctpr1
|
||||
case 340: return gdb_get_reg64(mem_buf, env->ctprs[1].raw); // ctpr2
|
||||
case 341: return gdb_get_reg64(mem_buf, env->ctprs[2].raw); // ctpr3
|
||||
case 342: return gdb_get_reg64(mem_buf, 0); // eir
|
||||
case 343: return gdb_get_reg64(mem_buf, 0); // tr
|
||||
case 344: return gdb_get_reg64(mem_buf, 0); // cutd
|
||||
case 345: return gdb_get_reg64(mem_buf, 0); // cuir
|
||||
case 346: return gdb_get_reg64(mem_buf, 0); // tsd
|
||||
case 347: return gdb_get_reg64(mem_buf, env_lsr_get(env)); /* lsr */
|
||||
case 348: return gdb_get_reg64(mem_buf, env_ilcr_get(env)); /* ilcr */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (349 <= n && n < 356) {
|
||||
return gdb_get_reg64(mem_buf, 0); // unk
|
||||
}
|
||||
|
||||
if (356 <= n && n < 360) {
|
||||
uint64_t tags = 0;
|
||||
int i, offset = E2K_NR_COUNT + (n - 356) * 8;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
tags |= (uint64_t) env->tags[offset + i] << (i * 8);
|
||||
}
|
||||
return gdb_get_reg64(mem_buf, tags); // gN tags (tag len is 1 byte)
|
||||
}
|
||||
|
||||
if (360 <= n && n < 368) {
|
||||
uint64_t ext = 0;
|
||||
int i, offset = E2K_NR_COUNT + (n - 360) * 4;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
ext |= ((uint64_t) env->regs[offset + i].hi & 0xffff) << (i * 16);
|
||||
}
|
||||
return gdb_get_reg64(mem_buf, ext); // xgN
|
||||
}
|
||||
|
||||
if (n == 368) {
|
||||
return gdb_get_reg64(mem_buf, 0); // rpr_hi
|
||||
}
|
||||
|
||||
if (n == 369) {
|
||||
return gdb_get_reg64(mem_buf, 0); // rpr_lo
|
||||
}
|
||||
|
||||
if (370 <= n && n < 389) {
|
||||
return gdb_get_reg64(mem_buf, 0); // tir_N_lo
|
||||
}
|
||||
|
||||
if (389 <= n && n < 408) {
|
||||
return gdb_get_reg64(mem_buf, 0); // tir_N_hi
|
||||
}
|
||||
|
||||
if (408 <= n && n < 418) {
|
||||
return gdb_get_reg64(mem_buf, 0); // trap_cell_addr_N
|
||||
}
|
||||
|
||||
if (418 <= n && n < 428) {
|
||||
return gdb_get_reg64(mem_buf, 0); // trap_cell_val_N
|
||||
}
|
||||
|
||||
if (n == 428) {
|
||||
return gdb_get_reg64(mem_buf, 0); // trap_cell_tag_N [0, 7)
|
||||
}
|
||||
|
||||
if (n == 429) {
|
||||
return gdb_get_reg64(mem_buf, 0); // trap_cell_tag_N [8, 9)
|
||||
}
|
||||
|
||||
if (430 <= n && n < 440) {
|
||||
return gdb_get_reg64(mem_buf, 0); // trap_cell_info_N
|
||||
}
|
||||
|
||||
if (440 <= n && n < 472) {
|
||||
return gdb_get_reg64(mem_buf, env->dam[n - 440].raw); // dam_N
|
||||
}
|
||||
|
||||
if (472 <= n && n < 504) {
|
||||
return gdb_get_reg64(mem_buf, 0); // sbbp_N
|
||||
}
|
||||
|
||||
if (504 <= n && n < 552) {
|
||||
return gdb_get_reg64(mem_buf, 0); // mlt_N (3 regs)
|
||||
}
|
||||
|
||||
if (n == 552) {
|
||||
return gdb_get_reg64(mem_buf, env->pcsp.base); // pcsp_base
|
||||
}
|
||||
|
||||
if (n == 553) {
|
||||
return gdb_get_reg64(mem_buf, env->psp.base); // psp_base
|
||||
}
|
||||
|
||||
if (554 <= n && n < 573) {
|
||||
return gdb_get_reg64(mem_buf, 0); // unk
|
||||
}
|
||||
|
||||
if (n == 573) {
|
||||
return gdb_get_reg32(mem_buf, 0); // unk
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s: unknown register %d\n", __FUNCTION__, n);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int e2k_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
{
|
||||
// E2KCPU *cpu = E2K_CPU(cs);
|
||||
// CPUClass *cc = CPU_GET_CLASS(cs);
|
||||
// CPUE2KState *env = &cpu->env;
|
||||
|
||||
fprintf(stderr, "%s: unknown register %d\n", __FUNCTION__, n);
|
||||
|
||||
// TODO: e2k_cpu_gdb_write_register
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gdb_get_v2(CPUE2KState *env, GByteArray *buf, int n)
|
||||
{
|
||||
if (n == 0) {
|
||||
/* idr */
|
||||
return gdb_get_reg64(buf, env->idr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gdb_set_v2(CPUE2KState *env, uint8_t *mem_buf, int n)
|
||||
{
|
||||
fprintf(stderr, "%s: unknown register %d\n", __FUNCTION__, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gdb_get_v3(CPUE2KState *env, GByteArray *buf, int n)
|
||||
{
|
||||
if (n == 0) {
|
||||
/* core_mode */
|
||||
return gdb_get_reg64(buf, env->core_mode);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gdb_set_v3(CPUE2KState *env, uint8_t *mem_buf, int n)
|
||||
{
|
||||
fprintf(stderr, "%s: unknown register %d\n", __FUNCTION__, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gdb_get_v5(CPUE2KState *env, GByteArray *buf, int n)
|
||||
{
|
||||
if (n == 0) {
|
||||
/* lsr1 */
|
||||
return gdb_get_reg64(buf, env->lsr_lcnt);
|
||||
} else if (n == 1) {
|
||||
/* ilcr1 */
|
||||
return gdb_get_reg64(buf, env->ilcr_lcnt);
|
||||
} else if (n >= 2 && n < 34) {
|
||||
/* xgN (upper 64-bit) */
|
||||
return gdb_get_reg64(buf, env->regs[E2K_NR_COUNT + n - 2].hi);
|
||||
} else if (n >= 34 && n < 66) {
|
||||
/* qpgN tags */
|
||||
return gdb_get_reg8(buf, env->tags[E2K_NR_COUNT + n - 34]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gdb_set_v5(CPUE2KState *env, uint8_t *mem_buf, int n)
|
||||
{
|
||||
fprintf(stderr, "%s: unknown register %d\n", __FUNCTION__, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void e2k_cpu_register_gdb_regs_for_features(CPUState *cs)
|
||||
{
|
||||
E2KCPU *cpu = E2K_CPU(cs);
|
||||
CPUE2KState *env = &cpu->env;
|
||||
|
||||
if (env->version >= 2) {
|
||||
gdb_register_coprocessor(cs, gdb_get_v2, gdb_set_v2,
|
||||
1, "e2k-v2.xml", 574);
|
||||
}
|
||||
|
||||
if (env->version >= 3) {
|
||||
gdb_register_coprocessor(cs, gdb_get_v3, gdb_set_v3,
|
||||
1, "e2k-v3.xml", 575);
|
||||
}
|
||||
|
||||
if (env->version >= 5) {
|
||||
gdb_register_coprocessor(cs, gdb_get_v5, gdb_set_v5,
|
||||
66, "e2k-v5.xml", 576);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* e2k TCG specific prototypes for helpers
|
||||
*
|
||||
* Copyright (c) 2020-2021 Denis Drakhnya, Alibek Omarov
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef E2K_HELPER_TCG_H
|
||||
#define E2K_HELPER_TCG_H
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/exec-all.h"
|
||||
|
||||
#define glue3(x, y, z) glue(glue(x, y), z)
|
||||
#define glue4(x, y, z, w) glue(glue3(x, y, z), w)
|
||||
#define deref(x) *(x)
|
||||
#define ident(x) (x)
|
||||
|
||||
/* helper.c */
|
||||
void QEMU_NORETURN raise_exception(CPUE2KState *desc, int exception_index);
|
||||
void QEMU_NORETURN raise_exception_ra(CPUE2KState *desc, int exception_index,
|
||||
uintptr_t retaddr);
|
||||
|
||||
static inline uint64_t env_wd_get(CPUE2KState *env)
|
||||
{
|
||||
E2KWdState *wd = &env->wd;
|
||||
uint64_t ret = 0;
|
||||
|
||||
ret = deposit64(ret, WD_SIZE_OFF, WD_SIZE_LEN, wd->size * 8);
|
||||
ret = deposit64(ret, WD_PSIZE_OFF, WD_PSIZE_LEN, wd->psize * 8);
|
||||
ret = deposit64(ret, WD_FX_OFF, 1, wd->fx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void env_wd_set(CPUE2KState *env, uint64_t raw)
|
||||
{
|
||||
env->wd.size = extract64(raw, WD_SIZE_OFF, WD_SIZE_LEN) / 8;
|
||||
env->wd.psize = extract64(raw, WD_PSIZE_OFF, WD_PSIZE_LEN) / 8;
|
||||
env->wd.fx = extract64(raw, WD_FX_OFF, 1);
|
||||
}
|
||||
|
||||
static inline uint32_t env_br_get(CPUE2KState *env)
|
||||
{
|
||||
E2KBnState *bn = &env->bn;
|
||||
E2KBpState *bp = &env->bp;
|
||||
uint32_t ret = 0;
|
||||
|
||||
ret = deposit32(ret, BR_RBS_OFF, BR_RBS_LEN, bn->base / 2);
|
||||
ret = deposit32(ret, BR_RSZ_OFF, BR_RSZ_LEN, bn->size / 2 - 1);
|
||||
ret = deposit32(ret, BR_RCUR_OFF, BR_RCUR_LEN, bn->cur / 2);
|
||||
|
||||
ret = deposit32(ret, BR_PSZ_OFF, BR_PSZ_LEN, bp->size - 1);
|
||||
ret = deposit32(ret, BR_PCUR_OFF, BR_PCUR_LEN, bp->cur);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void env_br_set(CPUE2KState *env, uint32_t br)
|
||||
{
|
||||
E2KBnState *bn = &env->bn;
|
||||
E2KBpState *bp = &env->bp;
|
||||
|
||||
bn->base = extract32(br, BR_RBS_OFF, BR_RBS_LEN) * 2;
|
||||
bn->size = extract32(br, BR_RSZ_OFF, BR_RSZ_LEN) * 2 + 2;
|
||||
bn->cur = extract32(br, BR_RCUR_OFF, BR_RCUR_LEN) * 2;
|
||||
|
||||
bp->size = extract32(br, BR_PSZ_OFF, BR_PSZ_LEN) + 1;
|
||||
bp->cur = extract32(br, BR_PCUR_OFF, BR_PCUR_LEN);
|
||||
}
|
||||
|
||||
static inline uint64_t env_lsr_get(CPUE2KState *env)
|
||||
{
|
||||
uint64_t lsr = env->lsr;
|
||||
lsr = deposit64(lsr, LSR_LCNT_OFF, LSR_LCNT_LEN, env->lsr_lcnt);
|
||||
lsr = deposit64(lsr, LSR_ECNT_OFF, LSR_ECNT_LEN, env->lsr_ecnt);
|
||||
lsr = deposit64(lsr, LSR_VLC_OFF, 1, env->lsr_vlc);
|
||||
lsr = deposit64(lsr, LSR_OVER_OFF, 1, env->lsr_over);
|
||||
lsr = deposit64(lsr, LSR_PCNT_OFF, LSR_PCNT_LEN, env->lsr_pcnt);
|
||||
lsr = deposit64(lsr, LSR_STRMD_OFF, LSR_STRMD_LEN, env->lsr_strmd);
|
||||
return lsr;
|
||||
}
|
||||
|
||||
static inline void env_lsr_set(CPUE2KState *env, uint64_t val)
|
||||
{
|
||||
env->lsr = val;
|
||||
env->lsr_lcnt = extract64(val, LSR_LCNT_OFF, LSR_LCNT_LEN);
|
||||
env->lsr_ecnt = extract64(val, LSR_ECNT_OFF, LSR_ECNT_LEN);
|
||||
env->lsr_vlc = extract64(val, LSR_VLC_OFF, 1);
|
||||
env->lsr_over = extract64(val, LSR_OVER_OFF, 1);
|
||||
env->lsr_pcnt = extract64(val, LSR_PCNT_OFF, LSR_PCNT_LEN);
|
||||
env->lsr_strmd = extract64(val, LSR_STRMD_OFF, LSR_STRMD_LEN);
|
||||
}
|
||||
|
||||
static inline uint64_t env_ilcr_get(CPUE2KState *env)
|
||||
{
|
||||
return ((uint64_t) env->ilcr << LSR_ECNT_OFF)
|
||||
| (env->ilcr_lcnt & GEN_MASK(0, LSR_LCNT_LEN));
|
||||
}
|
||||
|
||||
static inline void env_ilcr_set(CPUE2KState *env, uint64_t value)
|
||||
{
|
||||
env->ilcr = (value >> LSR_ECNT_OFF) & ILCR_MASK;
|
||||
env->ilcr_lcnt = value & GEN_MASK(0, LSR_LCNT_LEN);
|
||||
}
|
||||
|
||||
static inline uint64_t env_usd_lo_get(CPUE2KState *env)
|
||||
{
|
||||
uint64_t r = 0;
|
||||
|
||||
r = deposit64(r, USD_LO_BASE_OFF, USD_LO_BASE_LEN, env->usd.base);
|
||||
r |= env->usd.protected ? USD_LO_PROTECTED_BIT : 0;
|
||||
r |= env->usd.read ? USD_LO_READ_BIT : 0;
|
||||
r |= env->usd.write ? USD_LO_WRITE_BIT : 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void env_usd_lo_set(CPUE2KState *env, uint64_t value)
|
||||
{
|
||||
env->usd.base = extract64(value, USD_LO_BASE_OFF, USD_LO_BASE_LEN);
|
||||
env->usd.protected = (value & USD_LO_PROTECTED_BIT) != 0;
|
||||
env->usd.read = (value & USD_LO_READ_BIT) != 0;
|
||||
env->usd.write = (value & USD_LO_WRITE_BIT) != 0;
|
||||
}
|
||||
|
||||
#endif /* E2K_HELPER_TCG_H */
|
|
@ -0,0 +1,488 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "qemu/log.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "helper-tcg.h"
|
||||
#include "trace.h"
|
||||
#include "hw/e2k/memmap.h"
|
||||
|
||||
static inline void reset_ctprs(CPUE2KState *env)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
env->ctprs[i].tag = CTPR_TAG_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void ps_push(CPUE2KState *env, uint64_t value, uint8_t tag)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
if ((env->psp.index + 8) > env->psp.size) {
|
||||
raise_exception(env, EXCP_PROC_STACK_BOUNDS);
|
||||
}
|
||||
#endif
|
||||
|
||||
cpu_stq_le_data(env, env->psp.base + env->psp.index, value);
|
||||
if (env->enable_tags) {
|
||||
cpu_stb_data(env, env->psp.base_tag + env->psp.index / 8, tag);
|
||||
}
|
||||
env->psp.index += 8;
|
||||
}
|
||||
|
||||
static inline uint64_t ps_pop(CPUE2KState *env, uint8_t *ret_tag)
|
||||
{
|
||||
if (env->psp.index < 8) {
|
||||
raise_exception(env, EXCP_PROC_STACK_BOUNDS);
|
||||
}
|
||||
env->psp.index -= 8;
|
||||
if (ret_tag != NULL) {
|
||||
if (env->enable_tags) {
|
||||
abi_ptr ptr = env->psp.base_tag + env->psp.index / 8;
|
||||
*ret_tag = cpu_ldub_data(env, ptr);
|
||||
} else {
|
||||
*ret_tag = 0;
|
||||
}
|
||||
}
|
||||
return cpu_ldq_le_data(env, env->psp.base + env->psp.index);
|
||||
}
|
||||
|
||||
|
||||
static void ps_spill(CPUE2KState *env, int n, bool fx)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (env->version >= 5) {
|
||||
for (i = 0; i < n; i++) {
|
||||
ps_push(env, env->regs[i].lo, env->tags[i]);
|
||||
if (fx || E2K_FORCE_FX) {
|
||||
ps_push(env, env->regs[i].hi, 0);
|
||||
}
|
||||
}
|
||||
} else{
|
||||
for (i = 0; i < n; i += 2) {
|
||||
E2KReg r0 = env->regs[i + 0];
|
||||
E2KReg r1 = env->regs[i + 1];
|
||||
ps_push(env, r0.lo, env->tags[i]);
|
||||
ps_push(env, r1.lo, env->tags[i + 1]);
|
||||
if (fx || E2K_FORCE_FX) {
|
||||
ps_push(env, r0.hi, 0);
|
||||
ps_push(env, r1.hi, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ps_fill(CPUE2KState *env, int n, bool fx)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (env->version >= 5) {
|
||||
for (i = n; i-- > 0;) {
|
||||
if (fx || E2K_FORCE_FX) {
|
||||
env->regs[i].hi = ps_pop(env, NULL);
|
||||
}
|
||||
env->regs[i].lo = ps_pop(env, &env->tags[i]);
|
||||
}
|
||||
} else {
|
||||
for (i = n; i > 0; i -= 2) {
|
||||
E2KReg *r0 = &env->regs[i - 1];
|
||||
E2KReg *r1 = &env->regs[i - 2];
|
||||
if (fx || E2K_FORCE_FX) {
|
||||
r0->hi = ps_pop(env, NULL);
|
||||
r1->hi = ps_pop(env, NULL);
|
||||
}
|
||||
r0->lo = ps_pop(env, &env->tags[i - 1]);
|
||||
r1->lo = ps_pop(env, &env->tags[i - 2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void move_regs(CPUE2KState *env, int dst, int src, int n)
|
||||
{
|
||||
memmove(&env->regs[dst], &env->regs[src], n * sizeof(env->regs[0]));
|
||||
if (env->enable_tags) {
|
||||
memmove(&env->tags[dst], &env->tags[src], n * sizeof(env->tags[0]));
|
||||
}
|
||||
}
|
||||
|
||||
static void callee_window(CPUE2KState *env, int base, int size, bool fx)
|
||||
{
|
||||
ps_spill(env, base, fx);
|
||||
move_regs(env, 0, base, size - base);
|
||||
}
|
||||
|
||||
static void caller_window(CPUE2KState *env, int base, int params, bool fx)
|
||||
{
|
||||
move_regs(env, base, 0, params);
|
||||
ps_fill(env, base, fx);
|
||||
}
|
||||
|
||||
static void crs_write(CPUE2KState *env, target_ulong addr, E2KCrs *crs)
|
||||
{
|
||||
cpu_stq_le_data(env, addr + offsetof(E2KCrs, cr0_lo), crs->cr0_lo);
|
||||
cpu_stq_le_data(env, addr + offsetof(E2KCrs, cr0_hi), crs->cr0_hi);
|
||||
cpu_stq_le_data(env, addr + offsetof(E2KCrs, cr1.lo), crs->cr1.lo);
|
||||
cpu_stq_le_data(env, addr + offsetof(E2KCrs, cr1.hi), crs->cr1.hi);
|
||||
}
|
||||
|
||||
static void crs_read(CPUE2KState *env, target_ulong addr, E2KCrs *crs)
|
||||
{
|
||||
crs->cr0_lo = cpu_ldq_le_data(env, addr + offsetof(E2KCrs, cr0_lo));
|
||||
crs->cr0_hi = cpu_ldq_le_data(env, addr + offsetof(E2KCrs, cr0_hi));
|
||||
crs->cr1.lo = cpu_ldq_le_data(env, addr + offsetof(E2KCrs, cr1.lo));
|
||||
crs->cr1.hi = cpu_ldq_le_data(env, addr + offsetof(E2KCrs, cr1.hi));
|
||||
}
|
||||
|
||||
static void pcs_push(CPUE2KState *env, E2KCrs *crs)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
if ((env->pcsp.index + sizeof(E2KCrs) * 2) > env->pcsp.size) {
|
||||
raise_exception(env, EXCP_CHAIN_STACK_BOUNDS);
|
||||
}
|
||||
#endif
|
||||
|
||||
env->pcsp.index += sizeof(E2KCrs);
|
||||
crs_write(env, env->pcsp.base + env->pcsp.index, crs);
|
||||
}
|
||||
|
||||
static void pcs_pop(CPUE2KState *env, E2KCrs *crs)
|
||||
{
|
||||
crs_read(env, env->pcsp.base + env->pcsp.index, crs);
|
||||
|
||||
if (env->pcsp.index < sizeof(E2KCrs)) {
|
||||
raise_exception(env, EXCP_CHAIN_STACK_BOUNDS);
|
||||
} else {
|
||||
env->pcsp.index -= sizeof(E2KCrs);
|
||||
}
|
||||
}
|
||||
|
||||
void e2k_proc_call(CPUE2KState *env, int base, target_ulong ret_ip,
|
||||
bool force_fx)
|
||||
{
|
||||
E2KCrs crs;
|
||||
|
||||
crs.cr0_lo = env->pregs;
|
||||
crs.cr0_hi = ret_ip & ~7;
|
||||
crs.cr1.wbs = base / 2;
|
||||
crs.cr1.wpsz = env->wd.psize / 2;
|
||||
crs.cr1.wfx = env->wd.fx;
|
||||
crs.cr1.wdbl = env->wdbl;
|
||||
crs.cr1.psr = env->psr;
|
||||
crs.cr1.cuir = env->cuir;
|
||||
crs.cr1.br = env_br_get(env);
|
||||
crs.cr1.ussz = env->usd.size >> 4;
|
||||
|
||||
pcs_push(env, &crs);
|
||||
callee_window(env, base, env->wd.size, env->wd.fx || force_fx);
|
||||
|
||||
env->wd.fx = true;
|
||||
env->wd.size -= base;
|
||||
env->wd.psize = env->wd.size;
|
||||
}
|
||||
|
||||
void e2k_proc_return(CPUE2KState *env, bool force_fx)
|
||||
{
|
||||
E2KCrs crs;
|
||||
int base;
|
||||
|
||||
pcs_pop(env, &crs);
|
||||
base = crs.cr1.wbs * 2;
|
||||
|
||||
caller_window(env, base, env->wd.psize, crs.cr1.wfx || force_fx);
|
||||
|
||||
env->pregs = crs.cr0_lo;
|
||||
env->ip = crs.cr0_hi & ~7;
|
||||
env_br_set(env, crs.cr1.br);
|
||||
env->cuir = crs.cr1.cuir;
|
||||
env->psr = crs.cr1.psr;
|
||||
env->wd.size = env->wd.psize + base;
|
||||
env->wd.psize = crs.cr1.wpsz * 2;
|
||||
env->wd.fx = crs.cr1.wfx;
|
||||
env->wdbl = crs.cr1.wdbl;
|
||||
env->usd.size = crs.cr1.ussz << 4;
|
||||
env->usd.base = env->sbr - env->usd.size;
|
||||
}
|
||||
|
||||
static inline void do_call(CPUE2KState *env, int wbs, target_ulong ret_ip)
|
||||
{
|
||||
e2k_proc_call(env, wbs * 2, ret_ip, false);
|
||||
reset_ctprs(env);
|
||||
}
|
||||
|
||||
void HELPER(call)(CPUE2KState *env, uint64_t ctpr_raw, int call_wbs,
|
||||
target_ulong pc_next)
|
||||
{
|
||||
E2KCtpr ctpr = { .raw = ctpr_raw };
|
||||
|
||||
switch (ctpr.tag) {
|
||||
case CTPR_TAG_DISP:
|
||||
case CTPR_TAG_SDISP:
|
||||
do_call(env, call_wbs, pc_next);
|
||||
env->ip = ctpr.base;
|
||||
break;
|
||||
default:
|
||||
raise_exception(env, EXCP_ILLEGAL_OPCODE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
void HELPER(expand_stacks)(CPUE2KState *env)
|
||||
{
|
||||
if ((env->psp.size - env->psp.index) <= (E2K_REG_LEN * E2K_NR_COUNT * 4)) {
|
||||
raise_exception_ra(env, EXCP_PROC_STACK_BOUNDS, GETPC());
|
||||
}
|
||||
|
||||
if ((env->pcsp.size - env->pcsp.index) <= (sizeof(E2KCrs) * 2)) {
|
||||
raise_exception_ra(env, EXCP_CHAIN_STACK_BOUNDS, GETPC());
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_USER_ONLY */
|
||||
|
||||
uint64_t HELPER(prep_return)(CPUE2KState *env, int ipd)
|
||||
{
|
||||
E2KCtpr ret = { 0 };
|
||||
target_ulong addr = env->pcsp.base + env->pcsp.index + offsetof(E2KCrs, cr0_hi);
|
||||
uint64_t cr0_hi = cpu_ldq_le_data(env, addr) & ~7;
|
||||
|
||||
ret.ipd = ipd;
|
||||
ret.base = cr0_hi;
|
||||
ret.tag = CTPR_TAG_RETURN;
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
ret.opc = cr0_hi == E2K_SIGRET_ADDR ? CTPR_OPC_SIGRET : 0;
|
||||
#else
|
||||
// TODO: set ctpr.opc
|
||||
ret.opc = 0;
|
||||
#endif
|
||||
|
||||
return ret.raw;
|
||||
}
|
||||
|
||||
void HELPER(return)(CPUE2KState *env)
|
||||
{
|
||||
CtprOpc opc = env->ctprs[2].opc;
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
if (opc == CTPR_OPC_SIGRET) {
|
||||
CPUState *cs = env_cpu(env);
|
||||
env->wd.psize = 2;
|
||||
env->regs[0].lo = 119; /* TARGET_NR_sigreturn */
|
||||
env->tags[0] = E2K_TAG_NUMBER64;
|
||||
cs->exception_index = EXCP_SYSCALL;
|
||||
cpu_loop_exit(cs);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (opc != 0) {
|
||||
qemu_log(TARGET_FMT_lx ": unknown return ctpr opc %d\n", env->ip, opc);
|
||||
}
|
||||
|
||||
e2k_proc_return(env, false);
|
||||
reset_ctprs(env);
|
||||
}
|
||||
|
||||
void QEMU_NORETURN raise_exception(CPUE2KState *env, int exception_index)
|
||||
{
|
||||
raise_exception_ra(env, exception_index, 0);
|
||||
}
|
||||
|
||||
void QEMU_NORETURN raise_exception_ra(CPUE2KState *env, int exception_index,
|
||||
uintptr_t retaddr)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
switch (exception_index) {
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
case EXCP_SYSCALL:
|
||||
#endif
|
||||
case EXCP_PROC_STACK_BOUNDS:
|
||||
case EXCP_CHAIN_STACK_BOUNDS:
|
||||
/* ignore */
|
||||
break;
|
||||
default:
|
||||
e2k_proc_call(env, env->wd.size, env->ip, true);
|
||||
break;
|
||||
}
|
||||
cs->exception_index = exception_index;
|
||||
cpu_loop_exit_restore(cs, retaddr);
|
||||
}
|
||||
|
||||
void HELPER(raise_exception)(CPUE2KState *env, int exception_index)
|
||||
{
|
||||
raise_exception(env, exception_index);
|
||||
}
|
||||
|
||||
void HELPER(setwd)(CPUE2KState *env, int wsz, int nfx, int dbl)
|
||||
{
|
||||
int size, diff;
|
||||
|
||||
size = wsz * 2;
|
||||
diff = size - env->wd.size;
|
||||
|
||||
if (size < env->wd.psize) {
|
||||
raise_exception(env, EXCP_ILLEGAL_OPCODE);
|
||||
}
|
||||
|
||||
if (diff > 0) {
|
||||
// FIXME: zeroing registers is not needed, but useful for debugging
|
||||
#if 0
|
||||
memset(&env->regs[env->wd.size], 0, diff * sizeof(env->regs[0]));
|
||||
#endif
|
||||
if (env->enable_tags) {
|
||||
memset(&env->tags[env->wd.size], E2K_TAG_NON_NUMBER128, diff);
|
||||
}
|
||||
}
|
||||
|
||||
env->wd.size = size;
|
||||
env->wd.fx = nfx == 0;
|
||||
env->wdbl = dbl;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
hwaddr e2k_get_phys_page_attrs_debug(CPUState *cs, vaddr addr, MemTxAttrs *attrs)
|
||||
{
|
||||
E2KCPU *cpu = E2K_CPU(cs);
|
||||
CPUE2KState *env = &cpu->env;
|
||||
uint64_t pte;
|
||||
uint32_t page_offset;
|
||||
int page_size;
|
||||
|
||||
if (!(env->mmu.cr & MMU_CR_TLB_EN)) {
|
||||
pte = addr & PTE_MASK;
|
||||
page_size = PTE_SIZE;
|
||||
} else {
|
||||
// TODO: page table walk
|
||||
abort();
|
||||
}
|
||||
|
||||
pte &= ((1ULL << (env->version >= 6 ? 48 : 40)) - 1) & ~(page_size - 1);
|
||||
page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
|
||||
return pte | page_offset;
|
||||
}
|
||||
|
||||
static int handle_mmu_fault(CPUState *cs, vaddr addr, int size,
|
||||
MMUAccessType access_type, int mmu_idx)
|
||||
{
|
||||
E2KCPU *cpu = E2K_CPU(cs);
|
||||
CPUE2KState *env = &cpu->env;
|
||||
|
||||
if (!(env->mmu.cr & MMU_CR_TLB_EN)) {
|
||||
int prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
||||
|
||||
tlb_set_page(cs, addr, addr, prot, mmu_idx, PTE_SIZE);
|
||||
} else {
|
||||
// TODO: page table walk
|
||||
abort();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool e2k_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||
MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr)
|
||||
{
|
||||
E2KCPU *cpu = E2K_CPU(cs);
|
||||
CPUE2KState *env = &cpu->env;
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
raise_exception_ra(env, EXCP_DATA_PAGE, retaddr);
|
||||
#else
|
||||
env->retaddr = retaddr;
|
||||
if (handle_mmu_fault(cs, address, size, access_type, mmu_idx)) {
|
||||
raise_exception_ra(env, EXCP_DATA_PAGE, retaddr);
|
||||
}
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void HELPER(break_restore_state)(CPUE2KState *env)
|
||||
{
|
||||
e2k_proc_return(env, true);
|
||||
env->is_bp = false;
|
||||
}
|
||||
|
||||
void HELPER(debug)(CPUE2KState *env)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
env->is_bp = true;
|
||||
e2k_proc_call(env, env->wd.size, env->ip, true);
|
||||
cs->exception_index = EXCP_DEBUG;
|
||||
cpu_loop_exit(cs);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
static AddressSpace *get_addressspace_by_addr(target_ulong *addr, CPUState *env, MemTxAttrs attrs)
|
||||
{
|
||||
if (*addr >= E2K_IO_AREA_BASE && *addr < E2K_IO_AREA_BASE + E2K_IO_AREA_SIZE)
|
||||
{
|
||||
*addr -= E2K_IO_AREA_BASE;
|
||||
return &address_space_io;
|
||||
}
|
||||
|
||||
return cpu_addressspace(env, attrs);
|
||||
}
|
||||
|
||||
#define GEN_IO_LD_IMPL(T, f, op) \
|
||||
T HELPER(f)(CPUE2KState *env, target_ulong port) \
|
||||
{ \
|
||||
MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; \
|
||||
AddressSpace *as = get_addressspace_by_addr(&port, env_cpu(env), attrs); \
|
||||
T ret = address_space_ ## op (as, port, attrs, NULL); \
|
||||
trace_ioaddr_in(#f, port, ret); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define GET_IO_ST_IMPL(T, f, op) \
|
||||
void HELPER(f)(CPUE2KState *env, target_ulong port, T val) \
|
||||
{ \
|
||||
MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; \
|
||||
AddressSpace *as = get_addressspace_by_addr(&port, env_cpu(env), attrs); \
|
||||
address_space_ ## op (as, port, val, attrs, NULL); \
|
||||
trace_ioaddr_out(#f, port, val); \
|
||||
}
|
||||
|
||||
GEN_IO_LD_IMPL(uint64_t, inb, ldub)
|
||||
GEN_IO_LD_IMPL(uint64_t, inh, lduw)
|
||||
GEN_IO_LD_IMPL(uint64_t, inw, ldl)
|
||||
GEN_IO_LD_IMPL(uint64_t, ind, ldq)
|
||||
GET_IO_ST_IMPL(uint32_t, outb, stb)
|
||||
GET_IO_ST_IMPL(uint32_t, outh, stw)
|
||||
GET_IO_ST_IMPL(uint32_t, outw, stl)
|
||||
GET_IO_ST_IMPL(uint64_t, outd, stq)
|
||||
|
||||
uint64_t HELPER(mmu_ind)(CPUE2KState *env, target_ulong reg)
|
||||
{
|
||||
trace_mmu_ind(reg, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void HELPER(mmu_outd)(CPUE2KState *env, target_ulong reg, uint64_t val)
|
||||
{
|
||||
trace_mmu_outd(reg, val);
|
||||
}
|
||||
|
||||
void cpu_report_tpr_access(CPUE2KState *env, TPRAccess access)
|
||||
{
|
||||
#if 0
|
||||
E2KCPU *cpu = env_archcpu(env);
|
||||
CPUState *cs = env_cpu(env);
|
||||
|
||||
if (kvm_enabled() || whpx_enabled()) {
|
||||
env->tpr_access_type = access;
|
||||
|
||||
cpu_interrupt(cs, CPU_INTERRUPT_TPR);
|
||||
} else if (tcg_enabled()) {
|
||||
cpu_restore_state(cs, cs->mem_io_pc, false);
|
||||
|
||||
apic_handle_tpr_access_report(cpu->apic_state, env->eip, access);
|
||||
}
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,355 @@
|
|||
#define dh_alias_vec ptr
|
||||
#define dh_alias_f80 ptr
|
||||
#define dh_ctype_vec E2KReg *
|
||||
#define dh_ctype_f80 floatx80 *
|
||||
#define dh_is_signed_vec dh_is_signed_ptr
|
||||
#define dh_is_signed_f80 dh_is_signed_ptr
|
||||
|
||||
DEF_HELPER_2(raise_exception, noreturn, env, int)
|
||||
DEF_HELPER_1(debug, noreturn, env)
|
||||
DEF_HELPER_1(break_restore_state, void, env)
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
DEF_HELPER_1(expand_stacks, void, env)
|
||||
#else
|
||||
DEF_HELPER_2(inb, i64, env, tl)
|
||||
DEF_HELPER_2(inh, i64, env, tl)
|
||||
DEF_HELPER_2(inw, i64, env, tl)
|
||||
DEF_HELPER_2(ind, i64, env, tl)
|
||||
DEF_HELPER_3(outb, void, env, tl, i32)
|
||||
DEF_HELPER_3(outh, void, env, tl, i32)
|
||||
DEF_HELPER_3(outw, void, env, tl, i32)
|
||||
DEF_HELPER_3(outd, void, env, tl, i64)
|
||||
|
||||
DEF_HELPER_2(mmu_ind, i64, env, tl)
|
||||
DEF_HELPER_3(mmu_outd, void, env, tl, i64)
|
||||
#endif
|
||||
|
||||
DEF_HELPER_4(call, void, env, i64, int, tl)
|
||||
DEF_HELPER_2(prep_return, i64, env, int)
|
||||
DEF_HELPER_1(return, void, env)
|
||||
|
||||
DEF_HELPER_4(setwd, void, env, int, int, int)
|
||||
|
||||
DEF_HELPER_FLAGS_4(probe_read_access, TCG_CALL_NO_RWG, int, env, tl, int, int)
|
||||
DEF_HELPER_FLAGS_4(probe_write_access, TCG_CALL_NO_RWG, int, env, tl, int, int)
|
||||
|
||||
DEF_HELPER_1(aau_load_program, void, env)
|
||||
DEF_HELPER_6(mova_ptr, tl, env, int, int, int, int, int)
|
||||
DEF_HELPER_3(aau_am, void, env, int, int)
|
||||
DEF_HELPER_4(dam_lock_addr, void, env, i64, int, int)
|
||||
DEF_HELPER_4(dam_unlock_addr, int, env, i64, int, int)
|
||||
|
||||
DEF_HELPER_2(getsp, i64, env, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_2(state_reg_get, TCG_CALL_NO_WG_SE, i64, env, int)
|
||||
DEF_HELPER_3(state_reg_set, void, env, i64, int)
|
||||
|
||||
DEF_HELPER_FLAGS_2(sxt, TCG_CALL_NO_RWG_SE, i64, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(clmull, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(clmulh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
/* Packed Min/Max */
|
||||
DEF_HELPER_FLAGS_2(pminub, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pminsb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pminuh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pminsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pminuw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pminsw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pmaxub, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pmaxsb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pmaxuh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pmaxsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pmaxuw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pmaxsw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
/* Packed Cmp */
|
||||
DEF_HELPER_FLAGS_2(pcmpeqb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pcmpeqh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pcmpeqw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pcmpeqd, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pcmpgtb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pcmpgth, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pcmpgtw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pcmpgtd, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
/* Pached Horizontal Add */
|
||||
DEF_HELPER_FLAGS_2(phaddh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(phaddw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(phaddsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_3(qphaddh, TCG_CALL_NO_RWG, void, vec, vec, vec)
|
||||
DEF_HELPER_FLAGS_3(qphaddw, TCG_CALL_NO_RWG, void, vec, vec, vec)
|
||||
DEF_HELPER_FLAGS_3(qphaddsh, TCG_CALL_NO_RWG, void, vec, vec, vec)
|
||||
|
||||
/* Packed Horizontal Sub */
|
||||
DEF_HELPER_FLAGS_2(phsubh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(phsubw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(phsubsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_3(qphsubh, TCG_CALL_NO_RWG, void, vec, vec, vec)
|
||||
DEF_HELPER_FLAGS_3(qphsubw, TCG_CALL_NO_RWG, void, vec, vec, vec)
|
||||
DEF_HELPER_FLAGS_3(qphsubsh, TCG_CALL_NO_RWG, void, vec, vec, vec)
|
||||
|
||||
/* Packed Add using saturation */
|
||||
DEF_HELPER_FLAGS_2(paddsb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(paddsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(paddusb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(paddush, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
/* Packed Sub using saturation */
|
||||
DEF_HELPER_FLAGS_2(psubsb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psubsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psubusb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psubush, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
/* Packed shifts */
|
||||
DEF_HELPER_FLAGS_2(psllh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psllw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pslld, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psrlh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psrlw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psrld, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
/* Packed shifts with sign */
|
||||
DEF_HELPER_FLAGS_2(psrah, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psraw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
/* Packed Mul */
|
||||
DEF_HELPER_FLAGS_2(pmaddh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pmaddubsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pmulhh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pmullh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pmulhuh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pmulubhh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pmulhrsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
/* Packed Sign Mul */
|
||||
DEF_HELPER_FLAGS_2(psignb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psignh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(psignw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
/* Packed Move Mask */
|
||||
DEF_HELPER_FLAGS_2(pmovmskb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pmovmskps, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pmovmskpd, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
/* Packed packs */
|
||||
DEF_HELPER_FLAGS_2(packsshb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(packushb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(packsswh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(packuswh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
/* Packed unpacks */
|
||||
DEF_HELPER_FLAGS_2(punpcklbh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(punpcklhw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(punpcklwd, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(punpckhbh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(punpckhhw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(punpckhwd, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
/* Packed shuffle */
|
||||
DEF_HELPER_FLAGS_3(pshufb, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(pmerge, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pshufh, TCG_CALL_NO_RWG_SE, i64, i64, i32)
|
||||
DEF_HELPER_FLAGS_3(pshufw, TCG_CALL_NO_RWG_SE, i64, i64, i64, i32)
|
||||
|
||||
/* Packed uncategorized */
|
||||
DEF_HELPER_FLAGS_2(psadbw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pavgusb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pavgush, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(phminposuh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(mpsadbh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_4(plog, TCG_CALL_NO_RWG_SE, i64, i32, i64, i64, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_3(qpmpsadbh, TCG_CALL_NO_RWG, void, vec, vec, i32)
|
||||
DEF_HELPER_FLAGS_3(qpmulubhh, TCG_CALL_NO_RWG, void, vec, i64, vec)
|
||||
DEF_HELPER_FLAGS_2(qphminposuh, TCG_CALL_NO_RWG_SE, i64, vec, vec)
|
||||
DEF_HELPER_FLAGS_1(qpsgn2mskb, TCG_CALL_NO_RWG_SE, i32, vec)
|
||||
DEF_HELPER_FLAGS_3(qpmsk2sgnb, TCG_CALL_NO_RWG, void, vec, vec, i32)
|
||||
DEF_HELPER_FLAGS_4(qppermb, TCG_CALL_NO_RWG, void, vec, vec, vec, vec)
|
||||
DEF_HELPER_FLAGS_4(qpshufb, TCG_CALL_NO_RWG, void, vec, vec, vec, vec)
|
||||
|
||||
/* Float 32/64 Ops */
|
||||
DEF_HELPER_FLAGS_3(fadds, TCG_CALL_NO_RWG, i32, env, i32, i32)
|
||||
DEF_HELPER_FLAGS_3(fsubs, TCG_CALL_NO_RWG, i32, env, i32, i32)
|
||||
DEF_HELPER_FLAGS_3(fmuls, TCG_CALL_NO_RWG, i32, env, i32, i32)
|
||||
DEF_HELPER_FLAGS_3(fdivs, TCG_CALL_NO_RWG, i32, env, i32, i32)
|
||||
DEF_HELPER_FLAGS_3(fmins, TCG_CALL_NO_RWG, i32, env, i32, i32)
|
||||
DEF_HELPER_FLAGS_3(fmaxs, TCG_CALL_NO_RWG, i32, env, i32, i32)
|
||||
DEF_HELPER_FLAGS_3(fscales, TCG_CALL_NO_RWG, i32, env, i32, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_3(faddd, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(fsubd, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(fmuld, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(fdivd, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(fmind, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(fmaxd, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(fscaled, TCG_CALL_NO_RWG, i64, env, i64, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_2(frcps, TCG_CALL_NO_RWG, i32, env, i32)
|
||||
DEF_HELPER_FLAGS_2(fsqrts, TCG_CALL_NO_RWG, i32, env, i32)
|
||||
DEF_HELPER_FLAGS_2(frsqrts, TCG_CALL_NO_RWG, i32, env, i32)
|
||||
DEF_HELPER_FLAGS_3(fsqrttd, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
||||
|
||||
/* Packed Float ops */
|
||||
DEF_HELPER_FLAGS_3(pfadds, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(pfsubs, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(pfmuls, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(pfmaxs, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(pfmins, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(pfhadds, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(pfhsubs, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(pfaddsubs, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_4(qpfhadds, TCG_CALL_NO_RWG, void, vec, env, vec, vec)
|
||||
DEF_HELPER_FLAGS_4(qpfhsubs, TCG_CALL_NO_RWG, void, vec, env, vec, vec)
|
||||
|
||||
DEF_HELPER_FLAGS_3(pfstoifs, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(pistofs, TCG_CALL_NO_RWG, i64, env, i64)
|
||||
DEF_HELPER_FLAGS_2(pfstois, TCG_CALL_NO_RWG, i64, env, i64)
|
||||
DEF_HELPER_FLAGS_2(pfstoistr, TCG_CALL_NO_RWG, i64, env, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_3(qpfstoid, TCG_CALL_NO_RWG, void, vec, env, i64)
|
||||
DEF_HELPER_FLAGS_3(qpfstoidtr, TCG_CALL_NO_RWG, void, vec, env, i64)
|
||||
DEF_HELPER_FLAGS_3(qpistofd, TCG_CALL_NO_RWG, void, vec, env, i64)
|
||||
DEF_HELPER_FLAGS_3(qpfstofd, TCG_CALL_NO_RWG, void, vec, env, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_2(qpfdtois, TCG_CALL_NO_RWG, i64, env, vec)
|
||||
DEF_HELPER_FLAGS_2(qpfdtoistr, TCG_CALL_NO_RWG, i64, env, vec)
|
||||
DEF_HELPER_FLAGS_2(qpidtofs, TCG_CALL_NO_RWG, i64, env, vec)
|
||||
DEF_HELPER_FLAGS_2(qpfdtofs, TCG_CALL_NO_RWG, i64, env, vec)
|
||||
|
||||
DEF_HELPER_FLAGS_3(pfcmpeqs, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(pfcmplts, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(pfcmples, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(pfcmpuods, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(pfcmpneqs, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(pfcmpnlts, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(pfcmpnles, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(pfcmpods, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
||||
|
||||
/* FMA */
|
||||
DEF_HELPER_FLAGS_4(fmas, TCG_CALL_NO_RWG, i32, env, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_4(fmss, TCG_CALL_NO_RWG, i32, env, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_4(fnmas, TCG_CALL_NO_RWG, i32, env, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_4(fnmss, TCG_CALL_NO_RWG, i32, env, i32, i32, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(fmad, TCG_CALL_NO_RWG, i64, env, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_4(fmsd, TCG_CALL_NO_RWG, i64, env, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_4(fnmad, TCG_CALL_NO_RWG, i64, env, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_4(fnmsd, TCG_CALL_NO_RWG, i64, env, i64, i64, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_5(qpfmas, TCG_CALL_NO_RWG, void, vec, env, vec, vec, vec)
|
||||
DEF_HELPER_FLAGS_5(qpfmss, TCG_CALL_NO_RWG, void, vec, env, vec, vec, vec)
|
||||
DEF_HELPER_FLAGS_5(qpfnmas, TCG_CALL_NO_RWG, void, vec, env, vec, vec, vec)
|
||||
DEF_HELPER_FLAGS_5(qpfnmss, TCG_CALL_NO_RWG, void, vec, env, vec, vec, vec)
|
||||
DEF_HELPER_FLAGS_5(qpfmass, TCG_CALL_NO_RWG, void, vec, env, vec, vec, vec)
|
||||
DEF_HELPER_FLAGS_5(qpfmsas, TCG_CALL_NO_RWG, void, vec, env, vec, vec, vec)
|
||||
|
||||
DEF_HELPER_FLAGS_5(qpfmad, TCG_CALL_NO_RWG, void, vec, env, vec, vec, vec)
|
||||
DEF_HELPER_FLAGS_5(qpfmsd, TCG_CALL_NO_RWG, void, vec, env, vec, vec, vec)
|
||||
DEF_HELPER_FLAGS_5(qpfnmad, TCG_CALL_NO_RWG, void, vec, env, vec, vec, vec)
|
||||
DEF_HELPER_FLAGS_5(qpfnmsd, TCG_CALL_NO_RWG, void, vec, env, vec, vec, vec)
|
||||
DEF_HELPER_FLAGS_5(qpfmasd, TCG_CALL_NO_RWG, void, vec, env, vec, vec, vec)
|
||||
DEF_HELPER_FLAGS_5(qpfmsad, TCG_CALL_NO_RWG, void, vec, env, vec, vec, vec)
|
||||
|
||||
/* Float x80 ops */
|
||||
#define DEF_FX_OP2(op) \
|
||||
DEF_HELPER_FLAGS_3(glue(op, ss), TCG_CALL_NO_RWG, i32, env, f80, i32) \
|
||||
DEF_HELPER_FLAGS_3(glue(op, dd), TCG_CALL_NO_RWG, i64, env, f80, i64) \
|
||||
DEF_HELPER_FLAGS_4(glue(op, sx), TCG_CALL_NO_RWG, void, f80, env, f80, i32) \
|
||||
DEF_HELPER_FLAGS_4(glue(op, dx), TCG_CALL_NO_RWG, void, f80, env, f80, i64) \
|
||||
DEF_HELPER_FLAGS_4(glue(op, xx), TCG_CALL_NO_RWG, void, f80, env, f80, f80) \
|
||||
DEF_HELPER_FLAGS_3(glue(op, xd), TCG_CALL_NO_RWG, i64, env, f80, f80) \
|
||||
DEF_HELPER_FLAGS_3(glue(op, xs), TCG_CALL_NO_RWG, i32, env, f80, f80)
|
||||
|
||||
DEF_FX_OP2(fxadd)
|
||||
DEF_FX_OP2(fxsub)
|
||||
DEF_FX_OP2(fxmul)
|
||||
DEF_FX_OP2(fxdiv)
|
||||
|
||||
#undef DEF_FX_OP2
|
||||
|
||||
DEF_HELPER_FLAGS_3(fxdivtss, TCG_CALL_NO_RWG, f32, env, f32, f80)
|
||||
DEF_HELPER_FLAGS_3(fxdivtdd, TCG_CALL_NO_RWG, f64, env, f64, f80)
|
||||
DEF_HELPER_FLAGS_4(fxdivtsx, TCG_CALL_NO_RWG, void, f80, env, f32, f80)
|
||||
DEF_HELPER_FLAGS_4(fxdivtdx, TCG_CALL_NO_RWG, void, f80, env, f64, f80)
|
||||
|
||||
DEF_HELPER_FLAGS_3(fxrsubss, TCG_CALL_NO_RWG, i32, env, f80, i32)
|
||||
DEF_HELPER_FLAGS_3(fxrsubdd, TCG_CALL_NO_RWG, i64, env, f80, i64)
|
||||
DEF_HELPER_FLAGS_4(fxrsubsx, TCG_CALL_NO_RWG, void, f80, env, f80, i32)
|
||||
DEF_HELPER_FLAGS_4(fxrsubdx, TCG_CALL_NO_RWG, void, f80, env, f80, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_4(fxsqrttsx, TCG_CALL_NO_RWG, void, f80, env, i32, f80)
|
||||
DEF_HELPER_FLAGS_4(fxsqrttdx, TCG_CALL_NO_RWG, void, f80, env, i64, f80)
|
||||
DEF_HELPER_FLAGS_4(fxsqrttxx, TCG_CALL_NO_RWG, void, f80, env, f80, f80)
|
||||
|
||||
DEF_HELPER_FLAGS_4(fxscalesx, TCG_CALL_NO_RWG, void, f80, env, f80, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_3(fxcmpodsf, TCG_CALL_NO_RWG, i32, env, f80, f32)
|
||||
DEF_HELPER_FLAGS_3(fxcmpudsf, TCG_CALL_NO_RWG, i32, env, f80, f32)
|
||||
DEF_HELPER_FLAGS_3(fxcmpoddf, TCG_CALL_NO_RWG, i32, env, f80, f64)
|
||||
DEF_HELPER_FLAGS_3(fxcmpuddf, TCG_CALL_NO_RWG, i32, env, f80, f64)
|
||||
DEF_HELPER_FLAGS_3(fxcmpodxf, TCG_CALL_NO_RWG, i32, env, f80, f80)
|
||||
DEF_HELPER_FLAGS_3(fxcmpudxf, TCG_CALL_NO_RWG, i32, env, f80, f80)
|
||||
|
||||
/* Float Comparisons */
|
||||
#define DEF_HELPER_FP_CMP(P, S, R, A, B) \
|
||||
DEF_HELPER_FLAGS_3(glue(glue(P, cmpeq), S), TCG_CALL_NO_RWG, R, env, A, B) \
|
||||
DEF_HELPER_FLAGS_3(glue(glue(P, cmpneq), S), TCG_CALL_NO_RWG, R, env, A, B) \
|
||||
DEF_HELPER_FLAGS_3(glue(glue(P, cmple), S), TCG_CALL_NO_RWG, R, env, A, B) \
|
||||
DEF_HELPER_FLAGS_3(glue(glue(P, cmpnle), S), TCG_CALL_NO_RWG, R, env, A, B) \
|
||||
DEF_HELPER_FLAGS_3(glue(glue(P, cmplt), S), TCG_CALL_NO_RWG, R, env, A, B) \
|
||||
DEF_HELPER_FLAGS_3(glue(glue(P, cmpnlt), S), TCG_CALL_NO_RWG, R, env, A, B) \
|
||||
DEF_HELPER_FLAGS_3(glue(glue(P, cmpuod), S), TCG_CALL_NO_RWG, R, env, A, B) \
|
||||
DEF_HELPER_FLAGS_3(glue(glue(P, cmpod), S), TCG_CALL_NO_RWG, R, env, A, B)
|
||||
|
||||
DEF_HELPER_FP_CMP(f, s, i32, i32, i32)
|
||||
DEF_HELPER_FP_CMP(f, d, i64, i64, i64)
|
||||
DEF_HELPER_FP_CMP(fx, s, i64, f80, i32)
|
||||
DEF_HELPER_FP_CMP(fx, d, i64, f80, i64)
|
||||
DEF_HELPER_FP_CMP(fx, x, i64, f80, f80)
|
||||
|
||||
#undef DEF_HELPER_FP_CMP
|
||||
|
||||
/* Float Flag Comparisons */
|
||||
DEF_HELPER_FLAGS_3(fcmpodsf, TCG_CALL_NO_RWG, i32, env, i32, i32)
|
||||
DEF_HELPER_FLAGS_3(fcmpudsf, TCG_CALL_NO_RWG, i32, env, i32, i32)
|
||||
DEF_HELPER_FLAGS_3(fcmpoddf, TCG_CALL_NO_RWG, i32, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(fcmpuddf, TCG_CALL_NO_RWG, i32, env, i64, i64)
|
||||
|
||||
/* Float Conversions */
|
||||
DEF_HELPER_FLAGS_2(fstofd, TCG_CALL_NO_RWG, i64, env, i32)
|
||||
DEF_HELPER_FLAGS_3(fstofx, TCG_CALL_NO_RWG, void, f80, env, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_2(fdtofs, TCG_CALL_NO_RWG, i32, env, i64)
|
||||
DEF_HELPER_FLAGS_3(fdtofx, TCG_CALL_NO_RWG, void, f80, env, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_2(fxtofs, TCG_CALL_NO_RWG, i32, env, f80)
|
||||
DEF_HELPER_FLAGS_2(fxtofd, TCG_CALL_NO_RWG, i64, env, f80)
|
||||
|
||||
DEF_HELPER_FLAGS_2(istofs, TCG_CALL_NO_RWG, i32, env, i32)
|
||||
DEF_HELPER_FLAGS_2(istofd, TCG_CALL_NO_RWG, i64, env, i32)
|
||||
DEF_HELPER_FLAGS_3(istofx, TCG_CALL_NO_RWG, void, f80, env, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_2(idtofs, TCG_CALL_NO_RWG, i32, env, i64)
|
||||
DEF_HELPER_FLAGS_2(idtofd, TCG_CALL_NO_RWG, i64, env, i64)
|
||||
DEF_HELPER_FLAGS_3(idtofx, TCG_CALL_NO_RWG, void, f80, env, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_2(fstois, TCG_CALL_NO_RWG, i32, env, i32)
|
||||
DEF_HELPER_FLAGS_2(fstoid, TCG_CALL_NO_RWG, i64, env, i32)
|
||||
DEF_HELPER_FLAGS_2(fstoistr, TCG_CALL_NO_RWG, i32, env, i32)
|
||||
DEF_HELPER_FLAGS_2(fstoidtr, TCG_CALL_NO_RWG, i64, env, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_2(fdtois, TCG_CALL_NO_RWG, i32, env, i64)
|
||||
DEF_HELPER_FLAGS_2(fdtoid, TCG_CALL_NO_RWG, i64, env, i64)
|
||||
DEF_HELPER_FLAGS_2(fdtoistr, TCG_CALL_NO_RWG, i32, env, i64)
|
||||
DEF_HELPER_FLAGS_2(fdtoidtr, TCG_CALL_NO_RWG, i64, env, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_2(fxtois, TCG_CALL_NO_RWG, i32, env, f80)
|
||||
DEF_HELPER_FLAGS_2(fxtoistr, TCG_CALL_NO_RWG, i32, env, f80)
|
||||
DEF_HELPER_FLAGS_2(fxtoid, TCG_CALL_NO_RWG, i64, env, f80)
|
||||
DEF_HELPER_FLAGS_2(fxtoidtr, TCG_CALL_NO_RWG, i64, env, f80)
|
||||
|
||||
/* Float Rounding */
|
||||
DEF_HELPER_FLAGS_3(fstoifs, TCG_CALL_NO_RWG, i32, env, i32, i32)
|
||||
DEF_HELPER_FLAGS_3(fdtoifd, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
|
@ -0,0 +1,88 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "exec/helper-proto.h"
|
||||
|
||||
static inline void init_prefetch_area(E2KAauAreaState *s, E2KAauPrefInstr pi,
|
||||
uint32_t *inds)
|
||||
{
|
||||
s->last_page = 0;
|
||||
s->last_page_valid = false;
|
||||
if (pi.fmt != 0) {
|
||||
s->pi = pi;
|
||||
s->ldi = 0;
|
||||
s->cdi = inds[pi.ind];
|
||||
} else {
|
||||
s->pi.raw = 0;
|
||||
s->ldi = 0;
|
||||
s->cdi = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void HELPER(aau_load_program)(CPUE2KState *env)
|
||||
{
|
||||
unsigned int i;
|
||||
E2KCtpr ctpr = env->ctprs[1];
|
||||
|
||||
if (ctpr.tag != CTPR_TAG_DISP || ctpr.opc != CTPR_OPC_LDISP) {
|
||||
helper_raise_exception(env, EXCP_ILLEGAL_OPCODE);
|
||||
}
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
E2KAauPrefInstr l, r;
|
||||
size_t offset = i * 16;
|
||||
|
||||
l.raw = cpu_ldq_le_data(env, ctpr.base + offset);
|
||||
r.raw = cpu_ldq_le_data(env, ctpr.base + offset + 8);
|
||||
|
||||
init_prefetch_area(&env->aau.pl.area[i], l, env->aau.inds);
|
||||
init_prefetch_area(&env->aau.pr.area[i], r, env->aau.inds);
|
||||
|
||||
if (l.ct || r.ct) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
target_ulong HELPER(mova_ptr)(CPUE2KState *env, int chan, int area, int ind,
|
||||
int size, int mmu_idx)
|
||||
{
|
||||
E2KAauPrefState *ps = chan < 2 ? &env->aau.pl : &env->aau.pr;
|
||||
E2KAauAreaState *as = &ps->area[area];
|
||||
E2KAauPrefInstr instr = as->pi;
|
||||
E2KAad aad = env->aau.ds[instr.aad];
|
||||
target_ulong addr = aad.base + as->cdi + instr.disp + ind;
|
||||
target_ulong page = addr & TARGET_PAGE_MASK;
|
||||
|
||||
if (addr & (size - 1)) {
|
||||
return 0;
|
||||
} else if (page != as->last_page) {
|
||||
void *ignore;
|
||||
int flags;
|
||||
|
||||
flags = probe_access_flags(env, page, MMU_DATA_LOAD, mmu_idx,
|
||||
true, &ignore, 0);
|
||||
as->last_page = page;
|
||||
as->last_page_valid = !(flags & TLB_INVALID_MASK);
|
||||
}
|
||||
|
||||
return as->last_page_valid ? addr : 0;
|
||||
}
|
||||
|
||||
void HELPER(aau_am)(CPUE2KState *env, int chan, int area)
|
||||
{
|
||||
E2KAauPrefState *ps = chan < 2 ? &env->aau.pl : &env->aau.pr;
|
||||
E2KAauAreaState *as = &ps->area[area];
|
||||
E2KAauPrefInstr instr = as->pi;
|
||||
uint32_t incr = env->aau.incrs[instr.incr];
|
||||
int size;
|
||||
|
||||
if (instr.fmt == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
size = 1 << (instr.fmt - 1);
|
||||
as->cdi += size * incr;
|
||||
}
|
|
@ -0,0 +1,608 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "cpu.h"
|
||||
#include "helper-tcg.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "exec/helper-proto.h"
|
||||
|
||||
static FloatRoundMode rm[] = {
|
||||
float_round_nearest_even,
|
||||
float_round_down,
|
||||
float_round_up,
|
||||
float_round_to_zero,
|
||||
};
|
||||
|
||||
static inline int fpu_flags(int flags)
|
||||
{
|
||||
return (flags & float_flag_invalid ? FP_IE : 0) |
|
||||
(flags & float_flag_divbyzero ? FP_ZE : 0) |
|
||||
(flags & float_flag_overflow ? FP_OE : 0) |
|
||||
(flags & float_flag_underflow ? FP_UE : 0) |
|
||||
(flags & float_flag_inexact ? FP_PE : 0) |
|
||||
(flags & float_flag_input_denormal ? FP_DE : 0);
|
||||
}
|
||||
|
||||
static inline void fx_merge_exception_flags(CPUE2KState *env, int old_flags)
|
||||
{
|
||||
int new_flags = get_float_exception_flags(&env->fx_status);
|
||||
float_raise(old_flags, &env->fx_status);
|
||||
env->fpsr.ef |= fpu_flags(new_flags);
|
||||
if (env->fpsr.ef & (~env->fpcr.em & FP_EM)) {
|
||||
env->fpsr.es = 1;
|
||||
env->fpsr.b = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void fp_merge_exception_flags(CPUE2KState *env, int old_flags)
|
||||
{
|
||||
int new_flags = get_float_exception_flags(&env->fp_status);
|
||||
float_raise(old_flags, &env->fp_status);
|
||||
env->pfpfr.ef |= fpu_flags(new_flags);
|
||||
}
|
||||
|
||||
static inline int save_exception_flags(float_status *s)
|
||||
{
|
||||
int old_flags = get_float_exception_flags(s);
|
||||
set_float_exception_flags(0, s);
|
||||
return old_flags;
|
||||
}
|
||||
|
||||
#define fx_save_exception_flags(e) save_exception_flags(&(e)->fx_status)
|
||||
#define fp_save_exception_flags(e) save_exception_flags(&(e)->fp_status)
|
||||
|
||||
void e2k_update_fx_status(CPUE2KState *env)
|
||||
{
|
||||
int x;
|
||||
|
||||
set_float_rounding_mode(rm[env->fpcr.rc], &env->fx_status);
|
||||
|
||||
switch(env->fpcr.pc) {
|
||||
case FPCR_PC_XP: x = floatx80_precision_x; break;
|
||||
case FPCR_PC_DP: x = floatx80_precision_d; break;
|
||||
case FPCR_PC_SP: x = floatx80_precision_s; break;
|
||||
case FPCR_PC_RESERVED:
|
||||
default:
|
||||
qemu_log_mask(LOG_UNIMP, "unknown precision mode 0x%x\n", env->fpcr.pc);
|
||||
abort();
|
||||
}
|
||||
|
||||
set_floatx80_rounding_precision(x, &env->fx_status);
|
||||
}
|
||||
|
||||
void e2k_update_fp_status(CPUE2KState *env)
|
||||
{
|
||||
set_float_rounding_mode(rm[env->pfpfr.rc], &env->fp_status);
|
||||
}
|
||||
|
||||
#define TOIF_RC_CURRENT 0x4
|
||||
#define TOIF_RC_IGNORE_INEXACT 0x8
|
||||
|
||||
static inline void toif_set_round_mode(uint32_t flags, float_status *s)
|
||||
{
|
||||
if ((flags & TOIF_RC_CURRENT) == 0) {
|
||||
set_float_rounding_mode(rm[flags & FP_RC_CHOP], s);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void toif_clear_inexact(uint32_t flags, float_status *s)
|
||||
{
|
||||
if(flags & TOIF_RC_IGNORE_INEXACT) {
|
||||
int new_flags = get_float_exception_flags(s);
|
||||
new_flags = new_flags & (~float_flag_inexact);
|
||||
set_float_exception_flags(new_flags, s);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TARGET_E2K_PRECISE_FSQRTID
|
||||
uint64 HELPER(fsqrtid)(CPUE2KState *env, uint64_t x)
|
||||
{
|
||||
#error implement
|
||||
return x;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define IMPL_FSCALE(name, ty, exp_len, exp_off, mul, cvt) \
|
||||
ty HELPER(name)(CPUE2KState *env, ty src1, uint32_t src2) \
|
||||
{ \
|
||||
int32_t p = (int32_t) src2; \
|
||||
ty max = (1 << exp_len) - 1; \
|
||||
int32_t bias = max >> 1; \
|
||||
ty exp; \
|
||||
ty m = 0; \
|
||||
if (p <= -bias) { \
|
||||
exp = 0; \
|
||||
p += bias + exp_off - 1; \
|
||||
if (p >= 0 && p < exp_off) { \
|
||||
m = 1ULL << p; \
|
||||
} else { \
|
||||
m = p == -1; \
|
||||
} \
|
||||
} else if (p > bias) { \
|
||||
exp = max; \
|
||||
} else { \
|
||||
exp = bias + p; \
|
||||
} \
|
||||
ty s2 = (exp << exp_off) | m; \
|
||||
return mul(env, src1, s2); \
|
||||
}
|
||||
|
||||
IMPL_FSCALE(fscaled, uint64_t, 11, 52, helper_fmuld, uint64_to_float64)
|
||||
IMPL_FSCALE(fscales, uint32_t, 8, 23, helper_fmuls, uint32_to_float32)
|
||||
|
||||
void HELPER(fxscalesx)(floatx80 *r, CPUE2KState *env, floatx80 *a, uint32_t b)
|
||||
{
|
||||
floatx80 v;
|
||||
int32_t p = (int32_t) b;
|
||||
uint16_t max = (1 << 15) - 1;
|
||||
int16_t bias = max >> 1;
|
||||
if (p <= -bias) {
|
||||
v.high = 0;
|
||||
p += bias + 62;
|
||||
if (p >= 0 && p < 63) {
|
||||
v.low = 1ULL << p;
|
||||
} else {
|
||||
v.low = p == -1;
|
||||
}
|
||||
} else if (p > bias) {
|
||||
v.low = 1UL << 63;
|
||||
v.high = max;
|
||||
} else {
|
||||
v.low = 1UL << 63;
|
||||
v.high = bias + p;
|
||||
}
|
||||
helper_fxmulxx(r, env, a, &v);
|
||||
}
|
||||
|
||||
#define type_name_i32 int32
|
||||
#define type_name_i64 int64
|
||||
#define type_name_f32 float32
|
||||
#define type_name_f64 float64
|
||||
#define type_name_f80 floatx80
|
||||
#define type_name(S) glue(type_name_, S)
|
||||
|
||||
#define arg_type_i32 uint32_t
|
||||
#define arg_type_i64 uint64_t
|
||||
#define arg_type_f32 uint32_t
|
||||
#define arg_type_f64 uint64_t
|
||||
#define arg_type_f80 floatx80 *
|
||||
#define arg_type(S) glue(arg_type_, S)
|
||||
|
||||
#define ret_arg_i32
|
||||
#define ret_arg_i64
|
||||
#define ret_arg_f32
|
||||
#define ret_arg_f64
|
||||
#define ret_arg_f80 floatx80 *ret,
|
||||
#define ret_arg(S) glue(ret_arg_, S)
|
||||
|
||||
#define ret_type_i32 uint32_t
|
||||
#define ret_type_i64 uint64_t
|
||||
#define ret_type_f32 uint32_t
|
||||
#define ret_type_f64 uint64_t
|
||||
#define ret_type_f80 void
|
||||
#define ret_type(S) glue(ret_type_, S)
|
||||
|
||||
#define make_i32(v) (v)
|
||||
#define make_i64(v) (v)
|
||||
#define make_f32(v) make_float32(v)
|
||||
#define make_f64(v) make_float64(v)
|
||||
#define make_f80(v) (*(v))
|
||||
#define make(S, v) glue(make_, S)(v)
|
||||
|
||||
#define float_val_f32(v) float32_val(v)
|
||||
#define float_val_f64(v) float64_val(v)
|
||||
#define float_val(S, v) glue(float_val_, S)(v)
|
||||
|
||||
#define type_i32 uint32_t
|
||||
#define type_i64 uint64_t
|
||||
#define type_f32 float32
|
||||
#define type_f64 float64
|
||||
#define type_f80 floatx80
|
||||
#define type(S) glue(type_, S)
|
||||
|
||||
#define int32_to_int32(v, s) (v)
|
||||
#define int64_to_int64(v, s) (v)
|
||||
#define float32_to_float32(v, s) (v)
|
||||
#define float64_to_float64(v, s) (v)
|
||||
#define floatx80_to_floatx80(v, s) (v)
|
||||
#define convert(F, T, v, s) glue3(type_name(F), _to_, type_name(T))(v, s)
|
||||
|
||||
#define ret_i32(v) return (v)
|
||||
#define ret_i64(v) return (v)
|
||||
#define ret_f32(v) return float32_val(v)
|
||||
#define ret_f64(v) return float64_val(v)
|
||||
#define ret_f80(v) *ret = v
|
||||
#define ret(S, v) glue(ret_, S)(v)
|
||||
|
||||
#define fpu_mov(x, s) (x)
|
||||
#define ident(x) (x)
|
||||
#define not(x) (!(x))
|
||||
|
||||
#define IMPL_ALOPF2_FPU_BASIC(FPU, name, S2, R, T2, TR, op) \
|
||||
ret_type(R) HELPER(name)(ret_arg(R) CPUE2KState *env, arg_type(S2) s2) \
|
||||
{ \
|
||||
int old_flags = glue(FPU, _save_exception_flags)(env); \
|
||||
float_status *s = &env->glue(FPU, _status); \
|
||||
type(T2) t2 = convert(S2, T2, make(S2, s2), s); \
|
||||
type(TR) tr = op(t2, s); \
|
||||
type(R) r = convert(TR, R, tr, s); \
|
||||
glue(FPU, _merge_exception_flags)(env, old_flags); \
|
||||
ret(R, r); \
|
||||
}
|
||||
|
||||
#define IMPL_ALOPF2_FPU(FPU, name, S2, R, op) \
|
||||
IMPL_ALOPF2_FPU_BASIC(FPU, name, S2, R, S2, R, op)
|
||||
|
||||
#define IMPL_ALOPF2_FP(name, S2, R, op) \
|
||||
IMPL_ALOPF2_FPU_BASIC(fp, name, R, S2, R, S2, op)
|
||||
|
||||
#define IMPL_ALOPF2_FPU_CVT_OP(FPU, name, S2, R, op) \
|
||||
ret_type(R) HELPER(name)(ret_arg(R) CPUE2KState *env, arg_type(S2) s2) \
|
||||
{ \
|
||||
int old_flags = glue(FPU, _save_exception_flags)(env); \
|
||||
float_status *s = &env->glue(FPU, _status); \
|
||||
type(R) r = op(make(S2, s2), s); \
|
||||
glue(FPU, _merge_exception_flags)(env, old_flags); \
|
||||
ret(R, r); \
|
||||
}
|
||||
|
||||
#define IMPL_ALOPF2_FPU_CVT(FPU, name, S2, R) \
|
||||
ret_type(R) HELPER(name)(ret_arg(R) CPUE2KState *env, arg_type(S2) s2) \
|
||||
{ \
|
||||
int old_flags = glue(FPU, _save_exception_flags)(env); \
|
||||
float_status *s = &env->glue(FPU, _status); \
|
||||
type(R) r = convert(S2, R, make(S2, s2), s); \
|
||||
glue(FPU, _merge_exception_flags)(env, old_flags); \
|
||||
ret(R, r); \
|
||||
}
|
||||
|
||||
#define IMPL_ALOPF1_FPU(FPU, name, S1, S2, R, T1, T2, TR, op) \
|
||||
ret_type(R) HELPER(name)(ret_arg(R) CPUE2KState *env, \
|
||||
arg_type(S1) s1, arg_type(S2) s2) \
|
||||
{ \
|
||||
int old_flags = glue(FPU, _save_exception_flags)(env); \
|
||||
float_status *s = &env->glue(FPU, _status); \
|
||||
type(T1) t1 = convert(S1, T1, make(S1, s1), s); \
|
||||
type(T2) t2 = convert(S2, T2, make(S2, s2), s); \
|
||||
type(TR) tr = op(t1, t2, s); \
|
||||
type(R) r = convert(TR, R, tr, s); \
|
||||
glue(FPU, _merge_exception_flags)(env, old_flags); \
|
||||
ret(R, r); \
|
||||
}
|
||||
|
||||
#define IMPL_ALOPF1_FX(name, S1, S2, R, op) \
|
||||
IMPL_ALOPF1_FPU(fx, name, S1, S2, R, f80, f80, f80, op)
|
||||
|
||||
#define IMPL_ALOPF1_FP(name, S1, S2, R, op) \
|
||||
IMPL_ALOPF1_FPU(fp, name, S1, S2, R, S1, S2, R, op)
|
||||
|
||||
#define IMPL_ALOPF1_FPU_CMP_BASIC(FPU, name, S1, S2, R, T1, T2, TR, op1, op2) \
|
||||
ret_type(R) HELPER(name)(ret_arg(R) CPUE2KState *env, \
|
||||
arg_type(S1) s1, arg_type(S2) s2) \
|
||||
{ \
|
||||
int old_flags = glue(FPU, _save_exception_flags)(env); \
|
||||
float_status *s = &env->glue(FPU, _status); \
|
||||
type(T1) t1 = convert(S1, T1, make(S1, s1), s); \
|
||||
type(T2) t2 = convert(S2, T2, make(S2, s2), s); \
|
||||
type(TR) tr = op2(op1(t1, t2, s)) ? -1 : 0; \
|
||||
type(R) r = convert(TR, R, tr, s); \
|
||||
glue(FPU, _merge_exception_flags)(env, old_flags); \
|
||||
ret(R, r); \
|
||||
}
|
||||
|
||||
#define IMPL_ALOPF1_FPU_CMP(FPU, name, S1, S2, R, T, op1, op2) \
|
||||
IMPL_ALOPF1_FPU_CMP_BASIC(FPU, name, S1, S2, R, T, T, R, op1, op2)
|
||||
|
||||
#define IMPL_ALOPF1_FP_S(name, S1, S2, R, op) \
|
||||
ret_type(R) HELPER(name)(CPUE2KState *env, arg_type(S1) s1, \
|
||||
arg_type(S2) s2) \
|
||||
{ \
|
||||
int old_flags = fp_save_exception_flags(env); \
|
||||
type(R) r = op(R, make(S1, s1), make(S2, s2), &env->fp_status); \
|
||||
fp_merge_exception_flags(env, old_flags); \
|
||||
return float_val(R, r); \
|
||||
}
|
||||
|
||||
#define IMPL_ALOPF21_FPU(FPU, name, S1, S2, S3, R, T1, T2, T3, TR, op) \
|
||||
ret_type(R) HELPER(name)(ret_arg(R) CPUE2KState *env, \
|
||||
arg_type(S1) s1, arg_type(S2) s2, arg_type(S3) s3) \
|
||||
{ \
|
||||
int old_flags = glue(FPU, _save_exception_flags)(env); \
|
||||
float_status *s = &env->glue(FPU, _status); \
|
||||
type(T1) t1 = convert(S1, T1, make(S1, s1), s); \
|
||||
type(T2) t2 = convert(S2, T2, make(S2, s2), s); \
|
||||
type(T3) t3 = convert(S3, T3, make(S3, s3), s); \
|
||||
type(TR) tr = op(t1, t2, t3, s); \
|
||||
type(R) r = convert(TR, R, tr, s); \
|
||||
glue(FPU, _merge_exception_flags)(env, old_flags); \
|
||||
ret(R, r); \
|
||||
}
|
||||
|
||||
#define IMPL_ALOPF21_FP(name, T, op) \
|
||||
IMPL_ALOPF21_FPU(fp, name, T, T, T, T, T, T, T, T, op)
|
||||
|
||||
#define IMPL_ALOPF1_FX_MANY(name, op) \
|
||||
IMPL_ALOPF1_FX(glue3(fx, name, ss), f80, f32, f32, op) \
|
||||
IMPL_ALOPF1_FX(glue3(fx, name, dd), f80, f64, f64, op) \
|
||||
IMPL_ALOPF1_FX(glue3(fx, name, sx), f80, f32, f80, op) \
|
||||
IMPL_ALOPF1_FX(glue3(fx, name, dx), f80, f64, f80, op) \
|
||||
IMPL_ALOPF1_FX(glue3(fx, name, xx), f80, f80, f80, op) \
|
||||
IMPL_ALOPF1_FX(glue3(fx, name, xd), f80, f80, f64, op) \
|
||||
IMPL_ALOPF1_FX(glue3(fx, name, xs), f80, f80, f32, op)
|
||||
|
||||
IMPL_ALOPF1_FX_MANY(add, floatx80_add)
|
||||
IMPL_ALOPF1_FX_MANY(sub, floatx80_sub)
|
||||
IMPL_ALOPF1_FX_MANY(mul, floatx80_mul)
|
||||
IMPL_ALOPF1_FX_MANY(div, floatx80_div)
|
||||
|
||||
#define floatx80_rsub(x, y, s) floatx80_sub(y, x, s)
|
||||
|
||||
IMPL_ALOPF1_FX(fxrsubss, f80, f32, f32, floatx80_rsub)
|
||||
IMPL_ALOPF1_FX(fxrsubdd, f80, f64, f64, floatx80_rsub)
|
||||
IMPL_ALOPF1_FX(fxrsubsx, f80, f32, f80, floatx80_rsub)
|
||||
IMPL_ALOPF1_FX(fxrsubdx, f80, f64, f80, floatx80_rsub)
|
||||
|
||||
IMPL_ALOPF1_FX(fxdivtss, f32, f80, f32, floatx80_div)
|
||||
IMPL_ALOPF1_FX(fxdivtdd, f64, f80, f64, floatx80_div)
|
||||
IMPL_ALOPF1_FX(fxdivtsx, f32, f80, f80, floatx80_div)
|
||||
IMPL_ALOPF1_FX(fxdivtdx, f64, f80, f80, floatx80_div)
|
||||
|
||||
static floatx80 fxsqrtt(floatx80 a, floatx80 b, float_status *s)
|
||||
{
|
||||
// TODO: fxsqrtt
|
||||
return floatx80_sqrt(a, s);
|
||||
}
|
||||
|
||||
IMPL_ALOPF1_FX(fxsqrttsx, f32, f80, f80, fxsqrtt)
|
||||
IMPL_ALOPF1_FX(fxsqrttdx, f64, f80, f80, fxsqrtt)
|
||||
IMPL_ALOPF1_FX(fxsqrttxx, f80, f80, f80, fxsqrtt)
|
||||
|
||||
#define CMPODF_BASIC(p, x, y, s) ({ \
|
||||
uint32_t ret = 0x45; \
|
||||
if (!glue(p, _is_any_nan)(x) && !glue(p, _is_any_nan)(y)) { \
|
||||
FloatRelation relation = glue(p, _compare_quiet)(x, y, s); \
|
||||
switch (relation) { \
|
||||
case float_relation_greater: ret = 0x00; break; \
|
||||
case float_relation_less: ret = 0x01; break; \
|
||||
case float_relation_equal: ret = 0x40; break; \
|
||||
case float_relation_unordered: ret = 0x45; break; \
|
||||
} \
|
||||
} \
|
||||
ret;\
|
||||
})
|
||||
|
||||
#define FXCMPODF(x, y, s) CMPODF_BASIC(floatx80, x, y, s)
|
||||
#define FCMPODDF(x, y, s) CMPODF_BASIC(float64, x, y, s)
|
||||
#define FCMPODSF(x, y, s) CMPODF_BASIC(float32, x, y, s)
|
||||
// TODO: cmpudf
|
||||
#define FXCMPUDF FXCMPODF
|
||||
#define FCMPUDSF FCMPODSF
|
||||
#define FCMPUDDF FCMPODDF
|
||||
|
||||
#define IMPL_CMPF_FX(name, S1, S2, op) \
|
||||
IMPL_ALOPF1_FPU(fx, name, S1, S2, i32, f80, f80, i32, op)
|
||||
|
||||
IMPL_CMPF_FX(fxcmpodsf, f80, f32, FXCMPODF)
|
||||
IMPL_CMPF_FX(fxcmpoddf, f80, f64, FXCMPODF)
|
||||
IMPL_CMPF_FX(fxcmpodxf, f80, f80, FXCMPODF)
|
||||
|
||||
IMPL_CMPF_FX(fxcmpudsf, f80, f32, FXCMPUDF)
|
||||
IMPL_CMPF_FX(fxcmpuddf, f80, f64, FXCMPUDF)
|
||||
IMPL_CMPF_FX(fxcmpudxf, f80, f80, FXCMPUDF)
|
||||
|
||||
#define IMPL_CMPF_FP(name, T, R, op) \
|
||||
IMPL_ALOPF1_FPU(fp, name, T, T, R, T, T, R, op)
|
||||
|
||||
IMPL_CMPF_FP(fcmpodsf, f32, i32, FCMPODSF)
|
||||
IMPL_CMPF_FP(fcmpoddf, f64, i32, FCMPODDF)
|
||||
|
||||
IMPL_CMPF_FP(fcmpudsf, f32, i32, FCMPUDSF)
|
||||
IMPL_CMPF_FP(fcmpuddf, f64, i32, FCMPUDDF)
|
||||
|
||||
#define cmp_op(T, op) glue3(type_name(T), _, op)
|
||||
|
||||
#define IMPL_ALOPF1_FPU_CMP_ALL(F, P, S, T, R, A, B) \
|
||||
IMPL_ALOPF1_FPU_CMP(F, glue3(P, cmpeq, S), A, B, R, T, cmp_op(T, eq), ident) \
|
||||
IMPL_ALOPF1_FPU_CMP(F, glue3(P, cmpneq, S), A, B, R, T, cmp_op(T, eq), not) \
|
||||
IMPL_ALOPF1_FPU_CMP(F, glue3(P, cmple, S), A, B, R, T, cmp_op(T, le), ident) \
|
||||
IMPL_ALOPF1_FPU_CMP(F, glue3(P, cmpnle, S), A, B, R, T, cmp_op(T, le), not) \
|
||||
IMPL_ALOPF1_FPU_CMP(F, glue3(P, cmplt, S), A, B, R, T, cmp_op(T, lt), ident) \
|
||||
IMPL_ALOPF1_FPU_CMP(F, glue3(P, cmpnlt, S), A, B, R, T, cmp_op(T, lt), not) \
|
||||
IMPL_ALOPF1_FPU_CMP(F, glue3(P, cmpuod, S), A, B, R, T, cmp_op(T, unordered), ident) \
|
||||
IMPL_ALOPF1_FPU_CMP(F, glue3(P, cmpod, S), A, B, R, T, cmp_op(T, unordered), not)
|
||||
|
||||
IMPL_ALOPF1_FPU_CMP_ALL(fp, f, s, f32, i32, f32, f32)
|
||||
IMPL_ALOPF1_FPU_CMP_ALL(fp, f, d, f64, i64, f64, f64)
|
||||
IMPL_ALOPF1_FPU_CMP_ALL(fx, fx, s, f80, i64, f80, f32)
|
||||
IMPL_ALOPF1_FPU_CMP_ALL(fx, fx, d, f80, i64, f80, f64)
|
||||
IMPL_ALOPF1_FPU_CMP_ALL(fx, fx, x, f80, i64, f80, f80)
|
||||
|
||||
IMPL_ALOPF2_FPU_CVT(fp, fstofd, f32, f64)
|
||||
IMPL_ALOPF2_FPU_CVT(fx, fstofx, f32, f80)
|
||||
IMPL_ALOPF2_FPU_CVT(fp, fdtofs, f64, f32)
|
||||
IMPL_ALOPF2_FPU_CVT(fx, fdtofx, f64, f80)
|
||||
IMPL_ALOPF2_FPU_CVT(fx, fxtofs, f80, f32)
|
||||
IMPL_ALOPF2_FPU_CVT(fx, fxtofd, f80, f64)
|
||||
|
||||
IMPL_ALOPF2_FPU_CVT(fp, istofs, i32, f32)
|
||||
IMPL_ALOPF2_FPU_CVT(fp, istofd, i32, f64)
|
||||
IMPL_ALOPF2_FPU_CVT(fx, istofx, i32, f80)
|
||||
|
||||
IMPL_ALOPF2_FPU_CVT(fp, idtofs, i64, f32)
|
||||
IMPL_ALOPF2_FPU_CVT(fp, idtofd, i64, f64)
|
||||
IMPL_ALOPF2_FPU_CVT(fx, idtofx, i64, f80)
|
||||
|
||||
/*
|
||||
* I assume e2k behaves like x86.
|
||||
*
|
||||
* e2k/x86 mandates that we return the indefinite integer value for the result
|
||||
* of any float-to-integer conversion that raises the 'invalid' exception.
|
||||
* Wrap the softfloat functions to get this behaviour.
|
||||
*/
|
||||
#define WRAP_F2I(RET, func, T, defval) \
|
||||
static RET glue(e2k_, func)(T x, float_status *s) \
|
||||
{ \
|
||||
int oldflags, newflags; \
|
||||
RET r; \
|
||||
\
|
||||
oldflags = get_float_exception_flags(s); \
|
||||
set_float_exception_flags(0, s); \
|
||||
r = func(x, s); \
|
||||
newflags = get_float_exception_flags(s); \
|
||||
if (newflags & float_flag_invalid) { \
|
||||
r = defval; \
|
||||
} \
|
||||
set_float_exception_flags(newflags | oldflags, s); \
|
||||
return r; \
|
||||
}
|
||||
|
||||
WRAP_F2I(int32_t, float32_to_int32, float32, INT32_MIN)
|
||||
WRAP_F2I(int32_t, float32_to_int32_round_to_zero, float32, INT32_MIN)
|
||||
WRAP_F2I(int64_t, float32_to_int64, float32, INT64_MIN)
|
||||
WRAP_F2I(int64_t, float32_to_int64_round_to_zero, float32, INT64_MIN)
|
||||
WRAP_F2I(int32_t, float64_to_int32, float64, INT32_MIN)
|
||||
WRAP_F2I(int32_t, float64_to_int32_round_to_zero, float64, INT32_MIN)
|
||||
WRAP_F2I(int64_t, float64_to_int64, float64, INT64_MIN)
|
||||
WRAP_F2I(int64_t, float64_to_int64_round_to_zero, float64, INT64_MIN)
|
||||
WRAP_F2I(int32_t, floatx80_to_int32, floatx80, INT32_MIN)
|
||||
WRAP_F2I(int32_t, floatx80_to_int32_round_to_zero, floatx80, INT32_MIN)
|
||||
WRAP_F2I(int64_t, floatx80_to_int64, floatx80, INT64_MIN)
|
||||
WRAP_F2I(int64_t, floatx80_to_int64_round_to_zero, floatx80, INT64_MIN)
|
||||
|
||||
IMPL_ALOPF2_FPU_CVT_OP(fp, fstois, f32, i32, e2k_float32_to_int32)
|
||||
IMPL_ALOPF2_FPU_CVT_OP(fp, fdtois, f64, i32, e2k_float64_to_int32)
|
||||
IMPL_ALOPF2_FPU_CVT_OP(fx, fxtois, f80, i32, e2k_floatx80_to_int32)
|
||||
IMPL_ALOPF2_FPU_CVT_OP(fp, fstoid, f32, i64, e2k_float32_to_int64)
|
||||
IMPL_ALOPF2_FPU_CVT_OP(fp, fdtoid, f64, i64, e2k_float64_to_int64)
|
||||
IMPL_ALOPF2_FPU_CVT_OP(fx, fxtoid, f80, i64, e2k_floatx80_to_int64)
|
||||
|
||||
IMPL_ALOPF2_FPU_CVT_OP(fp, fstoistr, f32, i32, e2k_float32_to_int32_round_to_zero)
|
||||
IMPL_ALOPF2_FPU_CVT_OP(fp, fstoidtr, f32, i64, e2k_float32_to_int64_round_to_zero)
|
||||
IMPL_ALOPF2_FPU_CVT_OP(fp, fdtoistr, f64, i32, e2k_float64_to_int32_round_to_zero)
|
||||
IMPL_ALOPF2_FPU_CVT_OP(fp, fdtoidtr, f64, i64, e2k_float64_to_int64_round_to_zero)
|
||||
IMPL_ALOPF2_FPU_CVT_OP(fx, fxtoistr, f80, i32, e2k_floatx80_to_int32_round_to_zero)
|
||||
IMPL_ALOPF2_FPU_CVT_OP(fx, fxtoidtr, f80, i64, e2k_floatx80_to_int64_round_to_zero)
|
||||
|
||||
#define IMPL_FTOIF(name, A, B) \
|
||||
static type(B) name(type(A) flags, type(B) f, float_status *s) \
|
||||
{ \
|
||||
FloatRoundMode oldrm = get_float_rounding_mode(s); \
|
||||
type(B) ret; \
|
||||
\
|
||||
toif_set_round_mode(flags, s); \
|
||||
ret = glue(type_name(B), _round_to_int)(f, s); \
|
||||
set_float_rounding_mode(oldrm, s); \
|
||||
toif_clear_inexact(flags, s); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
IMPL_FTOIF(fstoifs, i32, f32)
|
||||
IMPL_FTOIF(fdtoifd, i64, f64)
|
||||
|
||||
IMPL_ALOPF1_FP(fstoifs, i32, f32, f32, fstoifs)
|
||||
IMPL_ALOPF1_FP(fdtoifd, i64, f64, f64, fdtoifd)
|
||||
|
||||
/* TODO: frcps: test if valid, test exception flags */
|
||||
#define frcps(a, s) float32_div(float32_one, a, s)
|
||||
#define frsqrts(a, s) float32_div(float32_one, float32_sqrt(a, s), s)
|
||||
|
||||
static float64 fsqrttd(float64 a, float64 b, float_status *s)
|
||||
{
|
||||
// TODO: fxsqrtt
|
||||
return float64_sqrt(a, s);
|
||||
}
|
||||
|
||||
/*
|
||||
* I assume e2k behaves like x86.
|
||||
*
|
||||
* Note that the choice of comparison op here is important to get the
|
||||
* special cases right: for min and max Intel specifies that (-0,0),
|
||||
* (NaN, anything) and (anything, NaN) return the second argument.
|
||||
*/
|
||||
#define FPU_MIN(T, a, b, s) \
|
||||
(glue(type_name(T), _lt)(a, b, s) ? (a) : (b))
|
||||
#define FPU_MAX(T, a, b, s) \
|
||||
(glue(type_name(T), _lt)(b, a, s) ? (a) : (b))
|
||||
|
||||
#define IMPL_ALOPF1_FP_MANY(S, T) \
|
||||
IMPL_ALOPF1_FP(glue(fadd, S), T, T, T, glue(type_name(T), _add)) \
|
||||
IMPL_ALOPF1_FP(glue(fsub, S), T, T, T, glue(type_name(T), _sub)) \
|
||||
IMPL_ALOPF1_FP(glue(fmul, S), T, T, T, glue(type_name(T), _mul)) \
|
||||
IMPL_ALOPF1_FP(glue(fdiv, S), T, T, T, glue(type_name(T), _div)) \
|
||||
IMPL_ALOPF1_FP_S(glue(fmin, S), T, T, T, FPU_MIN) \
|
||||
IMPL_ALOPF1_FP_S(glue(fmax, S), T, T, T, FPU_MAX)
|
||||
|
||||
IMPL_ALOPF1_FP_MANY(s, f32)
|
||||
IMPL_ALOPF1_FP_MANY(d, f64)
|
||||
|
||||
IMPL_ALOPF2_FP(fsqrts, f32, f32, float32_sqrt)
|
||||
IMPL_ALOPF2_FP(frcps, f32, f32, frcps)
|
||||
IMPL_ALOPF2_FP(frsqrts, f32, f32, frsqrts)
|
||||
IMPL_ALOPF1_FP(fsqrttd, f64, f64, f64, fsqrttd)
|
||||
|
||||
#define FMA(T, x, y, z, f, s) \
|
||||
glue(type_name(T), _muladd)(x, y, z, f, s)
|
||||
|
||||
#define FMAS(x, y, z, s) FMA(f32, x, y, z, 0, s)
|
||||
#define FMAD(x, y, z, s) FMA(f64, x, y, z, 0, s)
|
||||
#define FMSS(x, y, z, s) FMA(f32, x, y, z, float_muladd_negate_c, s)
|
||||
#define FMSD(x, y, z, s) FMA(f64, x, y, z, float_muladd_negate_c, s)
|
||||
#define FNMAS(x, y, z, s) FMA(f32, x, y, z, float_muladd_negate_product, s)
|
||||
#define FNMAD(x, y, z, s) FMA(f64, x, y, z, float_muladd_negate_product, s)
|
||||
#define FNMSS(x, y, z, s) FMA(f32, x, y, z, float_muladd_negate_product | float_muladd_negate_c, s)
|
||||
#define FNMSD(x, y, z, s) FMA(f64, x, y, z, float_muladd_negate_product | float_muladd_negate_c, s)
|
||||
|
||||
IMPL_ALOPF21_FP(fmas, f32, FMAS)
|
||||
IMPL_ALOPF21_FP(fmss, f32, FMSS)
|
||||
IMPL_ALOPF21_FP(fnmas, f32, FNMAS)
|
||||
IMPL_ALOPF21_FP(fnmss, f32, FNMSS)
|
||||
IMPL_ALOPF21_FP(fmad, f64, FMAD)
|
||||
IMPL_ALOPF21_FP(fmsd, f64, FMSD)
|
||||
IMPL_ALOPF21_FP(fnmad, f64, FNMAD)
|
||||
IMPL_ALOPF21_FP(fnmsd, f64, FNMSD)
|
||||
|
||||
#define qp_len_uw 4
|
||||
#define qp_len_ud 2
|
||||
#define qp_len(T) glue(qp_len_, T)
|
||||
|
||||
#define IMPL_OP3_QP_ENV(name, T, F, code) \
|
||||
void HELPER(name)(E2KReg *r, CPUE2KState *env, E2KReg *s1, \
|
||||
E2KReg *s2, E2KReg *s3) \
|
||||
{ \
|
||||
int old_flags = fp_save_exception_flags(env); \
|
||||
int i; \
|
||||
\
|
||||
for (i = 0; i < qp_len(T); i++) { \
|
||||
type(F) a = make(F, s1->T[i]); \
|
||||
type(F) b = make(F, s2->T[i]); \
|
||||
type(F) c = make(F, s3->T[i]); \
|
||||
{ code; } \
|
||||
} \
|
||||
\
|
||||
fp_merge_exception_flags(env, old_flags); \
|
||||
}
|
||||
|
||||
#define IMPL_OP3_QP_ENV_OP(name, T, F, op) \
|
||||
IMPL_OP3_QP_ENV(name, T, F, { \
|
||||
r->T[i] = float_val(F, op(a, b, c, &env->fp_status)); \
|
||||
})
|
||||
|
||||
IMPL_OP3_QP_ENV_OP(qpfmas, uw, f32, FMAS)
|
||||
IMPL_OP3_QP_ENV_OP(qpfmss, uw, f32, FMSS)
|
||||
IMPL_OP3_QP_ENV_OP(qpfnmas, uw, f32, FNMAS)
|
||||
IMPL_OP3_QP_ENV_OP(qpfnmss, uw, f32, FNMSS)
|
||||
IMPL_OP3_QP_ENV_OP(qpfmad, ud, f64, FMAD)
|
||||
IMPL_OP3_QP_ENV_OP(qpfmsd, ud, f64, FMSD)
|
||||
IMPL_OP3_QP_ENV_OP(qpfnmad, ud, f64, FNMAD)
|
||||
IMPL_OP3_QP_ENV_OP(qpfnmsd, ud, f64, FNMSD)
|
||||
|
||||
#define IMPL_OP3_QP_ENV_OP_ALT(name, T, F, op1, op2) \
|
||||
IMPL_OP3_QP_ENV(name, T, F, { \
|
||||
r->T[i] = float_val(F, i & 1 ? op2(a, b, c, &env->fp_status) : \
|
||||
op1(a, b, c, &env->fp_status)); \
|
||||
})
|
||||
|
||||
IMPL_OP3_QP_ENV_OP_ALT(qpfmass, uw, f32, FMAS, FMSS)
|
||||
IMPL_OP3_QP_ENV_OP_ALT(qpfmsas, uw, f32, FMSS, FMAS)
|
||||
IMPL_OP3_QP_ENV_OP_ALT(qpfmasd, ud, f64, FMAD, FMSD)
|
||||
IMPL_OP3_QP_ENV_OP_ALT(qpfmsad, ud, f64, FMSD, FMAD)
|
|
@ -0,0 +1,355 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "cpu.h"
|
||||
#include "helper-tcg.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "exec/helper-proto.h"
|
||||
|
||||
uint64_t HELPER(sxt)(uint32_t s1, uint32_t s2)
|
||||
{
|
||||
int size = MIN(32, 8 << (s1 & 3));
|
||||
return s1 & 4 ? extract32(s2, 0, size) : sextract64(s2, 0, size);
|
||||
}
|
||||
|
||||
static uint64_t cr_read(CPUE2KState *env, size_t offset)
|
||||
{
|
||||
target_ulong addr = env->pcsp.base + env->pcsp.index + offset;
|
||||
return cpu_ldq_le_data(env, addr);
|
||||
}
|
||||
|
||||
static void cr_write(CPUE2KState *env, size_t offset, uint64_t data)
|
||||
{
|
||||
target_ulong addr = env->pcsp.base + env->pcsp.index + offset;
|
||||
cpu_stq_le_data(env, addr, data);
|
||||
}
|
||||
|
||||
uint64_t HELPER(state_reg_get)(CPUE2KState *env, int index)
|
||||
{
|
||||
switch (index) {
|
||||
case SR_PSR: return env->psr;
|
||||
case SR_WD: return env_wd_get(env);
|
||||
case SR_CORE_MODE: return env->core_mode;
|
||||
case SR_CWD: return 0; /* ignore */
|
||||
case SR_PSP_HI: return env->psp.hi;
|
||||
case SR_PSP_LO: return env->psp.lo;
|
||||
case SR_PSHTP: return 0; /* ignore */
|
||||
case SR_PCSP_HI: return env->pcsp.hi;
|
||||
case SR_PCSP_LO: return env->pcsp.lo;
|
||||
case SR_PCSHTP: return 0; /* ignore */
|
||||
case SR_CTPR1: return env->ctprs[0].raw;
|
||||
case SR_CTPR2: return env->ctprs[1].raw;
|
||||
case SR_CTPR3: return env->ctprs[2].raw;
|
||||
case SR_SBR: return env->sbr;
|
||||
case SR_CUTD:
|
||||
case SR_EIR:
|
||||
case SR_TSD: goto todo;
|
||||
case SR_CUIR: return env->cuir;
|
||||
case SR_OSCUD_HI: return env->oscud.hi;
|
||||
case SR_OSCUD_LO: return env->oscud.lo;
|
||||
case SR_OSGD_HI: return env->osgd.hi;
|
||||
case SR_OSGD_LO: return env->osgd.lo;
|
||||
case SR_OSEM: goto todo;
|
||||
case SR_USD_HI: return env->usd.hi;
|
||||
case SR_USD_LO: return env->usd.lo;
|
||||
case SR_TR: goto todo;
|
||||
case SR_OSR0: return env->osr0;
|
||||
case SR_CUD_HI: return env->cud.hi;
|
||||
case SR_CUD_LO: return env->cud.lo;
|
||||
case SR_GD_HI: return env->gd.hi;
|
||||
case SR_GD_LO: return env->gd.lo;
|
||||
case SR_CS_HI: return env->cs.hi;
|
||||
case SR_CS_LO: return env->cs.lo;
|
||||
case SR_DS_HI: return env->ds.hi;
|
||||
case SR_DS_LO: return env->ds.lo;
|
||||
case SR_ES_HI: return env->es.hi;
|
||||
case SR_ES_LO: return env->es.lo;
|
||||
case SR_FS_HI: return env->fs.hi;
|
||||
case SR_FS_LO: return env->fs.lo;
|
||||
case SR_GS_HI: return env->gs.hi;
|
||||
case SR_GS_LO: return env->gs.lo;
|
||||
case SR_SS_HI: return env->ss.hi;
|
||||
case SR_SS_LO: return env->ss.lo;
|
||||
case SR_DIBCR:
|
||||
case SR_DIMCR:
|
||||
case SR_DIBSR:
|
||||
case SR_DTCR:
|
||||
case SR_DIBAR0:
|
||||
case SR_DIBAR1:
|
||||
case SR_DIBAR2:
|
||||
case SR_DIBAR3:
|
||||
case SR_DIMAR0:
|
||||
case SR_DIMAR1:
|
||||
case SR_DTRAF:
|
||||
case SR_DTART: goto todo;
|
||||
case SR_CR0_HI: return cr_read(env, offsetof(E2KCrs, cr0_hi));
|
||||
case SR_CR0_LO: return cr_read(env, offsetof(E2KCrs, cr0_lo));
|
||||
case SR_CR1_HI: return cr_read(env, offsetof(E2KCrs, cr1.hi));
|
||||
case SR_CR1_LO: return cr_read(env, offsetof(E2KCrs, cr1.lo));
|
||||
case SR_SCLKM1:
|
||||
case SR_SCLKM2:
|
||||
case SR_CU_HW0: goto todo;
|
||||
case SR_UPSR: return env->upsr;
|
||||
case SR_IP: return env->ip;
|
||||
case SR_NIP: return env->nip;
|
||||
case SR_LSR: return env_lsr_get(env);
|
||||
case SR_PFPFR: return env->pfpfr.raw;
|
||||
case SR_FPCR: return env->fpcr.raw;
|
||||
case SR_FPSR: return env->fpsr.raw;
|
||||
case SR_ILCR: return env_ilcr_get(env);
|
||||
case SR_BR: return env_br_get(env);
|
||||
case SR_BGR: return env->bgr;
|
||||
case SR_IDR: return env->idr;
|
||||
case SR_CLKR: return cpu_get_host_ticks(); // FIXME
|
||||
case SR_RNDPR:
|
||||
case SR_SCLKR:
|
||||
case SR_TIR_HI:
|
||||
case SR_TIR_LO:
|
||||
case SR_RPR:
|
||||
case SR_SBBP:
|
||||
case SR_RPR_HI:
|
||||
case SR_UPSRM: goto todo;
|
||||
case SR_LSR1: return env->lsr_lcnt;
|
||||
case SR_ILCR1: return env->ilcr_lcnt;
|
||||
default:
|
||||
/* The index is checked during translation. */
|
||||
g_assert_not_reached();
|
||||
break;
|
||||
}
|
||||
|
||||
todo:
|
||||
qemu_log("reading a state register %#x is not implemented\n", index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CASE_RWAP_SET(e, f) \
|
||||
case glue(e, _HI): \
|
||||
env->f.hi = value; \
|
||||
break; \
|
||||
case glue(e, _LO): \
|
||||
env->f.lo = value & E2K_RWAP_LO_MASK; \
|
||||
break;
|
||||
|
||||
void HELPER(state_reg_set)(CPUE2KState *env, uint64_t value, int index)
|
||||
{
|
||||
switch (index) {
|
||||
case SR_UPSR:
|
||||
case SR_LSR:
|
||||
case SR_ILCR:
|
||||
case SR_PFPFR:
|
||||
case SR_FPCR:
|
||||
case SR_FPSR:
|
||||
case SR_SCLKR:
|
||||
case SR_TIR_HI:
|
||||
case SR_TIR_LO:
|
||||
case SR_RPR:
|
||||
case SR_SBBP:
|
||||
case SR_RPR_HI:
|
||||
case SR_UPSRM:
|
||||
case SR_LSR1:
|
||||
case SR_ILCR1:
|
||||
break;
|
||||
case SR_CUIR:
|
||||
raise_exception(env, EXCP_ILLEGAL_OPCODE); /* FIXME */
|
||||
break;
|
||||
default:
|
||||
if ((env->psr & PSR_PM) == 0) {
|
||||
raise_exception(env, EXCP_PRIV_ACTION);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (index) {
|
||||
case SR_PSR:
|
||||
env->psr = value & PSR_MASK;
|
||||
break;
|
||||
case SR_WD:
|
||||
env_wd_set(env, value);
|
||||
break;
|
||||
case SR_CORE_MODE:
|
||||
// FIXME: core_mode
|
||||
qemu_log("FIXME: core_mode is set to %#lx\n", value);
|
||||
env->core_mode = value;
|
||||
break;
|
||||
case SR_CWD:
|
||||
/* ignore */
|
||||
break;
|
||||
case SR_PSP_HI:
|
||||
env->psp.hi = value;
|
||||
break;
|
||||
case SR_PSP_LO:
|
||||
env->psp.lo = value & E2K_PSP_LO_MASK;
|
||||
break;
|
||||
case SR_PSHTP:
|
||||
/* ignore */
|
||||
break;
|
||||
case SR_PCSP_HI:
|
||||
env->pcsp.hi = value;
|
||||
break;
|
||||
case SR_PCSP_LO:
|
||||
env->pcsp.lo = value & E2K_PSP_LO_MASK;
|
||||
break;
|
||||
case SR_PCSHTP:
|
||||
/* ignore */
|
||||
break;
|
||||
case SR_CTPR1:
|
||||
env->ctprs[0].raw = value;
|
||||
break;
|
||||
case SR_CTPR2:
|
||||
env->ctprs[1].raw = value;
|
||||
break;
|
||||
case SR_CTPR3:
|
||||
env->ctprs[2].raw = value;
|
||||
break;
|
||||
case SR_SBR:
|
||||
env->sbr = value;
|
||||
break;
|
||||
case SR_CUTD:
|
||||
case SR_EIR:
|
||||
case SR_TSD:
|
||||
goto todo;
|
||||
case SR_CUIR:
|
||||
env->cuir = value & CUIR_MASK;
|
||||
break;
|
||||
case SR_OSEM:
|
||||
case SR_TR:
|
||||
goto todo;
|
||||
case SR_OSR0:
|
||||
env->osr0 = value;
|
||||
break;
|
||||
CASE_RWAP_SET(SR_OSCUD, oscud)
|
||||
CASE_RWAP_SET(SR_OSGD, osgd)
|
||||
CASE_RWAP_SET(SR_USD, usd)
|
||||
CASE_RWAP_SET(SR_CUD, cud)
|
||||
CASE_RWAP_SET(SR_GD, gd)
|
||||
CASE_RWAP_SET(SR_CS, cs)
|
||||
CASE_RWAP_SET(SR_DS, ds)
|
||||
CASE_RWAP_SET(SR_ES, es)
|
||||
CASE_RWAP_SET(SR_FS, fs)
|
||||
CASE_RWAP_SET(SR_GS, gs)
|
||||
CASE_RWAP_SET(SR_SS, ss)
|
||||
case SR_DIBCR:
|
||||
case SR_DIMCR:
|
||||
case SR_DIBSR:
|
||||
case SR_DTCR:
|
||||
case SR_DIBAR0:
|
||||
case SR_DIBAR1:
|
||||
case SR_DIBAR2:
|
||||
case SR_DIBAR3:
|
||||
case SR_DIMAR0:
|
||||
case SR_DIMAR1:
|
||||
case SR_DTRAF:
|
||||
case SR_DTART:
|
||||
case SR_CR0_HI:
|
||||
cr_write(env, offsetof(E2KCrs, cr0_hi), value);
|
||||
break;
|
||||
case SR_CR0_LO:
|
||||
cr_write(env, offsetof(E2KCrs, cr0_lo), value);
|
||||
break;
|
||||
case SR_CR1_HI:
|
||||
cr_write(env, offsetof(E2KCrs, cr1.hi), value);
|
||||
break;
|
||||
case SR_CR1_LO:
|
||||
cr_write(env, offsetof(E2KCrs, cr1.lo), value);
|
||||
break;
|
||||
case SR_SCLKM1:
|
||||
case SR_SCLKM2:
|
||||
case SR_CU_HW0:
|
||||
goto todo;
|
||||
case SR_UPSR:
|
||||
env->upsr = value & UPSR_MASK;
|
||||
break;
|
||||
case SR_LSR:
|
||||
env_lsr_set(env, value);
|
||||
env_ilcr_set(env, value);
|
||||
break;
|
||||
case SR_PFPFR:
|
||||
env->pfpfr.raw = value;
|
||||
e2k_update_fp_status(env);
|
||||
break;
|
||||
case SR_FPCR:
|
||||
env->fpcr.raw = value;
|
||||
e2k_update_fx_status(env);
|
||||
break;
|
||||
case SR_FPSR:
|
||||
env->fpsr.raw = value;
|
||||
break;
|
||||
case SR_ILCR:
|
||||
env->ilcr = (value >> LSR_ECNT_OFF) & ILCR_MASK;
|
||||
env->ilcr_lcnt = value & GEN_MASK(0, LSR_LCNT_LEN);
|
||||
break;
|
||||
case SR_BR:
|
||||
env_br_set(env, value);
|
||||
break;
|
||||
case SR_BGR:
|
||||
env->bgr = value & BGR_MASK;
|
||||
break;
|
||||
case SR_RNDPR:
|
||||
case SR_SCLKR:
|
||||
case SR_TIR_HI:
|
||||
case SR_TIR_LO:
|
||||
case SR_RPR:
|
||||
case SR_SBBP:
|
||||
case SR_RPR_HI:
|
||||
case SR_UPSRM:
|
||||
goto todo;
|
||||
case SR_LSR1:
|
||||
env->lsr_lcnt = value;
|
||||
env->ilcr_lcnt = value;
|
||||
break;
|
||||
case SR_ILCR1:
|
||||
env->ilcr_lcnt = value;
|
||||
break;
|
||||
default:
|
||||
/* The index is checked during translation. */
|
||||
g_assert_not_reached();
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
todo:
|
||||
qemu_log("write to state register %#x is not implemented\n", index);
|
||||
}
|
||||
|
||||
uint64_t HELPER(getsp)(CPUE2KState *env, uint32_t src2)
|
||||
{
|
||||
int32_t s2 = src2 & ~0xf;
|
||||
|
||||
env->usd.base += s2;
|
||||
env->usd.size -= s2;
|
||||
|
||||
return env->usd.base;
|
||||
}
|
||||
|
||||
void HELPER(dam_lock_addr)(CPUE2KState *env, uint64_t addr, int size, int reg)
|
||||
{
|
||||
// TODO: helper_dam_lock_addr
|
||||
}
|
||||
|
||||
int HELPER(dam_unlock_addr)(CPUE2KState *env, uint64_t addr, int size, int reg)
|
||||
{
|
||||
// TODO: helper_dam_unlock_addr
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint64_t HELPER(clmull)(uint64_t s1, uint64_t s2)
|
||||
{
|
||||
uint64_t r = 0;
|
||||
|
||||
for (; s1; s1 >>= 1, s2 <<= 1) {
|
||||
r ^= s1 & 1 ? s2 : 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
uint64_t HELPER(clmulh)(uint64_t s1, uint64_t s2)
|
||||
{
|
||||
uint64_t r = 0;
|
||||
|
||||
for (s2 >>= 1; s1; s1 <<= 1, s2 >>= 1) {
|
||||
r ^= s1 & (1ULL << 63) ? s2 : 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "exec/helper-proto.h"
|
||||
|
||||
static int e2k_probe_access(CPUE2KState *env, target_ulong addr, int size,
|
||||
MMUAccessType access_type, int mmu_idx)
|
||||
{
|
||||
target_ulong addr_end = addr + size - 1;
|
||||
int flags;
|
||||
void *ignore;
|
||||
|
||||
flags = probe_access_flags(env, addr, access_type, mmu_idx,
|
||||
true, &ignore, 0);
|
||||
|
||||
if (flags & TLB_INVALID_MASK) {
|
||||
return 0;
|
||||
} else if ((addr & TARGET_PAGE_MASK) != (addr_end & TARGET_PAGE_MASK)) {
|
||||
flags = probe_access_flags(env, addr_end, access_type, mmu_idx, true,
|
||||
&ignore, 0);
|
||||
return !(flags & TLB_INVALID_MASK);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int HELPER(probe_read_access)(CPUE2KState *env, target_ulong addr,
|
||||
int size, int mmu_idx)
|
||||
{
|
||||
return e2k_probe_access(env, addr, size, MMU_DATA_LOAD, mmu_idx);
|
||||
}
|
||||
|
||||
int HELPER(probe_write_access)(CPUE2KState *env, target_ulong addr,
|
||||
int size, int mmu_idx)
|
||||
{
|
||||
return e2k_probe_access(env, addr, size, MMU_DATA_STORE, mmu_idx);
|
||||
}
|
|
@ -0,0 +1,604 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "cpu.h"
|
||||
#include "helper-tcg.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "exec/helper-proto.h"
|
||||
|
||||
static uint8_t reverse_bits(uint8_t b)
|
||||
{
|
||||
b = ((b & 0xf0) >> 4) | ((b & 0x0f) << 4);
|
||||
b = ((b & 0xcc) >> 2) | ((b & 0x33) << 2);
|
||||
b = ((b & 0xaa) >> 1) | ((b & 0x55) << 1);
|
||||
return b;
|
||||
}
|
||||
|
||||
#define vec64_ub 8
|
||||
#define vec64_uh 4
|
||||
#define vec64_uw 2
|
||||
#define vec64_ud 1
|
||||
|
||||
#define vec64_sb vec64_ub
|
||||
#define vec64_sh vec64_uh
|
||||
#define vec64_sw vec64_uw
|
||||
#define vec64_sd vec64_ud
|
||||
|
||||
#define vec64_len(type) glue(vec64_, type)
|
||||
|
||||
#define vec128_ub 16
|
||||
#define vec128_uh 8
|
||||
#define vec128_uw 4
|
||||
#define vec128_ud 2
|
||||
|
||||
#define vec128_sb vec128_ub
|
||||
#define vec128_sh vec128_uh
|
||||
#define vec128_sw vec128_uw
|
||||
#define vec128_sd vec128_ud
|
||||
|
||||
#define vec128_len(type) glue(vec128_, type)
|
||||
|
||||
typedef union {
|
||||
uint8_t ub[vec64_ub];
|
||||
uint16_t uh[vec64_uh];
|
||||
uint32_t uw[vec64_uw];
|
||||
uint64_t ud[vec64_ud];
|
||||
int8_t sb[vec64_ub];
|
||||
int16_t sh[vec64_uh];
|
||||
int32_t sw[vec64_uw];
|
||||
int64_t sd[vec64_ud];
|
||||
} vec64;
|
||||
|
||||
#define shr16(x) ((x) >> 16)
|
||||
#define shr14_add1_shr1(x) ((((x) >> 14) + 1) >> 1)
|
||||
#define and16(x) ((x) & 0xffff)
|
||||
#define satsb(x) MIN(MAX(x, -128), 127)
|
||||
#define satsh(x) MIN(MAX(x, -32768), 32767)
|
||||
#define satub(x) MIN(MAX(x, 0), 255)
|
||||
#define satuh(x) MIN(MAX(x, 0), 65535)
|
||||
|
||||
#define add(a, b) ((a) + (b))
|
||||
#define sub(a, b) ((a) - (b))
|
||||
#define mul(a, b) ((a) * (b))
|
||||
#define div(a, b) ((a) / (b))
|
||||
|
||||
#define GEN_HELPER_PACKED_N(name, n, code) \
|
||||
uint64_t HELPER(name)(uint64_t src1, uint64_t src2) \
|
||||
{ \
|
||||
size_t i = 0; \
|
||||
vec64 s1 = { .ud[0] = src1 }, s2 = { .ud[0] = src2 }; \
|
||||
vec64 dst = { .ud[0] = 0 }; \
|
||||
for (; i < n; i++) { \
|
||||
code \
|
||||
} \
|
||||
return dst.ud[0]; \
|
||||
}
|
||||
#define GEN_HELPER_PACKED(name, type, code) \
|
||||
GEN_HELPER_PACKED_N(name, vec64_len(type), code)
|
||||
|
||||
#define GEN_HELPER_PACKED_OP(name, type, op) \
|
||||
GEN_HELPER_PACKED_N(name, vec64_len(type), { \
|
||||
dst.type[i] = op(s1.type[i], s2.type[i]); \
|
||||
})
|
||||
|
||||
#define GEN_HELPER_PACKED_SCALAR(name, type, code) \
|
||||
uint64_t HELPER(name)(uint64_t src1, uint64_t s2) \
|
||||
{ \
|
||||
size_t i = 0; \
|
||||
vec64 s1 = { .ud[0] = src1 }, dst = { .ud[0] = 0 }; \
|
||||
for (; i < glue(vec64_, type); i++) { \
|
||||
code \
|
||||
} \
|
||||
return dst.ud[0]; \
|
||||
}
|
||||
|
||||
#define IMPL_QPACKED_N(name, n, code) \
|
||||
void HELPER(name)(E2KReg *r, E2KReg *s1, E2KReg *s2) \
|
||||
{ \
|
||||
int i; \
|
||||
\
|
||||
for (i = 0; i < n; i++) { \
|
||||
code \
|
||||
} \
|
||||
}
|
||||
|
||||
#define IMPL_QPACKED(name, type, code) \
|
||||
IMPL_QPACKED_N(name, vec64_len(type), code)
|
||||
|
||||
#define IMPL_QPACKED_OP(name, type, op) \
|
||||
IMPL_QPACKED_N(name, vec128_len(type), { \
|
||||
r->type[i] = op(s1->type[i], s2->type[i]); \
|
||||
})
|
||||
|
||||
#define GEN_HELPER_PACKED_MINMAX(name, type, op) \
|
||||
GEN_HELPER_PACKED_OP(glue(name, type), type, op)
|
||||
|
||||
GEN_HELPER_PACKED_MINMAX(pmin, ub, MIN)
|
||||
GEN_HELPER_PACKED_MINMAX(pmin, sb, MIN)
|
||||
GEN_HELPER_PACKED_MINMAX(pmin, uh, MIN)
|
||||
GEN_HELPER_PACKED_MINMAX(pmin, sh, MIN)
|
||||
GEN_HELPER_PACKED_MINMAX(pmin, uw, MIN)
|
||||
GEN_HELPER_PACKED_MINMAX(pmin, sw, MIN)
|
||||
|
||||
GEN_HELPER_PACKED_MINMAX(pmax, ub, MAX)
|
||||
GEN_HELPER_PACKED_MINMAX(pmax, sb, MAX)
|
||||
GEN_HELPER_PACKED_MINMAX(pmax, uh, MAX)
|
||||
GEN_HELPER_PACKED_MINMAX(pmax, sh, MAX)
|
||||
GEN_HELPER_PACKED_MINMAX(pmax, uw, MAX)
|
||||
GEN_HELPER_PACKED_MINMAX(pmax, sw, MAX)
|
||||
|
||||
#define GEN_HELPER_PACKED_CMP(name, type, op) \
|
||||
GEN_HELPER_PACKED(name, type, { \
|
||||
dst.type[i] = s1.type[i] op s2.type[i] ? -1 : 0; \
|
||||
})
|
||||
|
||||
GEN_HELPER_PACKED_CMP(pcmpeqb, ub, ==)
|
||||
GEN_HELPER_PACKED_CMP(pcmpeqh, uh, ==)
|
||||
GEN_HELPER_PACKED_CMP(pcmpeqw, uw, ==)
|
||||
GEN_HELPER_PACKED_CMP(pcmpeqd, ud, ==)
|
||||
|
||||
GEN_HELPER_PACKED_CMP(pcmpgtb, sb, >)
|
||||
GEN_HELPER_PACKED_CMP(pcmpgth, sh, >)
|
||||
GEN_HELPER_PACKED_CMP(pcmpgtw, sw, >)
|
||||
GEN_HELPER_PACKED_CMP(pcmpgtd, sd, >)
|
||||
|
||||
#define GEN_HELPER_PACKED_BINOP_MAP(name, type, op, cast, map) \
|
||||
GEN_HELPER_PACKED(name, type, { \
|
||||
dst.type[i] = map((cast) s1.type[i] op s2.type[i]); \
|
||||
})
|
||||
|
||||
GEN_HELPER_PACKED_BINOP_MAP(paddsb, sb, +, int16_t, satsb)
|
||||
GEN_HELPER_PACKED_BINOP_MAP(paddsh, sh, +, int32_t, satsh)
|
||||
GEN_HELPER_PACKED_BINOP_MAP(paddusb, ub, +, int16_t, satub)
|
||||
GEN_HELPER_PACKED_BINOP_MAP(paddush, uh, +, int32_t, satuh)
|
||||
|
||||
GEN_HELPER_PACKED_BINOP_MAP(psubsb, sb, -, int16_t, satsb)
|
||||
GEN_HELPER_PACKED_BINOP_MAP(psubsh, sh, -, int32_t, satsh)
|
||||
GEN_HELPER_PACKED_BINOP_MAP(psubusb, ub, -, int16_t, satub)
|
||||
GEN_HELPER_PACKED_BINOP_MAP(psubush, uh, -, int32_t, satuh)
|
||||
|
||||
#define GEN_HELPER_PACKED_HORIZONTAL_OP(name, type, op, map) \
|
||||
GEN_HELPER_PACKED_N(name, vec64_len(type) / 2, { \
|
||||
int j = i * 2; \
|
||||
dst.type[i ] = map(op(s1.type[j], s1.type[j + 1])); \
|
||||
dst.type[i + vec64_len(type) / 2] = map(op(s2.type[j], s2.type[j + 1])); \
|
||||
}) \
|
||||
IMPL_QPACKED_N(glue(q, name), vec128_len(type) / 2, { \
|
||||
int j = i * 2; \
|
||||
r->type[i ] = map(op(s1->type[j], s1->type[j + 1])); \
|
||||
r->type[i + vec128_len(type) / 2] = map(op(s2->type[j], s2->type[j + 1])); \
|
||||
})
|
||||
|
||||
GEN_HELPER_PACKED_HORIZONTAL_OP(phaddh, sh, add, ident)
|
||||
GEN_HELPER_PACKED_HORIZONTAL_OP(phaddw, sw, add, ident)
|
||||
GEN_HELPER_PACKED_HORIZONTAL_OP(phaddsh, sh, add, satsh)
|
||||
GEN_HELPER_PACKED_HORIZONTAL_OP(phsubh, sh, sub, ident)
|
||||
GEN_HELPER_PACKED_HORIZONTAL_OP(phsubw, sw, sub, ident)
|
||||
GEN_HELPER_PACKED_HORIZONTAL_OP(phsubsh, sh, sub, satsh)
|
||||
|
||||
#define GEN_HELPER_PACKED_SCALAR_BINOP(name, type, op) \
|
||||
GEN_HELPER_PACKED_SCALAR(name, type, { \
|
||||
dst.type[i] = s2 < sizeof(s1.type[0]) * 8 ? s1.type[i] op s2 : 0; \
|
||||
})
|
||||
|
||||
GEN_HELPER_PACKED_SCALAR_BINOP(psllh, uh, <<)
|
||||
GEN_HELPER_PACKED_SCALAR_BINOP(psllw, uw, <<)
|
||||
GEN_HELPER_PACKED_SCALAR_BINOP(pslld, ud, <<)
|
||||
GEN_HELPER_PACKED_SCALAR_BINOP(psrlh, uh, >>)
|
||||
GEN_HELPER_PACKED_SCALAR_BINOP(psrlw, uw, >>)
|
||||
GEN_HELPER_PACKED_SCALAR_BINOP(psrld, ud, >>)
|
||||
|
||||
#define GEN_HELPER_PACKED_SRA(name, type, t) \
|
||||
GEN_HELPER_PACKED_SCALAR(name, type, { \
|
||||
int max = sizeof(s1.type[0]) * 8 - 1; \
|
||||
dst.type[i] = (t) s1.type[i] >> (s2 < max ? s2 : max); \
|
||||
})
|
||||
|
||||
GEN_HELPER_PACKED_SRA(psrah, sh, int32_t)
|
||||
GEN_HELPER_PACKED_SRA(psraw, sw, int64_t)
|
||||
|
||||
#define GEN_HELPER_PACKED_MAD(name, dst_type, t0, t1, cast, op) \
|
||||
GEN_HELPER_PACKED(name, dst_type, { \
|
||||
int j = i * 2; \
|
||||
dst.dst_type[i] = op( \
|
||||
(cast) s1.t0[j + 1] * s2.t1[j + 1] + \
|
||||
(cast) s1.t0[j ] * s2.t1[j ] \
|
||||
); \
|
||||
})
|
||||
|
||||
GEN_HELPER_PACKED_MAD(pmaddh, sw, sh, sh, int32_t, ident)
|
||||
GEN_HELPER_PACKED_MAD(pmaddubsh, sh, sb, ub, int32_t, satsh)
|
||||
|
||||
GEN_HELPER_PACKED(psadbw, ub, { dst.uw[0] += abs(s1.ub[i] - s2.ub[i]); })
|
||||
|
||||
GEN_HELPER_PACKED(pavgusb, ub, { dst.ub[i] = (s1.ub[i] + s2.ub[i] + 1) >> 1; })
|
||||
GEN_HELPER_PACKED(pavgush, uh, { dst.uh[i] = (s1.uh[i] + s2.uh[i] + 1) >> 1; })
|
||||
|
||||
#define GEN_HELPER_PACKED_MULH(name, type, cast, map) \
|
||||
GEN_HELPER_PACKED(name, type, { \
|
||||
dst.type[i] = map(((cast) s1.type[i]) * s2.type[i]); \
|
||||
})
|
||||
|
||||
GEN_HELPER_PACKED_MULH(pmulhh, sh, int32_t, shr16)
|
||||
GEN_HELPER_PACKED_MULH(pmullh, sh, int32_t, and16)
|
||||
GEN_HELPER_PACKED_MULH(pmulhuh, uh, uint32_t, shr16)
|
||||
GEN_HELPER_PACKED_MULH(pmulhrsh, sh, int32_t, shr14_add1_shr1)
|
||||
|
||||
GEN_HELPER_PACKED(pmulubhh, uh, { \
|
||||
dst.uh[i] = ((int16_t) s1.ub[i] * s2.sh[i] + 0x80) >> 8; \
|
||||
})
|
||||
|
||||
GEN_HELPER_PACKED(mpsadbh, uh, { \
|
||||
dst.uh[i] = abs((int16_t) s1.ub[i ] - s2.ub[0]) \
|
||||
+ abs((int16_t) s1.ub[i + 1] - s2.ub[1]) \
|
||||
+ abs((int16_t) s1.ub[i + 2] - s2.ub[2]) \
|
||||
+ abs((int16_t) s1.ub[i + 3] - s2.ub[3]); \
|
||||
})
|
||||
|
||||
#define mul_sign(a, b) ((b) < 0 ? -(a) : ((b) > 0 ? (a) : 0))
|
||||
|
||||
GEN_HELPER_PACKED_OP(psignb, sb, mul_sign)
|
||||
GEN_HELPER_PACKED_OP(psignh, sh, mul_sign)
|
||||
GEN_HELPER_PACKED_OP(psignw, sw, mul_sign)
|
||||
|
||||
#define MOVMASK(mask_type, type) { \
|
||||
dst.mask_type[0] |= (s1.type[i] < 0) << (i + glue(vec64_, type)); \
|
||||
dst.mask_type[0] |= (s2.type[i] < 0) << (i ); \
|
||||
}
|
||||
|
||||
GEN_HELPER_PACKED(pmovmskb, sb, MOVMASK(uh, sb))
|
||||
GEN_HELPER_PACKED(pmovmskps, sw, MOVMASK(ub, sw))
|
||||
GEN_HELPER_PACKED(pmovmskpd, sd, MOVMASK(ub, sd))
|
||||
|
||||
#define PACK(dst_type, type, op) { \
|
||||
dst.dst_type[i + glue(vec64_, type)] = op(s1.type[i]); \
|
||||
dst.dst_type[i ] = op(s2.type[i]); \
|
||||
}
|
||||
|
||||
GEN_HELPER_PACKED(packsshb, sh, PACK(sb, sh, satsb))
|
||||
GEN_HELPER_PACKED(packushb, uh, PACK(ub, sh, satub))
|
||||
GEN_HELPER_PACKED(packsswh, sw, PACK(sh, sw, satsh))
|
||||
GEN_HELPER_PACKED(packuswh, sw, PACK(uh, sw, satuh))
|
||||
|
||||
#define GEN_HELPER_PACKED_UNPACK(name, type, offset) \
|
||||
GEN_HELPER_PACKED(name, type, { \
|
||||
int j = offset + i / 2; \
|
||||
dst.type[i] = i & 1 ? s1.type[j] : s2.type[j]; \
|
||||
})
|
||||
|
||||
GEN_HELPER_PACKED_UNPACK(punpcklbh, ub, 0)
|
||||
GEN_HELPER_PACKED_UNPACK(punpcklhw, uh, 0)
|
||||
GEN_HELPER_PACKED_UNPACK(punpcklwd, uw, 0)
|
||||
GEN_HELPER_PACKED_UNPACK(punpckhbh, ub, 4)
|
||||
GEN_HELPER_PACKED_UNPACK(punpckhhw, uh, 2)
|
||||
GEN_HELPER_PACKED_UNPACK(punpckhwd, uw, 1)
|
||||
|
||||
uint64_t HELPER(pshufb)(uint64_t src1, uint64_t src2, uint64_t src3)
|
||||
{
|
||||
vec64 ret, s1, s2, s3;
|
||||
int i;
|
||||
|
||||
s1.ud[0] = src1;
|
||||
s2.ud[0] = src2;
|
||||
s3.ud[0] = src3;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
uint8_t desc = s3.ub[i];
|
||||
int index = desc & 7;
|
||||
uint8_t byte = desc & 8 ? s1.ub[index] : s2.ub[index];
|
||||
|
||||
byte = desc & 0x10 ? ~byte : byte;
|
||||
byte = desc & 0x20 ? reverse_bits(byte) : byte;
|
||||
byte = desc & 0x40 ? (byte & 0x80 ? 0xff : 0) : byte;
|
||||
|
||||
if (desc & 0x80) {
|
||||
switch ((desc & 0x70) >> 4) {
|
||||
case 2: byte = 0x7f; break;
|
||||
case 4: byte = 0x80; break;
|
||||
case 6: byte = 0xff; break;
|
||||
default: byte = 0; break;
|
||||
}
|
||||
}
|
||||
|
||||
ret.ub[i] = byte;
|
||||
}
|
||||
|
||||
return ret.ud[0];
|
||||
}
|
||||
|
||||
uint64_t HELPER(pmerge)(uint64_t src1, uint64_t src2, uint64_t src3)
|
||||
{
|
||||
vec64 r, s1, s2, s3;
|
||||
int i;
|
||||
|
||||
s1.ud[0] = src1;
|
||||
s2.ud[0] = src2;
|
||||
s3.ud[0] = src3;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
r.ub[i] = s3.sb[i] < 0 ? s2.ub[i] : s1.ub[i];
|
||||
}
|
||||
|
||||
return r.ud[0];
|
||||
}
|
||||
|
||||
uint64_t HELPER(pshufh)(uint64_t src1, uint32_t imm8)
|
||||
{
|
||||
int i;
|
||||
vec64 s1 = { .ud[0] = src1 }, dst;
|
||||
for (i = 0; i < vec64_uh; i++) {
|
||||
int j = (imm8 >> (i * 2)) & 0x3;
|
||||
dst.uh[i] = s1.uh[j];
|
||||
}
|
||||
return dst.ud[0];
|
||||
}
|
||||
|
||||
uint64_t HELPER(pshufw)(uint64_t src1, uint64_t src2, uint32_t imm8)
|
||||
{
|
||||
int i;
|
||||
vec64 s1 = { .ud[0] = src1 }, s2 = { .ud[0] = src2 }, dst;
|
||||
for (i = 0; i < vec64_uw; i++) {
|
||||
int sel = (imm8 >> (i * 2)) & 0x3;
|
||||
int j = sel & 1;
|
||||
dst.uw[i] = sel > 1 ? s1.uw[j] : s2.uw[j];
|
||||
}
|
||||
return dst.ud[0];
|
||||
}
|
||||
|
||||
uint64_t HELPER(phminposuh)(uint64_t src1, uint64_t src2)
|
||||
{
|
||||
int i;
|
||||
vec64 s1 = { .ud[0] = src1 }, s2 = { .ud[0] = src2 }, dst = { .ud[0] = 0 };
|
||||
dst.uh[0] = s1.uh[0];
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (s1.uh[i] < dst.uh[0]) {
|
||||
dst.uh[0] = s1.uh[i];
|
||||
dst.uh[1] = i;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (s2.uh[i] < dst.uh[0]) {
|
||||
dst.uh[0] = s2.uh[i];
|
||||
dst.uh[1] = 4 + i;
|
||||
}
|
||||
}
|
||||
return dst.ud[0];
|
||||
}
|
||||
|
||||
void HELPER(qpmpsadbh)(E2KReg *r, E2KReg *s1, uint32_t s2)
|
||||
{
|
||||
r->ud[0] = helper_mpsadbh(s1->ud[0], s2);
|
||||
r->ud[1] = helper_mpsadbh(s1->ud[1], s2);
|
||||
}
|
||||
|
||||
void HELPER(qpmulubhh)(E2KReg *r, uint64_t s1, E2KReg *s2)
|
||||
{
|
||||
r->ud[0] = helper_pmulubhh(s1 , s2->ud[0]);
|
||||
r->ud[1] = helper_pmulubhh(s1 >> 32, s2->ud[1]);
|
||||
}
|
||||
|
||||
uint64_t HELPER(qphminposuh)(E2KReg *s1, E2KReg *s2)
|
||||
{
|
||||
int i;
|
||||
uint16_t v = s1->uh[0];
|
||||
uint16_t p = 0;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (s1->uh[i] < v) {
|
||||
v = s1->uh[i];
|
||||
p = i;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (s2->uh[i] < v) {
|
||||
v = s2->uh[i];
|
||||
p = 8 + i;
|
||||
}
|
||||
}
|
||||
return ((uint64_t) p << 16) | v;
|
||||
}
|
||||
|
||||
uint32_t HELPER(qpsgn2mskb)(E2KReg *s2)
|
||||
{
|
||||
uint32_t r = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
r |= s2->sb[i] < 0 ? 1 << i : 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void HELPER(qpmsk2sgnb)(E2KReg *r, E2KReg *s1, uint32_t s2)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
r->ub[i] = s2 & (1 << i) ? s1->ub[i] | 0x80 : s1->ub[i] & 0x7f;
|
||||
}
|
||||
}
|
||||
|
||||
void HELPER(qppermb)(E2KReg *r, E2KReg *s1, E2KReg *s2, E2KReg *s3)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
uint8_t sel = s3->ub[i];
|
||||
int index = sel & 0x0f;
|
||||
uint8_t byte = sel & 0x10 ? s1->ub[index] : s2->ub[index];
|
||||
|
||||
byte = sel & 0x20 ? ~byte : byte;
|
||||
byte = sel & 0x40 ? reverse_bits(byte) : byte;
|
||||
byte = sel & 0x80 ? (byte & 0x80 ? 0xff : 0) : byte;
|
||||
|
||||
r->ub[i] = byte;
|
||||
}
|
||||
}
|
||||
|
||||
void HELPER(qpshufb)(E2KReg *r, E2KReg *s1, E2KReg *s2, E2KReg *s3)
|
||||
{
|
||||
r->ud[0] = helper_pshufb(s2->ud[1], s2->ud[0], s3->ud[0]);
|
||||
r->ud[1] = helper_pshufb(s1->ud[1], s1->ud[0], s3->ud[1]);
|
||||
}
|
||||
|
||||
static uint64_t get_value_from_truth_table(bool x, bool y, bool z, uint32_t truth_table)
|
||||
{
|
||||
int pos = x << 2 | y << 1 | z;
|
||||
return (truth_table >> pos) & 1ULL;
|
||||
}
|
||||
|
||||
uint64_t HELPER(plog)(uint32_t opc, uint64_t src1, uint64_t src2, uint64_t src3)
|
||||
{
|
||||
int i;
|
||||
uint64_t ret = 0;
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
uint32_t x = extract64(src1, i, 1);
|
||||
uint32_t y = extract64(src2, i, 1);
|
||||
uint32_t z = extract64(src3, i, 1);
|
||||
|
||||
uint64_t bit = get_value_from_truth_table(x, y, z, opc);
|
||||
|
||||
ret |= bit << i;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define GEN_ENV_HELPER_PACKED_N(name, n, code) \
|
||||
uint64_t HELPER(name)(CPUE2KState *env, uint64_t src1, uint64_t src2) \
|
||||
{ \
|
||||
size_t i = 0; \
|
||||
vec64 s1 = { .ud[0] = src1 }, s2 = { .ud[0] = src2 }; \
|
||||
vec64 dst = { .ud[0] = 0 }; \
|
||||
for (; i < n; i++) { \
|
||||
code \
|
||||
} \
|
||||
return dst.ud[0]; \
|
||||
}
|
||||
|
||||
#define GEN_ENV_HELPER_PACKED(name, type, code) \
|
||||
GEN_ENV_HELPER_PACKED_N(name, vec64_len(type), code)
|
||||
|
||||
#define GEN_ENV_HELPER_PACKED_OP(name, type, op) \
|
||||
GEN_ENV_HELPER_PACKED_N(name, vec64_len(type), { \
|
||||
dst.type[i] = op(env, s1.type[i], s2.type[i]); \
|
||||
})
|
||||
|
||||
#define GEN_ENV_HELPER_PACKED_HORIZONTAL_OP(name, type, op, map) \
|
||||
GEN_ENV_HELPER_PACKED_N(name, vec64_len(type) / 2, { \
|
||||
int j = i * 2; \
|
||||
dst.type[i ] = map(op(env, s1.type[j], s1.type[j + 1])); \
|
||||
dst.type[i + vec64_len(type) / 2] = map(op(env, s2.type[j], s2.type[j + 1])); \
|
||||
})
|
||||
|
||||
#define IMPL_QPACKED_ENV_N(name, n, code) \
|
||||
void HELPER(name)(E2KReg *r, CPUE2KState *env, E2KReg *s1, E2KReg *s2) \
|
||||
{ \
|
||||
int i; \
|
||||
\
|
||||
for (i = 0; i < n; i++) { \
|
||||
code \
|
||||
} \
|
||||
}
|
||||
|
||||
#define IMPL_QPACKED_ENV(name, type, code) \
|
||||
IMPL_QPACKED_ENV_N(name, vec128_len(type), code)
|
||||
|
||||
#define IMPL_QPACKED_ENV_OP(name, type, op) \
|
||||
IMPL_QPACKED_ENV_N(name, vec128_len(type), { \
|
||||
r->type[i] = op(env, s1->type[i], s2->type[i]); \
|
||||
})
|
||||
|
||||
#define IMPL_QPACKED_ENV_HOP(name, type, op, map) \
|
||||
IMPL_QPACKED_ENV_N(name, vec128_len(type) / 2, { \
|
||||
int j = i * 2; \
|
||||
r->type[i ] = map(op(env, s1->type[j], s1->type[j + 1])); \
|
||||
r->type[i + vec128_len(type) / 2] = map(op(env, s2->type[j], s2->type[j + 1])); \
|
||||
})
|
||||
|
||||
GEN_ENV_HELPER_PACKED_OP(pfadds, uw, helper_fadds)
|
||||
GEN_ENV_HELPER_PACKED_OP(pfsubs, uw, helper_fsubs)
|
||||
GEN_ENV_HELPER_PACKED_OP(pfmuls, uw, helper_fmuls)
|
||||
GEN_ENV_HELPER_PACKED_OP(pfmaxs, uw, helper_fmaxs)
|
||||
GEN_ENV_HELPER_PACKED_OP(pfmins, uw, helper_fmins)
|
||||
GEN_ENV_HELPER_PACKED_HORIZONTAL_OP(pfhadds, uw, helper_fadds, ident)
|
||||
GEN_ENV_HELPER_PACKED_HORIZONTAL_OP(pfhsubs, uw, helper_fsubs, ident)
|
||||
IMPL_QPACKED_ENV_HOP(qpfhadds, uw, helper_fadds, ident)
|
||||
IMPL_QPACKED_ENV_HOP(qpfhsubs, uw, helper_fsubs, ident)
|
||||
|
||||
GEN_ENV_HELPER_PACKED_OP(pfcmpeqs, uw, helper_fcmpeqs)
|
||||
GEN_ENV_HELPER_PACKED_OP(pfcmplts, uw, helper_fcmplts)
|
||||
GEN_ENV_HELPER_PACKED_OP(pfcmples, uw, helper_fcmples)
|
||||
GEN_ENV_HELPER_PACKED_OP(pfcmpuods, uw, helper_fcmpuods)
|
||||
GEN_ENV_HELPER_PACKED_OP(pfcmpneqs, uw, helper_fcmpneqs)
|
||||
GEN_ENV_HELPER_PACKED_OP(pfcmpnlts, uw, helper_fcmpnlts)
|
||||
GEN_ENV_HELPER_PACKED_OP(pfcmpnles, uw, helper_fcmpnles)
|
||||
GEN_ENV_HELPER_PACKED_OP(pfcmpods, uw, helper_fcmpods)
|
||||
|
||||
GEN_ENV_HELPER_PACKED(pfaddsubs, uw, { \
|
||||
if (i & 1) { \
|
||||
dst.uw[i] = helper_fadds(env, s1.uw[i], s2.uw[i]); \
|
||||
} else { \
|
||||
dst.uw[i] = helper_fsubs(env, s1.uw[i], s2.uw[i]); \
|
||||
} \
|
||||
})
|
||||
|
||||
#define GEN_ENV_HELPER_PACKED_UNARY_N(name, n, code) \
|
||||
uint64_t HELPER(name)(CPUE2KState *env, uint64_t src2) \
|
||||
{ \
|
||||
size_t i = 0; \
|
||||
vec64 s2 = { .ud[0] = src2 }; \
|
||||
vec64 dst = { .ud[0] = 0 }; \
|
||||
for (; i < n; i++) { \
|
||||
code \
|
||||
} \
|
||||
return dst.ud[0]; \
|
||||
}
|
||||
#define GEN_ENV_HELPER_PACKED_UNARY(name, type, code) \
|
||||
GEN_ENV_HELPER_PACKED_UNARY_N(name, vec64_len(type), code)
|
||||
#define GEN_ENV_HELPER_PACKED_UNARY_OP(name, type, op) \
|
||||
GEN_ENV_HELPER_PACKED_UNARY_N(name, vec64_len(type), { \
|
||||
dst.type[i] = op(env, s2.type[i]); \
|
||||
})
|
||||
|
||||
#define GEN_ENV_HELPER_PACKED_OP_CVT(name, type, op) \
|
||||
GEN_ENV_HELPER_PACKED_N(name, vec64_len(type), { \
|
||||
dst.type[i] = op(env, s1.uw[0], s2.type[i]); \
|
||||
})
|
||||
|
||||
GEN_ENV_HELPER_PACKED_OP_CVT(pfstoifs, uw, helper_fstoifs)
|
||||
GEN_ENV_HELPER_PACKED_UNARY_OP(pistofs, uw, helper_istofs)
|
||||
GEN_ENV_HELPER_PACKED_UNARY_OP(pfstois, uw, helper_fstois)
|
||||
GEN_ENV_HELPER_PACKED_UNARY_OP(pfstoistr, uw, helper_fstoistr)
|
||||
|
||||
#define IMPL_QPACKED_ENV_CVT_EXT(name, op) \
|
||||
void HELPER(name)(E2KReg *r, CPUE2KState *env, uint64_t src2) \
|
||||
{ \
|
||||
vec64 s2 = { .ud[0] = src2 }; \
|
||||
\
|
||||
r->ud[0] = op(env, s2.uw[0]); \
|
||||
r->ud[1] = op(env, s2.uw[1]); \
|
||||
}
|
||||
|
||||
IMPL_QPACKED_ENV_CVT_EXT(qpfstoid, helper_fstoid)
|
||||
IMPL_QPACKED_ENV_CVT_EXT(qpfstoidtr, helper_fstoidtr)
|
||||
IMPL_QPACKED_ENV_CVT_EXT(qpistofd, helper_istofd)
|
||||
IMPL_QPACKED_ENV_CVT_EXT(qpfstofd, helper_fstofd)
|
||||
|
||||
#define IMPL_QPACKED_ENV_CVT_TRUNC(name, op) \
|
||||
uint64_t HELPER(name)(CPUE2KState *env, E2KReg *s2) \
|
||||
{ \
|
||||
vec64 r; \
|
||||
\
|
||||
r.uw[0] = op(env, s2->ud[0]); \
|
||||
r.uw[1] = op(env, s2->ud[1]); \
|
||||
\
|
||||
return r.ud[0]; \
|
||||
}
|
||||
|
||||
IMPL_QPACKED_ENV_CVT_TRUNC(qpfdtois, helper_fdtois)
|
||||
IMPL_QPACKED_ENV_CVT_TRUNC(qpfdtoistr, helper_fdtoistr)
|
||||
IMPL_QPACKED_ENV_CVT_TRUNC(qpidtofs, helper_idtofs)
|
||||
IMPL_QPACKED_ENV_CVT_TRUNC(qpfdtofs, helper_fdtofs)
|
|
@ -0,0 +1,18 @@
|
|||
e2k_ss = ss.source_set()
|
||||
e2k_ss.add(files(
|
||||
'cpu.c',
|
||||
'cpu-dump.c',
|
||||
'gdbstub.c',
|
||||
'helper.c',
|
||||
'helper_aau.c',
|
||||
'helper_fpu.c',
|
||||
'helper_int.c',
|
||||
'helper_sm.c',
|
||||
'helper_vec.c',
|
||||
'translate.c',
|
||||
))
|
||||
|
||||
e2k_softmmu_ss = ss.source_set()
|
||||
|
||||
target_arch += {'e2k': e2k_ss}
|
||||
target_softmmu_arch += {'e2k': e2k_softmmu_ss}
|
|
@ -0,0 +1,7 @@
|
|||
# See docs/devel/tracing.txt for syntax documentation.
|
||||
|
||||
# helper.c
|
||||
mmu_ind(uint64_t reg, uint64_t ret) "MMU reg read 0x%lx -> 0x%lx"
|
||||
mmu_outd(uint64_t reg, uint64_t ret) "MMU reg write 0x%lx <- 0x%lx"
|
||||
ioaddr_in(const char *op, uint64_t reg, uint64_t ret) "MAS_IOADDR %s read 0x%lx -> 0x%lx"
|
||||
ioaddr_out(const char *op, uint64_t reg, uint64_t ret) "MAS_IOADDR %s write 0x%lx <- 0x%lx"
|
|
@ -0,0 +1 @@
|
|||
#include "trace/trace-target_e2k.h"
|
File diff suppressed because it is too large
Load Diff
|
@ -3,6 +3,7 @@ subdir('arm')
|
|||
subdir('avr')
|
||||
subdir('cris')
|
||||
subdir('hexagon')
|
||||
subdir('e2k')
|
||||
subdir('hppa')
|
||||
subdir('i386')
|
||||
subdir('m68k')
|
||||
|
|
|
@ -96,7 +96,9 @@ ifdef CONFIG_USER_ONLY
|
|||
# sub-targets (e.g. ARM & AArch64) then it is up to
|
||||
# $(TARGET_NAME)/Makefile.target to include the common parent
|
||||
# architecture in its VPATH.
|
||||
ifneq ($(CROSS_CC_GUEST_NO_MULTIARCH_TESTS),y)
|
||||
-include $(SRC_PATH)/tests/tcg/multiarch/Makefile.target
|
||||
endif
|
||||
-include $(SRC_PATH)/tests/tcg/$(TARGET_NAME)/Makefile.target
|
||||
|
||||
# Add the common build options
|
||||
|
|
|
@ -48,6 +48,8 @@ fi
|
|||
: ${cross_cc_cflags_aarch64_be="-mbig-endian"}
|
||||
: $(cross_cc_alpha="alpha-linux-gnu-gcc")
|
||||
: ${cross_cc_arm="arm-linux-gnueabihf-gcc"}
|
||||
: ${cross_cc_e2k="e2k-linux-as"} # C compiler isn't public yet
|
||||
: ${cross_cc_e2k_ignore_checks="yes"}
|
||||
: ${cross_cc_cflags_armeb="-mbig-endian"}
|
||||
: ${cross_cc_hexagon="hexagon-unknown-linux-musl-clang"}
|
||||
: ${cross_cc_cflags_hexagon="-mv67 -O2 -static"}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# E2K tests
|
||||
#
|
||||
|
||||
E2K_SRC = $(SRC_PATH)/tests/tcg/e2k
|
||||
E2K_ALL = $(wildcard $(E2K_SRC)/*.s)
|
||||
|
||||
TESTS = $(patsubst $(E2K_SRC)/%.s, %, $(E2K_ALL))
|
||||
VPATH = $(E2K_SRC)
|
||||
|
||||
CROSS = e2k-linux-
|
||||
AS = $(CROSS)as
|
||||
LD = $(CROSS)ld
|
||||
|
||||
ASFLAGS = -mcpu=elbrus-v4 -g -I$(E2K_SRC)
|
||||
LDFLAGS =
|
||||
|
||||
%.o: %.s
|
||||
$(AS) $(ASFLAGS) $< -o $@
|
||||
|
||||
%: %.o
|
||||
$(LD) $(LDFLAGS) $< -o $@
|
|
@ -0,0 +1,123 @@
|
|||
.set SYSCALL32_TRAPNUM, 0x1
|
||||
.set SYSCALL64_TRAPNUM, 0x3
|
||||
|
||||
.set __NR_exit, 0x1
|
||||
.set __NR_write, 0x4
|
||||
|
||||
.macro e2k_syscall_1 trapnum sysnum v1
|
||||
{
|
||||
addd 0x0, \sysnum, %b[0]
|
||||
addd 0x0, \v1, %b[1]
|
||||
sdisp %ctpr1, \trapnum
|
||||
}
|
||||
{
|
||||
call %ctpr1, wbs = 0x4
|
||||
}
|
||||
.endm
|
||||
|
||||
.macro e2k_syscall_2 trapnum sysnum v1 v2
|
||||
{
|
||||
sdisp %ctpr1, \trapnum
|
||||
addd 0x0, \sysnum, %b[0]
|
||||
addd 0x0, \v1, %b[1]
|
||||
addd 0x0, \v2, %b[2]
|
||||
}
|
||||
{
|
||||
call %ctpr1, wbs = 0x4
|
||||
}
|
||||
.endm
|
||||
|
||||
.macro e2k_syscall_3 trapnum sysnum v1 v2 v3
|
||||
{
|
||||
sdisp %ctpr1, \trapnum
|
||||
addd 0x0, \sysnum, %b[0]
|
||||
addd 0x0, \v1, %b[1]
|
||||
addd 0x0, \v2, %b[2]
|
||||
addd 0x0, \v3, %b[3]
|
||||
}
|
||||
{
|
||||
call %ctpr1, wbs = 0x4
|
||||
}
|
||||
.endm
|
||||
|
||||
.macro e2k_syscall_4 trapnum sysnum v1 v2 v3 v4
|
||||
{
|
||||
sdisp %ctpr1, \trapnum
|
||||
addd 0x0, \sysnum, %b[0]
|
||||
addd 0x0, \v1, %b[1]
|
||||
addd 0x0, \v2, %b[2]
|
||||
addd 0x0, \v3, %b[3]
|
||||
addd 0x0, \v4, %b[4]
|
||||
}
|
||||
{
|
||||
call %ctpr1, wbs = 0x4
|
||||
}
|
||||
.endm
|
||||
|
||||
.macro e2k_syscall_5 trapnum sysnum v1 v2 v3 v4 v5
|
||||
{
|
||||
sdisp %ctpr1, \trapnum
|
||||
addd 0x0, \sysnum, %b[0]
|
||||
addd 0x0, \v1, %b[1]
|
||||
addd 0x0, \v2, %b[2]
|
||||
addd 0x0, \v3, %b[3]
|
||||
addd 0x0, \v4, %b[4]
|
||||
addd 0x0, \v5, %b[5]
|
||||
}
|
||||
{
|
||||
call %ctpr1, wbs = 0x4
|
||||
}
|
||||
.endm
|
||||
|
||||
.macro e2k_syscall_6 trapnum sysnum v1 v2 v3 v4 v5 v6
|
||||
{
|
||||
sdisp %ctpr1, \trapnum
|
||||
addd 0x0, \sysnum, %b[0]
|
||||
addd 0x0, \v1, %b[1]
|
||||
addd 0x0, \v2, %b[2]
|
||||
addd 0x0, \v3, %b[3]
|
||||
addd 0x0, \v4, %b[4]
|
||||
addd 0x0, \v5, %b[5]
|
||||
}
|
||||
{
|
||||
addd 0x0, \v6, %b[5]
|
||||
call %ctpr1, wbs = 0x4
|
||||
}
|
||||
.endm
|
||||
|
||||
.macro e2k_syscall_7 trapnum sysnum v1 v2 v3 v4 v5 v6 v7
|
||||
{
|
||||
sdisp %ctpr1, \trapnum
|
||||
addd 0x0, \sysnum, %b[0]
|
||||
addd 0x0, \v1, %b[1]
|
||||
addd 0x0, \v2, %b[2]
|
||||
addd 0x0, \v3, %b[3]
|
||||
addd 0x0, \v4, %b[4]
|
||||
addd 0x0, \v5, %b[5]
|
||||
}
|
||||
{
|
||||
addd 0x0, \v6, %b[6]
|
||||
addd 0x0, \v7, %b[7]
|
||||
call %ctpr1, wbs = 0x4
|
||||
}
|
||||
.endm
|
||||
|
||||
.macro assert op reg1 reg2 counter_reg
|
||||
{
|
||||
\op \reg1, \reg2, %pred0
|
||||
addd 0x0, \counter_reg, %b[0]
|
||||
disp %ctpr1, _test_fail
|
||||
}
|
||||
{
|
||||
addd 0x1, \counter_reg, \counter_reg
|
||||
call %ctpr1, wbs = 0x4 ? ~%pred0
|
||||
}
|
||||
.endm
|
||||
|
||||
_test_fail:
|
||||
{
|
||||
setwd wsz = 0x8, nfx = 0x0, dbl = 0x0
|
||||
setbn rsz = 0x3, rbs = 0x4, rcur = 0x0
|
||||
}
|
||||
e2k_syscall_3 SYSCALL64_TRAPNUM, __NR_write, 0, [ _test_failed_str ], _test_failed_strlen
|
||||
e2k_syscall_1 SYSCALL64_TRAPNUM, __NR_exit, %dr0
|
|
@ -0,0 +1,6 @@
|
|||
_stop:
|
||||
e2k_syscall_1 SYSCALL64_TRAPNUM, __NR_exit, 0
|
||||
|
||||
_test_failed_str:
|
||||
.ascii "TEST FAILED\n\0"
|
||||
.set _test_failed_strlen, . - _test_failed_str
|
|
@ -0,0 +1,23 @@
|
|||
.global _start
|
||||
.include "macros.inc"
|
||||
|
||||
_start:
|
||||
{
|
||||
setwd wsz=0x8, nfx=1
|
||||
setbn rbs=0x4, rsz=0x3, rcur=0
|
||||
}
|
||||
{
|
||||
addd 0x0, 0x0, %r0 ! counter
|
||||
addd 0x2, 0xFFFFFFFFFFFFFFFF, %r1
|
||||
}
|
||||
{
|
||||
addd 0x2, 0x2, %r2
|
||||
adds 0x2, 0x2, %r3
|
||||
adds 0x2, 0xFFFFFFFF, %r4
|
||||
}
|
||||
assert cmpedb, %r1, 0x1, %r0
|
||||
assert cmpedb, %r2, 0x4, %r0
|
||||
assert cmpesb, %r3, 0x4, %r0
|
||||
assert cmpesb, %r4, 0x1, %r0
|
||||
|
||||
.include "macros_end.inc"
|
Loading…
Reference in New Issue