Compare commits

...

1101 Commits

Author SHA1 Message Date
(no author)
2f5ab9e8cd This commit was manufactured by cvs2svn to create tag
'release_0_6_1'.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/tags/release_0_6_1@1149 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 20:52:55 +00:00
bellard
c72a345f5b do not remove docs
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1148 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 20:52:54 +00:00
bellard
102a52e471 FMOD configure options (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1147 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 19:57:29 +00:00
bellard
c76338c34f update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1146 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 19:52:18 +00:00
bellard
bf2b84e4a7 better ctrl-alt handling, at least for SDL/X11
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1145 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 19:46:35 +00:00
bellard
9f059eca52 win32/SDL build fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1144 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 18:59:52 +00:00
bellard
53360e00e2 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1143 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 18:58:40 +00:00
bellard
ef6ff6b71e removed warning
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1142 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 18:58:04 +00:00
bellard
546fa6abd1 vga font change detection
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1141 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 17:52:01 +00:00
bellard
e875c40a15 indent fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1140 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 17:30:35 +00:00
bellard
a98d49b136 Mac OS compile fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1139 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 16:22:05 +00:00
bellard
44a095a77c mmap audio fix (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1138 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 16:02:51 +00:00
bellard
15b6147000 audio fix (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1137 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 16:02:09 +00:00
bellard
9e89a4be8e boot device 'b' is not supported
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1136 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 15:42:27 +00:00
bellard
61a8c4ec3a enter insn fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1135 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 15:39:16 +00:00
bellard
9746b15b4e 'info mem' monitor command fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1134 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-11 18:30:24 +00:00
bellard
7372f88dc1 audio fixes (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1133 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-11 16:55:09 +00:00
bellard
d7382233d8 audio clean up (initial patch by malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1132 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-10 00:16:34 +00:00
bellard
fb065187e4 audio clean up (initial patch by malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1131 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-09 23:09:44 +00:00
bellard
bf71c9d9b6 disabled again register usage for ppc because my previous patch seems still buggy
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1130 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-09 22:12:08 +00:00
bellard
7a987127f4 bit mask conversion fix (Harald Welte
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1129 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-09 22:08:48 +00:00
bellard
e0fe67aa72 enabled DMA
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1128 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-09 22:04:05 +00:00
bellard
f6c958c865 CRTC register write protection fix - line_compare, multi_scan and double_scan fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1127 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-07 22:57:20 +00:00
bellard
9bb34eac8b CRTC register write protection fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1126 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-07 22:54:14 +00:00
bellard
85571bc741 audio merge (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1125 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-07 18:04:02 +00:00
bellard
8f46820d92 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1124 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-07 17:44:42 +00:00
bellard
dbb2c92142 SDL config fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1123 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-24 22:17:47 +00:00
bellard
0d1a29f9fc correct handling of saved host registers
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1122 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-12 22:01:28 +00:00
bellard
b8b5ac6376 do not assume signed char
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1121 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-12 21:52:40 +00:00
bellard
40b6ecc6bc no need to use LARGE translation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1120 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-12 21:50:05 +00:00
bellard
f3ff649d3b openpty fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1119 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-10 18:00:00 +00:00
bellard
953569d21b fdc fix (Mike Nordell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1118 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-10 17:51:13 +00:00
bellard
a0c4cb4a70 sparc fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1117 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-10 17:46:24 +00:00
bellard
188d857911 limited 8 bit support - removed unaligned memory accesses in VGA (initial patch by Johannes Schindelin)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1116 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-10 15:44:19 +00:00
bellard
9bc9d1c75a info version command
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1115 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-10 15:15:51 +00:00
bellard
8926b517e9 faster Cirrus VGA VRAM access
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1114 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-10 15:14:20 +00:00
bellard
6d46bf8ae3 win32 fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1113 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-09 22:57:43 +00:00
bellard
032a8c9e35 help fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1112 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-09 22:56:44 +00:00
bellard
a7dfe172fa IDE standby fix for Linux 2.6 guest - segfault fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1111 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-09 20:27:55 +00:00
bellard
7fe48483cd monitor fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1110 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-09 18:08:01 +00:00
bellard
8e3a9fd280 monitor fixes (Johannes Schindelin)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1109 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-09 17:32:58 +00:00
bellard
d75d9f6be9 SDL Audio support and SB16 fixes (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1108 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-09 17:20:54 +00:00
bellard
769bec7271 IDE fix for NT4 (Ben Pfaf)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1107 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-09 16:48:57 +00:00
bellard
655aa52a90 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1106 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-09 16:48:17 +00:00
bellard
ba6c23778c cmos init for IDE (Ben Pfaf)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1105 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-09 16:47:59 +00:00
bellard
4b19ec0c2b spelling fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1104 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-09 16:44:33 +00:00
bellard
e388818682 BSD getopt fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1103 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-09 16:44:06 +00:00
bellard
02d2c54cd3 windows fixes (Gregory Alexander)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1102 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-07 23:27:35 +00:00
bellard
890fa6bebb floppy fixes (initial patch by Mike Nordell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1101 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-07 23:10:29 +00:00
bellard
a4c4785b93 floppy fix from Volker Ruppert
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1100 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-07 21:27:06 +00:00
bellard
7993f8bc51 sparc merge (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1099 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-04 23:42:21 +00:00
bellard
8d5f07fa3b sparc merge (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1098 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-04 21:23:09 +00:00
bellard
023fcb9507 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1097 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-03 21:48:00 +00:00
bellard
a5ba1ca608 BIOS floppy fix for NT4 (Mike Nordell, Derek Fawcus)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1096 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-03 21:47:33 +00:00
bellard
b769d8fef6 removed access_type hack
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1095 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-03 15:07:13 +00:00
bellard
32ff25bf68 ctrl-alt is the default grab key - reset modifiers when toggling grab state
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1094 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-03 14:33:54 +00:00
bellard
f98593103b update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1093 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-03 14:33:10 +00:00
bellard
30ca2aab8e ne2000 savevm support (Johannes Schindelin)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1092 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-03 13:56:00 +00:00
bellard
8a8a608f6e use memset() (Daniel Egger)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1091 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-03 13:36:49 +00:00
bellard
d63d307f6e -loadvm and -full-screen options
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1090 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-03 13:29:03 +00:00
bellard
487be8a1a7 hack for bootp support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1089 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-03 11:44:41 +00:00
bellard
2518bd0dc2 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1088 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-30 22:35:13 +00:00
bellard
e95c8d51c2 full system SPARC emulation (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1087 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-30 22:22:08 +00:00
bellard
4971b827da pointer arith fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1086 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-30 22:19:55 +00:00
bellard
420557e898 full system SPARC emulation (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1085 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-30 22:13:50 +00:00
bellard
6d5e216de9 SPARC fixes (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1084 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-30 22:04:13 +00:00
bellard
e8af50a30e full system SPARC emulation (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1083 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-30 21:55:55 +00:00
bellard
525d67bcc8 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1082 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-30 18:58:48 +00:00
bellard
d981b88344 give a new address at DHCPREQUEST too (useful if the OS remembers its IP address
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1081 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-30 18:57:28 +00:00
bellard
4a4883b84d update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1080 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-29 22:47:43 +00:00
bellard
16c460b154 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1079 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-29 21:56:51 +00:00
bellard
0ecf89aae3 level triggered IRQ fix (Steve Wormley)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1078 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-29 21:55:52 +00:00
bellard
28d34b8246 zlib.h is an external header
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1077 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-29 21:30:43 +00:00
bellard
3c56521b70 cloop driver (Johannes Schindelin)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1076 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-29 21:29:14 +00:00
bellard
096b7ea42b win32 load_kernel() fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1075 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-29 21:19:16 +00:00
bellard
d5a8f07c52 no data exec support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1074 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-29 21:15:28 +00:00
bellard
345fbaa3ca removed unused prototype
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1073 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-18 19:36:08 +00:00
bellard
1d96905d76 fixed stdio write
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1072 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-18 19:34:39 +00:00
bellard
99679ececc removed warning
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1071 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-18 19:33:56 +00:00
bellard
eb45f5fec4 prototype fixed
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1070 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-18 19:33:09 +00:00
bellard
b86bda5bb1 adde TLB dump
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1069 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-18 19:32:46 +00:00
bellard
e2731add29 fixed block close() method prototype
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1068 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-18 19:32:11 +00:00
bellard
c9a621176e memory leak fix (Juergen Keil)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1067 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-13 21:42:51 +00:00
bellard
cf720db33a uname fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1066 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-13 21:41:39 +00:00
bellard
29e619b1e8 uname + sysctl fix (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1065 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-13 21:41:04 +00:00
bellard
6f28fb86c9 zero file case (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1064 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-13 21:39:32 +00:00
bellard
c94c8d6499 win32 + Mac OS X compile
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1063 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-13 21:37:34 +00:00
bellard
01038d2a76 monitor fix (Derek Fawcus)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1062 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-13 21:36:46 +00:00
bellard
03ffbb69a8 smb config fix for NT
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1061 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-06 00:14:04 +00:00
bellard
a3d4af03bb allow inetd like program exec
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1060 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-05 23:10:26 +00:00
bellard
9d728e8c4e smb support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1059 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-05 23:09:03 +00:00
bellard
36d54d15e1 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1058 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-05 16:04:16 +00:00
bellard
c4dfa5b7be removed duplicated option
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1057 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-29 13:10:18 +00:00
bellard
75c2380584 fixed image creation with base filename
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1056 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-27 21:28:58 +00:00
bellard
7c08dbf325 endianness fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1055 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-25 22:30:56 +00:00
bellard
9bf05444b2 port redirection support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1054 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-25 22:12:49 +00:00
bellard
a3504c87ca removed gettimeofday usage
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1053 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-25 20:55:44 +00:00
bellard
7143c62c95 vmdk 3 fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1052 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-25 20:50:14 +00:00
bellard
4e8b5da233 MULSCC fix (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1051 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-24 22:06:03 +00:00
bellard
c7f746434f TFTP support (Magnus Damm)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1050 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-24 21:57:12 +00:00
bellard
60e336dbb8 serial interrupt fix (Hampa Hug)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1049 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-24 21:55:28 +00:00
bellard
8d11df9e5a multiple serial port support - terminal init fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1048 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-24 21:13:40 +00:00
bellard
05d5818c5c update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1047 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-24 21:12:04 +00:00
bellard
cabf23c380 bound instruction fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1046 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-15 14:51:07 +00:00
bellard
e82d8ade13 fixed bound memory reference
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1045 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-15 14:47:30 +00:00
bellard
d2bfb39ad2 use the kernel sigaction syscall to avoid relying on glibc one
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1044 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-03 22:09:30 +00:00
bellard
3611a29c09 -fno-gcse option for opcodes to use asm macros with gcc >= 3.3 on i386 (Piotr Krysik)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1043 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-03 21:42:45 +00:00
bellard
0f6e3eb211 enabled asm memory helpers
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1042 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-03 21:37:41 +00:00
bellard
57d1a2b62c win32 port
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1041 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-03 21:15:11 +00:00
bellard
d5249393ef 64 bit file I/O by default
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1040 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-03 21:14:23 +00:00
bellard
11c0315f9b update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1039 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-01 22:05:00 +00:00
bellard
a3fb0cf907 removed unneeded tools
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1038 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-01 22:00:34 +00:00
bellard
ea2384d36e new disk image layer
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1037 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-01 21:59:26 +00:00
bellard
e4d4fe3c34 AES crypto support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1036 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-01 21:54:53 +00:00
bellard
5905b2e5fd password input support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1035 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-01 21:53:26 +00:00
bellard
7e2515e87c separated readline from monitor code - added password input support - added output buffer
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1034 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-01 21:52:19 +00:00
bellard
3d2cfdf169 output disassembled code to monitor console
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1033 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-01 21:49:07 +00:00
bellard
6fcfafb742 console focus support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1032 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-01 21:48:30 +00:00
bellard
af8ffdfd2b byte swap functions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1031 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-01 21:48:12 +00:00
bellard
b932caba32 new disk image layer
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1030 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-01 21:46:49 +00:00
bellard
3eb2619fe5 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1029 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-14 19:20:07 +00:00
bellard
3e11db9a0c update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1028 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-14 17:47:14 +00:00
bellard
c6f37d0e4f virtual console
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1027 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-14 17:39:50 +00:00
bellard
a0a821a4c0 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1026 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-14 17:38:57 +00:00
bellard
49b3b9fb1a update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1025 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-14 17:31:32 +00:00
bellard
e7f0ad58c1 virtual console
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1024 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-14 17:28:59 +00:00
bellard
82c643ff50 char device support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1023 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-14 17:28:13 +00:00
bellard
457831f4bc virtual console support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1022 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-14 17:22:33 +00:00
bellard
2571929a77 added qemu_strdup()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1021 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-14 17:21:57 +00:00
bellard
81d0912d2d completion support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1020 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-14 17:21:37 +00:00
bellard
d1d9f42119 compile fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1019 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-14 17:20:55 +00:00
bellard
450e18b8b8 slirp for win32 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1018 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-14 17:20:11 +00:00
bellard
3db38e87a0 virtual console support - slirp for win32 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1017 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-14 17:19:55 +00:00
bellard
379ff53dc9 win32 compile
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1016 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-12 22:33:07 +00:00
bellard
ce93da6ffe win32 compile
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1015 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-12 21:21:31 +00:00
bellard
ee2654ac24 removed unused includes - BSD port
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1014 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-12 21:11:45 +00:00
bellard
354ff22657 avoid warning
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1013 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-12 20:40:05 +00:00
bellard
6b65279459 comment
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1012 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-12 20:33:47 +00:00
bellard
12c28fed49 adb fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1011 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-12 20:26:20 +00:00
bellard
38f0b147a5 fixed ADB error reporting
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1010 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-12 20:16:00 +00:00
bellard
bec9d989db fixed register 0 usage - fixed mouse buttons
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1009 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-12 20:15:26 +00:00
bellard
cab84d9844 Mac OS X port (Pierre d'Herbemont)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1008 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-12 18:51:50 +00:00
bellard
1b039c09fe OS X port
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1007 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-12 18:39:45 +00:00
bellard
fbf59244b8 static build fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1005 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 18:18:19 +00:00
bellard
fa36761d7f ppc bios version 0.3
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1004 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 16:57:29 +00:00
bellard
d08c49aae0 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1003 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 16:40:19 +00:00
bellard
fcc941fe20 added .cvsignore
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1002 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 16:28:35 +00:00
bellard
96bcd4f884 Mac OS X port
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1001 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 16:26:15 +00:00
bellard
e3371e62f3 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1000 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 16:26:02 +00:00
bellard
82eec0a174 Mac OS X port (Pierre d'Herbemont)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@999 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 16:22:18 +00:00
bellard
933dc6ebc4 Mac OS X port
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@998 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 15:33:29 +00:00
bellard
1e6cae953d comment
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@997 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 15:31:19 +00:00
bellard
6d463de2b3 removed stdout reference (not portable)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@996 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 15:28:48 +00:00
bellard
bbbc4663d1 removed unused definitions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@995 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 15:27:59 +00:00
bellard
02e1ec9bc4 Mac OS X port (Pierre d'Herbemont)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@994 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 15:15:39 +00:00
bellard
3df3f6fd7b odd memory access fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@993 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 14:45:19 +00:00
bellard
2c6ab8329e load/save state support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@992 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 13:41:46 +00:00
bellard
675376f2b4 kbd save/restore
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@991 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 13:39:53 +00:00
bellard
15a34c6364 doc update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@990 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-08 21:26:26 +00:00
bellard
1bfe856eb2 Cirrus VGA is the default - 128 MB default memory - 800x600 default PPC resolution
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@989 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-08 21:17:50 +00:00
bellard
7e71f16f9a update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@988 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-08 21:16:21 +00:00
bellard
38a64f9dfe fixed b[l] decoding
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@987 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-07 22:06:01 +00:00
bellard
e02aa6869e suppressed unused function
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@986 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-07 22:04:21 +00:00
bellard
7db4eea691 removed unused code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@985 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-06 20:57:47 +00:00
bellard
b30d4608da 24 bpp fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@984 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-06 01:50:49 +00:00
bellard
81ca79911a 24 bpp mode fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@983 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-06 01:47:47 +00:00
bellard
e58d12ed5b Darwin patch
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@982 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-05 22:13:07 +00:00
bellard
d549f7d98f Darwin patch (initial patch by Pierre d'Herbemont)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@981 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-05 21:47:44 +00:00
bellard
83fb7adf6c Darwin patch (initial patch by Pierre d'Herbemont)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@980 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-05 21:25:26 +00:00
bellard
1d43a71773 forgot fclose()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@979 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-05 21:18:42 +00:00
bellard
ae184e4ab7 dac write index register is r/w - CR1D access fix (Volker Ruppert)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@978 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-26 16:13:19 +00:00
bellard
e6eccb38eb dac write index register is r/w (Volker Ruppert)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@977 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-26 16:12:26 +00:00
bellard
9da9886121 fixed case where ram < 16 MB
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@976 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-26 15:53:17 +00:00
bellard
a1968d7196 RT signal may not be a good idea
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@975 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-25 17:06:27 +00:00
bellard
7f5d44e0ff new Cirrus VGA BIOS from the LGPL'ed VGA BIOS project including VESA support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@974 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-25 15:02:13 +00:00
bellard
acf5feac80 hlt instruction fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@973 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-25 14:58:58 +00:00
bellard
d187d4b218 configure BMDMA
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@972 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-25 14:55:10 +00:00
bellard
9808745072 BMDMA support - CDROM fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@971 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-25 14:54:19 +00:00
bellard
02ba45c536 use RT signal for /dev/rtc - restore stdin flags (Bob Barry) - cpu save fix (Johannes Schindelin)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@970 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-25 14:46:23 +00:00
bellard
107db44327 consider that all archs have SMC (workaround)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@969 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-22 18:48:46 +00:00
bellard
dc5d0b3d1b disable buggy tb_invalidate_page_range()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@968 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-22 18:43:30 +00:00
bellard
7496f5266c cpu_single_env init
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@967 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-22 10:56:50 +00:00
bellard
91d848ebf3 disable PCI device for PMAC
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@966 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 22:46:48 +00:00
bellard
e2733d20b2 ADB fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@965 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 22:46:10 +00:00
bellard
637f6cd735 ppc bios
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@964 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 19:54:47 +00:00
bellard
638260eb8e update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@963 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 19:54:19 +00:00
bellard
30468f786c added PCI bus - added IRQ support for PowerPC bridges - suppressed PREP PCI bios init
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@962 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 19:45:35 +00:00
bellard
46e50e9d58 added PCI bus
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@961 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 19:43:00 +00:00
bellard
7c29d0c0cf dma init fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@960 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:58:50 +00:00
bellard
514fb8c10e removed traces
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@959 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:57:45 +00:00
bellard
53c862a88e endianness fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@958 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:56:45 +00:00
bellard
b6b8bd1819 ppc init fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@957 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:55:53 +00:00
bellard
fd0bbb12c3 cmdline init fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@956 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:53:42 +00:00
bellard
f2aa58c6f4 UniNorth PCI bridge support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@955 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:52:24 +00:00
bellard
611493d966 openpic fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@954 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:50:43 +00:00
bellard
e1bb04f740 memory mapped NVRAM (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@953 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:49:53 +00:00
bellard
1ade1de223 pmac macio based ide support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@952 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:48:36 +00:00
bellard
b0bda528c3 high page register support for PPC PREP
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@951 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:47:42 +00:00
bellard
819e712bfe cuda fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@950 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:47:13 +00:00
bellard
28b9b5af25 ppc update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@949 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:46:35 +00:00
bellard
e9b137c2dd added -g option for OF initial resolution
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@948 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:46:10 +00:00
bellard
95ea3fa19c added open pic for PPC
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@947 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:44:21 +00:00
bellard
7587cf4401 accept bigger PC BIOSes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@946 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 13:43:27 +00:00
bellard
7086749072 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@945 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 13:42:16 +00:00
bellard
63b7e03697 boot to top of 4GB space
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@944 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 13:38:54 +00:00
bellard
678f2df60f update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@943 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 13:12:23 +00:00
bellard
9e57f14d60 added APM support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@942 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 13:06:36 +00:00
bellard
987c1c6921 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@941 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 13:02:46 +00:00
bellard
ffddfee379 added cpu_reset()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@940 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 13:01:25 +00:00
bellard
a2f659ee48 new reset API - shutdown support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@939 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 13:00:26 +00:00
bellard
d7d02e3c3a new reset API
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@938 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 12:58:36 +00:00
bellard
bb0c6722b6 reset and shutdown support - PCI is now the default
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@937 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 12:37:32 +00:00
bellard
979a54fb20 new reset API
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@936 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 12:36:04 +00:00
bellard
e4f9082b9a added system_reset command
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@935 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 12:35:44 +00:00
bellard
d95dc32d13 added cpu_reset()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@934 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 12:35:26 +00:00
bellard
53ad66e8c3 print error messages if boot error
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@933 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-19 17:35:07 +00:00
bellard
eba2af633f buffer overflow fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@932 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-19 17:23:39 +00:00
bellard
95ce326e5b buffer overflow fix - printf format fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@931 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-19 17:22:53 +00:00
bellard
a5448a7de5 sysinfo syscall (Francois Guimond)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@930 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-19 16:59:03 +00:00
bellard
9231944d96 sigset_t endianness fix in signal context
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@929 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-19 16:58:13 +00:00
bellard
d69d1fa01a const fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@928 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-19 16:57:17 +00:00
bellard
05efe46eaa VMware 4 disk images support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@927 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-16 20:34:33 +00:00
bellard
dbda808a4a OpenPIC support (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@926 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-15 21:38:40 +00:00
bellard
a049791855 compile fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@925 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-14 19:33:16 +00:00
bellard
ea1c18022e fixed self modifying code in case of asynchronous interrupt
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@924 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-14 18:56:36 +00:00
bellard
516633dc42 jump to gate fix (aka OS/2 Warp install bug)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@923 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-13 15:20:01 +00:00
bellard
dc196a57e3 fixed 16 bit segment optimisations
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@922 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-13 13:26:14 +00:00
bellard
2a2820560d IDE ATA identify fix (aka FreeBSD 4.10 fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@921 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-12 22:23:16 +00:00
bellard
665656a99b ffree test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@920 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-12 11:38:00 +00:00
bellard
658c8bdadc added ffree - added cpu log option
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@919 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-12 11:35:12 +00:00
bellard
5fef40fb4d added ffree
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@918 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-12 11:34:10 +00:00
bellard
e69390cee7 pattern fill fixes and optimization
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@917 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-09 23:12:09 +00:00
bellard
7f647cf68f IDE1 init fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@916 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-09 21:28:36 +00:00
bellard
a130a41e69 interlace support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@915 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-08 00:59:19 +00:00
bellard
78e127efdb set memory size to 4MB for 5446 - fixed memory size probe (aka Win2000 bug) - fixed interlace support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@914 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-08 00:58:26 +00:00
bellard
ee38b4c813 fixed full screen refresh
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@913 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-08 00:56:42 +00:00
bellard
3440557b6d ioport read command
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@912 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-08 00:55:58 +00:00
bellard
d329a6fb22 audip fixes (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@911 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-07 20:58:31 +00:00
bellard
7ebb5e4139 debug
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@910 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-07 20:51:58 +00:00
bellard
57ccbabecb allow 32 but unaligned access (aka Win PCI network bug - initial patch by Renzo Davoli)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@909 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-07 20:45:42 +00:00
bellard
eb26db16d7 endianness functions for unaligned memory accesses
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@908 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-07 20:43:57 +00:00
bellard
4c8732d71b cirrus blitter fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@907 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-07 19:46:45 +00:00
bellard
1cc98a5f04 hardware cursor depth = 15 fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@906 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-06 16:06:33 +00:00
bellard
de9258a87f specific VGA BIOS for Cirrus VGA Card
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@905 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-06 15:50:03 +00:00
bellard
37f53b4c05 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@904 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-06 15:48:55 +00:00
bellard
a8aa669ba4 generic hardware cursor support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@903 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-06 15:17:19 +00:00
bellard
a5082316e9 hardware cursor support - fill with rop support - color expand and color expand with transparent support - various optimisations
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@902 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-06 15:16:19 +00:00
bellard
20ba3ae101 better to use different ID for ISA and PCI
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@901 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 18:50:58 +00:00
bellard
4c7634bcb3 init VGA with default config
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@900 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 18:49:26 +00:00
bellard
a21ae81d8a change ID to CLGD5446 - added solidfill support - fixed hidden dac access
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@899 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 17:59:37 +00:00
bellard
aeb3c85f59 Cirrus fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@898 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 14:26:11 +00:00
bellard
1f04275ec1 -cirrusvga option
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@897 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 13:46:47 +00:00
bellard
4e3e9d0b4d avoid using anonymous struct extension (not supported by all gcc 3.x)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@896 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 13:18:45 +00:00
bellard
358c640721 host bridge config fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@895 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 12:49:34 +00:00
bellard
e36f36e15f mmio support for vga registers - line offset fix - (aka XFree86 4.3.0 fixes)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@894 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 12:47:01 +00:00
bellard
7b17d41e96 Cirrus VGA display fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@893 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 11:06:28 +00:00
bellard
d6bfa22f72 Cirrus VGA emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@892 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 10:32:30 +00:00
bellard
e6e5ad80d8 Cirrus VGA emulation (initial patch by Suzu - heavily modified for easier merge)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@891 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 10:31:55 +00:00
bellard
798b0c25cc generic VGA API layer
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@890 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 10:30:49 +00:00
bellard
22a56b8a87 sdl keyboard fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@889 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 08:32:36 +00:00
bellard
44bbf73f92 dhcp packet size fix (aka pump fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@888 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-04 15:30:48 +00:00
bellard
00ffa62a91 added some keys
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@887 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-04 13:25:15 +00:00
bellard
de2200d36d fixed window switch - fixed caps lock and num lock - simplified keycodes (initial idea by Mark Jonckheere)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@886 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-04 13:15:06 +00:00
bellard
710c15a2e9 lmsw fix (aka dos4gw bug)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@885 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-04 11:20:49 +00:00
bellard
443f1376bc slirp is enabled by default
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@884 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-04 11:13:20 +00:00
bellard
a3a91a355b sendkey command
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@883 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-04 11:06:21 +00:00
bellard
ab2572d7ea added -fno-strict-aliasing
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@882 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 19:07:57 +00:00
bellard
267002cd28 CUDA + ADB support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@881 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 18:46:20 +00:00
bellard
63066f4f13 hid event handling
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@880 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 18:45:02 +00:00
bellard
caf9a12e9a CUDA + ADB support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@879 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 18:35:40 +00:00
bellard
1f62d9383f fixed PCI config default write permissions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@878 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 16:40:20 +00:00
bellard
7727994d21 support for opaque data on memory I/Os
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@877 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 14:08:36 +00:00
bellard
8a8696a3c4 support for opaque data on memory I/Os - PCI ROM memory support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@876 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 14:06:32 +00:00
bellard
8998028497 -localtime option
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@875 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 14:04:03 +00:00
bellard
a4193c8a4b support for opaque data on memory I/Os
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@874 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 14:01:43 +00:00
bellard
170c6f8705 header fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@873 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 12:53:17 +00:00
bellard
43f493afb4 more accurate emulation (do not depend on localtime() or gmtime()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@872 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 12:51:19 +00:00
bellard
ee22c2f7db -localtime option
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@871 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 12:49:50 +00:00
bellard
be3edd9590 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@870 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 12:48:45 +00:00
bellard
023fe10d24 fnop FPU exception support (aka FreeBSD FPU probe) - sysenter/sysexit support (untested, not enabled in cpuid)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@869 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-29 11:08:52 +00:00
bellard
f66723fab9 put ready it after write command (aka FreeBSD HD access fix) - access 16 mult sector count
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@868 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-29 11:04:25 +00:00
bellard
8cc43feffc compile fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@867 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-26 23:29:15 +00:00
bellard
09a79b4974 partial big endian fixes - change VESA VBE ports for non i386 targets to avoid unaligned accesses
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@866 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-26 22:58:01 +00:00
bellard
642012017c PowerPC prep/chrp/pmac support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@865 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-26 22:55:16 +00:00
bellard
2444ca413b trace fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@864 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-26 22:16:35 +00:00
bellard
77d4bc349a PowerPC prep/chrp/pmac support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@863 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-26 22:13:53 +00:00
bellard
a2a444d6e0 PowerPC merge
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@862 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 22:34:16 +00:00
bellard
4b3686faee PowerPC merge
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@861 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 22:18:12 +00:00
bellard
85c4adf65f PowerPC merge
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@860 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 21:25:39 +00:00
bellard
b69fedff84 PowerPC merge
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@859 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 21:17:08 +00:00
bellard
5fd386f698 PowerPC merge
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@858 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 21:11:22 +00:00
bellard
0ced658970 PowerPC merge
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@857 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 21:06:12 +00:00
bellard
b415a4078d update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@856 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 21:04:06 +00:00
bellard
f18ac341fe cleanup
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@855 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 21:00:55 +00:00
bellard
63ce9e0a42 pci empty device read fix - piix3 ide init
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@854 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 19:12:03 +00:00
bellard
e1c485be84 use PIIX3 like IDE controller
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@853 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 19:10:46 +00:00
bellard
34e538ae5d added PIIX3 like IDE controller - PCI irq generation - SETFEATURES IDE command support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@852 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 19:10:26 +00:00
bellard
9995c51ffd pixx3 ide controller
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@851 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 19:09:22 +00:00
bellard
e58a7c24ac int13 cdrom 32 bit register update fix (aka FreeBSD CDROM boot)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@850 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 16:28:35 +00:00
bellard
777428f2d2 fixed 2.88 MB boot (aka FreeBSD 5.2.1 boot fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@849 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 16:26:20 +00:00
bellard
5b60212f2a typos (Pavel Janik)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@848 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-22 21:41:05 +00:00
bellard
a00bad7ed4 default ram size define (Pavel Janik)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@847 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-22 21:39:06 +00:00
bellard
25b42e9d53 added missing copyright file
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@846 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-22 18:30:22 +00:00
bellard
8d6c7eb896 receive status register support (aka GRUB netboot fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@845 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-22 16:52:29 +00:00
bellard
7bf5be70f7 pci memory mapping fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@844 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-22 16:28:18 +00:00
bellard
fb9f944458 PCI BIOS fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@843 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-22 16:27:00 +00:00
bellard
92e873b996 support for non continuous RAM or ROM
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@842 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-21 14:52:29 +00:00
bellard
9fddaa0c0c PowerPC merge: real time TB and decrementer - faster and simpler exception handling (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@841 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-21 12:59:32 +00:00
bellard
4a0fb71e67 irq statistics code (initial patch by Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@840 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-21 11:39:07 +00:00
bellard
274da6b24b 64 bit fix (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@839 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 21:56:27 +00:00
bellard
15aeac3805 PIC spurious irq support (aka Solaris install bug)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@838 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 16:12:05 +00:00
bellard
28ab0e2edb added cpu_get_tsc()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@837 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 14:02:14 +00:00
bellard
b54ad0498e PIC reset fix (initial patch by Hidemi KAWAI)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@836 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 13:42:52 +00:00
bellard
4399059e4d update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@835 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 13:24:37 +00:00
bellard
43003046cb BSD fix + ppc-softmmu support for win32
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@834 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 13:23:39 +00:00
bellard
d157e205e9 win32 fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@833 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 13:22:36 +00:00
bellard
5f21aef2b0 suppressed unneeded header
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@832 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 13:20:55 +00:00
bellard
829309c70c BSD fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@831 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 13:20:12 +00:00
bellard
c6a1c22ba6 fixed invalid includes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@830 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 13:10:49 +00:00
bellard
b71e95fc2c win32 patch (kazu)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@829 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 13:08:06 +00:00
bellard
04a3b84c83 64 bit support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@828 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:51:57 +00:00
bellard
86e0c04896 info pci command
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@827 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:49:21 +00:00
bellard
5ce276a11a VGA PCI support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@826 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:48:53 +00:00
bellard
5768f5aca6 PCI interrupt support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@825 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:47:45 +00:00
bellard
1078f663ae dummy VGA PCI support - VGA font selection fix (Daniel Serpell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@824 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:46:38 +00:00
bellard
0ac32c8375 PCI interrupt support - PCI BIOS interrupt remapping - more accurate memory mapping - 'info pci' monitor command
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@823 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:45:00 +00:00
bellard
4a9c9687c6 PCI irq support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@822 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:43:25 +00:00
bellard
73c11f630b cleanup
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@821 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:42:19 +00:00
bellard
660de33686 PIIX ELCR register support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@820 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:41:21 +00:00
bellard
69135b5c04 suppressed pci2isa.c
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@819 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:40:26 +00:00
bellard
69b910399a PCI support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@818 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-18 23:05:28 +00:00
bellard
158156d13d -user-net is optional - EAGAIN fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@817 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-17 21:13:42 +00:00
bellard
e63c59cb34 ppc fix (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@816 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-17 21:05:06 +00:00
bellard
13ab5daa86 NVRAM fixes (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@815 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-17 20:21:49 +00:00
bellard
ef792f9ddb added CPU_INTERRUPT_TIMER
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@814 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-17 20:19:32 +00:00
bellard
47cea614a1 vmdk2raw: convert VMware disk images to raw images
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@813 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-17 20:06:42 +00:00
bellard
aedf53821f different serial number for each drive (initial patch by Mike Nordell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@812 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-17 19:56:47 +00:00
bellard
7f5e145212 BSR/BSF 'undefined behaviour' test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@811 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-16 16:02:40 +00:00
bellard
f528bfd45d update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@810 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-16 15:57:26 +00:00
bellard
686f3f266b BSR/BSF undefined behaviour fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@809 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-16 15:56:04 +00:00
bellard
5b1214a48e int15, ah=86 BIOS fix (aka Solaris x86 hardware probe hang up fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@808 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-16 15:52:12 +00:00
bellard
3f433d2c87 int13 CDROM BIOS fix (aka Solaris x86 install CD fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@807 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-16 14:21:17 +00:00
bellard
1a084f3d51 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@806 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-13 22:34:49 +00:00
bellard
cd6f11693a custom option parsing to have same behavior on all OSes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@805 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-13 22:02:20 +00:00
bellard
b939777cec floppy fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@804 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-12 22:07:40 +00:00
bellard
d6b86f4d85 -tun-fd option fix (Renzo Davoli)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@803 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-12 19:59:20 +00:00
bellard
3a1bc175ea allow '-nics 0'
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@802 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-12 19:54:43 +00:00
bellard
db45c29a65 faster I/Os - default 16 bit I/O fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@801 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-12 19:50:26 +00:00
bellard
7d3505c55a bsd port (Markus Niemisto)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@800 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-12 19:32:15 +00:00
bellard
fd872598d8 primitive ioport debug - /dev/rtc fast timer support (needed for better simulation accuracy with Linux 2.4)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@799 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-12 19:11:15 +00:00
bellard
8cd0ac2fe1 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@798 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-12 19:09:16 +00:00
bellard
7efa43875d better packaging support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@797 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-12 18:54:06 +00:00
bellard
44c513c4c9 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@796 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 21:24:35 +00:00
bellard
2ee73ac3a8 division by zero FPU exception support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@795 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 21:08:41 +00:00
bellard
28c3ee3fed cr0.ET fix (Win95 boot fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@794 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 21:05:19 +00:00
bellard
f929aad6e3 MSDOS compatibility mode FPU exception support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@793 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 21:03:41 +00:00
bellard
e309de25a6 SPECIFY command fix (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@792 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 21:01:23 +00:00
bellard
10d315a8f2 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@791 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 21:00:00 +00:00
bellard
2b64948eb5 64 bit fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@790 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 15:27:20 +00:00
bellard
1f50f8d1d4 better install
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@789 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 14:44:43 +00:00
bellard
a1b74fe8fe update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@788 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 13:26:35 +00:00
bellard
ed5fd2cce4 timer for READ_ID (win98 floppy fix) - simpler irq handling
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@787 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 13:14:18 +00:00
bellard
bee3290936 typo
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@786 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-05 18:50:02 +00:00
bellard
beddab753d arm load/store half word fix (Ulrich Hecht)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@785 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-05 18:36:10 +00:00
bellard
512176dbd8 fixed dhcp for windows client
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@784 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-04 03:14:47 +00:00
bellard
fb6cf1d09c fixed floppy reset (aka win98 floppy probe fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@783 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-04 02:04:17 +00:00
bellard
66201e2ddf ide slave fixes (aka Win98 CD-ROM detection fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@782 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-04 01:29:51 +00:00
bellard
ec844b96c0 pit fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@781 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-03 23:18:25 +00:00
bellard
f72e8ff4a6 utime fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@780 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-03 19:23:07 +00:00
bellard
b06eddd39d update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@779 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-29 22:34:24 +00:00
bellard
6f51f6b593 keyboard irq generation fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@778 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-29 22:23:55 +00:00
bellard
0294ffb9c8 disable grab if the window no longer has the focus (Windows case) (Mike Nordell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@777 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-29 22:15:15 +00:00
bellard
d8d8aa4e2c SDL static config fix (Roman Zippel)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@776 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-29 20:14:07 +00:00
bellard
141253b254 Bochs VBE emulation fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@775 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-29 19:21:16 +00:00
bellard
646be93b4c Bochs VBE emulation fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@774 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-28 22:38:47 +00:00
bellard
26aa7d72cc isa memory remapping support (aka PPC PREP VGA support)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@773 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-28 22:26:05 +00:00
bellard
8e9c4afe70 full screen support (initial patch by malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@772 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-28 19:33:40 +00:00
bellard
bbc9d34839 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@771 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 21:15:11 +00:00
bellard
a8c490cda5 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@770 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 20:59:17 +00:00
bellard
4606bb3f06 copyright update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@769 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 20:58:11 +00:00
bellard
aaaa7df625 added temporary option -enable-audio
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@768 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 20:56:53 +00:00
bellard
9d4fb82e3c update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@767 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 20:55:38 +00:00
bellard
9fafc9eaf0 avoid errno variable name
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@766 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 19:50:09 +00:00
bellard
1ef59d0acf ppc fixes (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@765 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 19:48:05 +00:00
bellard
7fd7b91fac amd64 port
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@764 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 19:46:45 +00:00
bellard
d927637dca init dummy net if tun/tap network error
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@763 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 19:44:57 +00:00
bellard
4f2ac23784 amd64 port (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@762 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 19:44:02 +00:00
bellard
f658b4db79 isa bridge endianness fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@761 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 22:10:09 +00:00
bellard
0c4ad8dc2a ide endianness fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@760 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 22:09:16 +00:00
bellard
165c6fc8ce more endianness macros
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@759 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 22:08:49 +00:00
bellard
2e12669a4c consistent use of target_ulong and target_phys_addr_t
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@758 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 21:28:44 +00:00
bellard
52c00a5f15 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@757 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 21:27:03 +00:00
bellard
ab6d960ffa added target_phys_addr_t
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@756 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 21:25:15 +00:00
bellard
fbf9eeb34d added cpu_resume_from_signal() - irq fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@755 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 21:21:33 +00:00
bellard
046d6672e2 avoid unneeded casts
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@754 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 21:15:35 +00:00
bellard
75dfaa1e64 x86-64 port (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@753 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 19:04:19 +00:00
bellard
1115dde719 x86-64 port (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@752 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 18:57:49 +00:00
bellard
57206fd42a more register values in monitor
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@751 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 18:54:52 +00:00
bellard
4c27ba27c5 added 'info pic' - added 16/32 bit x86 instruction dump
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@750 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 18:05:08 +00:00
bellard
ba91cd80d5 fixed very unlikely irq bug
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@749 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 18:03:53 +00:00
bellard
6f1f31c069 ARM cache flush support (untested) - '-d' option fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@748 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 18:00:45 +00:00
bellard
5467a72294 disabled S3 VGA
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@747 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 17:59:00 +00:00
bellard
1b8eb456eb avoid error if too many sectors in non LBA mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@746 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 17:58:25 +00:00
bellard
d720b93d0b precise self modifying code support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@745 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 17:57:43 +00:00
bellard
eeab3a558f dump A20 state
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@744 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 17:56:46 +00:00
bellard
658138bcbc flush insn support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@743 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 17:56:08 +00:00
bellard
1190935d98 precise self modifying code test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@742 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 17:54:32 +00:00
bellard
bfbc9133eb 64 bit seek for win32 (Mike Nordell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@741 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 14:43:10 +00:00
bellard
ad6a4837f8 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@740 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-24 00:16:28 +00:00
bellard
039d3da365 added user mode libqemu usage example
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@739 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-24 00:11:51 +00:00
bellard
a7e61ed446 create slirp directory
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@738 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-22 21:46:47 +00:00
bellard
b5075d29a8 more imul tests
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@737 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-22 21:37:55 +00:00
bellard
91caaa612a update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@736 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-22 21:36:13 +00:00
bellard
d64477afa1 imul imm8 fix - 0x82 opcode support (Hidemi KAWAI)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@735 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-22 21:34:25 +00:00
bellard
f6bac3809f fixed options definition
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@734 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-22 00:35:09 +00:00
bellard
f0cbd3ec9f initial user mode network support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@733 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-22 00:10:48 +00:00
bellard
7c1f25b46a probe static SDL link
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@732 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-22 00:02:08 +00:00
bellard
ee9dbb297d NE2000 fixes for windows (Renzo Davoli)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@731 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-21 23:29:33 +00:00
bellard
c20709aa32 initial user mode network support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@730 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-21 23:27:19 +00:00
bellard
92cb7d5423 NT mouse fix (Mark Jonckheere)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@729 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-16 22:17:49 +00:00
bellard
202a456a2b safer sb16 code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@728 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-16 22:09:02 +00:00
bellard
3294b949eb avoid segfault if transient invalid text resolution
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@727 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-15 22:35:16 +00:00
bellard
2aebb3eb2b blanking support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@726 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-15 22:28:04 +00:00
bellard
95917e3f57 suppressed no longer needed vm86 segment hack (Mike Nordell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@725 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-15 22:13:27 +00:00
bellard
f186904281 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@724 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-12 20:58:23 +00:00
bellard
c5df018e56 ppc: suppressed unneeded globals and headers - added explicit type for ppc nvram
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@723 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-12 20:54:52 +00:00
bellard
a541f297a3 PowerPC system emulation fixes (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@722 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-12 20:39:29 +00:00
bellard
df475d18d8 fixed invalid command test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@721 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-12 19:07:27 +00:00
bellard
2f0c934ef9 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@720 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-11 14:55:01 +00:00
bellard
fd836909df VM86 EIP masking fix (aka NT5 install fix) (Mike Nordell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@719 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-11 14:54:42 +00:00
bellard
289e09e77b fixed keyboard random bug (Mike Nordell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@718 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-10 19:04:48 +00:00
bellard
7ae9862745 ide select logic fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@717 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-07 22:13:51 +00:00
bellard
41b9be476c preserve partition table when using -linux option
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@716 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-07 21:30:08 +00:00
bellard
52302d7274 fix the no device case
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@715 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-07 21:01:17 +00:00
bellard
333190eb97 base memory size in cmos
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@714 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-07 20:51:30 +00:00
bellard
eccabc6ee0 vga 9 pixel wide text char fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@713 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-07 20:31:38 +00:00
bellard
bb058620c3 refuse write accesses in BIOS area (aka EMM386.EXE fix) (Mike Nordell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@712 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-07 20:21:16 +00:00
bellard
9eb153f18f dma clean up - added missing read accesses
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@711 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-06 22:43:01 +00:00
bellard
aaba6c1516 win32: correct keycode remapping
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@710 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-06 19:30:16 +00:00
bellard
38e205a25b win32: do not use all cpu time
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@709 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-06 19:29:17 +00:00
bellard
e1a237441d port 92 access
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@708 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-05 20:26:03 +00:00
bellard
57c3072482 fixing free
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@707 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-04 20:36:29 +00:00
bellard
73332e5ccd qemu fast fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@706 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-04 20:22:28 +00:00
bellard
1f673135ac doc update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@705 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-04 15:21:17 +00:00
bellard
aa455485c9 history support (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@704 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-04 13:07:25 +00:00
bellard
9307c4c1d9 improved monitor: type check, expression evaluator, memory dump, disassembly
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@703 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-04 12:57:25 +00:00
bellard
40c3bac35a win32 port (Kazu)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@702 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-04 12:56:28 +00:00
bellard
6eaee46144 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@701 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-04 12:55:00 +00:00
bellard
0f2f112156 tun-fd fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@700 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-04 09:37:47 +00:00
bellard
4721c45750 UIP update fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@699 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-03 12:27:31 +00:00
bellard
a6e022ad13 fixed SDL probing for cross compilation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@698 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-02 21:55:47 +00:00
bellard
702c651c4a added -macaddr option
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@697 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-02 21:21:32 +00:00
bellard
1154e441aa avoid rounding problems
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@696 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-02 20:58:56 +00:00
bellard
e463b581ea rdtsc fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@695 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-02 20:57:58 +00:00
bellard
11d9f695e7 win32 cross compile fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@694 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-02 20:55:59 +00:00
bellard
0c607d5728 win32 port (initial patch by kazu)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@693 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-31 23:54:52 +00:00
bellard
67b915a5dd win32 port (initial patch by kazu)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@692 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-31 23:37:16 +00:00
bellard
bb27c19087 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@691 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-31 19:05:07 +00:00
bellard
8a7ddc38a6 new timer API - new API to save/restore the virtual machine state
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@690 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-31 19:00:16 +00:00
bellard
b0a21b5334 use new timer API
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@689 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-31 18:58:38 +00:00
bellard
dff38e7b40 more precise RTC emulation (periodic timers + time updates)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@688 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-31 18:57:29 +00:00
bellard
1f1af9fd7f added cpu_get_fp80() and cpu_set_fp80()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@687 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-31 18:56:43 +00:00
bellard
858693c638 moved gdbstub to qemu - new asynchronous gdbstub
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@686 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-31 18:52:07 +00:00
bellard
9b14bb04ca install fix (Rusty Russel)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@685 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-26 22:43:34 +00:00
bellard
c101c49c54 added qemu-mkcow man page
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@684 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-26 22:42:54 +00:00
bellard
4bb2fcc7c9 gcc 2.95.4 compile fix (Petter Reinholdtsen)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@683 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-26 22:38:57 +00:00
bellard
08cea4eef8 fixed ljmp and iret to TSS
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@682 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-26 22:26:53 +00:00
bellard
883da8e219 task switch fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@681 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-24 00:50:26 +00:00
bellard
78ebca6e13 fixed IDE probe
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@680 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-23 22:42:43 +00:00
bellard
5e2a644399 removed most of global context uses - removed unneeded abort() which cause problems during win95 hardware scan
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@679 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-23 22:42:11 +00:00
bellard
11774f549e protected lret x86 'bug' emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@678 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-21 18:28:57 +00:00
bellard
d9d849fc5d update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@677 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-21 17:12:48 +00:00
bellard
e19e89a5d4 more log items
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@676 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-21 17:08:23 +00:00
bellard
f193c7979c do not depend on thunk.h - more log items
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@675 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-21 17:06:25 +00:00
bellard
3035f7ff83 use new directory layout
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@674 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-21 17:02:00 +00:00
bellard
4afa64828b fixed protected lret imm insn (one more OS/2 fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@673 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-20 22:04:16 +00:00
bellard
c45c3d0059 write to both IDE drives - return 0 for not present drives
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@672 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-20 22:01:15 +00:00
bellard
baca51faff updated floppy driver: formatting code, disk geometry auto detect (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@671 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-19 23:05:34 +00:00
bellard
bc51c5c989 initial x86-64 host support (Gwenole Beauchesne)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@670 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-17 23:46:04 +00:00
bellard
5069146392 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@669 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-17 23:44:10 +00:00
bellard
59a983b921 device independent VGA screen dump
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@668 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-17 23:17:16 +00:00
bellard
4e463d8d50 tun-fd option fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@667 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-16 00:02:58 +00:00
bellard
94fe4f9fa3 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@666 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:49:05 +00:00
bellard
0fb48229a7 added qemu_mallocz()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@665 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:48:47 +00:00
bellard
b41a2cd1e4 io port API change
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@664 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:46:48 +00:00
bellard
c4b1fcc0f9 added I/O API - io port API change - added multiple network interface support - redirect serial port to a pseudo terminal if using graphical mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@663 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:44:30 +00:00
bellard
0f35920cd8 io port API change - removed dumb console redraw (not useful)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@662 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:42:10 +00:00
bellard
7d977de7e1 io port API change
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@661 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:41:34 +00:00
bellard
07d898662d added qemu_mallocz()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@660 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:41:12 +00:00
bellard
caed880216 removable device support - io port API change
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@659 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:40:43 +00:00
bellard
b338082b3f remoable device support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@658 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:38:54 +00:00
bellard
9dc39cbae3 added a command line monitor
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@657 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:38:27 +00:00
bellard
80cabfad16 separated more devices from emulator
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@656 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 12:20:30 +00:00
bellard
38ca2abc2e m68k compile fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@655 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-13 18:32:13 +00:00
bellard
73bdea1951 2.6 kernel compile fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@654 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-04 22:50:52 +00:00
bellard
00af2b2680 added cow.h
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@653 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-26 00:20:56 +00:00
bellard
a735aa3139 added precompiled linux boot sector
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@652 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:54:25 +00:00
bellard
6b2b6112f8 more FPU context save tests
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@651 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:34:07 +00:00
bellard
bf08806145 native FPU support in code copy mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@650 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:33:36 +00:00
bellard
f9e92e973f use physical memory access functions for DMA
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@649 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:32:01 +00:00
bellard
8dc75d7535 moved DMA and SB16 outside timer (may break SB16)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@648 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:30:56 +00:00
bellard
03857e318e native FPU support in code copy mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@647 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:26:33 +00:00
bellard
16f62432c4 DMA API change
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@646 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:25:55 +00:00
bellard
8b1f24b090 new physical memory access API (used by DMA accesses)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@645 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:24:38 +00:00
bellard
b448f2f36c new physical memory access API (used by DMA accesses) - code copy FP fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@644 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:24:04 +00:00
bellard
97eb5b14dc native FPU support in code copy mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@643 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:19:55 +00:00
bellard
7eee2a509a CR0.MP/EM/TS support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@642 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:17:58 +00:00
bellard
42c3c0cced native FPU support (disabled)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@641 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:17:25 +00:00
bellard
9588b95a08 CR0.MP/EM/TS support - native fpu support in code copy mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@640 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:15:55 +00:00
bellard
2edcdce334 fpu fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@639 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:15:06 +00:00
bellard
8853f86e1d shm support, more setsockopt and getsockopt calls, fds fix (initial patch by Paul McKerras)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@638 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-22 14:57:26 +00:00
bellard
e374bfa35b shm tests - disabled clone test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@637 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-22 14:54:18 +00:00
bellard
b88e4a9a3b small test optimisations
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@636 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-22 13:41:47 +00:00
bellard
537730b956 zero offset optimisation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@635 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-22 13:40:57 +00:00
bellard
edf779ffcc use kernel like macros for user access (will be useful someday to have a better error checking
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@634 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-22 13:40:13 +00:00
bellard
121061dcdf O_DIRECT compile fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@633 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-22 11:56:01 +00:00
bellard
83d7396850 faster big endian accesses on i386 - big endian ldsw_raw fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@632 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-22 11:53:50 +00:00
bellard
6b2d3e3c96 fixed blr/bctr cases
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@631 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-21 15:41:09 +00:00
bellard
e98a6e40a9 adding direct block chaining support - simplified branch code gen
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@630 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-21 15:35:00 +00:00
bellard
28fbe299c3 lwarx fix (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@629 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-21 14:13:13 +00:00
bellard
297d8e6227 Fix check for lswi (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@628 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-21 14:11:27 +00:00
bellard
004bc62c28 update nip when processing exceptions (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@627 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-21 14:10:04 +00:00
bellard
ed1c0bcb0c use osdep.h
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@626 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 22:17:43 +00:00
bellard
22a46c55e4 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@625 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 22:13:24 +00:00
bellard
ea88812f4f added OS dependent functions (temporary as most functions are generic in fact)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@624 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 22:12:40 +00:00
bellard
58fe2f10f0 experimental code copy support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@623 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 22:11:32 +00:00
bellard
3a1d9b8bbb fixed lea exception
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@622 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 22:10:33 +00:00
bellard
0e4b179d33 experimental code copy support - fixed A20 emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@621 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 22:08:32 +00:00
bellard
77fef8c148 experimental code copy support - added new Linux kernel loader
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@620 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 22:05:46 +00:00
bellard
59817ccb2c use qemu memory allocation - added dirty bit support when using host MMU
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@619 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 22:01:13 +00:00
bellard
bf3e8bf11e experimental code copy support - CPU_INTERRUPT_EXITTB support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@618 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:58:54 +00:00
bellard
9acbed0605 added CPU_INTERRUPT_EXITTB and code_copy_enabled
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@617 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:57:02 +00:00
bellard
cf98951b82 force boot sector feature
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@616 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:56:36 +00:00
bellard
f72b519c86 added osdep.o and nwfpe
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@615 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:55:35 +00:00
bellard
07ce05eaa9 fast Linux boot support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@614 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:55:09 +00:00
bellard
b324e814a9 suppressed unused variables
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@613 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:54:14 +00:00
bellard
c69810559b arm nwfpe support - added code no-code-copy option - __preinit_array_start bug fix (untested)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@612 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:49:03 +00:00
bellard
28c4f361ac arm nwfpe support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@611 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:47:43 +00:00
bellard
3d57da2a70 suppressed dummy FPU ops
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@610 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:47:14 +00:00
bellard
00406dff19 added arm nwfpe support (initial patch by Ulrich Hecht)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@609 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:43:58 +00:00
bellard
69de927c6c arm nwfpe support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@608 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:40:43 +00:00
bellard
72cbca10e1 direct chaining support for SPARC
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@607 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 20:30:05 +00:00
bellard
34f715e754 fixed WP semantics
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@606 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-07 20:42:14 +00:00
bellard
cae61cef89 bochs vbe: virtual screen support and bank switch (untested)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@605 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-06 23:58:08 +00:00
bellard
6411cfb6f3 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@604 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-06 19:57:09 +00:00
bellard
898712a85c sdl_cleanup fix (Martin Garton)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@603 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-06 19:56:42 +00:00
bellard
4fa0f5d292 added bochs VBE support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@602 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-06 19:47:52 +00:00
bellard
1ccde1cb94 added generic physical memory dirty bit support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@601 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-06 19:46:14 +00:00
bellard
ad08132319 added tlb_flush() flags
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@600 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-03 23:39:42 +00:00
bellard
415e561f1d cleanup
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@599 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-03 23:37:12 +00:00
bellard
ee8b7021da temporary interrupt locking fix (need rework)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@598 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-03 23:35:10 +00:00
bellard
625976dac8 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@597 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-03 23:30:47 +00:00
bellard
1ac157da77 more precise TLB invalidation - init cleanup
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@596 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-03 23:28:30 +00:00
bellard
64a595f26a cleanup
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@595 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-03 23:27:13 +00:00
bellard
3ad9a57e4f ide identify fix (initial patch by Jens Axboe)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@594 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-01 17:55:47 +00:00
bellard
7f777bf385 fixed atapi error codes (initial patch by Jens Axboe)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@593 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-01 17:37:48 +00:00
bellard
56bf1d37a0 SEEK_STAT bit ata reset fix (Jens Axboe)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@592 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-01 17:24:11 +00:00
bellard
c92b2e845f vga memory address fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@591 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-27 00:14:11 +00:00
bellard
68e73e391f clean tests dir
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@590 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-25 15:47:27 +00:00
bellard
c0637b3794 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@589 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-25 15:38:01 +00:00
bellard
e98c87213e update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@588 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-25 15:26:12 +00:00
bellard
3d4b4c0f4b update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@587 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-25 15:22:15 +00:00
bellard
8145122b08 correct NT flag behavior - zero ldt task switch bug fix - task switch thru call insn bug fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@586 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 16:27:56 +00:00
bellard
7399c5a9be fixed eflags optimisations with string operation (aka linux 2.6.2rc1 fix) - removed warnings
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@585 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 16:24:06 +00:00
bellard
10f0e412f8 combine PDE and PTE protections as in intel specs - added cpu_get_phys_page_debug()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@584 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 15:29:03 +00:00
bellard
4b7aba5173 correct NT flag behavior
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@583 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 15:27:58 +00:00
bellard
35b66fc4f9 correct target_ulong definition
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@582 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 15:26:06 +00:00
bellard
13eb76e091 virtual memory access for gdbstub
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@581 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 15:23:36 +00:00
bellard
3cf1e035ba added TARGET_LONG_BITS
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@580 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 15:19:09 +00:00
bellard
a6b025d37d added cpu_get_phys_page_debug()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@579 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 15:18:16 +00:00
bellard
edfcbd9937 added cpu_get_phys_page_debug()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@578 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 15:11:05 +00:00
bellard
612b477d48 removed warnings
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@577 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 15:10:18 +00:00
bellard
6c9bf8936a update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@576 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 13:46:56 +00:00
bellard
bb551faa4a increased physical RAM limit to 2047 MB in soft MMU mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@575 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 13:42:26 +00:00
bellard
a136e5a8b1 ATAPI transfer size fix (NetBSD CDROM access fix) - added WIN_CHECKPOWERMODE1 - set error to zero in some cases
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@574 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-22 23:52:27 +00:00
bellard
4796f5e9bc interrupt to conforming segment fix (QNX boot fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@573 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-19 23:46:39 +00:00
bellard
3504fe171b 16 bit DMA fix (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@572 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-19 21:11:02 +00:00
bellard
ab1f142ba0 L4 fix for rep nop (should handle all cases)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@571 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-19 20:31:37 +00:00
bellard
4120b61d00 test at least one invalid lock op code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@570 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-19 20:29:34 +00:00
bellard
7f957d280b PowerPC merge (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@569 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 23:19:48 +00:00
bellard
2be3bc02dd update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@568 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 23:14:25 +00:00
bellard
c27357906a avoid exiting directly if file not found
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@567 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:55:23 +00:00
bellard
985a19d6d1 PowerPC merge (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@566 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:49:57 +00:00
bellard
3f5dcc340c PowerPC merge (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@565 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:44:01 +00:00
bellard
f09936ac82 ARM fcntl flag fixes (Lennert Buytenhek)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@564 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:39:25 +00:00
bellard
d030931173 automatic floppy boot
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@563 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:35:25 +00:00
bellard
825bd5f8e5 temporary gcc 3.3 fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@562 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:25:49 +00:00
bellard
bc0b1dc1eb sb16 patch (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@561 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:19:31 +00:00
bellard
630be16f6c alpha fix (Falk Hueffner)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@560 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:06:47 +00:00
bellard
44a91cae10 suppressed cast to lvalue
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@559 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:05:44 +00:00
bellard
d575b78aab more xadd tests - cmpxchg8b test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@558 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:57:29 +00:00
bellard
6e44ba7fa2 cmos return current date - current irq priority in PIC (L4 Pistachio support) - help fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@557 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:56:49 +00:00
bellard
6986f88c3f cast to return type
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@556 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:53:18 +00:00
bellard
988578886e fixed tlb invalidation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@555 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:52:14 +00:00
bellard
c4c7e3e610 ppc code gen size fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@554 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:50:28 +00:00
bellard
b516f85ca8 simpler second page physical address test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@553 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:50:04 +00:00
bellard
1e4fe7cee2 fixed potential exception pb on cmpxchg
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@552 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:44:40 +00:00
bellard
debf7a7c7e comments fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@551 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:43:36 +00:00
bellard
5a1388b6df xadd fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@550 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:41:29 +00:00
bellard
777aca2fd3 fixed dirty bit support for 4M pages (L4 Pistachio fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@549 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:39:51 +00:00
bellard
69e5bc9068 generate read error if no image (win XP install boot)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@548 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:37:47 +00:00
bellard
c8135d9af6 fixed subtle bug: in some cases PG_DIRTY was not set correctly
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@547 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-13 00:00:25 +00:00
bellard
9e62fd7f26 ppc support (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@546 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-05 22:49:06 +00:00
bellard
8977f3c107 Floppy disk emulation (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@545 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-05 00:09:06 +00:00
bellard
728c9fd5a9 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@544 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-05 00:08:14 +00:00
bellard
bd49793889 use generic GenOpFunc
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@543 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-05 00:06:41 +00:00
bellard
16d17fdb8e debug fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@542 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-05 00:05:50 +00:00
bellard
4487d0ac49 changed cpu_x86_in/out to cpu_in/out
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@541 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-05 00:05:04 +00:00
bellard
7138fcfbf7 use CPUState
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@540 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-05 00:02:28 +00:00
bellard
c45886db19 PowerPC system emulation (Jocelyn Mayer) - PIC poll mode (Jocelyn Mayer) - use CPUState - Floppy support (Jocelyn Mayer) - command line debug (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@539 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-05 00:02:06 +00:00
bellard
ffa65c3b70 fcntl flags convertion (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@538 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:57:22 +00:00
bellard
2d603d2216 PowerPC support - float macros
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@537 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:56:24 +00:00
bellard
61190b14fc PowerPC update (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@536 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:54:31 +00:00
bellard
9886cc165a factorized GenOpFunc
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@535 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:53:54 +00:00
bellard
ce09776be2 PowerPC System emulation (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@534 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:53:18 +00:00
bellard
5be1a8e065 ppc fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@533 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:51:58 +00:00
bellard
09683d3597 changed cpu_x86_in/out to cpu_in/out
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@532 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:49:41 +00:00
bellard
590b7eed18 aalib support with SDL
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@531 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:49:02 +00:00
bellard
af5ad10728 infer access type
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@530 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:28:12 +00:00
bellard
ac9eb0731a suppressed explicit access type and use the exception routine to infer it from the micro operation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@529 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:26:24 +00:00
bellard
9a64fbe4d8 PowerPC system emulation (Jocelyn Mayer) - modified patch to use new TLB api
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@528 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 22:58:38 +00:00
bellard
efe160c502 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@527 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:28:47 +00:00
bellard
dc887a4dae make the bios be a ROM memory - glibc hacks for setvbuf and signals - correct century storage in CMOS emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@526 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:18:57 +00:00
bellard
b9f1950797 hack for target_ulong define
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@525 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:17:13 +00:00
bellard
e16c53fabb assembly soft MMU defines on i386
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@524 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:15:29 +00:00
bellard
8351d2d481 WHEEL defines may not be available in SDL
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@523 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:15:01 +00:00
bellard
08785f48b7 updated so that PPC/ARM/SPARC executables are automatically launched when invoked
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@522 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:12:46 +00:00
bellard
75c6215f98 correct cpu state
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@521 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:08:37 +00:00
bellard
6b136f9e8f CD-ROM detection fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@520 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:08:12 +00:00
bellard
2ddbbd10de (temporary) only physical dump is possible in gdb
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@519 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:07:27 +00:00
bellard
9fa3e85353 new generic TLB support - faster self modifying code support - added ROM memory support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@518 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:06:42 +00:00
bellard
4390df5107 added support for direct patching on i386 host (faster emulation) - increased translation buffer size - added new TLB support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@517 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:03:10 +00:00
bellard
ecd854fdb4 added support for direct patching on i386 host (faster emulation)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@516 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:45:05 +00:00
bellard
513b500f75 include stddef.h for size_t definition
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@515 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:44:08 +00:00
bellard
edf75d592c export more memory defines
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@514 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:43:30 +00:00
bellard
1376847f9f support for new TLB handling
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@513 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:43:01 +00:00
bellard
17348a7f5e waiting for TARGET_HAS_SMC patch
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@512 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:36:11 +00:00
bellard
4f31916ffb added raw/user/kernel memory accesses for shifts/adc/sbb/cmpxchg/push/pop (faster emulation) - make 'call Ev' exception safe - in/out dx fix - PE flag is static
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@511 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:35:00 +00:00
bellard
943144d91a added raw/user/kernel memory accesses (faster emulation)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@510 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:31:11 +00:00
bellard
34e01bbf07 fixed dx based protected in/outs (win98 install) - changed JUMP_TB2 branch number arg
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@509 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:30:14 +00:00
bellard
7f1135b9a4 added stx_T1_A0 micro ops
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@508 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:28:06 +00:00
bellard
f68dd77007 fixed word bit operations with memory offset - suppressed push/pop micro operations
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@507 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:27:42 +00:00
bellard
436d8b892a correct value for ADDSEG is real mode (fixes GRUB boot) - update static protected mode state - use generic tlb_set_page()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@506 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:26:31 +00:00
bellard
dc6f57fd55 debug updates - page_unprotect() is no longer needed in softmmu case
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@505 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:24:35 +00:00
bellard
65262d5738 added PE to static CPU state (avoids flushing translated code when swiching between protected and real mode) - moved memory defs to cpu-all.h
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@504 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:20:53 +00:00
bellard
773b93ee06 signal fix: update the host signal 'signal ignored' state to avoid unexpected -EINTR values (ash fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@503 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:15:59 +00:00
bellard
82c7e2a4c6 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@501 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 16:10:33 +00:00
bellard
546cdbd77d first multi target test (lauches 'ls')
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@500 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 16:08:39 +00:00
bellard
c265508067 more precise PIT gate emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@499 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 16:07:06 +00:00
bellard
dd4e27d810 removed test code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@498 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:58:16 +00:00
bellard
a41bc9af8f explicited S3 specific code - added more debug code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@497 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:55:00 +00:00
bellard
3bfd9da14f termios support for SPARC and PPC
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@496 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:52:31 +00:00
bellard
c573ff6752 stat64 fix - added getpagesize()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@495 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:51:36 +00:00
bellard
060366c5ad SPARC fixes : syscall fixes - added user register window exception support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@494 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:50:01 +00:00
bellard
6da41eafc4 added CPU callbacks
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@493 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:48:38 +00:00
bellard
0124311e00 more generic TLB support - began to fix unlikely interrupt issues
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@492 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:48:17 +00:00
bellard
f515528907 aligned stack on 16 byte boundary - PPC target fixes - SPARC target fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@491 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:46:50 +00:00
bellard
b453b70bd8 sparc fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@490 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:45:21 +00:00
bellard
0ac4bd56a8 float access fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@489 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:44:17 +00:00
bellard
3811a291e2 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@488 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:27:57 +00:00
bellard
3415a4ddb4 invd and wbinvd support - fixed code gen logic for invlpg - simpler exception handling in load_seg()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@487 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:21:33 +00:00
bellard
b7f0f463a5 debug fixes - use more generic TLB mappings
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@486 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:20:25 +00:00
bellard
8e682019e3 correct zero segment values when coming from VM86 mode - cache infos in CPUID - simpler exception handling in load_seg() - validate segments after lret/iret
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@485 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:18:37 +00:00
bellard
cf495bcf9f SPARC fixes: corrected PC/NPC logic (now slower but can be optimized a lot) - fixed flags computations - added register window exceptions support - fixed mul and div - added mulscc - fixed immediate field decoding
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@484 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:01:44 +00:00
bellard
fb0eaffc6d PowerPC fixes (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@483 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 14:57:11 +00:00
bellard
07ad1b93a3 disable keyboard interrupts if keyboard clock disabled (may not be fully correct) - added keyboard ID for extended keyboard
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@482 c046a42c-6fe2-441c-8c8c-71466251a162
2003-12-02 22:18:10 +00:00
bellard
d36cd60e6c P4 style multiplication eflags
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@481 c046a42c-6fe2-441c-8c8c-71466251a162
2003-12-02 22:01:31 +00:00
bellard
5e809a8095 dump irq inhibit flag as it is a part of the cpu state
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@480 c046a42c-6fe2-441c-8c8c-71466251a162
2003-12-02 21:59:21 +00:00
bellard
791c2261d6 more complete eflags testing for multiplication (P4 case only)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@479 c046a42c-6fe2-441c-8c8c-71466251a162
2003-12-02 21:55:34 +00:00
bellard
163a7cb620 imull fix (suggested by Robert J. Harley)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@478 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-30 19:40:08 +00:00
bellard
6bb705711b a20 fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@477 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-23 23:26:39 +00:00
bellard
4136f33c7e fixed eflags IF/IOPL update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@476 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-23 23:09:40 +00:00
bellard
6dca2016fc fixed PPC state reloading
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@475 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-23 17:32:06 +00:00
bellard
678673089d PowerPC target support (Jocelyn Mayer) - added better support for uid16
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@474 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-23 17:05:30 +00:00
bellard
28b6751f30 suppressed use of gen_multi - use intermediate FT0 register for floats - use T0 temporary for fpscr update - use PARAM1 for spr access - added untested single load/store support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@473 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-23 16:58:08 +00:00
bellard
79aceca54a PowerPC support (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@472 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-23 14:55:54 +00:00
bellard
6a8c397deb FTST instruction fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@471 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-22 23:57:34 +00:00
bellard
9cdf757fd5 more fcmovxx tests
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@470 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-19 22:12:47 +00:00
bellard
36bdbe5479 fixed TB linking in case of code invalidation (fixes random segfaults)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@469 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-19 22:12:02 +00:00
bellard
8004340674 added fcmovxx support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@468 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-19 22:09:03 +00:00
bellard
a2cc3b2433 added fcmovxx support (fixes segfaults in some recent linux tools) - fixed irq inhibit logic : the irqs are inhibited only for one instruction after, even if the next one also inhibit irqs - stop translation after irq inhibition stops to give a chance to irqs (fixes install NT kernel startup)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@467 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-19 22:08:13 +00:00
bellard
afa05eb15e always completely redefine the TLB in case of MMU fault
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@466 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-19 22:04:21 +00:00
bellard
de5eaa6452 static config for SDL
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@465 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-16 23:18:17 +00:00
bellard
7517502475 fcmovx support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@464 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-16 20:18:52 +00:00
bellard
8f2b1fb008 more hack for CMOS interruption (enable linux /dev/rtc not to hang) - auto boot on cdrom if only device present
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@463 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-16 19:46:01 +00:00
bellard
891b38e446 more precise stack operations in call/int gates (16 bit wrapping is handled in all cases) - makes all call/int gates operations restartable in case of exception
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@462 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-16 16:06:03 +00:00
bellard
7dea1da4ae quick and dirty CMOS irq emulation (windows install uses it) - emm386 keyboard fix (need a better way...) - better serial emulation (windows install uses it) - LDT and TR caches init fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@461 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-16 15:59:30 +00:00
bellard
4ce900b44c make windows happier
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@460 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-16 15:46:05 +00:00
bellard
f3f2d9be03 call gate fix - verr and verw fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@459 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-13 23:15:36 +00:00
bellard
77729c2445 fixed pop %sp bug
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@458 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-13 23:09:07 +00:00
bellard
d71b9a8b2f fixed lmsw instruction
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@457 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-13 02:48:18 +00:00
bellard
181f1558cd update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@456 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-13 01:47:16 +00:00
bellard
2750332396 Soundblaster 16 support (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@455 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-13 01:46:15 +00:00
bellard
f115e911d7 iret and int fix for vm86 - added undefined instructions for real and vm86 modes - added verr, verrw, arpl - added port io map
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@454 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-13 01:43:28 +00:00
bellard
3ab493de4c added verr, verw, arpl - more precise segment rights checks
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@453 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-13 01:42:19 +00:00
bellard
3e25f9515a io map checks
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@452 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-13 00:13:08 +00:00
bellard
246d897f4c dump more registers
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@451 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-12 23:55:40 +00:00
bellard
7e84c2498f full TSS support - IO map check support - conforming segment check fixes - iret in vm86 mode fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@450 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-12 23:39:19 +00:00
bellard
e670b89e3b added comments and TSS bit
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@449 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-12 23:23:42 +00:00
bellard
bd0d90b21d make Knoppix CD-ROM probe happy
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@448 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-12 22:23:01 +00:00
bellard
1a0636f8d7 new VGA bios
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@447 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-11 14:20:17 +00:00
bellard
2e134c9c55 64-bit multiplication fix (Ulrich Hecht)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@446 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-11 13:55:33 +00:00
bellard
5391d80669 moved IDE driver to ide.c
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@445 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-11 13:48:59 +00:00
bellard
36b486bb74 hardware level IDE CD-ROM emulation - added second IDE interface for up to 4 IDE disks emulation - added -boot command to enable CD boot
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@444 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-11 13:36:08 +00:00
bellard
4ad06a29b2 soft mmu fix (aka debian random seg fault fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@443 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-09 16:58:12 +00:00
bellard
e58143b355 ppc fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@442 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-09 14:42:54 +00:00
bellard
1f5476fcce a20 support - keyboard led fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@441 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-04 23:35:20 +00:00
bellard
461c0471af a20 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@440 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-04 23:34:23 +00:00
bellard
9c3ad57432 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@439 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-04 23:33:13 +00:00
bellard
e748ba4f53 ARM half word load/store fix (Ulrich Hecht)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@438 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-03 22:25:25 +00:00
bellard
b8ed223bfe big endian fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@437 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-30 22:10:22 +00:00
bellard
c970a162e7 temporary hack for PowerPC system emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@436 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-30 01:21:44 +00:00
bellard
c321f67309 enabled system emulator build on PowerPC - increased portability of soft mmu code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@435 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-30 01:18:42 +00:00
bellard
7f7f987341 endianness and portability fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@434 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-30 01:11:23 +00:00
bellard
aebcb60e55 no need for locks in system mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@433 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-30 01:08:17 +00:00
bellard
1a18c71b50 unused functions in system mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@432 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-30 01:07:51 +00:00
bellard
03a6c5103d cannot simply write segment registers in system mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@431 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-30 01:07:22 +00:00
bellard
128b346e0a cmov fix (bug on PowerPC)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@430 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-30 01:05:49 +00:00
bellard
415fa2ea77 soft MMU performance fix (oops)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@429 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-30 00:39:38 +00:00
bellard
9951bf39f9 fixed long double accesses when using soft MMU
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@428 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-28 23:06:17 +00:00
bellard
8948b5d613 fixed ldq() macros
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@427 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-28 23:04:30 +00:00
bellard
5086347239 CONFIG_STATIC patch
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@426 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-28 23:04:01 +00:00
bellard
9d4520d0e0 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@425 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-28 01:38:57 +00:00
bellard
5b9f457a89 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@424 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-28 00:49:54 +00:00
bellard
3a4739d651 static link
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@423 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-28 00:48:22 +00:00
bellard
76b62fd001 added binary archive
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@422 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-28 00:47:44 +00:00
bellard
b1f645758a redhat 9 fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@421 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-28 00:47:19 +00:00
bellard
bc1b050d85 fixed distclean target
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@420 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-28 00:12:52 +00:00
bellard
03d5f74aee update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@419 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-28 00:09:43 +00:00
bellard
9f05cc34df fixed big endian ops
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@418 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-28 00:09:28 +00:00
bellard
285dc330bd update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@417 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 23:58:04 +00:00
bellard
baf8ebf01a fixed virtual memory access
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@416 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 23:57:40 +00:00
bellard
9d16dd550e make cpu test static
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@415 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 23:56:59 +00:00
bellard
78d6da976c license
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@414 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 23:55:20 +00:00
bellard
dd6ee15c37 fixed idt/gdt relocation bug - added support for Redhat kernels
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@413 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 23:36:59 +00:00
bellard
0db634747e qemu with softmmu is now the default executable
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@412 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 21:37:46 +00:00
bellard
6e59c1db89 full soft mmu support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@411 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 21:24:54 +00:00
bellard
61382a500a full softmmu support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@410 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 21:22:23 +00:00
bellard
3a51dee658 disabled signal hacks for softmmu version (qemu should be much more portable now...)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@409 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 21:18:35 +00:00
bellard
cc38b844d7 factorized debug code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@408 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 21:16:14 +00:00
bellard
c6105c0a04 added correct memory access code for system emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@407 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 21:13:58 +00:00
bellard
93a40ea926 fixed mmu fault priviledge logic
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@406 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 21:13:06 +00:00
bellard
db8d746688 comments
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@405 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 21:12:17 +00:00
bellard
997344f303 added i386 user only target
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@404 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 21:10:39 +00:00
bellard
16e9b7de41 filename fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@403 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 21:09:52 +00:00
bellard
3486513433 log activation from gdb - gdb single step support for x86 - stop timer when cpu is being debugged
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@402 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-05 14:28:56 +00:00
bellard
0806e3f66f updated
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@401 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-01 00:15:32 +00:00
bellard
39b4da28b3 bios binary images
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@400 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-01 00:14:04 +00:00
bellard
5a67135a0b automatic man page generation - BIOS installation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@399 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-01 00:13:48 +00:00
bellard
42f1e0e49b tun-fd option support for external tundev config (Rusty Russell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@398 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 22:11:17 +00:00
bellard
27c3f2cb9b buffer overflow fix - handle case where stdin is closed (Rusty Russell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@397 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 21:40:47 +00:00
bellard
a07cf92aed multiscan/doublescan fix (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@396 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 21:29:03 +00:00
bellard
01e3b763a6 removed SIGIOT
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@395 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 21:10:14 +00:00
bellard
0ae04d7367 allow Ctrl-C to be pressed when using gdb stub and SDL
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@394 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 21:09:16 +00:00
bellard
ebc054881f added utime syscall - fixed nanosleep exact behaviour
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@393 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 21:08:41 +00:00
bellard
a20dd508aa simplified invocation - added automatic IDE disk geometry guessing to reuse old disk images directly
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@392 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 21:07:02 +00:00
bellard
6180a1818a new directory structure
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@391 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 21:04:53 +00:00
bellard
d3eead2eec new directory structure
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@390 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 20:59:51 +00:00
bellard
853d6f7a83 sparc support - hack to fix case where real_host_page_size < TARGET_PAGE_SIZE (typically sparc target case)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@389 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 20:58:32 +00:00
bellard
93ac68bca5 sparc emulation target (thanx to Thomas M. Ogrisegg)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@388 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 20:57:29 +00:00
bellard
1e43adfc89 new directory structure - changed naming of qemu and vl
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@387 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 20:54:24 +00:00
bellard
7a3f194486 sparc emulation target (thanx to Thomas M. Ogrisegg)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@386 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 20:36:07 +00:00
bellard
2c0262afa7 new directory structure
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@385 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 20:34:21 +00:00
bellard
196ad10903 portable Linux test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@384 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-28 18:59:32 +00:00
bellard
b7dda06abf Redhat 9 fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@383 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-17 22:57:56 +00:00
bellard
fcf8fcc8e5 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@382 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-17 22:56:56 +00:00
bellard
dbc5594cb6 finished simplifying string operations - correct TF flag handling for string operations and ss loading - simplified basic block exit code generation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@381 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-17 22:56:30 +00:00
bellard
4cbb86e1c4 added JUMP_TB2 for a third basic block exit jump point
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@380 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-17 22:53:29 +00:00
bellard
f513a41a3d finished simplifying string operations
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@379 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-17 22:52:47 +00:00
bellard
c106152d26 added two more jump points
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@378 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-17 22:51:45 +00:00
bellard
facc68be25 removed x86 hacks
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@377 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-17 22:51:18 +00:00
bellard
3ff0631ed9 added linux < 2.4.21 vm86 bug workaround - added extensive TF flag test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@376 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-17 22:49:51 +00:00
bellard
b1ba65744e depth 32 fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@375 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-16 21:47:08 +00:00
bellard
b67d59594e glibc 2.3.x fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@374 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-16 21:46:04 +00:00
bellard
2e255c6b9f faster and more accurate segment handling
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@373 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-21 23:25:21 +00:00
bellard
3f33731662 pop ss, mov ss, x and sti disable irqs for the next instruction - began dispatch optimization by adding new x86 cpu 'hidden' flags
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@372 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-20 23:02:09 +00:00
bellard
d05e66d217 no error code if hardware interrupt
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@371 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-20 21:34:35 +00:00
bellard
2d80ae8987 avoid problems if make clean was not made before updating
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@370 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-11 23:01:33 +00:00
bellard
17383a2a2a gcc 3.x is mandatory now on PowerPC
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@369 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-11 22:28:58 +00:00
bellard
9257a9e49c workaround for gcc 3.3 bug or overoptimisation if a label is not used
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@368 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-11 22:21:18 +00:00
bellard
70a194b930 fixed invalid Linux asm/unistd.h header for PowerPC and gcc 3.3
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@367 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-11 22:20:16 +00:00
bellard
2573109866 pass function name to JMUP_TB()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@366 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-11 22:19:11 +00:00
bellard
9dfa5b421d 64 bit fixes (Falk Hueffner)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@365 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-11 20:35:58 +00:00
bellard
9da8ba18e6 mode X double scan fix (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@364 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-11 20:33:04 +00:00
bellard
76bc683820 updated
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@363 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 23:41:46 +00:00
bellard
3b22c4707d fixed invalid ESP usage (Jon Nall)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@362 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 23:40:50 +00:00
bellard
96e6e05372 fixed invalid code gen
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@361 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 23:39:55 +00:00
bellard
e2222c3924 removed warnings
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@360 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 23:39:03 +00:00
bellard
31e8f3c894 PowerPC fix (Jon Nall)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@359 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 22:52:34 +00:00
bellard
9368caf64d updated
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@358 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 22:15:31 +00:00
bellard
38e584a072 m68k host port (Richard Zidlicky)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@357 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 22:14:22 +00:00
bellard
313aa56710 added VGA emulation - added PS/2 mouse and keyboard emulation - use SDL for VGA display
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@356 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 21:52:11 +00:00
bellard
4cbf74b6b8 soft mmu support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@355 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 21:48:43 +00:00
bellard
33417e7025 soft mmu support - Memory I/O API - synthetize string instructions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@354 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 21:47:01 +00:00
bellard
4021dab059 soft mmu support - moved unrelated code to help2-i386.c - synthetize string instructions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@353 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 21:41:46 +00:00
bellard
626df76abb build all targets at the same time
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@352 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 21:39:31 +00:00
bellard
abcd5da72e use bswap.h
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@351 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 21:38:48 +00:00
bellard
97a847bc03 build all targets at the same time - SDL probe support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@350 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 21:36:04 +00:00
bellard
ab93bbe2ae soft mmu support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@349 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 21:35:13 +00:00
bellard
0f0b726444 SDL support for VGA, keyboard and mouse
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@348 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-09 18:26:36 +00:00
bellard
b92e5a22ec Software MMU support (used for memory mapped devices such as VGA)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@347 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-08 23:58:05 +00:00
bellard
17b0018b42 Full VGA support, including old CGA modes, VGA planar and mode X
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@346 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-08 23:50:57 +00:00
bellard
39cf780327 fixed graphical VGA 16 color mode - fixed 9 pixel wide text mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@345 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-05 23:06:22 +00:00
bellard
e89f66eca9 Hardware level VGA emulation (only text mode is tested)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@344 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-04 23:30:47 +00:00
bellard
b6d78bfa0d correct CPL support (should fix flat real mode support)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@343 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-29 20:53:01 +00:00
bellard
c33a346edf first part of single stepping support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@342 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-29 20:50:33 +00:00
bellard
61a2ad53cb refresh clock dummy emulation (netbsd boot fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@341 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-27 22:19:00 +00:00
bellard
2c1794c42e more generic ljmp and lcall - fixed REPNZ usage for non compare string ops (FreeDos boot loader fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@340 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-27 21:11:27 +00:00
bellard
8a4c1cc411 fixed ss segment load - added ICEBP instruction
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@339 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-26 20:34:00 +00:00
bellard
330d0414a5 keyboard emulation - accepts to boot with Bochs BIOS and LGPL'ed VGA BIOS
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@338 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-26 18:11:40 +00:00
bellard
3802ce26a1 set to protected mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@337 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-26 18:02:28 +00:00
bellard
4abe615b84 removed debug
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@336 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-26 18:01:58 +00:00
bellard
a412ac572f real mode support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@335 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-26 18:01:40 +00:00
bellard
b2b5fb228f popw (%esp) test)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@334 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-26 18:00:58 +00:00
bellard
8f186479e2 real mode support (now boots from BOCHS BIOS and LGPL'ed VGA BIOS)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@333 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-26 17:59:00 +00:00
bellard
4c3a88a284 gdb stub breakpoints support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@332 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-26 12:06:08 +00:00
bellard
d6b4936796 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@331 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-13 22:37:44 +00:00
bellard
9d0fe224f4 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@330 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-13 22:08:50 +00:00
bellard
6e0374f6b5 debug print
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@329 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-13 17:34:37 +00:00
bellard
9e5f5284b3 convert signal numbers
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@328 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-13 17:33:54 +00:00
bellard
c596ed1713 times() fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@327 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-13 17:32:31 +00:00
bellard
91cf4d88fb gcc 3.2.2 bug workaround (RedHat 9 fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@326 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-13 17:31:01 +00:00
bellard
a96fc003bd sparc fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@325 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-13 17:30:15 +00:00
bellard
d44b29c21e address printing fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@324 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-13 17:29:55 +00:00
bellard
070893f425 RedHat 9 fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@323 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-13 17:27:19 +00:00
bellard
9621339dca changed basic block exit generation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@322 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-11 15:17:41 +00:00
bellard
ede28208d8 added nop test for exception
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@321 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-11 14:49:58 +00:00
bellard
7739f36e38 fixed EIP exception bug in case of nop operations (kernel 2.5.74 copy_from_user() bug)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@320 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-11 14:49:22 +00:00
bellard
f8c8799840 added return for ARM case (may be incorrect - need checking)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@319 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-09 19:41:41 +00:00
bellard
43fff2384e ARM signal support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@318 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-09 19:31:39 +00:00
bellard
1b21b62ab4 ARM fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@317 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-09 17:16:27 +00:00
bellard
a1516e92b6 ARM init fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@316 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-09 17:13:37 +00:00
bellard
6fb883e8e3 ARM fix: mmap
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@315 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-09 17:12:39 +00:00
bellard
6e295807ac ARM fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@314 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-09 17:10:32 +00:00
bellard
f2674e31e0 old select support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@313 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-09 12:26:09 +00:00
bellard
4690764bba update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@312 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-07 12:17:46 +00:00
bellard
3c1cf9fa86 dummy rdmsr and wrmsr support - xor reg, reg optimization
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@311 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-07 11:30:47 +00:00
bellard
1f47a9223e added disk image help
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@310 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-06 19:01:55 +00:00
bellard
33e3963e1b added user mode Linux Copy On Write disk image support - added -snapshot support (initial patch by Rusty Russell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@309 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-06 17:15:21 +00:00
bellard
cd4c3e888a added IDE WIN_READ_NATIVE_MAX command (2.5.xx fix) - added support for proper system shutdown
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@308 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-04 14:38:25 +00:00
bellard
7916e2245d allow up to 256 MB of ram
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@307 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-01 16:27:45 +00:00
bellard
abd0aaff03 fixed date storage in CMOS
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@306 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-01 15:07:57 +00:00
bellard
c39d5b78f6 make FPU load exception safe
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@305 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-01 15:07:14 +00:00
bellard
4d40895f2c more accurate bcd convert - fixed FPU exceptions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@304 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-01 15:05:19 +00:00
bellard
e477b8b81b correct eflags evaluation order for all operations - fixed important CPU state restoring bug in some exception cases - disabled unsafe inc flags optimisation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@303 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-30 23:36:57 +00:00
bellard
b118d61e55 added PIC debug
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@302 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-30 23:36:21 +00:00
bellard
2f62b397b5 dummy label to avoid gcc optimisations
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@301 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-30 23:18:59 +00:00
bellard
907a5b2690 fixed invalid irq jump chaining
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@300 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-30 23:18:22 +00:00
bellard
0849bf0821 allow read only images
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@299 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-30 23:17:31 +00:00
bellard
305034817d removed unused assignment
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@298 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-30 23:17:08 +00:00
bellard
ec410fc9ce update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@297 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-30 23:16:33 +00:00
bellard
68a7931591 reduced irq latency
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@296 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-30 13:12:32 +00:00
bellard
c9159e5321 added IDE mult support - reduced irq latency (IDE should have good performances now)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@295 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-30 13:06:39 +00:00
bellard
8c9b861e74 added block.c
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@294 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-30 10:12:19 +00:00
bellard
5797fa5d7e first step to fix precise eflags update in case of exception
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@293 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-30 10:11:50 +00:00
bellard
8ef9a8ece3 added nop operations
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@292 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-30 10:04:47 +00:00
bellard
fc01f7e7f9 IDE emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@291 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-30 10:03:06 +00:00
bellard
3b0dca51b0 gdb stub defines
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@290 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-27 18:52:23 +00:00
bellard
da415d54bf gdb usage information
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@289 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-27 18:50:50 +00:00
bellard
b4608c0455 added gdb support to vl
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@288 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-27 17:34:32 +00:00
bellard
d5a0b50c6f update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@287 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-27 12:02:03 +00:00
bellard
87858c89ca more precise timer emulation - fixed NE2000 probe problems - added VLTMPDIR support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@286 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-27 12:01:39 +00:00
bellard
a6f816d697 fixed endianness (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@285 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-26 17:09:07 +00:00
bellard
0ad041d476 fixed inline pb
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@284 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-25 22:11:41 +00:00
bellard
1eb20527c8 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@283 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-25 16:21:49 +00:00
bellard
e3e86d56c4 gcc3 compile fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@282 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-25 16:21:11 +00:00
bellard
1df912cf9e VL license of the day is MIT/BSD
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@281 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-25 16:20:35 +00:00
bellard
4351832355 added invlpg emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@280 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-25 16:19:50 +00:00
bellard
59faf6d6a6 compile fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@279 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-25 16:18:50 +00:00
bellard
725af7d460 untested RH9 fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@278 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-25 16:18:32 +00:00
bellard
a363e34cc5 fixed VM86 support in Virtual Linux - fixed compilation issues with gcc 2.96 - cpuid returns now pentium pro in order to avoid F00F bug workaround in Linux kernel
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@277 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-25 16:18:05 +00:00
bellard
ea041c0e33 more precise cpu_interrupt()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@276 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-25 16:16:50 +00:00
bellard
83479e770d suppressed ring 0 hacks
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@275 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-25 16:12:37 +00:00
bellard
e2f2289897 arm fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@274 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-25 16:09:48 +00:00
bellard
844c72eccc more compiler tests
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@273 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-25 16:09:14 +00:00
bellard
6b1534cc67 fixed compilation for gcc 2.96 - added QEMU system emulator
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@272 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-25 16:08:39 +00:00
bellard
e8cd23de30 fixed compilation for gcc 2.96
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@271 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-25 16:08:13 +00:00
bellard
7c2d6a781c faster task switch
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@270 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-25 00:08:13 +00:00
bellard
f1510b2cc3 added NE2000 emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@269 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-25 00:07:40 +00:00
bellard
357a94326c added link script for vl
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@268 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-24 14:39:12 +00:00
bellard
0824d6fc67 for hard core developpers only: a new user mode linux project :-)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@267 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-24 13:42:40 +00:00
bellard
6c0372d30b updated
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@266 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-24 13:40:52 +00:00
bellard
92ccca6aa8 declare user mode only simulation for QEMU
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@265 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-24 13:30:31 +00:00
bellard
dd3587f38e iret and popl (%esp) tests
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@264 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-24 13:29:40 +00:00
bellard
7d83131cc5 use inline function
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@263 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-24 13:28:48 +00:00
bellard
66e85a21c7 MMU support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@262 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-24 13:28:12 +00:00
bellard
90a9fdae1f more ring 0 operations
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@261 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-24 13:27:18 +00:00
bellard
3fb2ded1d5 hardware interrupt support - support forfull ring 0 exception simulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@260 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-24 13:22:59 +00:00
bellard
f76af4b3f3 correct restoring of CC_OP in case of exception
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@259 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-24 13:21:23 +00:00
bellard
717fc2ad8d more ring 0 instructions - full x86 MMU emulation based on mmap() syscall - fixed popl (%esp)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@258 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-24 13:20:53 +00:00
bellard
c05bab779e force IOPL=3
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@257 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-21 13:14:43 +00:00
bellard
a52c757c9f fixed case where SS != USER_DS (fixes dosemu DPMI emulation)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@256 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-21 13:14:12 +00:00
bellard
970a87a6bb new segment access
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@255 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-21 13:13:25 +00:00
bellard
d8bc1fd0ae ring 0 ops
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@254 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-21 13:13:13 +00:00
bellard
7501267e22 cpu_abort()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@253 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-21 13:11:07 +00:00
bellard
13b55754af ring 0 data structures
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@252 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-21 13:09:53 +00:00
bellard
972ddf7840 added cpu_abort()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@251 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-21 13:08:39 +00:00
bellard
322d0c6657 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@250 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-15 23:29:28 +00:00
bellard
2054396a04 fixed include macro pb
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@249 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-15 23:28:43 +00:00
bellard
039de852ec fixed op_label computation on ppc
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@248 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-15 22:50:44 +00:00
bellard
144c345daf consistent hello naming
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@247 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-15 20:42:31 +00:00
bellard
de83cd02e0 arm emulation support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@246 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-15 20:25:43 +00:00
bellard
6380ab5e26 added missing link scripts
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@245 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-15 20:25:04 +00:00
bellard
b346ff468e ARM emulation support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@244 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-15 20:05:50 +00:00
bellard
5a9fdfec7e factorized cpu defines
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@243 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-15 20:02:25 +00:00
bellard
d19893dab5 extracted generic code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@242 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-15 19:58:51 +00:00
bellard
2521d69883 factorized more definitions - suppressed broken sound ioctls
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@241 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-15 19:58:13 +00:00
bellard
2ab83ea784 automatic ioctl number conversion - minimum ARM fork() support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@240 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-15 19:56:46 +00:00
bellard
2437490100 fixed serious ioctl parameter conversion issue - exported type size and align functions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@239 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-15 19:52:54 +00:00
bellard
e4533c7a8c main cpu loop is target independent
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@238 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-15 19:51:39 +00:00
bellard
1e5ffbedde fixed float to int overflow bug - added ARM host correct roundings for float rounding
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@237 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-15 19:49:16 +00:00
bellard
79638566e5 moved dyngen generic code to dyngen-exec.h
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@236 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-15 19:46:57 +00:00
bellard
03daf0e361 moved cache flush to dyngen header
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@235 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-15 19:45:20 +00:00
bellard
d219f7e7ed output gen_op_xxx() in a separate file
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@234 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-15 19:44:49 +00:00
bellard
95cbfc643d changed disas() prototype for multi target support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@233 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-15 19:44:10 +00:00
bellard
5898e81684 ARM emulation support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@232 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-15 19:42:24 +00:00
bellard
394411ac74 added hello world for ARM
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@231 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-15 19:37:07 +00:00
bellard
ea76864009 more precise float rounding tests
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@230 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-15 19:36:33 +00:00
bellard
43ce4dfe9e added static build option
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@229 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-09 19:53:12 +00:00
bellard
ebc06f87ca alpha fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@228 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-09 19:46:12 +00:00
bellard
5bbe92995c disas endian fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@227 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-09 19:38:38 +00:00
bellard
411bffc41c update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@226 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-09 15:38:23 +00:00
bellard
ff1f20a3ee arm support - suppressed possibly unsafe sparc nop deletion
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@225 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-09 15:34:19 +00:00
bellard
9c5d1246c7 use -mflat for helper-i386.c on sparc - use custom ld script on sparc to free zero memory addresses for vm86 emulation - arm support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@224 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-09 15:33:05 +00:00
bellard
8dd7cb0621 moved to disas.c
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@223 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-09 15:31:02 +00:00
bellard
d30329297b removed unused dependancy if non x86
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@222 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-09 15:30:37 +00:00
bellard
a95c67907c arm support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@221 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-09 15:29:55 +00:00
bellard
0f533160c7 removed unused code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@220 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-09 15:29:20 +00:00
bellard
e163bca720 weird arm double format support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@219 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-09 15:28:45 +00:00
bellard
8c6939c0b0 arm support - modified sparc to work with direct chaining
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@218 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-09 15:28:00 +00:00
bellard
2d0e9143e2 more code moved to helpers - sipmplified x86 float constants definitions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@217 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-09 15:25:54 +00:00
bellard
87f4827e1d more code moved to helpers
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@216 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-09 15:24:58 +00:00
bellard
4a585ccb2f avoid unaligned file offset in anonymous mapping
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@215 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-09 15:24:18 +00:00
bellard
aa0aa4fa31 added ARM and Sparc disassemblers
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@214 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-09 15:23:31 +00:00
bellard
84fa15d854 big endian/unaligned fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@213 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-09 15:20:55 +00:00
bellard
4add45b4f6 getdents for 64 bit cpus
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@212 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-05 01:52:59 +00:00
bellard
4f101ad7ff 64 bit fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@211 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-05 01:52:19 +00:00
bellard
c1db2eb8c3 tested tools
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@210 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-05 01:05:11 +00:00
bellard
82d19dafe4 added helper-i386.c - alpha fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@209 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-05 00:58:28 +00:00
bellard
5286db75a8 convert mmap flags (alpha fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@208 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-05 00:57:30 +00:00
bellard
917f95fd4d alpha fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@207 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-05 00:56:37 +00:00
bellard
fe31975692 fixed __op_label handling if RELA relocations are used
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@206 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-05 00:56:05 +00:00
bellard
95f7652d65 use 32 bit pointer for tb_next even on 64 bit archs
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@205 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-05 00:54:44 +00:00
bellard
3ec9c4fcc6 separated helpers from micro operations
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@204 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-05 00:54:09 +00:00
bellard
2f87c60799 Alpha update (Falk Hueffner)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@203 c046a42c-6fe2-441c-8c8c-71466251a162
2003-06-02 20:38:09 +00:00
bellard
03bfca946a more FPU tests
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@202 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-29 20:06:57 +00:00
bellard
ed2dcdf68e save FPU state in signal handler
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@201 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-29 20:06:27 +00:00
bellard
4304763ba2 misplaced #endif
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@200 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-29 20:05:35 +00:00
bellard
c1e42a1397 search data in both .data and .sdata
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@199 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-29 20:05:18 +00:00
bellard
d0a1ffc957 added fsave/frstor/fstenv/fldenv/fcomi - fixed cpuid - make lret/iret restartable
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@198 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-29 20:04:28 +00:00
bellard
df0f11a03b update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@197 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-28 00:27:57 +00:00
bellard
2d92f0b8f0 autogen opc-i386.h
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@196 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-28 00:24:44 +00:00
bellard
aad13cd131 segment defines
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@195 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-27 23:30:06 +00:00
bellard
a513fe19ac precise exceptions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@194 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-27 23:29:48 +00:00
bellard
f4beb510a4 precise exceptions - more accurate interrupt semantics
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@193 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-27 23:28:08 +00:00
bellard
d731dae8e3 currently generated
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@192 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-27 23:26:25 +00:00
bellard
c9087c2a60 cr2 update (dosemu VGA support fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@191 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-27 23:25:41 +00:00
bellard
14ae3ba7f9 mmap2 fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@190 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-27 23:25:06 +00:00
bellard
5a91de8c90 precise exception support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@189 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-27 23:24:27 +00:00
bellard
e3b32540df more exception tests - support for precise exceptions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@188 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-27 23:23:22 +00:00
bellard
a37904dd86 fwait fix (aka DOS Navigator fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@187 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-25 23:10:30 +00:00
bellard
cf25629d1e more efficient locking
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@186 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-25 19:20:31 +00:00
bellard
0ca790b92e direct chaining for PowerPC and i386
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@185 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-25 16:51:57 +00:00
bellard
d1fe2b2459 self modifying code also tests translation block chaining invalidation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@184 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-25 16:47:16 +00:00
bellard
d4e8164f7e direct chaining for PowerPC and i386
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@183 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-25 16:46:15 +00:00
bellard
08351fb37a fixed cast
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@182 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-25 16:42:20 +00:00
bellard
85e53d4108 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@181 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-25 16:41:52 +00:00
bellard
aa05ae6fec added exec.h
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@180 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-25 16:41:18 +00:00
bellard
1565b7bcd7 fixed page_unprotect() if host_page_size > TARGET_PAGE_SIZE
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@179 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-16 16:07:10 +00:00
bellard
b409186b8d added getrusage
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@178 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-16 15:39:34 +00:00
bellard
418a97afa1 fixed 32 bit popf/iret emulation in vm86 mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@177 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-16 15:12:51 +00:00
bellard
5132455efe test-i386 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@176 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-16 13:58:37 +00:00
bellard
c0ad5542a8 fixed popf TF flag bug (should never hapen in user code except in test-i386!)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@175 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-16 13:46:28 +00:00
bellard
3a27ad0b57 added vm86, exceptions and self modifying regression tests
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@174 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-16 13:43:31 +00:00
bellard
2b413144dc cosmetics
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@173 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-14 23:01:10 +00:00
bellard
3ebcc707d2 removed invalid eip update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@172 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-14 22:47:15 +00:00
bellard
7775e9ecc2 added do_fcntl()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@171 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-14 22:46:48 +00:00
bellard
03d843ddf2 fixed invalid signal masking
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@170 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-14 22:41:55 +00:00
bellard
eb51d102bb better locks
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@169 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-14 21:51:13 +00:00
bellard
25eb44841e better locking - added PowerPC signal handler (add it for the other archs too because it needed for full exception support)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@168 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-14 21:50:54 +00:00
bellard
b333af0666 removed trace - merged 2.4.20 vm86 patches
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@167 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-14 21:48:51 +00:00
bellard
76c8b7710b file list update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@166 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-14 19:48:46 +00:00
bellard
70e198602b update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@165 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-14 19:02:49 +00:00
bellard
206f0fa759 pread/pwrite syscalls - use page_unprotect_range() in vital cases to avoid problems if the kernel writes data in protected page (needed for self-modifying code support)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@164 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-14 19:01:56 +00:00
bellard
fd6ce8f660 self-modifying code support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@163 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-14 19:00:11 +00:00
bellard
727d01d4f6 return code size
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@162 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-14 18:58:05 +00:00
bellard
ae22853141 Sparc update (David S. Miller)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@161 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-13 18:59:59 +00:00
bellard
d418c81eff fixed small page handling
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@160 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-13 00:57:50 +00:00
bellard
2a29ca73c9 more exception tests
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@159 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-13 00:29:04 +00:00
bellard
54936004fd mmap emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@158 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-13 00:25:15 +00:00
bellard
74c95119f2 Alpha fixes (Falk Hueffner)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@157 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-11 12:27:31 +00:00
bellard
366c1b8bfa warning fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@156 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-11 12:27:02 +00:00
bellard
a993ba85cf alpha disas (Falk Hueffner)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@155 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-11 12:25:45 +00:00
bellard
226c91327d fixed from 2.4.20 kernel
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@154 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-10 21:41:47 +00:00
bellard
b8bf3e3aac eflags fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@153 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-10 21:39:42 +00:00
bellard
288426fe3c added LAR/LSL tests
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@152 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-10 21:39:12 +00:00
bellard
72cc388104 fixed SHL C flag computation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@151 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-10 21:38:19 +00:00
bellard
378180d8dc added LAR/LSL
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@150 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-10 21:37:51 +00:00
bellard
78c34e98cd added LAR/LSL - fixed INT3 and INTO EIP computation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@149 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-10 21:37:05 +00:00
bellard
2792c4f2af added EIP return to INTO - fixed SHL C flag computation - added LAR/LSL
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@148 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-10 21:35:30 +00:00
bellard
447db2139a sigtrap support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@147 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-10 15:10:36 +00:00
bellard
564c8f9978 simplified exception support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@146 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-10 15:10:02 +00:00
bellard
c50c0c3fbf TF flag support - fixed eflags computation before exception
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@145 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-10 15:07:51 +00:00
bellard
cabb4d616d TF flag support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@144 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-10 15:07:00 +00:00
bellard
631271d716 added vm86.c
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@143 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-10 13:14:52 +00:00
bellard
9d27abd94f fixed invalid CPL logic in vm86 mode - use generic CPU dump state function
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@142 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-10 13:13:54 +00:00
bellard
148dfc2a8b fixed GPF generation - fixed 'lret im' instruction (main fix for dosemu) - fixed HLT instruction
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@141 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-10 13:09:33 +00:00
bellard
3acace1333 removed unnecessary VME support - fixed selector GPF exception
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@140 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-10 12:39:11 +00:00
bellard
0221cfcd71 more console ioctls
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@139 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-10 12:38:16 +00:00
bellard
f351077efb added dump function
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@138 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-10 12:37:32 +00:00
bellard
e84be9dbca added vm86.c
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@137 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-10 12:37:12 +00:00
bellard
46ddf5511d vm86 emulation closer to Linux kernel code - added correct IRQ emulation for dosemu
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@136 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-10 12:36:41 +00:00
bellard
89e957e7a2 moved vm86 stuff to vm86.c
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@135 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-10 12:33:15 +00:00
bellard
982b431579 added CPL/IOPL support - fixed subtle inc/dec flag optimisation bug - added HLT instruction
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@134 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-08 15:44:24 +00:00
bellard
bf7c65bdf4 changed I/O function prototype to include emulator state
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@133 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-08 15:42:38 +00:00
bellard
8e5a0667f8 added KDGKBTYPE
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@132 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-08 15:42:10 +00:00
bellard
19b84f3c35 added setgroups and getgroups syscalls
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@131 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-08 15:41:49 +00:00
bellard
08fc60898b more siginfo constants
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@130 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-08 15:41:15 +00:00
bellard
082391983e added op_gpf
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@129 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-08 15:40:45 +00:00
bellard
504e56ebdc more accurate GPF generation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@128 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-08 15:39:48 +00:00
bellard
455b761956 added raise_exception_err()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@127 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-08 15:38:21 +00:00
bellard
b56dad1c7b added raise_exception_err() - added cr2 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@126 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-08 15:38:04 +00:00
bellard
9ba5695ce5 added CPL and IOPL as translation time constants - changed I/O function prototype to include emulator state - added error_code and cr2 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@125 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-08 15:35:34 +00:00
bellard
66099dd9af added trapno and error_code report in ucontext
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@124 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-08 15:34:02 +00:00
bellard
b689bc57d6 more accurate signal handling
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@123 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-08 15:33:33 +00:00
bellard
a69d83b60b systematic exception test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@122 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-08 15:32:33 +00:00
bellard
86840ae241 update (test)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@121 c046a42c-6fe2-441c-8c8c-71466251a162
2003-05-08 15:30:27 +00:00
bellard
3c51961e0e update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@120 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-29 21:34:02 +00:00
bellard
d014c98c8d sparc support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@119 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-29 21:26:53 +00:00
bellard
a98fd896cd target cpu definition
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@118 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-29 21:24:12 +00:00
bellard
d6cdca958e alpha support - ia64 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@117 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-29 21:24:00 +00:00
bellard
efdea7bf19 ia64 support - alpha support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@116 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-29 21:12:28 +00:00
bellard
0d3301964d ia64 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@115 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-29 21:10:09 +00:00
bellard
fe1e3ce3e9 fcntl constants
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@114 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-29 21:09:46 +00:00
bellard
bb326a3749 fix _start routine name
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@113 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-29 21:08:48 +00:00
bellard
27725c1d74 ia64 support - fcntl uses TARGET_ constants
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@112 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-29 21:08:18 +00:00
bellard
e026db5893 alpha support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@111 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-29 21:07:28 +00:00
bellard
43f04c233c alpha support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@110 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-29 20:53:42 +00:00
bellard
a8baa8c555 ia64 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@109 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-29 20:53:31 +00:00
bellard
728584be27 fstat64 fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@108 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-29 20:43:36 +00:00
bellard
b9adb4a6bc PowerPC disas code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@107 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-29 20:41:16 +00:00
bellard
ae48a07313 flock
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@106 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-29 20:41:02 +00:00
bellard
956034d7e5 log fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@105 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-29 20:40:53 +00:00
bellard
6cd9f35b9b update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@104 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-29 20:40:35 +00:00
bellard
689f936f7e symbol fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@103 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-29 20:40:07 +00:00
bellard
6977fbfd8b loglevel export
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@102 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-29 20:39:23 +00:00
bellard
77e4672d8d flock support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@101 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-29 20:39:06 +00:00
bellard
d34720fd7d comment
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@100 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-29 20:37:44 +00:00
bellard
d9c4d1cc1a cleanup
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@99 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-29 20:37:14 +00:00
bellard
f644caa51a update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@98 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-11 01:17:32 +00:00
bellard
1eb87257da update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@97 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-11 01:12:28 +00:00
bellard
32ce63371a path patch
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@96 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-11 00:16:16 +00:00
bellard
ec86b0fb3a stat patches - path patches - added exit_group() syscall
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@95 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-11 00:15:04 +00:00
bellard
1d346ae63a added prefix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@94 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-11 00:14:24 +00:00
bellard
74cd30b811 RH9 fix - path patch
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@93 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-11 00:13:41 +00:00
bellard
7fb9a24e39 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@92 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-11 00:13:04 +00:00
bellard
afeb6ee377 suppressed undefined shldw shrdw
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@91 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-11 00:12:54 +00:00
bellard
f29042b531 TIOCGPTN and TIOCSPTLCK ioctls
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@90 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-10 00:12:45 +00:00
bellard
09bfb054fb first self virtualizable version
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@89 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-10 00:03:40 +00:00
bellard
2677e107e6 warning fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@88 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-10 00:03:27 +00:00
bellard
66cd58461d update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@87 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-10 00:02:58 +00:00
bellard
bb0ebb1f2d ISO C fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@86 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-10 00:02:33 +00:00
bellard
27c75a9a90 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@85 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-07 21:35:21 +00:00
bellard
d0cd3b8d84 64 bit fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@84 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-07 21:35:13 +00:00
bellard
9af9eaaa76 endian fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@83 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-07 21:34:41 +00:00
bellard
8c8f42f76c clock_t fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@82 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-07 21:34:27 +00:00
bellard
51fe68905b powerpc div and rint fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@81 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-07 21:34:14 +00:00
bellard
7fe70ecc56 powerpc fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@80 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-07 21:33:40 +00:00
bellard
d03cda5923 alpha fix - powerpc fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@79 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-07 21:33:21 +00:00
bellard
30ac07d4f0 moved i386 specific stuff outside elf.h
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@78 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-07 21:33:03 +00:00
bellard
8857052055 more cpu support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@77 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-07 21:32:32 +00:00
bellard
ce11fedc6e 64 bit support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@76 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-07 21:32:22 +00:00
bellard
43d4145a98 bfd.h dependancy removed
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@75 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-07 21:31:44 +00:00
bellard
295defa5f1 alpha addition
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@74 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-07 21:31:29 +00:00
bellard
f801f97e04 personality fix - i386 interpreter fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@73 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-07 21:31:06 +00:00
bellard
f48c3dd51a -statis for test-i386
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@72 c046a42c-6fe2-441c-8c8c-71466251a162
2003-04-07 21:30:39 +00:00
bellard
62296fe351 added runcom test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@71 c046a42c-6fe2-441c-8c8c-71466251a162
2003-03-30 21:41:51 +00:00
bellard
32f36bcefc added SIOCATMARK and times() syscall
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@70 c046a42c-6fe2-441c-8c8c-71466251a162
2003-03-30 21:29:48 +00:00
bellard
bc8a22cc30 better vm86 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@69 c046a42c-6fe2-441c-8c8c-71466251a162
2003-03-30 21:02:40 +00:00
bellard
f631ef9bd2 better vm86 support - added iret - fixed push/pop fs/gs
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@68 c046a42c-6fe2-441c-8c8c-71466251a162
2003-03-30 21:01:16 +00:00
bellard
f7341ff400 fixed execve bug
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@67 c046a42c-6fe2-441c-8c8c-71466251a162
2003-03-30 21:00:25 +00:00
bellard
fd429f2f6c update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@66 c046a42c-6fe2-441c-8c8c-71466251a162
2003-03-30 20:59:46 +00:00
bellard
fb3e5849bb s390 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@65 c046a42c-6fe2-441c-8c8c-71466251a162
2003-03-29 17:32:36 +00:00
bellard
7854b05654 endian fixes by Ulrich weigand
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@64 c046a42c-6fe2-441c-8c8c-71466251a162
2003-03-29 17:22:23 +00:00
bellard
500dab07e8 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@63 c046a42c-6fe2-441c-8c8c-71466251a162
2003-03-29 16:58:09 +00:00
bellard
f6630e791b version
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@62 c046a42c-6fe2-441c-8c8c-71466251a162
2003-03-29 16:57:48 +00:00
bellard
168485b75b wine help
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@61 c046a42c-6fe2-441c-8c8c-71466251a162
2003-03-29 16:57:34 +00:00
bellard
5cd4393b14 first vm86 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@60 c046a42c-6fe2-441c-8c8c-71466251a162
2003-03-29 16:54:36 +00:00
bellard
7ed601b782 more syscalls
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@59 c046a42c-6fe2-441c-8c8c-71466251a162
2003-03-29 16:54:05 +00:00
bellard
d1f2367bc0 changed flag names
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@58 c046a42c-6fe2-441c-8c8c-71466251a162
2003-03-29 16:53:34 +00:00
bellard
851e67a1b4 primitive vm86 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@57 c046a42c-6fe2-441c-8c8c-71466251a162
2003-03-29 16:53:14 +00:00
bellard
fc2b4c4879 eflags update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@56 c046a42c-6fe2-441c-8c8c-71466251a162
2003-03-29 16:52:44 +00:00
bellard
9c605cb135 added cmpxchg8b, cpuid, bound, eflags support, vm86 mode, 16bit/override string ops
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@55 c046a42c-6fe2-441c-8c8c-71466251a162
2003-03-29 16:51:35 +00:00
bellard
24f9e90b0e 16bit/override support in string operations
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@54 c046a42c-6fe2-441c-8c8c-71466251a162
2003-03-29 16:50:40 +00:00
bellard
a4a0ffdb2b added cmpxchg8b, cpuid, bound, eflags support, vm86 mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@53 c046a42c-6fe2-441c-8c8c-71466251a162
2003-03-29 16:49:21 +00:00
bellard
0ea00c9a3c added number of arguments
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@52 c046a42c-6fe2-441c-8c8c-71466251a162
2003-03-29 16:47:34 +00:00
bellard
e1d4294a45 more tests
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@51 c046a42c-6fe2-441c-8c8c-71466251a162
2003-03-29 16:45:07 +00:00
bellard
c3c7c29246 added runcom
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@50 c046a42c-6fe2-441c-8c8c-71466251a162
2003-03-29 16:44:42 +00:00
bellard
31bb950be6 xchg lock, xlat instr
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@49 c046a42c-6fe2-441c-8c8c-71466251a162
2003-03-26 22:33:47 +00:00
bellard
8083a3e508 dirent fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@48 c046a42c-6fe2-441c-8c8c-71466251a162
2003-03-24 23:12:16 +00:00
bellard
644c433cb3 ld.so load fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@47 c046a42c-6fe2-441c-8c8c-71466251a162
2003-03-24 23:00:36 +00:00
268 changed files with 127688 additions and 9091 deletions

15
.cvsignore Normal file
View File

@@ -0,0 +1,15 @@
arm-user
config-host.*
dyngen
i386
i386-softmmu
i386-user
ppc-softmmu
ppc-user
qemu-doc.html
qemu-tech.html
qemu.1
qemu.pod
sparc-user
qemu-img
sparc-softmmu

View File

@@ -1,36 +1,14 @@
------------------------------------------------------------------------------
NOTE:
Some code of the Twin package was modified for DOSEMU by the DOSEMU-team.
The original is 'Copyright 1997 Willows Software, Inc.' and generously
was put under the GNU Library General Public License.
( for more information see http://www.willows.com/ )
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
We make use of section 3 of the GNU Library General Public License
('...opt to apply the terms of the ordinary GNU General Public License...'),
because the resulting product is an integrated part of DOSEMU and
can not be considered to be a 'library' in the terms of Library License.
Therefore, the below GNU LIBRARY GENERAL PUBLIC LICENSE applies only to the
_unchanged_ Twin package from Willows. For the DOSEMU-changed parts the normal
GNU GENERAL PUBLIC LICENSE applies. This GPL (file COPYING) can be found in
the root directory of the DOSEMU distribution.
The act of transformation to GPL was indicated to the maintainer of the Twin
package (Rob Penrose <rob@Canopy.Com>) and he acknowledge agreement.
Nov. 1 1997, The DOSEMU team.
------------------------------------------------------------------------------
GNU LIBRARY GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the library GPL. It is
numbered 2 because it goes with version 2 of the ordinary GPL.]
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
@@ -39,97 +17,109 @@ freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Library General Public License, applies to some
specially designated Free Software Foundation software, and to any
other libraries whose authors decide to use it. You can use it for
your libraries, too.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if
you distribute copies of the library, or if you modify it.
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link a program with the library, you must provide
complete object files to the recipients so that they can relink them
with the library, after making changes to the library and recompiling
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
Our method of protecting your rights has two steps: (1) copyright
the library, and (2) offer you this license which gives you legal
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
Also, for each distributor's protection, we want to make certain
that everyone understands that there is no warranty for this free
library. If the library is modified by someone else and passed on, we
want its recipients to know that what they have is not the original
version, so that any problems introduced by others will not reflect on
the original authors' reputations.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that companies distributing free
software will individually obtain patent licenses, thus in effect
transforming the program into proprietary software. To prevent this,
we have made it clear that any patent must be licensed for everyone's
free use or not licensed at all.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the ordinary
GNU General Public License, which was designed for utility programs. This
license, the GNU Library General Public License, applies to certain
designated libraries. This license is quite different from the ordinary
one; be sure to read it in full, and don't assume that anything in it is
the same as in the ordinary license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
The reason we have a separate public license for some libraries is that
they blur the distinction we usually make between modifying or adding to a
program and simply using it. Linking a program with a library, without
changing the library, is in some sense simply using the library, and is
analogous to running a utility program or application program. However, in
a textual and legal sense, the linked executable is a combined work, a
derivative of the original library, and the ordinary General Public License
treats it as such.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
Because of this blurred distinction, using the ordinary General
Public License for libraries did not effectively promote software
sharing, because most developers did not use the libraries. We
concluded that weaker conditions might promote sharing better.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
However, unrestricted linking of non-free programs would deprive the
users of those programs of all benefit from the free status of the
libraries themselves. This Library General Public License is intended to
permit developers of non-free programs to use free libraries, while
preserving your freedom as a user of such programs to change the free
libraries that are incorporated in them. (We have not seen how to achieve
this as regards changes in header files, but we have achieved it as regards
changes in the actual functions of the Library.) The hope is that this
will lead to faster development of free libraries.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, while the latter only
works together with the library.
Note that it is possible for a library to be covered by the ordinary
General Public License rather than by this special one.
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LIBRARY GENERAL PUBLIC LICENSE
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library which
contains a notice placed by the copyright holder or other authorized
party saying it may be distributed under the terms of this Library
General Public License (also called "this License"). Each licensee is
addressed as "you".
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
@@ -278,7 +268,7 @@ distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also compile or
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
@@ -305,23 +295,31 @@ of these things:
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Accompany the work with a written offer, valid for at
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
c) If distribution of the work is made by offering access to copy
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
d) Verify that the user has already received a copy of these
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the source code distributed need not include anything that is normally
distributed (in either source or binary form) with the major
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
@@ -370,7 +368,7 @@ Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
@@ -413,7 +411,7 @@ excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Library General Public License from time to time.
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
@@ -459,7 +457,7 @@ DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Libraries
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
@@ -476,18 +474,18 @@ convey the exclusion of warranty; and each file should have at least the
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
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
Library General Public License for more details.
Lesser General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
@@ -502,3 +500,5 @@ necessary. Here is a sample; alter the names:
Ty Coon, President of Vice
That's all there is to it!

286
Changelog
View File

@@ -1,8 +1,294 @@
version 0.6.1:
- Mac OS X port (Pierre d'Herbemont)
- Virtual console support
- Better monitor line edition
- New block device layer
- New 'qcow' growable disk image support with AES encryption and
transparent decompression
- VMware 3 and 4 read-only disk image support (untested)
- Support for up to 4 serial ports
- TFTP server support (Magnus Damm)
- Port redirection support in user mode networking
- Support for not executable data sections
- Compressed loop disk image support (Johannes Schindelin)
- Level triggered IRQ fix (aka NE2000 PCI performance fix) (Steve
Wormley)
- Fixed Fedora Core 2 problems (now you can run qemu without any
LD_ASSUME_KERNEL tricks on FC2)
- DHCP fix for Windows (accept DHCPREQUEST alone)
- SPARC system emulation (Blue Swirl)
- Automatic Samba configuration for host file access from Windows.
- '-loadvm' and '-full-screen' options
- ne2000 savevm support (Johannes Schindelin)
- Ctrl-Alt is now the default grab key. Ctrl-Alt-[0-9] switches to
the virtual consoles.
- BIOS floppy fix for NT4 (Mike Nordell, Derek Fawcus, Volker Ruppert)
- Floppy fixes for NT4 and NT5 (Mike Nordell)
- NT4 IDE fixes (Ben Pfaf, Mike Nordell)
- SDL Audio support and SB16 fixes (malc)
- ENTER instruction bug fix (initial patch by Stefan Kisdaroczi)
- VGA font change fix
- VGA read-only CRTC register fix
version 0.6.0:
- minimalist FPU exception support (NetBSD FPU probe fix)
- cr0.ET fix (Win95 boot)
- *BSD port (Markus Niemisto)
- I/O access fix (signaled by Mark Jonckheere)
- IDE drives serial number fix (Mike Nordell)
- int13 CDROM BIOS fix (aka Solaris x86 install CD fix)
- int15, ah=86 BIOS fix (aka Solaris x86 hardware probe hang up fix)
- BSR/BSF "undefined behaviour" fix
- vmdk2raw: convert VMware disk images to raw images
- PCI support
- NE2K PCI support
- dummy VGA PCI support
- VGA font selection fix (Daniel Serpell)
- PIC reset fix (Hidemi KAWAI)
- PIC spurious irq support (aka Solaris install bug)
- added '-localtime' option
- Cirrus CL-GD54xx VGA support (initial patch by Makoto Suzuki (suzu))
- APM and system shutdown support
- Fixed system reset
- Support for other PC BIOSes
- Initial PowerMac hardware emulation
- PowerMac/PREP OpenFirmware compatible BIOS (Jocelyn Mayer)
- initial IDE BMDMA support (needed for Darwin x86)
- Set the default memory size for PC emulation to 128 MB
version 0.5.5:
- SDL full screen support (initial patch by malc)
- VGA support on PowerPC PREP
- VBE fixes (Matthew Mastracci)
- PIT fixes (aka Win98 hardware probe and "VGA slowness" bug)
- IDE master only fixes (aka Win98 CD-ROM probe bug)
- ARM load/store half word fix (Ulrich Hecht)
- FDC fixes for Win98
version 0.5.4:
- qemu-fast fixes
- BIOS area protection fix (aka EMM386.EXE fix) (Mike Nordell)
- keyboard/mouse fix (Mike Nordell)
- IDE fixes (Linux did not recognized slave drivers)
- VM86 EIP masking fix (aka NT5 install fix) (Mike Nordell)
- QEMU can now boot a PowerPC Linux kernel (Jocelyn Mayer)
- User mode network stack
- imul imm8 fix + 0x82 opcode support (Hidemi KAWAI)
- precise self modifying code (aka BeOS install bug)
version 0.5.3:
- added Bochs VESA VBE support
- VGA memory map mode 3 access fix (OS/2 install fix)
- IDE fixes (Jens Axboe)
- CPU interrupt fixes
- fixed various TLB invalidation cases (NT install)
- fixed cr0.WP semantics (XP install)
- direct chaining support for SPARC and PowerPC (faster)
- ARM NWFPE support (initial patch by Ulrich Hecht)
- added specific x86 to x86 translator (close to native performance
in qemu-i386 and qemu-fast)
- shm syscalls support (Paul McKerras)
- added accurate CR0.MP/ME/TS emulation
- fixed DMA memory write access (Win95 boot floppy fix)
- graphical x86 linux loader
- command line monitor
- generic removable device support
- support of CD-ROM change
- multiple network interface support
- initial x86-64 host support (Gwenole Beauchesne)
- lret to outer priviledge fix (OS/2 install fix)
- task switch fixes (SkyOS boot)
- VM save/restore commands
- new timer API
- more precise RTC emulation (periodic timers + time updates)
- Win32 port (initial patch by Kazu)
version 0.5.2:
- improved soft MMU speed (assembly functions and specializing)
- improved multitasking speed by avoiding flushing TBs when
switching tasks
- improved qemu-fast speed
- improved self modifying code handling (big performance gain in
softmmu mode).
- fixed IO checking
- fixed CD-ROM detection (win98 install CD)
- fixed addseg real mode bug (GRUB boot fix)
- added ROM memory support (win98 boot)
- fixed 'call Ev' in case of paging exception
- updated the script 'qemu-binfmt-conf.sh' to use QEMU automagically
when launching executables for the supported target CPUs.
- PowerPC system emulation update (Jocelyn Mayer)
- PC floppy emulation and DMA fixes (Jocelyn Mayer)
- polled mode for PIC (Jocelyn Mayer)
- fixed PTE dirty bit handling
- fixed xadd same reg bug
- fixed cmpxchg exception safeness
- access to virtual memory in gdb stub
- task gate and NT flag fixes
- eflags optimisation fix for string operations
version 0.5.1:
- float access fixes when using soft mmu
- PC emulation support on PowerPC
- A20 support
- IDE CD-ROM emulation
- ARM fixes (Ulrich Hecht)
- SB16 emulation (malc)
- IRET and INT fixes in VM86 mode with IOPL=3
- Port I/Os use TSS io map
- Full task switching/task gate support
- added verr, verw, arpl, fcmovxx
- PowerPC target support (Jocelyn Mayer)
- Major SPARC target fixes (dynamically linked programs begin to work)
version 0.5.0:
- full hardware level VGA emulation
- graphical display with SDL
- added PS/2 mouse and keyboard emulation
- popw (%esp) fix
- mov to/from segment data width fix
- added real mode support
- added Bochs BIOS and LGPL'ed VGA BIOS loader in qemu
- m68k host port (Richard Zidlicky)
- partial soft MMU support for memory mapped I/Os
- multi-target build
- fixed: no error code in hardware interrupts
- fixed: pop ss, mov ss, x and sti disable hardware irqs for the next insn
- correct single stepping thru string operations
- preliminary SPARC target support (Thomas M. Ogrisegg)
- tun-fd option (Rusty Russell)
- automatic IDE geometry detection
- renamed 'vl' to qemu[-fast] and user qemu to qemu-{cpu}.
- added man page
- added full soft mmu mode to launch unpatched OSes.
version 0.4.3:
- x86 exception fix in case of nop instruction.
- gcc 3.2.2 bug workaround (RedHat 9 fix)
- sparc and Alpha host fixes
- many ARM target fixes: 'ls' and 'bash' can be launched.
version 0.4.2:
- many exception handling fixes (can compile a Linux kernel inside vl)
- IDE emulation support
- initial GDB stub support
- deferred update support for disk images (Rusty Russell)
- accept User Mode Linux Copy On Write disk images
- SMP kernels can at least be booted
version 0.4.1:
- more accurate timer support in vl.
- more reliable NE2000 probe in vl.
- added 2.5.66 kernel in vl-test.
- added VLTMPDIR environment variable in vl.
version 0.4:
- initial support for ring 0 x86 processor emulation
- fixed signal handling for correct dosemu DPMI emulation
- fast x86 MMU emulation with mmap()
- fixed popl (%esp) case
- Linux kernel can be executed by QEMU with the 'vl' command.
version 0.3:
- initial support for ARM emulation
- added fnsave, frstor, fnstenv, fldenv FPU instructions
- added FPU register save in signal emulation
- initial ARM port
- Sparc and Alpha ports work on the regression test
- generic ioctl number conversion
- fixed ioctl type conversion
version 0.2:
- PowerPC disassembly and ELF symbols output (Rusty Russell)
- flock support (Rusty Russell)
- ugetrlimit support (Rusty Russell)
- fstat64 fix (Rusty Russell)
- initial Alpha port (Falk Hueffner)
- initial IA64 port (Matt Wilson)
- initial Sparc and Sparc64 port (David S. Miller)
- added HLT instruction
- LRET instruction fix.
- added GPF generation for I/Os.
- added INT3 and TF flag support.
- SHL instruction C flag fix.
- mmap emulation for host page size > 4KB
- self-modifying code support
- better VM86 support (dosemu works on non trivial programs)
- precise exception support (EIP is computed correctly in most cases)
- more precise LDT/GDT/IDT emulation
- faster segment load in vm86 mode
- direct chaining of basic blocks (faster emulation)
version 0.1.6:
- automatic library search system. QEMU can now work with unpatched
ELF dynamic loader and libc (Rusty Russell).
- ISO C warning fixes (Alistair Strachan)
- first self-virtualizable version (works only as long as the
translation cache is not flushed)
- RH9 fixes
version 0.1.5:
- ppc64 support + personality() patch (Rusty Russell)
- first Alpha CPU patches (Falk Hueffner)
- removed bfd.h dependancy
- fixed shrd, shld, idivl and divl on PowerPC.
- fixed buggy glibc PowerPC rint() function (test-i386 passes now on PowerPC).
version 0.1.4:
- more accurate VM86 emulation (can launch small DOS 16 bit
executables in wine).
- fixed push/pop fs/gs
- added iret instruction.
- added times() syscall and SIOCATMARK ioctl.
version 0.1.3:
- S390 support (Ulrich Weigand)
- glibc 2.3.x compile fix (Ulrich Weigand)
- socketcall endian fix (Ulrich Weigand)
- struct sockaddr endian fix (Ulrich Weigand)
- sendmsg/recvmsg endian fix (Ulrich Weigand)
- execve endian fix (Ulrich Weigand)
- fdset endian fix (Ulrich Weigand)
- partial setsockopt syscall support (Ulrich Weigand)
- more accurate pushf/popf emulation
- first partial vm86() syscall support (can be used with runcom example).
- added bound, cmpxchg8b, cpuid instructions
- added 16 bit addressing support/override for string operations
- poll() fix
version 0.1.2:
- compile fixes
- xlat instruction
- xchg instruction memory lock
- added simple vm86 example (not working with QEMU yet). The 54 byte
DOS executable 'pi_10.com' program was released by Bertram
Felgenhauer (more information at http://www.boo.net/~jasonp/pipage.html).
version 0.1.1:
- glibc 2.2 compilation fixes
- added -s and -L options
- binary distribution of x86 glibc and wine
- big endian fixes in ELF loader and getdents.
version 0.1:

180
Makefile
View File

@@ -1,131 +1,111 @@
include config.mak
-include config-host.mak
CFLAGS=-Wall -O2 -g
CFLAGS=-Wall -O2 -g -fno-strict-aliasing
ifdef CONFIG_DARWIN
CFLAGS+= -mdynamic-no-pic
endif
ifdef CONFIG_WIN32
CFLAGS+=-fpack-struct
endif
LDFLAGS=-g
LIBS=
DEFINES=-DHAVE_BYTESWAP_H
ifeq ($(ARCH),i386)
CFLAGS+=-fomit-frame-pointer
OP_CFLAGS=$(CFLAGS) -mpreferred-stack-boundary=2
ifeq ($(GCC_MAJOR),3)
OP_CFLAGS+= -falign-functions=0
else
OP_CFLAGS+= -malign-functions=0
endif
DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
TOOLS=qemu-img
ifdef CONFIG_STATIC
LDFLAGS+=-static
endif
DOCS=qemu-doc.html qemu-tech.html qemu.1
ifeq ($(ARCH),ppc)
OP_CFLAGS=$(CFLAGS)
endif
all: dyngen$(EXESUF) $(TOOLS) $(DOCS)
for d in $(TARGET_DIRS); do \
$(MAKE) -C $$d $@ || exit 1 ; \
done
ifeq ($(GCC_MAJOR),3)
# very important to generate a return at the end of every operation
OP_CFLAGS+=-fno-reorder-blocks -fno-optimize-sibling-calls
endif
qemu-img: qemu-img.c block.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c
$(CC) -DQEMU_TOOL $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ -lz $(LIBS)
#########################################################
DEFINES+=-D_GNU_SOURCE
LDSCRIPT=$(ARCH).ld
LIBS+=-lm
# profiling code
ifdef TARGET_GPROF
LDFLAGS+=-p
main.o: CFLAGS+=-p
endif
OBJS= elfload.o main.o syscall.o signal.o
SRCS:= $(OBJS:.o=.c)
OBJS+= libqemu.a
LIBOBJS+=thunk.o translate-i386.o op-i386.o exec-i386.o
# NOTE: the disassembler code is only needed for debugging
LIBOBJS+=i386-dis.o dis-buf.o
all: qemu qemu-doc.html
qemu: $(OBJS)
$(CC) -Wl,-T,$(LDSCRIPT) $(LDFLAGS) -o $@ $^ $(LIBS)
depend: $(SRCS)
$(CC) -MM $(CFLAGS) $^ 1>.depend
# libqemu
libqemu.a: $(LIBOBJS)
rm -f $@
$(AR) rcs $@ $(LIBOBJS)
dyngen: dyngen.c
$(HOST_CC) -O2 -Wall -g $< -o $@
translate-i386.o: translate-i386.c op-i386.h cpu-i386.h
op-i386.h: op-i386.o dyngen
./dyngen -o $@ $<
op-i386.o: op-i386.c opreg_template.h ops_template.h
$(CC) $(OP_CFLAGS) $(DEFINES) -c -o $@ $<
%.o: %.c
$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
dyngen$(EXESUF): dyngen.c
$(HOST_CC) $(CFLAGS) $(DEFINES) -o $@ $^
clean:
# avoid old build problems by removing potentially incorrect old files
rm -f config.mak config.h op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
rm -f *.o *.a $(TOOLS) dyngen$(EXESUF) TAGS qemu.pod *~ */*~
$(MAKE) -C tests clean
rm -f *.o *.a *~ qemu dyngen TAGS
for d in $(TARGET_DIRS); do \
$(MAKE) -C $$d $@ || exit 1 ; \
done
distclean: clean
rm -f config.mak config.h
rm -f config-host.mak config-host.h
for d in $(TARGET_DIRS); do \
rm -rf $$d || exit 1 ; \
done
install: qemu
install -m 755 -s qemu $(prefix)/bin
install: all
mkdir -p "$(bindir)"
ifndef CONFIG_WIN32
install -m 755 -s $(TOOLS) "$(bindir)"
endif
mkdir -p "$(datadir)"
install -m 644 pc-bios/bios.bin pc-bios/vgabios.bin \
pc-bios/vgabios-cirrus.bin \
pc-bios/ppc_rom.bin \
pc-bios/proll.bin \
pc-bios/linux_boot.bin "$(datadir)"
mkdir -p "$(docdir)"
install -m 644 qemu-doc.html qemu-tech.html "$(docdir)"
ifndef CONFIG_WIN32
mkdir -p "$(mandir)/man1"
install qemu.1 qemu-mkcow.1 "$(mandir)/man1"
endif
for d in $(TARGET_DIRS); do \
$(MAKE) -C $$d $@ || exit 1 ; \
done
# various test targets
test speed: qemu
make -C tests $@
test speed test2: all
$(MAKE) -C tests $@
TAGS:
etags *.[ch] i386/*.[ch]
etags *.[ch] tests/*.[ch]
# documentation
qemu-doc.html: qemu-doc.texi
%.html: %.texi
texi2html -monolithic -number $<
FILES= \
README COPYING COPYING.LIB TODO Changelog VERSION \
dyngen.c ioctls.h ops_template.h syscall_types.h\
Makefile elf.h linux_bin.h segment.h thunk.c\
elfload.c main.c signal.c thunk.h\
cpu-i386.h qemu.h op-i386.c opc-i386.h syscall-i386.h translate-i386.c\
dis-asm.h gen-i386.h op-i386.h syscall.c\
dis-buf.c i386-dis.c opreg_template.h syscall_defs.h\
i386.ld ppc.ld exec-i386.h exec-i386.c configure \
tests/Makefile\
tests/test-i386.c tests/test-i386-shift.h tests/test-i386.h\
tests/test-i386-muldiv.h tests/test-i386-code16.S\
tests/hello.c tests/hello tests/sha1.c \
tests/testsig.c tests/testclone.c tests/testthread.c \
qemu-doc.texi qemu-doc.html
qemu.1: qemu-doc.texi
./texi2pod.pl $< qemu.pod
pod2man --section=1 --center=" " --release=" " qemu.pod > $@
FILE=qemu-$(VERSION)
FILE=qemu-$(shell cat VERSION)
# tar release (use 'make -k tar' on a checkouted tree)
tar:
rm -rf /tmp/$(FILE)
mkdir -p /tmp/$(FILE)
cp -P $(FILES) /tmp/$(FILE)
( cd /tmp ; tar zcvf ~/$(FILE).tar.gz $(FILE) )
cp -r . /tmp/$(FILE)
( cd /tmp ; tar zcvf ~/$(FILE).tar.gz $(FILE) --exclude CVS )
rm -rf /tmp/$(FILE)
# generate a binary distribution including the test binary environnment
BINPATH=/usr/local/qemu-i386
# generate a binary distribution
tarbin:
tar zcvf /tmp/qemu-i386-glibc21.tar.gz \
$(BINPATH)/etc $(BINPATH)/lib $(BINPATH)/bin
tar zcvf /tmp/qemu-i386-wine.tar.gz \
$(BINPATH)/X11R6 $(BINPATH)/wine
( cd / ; tar zcvf ~/qemu-$(VERSION)-i386.tar.gz \
$(bindir)/qemu $(bindir)/qemu-fast \
$(bindir)/qemu-system-ppc \
$(bindir)/qemu-i386 \
$(bindir)/qemu-arm \
$(bindir)/qemu-sparc \
$(bindir)/qemu-ppc \
$(bindir)/qemu-img \
$(datadir)/bios.bin \
$(datadir)/vgabios.bin \
$(datadir)/vgabios-cirrus.bin \
$(datadir)/ppc_rom.bin \
$(datadir)/proll.bin \
$(datadir)/linux_boot.bin \
$(docdir)/qemu-doc.html \
$(docdir)/qemu-tech.html \
$(mandir)/man1/qemu.1 $(mandir)/man1/qemu-mkcow.1 )
ifneq ($(wildcard .depend),)
include .depend

405
Makefile.target Normal file
View File

@@ -0,0 +1,405 @@
include config.mak
TARGET_PATH=$(SRC_PATH)/target-$(TARGET_ARCH)
VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw:$(SRC_PATH)/audio
DEFINES=-I. -I$(TARGET_PATH) -I$(SRC_PATH)
ifdef CONFIG_USER_ONLY
VPATH+=:$(SRC_PATH)/linux-user
DEFINES+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ARCH)
endif
CFLAGS=-Wall -O2 -g -fno-strict-aliasing
LDFLAGS=-g
LIBS=
HELPER_CFLAGS=$(CFLAGS)
DYNGEN=../dyngen$(EXESUF)
# user emulator name
QEMU_USER=qemu-$(TARGET_ARCH)
# system emulator name
ifdef CONFIG_SOFTMMU
ifeq ($(TARGET_ARCH), i386)
QEMU_SYSTEM=qemu$(EXESUF)
else
QEMU_SYSTEM=qemu-system-$(TARGET_ARCH)$(EXESUF)
endif
else
QEMU_SYSTEM=qemu-fast
endif
ifdef CONFIG_USER_ONLY
PROGS=$(QEMU_USER)
else
ifeq ($(TARGET_ARCH), i386)
ifeq ($(ARCH), i386)
PROGS+=$(QEMU_SYSTEM)
ifndef CONFIG_SOFTMMU
CONFIG_STATIC=y
endif
else
# the system emulator using soft mmu is portable
ifdef CONFIG_SOFTMMU
PROGS+=$(QEMU_SYSTEM)
endif
endif # ARCH != i386
endif # TARGET_ARCH = i386
ifeq ($(TARGET_ARCH), ppc)
ifeq ($(ARCH), ppc)
PROGS+=$(QEMU_SYSTEM)
endif
ifeq ($(ARCH), i386)
ifdef CONFIG_SOFTMMU
PROGS+=$(QEMU_SYSTEM)
endif
endif # ARCH = i386
ifeq ($(ARCH), amd64)
ifdef CONFIG_SOFTMMU
PROGS+=$(QEMU_SYSTEM)
endif
endif # ARCH = amd64
endif # TARGET_ARCH = ppc
ifeq ($(TARGET_ARCH), sparc)
ifeq ($(ARCH), ppc)
PROGS+=$(QEMU_SYSTEM)
endif
ifeq ($(ARCH), i386)
ifdef CONFIG_SOFTMMU
PROGS+=$(QEMU_SYSTEM)
endif
endif # ARCH = i386
ifeq ($(ARCH), amd64)
ifdef CONFIG_SOFTMMU
PROGS+=$(QEMU_SYSTEM)
endif
endif # ARCH = amd64
endif # TARGET_ARCH = sparc
endif # !CONFIG_USER_ONLY
ifdef CONFIG_STATIC
LDFLAGS+=-static
endif
ifeq ($(ARCH),i386)
CFLAGS+=-fomit-frame-pointer
OP_CFLAGS=$(CFLAGS) -mpreferred-stack-boundary=2
ifeq ($(HAVE_GCC3_OPTIONS),yes)
OP_CFLAGS+= -falign-functions=0 -fno-gcse
else
OP_CFLAGS+= -malign-functions=0
endif
ifdef TARGET_GPROF
USE_I386_LD=y
endif
ifdef CONFIG_STATIC
USE_I386_LD=y
endif
ifdef USE_I386_LD
LDFLAGS+=-Wl,-T,$(SRC_PATH)/i386.ld
else
# WARNING: this LDFLAGS is _very_ tricky : qemu is an ELF shared object
# that the kernel ELF loader considers as an executable. I think this
# is the simplest way to make it self virtualizable!
LDFLAGS+=-Wl,-shared
endif
endif
ifeq ($(ARCH),amd64)
OP_CFLAGS=$(CFLAGS) -falign-functions=0
LDFLAGS+=-Wl,-T,$(SRC_PATH)/amd64.ld
endif
ifeq ($(ARCH),ppc)
CFLAGS+= -D__powerpc__
OP_CFLAGS=$(CFLAGS)
LDFLAGS+=-Wl,-T,$(SRC_PATH)/ppc.ld
endif
ifeq ($(ARCH),s390)
OP_CFLAGS=$(CFLAGS)
LDFLAGS+=-Wl,-T,$(SRC_PATH)/s390.ld
endif
ifeq ($(ARCH),sparc)
CFLAGS+=-m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
LDFLAGS+=-m32
OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0
HELPER_CFLAGS=$(CFLAGS) -ffixed-i0 -mflat
# -static is used to avoid g1/g3 usage by the dynamic linker
LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc.ld -static
endif
ifeq ($(ARCH),sparc64)
CFLAGS+=-m64 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
LDFLAGS+=-m64
OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0
endif
ifeq ($(ARCH),alpha)
# -msmall-data is not used because we want two-instruction relocations
# for the constant constructions
OP_CFLAGS=-Wall -O2 -g
# Ensure there's only a single GP
CFLAGS += -msmall-data
LDFLAGS+=-Wl,-T,$(SRC_PATH)/alpha.ld
endif
ifeq ($(ARCH),ia64)
OP_CFLAGS=$(CFLAGS)
endif
ifeq ($(ARCH),arm)
OP_CFLAGS=$(CFLAGS) -mno-sched-prolog
LDFLAGS+=-Wl,-T,$(SRC_PATH)/arm.ld
endif
ifeq ($(ARCH),m68k)
OP_CFLAGS=$(CFLAGS) -fomit-frame-pointer
LDFLAGS+=-Wl,-T,m68k.ld
endif
ifeq ($(HAVE_GCC3_OPTIONS),yes)
# very important to generate a return at the end of every operation
OP_CFLAGS+=-fno-reorder-blocks -fno-optimize-sibling-calls
endif
ifeq ($(CONFIG_DARWIN),yes)
OP_CFLAGS+= -mdynamic-no-pic
endif
#########################################################
DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
LIBS+=-lm
ifndef CONFIG_USER_ONLY
LIBS+=-lz
endif
ifdef CONFIG_WIN32
LIBS+=-lwinmm -lws2_32 -liphlpapi
endif
# profiling code
ifdef TARGET_GPROF
LDFLAGS+=-p
main.o: CFLAGS+=-p
endif
OBJS= elfload.o main.o syscall.o mmap.o signal.o path.o osdep.o thunk.o
ifeq ($(TARGET_ARCH), i386)
OBJS+= vm86.o
endif
ifeq ($(TARGET_ARCH), arm)
OBJS+=nwfpe/softfloat.o nwfpe/fpa11.o nwfpe/fpa11_cpdo.o \
nwfpe/fpa11_cpdt.o nwfpe/fpa11_cprt.o nwfpe/fpopcode.o nwfpe/single_cpdo.o \
nwfpe/double_cpdo.o nwfpe/extended_cpdo.o
endif
SRCS:= $(OBJS:.o=.c)
OBJS+= libqemu.a
# cpu emulator library
LIBOBJS=exec.o translate-all.o cpu-exec.o\
translate.o op.o
ifeq ($(TARGET_ARCH), i386)
LIBOBJS+=helper.o helper2.o
ifeq ($(ARCH), i386)
LIBOBJS+=translate-copy.o
endif
endif
ifeq ($(TARGET_ARCH), ppc)
LIBOBJS+= op_helper.o helper.o
endif
ifeq ($(TARGET_ARCH), sparc)
LIBOBJS+= op_helper.o helper.o
endif
# NOTE: the disassembler code is only needed for debugging
LIBOBJS+=disas.o
ifeq ($(findstring i386, $(TARGET_ARCH) $(ARCH)),i386)
USE_I386_DIS=y
endif
ifeq ($(findstring amd64, $(TARGET_ARCH) $(ARCH)),amd64)
USE_I386_DIS=y
endif
ifdef USE_I386_DIS
LIBOBJS+=i386-dis.o
endif
ifeq ($(findstring alpha, $(TARGET_ARCH) $(ARCH)),alpha)
LIBOBJS+=alpha-dis.o
endif
ifeq ($(findstring ppc, $(TARGET_ARCH) $(ARCH)),ppc)
LIBOBJS+=ppc-dis.o
endif
ifeq ($(findstring sparc, $(TARGET_ARCH) $(ARCH)),sparc)
LIBOBJS+=sparc-dis.o
endif
ifeq ($(findstring arm, $(TARGET_ARCH) $(ARCH)),arm)
LIBOBJS+=arm-dis.o
endif
ifeq ($(ARCH),ia64)
OBJS += ia64-syscall.o
endif
all: $(PROGS)
$(QEMU_USER): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
ifeq ($(ARCH),alpha)
# Mark as 32 bit binary, i. e. it will be mapped into the low 31 bit of
# the address space (31 bit so sign extending doesn't matter)
echo -ne '\001\000\000\000' | dd of=qemu bs=1 seek=48 count=4 conv=notrunc
endif
# must use static linking to avoid leaving stuff in virtual address space
VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o
VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o
SOUND_HW = sb16.o
AUDIODRV = audio.o noaudio.o wavaudio.o
ifdef CONFIG_SDL
AUDIODRV += sdlaudio.o
endif
ifdef CONFIG_OSS
AUDIODRV += ossaudio.o
endif
pc.o: DEFINES := -DUSE_SB16 $(DEFINES)
ifdef CONFIG_ADLIB
SOUND_HW += fmopl.o adlib.o
endif
ifdef CONFIG_FMOD
AUDIODRV += fmodaudio.o
audio.o fmodaudio.o: DEFINES := -I$(CONFIG_FMOD_INC) $(DEFINES)
LIBS += $(CONFIG_FMOD_LIB)
endif
ifeq ($(TARGET_ARCH), i386)
# Hardware support
VL_OBJS+= ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o
VL_OBJS+= cirrus_vga.o mixeng.o
endif
ifeq ($(TARGET_ARCH), ppc)
VL_OBJS+= ppc.o ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o mixeng.o
endif
ifeq ($(TARGET_ARCH), sparc)
VL_OBJS+= sun4m.o tcx.o lance.o iommu.o sched.o m48t08.o magic-load.o timer.o
endif
ifdef CONFIG_GDBSTUB
VL_OBJS+=gdbstub.o
endif
ifdef CONFIG_SDL
VL_OBJS+=sdl.o
endif
ifdef CONFIG_SLIRP
DEFINES+=-I$(SRC_PATH)/slirp
SLIRP_OBJS=cksum.o if.o ip_icmp.o ip_input.o ip_output.o \
slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o \
tcp_subr.o tcp_timer.o udp.o bootp.o debug.o tftp.o
VL_OBJS+=$(addprefix slirp/, $(SLIRP_OBJS))
endif
VL_LDFLAGS=
# specific flags are needed for non soft mmu emulator
ifdef CONFIG_STATIC
VL_LDFLAGS+=-static
endif
ifndef CONFIG_SOFTMMU
VL_LDFLAGS+=-Wl,-T,$(SRC_PATH)/i386-vl.ld
endif
ifndef CONFIG_DARWIN
ifndef CONFIG_WIN32
VL_LIBS=-lutil
endif
endif
$(QEMU_SYSTEM): $(VL_OBJS) libqemu.a
$(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(VL_LIBS)
sdl.o: sdl.c
$(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $<
sdlaudio.o: sdlaudio.c
$(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $<
depend: $(SRCS)
$(CC) -MM $(CFLAGS) $(DEFINES) $^ 1>.depend
# libqemu
libqemu.a: $(LIBOBJS)
rm -f $@
$(AR) rcs $@ $(LIBOBJS)
translate.o: translate.c gen-op.h opc.h cpu.h
translate-all.o: translate-all.c op.h opc.h cpu.h
op.h: op.o $(DYNGEN)
$(DYNGEN) -o $@ $<
opc.h: op.o $(DYNGEN)
$(DYNGEN) -c -o $@ $<
gen-op.h: op.o $(DYNGEN)
$(DYNGEN) -g -o $@ $<
op.o: op.c
$(CC) $(OP_CFLAGS) $(DEFINES) -c -o $@ $<
helper.o: helper.c
$(CC) $(HELPER_CFLAGS) $(DEFINES) -c -o $@ $<
ifeq ($(TARGET_ARCH), i386)
op.o: op.c opreg_template.h ops_template.h ops_template_mem.h ops_mem.h
endif
ifeq ($(TARGET_ARCH), arm)
op.o: op.c op_template.h
endif
ifeq ($(TARGET_ARCH), sparc)
op.o: op.c op_template.h op_mem.h
endif
ifeq ($(TARGET_ARCH), ppc)
op.o: op.c op_template.h op_mem.h
op_helper.o: op_helper_mem.h
endif
mixeng.o: mixeng.c mixeng.h mixeng_template.h
%.o: %.c
$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
%.o: %.S
$(CC) $(DEFINES) -c -o $@ $<
clean:
rm -f *.o *.a *~ $(PROGS) gen-op.h opc.h op.h nwfpe/*.o slirp/*.o
install: all
ifneq ($(PROGS),)
install -m 755 -s $(PROGS) "$(bindir)"
endif
ifneq ($(wildcard .depend),)
include .depend
endif

44
README
View File

@@ -9,28 +9,48 @@ Type
./configure
make
to build qemu and libqemu.a.
to build qemu, qemu-CPU and libqemu.a (CPU is the name of the various
supported target CPUs).
Type
make install
to install QEMU in /usr/local/bin
to install QEMU in /usr/local
* On x86 you should be able to launch any program by using the
libraries installed on your PC. For example:
Tested tool versions
--------------------
./qemu -L / /bin/ls
In order to compile QEMU succesfully, it is very important that you
have the right tools. The most important one is gcc. I cannot guaranty
that QEMU works if you do not use a tested gcc version. Look at
'configure' and 'Makefile' if you want to make a different gcc
version work.
* On non x86 CPUs, you need first to download at least an x86 glibc
(qemu-i386-glibc21.tar.gz on the qemu web page). Then you can launch
the precompiled 'ls' x86 executable:
host gcc binutils glibc linux distribution
----------------------------------------------------------------------
x86 2.95.2 2.13.2 2.1.3 2.4.18
3.2 2.13.2 2.1.3 2.4.18
2.96 2.11.93.0.2 2.2.5 2.4.18 Red Hat 7.3
3.2.2 2.13.90.0.18 2.3.2 2.4.20 Red Hat 9
./qemu /usr/local/qemu-i386/bin/ls
PowerPC 3.3 [4] 2.13.90.0.18 2.3.1 2.4.20briq
3.2
You can look at /usr/local/qemu-i386/bin/qemu-conf.sh so that QEMU is
automatically launched by the Linux kernel when you try to launch x86
executables.
Alpha 3.3 [1] 2.14.90.0.4 2.2.5 2.2.20 [2] Debian 3.0
Sparc32 2.95.4 2.12.90.0.1 2.2.5 2.4.18 Debian 3.0
ARM 2.95.4 2.12.90.0.1 2.2.5 2.4.9 [3] Debian 3.0
[1] On Alpha, QEMU needs the gcc 'visibility' attribute only available
for gcc version >= 3.3.
[2] Linux >= 2.4.20 is necessary for precise exception support
(untested).
[3] 2.4.9-ac10-rmk2-np1-cerf2
[4] gcc 2.95.x generates invalid code when using too many register
variables. You must use gcc 3.x on PowerPC.
Documentation
-------------

16
README.distrib Normal file
View File

@@ -0,0 +1,16 @@
Information about the various packages used to build the current qemu
x86 binary distribution:
* gcc 2.95.2 was used for the build. A glibc 2.1.3 Debian distribution
was used to get most of the binary packages.
* wine-20020411 tarball
./configure --prefix=/usr/local/wine-i386
All exe and libs were stripped. Some compile time tools and the
includes were deleted.
* ldconfig was launched to build the library links:
qemu-i386 /usr/gnemul/qemu-i386/bin/ldconfig-i386 -C /usr/gnemul/qemu-i386/etc/ld.so.cache

72
TODO
View File

@@ -1,10 +1,66 @@
- optimize translated cache chaining (DLL PLT-like system)
short term:
----------
- debug option in 'configure' script + disable -fomit-frame-pointer
- Solaris display error with Cirrus VGA
(http://lists.gnu.org/archive/html/qemu-devel/2004-10/msg00390.html).
- Precise VGA timings for old games/demos (malc patch)
- merge PIC spurious interrupt patch
- merge VNC keyboard patch
- merge Solaris patch
- merge ARM patches + self modifying code patch (Paul Brook)
- warning for OS/2: must not use 128 MB memory
- config file (at least for windows/Mac OS X)
- commit message if execution of code in IO memory
- update doc: PCI infos.
- VNC patch + Synaptic patch.
- basic VGA optimizations
- test sysenter/sysexit and fxsr for L4 pistachio 686
- physical memory cache (reduce qemu-fast address space size to about 32 MB)
- better code fetch (different exception handling + CS.limit support)
- do not resize vga if invalid size.
- avoid looping if only exceptions
- cycle counter for all archs
- TLB code protection support for PPC
- see openMosix Doc
- disable SMC handling for ARM/SPARC/PPC (not finished)
- see undefined flags for BTx insn
- user/kernel PUSHL/POPL in helper.c
- keyboard output buffer filling timing emulation
- return UD exception if LOCK prefix incorrectly used
- test ldt limit < 7 ?
- tests for each target CPU
- fix CCOP optimisation
- fix all remaining thread lock issues (must put TBs in a specific invalid
state, find a solution for tb_flush()).
- fix arm fpu rounding (at least for float->integer conversions)
- SMP support
ppc specific:
------------
- TLB invalidate not needed if msr_pr changes
- endianness bugs in do_load_fpscr and do_store_fpscr
- SPR_ENCODE() not useful
- enable shift optimizations ?
lower priority:
--------------
- more friendly BIOS (logo)
- int15 ah=86: use better timing
- HDD geometry in CMOS (not used except for very old DOS programs)
- suppress shift_mem ops
- fix some 16 bit sp push/pop overflow (pusha/popa, lcall lret)
- sysenter/sysexit emulation
- optimize FPU operations (evaluate x87 stack pointer statically)
- add IPC syscalls
- use -msoft-float on ARM
- use kernel traps for unaligned accesses on ARM ?
- handle rare page fault cases (in particular if page fault in helpers or
in syscall emulation code).
- fix thread stack freeing (use kernel 2.5.x CLONE_CHILD_CLEARTID)
- more syscalls (in particular all 64 bit ones, IPCs, fix 64 bit
issues, fix 16 bit uid issues)
- finish signal handing (fp87 state, more siginfo conversions)
- verify thread support (clone() and various locks)
- vm86 syscall support
- overrides/16bit for string ops
- make it self runnable (use same trick as ld.so : include its own relocator and libc)
- improved 16 bit support
- fix FPU exceptions (in particular: gen_op_fpush not before mem load)
- use page_unprotect_range in every suitable syscall to handle all
cases of self modifying code.
- use gcc as a backend to generate better code (easy to do by using
op-i386.c operations as local inline functions).
- add SSE2/MMX operations

View File

@@ -1 +1 @@
0.1.1
0.6.1

431
a.out.h Normal file
View File

@@ -0,0 +1,431 @@
/* a.out.h
Copyright 1997, 1998, 1999, 2001 Red Hat, Inc.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#ifndef _A_OUT_H_
#define _A_OUT_H_
#ifdef __cplusplus
extern "C" {
#endif
#define COFF_IMAGE_WITH_PE
#define COFF_LONG_SECTION_NAMES
/*** coff information for Intel 386/486. */
/********************** FILE HEADER **********************/
struct external_filehdr {
short f_magic; /* magic number */
short f_nscns; /* number of sections */
unsigned long f_timdat; /* time & date stamp */
unsigned long f_symptr; /* file pointer to symtab */
unsigned long f_nsyms; /* number of symtab entries */
short f_opthdr; /* sizeof(optional hdr) */
short f_flags; /* flags */
};
/* Bits for f_flags:
* F_RELFLG relocation info stripped from file
* F_EXEC file is executable (no unresolved external references)
* F_LNNO line numbers stripped from file
* F_LSYMS local symbols stripped from file
* F_AR32WR file has byte ordering of an AR32WR machine (e.g. vax)
*/
#define F_RELFLG (0x0001)
#define F_EXEC (0x0002)
#define F_LNNO (0x0004)
#define F_LSYMS (0x0008)
#define I386MAGIC 0x14c
#define I386PTXMAGIC 0x154
#define I386AIXMAGIC 0x175
/* This is Lynx's all-platform magic number for executables. */
#define LYNXCOFFMAGIC 0415
#define I386BADMAG(x) (((x).f_magic != I386MAGIC) \
&& (x).f_magic != I386AIXMAGIC \
&& (x).f_magic != I386PTXMAGIC \
&& (x).f_magic != LYNXCOFFMAGIC)
#define FILHDR struct external_filehdr
#define FILHSZ 20
/********************** AOUT "OPTIONAL HEADER"=
**********************/
typedef struct
{
unsigned short magic; /* type of file */
unsigned short vstamp; /* version stamp */
unsigned long tsize; /* text size in bytes, padded to FW bdry*/
unsigned long dsize; /* initialized data " " */
unsigned long bsize; /* uninitialized data " " */
unsigned long entry; /* entry pt. */
unsigned long text_start; /* base of text used for this file */
unsigned long data_start; /* base of data used for this file=
*/
}
AOUTHDR;
#define AOUTSZ 28
#define AOUTHDRSZ 28
#define OMAGIC 0404 /* object files, eg as output */
#define ZMAGIC 0413 /* demand load format, eg normal ld output */
#define STMAGIC 0401 /* target shlib */
#define SHMAGIC 0443 /* host shlib */
/* define some NT default values */
/* #define NT_IMAGE_BASE 0x400000 moved to internal.h */
#define NT_SECTION_ALIGNMENT 0x1000
#define NT_FILE_ALIGNMENT 0x200
#define NT_DEF_RESERVE 0x100000
#define NT_DEF_COMMIT 0x1000
/********************** SECTION HEADER **********************/
struct external_scnhdr {
char s_name[8]; /* section name */
unsigned long s_paddr; /* physical address, offset
of last addr in scn */
unsigned long s_vaddr; /* virtual address */
unsigned long s_size; /* section size */
unsigned long s_scnptr; /* file ptr to raw data for section */
unsigned long s_relptr; /* file ptr to relocation */
unsigned long s_lnnoptr; /* file ptr to line numbers */
unsigned short s_nreloc; /* number of relocation entries */
unsigned short s_nlnno; /* number of line number entries*/
unsigned long s_flags; /* flags */
};
#define SCNHDR struct external_scnhdr
#define SCNHSZ 40
/*
* names of "special" sections
*/
#define _TEXT ".text"
#define _DATA ".data"
#define _BSS ".bss"
#define _COMMENT ".comment"
#define _LIB ".lib"
/********************** LINE NUMBERS **********************/
/* 1 line number entry for every "breakpointable" source line in a section.
* Line numbers are grouped on a per function basis; first entry in a function
* grouping will have l_lnno = 0 and in place of physical address will be the
* symbol table index of the function name.
*/
struct external_lineno {
union {
unsigned long l_symndx; /* function name symbol index, iff l_lnno 0 */
unsigned long l_paddr; /* (physical) address of line number */
} l_addr;
unsigned short l_lnno; /* line number */
};
#define LINENO struct external_lineno
#define LINESZ 6
/********************** SYMBOLS **********************/
#define E_SYMNMLEN 8 /* # characters in a symbol name */
#define E_FILNMLEN 14 /* # characters in a file name */
#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
struct external_syment
{
union {
char e_name[E_SYMNMLEN];
struct {
unsigned long e_zeroes;
unsigned long e_offset;
} e;
} e;
unsigned long e_value;
unsigned short e_scnum;
unsigned short e_type;
char e_sclass[1];
char e_numaux[1];
};
#define N_BTMASK (0xf)
#define N_TMASK (0x30)
#define N_BTSHFT (4)
#define N_TSHIFT (2)
union external_auxent {
struct {
unsigned long x_tagndx; /* str, un, or enum tag indx */
union {
struct {
unsigned short x_lnno; /* declaration line number */
unsigned short x_size; /* str/union/array size */
} x_lnsz;
unsigned long x_fsize; /* size of function */
} x_misc;
union {
struct { /* if ISFCN, tag, or .bb */
unsigned long x_lnnoptr;/* ptr to fcn line # */
unsigned long x_endndx; /* entry ndx past block end */
} x_fcn;
struct { /* if ISARY, up to 4 dimen. */
char x_dimen[E_DIMNUM][2];
} x_ary;
} x_fcnary;
unsigned short x_tvndx; /* tv index */
} x_sym;
union {
char x_fname[E_FILNMLEN];
struct {
unsigned long x_zeroes;
unsigned long x_offset;
} x_n;
} x_file;
struct {
unsigned long x_scnlen; /* section length */
unsigned short x_nreloc; /* # relocation entries */
unsigned short x_nlinno; /* # line numbers */
unsigned long x_checksum; /* section COMDAT checksum */
unsigned short x_associated;/* COMDAT associated section index */
char x_comdat[1]; /* COMDAT selection number */
} x_scn;
struct {
unsigned long x_tvfill; /* tv fill value */
unsigned short x_tvlen; /* length of .tv */
char x_tvran[2][2]; /* tv range */
} x_tv; /* info about .tv section (in auxent of symbol .tv)) */
};
#define SYMENT struct external_syment
#define SYMESZ 18
#define AUXENT union external_auxent
#define AUXESZ 18
#define _ETEXT "etext"
/********************** RELOCATION DIRECTIVES **********************/
struct external_reloc {
char r_vaddr[4];
char r_symndx[4];
char r_type[2];
};
#define RELOC struct external_reloc
#define RELSZ 10
/* end of coff/i386.h */
/* PE COFF header information */
#ifndef _PE_H
#define _PE_H
/* NT specific file attributes */
#define IMAGE_FILE_RELOCS_STRIPPED 0x0001
#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002
#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004
#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008
#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080
#define IMAGE_FILE_32BIT_MACHINE 0x0100
#define IMAGE_FILE_DEBUG_STRIPPED 0x0200
#define IMAGE_FILE_SYSTEM 0x1000
#define IMAGE_FILE_DLL 0x2000
#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000
/* additional flags to be set for section headers to allow the NT loader to
read and write to the section data (to replace the addresses of data in
dlls for one thing); also to execute the section in .text's case=
*/
#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000
#define IMAGE_SCN_MEM_EXECUTE 0x20000000
#define IMAGE_SCN_MEM_READ 0x40000000
#define IMAGE_SCN_MEM_WRITE 0x80000000
/*
* Section characteristics added for ppc-nt
*/
#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 /* Reserved. */
#define IMAGE_SCN_CNT_CODE 0x00000020 /* Section contains code. */
#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 /* Section contains initialized data. */
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 /* Section contains uninitialized data. */
#define IMAGE_SCN_LNK_OTHER 0x00000100 /* Reserved. */
#define IMAGE_SCN_LNK_INFO 0x00000200 /* Section contains comments or some other type of information. */
#define IMAGE_SCN_LNK_REMOVE 0x00000800 /* Section contents will not become part of image. */
#define IMAGE_SCN_LNK_COMDAT 0x00001000 /* Section contents comdat. */
#define IMAGE_SCN_MEM_FARDATA 0x00008000
#define IMAGE_SCN_MEM_PURGEABLE 0x00020000
#define IMAGE_SCN_MEM_16BIT 0x00020000
#define IMAGE_SCN_MEM_LOCKED 0x00040000
#define IMAGE_SCN_MEM_PRELOAD 0x00080000
#define IMAGE_SCN_ALIGN_1BYTES 0x00100000
#define IMAGE_SCN_ALIGN_2BYTES 0x00200000
#define IMAGE_SCN_ALIGN_4BYTES 0x00300000
#define IMAGE_SCN_ALIGN_8BYTES 0x00400000
#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 /* Default alignment if no others are specified. */
#define IMAGE_SCN_ALIGN_32BYTES 0x00600000
#define IMAGE_SCN_ALIGN_64BYTES 0x00700000
#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 /* Section contains extended relocations. */
#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 /* Section is not cachable. */
#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 /* Section is not pageable. */
#define IMAGE_SCN_MEM_SHARED 0x10000000 /* Section is shareable. */
/* COMDAT selection codes. */
#define IMAGE_COMDAT_SELECT_NODUPLICATES (1) /* Warn if duplicates. */
#define IMAGE_COMDAT_SELECT_ANY (2) /* No warning. */
#define IMAGE_COMDAT_SELECT_SAME_SIZE (3) /* Warn if different size. */
#define IMAGE_COMDAT_SELECT_EXACT_MATCH (4) /* Warn if different. */
#define IMAGE_COMDAT_SELECT_ASSOCIATIVE (5) /* Base on other section. */
/* Magic values that are true for all dos/nt implementations */
#define DOSMAGIC 0x5a4d
#define NT_SIGNATURE 0x00004550
/* NT allows long filenames, we want to accommodate this. This may break
some of the bfd functions */
#undef FILNMLEN
#define FILNMLEN 18 /* # characters in a file name */
#ifdef COFF_IMAGE_WITH_PE
/* The filehdr is only weired in images */
#undef FILHDR
struct external_PE_filehdr
{
/* DOS header fields */
unsigned short e_magic; /* Magic number, 0x5a4d */
unsigned short e_cblp; /* Bytes on last page of file, 0x90 */
unsigned short e_cp; /* Pages in file, 0x3 */
unsigned short e_crlc; /* Relocations, 0x0 */
unsigned short e_cparhdr; /* Size of header in paragraphs, 0x4 */
unsigned short e_minalloc; /* Minimum extra paragraphs needed, 0x0 */
unsigned short e_maxalloc; /* Maximum extra paragraphs needed, 0xFFFF */
unsigned short e_ss; /* Initial (relative) SS value, 0x0 */
unsigned short e_sp; /* Initial SP value, 0xb8 */
unsigned short e_csum; /* Checksum, 0x0 */
unsigned short e_ip; /* Initial IP value, 0x0 */
unsigned short e_cs; /* Initial (relative) CS value, 0x0 */
unsigned short e_lfarlc; /* File address of relocation table, 0x40 */
unsigned short e_ovno; /* Overlay number, 0x0 */
char e_res[4][2]; /* Reserved words, all 0x0 */
unsigned short e_oemid; /* OEM identifier (for e_oeminfo), 0x0 */
unsigned short e_oeminfo; /* OEM information; e_oemid specific, 0x0 */
char e_res2[10][2]; /* Reserved words, all 0x0 */
unsigned long e_lfanew; /* File address of new exe header, 0x80 */
char dos_message[16][4]; /* other stuff, always follow DOS header */
unsigned int nt_signature; /* required NT signature, 0x4550 */
/* From standard header */
unsigned short f_magic; /* magic number */
unsigned short f_nscns; /* number of sections */
unsigned long f_timdat; /* time & date stamp */
unsigned long f_symptr; /* file pointer to symtab */
unsigned long f_nsyms; /* number of symtab entries */
unsigned short f_opthdr; /* sizeof(optional hdr) */
unsigned short f_flags; /* flags */
};
#define FILHDR struct external_PE_filehdr
#undef FILHSZ
#define FILHSZ 152
#endif
typedef struct
{
unsigned short magic; /* type of file */
unsigned short vstamp; /* version stamp */
unsigned long tsize; /* text size in bytes, padded to FW bdry*/
unsigned long dsize; /* initialized data " " */
unsigned long bsize; /* uninitialized data " " */
unsigned long entry; /* entry pt. */
unsigned long text_start; /* base of text used for this file */
unsigned long data_start; /* base of all data used for this file */
/* NT extra fields; see internal.h for descriptions */
unsigned long ImageBase;
unsigned long SectionAlignment;
unsigned long FileAlignment;
unsigned short MajorOperatingSystemVersion;
unsigned short MinorOperatingSystemVersion;
unsigned short MajorImageVersion;
unsigned short MinorImageVersion;
unsigned short MajorSubsystemVersion;
unsigned short MinorSubsystemVersion;
char Reserved1[4];
unsigned long SizeOfImage;
unsigned long SizeOfHeaders;
unsigned long CheckSum;
unsigned short Subsystem;
unsigned short DllCharacteristics;
unsigned long SizeOfStackReserve;
unsigned long SizeOfStackCommit;
unsigned long SizeOfHeapReserve;
unsigned long SizeOfHeapCommit;
unsigned long LoaderFlags;
unsigned long NumberOfRvaAndSizes;
/* IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; */
char DataDirectory[16][2][4]; /* 16 entries, 2 elements/entry, 4 chars */
} PEAOUTHDR;
#undef AOUTSZ
#define AOUTSZ (AOUTHDRSZ + 196)
#undef E_FILNMLEN
#define E_FILNMLEN 18 /* # characters in a file name */
#endif
/* end of coff/pe.h */
#define DT_NON (0) /* no derived type */
#define DT_PTR (1) /* pointer */
#define DT_FCN (2) /* function */
#define DT_ARY (3) /* array */
#define ISPTR(x) (((x) & N_TMASK) == (DT_PTR << N_BTSHFT))
#define ISFCN(x) (((x) & N_TMASK) == (DT_FCN << N_BTSHFT))
#define ISARY(x) (((x) & N_TMASK) == (DT_ARY << N_BTSHFT))
#ifdef __cplusplus
}
#endif
#endif /* _A_OUT_H_ */

1317
aes.c Normal file

File diff suppressed because it is too large Load Diff

26
aes.h Normal file
View File

@@ -0,0 +1,26 @@
#ifndef QEMU_AES_H
#define QEMU_AES_H
#define AES_MAXNR 14
#define AES_BLOCK_SIZE 16
struct aes_key_st {
uint32_t rd_key[4 *(AES_MAXNR + 1)];
int rounds;
};
typedef struct aes_key_st AES_KEY;
int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
void AES_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
void AES_decrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
const unsigned long length, const AES_KEY *key,
unsigned char *ivec, const int enc);
#endif

1963
alpha-dis.c Normal file

File diff suppressed because it is too large Load Diff

128
alpha.ld Normal file
View File

@@ -0,0 +1,128 @@
OUTPUT_FORMAT("elf64-alpha", "elf64-alpha",
"elf64-alpha")
OUTPUT_ARCH(alpha)
ENTRY(__start)
SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/alpha-unknown-linux-gnu/lib);
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = 0x60000000 + SIZEOF_HEADERS;
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rel.text :
{ *(.rel.text) *(.rel.gnu.linkonce.t*) }
.rela.text :
{ *(.rela.text) *(.rela.gnu.linkonce.t*) }
.rel.data :
{ *(.rel.data) *(.rel.gnu.linkonce.d*) }
.rela.data :
{ *(.rela.data) *(.rela.gnu.linkonce.d*) }
.rel.rodata :
{ *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
.rela.rodata :
{ *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
.rel.got : { *(.rel.got) }
.rela.got : { *(.rela.got) }
.rel.ctors : { *(.rel.ctors) }
.rela.ctors : { *(.rela.ctors) }
.rel.dtors : { *(.rel.dtors) }
.rela.dtors : { *(.rela.dtors) }
.rel.init : { *(.rel.init) }
.rela.init : { *(.rela.init) }
.rel.fini : { *(.rel.fini) }
.rela.fini : { *(.rela.fini) }
.rel.bss : { *(.rel.bss) }
.rela.bss : { *(.rela.bss) }
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
.init : { *(.init) } =0x47ff041f
.text :
{
*(.text)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
*(.gnu.linkonce.t*)
} =0x47ff041f
_etext = .;
PROVIDE (etext = .);
.fini : { *(.fini) } =0x47ff041f
.rodata : { *(.rodata) *(.gnu.linkonce.r*) }
.rodata1 : { *(.rodata1) }
.reginfo : { *(.reginfo) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = ALIGN(0x100000) + (. & (0x100000 - 1));
.data :
{
*(.data)
*(.gnu.linkonce.d*)
CONSTRUCTORS
}
.data1 : { *(.data1) }
.ctors :
{
*(.ctors)
}
.dtors :
{
*(.dtors)
}
.plt : { *(.plt) }
.got : { *(.got.plt) *(.got) }
.dynamic : { *(.dynamic) }
/* We want the small data sections together, so single-instruction offsets
can access them all, and initialized data all before uninitialized, so
we can shorten the on-disk segment size. */
.sdata : { *(.sdata) }
_edata = .;
PROVIDE (edata = .);
__bss_start = .;
.sbss : { *(.sbss) *(.scommon) }
.bss :
{
*(.dynbss)
*(.bss)
*(COMMON)
}
_end = . ;
PROVIDE (end = .);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* These must appear regardless of . */
}

171
amd64.ld Normal file
View File

@@ -0,0 +1,171 @@
/* Default linker script, for normal executables */
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(_start)
SEARCH_DIR("/lib64"); SEARCH_DIR("/usr/lib64"); SEARCH_DIR("/usr/local/lib64");
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = 0x60000000 + SIZEOF_HEADERS;
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rel.init : { *(.rel.init) }
.rela.init : { *(.rela.init) }
.rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }
.rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
.rel.fini : { *(.rel.fini) }
.rela.fini : { *(.rela.fini) }
.rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }
.rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
.rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
.rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
.rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
.rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
.rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
.rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
.rel.ctors : { *(.rel.ctors) }
.rela.ctors : { *(.rela.ctors) }
.rel.dtors : { *(.rel.dtors) }
.rela.dtors : { *(.rela.dtors) }
.rel.got : { *(.rel.got) }
.rela.got : { *(.rela.got) }
.rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
.rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
.init :
{
KEEP (*(.init))
} =0x90909090
.plt : { *(.plt) }
.text :
{
*(.text .stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
} =0x90909090
.fini :
{
KEEP (*(.fini))
} =0x90909090
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
.eh_frame_hdr : { *(.eh_frame_hdr) }
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = ALIGN (0x100000) - ((0x100000 - .) & (0x100000 - 1)); . = DATA_SEGMENT_ALIGN (0x100000, 0x1000);
/* Ensure the __preinit_array_start label is properly aligned. We
could instead move the label definition inside the section, but
the linker would then create the section even if it turns out to
be empty, which isn't pretty. */
. = ALIGN(64 / 8);
PROVIDE (__preinit_array_start = .);
.preinit_array : { *(.preinit_array) }
PROVIDE (__preinit_array_end = .);
PROVIDE (__init_array_start = .);
.init_array : { *(.init_array) }
PROVIDE (__init_array_end = .);
PROVIDE (__fini_array_start = .);
.fini_array : { *(.fini_array) }
PROVIDE (__fini_array_end = .);
.data :
{
*(.data .data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
}
.data1 : { *(.data1) }
.tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table) }
.dynamic : { *(.dynamic) }
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
/* We don't want to include the .ctor section from
from the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
}
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
}
.jcr : { KEEP (*(.jcr)) }
.got : { *(.got.plt) *(.got) }
_edata = .;
PROVIDE (edata = .);
__bss_start = .;
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections. */
. = ALIGN(64 / 8);
}
. = ALIGN(64 / 8);
_end = .;
PROVIDE (end = .);
. = DATA_SEGMENT_END (.);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
}

1675
arm-dis.c Normal file

File diff suppressed because it is too large Load Diff

128
arm.ld Normal file
View File

@@ -0,0 +1,128 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm",
"elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/alpha-unknown-linux-gnu/lib);
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = 0x60000000 + SIZEOF_HEADERS;
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rel.text :
{ *(.rel.text) *(.rel.gnu.linkonce.t*) }
.rela.text :
{ *(.rela.text) *(.rela.gnu.linkonce.t*) }
.rel.data :
{ *(.rel.data) *(.rel.gnu.linkonce.d*) }
.rela.data :
{ *(.rela.data) *(.rela.gnu.linkonce.d*) }
.rel.rodata :
{ *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
.rela.rodata :
{ *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
.rel.got : { *(.rel.got) }
.rela.got : { *(.rela.got) }
.rel.ctors : { *(.rel.ctors) }
.rela.ctors : { *(.rela.ctors) }
.rel.dtors : { *(.rel.dtors) }
.rela.dtors : { *(.rela.dtors) }
.rel.init : { *(.rel.init) }
.rela.init : { *(.rela.init) }
.rel.fini : { *(.rel.fini) }
.rela.fini : { *(.rela.fini) }
.rel.bss : { *(.rel.bss) }
.rela.bss : { *(.rela.bss) }
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
.init : { *(.init) } =0x47ff041f
.text :
{
*(.text)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
*(.gnu.linkonce.t*)
} =0x47ff041f
_etext = .;
PROVIDE (etext = .);
.fini : { *(.fini) } =0x47ff041f
.rodata : { *(.rodata) *(.gnu.linkonce.r*) }
.rodata1 : { *(.rodata1) }
.reginfo : { *(.reginfo) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = ALIGN(0x100000) + (. & (0x100000 - 1));
.data :
{
*(.data)
*(.gnu.linkonce.d*)
CONSTRUCTORS
}
.data1 : { *(.data1) }
.ctors :
{
*(.ctors)
}
.dtors :
{
*(.dtors)
}
.plt : { *(.plt) }
.got : { *(.got.plt) *(.got) }
.dynamic : { *(.dynamic) }
/* We want the small data sections together, so single-instruction offsets
can access them all, and initialized data all before uninitialized, so
we can shorten the on-disk segment size. */
.sdata : { *(.sdata) }
_edata = .;
PROVIDE (edata = .);
__bss_start = .;
.sbss : { *(.sbss) *(.scommon) }
.bss :
{
*(.dynbss)
*(.bss)
*(COMMON)
}
_end = . ;
PROVIDE (end = .);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* These must appear regardless of . */
}

910
audio/audio.c Normal file
View File

@@ -0,0 +1,910 @@
/*
* QEMU Audio subsystem
*
* Copyright (c) 2003-2004 Vassili Karpov (malc)
*
* 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 <assert.h>
#include "vl.h"
#define USE_WAV_AUDIO
#include "audio/audio_int.h"
#define dolog(...) AUD_log ("audio", __VA_ARGS__)
#ifdef DEBUG
#define ldebug(...) dolog (__VA_ARGS__)
#else
#define ldebug(...)
#endif
#define QC_AUDIO_DRV "QEMU_AUDIO_DRV"
#define QC_VOICES "QEMU_VOICES"
#define QC_FIXED_FORMAT "QEMU_FIXED_FORMAT"
#define QC_FIXED_FREQ "QEMU_FIXED_FREQ"
static HWVoice *hw_voices;
AudioState audio_state = {
1, /* use fixed settings */
44100, /* fixed frequency */
2, /* fixed channels */
AUD_FMT_S16, /* fixed format */
1, /* number of hw voices */
-1 /* voice size */
};
/* http://www.df.lth.se/~john_e/gems/gem002d.html */
/* http://www.multi-platforms.com/Tips/PopCount.htm */
uint32_t popcount (uint32_t u)
{
u = ((u&0x55555555) + ((u>>1)&0x55555555));
u = ((u&0x33333333) + ((u>>2)&0x33333333));
u = ((u&0x0f0f0f0f) + ((u>>4)&0x0f0f0f0f));
u = ((u&0x00ff00ff) + ((u>>8)&0x00ff00ff));
u = ( u&0x0000ffff) + (u>>16);
return u;
}
inline uint32_t lsbindex (uint32_t u)
{
return popcount ((u&-u)-1);
}
int audio_get_conf_int (const char *key, int defval)
{
int val = defval;
char *strval;
strval = getenv (key);
if (strval) {
val = atoi (strval);
}
return val;
}
const char *audio_get_conf_str (const char *key, const char *defval)
{
const char *val = getenv (key);
if (!val)
return defval;
else
return val;
}
void AUD_log (const char *cap, const char *fmt, ...)
{
va_list ap;
fprintf (stderr, "%s: ", cap);
va_start (ap, fmt);
vfprintf (stderr, fmt, ap);
va_end (ap);
}
/*
* Soft Voice
*/
void pcm_sw_free_resources (SWVoice *sw)
{
if (sw->buf) qemu_free (sw->buf);
if (sw->rate) st_rate_stop (sw->rate);
sw->buf = NULL;
sw->rate = NULL;
}
int pcm_sw_alloc_resources (SWVoice *sw)
{
sw->buf = qemu_mallocz (sw->hw->samples * sizeof (st_sample_t));
if (!sw->buf)
return -1;
sw->rate = st_rate_start (sw->freq, sw->hw->freq);
if (!sw->rate) {
qemu_free (sw->buf);
sw->buf = NULL;
return -1;
}
return 0;
}
void pcm_sw_fini (SWVoice *sw)
{
pcm_sw_free_resources (sw);
}
int pcm_sw_init (SWVoice *sw, HWVoice *hw, int freq,
int nchannels, audfmt_e fmt)
{
int bits = 8, sign = 0;
switch (fmt) {
case AUD_FMT_S8:
sign = 1;
case AUD_FMT_U8:
break;
case AUD_FMT_S16:
sign = 1;
case AUD_FMT_U16:
bits = 16;
break;
}
sw->hw = hw;
sw->freq = freq;
sw->fmt = fmt;
sw->nchannels = nchannels;
sw->shift = (nchannels == 2) + (bits == 16);
sw->align = (1 << sw->shift) - 1;
sw->left = 0;
sw->pos = 0;
sw->wpos = 0;
sw->live = 0;
sw->ratio = (sw->hw->freq * ((int64_t) INT_MAX)) / sw->freq;
sw->bytes_per_second = sw->freq << sw->shift;
sw->conv = mixeng_conv[nchannels == 2][sign][bits == 16];
pcm_sw_free_resources (sw);
return pcm_sw_alloc_resources (sw);
}
/* Hard voice */
void pcm_hw_free_resources (HWVoice *hw)
{
if (hw->mix_buf)
qemu_free (hw->mix_buf);
hw->mix_buf = NULL;
}
int pcm_hw_alloc_resources (HWVoice *hw)
{
hw->mix_buf = qemu_mallocz (hw->samples * sizeof (st_sample_t));
if (!hw->mix_buf)
return -1;
return 0;
}
void pcm_hw_fini (HWVoice *hw)
{
if (hw->active) {
ldebug ("pcm_hw_fini: %d %d %d\n", hw->freq, hw->nchannels, hw->fmt);
pcm_hw_free_resources (hw);
hw->pcm_ops->fini (hw);
memset (hw, 0, audio_state.drv->voice_size);
}
}
void pcm_hw_gc (HWVoice *hw)
{
if (hw->nb_voices)
return;
pcm_hw_fini (hw);
}
int pcm_hw_get_live (HWVoice *hw)
{
int i, alive = 0, live = hw->samples;
for (i = 0; i < hw->nb_voices; i++) {
if (hw->pvoice[i]->live) {
live = audio_MIN (hw->pvoice[i]->live, live);
alive += 1;
}
}
if (alive)
return live;
else
return -1;
}
int pcm_hw_get_live2 (HWVoice *hw, int *nb_active)
{
int i, alive = 0, live = hw->samples;
*nb_active = 0;
for (i = 0; i < hw->nb_voices; i++) {
if (hw->pvoice[i]->live) {
if (hw->pvoice[i]->live < live) {
*nb_active = hw->pvoice[i]->active != 0;
live = hw->pvoice[i]->live;
}
alive += 1;
}
}
if (alive)
return live;
else
return -1;
}
void pcm_hw_dec_live (HWVoice *hw, int decr)
{
int i;
for (i = 0; i < hw->nb_voices; i++) {
if (hw->pvoice[i]->live) {
hw->pvoice[i]->live -= decr;
}
}
}
void pcm_hw_clear (HWVoice *hw, void *buf, int len)
{
if (!len)
return;
switch (hw->fmt) {
case AUD_FMT_S16:
case AUD_FMT_S8:
memset (buf, len << hw->shift, 0x00);
break;
case AUD_FMT_U8:
memset (buf, len << hw->shift, 0x80);
break;
case AUD_FMT_U16:
{
unsigned int i;
uint16_t *p = buf;
int shift = hw->nchannels - 1;
for (i = 0; i < len << shift; i++) {
p[i] = INT16_MAX;
}
}
break;
}
}
int pcm_hw_write (SWVoice *sw, void *buf, int size)
{
int hwsamples, samples, isamp, osamp, wpos, live, dead, left, swlim, blck;
int ret = 0, pos = 0;
if (!sw)
return size;
hwsamples = sw->hw->samples;
samples = size >> sw->shift;
if (!sw->live) {
sw->wpos = sw->hw->rpos;
}
wpos = sw->wpos;
live = sw->live;
dead = hwsamples - live;
swlim = (dead * ((int64_t) INT_MAX)) / sw->ratio;
swlim = audio_MIN (swlim, samples);
ldebug ("size=%d live=%d dead=%d swlim=%d wpos=%d\n",
size, live, dead, swlim, wpos);
if (swlim)
sw->conv (sw->buf, buf, swlim);
while (swlim) {
dead = hwsamples - live;
left = hwsamples - wpos;
blck = audio_MIN (dead, left);
if (!blck) {
/* dolog ("swlim=%d\n", swlim); */
break;
}
isamp = swlim;
osamp = blck;
st_rate_flow (sw->rate, sw->buf + pos, sw->hw->mix_buf + wpos, &isamp, &osamp);
ret += isamp;
swlim -= isamp;
pos += isamp;
live += osamp;
wpos = (wpos + osamp) % hwsamples;
}
sw->wpos = wpos;
sw->live = live;
return ret << sw->shift;
}
int pcm_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
{
int sign = 0, bits = 8;
pcm_hw_fini (hw);
ldebug ("pcm_hw_init: %d %d %d\n", freq, nchannels, fmt);
if (hw->pcm_ops->init (hw, freq, nchannels, fmt)) {
memset (hw, 0, audio_state.drv->voice_size);
return -1;
}
switch (hw->fmt) {
case AUD_FMT_S8:
sign = 1;
case AUD_FMT_U8:
break;
case AUD_FMT_S16:
sign = 1;
case AUD_FMT_U16:
bits = 16;
break;
}
hw->nb_voices = 0;
hw->active = 1;
hw->shift = (hw->nchannels == 2) + (bits == 16);
hw->bytes_per_second = hw->freq << hw->shift;
hw->align = (1 << hw->shift) - 1;
hw->samples = hw->bufsize >> hw->shift;
hw->clip = mixeng_clip[hw->nchannels == 2][sign][bits == 16];
if (pcm_hw_alloc_resources (hw)) {
pcm_hw_fini (hw);
return -1;
}
return 0;
}
static int dist (void *hw)
{
if (hw) {
return (((uint8_t *) hw - (uint8_t *) hw_voices)
/ audio_state.voice_size) + 1;
}
else {
return 0;
}
}
#define ADVANCE(hw) hw ? advance (hw, audio_state.voice_size) : hw_voices
HWVoice *pcm_hw_find_any (HWVoice *hw)
{
int i = dist (hw);
for (; i < audio_state.nb_hw_voices; i++) {
hw = ADVANCE (hw);
return hw;
}
return NULL;
}
HWVoice *pcm_hw_find_any_active (HWVoice *hw)
{
int i = dist (hw);
for (; i < audio_state.nb_hw_voices; i++) {
hw = ADVANCE (hw);
if (hw->active)
return hw;
}
return NULL;
}
HWVoice *pcm_hw_find_any_active_enabled (HWVoice *hw)
{
int i = dist (hw);
for (; i < audio_state.nb_hw_voices; i++) {
hw = ADVANCE (hw);
if (hw->active && hw->enabled)
return hw;
}
return NULL;
}
HWVoice *pcm_hw_find_any_passive (HWVoice *hw)
{
int i = dist (hw);
for (; i < audio_state.nb_hw_voices; i++) {
hw = ADVANCE (hw);
if (!hw->active)
return hw;
}
return NULL;
}
HWVoice *pcm_hw_find_specific (HWVoice *hw, int freq,
int nchannels, audfmt_e fmt)
{
while ((hw = pcm_hw_find_any_active (hw))) {
if (hw->freq == freq &&
hw->nchannels == nchannels &&
hw->fmt == fmt)
return hw;
}
return NULL;
}
HWVoice *pcm_hw_add (int freq, int nchannels, audfmt_e fmt)
{
HWVoice *hw;
if (audio_state.fixed_format) {
freq = audio_state.fixed_freq;
nchannels = audio_state.fixed_channels;
fmt = audio_state.fixed_fmt;
}
hw = pcm_hw_find_specific (NULL, freq, nchannels, fmt);
if (hw)
return hw;
hw = pcm_hw_find_any_passive (NULL);
if (hw) {
hw->pcm_ops = audio_state.drv->pcm_ops;
if (!hw->pcm_ops)
return NULL;
if (pcm_hw_init (hw, freq, nchannels, fmt)) {
pcm_hw_gc (hw);
return NULL;
}
else
return hw;
}
return pcm_hw_find_any (NULL);
}
int pcm_hw_add_sw (HWVoice *hw, SWVoice *sw)
{
SWVoice **pvoice = qemu_mallocz ((hw->nb_voices + 1) * sizeof (sw));
if (!pvoice)
return -1;
memcpy (pvoice, hw->pvoice, hw->nb_voices * sizeof (sw));
qemu_free (hw->pvoice);
hw->pvoice = pvoice;
hw->pvoice[hw->nb_voices++] = sw;
return 0;
}
int pcm_hw_del_sw (HWVoice *hw, SWVoice *sw)
{
int i, j;
if (hw->nb_voices > 1) {
SWVoice **pvoice = qemu_mallocz ((hw->nb_voices - 1) * sizeof (sw));
if (!pvoice) {
dolog ("Can not maintain consistent state (not enough memory)\n");
return -1;
}
for (i = 0, j = 0; i < hw->nb_voices; i++) {
if (j >= hw->nb_voices - 1) {
dolog ("Can not maintain consistent state "
"(invariant violated)\n");
return -1;
}
if (hw->pvoice[i] != sw)
pvoice[j++] = hw->pvoice[i];
}
qemu_free (hw->pvoice);
hw->pvoice = pvoice;
hw->nb_voices -= 1;
}
else {
qemu_free (hw->pvoice);
hw->pvoice = NULL;
hw->nb_voices = 0;
}
return 0;
}
SWVoice *pcm_create_voice_pair (int freq, int nchannels, audfmt_e fmt)
{
SWVoice *sw;
HWVoice *hw;
sw = qemu_mallocz (sizeof (*sw));
if (!sw)
goto err1;
hw = pcm_hw_add (freq, nchannels, fmt);
if (!hw)
goto err2;
if (pcm_hw_add_sw (hw, sw))
goto err3;
if (pcm_sw_init (sw, hw, freq, nchannels, fmt))
goto err4;
return sw;
err4:
pcm_hw_del_sw (hw, sw);
err3:
pcm_hw_gc (hw);
err2:
qemu_free (sw);
err1:
return NULL;
}
SWVoice *AUD_open (SWVoice *sw, const char *name,
int freq, int nchannels, audfmt_e fmt)
{
if (!audio_state.drv) {
return NULL;
}
if (sw && freq == sw->freq && sw->nchannels == nchannels && sw->fmt == fmt) {
return sw;
}
if (sw) {
ldebug ("Different format %s %d %d %d\n",
name,
sw->freq == freq,
sw->nchannels == nchannels,
sw->fmt == fmt);
}
if (nchannels != 1 && nchannels != 2) {
dolog ("Bogus channel count %d for voice %s\n", nchannels, name);
return NULL;
}
if (!audio_state.fixed_format && sw) {
pcm_sw_fini (sw);
pcm_hw_del_sw (sw->hw, sw);
pcm_hw_gc (sw->hw);
if (sw->name) {
qemu_free (sw->name);
sw->name = NULL;
}
qemu_free (sw);
sw = NULL;
}
if (sw) {
HWVoice *hw = sw->hw;
if (!hw) {
dolog ("Internal logic error voice %s has no hardware store\n",
name);
return sw;
}
if (pcm_sw_init (sw, hw, freq, nchannels, fmt)) {
pcm_sw_fini (sw);
pcm_hw_del_sw (hw, sw);
pcm_hw_gc (hw);
if (sw->name) {
qemu_free (sw->name);
sw->name = NULL;
}
qemu_free (sw);
return NULL;
}
}
else {
sw = pcm_create_voice_pair (freq, nchannels, fmt);
if (!sw) {
dolog ("Failed to create voice %s\n", name);
return NULL;
}
}
if (sw->name) {
qemu_free (sw->name);
sw->name = NULL;
}
sw->name = qemu_strdup (name);
return sw;
}
void AUD_close (SWVoice *sw)
{
if (!sw)
return;
pcm_sw_fini (sw);
pcm_hw_del_sw (sw->hw, sw);
pcm_hw_gc (sw->hw);
if (sw->name) {
qemu_free (sw->name);
sw->name = NULL;
}
qemu_free (sw);
}
int AUD_write (SWVoice *sw, void *buf, int size)
{
int bytes;
if (!sw->hw->enabled)
dolog ("Writing to disabled voice %s\n", sw->name);
bytes = sw->hw->pcm_ops->write (sw, buf, size);
return bytes;
}
void AUD_run (void)
{
HWVoice *hw = NULL;
while ((hw = pcm_hw_find_any_active_enabled (hw))) {
int i;
if (hw->pending_disable && pcm_hw_get_live (hw) <= 0) {
hw->enabled = 0;
hw->pcm_ops->ctl (hw, VOICE_DISABLE);
for (i = 0; i < hw->nb_voices; i++) {
hw->pvoice[i]->live = 0;
/* hw->pvoice[i]->old_ticks = 0; */
}
continue;
}
hw->pcm_ops->run (hw);
assert (hw->rpos < hw->samples);
for (i = 0; i < hw->nb_voices; i++) {
SWVoice *sw = hw->pvoice[i];
if (!sw->active && !sw->live && sw->old_ticks) {
int64_t delta = qemu_get_clock (vm_clock) - sw->old_ticks;
if (delta > audio_state.ticks_threshold) {
ldebug ("resetting old_ticks for %s\n", sw->name);
sw->old_ticks = 0;
}
}
}
}
}
int AUD_get_free (SWVoice *sw)
{
int free;
if (!sw)
return 4096;
free = ((sw->hw->samples - sw->live) << sw->hw->shift) * sw->ratio
/ INT_MAX;
free &= ~sw->hw->align;
if (!free) return 0;
return free;
}
int AUD_get_buffer_size (SWVoice *sw)
{
return sw->hw->bufsize;
}
void AUD_adjust (SWVoice *sw, int bytes)
{
if (!sw)
return;
sw->old_ticks += (ticks_per_sec * (int64_t) bytes) / sw->bytes_per_second;
}
void AUD_reset (SWVoice *sw)
{
sw->active = 0;
sw->old_ticks = 0;
}
int AUD_calc_elapsed (SWVoice *sw)
{
int64_t now, delta, bytes;
int dead, swlim;
if (!sw)
return 0;
now = qemu_get_clock (vm_clock);
delta = now - sw->old_ticks;
bytes = (delta * sw->bytes_per_second) / ticks_per_sec;
if (delta < 0) {
dolog ("whoops delta(<0)=%lld\n", delta);
return 0;
}
dead = sw->hw->samples - sw->live;
swlim = ((dead * (int64_t) INT_MAX) / sw->ratio);
if (bytes > swlim) {
return swlim;
}
else {
return bytes;
}
}
void AUD_enable (SWVoice *sw, int on)
{
int i;
HWVoice *hw;
if (!sw)
return;
hw = sw->hw;
if (on) {
if (!sw->live)
sw->wpos = sw->hw->rpos;
if (!sw->old_ticks) {
sw->old_ticks = qemu_get_clock (vm_clock);
}
}
if (sw->active != on) {
if (on) {
hw->pending_disable = 0;
if (!hw->enabled) {
hw->enabled = 1;
for (i = 0; i < hw->nb_voices; i++) {
ldebug ("resetting voice\n");
sw = hw->pvoice[i];
sw->old_ticks = qemu_get_clock (vm_clock);
}
hw->pcm_ops->ctl (hw, VOICE_ENABLE);
}
}
else {
if (hw->enabled && !hw->pending_disable) {
int nb_active = 0;
for (i = 0; i < hw->nb_voices; i++) {
nb_active += hw->pvoice[i]->active != 0;
}
if (nb_active == 1) {
hw->pending_disable = 1;
}
}
}
sw->active = on;
}
}
static struct audio_output_driver *drvtab[] = {
#ifdef CONFIG_OSS
&oss_output_driver,
#endif
#ifdef CONFIG_FMOD
&fmod_output_driver,
#endif
#ifdef CONFIG_SDL
&sdl_output_driver,
#endif
&no_output_driver,
#ifdef USE_WAV_AUDIO
&wav_output_driver,
#endif
};
static int voice_init (struct audio_output_driver *drv)
{
audio_state.opaque = drv->init ();
if (audio_state.opaque) {
if (audio_state.nb_hw_voices > drv->max_voices) {
dolog ("`%s' does not support %d multiple hardware channels\n"
"Resetting to %d\n",
drv->name, audio_state.nb_hw_voices, drv->max_voices);
audio_state.nb_hw_voices = drv->max_voices;
}
hw_voices = qemu_mallocz (audio_state.nb_hw_voices * drv->voice_size);
if (hw_voices) {
audio_state.drv = drv;
return 1;
}
else {
dolog ("Not enough memory for %d `%s' voices (each %d bytes)\n",
audio_state.nb_hw_voices, drv->name, drv->voice_size);
drv->fini (audio_state.opaque);
return 0;
}
}
else {
dolog ("Could not init `%s' audio\n", drv->name);
return 0;
}
}
static void audio_vm_stop_handler (void *opaque, int reason)
{
HWVoice *hw = NULL;
while ((hw = pcm_hw_find_any (hw))) {
if (!hw->pcm_ops)
continue;
hw->pcm_ops->ctl (hw, reason ? VOICE_ENABLE : VOICE_DISABLE);
}
}
static void audio_atexit (void)
{
HWVoice *hw = NULL;
while ((hw = pcm_hw_find_any (hw))) {
if (!hw->pcm_ops)
continue;
hw->pcm_ops->ctl (hw, VOICE_DISABLE);
hw->pcm_ops->fini (hw);
}
audio_state.drv->fini (audio_state.opaque);
}
static void audio_save (QEMUFile *f, void *opaque)
{
}
static int audio_load (QEMUFile *f, void *opaque, int version_id)
{
if (version_id != 1)
return -EINVAL;
return 0;
}
void AUD_init (void)
{
int i;
int done = 0;
const char *drvname;
audio_state.fixed_format =
!!audio_get_conf_int (QC_FIXED_FORMAT, audio_state.fixed_format);
audio_state.fixed_freq =
audio_get_conf_int (QC_FIXED_FREQ, audio_state.fixed_freq);
audio_state.nb_hw_voices =
audio_get_conf_int (QC_VOICES, audio_state.nb_hw_voices);
if (audio_state.nb_hw_voices <= 0) {
dolog ("Bogus number of voices %d, resetting to 1\n",
audio_state.nb_hw_voices);
}
drvname = audio_get_conf_str (QC_AUDIO_DRV, NULL);
if (drvname) {
int found = 0;
for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
if (!strcmp (drvname, drvtab[i]->name)) {
done = voice_init (drvtab[i]);
found = 1;
break;
}
}
if (!found) {
dolog ("Unknown audio driver `%s'\n", drvname);
}
}
qemu_add_vm_stop_handler (audio_vm_stop_handler, NULL);
atexit (audio_atexit);
if (!done) {
for (i = 0; !done && i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
if (drvtab[i]->can_be_default)
done = voice_init (drvtab[i]);
}
}
audio_state.ticks_threshold = ticks_per_sec / 50;
audio_state.freq_threshold = 100;
register_savevm ("audio", 0, 1, audio_save, audio_load, NULL);
if (!done) {
dolog ("Can not initialize audio subsystem\n");
voice_init (&no_output_driver);
}
}

65
audio/audio.h Normal file
View File

@@ -0,0 +1,65 @@
/*
* QEMU Audio subsystem header
*
* Copyright (c) 2003-2004 Vassili Karpov (malc)
*
* 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 QEMU_AUDIO_H
#define QEMU_AUDIO_H
#include "mixeng.h"
typedef enum {
AUD_FMT_U8,
AUD_FMT_S8,
AUD_FMT_U16,
AUD_FMT_S16
} audfmt_e;
typedef struct SWVoice SWVoice;
SWVoice * AUD_open (SWVoice *sw, const char *name, int freq,
int nchannels, audfmt_e fmt);
void AUD_init (void);
void AUD_log (const char *cap, const char *fmt, ...)
__attribute__ ((__format__ (__printf__, 2, 3)));;
void AUD_close (SWVoice *sw);
int AUD_write (SWVoice *sw, void *pcm_buf, int size);
void AUD_adjust (SWVoice *sw, int leftover);
void AUD_reset (SWVoice *sw);
int AUD_get_free (SWVoice *sw);
int AUD_get_buffer_size (SWVoice *sw);
void AUD_run (void);
void AUD_enable (SWVoice *sw, int on);
int AUD_calc_elapsed (SWVoice *sw);
static inline void *advance (void *p, int incr)
{
uint8_t *d = p;
return (d + incr);
}
uint32_t popcount (uint32_t u);
inline uint32_t lsbindex (uint32_t u);
#define audio_MIN(a, b) ((a)>(b)?(b):(a))
#define audio_MAX(a, b) ((a)<(b)?(b):(a))
#endif /* audio.h */

164
audio/audio_int.h Normal file
View File

@@ -0,0 +1,164 @@
/*
* QEMU Audio subsystem header
*
* Copyright (c) 2003-2004 Vassili Karpov (malc)
*
* 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 QEMU_AUDIO_INT_H
#define QEMU_AUDIO_INT_H
#include "vl.h"
struct pcm_ops;
typedef struct HWVoice {
int active;
int enabled;
int pending_disable;
int valid;
int freq;
f_sample *clip;
audfmt_e fmt;
int nchannels;
int align;
int shift;
int rpos;
int bufsize;
int bytes_per_second;
st_sample_t *mix_buf;
int samples;
int64_t old_ticks;
int nb_voices;
struct SWVoice **pvoice;
struct pcm_ops *pcm_ops;
} HWVoice;
extern struct pcm_ops no_pcm_ops;
extern struct audio_output_driver no_output_driver;
extern struct pcm_ops oss_pcm_ops;
extern struct audio_output_driver oss_output_driver;
extern struct pcm_ops sdl_pcm_ops;
extern struct audio_output_driver sdl_output_driver;
extern struct pcm_ops wav_pcm_ops;
extern struct audio_output_driver wav_output_driver;
extern struct pcm_ops fmod_pcm_ops;
extern struct audio_output_driver fmod_output_driver;
struct audio_output_driver {
const char *name;
void *(*init) (void);
void (*fini) (void *);
struct pcm_ops *pcm_ops;
int can_be_default;
int max_voices;
int voice_size;
};
typedef struct AudioState {
int fixed_format;
int fixed_freq;
int fixed_channels;
int fixed_fmt;
int nb_hw_voices;
int voice_size;
int64_t ticks_threshold;
int freq_threshold;
void *opaque;
struct audio_output_driver *drv;
} AudioState;
extern AudioState audio_state;
struct SWVoice {
int freq;
audfmt_e fmt;
int nchannels;
int shift;
int align;
t_sample *conv;
int left;
int pos;
int bytes_per_second;
int64_t ratio;
st_sample_t *buf;
void *rate;
int wpos;
int live;
int active;
int64_t old_ticks;
HWVoice *hw;
char *name;
};
struct pcm_ops {
int (*init) (HWVoice *hw, int freq, int nchannels, audfmt_e fmt);
void (*fini) (HWVoice *hw);
void (*run) (HWVoice *hw);
int (*write) (SWVoice *sw, void *buf, int size);
int (*ctl) (HWVoice *hw, int cmd, ...);
};
void pcm_sw_free_resources (SWVoice *sw);
int pcm_sw_alloc_resources (SWVoice *sw);
void pcm_sw_fini (SWVoice *sw);
int pcm_sw_init (SWVoice *sw, HWVoice *hw, int freq,
int nchannels, audfmt_e fmt);
void pcm_hw_clear (HWVoice *hw, void *buf, int len);
HWVoice * pcm_hw_find_any (HWVoice *hw);
HWVoice * pcm_hw_find_any_active (HWVoice *hw);
HWVoice * pcm_hw_find_any_passive (HWVoice *hw);
HWVoice * pcm_hw_find_specific (HWVoice *hw, int freq,
int nchannels, audfmt_e fmt);
HWVoice * pcm_hw_add (int freq, int nchannels, audfmt_e fmt);
int pcm_hw_add_sw (HWVoice *hw, SWVoice *sw);
int pcm_hw_del_sw (HWVoice *hw, SWVoice *sw);
SWVoice * pcm_create_voice_pair (int freq, int nchannels, audfmt_e fmt);
void pcm_hw_free_resources (HWVoice *hw);
int pcm_hw_alloc_resources (HWVoice *hw);
void pcm_hw_fini (HWVoice *hw);
void pcm_hw_gc (HWVoice *hw);
int pcm_hw_get_live (HWVoice *hw);
int pcm_hw_get_live2 (HWVoice *hw, int *nb_active);
void pcm_hw_dec_live (HWVoice *hw, int decr);
int pcm_hw_write (SWVoice *sw, void *buf, int len);
int audio_get_conf_int (const char *key, int defval);
const char *audio_get_conf_str (const char *key, const char *defval);
struct audio_output_driver;
#define VOICE_ENABLE 1
#define VOICE_DISABLE 2
#endif /* audio_int.h */

469
audio/fmodaudio.c Normal file
View File

@@ -0,0 +1,469 @@
/*
* QEMU FMOD audio output driver
*
* Copyright (c) 2004 Vassili Karpov (malc)
*
* 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 <fmod.h>
#include <fmod_errors.h>
#include "vl.h"
#include "audio/audio_int.h"
typedef struct FMODVoice {
HWVoice hw;
unsigned int old_pos;
FSOUND_SAMPLE *fmod_sample;
int channel;
} FMODVoice;
#define dolog(...) AUD_log ("fmod", __VA_ARGS__)
#ifdef DEBUG
#define ldebug(...) dolog (__VA_ARGS__)
#else
#define ldebug(...)
#endif
#define QC_FMOD_DRV "QEMU_FMOD_DRV"
#define QC_FMOD_FREQ "QEMU_FMOD_FREQ"
#define QC_FMOD_SAMPLES "QEMU_FMOD_SAMPLES"
#define QC_FMOD_CHANNELS "QEMU_FMOD_CHANNELS"
#define QC_FMOD_BUFSIZE "QEMU_FMOD_BUFSIZE"
#define QC_FMOD_THRESHOLD "QEMU_FMOD_THRESHOLD"
static struct {
int nb_samples;
int freq;
int nb_channels;
int bufsize;
int threshold;
} conf = {
2048,
44100,
1,
0,
128
};
#define errstr() FMOD_ErrorString (FSOUND_GetError ())
static int fmod_hw_write (SWVoice *sw, void *buf, int len)
{
return pcm_hw_write (sw, buf, len);
}
static void fmod_clear_sample (FMODVoice *fmd)
{
HWVoice *hw = &fmd->hw;
int status;
void *p1 = 0, *p2 = 0;
unsigned int len1 = 0, len2 = 0;
status = FSOUND_Sample_Lock (
fmd->fmod_sample,
0,
hw->samples << hw->shift,
&p1,
&p2,
&len1,
&len2
);
if (!status) {
dolog ("Failed to lock sample\nReason: %s\n", errstr ());
return;
}
if ((len1 & hw->align) || (len2 & hw->align)) {
dolog ("Locking sample returned unaligned length %d, %d\n",
len1, len2);
goto fail;
}
if (len1 + len2 != hw->samples << hw->shift) {
dolog ("Locking sample returned incomplete length %d, %d\n",
len1 + len2, hw->samples << hw->shift);
goto fail;
}
pcm_hw_clear (hw, p1, hw->samples);
fail:
status = FSOUND_Sample_Unlock (fmd->fmod_sample, p1, p2, len1, len2);
if (!status) {
dolog ("Failed to unlock sample\nReason: %s\n", errstr ());
}
}
static int fmod_write_sample (HWVoice *hw, uint8_t *dst, st_sample_t *src,
int src_size, int src_pos, int dst_len)
{
int src_len1 = dst_len, src_len2 = 0, pos = src_pos + dst_len;
st_sample_t *src1 = src + src_pos, *src2 = 0;
if (src_pos + dst_len > src_size) {
src_len1 = src_size - src_pos;
src2 = src;
src_len2 = dst_len - src_len1;
pos = src_len2;
}
if (src_len1) {
hw->clip (dst, src1, src_len1);
memset (src1, 0, src_len1 * sizeof (st_sample_t));
advance (dst, src_len1);
}
if (src_len2) {
hw->clip (dst, src2, src_len2);
memset (src2, 0, src_len2 * sizeof (st_sample_t));
}
return pos;
}
static int fmod_unlock_sample (FMODVoice *fmd, void *p1, void *p2,
unsigned int blen1, unsigned int blen2)
{
int status = FSOUND_Sample_Unlock (fmd->fmod_sample, p1, p2, blen1, blen2);
if (!status) {
dolog ("Failed to unlock sample\nReason: %s\n", errstr ());
return -1;
}
return 0;
}
static int fmod_lock_sample (FMODVoice *fmd, int pos, int len,
void **p1, void **p2,
unsigned int *blen1, unsigned int *blen2)
{
HWVoice *hw = &fmd->hw;
int status;
status = FSOUND_Sample_Lock (
fmd->fmod_sample,
pos << hw->shift,
len << hw->shift,
p1,
p2,
blen1,
blen2
);
if (!status) {
dolog ("Failed to lock sample\nReason: %s\n", errstr ());
return -1;
}
if ((*blen1 & hw->align) || (*blen2 & hw->align)) {
dolog ("Locking sample returned unaligned length %d, %d\n",
*blen1, *blen2);
fmod_unlock_sample (fmd, *p1, *p2, *blen1, *blen2);
return -1;
}
return 0;
}
static void fmod_hw_run (HWVoice *hw)
{
FMODVoice *fmd = (FMODVoice *) hw;
int rpos, live, decr;
void *p1 = 0, *p2 = 0;
unsigned int blen1 = 0, blen2 = 0;
unsigned int len1 = 0, len2 = 0;
int nb_active;
live = pcm_hw_get_live2 (hw, &nb_active);
if (live <= 0) {
return;
}
if (!hw->pending_disable
&& nb_active
&& conf.threshold
&& live <= conf.threshold) {
ldebug ("live=%d nb_active=%d\n", live, nb_active);
return;
}
decr = live;
#if 1
if (fmd->channel >= 0) {
int pos2 = (fmd->old_pos + decr) % hw->samples;
int pos = FSOUND_GetCurrentPosition (fmd->channel);
if (fmd->old_pos < pos && pos2 >= pos) {
decr = pos - fmd->old_pos - (pos2 == pos) - 1;
}
else if (fmd->old_pos > pos && pos2 >= pos && pos2 < fmd->old_pos) {
decr = (hw->samples - fmd->old_pos) + pos - (pos2 == pos) - 1;
}
/* ldebug ("pos=%d pos2=%d old=%d live=%d decr=%d\n", */
/* pos, pos2, fmd->old_pos, live, decr); */
}
#endif
if (decr <= 0) {
return;
}
if (fmod_lock_sample (fmd, fmd->old_pos, decr, &p1, &p2, &blen1, &blen2)) {
return;
}
len1 = blen1 >> hw->shift;
len2 = blen2 >> hw->shift;
ldebug ("%p %p %d %d %d %d\n", p1, p2, len1, len2, blen1, blen2);
decr = len1 + len2;
rpos = hw->rpos;
if (len1) {
rpos = fmod_write_sample (hw, p1, hw->mix_buf, hw->samples, rpos, len1);
}
if (len2) {
rpos = fmod_write_sample (hw, p2, hw->mix_buf, hw->samples, rpos, len2);
}
fmod_unlock_sample (fmd, p1, p2, blen1, blen2);
pcm_hw_dec_live (hw, decr);
hw->rpos = rpos % hw->samples;
fmd->old_pos = (fmd->old_pos + decr) % hw->samples;
}
static int AUD_to_fmodfmt (audfmt_e fmt, int stereo)
{
int mode = FSOUND_LOOP_NORMAL;
switch (fmt) {
case AUD_FMT_S8:
mode |= FSOUND_SIGNED | FSOUND_8BITS;
break;
case AUD_FMT_U8:
mode |= FSOUND_UNSIGNED | FSOUND_8BITS;
break;
case AUD_FMT_S16:
mode |= FSOUND_SIGNED | FSOUND_16BITS;
break;
case AUD_FMT_U16:
mode |= FSOUND_UNSIGNED | FSOUND_16BITS;
break;
default:
dolog ("Internal logic error: Bad audio format %d\nAborting\n", fmt);
exit (EXIT_FAILURE);
}
mode |= stereo ? FSOUND_STEREO : FSOUND_MONO;
return mode;
}
static void fmod_hw_fini (HWVoice *hw)
{
FMODVoice *fmd = (FMODVoice *) hw;
if (fmd->fmod_sample) {
FSOUND_Sample_Free (fmd->fmod_sample);
fmd->fmod_sample = 0;
if (fmd->channel >= 0) {
FSOUND_StopSound (fmd->channel);
}
}
}
static int fmod_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
{
int bits16, mode, channel;
FMODVoice *fmd = (FMODVoice *) hw;
mode = AUD_to_fmodfmt (fmt, nchannels == 2 ? 1 : 0);
fmd->fmod_sample = FSOUND_Sample_Alloc (
FSOUND_FREE, /* index */
conf.nb_samples, /* length */
mode, /* mode */
freq, /* freq */
255, /* volume */
128, /* pan */
255 /* priority */
);
if (!fmd->fmod_sample) {
dolog ("Failed to allocate FMOD sample\nReason: %s\n", errstr ());
return -1;
}
channel = FSOUND_PlaySoundEx (FSOUND_FREE, fmd->fmod_sample, 0, 1);
if (channel < 0) {
dolog ("Failed to start playing sound\nReason: %s\n", errstr ());
FSOUND_Sample_Free (fmd->fmod_sample);
return -1;
}
fmd->channel = channel;
hw->freq = freq;
hw->fmt = fmt;
hw->nchannels = nchannels;
bits16 = fmt == AUD_FMT_U16 || fmt == AUD_FMT_S16;
hw->bufsize = conf.nb_samples << (nchannels == 2) << bits16;
return 0;
}
static int fmod_hw_ctl (HWVoice *hw, int cmd, ...)
{
int status;
FMODVoice *fmd = (FMODVoice *) hw;
switch (cmd) {
case VOICE_ENABLE:
fmod_clear_sample (fmd);
status = FSOUND_SetPaused (fmd->channel, 0);
if (!status) {
dolog ("Failed to resume channel %d\nReason: %s\n",
fmd->channel, errstr ());
}
break;
case VOICE_DISABLE:
status = FSOUND_SetPaused (fmd->channel, 1);
if (!status) {
dolog ("Failed to pause channel %d\nReason: %s\n",
fmd->channel, errstr ());
}
break;
}
return 0;
}
static struct {
const char *name;
int type;
} drvtab[] = {
{"none", FSOUND_OUTPUT_NOSOUND},
#ifdef _WIN32
{"winmm", FSOUND_OUTPUT_WINMM},
{"dsound", FSOUND_OUTPUT_DSOUND},
{"a3d", FSOUND_OUTPUT_A3D},
{"asio", FSOUND_OUTPUT_ASIO},
#endif
#ifdef __linux__
{"oss", FSOUND_OUTPUT_OSS},
{"alsa", FSOUND_OUTPUT_ALSA},
{"esd", FSOUND_OUTPUT_ESD},
#endif
#ifdef __APPLE__
{"mac", FSOUND_OUTPUT_MAC},
#endif
#if 0
{"xbox", FSOUND_OUTPUT_XBOX},
{"ps2", FSOUND_OUTPUT_PS2},
{"gcube", FSOUND_OUTPUT_GC},
#endif
{"nort", FSOUND_OUTPUT_NOSOUND_NONREALTIME}
};
static void *fmod_audio_init (void)
{
int i;
double ver;
int status;
int output_type = -1;
const char *drv = audio_get_conf_str (QC_FMOD_DRV, NULL);
ver = FSOUND_GetVersion ();
if (ver < FMOD_VERSION) {
dolog ("Wrong FMOD version %f, need at least %f\n", ver, FMOD_VERSION);
return NULL;
}
if (drv) {
int found = 0;
for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
if (!strcmp (drv, drvtab[i].name)) {
output_type = drvtab[i].type;
found = 1;
break;
}
}
if (!found) {
dolog ("Unknown FMOD output driver `%s'\n", drv);
}
}
if (output_type != -1) {
status = FSOUND_SetOutput (output_type);
if (!status) {
dolog ("FSOUND_SetOutput(%d) failed\nReason: %s\n",
output_type, errstr ());
return NULL;
}
}
conf.freq = audio_get_conf_int (QC_FMOD_FREQ, conf.freq);
conf.nb_samples = audio_get_conf_int (QC_FMOD_SAMPLES, conf.nb_samples);
conf.nb_channels =
audio_get_conf_int (QC_FMOD_CHANNELS,
(audio_state.nb_hw_voices > 1
? audio_state.nb_hw_voices
: conf.nb_channels));
conf.bufsize = audio_get_conf_int (QC_FMOD_BUFSIZE, conf.bufsize);
conf.threshold = audio_get_conf_int (QC_FMOD_THRESHOLD, conf.threshold);
if (conf.bufsize) {
status = FSOUND_SetBufferSize (conf.bufsize);
if (!status) {
dolog ("FSOUND_SetBufferSize (%d) failed\nReason: %s\n",
conf.bufsize, errstr ());
}
}
status = FSOUND_Init (conf.freq, conf.nb_channels, 0);
if (!status) {
dolog ("FSOUND_Init failed\nReason: %s\n", errstr ());
return NULL;
}
return &conf;
}
static void fmod_audio_fini (void *opaque)
{
FSOUND_Close ();
}
struct pcm_ops fmod_pcm_ops = {
fmod_hw_init,
fmod_hw_fini,
fmod_hw_run,
fmod_hw_write,
fmod_hw_ctl
};
struct audio_output_driver fmod_output_driver = {
"fmod",
fmod_audio_init,
fmod_audio_fini,
&fmod_pcm_ops,
1,
INT_MAX,
sizeof (FMODVoice)
};

255
audio/mixeng.c Normal file
View File

@@ -0,0 +1,255 @@
/*
* QEMU Mixing engine
*
* Copyright (c) 2004 Vassili Karpov (malc)
* Copyright (c) 1998 Fabrice Bellard
*
* 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 "vl.h"
//#define DEBUG_FP
#include "audio/mixeng.h"
#define IN_T int8_t
#define IN_MIN CHAR_MIN
#define IN_MAX CHAR_MAX
#define SIGNED
#include "mixeng_template.h"
#undef SIGNED
#undef IN_MAX
#undef IN_MIN
#undef IN_T
#define IN_T uint8_t
#define IN_MIN 0
#define IN_MAX UCHAR_MAX
#include "mixeng_template.h"
#undef IN_MAX
#undef IN_MIN
#undef IN_T
#define IN_T int16_t
#define IN_MIN SHRT_MIN
#define IN_MAX SHRT_MAX
#define SIGNED
#include "mixeng_template.h"
#undef SIGNED
#undef IN_MAX
#undef IN_MIN
#undef IN_T
#define IN_T uint16_t
#define IN_MIN 0
#define IN_MAX USHRT_MAX
#include "mixeng_template.h"
#undef IN_MAX
#undef IN_MIN
#undef IN_T
t_sample *mixeng_conv[2][2][2] = {
{
{
conv_uint8_t_to_mono,
conv_uint16_t_to_mono
},
{
conv_int8_t_to_mono,
conv_int16_t_to_mono
}
},
{
{
conv_uint8_t_to_stereo,
conv_uint16_t_to_stereo
},
{
conv_int8_t_to_stereo,
conv_int16_t_to_stereo
}
}
};
f_sample *mixeng_clip[2][2][2] = {
{
{
clip_uint8_t_from_mono,
clip_uint16_t_from_mono
},
{
clip_int8_t_from_mono,
clip_int16_t_from_mono
}
},
{
{
clip_uint8_t_from_stereo,
clip_uint16_t_from_stereo
},
{
clip_int8_t_from_stereo,
clip_int16_t_from_stereo
}
}
};
/*
* August 21, 1998
* Copyright 1998 Fabrice Bellard.
*
* [Rewrote completly the code of Lance Norskog And Sundry
* Contributors with a more efficient algorithm.]
*
* This source code is freely redistributable and may be used for
* any purpose. This copyright notice must be maintained.
* Lance Norskog And Sundry Contributors are not responsible for
* the consequences of using this software.
*/
/*
* Sound Tools rate change effect file.
*/
/*
* Linear Interpolation.
*
* The use of fractional increment allows us to use no buffer. It
* avoid the problems at the end of the buffer we had with the old
* method which stored a possibly big buffer of size
* lcm(in_rate,out_rate).
*
* Limited to 16 bit samples and sampling frequency <= 65535 Hz. If
* the input & output frequencies are equal, a delay of one sample is
* introduced. Limited to processing 32-bit count worth of samples.
*
* 1 << FRAC_BITS evaluating to zero in several places. Changed with
* an (unsigned long) cast to make it safe. MarkMLl 2/1/99
*/
/* Private data */
typedef struct ratestuff {
uint64_t opos;
uint64_t opos_inc;
uint32_t ipos; /* position in the input stream (integer) */
st_sample_t ilast; /* last sample in the input stream */
} *rate_t;
/*
* Prepare processing.
*/
void *st_rate_start (int inrate, int outrate)
{
rate_t rate = (rate_t) qemu_mallocz (sizeof (struct ratestuff));
if (!rate) {
exit (EXIT_FAILURE);
}
if (inrate == outrate) {
// exit (EXIT_FAILURE);
}
if (inrate >= 65535 || outrate >= 65535) {
// exit (EXIT_FAILURE);
}
rate->opos = 0;
/* increment */
rate->opos_inc = (inrate * ((int64_t) UINT_MAX)) / outrate;
rate->ipos = 0;
rate->ilast.l = 0;
rate->ilast.r = 0;
return rate;
}
/*
* Processed signed long samples from ibuf to obuf.
* Return number of samples processed.
*/
void st_rate_flow (void *opaque, st_sample_t *ibuf, st_sample_t *obuf,
int *isamp, int *osamp)
{
rate_t rate = (rate_t) opaque;
st_sample_t *istart, *iend;
st_sample_t *ostart, *oend;
st_sample_t ilast, icur, out;
int64_t t;
ilast = rate->ilast;
istart = ibuf;
iend = ibuf + *isamp;
ostart = obuf;
oend = obuf + *osamp;
if (rate->opos_inc == 1ULL << 32) {
int i, n = *isamp > *osamp ? *osamp : *isamp;
for (i = 0; i < n; i++) {
obuf[i].l += ibuf[i].r;
obuf[i].r += ibuf[i].r;
}
*isamp = n;
*osamp = n;
return;
}
while (obuf < oend) {
/* Safety catch to make sure we have input samples. */
if (ibuf >= iend)
break;
/* read as many input samples so that ipos > opos */
while (rate->ipos <= (rate->opos >> 32)) {
ilast = *ibuf++;
rate->ipos++;
/* See if we finished the input buffer yet */
if (ibuf >= iend) goto the_end;
}
icur = *ibuf;
/* interpolate */
t = rate->opos & 0xffffffff;
out.l = (ilast.l * (INT_MAX - t) + icur.l * t) / INT_MAX;
out.r = (ilast.r * (INT_MAX - t) + icur.r * t) / INT_MAX;
/* output sample & increment position */
#if 0
*obuf++ = out;
#else
obuf->l += out.l;
obuf->r += out.r;
obuf += 1;
#endif
rate->opos += rate->opos_inc;
}
the_end:
*isamp = ibuf - istart;
*osamp = obuf - ostart;
rate->ilast = ilast;
}
void st_rate_stop (void *opaque)
{
qemu_free (opaque);
}

39
audio/mixeng.h Normal file
View File

@@ -0,0 +1,39 @@
/*
* QEMU Mixing engine header
*
* Copyright (c) 2004 Vassili Karpov (malc)
*
* 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 QEMU_MIXENG_H
#define QEMU_MIXENG_H
typedef void (t_sample) (void *dst, const void *src, int samples);
typedef void (f_sample) (void *dst, const void *src, int samples);
typedef struct { int64_t l; int64_t r; } st_sample_t;
extern t_sample *mixeng_conv[2][2][2];
extern f_sample *mixeng_clip[2][2][2];
void *st_rate_start (int inrate, int outrate);
void st_rate_flow (void *opaque, st_sample_t *ibuf, st_sample_t *obuf,
int *isamp, int *osamp);
void st_rate_stop (void *opaque);
#endif /* mixeng.h */

111
audio/mixeng_template.h Normal file
View File

@@ -0,0 +1,111 @@
/*
* QEMU Mixing engine
*
* Copyright (c) 2004 Vassili Karpov (malc)
*
* 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.
*/
/*
* Tusen tack till Mike Nordell
* dec++'ified by Dscho
*/
#ifdef SIGNED
#define HALFT IN_MAX
#define HALF IN_MAX
#else
#define HALFT ((IN_MAX)>>1)
#define HALF HALFT
#endif
static int64_t inline glue(conv_,IN_T) (IN_T v)
{
#ifdef SIGNED
return (INT_MAX*(int64_t)v)/HALF;
#else
return (INT_MAX*((int64_t)v-HALFT))/HALF;
#endif
}
static IN_T inline glue(clip_,IN_T) (int64_t v)
{
if (v >= INT_MAX)
return IN_MAX;
else if (v < -INT_MAX)
return IN_MIN;
#ifdef SIGNED
return (IN_T) (v*HALF/INT_MAX);
#else
return (IN_T) (v+INT_MAX/2)*HALF/INT_MAX;
#endif
}
static void glue(glue(conv_,IN_T),_to_stereo) (void *dst, const void *src,
int samples)
{
st_sample_t *out = (st_sample_t *) dst;
IN_T *in = (IN_T *) src;
while (samples--) {
out->l = glue(conv_,IN_T) (*in++);
out->r = glue(conv_,IN_T) (*in++);
out += 1;
}
}
static void glue(glue(conv_,IN_T),_to_mono) (void *dst, const void *src,
int samples)
{
st_sample_t *out = (st_sample_t *) dst;
IN_T *in = (IN_T *) src;
while (samples--) {
out->l = glue(conv_,IN_T) (in[0]);
out->r = out->l;
out += 1;
in += 1;
}
}
static void glue(glue(clip_,IN_T),_from_stereo) (void *dst, const void *src,
int samples)
{
st_sample_t *in = (st_sample_t *) src;
IN_T *out = (IN_T *) dst;
while (samples--) {
*out++ = glue(clip_,IN_T) (in->l);
*out++ = glue(clip_,IN_T) (in->r);
in += 1;
}
}
static void glue(glue(clip_,IN_T),_from_mono) (void *dst, const void *src,
int samples)
{
st_sample_t *in = (st_sample_t *) src;
IN_T *out = (IN_T *) dst;
while (samples--) {
*out++ = glue(clip_,IN_T) (in->l + in->r);
in += 1;
}
}
#undef HALF
#undef HALFT

130
audio/noaudio.c Normal file
View File

@@ -0,0 +1,130 @@
/*
* QEMU NULL audio output driver
*
* Copyright (c) 2004 Vassili Karpov (malc)
*
* 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 "vl.h"
#include "audio/audio_int.h"
typedef struct NoVoice {
HWVoice hw;
int64_t old_ticks;
} NoVoice;
#define dolog(...) AUD_log ("noaudio", __VA_ARGS__)
#ifdef DEBUG
#define ldebug(...) dolog (__VA_ARGS__)
#else
#define ldebug(...)
#endif
static void no_hw_run (HWVoice *hw)
{
NoVoice *no = (NoVoice *) hw;
int rpos, live, decr, samples;
uint8_t *dst;
st_sample_t *src;
int64_t now = qemu_get_clock (vm_clock);
int64_t ticks = now - no->old_ticks;
int64_t bytes = (ticks * hw->bytes_per_second) / ticks_per_sec;
if (bytes > INT_MAX)
samples = INT_MAX >> hw->shift;
else
samples = bytes >> hw->shift;
live = pcm_hw_get_live (hw);
if (live <= 0)
return;
no->old_ticks = now;
decr = audio_MIN (live, samples);
samples = decr;
rpos = hw->rpos;
while (samples) {
int left_till_end_samples = hw->samples - rpos;
int convert_samples = audio_MIN (samples, left_till_end_samples);
src = advance (hw->mix_buf, rpos * sizeof (st_sample_t));
memset (src, 0, convert_samples * sizeof (st_sample_t));
rpos = (rpos + convert_samples) % hw->samples;
samples -= convert_samples;
}
pcm_hw_dec_live (hw, decr);
hw->rpos = rpos;
}
static int no_hw_write (SWVoice *sw, void *buf, int len)
{
return pcm_hw_write (sw, buf, len);
}
static int no_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
{
NoVoice *no = (NoVoice *) hw;
hw->freq = freq;
hw->nchannels = nchannels;
hw->fmt = fmt;
hw->bufsize = 4096;
return 0;
}
static void no_hw_fini (HWVoice *hw)
{
(void) hw;
}
static int no_hw_ctl (HWVoice *hw, int cmd, ...)
{
(void) hw;
(void) cmd;
return 0;
}
static void *no_audio_init (void)
{
return &no_audio_init;
}
static void no_audio_fini (void *opaque)
{
}
struct pcm_ops no_pcm_ops = {
no_hw_init,
no_hw_fini,
no_hw_run,
no_hw_write,
no_hw_ctl
};
struct audio_output_driver no_output_driver = {
"none",
no_audio_init,
no_audio_fini,
&no_pcm_ops,
1,
1,
sizeof (NoVoice)
};

475
audio/ossaudio.c Normal file
View File

@@ -0,0 +1,475 @@
/*
* QEMU OSS audio output driver
*
* Copyright (c) 2003-2004 Vassili Karpov (malc)
*
* 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 <sys/mman.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
#include <assert.h>
#include "vl.h"
#include "audio/audio_int.h"
typedef struct OSSVoice {
HWVoice hw;
void *pcm_buf;
int fd;
int nfrags;
int fragsize;
int mmapped;
int old_optr;
} OSSVoice;
#define dolog(...) AUD_log ("oss", __VA_ARGS__)
#ifdef DEBUG
#define ldebug(...) dolog (__VA_ARGS__)
#else
#define ldebug(...)
#endif
#define QC_OSS_FRAGSIZE "QEMU_OSS_FRAGSIZE"
#define QC_OSS_NFRAGS "QEMU_OSS_NFRAGS"
#define QC_OSS_MMAP "QEMU_OSS_MMAP"
#define QC_OSS_DEV "QEMU_OSS_DEV"
#define errstr() strerror (errno)
static struct {
int try_mmap;
int nfrags;
int fragsize;
const char *dspname;
} conf = {
.try_mmap = 0,
.nfrags = 4,
.fragsize = 4096,
.dspname = "/dev/dsp"
};
struct oss_params {
int freq;
audfmt_e fmt;
int nchannels;
int nfrags;
int fragsize;
};
static int oss_hw_write (SWVoice *sw, void *buf, int len)
{
return pcm_hw_write (sw, buf, len);
}
static int AUD_to_ossfmt (audfmt_e fmt)
{
switch (fmt) {
case AUD_FMT_S8: return AFMT_S8;
case AUD_FMT_U8: return AFMT_U8;
case AUD_FMT_S16: return AFMT_S16_LE;
case AUD_FMT_U16: return AFMT_U16_LE;
default:
dolog ("Internal logic error: Bad audio format %d\nAborting\n", fmt);
exit (EXIT_FAILURE);
}
}
static int oss_to_audfmt (int fmt)
{
switch (fmt) {
case AFMT_S8: return AUD_FMT_S8;
case AFMT_U8: return AUD_FMT_U8;
case AFMT_S16_LE: return AUD_FMT_S16;
case AFMT_U16_LE: return AUD_FMT_U16;
default:
dolog ("Internal logic error: Unrecognized OSS audio format %d\n"
"Aborting\n",
fmt);
exit (EXIT_FAILURE);
}
}
#ifdef DEBUG_PCM
static void oss_dump_pcm_info (struct oss_params *req, struct oss_params *obt)
{
dolog ("parameter | requested value | obtained value\n");
dolog ("format | %10d | %10d\n", req->fmt, obt->fmt);
dolog ("channels | %10d | %10d\n", req->nchannels, obt->nchannels);
dolog ("frequency | %10d | %10d\n", req->freq, obt->freq);
dolog ("nfrags | %10d | %10d\n", req->nfrags, obt->nfrags);
dolog ("fragsize | %10d | %10d\n", req->fragsize, obt->fragsize);
}
#endif
static int oss_open (struct oss_params *req, struct oss_params *obt, int *pfd)
{
int fd;
int mmmmssss;
audio_buf_info abinfo;
int fmt, freq, nchannels;
const char *dspname = conf.dspname;
fd = open (dspname, O_RDWR | O_NONBLOCK);
if (-1 == fd) {
dolog ("Could not initialize audio hardware. Failed to open `%s':\n"
"Reason:%s\n",
dspname,
errstr ());
return -1;
}
freq = req->freq;
nchannels = req->nchannels;
fmt = req->fmt;
if (ioctl (fd, SNDCTL_DSP_SAMPLESIZE, &fmt)) {
dolog ("Could not initialize audio hardware\n"
"Failed to set sample size\n"
"Reason: %s\n",
errstr ());
goto err;
}
if (ioctl (fd, SNDCTL_DSP_CHANNELS, &nchannels)) {
dolog ("Could not initialize audio hardware\n"
"Failed to set number of channels\n"
"Reason: %s\n",
errstr ());
goto err;
}
if (ioctl (fd, SNDCTL_DSP_SPEED, &freq)) {
dolog ("Could not initialize audio hardware\n"
"Failed to set frequency\n"
"Reason: %s\n",
errstr ());
goto err;
}
if (ioctl (fd, SNDCTL_DSP_NONBLOCK)) {
dolog ("Could not initialize audio hardware\n"
"Failed to set non-blocking mode\n"
"Reason: %s\n",
errstr ());
goto err;
}
mmmmssss = (req->nfrags << 16) | lsbindex (req->fragsize);
if (ioctl (fd, SNDCTL_DSP_SETFRAGMENT, &mmmmssss)) {
dolog ("Could not initialize audio hardware\n"
"Failed to set buffer length (%d, %d)\n"
"Reason:%s\n",
conf.nfrags, conf.fragsize,
errstr ());
goto err;
}
if (ioctl (fd, SNDCTL_DSP_GETOSPACE, &abinfo)) {
dolog ("Could not initialize audio hardware\n"
"Failed to get buffer length\n"
"Reason:%s\n",
errstr ());
goto err;
}
obt->fmt = fmt;
obt->nchannels = nchannels;
obt->freq = freq;
obt->nfrags = abinfo.fragstotal;
obt->fragsize = abinfo.fragsize;
*pfd = fd;
if ((req->fmt != obt->fmt) ||
(req->nchannels != obt->nchannels) ||
(req->freq != obt->freq) ||
(req->fragsize != obt->fragsize) ||
(req->nfrags != obt->nfrags)) {
#ifdef DEBUG_PCM
dolog ("Audio parameters mismatch\n");
oss_dump_pcm_info (req, obt);
#endif
}
#ifdef DEBUG_PCM
oss_dump_pcm_info (req, obt);
#endif
return 0;
err:
close (fd);
return -1;
}
static void oss_hw_run (HWVoice *hw)
{
OSSVoice *oss = (OSSVoice *) hw;
int err, rpos, live, decr;
int samples;
uint8_t *dst;
st_sample_t *src;
struct audio_buf_info abinfo;
struct count_info cntinfo;
live = pcm_hw_get_live (hw);
if (live <= 0)
return;
if (oss->mmapped) {
int bytes;
err = ioctl (oss->fd, SNDCTL_DSP_GETOPTR, &cntinfo);
if (err < 0) {
dolog ("SNDCTL_DSP_GETOPTR failed\nReason: %s\n", errstr ());
return;
}
if (cntinfo.ptr == oss->old_optr) {
if (abs (hw->samples - live) < 64)
dolog ("overrun\n");
return;
}
if (cntinfo.ptr > oss->old_optr) {
bytes = cntinfo.ptr - oss->old_optr;
}
else {
bytes = hw->bufsize + cntinfo.ptr - oss->old_optr;
}
decr = audio_MIN (bytes >> hw->shift, live);
}
else {
err = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &abinfo);
if (err < 0) {
dolog ("SNDCTL_DSP_GETOSPACE failed\nReason: %s\n", errstr ());
return;
}
decr = audio_MIN (abinfo.bytes >> hw->shift, live);
if (decr <= 0)
return;
}
samples = decr;
rpos = hw->rpos;
while (samples) {
int left_till_end_samples = hw->samples - rpos;
int convert_samples = audio_MIN (samples, left_till_end_samples);
src = advance (hw->mix_buf, rpos * sizeof (st_sample_t));
dst = advance (oss->pcm_buf, rpos << hw->shift);
hw->clip (dst, src, convert_samples);
if (!oss->mmapped) {
int written;
written = write (oss->fd, dst, convert_samples << hw->shift);
/* XXX: follow errno recommendations ? */
if (written == -1) {
dolog ("Failed to write audio\nReason: %s\n", errstr ());
continue;
}
if (written != convert_samples << hw->shift) {
int wsamples = written >> hw->shift;
int wbytes = wsamples << hw->shift;
if (wbytes != written) {
dolog ("Unaligned write %d, %d\n", wbytes, written);
}
memset (src, 0, wbytes);
decr -= samples;
rpos = (rpos + wsamples) % hw->samples;
break;
}
}
memset (src, 0, convert_samples * sizeof (st_sample_t));
rpos = (rpos + convert_samples) % hw->samples;
samples -= convert_samples;
}
if (oss->mmapped) {
oss->old_optr = cntinfo.ptr;
}
pcm_hw_dec_live (hw, decr);
hw->rpos = rpos;
}
static void oss_hw_fini (HWVoice *hw)
{
int err;
OSSVoice *oss = (OSSVoice *) hw;
ldebug ("oss_hw_fini\n");
err = close (oss->fd);
if (err) {
dolog ("Failed to close OSS descriptor\nReason: %s\n", errstr ());
}
oss->fd = -1;
if (oss->pcm_buf) {
if (oss->mmapped) {
err = munmap (oss->pcm_buf, hw->bufsize);
if (err) {
dolog ("Failed to unmap OSS buffer\nReason: %s\n",
errstr ());
}
}
else {
qemu_free (oss->pcm_buf);
}
oss->pcm_buf = NULL;
}
}
static int oss_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
{
OSSVoice *oss = (OSSVoice *) hw;
struct oss_params req, obt;
assert (!oss->fd);
req.fmt = AUD_to_ossfmt (fmt);
req.freq = freq;
req.nchannels = nchannels;
req.fragsize = conf.fragsize;
req.nfrags = conf.nfrags;
if (oss_open (&req, &obt, &oss->fd))
return -1;
hw->freq = obt.freq;
hw->fmt = oss_to_audfmt (obt.fmt);
hw->nchannels = obt.nchannels;
oss->nfrags = obt.nfrags;
oss->fragsize = obt.fragsize;
hw->bufsize = obt.nfrags * obt.fragsize;
oss->mmapped = 0;
if (conf.try_mmap) {
oss->pcm_buf = mmap (0, hw->bufsize, PROT_READ | PROT_WRITE,
MAP_SHARED, oss->fd, 0);
if (oss->pcm_buf == MAP_FAILED) {
dolog ("Failed to mmap OSS device\nReason: %s\n",
errstr ());
} else {
int err;
int trig = 0;
if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
dolog ("SNDCTL_DSP_SETTRIGGER 0 failed\nReason: %s\n",
errstr ());
}
else {
trig = PCM_ENABLE_OUTPUT;
if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
dolog ("SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"
"Reason: %s\n", errstr ());
}
else {
oss->mmapped = 1;
}
}
if (!oss->mmapped) {
err = munmap (oss->pcm_buf, hw->bufsize);
if (err) {
dolog ("Failed to unmap OSS device\nReason: %s\n",
errstr ());
}
}
}
}
if (!oss->mmapped) {
oss->pcm_buf = qemu_mallocz (hw->bufsize);
if (!oss->pcm_buf) {
close (oss->fd);
oss->fd = -1;
return -1;
}
}
return 0;
}
static int oss_hw_ctl (HWVoice *hw, int cmd, ...)
{
int trig;
OSSVoice *oss = (OSSVoice *) hw;
if (!oss->mmapped)
return 0;
switch (cmd) {
case VOICE_ENABLE:
ldebug ("enabling voice\n");
pcm_hw_clear (hw, oss->pcm_buf, hw->samples);
trig = PCM_ENABLE_OUTPUT;
if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
dolog ("SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"
"Reason: %s\n", errstr ());
return -1;
}
break;
case VOICE_DISABLE:
ldebug ("disabling voice\n");
trig = 0;
if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
dolog ("SNDCTL_DSP_SETTRIGGER 0 failed\nReason: %s\n",
errstr ());
return -1;
}
break;
}
return 0;
}
static void *oss_audio_init (void)
{
conf.fragsize = audio_get_conf_int (QC_OSS_FRAGSIZE, conf.fragsize);
conf.nfrags = audio_get_conf_int (QC_OSS_NFRAGS, conf.nfrags);
conf.try_mmap = audio_get_conf_int (QC_OSS_MMAP, conf.try_mmap);
conf.dspname = audio_get_conf_str (QC_OSS_DEV, conf.dspname);
return &conf;
}
static void oss_audio_fini (void *opaque)
{
}
struct pcm_ops oss_pcm_ops = {
oss_hw_init,
oss_hw_fini,
oss_hw_run,
oss_hw_write,
oss_hw_ctl
};
struct audio_output_driver oss_output_driver = {
"oss",
oss_audio_init,
oss_audio_fini,
&oss_pcm_ops,
1,
INT_MAX,
sizeof (OSSVoice)
};

332
audio/sdlaudio.c Normal file
View File

@@ -0,0 +1,332 @@
/*
* QEMU SDL audio output driver
*
* Copyright (c) 2004 Vassili Karpov (malc)
*
* 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 <SDL.h>
#include <SDL_thread.h>
#include "vl.h"
#include "audio/audio_int.h"
typedef struct SDLVoice {
HWVoice hw;
} SDLVoice;
#define dolog(...) AUD_log ("sdl", __VA_ARGS__)
#ifdef DEBUG
#define ldebug(...) dolog (__VA_ARGS__)
#else
#define ldebug(...)
#endif
#define QC_SDL_SAMPLES "QEMU_SDL_SAMPLES"
#define errstr() SDL_GetError ()
static struct {
int nb_samples;
} conf = {
1024
};
struct SDLAudioState {
int exit;
SDL_mutex *mutex;
SDL_sem *sem;
int initialized;
} glob_sdl;
typedef struct SDLAudioState SDLAudioState;
static void sdl_hw_run (HWVoice *hw)
{
(void) hw;
}
static int sdl_lock (SDLAudioState *s)
{
if (SDL_LockMutex (s->mutex)) {
dolog ("SDL_LockMutex failed\nReason: %s\n", errstr ());
return -1;
}
return 0;
}
static int sdl_unlock (SDLAudioState *s)
{
if (SDL_UnlockMutex (s->mutex)) {
dolog ("SDL_UnlockMutex failed\nReason: %s\n", errstr ());
return -1;
}
return 0;
}
static int sdl_post (SDLAudioState *s)
{
if (SDL_SemPost (s->sem)) {
dolog ("SDL_SemPost failed\nReason: %s\n", errstr ());
return -1;
}
return 0;
}
static int sdl_wait (SDLAudioState *s)
{
if (SDL_SemWait (s->sem)) {
dolog ("SDL_SemWait failed\nReason: %s\n", errstr ());
return -1;
}
return 0;
}
static int sdl_unlock_and_post (SDLAudioState *s)
{
if (sdl_unlock (s))
return -1;
return sdl_post (s);
}
static int sdl_hw_write (SWVoice *sw, void *buf, int len)
{
int ret;
SDLAudioState *s = &glob_sdl;
sdl_lock (s);
ret = pcm_hw_write (sw, buf, len);
sdl_unlock_and_post (s);
return ret;
}
static int AUD_to_sdlfmt (audfmt_e fmt, int *shift)
{
*shift = 0;
switch (fmt) {
case AUD_FMT_S8: return AUDIO_S8;
case AUD_FMT_U8: return AUDIO_U8;
case AUD_FMT_S16: *shift = 1; return AUDIO_S16LSB;
case AUD_FMT_U16: *shift = 1; return AUDIO_U16LSB;
default:
dolog ("Internal logic error: Bad audio format %d\nAborting\n", fmt);
exit (EXIT_FAILURE);
}
}
static int sdl_to_audfmt (int fmt)
{
switch (fmt) {
case AUDIO_S8: return AUD_FMT_S8;
case AUDIO_U8: return AUD_FMT_U8;
case AUDIO_S16LSB: return AUD_FMT_S16;
case AUDIO_U16LSB: return AUD_FMT_U16;
default:
dolog ("Internal logic error: Unrecognized SDL audio format %d\n"
"Aborting\n", fmt);
exit (EXIT_FAILURE);
}
}
static int sdl_open (SDL_AudioSpec *req, SDL_AudioSpec *obt)
{
int status;
status = SDL_OpenAudio (req, obt);
if (status) {
dolog ("SDL_OpenAudio failed\nReason: %s\n", errstr ());
}
return status;
}
static void sdl_close (SDLAudioState *s)
{
if (s->initialized) {
sdl_lock (s);
s->exit = 1;
sdl_unlock_and_post (s);
SDL_PauseAudio (1);
SDL_CloseAudio ();
s->initialized = 0;
}
}
static void sdl_callback (void *opaque, Uint8 *buf, int len)
{
SDLVoice *sdl = opaque;
SDLAudioState *s = &glob_sdl;
HWVoice *hw = &sdl->hw;
int samples = len >> hw->shift;
if (s->exit) {
return;
}
while (samples) {
int to_mix, live, decr;
/* dolog ("in callback samples=%d\n", samples); */
sdl_wait (s);
if (s->exit) {
return;
}
sdl_lock (s);
live = pcm_hw_get_live (hw);
if (live <= 0)
goto again;
/* dolog ("in callback live=%d\n", live); */
to_mix = audio_MIN (samples, live);
decr = to_mix;
while (to_mix) {
int chunk = audio_MIN (to_mix, hw->samples - hw->rpos);
st_sample_t *src = hw->mix_buf + hw->rpos;
/* dolog ("in callback to_mix %d, chunk %d\n", to_mix, chunk); */
hw->clip (buf, src, chunk);
memset (src, 0, chunk * sizeof (st_sample_t));
hw->rpos = (hw->rpos + chunk) % hw->samples;
to_mix -= chunk;
buf += chunk << hw->shift;
}
samples -= decr;
pcm_hw_dec_live (hw, decr);
again:
sdl_unlock (s);
}
/* dolog ("done len=%d\n", len); */
}
static void sdl_hw_fini (HWVoice *hw)
{
ldebug ("sdl_hw_fini %d fixed=%d\n",
glob_sdl.initialized, audio_conf.fixed_format);
sdl_close (&glob_sdl);
}
static int sdl_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
{
SDLVoice *sdl = (SDLVoice *) hw;
SDLAudioState *s = &glob_sdl;
SDL_AudioSpec req, obt;
int shift;
ldebug ("sdl_hw_init %d freq=%d fixed=%d\n",
s->initialized, freq, audio_conf.fixed_format);
if (nchannels != 2) {
dolog ("Bogus channel count %d\n", nchannels);
return -1;
}
req.freq = freq;
req.format = AUD_to_sdlfmt (fmt, &shift);
req.channels = nchannels;
req.samples = conf.nb_samples;
shift <<= nchannels == 2;
req.callback = sdl_callback;
req.userdata = sdl;
if (sdl_open (&req, &obt))
return -1;
hw->freq = obt.freq;
hw->fmt = sdl_to_audfmt (obt.format);
hw->nchannels = obt.channels;
hw->bufsize = obt.samples << shift;
s->initialized = 1;
s->exit = 0;
SDL_PauseAudio (0);
return 0;
}
static int sdl_hw_ctl (HWVoice *hw, int cmd, ...)
{
(void) hw;
switch (cmd) {
case VOICE_ENABLE:
SDL_PauseAudio (0);
break;
case VOICE_DISABLE:
SDL_PauseAudio (1);
break;
}
return 0;
}
static void *sdl_audio_init (void)
{
SDLAudioState *s = &glob_sdl;
conf.nb_samples = audio_get_conf_int (QC_SDL_SAMPLES, conf.nb_samples);
if (SDL_InitSubSystem (SDL_INIT_AUDIO)) {
dolog ("SDL failed to initialize audio subsystem\nReason: %s\n",
errstr ());
return NULL;
}
s->mutex = SDL_CreateMutex ();
if (!s->mutex) {
dolog ("Failed to create SDL mutex\nReason: %s\n", errstr ());
SDL_QuitSubSystem (SDL_INIT_AUDIO);
return NULL;
}
s->sem = SDL_CreateSemaphore (0);
if (!s->sem) {
dolog ("Failed to create SDL semaphore\nReason: %s\n", errstr ());
SDL_DestroyMutex (s->mutex);
SDL_QuitSubSystem (SDL_INIT_AUDIO);
return NULL;
}
return s;
}
static void sdl_audio_fini (void *opaque)
{
SDLAudioState *s = opaque;
sdl_close (s);
SDL_DestroySemaphore (s->sem);
SDL_DestroyMutex (s->mutex);
SDL_QuitSubSystem (SDL_INIT_AUDIO);
}
struct pcm_ops sdl_pcm_ops = {
sdl_hw_init,
sdl_hw_fini,
sdl_hw_run,
sdl_hw_write,
sdl_hw_ctl
};
struct audio_output_driver sdl_output_driver = {
"sdl",
sdl_audio_init,
sdl_audio_fini,
&sdl_pcm_ops,
1,
1,
sizeof (SDLVoice)
};

217
audio/wavaudio.c Normal file
View File

@@ -0,0 +1,217 @@
/*
* QEMU WAV audio output driver
*
* Copyright (c) 2004 Vassili Karpov (malc)
*
* 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 "vl.h"
#include "audio/audio_int.h"
typedef struct WAVVoice {
HWVoice hw;
QEMUFile *f;
int64_t old_ticks;
void *pcm_buf;
int total_samples;
} WAVVoice;
#define dolog(...) AUD_log ("wav", __VA_ARGS__)
#ifdef DEBUG
#define ldebug(...) dolog (__VA_ARGS__)
#else
#define ldebug(...)
#endif
static struct {
const char *wav_path;
} conf = {
.wav_path = "qemu.wav"
};
static void wav_hw_run (HWVoice *hw)
{
WAVVoice *wav = (WAVVoice *) hw;
int rpos, live, decr, samples;
uint8_t *dst;
st_sample_t *src;
int64_t now = qemu_get_clock (vm_clock);
int64_t ticks = now - wav->old_ticks;
int64_t bytes = (ticks * hw->bytes_per_second) / ticks_per_sec;
if (bytes > INT_MAX)
samples = INT_MAX >> hw->shift;
else
samples = bytes >> hw->shift;
live = pcm_hw_get_live (hw);
if (live <= 0)
return;
wav->old_ticks = now;
decr = audio_MIN (live, samples);
samples = decr;
rpos = hw->rpos;
while (samples) {
int left_till_end_samples = hw->samples - rpos;
int convert_samples = audio_MIN (samples, left_till_end_samples);
src = advance (hw->mix_buf, rpos * sizeof (st_sample_t));
dst = advance (wav->pcm_buf, rpos << hw->shift);
hw->clip (dst, src, convert_samples);
qemu_put_buffer (wav->f, dst, convert_samples << hw->shift);
memset (src, 0, convert_samples * sizeof (st_sample_t));
rpos = (rpos + convert_samples) % hw->samples;
samples -= convert_samples;
wav->total_samples += convert_samples;
}
pcm_hw_dec_live (hw, decr);
hw->rpos = rpos;
}
static int wav_hw_write (SWVoice *sw, void *buf, int len)
{
return pcm_hw_write (sw, buf, len);
}
/* VICE code: Store number as little endian. */
static void le_store (uint8_t *buf, uint32_t val, int len)
{
int i;
for (i = 0; i < len; i++) {
buf[i] = (uint8_t) (val & 0xff);
val >>= 8;
}
}
static int wav_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
{
WAVVoice *wav = (WAVVoice *) hw;
int bits16 = 0, stereo = audio_state.fixed_channels == 2;
uint8_t hdr[] = {
0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56,
0x45, 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0x10, 0xb1, 0x02, 0x00, 0x04,
0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00
};
switch (audio_state.fixed_fmt) {
case AUD_FMT_S8:
case AUD_FMT_U8:
break;
case AUD_FMT_S16:
case AUD_FMT_U16:
bits16 = 1;
break;
}
hdr[34] = bits16 ? 0x10 : 0x08;
hw->freq = 44100;
hw->nchannels = stereo ? 2 : 1;
hw->fmt = bits16 ? AUD_FMT_S16 : AUD_FMT_U8;
hw->bufsize = 4096;
wav->pcm_buf = qemu_mallocz (hw->bufsize);
if (!wav->pcm_buf)
return -1;
le_store (hdr + 22, hw->nchannels, 2);
le_store (hdr + 24, hw->freq, 4);
le_store (hdr + 28, hw->freq << (bits16 + stereo), 4);
le_store (hdr + 32, 1 << (bits16 + stereo), 2);
wav->f = fopen (conf.wav_path, "wb");
if (!wav->f) {
dolog ("failed to open wave file `%s'\nReason: %s\n",
conf.wav_path, strerror (errno));
qemu_free (wav->pcm_buf);
wav->pcm_buf = NULL;
return -1;
}
qemu_put_buffer (wav->f, hdr, sizeof (hdr));
return 0;
}
static void wav_hw_fini (HWVoice *hw)
{
WAVVoice *wav = (WAVVoice *) hw;
int stereo = hw->nchannels == 2;
uint8_t rlen[4];
uint8_t dlen[4];
uint32_t rifflen = (wav->total_samples << stereo) + 36;
uint32_t datalen = wav->total_samples << stereo;
if (!wav->f || !hw->active)
return;
le_store (rlen, rifflen, 4);
le_store (dlen, datalen, 4);
qemu_fseek (wav->f, 4, SEEK_SET);
qemu_put_buffer (wav->f, rlen, 4);
qemu_fseek (wav->f, 32, SEEK_CUR);
qemu_put_buffer (wav->f, dlen, 4);
fclose (wav->f);
wav->f = NULL;
qemu_free (wav->pcm_buf);
wav->pcm_buf = NULL;
}
static int wav_hw_ctl (HWVoice *hw, int cmd, ...)
{
(void) hw;
(void) cmd;
return 0;
}
static void *wav_audio_init (void)
{
return &conf;
}
static void wav_audio_fini (void *opaque)
{
ldebug ("wav_fini");
}
struct pcm_ops wav_pcm_ops = {
wav_hw_init,
wav_hw_fini,
wav_hw_run,
wav_hw_write,
wav_hw_ctl
};
struct audio_output_driver wav_output_driver = {
"wav",
wav_audio_init,
wav_audio_fini,
&wav_pcm_ops,
1,
1,
sizeof (WAVVoice)
};

167
block-cloop.c Normal file
View File

@@ -0,0 +1,167 @@
/*
* QEMU System Emulator block driver
*
* Copyright (c) 2004 Johannes E. Schindelin
*
* 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 "vl.h"
#include "block_int.h"
#include <zlib.h>
typedef struct BDRVCloopState {
int fd;
uint32_t block_size;
uint32_t n_blocks;
uint64_t* offsets;
uint32_t sectors_per_block;
uint32_t current_block;
char* compressed_block;
char* uncompressed_block;
z_stream zstream;
} BDRVCloopState;
static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename)
{
const char* magic_version_2_0="#!/bin/sh\n"
"#V2.0 Format\n"
"modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n";
int length=strlen(magic_version_2_0);
if(length>buf_size)
length=buf_size;
if(!memcmp(magic_version_2_0,buf,length))
return 2;
return 0;
}
static int cloop_open(BlockDriverState *bs, const char *filename)
{
BDRVCloopState *s = bs->opaque;
uint32_t offsets_size,max_compressed_block_size=1,i;
s->fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
if (s->fd < 0)
return -1;
bs->read_only = 1;
/* read header */
if(lseek(s->fd,128,SEEK_SET)<0) {
cloop_close:
close(s->fd);
return -1;
}
if(read(s->fd,&s->block_size,4)<4)
goto cloop_close;
s->block_size=be32_to_cpu(s->block_size);
if(read(s->fd,&s->n_blocks,4)<4)
goto cloop_close;
s->n_blocks=be32_to_cpu(s->n_blocks);
/* read offsets */
offsets_size=s->n_blocks*sizeof(uint64_t);
if(!(s->offsets=(uint64_t*)malloc(offsets_size)))
goto cloop_close;
if(read(s->fd,s->offsets,offsets_size)<offsets_size)
goto cloop_close;
for(i=0;i<s->n_blocks;i++) {
s->offsets[i]=be64_to_cpu(s->offsets[i]);
if(i>0) {
uint32_t size=s->offsets[i]-s->offsets[i-1];
if(size>max_compressed_block_size)
max_compressed_block_size=size;
}
}
/* initialize zlib engine */
if(!(s->compressed_block=(char*)malloc(max_compressed_block_size+1)))
goto cloop_close;
if(!(s->uncompressed_block=(char*)malloc(s->block_size)))
goto cloop_close;
if(inflateInit(&s->zstream) != Z_OK)
goto cloop_close;
s->current_block=s->n_blocks;
s->sectors_per_block = s->block_size/512;
bs->total_sectors = s->n_blocks*s->sectors_per_block;
return 0;
}
static inline int cloop_read_block(BDRVCloopState *s,int block_num)
{
if(s->current_block != block_num) {
int ret;
uint32_t bytes = s->offsets[block_num+1]-s->offsets[block_num];
lseek(s->fd, s->offsets[block_num], SEEK_SET);
ret = read(s->fd, s->compressed_block, bytes);
if (ret != bytes)
return -1;
s->zstream.next_in = s->compressed_block;
s->zstream.avail_in = bytes;
s->zstream.next_out = s->uncompressed_block;
s->zstream.avail_out = s->block_size;
ret = inflateReset(&s->zstream);
if(ret != Z_OK)
return -1;
ret = inflate(&s->zstream, Z_FINISH);
if(ret != Z_STREAM_END || s->zstream.total_out != s->block_size)
return -1;
s->current_block = block_num;
}
return 0;
}
static int cloop_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVCloopState *s = bs->opaque;
int i;
for(i=0;i<nb_sectors;i++) {
uint32_t sector_offset_in_block=((sector_num+i)%s->sectors_per_block),
block_num=(sector_num+i)/s->sectors_per_block;
if(cloop_read_block(s, block_num) != 0)
return -1;
memcpy(buf+i*512,s->uncompressed_block+sector_offset_in_block*512,512);
}
return 0;
}
static void cloop_close(BlockDriverState *bs)
{
BDRVCloopState *s = bs->opaque;
close(s->fd);
free(s->compressed_block);
free(s->uncompressed_block);
inflateEnd(&s->zstream);
}
BlockDriver bdrv_cloop = {
"cloop",
sizeof(BDRVCloopState),
cloop_probe,
cloop_open,
cloop_read,
NULL,
cloop_close,
};

263
block-cow.c Normal file
View File

@@ -0,0 +1,263 @@
/*
* Block driver for the COW format
*
* Copyright (c) 2004 Fabrice Bellard
*
* 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 _WIN32
#include "vl.h"
#include "block_int.h"
#include <sys/mman.h>
/**************************************************************/
/* COW block driver using file system holes */
/* user mode linux compatible COW file */
#define COW_MAGIC 0x4f4f4f4d /* MOOO */
#define COW_VERSION 2
struct cow_header_v2 {
uint32_t magic;
uint32_t version;
char backing_file[1024];
int32_t mtime;
uint64_t size;
uint32_t sectorsize;
};
typedef struct BDRVCowState {
int fd;
uint8_t *cow_bitmap; /* if non NULL, COW mappings are used first */
uint8_t *cow_bitmap_addr; /* mmap address of cow_bitmap */
int cow_bitmap_size;
int64_t cow_sectors_offset;
} BDRVCowState;
static int cow_probe(const uint8_t *buf, int buf_size, const char *filename)
{
const struct cow_header_v2 *cow_header = (const void *)buf;
if (be32_to_cpu(cow_header->magic) == COW_MAGIC &&
be32_to_cpu(cow_header->version) == COW_VERSION)
return 100;
else
return 0;
}
static int cow_open(BlockDriverState *bs, const char *filename)
{
BDRVCowState *s = bs->opaque;
int fd;
struct cow_header_v2 cow_header;
int64_t size;
fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
if (fd < 0) {
fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
if (fd < 0)
return -1;
}
s->fd = fd;
/* see if it is a cow image */
if (read(fd, &cow_header, sizeof(cow_header)) != sizeof(cow_header)) {
goto fail;
}
if (be32_to_cpu(cow_header.magic) != COW_MAGIC ||
be32_to_cpu(cow_header.version) != COW_VERSION) {
goto fail;
}
/* cow image found */
size = be64_to_cpu(cow_header.size);
bs->total_sectors = size / 512;
pstrcpy(bs->backing_file, sizeof(bs->backing_file),
cow_header.backing_file);
#if 0
if (cow_header.backing_file[0] != '\0') {
if (stat(cow_header.backing_file, &st) != 0) {
fprintf(stderr, "%s: could not find original disk image '%s'\n", filename, cow_header.backing_file);
goto fail;
}
if (st.st_mtime != be32_to_cpu(cow_header.mtime)) {
fprintf(stderr, "%s: original raw disk image '%s' does not match saved timestamp\n", filename, cow_header.backing_file);
goto fail;
}
fd = open(cow_header.backing_file, O_RDONLY | O_LARGEFILE);
if (fd < 0)
goto fail;
bs->fd = fd;
}
#endif
/* mmap the bitmap */
s->cow_bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
s->cow_bitmap_addr = mmap(get_mmap_addr(s->cow_bitmap_size),
s->cow_bitmap_size,
PROT_READ | PROT_WRITE,
MAP_SHARED, s->fd, 0);
if (s->cow_bitmap_addr == MAP_FAILED)
goto fail;
s->cow_bitmap = s->cow_bitmap_addr + sizeof(cow_header);
s->cow_sectors_offset = (s->cow_bitmap_size + 511) & ~511;
return 0;
fail:
close(fd);
return -1;
}
static inline void set_bit(uint8_t *bitmap, int64_t bitnum)
{
bitmap[bitnum / 8] |= (1 << (bitnum%8));
}
static inline int is_bit_set(const uint8_t *bitmap, int64_t bitnum)
{
return !!(bitmap[bitnum / 8] & (1 << (bitnum%8)));
}
/* Return true if first block has been changed (ie. current version is
* in COW file). Set the number of continuous blocks for which that
* is true. */
static inline int is_changed(uint8_t *bitmap,
int64_t sector_num, int nb_sectors,
int *num_same)
{
int changed;
if (!bitmap || nb_sectors == 0) {
*num_same = nb_sectors;
return 0;
}
changed = is_bit_set(bitmap, sector_num);
for (*num_same = 1; *num_same < nb_sectors; (*num_same)++) {
if (is_bit_set(bitmap, sector_num + *num_same) != changed)
break;
}
return changed;
}
static int cow_is_allocated(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum)
{
BDRVCowState *s = bs->opaque;
return is_changed(s->cow_bitmap, sector_num, nb_sectors, pnum);
}
static int cow_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVCowState *s = bs->opaque;
int ret, n;
while (nb_sectors > 0) {
if (is_changed(s->cow_bitmap, sector_num, nb_sectors, &n)) {
lseek(s->fd, s->cow_sectors_offset + sector_num * 512, SEEK_SET);
ret = read(s->fd, buf, n * 512);
if (ret != n * 512)
return -1;
} else {
memset(buf, 0, n * 512);
}
nb_sectors -= n;
sector_num += n;
buf += n * 512;
}
return 0;
}
static int cow_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
BDRVCowState *s = bs->opaque;
int ret, i;
lseek(s->fd, s->cow_sectors_offset + sector_num * 512, SEEK_SET);
ret = write(s->fd, buf, nb_sectors * 512);
if (ret != nb_sectors * 512)
return -1;
for (i = 0; i < nb_sectors; i++)
set_bit(s->cow_bitmap, sector_num + i);
return 0;
}
static void cow_close(BlockDriverState *bs)
{
BDRVCowState *s = bs->opaque;
munmap(s->cow_bitmap_addr, s->cow_bitmap_size);
close(s->fd);
}
static int cow_create(const char *filename, int64_t image_sectors,
const char *image_filename, int flags)
{
int fd, cow_fd;
struct cow_header_v2 cow_header;
struct stat st;
if (flags)
return -ENOTSUP;
cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
0644);
if (cow_fd < 0)
return -1;
memset(&cow_header, 0, sizeof(cow_header));
cow_header.magic = cpu_to_be32(COW_MAGIC);
cow_header.version = cpu_to_be32(COW_VERSION);
if (image_filename) {
fd = open(image_filename, O_RDONLY | O_BINARY);
if (fd < 0) {
close(cow_fd);
return -1;
}
if (fstat(fd, &st) != 0) {
close(fd);
return -1;
}
close(fd);
cow_header.mtime = cpu_to_be32(st.st_mtime);
realpath(image_filename, cow_header.backing_file);
}
cow_header.sectorsize = cpu_to_be32(512);
cow_header.size = cpu_to_be64(image_sectors * 512);
write(cow_fd, &cow_header, sizeof(cow_header));
/* resize to include at least all the bitmap */
ftruncate(cow_fd, sizeof(cow_header) + ((image_sectors + 7) >> 3));
close(cow_fd);
return 0;
}
BlockDriver bdrv_cow = {
"cow",
sizeof(BDRVCowState),
cow_probe,
cow_open,
cow_read,
cow_write,
cow_close,
cow_create,
cow_is_allocated,
};
#endif

677
block-qcow.c Normal file
View File

@@ -0,0 +1,677 @@
/*
* Block driver for the QCOW format
*
* Copyright (c) 2004 Fabrice Bellard
*
* 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 "vl.h"
#include "block_int.h"
#include <zlib.h>
#include "aes.h"
/**************************************************************/
/* QEMU COW block driver with compression and encryption support */
#define QCOW_MAGIC (('Q' << 24) | ('F' << 16) | ('I' << 8) | 0xfb)
#define QCOW_VERSION 1
#define QCOW_CRYPT_NONE 0
#define QCOW_CRYPT_AES 1
#define QCOW_OFLAG_COMPRESSED (1LL << 63)
typedef struct QCowHeader {
uint32_t magic;
uint32_t version;
uint64_t backing_file_offset;
uint32_t backing_file_size;
uint32_t mtime;
uint64_t size; /* in bytes */
uint8_t cluster_bits;
uint8_t l2_bits;
uint32_t crypt_method;
uint64_t l1_table_offset;
} QCowHeader;
#define L2_CACHE_SIZE 16
typedef struct BDRVQcowState {
int fd;
int cluster_bits;
int cluster_size;
int cluster_sectors;
int l2_bits;
int l2_size;
int l1_size;
uint64_t cluster_offset_mask;
uint64_t l1_table_offset;
uint64_t *l1_table;
uint64_t *l2_cache;
uint64_t l2_cache_offsets[L2_CACHE_SIZE];
uint32_t l2_cache_counts[L2_CACHE_SIZE];
uint8_t *cluster_cache;
uint8_t *cluster_data;
uint64_t cluster_cache_offset;
uint32_t crypt_method; /* current crypt method, 0 if no key yet */
uint32_t crypt_method_header;
AES_KEY aes_encrypt_key;
AES_KEY aes_decrypt_key;
} BDRVQcowState;
static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset);
static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
{
const QCowHeader *cow_header = (const void *)buf;
if (be32_to_cpu(cow_header->magic) == QCOW_MAGIC &&
be32_to_cpu(cow_header->version) == QCOW_VERSION)
return 100;
else
return 0;
}
static int qcow_open(BlockDriverState *bs, const char *filename)
{
BDRVQcowState *s = bs->opaque;
int fd, len, i, shift;
QCowHeader header;
fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
if (fd < 0) {
fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
if (fd < 0)
return -1;
}
s->fd = fd;
if (read(fd, &header, sizeof(header)) != sizeof(header))
goto fail;
be32_to_cpus(&header.magic);
be32_to_cpus(&header.version);
be64_to_cpus(&header.backing_file_offset);
be32_to_cpus(&header.backing_file_size);
be32_to_cpus(&header.mtime);
be64_to_cpus(&header.size);
be32_to_cpus(&header.crypt_method);
be64_to_cpus(&header.l1_table_offset);
if (header.magic != QCOW_MAGIC || header.version != QCOW_VERSION)
goto fail;
if (header.size <= 1 || header.cluster_bits < 9)
goto fail;
if (header.crypt_method > QCOW_CRYPT_AES)
goto fail;
s->crypt_method_header = header.crypt_method;
if (s->crypt_method_header)
bs->encrypted = 1;
s->cluster_bits = header.cluster_bits;
s->cluster_size = 1 << s->cluster_bits;
s->cluster_sectors = 1 << (s->cluster_bits - 9);
s->l2_bits = header.l2_bits;
s->l2_size = 1 << s->l2_bits;
bs->total_sectors = header.size / 512;
s->cluster_offset_mask = (1LL << (63 - s->cluster_bits)) - 1;
/* read the level 1 table */
shift = s->cluster_bits + s->l2_bits;
s->l1_size = (header.size + (1LL << shift) - 1) >> shift;
s->l1_table_offset = header.l1_table_offset;
s->l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t));
if (!s->l1_table)
goto fail;
lseek(fd, s->l1_table_offset, SEEK_SET);
if (read(fd, s->l1_table, s->l1_size * sizeof(uint64_t)) !=
s->l1_size * sizeof(uint64_t))
goto fail;
for(i = 0;i < s->l1_size; i++) {
be64_to_cpus(&s->l1_table[i]);
}
/* alloc L2 cache */
s->l2_cache = qemu_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t));
if (!s->l2_cache)
goto fail;
s->cluster_cache = qemu_malloc(s->cluster_size);
if (!s->cluster_cache)
goto fail;
s->cluster_data = qemu_malloc(s->cluster_size);
if (!s->cluster_data)
goto fail;
s->cluster_cache_offset = -1;
/* read the backing file name */
if (header.backing_file_offset != 0) {
len = header.backing_file_size;
if (len > 1023)
len = 1023;
lseek(fd, header.backing_file_offset, SEEK_SET);
if (read(fd, bs->backing_file, len) != len)
goto fail;
bs->backing_file[len] = '\0';
}
return 0;
fail:
qemu_free(s->l1_table);
qemu_free(s->l2_cache);
qemu_free(s->cluster_cache);
qemu_free(s->cluster_data);
close(fd);
return -1;
}
static int qcow_set_key(BlockDriverState *bs, const char *key)
{
BDRVQcowState *s = bs->opaque;
uint8_t keybuf[16];
int len, i;
memset(keybuf, 0, 16);
len = strlen(key);
if (len > 16)
len = 16;
/* XXX: we could compress the chars to 7 bits to increase
entropy */
for(i = 0;i < len;i++) {
keybuf[i] = key[i];
}
s->crypt_method = s->crypt_method_header;
if (AES_set_encrypt_key(keybuf, 128, &s->aes_encrypt_key) != 0)
return -1;
if (AES_set_decrypt_key(keybuf, 128, &s->aes_decrypt_key) != 0)
return -1;
#if 0
/* test */
{
uint8_t in[16];
uint8_t out[16];
uint8_t tmp[16];
for(i=0;i<16;i++)
in[i] = i;
AES_encrypt(in, tmp, &s->aes_encrypt_key);
AES_decrypt(tmp, out, &s->aes_decrypt_key);
for(i = 0; i < 16; i++)
printf(" %02x", tmp[i]);
printf("\n");
for(i = 0; i < 16; i++)
printf(" %02x", out[i]);
printf("\n");
}
#endif
return 0;
}
/* The crypt function is compatible with the linux cryptoloop
algorithm for < 4 GB images. NOTE: out_buf == in_buf is
supported */
static void encrypt_sectors(BDRVQcowState *s, int64_t sector_num,
uint8_t *out_buf, const uint8_t *in_buf,
int nb_sectors, int enc,
const AES_KEY *key)
{
union {
uint64_t ll[2];
uint8_t b[16];
} ivec;
int i;
for(i = 0; i < nb_sectors; i++) {
ivec.ll[0] = cpu_to_le64(sector_num);
ivec.ll[1] = 0;
AES_cbc_encrypt(in_buf, out_buf, 512, key,
ivec.b, enc);
sector_num++;
in_buf += 512;
out_buf += 512;
}
}
/* 'allocate' is:
*
* 0 to not allocate.
*
* 1 to allocate a normal cluster (for sector indexes 'n_start' to
* 'n_end')
*
* 2 to allocate a compressed cluster of size
* 'compressed_size'. 'compressed_size' must be > 0 and <
* cluster_size
*
* return 0 if not allocated.
*/
static uint64_t get_cluster_offset(BlockDriverState *bs,
uint64_t offset, int allocate,
int compressed_size,
int n_start, int n_end)
{
BDRVQcowState *s = bs->opaque;
int min_index, i, j, l1_index, l2_index;
uint64_t l2_offset, *l2_table, cluster_offset, tmp;
uint32_t min_count;
int new_l2_table;
l1_index = offset >> (s->l2_bits + s->cluster_bits);
l2_offset = s->l1_table[l1_index];
new_l2_table = 0;
if (!l2_offset) {
if (!allocate)
return 0;
/* allocate a new l2 entry */
l2_offset = lseek(s->fd, 0, SEEK_END);
/* round to cluster size */
l2_offset = (l2_offset + s->cluster_size - 1) & ~(s->cluster_size - 1);
/* update the L1 entry */
s->l1_table[l1_index] = l2_offset;
tmp = cpu_to_be64(l2_offset);
lseek(s->fd, s->l1_table_offset + l1_index * sizeof(tmp), SEEK_SET);
if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))
return 0;
new_l2_table = 1;
}
for(i = 0; i < L2_CACHE_SIZE; i++) {
if (l2_offset == s->l2_cache_offsets[i]) {
/* increment the hit count */
if (++s->l2_cache_counts[i] == 0xffffffff) {
for(j = 0; j < L2_CACHE_SIZE; j++) {
s->l2_cache_counts[j] >>= 1;
}
}
l2_table = s->l2_cache + (i << s->l2_bits);
goto found;
}
}
/* not found: load a new entry in the least used one */
min_index = 0;
min_count = 0xffffffff;
for(i = 0; i < L2_CACHE_SIZE; i++) {
if (s->l2_cache_counts[i] < min_count) {
min_count = s->l2_cache_counts[i];
min_index = i;
}
}
l2_table = s->l2_cache + (min_index << s->l2_bits);
lseek(s->fd, l2_offset, SEEK_SET);
if (new_l2_table) {
memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
if (write(s->fd, l2_table, s->l2_size * sizeof(uint64_t)) !=
s->l2_size * sizeof(uint64_t))
return 0;
} else {
if (read(s->fd, l2_table, s->l2_size * sizeof(uint64_t)) !=
s->l2_size * sizeof(uint64_t))
return 0;
}
s->l2_cache_offsets[min_index] = l2_offset;
s->l2_cache_counts[min_index] = 1;
found:
l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
cluster_offset = be64_to_cpu(l2_table[l2_index]);
if (!cluster_offset ||
((cluster_offset & QCOW_OFLAG_COMPRESSED) && allocate == 1)) {
if (!allocate)
return 0;
/* allocate a new cluster */
if ((cluster_offset & QCOW_OFLAG_COMPRESSED) &&
(n_end - n_start) < s->cluster_sectors) {
/* if the cluster is already compressed, we must
decompress it in the case it is not completely
overwritten */
if (decompress_cluster(s, cluster_offset) < 0)
return 0;
cluster_offset = lseek(s->fd, 0, SEEK_END);
cluster_offset = (cluster_offset + s->cluster_size - 1) &
~(s->cluster_size - 1);
/* write the cluster content */
lseek(s->fd, cluster_offset, SEEK_SET);
if (write(s->fd, s->cluster_cache, s->cluster_size) !=
s->cluster_size)
return -1;
} else {
cluster_offset = lseek(s->fd, 0, SEEK_END);
if (allocate == 1) {
/* round to cluster size */
cluster_offset = (cluster_offset + s->cluster_size - 1) &
~(s->cluster_size - 1);
ftruncate(s->fd, cluster_offset + s->cluster_size);
/* if encrypted, we must initialize the cluster
content which won't be written */
if (s->crypt_method &&
(n_end - n_start) < s->cluster_sectors) {
uint64_t start_sect;
start_sect = (offset & ~(s->cluster_size - 1)) >> 9;
memset(s->cluster_data + 512, 0xaa, 512);
for(i = 0; i < s->cluster_sectors; i++) {
if (i < n_start || i >= n_end) {
encrypt_sectors(s, start_sect + i,
s->cluster_data,
s->cluster_data + 512, 1, 1,
&s->aes_encrypt_key);
lseek(s->fd, cluster_offset + i * 512, SEEK_SET);
if (write(s->fd, s->cluster_data, 512) != 512)
return -1;
}
}
}
} else {
cluster_offset |= QCOW_OFLAG_COMPRESSED |
(uint64_t)compressed_size << (63 - s->cluster_bits);
}
}
/* update L2 table */
tmp = cpu_to_be64(cluster_offset);
l2_table[l2_index] = tmp;
lseek(s->fd, l2_offset + l2_index * sizeof(tmp), SEEK_SET);
if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))
return 0;
}
return cluster_offset;
}
static int qcow_is_allocated(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum)
{
BDRVQcowState *s = bs->opaque;
int index_in_cluster, n;
uint64_t cluster_offset;
cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0);
index_in_cluster = sector_num & (s->cluster_sectors - 1);
n = s->cluster_sectors - index_in_cluster;
if (n > nb_sectors)
n = nb_sectors;
*pnum = n;
return (cluster_offset != 0);
}
static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
const uint8_t *buf, int buf_size)
{
z_stream strm1, *strm = &strm1;
int ret, out_len;
memset(strm, 0, sizeof(*strm));
strm->next_in = (uint8_t *)buf;
strm->avail_in = buf_size;
strm->next_out = out_buf;
strm->avail_out = out_buf_size;
ret = inflateInit2(strm, -12);
if (ret != Z_OK)
return -1;
ret = inflate(strm, Z_FINISH);
out_len = strm->next_out - out_buf;
if ((ret != Z_STREAM_END && ret != Z_BUF_ERROR) ||
out_len != out_buf_size) {
inflateEnd(strm);
return -1;
}
inflateEnd(strm);
return 0;
}
static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
{
int ret, csize;
uint64_t coffset;
coffset = cluster_offset & s->cluster_offset_mask;
if (s->cluster_cache_offset != coffset) {
csize = cluster_offset >> (63 - s->cluster_bits);
csize &= (s->cluster_size - 1);
lseek(s->fd, coffset, SEEK_SET);
ret = read(s->fd, s->cluster_data, csize);
if (ret != csize)
return -1;
if (decompress_buffer(s->cluster_cache, s->cluster_size,
s->cluster_data, csize) < 0) {
return -1;
}
s->cluster_cache_offset = coffset;
}
return 0;
}
static int qcow_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVQcowState *s = bs->opaque;
int ret, index_in_cluster, n;
uint64_t cluster_offset;
while (nb_sectors > 0) {
cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0);
index_in_cluster = sector_num & (s->cluster_sectors - 1);
n = s->cluster_sectors - index_in_cluster;
if (n > nb_sectors)
n = nb_sectors;
if (!cluster_offset) {
memset(buf, 0, 512 * n);
} else if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
if (decompress_cluster(s, cluster_offset) < 0)
return -1;
memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n);
} else {
lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
ret = read(s->fd, buf, n * 512);
if (ret != n * 512)
return -1;
if (s->crypt_method) {
encrypt_sectors(s, sector_num, buf, buf, n, 0,
&s->aes_decrypt_key);
}
}
nb_sectors -= n;
sector_num += n;
buf += n * 512;
}
return 0;
}
static int qcow_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
BDRVQcowState *s = bs->opaque;
int ret, index_in_cluster, n;
uint64_t cluster_offset;
while (nb_sectors > 0) {
index_in_cluster = sector_num & (s->cluster_sectors - 1);
n = s->cluster_sectors - index_in_cluster;
if (n > nb_sectors)
n = nb_sectors;
cluster_offset = get_cluster_offset(bs, sector_num << 9, 1, 0,
index_in_cluster,
index_in_cluster + n);
if (!cluster_offset)
return -1;
lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
if (s->crypt_method) {
encrypt_sectors(s, sector_num, s->cluster_data, buf, n, 1,
&s->aes_encrypt_key);
ret = write(s->fd, s->cluster_data, n * 512);
} else {
ret = write(s->fd, buf, n * 512);
}
if (ret != n * 512)
return -1;
nb_sectors -= n;
sector_num += n;
buf += n * 512;
}
s->cluster_cache_offset = -1; /* disable compressed cache */
return 0;
}
static void qcow_close(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
qemu_free(s->l1_table);
qemu_free(s->l2_cache);
qemu_free(s->cluster_cache);
qemu_free(s->cluster_data);
close(s->fd);
}
static int qcow_create(const char *filename, int64_t total_size,
const char *backing_file, int flags)
{
int fd, header_size, backing_filename_len, l1_size, i, shift;
QCowHeader header;
char backing_filename[1024];
uint64_t tmp;
struct stat st;
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
0644);
if (fd < 0)
return -1;
memset(&header, 0, sizeof(header));
header.magic = cpu_to_be32(QCOW_MAGIC);
header.version = cpu_to_be32(QCOW_VERSION);
header.size = cpu_to_be64(total_size * 512);
header_size = sizeof(header);
backing_filename_len = 0;
if (backing_file) {
realpath(backing_file, backing_filename);
if (stat(backing_filename, &st) != 0) {
return -1;
}
header.mtime = cpu_to_be32(st.st_mtime);
header.backing_file_offset = cpu_to_be64(header_size);
backing_filename_len = strlen(backing_filename);
header.backing_file_size = cpu_to_be32(backing_filename_len);
header_size += backing_filename_len;
header.cluster_bits = 9; /* 512 byte cluster to avoid copying
unmodifyed sectors */
header.l2_bits = 12; /* 32 KB L2 tables */
} else {
header.cluster_bits = 12; /* 4 KB clusters */
header.l2_bits = 9; /* 4 KB L2 tables */
}
header_size = (header_size + 7) & ~7;
shift = header.cluster_bits + header.l2_bits;
l1_size = ((total_size * 512) + (1LL << shift) - 1) >> shift;
header.l1_table_offset = cpu_to_be64(header_size);
if (flags) {
header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
} else {
header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);
}
/* write all the data */
write(fd, &header, sizeof(header));
if (backing_file) {
write(fd, backing_filename, backing_filename_len);
}
lseek(fd, header_size, SEEK_SET);
tmp = 0;
for(i = 0;i < l1_size; i++) {
write(fd, &tmp, sizeof(tmp));
}
close(fd);
return 0;
}
int qcow_get_cluster_size(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
if (bs->drv != &bdrv_qcow)
return -1;
return s->cluster_size;
}
/* XXX: put compressed sectors first, then all the cluster aligned
tables to avoid losing bytes in alignment */
int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf)
{
BDRVQcowState *s = bs->opaque;
z_stream strm;
int ret, out_len;
uint8_t *out_buf;
uint64_t cluster_offset;
if (bs->drv != &bdrv_qcow)
return -1;
out_buf = qemu_malloc(s->cluster_size + (s->cluster_size / 1000) + 128);
if (!out_buf)
return -1;
/* best compression, small window, no zlib header */
memset(&strm, 0, sizeof(strm));
ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION,
Z_DEFLATED, -12,
9, Z_DEFAULT_STRATEGY);
if (ret != 0) {
qemu_free(out_buf);
return -1;
}
strm.avail_in = s->cluster_size;
strm.next_in = (uint8_t *)buf;
strm.avail_out = s->cluster_size;
strm.next_out = out_buf;
ret = deflate(&strm, Z_FINISH);
if (ret != Z_STREAM_END && ret != Z_OK) {
qemu_free(out_buf);
deflateEnd(&strm);
return -1;
}
out_len = strm.next_out - out_buf;
deflateEnd(&strm);
if (ret != Z_STREAM_END || out_len >= s->cluster_size) {
/* could not compress: write normal cluster */
qcow_write(bs, sector_num, buf, s->cluster_sectors);
} else {
cluster_offset = get_cluster_offset(bs, sector_num << 9, 2,
out_len, 0, 0);
cluster_offset &= s->cluster_offset_mask;
lseek(s->fd, cluster_offset, SEEK_SET);
if (write(s->fd, out_buf, out_len) != out_len) {
qemu_free(out_buf);
return -1;
}
}
qemu_free(out_buf);
return 0;
}
BlockDriver bdrv_qcow = {
"qcow",
sizeof(BDRVQcowState),
qcow_probe,
qcow_open,
qcow_read,
qcow_write,
qcow_close,
qcow_create,
qcow_is_allocated,
qcow_set_key,
};

279
block-vmdk.c Normal file
View File

@@ -0,0 +1,279 @@
/*
* Block driver for the VMDK format
*
* Copyright (c) 2004 Fabrice Bellard
*
* 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 "vl.h"
#include "block_int.h"
/* XXX: this code is untested */
/* XXX: add write support */
#define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D')
#define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V')
typedef struct {
uint32_t version;
uint32_t flags;
uint32_t disk_sectors;
uint32_t granularity;
uint32_t l1dir_offset;
uint32_t l1dir_size;
uint32_t file_sectors;
uint32_t cylinders;
uint32_t heads;
uint32_t sectors_per_track;
} VMDK3Header;
typedef struct {
uint32_t version;
uint32_t flags;
int64_t capacity;
int64_t granularity;
int64_t desc_offset;
int64_t desc_size;
int32_t num_gtes_per_gte;
int64_t rgd_offset;
int64_t gd_offset;
int64_t grain_offset;
char filler[1];
char check_bytes[4];
} VMDK4Header;
#define L2_CACHE_SIZE 16
typedef struct BDRVVmdkState {
int fd;
int64_t l1_table_offset;
uint32_t *l1_table;
unsigned int l1_size;
uint32_t l1_entry_sectors;
unsigned int l2_size;
uint32_t *l2_cache;
uint32_t l2_cache_offsets[L2_CACHE_SIZE];
uint32_t l2_cache_counts[L2_CACHE_SIZE];
unsigned int cluster_sectors;
} BDRVVmdkState;
static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
{
uint32_t magic;
if (buf_size < 4)
return 0;
magic = be32_to_cpu(*(uint32_t *)buf);
if (magic == VMDK3_MAGIC ||
magic == VMDK4_MAGIC)
return 100;
else
return 0;
}
static int vmdk_open(BlockDriverState *bs, const char *filename)
{
BDRVVmdkState *s = bs->opaque;
int fd, i;
uint32_t magic;
int l1_size;
fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
if (fd < 0)
return -1;
if (read(fd, &magic, sizeof(magic)) != sizeof(magic))
goto fail;
magic = be32_to_cpu(magic);
if (magic == VMDK3_MAGIC) {
VMDK3Header header;
if (read(fd, &header, sizeof(header)) !=
sizeof(header))
goto fail;
s->cluster_sectors = le32_to_cpu(header.granularity);
s->l2_size = 1 << 9;
s->l1_size = 1 << 6;
bs->total_sectors = le32_to_cpu(header.disk_sectors);
s->l1_table_offset = le32_to_cpu(header.l1dir_offset) * 512;
s->l1_entry_sectors = s->l2_size * s->cluster_sectors;
} else if (magic == VMDK4_MAGIC) {
VMDK4Header header;
if (read(fd, &header, sizeof(header)) != sizeof(header))
goto fail;
bs->total_sectors = le32_to_cpu(header.capacity);
s->cluster_sectors = le32_to_cpu(header.granularity);
s->l2_size = le32_to_cpu(header.num_gtes_per_gte);
s->l1_entry_sectors = s->l2_size * s->cluster_sectors;
if (s->l1_entry_sectors <= 0)
goto fail;
s->l1_size = (bs->total_sectors + s->l1_entry_sectors - 1)
/ s->l1_entry_sectors;
s->l1_table_offset = le64_to_cpu(header.rgd_offset) * 512;
} else {
goto fail;
}
/* read the L1 table */
l1_size = s->l1_size * sizeof(uint32_t);
s->l1_table = qemu_malloc(l1_size);
if (!s->l1_table)
goto fail;
if (lseek(fd, s->l1_table_offset, SEEK_SET) == -1)
goto fail;
if (read(fd, s->l1_table, l1_size) != l1_size)
goto fail;
for(i = 0; i < s->l1_size; i++) {
le32_to_cpus(&s->l1_table[i]);
}
s->l2_cache = qemu_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint32_t));
if (!s->l2_cache)
goto fail;
s->fd = fd;
/* XXX: currently only read only */
bs->read_only = 1;
return 0;
fail:
qemu_free(s->l1_table);
qemu_free(s->l2_cache);
close(fd);
return -1;
}
static uint64_t get_cluster_offset(BlockDriverState *bs,
uint64_t offset)
{
BDRVVmdkState *s = bs->opaque;
unsigned int l1_index, l2_offset, l2_index;
int min_index, i, j;
uint32_t min_count, *l2_table;
uint64_t cluster_offset;
l1_index = (offset >> 9) / s->l1_entry_sectors;
if (l1_index >= s->l1_size)
return 0;
l2_offset = s->l1_table[l1_index];
if (!l2_offset)
return 0;
for(i = 0; i < L2_CACHE_SIZE; i++) {
if (l2_offset == s->l2_cache_offsets[i]) {
/* increment the hit count */
if (++s->l2_cache_counts[i] == 0xffffffff) {
for(j = 0; j < L2_CACHE_SIZE; j++) {
s->l2_cache_counts[j] >>= 1;
}
}
l2_table = s->l2_cache + (i * s->l2_size);
goto found;
}
}
/* not found: load a new entry in the least used one */
min_index = 0;
min_count = 0xffffffff;
for(i = 0; i < L2_CACHE_SIZE; i++) {
if (s->l2_cache_counts[i] < min_count) {
min_count = s->l2_cache_counts[i];
min_index = i;
}
}
l2_table = s->l2_cache + (min_index * s->l2_size);
lseek(s->fd, (int64_t)l2_offset * 512, SEEK_SET);
if (read(s->fd, l2_table, s->l2_size * sizeof(uint32_t)) !=
s->l2_size * sizeof(uint32_t))
return 0;
s->l2_cache_offsets[min_index] = l2_offset;
s->l2_cache_counts[min_index] = 1;
found:
l2_index = ((offset >> 9) / s->cluster_sectors) % s->l2_size;
cluster_offset = le32_to_cpu(l2_table[l2_index]);
cluster_offset <<= 9;
return cluster_offset;
}
static int vmdk_is_allocated(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum)
{
BDRVVmdkState *s = bs->opaque;
int index_in_cluster, n;
uint64_t cluster_offset;
cluster_offset = get_cluster_offset(bs, sector_num << 9);
index_in_cluster = sector_num % s->cluster_sectors;
n = s->cluster_sectors - index_in_cluster;
if (n > nb_sectors)
n = nb_sectors;
*pnum = n;
return (cluster_offset != 0);
}
static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVVmdkState *s = bs->opaque;
int ret, index_in_cluster, n;
uint64_t cluster_offset;
while (nb_sectors > 0) {
cluster_offset = get_cluster_offset(bs, sector_num << 9);
index_in_cluster = sector_num % s->cluster_sectors;
n = s->cluster_sectors - index_in_cluster;
if (n > nb_sectors)
n = nb_sectors;
if (!cluster_offset) {
memset(buf, 0, 512 * n);
} else {
lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
ret = read(s->fd, buf, n * 512);
if (ret != n * 512)
return -1;
}
nb_sectors -= n;
sector_num += n;
buf += n * 512;
}
return 0;
}
static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
return -1;
}
static void vmdk_close(BlockDriverState *bs)
{
BDRVVmdkState *s = bs->opaque;
qemu_free(s->l1_table);
qemu_free(s->l2_cache);
close(s->fd);
}
BlockDriver bdrv_vmdk = {
"vmdk",
sizeof(BDRVVmdkState),
vmdk_probe,
vmdk_open,
vmdk_read,
vmdk_write,
vmdk_close,
NULL, /* no create yet */
vmdk_is_allocated,
};

600
block.c Normal file
View File

@@ -0,0 +1,600 @@
/*
* QEMU System Emulator block driver
*
* Copyright (c) 2003 Fabrice Bellard
*
* 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 "vl.h"
#include "block_int.h"
static BlockDriverState *bdrv_first;
static BlockDriver *first_drv;
void bdrv_register(BlockDriver *bdrv)
{
bdrv->next = first_drv;
first_drv = bdrv;
}
/* create a new block device (by default it is empty) */
BlockDriverState *bdrv_new(const char *device_name)
{
BlockDriverState **pbs, *bs;
bs = qemu_mallocz(sizeof(BlockDriverState));
if(!bs)
return NULL;
pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
if (device_name[0] != '\0') {
/* insert at the end */
pbs = &bdrv_first;
while (*pbs != NULL)
pbs = &(*pbs)->next;
*pbs = bs;
}
return bs;
}
BlockDriver *bdrv_find_format(const char *format_name)
{
BlockDriver *drv1;
for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
if (!strcmp(drv1->format_name, format_name))
return drv1;
}
return NULL;
}
int bdrv_create(BlockDriver *drv,
const char *filename, int64_t size_in_sectors,
const char *backing_file, int flags)
{
if (!drv->bdrv_create)
return -ENOTSUP;
return drv->bdrv_create(filename, size_in_sectors, backing_file, flags);
}
#ifdef _WIN32
static void get_tmp_filename(char *filename, int size)
{
/* XXX: find a better function */
tmpnam(filename);
}
#else
static void get_tmp_filename(char *filename, int size)
{
int fd;
/* XXX: race condition possible */
pstrcpy(filename, size, "/tmp/vl.XXXXXX");
fd = mkstemp(filename);
close(fd);
}
#endif
static BlockDriver *find_image_format(const char *filename)
{
int fd, ret, score, score_max;
BlockDriver *drv1, *drv;
uint8_t buf[1024];
fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
if (fd < 0)
return NULL;
ret = read(fd, buf, sizeof(buf));
if (ret < 0) {
close(fd);
return NULL;
}
close(fd);
drv = NULL;
score_max = 0;
for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
score = drv1->bdrv_probe(buf, ret, filename);
if (score > score_max) {
score_max = score;
drv = drv1;
}
}
return drv;
}
int bdrv_open(BlockDriverState *bs, const char *filename, int snapshot)
{
return bdrv_open2(bs, filename, snapshot, NULL);
}
int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot,
BlockDriver *drv)
{
int ret;
char tmp_filename[1024];
bs->read_only = 0;
bs->is_temporary = 0;
bs->encrypted = 0;
if (snapshot) {
BlockDriverState *bs1;
int64_t total_size;
/* if snapshot, we create a temporary backing file and open it
instead of opening 'filename' directly */
/* if there is a backing file, use it */
bs1 = bdrv_new("");
if (!bs1) {
return -1;
}
if (bdrv_open(bs1, filename, 0) < 0) {
bdrv_delete(bs1);
return -1;
}
total_size = bs1->total_sectors;
bdrv_delete(bs1);
get_tmp_filename(tmp_filename, sizeof(tmp_filename));
/* XXX: use cow for linux as it is more efficient ? */
if (bdrv_create(&bdrv_qcow, tmp_filename,
total_size, filename, 0) < 0) {
return -1;
}
filename = tmp_filename;
bs->is_temporary = 1;
}
pstrcpy(bs->filename, sizeof(bs->filename), filename);
if (!drv) {
drv = find_image_format(filename);
if (!drv)
return -1;
}
bs->drv = drv;
bs->opaque = qemu_mallocz(drv->instance_size);
if (bs->opaque == NULL && drv->instance_size > 0)
return -1;
ret = drv->bdrv_open(bs, filename);
if (ret < 0) {
qemu_free(bs->opaque);
return -1;
}
#ifndef _WIN32
if (bs->is_temporary) {
unlink(filename);
}
#endif
if (bs->backing_file[0] != '\0' && drv->bdrv_is_allocated) {
/* if there is a backing file, use it */
bs->backing_hd = bdrv_new("");
if (!bs->backing_hd) {
fail:
bdrv_close(bs);
return -1;
}
if (bdrv_open(bs->backing_hd, bs->backing_file, 0) < 0)
goto fail;
}
bs->inserted = 1;
/* call the change callback */
if (bs->change_cb)
bs->change_cb(bs->change_opaque);
return 0;
}
void bdrv_close(BlockDriverState *bs)
{
if (bs->inserted) {
if (bs->backing_hd)
bdrv_delete(bs->backing_hd);
bs->drv->bdrv_close(bs);
qemu_free(bs->opaque);
#ifdef _WIN32
if (bs->is_temporary) {
unlink(bs->filename);
}
#endif
bs->opaque = NULL;
bs->drv = NULL;
bs->inserted = 0;
/* call the change callback */
if (bs->change_cb)
bs->change_cb(bs->change_opaque);
}
}
void bdrv_delete(BlockDriverState *bs)
{
/* XXX: remove the driver list */
bdrv_close(bs);
qemu_free(bs);
}
/* commit COW file into the raw image */
int bdrv_commit(BlockDriverState *bs)
{
int64_t i;
int n, j;
unsigned char sector[512];
if (!bs->inserted)
return -ENOENT;
if (bs->read_only) {
return -EACCES;
}
if (!bs->backing_hd) {
return -ENOTSUP;
}
for (i = 0; i < bs->total_sectors;) {
if (bs->drv->bdrv_is_allocated(bs, i, 65536, &n)) {
for(j = 0; j < n; j++) {
if (bdrv_read(bs, i, sector, 1) != 0) {
return -EIO;
}
if (bdrv_write(bs->backing_hd, i, sector, 1) != 0) {
return -EIO;
}
i++;
}
} else {
i += n;
}
}
return 0;
}
/* return -1 if error */
int bdrv_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
int ret, n;
BlockDriver *drv = bs->drv;
if (!bs->inserted)
return -1;
while (nb_sectors > 0) {
if (sector_num == 0 && bs->boot_sector_enabled) {
memcpy(buf, bs->boot_sector_data, 512);
n = 1;
} else if (bs->backing_hd) {
if (drv->bdrv_is_allocated(bs, sector_num, nb_sectors, &n)) {
ret = drv->bdrv_read(bs, sector_num, buf, n);
if (ret < 0)
return -1;
} else {
/* read from the base image */
ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
if (ret < 0)
return -1;
}
} else {
ret = drv->bdrv_read(bs, sector_num, buf, nb_sectors);
if (ret < 0)
return -1;
/* no need to loop */
break;
}
nb_sectors -= n;
sector_num += n;
buf += n * 512;
}
return 0;
}
/* return -1 if error */
int bdrv_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
if (!bs->inserted)
return -1;
if (bs->read_only)
return -1;
return bs->drv->bdrv_write(bs, sector_num, buf, nb_sectors);
}
void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr)
{
*nb_sectors_ptr = bs->total_sectors;
}
/* force a given boot sector. */
void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size)
{
bs->boot_sector_enabled = 1;
if (size > 512)
size = 512;
memcpy(bs->boot_sector_data, data, size);
memset(bs->boot_sector_data + size, 0, 512 - size);
}
void bdrv_set_geometry_hint(BlockDriverState *bs,
int cyls, int heads, int secs)
{
bs->cyls = cyls;
bs->heads = heads;
bs->secs = secs;
}
void bdrv_set_type_hint(BlockDriverState *bs, int type)
{
bs->type = type;
bs->removable = ((type == BDRV_TYPE_CDROM ||
type == BDRV_TYPE_FLOPPY));
}
void bdrv_get_geometry_hint(BlockDriverState *bs,
int *pcyls, int *pheads, int *psecs)
{
*pcyls = bs->cyls;
*pheads = bs->heads;
*psecs = bs->secs;
}
int bdrv_get_type_hint(BlockDriverState *bs)
{
return bs->type;
}
int bdrv_is_removable(BlockDriverState *bs)
{
return bs->removable;
}
int bdrv_is_read_only(BlockDriverState *bs)
{
return bs->read_only;
}
int bdrv_is_inserted(BlockDriverState *bs)
{
return bs->inserted;
}
int bdrv_is_locked(BlockDriverState *bs)
{
return bs->locked;
}
void bdrv_set_locked(BlockDriverState *bs, int locked)
{
bs->locked = locked;
}
void bdrv_set_change_cb(BlockDriverState *bs,
void (*change_cb)(void *opaque), void *opaque)
{
bs->change_cb = change_cb;
bs->change_opaque = opaque;
}
int bdrv_is_encrypted(BlockDriverState *bs)
{
if (bs->backing_hd && bs->backing_hd->encrypted)
return 1;
return bs->encrypted;
}
int bdrv_set_key(BlockDriverState *bs, const char *key)
{
int ret;
if (bs->backing_hd && bs->backing_hd->encrypted) {
ret = bdrv_set_key(bs->backing_hd, key);
if (ret < 0)
return ret;
if (!bs->encrypted)
return 0;
}
if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
return -1;
return bs->drv->bdrv_set_key(bs, key);
}
void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
{
if (!bs->inserted || !bs->drv) {
buf[0] = '\0';
} else {
pstrcpy(buf, buf_size, bs->drv->format_name);
}
}
void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
void *opaque)
{
BlockDriver *drv;
for (drv = first_drv; drv != NULL; drv = drv->next) {
it(opaque, drv->format_name);
}
}
BlockDriverState *bdrv_find(const char *name)
{
BlockDriverState *bs;
for (bs = bdrv_first; bs != NULL; bs = bs->next) {
if (!strcmp(name, bs->device_name))
return bs;
}
return NULL;
}
void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque)
{
BlockDriverState *bs;
for (bs = bdrv_first; bs != NULL; bs = bs->next) {
it(opaque, bs->device_name);
}
}
const char *bdrv_get_device_name(BlockDriverState *bs)
{
return bs->device_name;
}
void bdrv_info(void)
{
BlockDriverState *bs;
for (bs = bdrv_first; bs != NULL; bs = bs->next) {
term_printf("%s:", bs->device_name);
term_printf(" type=");
switch(bs->type) {
case BDRV_TYPE_HD:
term_printf("hd");
break;
case BDRV_TYPE_CDROM:
term_printf("cdrom");
break;
case BDRV_TYPE_FLOPPY:
term_printf("floppy");
break;
}
term_printf(" removable=%d", bs->removable);
if (bs->removable) {
term_printf(" locked=%d", bs->locked);
}
if (bs->inserted) {
term_printf(" file=%s", bs->filename);
if (bs->backing_file[0] != '\0')
term_printf(" backing_file=%s", bs->backing_file);
term_printf(" ro=%d", bs->read_only);
term_printf(" drv=%s", bs->drv->format_name);
if (bs->encrypted)
term_printf(" encrypted");
} else {
term_printf(" [not inserted]");
}
term_printf("\n");
}
}
/**************************************************************/
/* RAW block driver */
typedef struct BDRVRawState {
int fd;
} BDRVRawState;
static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
{
return 1; /* maybe */
}
static int raw_open(BlockDriverState *bs, const char *filename)
{
BDRVRawState *s = bs->opaque;
int fd;
int64_t size;
fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
if (fd < 0) {
fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
if (fd < 0)
return -1;
bs->read_only = 1;
}
size = lseek(fd, 0, SEEK_END);
bs->total_sectors = size / 512;
s->fd = fd;
return 0;
}
static int raw_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVRawState *s = bs->opaque;
int ret;
lseek(s->fd, sector_num * 512, SEEK_SET);
ret = read(s->fd, buf, nb_sectors * 512);
if (ret != nb_sectors * 512)
return -1;
return 0;
}
static int raw_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
BDRVRawState *s = bs->opaque;
int ret;
lseek(s->fd, sector_num * 512, SEEK_SET);
ret = write(s->fd, buf, nb_sectors * 512);
if (ret != nb_sectors * 512)
return -1;
return 0;
}
static void raw_close(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
close(s->fd);
}
static int raw_create(const char *filename, int64_t total_size,
const char *backing_file, int flags)
{
int fd;
if (flags || backing_file)
return -ENOTSUP;
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
0644);
if (fd < 0)
return -EIO;
ftruncate(fd, total_size * 512);
close(fd);
return 0;
}
BlockDriver bdrv_raw = {
"raw",
sizeof(BDRVRawState),
raw_probe,
raw_open,
raw_read,
raw_write,
raw_close,
raw_create,
};
void bdrv_init(void)
{
bdrv_register(&bdrv_raw);
#ifndef _WIN32
bdrv_register(&bdrv_cow);
#endif
bdrv_register(&bdrv_qcow);
bdrv_register(&bdrv_vmdk);
bdrv_register(&bdrv_cloop);
}

77
block_int.h Normal file
View File

@@ -0,0 +1,77 @@
/*
* QEMU System Emulator block driver
*
* Copyright (c) 2003 Fabrice Bellard
*
* 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 BLOCK_INT_H
#define BLOCK_INT_H
struct BlockDriver {
const char *format_name;
int instance_size;
int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename);
int (*bdrv_open)(BlockDriverState *bs, const char *filename);
int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors);
int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors);
void (*bdrv_close)(BlockDriverState *bs);
int (*bdrv_create)(const char *filename, int64_t total_sectors,
const char *backing_file, int flags);
int (*bdrv_is_allocated)(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum);
int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
struct BlockDriver *next;
};
struct BlockDriverState {
int64_t total_sectors;
int read_only; /* if true, the media is read only */
int inserted; /* if true, the media is present */
int removable; /* if true, the media can be removed */
int locked; /* if true, the media cannot temporarily be ejected */
int encrypted; /* if true, the media is encrypted */
/* event callback when inserting/removing */
void (*change_cb)(void *opaque);
void *change_opaque;
BlockDriver *drv;
void *opaque;
int boot_sector_enabled;
uint8_t boot_sector_data[512];
char filename[1024];
char backing_file[1024]; /* if non zero, the image is a diff of
this file image */
int is_temporary;
BlockDriverState *backing_hd;
/* NOTE: the following infos are only hints for real hardware
drivers. They are not used by the block driver */
int cyls, heads, secs;
int type;
char device_name[32];
BlockDriverState *next;
};
#endif /* BLOCK_INT_H */

202
bswap.h Normal file
View File

@@ -0,0 +1,202 @@
#ifndef BSWAP_H
#define BSWAP_H
#include "config-host.h"
#include <inttypes.h>
#ifdef HAVE_BYTESWAP_H
#include <byteswap.h>
#else
#define bswap_16(x) \
({ \
uint16_t __x = (x); \
((uint16_t)( \
(((uint16_t)(__x) & (uint16_t)0x00ffU) << 8) | \
(((uint16_t)(__x) & (uint16_t)0xff00U) >> 8) )); \
})
#define bswap_32(x) \
({ \
uint32_t __x = (x); \
((uint32_t)( \
(((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
(((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
(((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
(((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
})
#define bswap_64(x) \
({ \
uint64_t __x = (x); \
((uint64_t)( \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \
})
#endif /* !HAVE_BYTESWAP_H */
static inline uint16_t bswap16(uint16_t x)
{
return bswap_16(x);
}
static inline uint32_t bswap32(uint32_t x)
{
return bswap_32(x);
}
static inline uint64_t bswap64(uint64_t x)
{
return bswap_64(x);
}
static inline void bswap16s(uint16_t *s)
{
*s = bswap16(*s);
}
static inline void bswap32s(uint32_t *s)
{
*s = bswap32(*s);
}
static inline void bswap64s(uint64_t *s)
{
*s = bswap64(*s);
}
#if defined(WORDS_BIGENDIAN)
#define be_bswap(v, size) (v)
#define le_bswap(v, size) bswap ## size(v)
#define be_bswaps(v, size)
#define le_bswaps(p, size) *p = bswap ## size(*p);
#else
#define le_bswap(v, size) (v)
#define be_bswap(v, size) bswap ## size(v)
#define le_bswaps(v, size)
#define be_bswaps(p, size) *p = bswap ## size(*p);
#endif
#define CPU_CONVERT(endian, size, type)\
static inline type endian ## size ## _to_cpu(type v)\
{\
return endian ## _bswap(v, size);\
}\
\
static inline type cpu_to_ ## endian ## size(type v)\
{\
return endian ## _bswap(v, size);\
}\
\
static inline void endian ## size ## _to_cpus(type *p)\
{\
endian ## _bswaps(p, size)\
}\
\
static inline void cpu_to_ ## endian ## size ## s(type *p)\
{\
endian ## _bswaps(p, size)\
}\
\
static inline type endian ## size ## _to_cpup(const type *p)\
{\
return endian ## size ## _to_cpu(*p);\
}\
\
static inline void cpu_to_ ## endian ## size ## w(type *p, type v)\
{\
*p = cpu_to_ ## endian ## size(v);\
}
CPU_CONVERT(be, 16, uint16_t)
CPU_CONVERT(be, 32, uint32_t)
CPU_CONVERT(be, 64, uint64_t)
CPU_CONVERT(le, 16, uint16_t)
CPU_CONVERT(le, 32, uint32_t)
CPU_CONVERT(le, 64, uint64_t)
/* unaligned versions (optimized for frequent unaligned accesses)*/
#if defined(__i386__) || defined(__powerpc__)
#define cpu_to_le16wu(p, v) cpu_to_le16w(p, v)
#define cpu_to_le32wu(p, v) cpu_to_le32w(p, v)
#define le16_to_cpupu(p) le16_to_cpup(p)
#define le32_to_cpupu(p) le32_to_cpup(p)
#define cpu_to_be16wu(p, v) cpu_to_be16w(p, v)
#define cpu_to_be32wu(p, v) cpu_to_be32w(p, v)
#else
static inline void cpu_to_le16wu(uint16_t *p, uint16_t v)
{
uint8_t *p1 = (uint8_t *)p;
p1[0] = v;
p1[1] = v >> 8;
}
static inline void cpu_to_le32wu(uint32_t *p, uint32_t v)
{
uint8_t *p1 = (uint8_t *)p;
p1[0] = v;
p1[1] = v >> 8;
p1[2] = v >> 16;
p1[3] = v >> 24;
}
static inline uint16_t le16_to_cpupu(const uint16_t *p)
{
const uint8_t *p1 = (const uint8_t *)p;
return p1[0] | (p1[1] << 8);
}
static inline uint32_t le32_to_cpupu(const uint32_t *p)
{
const uint8_t *p1 = (const uint8_t *)p;
return p1[0] | (p1[1] << 8) | (p1[2] << 16) | (p1[3] << 24);
}
static inline void cpu_to_be16wu(uint16_t *p, uint16_t v)
{
uint8_t *p1 = (uint8_t *)p;
p1[0] = v >> 8;
p1[1] = v;
}
static inline void cpu_to_be32wu(uint32_t *p, uint32_t v)
{
uint8_t *p1 = (uint8_t *)p;
p1[0] = v >> 24;
p1[1] = v >> 16;
p1[2] = v >> 8;
p1[3] = v;
}
#endif
#ifdef WORDS_BIGENDIAN
#define cpu_to_32wu cpu_to_be32wu
#else
#define cpu_to_32wu cpu_to_le32wu
#endif
#undef le_bswap
#undef be_bswap
#undef le_bswaps
#undef be_bswaps
#endif /* BSWAP_H */

487
configure vendored
View File

@@ -15,10 +15,11 @@ TMPC="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.c"
TMPO="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.o"
TMPE="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}"
TMPS="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.S"
TMPH="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.h"
# default parameters
prefix="/usr/local"
prefix=""
interp_prefix="/usr/gnemul/qemu-%M"
static="no"
cross_prefix=""
cc="gcc"
host_cc="gcc"
@@ -26,9 +27,10 @@ ar="ar"
make="make"
strip="strip"
cpu=`uname -m`
target_list="i386-user i386 i386-softmmu arm-user sparc-user ppc-user ppc-softmmu sparc-softmmu"
case "$cpu" in
i386|i486|i586|i686|i86pc|BePC)
cpu="x86"
cpu="i386"
;;
armv4l)
cpu="armv4l"
@@ -36,41 +38,80 @@ case "$cpu" in
alpha)
cpu="alpha"
;;
"Power Macintosh"|ppc)
"Power Macintosh"|ppc|ppc64)
cpu="powerpc"
;;
mips)
cpu="mips"
;;
s390)
cpu="s390"
;;
sparc)
cpu="sparc"
;;
sparc64)
cpu="sparc64"
;;
ia64)
cpu="ia64"
;;
m68k)
cpu="m68k"
;;
x86_64|amd64)
cpu="amd64"
;;
*)
cpu="unknown"
;;
esac
gprof="no"
bigendian="no"
mingw32="no"
EXESUF=""
gdbstub="yes"
slirp="yes"
adlib="no"
oss="no"
fmod="no"
fmod_lib=""
fmod_inc=""
# OS specific
targetos=`uname -s`
case $targetos in
BeOS)
prefix="/boot/home/config"
# helps building libavcodec
CFLAGS="-O2 -DPIC"
# no need for libm, but the inet stuff
# Check for BONE
if (echo $BEINCLUDES|grep 'headers/be/bone' >/dev/null); then
extralibs="-lbind -lsocket"
else
echo "Not sure building for net_server will succeed... good luck."
extralibs="-lsocket"
fi ;;
BSD/OS)
extralibs="-lpoll -lgnugetopt -lm"
make="gmake"
MINGW32*)
mingw32="yes"
;;
FreeBSD)
bsd="yes"
oss="yes"
;;
NetBSD)
bsd="yes"
oss="yes"
;;
OpenBSD)
bsd="yes"
oss="yes"
;;
Darwin)
bsd="yes"
darwin="yes"
;;
*)
oss="yes"
;;
*) ;;
esac
if [ "$bsd" = "yes" ] ; then
if [ ! "$darwin" = "yes" ] ; then
make="gmake"
fi
target_list="i386-softmmu ppc-softmmu sparc-softmmu"
fi
# find source path
# XXX: we assume an absolute path is given when launching configure,
# except in './configure' case.
@@ -86,6 +127,8 @@ for opt do
case "$opt" in
--prefix=*) prefix=`echo $opt | cut -d '=' -f 2`
;;
--interp-prefix=*) interp_prefix=`echo $opt | cut -d '=' -f 2`
;;
--source-path=*) source_path=`echo $opt | cut -d '=' -f 2`
;;
--cross-prefix=*) cross_prefix=`echo $opt | cut -d '=' -f 2`
@@ -102,8 +145,26 @@ for opt do
;;
--cpu=*) cpu=`echo $opt | cut -d '=' -f 2`
;;
--target-list=*) target_list=${opt#--target-list=}
;;
--enable-gprof) gprof="yes"
;;
--static) static="yes"
;;
--disable-sdl) sdl="no"
;;
--enable-fmod) fmod="yes"
;;
--fmod-lib=*) fmod_lib=${opt#--fmod-lib=}
;;
--fmod-inc=*) fmod_inc=${opt#--fmod-inc=}
;;
--enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-"
;;
--disable-slirp) slirp="no"
;;
--enable-adlib) adlib="yes"
;;
esac
done
@@ -116,6 +177,13 @@ cc="${cross_prefix}${cc}"
ar="${cross_prefix}${ar}"
strip="${cross_prefix}${strip}"
if test "$mingw32" = "yes" ; then
target_list="i386-softmmu ppc-softmmu sparc-softmmu"
EXESUF=".exe"
gdbstub="no"
oss="no"
fi
if test -z "$cross_prefix" ; then
# ---
@@ -137,28 +205,74 @@ fi
else
# if cross compiling, cannot launch a program, so make a static guess
if test "$cpu" = "powerpc" -o "$cpu" = "mips" ; then
if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" -o "$cpu" = "sparc" -o "$cpu" = "sparc64" -o "$cpu" = "m68k"; then
bigendian="yes"
fi
fi
# check gcc version
# check gcc options support
cat > $TMPC <<EOF
int main(void) {
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)
return 0;
#else
#error gcc < 3.2
#endif
}
EOF
gcc_major="2"
if $cc -o $TMPO $TMPC 2> /dev/null ; then
gcc_major="3"
have_gcc3_options="no"
if $cc -fno-reorder-blocks -fno-optimize-sibling-calls -o $TMPO $TMPC 2> /dev/null ; then
have_gcc3_options="yes"
fi
##########################################
# SDL probe
sdl_too_old=no
if test -z "$sdl" ; then
sdl_config="sdl-config"
sdl=no
sdl_static=no
if test "$mingw32" = "yes" -a ! -z "$cross_prefix" ; then
# win32 cross compilation case
sdl_config="i386-mingw32msvc-sdl-config"
sdl=yes
else
# normal SDL probe
cat > $TMPC << EOF
#include <SDL.h>
#undef main /* We don't want SDL to override our main() */
int main( void ) { return SDL_Init (SDL_INIT_VIDEO); }
EOF
if $cc -o $TMPE `$sdl_config --cflags 2> /dev/null` $TMPC `$sdl_config --libs 2> /dev/null` 2> /dev/null ; then
_sdlversion=`$sdl_config --version | sed 's/[^0-9]//g'`
if test "$_sdlversion" -lt 121 ; then
sdl_too_old=yes
else
sdl=yes
fi
# static link with sdl ?
if test "$sdl" = "yes" ; then
aa="no"
`$sdl_config --static-libs | grep \\\-laa > /dev/null` && aa="yes"
sdl_static_libs=`$sdl_config --static-libs`
if [ "$aa" = "yes" ] ; then
sdl_static_libs="$sdl_static_libs `aalib-config --static-libs`"
fi
if $cc -o $TMPE `$sdl_config --cflags 2> /dev/null` $TMPC $sdl_static_libs 2> /dev/null; then
sdl_static=yes
fi
fi # static link
fi # sdl compile test
fi # cross compilation
fi # -z $sdl
if test x"$1" = x"-h" -o x"$1" = x"--help" ; then
cat << EOF
@@ -169,71 +283,296 @@ EOF
echo "Standard options:"
echo " --help print this message"
echo " --prefix=PREFIX install in PREFIX [$prefix]"
echo " for audio/video/image support"
echo " --interp-prefix=PREFIX where to find shared libraries, etc."
echo " use %M for cpu name [$interp_prefix]"
echo " --target-list=LIST set target list [$target_list]"
echo ""
echo "Advanced options (experts only):"
echo " --source-path=PATH path of source code [$source_path]"
echo " --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]"
echo " --cc=CC use C compiler CC [$cc]"
echo " --make=MAKE use specified make [$make]"
echo " --static enable static build [$static]"
echo " --enable-mingw32 enable Win32 cross compilation with mingw32"
echo " --enable-fmod enable FMOD audio output driver"
echo " --fmod-lib path to FMOD library"
echo " --fmod-inc path to FMOD includes"
echo ""
echo "NOTE: The object files are build at the place where configure is launched"
exit 1
fi
echo "Install prefix $prefix"
echo "Source path $source_path"
echo "C compiler $cc"
echo "make $make"
echo "CPU $cpu"
echo "Big Endian $bigendian"
echo "gprof enabled $gprof"
if test "$mingw32" = "yes" ; then
if test -z "$prefix" ; then
prefix="/c/Program Files/Qemu"
fi
mandir="$prefix"
datadir="$prefix"
docdir="$prefix"
bindir="$prefix"
else
if test -z "$prefix" ; then
prefix="/usr/local"
fi
mandir="$prefix/share/man"
datadir="$prefix/share/qemu"
docdir="$prefix/share/doc/qemu"
bindir="$prefix/bin"
fi
echo "Creating config.mak and config.h"
echo "Install prefix $prefix"
echo "BIOS directory $datadir"
echo "binary directory $bindir"
if test "$mingw32" = "no" ; then
echo "Manual directory $mandir"
echo "ELF interp prefix $interp_prefix"
fi
echo "Source path $source_path"
echo "C compiler $cc"
echo "make $make"
echo "host CPU $cpu"
echo "host big endian $bigendian"
echo "target list $target_list"
echo "gprof enabled $gprof"
echo "static build $static"
echo "SDL support $sdl"
echo "SDL static link $sdl_static"
echo "mingw32 support $mingw32"
echo "Adlib support $adlib"
echo -n "FMOD support $fmod"
if test $fmod = "yes"; then
echo -n " (lib='$fmod_lib' include='$fmod_inc')"
fi
echo ""
echo "# Automatically generated by configure - do not modify" > config.mak
echo "/* Automatically generated by configure - do not modify */" > $TMPH
if test $sdl_too_old = "yes"; then
echo "-> Your SDL version is too old - please upgrade to have FFplay/SDL support"
fi
if test "$sdl_static" = "no"; then
echo "WARNING: cannot compile statically with SDL - qemu-fast won't have a graphical output"
fi
echo "prefix=$prefix" >> config.mak
echo "#define CONFIG_QEMU_PREFIX \"$prefix\"" >> $TMPH
echo "MAKE=$make" >> config.mak
echo "CC=$cc" >> config.mak
echo "GCC_MAJOR=$gcc_major" >> config.mak
echo "HOST_CC=$host_cc" >> config.mak
echo "AR=$ar" >> config.mak
echo "STRIP=$strip -s -R .comment -R .note" >> config.mak
echo "CFLAGS=$CFLAGS" >> config.mak
echo "LDFLAGS=$LDFLAGS" >> config.mak
if test "$cpu" = "x86" ; then
echo "ARCH=i386" >> config.mak
config_mak="config-host.mak"
config_h="config-host.h"
#echo "Creating $config_mak and $config_h"
echo "# Automatically generated by configure - do not modify" > $config_mak
echo "/* Automatically generated by configure - do not modify */" > $config_h
echo "prefix=$prefix" >> $config_mak
echo "bindir=$bindir" >> $config_mak
echo "mandir=$mandir" >> $config_mak
echo "datadir=$datadir" >> $config_mak
echo "docdir=$docdir" >> $config_mak
echo "#define CONFIG_QEMU_SHAREDIR \"$datadir\"" >> $config_h
echo "MAKE=$make" >> $config_mak
echo "CC=$cc" >> $config_mak
if test "$have_gcc3_options" = "yes" ; then
echo "HAVE_GCC3_OPTIONS=yes" >> $config_mak
fi
echo "HOST_CC=$host_cc" >> $config_mak
echo "AR=$ar" >> $config_mak
echo "STRIP=$strip -s -R .comment -R .note" >> $config_mak
echo "CFLAGS=$CFLAGS" >> $config_mak
echo "LDFLAGS=$LDFLAGS" >> $config_mak
echo "EXESUF=$EXESUF" >> $config_mak
if test "$cpu" = "i386" ; then
echo "ARCH=i386" >> $config_mak
echo "#define HOST_I386 1" >> $config_h
elif test "$cpu" = "amd64" ; then
echo "ARCH=amd64" >> $config_mak
echo "#define HOST_AMD64 1" >> $config_h
elif test "$cpu" = "armv4l" ; then
echo "ARCH=arm" >> config.mak
echo "ARCH=arm" >> $config_mak
echo "#define HOST_ARM 1" >> $config_h
elif test "$cpu" = "powerpc" ; then
echo "ARCH=ppc" >> config.mak
echo "ARCH=ppc" >> $config_mak
echo "#define HOST_PPC 1" >> $config_h
elif test "$cpu" = "mips" ; then
echo "ARCH=mips" >> config.mak
echo "ARCH=mips" >> $config_mak
echo "#define HOST_MIPS 1" >> $config_h
elif test "$cpu" = "s390" ; then
echo "ARCH=s390" >> $config_mak
echo "#define HOST_S390 1" >> $config_h
elif test "$cpu" = "alpha" ; then
echo "ARCH=alpha" >> $config_mak
echo "#define HOST_ALPHA 1" >> $config_h
elif test "$cpu" = "sparc" ; then
echo "ARCH=sparc" >> $config_mak
echo "#define HOST_SPARC 1" >> $config_h
elif test "$cpu" = "sparc64" ; then
echo "ARCH=sparc64" >> $config_mak
echo "#define HOST_SPARC64 1" >> $config_h
elif test "$cpu" = "ia64" ; then
echo "ARCH=ia64" >> $config_mak
echo "#define HOST_IA64 1" >> $config_h
elif test "$cpu" = "m68k" ; then
echo "ARCH=m68k" >> $config_mak
echo "#define HOST_M68K 1" >> $config_h
else
echo "Unsupported CPU"
exit 1
fi
if test "$bigendian" = "yes" ; then
echo "WORDS_BIGENDIAN=yes" >> config.mak
echo "#define WORDS_BIGENDIAN 1" >> $TMPH
echo "WORDS_BIGENDIAN=yes" >> $config_mak
echo "#define WORDS_BIGENDIAN 1" >> $config_h
fi
if test "$mingw32" = "yes" ; then
echo "CONFIG_WIN32=yes" >> $config_mak
echo "#define CONFIG_WIN32 1" >> $config_h
elif test -f "/usr/include/byteswap.h" ; then
echo "#define HAVE_BYTESWAP_H 1" >> $config_h
fi
if test "$darwin" = "yes" ; then
echo "CONFIG_DARWIN=yes" >> $config_mak
echo "#define CONFIG_DARWIN 1" >> $config_h
fi
if test "$gdbstub" = "yes" ; then
echo "CONFIG_GDBSTUB=yes" >> $config_mak
echo "#define CONFIG_GDBSTUB 1" >> $config_h
fi
if test "$gprof" = "yes" ; then
echo "TARGET_GPROF=yes" >> config.mak
echo "#define HAVE_GPROF 1" >> $TMPH
echo "TARGET_GPROF=yes" >> $config_mak
echo "#define HAVE_GPROF 1" >> $config_h
fi
echo -n "VERSION=" >>config.mak
head $source_path/VERSION >>config.mak
echo "" >>config.mak
echo -n "#define QEMU_VERSION \"" >> $TMPH
head $source_path/VERSION >> $TMPH
echo "\"" >> $TMPH
if test "$network" = "yes" ; then
echo "#define CONFIG_NETWORK 1" >> $TMPH
echo "CONFIG_NETWORK=yes" >> config.mak
if test "$static" = "yes" ; then
echo "CONFIG_STATIC=yes" >> $config_mak
echo "#define CONFIG_STATIC 1" >> $config_h
fi
if test "$slirp" = "yes" ; then
echo "CONFIG_SLIRP=yes" >> $config_mak
echo "#define CONFIG_SLIRP 1" >> $config_h
fi
if test "$adlib" = "yes" ; then
echo "CONFIG_ADLIB=yes" >> $config_mak
echo "#define CONFIG_ADLIB 1" >> $config_h
fi
if test "$oss" = "yes" ; then
echo "CONFIG_OSS=yes" >> $config_mak
echo "#define CONFIG_OSS 1" >> $config_h
fi
if test "$fmod" = "yes" ; then
echo "CONFIG_FMOD=yes" >> $config_mak
echo "CONFIG_FMOD_LIB=$fmod_lib" >> $config_mak
echo "CONFIG_FMOD_INC=$fmod_inc" >> $config_mak
echo "#define CONFIG_FMOD 1" >> $config_h
fi
echo -n "VERSION=" >>$config_mak
head $source_path/VERSION >>$config_mak
echo "" >>$config_mak
echo -n "#define QEMU_VERSION \"" >> $config_h
head $source_path/VERSION >> $config_h
echo "\"" >> $config_h
echo "SRC_PATH=$source_path" >> $config_mak
echo "TARGET_DIRS=$target_list" >> $config_mak
# XXX: suppress that
if [ "$bsd" = "yes" ] ; then
echo "#define O_LARGEFILE 0" >> $config_h
echo "#define MAP_ANONYMOUS MAP_ANON" >> $config_h
echo "#define _BSD 1" >> $config_h
fi
for target in $target_list; do
target_dir="$target"
config_mak=$target_dir/config.mak
config_h=$target_dir/config.h
target_cpu=`echo $target | cut -d '-' -f 1`
target_bigendian="no"
[ "$target_cpu" = "sparc" ] && target_bigendian=yes
[ "$target_cpu" = "ppc" ] && target_bigendian=yes
target_softmmu="no"
if expr $target : '.*-softmmu' > /dev/null ; then
target_softmmu="yes"
fi
target_user_only="no"
if expr $target : '.*-user' > /dev/null ; then
target_user_only="yes"
fi
#echo "Creating $config_mak, $config_h and $target_dir/Makefile"
mkdir -p $target_dir
if test "$target" = "arm-user" ; then
mkdir -p $target_dir/nwfpe
fi
if test "$target_user_only" = "no" ; then
mkdir -p $target_dir/slirp
fi
ln -sf $source_path/Makefile.target $target_dir/Makefile
echo "# Automatically generated by configure - do not modify" > $config_mak
echo "/* Automatically generated by configure - do not modify */" > $config_h
echo "include ../config-host.mak" >> $config_mak
echo "#include \"../config-host.h\"" >> $config_h
interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_cpu/g"`
echo "#define CONFIG_QEMU_PREFIX \"$interp_prefix1\"" >> $config_h
if test "$target_cpu" = "i386" ; then
echo "TARGET_ARCH=i386" >> $config_mak
echo "#define TARGET_ARCH \"i386\"" >> $config_h
echo "#define TARGET_I386 1" >> $config_h
elif test "$target_cpu" = "arm" ; then
echo "TARGET_ARCH=arm" >> $config_mak
echo "#define TARGET_ARCH \"arm\"" >> $config_h
echo "#define TARGET_ARM 1" >> $config_h
elif test "$target_cpu" = "sparc" ; then
echo "TARGET_ARCH=sparc" >> $config_mak
echo "#define TARGET_ARCH \"sparc\"" >> $config_h
echo "#define TARGET_SPARC 1" >> $config_h
elif test "$target_cpu" = "ppc" ; then
echo "TARGET_ARCH=ppc" >> $config_mak
echo "#define TARGET_ARCH \"ppc\"" >> $config_h
echo "#define TARGET_PPC 1" >> $config_h
else
echo "Unsupported target CPU"
exit 1
fi
if test "$target_bigendian" = "yes" ; then
echo "TARGET_WORDS_BIGENDIAN=yes" >> $config_mak
echo "#define TARGET_WORDS_BIGENDIAN 1" >> $config_h
fi
if test "$target_softmmu" = "yes" ; then
echo "CONFIG_SOFTMMU=yes" >> $config_mak
echo "#define CONFIG_SOFTMMU 1" >> $config_h
fi
if test "$target_user_only" = "yes" ; then
echo "CONFIG_USER_ONLY=yes" >> $config_mak
echo "#define CONFIG_USER_ONLY 1" >> $config_h
fi
# sdl defines
if test "$target_user_only" = "no"; then
if test "$target_softmmu" = "no" -o "$static" = "yes"; then
sdl1=$sdl_static
else
sdl1=$sdl
fi
if test "$sdl1" = "yes" ; then
echo "#define CONFIG_SDL 1" >> $config_h
echo "CONFIG_SDL=yes" >> $config_mak
if test "$target_softmmu" = "no" -o "$static" = "yes"; then
echo "SDL_LIBS=$sdl_static_libs" >> $config_mak
else
echo "SDL_LIBS=`$sdl_config --libs`" >> $config_mak
fi
echo -n "SDL_CFLAGS=`$sdl_config --cflags`" >> $config_mak
if [ "${aa}" = "yes" ] ; then
echo -n " `aalib-config --cflags`" >> $config_mak ;
fi
echo "" >> $config_mak
fi
fi
done # for target in $targets
# build tree in object directory if source path is different from current one
if test "$source_path_used" = "yes" ; then
@@ -246,13 +585,5 @@ if test "$source_path_used" = "yes" ; then
ln -sf $source_path/$f $f
done
fi
echo "SRC_PATH=$source_path" >> config.mak
diff $TMPH config.h >/dev/null 2>&1
if test $? -ne 0 ; then
mv -f $TMPH config.h
else
echo "config.h is unchanged"
fi
rm -f $TMPH
rm -f $TMPO $TMPC $TMPE $TMPS

731
console.c Normal file
View File

@@ -0,0 +1,731 @@
/*
* QEMU graphical console
*
* Copyright (c) 2004 Fabrice Bellard
*
* 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 "vl.h"
#define DEFAULT_BACKSCROLL 512
#define MAX_CONSOLES 12
#define RGBA(r, g, b, a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
#define RGB(r, g, b) RGBA(r, g, b, 0xff)
typedef struct TextCell {
uint8_t ch;
uint8_t bgcol:4;
uint8_t fgcol:4;
} TextCell;
#define MAX_ESC_PARAMS 3
enum TTYState {
TTY_STATE_NORM,
TTY_STATE_ESC,
TTY_STATE_CSI,
};
struct TextConsole {
int text_console; /* true if text console */
DisplayState *ds;
int g_width, g_height;
int width;
int height;
int total_height;
int backscroll_height;
int fgcol;
int bgcol;
int x, y;
int y_displayed;
int y_base;
TextCell *cells;
enum TTYState state;
int esc_params[MAX_ESC_PARAMS];
int nb_esc_params;
/* kbd read handler */
IOReadHandler *fd_read;
void *fd_opaque;
};
static TextConsole *active_console;
static TextConsole *consoles[MAX_CONSOLES];
static int nb_consoles = 0;
/* convert a RGBA color to a color index usable in graphic primitives */
static unsigned int vga_get_color(DisplayState *ds, unsigned int rgba)
{
unsigned int r, g, b, color;
switch(ds->depth) {
#if 0
case 8:
r = (rgba >> 16) & 0xff;
g = (rgba >> 8) & 0xff;
b = (rgba) & 0xff;
color = (rgb_to_index[r] * 6 * 6) +
(rgb_to_index[g] * 6) +
(rgb_to_index[b]);
break;
#endif
case 15:
r = (rgba >> 16) & 0xff;
g = (rgba >> 8) & 0xff;
b = (rgba) & 0xff;
color = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
break;
case 16:
r = (rgba >> 16) & 0xff;
g = (rgba >> 8) & 0xff;
b = (rgba) & 0xff;
color = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
break;
case 32:
default:
color = rgba;
break;
}
return color;
}
static void vga_fill_rect (DisplayState *ds,
int posx, int posy, int width, int height, uint32_t color)
{
uint8_t *d, *d1;
int x, y, bpp;
bpp = (ds->depth + 7) >> 3;
d1 = ds->data +
ds->linesize * posy + bpp * posx;
for (y = 0; y < height; y++) {
d = d1;
switch(bpp) {
case 1:
for (x = 0; x < width; x++) {
*((uint8_t *)d) = color;
d++;
}
break;
case 2:
for (x = 0; x < width; x++) {
*((uint16_t *)d) = color;
d += 2;
}
break;
case 4:
for (x = 0; x < width; x++) {
*((uint32_t *)d) = color;
d += 4;
}
break;
}
d1 += ds->linesize;
}
}
/* copy from (xs, ys) to (xd, yd) a rectangle of size (w, h) */
static void vga_bitblt(DisplayState *ds, int xs, int ys, int xd, int yd, int w, int h)
{
const uint8_t *s;
uint8_t *d;
int wb, y, bpp;
bpp = (ds->depth + 7) >> 3;
wb = w * bpp;
if (yd <= ys) {
s = ds->data +
ds->linesize * ys + bpp * xs;
d = ds->data +
ds->linesize * yd + bpp * xd;
for (y = 0; y < h; y++) {
memmove(d, s, wb);
d += ds->linesize;
s += ds->linesize;
}
} else {
s = ds->data +
ds->linesize * (ys + h - 1) + bpp * xs;
d = ds->data +
ds->linesize * (yd + h - 1) + bpp * xd;
for (y = 0; y < h; y++) {
memmove(d, s, wb);
d -= ds->linesize;
s -= ds->linesize;
}
}
}
/***********************************************************/
/* basic char display */
#define FONT_HEIGHT 16
#define FONT_WIDTH 8
#include "vgafont.h"
#define cbswap_32(__x) \
((uint32_t)( \
(((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
(((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
(((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
(((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
#ifdef WORDS_BIGENDIAN
#define PAT(x) x
#else
#define PAT(x) cbswap_32(x)
#endif
static const uint32_t dmask16[16] = {
PAT(0x00000000),
PAT(0x000000ff),
PAT(0x0000ff00),
PAT(0x0000ffff),
PAT(0x00ff0000),
PAT(0x00ff00ff),
PAT(0x00ffff00),
PAT(0x00ffffff),
PAT(0xff000000),
PAT(0xff0000ff),
PAT(0xff00ff00),
PAT(0xff00ffff),
PAT(0xffff0000),
PAT(0xffff00ff),
PAT(0xffffff00),
PAT(0xffffffff),
};
static const uint32_t dmask4[4] = {
PAT(0x00000000),
PAT(0x0000ffff),
PAT(0xffff0000),
PAT(0xffffffff),
};
static uint32_t color_table[8];
static const uint32_t color_table_rgb[8] = {
RGB(0x00, 0x00, 0x00),
RGB(0xff, 0x00, 0x00),
RGB(0x00, 0xff, 0x00),
RGB(0xff, 0xff, 0x00),
RGB(0x00, 0x00, 0xff),
RGB(0xff, 0x00, 0xff),
RGB(0x00, 0xff, 0xff),
RGB(0xff, 0xff, 0xff),
};
static inline unsigned int col_expand(DisplayState *ds, unsigned int col)
{
switch(ds->depth) {
case 8:
col |= col << 8;
col |= col << 16;
break;
case 15:
case 16:
col |= col << 16;
break;
default:
break;
}
return col;
}
static void vga_putcharxy(DisplayState *ds, int x, int y, int ch,
unsigned int fgcol, unsigned int bgcol)
{
uint8_t *d;
const uint8_t *font_ptr;
unsigned int font_data, linesize, xorcol, bpp;
int i;
bpp = (ds->depth + 7) >> 3;
d = ds->data +
ds->linesize * y * FONT_HEIGHT + bpp * x * FONT_WIDTH;
linesize = ds->linesize;
font_ptr = vgafont16 + FONT_HEIGHT * ch;
xorcol = bgcol ^ fgcol;
switch(ds->depth) {
case 8:
for(i = 0; i < FONT_HEIGHT; i++) {
font_data = *font_ptr++;
((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
d += linesize;
}
break;
case 16:
case 15:
for(i = 0; i < FONT_HEIGHT; i++) {
font_data = *font_ptr++;
((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol;
((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol;
((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol;
((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
d += linesize;
}
break;
case 32:
for(i = 0; i < FONT_HEIGHT; i++) {
font_data = *font_ptr++;
((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
d += linesize;
}
break;
}
}
static void text_console_resize(TextConsole *s)
{
TextCell *cells, *c, *c1;
int w1, x, y, last_width;
last_width = s->width;
s->width = s->g_width / FONT_WIDTH;
s->height = s->g_height / FONT_HEIGHT;
w1 = last_width;
if (s->width < w1)
w1 = s->width;
cells = qemu_malloc(s->width * s->total_height * sizeof(TextCell));
for(y = 0; y < s->total_height; y++) {
c = &cells[y * s->width];
if (w1 > 0) {
c1 = &s->cells[y * last_width];
for(x = 0; x < w1; x++) {
*c++ = *c1++;
}
}
for(x = w1; x < s->width; x++) {
c->ch = ' ';
c->fgcol = 7;
c->bgcol = 0;
c++;
}
}
free(s->cells);
s->cells = cells;
}
static void update_xy(TextConsole *s, int x, int y)
{
TextCell *c;
int y1, y2;
if (s == active_console) {
y1 = (s->y_base + y) % s->total_height;
y2 = y1 - s->y_displayed;
if (y2 < 0)
y2 += s->total_height;
if (y2 < s->height) {
c = &s->cells[y1 * s->width + x];
vga_putcharxy(s->ds, x, y2, c->ch,
color_table[c->fgcol], color_table[c->bgcol]);
dpy_update(s->ds, x * FONT_WIDTH, y2 * FONT_HEIGHT,
FONT_WIDTH, FONT_HEIGHT);
}
}
}
static void console_show_cursor(TextConsole *s, int show)
{
TextCell *c;
int y, y1;
if (s == active_console) {
y1 = (s->y_base + s->y) % s->total_height;
y = y1 - s->y_displayed;
if (y < 0)
y += s->total_height;
if (y < s->height) {
c = &s->cells[y1 * s->width + s->x];
if (show) {
vga_putcharxy(s->ds, s->x, y, c->ch,
color_table[0], color_table[7]);
} else {
vga_putcharxy(s->ds, s->x, y, c->ch,
color_table[c->fgcol], color_table[c->bgcol]);
}
dpy_update(s->ds, s->x * FONT_WIDTH, y * FONT_HEIGHT,
FONT_WIDTH, FONT_HEIGHT);
}
}
}
static void console_refresh(TextConsole *s)
{
TextCell *c;
int x, y, y1;
if (s != active_console)
return;
vga_fill_rect(s->ds, 0, 0, s->ds->width, s->ds->height,
color_table[0]);
y1 = s->y_displayed;
for(y = 0; y < s->height; y++) {
c = s->cells + y1 * s->width;
for(x = 0; x < s->width; x++) {
vga_putcharxy(s->ds, x, y, c->ch,
color_table[c->fgcol], color_table[c->bgcol]);
c++;
}
if (++y1 == s->total_height)
y1 = 0;
}
dpy_update(s->ds, 0, 0, s->ds->width, s->ds->height);
console_show_cursor(s, 1);
}
static void console_scroll(int ydelta)
{
TextConsole *s;
int i, y1;
s = active_console;
if (!s || !s->text_console)
return;
if (ydelta > 0) {
for(i = 0; i < ydelta; i++) {
if (s->y_displayed == s->y_base)
break;
if (++s->y_displayed == s->total_height)
s->y_displayed = 0;
}
} else {
ydelta = -ydelta;
i = s->backscroll_height;
if (i > s->total_height - s->height)
i = s->total_height - s->height;
y1 = s->y_base - i;
if (y1 < 0)
y1 += s->total_height;
for(i = 0; i < ydelta; i++) {
if (s->y_displayed == y1)
break;
if (--s->y_displayed < 0)
s->y_displayed = s->total_height - 1;
}
}
console_refresh(s);
}
static void console_put_lf(TextConsole *s)
{
TextCell *c;
int x, y1;
s->x = 0;
s->y++;
if (s->y >= s->height) {
s->y = s->height - 1;
if (s->y_displayed == s->y_base) {
if (++s->y_displayed == s->total_height)
s->y_displayed = 0;
}
if (++s->y_base == s->total_height)
s->y_base = 0;
if (s->backscroll_height < s->total_height)
s->backscroll_height++;
y1 = (s->y_base + s->height - 1) % s->total_height;
c = &s->cells[y1 * s->width];
for(x = 0; x < s->width; x++) {
c->ch = ' ';
c->fgcol = s->fgcol;
c->bgcol = s->bgcol;
c++;
}
if (s == active_console && s->y_displayed == s->y_base) {
vga_bitblt(s->ds, 0, FONT_HEIGHT, 0, 0,
s->width * FONT_WIDTH,
(s->height - 1) * FONT_HEIGHT);
vga_fill_rect(s->ds, 0, (s->height - 1) * FONT_HEIGHT,
s->width * FONT_WIDTH, FONT_HEIGHT,
color_table[s->bgcol]);
dpy_update(s->ds, 0, 0,
s->width * FONT_WIDTH, s->height * FONT_HEIGHT);
}
}
}
static void console_putchar(TextConsole *s, int ch)
{
TextCell *c;
int y1, i, x;
switch(s->state) {
case TTY_STATE_NORM:
switch(ch) {
case '\r':
s->x = 0;
break;
case '\n':
console_put_lf(s);
break;
case 27:
s->state = TTY_STATE_ESC;
break;
default:
y1 = (s->y_base + s->y) % s->total_height;
c = &s->cells[y1 * s->width + s->x];
c->ch = ch;
c->fgcol = s->fgcol;
c->bgcol = s->bgcol;
update_xy(s, s->x, s->y);
s->x++;
if (s->x >= s->width)
console_put_lf(s);
break;
}
break;
case TTY_STATE_ESC:
if (ch == '[') {
for(i=0;i<MAX_ESC_PARAMS;i++)
s->esc_params[i] = 0;
s->nb_esc_params = 0;
s->state = TTY_STATE_CSI;
} else {
s->state = TTY_STATE_NORM;
}
break;
case TTY_STATE_CSI:
if (ch >= '0' && ch <= '9') {
if (s->nb_esc_params < MAX_ESC_PARAMS) {
s->esc_params[s->nb_esc_params] =
s->esc_params[s->nb_esc_params] * 10 + ch - '0';
}
} else {
s->nb_esc_params++;
if (ch == ';')
break;
s->state = TTY_STATE_NORM;
switch(ch) {
case 'D':
if (s->x > 0)
s->x--;
break;
case 'C':
if (s->x < (s->width - 1))
s->x++;
break;
case 'K':
/* clear to eol */
y1 = (s->y_base + s->y) % s->total_height;
for(x = s->x; x < s->width; x++) {
c = &s->cells[y1 * s->width + x];
c->ch = ' ';
c->fgcol = s->fgcol;
c->bgcol = s->bgcol;
c++;
update_xy(s, x, s->y);
}
break;
default:
break;
}
break;
}
}
}
void console_select(unsigned int index)
{
TextConsole *s;
if (index >= MAX_CONSOLES)
return;
s = consoles[index];
if (s) {
active_console = s;
if (s->text_console) {
if (s->g_width != s->ds->width ||
s->g_height != s->ds->height) {
s->g_width = s->ds->width;
s->g_height = s->ds->height;
text_console_resize(s);
}
console_refresh(s);
}
}
}
static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
{
TextConsole *s = chr->opaque;
int i;
console_show_cursor(s, 0);
for(i = 0; i < len; i++) {
console_putchar(s, buf[i]);
}
console_show_cursor(s, 1);
return len;
}
static void console_chr_add_read_handler(CharDriverState *chr,
IOCanRWHandler *fd_can_read,
IOReadHandler *fd_read, void *opaque)
{
TextConsole *s = chr->opaque;
s->fd_read = fd_read;
s->fd_opaque = opaque;
}
static void console_send_event(CharDriverState *chr, int event)
{
TextConsole *s = chr->opaque;
int i;
if (event == CHR_EVENT_FOCUS) {
for(i = 0; i < nb_consoles; i++) {
if (consoles[i] == s) {
console_select(i);
break;
}
}
}
}
/* called when an ascii key is pressed */
void kbd_put_keysym(int keysym)
{
TextConsole *s;
uint8_t buf[16], *q;
int c;
s = active_console;
if (!s || !s->text_console)
return;
switch(keysym) {
case QEMU_KEY_CTRL_UP:
console_scroll(-1);
break;
case QEMU_KEY_CTRL_DOWN:
console_scroll(1);
break;
case QEMU_KEY_CTRL_PAGEUP:
console_scroll(-10);
break;
case QEMU_KEY_CTRL_PAGEDOWN:
console_scroll(10);
break;
default:
if (s->fd_read) {
/* convert the QEMU keysym to VT100 key string */
q = buf;
if (keysym >= 0xe100 && keysym <= 0xe11f) {
*q++ = '\033';
*q++ = '[';
c = keysym - 0xe100;
if (c >= 10)
*q++ = '0' + (c / 10);
*q++ = '0' + (c % 10);
*q++ = '~';
} else if (keysym >= 0xe120 && keysym <= 0xe17f) {
*q++ = '\033';
*q++ = '[';
*q++ = keysym & 0xff;
} else {
*q++ = keysym;
}
s->fd_read(s->fd_opaque, buf, q - buf);
}
break;
}
}
TextConsole *graphic_console_init(DisplayState *ds)
{
TextConsole *s;
if (nb_consoles >= MAX_CONSOLES)
return NULL;
s = qemu_mallocz(sizeof(TextConsole));
if (!s) {
return NULL;
}
if (!active_console)
active_console = s;
s->ds = ds;
consoles[nb_consoles++] = s;
return s;
}
int is_active_console(TextConsole *s)
{
return s == active_console;
}
CharDriverState *text_console_init(DisplayState *ds)
{
CharDriverState *chr;
TextConsole *s;
int i;
static int color_inited;
chr = qemu_mallocz(sizeof(CharDriverState));
if (!chr)
return NULL;
s = graphic_console_init(ds);
if (!s) {
free(chr);
return NULL;
}
s->text_console = 1;
chr->opaque = s;
chr->chr_write = console_puts;
chr->chr_add_read_handler = console_chr_add_read_handler;
chr->chr_send_event = console_send_event;
if (!color_inited) {
color_inited = 1;
for(i = 0; i < 8; i++) {
color_table[i] = col_expand(s->ds,
vga_get_color(s->ds, color_table_rgb[i]));
}
}
s->y_displayed = 0;
s->y_base = 0;
s->total_height = DEFAULT_BACKSCROLL;
s->x = 0;
s->y = 0;
s->fgcol = 7;
s->bgcol = 0;
s->g_width = s->ds->width;
s->g_height = s->ds->height;
text_console_resize(s);
return chr;
}

727
cpu-all.h Normal file
View File

@@ -0,0 +1,727 @@
/*
* defines common to all virtual CPUs
*
* Copyright (c) 2003 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef CPU_ALL_H
#define CPU_ALL_H
#if defined(__arm__) || defined(__sparc__)
#define WORDS_ALIGNED
#endif
/* some important defines:
*
* WORDS_ALIGNED : if defined, the host cpu can only make word aligned
* memory accesses.
*
* WORDS_BIGENDIAN : if defined, the host cpu is big endian and
* otherwise little endian.
*
* (TARGET_WORDS_ALIGNED : same for target cpu (not supported yet))
*
* TARGET_WORDS_BIGENDIAN : same for target cpu
*/
#include "bswap.h"
#if defined(WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
#define BSWAP_NEEDED
#endif
#ifdef BSWAP_NEEDED
static inline uint16_t tswap16(uint16_t s)
{
return bswap16(s);
}
static inline uint32_t tswap32(uint32_t s)
{
return bswap32(s);
}
static inline uint64_t tswap64(uint64_t s)
{
return bswap64(s);
}
static inline void tswap16s(uint16_t *s)
{
*s = bswap16(*s);
}
static inline void tswap32s(uint32_t *s)
{
*s = bswap32(*s);
}
static inline void tswap64s(uint64_t *s)
{
*s = bswap64(*s);
}
#else
static inline uint16_t tswap16(uint16_t s)
{
return s;
}
static inline uint32_t tswap32(uint32_t s)
{
return s;
}
static inline uint64_t tswap64(uint64_t s)
{
return s;
}
static inline void tswap16s(uint16_t *s)
{
}
static inline void tswap32s(uint32_t *s)
{
}
static inline void tswap64s(uint64_t *s)
{
}
#endif
#if TARGET_LONG_SIZE == 4
#define tswapl(s) tswap32(s)
#define tswapls(s) tswap32s((uint32_t *)(s))
#else
#define tswapl(s) tswap64(s)
#define tswapls(s) tswap64s((uint64_t *)(s))
#endif
/* NOTE: arm is horrible as double 32 bit words are stored in big endian ! */
typedef union {
double d;
#if !defined(WORDS_BIGENDIAN) && !defined(__arm__)
struct {
uint32_t lower;
uint32_t upper;
} l;
#else
struct {
uint32_t upper;
uint32_t lower;
} l;
#endif
uint64_t ll;
} CPU_DoubleU;
/* CPU memory access without any memory or io remapping */
/*
* the generic syntax for the memory accesses is:
*
* load: ld{type}{sign}{size}{endian}_{access_type}(ptr)
*
* store: st{type}{size}{endian}_{access_type}(ptr, val)
*
* type is:
* (empty): integer access
* f : float access
*
* sign is:
* (empty): for floats or 32 bit size
* u : unsigned
* s : signed
*
* size is:
* b: 8 bits
* w: 16 bits
* l: 32 bits
* q: 64 bits
*
* endian is:
* (empty): target cpu endianness or 8 bit access
* r : reversed target cpu endianness (not implemented yet)
* be : big endian (not implemented yet)
* le : little endian (not implemented yet)
*
* access_type is:
* raw : host memory access
* user : user mode access using soft MMU
* kernel : kernel mode access using soft MMU
*/
static inline int ldub_raw(void *ptr)
{
return *(uint8_t *)ptr;
}
static inline int ldsb_raw(void *ptr)
{
return *(int8_t *)ptr;
}
static inline void stb_raw(void *ptr, int v)
{
*(uint8_t *)ptr = v;
}
/* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the
kernel handles unaligned load/stores may give better results, but
it is a system wide setting : bad */
#if !defined(TARGET_WORDS_BIGENDIAN) && (defined(WORDS_BIGENDIAN) || defined(WORDS_ALIGNED))
/* conservative code for little endian unaligned accesses */
static inline int lduw_raw(void *ptr)
{
#ifdef __powerpc__
int val;
__asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
return val;
#else
uint8_t *p = ptr;
return p[0] | (p[1] << 8);
#endif
}
static inline int ldsw_raw(void *ptr)
{
#ifdef __powerpc__
int val;
__asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
return (int16_t)val;
#else
uint8_t *p = ptr;
return (int16_t)(p[0] | (p[1] << 8));
#endif
}
static inline int ldl_raw(void *ptr)
{
#ifdef __powerpc__
int val;
__asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
return val;
#else
uint8_t *p = ptr;
return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
#endif
}
static inline uint64_t ldq_raw(void *ptr)
{
uint8_t *p = ptr;
uint32_t v1, v2;
v1 = ldl_raw(p);
v2 = ldl_raw(p + 4);
return v1 | ((uint64_t)v2 << 32);
}
static inline void stw_raw(void *ptr, int v)
{
#ifdef __powerpc__
__asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
#else
uint8_t *p = ptr;
p[0] = v;
p[1] = v >> 8;
#endif
}
static inline void stl_raw(void *ptr, int v)
{
#ifdef __powerpc__
__asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
#else
uint8_t *p = ptr;
p[0] = v;
p[1] = v >> 8;
p[2] = v >> 16;
p[3] = v >> 24;
#endif
}
static inline void stq_raw(void *ptr, uint64_t v)
{
uint8_t *p = ptr;
stl_raw(p, (uint32_t)v);
stl_raw(p + 4, v >> 32);
}
/* float access */
static inline float ldfl_raw(void *ptr)
{
union {
float f;
uint32_t i;
} u;
u.i = ldl_raw(ptr);
return u.f;
}
static inline void stfl_raw(void *ptr, float v)
{
union {
float f;
uint32_t i;
} u;
u.f = v;
stl_raw(ptr, u.i);
}
static inline double ldfq_raw(void *ptr)
{
CPU_DoubleU u;
u.l.lower = ldl_raw(ptr);
u.l.upper = ldl_raw(ptr + 4);
return u.d;
}
static inline void stfq_raw(void *ptr, double v)
{
CPU_DoubleU u;
u.d = v;
stl_raw(ptr, u.l.lower);
stl_raw(ptr + 4, u.l.upper);
}
#elif defined(TARGET_WORDS_BIGENDIAN) && (!defined(WORDS_BIGENDIAN) || defined(WORDS_ALIGNED))
static inline int lduw_raw(void *ptr)
{
#if defined(__i386__)
int val;
asm volatile ("movzwl %1, %0\n"
"xchgb %b0, %h0\n"
: "=q" (val)
: "m" (*(uint16_t *)ptr));
return val;
#else
uint8_t *b = (uint8_t *) ptr;
return ((b[0] << 8) | b[1]);
#endif
}
static inline int ldsw_raw(void *ptr)
{
#if defined(__i386__)
int val;
asm volatile ("movzwl %1, %0\n"
"xchgb %b0, %h0\n"
: "=q" (val)
: "m" (*(uint16_t *)ptr));
return (int16_t)val;
#else
uint8_t *b = (uint8_t *) ptr;
return (int16_t)((b[0] << 8) | b[1]);
#endif
}
static inline int ldl_raw(void *ptr)
{
#if defined(__i386__) || defined(__x86_64__)
int val;
asm volatile ("movl %1, %0\n"
"bswap %0\n"
: "=r" (val)
: "m" (*(uint32_t *)ptr));
return val;
#else
uint8_t *b = (uint8_t *) ptr;
return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
#endif
}
static inline uint64_t ldq_raw(void *ptr)
{
uint32_t a,b;
a = ldl_raw(ptr);
b = ldl_raw(ptr+4);
return (((uint64_t)a<<32)|b);
}
static inline void stw_raw(void *ptr, int v)
{
#if defined(__i386__)
asm volatile ("xchgb %b0, %h0\n"
"movw %w0, %1\n"
: "=q" (v)
: "m" (*(uint16_t *)ptr), "0" (v));
#else
uint8_t *d = (uint8_t *) ptr;
d[0] = v >> 8;
d[1] = v;
#endif
}
static inline void stl_raw(void *ptr, int v)
{
#if defined(__i386__) || defined(__x86_64__)
asm volatile ("bswap %0\n"
"movl %0, %1\n"
: "=r" (v)
: "m" (*(uint32_t *)ptr), "0" (v));
#else
uint8_t *d = (uint8_t *) ptr;
d[0] = v >> 24;
d[1] = v >> 16;
d[2] = v >> 8;
d[3] = v;
#endif
}
static inline void stq_raw(void *ptr, uint64_t v)
{
stl_raw(ptr, v >> 32);
stl_raw(ptr + 4, v);
}
/* float access */
static inline float ldfl_raw(void *ptr)
{
union {
float f;
uint32_t i;
} u;
u.i = ldl_raw(ptr);
return u.f;
}
static inline void stfl_raw(void *ptr, float v)
{
union {
float f;
uint32_t i;
} u;
u.f = v;
stl_raw(ptr, u.i);
}
static inline double ldfq_raw(void *ptr)
{
CPU_DoubleU u;
u.l.upper = ldl_raw(ptr);
u.l.lower = ldl_raw(ptr + 4);
return u.d;
}
static inline void stfq_raw(void *ptr, double v)
{
CPU_DoubleU u;
u.d = v;
stl_raw(ptr, u.l.upper);
stl_raw(ptr + 4, u.l.lower);
}
#else
static inline int lduw_raw(void *ptr)
{
return *(uint16_t *)ptr;
}
static inline int ldsw_raw(void *ptr)
{
return *(int16_t *)ptr;
}
static inline int ldl_raw(void *ptr)
{
return *(uint32_t *)ptr;
}
static inline uint64_t ldq_raw(void *ptr)
{
return *(uint64_t *)ptr;
}
static inline void stw_raw(void *ptr, int v)
{
*(uint16_t *)ptr = v;
}
static inline void stl_raw(void *ptr, int v)
{
*(uint32_t *)ptr = v;
}
static inline void stq_raw(void *ptr, uint64_t v)
{
*(uint64_t *)ptr = v;
}
/* float access */
static inline float ldfl_raw(void *ptr)
{
return *(float *)ptr;
}
static inline double ldfq_raw(void *ptr)
{
return *(double *)ptr;
}
static inline void stfl_raw(void *ptr, float v)
{
*(float *)ptr = v;
}
static inline void stfq_raw(void *ptr, double v)
{
*(double *)ptr = v;
}
#endif
/* MMU memory access macros */
#if defined(CONFIG_USER_ONLY)
/* if user mode, no other memory access functions */
#define ldub(p) ldub_raw(p)
#define ldsb(p) ldsb_raw(p)
#define lduw(p) lduw_raw(p)
#define ldsw(p) ldsw_raw(p)
#define ldl(p) ldl_raw(p)
#define ldq(p) ldq_raw(p)
#define ldfl(p) ldfl_raw(p)
#define ldfq(p) ldfq_raw(p)
#define stb(p, v) stb_raw(p, v)
#define stw(p, v) stw_raw(p, v)
#define stl(p, v) stl_raw(p, v)
#define stq(p, v) stq_raw(p, v)
#define stfl(p, v) stfl_raw(p, v)
#define stfq(p, v) stfq_raw(p, v)
#define ldub_code(p) ldub_raw(p)
#define ldsb_code(p) ldsb_raw(p)
#define lduw_code(p) lduw_raw(p)
#define ldsw_code(p) ldsw_raw(p)
#define ldl_code(p) ldl_raw(p)
#define ldub_kernel(p) ldub_raw(p)
#define ldsb_kernel(p) ldsb_raw(p)
#define lduw_kernel(p) lduw_raw(p)
#define ldsw_kernel(p) ldsw_raw(p)
#define ldl_kernel(p) ldl_raw(p)
#define ldfl_kernel(p) ldfl_raw(p)
#define ldfq_kernel(p) ldfq_raw(p)
#define stb_kernel(p, v) stb_raw(p, v)
#define stw_kernel(p, v) stw_raw(p, v)
#define stl_kernel(p, v) stl_raw(p, v)
#define stq_kernel(p, v) stq_raw(p, v)
#define stfl_kernel(p, v) stfl_raw(p, v)
#define stfq_kernel(p, vt) stfq_raw(p, v)
#endif /* defined(CONFIG_USER_ONLY) */
/* page related stuff */
#define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS)
#define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1)
#define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK)
extern unsigned long qemu_real_host_page_size;
extern unsigned long qemu_host_page_bits;
extern unsigned long qemu_host_page_size;
extern unsigned long qemu_host_page_mask;
#define HOST_PAGE_ALIGN(addr) (((addr) + qemu_host_page_size - 1) & qemu_host_page_mask)
/* same as PROT_xxx */
#define PAGE_READ 0x0001
#define PAGE_WRITE 0x0002
#define PAGE_EXEC 0x0004
#define PAGE_BITS (PAGE_READ | PAGE_WRITE | PAGE_EXEC)
#define PAGE_VALID 0x0008
/* original state of the write flag (used when tracking self-modifying
code */
#define PAGE_WRITE_ORG 0x0010
void page_dump(FILE *f);
int page_get_flags(unsigned long address);
void page_set_flags(unsigned long start, unsigned long end, int flags);
void page_unprotect_range(uint8_t *data, unsigned long data_size);
#define SINGLE_CPU_DEFINES
#ifdef SINGLE_CPU_DEFINES
#if defined(TARGET_I386)
#define CPUState CPUX86State
#define cpu_init cpu_x86_init
#define cpu_exec cpu_x86_exec
#define cpu_gen_code cpu_x86_gen_code
#define cpu_signal_handler cpu_x86_signal_handler
#elif defined(TARGET_ARM)
#define CPUState CPUARMState
#define cpu_init cpu_arm_init
#define cpu_exec cpu_arm_exec
#define cpu_gen_code cpu_arm_gen_code
#define cpu_signal_handler cpu_arm_signal_handler
#elif defined(TARGET_SPARC)
#define CPUState CPUSPARCState
#define cpu_init cpu_sparc_init
#define cpu_exec cpu_sparc_exec
#define cpu_gen_code cpu_sparc_gen_code
#define cpu_signal_handler cpu_sparc_signal_handler
#elif defined(TARGET_PPC)
#define CPUState CPUPPCState
#define cpu_init cpu_ppc_init
#define cpu_exec cpu_ppc_exec
#define cpu_gen_code cpu_ppc_gen_code
#define cpu_signal_handler cpu_ppc_signal_handler
#else
#error unsupported target CPU
#endif
#endif /* SINGLE_CPU_DEFINES */
void cpu_dump_state(CPUState *env, FILE *f,
int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
int flags);
void cpu_abort(CPUState *env, const char *fmt, ...);
extern CPUState *cpu_single_env;
extern int code_copy_enabled;
#define CPU_INTERRUPT_EXIT 0x01 /* wants exit from main loop */
#define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */
#define CPU_INTERRUPT_EXITTB 0x04 /* exit the current TB (use for x86 a20 case) */
#define CPU_INTERRUPT_TIMER 0x08 /* internal timer exception pending */
void cpu_interrupt(CPUState *s, int mask);
void cpu_reset_interrupt(CPUState *env, int mask);
int cpu_breakpoint_insert(CPUState *env, target_ulong pc);
int cpu_breakpoint_remove(CPUState *env, target_ulong pc);
void cpu_single_step(CPUState *env, int enabled);
void cpu_reset(CPUState *s);
/* Return the physical page corresponding to a virtual one. Use it
only for debugging because no protection checks are done. Return -1
if no page found. */
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr);
#define CPU_LOG_TB_OUT_ASM (1 << 0)
#define CPU_LOG_TB_IN_ASM (1 << 1)
#define CPU_LOG_TB_OP (1 << 2)
#define CPU_LOG_TB_OP_OPT (1 << 3)
#define CPU_LOG_INT (1 << 4)
#define CPU_LOG_EXEC (1 << 5)
#define CPU_LOG_PCALL (1 << 6)
#define CPU_LOG_IOPORT (1 << 7)
#define CPU_LOG_TB_CPU (1 << 8)
/* define log items */
typedef struct CPULogItem {
int mask;
const char *name;
const char *help;
} CPULogItem;
extern CPULogItem cpu_log_items[];
void cpu_set_log(int log_flags);
void cpu_set_log_filename(const char *filename);
int cpu_str_to_log_mask(const char *str);
/* IO ports API */
/* NOTE: as these functions may be even used when there is an isa
brige on non x86 targets, we always defined them */
#ifndef NO_CPU_IO_DEFS
void cpu_outb(CPUState *env, int addr, int val);
void cpu_outw(CPUState *env, int addr, int val);
void cpu_outl(CPUState *env, int addr, int val);
int cpu_inb(CPUState *env, int addr);
int cpu_inw(CPUState *env, int addr);
int cpu_inl(CPUState *env, int addr);
#endif
/* memory API */
extern int phys_ram_size;
extern int phys_ram_fd;
extern uint8_t *phys_ram_base;
extern uint8_t *phys_ram_dirty;
/* physical memory access */
#define IO_MEM_NB_ENTRIES 256
#define TLB_INVALID_MASK (1 << 3)
#define IO_MEM_SHIFT 4
#define IO_MEM_RAM (0 << IO_MEM_SHIFT) /* hardcoded offset */
#define IO_MEM_ROM (1 << IO_MEM_SHIFT) /* hardcoded offset */
#define IO_MEM_UNASSIGNED (2 << IO_MEM_SHIFT)
#define IO_MEM_CODE (3 << IO_MEM_SHIFT) /* used internally, never use directly */
#define IO_MEM_NOTDIRTY (4 << IO_MEM_SHIFT) /* used internally, never use directly */
typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value);
typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr);
void cpu_register_physical_memory(target_phys_addr_t start_addr,
unsigned long size,
unsigned long phys_offset);
int cpu_register_io_memory(int io_index,
CPUReadMemoryFunc **mem_read,
CPUWriteMemoryFunc **mem_write,
void *opaque);
CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index);
CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index);
void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
int len, int is_write);
static inline void cpu_physical_memory_read(target_phys_addr_t addr,
uint8_t *buf, int len)
{
cpu_physical_memory_rw(addr, buf, len, 0);
}
static inline void cpu_physical_memory_write(target_phys_addr_t addr,
const uint8_t *buf, int len)
{
cpu_physical_memory_rw(addr, (uint8_t *)buf, len, 1);
}
int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
uint8_t *buf, int len, int is_write);
/* read dirty bit (return 0 or 1) */
static inline int cpu_physical_memory_is_dirty(target_ulong addr)
{
return phys_ram_dirty[addr >> TARGET_PAGE_BITS];
}
static inline void cpu_physical_memory_set_dirty(target_ulong addr)
{
phys_ram_dirty[addr >> TARGET_PAGE_BITS] = 1;
}
void cpu_physical_memory_reset_dirty(target_ulong start, target_ulong end);
#endif /* CPU_ALL_H */

95
cpu-defs.h Normal file
View File

@@ -0,0 +1,95 @@
/*
* common defines for all CPUs
*
* Copyright (c) 2003 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef CPU_DEFS_H
#define CPU_DEFS_H
#include "config.h"
#include <setjmp.h>
#include <inttypes.h>
#include "osdep.h"
#ifndef TARGET_LONG_BITS
#error TARGET_LONG_BITS must be defined before including this header
#endif
#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
#define HOST_LONG_BITS 64
#else
#define HOST_LONG_BITS 32
#endif
#ifndef TARGET_PHYS_ADDR_BITS
#if TARGET_LONG_BITS >= HOST_LONG_BITS
#define TARGET_PHYS_ADDR_BITS TARGET_LONG_BITS
#else
#define TARGET_PHYS_ADDR_BITS HOST_LONG_BITS
#endif
#endif
#define TARGET_LONG_SIZE (TARGET_LONG_BITS / 8)
/* target_ulong is the type of a virtual address */
#if TARGET_LONG_SIZE == 4
typedef int32_t target_long;
typedef uint32_t target_ulong;
#elif TARGET_LONG_SIZE == 8
typedef int64_t target_long;
typedef uint64_t target_ulong;
#else
#error TARGET_LONG_SIZE undefined
#endif
/* target_phys_addr_t is the type of a physical address (its size can
be different from 'target_ulong'). We have sizeof(target_phys_addr)
= max(sizeof(unsigned long),
sizeof(size_of_target_physical_address)) because we must pass a
host pointer to memory operations in some cases */
#if TARGET_PHYS_ADDR_BITS == 32
typedef uint32_t target_phys_addr_t;
#elif TARGET_PHYS_ADDR_BITS == 64
typedef uint64_t target_phys_addr_t;
#else
#error TARGET_PHYS_ADDR_BITS undefined
#endif
#define HOST_LONG_SIZE (HOST_LONG_BITS / 8)
#define EXCP_INTERRUPT 256 /* async interruption */
#define EXCP_HLT 257 /* hlt instruction reached */
#define EXCP_DEBUG 258 /* cpu stopped after a breakpoint or singlestep */
#define MAX_BREAKPOINTS 32
#define CPU_TLB_SIZE 256
typedef struct CPUTLBEntry {
/* bit 31 to TARGET_PAGE_BITS : virtual address
bit TARGET_PAGE_BITS-1..IO_MEM_SHIFT : if non zero, memory io
zone number
bit 3 : indicates that the entry is invalid
bit 2..0 : zero
*/
target_ulong address;
/* addend to virtual address to get physical address */
target_phys_addr_t addend;
} CPUTLBEntry;
#endif

1038
cpu-exec.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,428 +0,0 @@
/*
* i386 virtual CPU header
*
* Copyright (c) 2003 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef CPU_I386_H
#define CPU_I386_H
#include "config.h"
#include <setjmp.h>
#define R_EAX 0
#define R_ECX 1
#define R_EDX 2
#define R_EBX 3
#define R_ESP 4
#define R_EBP 5
#define R_ESI 6
#define R_EDI 7
#define R_AL 0
#define R_CL 1
#define R_DL 2
#define R_BL 3
#define R_AH 4
#define R_CH 5
#define R_DH 6
#define R_BH 7
#define R_ES 0
#define R_CS 1
#define R_SS 2
#define R_DS 3
#define R_FS 4
#define R_GS 5
#define CC_C 0x0001
#define CC_P 0x0004
#define CC_A 0x0010
#define CC_Z 0x0040
#define CC_S 0x0080
#define CC_O 0x0800
#define TRAP_FLAG 0x0100
#define INTERRUPT_FLAG 0x0200
#define DIRECTION_FLAG 0x0400
#define IOPL_FLAG_MASK 0x3000
#define NESTED_FLAG 0x4000
#define BYTE_FL 0x8000 /* Intel reserved! */
#define RF_FLAG 0x10000
#define VM_FLAG 0x20000
/* AC 0x40000 */
#define EXCP00_DIVZ 1
#define EXCP01_SSTP 2
#define EXCP02_NMI 3
#define EXCP03_INT3 4
#define EXCP04_INTO 5
#define EXCP05_BOUND 6
#define EXCP06_ILLOP 7
#define EXCP07_PREX 8
#define EXCP08_DBLE 9
#define EXCP09_XERR 10
#define EXCP0A_TSS 11
#define EXCP0B_NOSEG 12
#define EXCP0C_STACK 13
#define EXCP0D_GPF 14
#define EXCP0E_PAGE 15
#define EXCP10_COPR 17
#define EXCP11_ALGN 18
#define EXCP12_MCHK 19
#define EXCP_INTERRUPT 256 /* async interruption */
enum {
CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
CC_OP_EFLAGS, /* all cc are explicitely computed, CC_SRC = flags */
CC_OP_MUL, /* modify all flags, C, O = (CC_SRC != 0) */
CC_OP_ADDB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
CC_OP_ADDW,
CC_OP_ADDL,
CC_OP_ADCB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
CC_OP_ADCW,
CC_OP_ADCL,
CC_OP_SUBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
CC_OP_SUBW,
CC_OP_SUBL,
CC_OP_SBBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
CC_OP_SBBW,
CC_OP_SBBL,
CC_OP_LOGICB, /* modify all flags, CC_DST = res */
CC_OP_LOGICW,
CC_OP_LOGICL,
CC_OP_INCB, /* modify all flags except, CC_DST = res, CC_SRC = C */
CC_OP_INCW,
CC_OP_INCL,
CC_OP_DECB, /* modify all flags except, CC_DST = res, CC_SRC = C */
CC_OP_DECW,
CC_OP_DECL,
CC_OP_SHLB, /* modify all flags, CC_DST = res, CC_SRC.lsb = C */
CC_OP_SHLW,
CC_OP_SHLL,
CC_OP_SARB, /* modify all flags, CC_DST = res, CC_SRC.lsb = C */
CC_OP_SARW,
CC_OP_SARL,
CC_OP_NB,
};
#ifdef __i386__
#define USE_X86LDOUBLE
#endif
#ifdef USE_X86LDOUBLE
typedef long double CPU86_LDouble;
#else
typedef double CPU86_LDouble;
#endif
typedef struct SegmentCache {
uint8_t *base;
unsigned long limit;
uint8_t seg_32bit;
} SegmentCache;
typedef struct SegmentDescriptorTable {
uint8_t *base;
unsigned long limit;
/* this is the returned base when reading the register, just to
avoid that the emulated program modifies it */
unsigned long emu_base;
} SegmentDescriptorTable;
typedef struct CPUX86State {
/* standard registers */
uint32_t regs[8];
uint32_t eip;
uint32_t eflags;
/* emulator internal eflags handling */
uint32_t cc_src;
uint32_t cc_dst;
uint32_t cc_op;
int32_t df; /* D flag : 1 if D = 0, -1 if D = 1 */
/* FPU state */
unsigned int fpstt; /* top of stack index */
unsigned int fpus;
unsigned int fpuc;
uint8_t fptags[8]; /* 0 = valid, 1 = empty */
CPU86_LDouble fpregs[8];
/* emulator internal variables */
CPU86_LDouble ft0;
/* segments */
uint32_t segs[6]; /* selector values */
SegmentCache seg_cache[6]; /* info taken from LDT/GDT */
SegmentDescriptorTable gdt;
SegmentDescriptorTable ldt;
SegmentDescriptorTable idt;
/* various CPU modes */
int vm86;
/* exception/interrupt handling */
jmp_buf jmp_env;
int exception_index;
int interrupt_request;
} CPUX86State;
/* all CPU memory access use these macros */
static inline int ldub(void *ptr)
{
return *(uint8_t *)ptr;
}
static inline int ldsb(void *ptr)
{
return *(int8_t *)ptr;
}
static inline void stb(void *ptr, int v)
{
*(uint8_t *)ptr = v;
}
#ifdef WORDS_BIGENDIAN
/* conservative code for little endian unaligned accesses */
static inline int lduw(void *ptr)
{
#ifdef __powerpc__
int val;
__asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
return val;
#else
uint8_t *p = ptr;
return p[0] | (p[1] << 8);
#endif
}
static inline int ldsw(void *ptr)
{
#ifdef __powerpc__
int val;
__asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
return (int16_t)val;
#else
uint8_t *p = ptr;
return (int16_t)(p[0] | (p[1] << 8));
#endif
}
static inline int ldl(void *ptr)
{
#ifdef __powerpc__
int val;
__asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
return val;
#else
uint8_t *p = ptr;
return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
#endif
}
static inline uint64_t ldq(void *ptr)
{
uint8_t *p = ptr;
uint32_t v1, v2;
v1 = ldl(p);
v2 = ldl(p + 4);
return v1 | ((uint64_t)v2 << 32);
}
static inline void stw(void *ptr, int v)
{
#ifdef __powerpc__
__asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
#else
uint8_t *p = ptr;
p[0] = v;
p[1] = v >> 8;
#endif
}
static inline void stl(void *ptr, int v)
{
#ifdef __powerpc__
__asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
#else
uint8_t *p = ptr;
p[0] = v;
p[1] = v >> 8;
p[2] = v >> 16;
p[3] = v >> 24;
#endif
}
static inline void stq(void *ptr, uint64_t v)
{
uint8_t *p = ptr;
stl(p, (uint32_t)v);
stl(p + 4, v >> 32);
}
/* float access */
static inline float ldfl(void *ptr)
{
union {
float f;
uint32_t i;
} u;
u.i = ldl(ptr);
return u.f;
}
static inline double ldfq(void *ptr)
{
union {
double d;
uint64_t i;
} u;
u.i = ldq(ptr);
return u.d;
}
static inline void stfl(void *ptr, float v)
{
union {
float f;
uint32_t i;
} u;
u.f = v;
stl(ptr, u.i);
}
static inline void stfq(void *ptr, double v)
{
union {
double d;
uint64_t i;
} u;
u.d = v;
stq(ptr, u.i);
}
#else
static inline int lduw(void *ptr)
{
return *(uint16_t *)ptr;
}
static inline int ldsw(void *ptr)
{
return *(int16_t *)ptr;
}
static inline int ldl(void *ptr)
{
return *(uint32_t *)ptr;
}
static inline uint64_t ldq(void *ptr)
{
return *(uint64_t *)ptr;
}
static inline void stw(void *ptr, int v)
{
*(uint16_t *)ptr = v;
}
static inline void stl(void *ptr, int v)
{
*(uint32_t *)ptr = v;
}
static inline void stq(void *ptr, uint64_t v)
{
*(uint64_t *)ptr = v;
}
/* float access */
static inline float ldfl(void *ptr)
{
return *(float *)ptr;
}
static inline double ldfq(void *ptr)
{
return *(double *)ptr;
}
static inline void stfl(void *ptr, float v)
{
*(float *)ptr = v;
}
static inline void stfq(void *ptr, double v)
{
*(double *)ptr = v;
}
#endif
#ifndef IN_OP_I386
void cpu_x86_outb(int addr, int val);
void cpu_x86_outw(int addr, int val);
void cpu_x86_outl(int addr, int val);
int cpu_x86_inb(int addr);
int cpu_x86_inw(int addr);
int cpu_x86_inl(int addr);
#endif
CPUX86State *cpu_x86_init(void);
int cpu_x86_exec(CPUX86State *s);
void cpu_x86_interrupt(CPUX86State *s);
void cpu_x86_close(CPUX86State *s);
/* needed to load some predefinied segment registers */
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector);
/* you can call this signal handler from your SIGBUS and SIGSEGV
signal handlers to inform the virtual CPU of exceptions. non zero
is returned if the signal was handled by the virtual CPU. */
struct siginfo;
int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
void *puc);
/* internal functions */
#define GEN_FLAG_CODE32_SHIFT 0
#define GEN_FLAG_ADDSEG_SHIFT 1
#define GEN_FLAG_SS32_SHIFT 2
#define GEN_FLAG_ST_SHIFT 3
int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
int *gen_code_size_ptr,
uint8_t *pc_start, uint8_t *cs_base, int flags);
void cpu_x86_tblocks_init(void);
#endif /* CPU_I386_H */

174
dis-asm.h
View File

@@ -11,7 +11,161 @@
#include <stdio.h>
#include <string.h>
#include "bfd.h"
#include <inttypes.h>
#define PARAMS(x) x
typedef void *PTR;
typedef uint64_t bfd_vma;
typedef int64_t bfd_signed_vma;
typedef uint8_t bfd_byte;
#define sprintf_vma(s,x) sprintf (s, "%0" PRIx64, x)
enum bfd_flavour {
bfd_target_unknown_flavour,
bfd_target_aout_flavour,
bfd_target_coff_flavour,
bfd_target_ecoff_flavour,
bfd_target_elf_flavour,
bfd_target_ieee_flavour,
bfd_target_nlm_flavour,
bfd_target_oasys_flavour,
bfd_target_tekhex_flavour,
bfd_target_srec_flavour,
bfd_target_ihex_flavour,
bfd_target_som_flavour,
bfd_target_os9k_flavour,
bfd_target_versados_flavour,
bfd_target_msdos_flavour,
bfd_target_evax_flavour
};
enum bfd_endian { BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN };
enum bfd_architecture
{
bfd_arch_unknown, /* File arch not known */
bfd_arch_obscure, /* Arch known, not one of these */
bfd_arch_m68k, /* Motorola 68xxx */
#define bfd_mach_m68000 1
#define bfd_mach_m68008 2
#define bfd_mach_m68010 3
#define bfd_mach_m68020 4
#define bfd_mach_m68030 5
#define bfd_mach_m68040 6
#define bfd_mach_m68060 7
bfd_arch_vax, /* DEC Vax */
bfd_arch_i960, /* Intel 960 */
/* The order of the following is important.
lower number indicates a machine type that
only accepts a subset of the instructions
available to machines with higher numbers.
The exception is the "ca", which is
incompatible with all other machines except
"core". */
#define bfd_mach_i960_core 1
#define bfd_mach_i960_ka_sa 2
#define bfd_mach_i960_kb_sb 3
#define bfd_mach_i960_mc 4
#define bfd_mach_i960_xa 5
#define bfd_mach_i960_ca 6
#define bfd_mach_i960_jx 7
#define bfd_mach_i960_hx 8
bfd_arch_a29k, /* AMD 29000 */
bfd_arch_sparc, /* SPARC */
#define bfd_mach_sparc 1
/* The difference between v8plus and v9 is that v9 is a true 64 bit env. */
#define bfd_mach_sparc_sparclet 2
#define bfd_mach_sparc_sparclite 3
#define bfd_mach_sparc_v8plus 4
#define bfd_mach_sparc_v8plusa 5 /* with ultrasparc add'ns. */
#define bfd_mach_sparc_sparclite_le 6
#define bfd_mach_sparc_v9 7
#define bfd_mach_sparc_v9a 8 /* with ultrasparc add'ns. */
#define bfd_mach_sparc_v8plusb 9 /* with cheetah add'ns. */
#define bfd_mach_sparc_v9b 10 /* with cheetah add'ns. */
/* Nonzero if MACH has the v9 instruction set. */
#define bfd_mach_sparc_v9_p(mach) \
((mach) >= bfd_mach_sparc_v8plus && (mach) <= bfd_mach_sparc_v9b \
&& (mach) != bfd_mach_sparc_sparclite_le)
bfd_arch_mips, /* MIPS Rxxxx */
#define bfd_mach_mips3000 3000
#define bfd_mach_mips3900 3900
#define bfd_mach_mips4000 4000
#define bfd_mach_mips4010 4010
#define bfd_mach_mips4100 4100
#define bfd_mach_mips4300 4300
#define bfd_mach_mips4400 4400
#define bfd_mach_mips4600 4600
#define bfd_mach_mips4650 4650
#define bfd_mach_mips5000 5000
#define bfd_mach_mips6000 6000
#define bfd_mach_mips8000 8000
#define bfd_mach_mips10000 10000
#define bfd_mach_mips16 16
bfd_arch_i386, /* Intel 386 */
#define bfd_mach_i386_i386 0
#define bfd_mach_i386_i8086 1
#define bfd_mach_i386_i386_intel_syntax 2
#define bfd_mach_x86_64 3
#define bfd_mach_x86_64_intel_syntax 4
bfd_arch_we32k, /* AT&T WE32xxx */
bfd_arch_tahoe, /* CCI/Harris Tahoe */
bfd_arch_i860, /* Intel 860 */
bfd_arch_romp, /* IBM ROMP PC/RT */
bfd_arch_alliant, /* Alliant */
bfd_arch_convex, /* Convex */
bfd_arch_m88k, /* Motorola 88xxx */
bfd_arch_pyramid, /* Pyramid Technology */
bfd_arch_h8300, /* Hitachi H8/300 */
#define bfd_mach_h8300 1
#define bfd_mach_h8300h 2
#define bfd_mach_h8300s 3
bfd_arch_powerpc, /* PowerPC */
bfd_arch_rs6000, /* IBM RS/6000 */
bfd_arch_hppa, /* HP PA RISC */
bfd_arch_d10v, /* Mitsubishi D10V */
bfd_arch_z8k, /* Zilog Z8000 */
#define bfd_mach_z8001 1
#define bfd_mach_z8002 2
bfd_arch_h8500, /* Hitachi H8/500 */
bfd_arch_sh, /* Hitachi SH */
#define bfd_mach_sh 0
#define bfd_mach_sh3 0x30
#define bfd_mach_sh3e 0x3e
#define bfd_mach_sh4 0x40
bfd_arch_alpha, /* Dec Alpha */
bfd_arch_arm, /* Advanced Risc Machines ARM */
#define bfd_mach_arm_2 1
#define bfd_mach_arm_2a 2
#define bfd_mach_arm_3 3
#define bfd_mach_arm_3M 4
#define bfd_mach_arm_4 5
#define bfd_mach_arm_4T 6
bfd_arch_ns32k, /* National Semiconductors ns32000 */
bfd_arch_w65, /* WDC 65816 */
bfd_arch_tic30, /* Texas Instruments TMS320C30 */
bfd_arch_v850, /* NEC V850 */
#define bfd_mach_v850 0
bfd_arch_arc, /* Argonaut RISC Core */
#define bfd_mach_arc_base 0
bfd_arch_m32r, /* Mitsubishi M32R/D */
#define bfd_mach_m32r 0 /* backwards compatibility */
bfd_arch_mn10200, /* Matsushita MN10200 */
bfd_arch_mn10300, /* Matsushita MN10300 */
bfd_arch_last
};
typedef struct symbol_cache_entry
{
const char *name;
union
{
PTR p;
bfd_vma i;
} udata;
} asymbol;
typedef int (*fprintf_ftype) PARAMS((FILE*, const char*, ...));
@@ -134,6 +288,9 @@ typedef struct disassemble_info {
zero if unknown. */
bfd_vma target2; /* Second target address for dref2 */
/* Command line options specific to the target disassembler. */
char * disassembler_options;
} disassemble_info;
@@ -154,8 +311,7 @@ extern int print_insn_h8300s PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_h8500 PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_alpha PARAMS ((bfd_vma, disassemble_info*));
extern disassembler_ftype arc_get_disassembler PARAMS ((int, int));
extern int print_insn_big_arm PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_little_arm PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_arm PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_sparc PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_big_a29k PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_little_a29k PARAMS ((bfd_vma, disassemble_info*));
@@ -175,9 +331,12 @@ extern int print_insn_w65 PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_d10v PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_v850 PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_tic30 PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_ppc PARAMS ((bfd_vma, disassemble_info*));
#if 0
/* Fetch the disassembler for a given BFD, if that support is available. */
extern disassembler_ftype disassembler PARAMS ((bfd *));
#endif
/* This block of definitions is for particular callers who read instructions
@@ -233,6 +392,15 @@ extern int generic_symbol_at_address
(INFO).bytes_per_line = 0, \
(INFO).bytes_per_chunk = 0, \
(INFO).display_endian = BFD_ENDIAN_UNKNOWN, \
(INFO).disassembler_options = NULL, \
(INFO).insn_info_valid = 0
#define _(x) x
/* from libbfd */
bfd_vma bfd_getl32 (const bfd_byte *addr);
bfd_vma bfd_getb32 (const bfd_byte *addr);
typedef enum bfd_boolean {false, true} boolean;
#endif /* ! defined (DIS_ASM_H) */

View File

@@ -1,79 +0,0 @@
/* Disassemble from a buffer, for GNU.
Copyright (C) 1993, 1994 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "dis-asm.h"
#include <errno.h>
/* Get LENGTH bytes from info's buffer, at target address memaddr.
Transfer them to myaddr. */
int
buffer_read_memory (memaddr, myaddr, length, info)
bfd_vma memaddr;
bfd_byte *myaddr;
int length;
struct disassemble_info *info;
{
if (memaddr < info->buffer_vma
|| memaddr + length > info->buffer_vma + info->buffer_length)
/* Out of bounds. Use EIO because GDB uses it. */
return EIO;
memcpy (myaddr, info->buffer + (memaddr - info->buffer_vma), length);
return 0;
}
/* Print an error message. We can assume that this is in response to
an error return from buffer_read_memory. */
void
perror_memory (status, memaddr, info)
int status;
bfd_vma memaddr;
struct disassemble_info *info;
{
if (status != EIO)
/* Can't happen. */
(*info->fprintf_func) (info->stream, "Unknown error %d\n", status);
else
/* Actually, address between memaddr and memaddr + len was
out of bounds. */
(*info->fprintf_func) (info->stream,
"Address 0x%x is out of bounds.\n", memaddr);
}
/* This could be in a separate file, to save miniscule amounts of space
in statically linked executables. */
/* Just print the address is hex. This is included for completeness even
though both GDB and objdump provide their own (to print symbolic
addresses). */
void
generic_print_address (addr, info)
bfd_vma addr;
struct disassemble_info *info;
{
(*info->fprintf_func) (info->stream, "0x%x", addr);
}
/* Just return the given address. */
int
generic_symbol_at_address (addr, info)
bfd_vma addr;
struct disassemble_info * info;
{
return 1;
}

298
disas.c Normal file
View File

@@ -0,0 +1,298 @@
/* General "disassemble this chunk" code. Used for debugging. */
#include "config.h"
#include "dis-asm.h"
#include "elf.h"
#include <errno.h>
#include "cpu.h"
#include "exec-all.h"
#include "disas.h"
/* Filled in by elfload.c. Simplistic, but will do for now. */
unsigned int disas_num_syms;
void *disas_symtab;
const char *disas_strtab;
/* Get LENGTH bytes from info's buffer, at target address memaddr.
Transfer them to myaddr. */
int
buffer_read_memory (memaddr, myaddr, length, info)
bfd_vma memaddr;
bfd_byte *myaddr;
int length;
struct disassemble_info *info;
{
if (memaddr < info->buffer_vma
|| memaddr + length > info->buffer_vma + info->buffer_length)
/* Out of bounds. Use EIO because GDB uses it. */
return EIO;
memcpy (myaddr, info->buffer + (memaddr - info->buffer_vma), length);
return 0;
}
#if !defined(CONFIG_USER_ONLY)
/* Get LENGTH bytes from info's buffer, at target address memaddr.
Transfer them to myaddr. */
static int
target_read_memory (memaddr, myaddr, length, info)
bfd_vma memaddr;
bfd_byte *myaddr;
int length;
struct disassemble_info *info;
{
int i;
for(i = 0; i < length; i++) {
myaddr[i] = ldub_code((void *)((long)memaddr + i));
}
return 0;
}
#endif
/* Print an error message. We can assume that this is in response to
an error return from buffer_read_memory. */
void
perror_memory (status, memaddr, info)
int status;
bfd_vma memaddr;
struct disassemble_info *info;
{
if (status != EIO)
/* Can't happen. */
(*info->fprintf_func) (info->stream, "Unknown error %d\n", status);
else
/* Actually, address between memaddr and memaddr + len was
out of bounds. */
(*info->fprintf_func) (info->stream,
"Address 0x%llx is out of bounds.\n", memaddr);
}
/* This could be in a separate file, to save miniscule amounts of space
in statically linked executables. */
/* Just print the address is hex. This is included for completeness even
though both GDB and objdump provide their own (to print symbolic
addresses). */
void
generic_print_address (addr, info)
bfd_vma addr;
struct disassemble_info *info;
{
(*info->fprintf_func) (info->stream, "0x%llx", addr);
}
/* Just return the given address. */
int
generic_symbol_at_address (addr, info)
bfd_vma addr;
struct disassemble_info * info;
{
return 1;
}
bfd_vma bfd_getl32 (const bfd_byte *addr)
{
unsigned long v;
v = (unsigned long) addr[0];
v |= (unsigned long) addr[1] << 8;
v |= (unsigned long) addr[2] << 16;
v |= (unsigned long) addr[3] << 24;
return (bfd_vma) v;
}
bfd_vma bfd_getb32 (const bfd_byte *addr)
{
unsigned long v;
v = (unsigned long) addr[0] << 24;
v |= (unsigned long) addr[1] << 16;
v |= (unsigned long) addr[2] << 8;
v |= (unsigned long) addr[3];
return (bfd_vma) v;
}
/* Disassemble this for me please... (debugging). 'flags' is only used
for i386: non zero means 16 bit code */
void disas(FILE *out, void *code, unsigned long size, int is_host, int flags)
{
uint8_t *pc;
int count;
struct disassemble_info disasm_info;
int (*print_insn)(bfd_vma pc, disassemble_info *info);
INIT_DISASSEMBLE_INFO(disasm_info, out, fprintf);
#if !defined(CONFIG_USER_ONLY)
if (!is_host) {
disasm_info.read_memory_func = target_read_memory;
}
#endif
disasm_info.buffer = code;
disasm_info.buffer_vma = (unsigned long)code;
disasm_info.buffer_length = size;
if (is_host) {
#ifdef WORDS_BIGENDIAN
disasm_info.endian = BFD_ENDIAN_BIG;
#else
disasm_info.endian = BFD_ENDIAN_LITTLE;
#endif
#if defined(__i386__)
disasm_info.mach = bfd_mach_i386_i386;
print_insn = print_insn_i386;
#elif defined(__x86_64__)
disasm_info.mach = bfd_mach_x86_64;
print_insn = print_insn_i386;
#elif defined(__powerpc__)
print_insn = print_insn_ppc;
#elif defined(__alpha__)
print_insn = print_insn_alpha;
#elif defined(__sparc__)
print_insn = print_insn_sparc;
#elif defined(__arm__)
print_insn = print_insn_arm;
#else
fprintf(out, "Asm output not supported on this arch\n");
return;
#endif
} else {
#ifdef TARGET_WORDS_BIGENDIAN
disasm_info.endian = BFD_ENDIAN_BIG;
#else
disasm_info.endian = BFD_ENDIAN_LITTLE;
#endif
#if defined(TARGET_I386)
if (!flags)
disasm_info.mach = bfd_mach_i386_i386;
else
disasm_info.mach = bfd_mach_i386_i8086;
print_insn = print_insn_i386;
#elif defined(TARGET_ARM)
print_insn = print_insn_arm;
#elif defined(TARGET_SPARC)
print_insn = print_insn_sparc;
#elif defined(TARGET_PPC)
print_insn = print_insn_ppc;
#else
fprintf(out, "Asm output not supported on this arch\n");
return;
#endif
}
for (pc = code; pc < (uint8_t *)code + size; pc += count) {
fprintf(out, "0x%08lx: ", (long)pc);
#ifdef __arm__
/* since data are included in the code, it is better to
display code data too */
if (is_host) {
fprintf(out, "%08x ", (int)bfd_getl32((const bfd_byte *)pc));
}
#endif
count = print_insn((unsigned long)pc, &disasm_info);
fprintf(out, "\n");
if (count < 0)
break;
}
}
/* Look up symbol for debugging purpose. Returns "" if unknown. */
const char *lookup_symbol(void *orig_addr)
{
unsigned int i;
/* Hack, because we know this is x86. */
Elf32_Sym *sym = disas_symtab;
for (i = 0; i < disas_num_syms; i++) {
if (sym[i].st_shndx == SHN_UNDEF
|| sym[i].st_shndx >= SHN_LORESERVE)
continue;
if (ELF_ST_TYPE(sym[i].st_info) != STT_FUNC)
continue;
if ((long)orig_addr >= sym[i].st_value
&& (long)orig_addr < sym[i].st_value + sym[i].st_size)
return disas_strtab + sym[i].st_name;
}
return "";
}
#if !defined(CONFIG_USER_ONLY)
void term_vprintf(const char *fmt, va_list ap);
void term_printf(const char *fmt, ...);
static int monitor_disas_is_physical;
static int
monitor_read_memory (memaddr, myaddr, length, info)
bfd_vma memaddr;
bfd_byte *myaddr;
int length;
struct disassemble_info *info;
{
if (monitor_disas_is_physical) {
cpu_physical_memory_rw(memaddr, myaddr, length, 0);
} else {
cpu_memory_rw_debug(cpu_single_env, memaddr,myaddr, length, 0);
}
return 0;
}
static int monitor_fprintf(FILE *stream, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
term_vprintf(fmt, ap);
va_end(ap);
return 0;
}
void monitor_disas(target_ulong pc, int nb_insn, int is_physical, int flags)
{
int count, i;
struct disassemble_info disasm_info;
int (*print_insn)(bfd_vma pc, disassemble_info *info);
INIT_DISASSEMBLE_INFO(disasm_info, NULL, monitor_fprintf);
monitor_disas_is_physical = is_physical;
disasm_info.read_memory_func = monitor_read_memory;
disasm_info.buffer_vma = pc;
#ifdef TARGET_WORDS_BIGENDIAN
disasm_info.endian = BFD_ENDIAN_BIG;
#else
disasm_info.endian = BFD_ENDIAN_LITTLE;
#endif
#if defined(TARGET_I386)
if (!flags)
disasm_info.mach = bfd_mach_i386_i386;
else
disasm_info.mach = bfd_mach_i386_i8086;
print_insn = print_insn_i386;
#elif defined(TARGET_ARM)
print_insn = print_insn_arm;
#elif defined(TARGET_SPARC)
print_insn = print_insn_sparc;
#elif defined(TARGET_PPC)
print_insn = print_insn_ppc;
#else
term_printf("Asm output not supported on this arch\n");
return;
#endif
for(i = 0; i < nb_insn; i++) {
term_printf("0x%08lx: ", (unsigned long)pc);
count = print_insn(pc, &disasm_info);
term_printf("\n");
if (count < 0)
break;
pc += count;
}
}
#endif

15
disas.h Normal file
View File

@@ -0,0 +1,15 @@
#ifndef _QEMU_DISAS_H
#define _QEMU_DISAS_H
/* Disassemble this for me please... (debugging). */
void disas(FILE *out, void *code, unsigned long size, int is_host, int flags);
void monitor_disas(target_ulong pc, int nb_insn, int is_physical, int flags);
/* Look up symbol for debugging purpose. Returns "" if unknown. */
const char *lookup_symbol(void *orig_addr);
/* Filled in by elfload.c. Simplistic, but will do for now. */
extern unsigned int disas_num_syms;
extern void *disas_symtab; /* FIXME: includes are a mess --RR */
extern const char *disas_strtab;
#endif /* _QEMU_DISAS_H */

241
dyngen-exec.h Normal file
View File

@@ -0,0 +1,241 @@
/*
* dyngen defines for micro operation code
*
* Copyright (c) 2003 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#if !defined(__DYNGEN_EXEC_H__)
#define __DYNGEN_EXEC_H__
/* NOTE: standard headers should be used with special care at this
point because host CPU registers are used as global variables. Some
host headers do not allow that. */
#include <stddef.h>
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
/* XXX may be done for all 64 bits targets ? */
#if defined (__x86_64__)
typedef unsigned long uint64_t;
#else
typedef unsigned long long uint64_t;
#endif
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
#if defined (__x86_64__)
typedef signed long int64_t;
#else
typedef signed long long int64_t;
#endif
#define INT8_MIN (-128)
#define INT16_MIN (-32767-1)
#define INT32_MIN (-2147483647-1)
#define INT64_MIN (-(int64_t)(9223372036854775807)-1)
#define INT8_MAX (127)
#define INT16_MAX (32767)
#define INT32_MAX (2147483647)
#define INT64_MAX ((int64_t)(9223372036854775807))
#define UINT8_MAX (255)
#define UINT16_MAX (65535)
#define UINT32_MAX (4294967295U)
#define UINT64_MAX ((uint64_t)(18446744073709551615))
typedef struct FILE FILE;
extern int fprintf(FILE *, const char *, ...);
extern int printf(const char *, ...);
#undef NULL
#define NULL 0
#if defined(_BSD) && !defined(__APPLE__)
#include <ieeefp.h>
#define FE_TONEAREST FP_RN
#define FE_DOWNWARD FP_RM
#define FE_UPWARD FP_RP
#define FE_TOWARDZERO FP_RZ
#define fesetround(x) fpsetround(x)
#else
#include <fenv.h>
#endif
#ifdef __i386__
#define AREG0 "ebp"
#define AREG1 "ebx"
#define AREG2 "esi"
#define AREG3 "edi"
#endif
#ifdef __x86_64__
#define AREG0 "rbp"
#define AREG1 "rbx"
#define AREG2 "r12"
#define AREG3 "r13"
#define AREG4 "r14"
#define AREG5 "r15"
#endif
#ifdef __powerpc__
#define AREG0 "r27"
#define AREG1 "r24"
#define AREG2 "r25"
#define AREG3 "r26"
/* XXX: suppress this hack */
#if defined(CONFIG_USER_ONLY)
#define AREG4 "r16"
#define AREG5 "r17"
#define AREG6 "r18"
#define AREG7 "r19"
#define AREG8 "r20"
#define AREG9 "r21"
#define AREG10 "r22"
#define AREG11 "r23"
#endif
#define USE_INT_TO_FLOAT_HELPERS
#define BUGGY_GCC_DIV64
#endif
#ifdef __arm__
#define AREG0 "r7"
#define AREG1 "r4"
#define AREG2 "r5"
#define AREG3 "r6"
#endif
#ifdef __mips__
#define AREG0 "s3"
#define AREG1 "s0"
#define AREG2 "s1"
#define AREG3 "s2"
#endif
#ifdef __sparc__
#define AREG0 "g6"
#define AREG1 "g1"
#define AREG2 "g2"
#define AREG3 "g3"
#define AREG4 "l0"
#define AREG5 "l1"
#define AREG6 "l2"
#define AREG7 "l3"
#define AREG8 "l4"
#define AREG9 "l5"
#define AREG10 "l6"
#define AREG11 "l7"
#define USE_FP_CONVERT
#endif
#ifdef __s390__
#define AREG0 "r10"
#define AREG1 "r7"
#define AREG2 "r8"
#define AREG3 "r9"
#endif
#ifdef __alpha__
/* Note $15 is the frame pointer, so anything in op-i386.c that would
require a frame pointer, like alloca, would probably loose. */
#define AREG0 "$15"
#define AREG1 "$9"
#define AREG2 "$10"
#define AREG3 "$11"
#define AREG4 "$12"
#define AREG5 "$13"
#define AREG6 "$14"
#endif
#ifdef __mc68000
#define AREG0 "%a5"
#define AREG1 "%a4"
#define AREG2 "%d7"
#define AREG3 "%d6"
#define AREG4 "%d5"
#endif
#ifdef __ia64__
#define AREG0 "r27"
#define AREG1 "r24"
#define AREG2 "r25"
#define AREG3 "r26"
#endif
/* force GCC to generate only one epilog at the end of the function */
#define FORCE_RET() asm volatile ("");
#ifndef OPPROTO
#define OPPROTO
#endif
#define xglue(x, y) x ## y
#define glue(x, y) xglue(x, y)
#define stringify(s) tostring(s)
#define tostring(s) #s
#ifdef __alpha__
/* the symbols are considered non exported so a br immediate is generated */
#define __hidden __attribute__((visibility("hidden")))
#else
#define __hidden
#endif
#if defined(__alpha__)
/* Suggested by Richard Henderson. This will result in code like
ldah $0,__op_param1($29) !gprelhigh
lda $0,__op_param1($0) !gprellow
We can then conveniently change $29 to $31 and adapt the offsets to
emit the appropriate constant. */
extern int __op_param1 __hidden;
extern int __op_param2 __hidden;
extern int __op_param3 __hidden;
#define PARAM1 ({ int _r; asm("" : "=r"(_r) : "0" (&__op_param1)); _r; })
#define PARAM2 ({ int _r; asm("" : "=r"(_r) : "0" (&__op_param2)); _r; })
#define PARAM3 ({ int _r; asm("" : "=r"(_r) : "0" (&__op_param3)); _r; })
#else
#if defined(__APPLE__)
static int __op_param1, __op_param2, __op_param3;
#else
extern int __op_param1, __op_param2, __op_param3;
#endif
#define PARAM1 ((long)(&__op_param1))
#define PARAM2 ((long)(&__op_param2))
#define PARAM3 ((long)(&__op_param3))
#endif /* !defined(__alpha__) */
extern int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3;
#ifdef __i386__
#define EXIT_TB() asm volatile ("ret")
#endif
#ifdef __x86_64__
#define EXIT_TB() asm volatile ("ret")
#endif
#ifdef __powerpc__
#define EXIT_TB() asm volatile ("blr")
#endif
#ifdef __s390__
#define EXIT_TB() asm volatile ("br %r14")
#endif
#ifdef __alpha__
#define EXIT_TB() asm volatile ("ret")
#endif
#ifdef __ia64__
#define EXIT_TB() asm volatile ("br.ret.sptk.many b0;;")
#endif
#ifdef __sparc__
#define EXIT_TB() asm volatile ("jmpl %i0 + 8, %g0\n" \
"nop")
#endif
#ifdef __arm__
#define EXIT_TB() asm volatile ("b exec_loop")
#endif
#ifdef __mc68000
#define EXIT_TB() asm volatile ("rts")
#endif
#endif /* !defined(__DYNGEN_EXEC_H__) */

2507
dyngen.c

File diff suppressed because it is too large Load Diff

208
dyngen.h Normal file
View File

@@ -0,0 +1,208 @@
/*
* dyngen helpers
*
* Copyright (c) 2003 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
int __op_param1, __op_param2, __op_param3;
int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3;
#ifdef __i386__
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
}
#endif
#ifdef __x86_64__
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
}
#endif
#ifdef __s390__
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
}
#endif
#ifdef __ia64__
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
}
#endif
#ifdef __powerpc__
#define MIN_CACHE_LINE_SIZE 8 /* conservative value */
static void inline flush_icache_range(unsigned long start, unsigned long stop)
{
unsigned long p;
p = start & ~(MIN_CACHE_LINE_SIZE - 1);
stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1);
for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
asm volatile ("dcbst 0,%0" : : "r"(p) : "memory");
}
asm volatile ("sync" : : : "memory");
for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
asm volatile ("icbi 0,%0" : : "r"(p) : "memory");
}
asm volatile ("sync" : : : "memory");
asm volatile ("isync" : : : "memory");
}
#endif
#ifdef __alpha__
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
asm ("imb");
}
#endif
#ifdef __sparc__
static void inline flush_icache_range(unsigned long start, unsigned long stop)
{
unsigned long p;
p = start & ~(8UL - 1UL);
stop = (stop + (8UL - 1UL)) & ~(8UL - 1UL);
for (; p < stop; p += 8)
__asm__ __volatile__("flush\t%0" : : "r" (p));
}
#endif
#ifdef __arm__
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
register unsigned long _beg __asm ("a1") = start;
register unsigned long _end __asm ("a2") = stop;
register unsigned long _flg __asm ("a3") = 0;
__asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg));
}
#endif
#ifdef __mc68000
#include <asm/cachectl.h>
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
cacheflush(start,FLUSH_SCOPE_LINE,FLUSH_CACHE_BOTH,stop-start+16);
}
#endif
#ifdef __alpha__
register int gp asm("$29");
static inline void immediate_ldah(void *p, int val) {
uint32_t *dest = p;
long high = ((val >> 16) + ((val >> 15) & 1)) & 0xffff;
*dest &= ~0xffff;
*dest |= high;
*dest |= 31 << 16;
}
static inline void immediate_lda(void *dest, int val) {
*(uint16_t *) dest = val;
}
void fix_bsr(void *p, int offset) {
uint32_t *dest = p;
*dest &= ~((1 << 21) - 1);
*dest |= (offset >> 2) & ((1 << 21) - 1);
}
#endif /* __alpha__ */
#ifdef __arm__
#define MAX_OP_SIZE (128 * 4) /* in bytes */
/* max size of the code that can be generated without calling arm_flush_ldr */
#define MAX_FRAG_SIZE (1024 * 4)
//#define MAX_FRAG_SIZE (135 * 4) /* for testing */
typedef struct LDREntry {
uint8_t *ptr;
uint32_t *data_ptr;
} LDREntry;
static LDREntry arm_ldr_table[1024];
static uint32_t arm_data_table[1024];
extern char exec_loop;
static inline void arm_reloc_pc24(uint32_t *ptr, uint32_t insn, int val)
{
*ptr = (insn & ~0xffffff) | ((insn + ((val - (int)ptr) >> 2)) & 0xffffff);
}
static uint8_t *arm_flush_ldr(uint8_t *gen_code_ptr,
LDREntry *ldr_start, LDREntry *ldr_end,
uint32_t *data_start, uint32_t *data_end,
int gen_jmp)
{
LDREntry *le;
uint32_t *ptr;
int offset, data_size, target;
uint8_t *data_ptr;
uint32_t insn;
data_size = (uint8_t *)data_end - (uint8_t *)data_start;
if (gen_jmp) {
/* generate branch to skip the data */
if (data_size == 0)
return gen_code_ptr;
target = (long)gen_code_ptr + data_size + 4;
arm_reloc_pc24((uint32_t *)gen_code_ptr, 0xeafffffe, target);
gen_code_ptr += 4;
}
/* copy the data */
data_ptr = gen_code_ptr;
memcpy(gen_code_ptr, data_start, data_size);
gen_code_ptr += data_size;
/* patch the ldr to point to the data */
for(le = ldr_start; le < ldr_end; le++) {
ptr = (uint32_t *)le->ptr;
offset = ((unsigned long)(le->data_ptr) - (unsigned long)data_start) +
(unsigned long)data_ptr -
(unsigned long)ptr - 8;
insn = *ptr & ~(0xfff | 0x00800000);
if (offset < 0) {
offset = - offset;
} else {
insn |= 0x00800000;
}
if (offset > 0xfff) {
fprintf(stderr, "Error ldr offset\n");
abort();
}
insn |= offset;
*ptr = insn;
}
return gen_code_ptr;
}
#endif /* __arm__ */

919
elf.h

File diff suppressed because it is too large Load Diff

599
exec-all.h Normal file
View File

@@ -0,0 +1,599 @@
/*
* internal execution defines for qemu
*
* Copyright (c) 2003 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* allow to see translation results - the slowdown should be negligible, so we leave it */
#define DEBUG_DISAS
#ifndef glue
#define xglue(x, y) x ## y
#define glue(x, y) xglue(x, y)
#define stringify(s) tostring(s)
#define tostring(s) #s
#endif
#if GCC_MAJOR < 3
#define __builtin_expect(x, n) (x)
#endif
#ifdef __i386__
#define REGPARM(n) __attribute((regparm(n)))
#else
#define REGPARM(n)
#endif
/* is_jmp field values */
#define DISAS_NEXT 0 /* next instruction can be analyzed */
#define DISAS_JUMP 1 /* only pc was modified dynamically */
#define DISAS_UPDATE 2 /* cpu state was modified dynamically */
#define DISAS_TB_JUMP 3 /* only pc was modified statically */
struct TranslationBlock;
/* XXX: make safe guess about sizes */
#define MAX_OP_PER_INSTR 32
#define OPC_BUF_SIZE 512
#define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
extern uint16_t gen_opc_buf[OPC_BUF_SIZE];
extern uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
extern uint32_t gen_opc_pc[OPC_BUF_SIZE];
extern uint32_t gen_opc_npc[OPC_BUF_SIZE];
extern uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
typedef void (GenOpFunc)(void);
typedef void (GenOpFunc1)(long);
typedef void (GenOpFunc2)(long, long);
typedef void (GenOpFunc3)(long, long, long);
#if defined(TARGET_I386)
void optimize_flags_init(void);
#endif
extern FILE *logfile;
extern int loglevel;
int gen_intermediate_code(CPUState *env, struct TranslationBlock *tb);
int gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb);
void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf);
int cpu_gen_code(CPUState *env, struct TranslationBlock *tb,
int max_code_size, int *gen_code_size_ptr);
int cpu_restore_state(struct TranslationBlock *tb,
CPUState *env, unsigned long searched_pc,
void *puc);
int cpu_gen_code_copy(CPUState *env, struct TranslationBlock *tb,
int max_code_size, int *gen_code_size_ptr);
int cpu_restore_state_copy(struct TranslationBlock *tb,
CPUState *env, unsigned long searched_pc,
void *puc);
void cpu_resume_from_signal(CPUState *env1, void *puc);
void cpu_exec_init(void);
int page_unprotect(unsigned long address, unsigned long pc, void *puc);
void tb_invalidate_phys_page_range(target_ulong start, target_ulong end,
int is_cpu_write_access);
void tb_invalidate_page_range(target_ulong start, target_ulong end);
void tlb_flush_page(CPUState *env, target_ulong addr);
void tlb_flush(CPUState *env, int flush_global);
int tlb_set_page(CPUState *env, target_ulong vaddr,
target_phys_addr_t paddr, int prot,
int is_user, int is_softmmu);
#define CODE_GEN_MAX_SIZE 65536
#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
#define CODE_GEN_HASH_BITS 15
#define CODE_GEN_HASH_SIZE (1 << CODE_GEN_HASH_BITS)
#define CODE_GEN_PHYS_HASH_BITS 15
#define CODE_GEN_PHYS_HASH_SIZE (1 << CODE_GEN_PHYS_HASH_BITS)
/* maximum total translate dcode allocated */
/* NOTE: the translated code area cannot be too big because on some
archs the range of "fast" function calls is limited. Here is a
summary of the ranges:
i386 : signed 32 bits
arm : signed 26 bits
ppc : signed 24 bits
sparc : signed 32 bits
alpha : signed 23 bits
*/
#if defined(__alpha__)
#define CODE_GEN_BUFFER_SIZE (2 * 1024 * 1024)
#elif defined(__powerpc__)
#define CODE_GEN_BUFFER_SIZE (6 * 1024 * 1024)
#else
#define CODE_GEN_BUFFER_SIZE (8 * 1024 * 1024)
#endif
//#define CODE_GEN_BUFFER_SIZE (128 * 1024)
/* estimated block size for TB allocation */
/* XXX: use a per code average code fragment size and modulate it
according to the host CPU */
#if defined(CONFIG_SOFTMMU)
#define CODE_GEN_AVG_BLOCK_SIZE 128
#else
#define CODE_GEN_AVG_BLOCK_SIZE 64
#endif
#define CODE_GEN_MAX_BLOCKS (CODE_GEN_BUFFER_SIZE / CODE_GEN_AVG_BLOCK_SIZE)
#if defined(__powerpc__)
#define USE_DIRECT_JUMP
#endif
#if defined(__i386__) && !defined(_WIN32)
#define USE_DIRECT_JUMP
#endif
typedef struct TranslationBlock {
target_ulong pc; /* simulated PC corresponding to this block (EIP + CS base) */
target_ulong cs_base; /* CS base for this block */
unsigned int flags; /* flags defining in which context the code was generated */
uint16_t size; /* size of target code for this block (1 <=
size <= TARGET_PAGE_SIZE) */
uint16_t cflags; /* compile flags */
#define CF_CODE_COPY 0x0001 /* block was generated in code copy mode */
#define CF_TB_FP_USED 0x0002 /* fp ops are used in the TB */
#define CF_FP_USED 0x0004 /* fp ops are used in the TB or in a chained TB */
#define CF_SINGLE_INSN 0x0008 /* compile only a single instruction */
uint8_t *tc_ptr; /* pointer to the translated code */
struct TranslationBlock *hash_next; /* next matching tb for virtual address */
/* next matching tb for physical address. */
struct TranslationBlock *phys_hash_next;
/* first and second physical page containing code. The lower bit
of the pointer tells the index in page_next[] */
struct TranslationBlock *page_next[2];
target_ulong page_addr[2];
/* the following data are used to directly call another TB from
the code of this one. */
uint16_t tb_next_offset[2]; /* offset of original jump target */
#ifdef USE_DIRECT_JUMP
uint16_t tb_jmp_offset[4]; /* offset of jump instruction */
#else
uint32_t tb_next[2]; /* address of jump generated code */
#endif
/* list of TBs jumping to this one. This is a circular list using
the two least significant bits of the pointers to tell what is
the next pointer: 0 = jmp_next[0], 1 = jmp_next[1], 2 =
jmp_first */
struct TranslationBlock *jmp_next[2];
struct TranslationBlock *jmp_first;
} TranslationBlock;
static inline unsigned int tb_hash_func(unsigned long pc)
{
return pc & (CODE_GEN_HASH_SIZE - 1);
}
static inline unsigned int tb_phys_hash_func(unsigned long pc)
{
return pc & (CODE_GEN_PHYS_HASH_SIZE - 1);
}
TranslationBlock *tb_alloc(unsigned long pc);
void tb_flush(CPUState *env);
void tb_link(TranslationBlock *tb);
void tb_link_phys(TranslationBlock *tb,
target_ulong phys_pc, target_ulong phys_page2);
extern TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE];
extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
extern uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];
extern uint8_t *code_gen_ptr;
/* find a translation block in the translation cache. If not found,
return NULL and the pointer to the last element of the list in pptb */
static inline TranslationBlock *tb_find(TranslationBlock ***pptb,
target_ulong pc,
target_ulong cs_base,
unsigned int flags)
{
TranslationBlock **ptb, *tb;
unsigned int h;
h = tb_hash_func(pc);
ptb = &tb_hash[h];
for(;;) {
tb = *ptb;
if (!tb)
break;
if (tb->pc == pc && tb->cs_base == cs_base && tb->flags == flags)
return tb;
ptb = &tb->hash_next;
}
*pptb = ptb;
return NULL;
}
#if defined(USE_DIRECT_JUMP)
#if defined(__powerpc__)
static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
{
uint32_t val, *ptr;
/* patch the branch destination */
ptr = (uint32_t *)jmp_addr;
val = *ptr;
val = (val & ~0x03fffffc) | ((addr - jmp_addr) & 0x03fffffc);
*ptr = val;
/* flush icache */
asm volatile ("dcbst 0,%0" : : "r"(ptr) : "memory");
asm volatile ("sync" : : : "memory");
asm volatile ("icbi 0,%0" : : "r"(ptr) : "memory");
asm volatile ("sync" : : : "memory");
asm volatile ("isync" : : : "memory");
}
#elif defined(__i386__)
static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
{
/* patch the branch destination */
*(uint32_t *)jmp_addr = addr - (jmp_addr + 4);
/* no need to flush icache explicitely */
}
#endif
static inline void tb_set_jmp_target(TranslationBlock *tb,
int n, unsigned long addr)
{
unsigned long offset;
offset = tb->tb_jmp_offset[n];
tb_set_jmp_target1((unsigned long)(tb->tc_ptr + offset), addr);
offset = tb->tb_jmp_offset[n + 2];
if (offset != 0xffff)
tb_set_jmp_target1((unsigned long)(tb->tc_ptr + offset), addr);
}
#else
/* set the jump target */
static inline void tb_set_jmp_target(TranslationBlock *tb,
int n, unsigned long addr)
{
tb->tb_next[n] = addr;
}
#endif
static inline void tb_add_jump(TranslationBlock *tb, int n,
TranslationBlock *tb_next)
{
/* NOTE: this test is only needed for thread safety */
if (!tb->jmp_next[n]) {
/* patch the native jump address */
tb_set_jmp_target(tb, n, (unsigned long)tb_next->tc_ptr);
/* add in TB jmp circular list */
tb->jmp_next[n] = tb_next->jmp_first;
tb_next->jmp_first = (TranslationBlock *)((long)(tb) | (n));
}
}
TranslationBlock *tb_find_pc(unsigned long pc_ptr);
#ifndef offsetof
#define offsetof(type, field) ((size_t) &((type *)0)->field)
#endif
#if defined(_WIN32)
#define ASM_DATA_SECTION ".section \".data\"\n"
#define ASM_PREVIOUS_SECTION ".section .text\n"
#elif defined(__APPLE__)
#define ASM_DATA_SECTION ".data\n"
#define ASM_PREVIOUS_SECTION ".text\n"
#define ASM_NAME(x) "_" #x
#else
#define ASM_DATA_SECTION ".section \".data\"\n"
#define ASM_PREVIOUS_SECTION ".previous\n"
#define ASM_NAME(x) stringify(x)
#endif
#if defined(__powerpc__)
/* we patch the jump instruction directly */
#define JUMP_TB(opname, tbparam, n, eip)\
do {\
asm volatile (ASM_DATA_SECTION\
ASM_NAME(__op_label) #n "." ASM_NAME(opname) ":\n"\
".long 1f\n"\
ASM_PREVIOUS_SECTION \
"b " ASM_NAME(__op_jmp) #n "\n"\
"1:\n");\
T0 = (long)(tbparam) + (n);\
EIP = eip;\
EXIT_TB();\
} while (0)
#define JUMP_TB2(opname, tbparam, n)\
do {\
asm volatile ("b " ASM_NAME(__op_jmp) #n "\n");\
} while (0)
#elif defined(__i386__) && defined(USE_DIRECT_JUMP)
/* we patch the jump instruction directly */
#define JUMP_TB(opname, tbparam, n, eip)\
do {\
asm volatile (".section .data\n"\
ASM_NAME(__op_label) #n "." ASM_NAME(opname) ":\n"\
".long 1f\n"\
ASM_PREVIOUS_SECTION \
"jmp " ASM_NAME(__op_jmp) #n "\n"\
"1:\n");\
T0 = (long)(tbparam) + (n);\
EIP = eip;\
EXIT_TB();\
} while (0)
#define JUMP_TB2(opname, tbparam, n)\
do {\
asm volatile ("jmp " ASM_NAME(__op_jmp) #n "\n");\
} while (0)
#else
/* jump to next block operations (more portable code, does not need
cache flushing, but slower because of indirect jump) */
#define JUMP_TB(opname, tbparam, n, eip)\
do {\
static void __attribute__((unused)) *__op_label ## n = &&label ## n;\
static void __attribute__((unused)) *dummy ## n = &&dummy_label ## n;\
goto *(void *)(((TranslationBlock *)tbparam)->tb_next[n]);\
label ## n:\
T0 = (long)(tbparam) + (n);\
EIP = eip;\
dummy_label ## n:\
EXIT_TB();\
} while (0)
/* second jump to same destination 'n' */
#define JUMP_TB2(opname, tbparam, n)\
do {\
goto *(void *)(((TranslationBlock *)tbparam)->tb_next[n - 2]);\
} while (0)
#endif
extern CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
extern void *io_mem_opaque[IO_MEM_NB_ENTRIES];
#ifdef __powerpc__
static inline int testandset (int *p)
{
int ret;
__asm__ __volatile__ (
"0: lwarx %0,0,%1\n"
" xor. %0,%3,%0\n"
" bne 1f\n"
" stwcx. %2,0,%1\n"
" bne- 0b\n"
"1: "
: "=&r" (ret)
: "r" (p), "r" (1), "r" (0)
: "cr0", "memory");
return ret;
}
#endif
#ifdef __i386__
static inline int testandset (int *p)
{
char ret;
long int readval;
__asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
: "=q" (ret), "=m" (*p), "=a" (readval)
: "r" (1), "m" (*p), "a" (0)
: "memory");
return ret;
}
#endif
#ifdef __x86_64__
static inline int testandset (int *p)
{
char ret;
int readval;
__asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
: "=q" (ret), "=m" (*p), "=a" (readval)
: "r" (1), "m" (*p), "a" (0)
: "memory");
return ret;
}
#endif
#ifdef __s390__
static inline int testandset (int *p)
{
int ret;
__asm__ __volatile__ ("0: cs %0,%1,0(%2)\n"
" jl 0b"
: "=&d" (ret)
: "r" (1), "a" (p), "0" (*p)
: "cc", "memory" );
return ret;
}
#endif
#ifdef __alpha__
static inline int testandset (int *p)
{
int ret;
unsigned long one;
__asm__ __volatile__ ("0: mov 1,%2\n"
" ldl_l %0,%1\n"
" stl_c %2,%1\n"
" beq %2,1f\n"
".subsection 2\n"
"1: br 0b\n"
".previous"
: "=r" (ret), "=m" (*p), "=r" (one)
: "m" (*p));
return ret;
}
#endif
#ifdef __sparc__
static inline int testandset (int *p)
{
int ret;
__asm__ __volatile__("ldstub [%1], %0"
: "=r" (ret)
: "r" (p)
: "memory");
return (ret ? 1 : 0);
}
#endif
#ifdef __arm__
static inline int testandset (int *spinlock)
{
register unsigned int ret;
__asm__ __volatile__("swp %0, %1, [%2]"
: "=r"(ret)
: "0"(1), "r"(spinlock));
return ret;
}
#endif
#ifdef __mc68000
static inline int testandset (int *p)
{
char ret;
__asm__ __volatile__("tas %1; sne %0"
: "=r" (ret)
: "m" (p)
: "cc","memory");
return ret == 0;
}
#endif
typedef int spinlock_t;
#define SPIN_LOCK_UNLOCKED 0
#if defined(CONFIG_USER_ONLY)
static inline void spin_lock(spinlock_t *lock)
{
while (testandset(lock));
}
static inline void spin_unlock(spinlock_t *lock)
{
*lock = 0;
}
static inline int spin_trylock(spinlock_t *lock)
{
return !testandset(lock);
}
#else
static inline void spin_lock(spinlock_t *lock)
{
}
static inline void spin_unlock(spinlock_t *lock)
{
}
static inline int spin_trylock(spinlock_t *lock)
{
return 1;
}
#endif
extern spinlock_t tb_lock;
extern int tb_invalidated_flag;
#if !defined(CONFIG_USER_ONLY)
void tlb_fill(unsigned long addr, int is_write, int is_user,
void *retaddr);
#define ACCESS_TYPE 3
#define MEMSUFFIX _code
#define env cpu_single_env
#define DATA_SIZE 1
#include "softmmu_header.h"
#define DATA_SIZE 2
#include "softmmu_header.h"
#define DATA_SIZE 4
#include "softmmu_header.h"
#undef ACCESS_TYPE
#undef MEMSUFFIX
#undef env
#endif
#if defined(CONFIG_USER_ONLY)
static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
{
return addr;
}
#else
/* NOTE: this function can trigger an exception */
/* NOTE2: the returned address is not exactly the physical address: it
is the offset relative to phys_ram_base */
/* XXX: i386 target specific */
static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
{
int is_user, index;
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
#if defined(TARGET_I386)
is_user = ((env->hflags & HF_CPL_MASK) == 3);
#elif defined (TARGET_PPC)
is_user = msr_pr;
#elif defined (TARGET_SPARC)
is_user = (env->psrs == 0);
#else
#error "Unimplemented !"
#endif
if (__builtin_expect(env->tlb_read[is_user][index].address !=
(addr & TARGET_PAGE_MASK), 0)) {
ldub_code((void *)addr);
}
return addr + env->tlb_read[is_user][index].addend - (unsigned long)phys_ram_base;
}
#endif

View File

@@ -1,499 +0,0 @@
/*
* i386 emulator main execution loop
*
* Copyright (c) 2003 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "exec-i386.h"
//#define DEBUG_EXEC
#define DEBUG_FLUSH
//#define DEBUG_SIGNAL
/* main execution loop */
/* maximum total translate dcode allocated */
#define CODE_GEN_BUFFER_SIZE (2048 * 1024)
//#define CODE_GEN_BUFFER_SIZE (128 * 1024)
#define CODE_GEN_MAX_SIZE 65536
#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
/* threshold to flush the translated code buffer */
#define CODE_GEN_BUFFER_MAX_SIZE (CODE_GEN_BUFFER_SIZE - CODE_GEN_MAX_SIZE)
#define CODE_GEN_MAX_BLOCKS (CODE_GEN_BUFFER_SIZE / 64)
#define CODE_GEN_HASH_BITS 15
#define CODE_GEN_HASH_SIZE (1 << CODE_GEN_HASH_BITS)
typedef struct TranslationBlock {
unsigned long pc; /* simulated PC corresponding to this block (EIP + CS base) */
unsigned long cs_base; /* CS base for this block */
unsigned int flags; /* flags defining in which context the code was generated */
uint8_t *tc_ptr; /* pointer to the translated code */
struct TranslationBlock *hash_next; /* next matching block */
} TranslationBlock;
TranslationBlock tbs[CODE_GEN_MAX_BLOCKS];
TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE];
int nb_tbs;
uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];
uint8_t *code_gen_ptr;
/* thread support */
#ifdef __powerpc__
static inline int testandset (int *p)
{
int ret;
__asm__ __volatile__ (
"0: lwarx %0,0,%1 ;"
" xor. %0,%3,%0;"
" bne 1f;"
" stwcx. %2,0,%1;"
" bne- 0b;"
"1: "
: "=&r" (ret)
: "r" (p), "r" (1), "r" (0)
: "cr0", "memory");
return ret;
}
#endif
#ifdef __i386__
static inline int testandset (int *p)
{
char ret;
long int readval;
__asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
: "=q" (ret), "=m" (*p), "=a" (readval)
: "r" (1), "m" (*p), "a" (0)
: "memory");
return ret;
}
#endif
int global_cpu_lock = 0;
void cpu_lock(void)
{
while (testandset(&global_cpu_lock));
}
void cpu_unlock(void)
{
global_cpu_lock = 0;
}
/* exception support */
/* NOTE: not static to force relocation generation by GCC */
void raise_exception(int exception_index)
{
/* NOTE: the register at this point must be saved by hand because
longjmp restore them */
#ifdef reg_EAX
env->regs[R_EAX] = EAX;
#endif
#ifdef reg_ECX
env->regs[R_ECX] = ECX;
#endif
#ifdef reg_EDX
env->regs[R_EDX] = EDX;
#endif
#ifdef reg_EBX
env->regs[R_EBX] = EBX;
#endif
#ifdef reg_ESP
env->regs[R_ESP] = ESP;
#endif
#ifdef reg_EBP
env->regs[R_EBP] = EBP;
#endif
#ifdef reg_ESI
env->regs[R_ESI] = ESI;
#endif
#ifdef reg_EDI
env->regs[R_EDI] = EDI;
#endif
env->exception_index = exception_index;
longjmp(env->jmp_env, 1);
}
#if defined(DEBUG_EXEC)
static const char *cc_op_str[] = {
"DYNAMIC",
"EFLAGS",
"MUL",
"ADDB",
"ADDW",
"ADDL",
"ADCB",
"ADCW",
"ADCL",
"SUBB",
"SUBW",
"SUBL",
"SBBB",
"SBBW",
"SBBL",
"LOGICB",
"LOGICW",
"LOGICL",
"INCB",
"INCW",
"INCL",
"DECB",
"DECW",
"DECL",
"SHLB",
"SHLW",
"SHLL",
"SARB",
"SARW",
"SARL",
};
static void cpu_x86_dump_state(FILE *f)
{
int eflags;
eflags = cc_table[CC_OP].compute_all();
eflags |= (DF & DIRECTION_FLAG);
fprintf(f,
"EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n"
"ESI=%08x EDI=%08X EBP=%08x ESP=%08x\n"
"CCS=%08x CCD=%08x CCO=%-8s EFL=%c%c%c%c%c%c%c\n"
"EIP=%08x\n",
env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX],
env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP],
env->cc_src, env->cc_dst, cc_op_str[env->cc_op],
eflags & DIRECTION_FLAG ? 'D' : '-',
eflags & CC_O ? 'O' : '-',
eflags & CC_S ? 'S' : '-',
eflags & CC_Z ? 'Z' : '-',
eflags & CC_A ? 'A' : '-',
eflags & CC_P ? 'P' : '-',
eflags & CC_C ? 'C' : '-',
env->eip);
#if 1
fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n",
(double)ST0, (double)ST1, (double)ST(2), (double)ST(3));
#endif
}
#endif
void cpu_x86_tblocks_init(void)
{
if (!code_gen_ptr) {
code_gen_ptr = code_gen_buffer;
}
}
/* flush all the translation blocks */
static void tb_flush(void)
{
int i;
#ifdef DEBUG_FLUSH
printf("gemu: flush code_size=%d nb_tbs=%d avg_tb_size=%d\n",
code_gen_ptr - code_gen_buffer,
nb_tbs,
(code_gen_ptr - code_gen_buffer) / nb_tbs);
#endif
nb_tbs = 0;
for(i = 0;i < CODE_GEN_HASH_SIZE; i++)
tb_hash[i] = NULL;
code_gen_ptr = code_gen_buffer;
/* XXX: flush processor icache at this point */
}
/* find a translation block in the translation cache. If not found,
return NULL and the pointer to the last element of the list in pptb */
static inline TranslationBlock *tb_find(TranslationBlock ***pptb,
unsigned long pc,
unsigned long cs_base,
unsigned int flags)
{
TranslationBlock **ptb, *tb;
unsigned int h;
h = pc & (CODE_GEN_HASH_SIZE - 1);
ptb = &tb_hash[h];
for(;;) {
tb = *ptb;
if (!tb)
break;
if (tb->pc == pc && tb->cs_base == cs_base && tb->flags == flags)
return tb;
ptb = &tb->hash_next;
}
*pptb = ptb;
return NULL;
}
/* allocate a new translation block. flush the translation buffer if
too many translation blocks or too much generated code */
static inline TranslationBlock *tb_alloc(void)
{
TranslationBlock *tb;
if (nb_tbs >= CODE_GEN_MAX_BLOCKS ||
(code_gen_ptr - code_gen_buffer) >= CODE_GEN_BUFFER_MAX_SIZE)
tb_flush();
tb = &tbs[nb_tbs++];
return tb;
}
int cpu_x86_exec(CPUX86State *env1)
{
int saved_T0, saved_T1, saved_A0;
CPUX86State *saved_env;
#ifdef reg_EAX
int saved_EAX;
#endif
#ifdef reg_ECX
int saved_ECX;
#endif
#ifdef reg_EDX
int saved_EDX;
#endif
#ifdef reg_EBX
int saved_EBX;
#endif
#ifdef reg_ESP
int saved_ESP;
#endif
#ifdef reg_EBP
int saved_EBP;
#endif
#ifdef reg_ESI
int saved_ESI;
#endif
#ifdef reg_EDI
int saved_EDI;
#endif
int code_gen_size, ret;
void (*gen_func)(void);
TranslationBlock *tb, **ptb;
uint8_t *tc_ptr, *cs_base, *pc;
unsigned int flags;
/* first we save global registers */
saved_T0 = T0;
saved_T1 = T1;
saved_A0 = A0;
saved_env = env;
env = env1;
#ifdef reg_EAX
saved_EAX = EAX;
EAX = env->regs[R_EAX];
#endif
#ifdef reg_ECX
saved_ECX = ECX;
ECX = env->regs[R_ECX];
#endif
#ifdef reg_EDX
saved_EDX = EDX;
EDX = env->regs[R_EDX];
#endif
#ifdef reg_EBX
saved_EBX = EBX;
EBX = env->regs[R_EBX];
#endif
#ifdef reg_ESP
saved_ESP = ESP;
ESP = env->regs[R_ESP];
#endif
#ifdef reg_EBP
saved_EBP = EBP;
EBP = env->regs[R_EBP];
#endif
#ifdef reg_ESI
saved_ESI = ESI;
ESI = env->regs[R_ESI];
#endif
#ifdef reg_EDI
saved_EDI = EDI;
EDI = env->regs[R_EDI];
#endif
/* put eflags in CPU temporary format */
T0 = env->eflags;
op_movl_eflags_T0();
CC_OP = CC_OP_EFLAGS;
env->interrupt_request = 0;
/* prepare setjmp context for exception handling */
if (setjmp(env->jmp_env) == 0) {
for(;;) {
if (env->interrupt_request) {
raise_exception(EXCP_INTERRUPT);
}
#ifdef DEBUG_EXEC
if (loglevel) {
cpu_x86_dump_state(logfile);
}
#endif
/* we compute the CPU state. We assume it will not
change during the whole generated block. */
flags = env->seg_cache[R_CS].seg_32bit << GEN_FLAG_CODE32_SHIFT;
flags |= env->seg_cache[R_SS].seg_32bit << GEN_FLAG_SS32_SHIFT;
flags |= (((unsigned long)env->seg_cache[R_DS].base |
(unsigned long)env->seg_cache[R_ES].base |
(unsigned long)env->seg_cache[R_SS].base) != 0) <<
GEN_FLAG_ADDSEG_SHIFT;
cs_base = env->seg_cache[R_CS].base;
pc = cs_base + env->eip;
tb = tb_find(&ptb, (unsigned long)pc, (unsigned long)cs_base,
flags);
if (!tb) {
/* if no translated code available, then translate it now */
/* XXX: very inefficient: we lock all the cpus when
generating code */
cpu_lock();
tc_ptr = code_gen_ptr;
ret = cpu_x86_gen_code(code_gen_ptr, CODE_GEN_MAX_SIZE,
&code_gen_size, pc, cs_base, flags);
/* if invalid instruction, signal it */
if (ret != 0) {
cpu_unlock();
raise_exception(EXCP06_ILLOP);
}
tb = tb_alloc();
*ptb = tb;
tb->pc = (unsigned long)pc;
tb->cs_base = (unsigned long)cs_base;
tb->flags = flags;
tb->tc_ptr = tc_ptr;
tb->hash_next = NULL;
code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
cpu_unlock();
}
/* execute the generated code */
tc_ptr = tb->tc_ptr;
gen_func = (void *)tc_ptr;
gen_func();
}
}
ret = env->exception_index;
/* restore flags in standard format */
op_movl_T0_eflags();
env->eflags = T0;
/* restore global registers */
#ifdef reg_EAX
EAX = saved_EAX;
#endif
#ifdef reg_ECX
ECX = saved_ECX;
#endif
#ifdef reg_EDX
EDX = saved_EDX;
#endif
#ifdef reg_EBX
EBX = saved_EBX;
#endif
#ifdef reg_ESP
ESP = saved_ESP;
#endif
#ifdef reg_EBP
EBP = saved_EBP;
#endif
#ifdef reg_ESI
ESI = saved_ESI;
#endif
#ifdef reg_EDI
EDI = saved_EDI;
#endif
T0 = saved_T0;
T1 = saved_T1;
A0 = saved_A0;
env = saved_env;
return ret;
}
void cpu_x86_interrupt(CPUX86State *s)
{
s->interrupt_request = 1;
}
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
{
CPUX86State *saved_env;
saved_env = env;
env = s;
load_seg(seg_reg, selector);
env = saved_env;
}
#undef EAX
#undef ECX
#undef EDX
#undef EBX
#undef ESP
#undef EBP
#undef ESI
#undef EDI
#undef EIP
#include <signal.h>
#include <sys/ucontext.h>
static inline int handle_cpu_signal(unsigned long pc,
sigset_t *old_set)
{
#ifdef DEBUG_SIGNAL
printf("gemu: SIGSEGV pc=0x%08lx oldset=0x%08lx\n",
pc, *(unsigned long *)old_set);
#endif
if (pc >= (unsigned long)code_gen_buffer &&
pc < (unsigned long)code_gen_buffer + CODE_GEN_BUFFER_SIZE) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
/* we restore the process signal mask as the sigreturn should
do it */
sigprocmask(SIG_SETMASK, old_set, NULL);
/* XXX: need to compute virtual pc position by retranslating
code. The rest of the CPU state should be correct. */
raise_exception(EXCP0D_GPF);
/* never comes here */
return 1;
} else {
return 0;
}
}
int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
void *puc)
{
#if defined(__i386__)
struct ucontext *uc = puc;
unsigned long pc;
sigset_t *pold_set;
#ifndef REG_EIP
/* for glibc 2.1 */
#define REG_EIP EIP
#endif
pc = uc->uc_mcontext.gregs[EIP];
pold_set = &uc->uc_sigmask;
return handle_cpu_signal(pc, pold_set);
#else
#warning No CPU specific signal handler: cannot handle target SIGSEGV events
return 0;
#endif
}

View File

@@ -1,164 +0,0 @@
/*
* i386 execution defines
*
* Copyright (c) 2003 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
typedef signed long long int64_t;
#define bswap32(x) \
({ \
uint32_t __x = (x); \
((uint32_t)( \
(((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
(((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
(((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
(((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
})
#define NULL 0
#include <fenv.h>
typedef struct FILE FILE;
extern FILE *logfile;
extern int loglevel;
extern int fprintf(FILE *, const char *, ...);
extern int printf(const char *, ...);
#ifdef __i386__
register unsigned int T0 asm("ebx");
register unsigned int T1 asm("esi");
register unsigned int A0 asm("edi");
register struct CPUX86State *env asm("ebp");
#endif
#ifdef __powerpc__
register unsigned int EAX asm("r16");
register unsigned int ECX asm("r17");
register unsigned int EDX asm("r18");
register unsigned int EBX asm("r19");
register unsigned int ESP asm("r20");
register unsigned int EBP asm("r21");
register unsigned int ESI asm("r22");
register unsigned int EDI asm("r23");
register unsigned int T0 asm("r24");
register unsigned int T1 asm("r25");
register unsigned int A0 asm("r26");
register struct CPUX86State *env asm("r27");
#define USE_INT_TO_FLOAT_HELPERS
#define reg_EAX
#define reg_ECX
#define reg_EDX
#define reg_EBX
#define reg_ESP
#define reg_EBP
#define reg_ESI
#define reg_EDI
#endif
#ifdef __arm__
register unsigned int T0 asm("r4");
register unsigned int T1 asm("r5");
register unsigned int A0 asm("r6");
register struct CPUX86State *env asm("r7");
#endif
#ifdef __mips__
register unsigned int T0 asm("s0");
register unsigned int T1 asm("s1");
register unsigned int A0 asm("s2");
register struct CPUX86State *env asm("s3");
#endif
#ifdef __sparc__
register unsigned int T0 asm("l0");
register unsigned int T1 asm("l1");
register unsigned int A0 asm("l2");
register struct CPUX86State *env asm("l3");
#endif
/* force GCC to generate only one epilog at the end of the function */
#define FORCE_RET() asm volatile ("");
#ifndef OPPROTO
#define OPPROTO
#endif
#define xglue(x, y) x ## y
#define glue(x, y) xglue(x, y)
#ifndef reg_EAX
#define EAX (env->regs[R_EAX])
#endif
#ifndef reg_ECX
#define ECX (env->regs[R_ECX])
#endif
#ifndef reg_EDX
#define EDX (env->regs[R_EDX])
#endif
#ifndef reg_EBX
#define EBX (env->regs[R_EBX])
#endif
#ifndef reg_ESP
#define ESP (env->regs[R_ESP])
#endif
#ifndef reg_EBP
#define EBP (env->regs[R_EBP])
#endif
#ifndef reg_ESI
#define ESI (env->regs[R_ESI])
#endif
#ifndef reg_EDI
#define EDI (env->regs[R_EDI])
#endif
#define EIP (env->eip)
#define DF (env->df)
#define CC_SRC (env->cc_src)
#define CC_DST (env->cc_dst)
#define CC_OP (env->cc_op)
/* float macros */
#define FT0 (env->ft0)
#define ST0 (env->fpregs[env->fpstt])
#define ST(n) (env->fpregs[(env->fpstt + (n)) & 7])
#define ST1 ST(1)
extern int __op_param1, __op_param2, __op_param3;
#define PARAM1 ((long)(&__op_param1))
#define PARAM2 ((long)(&__op_param2))
#define PARAM3 ((long)(&__op_param3))
#include "cpu-i386.h"
typedef struct CCTable {
int (*compute_all)(void); /* return all the flags */
int (*compute_c)(void); /* return the C flag */
} CCTable;
extern CCTable cc_table[];
void load_seg(int seg_reg, int selector);
void cpu_lock(void);
void cpu_unlock(void);
void raise_exception(int exception_index);
void OPPROTO op_movl_eflags_T0(void);
void OPPROTO op_movl_T0_eflags(void);

2155
exec.c Normal file

File diff suppressed because it is too large Load Diff

658
gdbstub.c Normal file
View File

@@ -0,0 +1,658 @@
/*
* gdb server stub
*
* Copyright (c) 2003 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "vl.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <signal.h>
//#define DEBUG_GDB
enum RSState {
RS_IDLE,
RS_GETLINE,
RS_CHKSUM1,
RS_CHKSUM2,
};
static int gdbserver_fd;
typedef struct GDBState {
enum RSState state;
int fd;
char line_buf[4096];
int line_buf_index;
int line_csum;
} GDBState;
static int get_char(GDBState *s)
{
uint8_t ch;
int ret;
for(;;) {
ret = read(s->fd, &ch, 1);
if (ret < 0) {
if (errno != EINTR && errno != EAGAIN)
return -1;
} else if (ret == 0) {
return -1;
} else {
break;
}
}
return ch;
}
static void put_buffer(GDBState *s, const uint8_t *buf, int len)
{
int ret;
while (len > 0) {
ret = write(s->fd, buf, len);
if (ret < 0) {
if (errno != EINTR && errno != EAGAIN)
return;
} else {
buf += ret;
len -= ret;
}
}
}
static inline int fromhex(int v)
{
if (v >= '0' && v <= '9')
return v - '0';
else if (v >= 'A' && v <= 'F')
return v - 'A' + 10;
else if (v >= 'a' && v <= 'f')
return v - 'a' + 10;
else
return 0;
}
static inline int tohex(int v)
{
if (v < 10)
return v + '0';
else
return v - 10 + 'a';
}
static void memtohex(char *buf, const uint8_t *mem, int len)
{
int i, c;
char *q;
q = buf;
for(i = 0; i < len; i++) {
c = mem[i];
*q++ = tohex(c >> 4);
*q++ = tohex(c & 0xf);
}
*q = '\0';
}
static void hextomem(uint8_t *mem, const char *buf, int len)
{
int i;
for(i = 0; i < len; i++) {
mem[i] = (fromhex(buf[0]) << 4) | fromhex(buf[1]);
buf += 2;
}
}
/* return -1 if error, 0 if OK */
static int put_packet(GDBState *s, char *buf)
{
char buf1[3];
int len, csum, ch, i;
#ifdef DEBUG_GDB
printf("reply='%s'\n", buf);
#endif
for(;;) {
buf1[0] = '$';
put_buffer(s, buf1, 1);
len = strlen(buf);
put_buffer(s, buf, len);
csum = 0;
for(i = 0; i < len; i++) {
csum += buf[i];
}
buf1[0] = '#';
buf1[1] = tohex((csum >> 4) & 0xf);
buf1[2] = tohex((csum) & 0xf);
put_buffer(s, buf1, 3);
ch = get_char(s);
if (ch < 0)
return -1;
if (ch == '+')
break;
}
return 0;
}
#if defined(TARGET_I386)
static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
{
uint32_t *registers = (uint32_t *)mem_buf;
int i, fpus;
for(i = 0; i < 8; i++) {
registers[i] = env->regs[i];
}
registers[8] = env->eip;
registers[9] = env->eflags;
registers[10] = env->segs[R_CS].selector;
registers[11] = env->segs[R_SS].selector;
registers[12] = env->segs[R_DS].selector;
registers[13] = env->segs[R_ES].selector;
registers[14] = env->segs[R_FS].selector;
registers[15] = env->segs[R_GS].selector;
/* XXX: convert floats */
for(i = 0; i < 8; i++) {
memcpy(mem_buf + 16 * 4 + i * 10, &env->fpregs[i], 10);
}
registers[36] = env->fpuc;
fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
registers[37] = fpus;
registers[38] = 0; /* XXX: convert tags */
registers[39] = 0; /* fiseg */
registers[40] = 0; /* fioff */
registers[41] = 0; /* foseg */
registers[42] = 0; /* fooff */
registers[43] = 0; /* fop */
for(i = 0; i < 16; i++)
tswapls(&registers[i]);
for(i = 36; i < 44; i++)
tswapls(&registers[i]);
return 44 * 4;
}
static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
{
uint32_t *registers = (uint32_t *)mem_buf;
int i;
for(i = 0; i < 8; i++) {
env->regs[i] = tswapl(registers[i]);
}
env->eip = tswapl(registers[8]);
env->eflags = tswapl(registers[9]);
#if defined(CONFIG_USER_ONLY)
#define LOAD_SEG(index, sreg)\
if (tswapl(registers[index]) != env->segs[sreg].selector)\
cpu_x86_load_seg(env, sreg, tswapl(registers[index]));
LOAD_SEG(10, R_CS);
LOAD_SEG(11, R_SS);
LOAD_SEG(12, R_DS);
LOAD_SEG(13, R_ES);
LOAD_SEG(14, R_FS);
LOAD_SEG(15, R_GS);
#endif
}
#elif defined (TARGET_PPC)
static uint32_t from_le32 (uint32_t *buf)
{
uint8_t *p = (uint8_t *)buf;
return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
}
static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
{
uint32_t *registers = (uint32_t *)mem_buf, tmp;
int i;
/* fill in gprs */
for(i = 0; i < 32; i++) {
registers[i] = tswapl(env->gpr[i]);
}
/* fill in fprs */
for (i = 0; i < 32; i++) {
registers[(i * 2) + 32] = tswapl(*((uint32_t *)&env->fpr[i]));
registers[(i * 2) + 33] = tswapl(*((uint32_t *)&env->fpr[i] + 1));
}
/* nip, msr, ccr, lnk, ctr, xer, mq */
registers[96] = tswapl(env->nip);
registers[97] = tswapl(_load_msr(env));
tmp = 0;
for (i = 0; i < 8; i++)
tmp |= env->crf[i] << (32 - ((i + 1) * 4));
registers[98] = tswapl(tmp);
registers[99] = tswapl(env->lr);
registers[100] = tswapl(env->ctr);
registers[101] = tswapl(_load_xer(env));
registers[102] = 0;
return 103 * 4;
}
static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
{
uint32_t *registers = (uint32_t *)mem_buf;
int i;
/* fill in gprs */
for (i = 0; i < 32; i++) {
env->gpr[i] = tswapl(registers[i]);
}
/* fill in fprs */
for (i = 0; i < 32; i++) {
*((uint32_t *)&env->fpr[i]) = tswapl(registers[(i * 2) + 32]);
*((uint32_t *)&env->fpr[i] + 1) = tswapl(registers[(i * 2) + 33]);
}
/* nip, msr, ccr, lnk, ctr, xer, mq */
env->nip = tswapl(registers[96]);
_store_msr(env, tswapl(registers[97]));
registers[98] = tswapl(registers[98]);
for (i = 0; i < 8; i++)
env->crf[i] = (registers[98] >> (32 - ((i + 1) * 4))) & 0xF;
env->lr = tswapl(registers[99]);
env->ctr = tswapl(registers[100]);
_store_xer(env, tswapl(registers[101]));
}
#elif defined (TARGET_SPARC)
static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
{
uint32_t *registers = (uint32_t *)mem_buf, tmp;
int i;
/* fill in g0..g7 */
for(i = 0; i < 7; i++) {
registers[i] = tswapl(env->gregs[i]);
}
/* fill in register window */
for(i = 0; i < 24; i++) {
registers[i + 8] = tswapl(env->regwptr[i]);
}
/* fill in fprs */
for (i = 0; i < 32; i++) {
registers[i + 32] = tswapl(*((uint32_t *)&env->fpr[i]));
}
/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
registers[64] = tswapl(env->y);
tmp = (0<<28) | (4<<24) | env->psr \
| (env->psrs? PSR_S : 0) \
| (env->psrs? PSR_PS : 0) \
| (env->psret? PSR_ET : 0) \
| env->cwp;
registers[65] = tswapl(tmp);
registers[66] = tswapl(env->wim);
registers[67] = tswapl(env->tbr);
registers[68] = tswapl(env->pc);
registers[69] = tswapl(env->npc);
registers[70] = tswapl(env->fsr);
registers[71] = 0; /* csr */
registers[72] = 0;
return 73 * 4;
}
static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
{
uint32_t *registers = (uint32_t *)mem_buf, tmp;
int i;
/* fill in g0..g7 */
for(i = 0; i < 7; i++) {
env->gregs[i] = tswapl(registers[i]);
}
/* fill in register window */
for(i = 0; i < 24; i++) {
env->regwptr[i] = tswapl(registers[i]);
}
/* fill in fprs */
for (i = 0; i < 32; i++) {
*((uint32_t *)&env->fpr[i]) = tswapl(registers[i + 32]);
}
/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
env->y = tswapl(registers[64]);
tmp = tswapl(registers[65]);
env->psr = tmp & ~PSR_ICC;
env->psrs = (tmp & PSR_S)? 1 : 0;
env->psrps = (tmp & PSR_PS)? 1 : 0;
env->psret = (tmp & PSR_ET)? 1 : 0;
env->cwp = (tmp & PSR_CWP);
env->wim = tswapl(registers[66]);
env->tbr = tswapl(registers[67]);
env->pc = tswapl(registers[68]);
env->npc = tswapl(registers[69]);
env->fsr = tswapl(registers[70]);
}
#else
static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
{
return 0;
}
static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
{
}
#endif
/* port = 0 means default port */
static int gdb_handle_packet(GDBState *s, const char *line_buf)
{
CPUState *env = cpu_single_env;
const char *p;
int ch, reg_size, type;
char buf[4096];
uint8_t mem_buf[2000];
uint32_t *registers;
uint32_t addr, len;
#ifdef DEBUG_GDB
printf("command='%s'\n", line_buf);
#endif
p = line_buf;
ch = *p++;
switch(ch) {
case '?':
snprintf(buf, sizeof(buf), "S%02x", SIGTRAP);
put_packet(s, buf);
break;
case 'c':
if (*p != '\0') {
addr = strtoul(p, (char **)&p, 16);
#if defined(TARGET_I386)
env->eip = addr;
#elif defined (TARGET_PPC)
env->nip = addr;
#elif defined (TARGET_SPARC)
env->pc = addr;
env->npc = addr + 4;
#endif
}
vm_start();
break;
case 's':
if (*p != '\0') {
addr = strtoul(p, (char **)&p, 16);
#if defined(TARGET_I386)
env->eip = addr;
#elif defined (TARGET_PPC)
env->nip = addr;
#elif defined (TARGET_SPARC)
env->pc = addr;
env->npc = addr + 4;
#endif
}
cpu_single_step(env, 1);
vm_start();
break;
case 'g':
reg_size = cpu_gdb_read_registers(env, mem_buf);
memtohex(buf, mem_buf, reg_size);
put_packet(s, buf);
break;
case 'G':
registers = (void *)mem_buf;
len = strlen(p) / 2;
hextomem((uint8_t *)registers, p, len);
cpu_gdb_write_registers(env, mem_buf, len);
put_packet(s, "OK");
break;
case 'm':
addr = strtoul(p, (char **)&p, 16);
if (*p == ',')
p++;
len = strtoul(p, NULL, 16);
if (cpu_memory_rw_debug(env, addr, mem_buf, len, 0) != 0)
memset(mem_buf, 0, len);
memtohex(buf, mem_buf, len);
put_packet(s, buf);
break;
case 'M':
addr = strtoul(p, (char **)&p, 16);
if (*p == ',')
p++;
len = strtoul(p, (char **)&p, 16);
if (*p == ',')
p++;
hextomem(mem_buf, p, len);
if (cpu_memory_rw_debug(env, addr, mem_buf, len, 1) != 0)
put_packet(s, "ENN");
else
put_packet(s, "OK");
break;
case 'Z':
type = strtoul(p, (char **)&p, 16);
if (*p == ',')
p++;
addr = strtoul(p, (char **)&p, 16);
if (*p == ',')
p++;
len = strtoul(p, (char **)&p, 16);
if (type == 0 || type == 1) {
if (cpu_breakpoint_insert(env, addr) < 0)
goto breakpoint_error;
put_packet(s, "OK");
} else {
breakpoint_error:
put_packet(s, "ENN");
}
break;
case 'z':
type = strtoul(p, (char **)&p, 16);
if (*p == ',')
p++;
addr = strtoul(p, (char **)&p, 16);
if (*p == ',')
p++;
len = strtoul(p, (char **)&p, 16);
if (type == 0 || type == 1) {
cpu_breakpoint_remove(env, addr);
put_packet(s, "OK");
} else {
goto breakpoint_error;
}
break;
default:
// unknown_command:
/* put empty packet */
buf[0] = '\0';
put_packet(s, buf);
break;
}
return RS_IDLE;
}
static void gdb_vm_stopped(void *opaque, int reason)
{
GDBState *s = opaque;
char buf[256];
int ret;
/* disable single step if it was enable */
cpu_single_step(cpu_single_env, 0);
if (reason == EXCP_DEBUG)
ret = SIGTRAP;
else
ret = 0;
snprintf(buf, sizeof(buf), "S%02x", ret);
put_packet(s, buf);
}
static void gdb_read_byte(GDBState *s, int ch)
{
int i, csum;
char reply[1];
if (vm_running) {
/* when the CPU is running, we cannot do anything except stop
it when receiving a char */
vm_stop(EXCP_INTERRUPT);
} else {
switch(s->state) {
case RS_IDLE:
if (ch == '$') {
s->line_buf_index = 0;
s->state = RS_GETLINE;
}
break;
case RS_GETLINE:
if (ch == '#') {
s->state = RS_CHKSUM1;
} else if (s->line_buf_index >= sizeof(s->line_buf) - 1) {
s->state = RS_IDLE;
} else {
s->line_buf[s->line_buf_index++] = ch;
}
break;
case RS_CHKSUM1:
s->line_buf[s->line_buf_index] = '\0';
s->line_csum = fromhex(ch) << 4;
s->state = RS_CHKSUM2;
break;
case RS_CHKSUM2:
s->line_csum |= fromhex(ch);
csum = 0;
for(i = 0; i < s->line_buf_index; i++) {
csum += s->line_buf[i];
}
if (s->line_csum != (csum & 0xff)) {
reply[0] = '-';
put_buffer(s, reply, 1);
s->state = RS_IDLE;
} else {
reply[0] = '+';
put_buffer(s, reply, 1);
s->state = gdb_handle_packet(s, s->line_buf);
}
break;
}
}
}
static int gdb_can_read(void *opaque)
{
return 256;
}
static void gdb_read(void *opaque, const uint8_t *buf, int size)
{
GDBState *s = opaque;
int i;
if (size == 0) {
/* end of connection */
qemu_del_vm_stop_handler(gdb_vm_stopped, s);
qemu_del_fd_read_handler(s->fd);
qemu_free(s);
vm_start();
} else {
for(i = 0; i < size; i++)
gdb_read_byte(s, buf[i]);
}
}
static void gdb_accept(void *opaque, const uint8_t *buf, int size)
{
GDBState *s;
struct sockaddr_in sockaddr;
socklen_t len;
int val, fd;
for(;;) {
len = sizeof(sockaddr);
fd = accept(gdbserver_fd, (struct sockaddr *)&sockaddr, &len);
if (fd < 0 && errno != EINTR) {
perror("accept");
return;
} else if (fd >= 0) {
break;
}
}
/* set short latency */
val = 1;
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
s = qemu_mallocz(sizeof(GDBState));
if (!s) {
close(fd);
return;
}
s->fd = fd;
fcntl(fd, F_SETFL, O_NONBLOCK);
/* stop the VM */
vm_stop(EXCP_INTERRUPT);
/* start handling I/O */
qemu_add_fd_read_handler(s->fd, gdb_can_read, gdb_read, s);
/* when the VM is stopped, the following callback is called */
qemu_add_vm_stop_handler(gdb_vm_stopped, s);
}
static int gdbserver_open(int port)
{
struct sockaddr_in sockaddr;
int fd, val, ret;
fd = socket(PF_INET, SOCK_STREAM, 0);
if (fd < 0) {
perror("socket");
return -1;
}
/* allow fast reuse */
val = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(port);
sockaddr.sin_addr.s_addr = 0;
ret = bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
if (ret < 0) {
perror("bind");
return -1;
}
ret = listen(fd, 0);
if (ret < 0) {
perror("listen");
return -1;
}
fcntl(fd, F_SETFL, O_NONBLOCK);
return fd;
}
int gdbserver_start(int port)
{
gdbserver_fd = gdbserver_open(port);
if (gdbserver_fd < 0)
return -1;
/* accept connections */
qemu_add_fd_read_handler(gdbserver_fd, NULL, gdb_accept, NULL);
return 0;
}

View File

386
hw/adb.c Normal file
View File

@@ -0,0 +1,386 @@
/*
* QEMU ADB support
*
* Copyright (c) 2004 Fabrice Bellard
*
* 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 "vl.h"
/* ADB commands */
#define ADB_BUSRESET 0x00
#define ADB_FLUSH 0x01
#define ADB_WRITEREG 0x08
#define ADB_READREG 0x0c
/* ADB device commands */
#define ADB_CMD_SELF_TEST 0xff
#define ADB_CMD_CHANGE_ID 0xfe
#define ADB_CMD_CHANGE_ID_AND_ACT 0xfd
#define ADB_CMD_CHANGE_ID_AND_ENABLE 0x00
/* ADB default device IDs (upper 4 bits of ADB command byte) */
#define ADB_DONGLE 1
#define ADB_KEYBOARD 2
#define ADB_MOUSE 3
#define ADB_TABLET 4
#define ADB_MODEM 5
#define ADB_MISC 7
/* error codes */
#define ADB_RET_NOTPRESENT (-2)
int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
{
ADBDevice *d;
int devaddr, cmd, i;
cmd = buf[0] & 0xf;
if (cmd == ADB_BUSRESET) {
for(i = 0; i < s->nb_devices; i++) {
d = &s->devices[i];
if (d->devreset) {
d->devreset(d);
}
}
return 0;
}
devaddr = buf[0] >> 4;
for(i = 0; i < s->nb_devices; i++) {
d = &s->devices[i];
if (d->devaddr == devaddr) {
return d->devreq(d, obuf, buf, len);
}
}
return ADB_RET_NOTPRESENT;
}
/* XXX: move that to cuda ? */
int adb_poll(ADBBusState *s, uint8_t *obuf)
{
ADBDevice *d;
int olen, i;
uint8_t buf[1];
olen = 0;
for(i = 0; i < s->nb_devices; i++) {
if (s->poll_index >= s->nb_devices)
s->poll_index = 0;
d = &s->devices[s->poll_index];
buf[0] = ADB_READREG | (d->devaddr << 4);
olen = adb_request(s, obuf + 1, buf, 1);
/* if there is data, we poll again the same device */
if (olen > 0) {
obuf[0] = buf[0];
olen++;
break;
}
s->poll_index++;
}
return olen;
}
ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
ADBDeviceRequest *devreq,
ADBDeviceReset *devreset,
void *opaque)
{
ADBDevice *d;
if (s->nb_devices >= MAX_ADB_DEVICES)
return NULL;
d = &s->devices[s->nb_devices++];
d->bus = s;
d->devaddr = devaddr;
d->devreq = devreq;
d->devreset = devreset;
d->opaque = opaque;
return d;
}
/***************************************************************/
/* Keyboard ADB device */
typedef struct KBDState {
uint8_t data[128];
int rptr, wptr, count;
} KBDState;
static const uint8_t pc_to_adb_keycode[256] = {
0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48,
12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54, 0, 1,
2, 3, 5, 4, 38, 40, 37, 41, 39, 50, 56, 42, 6, 7, 8, 9,
11, 45, 46, 43, 47, 44,123, 67, 58, 49, 57,122,120, 99,118, 96,
97, 98,100,101,109, 71,107, 89, 91, 92, 78, 86, 87, 88, 69, 83,
84, 85, 82, 65, 0, 0, 10,103,111, 0, 0,110, 81, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 94, 0, 93, 0, 0, 0, 0, 0, 0,104,102, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76,125, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 75, 0, 0,124, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,115, 62,116, 0, 59, 0, 60, 0,119,
61,121,114,117, 0, 0, 0, 0, 0, 0, 0, 55,126, 0,127, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
static void adb_kbd_put_keycode(void *opaque, int keycode)
{
ADBDevice *d = opaque;
KBDState *s = d->opaque;
if (s->count < sizeof(s->data)) {
s->data[s->wptr] = keycode;
if (++s->wptr == sizeof(s->data))
s->wptr = 0;
s->count++;
}
}
static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
{
static int ext_keycode;
KBDState *s = d->opaque;
int adb_keycode, keycode;
int olen;
olen = 0;
for(;;) {
if (s->count == 0)
break;
keycode = s->data[s->rptr];
if (++s->rptr == sizeof(s->data))
s->rptr = 0;
s->count--;
if (keycode == 0xe0) {
ext_keycode = 1;
} else {
if (ext_keycode)
adb_keycode = pc_to_adb_keycode[keycode | 0x80];
else
adb_keycode = pc_to_adb_keycode[keycode & 0x7f];
obuf[0] = adb_keycode | (keycode & 0x80);
/* NOTE: could put a second keycode if needed */
obuf[1] = 0xff;
olen = 2;
ext_keycode = 0;
break;
}
}
return olen;
}
static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
const uint8_t *buf, int len)
{
KBDState *s = d->opaque;
int cmd, reg, olen;
if ((buf[0] & 0x0f) == ADB_FLUSH) {
/* flush keyboard fifo */
s->wptr = s->rptr = s->count = 0;
return 0;
}
cmd = buf[0] & 0xc;
reg = buf[0] & 0x3;
olen = 0;
switch(cmd) {
case ADB_WRITEREG:
switch(reg) {
case 2:
/* LED status */
break;
case 3:
switch(buf[2]) {
case ADB_CMD_SELF_TEST:
break;
case ADB_CMD_CHANGE_ID:
case ADB_CMD_CHANGE_ID_AND_ACT:
case ADB_CMD_CHANGE_ID_AND_ENABLE:
d->devaddr = buf[1] & 0xf;
break;
default:
/* XXX: check this */
d->devaddr = buf[1] & 0xf;
d->handler = buf[2];
break;
}
}
break;
case ADB_READREG:
switch(reg) {
case 0:
olen = adb_kbd_poll(d, obuf);
break;
case 1:
break;
case 2:
obuf[0] = 0x00; /* XXX: check this */
obuf[1] = 0x07; /* led status */
olen = 2;
break;
case 3:
obuf[0] = d->handler;
obuf[1] = d->devaddr;
olen = 2;
break;
}
break;
}
return olen;
}
void adb_kbd_init(ADBBusState *bus)
{
ADBDevice *d;
KBDState *s;
s = qemu_mallocz(sizeof(KBDState));
d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request, NULL, s);
d->handler = 1;
qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
}
/***************************************************************/
/* Mouse ADB device */
typedef struct MouseState {
int buttons_state, last_buttons_state;
int dx, dy, dz;
} MouseState;
static void adb_mouse_event(void *opaque,
int dx1, int dy1, int dz1, int buttons_state)
{
ADBDevice *d = opaque;
MouseState *s = d->opaque;
s->dx += dx1;
s->dy += dy1;
s->dz += dz1;
s->buttons_state = buttons_state;
}
static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
{
MouseState *s = d->opaque;
int dx, dy;
if (s->last_buttons_state == s->buttons_state &&
s->dx == 0 && s->dy == 0)
return 0;
dx = s->dx;
if (dx < -63)
dx = -63;
else if (dx > 63)
dx = 63;
dy = s->dy;
if (dy < -63)
dy = -63;
else if (dy > 63)
dy = 63;
s->dx -= dx;
s->dy -= dy;
s->last_buttons_state = s->buttons_state;
dx &= 0x7f;
dy &= 0x7f;
if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
dy |= 0x80;
if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
dx |= 0x80;
obuf[0] = dy;
obuf[1] = dx;
return 2;
}
static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
const uint8_t *buf, int len)
{
MouseState *s = d->opaque;
int cmd, reg, olen;
if ((buf[0] & 0x0f) == ADB_FLUSH) {
/* flush mouse fifo */
s->buttons_state = s->last_buttons_state;
s->dx = 0;
s->dy = 0;
s->dz = 0;
return 0;
}
cmd = buf[0] & 0xc;
reg = buf[0] & 0x3;
olen = 0;
switch(cmd) {
case ADB_WRITEREG:
switch(reg) {
case 2:
break;
case 3:
switch(buf[2]) {
case ADB_CMD_SELF_TEST:
break;
case ADB_CMD_CHANGE_ID:
case ADB_CMD_CHANGE_ID_AND_ACT:
case ADB_CMD_CHANGE_ID_AND_ENABLE:
d->devaddr = buf[1] & 0xf;
break;
default:
/* XXX: check this */
d->devaddr = buf[1] & 0xf;
break;
}
}
break;
case ADB_READREG:
switch(reg) {
case 0:
olen = adb_mouse_poll(d, obuf);
break;
case 1:
break;
case 3:
obuf[0] = d->handler;
obuf[1] = d->devaddr;
olen = 2;
break;
}
break;
}
return olen;
}
void adb_mouse_init(ADBBusState *bus)
{
ADBDevice *d;
MouseState *s;
s = qemu_mallocz(sizeof(MouseState));
d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request, NULL, s);
d->handler = 2;
qemu_add_mouse_event_handler(adb_mouse_event, d);
}

313
hw/adlib.c Normal file
View File

@@ -0,0 +1,313 @@
/*
* QEMU Adlib emulation
*
* Copyright (c) 2004 Vassili Karpov (malc)
*
* 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 "vl.h"
#define dolog(...) AUD_log ("adlib", __VA_ARGS__)
#ifdef DEBUG
#define ldebug(...) dolog (__VA_ARGS__)
#else
#define ldebug(...)
#endif
#ifdef USE_YMF262
#define HAS_YMF262 1
#include "ymf262.h"
void YMF262UpdateOneQEMU(int which, INT16 *dst, int length);
#define SHIFT 2
#else
#include "fmopl.h"
#define SHIFT 1
#endif
#ifdef _WIN32
#include <windows.h>
#define small_delay() Sleep (1)
#else
#define small_delay() usleep (1)
#endif
#define IO_READ_PROTO(name) \
uint32_t name (void *opaque, uint32_t nport)
#define IO_WRITE_PROTO(name) \
void name (void *opaque, uint32_t nport, uint32_t val)
static struct {
int port;
int freq;
} conf = {0x220, 44100};
typedef struct {
int enabled;
int active;
int cparam;
int64_t ticks;
int bufpos;
int16_t *mixbuf;
double interval;
QEMUTimer *ts, *opl_ts;
SWVoice *voice;
int left, pos, samples, bytes_per_second, old_free;
int refcount;
#ifndef USE_YMF262
FM_OPL *opl;
#endif
} AdlibState;
static AdlibState adlib;
static IO_WRITE_PROTO(adlib_write)
{
AdlibState *s = opaque;
int a = nport & 3;
int status;
s->ticks = qemu_get_clock (vm_clock);
s->active = 1;
AUD_enable (s->voice, 1);
#ifdef USE_YMF262
status = YMF262Write (0, a, val);
#else
status = OPLWrite (s->opl, a, val);
#endif
}
static IO_READ_PROTO(adlib_read)
{
AdlibState *s = opaque;
uint8_t data;
int a = nport & 3;
#ifdef USE_YMF262
(void) s;
data = YMF262Read (0, a);
#else
data = OPLRead (s->opl, a);
#endif
return data;
}
static void OPL_timer (void *opaque)
{
AdlibState *s = opaque;
#ifdef USE_YMF262
YMF262TimerOver (s->cparam >> 1, s->cparam & 1);
#else
OPLTimerOver (s->opl, s->cparam);
#endif
qemu_mod_timer (s->opl_ts, qemu_get_clock (vm_clock) + s->interval);
}
static void YMF262TimerHandler (int c, double interval_Sec)
{
AdlibState *s = &adlib;
if (interval_Sec == 0.0) {
qemu_del_timer (s->opl_ts);
return;
}
s->cparam = c;
s->interval = ticks_per_sec * interval_Sec;
qemu_mod_timer (s->opl_ts, qemu_get_clock (vm_clock) + s->interval);
small_delay ();
}
static int write_audio (AdlibState *s, int samples)
{
int net = 0;
int ss = samples;
while (samples) {
int nbytes = samples << SHIFT;
int wbytes = AUD_write (s->voice,
s->mixbuf + (s->pos << (SHIFT - 1)),
nbytes);
int wsampl = wbytes >> SHIFT;
samples -= wsampl;
s->pos = (s->pos + wsampl) % s->samples;
net += wsampl;
if (!wbytes)
break;
}
if (net > ss) {
dolog ("WARNING: net > ss\n");
}
return net;
}
static void timer (void *opaque)
{
AdlibState *s = opaque;
int elapsed, samples, net = 0;
if (s->refcount)
dolog ("refcount=%d\n", s->refcount);
s->refcount += 1;
if (!(s->active && s->enabled))
goto reset;
AUD_run ();
while (s->left) {
int written = write_audio (s, s->left);
net += written;
if (!written)
goto reset2;
s->left -= written;
}
s->pos = 0;
elapsed = AUD_calc_elapsed (s->voice);
if (!elapsed)
goto reset2;
/* elapsed = AUD_get_free (s->voice); */
samples = elapsed >> SHIFT;
if (!samples)
goto reset2;
samples = audio_MIN (samples, s->samples - s->pos);
if (s->left)
dolog ("left=%d samples=%d elapsed=%d free=%d\n",
s->left, samples, elapsed, AUD_get_free (s->voice));
if (!samples)
goto reset2;
#ifdef USE_YMF262
YMF262UpdateOneQEMU (0, s->mixbuf + s->pos * 2, samples);
#else
YM3812UpdateOne (s->opl, s->mixbuf + s->pos, samples);
#endif
while (samples) {
int written = write_audio (s, samples);
net += written;
if (!written)
break;
samples -= written;
}
if (!samples)
s->pos = 0;
s->left = samples;
reset2:
AUD_adjust (s->voice, net << SHIFT);
reset:
qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + ticks_per_sec / 1024);
s->refcount -= 1;
}
static void Adlib_fini (AdlibState *s)
{
#ifdef USE_YMF262
YMF262Shutdown ();
#else
if (s->opl) {
OPLDestroy (s->opl);
s->opl = NULL;
}
#endif
if (s->opl_ts)
qemu_free_timer (s->opl_ts);
if (s->ts)
qemu_free_timer (s->ts);
#define maybe_free(p) if (p) qemu_free (p)
maybe_free (s->mixbuf);
#undef maybe_free
s->active = 0;
s->enabled = 0;
}
void Adlib_init (void)
{
AdlibState *s = &adlib;
memset (s, 0, sizeof (*s));
#ifdef USE_YMF262
if (YMF262Init (1, 14318180, conf.freq)) {
dolog ("YMF262Init %d failed\n", conf.freq);
return;
}
else {
YMF262SetTimerHandler (0, YMF262TimerHandler, 0);
s->enabled = 1;
}
#else
s->opl = OPLCreate (OPL_TYPE_YM3812, 3579545, conf.freq);
if (!s->opl) {
dolog ("OPLCreate %d failed\n", conf.freq);
return;
}
else {
OPLSetTimerHandler (s->opl, YMF262TimerHandler, 0);
s->enabled = 1;
}
#endif
s->opl_ts = qemu_new_timer (vm_clock, OPL_timer, s);
if (!s->opl_ts) {
dolog ("Can not get timer for adlib emulation\n");
Adlib_fini (s);
return;
}
s->ts = qemu_new_timer (vm_clock, timer, s);
if (!s->opl_ts) {
dolog ("Can not get timer for adlib emulation\n");
Adlib_fini (s);
return;
}
s->voice = AUD_open (s->voice, "adlib", conf.freq, SHIFT, AUD_FMT_S16);
if (!s->voice) {
Adlib_fini (s);
return;
}
s->bytes_per_second = conf.freq << SHIFT;
s->samples = AUD_get_buffer_size (s->voice) >> SHIFT;
s->mixbuf = qemu_mallocz (s->samples << SHIFT);
if (!s->mixbuf) {
dolog ("not enough memory for adlib mixing buffer (%d)\n",
s->samples << SHIFT);
Adlib_fini (s);
return;
}
register_ioport_read (0x388, 4, 1, adlib_read, s);
register_ioport_write (0x388, 4, 1, adlib_write, s);
register_ioport_read (conf.port, 4, 1, adlib_read, s);
register_ioport_write (conf.port, 4, 1, adlib_write, s);
register_ioport_read (conf.port + 8, 2, 1, adlib_read, s);
register_ioport_write (conf.port + 8, 2, 1, adlib_write, s);
qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + 1);
}

3115
hw/cirrus_vga.c Normal file

File diff suppressed because it is too large Load Diff

78
hw/cirrus_vga_rop.h Normal file
View File

@@ -0,0 +1,78 @@
/*
* QEMU Cirrus CLGD 54xx VGA Emulator.
*
* Copyright (c) 2004 Fabrice Bellard
*
* 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.
*/
static void
glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s,
uint8_t *dst,const uint8_t *src,
int dstpitch,int srcpitch,
int bltwidth,int bltheight)
{
int x,y;
dstpitch -= bltwidth;
srcpitch -= bltwidth;
for (y = 0; y < bltheight; y++) {
for (x = 0; x < bltwidth; x++) {
ROP_OP(*dst, *src);
dst++;
src++;
}
dst += dstpitch;
src += srcpitch;
}
}
static void
glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s,
uint8_t *dst,const uint8_t *src,
int dstpitch,int srcpitch,
int bltwidth,int bltheight)
{
int x,y;
dstpitch += bltwidth;
srcpitch += bltwidth;
for (y = 0; y < bltheight; y++) {
for (x = 0; x < bltwidth; x++) {
ROP_OP(*dst, *src);
dst--;
src--;
}
dst += dstpitch;
src += srcpitch;
}
}
#define DEPTH 8
#include "cirrus_vga_rop2.h"
#define DEPTH 16
#include "cirrus_vga_rop2.h"
#define DEPTH 24
#include "cirrus_vga_rop2.h"
#define DEPTH 32
#include "cirrus_vga_rop2.h"
#undef ROP_NAME
#undef ROP_OP

260
hw/cirrus_vga_rop2.h Normal file
View File

@@ -0,0 +1,260 @@
/*
* QEMU Cirrus CLGD 54xx VGA Emulator.
*
* Copyright (c) 2004 Fabrice Bellard
*
* 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.
*/
#if DEPTH == 8
#define PUTPIXEL() ROP_OP(d[0], col)
#elif DEPTH == 16
#define PUTPIXEL() ROP_OP(((uint16_t *)d)[0], col);
#elif DEPTH == 24
#define PUTPIXEL() ROP_OP(d[0], col); \
ROP_OP(d[1], (col >> 8)); \
ROP_OP(d[2], (col >> 16))
#elif DEPTH == 32
#define PUTPIXEL() ROP_OP(((uint32_t *)d)[0], col)
#else
#error unsupported DEPTH
#endif
static void
glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH)
(CirrusVGAState * s, uint8_t * dst,
const uint8_t * src,
int dstpitch, int srcpitch,
int bltwidth, int bltheight)
{
uint8_t *d;
int x, y, pattern_y, pattern_pitch, pattern_x;
unsigned int col;
const uint8_t *src1;
#if DEPTH == 8
pattern_pitch = 8;
#elif DEPTH == 16
pattern_pitch = 16;
#else
pattern_pitch = 32;
#endif
pattern_y = s->cirrus_blt_srcaddr & 7;
pattern_x = 0;
for(y = 0; y < bltheight; y++) {
d = dst;
src1 = src + pattern_y * pattern_pitch;
for (x = 0; x < bltwidth; x += (DEPTH / 8)) {
#if DEPTH == 8
col = src1[pattern_x];
pattern_x = (pattern_x + 1) & 7;
#elif DEPTH == 16
col = ((uint16_t *)(src1 + pattern_x))[0];
pattern_x = (pattern_x + 2) & 15;
#elif DEPTH == 24
{
const uint8_t *src2 = src1 + pattern_x * 3;
col = src2[0] | (src2[1] << 8) | (src2[2] << 16);
pattern_x = (pattern_x + 1) & 7;
}
#else
col = ((uint32_t *)(src1 + pattern_x))[0];
pattern_x = (pattern_x + 4) & 31;
#endif
PUTPIXEL();
d += (DEPTH / 8);
}
pattern_y = (pattern_y + 1) & 7;
dst += dstpitch;
}
}
/* NOTE: srcpitch is ignored */
static void
glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
(CirrusVGAState * s, uint8_t * dst,
const uint8_t * src,
int dstpitch, int srcpitch,
int bltwidth, int bltheight)
{
uint8_t *d;
int x, y;
unsigned bits, bits_xor;
unsigned int col;
unsigned bitmask;
unsigned index;
int srcskipleft = 0;
if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
bits_xor = 0xff;
col = s->cirrus_blt_bgcol;
} else {
bits_xor = 0x00;
col = s->cirrus_blt_fgcol;
}
for(y = 0; y < bltheight; y++) {
bitmask = 0x80 >> srcskipleft;
bits = *src++ ^ bits_xor;
d = dst;
for (x = 0; x < bltwidth; x += (DEPTH / 8)) {
if ((bitmask & 0xff) == 0) {
bitmask = 0x80;
bits = *src++ ^ bits_xor;
}
index = (bits & bitmask);
if (index) {
PUTPIXEL();
}
d += (DEPTH / 8);
bitmask >>= 1;
}
dst += dstpitch;
}
}
static void
glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH)
(CirrusVGAState * s, uint8_t * dst,
const uint8_t * src,
int dstpitch, int srcpitch,
int bltwidth, int bltheight)
{
uint32_t colors[2];
uint8_t *d;
int x, y;
unsigned bits;
unsigned int col;
unsigned bitmask;
int srcskipleft = 0;
colors[0] = s->cirrus_blt_bgcol;
colors[1] = s->cirrus_blt_fgcol;
for(y = 0; y < bltheight; y++) {
bitmask = 0x80 >> srcskipleft;
bits = *src++;
d = dst;
for (x = 0; x < bltwidth; x += (DEPTH / 8)) {
if ((bitmask & 0xff) == 0) {
bitmask = 0x80;
bits = *src++;
}
col = colors[!!(bits & bitmask)];
PUTPIXEL();
d += (DEPTH / 8);
bitmask >>= 1;
}
dst += dstpitch;
}
}
static void
glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH)
(CirrusVGAState * s, uint8_t * dst,
const uint8_t * src,
int dstpitch, int srcpitch,
int bltwidth, int bltheight)
{
uint8_t *d;
int x, y, bitpos, pattern_y;
unsigned int bits, bits_xor;
unsigned int col;
if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
bits_xor = 0xff;
col = s->cirrus_blt_bgcol;
} else {
bits_xor = 0x00;
col = s->cirrus_blt_fgcol;
}
pattern_y = s->cirrus_blt_srcaddr & 7;
for(y = 0; y < bltheight; y++) {
bits = src[pattern_y] ^ bits_xor;
bitpos = 7;
d = dst;
for (x = 0; x < bltwidth; x += (DEPTH / 8)) {
if ((bits >> bitpos) & 1) {
PUTPIXEL();
}
d += (DEPTH / 8);
bitpos = (bitpos - 1) & 7;
}
pattern_y = (pattern_y + 1) & 7;
dst += dstpitch;
}
}
static void
glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH)
(CirrusVGAState * s, uint8_t * dst,
const uint8_t * src,
int dstpitch, int srcpitch,
int bltwidth, int bltheight)
{
uint32_t colors[2];
uint8_t *d;
int x, y, bitpos, pattern_y;
unsigned int bits;
unsigned int col;
colors[0] = s->cirrus_blt_bgcol;
colors[1] = s->cirrus_blt_fgcol;
pattern_y = s->cirrus_blt_srcaddr & 7;
for(y = 0; y < bltheight; y++) {
bits = src[pattern_y];
bitpos = 7;
d = dst;
for (x = 0; x < bltwidth; x += (DEPTH / 8)) {
col = colors[(bits >> bitpos) & 1];
PUTPIXEL();
d += (DEPTH / 8);
bitpos = (bitpos - 1) & 7;
}
pattern_y = (pattern_y + 1) & 7;
dst += dstpitch;
}
}
static void
glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH)
(CirrusVGAState *s,
uint8_t *dst, int dst_pitch,
int width, int height)
{
uint8_t *d, *d1;
uint32_t col;
int x, y;
col = s->cirrus_blt_fgcol;
d1 = dst;
for(y = 0; y < height; y++) {
d = d1;
for(x = 0; x < width; x += (DEPTH / 8)) {
PUTPIXEL();
d += (DEPTH / 8);
}
d1 += dst_pitch;
}
}
#undef DEPTH
#undef PUTPIXEL

614
hw/cuda.c Normal file
View File

@@ -0,0 +1,614 @@
/*
* QEMU CUDA support
*
* Copyright (c) 2004 Fabrice Bellard
*
* 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 "vl.h"
//#define DEBUG_CUDA
//#define DEBUG_CUDA_PACKET
/* Bits in B data register: all active low */
#define TREQ 0x08 /* Transfer request (input) */
#define TACK 0x10 /* Transfer acknowledge (output) */
#define TIP 0x20 /* Transfer in progress (output) */
/* Bits in ACR */
#define SR_CTRL 0x1c /* Shift register control bits */
#define SR_EXT 0x0c /* Shift on external clock */
#define SR_OUT 0x10 /* Shift out if 1 */
/* Bits in IFR and IER */
#define IER_SET 0x80 /* set bits in IER */
#define IER_CLR 0 /* clear bits in IER */
#define SR_INT 0x04 /* Shift register full/empty */
#define T1_INT 0x40 /* Timer 1 interrupt */
/* Bits in ACR */
#define T1MODE 0xc0 /* Timer 1 mode */
#define T1MODE_CONT 0x40 /* continuous interrupts */
/* commands (1st byte) */
#define ADB_PACKET 0
#define CUDA_PACKET 1
#define ERROR_PACKET 2
#define TIMER_PACKET 3
#define POWER_PACKET 4
#define MACIIC_PACKET 5
#define PMU_PACKET 6
/* CUDA commands (2nd byte) */
#define CUDA_WARM_START 0x0
#define CUDA_AUTOPOLL 0x1
#define CUDA_GET_6805_ADDR 0x2
#define CUDA_GET_TIME 0x3
#define CUDA_GET_PRAM 0x7
#define CUDA_SET_6805_ADDR 0x8
#define CUDA_SET_TIME 0x9
#define CUDA_POWERDOWN 0xa
#define CUDA_POWERUP_TIME 0xb
#define CUDA_SET_PRAM 0xc
#define CUDA_MS_RESET 0xd
#define CUDA_SEND_DFAC 0xe
#define CUDA_BATTERY_SWAP_SENSE 0x10
#define CUDA_RESET_SYSTEM 0x11
#define CUDA_SET_IPL 0x12
#define CUDA_FILE_SERVER_FLAG 0x13
#define CUDA_SET_AUTO_RATE 0x14
#define CUDA_GET_AUTO_RATE 0x16
#define CUDA_SET_DEVICE_LIST 0x19
#define CUDA_GET_DEVICE_LIST 0x1a
#define CUDA_SET_ONE_SECOND_MODE 0x1b
#define CUDA_SET_POWER_MESSAGES 0x21
#define CUDA_GET_SET_IIC 0x22
#define CUDA_WAKEUP 0x23
#define CUDA_TIMER_TICKLE 0x24
#define CUDA_COMBINED_FORMAT_IIC 0x25
#define CUDA_TIMER_FREQ (4700000 / 6)
#define CUDA_ADB_POLL_FREQ 50
typedef struct CUDATimer {
unsigned int latch;
uint16_t counter_value; /* counter value at load time */
int64_t load_time;
int64_t next_irq_time;
QEMUTimer *timer;
} CUDATimer;
typedef struct CUDAState {
/* cuda registers */
uint8_t b; /* B-side data */
uint8_t a; /* A-side data */
uint8_t dirb; /* B-side direction (1=output) */
uint8_t dira; /* A-side direction (1=output) */
uint8_t sr; /* Shift register */
uint8_t acr; /* Auxiliary control register */
uint8_t pcr; /* Peripheral control register */
uint8_t ifr; /* Interrupt flag register */
uint8_t ier; /* Interrupt enable register */
uint8_t anh; /* A-side data, no handshake */
CUDATimer timers[2];
uint8_t last_b; /* last value of B register */
uint8_t last_acr; /* last value of B register */
int data_in_size;
int data_in_index;
int data_out_index;
int irq;
openpic_t *openpic;
uint8_t autopoll;
uint8_t data_in[128];
uint8_t data_out[16];
QEMUTimer *adb_poll_timer;
} CUDAState;
static CUDAState cuda_state;
ADBBusState adb_bus;
static void cuda_update(CUDAState *s);
static void cuda_receive_packet_from_host(CUDAState *s,
const uint8_t *data, int len);
static void cuda_timer_update(CUDAState *s, CUDATimer *ti,
int64_t current_time);
static void cuda_update_irq(CUDAState *s)
{
if (s->ifr & s->ier & (SR_INT | T1_INT)) {
openpic_set_irq(s->openpic, s->irq, 1);
} else {
openpic_set_irq(s->openpic, s->irq, 0);
}
}
static unsigned int get_counter(CUDATimer *s)
{
int64_t d;
unsigned int counter;
d = muldiv64(qemu_get_clock(vm_clock) - s->load_time,
CUDA_TIMER_FREQ, ticks_per_sec);
if (d <= s->counter_value) {
counter = d;
} else {
counter = s->latch - 1 - ((d - s->counter_value) % s->latch);
}
return counter;
}
static void set_counter(CUDAState *s, CUDATimer *ti, unsigned int val)
{
#ifdef DEBUG_CUDA
printf("cuda: T%d.counter=%d\n",
1 + (ti->timer == NULL), val);
#endif
ti->load_time = qemu_get_clock(vm_clock);
ti->counter_value = val;
cuda_timer_update(s, ti, ti->load_time);
}
static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time)
{
int64_t d, next_time, base;
/* current counter value */
d = muldiv64(current_time - s->load_time,
CUDA_TIMER_FREQ, ticks_per_sec);
if (d <= s->counter_value) {
next_time = s->counter_value + 1;
} else {
base = ((d - s->counter_value) / s->latch);
base = (base * s->latch) + s->counter_value;
next_time = base + s->latch;
}
#ifdef DEBUG_CUDA
printf("latch=%d counter=%lld delta_next=%lld\n",
s->latch, d, next_time - d);
#endif
next_time = muldiv64(next_time, ticks_per_sec, CUDA_TIMER_FREQ) +
s->load_time;
if (next_time <= current_time)
next_time = current_time + 1;
return next_time;
}
static void cuda_timer_update(CUDAState *s, CUDATimer *ti,
int64_t current_time)
{
if (!ti->timer)
return;
if ((s->acr & T1MODE) != T1MODE_CONT) {
qemu_del_timer(ti->timer);
} else {
ti->next_irq_time = get_next_irq_time(ti, current_time);
qemu_mod_timer(ti->timer, ti->next_irq_time);
}
}
static void cuda_timer1(void *opaque)
{
CUDAState *s = opaque;
CUDATimer *ti = &s->timers[0];
cuda_timer_update(s, ti, ti->next_irq_time);
s->ifr |= T1_INT;
cuda_update_irq(s);
}
static uint32_t cuda_readb(void *opaque, target_phys_addr_t addr)
{
CUDAState *s = opaque;
uint32_t val;
addr = (addr >> 9) & 0xf;
switch(addr) {
case 0:
val = s->b;
break;
case 1:
val = s->a;
break;
case 2:
val = s->dirb;
break;
case 3:
val = s->dira;
break;
case 4:
val = get_counter(&s->timers[0]) & 0xff;
s->ifr &= ~T1_INT;
cuda_update_irq(s);
break;
case 5:
val = get_counter(&s->timers[0]) >> 8;
s->ifr &= ~T1_INT;
cuda_update_irq(s);
break;
case 6:
val = s->timers[0].latch & 0xff;
break;
case 7:
val = (s->timers[0].latch >> 8) & 0xff;
break;
case 8:
val = get_counter(&s->timers[1]) & 0xff;
break;
case 9:
val = get_counter(&s->timers[1]) >> 8;
break;
case 10:
val = s->sr;
s->ifr &= ~SR_INT;
cuda_update_irq(s);
break;
case 11:
val = s->acr;
break;
case 12:
val = s->pcr;
break;
case 13:
val = s->ifr;
break;
case 14:
val = s->ier;
break;
default:
case 15:
val = s->anh;
break;
}
#ifdef DEBUG_CUDA
if (addr != 13 || val != 0)
printf("cuda: read: reg=0x%x val=%02x\n", addr, val);
#endif
return val;
}
static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
{
CUDAState *s = opaque;
addr = (addr >> 9) & 0xf;
#ifdef DEBUG_CUDA
printf("cuda: write: reg=0x%x val=%02x\n", addr, val);
#endif
switch(addr) {
case 0:
s->b = val;
cuda_update(s);
break;
case 1:
s->a = val;
break;
case 2:
s->dirb = val;
break;
case 3:
s->dira = val;
break;
case 4:
val = val | (get_counter(&s->timers[0]) & 0xff00);
set_counter(s, &s->timers[0], val);
break;
case 5:
val = (val << 8) | (get_counter(&s->timers[0]) & 0xff);
set_counter(s, &s->timers[0], val);
break;
case 6:
s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
break;
case 7:
s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
break;
case 8:
val = val | (get_counter(&s->timers[1]) & 0xff00);
set_counter(s, &s->timers[1], val);
break;
case 9:
val = (val << 8) | (get_counter(&s->timers[1]) & 0xff);
set_counter(s, &s->timers[1], val);
break;
case 10:
s->sr = val;
break;
case 11:
s->acr = val;
cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
cuda_update(s);
break;
case 12:
s->pcr = val;
break;
case 13:
/* reset bits */
s->ifr &= ~val;
cuda_update_irq(s);
break;
case 14:
if (val & IER_SET) {
/* set bits */
s->ier |= val & 0x7f;
} else {
/* reset bits */
s->ier &= ~val;
}
cuda_update_irq(s);
break;
default:
case 15:
s->anh = val;
break;
}
}
/* NOTE: TIP and TREQ are negated */
static void cuda_update(CUDAState *s)
{
int packet_received, len;
packet_received = 0;
if (!(s->b & TIP)) {
/* transfer requested from host */
if (s->acr & SR_OUT) {
/* data output */
if ((s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) {
if (s->data_out_index < sizeof(s->data_out)) {
#ifdef DEBUG_CUDA
printf("cuda: send: %02x\n", s->sr);
#endif
s->data_out[s->data_out_index++] = s->sr;
s->ifr |= SR_INT;
cuda_update_irq(s);
}
}
} else {
if (s->data_in_index < s->data_in_size) {
/* data input */
if ((s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) {
s->sr = s->data_in[s->data_in_index++];
#ifdef DEBUG_CUDA
printf("cuda: recv: %02x\n", s->sr);
#endif
/* indicate end of transfer */
if (s->data_in_index >= s->data_in_size) {
s->b = (s->b | TREQ);
}
s->ifr |= SR_INT;
cuda_update_irq(s);
}
}
}
} else {
/* no transfer requested: handle sync case */
if ((s->last_b & TIP) && (s->b & TACK) != (s->last_b & TACK)) {
/* update TREQ state each time TACK change state */
if (s->b & TACK)
s->b = (s->b | TREQ);
else
s->b = (s->b & ~TREQ);
s->ifr |= SR_INT;
cuda_update_irq(s);
} else {
if (!(s->last_b & TIP)) {
/* handle end of host to cuda transfert */
packet_received = (s->data_out_index > 0);
/* always an IRQ at the end of transfert */
s->ifr |= SR_INT;
cuda_update_irq(s);
}
/* signal if there is data to read */
if (s->data_in_index < s->data_in_size) {
s->b = (s->b & ~TREQ);
}
}
}
s->last_acr = s->acr;
s->last_b = s->b;
/* NOTE: cuda_receive_packet_from_host() can call cuda_update()
recursively */
if (packet_received) {
len = s->data_out_index;
s->data_out_index = 0;
cuda_receive_packet_from_host(s, s->data_out, len);
}
}
static void cuda_send_packet_to_host(CUDAState *s,
const uint8_t *data, int len)
{
#ifdef DEBUG_CUDA_PACKET
{
int i;
printf("cuda_send_packet_to_host:\n");
for(i = 0; i < len; i++)
printf(" %02x", data[i]);
printf("\n");
}
#endif
memcpy(s->data_in, data, len);
s->data_in_size = len;
s->data_in_index = 0;
cuda_update(s);
s->ifr |= SR_INT;
cuda_update_irq(s);
}
static void cuda_adb_poll(void *opaque)
{
CUDAState *s = opaque;
uint8_t obuf[ADB_MAX_OUT_LEN + 2];
int olen;
olen = adb_poll(&adb_bus, obuf + 2);
if (olen > 0) {
obuf[0] = ADB_PACKET;
obuf[1] = 0x40; /* polled data */
cuda_send_packet_to_host(s, obuf, olen + 2);
}
qemu_mod_timer(s->adb_poll_timer,
qemu_get_clock(vm_clock) +
(ticks_per_sec / CUDA_ADB_POLL_FREQ));
}
static void cuda_receive_packet(CUDAState *s,
const uint8_t *data, int len)
{
uint8_t obuf[16];
int ti, autopoll;
switch(data[0]) {
case CUDA_AUTOPOLL:
autopoll = (data[1] != 0);
if (autopoll != s->autopoll) {
s->autopoll = autopoll;
if (autopoll) {
qemu_mod_timer(s->adb_poll_timer,
qemu_get_clock(vm_clock) +
(ticks_per_sec / CUDA_ADB_POLL_FREQ));
} else {
qemu_del_timer(s->adb_poll_timer);
}
}
obuf[0] = CUDA_PACKET;
obuf[1] = data[1];
cuda_send_packet_to_host(s, obuf, 2);
break;
case CUDA_GET_TIME:
/* XXX: add time support ? */
ti = time(NULL);
obuf[0] = CUDA_PACKET;
obuf[1] = 0;
obuf[2] = 0;
obuf[3] = ti >> 24;
obuf[4] = ti >> 16;
obuf[5] = ti >> 8;
obuf[6] = ti;
cuda_send_packet_to_host(s, obuf, 7);
break;
case CUDA_SET_TIME:
case CUDA_FILE_SERVER_FLAG:
case CUDA_SET_DEVICE_LIST:
case CUDA_SET_AUTO_RATE:
case CUDA_SET_POWER_MESSAGES:
obuf[0] = CUDA_PACKET;
obuf[1] = 0;
cuda_send_packet_to_host(s, obuf, 2);
break;
default:
break;
}
}
static void cuda_receive_packet_from_host(CUDAState *s,
const uint8_t *data, int len)
{
#ifdef DEBUG_CUDA_PACKET
{
int i;
printf("cuda_receive_packet_to_host:\n");
for(i = 0; i < len; i++)
printf(" %02x", data[i]);
printf("\n");
}
#endif
switch(data[0]) {
case ADB_PACKET:
{
uint8_t obuf[ADB_MAX_OUT_LEN + 2];
int olen;
olen = adb_request(&adb_bus, obuf + 2, data + 1, len - 1);
if (olen > 0) {
obuf[0] = ADB_PACKET;
obuf[1] = 0x00;
} else {
/* error */
obuf[0] = ADB_PACKET;
obuf[1] = -olen;
olen = 0;
}
cuda_send_packet_to_host(s, obuf, olen + 2);
}
break;
case CUDA_PACKET:
cuda_receive_packet(s, data + 1, len - 1);
break;
}
}
static void cuda_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
{
}
static void cuda_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
{
}
static uint32_t cuda_readw (void *opaque, target_phys_addr_t addr)
{
return 0;
}
static uint32_t cuda_readl (void *opaque, target_phys_addr_t addr)
{
return 0;
}
static CPUWriteMemoryFunc *cuda_write[] = {
&cuda_writeb,
&cuda_writew,
&cuda_writel,
};
static CPUReadMemoryFunc *cuda_read[] = {
&cuda_readb,
&cuda_readw,
&cuda_readl,
};
int cuda_init(openpic_t *openpic, int irq)
{
CUDAState *s = &cuda_state;
int cuda_mem_index;
s->openpic = openpic;
s->irq = irq;
s->timers[0].timer = qemu_new_timer(vm_clock, cuda_timer1, s);
s->timers[0].latch = 0x10000;
set_counter(s, &s->timers[0], 0xffff);
s->timers[1].latch = 0x10000;
s->ier = T1_INT | SR_INT;
set_counter(s, &s->timers[1], 0xffff);
s->adb_poll_timer = qemu_new_timer(vm_clock, cuda_adb_poll, s);
cuda_mem_index = cpu_register_io_memory(0, cuda_read, cuda_write, s);
return cuda_mem_index;
}

535
hw/dma.c Normal file
View File

@@ -0,0 +1,535 @@
/*
* QEMU DMA emulation
*
* Copyright (c) 2003-2004 Vassili Karpov (malc)
*
* 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 "vl.h"
/* #define DEBUG_DMA */
#define dolog(...) fprintf (stderr, "dma: " __VA_ARGS__)
#ifdef DEBUG_DMA
#define lwarn(...) fprintf (stderr, "dma: " __VA_ARGS__)
#define linfo(...) fprintf (stderr, "dma: " __VA_ARGS__)
#define ldebug(...) fprintf (stderr, "dma: " __VA_ARGS__)
#else
#define lwarn(...)
#define linfo(...)
#define ldebug(...)
#endif
#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
struct dma_regs {
int now[2];
uint16_t base[2];
uint8_t mode;
uint8_t page;
uint8_t pageh;
uint8_t dack;
uint8_t eop;
DMA_transfer_handler transfer_handler;
void *opaque;
};
#define ADDR 0
#define COUNT 1
static struct dma_cont {
uint8_t status;
uint8_t command;
uint8_t mask;
uint8_t flip_flop;
int dshift;
struct dma_regs regs[4];
} dma_controllers[2];
enum {
CMD_MEMORY_TO_MEMORY = 0x01,
CMD_FIXED_ADDRESS = 0x02,
CMD_BLOCK_CONTROLLER = 0x04,
CMD_COMPRESSED_TIME = 0x08,
CMD_CYCLIC_PRIORITY = 0x10,
CMD_EXTENDED_WRITE = 0x20,
CMD_LOW_DREQ = 0x40,
CMD_LOW_DACK = 0x80,
CMD_NOT_SUPPORTED = CMD_MEMORY_TO_MEMORY | CMD_FIXED_ADDRESS
| CMD_COMPRESSED_TIME | CMD_CYCLIC_PRIORITY | CMD_EXTENDED_WRITE
| CMD_LOW_DREQ | CMD_LOW_DACK
};
static int channels[8] = {-1, 2, 3, 1, -1, -1, -1, 0};
static void write_page (void *opaque, uint32_t nport, uint32_t data)
{
struct dma_cont *d = opaque;
int ichan;
ichan = channels[nport & 7];
if (-1 == ichan) {
dolog ("invalid channel %#x %#x\n", nport, data);
return;
}
d->regs[ichan].page = data;
}
static void write_pageh (void *opaque, uint32_t nport, uint32_t data)
{
struct dma_cont *d = opaque;
int ichan;
ichan = channels[nport & 7];
if (-1 == ichan) {
dolog ("invalid channel %#x %#x\n", nport, data);
return;
}
d->regs[ichan].pageh = data;
}
static uint32_t read_page (void *opaque, uint32_t nport)
{
struct dma_cont *d = opaque;
int ichan;
ichan = channels[nport & 7];
if (-1 == ichan) {
dolog ("invalid channel read %#x\n", nport);
return 0;
}
return d->regs[ichan].page;
}
static uint32_t read_pageh (void *opaque, uint32_t nport)
{
struct dma_cont *d = opaque;
int ichan;
ichan = channels[nport & 7];
if (-1 == ichan) {
dolog ("invalid channel read %#x\n", nport);
return 0;
}
return d->regs[ichan].pageh;
}
static inline void init_chan (struct dma_cont *d, int ichan)
{
struct dma_regs *r;
r = d->regs + ichan;
r->now[ADDR] = r->base[ADDR] << d->dshift;
r->now[COUNT] = 0;
}
static inline int getff (struct dma_cont *d)
{
int ff;
ff = d->flip_flop;
d->flip_flop = !ff;
return ff;
}
static uint32_t read_chan (void *opaque, uint32_t nport)
{
struct dma_cont *d = opaque;
int ichan, nreg, iport, ff, val, dir;
struct dma_regs *r;
iport = (nport >> d->dshift) & 0x0f;
ichan = iport >> 1;
nreg = iport & 1;
r = d->regs + ichan;
dir = ((r->mode >> 5) & 1) ? -1 : 1;
ff = getff (d);
if (nreg)
val = (r->base[COUNT] << d->dshift) - r->now[COUNT];
else
val = r->now[ADDR] + r->now[COUNT] * dir;
ldebug ("read_chan %#x -> %d\n", iport, val);
return (val >> (d->dshift + (ff << 3))) & 0xff;
}
static void write_chan (void *opaque, uint32_t nport, uint32_t data)
{
struct dma_cont *d = opaque;
int iport, ichan, nreg;
struct dma_regs *r;
iport = (nport >> d->dshift) & 0x0f;
ichan = iport >> 1;
nreg = iport & 1;
r = d->regs + ichan;
if (getff (d)) {
r->base[nreg] = (r->base[nreg] & 0xff) | ((data << 8) & 0xff00);
init_chan (d, ichan);
} else {
r->base[nreg] = (r->base[nreg] & 0xff00) | (data & 0xff);
}
}
static void write_cont (void *opaque, uint32_t nport, uint32_t data)
{
struct dma_cont *d = opaque;
int iport, ichan = 0;
iport = (nport >> d->dshift) & 0x0f;
switch (iport) {
case 0x08: /* command */
if ((data != 0) && (data & CMD_NOT_SUPPORTED)) {
dolog ("command %#x not supported\n", data);
return;
}
d->command = data;
break;
case 0x09:
ichan = data & 3;
if (data & 4) {
d->status |= 1 << (ichan + 4);
}
else {
d->status &= ~(1 << (ichan + 4));
}
d->status &= ~(1 << ichan);
break;
case 0x0a: /* single mask */
if (data & 4)
d->mask |= 1 << (data & 3);
else
d->mask &= ~(1 << (data & 3));
break;
case 0x0b: /* mode */
{
ichan = data & 3;
#ifdef DEBUG_DMA
{
int op, ai, dir, opmode;
op = (data >> 2) & 3;
ai = (data >> 4) & 1;
dir = (data >> 5) & 1;
opmode = (data >> 6) & 3;
linfo ("ichan %d, op %d, ai %d, dir %d, opmode %d\n",
ichan, op, ai, dir, opmode);
}
#endif
d->regs[ichan].mode = data;
break;
}
case 0x0c: /* clear flip flop */
d->flip_flop = 0;
break;
case 0x0d: /* reset */
d->flip_flop = 0;
d->mask = ~0;
d->status = 0;
d->command = 0;
break;
case 0x0e: /* clear mask for all channels */
d->mask = 0;
break;
case 0x0f: /* write mask for all channels */
d->mask = data;
break;
default:
dolog ("unknown iport %#x\n", iport);
break;
}
#ifdef DEBUG_DMA
if (0xc != iport) {
linfo ("write_cont: nport %#06x, ichan % 2d, val %#06x\n",
nport, ichan, data);
}
#endif
}
static uint32_t read_cont (void *opaque, uint32_t nport)
{
struct dma_cont *d = opaque;
int iport, val;
iport = (nport >> d->dshift) & 0x0f;
switch (iport) {
case 0x08: /* status */
val = d->status;
d->status &= 0xf0;
break;
case 0x0f: /* mask */
val = d->mask;
break;
default:
val = 0;
break;
}
ldebug ("read_cont: nport %#06x, iport %#04x val %#x\n", nport, iport, val);
return val;
}
int DMA_get_channel_mode (int nchan)
{
return dma_controllers[nchan > 3].regs[nchan & 3].mode;
}
void DMA_hold_DREQ (int nchan)
{
int ncont, ichan;
ncont = nchan > 3;
ichan = nchan & 3;
linfo ("held cont=%d chan=%d\n", ncont, ichan);
dma_controllers[ncont].status |= 1 << (ichan + 4);
}
void DMA_release_DREQ (int nchan)
{
int ncont, ichan;
ncont = nchan > 3;
ichan = nchan & 3;
linfo ("released cont=%d chan=%d\n", ncont, ichan);
dma_controllers[ncont].status &= ~(1 << (ichan + 4));
}
static void channel_run (int ncont, int ichan)
{
int n;
struct dma_regs *r = &dma_controllers[ncont].regs[ichan];
#ifdef DEBUG_DMA
int dir, opmode;
dir = (r->mode >> 5) & 1;
opmode = (r->mode >> 6) & 3;
if (dir) {
dolog ("DMA in address decrement mode\n");
}
if (opmode != 1) {
dolog ("DMA not in single mode select %#x\n", opmode);
}
#endif
r = dma_controllers[ncont].regs + ichan;
n = r->transfer_handler (r->opaque, ichan + (ncont << 2),
r->now[COUNT], (r->base[COUNT] + 1) << ncont);
r->now[COUNT] = n;
ldebug ("dma_pos %d size %d\n", n, (r->base[COUNT] + 1) << ncont);
}
void DMA_run (void)
{
struct dma_cont *d;
int icont, ichan;
d = dma_controllers;
for (icont = 0; icont < 2; icont++, d++) {
for (ichan = 0; ichan < 4; ichan++) {
int mask;
mask = 1 << ichan;
if ((0 == (d->mask & mask)) && (0 != (d->status & (mask << 4))))
channel_run (icont, ichan);
}
}
}
void DMA_register_channel (int nchan,
DMA_transfer_handler transfer_handler,
void *opaque)
{
struct dma_regs *r;
int ichan, ncont;
ncont = nchan > 3;
ichan = nchan & 3;
r = dma_controllers[ncont].regs + ichan;
r->transfer_handler = transfer_handler;
r->opaque = opaque;
}
int DMA_read_memory (int nchan, void *buf, int pos, int len)
{
struct dma_regs *r = &dma_controllers[nchan > 3].regs[nchan & 3];
target_ulong addr = ((r->pageh & 0x7f) << 24) | (r->page << 16) | r->now[ADDR];
if (r->mode & 0x20) {
int i;
uint8_t *p = buf;
cpu_physical_memory_read (addr - pos - len, buf, len);
/* What about 16bit transfers? */
for (i = 0; i < len >> 1; i++) {
uint8_t b = p[len - i - 1];
p[i] = b;
}
}
else
cpu_physical_memory_read (addr + pos, buf, len);
return len;
}
int DMA_write_memory (int nchan, void *buf, int pos, int len)
{
struct dma_regs *r = &dma_controllers[nchan > 3].regs[nchan & 3];
target_ulong addr = ((r->pageh & 0x7f) << 24) | (r->page << 16) | r->now[ADDR];
if (r->mode & 0x20) {
int i;
uint8_t *p = buf;
cpu_physical_memory_write (addr - pos - len, buf, len);
/* What about 16bit transfers? */
for (i = 0; i < len; i++) {
uint8_t b = p[len - i - 1];
p[i] = b;
}
}
else
cpu_physical_memory_write (addr + pos, buf, len);
return len;
}
/* request the emulator to transfer a new DMA memory block ASAP */
void DMA_schedule(int nchan)
{
cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
}
static void dma_reset(void *opaque)
{
struct dma_cont *d = opaque;
write_cont (d, (0x0d << d->dshift), 0);
}
/* dshift = 0: 8 bit DMA, 1 = 16 bit DMA */
static void dma_init2(struct dma_cont *d, int base, int dshift,
int page_base, int pageh_base)
{
const static int page_port_list[] = { 0x1, 0x2, 0x3, 0x7 };
int i;
d->dshift = dshift;
for (i = 0; i < 8; i++) {
register_ioport_write (base + (i << dshift), 1, 1, write_chan, d);
register_ioport_read (base + (i << dshift), 1, 1, read_chan, d);
}
for (i = 0; i < LENOFA (page_port_list); i++) {
register_ioport_write (page_base + page_port_list[i], 1, 1,
write_page, d);
register_ioport_read (page_base + page_port_list[i], 1, 1,
read_page, d);
if (pageh_base >= 0) {
register_ioport_write (pageh_base + page_port_list[i], 1, 1,
write_pageh, d);
register_ioport_read (pageh_base + page_port_list[i], 1, 1,
read_pageh, d);
}
}
for (i = 0; i < 8; i++) {
register_ioport_write (base + ((i + 8) << dshift), 1, 1,
write_cont, d);
register_ioport_read (base + ((i + 8) << dshift), 1, 1,
read_cont, d);
}
qemu_register_reset(dma_reset, d);
dma_reset(d);
}
static void dma_save (QEMUFile *f, void *opaque)
{
struct dma_cont *d = opaque;
int i;
/* qemu_put_8s (f, &d->status); */
qemu_put_8s (f, &d->command);
qemu_put_8s (f, &d->mask);
qemu_put_8s (f, &d->flip_flop);
qemu_put_be32s (f, &d->dshift);
for (i = 0; i < 4; ++i) {
struct dma_regs *r = &d->regs[i];
qemu_put_be32s (f, &r->now[0]);
qemu_put_be32s (f, &r->now[1]);
qemu_put_be16s (f, &r->base[0]);
qemu_put_be16s (f, &r->base[1]);
qemu_put_8s (f, &r->mode);
qemu_put_8s (f, &r->page);
qemu_put_8s (f, &r->pageh);
qemu_put_8s (f, &r->dack);
qemu_put_8s (f, &r->eop);
}
}
static int dma_load (QEMUFile *f, void *opaque, int version_id)
{
struct dma_cont *d = opaque;
int i;
if (version_id != 1)
return -EINVAL;
/* qemu_get_8s (f, &d->status); */
qemu_get_8s (f, &d->command);
qemu_get_8s (f, &d->mask);
qemu_get_8s (f, &d->flip_flop);
qemu_get_be32s (f, &d->dshift);
for (i = 0; i < 4; ++i) {
struct dma_regs *r = &d->regs[i];
qemu_get_be32s (f, &r->now[0]);
qemu_get_be32s (f, &r->now[1]);
qemu_get_be16s (f, &r->base[0]);
qemu_get_be16s (f, &r->base[1]);
qemu_get_8s (f, &r->mode);
qemu_get_8s (f, &r->page);
qemu_get_8s (f, &r->pageh);
qemu_get_8s (f, &r->dack);
qemu_get_8s (f, &r->eop);
}
return 0;
}
void DMA_init (int high_page_enable)
{
dma_init2(&dma_controllers[0], 0x00, 0, 0x80,
high_page_enable ? 0x480 : -1);
dma_init2(&dma_controllers[1], 0xc0, 1, 0x88,
high_page_enable ? 0x488 : -1);
register_savevm ("dma", 0, 1, dma_save, dma_load, &dma_controllers[0]);
register_savevm ("dma", 1, 1, dma_save, dma_load, &dma_controllers[1]);
}

1719
hw/fdc.c Normal file

File diff suppressed because it is too large Load Diff

1390
hw/fmopl.c Normal file

File diff suppressed because it is too large Load Diff

174
hw/fmopl.h Normal file
View File

@@ -0,0 +1,174 @@
#ifndef __FMOPL_H_
#define __FMOPL_H_
/* --- select emulation chips --- */
#define BUILD_YM3812 (HAS_YM3812)
//#define BUILD_YM3526 (HAS_YM3526)
//#define BUILD_Y8950 (HAS_Y8950)
/* --- system optimize --- */
/* select bit size of output : 8 or 16 */
#define OPL_OUTPUT_BIT 16
/* compiler dependence */
#ifndef OSD_CPU_H
#define OSD_CPU_H
typedef unsigned char UINT8; /* unsigned 8bit */
typedef unsigned short UINT16; /* unsigned 16bit */
typedef unsigned int UINT32; /* unsigned 32bit */
typedef signed char INT8; /* signed 8bit */
typedef signed short INT16; /* signed 16bit */
typedef signed int INT32; /* signed 32bit */
#endif
#if (OPL_OUTPUT_BIT==16)
typedef INT16 OPLSAMPLE;
#endif
#if (OPL_OUTPUT_BIT==8)
typedef unsigned char OPLSAMPLE;
#endif
#if BUILD_Y8950
#include "ymdeltat.h"
#endif
typedef void (*OPL_TIMERHANDLER)(int channel,double interval_Sec);
typedef void (*OPL_IRQHANDLER)(int param,int irq);
typedef void (*OPL_UPDATEHANDLER)(int param,int min_interval_us);
typedef void (*OPL_PORTHANDLER_W)(int param,unsigned char data);
typedef unsigned char (*OPL_PORTHANDLER_R)(int param);
/* !!!!! here is private section , do not access there member direct !!!!! */
#define OPL_TYPE_WAVESEL 0x01 /* waveform select */
#define OPL_TYPE_ADPCM 0x02 /* DELTA-T ADPCM unit */
#define OPL_TYPE_KEYBOARD 0x04 /* keyboard interface */
#define OPL_TYPE_IO 0x08 /* I/O port */
/* Saving is necessary for member of the 'R' mark for suspend/resume */
/* ---------- OPL one of slot ---------- */
typedef struct fm_opl_slot {
INT32 TL; /* total level :TL << 8 */
INT32 TLL; /* adjusted now TL */
UINT8 KSR; /* key scale rate :(shift down bit) */
INT32 *AR; /* attack rate :&AR_TABLE[AR<<2] */
INT32 *DR; /* decay rate :&DR_TALBE[DR<<2] */
INT32 SL; /* sustin level :SL_TALBE[SL] */
INT32 *RR; /* release rate :&DR_TABLE[RR<<2] */
UINT8 ksl; /* keyscale level :(shift down bits) */
UINT8 ksr; /* key scale rate :kcode>>KSR */
UINT32 mul; /* multiple :ML_TABLE[ML] */
UINT32 Cnt; /* frequency count : */
UINT32 Incr; /* frequency step : */
/* envelope generator state */
UINT8 eg_typ; /* envelope type flag */
UINT8 evm; /* envelope phase */
INT32 evc; /* envelope counter */
INT32 eve; /* envelope counter end point */
INT32 evs; /* envelope counter step */
INT32 evsa; /* envelope step for AR :AR[ksr] */
INT32 evsd; /* envelope step for DR :DR[ksr] */
INT32 evsr; /* envelope step for RR :RR[ksr] */
/* LFO */
UINT8 ams; /* ams flag */
UINT8 vib; /* vibrate flag */
/* wave selector */
INT32 **wavetable;
}OPL_SLOT;
/* ---------- OPL one of channel ---------- */
typedef struct fm_opl_channel {
OPL_SLOT SLOT[2];
UINT8 CON; /* connection type */
UINT8 FB; /* feed back :(shift down bit) */
INT32 *connect1; /* slot1 output pointer */
INT32 *connect2; /* slot2 output pointer */
INT32 op1_out[2]; /* slot1 output for selfeedback */
/* phase generator state */
UINT32 block_fnum; /* block+fnum : */
UINT8 kcode; /* key code : KeyScaleCode */
UINT32 fc; /* Freq. Increment base */
UINT32 ksl_base; /* KeyScaleLevel Base step */
UINT8 keyon; /* key on/off flag */
} OPL_CH;
/* OPL state */
typedef struct fm_opl_f {
UINT8 type; /* chip type */
int clock; /* master clock (Hz) */
int rate; /* sampling rate (Hz) */
double freqbase; /* frequency base */
double TimerBase; /* Timer base time (==sampling time) */
UINT8 address; /* address register */
UINT8 status; /* status flag */
UINT8 statusmask; /* status mask */
UINT32 mode; /* Reg.08 : CSM , notesel,etc. */
/* Timer */
int T[2]; /* timer counter */
UINT8 st[2]; /* timer enable */
/* FM channel slots */
OPL_CH *P_CH; /* pointer of CH */
int max_ch; /* maximum channel */
/* Rythm sention */
UINT8 rythm; /* Rythm mode , key flag */
#if BUILD_Y8950
/* Delta-T ADPCM unit (Y8950) */
YM_DELTAT *deltat; /* DELTA-T ADPCM */
#endif
/* Keyboard / I/O interface unit (Y8950) */
UINT8 portDirection;
UINT8 portLatch;
OPL_PORTHANDLER_R porthandler_r;
OPL_PORTHANDLER_W porthandler_w;
int port_param;
OPL_PORTHANDLER_R keyboardhandler_r;
OPL_PORTHANDLER_W keyboardhandler_w;
int keyboard_param;
/* time tables */
INT32 AR_TABLE[75]; /* atttack rate tables */
INT32 DR_TABLE[75]; /* decay rate tables */
UINT32 FN_TABLE[1024]; /* fnumber -> increment counter */
/* LFO */
INT32 *ams_table;
INT32 *vib_table;
INT32 amsCnt;
INT32 amsIncr;
INT32 vibCnt;
INT32 vibIncr;
/* wave selector enable flag */
UINT8 wavesel;
/* external event callback handler */
OPL_TIMERHANDLER TimerHandler; /* TIMER handler */
int TimerParam; /* TIMER parameter */
OPL_IRQHANDLER IRQHandler; /* IRQ handler */
int IRQParam; /* IRQ parameter */
OPL_UPDATEHANDLER UpdateHandler; /* stream update handler */
int UpdateParam; /* stream update parameter */
} FM_OPL;
/* ---------- Generic interface section ---------- */
#define OPL_TYPE_YM3526 (0)
#define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL)
#define OPL_TYPE_Y8950 (OPL_TYPE_ADPCM|OPL_TYPE_KEYBOARD|OPL_TYPE_IO)
FM_OPL *OPLCreate(int type, int clock, int rate);
void OPLDestroy(FM_OPL *OPL);
void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset);
void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param);
void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param);
/* Y8950 port handlers */
void OPLSetPortHandler(FM_OPL *OPL,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param);
void OPLSetKeyboardHandler(FM_OPL *OPL,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param);
void OPLResetChip(FM_OPL *OPL);
int OPLWrite(FM_OPL *OPL,int a,int v);
unsigned char OPLRead(FM_OPL *OPL,int a);
int OPLTimerOver(FM_OPL *OPL,int c);
/* YM3626/YM3812 local section */
void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length);
void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length);
#endif

470
hw/i8254.c Normal file
View File

@@ -0,0 +1,470 @@
/*
* QEMU 8253/8254 interval timer emulation
*
* Copyright (c) 2003-2004 Fabrice Bellard
*
* 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 "vl.h"
//#define DEBUG_PIT
#define RW_STATE_LSB 1
#define RW_STATE_MSB 2
#define RW_STATE_WORD0 3
#define RW_STATE_WORD1 4
typedef struct PITChannelState {
int count; /* can be 65536 */
uint16_t latched_count;
uint8_t count_latched;
uint8_t status_latched;
uint8_t status;
uint8_t read_state;
uint8_t write_state;
uint8_t write_latch;
uint8_t rw_mode;
uint8_t mode;
uint8_t bcd; /* not supported */
uint8_t gate; /* timer start */
int64_t count_load_time;
/* irq handling */
int64_t next_transition_time;
QEMUTimer *irq_timer;
int irq;
} PITChannelState;
struct PITState {
PITChannelState channels[3];
};
static PITState pit_state;
static void pit_irq_timer_update(PITChannelState *s, int64_t current_time);
static int pit_get_count(PITChannelState *s)
{
uint64_t d;
int counter;
d = muldiv64(qemu_get_clock(vm_clock) - s->count_load_time, PIT_FREQ, ticks_per_sec);
switch(s->mode) {
case 0:
case 1:
case 4:
case 5:
counter = (s->count - d) & 0xffff;
break;
case 3:
/* XXX: may be incorrect for odd counts */
counter = s->count - ((2 * d) % s->count);
break;
default:
counter = s->count - (d % s->count);
break;
}
return counter;
}
/* get pit output bit */
static int pit_get_out1(PITChannelState *s, int64_t current_time)
{
uint64_t d;
int out;
d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec);
switch(s->mode) {
default:
case 0:
out = (d >= s->count);
break;
case 1:
out = (d < s->count);
break;
case 2:
if ((d % s->count) == 0 && d != 0)
out = 1;
else
out = 0;
break;
case 3:
out = (d % s->count) < ((s->count + 1) >> 1);
break;
case 4:
case 5:
out = (d == s->count);
break;
}
return out;
}
int pit_get_out(PITState *pit, int channel, int64_t current_time)
{
PITChannelState *s = &pit->channels[channel];
return pit_get_out1(s, current_time);
}
/* return -1 if no transition will occur. */
static int64_t pit_get_next_transition_time(PITChannelState *s,
int64_t current_time)
{
uint64_t d, next_time, base;
int period2;
d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec);
switch(s->mode) {
default:
case 0:
case 1:
if (d < s->count)
next_time = s->count;
else
return -1;
break;
case 2:
base = (d / s->count) * s->count;
if ((d - base) == 0 && d != 0)
next_time = base + s->count;
else
next_time = base + s->count + 1;
break;
case 3:
base = (d / s->count) * s->count;
period2 = ((s->count + 1) >> 1);
if ((d - base) < period2)
next_time = base + period2;
else
next_time = base + s->count;
break;
case 4:
case 5:
if (d < s->count)
next_time = s->count;
else if (d == s->count)
next_time = s->count + 1;
else
return -1;
break;
}
/* convert to timer units */
next_time = s->count_load_time + muldiv64(next_time, ticks_per_sec, PIT_FREQ);
/* fix potential rounding problems */
/* XXX: better solution: use a clock at PIT_FREQ Hz */
if (next_time <= current_time)
next_time = current_time + 1;
return next_time;
}
/* val must be 0 or 1 */
void pit_set_gate(PITState *pit, int channel, int val)
{
PITChannelState *s = &pit->channels[channel];
switch(s->mode) {
default:
case 0:
case 4:
/* XXX: just disable/enable counting */
break;
case 1:
case 5:
if (s->gate < val) {
/* restart counting on rising edge */
s->count_load_time = qemu_get_clock(vm_clock);
pit_irq_timer_update(s, s->count_load_time);
}
break;
case 2:
case 3:
if (s->gate < val) {
/* restart counting on rising edge */
s->count_load_time = qemu_get_clock(vm_clock);
pit_irq_timer_update(s, s->count_load_time);
}
/* XXX: disable/enable counting */
break;
}
s->gate = val;
}
int pit_get_gate(PITState *pit, int channel)
{
PITChannelState *s = &pit->channels[channel];
return s->gate;
}
static inline void pit_load_count(PITChannelState *s, int val)
{
if (val == 0)
val = 0x10000;
s->count_load_time = qemu_get_clock(vm_clock);
s->count = val;
pit_irq_timer_update(s, s->count_load_time);
}
/* if already latched, do not latch again */
static void pit_latch_count(PITChannelState *s)
{
if (!s->count_latched) {
s->latched_count = pit_get_count(s);
s->count_latched = s->rw_mode;
}
}
static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
PITState *pit = opaque;
int channel, access;
PITChannelState *s;
addr &= 3;
if (addr == 3) {
channel = val >> 6;
if (channel == 3) {
/* read back command */
for(channel = 0; channel < 3; channel++) {
s = &pit->channels[channel];
if (val & (2 << channel)) {
if (!(val & 0x20)) {
pit_latch_count(s);
}
if (!(val & 0x10) && !s->status_latched) {
/* status latch */
/* XXX: add BCD and null count */
s->status = (pit_get_out1(s, qemu_get_clock(vm_clock)) << 7) |
(s->rw_mode << 4) |
(s->mode << 1) |
s->bcd;
s->status_latched = 1;
}
}
}
} else {
s = &pit->channels[channel];
access = (val >> 4) & 3;
if (access == 0) {
pit_latch_count(s);
} else {
s->rw_mode = access;
s->read_state = access;
s->write_state = access;
s->mode = (val >> 1) & 7;
s->bcd = val & 1;
/* XXX: update irq timer ? */
}
}
} else {
s = &pit->channels[addr];
switch(s->write_state) {
default:
case RW_STATE_LSB:
pit_load_count(s, val);
break;
case RW_STATE_MSB:
pit_load_count(s, val << 8);
break;
case RW_STATE_WORD0:
s->write_latch = val;
s->write_state = RW_STATE_WORD1;
break;
case RW_STATE_WORD1:
pit_load_count(s, s->write_latch | (val << 8));
s->write_state = RW_STATE_WORD0;
break;
}
}
}
static uint32_t pit_ioport_read(void *opaque, uint32_t addr)
{
PITState *pit = opaque;
int ret, count;
PITChannelState *s;
addr &= 3;
s = &pit->channels[addr];
if (s->status_latched) {
s->status_latched = 0;
ret = s->status;
} else if (s->count_latched) {
switch(s->count_latched) {
default:
case RW_STATE_LSB:
ret = s->latched_count & 0xff;
s->count_latched = 0;
break;
case RW_STATE_MSB:
ret = s->latched_count >> 8;
s->count_latched = 0;
break;
case RW_STATE_WORD0:
ret = s->latched_count & 0xff;
s->count_latched = RW_STATE_MSB;
break;
}
} else {
switch(s->read_state) {
default:
case RW_STATE_LSB:
count = pit_get_count(s);
ret = count & 0xff;
break;
case RW_STATE_MSB:
count = pit_get_count(s);
ret = (count >> 8) & 0xff;
break;
case RW_STATE_WORD0:
count = pit_get_count(s);
ret = count & 0xff;
s->read_state = RW_STATE_WORD1;
break;
case RW_STATE_WORD1:
count = pit_get_count(s);
ret = (count >> 8) & 0xff;
s->read_state = RW_STATE_WORD0;
break;
}
}
return ret;
}
static void pit_irq_timer_update(PITChannelState *s, int64_t current_time)
{
int64_t expire_time;
int irq_level;
if (!s->irq_timer)
return;
expire_time = pit_get_next_transition_time(s, current_time);
irq_level = pit_get_out1(s, current_time);
pic_set_irq(s->irq, irq_level);
#ifdef DEBUG_PIT
printf("irq_level=%d next_delay=%f\n",
irq_level,
(double)(expire_time - current_time) / ticks_per_sec);
#endif
s->next_transition_time = expire_time;
if (expire_time != -1)
qemu_mod_timer(s->irq_timer, expire_time);
else
qemu_del_timer(s->irq_timer);
}
static void pit_irq_timer(void *opaque)
{
PITChannelState *s = opaque;
pit_irq_timer_update(s, s->next_transition_time);
}
static void pit_save(QEMUFile *f, void *opaque)
{
PITState *pit = opaque;
PITChannelState *s;
int i;
for(i = 0; i < 3; i++) {
s = &pit->channels[i];
qemu_put_be32s(f, &s->count);
qemu_put_be16s(f, &s->latched_count);
qemu_put_8s(f, &s->count_latched);
qemu_put_8s(f, &s->status_latched);
qemu_put_8s(f, &s->status);
qemu_put_8s(f, &s->read_state);
qemu_put_8s(f, &s->write_state);
qemu_put_8s(f, &s->write_latch);
qemu_put_8s(f, &s->rw_mode);
qemu_put_8s(f, &s->mode);
qemu_put_8s(f, &s->bcd);
qemu_put_8s(f, &s->gate);
qemu_put_be64s(f, &s->count_load_time);
if (s->irq_timer) {
qemu_put_be64s(f, &s->next_transition_time);
qemu_put_timer(f, s->irq_timer);
}
}
}
static int pit_load(QEMUFile *f, void *opaque, int version_id)
{
PITState *pit = opaque;
PITChannelState *s;
int i;
if (version_id != 1)
return -EINVAL;
for(i = 0; i < 3; i++) {
s = &pit->channels[i];
qemu_get_be32s(f, &s->count);
qemu_get_be16s(f, &s->latched_count);
qemu_get_8s(f, &s->count_latched);
qemu_get_8s(f, &s->status_latched);
qemu_get_8s(f, &s->status);
qemu_get_8s(f, &s->read_state);
qemu_get_8s(f, &s->write_state);
qemu_get_8s(f, &s->write_latch);
qemu_get_8s(f, &s->rw_mode);
qemu_get_8s(f, &s->mode);
qemu_get_8s(f, &s->bcd);
qemu_get_8s(f, &s->gate);
qemu_get_be64s(f, &s->count_load_time);
if (s->irq_timer) {
qemu_get_be64s(f, &s->next_transition_time);
qemu_get_timer(f, s->irq_timer);
}
}
return 0;
}
static void pit_reset(void *opaque)
{
PITState *pit = opaque;
PITChannelState *s;
int i;
for(i = 0;i < 3; i++) {
s = &pit->channels[i];
s->mode = 3;
s->gate = (i != 2);
pit_load_count(s, 0);
}
}
PITState *pit_init(int base, int irq)
{
PITState *pit = &pit_state;
PITChannelState *s;
s = &pit->channels[0];
/* the timer 0 is connected to an IRQ */
s->irq_timer = qemu_new_timer(vm_clock, pit_irq_timer, s);
s->irq = irq;
register_savevm("i8254", base, 1, pit_save, pit_load, pit);
qemu_register_reset(pit_reset, pit);
register_ioport_write(base, 4, 1, pit_ioport_write, pit);
register_ioport_read(base, 3, 1, pit_ioport_read, pit);
pit_reset(pit);
return pit;
}

512
hw/i8259.c Normal file
View File

@@ -0,0 +1,512 @@
/*
* QEMU 8259 interrupt controller emulation
*
* Copyright (c) 2003-2004 Fabrice Bellard
*
* 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 "vl.h"
/* debug PIC */
//#define DEBUG_PIC
//#define DEBUG_IRQ_LATENCY
//#define DEBUG_IRQ_COUNT
typedef struct PicState {
uint8_t last_irr; /* edge detection */
uint8_t irr; /* interrupt request register */
uint8_t imr; /* interrupt mask register */
uint8_t isr; /* interrupt service register */
uint8_t priority_add; /* highest irq priority */
uint8_t irq_base;
uint8_t read_reg_select;
uint8_t poll;
uint8_t special_mask;
uint8_t init_state;
uint8_t auto_eoi;
uint8_t rotate_on_auto_eoi;
uint8_t special_fully_nested_mode;
uint8_t init4; /* true if 4 byte init */
uint8_t elcr; /* PIIX edge/trigger selection*/
uint8_t elcr_mask;
} PicState;
/* 0 is master pic, 1 is slave pic */
static PicState pics[2];
#if defined(DEBUG_PIC) || defined (DEBUG_IRQ_COUNT)
static int irq_level[16];
#endif
#ifdef DEBUG_IRQ_COUNT
static uint64_t irq_count[16];
#endif
/* set irq level. If an edge is detected, then the IRR is set to 1 */
static inline void pic_set_irq1(PicState *s, int irq, int level)
{
int mask;
mask = 1 << irq;
if (s->elcr & mask) {
/* level triggered */
if (level) {
s->irr |= mask;
s->last_irr |= mask;
} else {
s->irr &= ~mask;
s->last_irr &= ~mask;
}
} else {
/* edge triggered */
if (level) {
if ((s->last_irr & mask) == 0)
s->irr |= mask;
s->last_irr |= mask;
} else {
s->last_irr &= ~mask;
}
}
}
/* return the highest priority found in mask (highest = smallest
number). Return 8 if no irq */
static inline int get_priority(PicState *s, int mask)
{
int priority;
if (mask == 0)
return 8;
priority = 0;
while ((mask & (1 << ((priority + s->priority_add) & 7))) == 0)
priority++;
return priority;
}
/* return the pic wanted interrupt. return -1 if none */
static int pic_get_irq(PicState *s)
{
int mask, cur_priority, priority;
mask = s->irr & ~s->imr;
priority = get_priority(s, mask);
if (priority == 8)
return -1;
/* compute current priority. If special fully nested mode on the
master, the IRQ coming from the slave is not taken into account
for the priority computation. */
mask = s->isr;
if (s->special_fully_nested_mode && s == &pics[0])
mask &= ~(1 << 2);
cur_priority = get_priority(s, mask);
if (priority < cur_priority) {
/* higher priority found: an irq should be generated */
return (priority + s->priority_add) & 7;
} else {
return -1;
}
}
/* raise irq to CPU if necessary. must be called every time the active
irq may change */
static void pic_update_irq(void)
{
int irq2, irq;
/* first look at slave pic */
irq2 = pic_get_irq(&pics[1]);
if (irq2 >= 0) {
/* if irq request by slave pic, signal master PIC */
pic_set_irq1(&pics[0], 2, 1);
pic_set_irq1(&pics[0], 2, 0);
}
/* look at requested irq */
irq = pic_get_irq(&pics[0]);
if (irq >= 0) {
#if defined(DEBUG_PIC)
{
int i;
for(i = 0; i < 2; i++) {
printf("pic%d: imr=%x irr=%x padd=%d\n",
i, pics[i].imr, pics[i].irr, pics[i].priority_add);
}
}
printf("pic: cpu_interrupt\n");
#endif
cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
}
}
#ifdef DEBUG_IRQ_LATENCY
int64_t irq_time[16];
#endif
void pic_set_irq(int irq, int level)
{
#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
if (level != irq_level[irq]) {
#if defined(DEBUG_PIC)
printf("pic_set_irq: irq=%d level=%d\n", irq, level);
#endif
irq_level[irq] = level;
#ifdef DEBUG_IRQ_COUNT
if (level == 1)
irq_count[irq]++;
#endif
}
#endif
#ifdef DEBUG_IRQ_LATENCY
if (level) {
irq_time[irq] = qemu_get_clock(vm_clock);
}
#endif
pic_set_irq1(&pics[irq >> 3], irq & 7, level);
pic_update_irq();
}
/* acknowledge interrupt 'irq' */
static inline void pic_intack(PicState *s, int irq)
{
if (s->auto_eoi) {
if (s->rotate_on_auto_eoi)
s->priority_add = (irq + 1) & 7;
} else {
s->isr |= (1 << irq);
}
/* We don't clear a level sensitive interrupt here */
if (!(s->elcr & (1 << irq)))
s->irr &= ~(1 << irq);
}
int cpu_get_pic_interrupt(CPUState *env)
{
int irq, irq2, intno;
/* read the irq from the PIC */
irq = pic_get_irq(&pics[0]);
if (irq >= 0) {
pic_intack(&pics[0], irq);
if (irq == 2) {
irq2 = pic_get_irq(&pics[1]);
if (irq2 >= 0) {
pic_intack(&pics[1], irq2);
} else {
/* spurious IRQ on slave controller */
irq2 = 7;
}
intno = pics[1].irq_base + irq2;
irq = irq2 + 8;
} else {
intno = pics[0].irq_base + irq;
}
} else {
/* spurious IRQ on host controller */
irq = 7;
intno = pics[0].irq_base + irq;
}
pic_update_irq();
#ifdef DEBUG_IRQ_LATENCY
printf("IRQ%d latency=%0.3fus\n",
irq,
(double)(qemu_get_clock(vm_clock) - irq_time[irq]) * 1000000.0 / ticks_per_sec);
#endif
#if defined(DEBUG_PIC)
printf("pic_interrupt: irq=%d\n", irq);
#endif
return intno;
}
static void pic_reset(void *opaque)
{
PicState *s = opaque;
int tmp;
tmp = s->elcr_mask;
memset(s, 0, sizeof(PicState));
s->elcr_mask = tmp;
}
static void pic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
PicState *s = opaque;
int priority, cmd, irq;
#ifdef DEBUG_PIC
printf("pic_write: addr=0x%02x val=0x%02x\n", addr, val);
#endif
addr &= 1;
if (addr == 0) {
if (val & 0x10) {
/* init */
pic_reset(s);
/* deassert a pending interrupt */
cpu_reset_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
s->init_state = 1;
s->init4 = val & 1;
if (val & 0x02)
hw_error("single mode not supported");
if (val & 0x08)
hw_error("level sensitive irq not supported");
} else if (val & 0x08) {
if (val & 0x04)
s->poll = 1;
if (val & 0x02)
s->read_reg_select = val & 1;
if (val & 0x40)
s->special_mask = (val >> 5) & 1;
} else {
cmd = val >> 5;
switch(cmd) {
case 0:
case 4:
s->rotate_on_auto_eoi = cmd >> 2;
break;
case 1: /* end of interrupt */
case 5:
priority = get_priority(s, s->isr);
if (priority != 8) {
irq = (priority + s->priority_add) & 7;
s->isr &= ~(1 << irq);
if (cmd == 5)
s->priority_add = (irq + 1) & 7;
pic_update_irq();
}
break;
case 3:
irq = val & 7;
s->isr &= ~(1 << irq);
pic_update_irq();
break;
case 6:
s->priority_add = (val + 1) & 7;
pic_update_irq();
break;
case 7:
irq = val & 7;
s->isr &= ~(1 << irq);
s->priority_add = (irq + 1) & 7;
pic_update_irq();
break;
default:
/* no operation */
break;
}
}
} else {
switch(s->init_state) {
case 0:
/* normal mode */
s->imr = val;
pic_update_irq();
break;
case 1:
s->irq_base = val & 0xf8;
s->init_state = 2;
break;
case 2:
if (s->init4) {
s->init_state = 3;
} else {
s->init_state = 0;
}
break;
case 3:
s->special_fully_nested_mode = (val >> 4) & 1;
s->auto_eoi = (val >> 1) & 1;
s->init_state = 0;
break;
}
}
}
static uint32_t pic_poll_read (PicState *s, uint32_t addr1)
{
int ret;
ret = pic_get_irq(s);
if (ret >= 0) {
if (addr1 >> 7) {
pics[0].isr &= ~(1 << 2);
pics[0].irr &= ~(1 << 2);
}
s->irr &= ~(1 << ret);
s->isr &= ~(1 << ret);
if (addr1 >> 7 || ret != 2)
pic_update_irq();
} else {
ret = 0x07;
pic_update_irq();
}
return ret;
}
static uint32_t pic_ioport_read(void *opaque, uint32_t addr1)
{
PicState *s = opaque;
unsigned int addr;
int ret;
addr = addr1;
addr &= 1;
if (s->poll) {
ret = pic_poll_read(s, addr1);
s->poll = 0;
} else {
if (addr == 0) {
if (s->read_reg_select)
ret = s->isr;
else
ret = s->irr;
} else {
ret = s->imr;
}
}
#ifdef DEBUG_PIC
printf("pic_read: addr=0x%02x val=0x%02x\n", addr1, ret);
#endif
return ret;
}
/* memory mapped interrupt status */
uint32_t pic_intack_read(CPUState *env)
{
int ret;
ret = pic_poll_read(&pics[0], 0x00);
if (ret == 2)
ret = pic_poll_read(&pics[1], 0x80) + 8;
/* Prepare for ISR read */
pics[0].read_reg_select = 1;
return ret;
}
static void elcr_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
PicState *s = opaque;
s->elcr = val & s->elcr_mask;
}
static uint32_t elcr_ioport_read(void *opaque, uint32_t addr1)
{
PicState *s = opaque;
return s->elcr;
}
static void pic_save(QEMUFile *f, void *opaque)
{
PicState *s = opaque;
qemu_put_8s(f, &s->last_irr);
qemu_put_8s(f, &s->irr);
qemu_put_8s(f, &s->imr);
qemu_put_8s(f, &s->isr);
qemu_put_8s(f, &s->priority_add);
qemu_put_8s(f, &s->irq_base);
qemu_put_8s(f, &s->read_reg_select);
qemu_put_8s(f, &s->poll);
qemu_put_8s(f, &s->special_mask);
qemu_put_8s(f, &s->init_state);
qemu_put_8s(f, &s->auto_eoi);
qemu_put_8s(f, &s->rotate_on_auto_eoi);
qemu_put_8s(f, &s->special_fully_nested_mode);
qemu_put_8s(f, &s->init4);
qemu_put_8s(f, &s->elcr);
}
static int pic_load(QEMUFile *f, void *opaque, int version_id)
{
PicState *s = opaque;
if (version_id != 1)
return -EINVAL;
qemu_get_8s(f, &s->last_irr);
qemu_get_8s(f, &s->irr);
qemu_get_8s(f, &s->imr);
qemu_get_8s(f, &s->isr);
qemu_get_8s(f, &s->priority_add);
qemu_get_8s(f, &s->irq_base);
qemu_get_8s(f, &s->read_reg_select);
qemu_get_8s(f, &s->poll);
qemu_get_8s(f, &s->special_mask);
qemu_get_8s(f, &s->init_state);
qemu_get_8s(f, &s->auto_eoi);
qemu_get_8s(f, &s->rotate_on_auto_eoi);
qemu_get_8s(f, &s->special_fully_nested_mode);
qemu_get_8s(f, &s->init4);
qemu_get_8s(f, &s->elcr);
return 0;
}
/* XXX: add generic master/slave system */
static void pic_init1(int io_addr, int elcr_addr, PicState *s)
{
register_ioport_write(io_addr, 2, 1, pic_ioport_write, s);
register_ioport_read(io_addr, 2, 1, pic_ioport_read, s);
if (elcr_addr >= 0) {
register_ioport_write(elcr_addr, 1, 1, elcr_ioport_write, s);
register_ioport_read(elcr_addr, 1, 1, elcr_ioport_read, s);
}
register_savevm("i8259", io_addr, 1, pic_save, pic_load, s);
qemu_register_reset(pic_reset, s);
}
void pic_info(void)
{
int i;
PicState *s;
for(i=0;i<2;i++) {
s = &pics[i];
term_printf("pic%d: irr=%02x imr=%02x isr=%02x hprio=%d irq_base=%02x rr_sel=%d elcr=%02x fnm=%d\n",
i, s->irr, s->imr, s->isr, s->priority_add,
s->irq_base, s->read_reg_select, s->elcr,
s->special_fully_nested_mode);
}
}
void irq_info(void)
{
#ifndef DEBUG_IRQ_COUNT
term_printf("irq statistic code not compiled.\n");
#else
int i;
int64_t count;
term_printf("IRQ statistics:\n");
for (i = 0; i < 16; i++) {
count = irq_count[i];
if (count > 0)
term_printf("%2d: %lld\n", i, count);
}
#endif
}
void pic_init(void)
{
pic_init1(0x20, 0x4d0, &pics[0]);
pic_init1(0xa0, 0x4d1, &pics[1]);
pics[0].elcr_mask = 0xf8;
pics[1].elcr_mask = 0xde;
}

2318
hw/ide.c Normal file

File diff suppressed because it is too large Load Diff

218
hw/iommu.c Normal file
View File

@@ -0,0 +1,218 @@
/*
* QEMU SPARC iommu emulation
*
* Copyright (c) 2003 Fabrice Bellard
*
* 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 "vl.h"
/* debug iommu */
//#define DEBUG_IOMMU
/* The IOMMU registers occupy three pages in IO space. */
struct iommu_regs {
/* First page */
volatile unsigned long control; /* IOMMU control */
volatile unsigned long base; /* Physical base of iopte page table */
volatile unsigned long _unused1[3];
volatile unsigned long tlbflush; /* write only */
volatile unsigned long pageflush; /* write only */
volatile unsigned long _unused2[1017];
/* Second page */
volatile unsigned long afsr; /* Async-fault status register */
volatile unsigned long afar; /* Async-fault physical address */
volatile unsigned long _unused3[2];
volatile unsigned long sbuscfg0; /* SBUS configuration registers, per-slot */
volatile unsigned long sbuscfg1;
volatile unsigned long sbuscfg2;
volatile unsigned long sbuscfg3;
volatile unsigned long mfsr; /* Memory-fault status register */
volatile unsigned long mfar; /* Memory-fault physical address */
volatile unsigned long _unused4[1014];
/* Third page */
volatile unsigned long mid; /* IOMMU module-id */
};
#define IOMMU_CTRL_IMPL 0xf0000000 /* Implementation */
#define IOMMU_CTRL_VERS 0x0f000000 /* Version */
#define IOMMU_CTRL_RNGE 0x0000001c /* Mapping RANGE */
#define IOMMU_RNGE_16MB 0x00000000 /* 0xff000000 -> 0xffffffff */
#define IOMMU_RNGE_32MB 0x00000004 /* 0xfe000000 -> 0xffffffff */
#define IOMMU_RNGE_64MB 0x00000008 /* 0xfc000000 -> 0xffffffff */
#define IOMMU_RNGE_128MB 0x0000000c /* 0xf8000000 -> 0xffffffff */
#define IOMMU_RNGE_256MB 0x00000010 /* 0xf0000000 -> 0xffffffff */
#define IOMMU_RNGE_512MB 0x00000014 /* 0xe0000000 -> 0xffffffff */
#define IOMMU_RNGE_1GB 0x00000018 /* 0xc0000000 -> 0xffffffff */
#define IOMMU_RNGE_2GB 0x0000001c /* 0x80000000 -> 0xffffffff */
#define IOMMU_CTRL_ENAB 0x00000001 /* IOMMU Enable */
#define IOMMU_AFSR_ERR 0x80000000 /* LE, TO, or BE asserted */
#define IOMMU_AFSR_LE 0x40000000 /* SBUS reports error after transaction */
#define IOMMU_AFSR_TO 0x20000000 /* Write access took more than 12.8 us. */
#define IOMMU_AFSR_BE 0x10000000 /* Write access received error acknowledge */
#define IOMMU_AFSR_SIZE 0x0e000000 /* Size of transaction causing error */
#define IOMMU_AFSR_S 0x01000000 /* Sparc was in supervisor mode */
#define IOMMU_AFSR_RESV 0x00f00000 /* Reserver, forced to 0x8 by hardware */
#define IOMMU_AFSR_ME 0x00080000 /* Multiple errors occurred */
#define IOMMU_AFSR_RD 0x00040000 /* A read operation was in progress */
#define IOMMU_AFSR_FAV 0x00020000 /* IOMMU afar has valid contents */
#define IOMMU_SBCFG_SAB30 0x00010000 /* Phys-address bit 30 when bypass enabled */
#define IOMMU_SBCFG_BA16 0x00000004 /* Slave supports 16 byte bursts */
#define IOMMU_SBCFG_BA8 0x00000002 /* Slave supports 8 byte bursts */
#define IOMMU_SBCFG_BYPASS 0x00000001 /* Bypass IOMMU, treat all addresses
produced by this device as pure
physical. */
#define IOMMU_MFSR_ERR 0x80000000 /* One or more of PERR1 or PERR0 */
#define IOMMU_MFSR_S 0x01000000 /* Sparc was in supervisor mode */
#define IOMMU_MFSR_CPU 0x00800000 /* CPU transaction caused parity error */
#define IOMMU_MFSR_ME 0x00080000 /* Multiple parity errors occurred */
#define IOMMU_MFSR_PERR 0x00006000 /* high bit indicates parity error occurred
on the even word of the access, low bit
indicated odd word caused the parity error */
#define IOMMU_MFSR_BM 0x00001000 /* Error occurred while in boot mode */
#define IOMMU_MFSR_C 0x00000800 /* Address causing error was marked cacheable */
#define IOMMU_MFSR_RTYP 0x000000f0 /* Memory request transaction type */
#define IOMMU_MID_SBAE 0x001f0000 /* SBus arbitration enable */
#define IOMMU_MID_SE 0x00100000 /* Enables SCSI/ETHERNET arbitration */
#define IOMMU_MID_SB3 0x00080000 /* Enable SBUS device 3 arbitration */
#define IOMMU_MID_SB2 0x00040000 /* Enable SBUS device 2 arbitration */
#define IOMMU_MID_SB1 0x00020000 /* Enable SBUS device 1 arbitration */
#define IOMMU_MID_SB0 0x00010000 /* Enable SBUS device 0 arbitration */
#define IOMMU_MID_MID 0x0000000f /* Module-id, hardcoded to 0x8 */
/* The format of an iopte in the page tables */
#define IOPTE_PAGE 0x07ffff00 /* Physical page number (PA[30:12]) */
#define IOPTE_CACHE 0x00000080 /* Cached (in vme IOCACHE or Viking/MXCC) */
#define IOPTE_WRITE 0x00000004 /* Writeable */
#define IOPTE_VALID 0x00000002 /* IOPTE is valid */
#define IOPTE_WAZ 0x00000001 /* Write as zeros */
#define PAGE_SHIFT 12
#define PAGE_SIZE (1 << PAGE_SHIFT)
#define PAGE_MASK (PAGE_SIZE - 1)
typedef struct IOMMUState {
uint32_t addr;
uint32_t regs[sizeof(struct iommu_regs)];
uint32_t iostart;
} IOMMUState;
static IOMMUState *ps;
static uint32_t iommu_mem_readw(void *opaque, target_phys_addr_t addr)
{
IOMMUState *s = opaque;
uint32_t saddr;
saddr = (addr - s->addr) >> 2;
switch (saddr) {
default:
return s->regs[saddr];
break;
}
return 0;
}
static void iommu_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
{
IOMMUState *s = opaque;
uint32_t saddr;
saddr = (addr - s->addr) >> 2;
switch (saddr) {
case 0:
switch (val & IOMMU_CTRL_RNGE) {
case IOMMU_RNGE_16MB:
s->iostart = 0xff000000;
break;
case IOMMU_RNGE_32MB:
s->iostart = 0xfe000000;
break;
case IOMMU_RNGE_64MB:
s->iostart = 0xfc000000;
break;
case IOMMU_RNGE_128MB:
s->iostart = 0xf8000000;
break;
case IOMMU_RNGE_256MB:
s->iostart = 0xf0000000;
break;
case IOMMU_RNGE_512MB:
s->iostart = 0xe0000000;
break;
case IOMMU_RNGE_1GB:
s->iostart = 0xc0000000;
break;
default:
case IOMMU_RNGE_2GB:
s->iostart = 0x80000000;
break;
}
/* Fall through */
default:
s->regs[saddr] = val;
break;
}
}
static CPUReadMemoryFunc *iommu_mem_read[3] = {
iommu_mem_readw,
iommu_mem_readw,
iommu_mem_readw,
};
static CPUWriteMemoryFunc *iommu_mem_write[3] = {
iommu_mem_writew,
iommu_mem_writew,
iommu_mem_writew,
};
uint32_t iommu_translate(uint32_t addr)
{
uint32_t *iopte = (void *)(ps->regs[1] << 4), pa;
iopte += ((addr - ps->iostart) >> PAGE_SHIFT);
cpu_physical_memory_rw((uint32_t)iopte, (void *) &pa, 4, 0);
bswap32s(&pa);
pa = (pa & IOPTE_PAGE) << 4; /* Loose higher bits of 36 */
return pa + (addr & PAGE_MASK);
}
void iommu_init(uint32_t addr)
{
IOMMUState *s;
int iommu_io_memory;
s = qemu_mallocz(sizeof(IOMMUState));
if (!s)
return;
s->addr = addr;
iommu_io_memory = cpu_register_io_memory(0, iommu_mem_read, iommu_mem_write, s);
cpu_register_physical_memory(addr, sizeof(struct iommu_regs),
iommu_io_memory);
ps = s;
}

468
hw/lance.c Normal file
View File

@@ -0,0 +1,468 @@
/*
* QEMU Lance emulation
*
* Copyright (c) 2003-2004 Fabrice Bellard
*
* 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 "vl.h"
/* debug LANCE card */
//#define DEBUG_LANCE
#ifndef LANCE_LOG_TX_BUFFERS
#define LANCE_LOG_TX_BUFFERS 4
#define LANCE_LOG_RX_BUFFERS 4
#endif
#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */
#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */
#define LE_CSR0 0
#define LE_CSR1 1
#define LE_CSR2 2
#define LE_CSR3 3
#define LE_MAXREG (LE_CSR3 + 1)
#define LE_RDP 0
#define LE_RAP 1
#define LE_MO_PROM 0x8000 /* Enable promiscuous mode */
#define LE_C0_ERR 0x8000 /* Error: set if BAB, SQE, MISS or ME is set */
#define LE_C0_BABL 0x4000 /* BAB: Babble: tx timeout. */
#define LE_C0_CERR 0x2000 /* SQE: Signal quality error */
#define LE_C0_MISS 0x1000 /* MISS: Missed a packet */
#define LE_C0_MERR 0x0800 /* ME: Memory error */
#define LE_C0_RINT 0x0400 /* Received interrupt */
#define LE_C0_TINT 0x0200 /* Transmitter Interrupt */
#define LE_C0_IDON 0x0100 /* IFIN: Init finished. */
#define LE_C0_INTR 0x0080 /* Interrupt or error */
#define LE_C0_INEA 0x0040 /* Interrupt enable */
#define LE_C0_RXON 0x0020 /* Receiver on */
#define LE_C0_TXON 0x0010 /* Transmitter on */
#define LE_C0_TDMD 0x0008 /* Transmitter demand */
#define LE_C0_STOP 0x0004 /* Stop the card */
#define LE_C0_STRT 0x0002 /* Start the card */
#define LE_C0_INIT 0x0001 /* Init the card */
#define LE_C3_BSWP 0x4 /* SWAP */
#define LE_C3_ACON 0x2 /* ALE Control */
#define LE_C3_BCON 0x1 /* Byte control */
/* Receive message descriptor 1 */
#define LE_R1_OWN 0x80 /* Who owns the entry */
#define LE_R1_ERR 0x40 /* Error: if FRA, OFL, CRC or BUF is set */
#define LE_R1_FRA 0x20 /* FRA: Frame error */
#define LE_R1_OFL 0x10 /* OFL: Frame overflow */
#define LE_R1_CRC 0x08 /* CRC error */
#define LE_R1_BUF 0x04 /* BUF: Buffer error */
#define LE_R1_SOP 0x02 /* Start of packet */
#define LE_R1_EOP 0x01 /* End of packet */
#define LE_R1_POK 0x03 /* Packet is complete: SOP + EOP */
#define LE_T1_OWN 0x80 /* Lance owns the packet */
#define LE_T1_ERR 0x40 /* Error summary */
#define LE_T1_EMORE 0x10 /* Error: more than one retry needed */
#define LE_T1_EONE 0x08 /* Error: one retry needed */
#define LE_T1_EDEF 0x04 /* Error: deferred */
#define LE_T1_SOP 0x02 /* Start of packet */
#define LE_T1_EOP 0x01 /* End of packet */
#define LE_T1_POK 0x03 /* Packet is complete: SOP + EOP */
#define LE_T3_BUF 0x8000 /* Buffer error */
#define LE_T3_UFL 0x4000 /* Error underflow */
#define LE_T3_LCOL 0x1000 /* Error late collision */
#define LE_T3_CLOS 0x0800 /* Error carrier loss */
#define LE_T3_RTY 0x0400 /* Error retry */
#define LE_T3_TDR 0x03ff /* Time Domain Reflectometry counter */
#define TX_RING_SIZE (1 << (LANCE_LOG_TX_BUFFERS))
#define TX_RING_MOD_MASK (TX_RING_SIZE - 1)
#define TX_RING_LEN_BITS ((LANCE_LOG_TX_BUFFERS) << 29)
#define RX_RING_SIZE (1 << (LANCE_LOG_RX_BUFFERS))
#define RX_RING_MOD_MASK (RX_RING_SIZE - 1)
#define RX_RING_LEN_BITS ((LANCE_LOG_RX_BUFFERS) << 29)
#define PKT_BUF_SZ 1544
#define RX_BUFF_SIZE PKT_BUF_SZ
#define TX_BUFF_SIZE PKT_BUF_SZ
struct lance_rx_desc {
unsigned short rmd0; /* low address of packet */
unsigned char rmd1_bits; /* descriptor bits */
unsigned char rmd1_hadr; /* high address of packet */
short length; /* This length is 2s complement (negative)!
* Buffer length
*/
unsigned short mblength; /* This is the actual number of bytes received */
};
struct lance_tx_desc {
unsigned short tmd0; /* low address of packet */
unsigned char tmd1_bits; /* descriptor bits */
unsigned char tmd1_hadr; /* high address of packet */
short length; /* Length is 2s complement (negative)! */
unsigned short misc;
};
/* The LANCE initialization block, described in databook. */
/* On the Sparc, this block should be on a DMA region */
struct lance_init_block {
unsigned short mode; /* Pre-set mode (reg. 15) */
unsigned char phys_addr[6]; /* Physical ethernet address */
unsigned filter[2]; /* Multicast filter. */
/* Receive and transmit ring base, along with extra bits. */
unsigned short rx_ptr; /* receive descriptor addr */
unsigned short rx_len; /* receive len and high addr */
unsigned short tx_ptr; /* transmit descriptor addr */
unsigned short tx_len; /* transmit len and high addr */
/* The Tx and Rx ring entries must aligned on 8-byte boundaries. */
struct lance_rx_desc brx_ring[RX_RING_SIZE];
struct lance_tx_desc btx_ring[TX_RING_SIZE];
char tx_buf [TX_RING_SIZE][TX_BUFF_SIZE];
char pad[2]; /* align rx_buf for copy_and_sum(). */
char rx_buf [RX_RING_SIZE][RX_BUFF_SIZE];
};
#define LEDMA_REGS 4
#if 0
/* Structure to describe the current status of DMA registers on the Sparc */
struct sparc_dma_registers {
uint32_t cond_reg; /* DMA condition register */
uint32_t st_addr; /* Start address of this transfer */
uint32_t cnt; /* How many bytes to transfer */
uint32_t dma_test; /* DMA test register */
};
#endif
typedef struct LEDMAState {
uint32_t addr;
uint32_t regs[LEDMA_REGS];
} LEDMAState;
typedef struct LANCEState {
uint32_t paddr;
NetDriverState *nd;
uint32_t leptr;
uint16_t addr;
uint16_t regs[LE_MAXREG];
uint8_t phys[6]; /* mac address */
int irq;
LEDMAState *ledma;
} LANCEState;
static unsigned int rxptr, txptr;
static void lance_send(void *opaque);
static void lance_reset(LANCEState *s)
{
memcpy(s->phys, s->nd->macaddr, 6);
rxptr = 0;
txptr = 0;
s->regs[LE_CSR0] = LE_C0_STOP;
}
static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr)
{
LANCEState *s = opaque;
uint32_t saddr;
saddr = addr - s->paddr;
switch (saddr >> 1) {
case LE_RDP:
return s->regs[s->addr];
case LE_RAP:
return s->addr;
default:
break;
}
return 0;
}
static void lance_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
{
LANCEState *s = opaque;
uint32_t saddr;
uint16_t reg;
saddr = addr - s->paddr;
switch (saddr >> 1) {
case LE_RDP:
switch(s->addr) {
case LE_CSR0:
if (val & LE_C0_STOP) {
s->regs[LE_CSR0] = LE_C0_STOP;
break;
}
reg = s->regs[LE_CSR0];
// 1 = clear for some bits
reg &= ~(val & 0x7f00);
// generated bits
reg &= ~(LE_C0_ERR | LE_C0_INTR);
if (reg & 0x7100)
reg |= LE_C0_ERR;
if (reg & 0x7f00)
reg |= LE_C0_INTR;
// direct bit
reg &= ~LE_C0_INEA;
reg |= val & LE_C0_INEA;
// exclusive bits
if (val & LE_C0_INIT) {
reg |= LE_C0_IDON | LE_C0_INIT;
reg &= ~LE_C0_STOP;
}
else if (val & LE_C0_STRT) {
reg |= LE_C0_STRT | LE_C0_RXON | LE_C0_TXON;
reg &= ~LE_C0_STOP;
}
s->regs[LE_CSR0] = reg;
// trigger bits
//if (val & LE_C0_TDMD)
if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA))
pic_set_irq(s->irq, 1);
break;
case LE_CSR1:
s->leptr = (s->leptr & 0xffff0000) | (val & 0xffff);
s->regs[s->addr] = val;
break;
case LE_CSR2:
s->leptr = (s->leptr & 0xffff) | ((val & 0xffff) << 16);
s->regs[s->addr] = val;
break;
case LE_CSR3:
s->regs[s->addr] = val;
break;
}
break;
case LE_RAP:
if (val < LE_MAXREG)
s->addr = val;
break;
default:
break;
}
lance_send(s);
}
static CPUReadMemoryFunc *lance_mem_read[3] = {
lance_mem_readw,
lance_mem_readw,
lance_mem_readw,
};
static CPUWriteMemoryFunc *lance_mem_write[3] = {
lance_mem_writew,
lance_mem_writew,
lance_mem_writew,
};
/* return the max buffer size if the LANCE can receive more data */
static int lance_can_receive(void *opaque)
{
LANCEState *s = opaque;
void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
struct lance_init_block *ib;
int i;
uint16_t temp;
if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
return 0;
ib = (void *) iommu_translate(dmaptr);
for (i = 0; i < RX_RING_SIZE; i++) {
cpu_physical_memory_read(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
temp &= 0xff;
if (temp == (LE_R1_OWN)) {
#ifdef DEBUG_LANCE
fprintf(stderr, "lance: can receive %d\n", RX_BUFF_SIZE);
#endif
return RX_BUFF_SIZE;
}
}
#ifdef DEBUG_LANCE
fprintf(stderr, "lance: cannot receive\n");
#endif
return 0;
}
#define MIN_BUF_SIZE 60
static void lance_receive(void *opaque, const uint8_t *buf, int size)
{
LANCEState *s = opaque;
void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
struct lance_init_block *ib;
unsigned int i, old_rxptr, j;
uint16_t temp;
if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
return;
ib = (void *) iommu_translate(dmaptr);
old_rxptr = rxptr;
for (i = rxptr; i != ((old_rxptr - 1) & RX_RING_MOD_MASK); i = (i + 1) & RX_RING_MOD_MASK) {
cpu_physical_memory_read(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
if (temp == (LE_R1_OWN)) {
rxptr = (rxptr + 1) & RX_RING_MOD_MASK;
temp = size;
bswap16s(&temp);
cpu_physical_memory_write(&ib->brx_ring[i].mblength, (void *) &temp, 2);
#if 0
cpu_physical_memory_write(&ib->rx_buf[i], buf, size);
#else
for (j = 0; j < size; j++) {
cpu_physical_memory_write(((void *)&ib->rx_buf[i]) + j, &buf[j], 1);
}
#endif
temp = LE_R1_POK;
cpu_physical_memory_write(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
s->regs[LE_CSR0] |= LE_C0_RINT | LE_C0_INTR;
if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA))
pic_set_irq(s->irq, 1);
#ifdef DEBUG_LANCE
fprintf(stderr, "lance: got packet, len %d\n", size);
#endif
return;
}
}
}
static void lance_send(void *opaque)
{
LANCEState *s = opaque;
void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
struct lance_init_block *ib;
unsigned int i, old_txptr, j;
uint16_t temp;
char pkt_buf[PKT_BUF_SZ];
if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
return;
ib = (void *) iommu_translate(dmaptr);
old_txptr = txptr;
for (i = txptr; i != ((old_txptr - 1) & TX_RING_MOD_MASK); i = (i + 1) & TX_RING_MOD_MASK) {
cpu_physical_memory_read(&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1);
if (temp == (LE_T1_POK|LE_T1_OWN)) {
cpu_physical_memory_read(&ib->btx_ring[i].length, (void *) &temp, 2);
bswap16s(&temp);
temp = (~temp) + 1;
#if 0
cpu_physical_memory_read(&ib->tx_buf[i], pkt_buf, temp);
#else
for (j = 0; j < temp; j++) {
cpu_physical_memory_read(((void *)&ib->tx_buf[i]) + j, &pkt_buf[j], 1);
}
#endif
#ifdef DEBUG_LANCE
fprintf(stderr, "lance: sending packet, len %d\n", temp);
#endif
qemu_send_packet(s->nd, pkt_buf, temp);
temp = LE_T1_POK;
cpu_physical_memory_write(&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1);
txptr = (txptr + 1) & TX_RING_MOD_MASK;
s->regs[LE_CSR0] |= LE_C0_TINT | LE_C0_INTR;
}
}
}
static uint32_t ledma_mem_readl(void *opaque, target_phys_addr_t addr)
{
LEDMAState *s = opaque;
uint32_t saddr;
saddr = (addr - s->addr) >> 2;
if (saddr < LEDMA_REGS)
return s->regs[saddr];
else
return 0;
}
static void ledma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
LEDMAState *s = opaque;
uint32_t saddr;
saddr = (addr - s->addr) >> 2;
if (saddr < LEDMA_REGS)
s->regs[saddr] = val;
}
static CPUReadMemoryFunc *ledma_mem_read[3] = {
ledma_mem_readl,
ledma_mem_readl,
ledma_mem_readl,
};
static CPUWriteMemoryFunc *ledma_mem_write[3] = {
ledma_mem_writel,
ledma_mem_writel,
ledma_mem_writel,
};
void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr)
{
LANCEState *s;
LEDMAState *led;
int lance_io_memory, ledma_io_memory;
s = qemu_mallocz(sizeof(LANCEState));
if (!s)
return;
s->paddr = leaddr;
s->nd = nd;
s->irq = irq;
lance_io_memory = cpu_register_io_memory(0, lance_mem_read, lance_mem_write, s);
cpu_register_physical_memory(leaddr, 8, lance_io_memory);
led = qemu_mallocz(sizeof(LEDMAState));
if (!led)
return;
s->ledma = led;
led->addr = ledaddr;
ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, led);
cpu_register_physical_memory(ledaddr, 16, ledma_io_memory);
lance_reset(s);
qemu_add_read_packet(nd, lance_can_receive, lance_receive, s);
}

391
hw/m48t08.c Normal file
View File

@@ -0,0 +1,391 @@
/*
* QEMU M48T08 NVRAM emulation for Sparc platform
*
* Copyright (c) 2003-2004 Jocelyn Mayer
*
* 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 "vl.h"
#include "m48t08.h"
//#define DEBUG_NVRAM
#if defined(DEBUG_NVRAM)
#define NVRAM_PRINTF(fmt, args...) do { printf(fmt , ##args); } while (0)
#else
#define NVRAM_PRINTF(fmt, args...) do { } while (0)
#endif
#define NVRAM_MAX_MEM 0xfff0
struct m48t08_t {
/* Hardware parameters */
int mem_index;
uint32_t mem_base;
uint16_t size;
/* RTC management */
time_t time_offset;
time_t stop_time;
/* NVRAM storage */
uint8_t lock;
uint16_t addr;
uint8_t *buffer;
};
/* Fake timer functions */
/* Generic helpers for BCD */
static inline uint8_t toBCD (uint8_t value)
{
return (((value / 10) % 10) << 4) | (value % 10);
}
static inline uint8_t fromBCD (uint8_t BCD)
{
return ((BCD >> 4) * 10) + (BCD & 0x0F);
}
/* RTC management helpers */
static void get_time (m48t08_t *NVRAM, struct tm *tm)
{
time_t t;
t = time(NULL) + NVRAM->time_offset;
#ifdef _WIN32
memcpy(tm,localtime(&t),sizeof(*tm));
#else
localtime_r (&t, tm) ;
#endif
}
static void set_time (m48t08_t *NVRAM, struct tm *tm)
{
time_t now, new_time;
new_time = mktime(tm);
now = time(NULL);
NVRAM->time_offset = new_time - now;
}
/* Direct access to NVRAM */
void m48t08_write (m48t08_t *NVRAM, uint32_t val)
{
struct tm tm;
int tmp;
if (NVRAM->addr > NVRAM_MAX_MEM && NVRAM->addr < 0x2000)
NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, NVRAM->addr, val);
switch (NVRAM->addr) {
case 0x1FF8:
/* control */
NVRAM->buffer[0x1FF8] = (val & ~0xA0) | 0x90;
break;
case 0x1FF9:
/* seconds (BCD) */
tmp = fromBCD(val & 0x7F);
if (tmp >= 0 && tmp <= 59) {
get_time(NVRAM, &tm);
tm.tm_sec = tmp;
set_time(NVRAM, &tm);
}
if ((val & 0x80) ^ (NVRAM->buffer[0x1FF9] & 0x80)) {
if (val & 0x80) {
NVRAM->stop_time = time(NULL);
} else {
NVRAM->time_offset += NVRAM->stop_time - time(NULL);
NVRAM->stop_time = 0;
}
}
NVRAM->buffer[0x1FF9] = val & 0x80;
break;
case 0x1FFA:
/* minutes (BCD) */
tmp = fromBCD(val & 0x7F);
if (tmp >= 0 && tmp <= 59) {
get_time(NVRAM, &tm);
tm.tm_min = tmp;
set_time(NVRAM, &tm);
}
break;
case 0x1FFB:
/* hours (BCD) */
tmp = fromBCD(val & 0x3F);
if (tmp >= 0 && tmp <= 23) {
get_time(NVRAM, &tm);
tm.tm_hour = tmp;
set_time(NVRAM, &tm);
}
break;
case 0x1FFC:
/* day of the week / century */
tmp = fromBCD(val & 0x07);
get_time(NVRAM, &tm);
tm.tm_wday = tmp;
set_time(NVRAM, &tm);
NVRAM->buffer[0x1FFC] = val & 0x40;
break;
case 0x1FFD:
/* date */
tmp = fromBCD(val & 0x1F);
if (tmp != 0) {
get_time(NVRAM, &tm);
tm.tm_mday = tmp;
set_time(NVRAM, &tm);
}
break;
case 0x1FFE:
/* month */
tmp = fromBCD(val & 0x1F);
if (tmp >= 1 && tmp <= 12) {
get_time(NVRAM, &tm);
tm.tm_mon = tmp - 1;
set_time(NVRAM, &tm);
}
break;
case 0x1FFF:
/* year */
tmp = fromBCD(val);
if (tmp >= 0 && tmp <= 99) {
get_time(NVRAM, &tm);
tm.tm_year = fromBCD(val);
set_time(NVRAM, &tm);
}
break;
default:
/* Check lock registers state */
if (NVRAM->addr >= 0x20 && NVRAM->addr <= 0x2F && (NVRAM->lock & 1))
break;
if (NVRAM->addr >= 0x30 && NVRAM->addr <= 0x3F && (NVRAM->lock & 2))
break;
if (NVRAM->addr < NVRAM_MAX_MEM ||
(NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) {
NVRAM->buffer[NVRAM->addr] = val & 0xFF;
}
break;
}
}
uint32_t m48t08_read (m48t08_t *NVRAM)
{
struct tm tm;
uint32_t retval = 0xFF;
switch (NVRAM->addr) {
case 0x1FF8:
/* control */
goto do_read;
case 0x1FF9:
/* seconds (BCD) */
get_time(NVRAM, &tm);
retval = (NVRAM->buffer[0x1FF9] & 0x80) | toBCD(tm.tm_sec);
break;
case 0x1FFA:
/* minutes (BCD) */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_min);
break;
case 0x1FFB:
/* hours (BCD) */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_hour);
break;
case 0x1FFC:
/* day of the week / century */
get_time(NVRAM, &tm);
retval = NVRAM->buffer[0x1FFC] | tm.tm_wday;
break;
case 0x1FFD:
/* date */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_mday);
break;
case 0x1FFE:
/* month */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_mon + 1);
break;
case 0x1FFF:
/* year */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_year);
break;
default:
/* Check lock registers state */
if (NVRAM->addr >= 0x20 && NVRAM->addr <= 0x2F && (NVRAM->lock & 1))
break;
if (NVRAM->addr >= 0x30 && NVRAM->addr <= 0x3F && (NVRAM->lock & 2))
break;
if (NVRAM->addr < NVRAM_MAX_MEM ||
(NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) {
do_read:
retval = NVRAM->buffer[NVRAM->addr];
}
break;
}
if (NVRAM->addr > NVRAM_MAX_MEM + 1 && NVRAM->addr < 0x2000)
NVRAM_PRINTF("0x%08x <= 0x%08x\n", NVRAM->addr, retval);
return retval;
}
void m48t08_set_addr (m48t08_t *NVRAM, uint32_t addr)
{
NVRAM->addr = addr;
}
void m48t08_toggle_lock (m48t08_t *NVRAM, int lock)
{
NVRAM->lock ^= 1 << lock;
}
static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
{
m48t08_t *NVRAM = opaque;
addr -= NVRAM->mem_base;
if (addr < NVRAM_MAX_MEM)
NVRAM->buffer[addr] = value;
}
static void nvram_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
{
m48t08_t *NVRAM = opaque;
addr -= NVRAM->mem_base;
if (addr < NVRAM_MAX_MEM) {
NVRAM->buffer[addr] = value >> 8;
NVRAM->buffer[addr + 1] = value;
}
}
static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
{
m48t08_t *NVRAM = opaque;
addr -= NVRAM->mem_base;
if (addr < NVRAM_MAX_MEM) {
NVRAM->buffer[addr] = value >> 24;
NVRAM->buffer[addr + 1] = value >> 16;
NVRAM->buffer[addr + 2] = value >> 8;
NVRAM->buffer[addr + 3] = value;
}
}
static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
{
m48t08_t *NVRAM = opaque;
uint32_t retval = 0;
addr -= NVRAM->mem_base;
if (addr < NVRAM_MAX_MEM)
retval = NVRAM->buffer[addr];
return retval;
}
static uint32_t nvram_readw (void *opaque, target_phys_addr_t addr)
{
m48t08_t *NVRAM = opaque;
uint32_t retval = 0;
addr -= NVRAM->mem_base;
if (addr < NVRAM_MAX_MEM) {
retval = NVRAM->buffer[addr] << 8;
retval |= NVRAM->buffer[addr + 1];
}
return retval;
}
static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr)
{
m48t08_t *NVRAM = opaque;
uint32_t retval = 0;
addr -= NVRAM->mem_base;
if (addr < NVRAM_MAX_MEM) {
retval = NVRAM->buffer[addr] << 24;
retval |= NVRAM->buffer[addr + 1] << 16;
retval |= NVRAM->buffer[addr + 2] << 8;
retval |= NVRAM->buffer[addr + 3];
}
return retval;
}
static CPUWriteMemoryFunc *nvram_write[] = {
&nvram_writeb,
&nvram_writew,
&nvram_writel,
};
static CPUReadMemoryFunc *nvram_read[] = {
&nvram_readb,
&nvram_readw,
&nvram_readl,
};
/* Initialisation routine */
m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size, uint8_t *macaddr)
{
m48t08_t *s;
int i;
unsigned char tmp = 0;
s = qemu_mallocz(sizeof(m48t08_t));
if (!s)
return NULL;
s->buffer = qemu_mallocz(size);
if (!s->buffer) {
qemu_free(s);
return NULL;
}
s->size = size;
s->mem_base = mem_base;
s->addr = 0;
if (mem_base != 0) {
s->mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s);
cpu_register_physical_memory(mem_base, 0x4000, s->mem_index);
}
s->lock = 0;
i = 0x1fd8;
s->buffer[i++] = 0x01;
s->buffer[i++] = 0x80; /* Sun4m OBP */
memcpy(&s->buffer[i], macaddr, 6);
/* Calculate checksum */
for (i = 0x1fd8; i < 0x1fe7; i++) {
tmp ^= s->buffer[i];
}
s->buffer[0x1fe7] = tmp;
return s;
}
#if 0
struct idprom
{
unsigned char id_format; /* Format identifier (always 0x01) */
unsigned char id_machtype; /* Machine type */
unsigned char id_ethaddr[6]; /* Hardware ethernet address */
long id_date; /* Date of manufacture */
unsigned int id_sernum:24; /* Unique serial number */
unsigned char id_cksum; /* Checksum - xor of the data bytes */
unsigned char reserved[16];
};
#endif

12
hw/m48t08.h Normal file
View File

@@ -0,0 +1,12 @@
#if !defined (__M48T08_H__)
#define __M48T08_H__
typedef struct m48t08_t m48t08_t;
void m48t08_write (m48t08_t *NVRAM, uint32_t val);
uint32_t m48t08_read (m48t08_t *NVRAM);
void m48t08_set_addr (m48t08_t *NVRAM, uint32_t addr);
void m48t08_toggle_lock (m48t08_t *NVRAM, int lock);
m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size, uint8_t *macaddr);
#endif /* !defined (__M48T08_H__) */

602
hw/m48t59.c Normal file
View File

@@ -0,0 +1,602 @@
/*
* QEMU M48T59 NVRAM emulation for PPC PREP platform
*
* Copyright (c) 2003-2004 Jocelyn Mayer
*
* 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 "vl.h"
#include "m48t59.h"
//#define DEBUG_NVRAM
#if defined(DEBUG_NVRAM)
#define NVRAM_PRINTF(fmt, args...) do { printf(fmt , ##args); } while (0)
#else
#define NVRAM_PRINTF(fmt, args...) do { } while (0)
#endif
struct m48t59_t {
/* Hardware parameters */
int IRQ;
int mem_index;
uint32_t mem_base;
uint32_t io_base;
uint16_t size;
/* RTC management */
time_t time_offset;
time_t stop_time;
/* Alarm & watchdog */
time_t alarm;
struct QEMUTimer *alrm_timer;
struct QEMUTimer *wd_timer;
/* NVRAM storage */
uint8_t lock;
uint16_t addr;
uint8_t *buffer;
};
/* Fake timer functions */
/* Generic helpers for BCD */
static inline uint8_t toBCD (uint8_t value)
{
return (((value / 10) % 10) << 4) | (value % 10);
}
static inline uint8_t fromBCD (uint8_t BCD)
{
return ((BCD >> 4) * 10) + (BCD & 0x0F);
}
/* RTC management helpers */
static void get_time (m48t59_t *NVRAM, struct tm *tm)
{
time_t t;
t = time(NULL) + NVRAM->time_offset;
#ifdef _WIN32
memcpy(tm,localtime(&t),sizeof(*tm));
#else
localtime_r (&t, tm) ;
#endif
}
static void set_time (m48t59_t *NVRAM, struct tm *tm)
{
time_t now, new_time;
new_time = mktime(tm);
now = time(NULL);
NVRAM->time_offset = new_time - now;
}
/* Alarm management */
static void alarm_cb (void *opaque)
{
struct tm tm, tm_now;
uint64_t next_time;
m48t59_t *NVRAM = opaque;
pic_set_irq(NVRAM->IRQ, 1);
if ((NVRAM->buffer[0x1FF5] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF2] & 0x80) == 0) {
/* Repeat once a month */
get_time(NVRAM, &tm_now);
memcpy(&tm, &tm_now, sizeof(struct tm));
tm.tm_mon++;
if (tm.tm_mon == 13) {
tm.tm_mon = 1;
tm.tm_year++;
}
next_time = mktime(&tm);
} else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF2] & 0x80) == 0) {
/* Repeat once a day */
next_time = 24 * 60 * 60 + mktime(&tm_now);
} else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF2] & 0x80) == 0) {
/* Repeat once an hour */
next_time = 60 * 60 + mktime(&tm_now);
} else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF3] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF2] & 0x80) == 0) {
/* Repeat once a minute */
next_time = 60 + mktime(&tm_now);
} else {
/* Repeat once a second */
next_time = 1 + mktime(&tm_now);
}
qemu_mod_timer(NVRAM->alrm_timer, next_time * 1000);
pic_set_irq(NVRAM->IRQ, 0);
}
static void get_alarm (m48t59_t *NVRAM, struct tm *tm)
{
#ifdef _WIN32
memcpy(tm,localtime(&NVRAM->alarm),sizeof(*tm));
#else
localtime_r (&NVRAM->alarm, tm);
#endif
}
static void set_alarm (m48t59_t *NVRAM, struct tm *tm)
{
NVRAM->alarm = mktime(tm);
if (NVRAM->alrm_timer != NULL) {
qemu_del_timer(NVRAM->alrm_timer);
NVRAM->alrm_timer = NULL;
}
if (NVRAM->alarm - time(NULL) > 0)
qemu_mod_timer(NVRAM->alrm_timer, NVRAM->alarm * 1000);
}
/* Watchdog management */
static void watchdog_cb (void *opaque)
{
m48t59_t *NVRAM = opaque;
NVRAM->buffer[0x1FF0] |= 0x80;
if (NVRAM->buffer[0x1FF7] & 0x80) {
NVRAM->buffer[0x1FF7] = 0x00;
NVRAM->buffer[0x1FFC] &= ~0x40;
/* May it be a hw CPU Reset instead ? */
qemu_system_reset_request();
} else {
pic_set_irq(NVRAM->IRQ, 1);
pic_set_irq(NVRAM->IRQ, 0);
}
}
static void set_up_watchdog (m48t59_t *NVRAM, uint8_t value)
{
uint64_t interval; /* in 1/16 seconds */
if (NVRAM->wd_timer != NULL) {
qemu_del_timer(NVRAM->wd_timer);
NVRAM->wd_timer = NULL;
}
NVRAM->buffer[0x1FF0] &= ~0x80;
if (value != 0) {
interval = (1 << (2 * (value & 0x03))) * ((value >> 2) & 0x1F);
qemu_mod_timer(NVRAM->wd_timer, ((uint64_t)time(NULL) * 1000) +
((interval * 1000) >> 4));
}
}
/* Direct access to NVRAM */
void m48t59_write (m48t59_t *NVRAM, uint32_t val)
{
struct tm tm;
int tmp;
if (NVRAM->addr > 0x1FF8 && NVRAM->addr < 0x2000)
NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, NVRAM->addr, val);
switch (NVRAM->addr) {
case 0x1FF0:
/* flags register : read-only */
break;
case 0x1FF1:
/* unused */
break;
case 0x1FF2:
/* alarm seconds */
tmp = fromBCD(val & 0x7F);
if (tmp >= 0 && tmp <= 59) {
get_alarm(NVRAM, &tm);
tm.tm_sec = tmp;
NVRAM->buffer[0x1FF2] = val;
set_alarm(NVRAM, &tm);
}
break;
case 0x1FF3:
/* alarm minutes */
tmp = fromBCD(val & 0x7F);
if (tmp >= 0 && tmp <= 59) {
get_alarm(NVRAM, &tm);
tm.tm_min = tmp;
NVRAM->buffer[0x1FF3] = val;
set_alarm(NVRAM, &tm);
}
break;
case 0x1FF4:
/* alarm hours */
tmp = fromBCD(val & 0x3F);
if (tmp >= 0 && tmp <= 23) {
get_alarm(NVRAM, &tm);
tm.tm_hour = tmp;
NVRAM->buffer[0x1FF4] = val;
set_alarm(NVRAM, &tm);
}
break;
case 0x1FF5:
/* alarm date */
tmp = fromBCD(val & 0x1F);
if (tmp != 0) {
get_alarm(NVRAM, &tm);
tm.tm_mday = tmp;
NVRAM->buffer[0x1FF5] = val;
set_alarm(NVRAM, &tm);
}
break;
case 0x1FF6:
/* interrupts */
NVRAM->buffer[0x1FF6] = val;
break;
case 0x1FF7:
/* watchdog */
NVRAM->buffer[0x1FF7] = val;
set_up_watchdog(NVRAM, val);
break;
case 0x1FF8:
/* control */
NVRAM->buffer[0x1FF8] = (val & ~0xA0) | 0x90;
break;
case 0x1FF9:
/* seconds (BCD) */
tmp = fromBCD(val & 0x7F);
if (tmp >= 0 && tmp <= 59) {
get_time(NVRAM, &tm);
tm.tm_sec = tmp;
set_time(NVRAM, &tm);
}
if ((val & 0x80) ^ (NVRAM->buffer[0x1FF9] & 0x80)) {
if (val & 0x80) {
NVRAM->stop_time = time(NULL);
} else {
NVRAM->time_offset += NVRAM->stop_time - time(NULL);
NVRAM->stop_time = 0;
}
}
NVRAM->buffer[0x1FF9] = val & 0x80;
break;
case 0x1FFA:
/* minutes (BCD) */
tmp = fromBCD(val & 0x7F);
if (tmp >= 0 && tmp <= 59) {
get_time(NVRAM, &tm);
tm.tm_min = tmp;
set_time(NVRAM, &tm);
}
break;
case 0x1FFB:
/* hours (BCD) */
tmp = fromBCD(val & 0x3F);
if (tmp >= 0 && tmp <= 23) {
get_time(NVRAM, &tm);
tm.tm_hour = tmp;
set_time(NVRAM, &tm);
}
break;
case 0x1FFC:
/* day of the week / century */
tmp = fromBCD(val & 0x07);
get_time(NVRAM, &tm);
tm.tm_wday = tmp;
set_time(NVRAM, &tm);
NVRAM->buffer[0x1FFC] = val & 0x40;
break;
case 0x1FFD:
/* date */
tmp = fromBCD(val & 0x1F);
if (tmp != 0) {
get_time(NVRAM, &tm);
tm.tm_mday = tmp;
set_time(NVRAM, &tm);
}
break;
case 0x1FFE:
/* month */
tmp = fromBCD(val & 0x1F);
if (tmp >= 1 && tmp <= 12) {
get_time(NVRAM, &tm);
tm.tm_mon = tmp - 1;
set_time(NVRAM, &tm);
}
break;
case 0x1FFF:
/* year */
tmp = fromBCD(val);
if (tmp >= 0 && tmp <= 99) {
get_time(NVRAM, &tm);
tm.tm_year = fromBCD(val);
set_time(NVRAM, &tm);
}
break;
default:
/* Check lock registers state */
if (NVRAM->addr >= 0x20 && NVRAM->addr <= 0x2F && (NVRAM->lock & 1))
break;
if (NVRAM->addr >= 0x30 && NVRAM->addr <= 0x3F && (NVRAM->lock & 2))
break;
if (NVRAM->addr < 0x1FF0 ||
(NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) {
NVRAM->buffer[NVRAM->addr] = val & 0xFF;
}
break;
}
}
uint32_t m48t59_read (m48t59_t *NVRAM)
{
struct tm tm;
uint32_t retval = 0xFF;
switch (NVRAM->addr) {
case 0x1FF0:
/* flags register */
goto do_read;
case 0x1FF1:
/* unused */
retval = 0;
break;
case 0x1FF2:
/* alarm seconds */
goto do_read;
case 0x1FF3:
/* alarm minutes */
goto do_read;
case 0x1FF4:
/* alarm hours */
goto do_read;
case 0x1FF5:
/* alarm date */
goto do_read;
case 0x1FF6:
/* interrupts */
goto do_read;
case 0x1FF7:
/* A read resets the watchdog */
set_up_watchdog(NVRAM, NVRAM->buffer[0x1FF7]);
goto do_read;
case 0x1FF8:
/* control */
goto do_read;
case 0x1FF9:
/* seconds (BCD) */
get_time(NVRAM, &tm);
retval = (NVRAM->buffer[0x1FF9] & 0x80) | toBCD(tm.tm_sec);
break;
case 0x1FFA:
/* minutes (BCD) */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_min);
break;
case 0x1FFB:
/* hours (BCD) */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_hour);
break;
case 0x1FFC:
/* day of the week / century */
get_time(NVRAM, &tm);
retval = NVRAM->buffer[0x1FFC] | tm.tm_wday;
break;
case 0x1FFD:
/* date */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_mday);
break;
case 0x1FFE:
/* month */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_mon + 1);
break;
case 0x1FFF:
/* year */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_year);
break;
default:
/* Check lock registers state */
if (NVRAM->addr >= 0x20 && NVRAM->addr <= 0x2F && (NVRAM->lock & 1))
break;
if (NVRAM->addr >= 0x30 && NVRAM->addr <= 0x3F && (NVRAM->lock & 2))
break;
if (NVRAM->addr < 0x1FF0 ||
(NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) {
do_read:
retval = NVRAM->buffer[NVRAM->addr];
}
break;
}
if (NVRAM->addr > 0x1FF9 && NVRAM->addr < 0x2000)
NVRAM_PRINTF("0x%08x <= 0x%08x\n", NVRAM->addr, retval);
return retval;
}
void m48t59_set_addr (m48t59_t *NVRAM, uint32_t addr)
{
NVRAM->addr = addr;
}
void m48t59_toggle_lock (m48t59_t *NVRAM, int lock)
{
NVRAM->lock ^= 1 << lock;
}
/* IO access to NVRAM */
static void NVRAM_writeb (void *opaque, uint32_t addr, uint32_t val)
{
m48t59_t *NVRAM = opaque;
addr -= NVRAM->io_base;
NVRAM_PRINTF("0x%08x => 0x%08x\n", addr, val);
switch (addr) {
case 0:
NVRAM->addr &= ~0x00FF;
NVRAM->addr |= val;
break;
case 1:
NVRAM->addr &= ~0xFF00;
NVRAM->addr |= val << 8;
break;
case 3:
m48t59_write(NVRAM, val);
NVRAM->addr = 0x0000;
break;
default:
break;
}
}
static uint32_t NVRAM_readb (void *opaque, uint32_t addr)
{
m48t59_t *NVRAM = opaque;
uint32_t retval;
addr -= NVRAM->io_base;
switch (addr) {
case 3:
retval = m48t59_read(NVRAM);
break;
default:
retval = -1;
break;
}
NVRAM_PRINTF("0x%08x <= 0x%08x\n", addr, retval);
return retval;
}
static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
{
m48t59_t *NVRAM = opaque;
addr -= NVRAM->mem_base;
if (addr < 0x1FF0)
NVRAM->buffer[addr] = value;
}
static void nvram_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
{
m48t59_t *NVRAM = opaque;
addr -= NVRAM->mem_base;
if (addr < 0x1FF0) {
NVRAM->buffer[addr] = value >> 8;
NVRAM->buffer[addr + 1] = value;
}
}
static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
{
m48t59_t *NVRAM = opaque;
addr -= NVRAM->mem_base;
if (addr < 0x1FF0) {
NVRAM->buffer[addr] = value >> 24;
NVRAM->buffer[addr + 1] = value >> 16;
NVRAM->buffer[addr + 2] = value >> 8;
NVRAM->buffer[addr + 3] = value;
}
}
static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
{
m48t59_t *NVRAM = opaque;
uint32_t retval = 0;
addr -= NVRAM->mem_base;
if (addr < 0x1FF0)
retval = NVRAM->buffer[addr];
return retval;
}
static uint32_t nvram_readw (void *opaque, target_phys_addr_t addr)
{
m48t59_t *NVRAM = opaque;
uint32_t retval = 0;
addr -= NVRAM->mem_base;
if (addr < 0x1FF0) {
retval = NVRAM->buffer[addr] << 8;
retval |= NVRAM->buffer[addr + 1];
}
return retval;
}
static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr)
{
m48t59_t *NVRAM = opaque;
uint32_t retval = 0;
addr -= NVRAM->mem_base;
if (addr < 0x1FF0) {
retval = NVRAM->buffer[addr] << 24;
retval |= NVRAM->buffer[addr + 1] << 16;
retval |= NVRAM->buffer[addr + 2] << 8;
retval |= NVRAM->buffer[addr + 3];
}
return retval;
}
static CPUWriteMemoryFunc *nvram_write[] = {
&nvram_writeb,
&nvram_writew,
&nvram_writel,
};
static CPUReadMemoryFunc *nvram_read[] = {
&nvram_readb,
&nvram_readw,
&nvram_readl,
};
/* Initialisation routine */
m48t59_t *m48t59_init (int IRQ, uint32_t mem_base,
uint32_t io_base, uint16_t size)
{
m48t59_t *s;
s = qemu_mallocz(sizeof(m48t59_t));
if (!s)
return NULL;
s->buffer = qemu_mallocz(size);
if (!s->buffer) {
qemu_free(s);
return NULL;
}
s->IRQ = IRQ;
s->size = size;
s->mem_base = mem_base;
s->io_base = io_base;
s->addr = 0;
register_ioport_read(io_base, 0x04, 1, NVRAM_readb, s);
register_ioport_write(io_base, 0x04, 1, NVRAM_writeb, s);
if (mem_base != 0) {
s->mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s);
cpu_register_physical_memory(mem_base, 0x4000, s->mem_index);
}
s->alrm_timer = qemu_new_timer(vm_clock, &alarm_cb, s);
s->wd_timer = qemu_new_timer(vm_clock, &watchdog_cb, s);
s->lock = 0;
return s;
}

13
hw/m48t59.h Normal file
View File

@@ -0,0 +1,13 @@
#if !defined (__M48T59_H__)
#define __M48T59_H__
typedef struct m48t59_t m48t59_t;
void m48t59_write (m48t59_t *NVRAM, uint32_t val);
uint32_t m48t59_read (m48t59_t *NVRAM);
void m48t59_set_addr (m48t59_t *NVRAM, uint32_t addr);
void m48t59_toggle_lock (m48t59_t *NVRAM, int lock);
m48t59_t *m48t59_init (int IRQ, uint32_t io_base,
uint32_t mem_base, uint16_t size);
#endif /* !defined (__M48T59_H__) */

326
hw/magic-load.c Normal file
View File

@@ -0,0 +1,326 @@
#include "vl.h"
#include "disas.h"
#define ELF_CLASS ELFCLASS32
#define ELF_DATA ELFDATA2MSB
#define ELF_ARCH EM_SPARC
#include "elf.h"
#ifdef BSWAP_NEEDED
static void bswap_ehdr(Elf32_Ehdr *ehdr)
{
bswap16s(&ehdr->e_type); /* Object file type */
bswap16s(&ehdr->e_machine); /* Architecture */
bswap32s(&ehdr->e_version); /* Object file version */
bswap32s(&ehdr->e_entry); /* Entry point virtual address */
bswap32s(&ehdr->e_phoff); /* Program header table file offset */
bswap32s(&ehdr->e_shoff); /* Section header table file offset */
bswap32s(&ehdr->e_flags); /* Processor-specific flags */
bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
bswap16s(&ehdr->e_phnum); /* Program header table entry count */
bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
bswap16s(&ehdr->e_shnum); /* Section header table entry count */
bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
}
static void bswap_phdr(Elf32_Phdr *phdr)
{
bswap32s(&phdr->p_type); /* Segment type */
bswap32s(&phdr->p_offset); /* Segment file offset */
bswap32s(&phdr->p_vaddr); /* Segment virtual address */
bswap32s(&phdr->p_paddr); /* Segment physical address */
bswap32s(&phdr->p_filesz); /* Segment size in file */
bswap32s(&phdr->p_memsz); /* Segment size in memory */
bswap32s(&phdr->p_flags); /* Segment flags */
bswap32s(&phdr->p_align); /* Segment alignment */
}
static void bswap_shdr(Elf32_Shdr *shdr)
{
bswap32s(&shdr->sh_name);
bswap32s(&shdr->sh_type);
bswap32s(&shdr->sh_flags);
bswap32s(&shdr->sh_addr);
bswap32s(&shdr->sh_offset);
bswap32s(&shdr->sh_size);
bswap32s(&shdr->sh_link);
bswap32s(&shdr->sh_info);
bswap32s(&shdr->sh_addralign);
bswap32s(&shdr->sh_entsize);
}
static void bswap_sym(Elf32_Sym *sym)
{
bswap32s(&sym->st_name);
bswap32s(&sym->st_value);
bswap32s(&sym->st_size);
bswap16s(&sym->st_shndx);
}
#else
#define bswap_ehdr(e) do { } while (0)
#define bswap_phdr(e) do { } while (0)
#define bswap_shdr(e) do { } while (0)
#define bswap_sym(e) do { } while (0)
#endif
static int find_phdr(struct elfhdr *ehdr, int fd, struct elf_phdr *phdr, uint32_t type)
{
int i, retval;
retval = lseek(fd, ehdr->e_phoff, SEEK_SET);
if (retval < 0)
return -1;
for (i = 0; i < ehdr->e_phnum; i++) {
retval = read(fd, phdr, sizeof(*phdr));
if (retval < 0)
return -1;
bswap_phdr(phdr);
if (phdr->p_type == type)
return 0;
}
return -1;
}
static void *find_shdr(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, uint32_t type)
{
int i, retval;
retval = lseek(fd, ehdr->e_shoff, SEEK_SET);
if (retval < 0)
return NULL;
for (i = 0; i < ehdr->e_shnum; i++) {
retval = read(fd, shdr, sizeof(*shdr));
if (retval < 0)
return NULL;
bswap_shdr(shdr);
if (shdr->sh_type == type)
return qemu_malloc(shdr->sh_size);
}
return NULL;
}
static int find_strtab(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
{
int retval;
retval = lseek(fd, ehdr->e_shoff + sizeof(struct elf_shdr) * symtab->sh_link, SEEK_SET);
if (retval < 0)
return -1;
retval = read(fd, shdr, sizeof(*shdr));
if (retval < 0)
return -1;
bswap_shdr(shdr);
if (shdr->sh_type == SHT_STRTAB)
return qemu_malloc(shdr->sh_size);;
return 0;
}
static int read_program(int fd, struct elf_phdr *phdr, void *dst)
{
int retval;
retval = lseek(fd, 0x4000, SEEK_SET);
if (retval < 0)
return -1;
return read(fd, dst, phdr->p_filesz);
}
static int read_section(int fd, struct elf_shdr *s, void *dst)
{
int retval;
retval = lseek(fd, s->sh_offset, SEEK_SET);
if (retval < 0)
return -1;
retval = read(fd, dst, s->sh_size);
if (retval < 0)
return -1;
return 0;
}
static void *process_section(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, uint32_t type)
{
void *dst;
dst = find_shdr(ehdr, fd, shdr, type);
if (!dst)
goto error;
if (read_section(fd, shdr, dst))
goto error;
return dst;
error:
qemu_free(dst);
return NULL;
}
static void *process_strtab(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
{
void *dst;
dst = find_strtab(ehdr, fd, shdr, symtab);
if (!dst)
goto error;
if (read_section(fd, shdr, dst))
goto error;
return dst;
error:
qemu_free(dst);
return NULL;
}
static void load_symbols(struct elfhdr *ehdr, int fd)
{
struct elf_shdr symtab, strtab;
struct elf_sym *syms;
int nsyms, i;
char *str;
/* Symbol table */
syms = process_section(ehdr, fd, &symtab, SHT_SYMTAB);
if (!syms)
return;
nsyms = symtab.sh_size / sizeof(struct elf_sym);
for (i = 0; i < nsyms; i++)
bswap_sym(&syms[i]);
/* String table */
str = process_strtab(ehdr, fd, &strtab, &symtab);
if (!str)
goto error_freesyms;
/* Commit */
if (disas_symtab)
qemu_free(disas_symtab); /* XXX Merge with old symbols? */
if (disas_strtab)
qemu_free(disas_strtab);
disas_symtab = syms;
disas_num_syms = nsyms;
disas_strtab = str;
return;
error_freesyms:
qemu_free(syms);
return;
}
int load_elf(const char * filename, uint8_t *addr)
{
struct elfhdr ehdr;
struct elf_phdr phdr;
int retval, fd;
fd = open(filename, O_RDONLY | O_BINARY);
if (fd < 0)
goto error;
retval = read(fd, &ehdr, sizeof(ehdr));
if (retval < 0)
goto error;
bswap_ehdr(&ehdr);
if (ehdr.e_ident[0] != 0x7f || ehdr.e_ident[1] != 'E'
|| ehdr.e_ident[2] != 'L' || ehdr.e_ident[3] != 'F'
|| ehdr.e_machine != EM_SPARC)
goto error;
if (find_phdr(&ehdr, fd, &phdr, PT_LOAD))
goto error;
retval = read_program(fd, &phdr, addr);
if (retval < 0)
goto error;
load_symbols(&ehdr, fd);
close(fd);
return retval;
error:
close(fd);
return -1;
}
int load_kernel(const char *filename, uint8_t *addr)
{
int fd, size;
fd = open(filename, O_RDONLY | O_BINARY);
if (fd < 0)
return -1;
/* load 32 bit code */
size = read(fd, addr, 16 * 1024 * 1024);
if (size < 0)
goto fail;
close(fd);
return size;
fail:
close(fd);
return -1;
}
typedef struct MAGICState {
uint32_t addr;
uint32_t saved_addr;
int magic_state;
char saved_kfn[1024];
} MAGICState;
static uint32_t magic_mem_readl(void *opaque, target_phys_addr_t addr)
{
int ret;
MAGICState *s = opaque;
if (s->magic_state == 0) {
ret = load_elf(s->saved_kfn, (uint8_t *)s->saved_addr);
if (ret < 0)
ret = load_kernel(s->saved_kfn, (uint8_t *)s->saved_addr);
if (ret < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
s->saved_kfn);
}
s->magic_state = 1; /* No more magic */
tb_flush();
return bswap32(ret);
}
return 0;
}
static void magic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
}
static CPUReadMemoryFunc *magic_mem_read[3] = {
magic_mem_readl,
magic_mem_readl,
magic_mem_readl,
};
static CPUWriteMemoryFunc *magic_mem_write[3] = {
magic_mem_writel,
magic_mem_writel,
magic_mem_writel,
};
void magic_init(const char *kfn, int kloadaddr, uint32_t addr)
{
int magic_io_memory;
MAGICState *s;
s = qemu_mallocz(sizeof(MAGICState));
if (!s)
return;
strcpy(s->saved_kfn, kfn);
s->saved_addr = kloadaddr;
s->magic_state = 0;
s->addr = addr;
magic_io_memory = cpu_register_io_memory(0, magic_mem_read, magic_mem_write, s);
cpu_register_physical_memory(addr, 4, magic_io_memory);
}

463
hw/mc146818rtc.c Normal file
View File

@@ -0,0 +1,463 @@
/*
* QEMU MC146818 RTC emulation
*
* Copyright (c) 2003-2004 Fabrice Bellard
*
* 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 "vl.h"
//#define DEBUG_CMOS
#define RTC_SECONDS 0
#define RTC_SECONDS_ALARM 1
#define RTC_MINUTES 2
#define RTC_MINUTES_ALARM 3
#define RTC_HOURS 4
#define RTC_HOURS_ALARM 5
#define RTC_ALARM_DONT_CARE 0xC0
#define RTC_DAY_OF_WEEK 6
#define RTC_DAY_OF_MONTH 7
#define RTC_MONTH 8
#define RTC_YEAR 9
#define RTC_REG_A 10
#define RTC_REG_B 11
#define RTC_REG_C 12
#define RTC_REG_D 13
#define REG_A_UIP 0x80
#define REG_B_SET 0x80
#define REG_B_PIE 0x40
#define REG_B_AIE 0x20
#define REG_B_UIE 0x10
struct RTCState {
uint8_t cmos_data[128];
uint8_t cmos_index;
struct tm current_tm;
int irq;
/* periodic timer */
QEMUTimer *periodic_timer;
int64_t next_periodic_time;
/* second update */
int64_t next_second_time;
QEMUTimer *second_timer;
QEMUTimer *second_timer2;
};
static void rtc_set_time(RTCState *s);
static void rtc_copy_date(RTCState *s);
static void rtc_timer_update(RTCState *s, int64_t current_time)
{
int period_code, period;
int64_t cur_clock, next_irq_clock;
period_code = s->cmos_data[RTC_REG_A] & 0x0f;
if (period_code != 0 &&
(s->cmos_data[RTC_REG_B] & REG_B_PIE)) {
if (period_code <= 2)
period_code += 7;
/* period in 32 Khz cycles */
period = 1 << (period_code - 1);
/* compute 32 khz clock */
cur_clock = muldiv64(current_time, 32768, ticks_per_sec);
next_irq_clock = (cur_clock & ~(period - 1)) + period;
s->next_periodic_time = muldiv64(next_irq_clock, ticks_per_sec, 32768) + 1;
qemu_mod_timer(s->periodic_timer, s->next_periodic_time);
} else {
qemu_del_timer(s->periodic_timer);
}
}
static void rtc_periodic_timer(void *opaque)
{
RTCState *s = opaque;
rtc_timer_update(s, s->next_periodic_time);
s->cmos_data[RTC_REG_C] |= 0xc0;
pic_set_irq(s->irq, 1);
}
static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
{
RTCState *s = opaque;
if ((addr & 1) == 0) {
s->cmos_index = data & 0x7f;
} else {
#ifdef DEBUG_CMOS
printf("cmos: write index=0x%02x val=0x%02x\n",
s->cmos_index, data);
#endif
switch(s->cmos_index) {
case RTC_SECONDS_ALARM:
case RTC_MINUTES_ALARM:
case RTC_HOURS_ALARM:
/* XXX: not supported */
s->cmos_data[s->cmos_index] = data;
break;
case RTC_SECONDS:
case RTC_MINUTES:
case RTC_HOURS:
case RTC_DAY_OF_WEEK:
case RTC_DAY_OF_MONTH:
case RTC_MONTH:
case RTC_YEAR:
s->cmos_data[s->cmos_index] = data;
/* if in set mode, do not update the time */
if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
rtc_set_time(s);
}
break;
case RTC_REG_A:
/* UIP bit is read only */
s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
(s->cmos_data[RTC_REG_A] & REG_A_UIP);
rtc_timer_update(s, qemu_get_clock(vm_clock));
break;
case RTC_REG_B:
if (data & REG_B_SET) {
/* set mode: reset UIP mode */
s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
data &= ~REG_B_UIE;
} else {
/* if disabling set mode, update the time */
if (s->cmos_data[RTC_REG_B] & REG_B_SET) {
rtc_set_time(s);
}
}
s->cmos_data[RTC_REG_B] = data;
rtc_timer_update(s, qemu_get_clock(vm_clock));
break;
case RTC_REG_C:
case RTC_REG_D:
/* cannot write to them */
break;
default:
s->cmos_data[s->cmos_index] = data;
break;
}
}
}
static inline int to_bcd(RTCState *s, int a)
{
if (s->cmos_data[RTC_REG_B] & 0x04) {
return a;
} else {
return ((a / 10) << 4) | (a % 10);
}
}
static inline int from_bcd(RTCState *s, int a)
{
if (s->cmos_data[RTC_REG_B] & 0x04) {
return a;
} else {
return ((a >> 4) * 10) + (a & 0x0f);
}
}
static void rtc_set_time(RTCState *s)
{
struct tm *tm = &s->current_tm;
tm->tm_sec = from_bcd(s, s->cmos_data[RTC_SECONDS]);
tm->tm_min = from_bcd(s, s->cmos_data[RTC_MINUTES]);
tm->tm_hour = from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
if (!(s->cmos_data[RTC_REG_B] & 0x02) &&
(s->cmos_data[RTC_HOURS] & 0x80)) {
tm->tm_hour += 12;
}
tm->tm_wday = from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]);
tm->tm_mday = from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
tm->tm_mon = from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
tm->tm_year = from_bcd(s, s->cmos_data[RTC_YEAR]) + 100;
}
static void rtc_copy_date(RTCState *s)
{
const struct tm *tm = &s->current_tm;
s->cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec);
s->cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min);
if (s->cmos_data[RTC_REG_B] & 0x02) {
/* 24 hour format */
s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour);
} else {
/* 12 hour format */
s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour % 12);
if (tm->tm_hour >= 12)
s->cmos_data[RTC_HOURS] |= 0x80;
}
s->cmos_data[RTC_DAY_OF_WEEK] = to_bcd(s, tm->tm_wday);
s->cmos_data[RTC_DAY_OF_MONTH] = to_bcd(s, tm->tm_mday);
s->cmos_data[RTC_MONTH] = to_bcd(s, tm->tm_mon + 1);
s->cmos_data[RTC_YEAR] = to_bcd(s, tm->tm_year % 100);
}
/* month is between 0 and 11. */
static int get_days_in_month(int month, int year)
{
static const int days_tab[12] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
int d;
if ((unsigned )month >= 12)
return 31;
d = days_tab[month];
if (month == 1) {
if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0))
d++;
}
return d;
}
/* update 'tm' to the next second */
static void rtc_next_second(struct tm *tm)
{
int days_in_month;
tm->tm_sec++;
if ((unsigned)tm->tm_sec >= 60) {
tm->tm_sec = 0;
tm->tm_min++;
if ((unsigned)tm->tm_min >= 60) {
tm->tm_min = 0;
tm->tm_hour++;
if ((unsigned)tm->tm_hour >= 24) {
tm->tm_hour = 0;
/* next day */
tm->tm_wday++;
if ((unsigned)tm->tm_wday >= 7)
tm->tm_wday = 0;
days_in_month = get_days_in_month(tm->tm_mon,
tm->tm_year + 1900);
tm->tm_mday++;
if (tm->tm_mday < 1) {
tm->tm_mday = 1;
} else if (tm->tm_mday > days_in_month) {
tm->tm_mday = 1;
tm->tm_mon++;
if (tm->tm_mon >= 12) {
tm->tm_mon = 0;
tm->tm_year++;
}
}
}
}
}
}
static void rtc_update_second(void *opaque)
{
RTCState *s = opaque;
int64_t delay;
/* if the oscillator is not in normal operation, we do not update */
if ((s->cmos_data[RTC_REG_A] & 0x70) != 0x20) {
s->next_second_time += ticks_per_sec;
qemu_mod_timer(s->second_timer, s->next_second_time);
} else {
rtc_next_second(&s->current_tm);
if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
/* update in progress bit */
s->cmos_data[RTC_REG_A] |= REG_A_UIP;
}
/* should be 244 us = 8 / 32768 seconds, but currently the
timers do not have the necessary resolution. */
delay = (ticks_per_sec * 1) / 100;
if (delay < 1)
delay = 1;
qemu_mod_timer(s->second_timer2,
s->next_second_time + delay);
}
}
static void rtc_update_second2(void *opaque)
{
RTCState *s = opaque;
if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
rtc_copy_date(s);
}
/* check alarm */
if (s->cmos_data[RTC_REG_B] & REG_B_AIE) {
if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 ||
s->cmos_data[RTC_SECONDS_ALARM] == s->current_tm.tm_sec) &&
((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 ||
s->cmos_data[RTC_MINUTES_ALARM] == s->current_tm.tm_mon) &&
((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 ||
s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) {
s->cmos_data[RTC_REG_C] |= 0xa0;
pic_set_irq(s->irq, 1);
}
}
/* update ended interrupt */
if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
s->cmos_data[RTC_REG_C] |= 0x90;
pic_set_irq(s->irq, 1);
}
/* clear update in progress bit */
s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
s->next_second_time += ticks_per_sec;
qemu_mod_timer(s->second_timer, s->next_second_time);
}
static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
{
RTCState *s = opaque;
int ret;
if ((addr & 1) == 0) {
return 0xff;
} else {
switch(s->cmos_index) {
case RTC_SECONDS:
case RTC_MINUTES:
case RTC_HOURS:
case RTC_DAY_OF_WEEK:
case RTC_DAY_OF_MONTH:
case RTC_MONTH:
case RTC_YEAR:
ret = s->cmos_data[s->cmos_index];
break;
case RTC_REG_A:
ret = s->cmos_data[s->cmos_index];
break;
case RTC_REG_C:
ret = s->cmos_data[s->cmos_index];
pic_set_irq(s->irq, 0);
s->cmos_data[RTC_REG_C] = 0x00;
break;
default:
ret = s->cmos_data[s->cmos_index];
break;
}
#ifdef DEBUG_CMOS
printf("cmos: read index=0x%02x val=0x%02x\n",
s->cmos_index, ret);
#endif
return ret;
}
}
void rtc_set_memory(RTCState *s, int addr, int val)
{
if (addr >= 0 && addr <= 127)
s->cmos_data[addr] = val;
}
void rtc_set_date(RTCState *s, const struct tm *tm)
{
s->current_tm = *tm;
rtc_copy_date(s);
}
static void rtc_save(QEMUFile *f, void *opaque)
{
RTCState *s = opaque;
qemu_put_buffer(f, s->cmos_data, 128);
qemu_put_8s(f, &s->cmos_index);
qemu_put_be32s(f, &s->current_tm.tm_sec);
qemu_put_be32s(f, &s->current_tm.tm_min);
qemu_put_be32s(f, &s->current_tm.tm_hour);
qemu_put_be32s(f, &s->current_tm.tm_wday);
qemu_put_be32s(f, &s->current_tm.tm_mday);
qemu_put_be32s(f, &s->current_tm.tm_mon);
qemu_put_be32s(f, &s->current_tm.tm_year);
qemu_put_timer(f, s->periodic_timer);
qemu_put_be64s(f, &s->next_periodic_time);
qemu_put_be64s(f, &s->next_second_time);
qemu_put_timer(f, s->second_timer);
qemu_put_timer(f, s->second_timer2);
}
static int rtc_load(QEMUFile *f, void *opaque, int version_id)
{
RTCState *s = opaque;
if (version_id != 1)
return -EINVAL;
qemu_get_buffer(f, s->cmos_data, 128);
qemu_get_8s(f, &s->cmos_index);
qemu_get_be32s(f, &s->current_tm.tm_sec);
qemu_get_be32s(f, &s->current_tm.tm_min);
qemu_get_be32s(f, &s->current_tm.tm_hour);
qemu_get_be32s(f, &s->current_tm.tm_wday);
qemu_get_be32s(f, &s->current_tm.tm_mday);
qemu_get_be32s(f, &s->current_tm.tm_mon);
qemu_get_be32s(f, &s->current_tm.tm_year);
qemu_get_timer(f, s->periodic_timer);
qemu_get_be64s(f, &s->next_periodic_time);
qemu_get_be64s(f, &s->next_second_time);
qemu_get_timer(f, s->second_timer);
qemu_get_timer(f, s->second_timer2);
return 0;
}
RTCState *rtc_init(int base, int irq)
{
RTCState *s;
s = qemu_mallocz(sizeof(RTCState));
if (!s)
return NULL;
s->irq = irq;
s->cmos_data[RTC_REG_A] = 0x26;
s->cmos_data[RTC_REG_B] = 0x02;
s->cmos_data[RTC_REG_C] = 0x00;
s->cmos_data[RTC_REG_D] = 0x80;
s->periodic_timer = qemu_new_timer(vm_clock,
rtc_periodic_timer, s);
s->second_timer = qemu_new_timer(vm_clock,
rtc_update_second, s);
s->second_timer2 = qemu_new_timer(vm_clock,
rtc_update_second2, s);
s->next_second_time = qemu_get_clock(vm_clock) + (ticks_per_sec * 99) / 100;
qemu_mod_timer(s->second_timer2, s->next_second_time);
register_ioport_write(base, 2, 1, cmos_ioport_write, s);
register_ioport_read(base, 2, 1, cmos_ioport_read, s);
register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s);
return s;
}

684
hw/ne2000.c Normal file
View File

@@ -0,0 +1,684 @@
/*
* QEMU NE2000 emulation
*
* Copyright (c) 2003-2004 Fabrice Bellard
*
* 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 "vl.h"
/* debug NE2000 card */
//#define DEBUG_NE2000
#define MAX_ETH_FRAME_SIZE 1514
#define E8390_CMD 0x00 /* The command register (for all pages) */
/* Page 0 register offsets. */
#define EN0_CLDALO 0x01 /* Low byte of current local dma addr RD */
#define EN0_STARTPG 0x01 /* Starting page of ring bfr WR */
#define EN0_CLDAHI 0x02 /* High byte of current local dma addr RD */
#define EN0_STOPPG 0x02 /* Ending page +1 of ring bfr WR */
#define EN0_BOUNDARY 0x03 /* Boundary page of ring bfr RD WR */
#define EN0_TSR 0x04 /* Transmit status reg RD */
#define EN0_TPSR 0x04 /* Transmit starting page WR */
#define EN0_NCR 0x05 /* Number of collision reg RD */
#define EN0_TCNTLO 0x05 /* Low byte of tx byte count WR */
#define EN0_FIFO 0x06 /* FIFO RD */
#define EN0_TCNTHI 0x06 /* High byte of tx byte count WR */
#define EN0_ISR 0x07 /* Interrupt status reg RD WR */
#define EN0_CRDALO 0x08 /* low byte of current remote dma address RD */
#define EN0_RSARLO 0x08 /* Remote start address reg 0 */
#define EN0_CRDAHI 0x09 /* high byte, current remote dma address RD */
#define EN0_RSARHI 0x09 /* Remote start address reg 1 */
#define EN0_RCNTLO 0x0a /* Remote byte count reg WR */
#define EN0_RCNTHI 0x0b /* Remote byte count reg WR */
#define EN0_RSR 0x0c /* rx status reg RD */
#define EN0_RXCR 0x0c /* RX configuration reg WR */
#define EN0_TXCR 0x0d /* TX configuration reg WR */
#define EN0_COUNTER0 0x0d /* Rcv alignment error counter RD */
#define EN0_DCFG 0x0e /* Data configuration reg WR */
#define EN0_COUNTER1 0x0e /* Rcv CRC error counter RD */
#define EN0_IMR 0x0f /* Interrupt mask reg WR */
#define EN0_COUNTER2 0x0f /* Rcv missed frame error counter RD */
#define EN1_PHYS 0x11
#define EN1_CURPAG 0x17
#define EN1_MULT 0x18
/* Register accessed at EN_CMD, the 8390 base addr. */
#define E8390_STOP 0x01 /* Stop and reset the chip */
#define E8390_START 0x02 /* Start the chip, clear reset */
#define E8390_TRANS 0x04 /* Transmit a frame */
#define E8390_RREAD 0x08 /* Remote read */
#define E8390_RWRITE 0x10 /* Remote write */
#define E8390_NODMA 0x20 /* Remote DMA */
#define E8390_PAGE0 0x00 /* Select page chip registers */
#define E8390_PAGE1 0x40 /* using the two high-order bits */
#define E8390_PAGE2 0x80 /* Page 3 is invalid. */
/* Bits in EN0_ISR - Interrupt status register */
#define ENISR_RX 0x01 /* Receiver, no error */
#define ENISR_TX 0x02 /* Transmitter, no error */
#define ENISR_RX_ERR 0x04 /* Receiver, with error */
#define ENISR_TX_ERR 0x08 /* Transmitter, with error */
#define ENISR_OVER 0x10 /* Receiver overwrote the ring */
#define ENISR_COUNTERS 0x20 /* Counters need emptying */
#define ENISR_RDC 0x40 /* remote dma complete */
#define ENISR_RESET 0x80 /* Reset completed */
#define ENISR_ALL 0x3f /* Interrupts we will enable */
/* Bits in received packet status byte and EN0_RSR*/
#define ENRSR_RXOK 0x01 /* Received a good packet */
#define ENRSR_CRC 0x02 /* CRC error */
#define ENRSR_FAE 0x04 /* frame alignment error */
#define ENRSR_FO 0x08 /* FIFO overrun */
#define ENRSR_MPA 0x10 /* missed pkt */
#define ENRSR_PHY 0x20 /* physical/multicast address */
#define ENRSR_DIS 0x40 /* receiver disable. set in monitor mode */
#define ENRSR_DEF 0x80 /* deferring */
/* Transmitted packet status, EN0_TSR. */
#define ENTSR_PTX 0x01 /* Packet transmitted without error */
#define ENTSR_ND 0x02 /* The transmit wasn't deferred. */
#define ENTSR_COL 0x04 /* The transmit collided at least once. */
#define ENTSR_ABT 0x08 /* The transmit collided 16 times, and was deferred. */
#define ENTSR_CRS 0x10 /* The carrier sense was lost. */
#define ENTSR_FU 0x20 /* A "FIFO underrun" occurred during transmit. */
#define ENTSR_CDH 0x40 /* The collision detect "heartbeat" signal was lost. */
#define ENTSR_OWC 0x80 /* There was an out-of-window collision. */
#define NE2000_PMEM_SIZE (32*1024)
#define NE2000_PMEM_START (16*1024)
#define NE2000_PMEM_END (NE2000_PMEM_SIZE+NE2000_PMEM_START)
#define NE2000_MEM_SIZE NE2000_PMEM_END
typedef struct NE2000State {
uint8_t cmd;
uint32_t start;
uint32_t stop;
uint8_t boundary;
uint8_t tsr;
uint8_t tpsr;
uint16_t tcnt;
uint16_t rcnt;
uint32_t rsar;
uint8_t rsr;
uint8_t isr;
uint8_t dcfg;
uint8_t imr;
uint8_t phys[6]; /* mac address */
uint8_t curpag;
uint8_t mult[8]; /* multicast mask array */
int irq;
PCIDevice *pci_dev;
NetDriverState *nd;
uint8_t mem[NE2000_MEM_SIZE];
} NE2000State;
static void ne2000_reset(NE2000State *s)
{
int i;
s->isr = ENISR_RESET;
memcpy(s->mem, s->nd->macaddr, 6);
s->mem[14] = 0x57;
s->mem[15] = 0x57;
/* duplicate prom data */
for(i = 15;i >= 0; i--) {
s->mem[2 * i] = s->mem[i];
s->mem[2 * i + 1] = s->mem[i];
}
}
static void ne2000_update_irq(NE2000State *s)
{
int isr;
isr = s->isr & s->imr;
#if defined(DEBUG_NE2000)
printf("NE2000: Set IRQ line %d to %d (%02x %02x)\n",
s->irq, isr ? 1 : 0, s->isr, s->imr);
#endif
if (s->irq == 16) {
/* PCI irq */
pci_set_irq(s->pci_dev, 0, (isr != 0));
} else {
/* ISA irq */
pic_set_irq(s->irq, (isr != 0));
}
}
/* return the max buffer size if the NE2000 can receive more data */
static int ne2000_can_receive(void *opaque)
{
NE2000State *s = opaque;
int avail, index, boundary;
if (s->cmd & E8390_STOP)
return 0;
index = s->curpag << 8;
boundary = s->boundary << 8;
if (index < boundary)
avail = boundary - index;
else
avail = (s->stop - s->start) - (index - boundary);
if (avail < (MAX_ETH_FRAME_SIZE + 4))
return 0;
return MAX_ETH_FRAME_SIZE;
}
#define MIN_BUF_SIZE 60
static void ne2000_receive(void *opaque, const uint8_t *buf, int size)
{
NE2000State *s = opaque;
uint8_t *p;
int total_len, next, avail, len, index;
uint8_t buf1[60];
#if defined(DEBUG_NE2000)
printf("NE2000: received len=%d\n", size);
#endif
/* if too small buffer, then expand it */
if (size < MIN_BUF_SIZE) {
memcpy(buf1, buf, size);
memset(buf1 + size, 0, MIN_BUF_SIZE - size);
buf = buf1;
size = MIN_BUF_SIZE;
}
index = s->curpag << 8;
/* 4 bytes for header */
total_len = size + 4;
/* address for next packet (4 bytes for CRC) */
next = index + ((total_len + 4 + 255) & ~0xff);
if (next >= s->stop)
next -= (s->stop - s->start);
/* prepare packet header */
p = s->mem + index;
s->rsr = ENRSR_RXOK; /* receive status */
/* XXX: check this */
if (buf[0] & 0x01)
s->rsr |= ENRSR_PHY;
p[0] = s->rsr;
p[1] = next >> 8;
p[2] = total_len;
p[3] = total_len >> 8;
index += 4;
/* write packet data */
while (size > 0) {
avail = s->stop - index;
len = size;
if (len > avail)
len = avail;
memcpy(s->mem + index, buf, len);
buf += len;
index += len;
if (index == s->stop)
index = s->start;
size -= len;
}
s->curpag = next >> 8;
/* now we can signal we have receive something */
s->isr |= ENISR_RX;
ne2000_update_irq(s);
}
static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
NE2000State *s = opaque;
int offset, page;
addr &= 0xf;
#ifdef DEBUG_NE2000
printf("NE2000: write addr=0x%x val=0x%02x\n", addr, val);
#endif
if (addr == E8390_CMD) {
/* control register */
s->cmd = val;
if (val & E8390_START) {
s->isr &= ~ENISR_RESET;
/* test specific case: zero length transfert */
if ((val & (E8390_RREAD | E8390_RWRITE)) &&
s->rcnt == 0) {
s->isr |= ENISR_RDC;
ne2000_update_irq(s);
}
if (val & E8390_TRANS) {
qemu_send_packet(s->nd, s->mem + (s->tpsr << 8), s->tcnt);
/* signal end of transfert */
s->tsr = ENTSR_PTX;
s->isr |= ENISR_TX;
ne2000_update_irq(s);
}
}
} else {
page = s->cmd >> 6;
offset = addr | (page << 4);
switch(offset) {
case EN0_STARTPG:
s->start = val << 8;
break;
case EN0_STOPPG:
s->stop = val << 8;
break;
case EN0_BOUNDARY:
s->boundary = val;
break;
case EN0_IMR:
s->imr = val;
ne2000_update_irq(s);
break;
case EN0_TPSR:
s->tpsr = val;
break;
case EN0_TCNTLO:
s->tcnt = (s->tcnt & 0xff00) | val;
break;
case EN0_TCNTHI:
s->tcnt = (s->tcnt & 0x00ff) | (val << 8);
break;
case EN0_RSARLO:
s->rsar = (s->rsar & 0xff00) | val;
break;
case EN0_RSARHI:
s->rsar = (s->rsar & 0x00ff) | (val << 8);
break;
case EN0_RCNTLO:
s->rcnt = (s->rcnt & 0xff00) | val;
break;
case EN0_RCNTHI:
s->rcnt = (s->rcnt & 0x00ff) | (val << 8);
break;
case EN0_DCFG:
s->dcfg = val;
break;
case EN0_ISR:
s->isr &= ~(val & 0x7f);
ne2000_update_irq(s);
break;
case EN1_PHYS ... EN1_PHYS + 5:
s->phys[offset - EN1_PHYS] = val;
break;
case EN1_CURPAG:
s->curpag = val;
break;
case EN1_MULT ... EN1_MULT + 7:
s->mult[offset - EN1_MULT] = val;
break;
}
}
}
static uint32_t ne2000_ioport_read(void *opaque, uint32_t addr)
{
NE2000State *s = opaque;
int offset, page, ret;
addr &= 0xf;
if (addr == E8390_CMD) {
ret = s->cmd;
} else {
page = s->cmd >> 6;
offset = addr | (page << 4);
switch(offset) {
case EN0_TSR:
ret = s->tsr;
break;
case EN0_BOUNDARY:
ret = s->boundary;
break;
case EN0_ISR:
ret = s->isr;
break;
case EN0_RSARLO:
ret = s->rsar & 0x00ff;
break;
case EN0_RSARHI:
ret = s->rsar >> 8;
break;
case EN1_PHYS ... EN1_PHYS + 5:
ret = s->phys[offset - EN1_PHYS];
break;
case EN1_CURPAG:
ret = s->curpag;
break;
case EN1_MULT ... EN1_MULT + 7:
ret = s->mult[offset - EN1_MULT];
break;
case EN0_RSR:
ret = s->rsr;
break;
default:
ret = 0x00;
break;
}
}
#ifdef DEBUG_NE2000
printf("NE2000: read addr=0x%x val=%02x\n", addr, ret);
#endif
return ret;
}
static inline void ne2000_mem_writeb(NE2000State *s, uint32_t addr,
uint32_t val)
{
if (addr < 32 ||
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
s->mem[addr] = val;
}
}
static inline void ne2000_mem_writew(NE2000State *s, uint32_t addr,
uint32_t val)
{
addr &= ~1; /* XXX: check exact behaviour if not even */
if (addr < 32 ||
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
*(uint16_t *)(s->mem + addr) = cpu_to_le16(val);
}
}
static inline void ne2000_mem_writel(NE2000State *s, uint32_t addr,
uint32_t val)
{
addr &= ~1; /* XXX: check exact behaviour if not even */
if (addr < 32 ||
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
cpu_to_le32wu((uint32_t *)(s->mem + addr), val);
}
}
static inline uint32_t ne2000_mem_readb(NE2000State *s, uint32_t addr)
{
if (addr < 32 ||
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
return s->mem[addr];
} else {
return 0xff;
}
}
static inline uint32_t ne2000_mem_readw(NE2000State *s, uint32_t addr)
{
addr &= ~1; /* XXX: check exact behaviour if not even */
if (addr < 32 ||
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
return le16_to_cpu(*(uint16_t *)(s->mem + addr));
} else {
return 0xffff;
}
}
static inline uint32_t ne2000_mem_readl(NE2000State *s, uint32_t addr)
{
addr &= ~1; /* XXX: check exact behaviour if not even */
if (addr < 32 ||
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
return le32_to_cpupu((uint32_t *)(s->mem + addr));
} else {
return 0xffffffff;
}
}
static inline void ne2000_dma_update(NE2000State *s, int len)
{
s->rsar += len;
/* wrap */
/* XXX: check what to do if rsar > stop */
if (s->rsar == s->stop)
s->rsar = s->start;
if (s->rcnt <= len) {
s->rcnt = 0;
/* signal end of transfert */
s->isr |= ENISR_RDC;
ne2000_update_irq(s);
} else {
s->rcnt -= len;
}
}
static void ne2000_asic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
NE2000State *s = opaque;
#ifdef DEBUG_NE2000
printf("NE2000: asic write val=0x%04x\n", val);
#endif
if (s->rcnt == 0)
return;
if (s->dcfg & 0x01) {
/* 16 bit access */
ne2000_mem_writew(s, s->rsar, val);
ne2000_dma_update(s, 2);
} else {
/* 8 bit access */
ne2000_mem_writeb(s, s->rsar, val);
ne2000_dma_update(s, 1);
}
}
static uint32_t ne2000_asic_ioport_read(void *opaque, uint32_t addr)
{
NE2000State *s = opaque;
int ret;
if (s->dcfg & 0x01) {
/* 16 bit access */
ret = ne2000_mem_readw(s, s->rsar);
ne2000_dma_update(s, 2);
} else {
/* 8 bit access */
ret = ne2000_mem_readb(s, s->rsar);
ne2000_dma_update(s, 1);
}
#ifdef DEBUG_NE2000
printf("NE2000: asic read val=0x%04x\n", ret);
#endif
return ret;
}
static void ne2000_asic_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
{
NE2000State *s = opaque;
#ifdef DEBUG_NE2000
printf("NE2000: asic writel val=0x%04x\n", val);
#endif
if (s->rcnt == 0)
return;
/* 32 bit access */
ne2000_mem_writel(s, s->rsar, val);
ne2000_dma_update(s, 4);
}
static uint32_t ne2000_asic_ioport_readl(void *opaque, uint32_t addr)
{
NE2000State *s = opaque;
int ret;
/* 32 bit access */
ret = ne2000_mem_readl(s, s->rsar);
ne2000_dma_update(s, 4);
#ifdef DEBUG_NE2000
printf("NE2000: asic readl val=0x%04x\n", ret);
#endif
return ret;
}
static void ne2000_reset_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
/* nothing to do (end of reset pulse) */
}
static uint32_t ne2000_reset_ioport_read(void *opaque, uint32_t addr)
{
NE2000State *s = opaque;
ne2000_reset(s);
return 0;
}
static void ne2000_save(QEMUFile* f,void* opaque)
{
NE2000State* s=(NE2000State*)opaque;
qemu_put_8s(f, &s->cmd);
qemu_put_be32s(f, &s->start);
qemu_put_be32s(f, &s->stop);
qemu_put_8s(f, &s->boundary);
qemu_put_8s(f, &s->tsr);
qemu_put_8s(f, &s->tpsr);
qemu_put_be16s(f, &s->tcnt);
qemu_put_be16s(f, &s->rcnt);
qemu_put_be32s(f, &s->rsar);
qemu_put_8s(f, &s->rsr);
qemu_put_8s(f, &s->isr);
qemu_put_8s(f, &s->dcfg);
qemu_put_8s(f, &s->imr);
qemu_put_buffer(f, s->phys, 6);
qemu_put_8s(f, &s->curpag);
qemu_put_buffer(f, s->mult, 8);
qemu_put_be32s(f, &s->irq);
qemu_put_buffer(f, s->mem, NE2000_MEM_SIZE);
}
static int ne2000_load(QEMUFile* f,void* opaque,int version_id)
{
NE2000State* s=(NE2000State*)opaque;
if (version_id != 1)
return -EINVAL;
qemu_get_8s(f, &s->cmd);
qemu_get_be32s(f, &s->start);
qemu_get_be32s(f, &s->stop);
qemu_get_8s(f, &s->boundary);
qemu_get_8s(f, &s->tsr);
qemu_get_8s(f, &s->tpsr);
qemu_get_be16s(f, &s->tcnt);
qemu_get_be16s(f, &s->rcnt);
qemu_get_be32s(f, &s->rsar);
qemu_get_8s(f, &s->rsr);
qemu_get_8s(f, &s->isr);
qemu_get_8s(f, &s->dcfg);
qemu_get_8s(f, &s->imr);
qemu_get_buffer(f, s->phys, 6);
qemu_get_8s(f, &s->curpag);
qemu_get_buffer(f, s->mult, 8);
qemu_get_be32s(f, &s->irq);
qemu_get_buffer(f, s->mem, NE2000_MEM_SIZE);
return 0;
}
void isa_ne2000_init(int base, int irq, NetDriverState *nd)
{
NE2000State *s;
s = qemu_mallocz(sizeof(NE2000State));
if (!s)
return;
register_ioport_write(base, 16, 1, ne2000_ioport_write, s);
register_ioport_read(base, 16, 1, ne2000_ioport_read, s);
register_ioport_write(base + 0x10, 1, 1, ne2000_asic_ioport_write, s);
register_ioport_read(base + 0x10, 1, 1, ne2000_asic_ioport_read, s);
register_ioport_write(base + 0x10, 2, 2, ne2000_asic_ioport_write, s);
register_ioport_read(base + 0x10, 2, 2, ne2000_asic_ioport_read, s);
register_ioport_write(base + 0x1f, 1, 1, ne2000_reset_ioport_write, s);
register_ioport_read(base + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
s->irq = irq;
s->nd = nd;
ne2000_reset(s);
qemu_add_read_packet(nd, ne2000_can_receive, ne2000_receive, s);
register_savevm("ne2000", 0, 1, ne2000_save, ne2000_load, s);
}
/***********************************************************/
/* PCI NE2000 definitions */
typedef struct PCINE2000State {
PCIDevice dev;
NE2000State ne2000;
} PCINE2000State;
static void ne2000_map(PCIDevice *pci_dev, int region_num,
uint32_t addr, uint32_t size, int type)
{
PCINE2000State *d = (PCINE2000State *)pci_dev;
NE2000State *s = &d->ne2000;
register_ioport_write(addr, 16, 1, ne2000_ioport_write, s);
register_ioport_read(addr, 16, 1, ne2000_ioport_read, s);
register_ioport_write(addr + 0x10, 1, 1, ne2000_asic_ioport_write, s);
register_ioport_read(addr + 0x10, 1, 1, ne2000_asic_ioport_read, s);
register_ioport_write(addr + 0x10, 2, 2, ne2000_asic_ioport_write, s);
register_ioport_read(addr + 0x10, 2, 2, ne2000_asic_ioport_read, s);
register_ioport_write(addr + 0x10, 4, 4, ne2000_asic_ioport_writel, s);
register_ioport_read(addr + 0x10, 4, 4, ne2000_asic_ioport_readl, s);
register_ioport_write(addr + 0x1f, 1, 1, ne2000_reset_ioport_write, s);
register_ioport_read(addr + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
}
void pci_ne2000_init(PCIBus *bus, NetDriverState *nd)
{
PCINE2000State *d;
NE2000State *s;
uint8_t *pci_conf;
d = (PCINE2000State *)pci_register_device(bus,
"NE2000", sizeof(PCINE2000State),
-1,
NULL, NULL);
pci_conf = d->dev.config;
pci_conf[0x00] = 0xec; // Realtek 8029
pci_conf[0x01] = 0x10;
pci_conf[0x02] = 0x29;
pci_conf[0x03] = 0x80;
pci_conf[0x0a] = 0x00; // ethernet network controller
pci_conf[0x0b] = 0x02;
pci_conf[0x0e] = 0x00; // header_type
pci_conf[0x3d] = 1; // interrupt pin 0
pci_register_io_region(&d->dev, 0, 0x100,
PCI_ADDRESS_SPACE_IO, ne2000_map);
s = &d->ne2000;
s->irq = 16; // PCI interrupt
s->pci_dev = (PCIDevice *)d;
s->nd = nd;
ne2000_reset(s);
qemu_add_read_packet(nd, ne2000_can_receive, ne2000_receive, s);
/* XXX: instance number ? */
register_savevm("ne2000", 0, 1, ne2000_save, ne2000_load, s);
register_savevm("ne2000_pci", 0, 1, generic_pci_save, generic_pci_load,
&d->dev);
}

1023
hw/openpic.c Normal file

File diff suppressed because it is too large Load Diff

582
hw/pc.c Normal file
View File

@@ -0,0 +1,582 @@
/*
* QEMU PC System Emulator
*
* Copyright (c) 2003-2004 Fabrice Bellard
*
* 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 "vl.h"
/* output Bochs bios info messages */
//#define DEBUG_BIOS
#define BIOS_FILENAME "bios.bin"
#define VGABIOS_FILENAME "vgabios.bin"
#define VGABIOS_CIRRUS_FILENAME "vgabios-cirrus.bin"
#define LINUX_BOOT_FILENAME "linux_boot.bin"
#define KERNEL_LOAD_ADDR 0x00100000
#define INITRD_LOAD_ADDR 0x00400000
#define KERNEL_PARAMS_ADDR 0x00090000
#define KERNEL_CMDLINE_ADDR 0x00099000
int speaker_data_on;
int dummy_refresh_clock;
static fdctrl_t *floppy_controller;
static RTCState *rtc_state;
static PITState *pit;
static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
{
}
/* MSDOS compatibility mode FPU exception support */
/* XXX: add IGNNE support */
void cpu_set_ferr(CPUX86State *s)
{
pic_set_irq(13, 1);
}
static void ioportF0_write(void *opaque, uint32_t addr, uint32_t data)
{
pic_set_irq(13, 0);
}
/* TSC handling */
uint64_t cpu_get_tsc(CPUX86State *env)
{
return qemu_get_clock(vm_clock);
}
/* PC cmos mappings */
#define REG_EQUIPMENT_BYTE 0x14
#define REG_IBM_CENTURY_BYTE 0x32
#define REG_IBM_PS2_CENTURY_BYTE 0x37
static inline int to_bcd(RTCState *s, int a)
{
return ((a / 10) << 4) | (a % 10);
}
static int cmos_get_fd_drive_type(int fd0)
{
int val;
switch (fd0) {
case 0:
/* 1.44 Mb 3"5 drive */
val = 4;
break;
case 1:
/* 2.88 Mb 3"5 drive */
val = 5;
break;
case 2:
/* 1.2 Mb 5"5 drive */
val = 2;
break;
default:
val = 0;
break;
}
return val;
}
static void cmos_init_hd(int type_ofs, int info_ofs, BlockDriverState *hd)
{
RTCState *s = rtc_state;
int cylinders, heads, sectors;
bdrv_get_geometry_hint(hd, &cylinders, &heads, &sectors);
rtc_set_memory(s, type_ofs, 47);
rtc_set_memory(s, info_ofs, cylinders);
rtc_set_memory(s, info_ofs + 1, cylinders >> 8);
rtc_set_memory(s, info_ofs + 2, heads);
rtc_set_memory(s, info_ofs + 3, 0xff);
rtc_set_memory(s, info_ofs + 4, 0xff);
rtc_set_memory(s, info_ofs + 5, 0xc0 | ((heads > 8) << 3));
rtc_set_memory(s, info_ofs + 6, cylinders);
rtc_set_memory(s, info_ofs + 7, cylinders >> 8);
rtc_set_memory(s, info_ofs + 8, sectors);
}
/* hd_table must contain 4 block drivers */
static void cmos_init(int ram_size, int boot_device, BlockDriverState **hd_table)
{
RTCState *s = rtc_state;
int val;
int fd0, fd1, nb;
time_t ti;
struct tm *tm;
int i;
/* set the CMOS date */
time(&ti);
if (rtc_utc)
tm = gmtime(&ti);
else
tm = localtime(&ti);
rtc_set_date(s, tm);
val = to_bcd(s, (tm->tm_year / 100) + 19);
rtc_set_memory(s, REG_IBM_CENTURY_BYTE, val);
rtc_set_memory(s, REG_IBM_PS2_CENTURY_BYTE, val);
/* various important CMOS locations needed by PC/Bochs bios */
/* memory size */
val = 640; /* base memory in K */
rtc_set_memory(s, 0x15, val);
rtc_set_memory(s, 0x16, val >> 8);
val = (ram_size / 1024) - 1024;
if (val > 65535)
val = 65535;
rtc_set_memory(s, 0x17, val);
rtc_set_memory(s, 0x18, val >> 8);
rtc_set_memory(s, 0x30, val);
rtc_set_memory(s, 0x31, val >> 8);
if (ram_size > (16 * 1024 * 1024))
val = (ram_size / 65536) - ((16 * 1024 * 1024) / 65536);
else
val = 0;
if (val > 65535)
val = 65535;
rtc_set_memory(s, 0x34, val);
rtc_set_memory(s, 0x35, val >> 8);
switch(boot_device) {
case 'a':
case 'b':
rtc_set_memory(s, 0x3d, 0x01); /* floppy boot */
break;
default:
case 'c':
rtc_set_memory(s, 0x3d, 0x02); /* hard drive boot */
break;
case 'd':
rtc_set_memory(s, 0x3d, 0x03); /* CD-ROM boot */
break;
}
/* floppy type */
fd0 = fdctrl_get_drive_type(floppy_controller, 0);
fd1 = fdctrl_get_drive_type(floppy_controller, 1);
val = (cmos_get_fd_drive_type(fd0) << 4) | cmos_get_fd_drive_type(fd1);
rtc_set_memory(s, 0x10, val);
val = 0;
nb = 0;
if (fd0 < 3)
nb++;
if (fd1 < 3)
nb++;
switch (nb) {
case 0:
break;
case 1:
val |= 0x01; /* 1 drive, ready for boot */
break;
case 2:
val |= 0x41; /* 2 drives, ready for boot */
break;
}
val |= 0x02; /* FPU is there */
val |= 0x04; /* PS/2 mouse installed */
rtc_set_memory(s, REG_EQUIPMENT_BYTE, val);
/* hard drives */
rtc_set_memory(s, 0x12, (hd_table[0] ? 0xf0 : 0) | (hd_table[1] ? 0x0f : 0));
if (hd_table[0])
cmos_init_hd(0x19, 0x1b, hd_table[0]);
if (hd_table[1])
cmos_init_hd(0x1a, 0x24, hd_table[1]);
val = 0;
for (i = 0; i < 4; i++) {
if (hd_table[i]) {
int cylinders, heads, sectors;
uint8_t translation;
/* NOTE: bdrv_get_geometry_hint() returns the geometry
that the hard disk returns. It is always such that: 1 <=
sects <= 63, 1 <= heads <= 16, 1 <= cylinders <=
16383. The BIOS geometry can be different. */
bdrv_get_geometry_hint(hd_table[i], &cylinders, &heads, &sectors);
if (cylinders <= 1024 && heads <= 16 && sectors <= 63) {
/* No translation. */
translation = 0;
} else {
/* LBA translation. */
translation = 1;
}
val |= translation << (i * 2);
}
}
rtc_set_memory(s, 0x39, val);
/* Disable check of 0x55AA signature on the last two bytes of
first sector of disk. XXX: make it the default ? */
// rtc_set_memory(s, 0x38, 1);
}
static void speaker_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
speaker_data_on = (val >> 1) & 1;
pit_set_gate(pit, 2, val & 1);
}
static uint32_t speaker_ioport_read(void *opaque, uint32_t addr)
{
int out;
out = pit_get_out(pit, 2, qemu_get_clock(vm_clock));
dummy_refresh_clock ^= 1;
return (speaker_data_on << 1) | pit_get_gate(pit, 2) | (out << 5) |
(dummy_refresh_clock << 4);
}
static void ioport92_write(void *opaque, uint32_t addr, uint32_t val)
{
cpu_x86_set_a20(cpu_single_env, (val >> 1) & 1);
/* XXX: bit 0 is fast reset */
}
static uint32_t ioport92_read(void *opaque, uint32_t addr)
{
return ((cpu_single_env->a20_mask >> 20) & 1) << 1;
}
/***********************************************************/
/* Bochs BIOS debug ports */
void bochs_bios_write(void *opaque, uint32_t addr, uint32_t val)
{
static const char shutdown_str[8] = "Shutdown";
static int shutdown_index = 0;
switch(addr) {
/* Bochs BIOS messages */
case 0x400:
case 0x401:
fprintf(stderr, "BIOS panic at rombios.c, line %d\n", val);
exit(1);
case 0x402:
case 0x403:
#ifdef DEBUG_BIOS
fprintf(stderr, "%c", val);
#endif
break;
case 0x8900:
/* same as Bochs power off */
if (val == shutdown_str[shutdown_index]) {
shutdown_index++;
if (shutdown_index == 8) {
shutdown_index = 0;
qemu_system_shutdown_request();
}
} else {
shutdown_index = 0;
}
break;
/* LGPL'ed VGA BIOS messages */
case 0x501:
case 0x502:
fprintf(stderr, "VGA BIOS panic, line %d\n", val);
exit(1);
case 0x500:
case 0x503:
#ifdef DEBUG_BIOS
fprintf(stderr, "%c", val);
#endif
break;
}
}
void bochs_bios_init(void)
{
register_ioport_write(0x400, 1, 2, bochs_bios_write, NULL);
register_ioport_write(0x401, 1, 2, bochs_bios_write, NULL);
register_ioport_write(0x402, 1, 1, bochs_bios_write, NULL);
register_ioport_write(0x403, 1, 1, bochs_bios_write, NULL);
register_ioport_write(0x8900, 1, 1, bochs_bios_write, NULL);
register_ioport_write(0x501, 1, 2, bochs_bios_write, NULL);
register_ioport_write(0x502, 1, 2, bochs_bios_write, NULL);
register_ioport_write(0x500, 1, 1, bochs_bios_write, NULL);
register_ioport_write(0x503, 1, 1, bochs_bios_write, NULL);
}
int load_kernel(const char *filename, uint8_t *addr,
uint8_t *real_addr)
{
int fd, size;
int setup_sects;
fd = open(filename, O_RDONLY | O_BINARY);
if (fd < 0)
return -1;
/* load 16 bit code */
if (read(fd, real_addr, 512) != 512)
goto fail;
setup_sects = real_addr[0x1F1];
if (!setup_sects)
setup_sects = 4;
if (read(fd, real_addr + 512, setup_sects * 512) !=
setup_sects * 512)
goto fail;
/* load 32 bit code */
size = read(fd, addr, 16 * 1024 * 1024);
if (size < 0)
goto fail;
close(fd);
return size;
fail:
close(fd);
return -1;
}
static const int ide_iobase[2] = { 0x1f0, 0x170 };
static const int ide_iobase2[2] = { 0x3f6, 0x376 };
static const int ide_irq[2] = { 14, 15 };
#define NE2000_NB_MAX 6
static int ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360, 0x280, 0x380 };
static int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
static int serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
static int serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 };
/* PC hardware initialisation */
void pc_init(int ram_size, int vga_ram_size, int boot_device,
DisplayState *ds, const char **fd_filename, int snapshot,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename)
{
char buf[1024];
int ret, linux_boot, initrd_size, i, nb_nics1;
unsigned long bios_offset, vga_bios_offset;
int bios_size, isa_bios_size;
PCIBus *pci_bus;
linux_boot = (kernel_filename != NULL);
/* allocate RAM */
cpu_register_physical_memory(0, ram_size, 0);
/* BIOS load */
bios_offset = ram_size + vga_ram_size;
vga_bios_offset = bios_offset + 256 * 1024;
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
bios_size = get_image_size(buf);
if (bios_size <= 0 ||
(bios_size % 65536) != 0 ||
bios_size > (256 * 1024)) {
goto bios_error;
}
ret = load_image(buf, phys_ram_base + bios_offset);
if (ret != bios_size) {
bios_error:
fprintf(stderr, "qemu: could not load PC bios '%s'\n", buf);
exit(1);
}
/* VGA BIOS load */
if (cirrus_vga_enabled) {
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_CIRRUS_FILENAME);
} else {
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
}
ret = load_image(buf, phys_ram_base + vga_bios_offset);
/* setup basic memory access */
cpu_register_physical_memory(0xc0000, 0x10000,
vga_bios_offset | IO_MEM_ROM);
/* map the last 128KB of the BIOS in ISA space */
isa_bios_size = bios_size;
if (isa_bios_size > (128 * 1024))
isa_bios_size = 128 * 1024;
cpu_register_physical_memory(0xd0000, (192 * 1024) - isa_bios_size,
IO_MEM_UNASSIGNED);
cpu_register_physical_memory(0x100000 - isa_bios_size,
isa_bios_size,
(bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM);
/* map all the bios at the top of memory */
cpu_register_physical_memory((uint32_t)(-bios_size),
bios_size, bios_offset | IO_MEM_ROM);
bochs_bios_init();
if (linux_boot) {
uint8_t bootsect[512];
uint8_t old_bootsect[512];
if (bs_table[0] == NULL) {
fprintf(stderr, "A disk image must be given for 'hda' when booting a Linux kernel\n");
exit(1);
}
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, LINUX_BOOT_FILENAME);
ret = load_image(buf, bootsect);
if (ret != sizeof(bootsect)) {
fprintf(stderr, "qemu: could not load linux boot sector '%s'\n",
buf);
exit(1);
}
if (bdrv_read(bs_table[0], 0, old_bootsect, 1) >= 0) {
/* copy the MSDOS partition table */
memcpy(bootsect + 0x1be, old_bootsect + 0x1be, 0x40);
}
bdrv_set_boot_sector(bs_table[0], bootsect, sizeof(bootsect));
/* now we can load the kernel */
ret = load_kernel(kernel_filename,
phys_ram_base + KERNEL_LOAD_ADDR,
phys_ram_base + KERNEL_PARAMS_ADDR);
if (ret < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
kernel_filename);
exit(1);
}
/* load initrd */
initrd_size = 0;
if (initrd_filename) {
initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR);
if (initrd_size < 0) {
fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
initrd_filename);
exit(1);
}
}
if (initrd_size > 0) {
stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x218, INITRD_LOAD_ADDR);
stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x21c, initrd_size);
}
pstrcpy(phys_ram_base + KERNEL_CMDLINE_ADDR, 4096,
kernel_cmdline);
stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x20, 0xA33F);
stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x22,
KERNEL_CMDLINE_ADDR - KERNEL_PARAMS_ADDR);
/* loader type */
stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x210, 0x01);
}
if (pci_enabled) {
pci_bus = i440fx_init();
piix3_init(pci_bus);
} else {
pci_bus = NULL;
}
/* init basic PC hardware */
register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
if (cirrus_vga_enabled) {
if (pci_enabled) {
pci_cirrus_vga_init(pci_bus,
ds, phys_ram_base + ram_size, ram_size,
vga_ram_size);
} else {
isa_cirrus_vga_init(ds, phys_ram_base + ram_size, ram_size,
vga_ram_size);
}
} else {
vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size,
vga_ram_size);
}
rtc_state = rtc_init(0x70, 8);
register_ioport_read(0x61, 1, 1, speaker_ioport_read, NULL);
register_ioport_write(0x61, 1, 1, speaker_ioport_write, NULL);
register_ioport_read(0x92, 1, 1, ioport92_read, NULL);
register_ioport_write(0x92, 1, 1, ioport92_write, NULL);
pic_init();
pit = pit_init(0x40, 0);
for(i = 0; i < MAX_SERIAL_PORTS; i++) {
if (serial_hds[i]) {
serial_init(serial_io[i], serial_irq[i], serial_hds[i]);
}
}
if (pci_enabled) {
for(i = 0; i < nb_nics; i++) {
pci_ne2000_init(pci_bus, &nd_table[i]);
}
pci_piix3_ide_init(pci_bus, bs_table);
} else {
nb_nics1 = nb_nics;
if (nb_nics1 > NE2000_NB_MAX)
nb_nics1 = NE2000_NB_MAX;
for(i = 0; i < nb_nics1; i++) {
isa_ne2000_init(ne2000_io[i], ne2000_irq[i], &nd_table[i]);
}
for(i = 0; i < 2; i++) {
isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
bs_table[2 * i], bs_table[2 * i + 1]);
}
}
kbd_init();
DMA_init(0);
if (audio_enabled) {
AUD_init();
#ifdef USE_SB16
if (sb16_enabled)
SB16_init ();
#endif
#ifdef CONFIG_ADLIB
if (adlib_enabled)
Adlib_init ();
#endif
#ifdef USE_GUS
if (gus_enabled)
GUS_init ();
#endif
}
floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table);
cmos_init(ram_size, boot_device, bs_table);
/* must be done after all PCI devices are instanciated */
/* XXX: should be done in the Bochs BIOS */
if (pci_enabled) {
pci_bios_init();
}
}

1524
hw/pci.c Normal file

File diff suppressed because it is too large Load Diff

706
hw/pckbd.c Normal file
View File

@@ -0,0 +1,706 @@
/*
* QEMU PC keyboard emulation
*
* Copyright (c) 2003 Fabrice Bellard
*
* 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 "vl.h"
/* debug PC keyboard */
//#define DEBUG_KBD
/* debug PC keyboard : only mouse */
//#define DEBUG_MOUSE
/* Keyboard Controller Commands */
#define KBD_CCMD_READ_MODE 0x20 /* Read mode bits */
#define KBD_CCMD_WRITE_MODE 0x60 /* Write mode bits */
#define KBD_CCMD_GET_VERSION 0xA1 /* Get controller version */
#define KBD_CCMD_MOUSE_DISABLE 0xA7 /* Disable mouse interface */
#define KBD_CCMD_MOUSE_ENABLE 0xA8 /* Enable mouse interface */
#define KBD_CCMD_TEST_MOUSE 0xA9 /* Mouse interface test */
#define KBD_CCMD_SELF_TEST 0xAA /* Controller self test */
#define KBD_CCMD_KBD_TEST 0xAB /* Keyboard interface test */
#define KBD_CCMD_KBD_DISABLE 0xAD /* Keyboard interface disable */
#define KBD_CCMD_KBD_ENABLE 0xAE /* Keyboard interface enable */
#define KBD_CCMD_READ_INPORT 0xC0 /* read input port */
#define KBD_CCMD_READ_OUTPORT 0xD0 /* read output port */
#define KBD_CCMD_WRITE_OUTPORT 0xD1 /* write output port */
#define KBD_CCMD_WRITE_OBUF 0xD2
#define KBD_CCMD_WRITE_AUX_OBUF 0xD3 /* Write to output buffer as if
initiated by the auxiliary device */
#define KBD_CCMD_WRITE_MOUSE 0xD4 /* Write the following byte to the mouse */
#define KBD_CCMD_DISABLE_A20 0xDD /* HP vectra only ? */
#define KBD_CCMD_ENABLE_A20 0xDF /* HP vectra only ? */
#define KBD_CCMD_RESET 0xFE
/* Keyboard Commands */
#define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */
#define KBD_CMD_ECHO 0xEE
#define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */
#define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */
#define KBD_CMD_ENABLE 0xF4 /* Enable scanning */
#define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */
#define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */
#define KBD_CMD_RESET 0xFF /* Reset */
/* Keyboard Replies */
#define KBD_REPLY_POR 0xAA /* Power on reset */
#define KBD_REPLY_ACK 0xFA /* Command ACK */
#define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */
/* Status Register Bits */
#define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */
#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */
#define KBD_STAT_SELFTEST 0x04 /* Self test successful */
#define KBD_STAT_CMD 0x08 /* Last write was a command write (0=data) */
#define KBD_STAT_UNLOCKED 0x10 /* Zero if keyboard locked */
#define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */
#define KBD_STAT_GTO 0x40 /* General receive/xmit timeout */
#define KBD_STAT_PERR 0x80 /* Parity error */
/* Controller Mode Register Bits */
#define KBD_MODE_KBD_INT 0x01 /* Keyboard data generate IRQ1 */
#define KBD_MODE_MOUSE_INT 0x02 /* Mouse data generate IRQ12 */
#define KBD_MODE_SYS 0x04 /* The system flag (?) */
#define KBD_MODE_NO_KEYLOCK 0x08 /* The keylock doesn't affect the keyboard if set */
#define KBD_MODE_DISABLE_KBD 0x10 /* Disable keyboard interface */
#define KBD_MODE_DISABLE_MOUSE 0x20 /* Disable mouse interface */
#define KBD_MODE_KCC 0x40 /* Scan code conversion to PC format */
#define KBD_MODE_RFU 0x80
/* Mouse Commands */
#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */
#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */
#define AUX_SET_RES 0xE8 /* Set resolution */
#define AUX_GET_SCALE 0xE9 /* Get scaling factor */
#define AUX_SET_STREAM 0xEA /* Set stream mode */
#define AUX_POLL 0xEB /* Poll */
#define AUX_RESET_WRAP 0xEC /* Reset wrap mode */
#define AUX_SET_WRAP 0xEE /* Set wrap mode */
#define AUX_SET_REMOTE 0xF0 /* Set remote mode */
#define AUX_GET_TYPE 0xF2 /* Get type */
#define AUX_SET_SAMPLE 0xF3 /* Set sample rate */
#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */
#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */
#define AUX_SET_DEFAULT 0xF6
#define AUX_RESET 0xFF /* Reset aux device */
#define AUX_ACK 0xFA /* Command byte ACK. */
#define MOUSE_STATUS_REMOTE 0x40
#define MOUSE_STATUS_ENABLED 0x20
#define MOUSE_STATUS_SCALE21 0x10
#define KBD_QUEUE_SIZE 256
typedef struct {
uint8_t aux[KBD_QUEUE_SIZE];
uint8_t data[KBD_QUEUE_SIZE];
int rptr, wptr, count;
} KBDQueue;
typedef struct KBDState {
KBDQueue queue;
uint8_t write_cmd; /* if non zero, write data to port 60 is expected */
uint8_t status;
uint8_t mode;
/* keyboard state */
int kbd_write_cmd;
int scan_enabled;
/* mouse state */
int mouse_write_cmd;
uint8_t mouse_status;
uint8_t mouse_resolution;
uint8_t mouse_sample_rate;
uint8_t mouse_wrap;
uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
uint8_t mouse_detect_state;
int mouse_dx; /* current values, needed for 'poll' mode */
int mouse_dy;
int mouse_dz;
uint8_t mouse_buttons;
} KBDState;
KBDState kbd_state;
/* update irq and KBD_STAT_[MOUSE_]OBF */
/* XXX: not generating the irqs if KBD_MODE_DISABLE_KBD is set may be
incorrect, but it avoids having to simulate exact delays */
static void kbd_update_irq(KBDState *s)
{
KBDQueue *q = &s->queue;
int irq12_level, irq1_level;
irq1_level = 0;
irq12_level = 0;
s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF);
if (q->count != 0) {
s->status |= KBD_STAT_OBF;
if (q->aux[q->rptr]) {
s->status |= KBD_STAT_MOUSE_OBF;
if (s->mode & KBD_MODE_MOUSE_INT)
irq12_level = 1;
} else {
if ((s->mode & KBD_MODE_KBD_INT) &&
!(s->mode & KBD_MODE_DISABLE_KBD))
irq1_level = 1;
}
}
pic_set_irq(1, irq1_level);
pic_set_irq(12, irq12_level);
}
static void kbd_queue(KBDState *s, int b, int aux)
{
KBDQueue *q = &s->queue;
#if defined(DEBUG_MOUSE) || defined(DEBUG_KBD)
if (aux)
printf("mouse event: 0x%02x\n", b);
#ifdef DEBUG_KBD
else
printf("kbd event: 0x%02x\n", b);
#endif
#endif
if (q->count >= KBD_QUEUE_SIZE)
return;
q->aux[q->wptr] = aux;
q->data[q->wptr] = b;
if (++q->wptr == KBD_QUEUE_SIZE)
q->wptr = 0;
q->count++;
kbd_update_irq(s);
}
static void pc_kbd_put_keycode(void *opaque, int keycode)
{
KBDState *s = opaque;
kbd_queue(s, keycode, 0);
}
static uint32_t kbd_read_status(void *opaque, uint32_t addr)
{
KBDState *s = opaque;
int val;
val = s->status;
#if defined(DEBUG_KBD)
printf("kbd: read status=0x%02x\n", val);
#endif
return val;
}
static void kbd_write_command(void *opaque, uint32_t addr, uint32_t val)
{
KBDState *s = opaque;
#ifdef DEBUG_KBD
printf("kbd: write cmd=0x%02x\n", val);
#endif
switch(val) {
case KBD_CCMD_READ_MODE:
kbd_queue(s, s->mode, 0);
break;
case KBD_CCMD_WRITE_MODE:
case KBD_CCMD_WRITE_OBUF:
case KBD_CCMD_WRITE_AUX_OBUF:
case KBD_CCMD_WRITE_MOUSE:
case KBD_CCMD_WRITE_OUTPORT:
s->write_cmd = val;
break;
case KBD_CCMD_MOUSE_DISABLE:
s->mode |= KBD_MODE_DISABLE_MOUSE;
break;
case KBD_CCMD_MOUSE_ENABLE:
s->mode &= ~KBD_MODE_DISABLE_MOUSE;
break;
case KBD_CCMD_TEST_MOUSE:
kbd_queue(s, 0x00, 0);
break;
case KBD_CCMD_SELF_TEST:
s->status |= KBD_STAT_SELFTEST;
kbd_queue(s, 0x55, 0);
break;
case KBD_CCMD_KBD_TEST:
kbd_queue(s, 0x00, 0);
break;
case KBD_CCMD_KBD_DISABLE:
s->mode |= KBD_MODE_DISABLE_KBD;
kbd_update_irq(s);
break;
case KBD_CCMD_KBD_ENABLE:
s->mode &= ~KBD_MODE_DISABLE_KBD;
kbd_update_irq(s);
break;
case KBD_CCMD_READ_INPORT:
kbd_queue(s, 0x00, 0);
break;
case KBD_CCMD_READ_OUTPORT:
/* XXX: check that */
#ifdef TARGET_I386
val = 0x01 | (((cpu_single_env->a20_mask >> 20) & 1) << 1);
#else
val = 0x01;
#endif
if (s->status & KBD_STAT_OBF)
val |= 0x10;
if (s->status & KBD_STAT_MOUSE_OBF)
val |= 0x20;
kbd_queue(s, val, 0);
break;
#ifdef TARGET_I386
case KBD_CCMD_ENABLE_A20:
cpu_x86_set_a20(cpu_single_env, 1);
break;
case KBD_CCMD_DISABLE_A20:
cpu_x86_set_a20(cpu_single_env, 0);
break;
#endif
case KBD_CCMD_RESET:
qemu_system_reset_request();
break;
case 0xff:
/* ignore that - I don't know what is its use */
break;
default:
fprintf(stderr, "qemu: unsupported keyboard cmd=0x%02x\n", val);
break;
}
}
static uint32_t kbd_read_data(void *opaque, uint32_t addr)
{
KBDState *s = opaque;
KBDQueue *q;
int val, index, aux;
q = &s->queue;
if (q->count == 0) {
/* NOTE: if no data left, we return the last keyboard one
(needed for EMM386) */
/* XXX: need a timer to do things correctly */
index = q->rptr - 1;
if (index < 0)
index = KBD_QUEUE_SIZE - 1;
val = q->data[index];
} else {
aux = q->aux[q->rptr];
val = q->data[q->rptr];
if (++q->rptr == KBD_QUEUE_SIZE)
q->rptr = 0;
q->count--;
/* reading deasserts IRQ */
if (aux)
pic_set_irq(12, 0);
else
pic_set_irq(1, 0);
}
/* reassert IRQs if data left */
kbd_update_irq(s);
#ifdef DEBUG_KBD
printf("kbd: read data=0x%02x\n", val);
#endif
return val;
}
static void kbd_reset_keyboard(KBDState *s)
{
s->scan_enabled = 1;
}
static void kbd_write_keyboard(KBDState *s, int val)
{
switch(s->kbd_write_cmd) {
default:
case -1:
switch(val) {
case 0x00:
kbd_queue(s, KBD_REPLY_ACK, 0);
break;
case 0x05:
kbd_queue(s, KBD_REPLY_RESEND, 0);
break;
case KBD_CMD_GET_ID:
kbd_queue(s, KBD_REPLY_ACK, 0);
kbd_queue(s, 0xab, 0);
kbd_queue(s, 0x83, 0);
break;
case KBD_CMD_ECHO:
kbd_queue(s, KBD_CMD_ECHO, 0);
break;
case KBD_CMD_ENABLE:
s->scan_enabled = 1;
kbd_queue(s, KBD_REPLY_ACK, 0);
break;
case KBD_CMD_SET_LEDS:
case KBD_CMD_SET_RATE:
s->kbd_write_cmd = val;
kbd_queue(s, KBD_REPLY_ACK, 0);
break;
case KBD_CMD_RESET_DISABLE:
kbd_reset_keyboard(s);
s->scan_enabled = 0;
kbd_queue(s, KBD_REPLY_ACK, 0);
break;
case KBD_CMD_RESET_ENABLE:
kbd_reset_keyboard(s);
s->scan_enabled = 1;
kbd_queue(s, KBD_REPLY_ACK, 0);
break;
case KBD_CMD_RESET:
kbd_reset_keyboard(s);
kbd_queue(s, KBD_REPLY_ACK, 0);
kbd_queue(s, KBD_REPLY_POR, 0);
break;
default:
kbd_queue(s, KBD_REPLY_ACK, 0);
break;
}
break;
case KBD_CMD_SET_LEDS:
kbd_queue(s, KBD_REPLY_ACK, 0);
s->kbd_write_cmd = -1;
break;
case KBD_CMD_SET_RATE:
kbd_queue(s, KBD_REPLY_ACK, 0);
s->kbd_write_cmd = -1;
break;
}
}
static void kbd_mouse_send_packet(KBDState *s)
{
unsigned int b;
int dx1, dy1, dz1;
dx1 = s->mouse_dx;
dy1 = s->mouse_dy;
dz1 = s->mouse_dz;
/* XXX: increase range to 8 bits ? */
if (dx1 > 127)
dx1 = 127;
else if (dx1 < -127)
dx1 = -127;
if (dy1 > 127)
dy1 = 127;
else if (dy1 < -127)
dy1 = -127;
b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
kbd_queue(s, b, 1);
kbd_queue(s, dx1 & 0xff, 1);
kbd_queue(s, dy1 & 0xff, 1);
/* extra byte for IMPS/2 or IMEX */
switch(s->mouse_type) {
default:
break;
case 3:
if (dz1 > 127)
dz1 = 127;
else if (dz1 < -127)
dz1 = -127;
kbd_queue(s, dz1 & 0xff, 1);
break;
case 4:
if (dz1 > 7)
dz1 = 7;
else if (dz1 < -7)
dz1 = -7;
b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
kbd_queue(s, b, 1);
break;
}
/* update deltas */
s->mouse_dx -= dx1;
s->mouse_dy -= dy1;
s->mouse_dz -= dz1;
}
static void pc_kbd_mouse_event(void *opaque,
int dx, int dy, int dz, int buttons_state)
{
KBDState *s = opaque;
/* check if deltas are recorded when disabled */
if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
return;
s->mouse_dx += dx;
s->mouse_dy -= dy;
s->mouse_dz += dz;
/* XXX: SDL sometimes generates nul events: we delete them */
if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 &&
s->mouse_buttons == buttons_state)
return;
s->mouse_buttons = buttons_state;
if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
(s->queue.count < (KBD_QUEUE_SIZE - 16))) {
for(;;) {
/* if not remote, send event. Multiple events are sent if
too big deltas */
kbd_mouse_send_packet(s);
if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
break;
}
}
}
static void kbd_write_mouse(KBDState *s, int val)
{
#ifdef DEBUG_MOUSE
printf("kbd: write mouse 0x%02x\n", val);
#endif
switch(s->mouse_write_cmd) {
default:
case -1:
/* mouse command */
if (s->mouse_wrap) {
if (val == AUX_RESET_WRAP) {
s->mouse_wrap = 0;
kbd_queue(s, AUX_ACK, 1);
return;
} else if (val != AUX_RESET) {
kbd_queue(s, val, 1);
return;
}
}
switch(val) {
case AUX_SET_SCALE11:
s->mouse_status &= ~MOUSE_STATUS_SCALE21;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_SET_SCALE21:
s->mouse_status |= MOUSE_STATUS_SCALE21;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_SET_STREAM:
s->mouse_status &= ~MOUSE_STATUS_REMOTE;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_SET_WRAP:
s->mouse_wrap = 1;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_SET_REMOTE:
s->mouse_status |= MOUSE_STATUS_REMOTE;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_GET_TYPE:
kbd_queue(s, AUX_ACK, 1);
kbd_queue(s, s->mouse_type, 1);
break;
case AUX_SET_RES:
case AUX_SET_SAMPLE:
s->mouse_write_cmd = val;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_GET_SCALE:
kbd_queue(s, AUX_ACK, 1);
kbd_queue(s, s->mouse_status, 1);
kbd_queue(s, s->mouse_resolution, 1);
kbd_queue(s, s->mouse_sample_rate, 1);
break;
case AUX_POLL:
kbd_queue(s, AUX_ACK, 1);
kbd_mouse_send_packet(s);
break;
case AUX_ENABLE_DEV:
s->mouse_status |= MOUSE_STATUS_ENABLED;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_DISABLE_DEV:
s->mouse_status &= ~MOUSE_STATUS_ENABLED;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_SET_DEFAULT:
s->mouse_sample_rate = 100;
s->mouse_resolution = 2;
s->mouse_status = 0;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_RESET:
s->mouse_sample_rate = 100;
s->mouse_resolution = 2;
s->mouse_status = 0;
kbd_queue(s, AUX_ACK, 1);
kbd_queue(s, 0xaa, 1);
kbd_queue(s, s->mouse_type, 1);
break;
default:
break;
}
break;
case AUX_SET_SAMPLE:
s->mouse_sample_rate = val;
#if 0
/* detect IMPS/2 or IMEX */
switch(s->mouse_detect_state) {
default:
case 0:
if (val == 200)
s->mouse_detect_state = 1;
break;
case 1:
if (val == 100)
s->mouse_detect_state = 2;
else if (val == 200)
s->mouse_detect_state = 3;
else
s->mouse_detect_state = 0;
break;
case 2:
if (val == 80)
s->mouse_type = 3; /* IMPS/2 */
s->mouse_detect_state = 0;
break;
case 3:
if (val == 80)
s->mouse_type = 4; /* IMEX */
s->mouse_detect_state = 0;
break;
}
#endif
kbd_queue(s, AUX_ACK, 1);
s->mouse_write_cmd = -1;
break;
case AUX_SET_RES:
s->mouse_resolution = val;
kbd_queue(s, AUX_ACK, 1);
s->mouse_write_cmd = -1;
break;
}
}
void kbd_write_data(void *opaque, uint32_t addr, uint32_t val)
{
KBDState *s = opaque;
#ifdef DEBUG_KBD
printf("kbd: write data=0x%02x\n", val);
#endif
switch(s->write_cmd) {
case 0:
kbd_write_keyboard(s, val);
break;
case KBD_CCMD_WRITE_MODE:
s->mode = val;
kbd_update_irq(s);
break;
case KBD_CCMD_WRITE_OBUF:
kbd_queue(s, val, 0);
break;
case KBD_CCMD_WRITE_AUX_OBUF:
kbd_queue(s, val, 1);
break;
case KBD_CCMD_WRITE_OUTPORT:
#ifdef TARGET_I386
cpu_x86_set_a20(cpu_single_env, (val >> 1) & 1);
#endif
if (!(val & 1)) {
qemu_system_reset_request();
}
break;
case KBD_CCMD_WRITE_MOUSE:
kbd_write_mouse(s, val);
break;
default:
break;
}
s->write_cmd = 0;
}
static void kbd_reset(void *opaque)
{
KBDState *s = opaque;
KBDQueue *q;
s->kbd_write_cmd = -1;
s->mouse_write_cmd = -1;
s->mode = KBD_MODE_KBD_INT | KBD_MODE_MOUSE_INT;
s->status = KBD_STAT_CMD | KBD_STAT_UNLOCKED;
q = &s->queue;
q->rptr = 0;
q->wptr = 0;
q->count = 0;
}
static void kbd_save(QEMUFile* f, void* opaque)
{
KBDState *s = (KBDState*)opaque;
qemu_put_8s(f, &s->write_cmd);
qemu_put_8s(f, &s->status);
qemu_put_8s(f, &s->mode);
qemu_put_be32s(f, &s->kbd_write_cmd);
qemu_put_be32s(f, &s->scan_enabled);
qemu_put_be32s(f, &s->mouse_write_cmd);
qemu_put_8s(f, &s->mouse_status);
qemu_put_8s(f, &s->mouse_resolution);
qemu_put_8s(f, &s->mouse_sample_rate);
qemu_put_8s(f, &s->mouse_wrap);
qemu_put_8s(f, &s->mouse_type);
qemu_put_8s(f, &s->mouse_detect_state);
qemu_put_be32s(f, &s->mouse_dx);
qemu_put_be32s(f, &s->mouse_dy);
qemu_put_be32s(f, &s->mouse_dz);
qemu_put_8s(f, &s->mouse_buttons);
}
static int kbd_load(QEMUFile* f, void* opaque, int version_id)
{
KBDState *s = (KBDState*)opaque;
if (version_id != 1)
return -EINVAL;
qemu_get_8s(f, &s->write_cmd);
qemu_get_8s(f, &s->status);
qemu_get_8s(f, &s->mode);
qemu_get_be32s(f, &s->kbd_write_cmd);
qemu_get_be32s(f, &s->scan_enabled);
qemu_get_be32s(f, &s->mouse_write_cmd);
qemu_get_8s(f, &s->mouse_status);
qemu_get_8s(f, &s->mouse_resolution);
qemu_get_8s(f, &s->mouse_sample_rate);
qemu_get_8s(f, &s->mouse_wrap);
qemu_get_8s(f, &s->mouse_type);
qemu_get_8s(f, &s->mouse_detect_state);
qemu_get_be32s(f, &s->mouse_dx);
qemu_get_be32s(f, &s->mouse_dy);
qemu_get_be32s(f, &s->mouse_dz);
qemu_get_8s(f, &s->mouse_buttons);
return 0;
}
void kbd_init(void)
{
KBDState *s = &kbd_state;
kbd_reset(s);
register_savevm("pckbd", 0, 1, kbd_save, kbd_load, s);
register_ioport_read(0x60, 1, 1, kbd_read_data, s);
register_ioport_write(0x60, 1, 1, kbd_write_data, s);
register_ioport_read(0x64, 1, 1, kbd_read_status, s);
register_ioport_write(0x64, 1, 1, kbd_write_command, s);
qemu_add_kbd_event_handler(pc_kbd_put_keycode, s);
qemu_add_mouse_event_handler(pc_kbd_mouse_event, s);
qemu_register_reset(kbd_reset, s);
}

462
hw/ppc.c Normal file
View File

@@ -0,0 +1,462 @@
/*
* QEMU generic PPC hardware System Emulator
*
* Copyright (c) 2003-2004 Jocelyn Mayer
*
* 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 "vl.h"
#include "m48t59.h"
/*****************************************************************************/
/* PPC time base and decrementer emulation */
//#define DEBUG_TB
struct ppc_tb_t {
/* Time base management */
int64_t tb_offset; /* Compensation */
uint32_t tb_freq; /* TB frequency */
/* Decrementer management */
uint64_t decr_next; /* Tick for next decr interrupt */
struct QEMUTimer *decr_timer;
};
static inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env)
{
/* TB time in tb periods */
return muldiv64(qemu_get_clock(vm_clock) + tb_env->tb_offset,
tb_env->tb_freq, ticks_per_sec);
}
uint32_t cpu_ppc_load_tbl (CPUState *env)
{
ppc_tb_t *tb_env = env->tb_env;
uint64_t tb;
tb = cpu_ppc_get_tb(tb_env);
#ifdef DEBUG_TB
{
static int last_time;
int now;
now = time(NULL);
if (last_time != now) {
last_time = now;
printf("%s: tb=0x%016lx %d %08lx\n",
__func__, tb, now, tb_env->tb_offset);
}
}
#endif
return tb & 0xFFFFFFFF;
}
uint32_t cpu_ppc_load_tbu (CPUState *env)
{
ppc_tb_t *tb_env = env->tb_env;
uint64_t tb;
tb = cpu_ppc_get_tb(tb_env);
#ifdef DEBUG_TB
printf("%s: tb=0x%016lx\n", __func__, tb);
#endif
return tb >> 32;
}
static void cpu_ppc_store_tb (ppc_tb_t *tb_env, uint64_t value)
{
tb_env->tb_offset = muldiv64(value, ticks_per_sec, tb_env->tb_freq)
- qemu_get_clock(vm_clock);
#ifdef DEBUG_TB
printf("%s: tb=0x%016lx offset=%08x\n", __func__, value);
#endif
}
void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
{
ppc_tb_t *tb_env = env->tb_env;
cpu_ppc_store_tb(tb_env,
((uint64_t)value << 32) | cpu_ppc_load_tbl(env));
}
void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
{
ppc_tb_t *tb_env = env->tb_env;
cpu_ppc_store_tb(tb_env,
((uint64_t)cpu_ppc_load_tbu(env) << 32) | value);
}
uint32_t cpu_ppc_load_decr (CPUState *env)
{
ppc_tb_t *tb_env = env->tb_env;
uint32_t decr;
decr = muldiv64(tb_env->decr_next - qemu_get_clock(vm_clock),
tb_env->tb_freq, ticks_per_sec);
#if defined(DEBUG_TB)
printf("%s: 0x%08x\n", __func__, decr);
#endif
return decr;
}
/* When decrementer expires,
* all we need to do is generate or queue a CPU exception
*/
static inline void cpu_ppc_decr_excp (CPUState *env)
{
/* Raise it */
#ifdef DEBUG_TB
printf("raise decrementer exception\n");
#endif
cpu_interrupt(env, CPU_INTERRUPT_TIMER);
}
static void _cpu_ppc_store_decr (CPUState *env, uint32_t decr,
uint32_t value, int is_excp)
{
ppc_tb_t *tb_env = env->tb_env;
uint64_t now, next;
#ifdef DEBUG_TB
printf("%s: 0x%08x => 0x%08x\n", __func__, decr, value);
#endif
now = qemu_get_clock(vm_clock);
next = now + muldiv64(value, ticks_per_sec, tb_env->tb_freq);
if (is_excp)
next += tb_env->decr_next - now;
if (next == now)
next++;
tb_env->decr_next = next;
/* Adjust timer */
qemu_mod_timer(tb_env->decr_timer, next);
/* If we set a negative value and the decrementer was positive,
* raise an exception.
*/
if ((value & 0x80000000) && !(decr & 0x80000000))
cpu_ppc_decr_excp(env);
}
void cpu_ppc_store_decr (CPUState *env, uint32_t value)
{
_cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0);
}
static void cpu_ppc_decr_cb (void *opaque)
{
_cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
}
/* Set up (once) timebase frequency (in Hz) */
ppc_tb_t *cpu_ppc_tb_init (CPUState *env, uint32_t freq)
{
ppc_tb_t *tb_env;
tb_env = qemu_mallocz(sizeof(ppc_tb_t));
if (tb_env == NULL)
return NULL;
env->tb_env = tb_env;
if (tb_env->tb_freq == 0 || 1) {
tb_env->tb_freq = freq;
/* Create new timer */
tb_env->decr_timer =
qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env);
/* There is a bug in 2.4 kernels:
* if a decrementer exception is pending when it enables msr_ee,
* it's not ready to handle it...
*/
_cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
}
return tb_env;
}
#if 0
/*****************************************************************************/
/* Handle system reset (for now, just stop emulation) */
void cpu_ppc_reset (CPUState *env)
{
printf("Reset asked... Stop emulation\n");
abort();
}
#endif
static void PPC_io_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
{
cpu_outb(NULL, addr & 0xffff, value);
}
static uint32_t PPC_io_readb (void *opaque, target_phys_addr_t addr)
{
uint32_t ret = cpu_inb(NULL, addr & 0xffff);
return ret;
}
static void PPC_io_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
{
#ifdef TARGET_WORDS_BIGENDIAN
value = bswap16(value);
#endif
cpu_outw(NULL, addr & 0xffff, value);
}
static uint32_t PPC_io_readw (void *opaque, target_phys_addr_t addr)
{
uint32_t ret = cpu_inw(NULL, addr & 0xffff);
#ifdef TARGET_WORDS_BIGENDIAN
ret = bswap16(ret);
#endif
return ret;
}
static void PPC_io_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
{
#ifdef TARGET_WORDS_BIGENDIAN
value = bswap32(value);
#endif
cpu_outl(NULL, addr & 0xffff, value);
}
static uint32_t PPC_io_readl (void *opaque, target_phys_addr_t addr)
{
uint32_t ret = cpu_inl(NULL, addr & 0xffff);
#ifdef TARGET_WORDS_BIGENDIAN
ret = bswap32(ret);
#endif
return ret;
}
CPUWriteMemoryFunc *PPC_io_write[] = {
&PPC_io_writeb,
&PPC_io_writew,
&PPC_io_writel,
};
CPUReadMemoryFunc *PPC_io_read[] = {
&PPC_io_readb,
&PPC_io_readw,
&PPC_io_readl,
};
/*****************************************************************************/
/* Debug port */
void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
{
addr &= 0xF;
switch (addr) {
case 0:
printf("%c", val);
break;
case 1:
printf("\n");
fflush(stdout);
break;
case 2:
printf("Set loglevel to %04x\n", val);
cpu_set_log(val | 0x100);
break;
}
}
/*****************************************************************************/
/* NVRAM helpers */
void NVRAM_set_byte (m48t59_t *nvram, uint32_t addr, uint8_t value)
{
m48t59_set_addr(nvram, addr);
m48t59_write(nvram, value);
}
uint8_t NVRAM_get_byte (m48t59_t *nvram, uint32_t addr)
{
m48t59_set_addr(nvram, addr);
return m48t59_read(nvram);
}
void NVRAM_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value)
{
m48t59_set_addr(nvram, addr);
m48t59_write(nvram, value >> 8);
m48t59_set_addr(nvram, addr + 1);
m48t59_write(nvram, value & 0xFF);
}
uint16_t NVRAM_get_word (m48t59_t *nvram, uint32_t addr)
{
uint16_t tmp;
m48t59_set_addr(nvram, addr);
tmp = m48t59_read(nvram) << 8;
m48t59_set_addr(nvram, addr + 1);
tmp |= m48t59_read(nvram);
return tmp;
}
void NVRAM_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value)
{
m48t59_set_addr(nvram, addr);
m48t59_write(nvram, value >> 24);
m48t59_set_addr(nvram, addr + 1);
m48t59_write(nvram, (value >> 16) & 0xFF);
m48t59_set_addr(nvram, addr + 2);
m48t59_write(nvram, (value >> 8) & 0xFF);
m48t59_set_addr(nvram, addr + 3);
m48t59_write(nvram, value & 0xFF);
}
uint32_t NVRAM_get_lword (m48t59_t *nvram, uint32_t addr)
{
uint32_t tmp;
m48t59_set_addr(nvram, addr);
tmp = m48t59_read(nvram) << 24;
m48t59_set_addr(nvram, addr + 1);
tmp |= m48t59_read(nvram) << 16;
m48t59_set_addr(nvram, addr + 2);
tmp |= m48t59_read(nvram) << 8;
m48t59_set_addr(nvram, addr + 3);
tmp |= m48t59_read(nvram);
return tmp;
}
void NVRAM_set_string (m48t59_t *nvram, uint32_t addr,
const unsigned char *str, uint32_t max)
{
int i;
for (i = 0; i < max && str[i] != '\0'; i++) {
m48t59_set_addr(nvram, addr + i);
m48t59_write(nvram, str[i]);
}
m48t59_set_addr(nvram, addr + max - 1);
m48t59_write(nvram, '\0');
}
int NVRAM_get_string (m48t59_t *nvram, uint8_t *dst, uint16_t addr, int max)
{
int i;
memset(dst, 0, max);
for (i = 0; i < max; i++) {
dst[i] = NVRAM_get_byte(nvram, addr + i);
if (dst[i] == '\0')
break;
}
return i;
}
static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
{
uint16_t tmp;
uint16_t pd, pd1, pd2;
tmp = prev >> 8;
pd = prev ^ value;
pd1 = pd & 0x000F;
pd2 = ((pd >> 4) & 0x000F) ^ pd1;
tmp ^= (pd1 << 3) | (pd1 << 8);
tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
return tmp;
}
uint16_t NVRAM_compute_crc (m48t59_t *nvram, uint32_t start, uint32_t count)
{
uint32_t i;
uint16_t crc = 0xFFFF;
int odd;
odd = count & 1;
count &= ~1;
for (i = 0; i != count; i++) {
crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
}
if (odd) {
crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
}
return crc;
}
#define CMDLINE_ADDR 0x017ff000
int PPC_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
const unsigned char *arch,
uint32_t RAM_size, int boot_device,
uint32_t kernel_image, uint32_t kernel_size,
const char *cmdline,
uint32_t initrd_image, uint32_t initrd_size,
uint32_t NVRAM_image,
int width, int height, int depth)
{
uint16_t crc;
/* Set parameters for Open Hack'Ware BIOS */
NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
NVRAM_set_lword(nvram, 0x10, 0x00000002); /* structure v2 */
NVRAM_set_word(nvram, 0x14, NVRAM_size);
NVRAM_set_string(nvram, 0x20, arch, 16);
NVRAM_set_lword(nvram, 0x30, RAM_size);
NVRAM_set_byte(nvram, 0x34, boot_device);
NVRAM_set_lword(nvram, 0x38, kernel_image);
NVRAM_set_lword(nvram, 0x3C, kernel_size);
if (cmdline) {
/* XXX: put the cmdline in NVRAM too ? */
strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
NVRAM_set_lword(nvram, 0x40, CMDLINE_ADDR);
NVRAM_set_lword(nvram, 0x44, strlen(cmdline));
} else {
NVRAM_set_lword(nvram, 0x40, 0);
NVRAM_set_lword(nvram, 0x44, 0);
}
NVRAM_set_lword(nvram, 0x48, initrd_image);
NVRAM_set_lword(nvram, 0x4C, initrd_size);
NVRAM_set_lword(nvram, 0x50, NVRAM_image);
NVRAM_set_word(nvram, 0x54, width);
NVRAM_set_word(nvram, 0x56, height);
NVRAM_set_word(nvram, 0x58, depth);
crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
NVRAM_set_word(nvram, 0xFC, crc);
return 0;
}
/*****************************************************************************/
void ppc_init (int ram_size, int vga_ram_size, int boot_device,
DisplayState *ds, const char **fd_filename, int snapshot,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename)
{
if (prep_enabled) {
ppc_prep_init(ram_size, vga_ram_size, boot_device, ds, fd_filename,
snapshot, kernel_filename, kernel_cmdline,
initrd_filename);
} else {
ppc_chrp_init(ram_size, vga_ram_size, boot_device, ds, fd_filename,
snapshot, kernel_filename, kernel_cmdline,
initrd_filename);
}
/* Special port to get debug messages from Open-Firmware */
register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL);
}

233
hw/ppc_chrp.c Normal file
View File

@@ -0,0 +1,233 @@
/*
* QEMU PPC CHRP/PMAC hardware System Emulator
*
* Copyright (c) 2004 Fabrice Bellard
*
* 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 "vl.h"
#define BIOS_FILENAME "ppc_rom.bin"
#define NVRAM_SIZE 0x2000
#define KERNEL_LOAD_ADDR 0x01000000
#define INITRD_LOAD_ADDR 0x01800000
/* MacIO devices (mapped inside the MacIO address space): CUDA, DBDMA,
NVRAM (not implemented). */
static int dbdma_mem_index;
static int cuda_mem_index;
static int ide0_mem_index;
static int ide1_mem_index;
static int openpic_mem_index;
/* DBDMA: currently no op - should suffice right now */
static void dbdma_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
{
printf("%s: 0x%08x <= 0x%08x\n", __func__, addr, value);
}
static void dbdma_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
{
}
static void dbdma_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
{
}
static uint32_t dbdma_readb (void *opaque, target_phys_addr_t addr)
{
printf("%s: 0x%08x => 0x00000000\n", __func__, addr);
return 0;
}
static uint32_t dbdma_readw (void *opaque, target_phys_addr_t addr)
{
return 0;
}
static uint32_t dbdma_readl (void *opaque, target_phys_addr_t addr)
{
return 0;
}
static CPUWriteMemoryFunc *dbdma_write[] = {
&dbdma_writeb,
&dbdma_writew,
&dbdma_writel,
};
static CPUReadMemoryFunc *dbdma_read[] = {
&dbdma_readb,
&dbdma_readw,
&dbdma_readl,
};
static void macio_map(PCIDevice *pci_dev, int region_num,
uint32_t addr, uint32_t size, int type)
{
cpu_register_physical_memory(addr + 0x08000, 0x1000, dbdma_mem_index);
cpu_register_physical_memory(addr + 0x16000, 0x2000, cuda_mem_index);
cpu_register_physical_memory(addr + 0x1f000, 0x1000, ide0_mem_index);
cpu_register_physical_memory(addr + 0x20000, 0x1000, ide1_mem_index);
cpu_register_physical_memory(addr + 0x40000, 0x40000, openpic_mem_index);
}
static void macio_init(PCIBus *bus)
{
PCIDevice *d;
d = pci_register_device(bus, "macio", sizeof(PCIDevice),
-1, NULL, NULL);
/* Note: this code is strongly inspirated from the corresponding code
in PearPC */
d->config[0x00] = 0x6b; // vendor_id
d->config[0x01] = 0x10;
d->config[0x02] = 0x22;
d->config[0x03] = 0x00;
d->config[0x0a] = 0x00; // class_sub = pci2pci
d->config[0x0b] = 0xff; // class_base = bridge
d->config[0x0e] = 0x00; // header_type
d->config[0x3d] = 0x01; // interrupt on pin 1
dbdma_mem_index = cpu_register_io_memory(0, dbdma_read, dbdma_write, NULL);
pci_register_io_region(d, 0, 0x80000,
PCI_ADDRESS_SPACE_MEM, macio_map);
}
/* PowerPC PREP hardware initialisation */
void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device,
DisplayState *ds, const char **fd_filename, int snapshot,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename)
{
char buf[1024];
openpic_t *openpic;
m48t59_t *nvram;
int PPC_io_memory;
int ret, linux_boot, i;
unsigned long bios_offset;
uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
PCIBus *pci_bus;
linux_boot = (kernel_filename != NULL);
/* allocate RAM */
cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
/* allocate and load BIOS */
bios_offset = ram_size + vga_ram_size;
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
ret = load_image(buf, phys_ram_base + bios_offset);
if (ret != BIOS_SIZE) {
fprintf(stderr, "qemu: could not load PPC PREP bios '%s'\n", buf);
exit(1);
}
cpu_register_physical_memory((uint32_t)(-BIOS_SIZE),
BIOS_SIZE, bios_offset | IO_MEM_ROM);
cpu_single_env->nip = 0xfffffffc;
if (linux_boot) {
kernel_base = KERNEL_LOAD_ADDR;
/* now we can load the kernel */
kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base);
if (kernel_size < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
kernel_filename);
exit(1);
}
/* load initrd */
if (initrd_filename) {
initrd_base = INITRD_LOAD_ADDR;
initrd_size = load_image(initrd_filename,
phys_ram_base + initrd_base);
if (initrd_size < 0) {
fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
initrd_filename);
exit(1);
}
} else {
initrd_base = 0;
initrd_size = 0;
}
boot_device = 'm';
} else {
kernel_base = 0;
kernel_size = 0;
initrd_base = 0;
initrd_size = 0;
}
/* Register CPU as a 74x/75x */
cpu_ppc_register(cpu_single_env, 0x00080000);
/* Set time-base frequency to 100 Mhz */
cpu_ppc_tb_init(cpu_single_env, 100UL * 1000UL * 1000UL);
isa_mem_base = 0x80000000;
pci_bus = pci_pmac_init();
/* Register 8 MB of ISA IO space */
PPC_io_memory = cpu_register_io_memory(0, PPC_io_read, PPC_io_write, NULL);
cpu_register_physical_memory(0xF2000000, 0x00800000, PPC_io_memory);
/* init basic PC hardware */
vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size,
vga_ram_size);
openpic = openpic_init(NULL, &openpic_mem_index, 1);
pci_pmac_set_openpic(pci_bus, openpic);
/* XXX: suppress that */
pic_init();
/* XXX: use Mac Serial port */
serial_init(0x3f8, 4, serial_hds[0]);
for(i = 0; i < nb_nics; i++) {
pci_ne2000_init(pci_bus, &nd_table[i]);
}
ide0_mem_index = pmac_ide_init(&bs_table[0], openpic, 0x13);
ide1_mem_index = pmac_ide_init(&bs_table[2], openpic, 0x13);
/* cuda also initialize ADB */
cuda_mem_index = cuda_init(openpic, 0x19);
adb_kbd_init(&adb_bus);
adb_mouse_init(&adb_bus);
macio_init(pci_bus);
nvram = m48t59_init(8, 0xFFF04000, 0x0074, NVRAM_SIZE);
if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8)
graphic_depth = 15;
PPC_NVRAM_set_params(nvram, NVRAM_SIZE, "CHRP", ram_size, boot_device,
kernel_base, kernel_size,
kernel_cmdline,
initrd_base, initrd_size,
/* XXX: need an option to load a NVRAM image */
0,
graphic_width, graphic_height, graphic_depth);
/* No PCI init: the BIOS will do it */
}

548
hw/ppc_prep.c Normal file
View File

@@ -0,0 +1,548 @@
/*
* QEMU PPC PREP hardware System Emulator
*
* Copyright (c) 2003-2004 Jocelyn Mayer
*
* 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 "vl.h"
//#define HARD_DEBUG_PPC_IO
//#define DEBUG_PPC_IO
#define BIOS_FILENAME "ppc_rom.bin"
#define KERNEL_LOAD_ADDR 0x01000000
#define INITRD_LOAD_ADDR 0x01800000
extern int loglevel;
extern FILE *logfile;
#if defined (HARD_DEBUG_PPC_IO) && !defined (DEBUG_PPC_IO)
#define DEBUG_PPC_IO
#endif
#if defined (HARD_DEBUG_PPC_IO)
#define PPC_IO_DPRINTF(fmt, args...) \
do { \
if (loglevel & CPU_LOG_IOPORT) { \
fprintf(logfile, "%s: " fmt, __func__ , ##args); \
} else { \
printf("%s : " fmt, __func__ , ##args); \
} \
} while (0)
#elif defined (DEBUG_PPC_IO)
#define PPC_IO_DPRINTF(fmt, args...) \
do { \
if (loglevel & CPU_LOG_IOPORT) { \
fprintf(logfile, "%s: " fmt, __func__ , ##args); \
} \
} while (0)
#else
#define PPC_IO_DPRINTF(fmt, args...) do { } while (0)
#endif
/* Constants for devices init */
static const int ide_iobase[2] = { 0x1f0, 0x170 };
static const int ide_iobase2[2] = { 0x3f6, 0x376 };
static const int ide_irq[2] = { 13, 13 };
#define NE2000_NB_MAX 6
static uint32_t ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360, 0x280, 0x380 };
static int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
//static PITState *pit;
/* ISA IO ports bridge */
#define PPC_IO_BASE 0x80000000
/* Speaker port 0x61 */
int speaker_data_on;
int dummy_refresh_clock;
static void speaker_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
#if 0
speaker_data_on = (val >> 1) & 1;
pit_set_gate(pit, 2, val & 1);
#endif
}
static uint32_t speaker_ioport_read(void *opaque, uint32_t addr)
{
#if 0
int out;
out = pit_get_out(pit, 2, qemu_get_clock(vm_clock));
dummy_refresh_clock ^= 1;
return (speaker_data_on << 1) | pit_get_gate(pit, 2) | (out << 5) |
(dummy_refresh_clock << 4);
#endif
return 0;
}
/* PCI intack register */
/* Read-only register (?) */
static void _PPC_intack_write (void *opaque, target_phys_addr_t addr, uint32_t value)
{
// printf("%s: 0x%08x => 0x%08x\n", __func__, addr, value);
}
static inline uint32_t _PPC_intack_read (target_phys_addr_t addr)
{
uint32_t retval = 0;
if (addr == 0xBFFFFFF0)
retval = pic_intack_read(NULL);
// printf("%s: 0x%08x <= %d\n", __func__, addr, retval);
return retval;
}
static uint32_t PPC_intack_readb (void *opaque, target_phys_addr_t addr)
{
return _PPC_intack_read(addr);
}
static uint32_t PPC_intack_readw (void *opaque, target_phys_addr_t addr)
{
#ifdef TARGET_WORDS_BIGENDIAN
return bswap16(_PPC_intack_read(addr));
#else
return _PPC_intack_read(addr);
#endif
}
static uint32_t PPC_intack_readl (void *opaque, target_phys_addr_t addr)
{
#ifdef TARGET_WORDS_BIGENDIAN
return bswap32(_PPC_intack_read(addr));
#else
return _PPC_intack_read(addr);
#endif
}
static CPUWriteMemoryFunc *PPC_intack_write[] = {
&_PPC_intack_write,
&_PPC_intack_write,
&_PPC_intack_write,
};
static CPUReadMemoryFunc *PPC_intack_read[] = {
&PPC_intack_readb,
&PPC_intack_readw,
&PPC_intack_readl,
};
/* PowerPC control and status registers */
#if 0 // Not used
static struct {
/* IDs */
uint32_t veni_devi;
uint32_t revi;
/* Control and status */
uint32_t gcsr;
uint32_t xcfr;
uint32_t ct32;
uint32_t mcsr;
/* General purpose registers */
uint32_t gprg[6];
/* Exceptions */
uint32_t feen;
uint32_t fest;
uint32_t fema;
uint32_t fecl;
uint32_t eeen;
uint32_t eest;
uint32_t eecl;
uint32_t eeint;
uint32_t eemck0;
uint32_t eemck1;
/* Error diagnostic */
} XCSR;
static void PPC_XCSR_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
{
printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value);
}
static void PPC_XCSR_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
{
#ifdef TARGET_WORDS_BIGENDIAN
value = bswap16(value);
#endif
printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value);
}
static void PPC_XCSR_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
{
#ifdef TARGET_WORDS_BIGENDIAN
value = bswap32(value);
#endif
printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value);
}
static uint32_t PPC_XCSR_readb (void *opaque, target_phys_addr_t addr)
{
uint32_t retval = 0;
printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval);
return retval;
}
static uint32_t PPC_XCSR_readw (void *opaque, target_phys_addr_t addr)
{
uint32_t retval = 0;
printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval);
#ifdef TARGET_WORDS_BIGENDIAN
retval = bswap16(retval);
#endif
return retval;
}
static uint32_t PPC_XCSR_readl (void *opaque, target_phys_addr_t addr)
{
uint32_t retval = 0;
printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval);
#ifdef TARGET_WORDS_BIGENDIAN
retval = bswap32(retval);
#endif
return retval;
}
static CPUWriteMemoryFunc *PPC_XCSR_write[] = {
&PPC_XCSR_writeb,
&PPC_XCSR_writew,
&PPC_XCSR_writel,
};
static CPUReadMemoryFunc *PPC_XCSR_read[] = {
&PPC_XCSR_readb,
&PPC_XCSR_readw,
&PPC_XCSR_readl,
};
#endif
/* Fake super-io ports for PREP platform (Intel 82378ZB) */
typedef struct sysctrl_t {
m48t59_t *nvram;
uint8_t state;
uint8_t syscontrol;
uint8_t fake_io[2];
} sysctrl_t;
enum {
STATE_HARDFILE = 0x01,
};
static sysctrl_t *sysctrl;
static void PREP_io_write (void *opaque, uint32_t addr, uint32_t val)
{
sysctrl_t *sysctrl = opaque;
PPC_IO_DPRINTF("0x%08lx => 0x%08x\n", (long)addr - PPC_IO_BASE, val);
sysctrl->fake_io[addr - 0x0398] = val;
}
static uint32_t PREP_io_read (void *opaque, uint32_t addr)
{
sysctrl_t *sysctrl = opaque;
PPC_IO_DPRINTF("0x%08lx <= 0x%08x\n", (long)addr - PPC_IO_BASE,
sysctrl->fake_io[addr - 0x0398]);
return sysctrl->fake_io[addr - 0x0398];
}
static void PREP_io_800_writeb (void *opaque, uint32_t addr, uint32_t val)
{
sysctrl_t *sysctrl = opaque;
PPC_IO_DPRINTF("0x%08lx => 0x%08x\n", (long)addr - PPC_IO_BASE, val);
switch (addr) {
case 0x0092:
/* Special port 92 */
/* Check soft reset asked */
if (val & 0x01) {
// cpu_interrupt(cpu_single_env, CPU_INTERRUPT_RESET);
}
/* Check LE mode */
if (val & 0x02) {
printf("Little Endian mode isn't supported (yet ?)\n");
abort();
}
break;
case 0x0800:
/* Motorola CPU configuration register : read-only */
break;
case 0x0802:
/* Motorola base module feature register : read-only */
break;
case 0x0803:
/* Motorola base module status register : read-only */
break;
case 0x0808:
/* Hardfile light register */
if (val & 1)
sysctrl->state |= STATE_HARDFILE;
else
sysctrl->state &= ~STATE_HARDFILE;
break;
case 0x0810:
/* Password protect 1 register */
if (sysctrl->nvram != NULL)
m48t59_toggle_lock(sysctrl->nvram, 1);
break;
case 0x0812:
/* Password protect 2 register */
if (sysctrl->nvram != NULL)
m48t59_toggle_lock(sysctrl->nvram, 2);
break;
case 0x0814:
/* L2 invalidate register */
// tlb_flush(cpu_single_env, 1);
break;
case 0x081C:
/* system control register */
sysctrl->syscontrol = val & 0x0F;
break;
case 0x0850:
/* I/O map type register */
if (!(val & 0x01)) {
printf("No support for non-continuous I/O map mode\n");
abort();
}
break;
default:
printf("ERROR: unaffected IO port write: %04lx => %02x\n",
(long)addr, val);
break;
}
}
static uint32_t PREP_io_800_readb (void *opaque, uint32_t addr)
{
sysctrl_t *sysctrl = opaque;
uint32_t retval = 0xFF;
switch (addr) {
case 0x0092:
/* Special port 92 */
retval = 0x00;
break;
case 0x0800:
/* Motorola CPU configuration register */
retval = 0xEF; /* MPC750 */
break;
case 0x0802:
/* Motorola Base module feature register */
retval = 0xAD; /* No ESCC, PMC slot neither ethernet */
break;
case 0x0803:
/* Motorola base module status register */
retval = 0xE0; /* Standard MPC750 */
break;
case 0x080C:
/* Equipment present register:
* no L2 cache
* no upgrade processor
* no cards in PCI slots
* SCSI fuse is bad
*/
retval = 0x3C;
break;
case 0x0810:
/* Motorola base module extended feature register */
retval = 0x39; /* No USB, CF and PCI bridge. NVRAM present */
break;
case 0x0818:
/* Keylock */
retval = 0x00;
break;
case 0x081C:
/* system control register
* 7 - 6 / 1 - 0: L2 cache enable
*/
retval = sysctrl->syscontrol;
break;
case 0x0823:
/* */
retval = 0x03; /* no L2 cache */
break;
case 0x0850:
/* I/O map type register */
retval = 0x01;
break;
default:
printf("ERROR: unaffected IO port: %04lx read\n", (long)addr);
break;
}
PPC_IO_DPRINTF("0x%08lx <= 0x%08x\n", (long)addr - PPC_IO_BASE, retval);
return retval;
}
extern CPUPPCState *global_env;
#define NVRAM_SIZE 0x2000
/* PowerPC PREP hardware initialisation */
void ppc_prep_init(int ram_size, int vga_ram_size, int boot_device,
DisplayState *ds, const char **fd_filename, int snapshot,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename)
{
char buf[1024];
m48t59_t *nvram;
int PPC_io_memory;
int ret, linux_boot, i, nb_nics1;
unsigned long bios_offset;
uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
PCIBus *pci_bus;
sysctrl = qemu_mallocz(sizeof(sysctrl_t));
if (sysctrl == NULL)
return;
linux_boot = (kernel_filename != NULL);
/* allocate RAM */
cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
/* allocate and load BIOS */
bios_offset = ram_size + vga_ram_size;
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
ret = load_image(buf, phys_ram_base + bios_offset);
if (ret != BIOS_SIZE) {
fprintf(stderr, "qemu: could not load PPC PREP bios '%s'\n", buf);
exit(1);
}
cpu_register_physical_memory((uint32_t)(-BIOS_SIZE),
BIOS_SIZE, bios_offset | IO_MEM_ROM);
cpu_single_env->nip = 0xfffffffc;
if (linux_boot) {
kernel_base = KERNEL_LOAD_ADDR;
/* now we can load the kernel */
kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base);
if (kernel_size < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
kernel_filename);
exit(1);
}
/* load initrd */
if (initrd_filename) {
initrd_base = INITRD_LOAD_ADDR;
initrd_size = load_image(initrd_filename,
phys_ram_base + initrd_base);
if (initrd_size < 0) {
fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
initrd_filename);
exit(1);
}
} else {
initrd_base = 0;
initrd_size = 0;
}
boot_device = 'm';
} else {
kernel_base = 0;
kernel_size = 0;
initrd_base = 0;
initrd_size = 0;
}
/* Register CPU as a 74x/75x */
cpu_ppc_register(cpu_single_env, 0x00080000);
/* Set time-base frequency to 100 Mhz */
cpu_ppc_tb_init(cpu_single_env, 100UL * 1000UL * 1000UL);
isa_mem_base = 0xc0000000;
pci_bus = pci_prep_init();
/* Register 64 KB of ISA IO space */
PPC_io_memory = cpu_register_io_memory(0, PPC_io_read, PPC_io_write, NULL);
cpu_register_physical_memory(0x80000000, 0x00010000, PPC_io_memory);
/* init basic PC hardware */
vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size,
vga_ram_size);
rtc_init(0x70, 8);
// openpic = openpic_init(0x00000000, 0xF0000000, 1);
// pic_init(openpic);
pic_init();
// pit = pit_init(0x40, 0);
serial_init(0x3f8, 4, serial_hds[0]);
nb_nics1 = nb_nics;
if (nb_nics1 > NE2000_NB_MAX)
nb_nics1 = NE2000_NB_MAX;
for(i = 0; i < nb_nics1; i++) {
isa_ne2000_init(ne2000_io[i], ne2000_irq[i], &nd_table[i]);
}
for(i = 0; i < 2; i++) {
isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
bs_table[2 * i], bs_table[2 * i + 1]);
}
kbd_init();
DMA_init(1);
// AUD_init();
// SB16_init();
fdctrl_init(6, 2, 0, 0x3f0, fd_table);
/* Register speaker port */
register_ioport_read(0x61, 1, 1, speaker_ioport_read, NULL);
register_ioport_write(0x61, 1, 1, speaker_ioport_write, NULL);
/* Register fake IO ports for PREP */
register_ioport_read(0x398, 2, 1, &PREP_io_read, sysctrl);
register_ioport_write(0x398, 2, 1, &PREP_io_write, sysctrl);
/* System control ports */
register_ioport_read(0x0092, 0x01, 1, &PREP_io_800_readb, sysctrl);
register_ioport_write(0x0092, 0x01, 1, &PREP_io_800_writeb, sysctrl);
register_ioport_read(0x0800, 0x52, 1, &PREP_io_800_readb, sysctrl);
register_ioport_write(0x0800, 0x52, 1, &PREP_io_800_writeb, sysctrl);
/* PCI intack location */
PPC_io_memory = cpu_register_io_memory(0, PPC_intack_read,
PPC_intack_write, NULL);
cpu_register_physical_memory(0xBFFFFFF0, 0x4, PPC_io_memory);
/* PowerPC control and status register group */
#if 0
PPC_io_memory = cpu_register_io_memory(0, PPC_XCSR_read, PPC_XCSR_write, NULL);
cpu_register_physical_memory(0xFEFF0000, 0x1000, PPC_io_memory);
#endif
nvram = m48t59_init(8, 0, 0x0074, NVRAM_SIZE);
if (nvram == NULL)
return;
sysctrl->nvram = nvram;
/* Initialise NVRAM */
PPC_NVRAM_set_params(nvram, NVRAM_SIZE, "PREP", ram_size, boot_device,
kernel_base, kernel_size,
kernel_cmdline,
initrd_base, initrd_size,
/* XXX: need an option to load a NVRAM image */
0,
graphic_width, graphic_height, graphic_depth);
}

1268
hw/sb16.c Normal file

File diff suppressed because it is too large Load Diff

268
hw/sched.c Normal file
View File

@@ -0,0 +1,268 @@
/*
* QEMU interrupt controller emulation
*
* Copyright (c) 2003-2004 Fabrice Bellard
*
* 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 "vl.h"
//#define DEBUG_IRQ_COUNT
/* These registers are used for sending/receiving irqs from/to
* different cpu's.
*/
struct sun4m_intreg_percpu {
unsigned int tbt; /* Intrs pending for this cpu, by PIL. */
/* These next two registers are WRITE-ONLY and are only
* "on bit" sensitive, "off bits" written have NO affect.
*/
unsigned int clear; /* Clear this cpus irqs here. */
unsigned int set; /* Set this cpus irqs here. */
};
/*
* djhr
* Actually the clear and set fields in this struct are misleading..
* according to the SLAVIO manual (and the same applies for the SEC)
* the clear field clears bits in the mask which will ENABLE that IRQ
* the set field sets bits in the mask to DISABLE the IRQ.
*
* Also the undirected_xx address in the SLAVIO is defined as
* RESERVED and write only..
*
* DAVEM_NOTE: The SLAVIO only specifies behavior on uniprocessor
* sun4m machines, for MP the layout makes more sense.
*/
struct sun4m_intreg_master {
unsigned int tbt; /* IRQ's that are pending, see sun4m masks. */
unsigned int irqs; /* Master IRQ bits. */
/* Again, like the above, two these registers are WRITE-ONLY. */
unsigned int clear; /* Clear master IRQ's by setting bits here. */
unsigned int set; /* Set master IRQ's by setting bits here. */
/* This register is both READ and WRITE. */
unsigned int undirected_target; /* Which cpu gets undirected irqs. */
};
#define SUN4M_INT_ENABLE 0x80000000
#define SUN4M_INT_E14 0x00000080
#define SUN4M_INT_E10 0x00080000
#define SUN4M_HARD_INT(x) (0x000000001 << (x))
#define SUN4M_SOFT_INT(x) (0x000010000 << (x))
#define SUN4M_INT_MASKALL 0x80000000 /* mask all interrupts */
#define SUN4M_INT_MODULE_ERR 0x40000000 /* module error */
#define SUN4M_INT_M2S_WRITE 0x20000000 /* write buffer error */
#define SUN4M_INT_ECC 0x10000000 /* ecc memory error */
#define SUN4M_INT_FLOPPY 0x00400000 /* floppy disk */
#define SUN4M_INT_MODULE 0x00200000 /* module interrupt */
#define SUN4M_INT_VIDEO 0x00100000 /* onboard video */
#define SUN4M_INT_REALTIME 0x00080000 /* system timer */
#define SUN4M_INT_SCSI 0x00040000 /* onboard scsi */
#define SUN4M_INT_AUDIO 0x00020000 /* audio/isdn */
#define SUN4M_INT_ETHERNET 0x00010000 /* onboard ethernet */
#define SUN4M_INT_SERIAL 0x00008000 /* serial ports */
#define SUN4M_INT_SBUSBITS 0x00003F80 /* sbus int bits */
#define SUN4M_INT_SBUS(x) (1 << (x+7))
#define SUN4M_INT_VME(x) (1 << (x))
typedef struct SCHEDState {
uint32_t addr, addrg;
uint32_t intreg_pending;
uint32_t intreg_enabled;
uint32_t intregm_pending;
uint32_t intregm_enabled;
} SCHEDState;
static SCHEDState *ps;
#ifdef DEBUG_IRQ_COUNT
static uint64_t irq_count[32];
#endif
static uint32_t intreg_mem_readl(void *opaque, target_phys_addr_t addr)
{
SCHEDState *s = opaque;
uint32_t saddr;
saddr = (addr - s->addr) >> 2;
switch (saddr) {
case 0:
return s->intreg_pending;
break;
default:
break;
}
return 0;
}
static void intreg_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
SCHEDState *s = opaque;
uint32_t saddr;
saddr = (addr - s->addr) >> 2;
switch (saddr) {
case 0:
s->intreg_pending = val;
break;
case 1: // clear
s->intreg_enabled &= ~val;
break;
case 2: // set
s->intreg_enabled |= val;
break;
default:
break;
}
}
static CPUReadMemoryFunc *intreg_mem_read[3] = {
intreg_mem_readl,
intreg_mem_readl,
intreg_mem_readl,
};
static CPUWriteMemoryFunc *intreg_mem_write[3] = {
intreg_mem_writel,
intreg_mem_writel,
intreg_mem_writel,
};
static uint32_t intregm_mem_readl(void *opaque, target_phys_addr_t addr)
{
SCHEDState *s = opaque;
uint32_t saddr;
saddr = (addr - s->addrg) >> 2;
switch (saddr) {
case 0:
return s->intregm_pending;
break;
case 1:
return s->intregm_enabled;
break;
default:
break;
}
return 0;
}
static void intregm_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
SCHEDState *s = opaque;
uint32_t saddr;
saddr = (addr - s->addrg) >> 2;
switch (saddr) {
case 0:
s->intregm_pending = val;
break;
case 1:
s->intregm_enabled = val;
break;
case 2: // clear
s->intregm_enabled &= ~val;
break;
case 3: // set
s->intregm_enabled |= val;
break;
default:
break;
}
}
static CPUReadMemoryFunc *intregm_mem_read[3] = {
intregm_mem_readl,
intregm_mem_readl,
intregm_mem_readl,
};
static CPUWriteMemoryFunc *intregm_mem_write[3] = {
intregm_mem_writel,
intregm_mem_writel,
intregm_mem_writel,
};
void pic_info(void)
{
term_printf("per-cpu: pending 0x%08x, enabled 0x%08x\n", ps->intreg_pending, ps->intreg_enabled);
term_printf("master: pending 0x%08x, enabled 0x%08x\n", ps->intregm_pending, ps->intregm_enabled);
}
void irq_info(void)
{
#ifndef DEBUG_IRQ_COUNT
term_printf("irq statistic code not compiled.\n");
#else
int i;
int64_t count;
term_printf("IRQ statistics:\n");
for (i = 0; i < 32; i++) {
count = irq_count[i];
if (count > 0)
term_printf("%2d: %lld\n", i, count);
}
#endif
}
static const unsigned int intr_to_mask[16] = {
0, 0, 0, 0, 0, 0, SUN4M_INT_ETHERNET, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
void pic_set_irq(int irq, int level)
{
if (irq < 16) {
unsigned int mask = intr_to_mask[irq];
ps->intreg_pending |= 1 << irq;
if (ps->intregm_enabled & mask) {
cpu_single_env->interrupt_index = irq;
cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
}
}
#ifdef DEBUG_IRQ_COUNT
if (level == 1)
irq_count[irq]++;
#endif
}
void sched_init(uint32_t addr, uint32_t addrg)
{
int intreg_io_memory, intregm_io_memory;
SCHEDState *s;
s = qemu_mallocz(sizeof(SCHEDState));
if (!s)
return;
s->addr = addr;
s->addrg = addrg;
intreg_io_memory = cpu_register_io_memory(0, intreg_mem_read, intreg_mem_write, s);
cpu_register_physical_memory(addr, 3, intreg_io_memory);
intregm_io_memory = cpu_register_io_memory(0, intregm_mem_read, intregm_mem_write, s);
cpu_register_physical_memory(addrg, 5, intregm_io_memory);
ps = s;
}

279
hw/serial.c Normal file
View File

@@ -0,0 +1,279 @@
/*
* QEMU 16450 UART emulation
*
* Copyright (c) 2003-2004 Fabrice Bellard
*
* 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 "vl.h"
//#define DEBUG_SERIAL
#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
#define UART_IER_MSI 0x08 /* Enable Modem status interrupt */
#define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */
#define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */
#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */
#define UART_IIR_NO_INT 0x01 /* No interrupts pending */
#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */
#define UART_IIR_MSI 0x00 /* Modem status interrupt */
#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */
#define UART_IIR_RDI 0x04 /* Receiver data interrupt */
#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */
/*
* These are the definitions for the Modem Control Register
*/
#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
#define UART_MCR_OUT2 0x08 /* Out2 complement */
#define UART_MCR_OUT1 0x04 /* Out1 complement */
#define UART_MCR_RTS 0x02 /* RTS complement */
#define UART_MCR_DTR 0x01 /* DTR complement */
/*
* These are the definitions for the Modem Status Register
*/
#define UART_MSR_DCD 0x80 /* Data Carrier Detect */
#define UART_MSR_RI 0x40 /* Ring Indicator */
#define UART_MSR_DSR 0x20 /* Data Set Ready */
#define UART_MSR_CTS 0x10 /* Clear to Send */
#define UART_MSR_DDCD 0x08 /* Delta DCD */
#define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */
#define UART_MSR_DDSR 0x02 /* Delta DSR */
#define UART_MSR_DCTS 0x01 /* Delta CTS */
#define UART_MSR_ANY_DELTA 0x0F /* Any of the delta bits! */
#define UART_LSR_TEMT 0x40 /* Transmitter empty */
#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
#define UART_LSR_BI 0x10 /* Break interrupt indicator */
#define UART_LSR_FE 0x08 /* Frame error indicator */
#define UART_LSR_PE 0x04 /* Parity error indicator */
#define UART_LSR_OE 0x02 /* Overrun error indicator */
#define UART_LSR_DR 0x01 /* Receiver data ready */
struct SerialState {
uint8_t divider;
uint8_t rbr; /* receive register */
uint8_t ier;
uint8_t iir; /* read only */
uint8_t lcr;
uint8_t mcr;
uint8_t lsr; /* read only */
uint8_t msr;
uint8_t scr;
/* NOTE: this hidden state is necessary for tx irq generation as
it can be reset while reading iir */
int thr_ipending;
int irq;
CharDriverState *chr;
};
static void serial_update_irq(SerialState *s)
{
if ((s->lsr & UART_LSR_DR) && (s->ier & UART_IER_RDI)) {
s->iir = UART_IIR_RDI;
} else if (s->thr_ipending && (s->ier & UART_IER_THRI)) {
s->iir = UART_IIR_THRI;
} else {
s->iir = UART_IIR_NO_INT;
}
if (s->iir != UART_IIR_NO_INT) {
pic_set_irq(s->irq, 1);
} else {
pic_set_irq(s->irq, 0);
}
}
static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
SerialState *s = opaque;
unsigned char ch;
addr &= 7;
#ifdef DEBUG_SERIAL
printf("serial: write addr=0x%02x val=0x%02x\n", addr, val);
#endif
switch(addr) {
default:
case 0:
if (s->lcr & UART_LCR_DLAB) {
s->divider = (s->divider & 0xff00) | val;
} else {
s->thr_ipending = 0;
s->lsr &= ~UART_LSR_THRE;
serial_update_irq(s);
ch = val;
qemu_chr_write(s->chr, &ch, 1);
s->thr_ipending = 1;
s->lsr |= UART_LSR_THRE;
s->lsr |= UART_LSR_TEMT;
serial_update_irq(s);
}
break;
case 1:
if (s->lcr & UART_LCR_DLAB) {
s->divider = (s->divider & 0x00ff) | (val << 8);
} else {
s->ier = val & 0x0f;
if (s->lsr & UART_LSR_THRE) {
s->thr_ipending = 1;
}
serial_update_irq(s);
}
break;
case 2:
break;
case 3:
s->lcr = val;
break;
case 4:
s->mcr = val & 0x1f;
break;
case 5:
break;
case 6:
s->msr = val;
break;
case 7:
s->scr = val;
break;
}
}
static uint32_t serial_ioport_read(void *opaque, uint32_t addr)
{
SerialState *s = opaque;
uint32_t ret;
addr &= 7;
switch(addr) {
default:
case 0:
if (s->lcr & UART_LCR_DLAB) {
ret = s->divider & 0xff;
} else {
ret = s->rbr;
s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
serial_update_irq(s);
}
break;
case 1:
if (s->lcr & UART_LCR_DLAB) {
ret = (s->divider >> 8) & 0xff;
} else {
ret = s->ier;
}
break;
case 2:
ret = s->iir;
/* reset THR pending bit */
if ((ret & 0x7) == UART_IIR_THRI)
s->thr_ipending = 0;
serial_update_irq(s);
break;
case 3:
ret = s->lcr;
break;
case 4:
ret = s->mcr;
break;
case 5:
ret = s->lsr;
break;
case 6:
if (s->mcr & UART_MCR_LOOP) {
/* in loopback, the modem output pins are connected to the
inputs */
ret = (s->mcr & 0x0c) << 4;
ret |= (s->mcr & 0x02) << 3;
ret |= (s->mcr & 0x01) << 5;
} else {
ret = s->msr;
}
break;
case 7:
ret = s->scr;
break;
}
#ifdef DEBUG_SERIAL
printf("serial: read addr=0x%02x val=0x%02x\n", addr, ret);
#endif
return ret;
}
static int serial_can_receive(SerialState *s)
{
return !(s->lsr & UART_LSR_DR);
}
static void serial_receive_byte(SerialState *s, int ch)
{
s->rbr = ch;
s->lsr |= UART_LSR_DR;
serial_update_irq(s);
}
static void serial_receive_break(SerialState *s)
{
s->rbr = 0;
s->lsr |= UART_LSR_BI | UART_LSR_DR;
serial_update_irq(s);
}
static int serial_can_receive1(void *opaque)
{
SerialState *s = opaque;
return serial_can_receive(s);
}
static void serial_receive1(void *opaque, const uint8_t *buf, int size)
{
SerialState *s = opaque;
serial_receive_byte(s, buf[0]);
}
static void serial_event(void *opaque, int event)
{
SerialState *s = opaque;
if (event == CHR_EVENT_BREAK)
serial_receive_break(s);
}
/* If fd is zero, it means that the serial device uses the console */
SerialState *serial_init(int base, int irq, CharDriverState *chr)
{
SerialState *s;
s = qemu_mallocz(sizeof(SerialState));
if (!s)
return NULL;
s->irq = irq;
s->lsr = UART_LSR_TEMT | UART_LSR_THRE;
s->iir = UART_IIR_NO_INT;
register_ioport_write(base, 8, 1, serial_ioport_write, s);
register_ioport_read(base, 8, 1, serial_ioport_read, s);
s->chr = chr;
qemu_chr_add_read_handler(chr, serial_can_receive1, serial_receive1, s);
qemu_chr_add_event_handler(chr, serial_event);
return s;
}

113
hw/sun4m.c Normal file
View File

@@ -0,0 +1,113 @@
/*
* QEMU Sun4m System Emulator
*
* Copyright (c) 2003-2004 Fabrice Bellard
*
* 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 "vl.h"
#include "m48t08.h"
#define KERNEL_LOAD_ADDR 0x00004000
#define MMU_CONTEXT_TBL 0x00003000
#define MMU_L1PTP (MMU_CONTEXT_TBL + 0x0400)
#define MMU_L2PTP (MMU_CONTEXT_TBL + 0x0800)
#define PROM_ADDR 0xffd04000
#define PROM_FILENAMEB "proll.bin"
#define PROM_FILENAMEE "proll.elf"
#define PROLL_MAGIC_ADDR 0x20000000
#define PHYS_JJ_EEPROM 0x71200000 /* [2000] MK48T08 */
#define PHYS_JJ_IDPROM_OFF 0x1FD8
#define PHYS_JJ_EEPROM_SIZE 0x2000
#define PHYS_JJ_IOMMU 0x10000000 /* First page of sun4m IOMMU */
#define PHYS_JJ_TCX_FB 0x50800000 /* Start address, frame buffer body */
#define PHYS_JJ_TCX_0E 0x5E000000 /* Top address, one byte used. */
#define PHYS_JJ_IOMMU 0x10000000 /* First page of sun4m IOMMU */
#define PHYS_JJ_LEDMA 0x78400010 /* ledma, off by 10 from unused SCSI */
#define PHYS_JJ_LE 0x78C00000 /* LANCE, typical sun4m */
#define PHYS_JJ_LE_IRQ 6
#define PHYS_JJ_CLOCK 0x71D00000
#define PHYS_JJ_CLOCK_IRQ 10
#define PHYS_JJ_CLOCK1 0x71D10000
#define PHYS_JJ_CLOCK1_IRQ 14
#define PHYS_JJ_INTR0 0x71E00000 /* CPU0 interrupt control registers */
#define PHYS_JJ_INTR_G 0x71E10000 /* Master interrupt control registers */
/* TSC handling */
uint64_t cpu_get_tsc()
{
return qemu_get_clock(vm_clock);
}
void DMA_run() {}
void SB16_run() {}
int serial_can_receive(SerialState *s) { return 0; }
void serial_receive_byte(SerialState *s, int ch) {}
void serial_receive_break(SerialState *s) {}
static m48t08_t *nvram;
/* Sun4m hardware initialisation */
void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
DisplayState *ds, const char **fd_filename, int snapshot,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename)
{
char buf[1024];
int ret, linux_boot;
unsigned long bios_offset;
linux_boot = (kernel_filename != NULL);
/* allocate RAM */
cpu_register_physical_memory(0, ram_size, 0);
bios_offset = ram_size;
iommu_init(PHYS_JJ_IOMMU);
sched_init(PHYS_JJ_INTR0, PHYS_JJ_INTR_G);
tcx_init(ds, PHYS_JJ_TCX_FB);
lance_init(&nd_table[0], PHYS_JJ_LE_IRQ, PHYS_JJ_LE, PHYS_JJ_LEDMA);
nvram = m48t08_init(PHYS_JJ_EEPROM, PHYS_JJ_EEPROM_SIZE, &nd_table[0].macaddr);
timer_init(PHYS_JJ_CLOCK, PHYS_JJ_CLOCK_IRQ);
timer_init(PHYS_JJ_CLOCK1, PHYS_JJ_CLOCK1_IRQ);
magic_init(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR, PROLL_MAGIC_ADDR);
/* We load Proll as the kernel and start it. It will issue a magic
IO to load the real kernel */
if (linux_boot) {
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEB);
ret = load_kernel(buf,
phys_ram_base + KERNEL_LOAD_ADDR);
if (ret < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
buf);
exit(1);
}
}
/* Setup a MMU entry for entire address space */
stl_raw(phys_ram_base + MMU_CONTEXT_TBL, (MMU_L1PTP >> 4) | 1);
stl_raw(phys_ram_base + MMU_L1PTP, (MMU_L2PTP >> 4) | 1);
stl_raw(phys_ram_base + MMU_L1PTP + (0x01 << 2), (MMU_L2PTP >> 4) | 1); // 01.. == 00..
stl_raw(phys_ram_base + MMU_L1PTP + (0xff << 2), (MMU_L2PTP >> 4) | 1); // ff.. == 00..
stl_raw(phys_ram_base + MMU_L1PTP + (0xf0 << 2), (MMU_L2PTP >> 4) | 1); // f0.. == 00..
/* 3 = U:RWX S:RWX */
stl_raw(phys_ram_base + MMU_L2PTP, (3 << PTE_ACCESS_SHIFT) | 2);
stl_raw(phys_ram_base + MMU_L2PTP, ((0x01 << PTE_PPN_SHIFT) >> 4 ) | (3 << PTE_ACCESS_SHIFT) | 2);
}

207
hw/tcx.c Normal file
View File

@@ -0,0 +1,207 @@
/*
* QEMU Sun4m System Emulator
*
* Copyright (c) 2003-2004 Fabrice Bellard
*
* 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 "vl.h"
#define MAXX 1024
#define MAXY 768
#define XSZ (8*80)
#define YSZ (24*11)
#define XOFF (MAXX-XSZ)
#define YOFF (MAXY-YSZ)
typedef struct TCXState {
uint32_t addr;
DisplayState *ds;
uint8_t *vram;
} TCXState;
static TCXState *ts;
void vga_update_display()
{
dpy_update(ts->ds, 0, 0, XSZ, YSZ);
}
void vga_invalidate_display() {}
static uint32_t tcx_mem_readb(void *opaque, target_phys_addr_t addr)
{
TCXState *s = opaque;
uint32_t saddr;
unsigned int x, y;
saddr = addr - s->addr - YOFF*MAXX - XOFF;
y = saddr / MAXX;
x = saddr - y * MAXX;
if (x < XSZ && y < YSZ) {
return s->vram[y * XSZ + x];
}
return 0;
}
static uint32_t tcx_mem_readw(void *opaque, target_phys_addr_t addr)
{
uint32_t v;
#ifdef TARGET_WORDS_BIGENDIAN
v = tcx_mem_readb(opaque, addr) << 8;
v |= tcx_mem_readb(opaque, addr + 1);
#else
v = tcx_mem_readb(opaque, addr);
v |= tcx_mem_readb(opaque, addr + 1) << 8;
#endif
return v;
}
static uint32_t tcx_mem_readl(void *opaque, target_phys_addr_t addr)
{
uint32_t v;
#ifdef TARGET_WORDS_BIGENDIAN
v = tcx_mem_readb(opaque, addr) << 24;
v |= tcx_mem_readb(opaque, addr + 1) << 16;
v |= tcx_mem_readb(opaque, addr + 2) << 8;
v |= tcx_mem_readb(opaque, addr + 3);
#else
v = tcx_mem_readb(opaque, addr);
v |= tcx_mem_readb(opaque, addr + 1) << 8;
v |= tcx_mem_readb(opaque, addr + 2) << 16;
v |= tcx_mem_readb(opaque, addr + 3) << 24;
#endif
return v;
}
static void tcx_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
{
TCXState *s = opaque;
uint32_t saddr;
unsigned int x, y;
char *sptr;
saddr = addr - s->addr - YOFF*MAXX - XOFF;
y = saddr / MAXX;
x = saddr - y * MAXX;
if (x < XSZ && y < YSZ) {
sptr = s->ds->data;
if (sptr) {
if (s->ds->depth == 24 || s->ds->depth == 32) {
/* XXX need to do CLUT translation */
sptr[y * s->ds->linesize + x*4] = val & 0xff;
sptr[y * s->ds->linesize + x*4+1] = val & 0xff;
sptr[y * s->ds->linesize + x*4+2] = val & 0xff;
}
else if (s->ds->depth == 8) {
sptr[y * s->ds->linesize + x] = val & 0xff;
}
}
cpu_physical_memory_set_dirty(addr);
s->vram[y * XSZ + x] = val & 0xff;
}
}
static void tcx_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
{
#ifdef TARGET_WORDS_BIGENDIAN
tcx_mem_writeb(opaque, addr, (val >> 8) & 0xff);
tcx_mem_writeb(opaque, addr + 1, val & 0xff);
#else
tcx_mem_writeb(opaque, addr, val & 0xff);
tcx_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
#endif
}
static void tcx_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
#ifdef TARGET_WORDS_BIGENDIAN
tcx_mem_writeb(opaque, addr, (val >> 24) & 0xff);
tcx_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
tcx_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
tcx_mem_writeb(opaque, addr + 3, val & 0xff);
#else
tcx_mem_writeb(opaque, addr, val & 0xff);
tcx_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
tcx_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
tcx_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
#endif
}
static CPUReadMemoryFunc *tcx_mem_read[3] = {
tcx_mem_readb,
tcx_mem_readw,
tcx_mem_readl,
};
static CPUWriteMemoryFunc *tcx_mem_write[3] = {
tcx_mem_writeb,
tcx_mem_writew,
tcx_mem_writel,
};
void tcx_init(DisplayState *ds, uint32_t addr)
{
TCXState *s;
int tcx_io_memory;
s = qemu_mallocz(sizeof(TCXState));
if (!s)
return;
s->ds = ds;
s->addr = addr;
ts = s;
tcx_io_memory = cpu_register_io_memory(0, tcx_mem_read, tcx_mem_write, s);
cpu_register_physical_memory(addr, 0x100000,
tcx_io_memory);
s->vram = qemu_mallocz(XSZ*YSZ);
dpy_resize(s->ds, XSZ, YSZ);
}
void vga_screen_dump(const char *filename)
{
TCXState *s = ts;
FILE *f;
uint8_t *d, *d1;
unsigned int v;
int y, x;
f = fopen(filename, "wb");
if (!f)
return -1;
fprintf(f, "P6\n%d %d\n%d\n",
XSZ, YSZ, 255);
d1 = s->vram;
for(y = 0; y < YSZ; y++) {
d = d1;
for(x = 0; x < XSZ; x++) {
v = *d;
fputc((v) & 0xff, f);
fputc((v) & 0xff, f);
fputc((v) & 0xff, f);
d++;
}
d1 += XSZ;
}
fclose(f);
return;
}

97
hw/timer.c Normal file
View File

@@ -0,0 +1,97 @@
/*
* QEMU Sparc timer controller emulation
*
* Copyright (c) 2003-2004 Fabrice Bellard
*
* 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 "vl.h"
/*
* Registers of hardware timer in sun4m.
*/
struct sun4m_timer_percpu {
volatile unsigned int l14_timer_limit; /* Initial value is 0x009c4000 */
volatile unsigned int l14_cur_count;
};
struct sun4m_timer_global {
volatile unsigned int l10_timer_limit;
volatile unsigned int l10_cur_count;
};
typedef struct TIMERState {
uint32_t addr;
uint32_t timer_regs[2];
int irq;
} TIMERState;
static uint32_t timer_mem_readl(void *opaque, target_phys_addr_t addr)
{
TIMERState *s = opaque;
uint32_t saddr;
saddr = (addr - s->addr) >> 2;
switch (saddr) {
default:
return s->timer_regs[saddr];
break;
}
return 0;
}
static void timer_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
TIMERState *s = opaque;
uint32_t saddr;
saddr = (addr - s->addr) >> 2;
switch (saddr) {
default:
s->timer_regs[saddr] = val;
break;
}
}
static CPUReadMemoryFunc *timer_mem_read[3] = {
timer_mem_readl,
timer_mem_readl,
timer_mem_readl,
};
static CPUWriteMemoryFunc *timer_mem_write[3] = {
timer_mem_writel,
timer_mem_writel,
timer_mem_writel,
};
void timer_init(uint32_t addr, int irq)
{
int timer_io_memory;
TIMERState *s;
s = qemu_mallocz(sizeof(TIMERState));
if (!s)
return;
s->addr = addr;
s->irq = irq;
timer_io_memory = cpu_register_io_memory(0, timer_mem_read, timer_mem_write, s);
cpu_register_physical_memory(addr, 2, timer_io_memory);
}

1925
hw/vga.c Normal file

File diff suppressed because it is too large Load Diff

168
hw/vga_int.h Normal file
View File

@@ -0,0 +1,168 @@
/*
* QEMU internal VGA defines.
*
* Copyright (c) 2003-2004 Fabrice Bellard
*
* 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.
*/
#define MSR_COLOR_EMULATION 0x01
#define MSR_PAGE_SELECT 0x20
#define ST01_V_RETRACE 0x08
#define ST01_DISP_ENABLE 0x01
/* bochs VBE support */
#define CONFIG_BOCHS_VBE
#define VBE_DISPI_MAX_XRES 1024
#define VBE_DISPI_MAX_YRES 768
#define VBE_DISPI_INDEX_ID 0x0
#define VBE_DISPI_INDEX_XRES 0x1
#define VBE_DISPI_INDEX_YRES 0x2
#define VBE_DISPI_INDEX_BPP 0x3
#define VBE_DISPI_INDEX_ENABLE 0x4
#define VBE_DISPI_INDEX_BANK 0x5
#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6
#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
#define VBE_DISPI_INDEX_X_OFFSET 0x8
#define VBE_DISPI_INDEX_Y_OFFSET 0x9
#define VBE_DISPI_INDEX_NB 0xa
#define VBE_DISPI_ID0 0xB0C0
#define VBE_DISPI_ID1 0xB0C1
#define VBE_DISPI_ID2 0xB0C2
#define VBE_DISPI_DISABLED 0x00
#define VBE_DISPI_ENABLED 0x01
#define VBE_DISPI_LFB_ENABLED 0x40
#define VBE_DISPI_NOCLEARMEM 0x80
#define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000
#ifdef CONFIG_BOCHS_VBE
#define VGA_STATE_COMMON_BOCHS_VBE \
uint16_t vbe_index; \
uint16_t vbe_regs[VBE_DISPI_INDEX_NB]; \
uint32_t vbe_start_addr; \
uint32_t vbe_line_offset; \
uint32_t vbe_bank_mask;
#else
#define VGA_STATE_COMMON_BOCHS_VBE
#endif /* !CONFIG_BOCHS_VBE */
#define CH_ATTR_SIZE (160 * 100)
#define VGA_MAX_HEIGHT 1024
#define VGA_STATE_COMMON \
uint8_t *vram_ptr; \
unsigned long vram_offset; \
unsigned int vram_size; \
uint32_t latch; \
uint8_t sr_index; \
uint8_t sr[256]; \
uint8_t gr_index; \
uint8_t gr[256]; \
uint8_t ar_index; \
uint8_t ar[21]; \
int ar_flip_flop; \
uint8_t cr_index; \
uint8_t cr[256]; /* CRT registers */ \
uint8_t msr; /* Misc Output Register */ \
uint8_t fcr; /* Feature Control Register */ \
uint8_t st00; /* status 0 */ \
uint8_t st01; /* status 1 */ \
uint8_t dac_state; \
uint8_t dac_sub_index; \
uint8_t dac_read_index; \
uint8_t dac_write_index; \
uint8_t dac_cache[3]; /* used when writing */ \
uint8_t palette[768]; \
int32_t bank_offset; \
int (*get_bpp)(struct VGAState *s); \
void (*get_offsets)(struct VGAState *s, \
uint32_t *pline_offset, \
uint32_t *pstart_addr); \
void (*get_resolution)(struct VGAState *s, \
int *pwidth, \
int *pheight); \
VGA_STATE_COMMON_BOCHS_VBE \
/* display refresh support */ \
DisplayState *ds; \
uint32_t font_offsets[2]; \
int graphic_mode; \
uint8_t shift_control; \
uint8_t double_scan; \
uint32_t line_offset; \
uint32_t line_compare; \
uint32_t start_addr; \
uint32_t plane_updated; \
uint8_t last_cw, last_ch; \
uint32_t last_width, last_height; /* in chars or pixels */ \
uint32_t last_scr_width, last_scr_height; /* in pixels */ \
uint8_t cursor_start, cursor_end; \
uint32_t cursor_offset; \
unsigned int (*rgb_to_pixel)(unsigned int r, \
unsigned int g, unsigned b); \
/* hardware mouse cursor support */ \
uint32_t invalidated_y_table[VGA_MAX_HEIGHT / 32]; \
void (*cursor_invalidate)(struct VGAState *s); \
void (*cursor_draw_line)(struct VGAState *s, uint8_t *d, int y); \
/* tell for each page if it has been updated since the last time */ \
uint32_t last_palette[256]; \
uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */
typedef struct VGAState {
VGA_STATE_COMMON
} VGAState;
static inline int c6_to_8(int v)
{
int b;
v &= 0x3f;
b = v & 1;
return (v << 2) | (b << 1) | b;
}
void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
unsigned long vga_ram_offset, int vga_ram_size);
uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr);
void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val);
void vga_invalidate_scanlines(VGAState *s, int y1, int y2);
void vga_draw_cursor_line_8(uint8_t *d1, const uint8_t *src1,
int poffset, int w,
unsigned int color0, unsigned int color1,
unsigned int color_xor);
void vga_draw_cursor_line_16(uint8_t *d1, const uint8_t *src1,
int poffset, int w,
unsigned int color0, unsigned int color1,
unsigned int color_xor);
void vga_draw_cursor_line_32(uint8_t *d1, const uint8_t *src1,
int poffset, int w,
unsigned int color0, unsigned int color1,
unsigned int color_xor);
extern const uint8_t sr_mask[8];
extern const uint8_t gr_mask[16];

519
hw/vga_template.h Normal file
View File

@@ -0,0 +1,519 @@
/*
* QEMU VGA Emulator templates
*
* Copyright (c) 2003 Fabrice Bellard
*
* 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.
*/
#if DEPTH == 8
#define BPP 1
#define PIXEL_TYPE uint8_t
#elif DEPTH == 15 || DEPTH == 16
#define BPP 2
#define PIXEL_TYPE uint16_t
#elif DEPTH == 32
#define BPP 4
#define PIXEL_TYPE uint32_t
#else
#error unsupport depth
#endif
#if DEPTH != 15
static inline void glue(vga_draw_glyph_line_, DEPTH)(uint8_t *d,
uint32_t font_data,
uint32_t xorcol,
uint32_t bgcol)
{
#if BPP == 1
((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
#elif BPP == 2
((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol;
((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol;
((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol;
((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
#else
((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
#endif
}
static void glue(vga_draw_glyph8_, DEPTH)(uint8_t *d, int linesize,
const uint8_t *font_ptr, int h,
uint32_t fgcol, uint32_t bgcol)
{
uint32_t font_data, xorcol;
xorcol = bgcol ^ fgcol;
do {
font_data = font_ptr[0];
glue(vga_draw_glyph_line_, DEPTH)(d, font_data, xorcol, bgcol);
font_ptr += 4;
d += linesize;
} while (--h);
}
static void glue(vga_draw_glyph16_, DEPTH)(uint8_t *d, int linesize,
const uint8_t *font_ptr, int h,
uint32_t fgcol, uint32_t bgcol)
{
uint32_t font_data, xorcol;
xorcol = bgcol ^ fgcol;
do {
font_data = font_ptr[0];
glue(vga_draw_glyph_line_, DEPTH)(d,
expand4to8[font_data >> 4],
xorcol, bgcol);
glue(vga_draw_glyph_line_, DEPTH)(d + 8 * BPP,
expand4to8[font_data & 0x0f],
xorcol, bgcol);
font_ptr += 4;
d += linesize;
} while (--h);
}
static void glue(vga_draw_glyph9_, DEPTH)(uint8_t *d, int linesize,
const uint8_t *font_ptr, int h,
uint32_t fgcol, uint32_t bgcol, int dup9)
{
uint32_t font_data, xorcol, v;
xorcol = bgcol ^ fgcol;
do {
font_data = font_ptr[0];
#if BPP == 1
cpu_to_32wu((uint32_t *)d, (dmask16[(font_data >> 4)] & xorcol) ^ bgcol);
v = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
cpu_to_32wu(((uint32_t *)d)+1, v);
if (dup9)
((uint8_t *)d)[8] = v >> (24 * (1 - BIG));
else
((uint8_t *)d)[8] = bgcol;
#elif BPP == 2
cpu_to_32wu(((uint32_t *)d)+0, (dmask4[(font_data >> 6)] & xorcol) ^ bgcol);
cpu_to_32wu(((uint32_t *)d)+1, (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol);
cpu_to_32wu(((uint32_t *)d)+2, (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol);
v = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
cpu_to_32wu(((uint32_t *)d)+3, v);
if (dup9)
((uint16_t *)d)[8] = v >> (16 * (1 - BIG));
else
((uint16_t *)d)[8] = bgcol;
#else
((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
v = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[7] = v;
if (dup9)
((uint32_t *)d)[8] = v;
else
((uint32_t *)d)[8] = bgcol;
#endif
font_ptr += 4;
d += linesize;
} while (--h);
}
/*
* 4 color mode
*/
static void glue(vga_draw_line2_, DEPTH)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
uint32_t plane_mask, *palette, data, v;
int x;
palette = s1->last_palette;
plane_mask = mask16[s1->ar[0x12] & 0xf];
width >>= 3;
for(x = 0; x < width; x++) {
data = ((uint32_t *)s)[0];
data &= plane_mask;
v = expand2[GET_PLANE(data, 0)];
v |= expand2[GET_PLANE(data, 2)] << 2;
((PIXEL_TYPE *)d)[0] = palette[v >> 12];
((PIXEL_TYPE *)d)[1] = palette[(v >> 8) & 0xf];
((PIXEL_TYPE *)d)[2] = palette[(v >> 4) & 0xf];
((PIXEL_TYPE *)d)[3] = palette[(v >> 0) & 0xf];
v = expand2[GET_PLANE(data, 1)];
v |= expand2[GET_PLANE(data, 3)] << 2;
((PIXEL_TYPE *)d)[4] = palette[v >> 12];
((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf];
((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf];
((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf];
d += BPP * 8;
s += 4;
}
}
#if BPP == 1
#define PUT_PIXEL2(d, n, v) ((uint16_t *)d)[(n)] = (v)
#elif BPP == 2
#define PUT_PIXEL2(d, n, v) ((uint32_t *)d)[(n)] = (v)
#else
#define PUT_PIXEL2(d, n, v) \
((uint32_t *)d)[2*(n)] = ((uint32_t *)d)[2*(n)+1] = (v)
#endif
/*
* 4 color mode, dup2 horizontal
*/
static void glue(vga_draw_line2d2_, DEPTH)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
uint32_t plane_mask, *palette, data, v;
int x;
palette = s1->last_palette;
plane_mask = mask16[s1->ar[0x12] & 0xf];
width >>= 3;
for(x = 0; x < width; x++) {
data = ((uint32_t *)s)[0];
data &= plane_mask;
v = expand2[GET_PLANE(data, 0)];
v |= expand2[GET_PLANE(data, 2)] << 2;
PUT_PIXEL2(d, 0, palette[v >> 12]);
PUT_PIXEL2(d, 1, palette[(v >> 8) & 0xf]);
PUT_PIXEL2(d, 2, palette[(v >> 4) & 0xf]);
PUT_PIXEL2(d, 3, palette[(v >> 0) & 0xf]);
v = expand2[GET_PLANE(data, 1)];
v |= expand2[GET_PLANE(data, 3)] << 2;
PUT_PIXEL2(d, 4, palette[v >> 12]);
PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
d += BPP * 16;
s += 4;
}
}
/*
* 16 color mode
*/
static void glue(vga_draw_line4_, DEPTH)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
uint32_t plane_mask, data, v, *palette;
int x;
palette = s1->last_palette;
plane_mask = mask16[s1->ar[0x12] & 0xf];
width >>= 3;
for(x = 0; x < width; x++) {
data = ((uint32_t *)s)[0];
data &= plane_mask;
v = expand4[GET_PLANE(data, 0)];
v |= expand4[GET_PLANE(data, 1)] << 1;
v |= expand4[GET_PLANE(data, 2)] << 2;
v |= expand4[GET_PLANE(data, 3)] << 3;
((PIXEL_TYPE *)d)[0] = palette[v >> 28];
((PIXEL_TYPE *)d)[1] = palette[(v >> 24) & 0xf];
((PIXEL_TYPE *)d)[2] = palette[(v >> 20) & 0xf];
((PIXEL_TYPE *)d)[3] = palette[(v >> 16) & 0xf];
((PIXEL_TYPE *)d)[4] = palette[(v >> 12) & 0xf];
((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf];
((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf];
((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf];
d += BPP * 8;
s += 4;
}
}
/*
* 16 color mode, dup2 horizontal
*/
static void glue(vga_draw_line4d2_, DEPTH)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
uint32_t plane_mask, data, v, *palette;
int x;
palette = s1->last_palette;
plane_mask = mask16[s1->ar[0x12] & 0xf];
width >>= 3;
for(x = 0; x < width; x++) {
data = ((uint32_t *)s)[0];
data &= plane_mask;
v = expand4[GET_PLANE(data, 0)];
v |= expand4[GET_PLANE(data, 1)] << 1;
v |= expand4[GET_PLANE(data, 2)] << 2;
v |= expand4[GET_PLANE(data, 3)] << 3;
PUT_PIXEL2(d, 0, palette[v >> 28]);
PUT_PIXEL2(d, 1, palette[(v >> 24) & 0xf]);
PUT_PIXEL2(d, 2, palette[(v >> 20) & 0xf]);
PUT_PIXEL2(d, 3, palette[(v >> 16) & 0xf]);
PUT_PIXEL2(d, 4, palette[(v >> 12) & 0xf]);
PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
d += BPP * 16;
s += 4;
}
}
/*
* 256 color mode, double pixels
*
* XXX: add plane_mask support (never used in standard VGA modes)
*/
static void glue(vga_draw_line8d2_, DEPTH)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
uint32_t *palette;
int x;
palette = s1->last_palette;
width >>= 3;
for(x = 0; x < width; x++) {
PUT_PIXEL2(d, 0, palette[s[0]]);
PUT_PIXEL2(d, 1, palette[s[1]]);
PUT_PIXEL2(d, 2, palette[s[2]]);
PUT_PIXEL2(d, 3, palette[s[3]]);
d += BPP * 8;
s += 4;
}
}
/*
* standard 256 color mode
*
* XXX: add plane_mask support (never used in standard VGA modes)
*/
static void glue(vga_draw_line8_, DEPTH)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
uint32_t *palette;
int x;
palette = s1->last_palette;
width >>= 3;
for(x = 0; x < width; x++) {
((PIXEL_TYPE *)d)[0] = palette[s[0]];
((PIXEL_TYPE *)d)[1] = palette[s[1]];
((PIXEL_TYPE *)d)[2] = palette[s[2]];
((PIXEL_TYPE *)d)[3] = palette[s[3]];
((PIXEL_TYPE *)d)[4] = palette[s[4]];
((PIXEL_TYPE *)d)[5] = palette[s[5]];
((PIXEL_TYPE *)d)[6] = palette[s[6]];
((PIXEL_TYPE *)d)[7] = palette[s[7]];
d += BPP * 8;
s += 8;
}
}
#endif /* DEPTH != 15 */
/* XXX: optimize */
/*
* 15 bit color
*/
static void glue(vga_draw_line15_, DEPTH)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
#if DEPTH == 15 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
memcpy(d, s, width * 2);
#else
int w;
uint32_t v, r, g, b;
w = width;
do {
v = lduw_raw((void *)s);
r = (v >> 7) & 0xf8;
g = (v >> 2) & 0xf8;
b = (v << 3) & 0xf8;
((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
s += 2;
d += BPP;
} while (--w != 0);
#endif
}
/*
* 16 bit color
*/
static void glue(vga_draw_line16_, DEPTH)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
#if DEPTH == 16 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
memcpy(d, s, width * 2);
#else
int w;
uint32_t v, r, g, b;
w = width;
do {
v = lduw_raw((void *)s);
r = (v >> 8) & 0xf8;
g = (v >> 3) & 0xfc;
b = (v << 3) & 0xf8;
((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
s += 2;
d += BPP;
} while (--w != 0);
#endif
}
/*
* 24 bit color
*/
static void glue(vga_draw_line24_, DEPTH)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
int w;
uint32_t r, g, b;
w = width;
do {
#if defined(TARGET_WORDS_BIGENDIAN)
r = s[0];
g = s[1];
b = s[2];
#else
b = s[0];
g = s[1];
r = s[2];
#endif
((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
s += 3;
d += BPP;
} while (--w != 0);
}
/*
* 32 bit color
*/
static void glue(vga_draw_line32_, DEPTH)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
#if DEPTH == 32 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
memcpy(d, s, width * 4);
#else
int w;
uint32_t r, g, b;
w = width;
do {
#if defined(TARGET_WORDS_BIGENDIAN)
r = s[1];
g = s[2];
b = s[3];
#else
b = s[0];
g = s[1];
r = s[2];
#endif
((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
s += 4;
d += BPP;
} while (--w != 0);
#endif
}
#if DEPTH != 15
void glue(vga_draw_cursor_line_, DEPTH)(uint8_t *d1,
const uint8_t *src1,
int poffset, int w,
unsigned int color0,
unsigned int color1,
unsigned int color_xor)
{
const uint8_t *plane0, *plane1;
int x, b0, b1;
uint8_t *d;
d = d1;
plane0 = src1;
plane1 = src1 + poffset;
for(x = 0; x < w; x++) {
b0 = (plane0[x >> 3] >> (7 - (x & 7))) & 1;
b1 = (plane1[x >> 3] >> (7 - (x & 7))) & 1;
#if DEPTH == 8
switch(b0 | (b1 << 1)) {
case 0:
break;
case 1:
d[0] ^= color_xor;
break;
case 2:
d[0] = color0;
break;
case 3:
d[0] = color1;
break;
}
#elif DEPTH == 16
switch(b0 | (b1 << 1)) {
case 0:
break;
case 1:
((uint16_t *)d)[0] ^= color_xor;
break;
case 2:
((uint16_t *)d)[0] = color0;
break;
case 3:
((uint16_t *)d)[0] = color1;
break;
}
#elif DEPTH == 32
switch(b0 | (b1 << 1)) {
case 0:
break;
case 1:
((uint32_t *)d)[0] ^= color_xor;
break;
case 2:
((uint32_t *)d)[0] = color0;
break;
case 3:
((uint32_t *)d)[0] = color1;
break;
}
#else
#error unsupported depth
#endif
d += BPP;
}
}
#endif
#undef PUT_PIXEL2
#undef DEPTH
#undef BPP
#undef PIXEL_TYPE

4472
i386-dis.c

File diff suppressed because it is too large Load Diff

140
i386-vl.ld Normal file
View File

@@ -0,0 +1,140 @@
/* ld script to make i386 Linux kernel
* Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
*/
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/alpha-unknown-linux-gnu/lib);
ENTRY(_start)
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = 0xa8000000 + SIZEOF_HEADERS;
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rel.text :
{ *(.rel.text) *(.rel.gnu.linkonce.t*) }
.rela.text :
{ *(.rela.text) *(.rela.gnu.linkonce.t*) }
.rel.data :
{ *(.rel.data) *(.rel.gnu.linkonce.d*) }
.rela.data :
{ *(.rela.data) *(.rela.gnu.linkonce.d*) }
.rel.rodata :
{ *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
.rela.rodata :
{ *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
.rel.got : { *(.rel.got) }
.rela.got : { *(.rela.got) }
.rel.ctors : { *(.rel.ctors) }
.rela.ctors : { *(.rela.ctors) }
.rel.dtors : { *(.rel.dtors) }
.rela.dtors : { *(.rela.dtors) }
.rel.init : { *(.rel.init) }
.rela.init : { *(.rela.init) }
.rel.fini : { *(.rel.fini) }
.rela.fini : { *(.rela.fini) }
.rel.bss : { *(.rel.bss) }
.rela.bss : { *(.rela.bss) }
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
.init : { *(.init) } =0x47ff041f
.text :
{
*(.text)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
*(.gnu.linkonce.t*)
} =0x47ff041f
_etext = .;
PROVIDE (etext = .);
.fini : { *(.fini) } =0x47ff041f
.rodata : { *(.rodata) *(.gnu.linkonce.r*) }
.rodata1 : { *(.rodata1) }
.reginfo : { *(.reginfo) }
__preinit_array_start = .;
.preinit_array : { *(.preinit_array) }
__preinit_array_end = .;
__init_array_start = .;
.init_array : { *(.init_array) }
__init_array_end = .;
__fini_array_start = .;
.fini_array : { *(.fini_array) }
__fini_array_end = .;
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = ALIGN(0x100000) + (. & (0x100000 - 1));
.data :
{
*(.data)
*(.gnu.linkonce.d*)
CONSTRUCTORS
}
.data1 : { *(.data1) }
.ctors :
{
*(.ctors)
}
.dtors :
{
*(.dtors)
}
.plt : { *(.plt) }
.got : { *(.got.plt) *(.got) }
.dynamic : { *(.dynamic) }
/* We want the small data sections together, so single-instruction offsets
can access them all, and initialized data all before uninitialized, so
we can shorten the on-disk segment size. */
.sdata : { *(.sdata) }
_edata = .;
PROVIDE (edata = .);
__bss_start = .;
.sbss : { *(.sbss) *(.scommon) }
.bss :
{
*(.dynbss)
*(.bss)
*(COMMON)
}
_end = . ;
PROVIDE (end = .);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* These must appear regardless of . */
}

10
i386.ld
View File

@@ -53,6 +53,16 @@ SECTIONS
_etext = .;
PROVIDE (etext = .);
.fini : { *(.fini) } =0x47ff041f
. = ALIGN(32 / 8);
PROVIDE (__preinit_array_start = .);
.preinit_array : { *(.preinit_array) }
PROVIDE (__preinit_array_end = .);
PROVIDE (__init_array_start = .);
.init_array : { *(.init_array) }
PROVIDE (__init_array_end = .);
PROVIDE (__fini_array_start = .);
.fini_array : { *(.fini_array) }
PROVIDE (__fini_array_end = .);
.rodata : { *(.rodata) *(.gnu.linkonce.r*) }
.rodata1 : { *(.rodata1) }
.reginfo : { *(.reginfo) }

32
ia64-syscall.S Normal file
View File

@@ -0,0 +1,32 @@
/* derived from glibc sysdeps/unix/sysv/linux/ia64/sysdep.S */
#define __ASSEMBLY__
#include <asm/asmmacro.h>
#include <asm/unistd.h>
ENTRY(__syscall_error)
.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(0)
alloc r33=ar.pfs, 0, 4, 0, 0
mov r32=rp
.body
mov r35=r8
mov r34=r1
;;
br.call.sptk.many b0 = __errno_location
.Lret0: /* force new bundle */
st4 [r8]=r35
mov r1=r34
mov rp=r32
mov r8=-1
mov ar.pfs=r33
br.ret.sptk.few b0
END(__syscall_error)
GLOBAL_ENTRY(__ia64_syscall)
mov r15=r37 /* syscall number */
break __BREAK_SYSCALL
cmp.eq p6,p0=-1,r10 /* r10 = -1 on error */
(p6) br.cond.spnt.few __syscall_error
br.ret.sptk.few b0
.endp __ia64_syscall

305
linux-2.6-qemu-fast.patch Normal file
View File

@@ -0,0 +1,305 @@
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .32324-linux-2.6.0/arch/i386/Kconfig .32324-linux-2.6.0.updated/arch/i386/Kconfig
--- .32324-linux-2.6.0/arch/i386/Kconfig 2003-10-09 18:02:48.000000000 +1000
+++ .32324-linux-2.6.0.updated/arch/i386/Kconfig 2003-12-26 16:46:49.000000000 +1100
@@ -307,6 +307,14 @@ config X86_GENERIC
when it has moderate overhead. This is intended for generic
distributions kernels.
+config QEMU
+ bool "Kernel to run under QEMU"
+ depends on EXPERIMENTAL
+ help
+ Select this if you want to boot the kernel inside qemu-fast,
+ the non-mmu version of the x86 emulator. See
+ <http://fabrice.bellard.free.fr/qemu/>. Say N.
+
#
# Define implied options from the CPU selection here
#
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .32324-linux-2.6.0/arch/i386/kernel/Makefile .32324-linux-2.6.0.updated/arch/i386/kernel/Makefile
--- .32324-linux-2.6.0/arch/i386/kernel/Makefile 2003-09-29 10:25:15.000000000 +1000
+++ .32324-linux-2.6.0.updated/arch/i386/kernel/Makefile 2003-12-26 16:46:49.000000000 +1100
@@ -46,12 +46,14 @@ quiet_cmd_syscall = SYSCALL $@
cmd_syscall = $(CC) -nostdlib $(SYSCFLAGS_$(@F)) \
-Wl,-T,$(filter-out FORCE,$^) -o $@
+export AFLAGS_vsyscall.lds.o += -P -C -U$(ARCH)
+
vsyscall-flags = -shared -s -Wl,-soname=linux-gate.so.1
SYSCFLAGS_vsyscall-sysenter.so = $(vsyscall-flags)
SYSCFLAGS_vsyscall-int80.so = $(vsyscall-flags)
$(obj)/vsyscall-int80.so $(obj)/vsyscall-sysenter.so: \
-$(obj)/vsyscall-%.so: $(src)/vsyscall.lds $(obj)/vsyscall-%.o FORCE
+$(obj)/vsyscall-%.so: $(src)/vsyscall.lds.s $(obj)/vsyscall-%.o FORCE
$(call if_changed,syscall)
# We also create a special relocatable object that should mirror the symbol
@@ -62,5 +64,5 @@ $(obj)/built-in.o: $(obj)/vsyscall-syms.
$(obj)/built-in.o: ld_flags += -R $(obj)/vsyscall-syms.o
SYSCFLAGS_vsyscall-syms.o = -r
-$(obj)/vsyscall-syms.o: $(src)/vsyscall.lds $(obj)/vsyscall-sysenter.o FORCE
+$(obj)/vsyscall-syms.o: $(src)/vsyscall.lds.s $(obj)/vsyscall-sysenter.o FORCE
$(call if_changed,syscall)
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .32324-linux-2.6.0/arch/i386/kernel/vmlinux.lds.S .32324-linux-2.6.0.updated/arch/i386/kernel/vmlinux.lds.S
--- .32324-linux-2.6.0/arch/i386/kernel/vmlinux.lds.S 2003-09-22 10:27:28.000000000 +1000
+++ .32324-linux-2.6.0.updated/arch/i386/kernel/vmlinux.lds.S 2003-12-26 16:46:49.000000000 +1100
@@ -3,6 +3,7 @@
*/
#include <asm-generic/vmlinux.lds.h>
+#include <asm/page.h>
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
@@ -10,7 +11,7 @@ ENTRY(startup_32)
jiffies = jiffies_64;
SECTIONS
{
- . = 0xC0000000 + 0x100000;
+ . = __PAGE_OFFSET + 0x100000;
/* read-only */
_text = .; /* Text and read-only data */
.text : {
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .32324-linux-2.6.0/arch/i386/kernel/vsyscall.lds .32324-linux-2.6.0.updated/arch/i386/kernel/vsyscall.lds
--- .32324-linux-2.6.0/arch/i386/kernel/vsyscall.lds 2003-09-22 10:07:26.000000000 +1000
+++ .32324-linux-2.6.0.updated/arch/i386/kernel/vsyscall.lds 1970-01-01 10:00:00.000000000 +1000
@@ -1,67 +0,0 @@
-/*
- * Linker script for vsyscall DSO. The vsyscall page is an ELF shared
- * object prelinked to its virtual address, and with only one read-only
- * segment (that fits in one page). This script controls its layout.
- */
-
-/* This must match <asm/fixmap.h>. */
-VSYSCALL_BASE = 0xffffe000;
-
-SECTIONS
-{
- . = VSYSCALL_BASE + SIZEOF_HEADERS;
-
- .hash : { *(.hash) } :text
- .dynsym : { *(.dynsym) }
- .dynstr : { *(.dynstr) }
- .gnu.version : { *(.gnu.version) }
- .gnu.version_d : { *(.gnu.version_d) }
- .gnu.version_r : { *(.gnu.version_r) }
-
- /* This linker script is used both with -r and with -shared.
- For the layouts to match, we need to skip more than enough
- space for the dynamic symbol table et al. If this amount
- is insufficient, ld -shared will barf. Just increase it here. */
- . = VSYSCALL_BASE + 0x400;
-
- .text : { *(.text) } :text =0x90909090
-
- .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
- .eh_frame : { KEEP (*(.eh_frame)) } :text
- .dynamic : { *(.dynamic) } :text :dynamic
- .useless : {
- *(.got.plt) *(.got)
- *(.data .data.* .gnu.linkonce.d.*)
- *(.dynbss)
- *(.bss .bss.* .gnu.linkonce.b.*)
- } :text
-}
-
-/*
- * We must supply the ELF program headers explicitly to get just one
- * PT_LOAD segment, and set the flags explicitly to make segments read-only.
- */
-PHDRS
-{
- text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
- dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
- eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */
-}
-
-/*
- * This controls what symbols we export from the DSO.
- */
-VERSION
-{
- LINUX_2.5 {
- global:
- __kernel_vsyscall;
- __kernel_sigreturn;
- __kernel_rt_sigreturn;
-
- local: *;
- };
-}
-
-/* The ELF entry point can be used to set the AT_SYSINFO value. */
-ENTRY(__kernel_vsyscall);
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .32324-linux-2.6.0/arch/i386/kernel/vsyscall.lds.S .32324-linux-2.6.0.updated/arch/i386/kernel/vsyscall.lds.S
--- .32324-linux-2.6.0/arch/i386/kernel/vsyscall.lds.S 1970-01-01 10:00:00.000000000 +1000
+++ .32324-linux-2.6.0.updated/arch/i386/kernel/vsyscall.lds.S 2003-12-26 16:46:49.000000000 +1100
@@ -0,0 +1,67 @@
+/*
+ * Linker script for vsyscall DSO. The vsyscall page is an ELF shared
+ * object prelinked to its virtual address, and with only one read-only
+ * segment (that fits in one page). This script controls its layout.
+ */
+#include <asm/fixmap.h>
+
+VSYSCALL_BASE = __FIXADDR_TOP - 0x1000;
+
+SECTIONS
+{
+ . = VSYSCALL_BASE + SIZEOF_HEADERS;
+
+ .hash : { *(.hash) } :text
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+
+ /* This linker script is used both with -r and with -shared.
+ For the layouts to match, we need to skip more than enough
+ space for the dynamic symbol table et al. If this amount
+ is insufficient, ld -shared will barf. Just increase it here. */
+ . = VSYSCALL_BASE + 0x400;
+
+ .text : { *(.text) } :text =0x90909090
+
+ .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
+ .eh_frame : { KEEP (*(.eh_frame)) } :text
+ .dynamic : { *(.dynamic) } :text :dynamic
+ .useless : {
+ *(.got.plt) *(.got)
+ *(.data .data.* .gnu.linkonce.d.*)
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ } :text
+}
+
+/*
+ * We must supply the ELF program headers explicitly to get just one
+ * PT_LOAD segment, and set the flags explicitly to make segments read-only.
+ */
+PHDRS
+{
+ text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
+ dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
+ eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */
+}
+
+/*
+ * This controls what symbols we export from the DSO.
+ */
+VERSION
+{
+ LINUX_2.5 {
+ global:
+ __kernel_vsyscall;
+ __kernel_sigreturn;
+ __kernel_rt_sigreturn;
+
+ local: *;
+ };
+}
+
+/* The ELF entry point can be used to set the AT_SYSINFO value. */
+ENTRY(__kernel_vsyscall);
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .32324-linux-2.6.0/include/asm-i386/fixmap.h .32324-linux-2.6.0.updated/include/asm-i386/fixmap.h
--- .32324-linux-2.6.0/include/asm-i386/fixmap.h 2003-09-22 10:09:12.000000000 +1000
+++ .32324-linux-2.6.0.updated/include/asm-i386/fixmap.h 2003-12-26 16:46:49.000000000 +1100
@@ -14,6 +14,19 @@
#define _ASM_FIXMAP_H
#include <linux/config.h>
+
+/* used by vmalloc.c, vsyscall.lds.S.
+ *
+ * Leave one empty page between vmalloc'ed areas and
+ * the start of the fixmap.
+ */
+#ifdef CONFIG_QEMU
+#define __FIXADDR_TOP 0xa7fff000
+#else
+#define __FIXADDR_TOP 0xfffff000
+#endif
+
+#ifndef __ASSEMBLY__
#include <linux/kernel.h>
#include <asm/acpi.h>
#include <asm/apicdef.h>
@@ -94,13 +107,8 @@ extern void __set_fixmap (enum fixed_add
#define clear_fixmap(idx) \
__set_fixmap(idx, 0, __pgprot(0))
-/*
- * used by vmalloc.c.
- *
- * Leave one empty page between vmalloc'ed areas and
- * the start of the fixmap.
- */
-#define FIXADDR_TOP (0xfffff000UL)
+#define FIXADDR_TOP ((unsigned long)__FIXADDR_TOP)
+
#define __FIXADDR_SIZE (__end_of_permanent_fixed_addresses << PAGE_SHIFT)
#define FIXADDR_START (FIXADDR_TOP - __FIXADDR_SIZE)
@@ -145,4 +153,5 @@ static inline unsigned long virt_to_fix(
return __virt_to_fix(vaddr);
}
+#endif /* !__ASSEMBLY__ */
#endif
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .32324-linux-2.6.0/include/asm-i386/page.h .32324-linux-2.6.0.updated/include/asm-i386/page.h
--- .32324-linux-2.6.0/include/asm-i386/page.h 2003-09-22 10:06:42.000000000 +1000
+++ .32324-linux-2.6.0.updated/include/asm-i386/page.h 2003-12-26 16:46:49.000000000 +1100
@@ -10,10 +10,10 @@
#define LARGE_PAGE_SIZE (1UL << PMD_SHIFT)
#ifdef __KERNEL__
-#ifndef __ASSEMBLY__
-
#include <linux/config.h>
+#ifndef __ASSEMBLY__
+
#ifdef CONFIG_X86_USE_3DNOW
#include <asm/mmx.h>
@@ -115,12 +115,19 @@ static __inline__ int get_order(unsigned
#endif /* __ASSEMBLY__ */
#ifdef __ASSEMBLY__
+#ifdef CONFIG_QEMU
+#define __PAGE_OFFSET (0x90000000)
+#else
#define __PAGE_OFFSET (0xC0000000)
+#endif /* QEMU */
+#else
+#ifdef CONFIG_QEMU
+#define __PAGE_OFFSET (0x90000000UL)
#else
#define __PAGE_OFFSET (0xC0000000UL)
+#endif /* QEMU */
#endif
-
#define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)
#define VMALLOC_RESERVE ((unsigned long)__VMALLOC_RESERVE)
#define MAXMEM (-__PAGE_OFFSET-__VMALLOC_RESERVE)
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .32324-linux-2.6.0/include/asm-i386/param.h .32324-linux-2.6.0.updated/include/asm-i386/param.h
--- .32324-linux-2.6.0/include/asm-i386/param.h 2003-09-21 17:26:06.000000000 +1000
+++ .32324-linux-2.6.0.updated/include/asm-i386/param.h 2003-12-26 16:46:49.000000000 +1100
@@ -2,7 +2,12 @@
#define _ASMi386_PARAM_H
#ifdef __KERNEL__
-# define HZ 1000 /* Internal kernel timer frequency */
+# include <linux/config.h>
+# ifdef CONFIG_QEMU
+# define HZ 100
+# else
+# define HZ 1000 /* Internal kernel timer frequency */
+# endif
# define USER_HZ 100 /* .. some user interfaces are in "ticks" */
# define CLOCKS_PER_SEC (USER_HZ) /* like times() */
#endif

36
linux-user/arm/syscall.h Normal file
View File

@@ -0,0 +1,36 @@
/* this struct defines the way the registers are stored on the
stack during a system call. */
struct target_pt_regs {
target_long uregs[18];
};
#define ARM_cpsr uregs[16]
#define ARM_pc uregs[15]
#define ARM_lr uregs[14]
#define ARM_sp uregs[13]
#define ARM_ip uregs[12]
#define ARM_fp uregs[11]
#define ARM_r10 uregs[10]
#define ARM_r9 uregs[9]
#define ARM_r8 uregs[8]
#define ARM_r7 uregs[7]
#define ARM_r6 uregs[6]
#define ARM_r5 uregs[5]
#define ARM_r4 uregs[4]
#define ARM_r3 uregs[3]
#define ARM_r2 uregs[2]
#define ARM_r1 uregs[1]
#define ARM_r0 uregs[0]
#define ARM_ORIG_r0 uregs[17]
#define ARM_SYSCALL_BASE 0x900000
#define ARM_NR_cacheflush (ARM_SYSCALL_BASE + 0xf0000 + 2)
#if defined(TARGET_WORDS_BIGENDIAN)
#define UNAME_MACHINE "armv4b"
#else
#define UNAME_MACHINE "armv4l"
#endif

261
linux-user/arm/syscall_nr.h Normal file
View File

@@ -0,0 +1,261 @@
/*
* This file contains the system call numbers.
*/
#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) /* removed */
#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) /* removed */
/* 18 was sys_stat */
#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_pause ( 29)
#define TARGET_NR_utime ( 30)
#define TARGET_NR_stty ( 31) /* removed */
#define TARGET_NR_gtty ( 32) /* removed */
#define TARGET_NR_access ( 33)
#define TARGET_NR_nice ( 34)
#define TARGET_NR_ftime ( 35) /* removed */
#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) /* removed */
#define TARGET_NR_brk ( 45)
#define TARGET_NR_setgid ( 46)
#define TARGET_NR_getgid ( 47)
#define TARGET_NR_signal ( 48) /* removed */
#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) /* removed */
#define TARGET_NR_ioctl ( 54)
#define TARGET_NR_fcntl ( 55)
#define TARGET_NR_mpx ( 56) /* removed */
#define TARGET_NR_setpgid ( 57)
#define TARGET_NR_ulimit ( 58) /* removed */
/* 59 was sys_olduname */
#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) /* removed */
#define TARGET_NR_ssetmask ( 69) /* removed */
#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 compat 2GB 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)
/* 84 was sys_lstat */
#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) /* removed */
#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)
/* 109 was sys_uname */
/* 110 was sys_iopl */
#define TARGET_NR_vhangup (111)
#define TARGET_NR_idle (112)
#define TARGET_NR_syscall (113) /* syscall to call a syscall! */
#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) /* removed */
#define TARGET_NR_init_module (128)
#define TARGET_NR_delete_module (129)
#define TARGET_NR_get_kernel_syms (130) /* removed */
#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) /* removed */
#define TARGET_NR_query_module (167) /* removed */
#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_pread (180)
#define TARGET_NR_pwrite (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)
/* 188 reserved */
/* 189 reserved */
#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_getdents64 (217)
#define TARGET_NR_pivot_root (218)
#define TARGET_NR_mincore (219)
#define TARGET_NR_madvise (220)
#define TARGET_NR_fcntl64 (221)
/* 222 for tux */
/* 223 is unused */
#define TARGET_NR_gettid (224)
#define TARGET_NR_readahead (225)
#define TARGET_NR_setxattr (226)
#define TARGET_NR_lsetxattr (227)
#define TARGET_NR_fsetxattr (228)
#define TARGET_NR_getxattr (229)
#define TARGET_NR_lgetxattr (230)
#define TARGET_NR_fgetxattr (231)
#define TARGET_NR_listxattr (232)
#define TARGET_NR_llistxattr (233)
#define TARGET_NR_flistxattr (234)
#define TARGET_NR_removexattr (235)
#define TARGET_NR_lremovexattr (236)
#define TARGET_NR_fremovexattr (237)
#define TARGET_NR_tkill (238)
#define TARGET_NR_sendfile64 (239)
#define TARGET_NR_futex (240)
#define TARGET_NR_sched_setaffinity (241)
#define TARGET_NR_sched_getaffinity (242)
#define TARGET_NR_io_setup (243)
#define TARGET_NR_io_destroy (244)
#define TARGET_NR_io_getevents (245)
#define TARGET_NR_io_submit (246)
#define TARGET_NR_io_cancel (247)
#define TARGET_NR_exit_group (248)
#define TARGET_NR_lookup_dcookie (249)
#define TARGET_NR_epoll_create (250)
#define TARGET_NR_epoll_ctl (251)
#define TARGET_NR_epoll_wait (252)
#define TARGET_NR_remap_file_pages (253)
/* 254 for set_thread_area */
/* 255 for get_thread_area */
/* 256 for set_tid_address */

Some files were not shown because too many files have changed in this diff Show More