realmode.c 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849
  1. #ifndef USE_SERIAL
  2. #define USE_SERIAL
  3. #endif
  4. #define ARRAY_SIZE(_a) (sizeof(_a)/sizeof((_a)[0]))
  5. asm(".code16gcc");
  6. typedef unsigned char u8;
  7. typedef unsigned short u16;
  8. typedef unsigned u32;
  9. typedef unsigned long long u64;
  10. #ifndef NULL
  11. #define NULL ((void*)0)
  12. #endif
  13. void realmode_start(void);
  14. void test_function(void);
  15. asm(
  16. "test_function: \n\t"
  17. "mov $0x1234, %eax \n\t"
  18. "ret"
  19. );
  20. static int strlen(const char *str)
  21. {
  22. int n;
  23. for (n = 0; *str; ++str)
  24. ++n;
  25. return n;
  26. }
  27. static void outb(u8 data, u16 port)
  28. {
  29. asm volatile("out %0, %1" : : "a"(data), "d"(port));
  30. }
  31. #ifdef USE_SERIAL
  32. static int serial_iobase = 0x3f8;
  33. static int serial_inited = 0;
  34. static u8 inb(u16 port)
  35. {
  36. u8 data;
  37. asm volatile("in %1, %0" : "=a"(data) : "d"(port));
  38. return data;
  39. }
  40. static void serial_outb(char ch)
  41. {
  42. u8 lsr;
  43. do {
  44. lsr = inb(serial_iobase + 0x05);
  45. } while (!(lsr & 0x20));
  46. outb(ch, serial_iobase + 0x00);
  47. }
  48. static void serial_init(void)
  49. {
  50. u8 lcr;
  51. /* set DLAB */
  52. lcr = inb(serial_iobase + 0x03);
  53. lcr |= 0x80;
  54. outb(lcr, serial_iobase + 0x03);
  55. /* set baud rate to 115200 */
  56. outb(0x01, serial_iobase + 0x00);
  57. outb(0x00, serial_iobase + 0x01);
  58. /* clear DLAB */
  59. lcr = inb(serial_iobase + 0x03);
  60. lcr &= ~0x80;
  61. outb(lcr, serial_iobase + 0x03);
  62. }
  63. #endif
  64. static void print_serial(const char *buf)
  65. {
  66. unsigned long len = strlen(buf);
  67. #ifdef USE_SERIAL
  68. unsigned long i;
  69. if (!serial_inited) {
  70. serial_init();
  71. serial_inited = 1;
  72. }
  73. for (i = 0; i < len; i++) {
  74. serial_outb(buf[i]);
  75. }
  76. #else
  77. asm volatile ("addr32/rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1));
  78. #endif
  79. }
  80. static void print_serial_u32(u32 value)
  81. {
  82. char n[12], *p;
  83. p = &n[11];
  84. *p = 0;
  85. do {
  86. *--p = '0' + (value % 10);
  87. value /= 10;
  88. } while (value > 0);
  89. print_serial(p);
  90. }
  91. static int failed;
  92. static void exit(int code)
  93. {
  94. outb(code, 0xf4);
  95. }
  96. struct regs {
  97. u32 eax, ebx, ecx, edx;
  98. u32 esi, edi, esp, ebp;
  99. u32 eip, eflags;
  100. };
  101. struct table_descr {
  102. u16 limit;
  103. void *base;
  104. } __attribute__((packed));
  105. static u64 gdt[] = {
  106. 0,
  107. 0x00cf9b000000ffffull, // flat 32-bit code segment
  108. 0x00cf93000000ffffull, // flat 32-bit data segment
  109. };
  110. static struct table_descr gdt_descr = {
  111. sizeof(gdt) - 1,
  112. gdt,
  113. };
  114. struct insn_desc {
  115. u16 ptr;
  116. u16 len;
  117. };
  118. struct {
  119. u32 stack[128];
  120. char top[];
  121. } tmp_stack;
  122. static struct regs inregs, outregs;
  123. static inline void init_inregs(struct regs *regs)
  124. {
  125. inregs = (struct regs){ 0 };
  126. if (regs)
  127. inregs = *regs;
  128. if (!inregs.esp)
  129. inregs.esp = (unsigned long)&tmp_stack.top;
  130. }
  131. static void exec_in_big_real_mode(struct insn_desc *insn)
  132. {
  133. unsigned long tmp;
  134. static struct regs save;
  135. int i;
  136. extern u8 test_insn[], test_insn_end[];
  137. for (i = 0; i < insn->len; ++i)
  138. test_insn[i] = ((u8 *)(unsigned long)insn->ptr)[i];
  139. for (; i < test_insn_end - test_insn; ++i)
  140. test_insn[i] = 0x90; // nop
  141. save = inregs;
  142. asm volatile(
  143. "lgdtl %[gdt_descr] \n\t"
  144. "mov %%cr0, %[tmp] \n\t"
  145. "or $1, %[tmp] \n\t"
  146. "mov %[tmp], %%cr0 \n\t"
  147. "mov %[bigseg], %%gs \n\t"
  148. "and $-2, %[tmp] \n\t"
  149. "mov %[tmp], %%cr0 \n\t"
  150. /* Save ES, because it is clobbered by some tests. */
  151. "pushw %%es \n\t"
  152. "pushw %[save]+36; popfw \n\t"
  153. "xchg %%eax, %[save]+0 \n\t"
  154. "xchg %%ebx, %[save]+4 \n\t"
  155. "xchg %%ecx, %[save]+8 \n\t"
  156. "xchg %%edx, %[save]+12 \n\t"
  157. "xchg %%esi, %[save]+16 \n\t"
  158. "xchg %%edi, %[save]+20 \n\t"
  159. "xchg %%esp, %[save]+24 \n\t"
  160. "xchg %%ebp, %[save]+28 \n\t"
  161. "test_insn: . = . + 32\n\t"
  162. "test_insn_end: \n\t"
  163. "xchg %%eax, %[save]+0 \n\t"
  164. "xchg %%ebx, %[save]+4 \n\t"
  165. "xchg %%ecx, %[save]+8 \n\t"
  166. "xchg %%edx, %[save]+12 \n\t"
  167. "xchg %%esi, %[save]+16 \n\t"
  168. "xchg %%edi, %[save]+20 \n\t"
  169. "xchg %%esp, %[save]+24 \n\t"
  170. "xchg %%ebp, %[save]+28 \n\t"
  171. /* Save EFLAGS in outregs*/
  172. "pushfl \n\t"
  173. "popl %[save]+36 \n\t"
  174. /* Restore ES for future rep string operations. */
  175. "popw %%es \n\t"
  176. /* Restore DF for the harness code */
  177. "cld\n\t"
  178. "xor %[tmp], %[tmp] \n\t"
  179. "mov %[tmp], %%gs \n\t"
  180. : [tmp]"=&r"(tmp), [save]"+m"(save)
  181. : [gdt_descr]"m"(gdt_descr), [bigseg]"r"((short)16)
  182. : "cc", "memory"
  183. );
  184. outregs = save;
  185. }
  186. #define R_AX 1
  187. #define R_BX 2
  188. #define R_CX 4
  189. #define R_DX 8
  190. #define R_SI 16
  191. #define R_DI 32
  192. #define R_SP 64
  193. #define R_BP 128
  194. int regs_equal(int ignore)
  195. {
  196. const u32 *p1 = &inregs.eax, *p2 = &outregs.eax; // yuck
  197. int i;
  198. for (i = 0; i < 8; ++i)
  199. if (!(ignore & (1 << i)) && p1[i] != p2[i])
  200. return 0;
  201. return 1;
  202. }
  203. static void report(const char *name, u16 regs_ignore, _Bool ok)
  204. {
  205. if (!regs_equal(regs_ignore)) {
  206. ok = 0;
  207. }
  208. print_serial(ok ? "PASS: " : "FAIL: ");
  209. print_serial(name);
  210. print_serial("\n");
  211. if (!ok)
  212. failed = 1;
  213. }
  214. #define MK_INSN(name, str) \
  215. asm ( \
  216. ".pushsection .data.insn \n\t" \
  217. "insn_" #name ": \n\t" \
  218. ".word 1001f, 1002f - 1001f \n\t" \
  219. ".popsection \n\t" \
  220. ".pushsection .text.insn, \"ax\" \n\t" \
  221. "1001: \n\t" \
  222. "insn_code_" #name ": " str " \n\t" \
  223. "1002: \n\t" \
  224. ".popsection" \
  225. ); \
  226. extern struct insn_desc insn_##name;
  227. void test_xchg(void)
  228. {
  229. MK_INSN(xchg_test1, "xchg %eax,%eax\n\t");
  230. MK_INSN(xchg_test2, "xchg %eax,%ebx\n\t");
  231. MK_INSN(xchg_test3, "xchg %eax,%ecx\n\t");
  232. MK_INSN(xchg_test4, "xchg %eax,%edx\n\t");
  233. MK_INSN(xchg_test5, "xchg %eax,%esi\n\t");
  234. MK_INSN(xchg_test6, "xchg %eax,%edi\n\t");
  235. MK_INSN(xchg_test7, "xchg %eax,%ebp\n\t");
  236. MK_INSN(xchg_test8, "xchg %eax,%esp\n\t");
  237. inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = 7};
  238. exec_in_big_real_mode(&insn_xchg_test1);
  239. report("xchg 1", 0, 1);
  240. exec_in_big_real_mode(&insn_xchg_test2);
  241. report("xchg 2", R_AX | R_BX,
  242. outregs.eax == inregs.ebx && outregs.ebx == inregs.eax);
  243. exec_in_big_real_mode(&insn_xchg_test3);
  244. report("xchg 3", R_AX | R_CX,
  245. outregs.eax == inregs.ecx && outregs.ecx == inregs.eax);
  246. exec_in_big_real_mode(&insn_xchg_test4);
  247. report("xchg 4", R_AX | R_DX,
  248. outregs.eax == inregs.edx && outregs.edx == inregs.eax);
  249. exec_in_big_real_mode(&insn_xchg_test5);
  250. report("xchg 5", R_AX | R_SI,
  251. outregs.eax == inregs.esi && outregs.esi == inregs.eax);
  252. exec_in_big_real_mode(&insn_xchg_test6);
  253. report("xchg 6", R_AX | R_DI,
  254. outregs.eax == inregs.edi && outregs.edi == inregs.eax);
  255. exec_in_big_real_mode(&insn_xchg_test7);
  256. report("xchg 7", R_AX | R_BP,
  257. outregs.eax == inregs.ebp && outregs.ebp == inregs.eax);
  258. exec_in_big_real_mode(&insn_xchg_test8);
  259. report("xchg 8", R_AX | R_SP,
  260. outregs.eax == inregs.esp && outregs.esp == inregs.eax);
  261. }
  262. void test_shld(void)
  263. {
  264. MK_INSN(shld_test, "shld $8,%edx,%eax\n\t");
  265. init_inregs(&(struct regs){ .eax = 0xbe, .edx = 0xef000000 });
  266. exec_in_big_real_mode(&insn_shld_test);
  267. report("shld", ~0, outregs.eax == 0xbeef);
  268. }
  269. void test_mov_imm(void)
  270. {
  271. MK_INSN(mov_r32_imm_1, "mov $1234567890, %eax");
  272. MK_INSN(mov_r16_imm_1, "mov $1234, %ax");
  273. MK_INSN(mov_r8_imm_1, "mov $0x12, %ah");
  274. MK_INSN(mov_r8_imm_2, "mov $0x34, %al");
  275. MK_INSN(mov_r8_imm_3, "mov $0x12, %ah\n\t" "mov $0x34, %al\n\t");
  276. init_inregs(NULL);
  277. exec_in_big_real_mode(&insn_mov_r16_imm_1);
  278. report("mov 1", R_AX, outregs.eax == 1234);
  279. /* test mov $imm, %eax */
  280. exec_in_big_real_mode(&insn_mov_r32_imm_1);
  281. report("mov 2", R_AX, outregs.eax == 1234567890);
  282. /* test mov $imm, %al/%ah */
  283. exec_in_big_real_mode(&insn_mov_r8_imm_1);
  284. report("mov 3", R_AX, outregs.eax == 0x1200);
  285. exec_in_big_real_mode(&insn_mov_r8_imm_2);
  286. report("mov 4", R_AX, outregs.eax == 0x34);
  287. exec_in_big_real_mode(&insn_mov_r8_imm_3);
  288. report("mov 5", R_AX, outregs.eax == 0x1234);
  289. }
  290. void test_sub_imm(void)
  291. {
  292. MK_INSN(sub_r32_imm_1, "mov $1234567890, %eax\n\t" "sub $10, %eax\n\t");
  293. MK_INSN(sub_r16_imm_1, "mov $1234, %ax\n\t" "sub $10, %ax\n\t");
  294. MK_INSN(sub_r8_imm_1, "mov $0x12, %ah\n\t" "sub $0x10, %ah\n\t");
  295. MK_INSN(sub_r8_imm_2, "mov $0x34, %al\n\t" "sub $0x10, %al\n\t");
  296. init_inregs(NULL);
  297. exec_in_big_real_mode(&insn_sub_r16_imm_1);
  298. report("sub 1", R_AX, outregs.eax == 1224);
  299. /* test mov $imm, %eax */
  300. exec_in_big_real_mode(&insn_sub_r32_imm_1);
  301. report("sub 2", R_AX, outregs.eax == 1234567880);
  302. /* test mov $imm, %al/%ah */
  303. exec_in_big_real_mode(&insn_sub_r8_imm_1);
  304. report("sub 3", R_AX, outregs.eax == 0x0200);
  305. exec_in_big_real_mode(&insn_sub_r8_imm_2);
  306. report("sub 4", R_AX, outregs.eax == 0x24);
  307. }
  308. void test_xor_imm(void)
  309. {
  310. MK_INSN(xor_r32_imm_1, "mov $1234567890, %eax\n\t" "xor $1234567890, %eax\n\t");
  311. MK_INSN(xor_r16_imm_1, "mov $1234, %ax\n\t" "xor $1234, %ax\n\t");
  312. MK_INSN(xor_r8_imm_1, "mov $0x12, %ah\n\t" "xor $0x12, %ah\n\t");
  313. MK_INSN(xor_r8_imm_2, "mov $0x34, %al\n\t" "xor $0x34, %al\n\t");
  314. init_inregs(NULL);
  315. exec_in_big_real_mode(&insn_xor_r16_imm_1);
  316. report("xor 1", R_AX, outregs.eax == 0);
  317. /* test mov $imm, %eax */
  318. exec_in_big_real_mode(&insn_xor_r32_imm_1);
  319. report("xor 2", R_AX, outregs.eax == 0);
  320. /* test mov $imm, %al/%ah */
  321. exec_in_big_real_mode(&insn_xor_r8_imm_1);
  322. report("xor 3", R_AX, outregs.eax == 0);
  323. exec_in_big_real_mode(&insn_xor_r8_imm_2);
  324. report("xor 4", R_AX, outregs.eax == 0);
  325. }
  326. void test_cmp_imm(void)
  327. {
  328. MK_INSN(cmp_test1, "mov $0x34, %al\n\t"
  329. "cmp $0x34, %al\n\t");
  330. MK_INSN(cmp_test2, "mov $0x34, %al\n\t"
  331. "cmp $0x39, %al\n\t");
  332. MK_INSN(cmp_test3, "mov $0x34, %al\n\t"
  333. "cmp $0x24, %al\n\t");
  334. init_inregs(NULL);
  335. /* test cmp imm8 with AL */
  336. /* ZF: (bit 6) Zero Flag becomes 1 if an operation results
  337. * in a 0 writeback, or 0 register
  338. */
  339. exec_in_big_real_mode(&insn_cmp_test1);
  340. report("cmp 1", ~0, (outregs.eflags & (1<<6)) == (1<<6));
  341. exec_in_big_real_mode(&insn_cmp_test2);
  342. report("cmp 2", ~0, (outregs.eflags & (1<<6)) == 0);
  343. exec_in_big_real_mode(&insn_cmp_test3);
  344. report("cmp 3", ~0, (outregs.eflags & (1<<6)) == 0);
  345. }
  346. void test_add_imm(void)
  347. {
  348. MK_INSN(add_test1, "mov $0x43211234, %eax \n\t"
  349. "add $0x12344321, %eax \n\t");
  350. MK_INSN(add_test2, "mov $0x12, %eax \n\t"
  351. "add $0x21, %al\n\t");
  352. init_inregs(NULL);
  353. exec_in_big_real_mode(&insn_add_test1);
  354. report("add 1", ~0, outregs.eax == 0x55555555);
  355. exec_in_big_real_mode(&insn_add_test2);
  356. report("add 2", ~0, outregs.eax == 0x33);
  357. }
  358. void test_eflags_insn(void)
  359. {
  360. MK_INSN(clc, "clc");
  361. MK_INSN(stc, "stc");
  362. MK_INSN(cli, "cli");
  363. MK_INSN(sti, "sti");
  364. MK_INSN(cld, "cld");
  365. MK_INSN(std, "std");
  366. init_inregs(NULL);
  367. exec_in_big_real_mode(&insn_clc);
  368. report("clc", ~0, (outregs.eflags & 1) == 0);
  369. exec_in_big_real_mode(&insn_stc);
  370. report("stc", ~0, (outregs.eflags & 1) == 1);
  371. exec_in_big_real_mode(&insn_cli);
  372. report("cli", ~0, !(outregs.eflags & (1 << 9)));
  373. exec_in_big_real_mode(&insn_sti);
  374. report("sti", ~0, outregs.eflags & (1 << 9));
  375. exec_in_big_real_mode(&insn_cld);
  376. report("cld", ~0, !(outregs.eflags & (1 << 10)));
  377. exec_in_big_real_mode(&insn_std);
  378. report("std", ~0, (outregs.eflags & (1 << 10)));
  379. }
  380. void test_io(void)
  381. {
  382. MK_INSN(io_test1, "mov $0xff, %al \n\t"
  383. "out %al, $0xe0 \n\t"
  384. "mov $0x00, %al \n\t"
  385. "in $0xe0, %al \n\t");
  386. MK_INSN(io_test2, "mov $0xffff, %ax \n\t"
  387. "out %ax, $0xe0 \n\t"
  388. "mov $0x0000, %ax \n\t"
  389. "in $0xe0, %ax \n\t");
  390. MK_INSN(io_test3, "mov $0xffffffff, %eax \n\t"
  391. "out %eax, $0xe0 \n\t"
  392. "mov $0x000000, %eax \n\t"
  393. "in $0xe0, %eax \n\t");
  394. MK_INSN(io_test4, "mov $0xe0, %dx \n\t"
  395. "mov $0xff, %al \n\t"
  396. "out %al, %dx \n\t"
  397. "mov $0x00, %al \n\t"
  398. "in %dx, %al \n\t");
  399. MK_INSN(io_test5, "mov $0xe0, %dx \n\t"
  400. "mov $0xffff, %ax \n\t"
  401. "out %ax, %dx \n\t"
  402. "mov $0x0000, %ax \n\t"
  403. "in %dx, %ax \n\t");
  404. MK_INSN(io_test6, "mov $0xe0, %dx \n\t"
  405. "mov $0xffffffff, %eax \n\t"
  406. "out %eax, %dx \n\t"
  407. "mov $0x00000000, %eax \n\t"
  408. "in %dx, %eax \n\t");
  409. init_inregs(NULL);
  410. exec_in_big_real_mode(&insn_io_test1);
  411. report("pio 1", R_AX, outregs.eax == 0xff);
  412. exec_in_big_real_mode(&insn_io_test2);
  413. report("pio 2", R_AX, outregs.eax == 0xffff);
  414. exec_in_big_real_mode(&insn_io_test3);
  415. report("pio 3", R_AX, outregs.eax == 0xffffffff);
  416. exec_in_big_real_mode(&insn_io_test4);
  417. report("pio 4", R_AX|R_DX, outregs.eax == 0xff);
  418. exec_in_big_real_mode(&insn_io_test5);
  419. report("pio 5", R_AX|R_DX, outregs.eax == 0xffff);
  420. exec_in_big_real_mode(&insn_io_test6);
  421. report("pio 6", R_AX|R_DX, outregs.eax == 0xffffffff);
  422. }
  423. asm ("retf: lretw");
  424. extern void retf(void);
  425. asm ("retf_imm: lretw $10");
  426. extern void retf_imm(void);
  427. void test_call(void)
  428. {
  429. u32 addr;
  430. MK_INSN(call1, "mov $test_function, %eax \n\t"
  431. "call *%eax\n\t");
  432. MK_INSN(call_near1, "jmp 2f\n\t"
  433. "1: mov $0x1234, %eax\n\t"
  434. "ret\n\t"
  435. "2: call 1b\t");
  436. MK_INSN(call_near2, "call 1f\n\t"
  437. "jmp 2f\n\t"
  438. "1: mov $0x1234, %eax\n\t"
  439. "ret\n\t"
  440. "2:\t");
  441. MK_INSN(call_far1, "lcallw *(%ebx)\n\t");
  442. MK_INSN(call_far2, "lcallw $0, $retf\n\t");
  443. MK_INSN(ret_imm, "sub $10, %sp; jmp 2f; 1: retw $10; 2: callw 1b");
  444. MK_INSN(retf_imm, "sub $10, %sp; lcallw $0, $retf_imm");
  445. init_inregs(NULL);
  446. exec_in_big_real_mode(&insn_call1);
  447. report("call 1", R_AX, outregs.eax == 0x1234);
  448. exec_in_big_real_mode(&insn_call_near1);
  449. report("call near 1", R_AX, outregs.eax == 0x1234);
  450. exec_in_big_real_mode(&insn_call_near2);
  451. report("call near 2", R_AX, outregs.eax == 0x1234);
  452. addr = (((unsigned)retf >> 4) << 16) | ((unsigned)retf & 0x0f);
  453. inregs.ebx = (unsigned)&addr;
  454. exec_in_big_real_mode(&insn_call_far1);
  455. report("call far 1", 0, 1);
  456. exec_in_big_real_mode(&insn_call_far2);
  457. report("call far 2", 0, 1);
  458. exec_in_big_real_mode(&insn_ret_imm);
  459. report("ret imm 1", 0, 1);
  460. exec_in_big_real_mode(&insn_retf_imm);
  461. report("retf imm 1", 0, 1);
  462. }
  463. void test_jcc_short(void)
  464. {
  465. MK_INSN(jnz_short1, "jnz 1f\n\t"
  466. "mov $0x1234, %eax\n\t"
  467. "1:\n\t");
  468. MK_INSN(jnz_short2, "1:\n\t"
  469. "cmp $0x1234, %eax\n\t"
  470. "mov $0x1234, %eax\n\t"
  471. "jnz 1b\n\t");
  472. MK_INSN(jmp_short1, "jmp 1f\n\t"
  473. "mov $0x1234, %eax\n\t"
  474. "1:\n\t");
  475. init_inregs(NULL);
  476. exec_in_big_real_mode(&insn_jnz_short1);
  477. report("jnz short 1", ~0, 1);
  478. exec_in_big_real_mode(&insn_jnz_short2);
  479. report("jnz short 2", R_AX, (outregs.eflags & (1 << 6)));
  480. exec_in_big_real_mode(&insn_jmp_short1);
  481. report("jmp short 1", ~0, 1);
  482. }
  483. void test_jcc_near(void)
  484. {
  485. /* encode near jmp manually. gas will not do it if offsets < 127 byte */
  486. MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t"
  487. "mov $0x1234, %eax\n\t");
  488. MK_INSN(jnz_near2, "cmp $0x1234, %eax\n\t"
  489. "mov $0x1234, %eax\n\t"
  490. ".byte 0x0f, 0x85, 0xf0, 0xff\n\t");
  491. MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t"
  492. "mov $0x1234, %eax\n\t");
  493. init_inregs(NULL);
  494. exec_in_big_real_mode(&insn_jnz_near1);
  495. report("jnz near 1", 0, 1);
  496. exec_in_big_real_mode(&insn_jnz_near2);
  497. report("jnz near 2", R_AX, outregs.eflags & (1 << 6));
  498. exec_in_big_real_mode(&insn_jmp_near1);
  499. report("jmp near 1", 0, 1);
  500. }
  501. void test_long_jmp()
  502. {
  503. MK_INSN(long_jmp, "call 1f\n\t"
  504. "jmp 2f\n\t"
  505. "1: jmp $0, $test_function\n\t"
  506. "2:\n\t");
  507. init_inregs(NULL);
  508. exec_in_big_real_mode(&insn_long_jmp);
  509. report("jmp far 1", R_AX, outregs.eax == 0x1234);
  510. }
  511. void test_push_pop()
  512. {
  513. MK_INSN(push32, "mov $0x12345678, %eax\n\t"
  514. "push %eax\n\t"
  515. "pop %ebx\n\t");
  516. MK_INSN(push16, "mov $0x1234, %ax\n\t"
  517. "push %ax\n\t"
  518. "pop %bx\n\t");
  519. MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten
  520. "mov $0x123, %ax\n\t"
  521. "mov %ax, %es\n\t"
  522. "pushl %es\n\t"
  523. "pop %ebx \n\t"
  524. );
  525. MK_INSN(pop_es, "push %eax\n\t"
  526. "popl %es\n\t"
  527. "mov %es, %bx\n\t"
  528. );
  529. MK_INSN(push_pop_ss, "push %ss\n\t"
  530. "pushw %ax\n\t"
  531. "popw %ss\n\t"
  532. "mov %ss, %bx\n\t"
  533. "pop %ss\n\t"
  534. );
  535. MK_INSN(push_pop_fs, "push %fs\n\t"
  536. "pushl %eax\n\t"
  537. "popl %fs\n\t"
  538. "mov %fs, %ebx\n\t"
  539. "pop %fs\n\t"
  540. );
  541. MK_INSN(push_pop_high_esp_bits,
  542. "xor $0x12340000, %esp \n\t"
  543. "push %ax; \n\t"
  544. "xor $0x12340000, %esp \n\t"
  545. "pop %bx");
  546. init_inregs(NULL);
  547. exec_in_big_real_mode(&insn_push32);
  548. report("push/pop 1", R_AX|R_BX,
  549. outregs.eax == outregs.ebx && outregs.eax == 0x12345678);
  550. exec_in_big_real_mode(&insn_push16);
  551. report("push/pop 2", R_AX|R_BX,
  552. outregs.eax == outregs.ebx && outregs.eax == 0x1234);
  553. exec_in_big_real_mode(&insn_push_es);
  554. report("push/pop 3", R_AX|R_BX,
  555. outregs.ebx == outregs.eax && outregs.eax == 0x123);
  556. exec_in_big_real_mode(&insn_pop_es);
  557. report("push/pop 4", R_AX|R_BX, outregs.ebx == outregs.eax);
  558. exec_in_big_real_mode(&insn_push_pop_ss);
  559. report("push/pop 5", R_AX|R_BX, outregs.ebx == outregs.eax);
  560. exec_in_big_real_mode(&insn_push_pop_fs);
  561. report("push/pop 6", R_AX|R_BX, outregs.ebx == outregs.eax);
  562. inregs.eax = 0x9977;
  563. inregs.ebx = 0x7799;
  564. exec_in_big_real_mode(&insn_push_pop_high_esp_bits);
  565. report("push/pop with high bits set in %esp", R_BX, outregs.ebx == 0x9977);
  566. }
  567. void test_null(void)
  568. {
  569. MK_INSN(null, "");
  570. init_inregs(NULL);
  571. exec_in_big_real_mode(&insn_null);
  572. report("null", 0, 1);
  573. }
  574. static void test_pusha_popa(void)
  575. {
  576. MK_INSN(pusha, "pusha\n\t"
  577. "pop %edi\n\t"
  578. "pop %esi\n\t"
  579. "pop %ebp\n\t"
  580. "add $4, %esp\n\t"
  581. "pop %ebx\n\t"
  582. "pop %edx\n\t"
  583. "pop %ecx\n\t"
  584. "pop %eax\n\t"
  585. );
  586. MK_INSN(popa, "push %eax\n\t"
  587. "push %ecx\n\t"
  588. "push %edx\n\t"
  589. "push %ebx\n\t"
  590. "push %esp\n\t"
  591. "push %ebp\n\t"
  592. "push %esi\n\t"
  593. "push %edi\n\t"
  594. "popa\n\t"
  595. );
  596. init_inregs(&(struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6 });
  597. exec_in_big_real_mode(&insn_pusha);
  598. report("pusha/popa 1", 0, 1);
  599. exec_in_big_real_mode(&insn_popa);
  600. report("pusha/popa 1", 0, 1);
  601. }
  602. void test_iret()
  603. {
  604. MK_INSN(iret32, "pushf\n\t"
  605. "pushl %cs\n\t"
  606. "call 1f\n\t" /* a near call will push eip onto the stack */
  607. "jmp 2f\n\t"
  608. "1: iretl\n\t"
  609. "2:\n\t"
  610. );
  611. MK_INSN(iret16, "pushfw\n\t"
  612. "pushw %cs\n\t"
  613. "callw 1f\n\t"
  614. "jmp 2f\n\t"
  615. "1: iretw\n\t"
  616. "2:\n\t");
  617. MK_INSN(iret_flags32, "pushfl\n\t"
  618. "popl %eax\n\t"
  619. "andl $~0x2, %eax\n\t"
  620. "orl $0xffc18028, %eax\n\t"
  621. "pushl %eax\n\t"
  622. "pushl %cs\n\t"
  623. "call 1f\n\t"
  624. "jmp 2f\n\t"
  625. "1: iretl\n\t"
  626. "2:\n\t");
  627. MK_INSN(iret_flags16, "pushfw\n\t"
  628. "popw %ax\n\t"
  629. "and $~0x2, %ax\n\t"
  630. "or $0x8028, %ax\n\t"
  631. "pushw %ax\n\t"
  632. "pushw %cs\n\t"
  633. "callw 1f\n\t"
  634. "jmp 2f\n\t"
  635. "1: iretw\n\t"
  636. "2:\n\t");
  637. init_inregs(NULL);
  638. exec_in_big_real_mode(&insn_iret32);
  639. report("iret 1", 0, 1);
  640. exec_in_big_real_mode(&insn_iret16);
  641. report("iret 2", 0, 1);
  642. exec_in_big_real_mode(&insn_iret_flags32);
  643. report("iret 3", R_AX, 1);
  644. report("rflags.rf", ~0, !(outregs.eflags & (1 << 16)));
  645. exec_in_big_real_mode(&insn_iret_flags16);
  646. report("iret 4", R_AX, 1);
  647. }
  648. void test_int()
  649. {
  650. init_inregs(NULL);
  651. *(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */
  652. *(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */
  653. MK_INSN(int11, "int $0x11\n\t");
  654. exec_in_big_real_mode(&insn_int11);
  655. report("int 1", 0, 1);
  656. }
  657. void test_imul()
  658. {
  659. MK_INSN(imul8_1, "mov $2, %al\n\t"
  660. "mov $-4, %cx\n\t"
  661. "imul %cl\n\t");
  662. MK_INSN(imul16_1, "mov $2, %ax\n\t"
  663. "mov $-4, %cx\n\t"
  664. "imul %cx\n\t");
  665. MK_INSN(imul32_1, "mov $2, %eax\n\t"
  666. "mov $-4, %ecx\n\t"
  667. "imul %ecx\n\t");
  668. MK_INSN(imul8_2, "mov $0x12340002, %eax\n\t"
  669. "mov $4, %cx\n\t"
  670. "imul %cl\n\t");
  671. MK_INSN(imul16_2, "mov $2, %ax\n\t"
  672. "mov $4, %cx\n\t"
  673. "imul %cx\n\t");
  674. MK_INSN(imul32_2, "mov $2, %eax\n\t"
  675. "mov $4, %ecx\n\t"
  676. "imul %ecx\n\t");
  677. init_inregs(NULL);
  678. exec_in_big_real_mode(&insn_imul8_1);
  679. report("imul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == (u8)-8);
  680. exec_in_big_real_mode(&insn_imul16_1);
  681. report("imul 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-8);
  682. exec_in_big_real_mode(&insn_imul32_1);
  683. report("imul 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-8);
  684. exec_in_big_real_mode(&insn_imul8_2);
  685. report("imul 4", R_AX | R_CX | R_DX,
  686. (outregs.eax & 0xffff) == 8
  687. && (outregs.eax & 0xffff0000) == 0x12340000);
  688. exec_in_big_real_mode(&insn_imul16_2);
  689. report("imul 5", R_AX | R_CX | R_DX, outregs.eax == 8);
  690. exec_in_big_real_mode(&insn_imul32_2);
  691. report("imul 6", R_AX | R_CX | R_DX, outregs.eax == 8);
  692. }
  693. void test_mul()
  694. {
  695. MK_INSN(mul8, "mov $2, %al\n\t"
  696. "mov $4, %cx\n\t"
  697. "imul %cl\n\t");
  698. MK_INSN(mul16, "mov $2, %ax\n\t"
  699. "mov $4, %cx\n\t"
  700. "imul %cx\n\t");
  701. MK_INSN(mul32, "mov $2, %eax\n\t"
  702. "mov $4, %ecx\n\t"
  703. "imul %ecx\n\t");
  704. init_inregs(NULL);
  705. exec_in_big_real_mode(&insn_mul8);
  706. report("mul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == 8);
  707. exec_in_big_real_mode(&insn_mul16);
  708. report("mul 2", R_AX | R_CX | R_DX, outregs.eax == 8);
  709. exec_in_big_real_mode(&insn_mul32);
  710. report("mul 3", R_AX | R_CX | R_DX, outregs.eax == 8);
  711. }
  712. void test_div()
  713. {
  714. MK_INSN(div8, "mov $257, %ax\n\t"
  715. "mov $2, %cl\n\t"
  716. "div %cl\n\t");
  717. MK_INSN(div16, "mov $512, %ax\n\t"
  718. "mov $5, %cx\n\t"
  719. "div %cx\n\t");
  720. MK_INSN(div32, "mov $512, %eax\n\t"
  721. "mov $5, %ecx\n\t"
  722. "div %ecx\n\t");
  723. init_inregs(NULL);
  724. exec_in_big_real_mode(&insn_div8);
  725. report("div 1", R_AX | R_CX | R_DX, outregs.eax == 384);
  726. exec_in_big_real_mode(&insn_div16);
  727. report("div 2", R_AX | R_CX | R_DX,
  728. outregs.eax == 102 && outregs.edx == 2);
  729. exec_in_big_real_mode(&insn_div32);
  730. report("div 3", R_AX | R_CX | R_DX,
  731. outregs.eax == 102 && outregs.edx == 2);
  732. }
  733. void test_idiv()
  734. {
  735. MK_INSN(idiv8, "mov $256, %ax\n\t"
  736. "mov $-2, %cl\n\t"
  737. "idiv %cl\n\t");
  738. MK_INSN(idiv16, "mov $512, %ax\n\t"
  739. "mov $-2, %cx\n\t"
  740. "idiv %cx\n\t");
  741. MK_INSN(idiv32, "mov $512, %eax\n\t"
  742. "mov $-2, %ecx\n\t"
  743. "idiv %ecx\n\t");
  744. init_inregs(NULL);
  745. exec_in_big_real_mode(&insn_idiv8);
  746. report("idiv 1", R_AX | R_CX | R_DX, outregs.eax == (u8)-128);
  747. exec_in_big_real_mode(&insn_idiv16);
  748. report("idiv 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-256);
  749. exec_in_big_real_mode(&insn_idiv32);
  750. report("idiv 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-256);
  751. }
  752. void test_cbw(void)
  753. {
  754. MK_INSN(cbw, "mov $0xFE, %eax \n\t"
  755. "cbw\n\t");
  756. MK_INSN(cwde, "mov $0xFFFE, %eax \n\t"
  757. "cwde\n\t");
  758. init_inregs(NULL);
  759. exec_in_big_real_mode(&insn_cbw);
  760. report("cbq 1", ~0, outregs.eax == 0xFFFE);
  761. exec_in_big_real_mode(&insn_cwde);
  762. report("cwde 1", ~0, outregs.eax == 0xFFFFFFFE);
  763. }
  764. void test_loopcc(void)
  765. {
  766. MK_INSN(loop, "mov $10, %ecx\n\t"
  767. "1: inc %eax\n\t"
  768. "loop 1b\n\t");
  769. MK_INSN(loope, "mov $10, %ecx\n\t"
  770. "mov $1, %eax\n\t"
  771. "1: dec %eax\n\t"
  772. "loope 1b\n\t");
  773. MK_INSN(loopne, "mov $10, %ecx\n\t"
  774. "mov $5, %eax\n\t"
  775. "1: dec %eax\n\t"
  776. "loopne 1b\n\t");
  777. init_inregs(NULL);
  778. exec_in_big_real_mode(&insn_loop);
  779. report("LOOPcc short 1", R_AX, outregs.eax == 10);
  780. exec_in_big_real_mode(&insn_loope);
  781. report("LOOPcc short 2", R_AX | R_CX,
  782. outregs.eax == -1 && outregs.ecx == 8);
  783. exec_in_big_real_mode(&insn_loopne);
  784. report("LOOPcc short 3", R_AX | R_CX,
  785. outregs.eax == 0 && outregs.ecx == 5);
  786. }
  787. static void test_das(void)
  788. {
  789. short i;
  790. u16 nr_fail = 0;
  791. static unsigned test_cases[1024] = {
  792. 0x46000000, 0x8701a000, 0x9710fa00, 0x97119a00,
  793. 0x02000101, 0x8301a101, 0x9310fb01, 0x93119b01,
  794. 0x02000202, 0x8301a202, 0x9710fc02, 0x97119c02,
  795. 0x06000303, 0x8701a303, 0x9310fd03, 0x93119d03,
  796. 0x02000404, 0x8301a404, 0x9310fe04, 0x93119e04,
  797. 0x06000505, 0x8701a505, 0x9710ff05, 0x97119f05,
  798. 0x06000606, 0x8701a606, 0x56100006, 0x9711a006,
  799. 0x02000707, 0x8301a707, 0x12100107, 0x9311a107,
  800. 0x02000808, 0x8301a808, 0x12100208, 0x9311a208,
  801. 0x06000909, 0x8701a909, 0x16100309, 0x9711a309,
  802. 0x1200040a, 0x9301a40a, 0x1210040a, 0x9311a40a,
  803. 0x1600050b, 0x9701a50b, 0x1610050b, 0x9711a50b,
  804. 0x1600060c, 0x9701a60c, 0x1610060c, 0x9711a60c,
  805. 0x1200070d, 0x9301a70d, 0x1210070d, 0x9311a70d,
  806. 0x1200080e, 0x9301a80e, 0x1210080e, 0x9311a80e,
  807. 0x1600090f, 0x9701a90f, 0x1610090f, 0x9711a90f,
  808. 0x02001010, 0x8301b010, 0x16100a10, 0x9711aa10,
  809. 0x06001111, 0x8701b111, 0x12100b11, 0x9311ab11,
  810. 0x06001212, 0x8701b212, 0x16100c12, 0x9711ac12,
  811. 0x02001313, 0x8301b313, 0x12100d13, 0x9311ad13,
  812. 0x06001414, 0x8701b414, 0x12100e14, 0x9311ae14,
  813. 0x02001515, 0x8301b515, 0x16100f15, 0x9711af15,
  814. 0x02001616, 0x8301b616, 0x12101016, 0x9311b016,
  815. 0x06001717, 0x8701b717, 0x16101117, 0x9711b117,
  816. 0x06001818, 0x8701b818, 0x16101218, 0x9711b218,
  817. 0x02001919, 0x8301b919, 0x12101319, 0x9311b319,
  818. 0x1600141a, 0x9701b41a, 0x1610141a, 0x9711b41a,
  819. 0x1200151b, 0x9301b51b, 0x1210151b, 0x9311b51b,
  820. 0x1200161c, 0x9301b61c, 0x1210161c, 0x9311b61c,
  821. 0x1600171d, 0x9701b71d, 0x1610171d, 0x9711b71d,
  822. 0x1600181e, 0x9701b81e, 0x1610181e, 0x9711b81e,
  823. 0x1200191f, 0x9301b91f, 0x1210191f, 0x9311b91f,
  824. 0x02002020, 0x8701c020, 0x12101a20, 0x9311ba20,
  825. 0x06002121, 0x8301c121, 0x16101b21, 0x9711bb21,
  826. 0x06002222, 0x8301c222, 0x12101c22, 0x9311bc22,
  827. 0x02002323, 0x8701c323, 0x16101d23, 0x9711bd23,
  828. 0x06002424, 0x8301c424, 0x16101e24, 0x9711be24,
  829. 0x02002525, 0x8701c525, 0x12101f25, 0x9311bf25,
  830. 0x02002626, 0x8701c626, 0x12102026, 0x9711c026,
  831. 0x06002727, 0x8301c727, 0x16102127, 0x9311c127,
  832. 0x06002828, 0x8301c828, 0x16102228, 0x9311c228,
  833. 0x02002929, 0x8701c929, 0x12102329, 0x9711c329,
  834. 0x1600242a, 0x9301c42a, 0x1610242a, 0x9311c42a,
  835. 0x1200252b, 0x9701c52b, 0x1210252b, 0x9711c52b,
  836. 0x1200262c, 0x9701c62c, 0x1210262c, 0x9711c62c,
  837. 0x1600272d, 0x9301c72d, 0x1610272d, 0x9311c72d,
  838. 0x1600282e, 0x9301c82e, 0x1610282e, 0x9311c82e,
  839. 0x1200292f, 0x9701c92f, 0x1210292f, 0x9711c92f,
  840. 0x06003030, 0x8301d030, 0x12102a30, 0x9711ca30,
  841. 0x02003131, 0x8701d131, 0x16102b31, 0x9311cb31,
  842. 0x02003232, 0x8701d232, 0x12102c32, 0x9711cc32,
  843. 0x06003333, 0x8301d333, 0x16102d33, 0x9311cd33,
  844. 0x02003434, 0x8701d434, 0x16102e34, 0x9311ce34,
  845. 0x06003535, 0x8301d535, 0x12102f35, 0x9711cf35,
  846. 0x06003636, 0x8301d636, 0x16103036, 0x9311d036,
  847. 0x02003737, 0x8701d737, 0x12103137, 0x9711d137,
  848. 0x02003838, 0x8701d838, 0x12103238, 0x9711d238,
  849. 0x06003939, 0x8301d939, 0x16103339, 0x9311d339,
  850. 0x1200343a, 0x9701d43a, 0x1210343a, 0x9711d43a,
  851. 0x1600353b, 0x9301d53b, 0x1610353b, 0x9311d53b,
  852. 0x1600363c, 0x9301d63c, 0x1610363c, 0x9311d63c,
  853. 0x1200373d, 0x9701d73d, 0x1210373d, 0x9711d73d,
  854. 0x1200383e, 0x9701d83e, 0x1210383e, 0x9711d83e,
  855. 0x1600393f, 0x9301d93f, 0x1610393f, 0x9311d93f,
  856. 0x02004040, 0x8301e040, 0x16103a40, 0x9311da40,
  857. 0x06004141, 0x8701e141, 0x12103b41, 0x9711db41,
  858. 0x06004242, 0x8701e242, 0x16103c42, 0x9311dc42,
  859. 0x02004343, 0x8301e343, 0x12103d43, 0x9711dd43,
  860. 0x06004444, 0x8701e444, 0x12103e44, 0x9711de44,
  861. 0x02004545, 0x8301e545, 0x16103f45, 0x9311df45,
  862. 0x02004646, 0x8301e646, 0x12104046, 0x9311e046,
  863. 0x06004747, 0x8701e747, 0x16104147, 0x9711e147,
  864. 0x06004848, 0x8701e848, 0x16104248, 0x9711e248,
  865. 0x02004949, 0x8301e949, 0x12104349, 0x9311e349,
  866. 0x1600444a, 0x9701e44a, 0x1610444a, 0x9711e44a,
  867. 0x1200454b, 0x9301e54b, 0x1210454b, 0x9311e54b,
  868. 0x1200464c, 0x9301e64c, 0x1210464c, 0x9311e64c,
  869. 0x1600474d, 0x9701e74d, 0x1610474d, 0x9711e74d,
  870. 0x1600484e, 0x9701e84e, 0x1610484e, 0x9711e84e,
  871. 0x1200494f, 0x9301e94f, 0x1210494f, 0x9311e94f,
  872. 0x06005050, 0x8701f050, 0x12104a50, 0x9311ea50,
  873. 0x02005151, 0x8301f151, 0x16104b51, 0x9711eb51,
  874. 0x02005252, 0x8301f252, 0x12104c52, 0x9311ec52,
  875. 0x06005353, 0x8701f353, 0x16104d53, 0x9711ed53,
  876. 0x02005454, 0x8301f454, 0x16104e54, 0x9711ee54,
  877. 0x06005555, 0x8701f555, 0x12104f55, 0x9311ef55,
  878. 0x06005656, 0x8701f656, 0x16105056, 0x9711f056,
  879. 0x02005757, 0x8301f757, 0x12105157, 0x9311f157,
  880. 0x02005858, 0x8301f858, 0x12105258, 0x9311f258,
  881. 0x06005959, 0x8701f959, 0x16105359, 0x9711f359,
  882. 0x1200545a, 0x9301f45a, 0x1210545a, 0x9311f45a,
  883. 0x1600555b, 0x9701f55b, 0x1610555b, 0x9711f55b,
  884. 0x1600565c, 0x9701f65c, 0x1610565c, 0x9711f65c,
  885. 0x1200575d, 0x9301f75d, 0x1210575d, 0x9311f75d,
  886. 0x1200585e, 0x9301f85e, 0x1210585e, 0x9311f85e,
  887. 0x1600595f, 0x9701f95f, 0x1610595f, 0x9711f95f,
  888. 0x06006060, 0x47010060, 0x16105a60, 0x9711fa60,
  889. 0x02006161, 0x03010161, 0x12105b61, 0x9311fb61,
  890. 0x02006262, 0x03010262, 0x16105c62, 0x9711fc62,
  891. 0x06006363, 0x07010363, 0x12105d63, 0x9311fd63,
  892. 0x02006464, 0x03010464, 0x12105e64, 0x9311fe64,
  893. 0x06006565, 0x07010565, 0x16105f65, 0x9711ff65,
  894. 0x06006666, 0x07010666, 0x16106066, 0x57110066,
  895. 0x02006767, 0x03010767, 0x12106167, 0x13110167,
  896. 0x02006868, 0x03010868, 0x12106268, 0x13110268,
  897. 0x06006969, 0x07010969, 0x16106369, 0x17110369,
  898. 0x1200646a, 0x1301046a, 0x1210646a, 0x1311046a,
  899. 0x1600656b, 0x1701056b, 0x1610656b, 0x1711056b,
  900. 0x1600666c, 0x1701066c, 0x1610666c, 0x1711066c,
  901. 0x1200676d, 0x1301076d, 0x1210676d, 0x1311076d,
  902. 0x1200686e, 0x1301086e, 0x1210686e, 0x1311086e,
  903. 0x1600696f, 0x1701096f, 0x1610696f, 0x1711096f,
  904. 0x02007070, 0x03011070, 0x16106a70, 0x17110a70,
  905. 0x06007171, 0x07011171, 0x12106b71, 0x13110b71,
  906. 0x06007272, 0x07011272, 0x16106c72, 0x17110c72,
  907. 0x02007373, 0x03011373, 0x12106d73, 0x13110d73,
  908. 0x06007474, 0x07011474, 0x12106e74, 0x13110e74,
  909. 0x02007575, 0x03011575, 0x16106f75, 0x17110f75,
  910. 0x02007676, 0x03011676, 0x12107076, 0x13111076,
  911. 0x06007777, 0x07011777, 0x16107177, 0x17111177,
  912. 0x06007878, 0x07011878, 0x16107278, 0x17111278,
  913. 0x02007979, 0x03011979, 0x12107379, 0x13111379,
  914. 0x1600747a, 0x1701147a, 0x1610747a, 0x1711147a,
  915. 0x1200757b, 0x1301157b, 0x1210757b, 0x1311157b,
  916. 0x1200767c, 0x1301167c, 0x1210767c, 0x1311167c,
  917. 0x1600777d, 0x1701177d, 0x1610777d, 0x1711177d,
  918. 0x1600787e, 0x1701187e, 0x1610787e, 0x1711187e,
  919. 0x1200797f, 0x1301197f, 0x1210797f, 0x1311197f,
  920. 0x82008080, 0x03012080, 0x12107a80, 0x13111a80,
  921. 0x86008181, 0x07012181, 0x16107b81, 0x17111b81,
  922. 0x86008282, 0x07012282, 0x12107c82, 0x13111c82,
  923. 0x82008383, 0x03012383, 0x16107d83, 0x17111d83,
  924. 0x86008484, 0x07012484, 0x16107e84, 0x17111e84,
  925. 0x82008585, 0x03012585, 0x12107f85, 0x13111f85,
  926. 0x82008686, 0x03012686, 0x92108086, 0x13112086,
  927. 0x86008787, 0x07012787, 0x96108187, 0x17112187,
  928. 0x86008888, 0x07012888, 0x96108288, 0x17112288,
  929. 0x82008989, 0x03012989, 0x92108389, 0x13112389,
  930. 0x9600848a, 0x1701248a, 0x9610848a, 0x1711248a,
  931. 0x9200858b, 0x1301258b, 0x9210858b, 0x1311258b,
  932. 0x9200868c, 0x1301268c, 0x9210868c, 0x1311268c,
  933. 0x9600878d, 0x1701278d, 0x9610878d, 0x1711278d,
  934. 0x9600888e, 0x1701288e, 0x9610888e, 0x1711288e,
  935. 0x9200898f, 0x1301298f, 0x9210898f, 0x1311298f,
  936. 0x86009090, 0x07013090, 0x92108a90, 0x13112a90,
  937. 0x82009191, 0x03013191, 0x96108b91, 0x17112b91,
  938. 0x82009292, 0x03013292, 0x92108c92, 0x13112c92,
  939. 0x86009393, 0x07013393, 0x96108d93, 0x17112d93,
  940. 0x82009494, 0x03013494, 0x96108e94, 0x17112e94,
  941. 0x86009595, 0x07013595, 0x92108f95, 0x13112f95,
  942. 0x86009696, 0x07013696, 0x96109096, 0x17113096,
  943. 0x82009797, 0x03013797, 0x92109197, 0x13113197,
  944. 0x82009898, 0x03013898, 0x92109298, 0x13113298,
  945. 0x86009999, 0x07013999, 0x96109399, 0x17113399,
  946. 0x1300349a, 0x1301349a, 0x1310349a, 0x1311349a,
  947. 0x1700359b, 0x1701359b, 0x1710359b, 0x1711359b,
  948. 0x1700369c, 0x1701369c, 0x1710369c, 0x1711369c,
  949. 0x1300379d, 0x1301379d, 0x1310379d, 0x1311379d,
  950. 0x1300389e, 0x1301389e, 0x1310389e, 0x1311389e,
  951. 0x1700399f, 0x1701399f, 0x1710399f, 0x1711399f,
  952. 0x030040a0, 0x030140a0, 0x17103aa0, 0x17113aa0,
  953. 0x070041a1, 0x070141a1, 0x13103ba1, 0x13113ba1,
  954. 0x070042a2, 0x070142a2, 0x17103ca2, 0x17113ca2,
  955. 0x030043a3, 0x030143a3, 0x13103da3, 0x13113da3,
  956. 0x070044a4, 0x070144a4, 0x13103ea4, 0x13113ea4,
  957. 0x030045a5, 0x030145a5, 0x17103fa5, 0x17113fa5,
  958. 0x030046a6, 0x030146a6, 0x131040a6, 0x131140a6,
  959. 0x070047a7, 0x070147a7, 0x171041a7, 0x171141a7,
  960. 0x070048a8, 0x070148a8, 0x171042a8, 0x171142a8,
  961. 0x030049a9, 0x030149a9, 0x131043a9, 0x131143a9,
  962. 0x170044aa, 0x170144aa, 0x171044aa, 0x171144aa,
  963. 0x130045ab, 0x130145ab, 0x131045ab, 0x131145ab,
  964. 0x130046ac, 0x130146ac, 0x131046ac, 0x131146ac,
  965. 0x170047ad, 0x170147ad, 0x171047ad, 0x171147ad,
  966. 0x170048ae, 0x170148ae, 0x171048ae, 0x171148ae,
  967. 0x130049af, 0x130149af, 0x131049af, 0x131149af,
  968. 0x070050b0, 0x070150b0, 0x13104ab0, 0x13114ab0,
  969. 0x030051b1, 0x030151b1, 0x17104bb1, 0x17114bb1,
  970. 0x030052b2, 0x030152b2, 0x13104cb2, 0x13114cb2,
  971. 0x070053b3, 0x070153b3, 0x17104db3, 0x17114db3,
  972. 0x030054b4, 0x030154b4, 0x17104eb4, 0x17114eb4,
  973. 0x070055b5, 0x070155b5, 0x13104fb5, 0x13114fb5,
  974. 0x070056b6, 0x070156b6, 0x171050b6, 0x171150b6,
  975. 0x030057b7, 0x030157b7, 0x131051b7, 0x131151b7,
  976. 0x030058b8, 0x030158b8, 0x131052b8, 0x131152b8,
  977. 0x070059b9, 0x070159b9, 0x171053b9, 0x171153b9,
  978. 0x130054ba, 0x130154ba, 0x131054ba, 0x131154ba,
  979. 0x170055bb, 0x170155bb, 0x171055bb, 0x171155bb,
  980. 0x170056bc, 0x170156bc, 0x171056bc, 0x171156bc,
  981. 0x130057bd, 0x130157bd, 0x131057bd, 0x131157bd,
  982. 0x130058be, 0x130158be, 0x131058be, 0x131158be,
  983. 0x170059bf, 0x170159bf, 0x171059bf, 0x171159bf,
  984. 0x070060c0, 0x070160c0, 0x17105ac0, 0x17115ac0,
  985. 0x030061c1, 0x030161c1, 0x13105bc1, 0x13115bc1,
  986. 0x030062c2, 0x030162c2, 0x17105cc2, 0x17115cc2,
  987. 0x070063c3, 0x070163c3, 0x13105dc3, 0x13115dc3,
  988. 0x030064c4, 0x030164c4, 0x13105ec4, 0x13115ec4,
  989. 0x070065c5, 0x070165c5, 0x17105fc5, 0x17115fc5,
  990. 0x070066c6, 0x070166c6, 0x171060c6, 0x171160c6,
  991. 0x030067c7, 0x030167c7, 0x131061c7, 0x131161c7,
  992. 0x030068c8, 0x030168c8, 0x131062c8, 0x131162c8,
  993. 0x070069c9, 0x070169c9, 0x171063c9, 0x171163c9,
  994. 0x130064ca, 0x130164ca, 0x131064ca, 0x131164ca,
  995. 0x170065cb, 0x170165cb, 0x171065cb, 0x171165cb,
  996. 0x170066cc, 0x170166cc, 0x171066cc, 0x171166cc,
  997. 0x130067cd, 0x130167cd, 0x131067cd, 0x131167cd,
  998. 0x130068ce, 0x130168ce, 0x131068ce, 0x131168ce,
  999. 0x170069cf, 0x170169cf, 0x171069cf, 0x171169cf,
  1000. 0x030070d0, 0x030170d0, 0x17106ad0, 0x17116ad0,
  1001. 0x070071d1, 0x070171d1, 0x13106bd1, 0x13116bd1,
  1002. 0x070072d2, 0x070172d2, 0x17106cd2, 0x17116cd2,
  1003. 0x030073d3, 0x030173d3, 0x13106dd3, 0x13116dd3,
  1004. 0x070074d4, 0x070174d4, 0x13106ed4, 0x13116ed4,
  1005. 0x030075d5, 0x030175d5, 0x17106fd5, 0x17116fd5,
  1006. 0x030076d6, 0x030176d6, 0x131070d6, 0x131170d6,
  1007. 0x070077d7, 0x070177d7, 0x171071d7, 0x171171d7,
  1008. 0x070078d8, 0x070178d8, 0x171072d8, 0x171172d8,
  1009. 0x030079d9, 0x030179d9, 0x131073d9, 0x131173d9,
  1010. 0x170074da, 0x170174da, 0x171074da, 0x171174da,
  1011. 0x130075db, 0x130175db, 0x131075db, 0x131175db,
  1012. 0x130076dc, 0x130176dc, 0x131076dc, 0x131176dc,
  1013. 0x170077dd, 0x170177dd, 0x171077dd, 0x171177dd,
  1014. 0x170078de, 0x170178de, 0x171078de, 0x171178de,
  1015. 0x130079df, 0x130179df, 0x131079df, 0x131179df,
  1016. 0x830080e0, 0x830180e0, 0x13107ae0, 0x13117ae0,
  1017. 0x870081e1, 0x870181e1, 0x17107be1, 0x17117be1,
  1018. 0x870082e2, 0x870182e2, 0x13107ce2, 0x13117ce2,
  1019. 0x830083e3, 0x830183e3, 0x17107de3, 0x17117de3,
  1020. 0x870084e4, 0x870184e4, 0x17107ee4, 0x17117ee4,
  1021. 0x830085e5, 0x830185e5, 0x13107fe5, 0x13117fe5,
  1022. 0x830086e6, 0x830186e6, 0x931080e6, 0x931180e6,
  1023. 0x870087e7, 0x870187e7, 0x971081e7, 0x971181e7,
  1024. 0x870088e8, 0x870188e8, 0x971082e8, 0x971182e8,
  1025. 0x830089e9, 0x830189e9, 0x931083e9, 0x931183e9,
  1026. 0x970084ea, 0x970184ea, 0x971084ea, 0x971184ea,
  1027. 0x930085eb, 0x930185eb, 0x931085eb, 0x931185eb,
  1028. 0x930086ec, 0x930186ec, 0x931086ec, 0x931186ec,
  1029. 0x970087ed, 0x970187ed, 0x971087ed, 0x971187ed,
  1030. 0x970088ee, 0x970188ee, 0x971088ee, 0x971188ee,
  1031. 0x930089ef, 0x930189ef, 0x931089ef, 0x931189ef,
  1032. 0x870090f0, 0x870190f0, 0x93108af0, 0x93118af0,
  1033. 0x830091f1, 0x830191f1, 0x97108bf1, 0x97118bf1,
  1034. 0x830092f2, 0x830192f2, 0x93108cf2, 0x93118cf2,
  1035. 0x870093f3, 0x870193f3, 0x97108df3, 0x97118df3,
  1036. 0x830094f4, 0x830194f4, 0x97108ef4, 0x97118ef4,
  1037. 0x870095f5, 0x870195f5, 0x93108ff5, 0x93118ff5,
  1038. 0x870096f6, 0x870196f6, 0x971090f6, 0x971190f6,
  1039. 0x830097f7, 0x830197f7, 0x931091f7, 0x931191f7,
  1040. 0x830098f8, 0x830198f8, 0x931092f8, 0x931192f8,
  1041. 0x870099f9, 0x870199f9, 0x971093f9, 0x971193f9,
  1042. 0x930094fa, 0x930194fa, 0x931094fa, 0x931194fa,
  1043. 0x970095fb, 0x970195fb, 0x971095fb, 0x971195fb,
  1044. 0x970096fc, 0x970196fc, 0x971096fc, 0x971196fc,
  1045. 0x930097fd, 0x930197fd, 0x931097fd, 0x931197fd,
  1046. 0x930098fe, 0x930198fe, 0x931098fe, 0x931198fe,
  1047. 0x970099ff, 0x970199ff, 0x971099ff, 0x971199ff,
  1048. };
  1049. MK_INSN(das, "das");
  1050. init_inregs(NULL);
  1051. for (i = 0; i < 1024; ++i) {
  1052. unsigned tmp = test_cases[i];
  1053. inregs.eax = tmp & 0xff;
  1054. inregs.eflags = (tmp >> 16) & 0xff;
  1055. exec_in_big_real_mode(&insn_das);
  1056. if (!regs_equal(R_AX)
  1057. || outregs.eax != ((tmp >> 8) & 0xff)
  1058. || (outregs.eflags & 0xff) != (tmp >> 24)) {
  1059. ++nr_fail;
  1060. break;
  1061. }
  1062. }
  1063. report("DAS", ~0, nr_fail == 0);
  1064. }
  1065. void test_cwd_cdq()
  1066. {
  1067. /* Sign-bit set */
  1068. MK_INSN(cwd_1, "mov $0x8000, %ax\n\t"
  1069. "cwd\n\t");
  1070. /* Sign-bit not set */
  1071. MK_INSN(cwd_2, "mov $0x1000, %ax\n\t"
  1072. "cwd\n\t");
  1073. /* Sign-bit set */
  1074. MK_INSN(cdq_1, "mov $0x80000000, %eax\n\t"
  1075. "cdq\n\t");
  1076. /* Sign-bit not set */
  1077. MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t"
  1078. "cdq\n\t");
  1079. init_inregs(NULL);
  1080. exec_in_big_real_mode(&insn_cwd_1);
  1081. report("cwd 1", R_AX | R_DX,
  1082. outregs.eax == 0x8000 && outregs.edx == 0xffff);
  1083. exec_in_big_real_mode(&insn_cwd_2);
  1084. report("cwd 2", R_AX | R_DX,
  1085. outregs.eax == 0x1000 && outregs.edx == 0);
  1086. exec_in_big_real_mode(&insn_cdq_1);
  1087. report("cdq 1", R_AX | R_DX,
  1088. outregs.eax == 0x80000000 && outregs.edx == 0xffffffff);
  1089. exec_in_big_real_mode(&insn_cdq_2);
  1090. report("cdq 2", R_AX | R_DX,
  1091. outregs.eax == 0x10000000 && outregs.edx == 0);
  1092. }
  1093. static struct {
  1094. void *address;
  1095. unsigned short sel;
  1096. } __attribute__((packed)) desc = {
  1097. (void *)0x1234,
  1098. 0x10,
  1099. };
  1100. void test_lds_lss()
  1101. {
  1102. init_inregs(&(struct regs){ .ebx = (unsigned long)&desc });
  1103. MK_INSN(lds, "push %ds\n\t"
  1104. "lds (%ebx), %eax\n\t"
  1105. "mov %ds, %ebx\n\t"
  1106. "pop %ds\n\t");
  1107. exec_in_big_real_mode(&insn_lds);
  1108. report("lds", R_AX | R_BX,
  1109. outregs.eax == (unsigned long)desc.address &&
  1110. outregs.ebx == desc.sel);
  1111. MK_INSN(les, "les (%ebx), %eax\n\t"
  1112. "mov %es, %ebx\n\t");
  1113. exec_in_big_real_mode(&insn_les);
  1114. report("les", R_AX | R_BX,
  1115. outregs.eax == (unsigned long)desc.address &&
  1116. outregs.ebx == desc.sel);
  1117. MK_INSN(lfs, "push %fs\n\t"
  1118. "lfs (%ebx), %eax\n\t"
  1119. "mov %fs, %ebx\n\t"
  1120. "pop %fs\n\t");
  1121. exec_in_big_real_mode(&insn_lfs);
  1122. report("lfs", R_AX | R_BX,
  1123. outregs.eax == (unsigned long)desc.address &&
  1124. outregs.ebx == desc.sel);
  1125. MK_INSN(lgs, "push %gs\n\t"
  1126. "lgs (%ebx), %eax\n\t"
  1127. "mov %gs, %ebx\n\t"
  1128. "pop %gs\n\t");
  1129. exec_in_big_real_mode(&insn_lgs);
  1130. report("lgs", R_AX | R_BX,
  1131. outregs.eax == (unsigned long)desc.address &&
  1132. outregs.ebx == desc.sel);
  1133. MK_INSN(lss, "push %ss\n\t"
  1134. "lss (%ebx), %eax\n\t"
  1135. "mov %ss, %ebx\n\t"
  1136. "pop %ss\n\t");
  1137. exec_in_big_real_mode(&insn_lss);
  1138. report("lss", R_AX | R_BX,
  1139. outregs.eax == (unsigned long)desc.address &&
  1140. outregs.ebx == desc.sel);
  1141. }
  1142. void test_jcxz(void)
  1143. {
  1144. MK_INSN(jcxz1, "jcxz 1f\n\t"
  1145. "mov $0x1234, %eax\n\t"
  1146. "1:\n\t");
  1147. MK_INSN(jcxz2, "mov $0x100, %ecx\n\t"
  1148. "jcxz 1f\n\t"
  1149. "mov $0x1234, %eax\n\t"
  1150. "mov $0, %ecx\n\t"
  1151. "1:\n\t");
  1152. MK_INSN(jcxz3, "mov $0x10000, %ecx\n\t"
  1153. "jcxz 1f\n\t"
  1154. "mov $0x1234, %eax\n\t"
  1155. "1:\n\t");
  1156. MK_INSN(jecxz1, "jecxz 1f\n\t"
  1157. "mov $0x1234, %eax\n\t"
  1158. "1:\n\t");
  1159. MK_INSN(jecxz2, "mov $0x10000, %ecx\n\t"
  1160. "jecxz 1f\n\t"
  1161. "mov $0x1234, %eax\n\t"
  1162. "mov $0, %ecx\n\t"
  1163. "1:\n\t");
  1164. init_inregs(NULL);
  1165. exec_in_big_real_mode(&insn_jcxz1);
  1166. report("jcxz short 1", 0, 1);
  1167. exec_in_big_real_mode(&insn_jcxz2);
  1168. report("jcxz short 2", R_AX, outregs.eax == 0x1234);
  1169. exec_in_big_real_mode(&insn_jcxz3);
  1170. report("jcxz short 3", R_CX, outregs.ecx == 0x10000);
  1171. exec_in_big_real_mode(&insn_jecxz1);
  1172. report("jecxz short 1", 0, 1);
  1173. exec_in_big_real_mode(&insn_jecxz2);
  1174. report("jecxz short 2", R_AX, outregs.eax == 0x1234);
  1175. }
  1176. static void test_cpuid(void)
  1177. {
  1178. MK_INSN(cpuid, "cpuid");
  1179. unsigned function = 0x1234;
  1180. unsigned eax, ebx, ecx, edx;
  1181. init_inregs(&(struct regs){ .eax = function });
  1182. eax = inregs.eax;
  1183. ecx = inregs.ecx;
  1184. asm("cpuid" : "+a"(eax), "=b"(ebx), "+c"(ecx), "=d"(edx));
  1185. exec_in_big_real_mode(&insn_cpuid);
  1186. report("cpuid", R_AX|R_BX|R_CX|R_DX,
  1187. outregs.eax == eax && outregs.ebx == ebx
  1188. && outregs.ecx == ecx && outregs.edx == edx);
  1189. }
  1190. static void test_ss_base_for_esp_ebp(void)
  1191. {
  1192. MK_INSN(ssrel1, "mov %ss, %ax; mov %bx, %ss; movl (%ebp), %ebx; mov %ax, %ss");
  1193. MK_INSN(ssrel2, "mov %ss, %ax; mov %bx, %ss; movl (%ebp,%edi,8), %ebx; mov %ax, %ss");
  1194. static unsigned array[] = { 0x12345678, 0, 0, 0, 0x87654321 };
  1195. init_inregs(&(struct regs){ .ebx = 1, .ebp = (unsigned)array });
  1196. exec_in_big_real_mode(&insn_ssrel1);
  1197. report("ss relative addressing (1)", R_AX | R_BX, outregs.ebx == 0x87654321);
  1198. inregs.ebx = 1;
  1199. inregs.ebp = (unsigned)array;
  1200. inregs.edi = 0;
  1201. exec_in_big_real_mode(&insn_ssrel2);
  1202. report("ss relative addressing (2)", R_AX | R_BX, outregs.ebx == 0x87654321);
  1203. }
  1204. extern unsigned long long r_gdt[];
  1205. static void test_sgdt_sidt(void)
  1206. {
  1207. MK_INSN(sgdt, "sgdtw (%eax)");
  1208. MK_INSN(sidt, "sidtw (%eax)");
  1209. struct table_descr x, y;
  1210. init_inregs(&(struct regs){ .eax = (unsigned)&y });
  1211. asm volatile("sgdtw %0" : "=m"(x));
  1212. exec_in_big_real_mode(&insn_sgdt);
  1213. report("sgdt", 0, x.limit == y.limit && x.base == y.base);
  1214. inregs.eax = (unsigned)&y;
  1215. asm volatile("sidtw %0" : "=m"(x));
  1216. exec_in_big_real_mode(&insn_sidt);
  1217. report("sidt", 0, x.limit == y.limit && x.base == y.base);
  1218. }
  1219. static void test_sahf(void)
  1220. {
  1221. MK_INSN(sahf, "sahf; pushfw; mov (%esp), %al; popfw");
  1222. init_inregs(&(struct regs){ .eax = 0xfd00 });
  1223. exec_in_big_real_mode(&insn_sahf);
  1224. report("sahf", R_AX, outregs.eax == (inregs.eax | 0xd7));
  1225. }
  1226. static void test_lahf(void)
  1227. {
  1228. MK_INSN(lahf, "pushfw; mov %al, (%esp); popfw; lahf");
  1229. init_inregs(&(struct regs){ .eax = 0xc7 });
  1230. exec_in_big_real_mode(&insn_lahf);
  1231. report("lahf", R_AX, (outregs.eax >> 8) == inregs.eax);
  1232. }
  1233. static void test_movzx_movsx(void)
  1234. {
  1235. MK_INSN(movsx, "movsx %al, %ebx");
  1236. MK_INSN(movzx, "movzx %al, %ebx");
  1237. MK_INSN(movzsah, "movsx %ah, %ebx");
  1238. MK_INSN(movzxah, "movzx %ah, %ebx");
  1239. init_inregs(&(struct regs){ .eax = 0x1234569c });
  1240. exec_in_big_real_mode(&insn_movsx);
  1241. report("movsx", R_BX, outregs.ebx == (signed char)inregs.eax);
  1242. exec_in_big_real_mode(&insn_movzx);
  1243. report("movzx", R_BX, outregs.ebx == (unsigned char)inregs.eax);
  1244. exec_in_big_real_mode(&insn_movzsah);
  1245. report("movsx ah", R_BX, outregs.ebx == (signed char)(inregs.eax>>8));
  1246. exec_in_big_real_mode(&insn_movzxah);
  1247. report("movzx ah", R_BX, outregs.ebx == (unsigned char)(inregs.eax >> 8));
  1248. }
  1249. static void test_bswap(void)
  1250. {
  1251. MK_INSN(bswap, "bswap %ecx");
  1252. init_inregs(&(struct regs){ .ecx = 0x12345678 });
  1253. exec_in_big_real_mode(&insn_bswap);
  1254. report("bswap", R_CX, outregs.ecx == 0x78563412);
  1255. }
  1256. static void test_aad(void)
  1257. {
  1258. MK_INSN(aad, "aad");
  1259. init_inregs(&(struct regs){ .eax = 0x12345678 });
  1260. exec_in_big_real_mode(&insn_aad);
  1261. report("aad", R_AX, outregs.eax == 0x123400d4);
  1262. }
  1263. static void test_aam(void)
  1264. {
  1265. MK_INSN(aam, "aam");
  1266. init_inregs(&(struct regs){ .eax = 0x76543210 });
  1267. exec_in_big_real_mode(&insn_aam);
  1268. report("aam", R_AX, outregs.eax == 0x76540106);
  1269. }
  1270. static void test_xlat(void)
  1271. {
  1272. MK_INSN(xlat, "xlat");
  1273. u8 table[256];
  1274. int i;
  1275. for (i = 0; i < 256; i++) {
  1276. table[i] = i + 1;
  1277. }
  1278. init_inregs(&(struct regs){ .eax = 0x89abcdef, .ebx = (u32)table });
  1279. exec_in_big_real_mode(&insn_xlat);
  1280. report("xlat", R_AX, outregs.eax == 0x89abcdf0);
  1281. }
  1282. static void test_salc(void)
  1283. {
  1284. MK_INSN(clc_salc, "clc; .byte 0xd6");
  1285. MK_INSN(stc_salc, "stc; .byte 0xd6");
  1286. init_inregs(&(struct regs){ .eax = 0x12345678 });
  1287. exec_in_big_real_mode(&insn_clc_salc);
  1288. report("salc (1)", R_AX, outregs.eax == 0x12345600);
  1289. exec_in_big_real_mode(&insn_stc_salc);
  1290. report("salc (2)", R_AX, outregs.eax == 0x123456ff);
  1291. }
  1292. static void test_fninit(void)
  1293. {
  1294. u16 fcw = -1, fsw = -1;
  1295. MK_INSN(fninit, "fninit ; fnstsw (%eax) ; fnstcw (%ebx)");
  1296. init_inregs(&(struct regs){ .eax = (u32)&fsw, .ebx = (u32)&fcw });
  1297. exec_in_big_real_mode(&insn_fninit);
  1298. report("fninit", 0, fsw == 0 && (fcw & 0x103f) == 0x003f);
  1299. }
  1300. static void test_nopl(void)
  1301. {
  1302. MK_INSN(nopl1, ".byte 0x90\n\r"); // 1 byte nop
  1303. MK_INSN(nopl2, ".byte 0x66, 0x90\n\r"); // 2 bytes nop
  1304. MK_INSN(nopl3, ".byte 0x0f, 0x1f, 0x00\n\r"); // 3 bytes nop
  1305. MK_INSN(nopl4, ".byte 0x0f, 0x1f, 0x40, 0x00\n\r"); // 4 bytes nop
  1306. exec_in_big_real_mode(&insn_nopl1);
  1307. exec_in_big_real_mode(&insn_nopl2);
  1308. exec_in_big_real_mode(&insn_nopl3);
  1309. exec_in_big_real_mode(&insn_nopl4);
  1310. report("nopl", 0, 1);
  1311. }
  1312. static u64 perf_baseline;
  1313. #define PERF_COUNT_SHIFT (30)
  1314. // 2**27 = ~1 second at 100 mIPS
  1315. #define PERF_COUNT (1 << PERF_COUNT_SHIFT)
  1316. #define MK_INSN_PERF(name, insn) \
  1317. MK_INSN(name, "rdtsc; mov %eax, %ebx; mov %edx, %esi\n" \
  1318. "1:" insn "\n" \
  1319. ".byte 0x67; loop 1b\n" \
  1320. "rdtsc");
  1321. static u64 cycles_in_big_real_mode(struct insn_desc *insn)
  1322. {
  1323. u64 start, end;
  1324. init_inregs(&(struct regs){ .ecx = PERF_COUNT });
  1325. exec_in_big_real_mode(insn);
  1326. start = ((u64)outregs.esi << 32) | outregs.ebx;
  1327. end = ((u64)outregs.edx << 32) | outregs.eax;
  1328. return end - start;
  1329. }
  1330. static void test_perf_loop(void)
  1331. {
  1332. /*
  1333. * This test runs simple instructions that should roughly take the
  1334. * the same time to emulate: PERF_COUNT iterations of "loop" and 3
  1335. * setup instructions. Other performance tests can run PERF_COUNT
  1336. * iterations of the same instruction and subtract the cycle count
  1337. * of this test.
  1338. */
  1339. MK_INSN_PERF(perf_loop, "");
  1340. perf_baseline = cycles_in_big_real_mode(&insn_perf_loop);
  1341. print_serial_u32(perf_baseline * 1000 >> PERF_COUNT_SHIFT);
  1342. print_serial(" millicycles/emulated jump instruction\n");
  1343. }
  1344. static void test_perf_mov(void)
  1345. {
  1346. u64 cyc;
  1347. MK_INSN_PERF(perf_move, "mov %esi, %edi");
  1348. cyc = cycles_in_big_real_mode(&insn_perf_move);
  1349. print_serial_u32(cyc * 1000 >> PERF_COUNT_SHIFT);
  1350. print_serial(" millicycles/emulated move instruction\n");
  1351. }
  1352. static void test_perf_arith(void)
  1353. {
  1354. u64 cyc;
  1355. MK_INSN_PERF(perf_arith, "add $4, %edi");
  1356. cyc = cycles_in_big_real_mode(&insn_perf_arith);
  1357. print_serial_u32(cyc * 1000 >> PERF_COUNT_SHIFT);
  1358. print_serial(" millicycles/emulated arithmetic instruction\n");
  1359. }
  1360. static void test_perf_memory_load(void)
  1361. {
  1362. u64 cyc, tmp;
  1363. MK_INSN_PERF(perf_memory_load, "cmp $0, (%edi)");
  1364. init_inregs(&(struct regs){ .edi = (u32)&tmp });
  1365. cyc = cycles_in_big_real_mode(&insn_perf_memory_load);
  1366. print_serial_u32(cyc * 1000 >> PERF_COUNT_SHIFT);
  1367. print_serial(" millicycles/emulated memory load instruction\n");
  1368. }
  1369. static void test_perf_memory_store(void)
  1370. {
  1371. u64 cyc, tmp;
  1372. MK_INSN_PERF(perf_memory_store, "mov %ax, (%edi)");
  1373. init_inregs(&(struct regs){ .edi = (u32)&tmp });
  1374. cyc = cycles_in_big_real_mode(&insn_perf_memory_store);
  1375. print_serial_u32(cyc * 1000 >> PERF_COUNT_SHIFT);
  1376. print_serial(" millicycles/emulated memory store instruction\n");
  1377. }
  1378. static void test_perf_memory_rmw(void)
  1379. {
  1380. u64 cyc, tmp;
  1381. MK_INSN_PERF(perf_memory_rmw, "add $1, (%edi)");
  1382. init_inregs(&(struct regs){ .edi = (u32)&tmp });
  1383. cyc = cycles_in_big_real_mode(&insn_perf_memory_rmw);
  1384. print_serial_u32(cyc * 1000 >> PERF_COUNT_SHIFT);
  1385. print_serial(" millicycles/emulated memory RMW instruction\n");
  1386. }
  1387. static void test_perf_memory_shl(void)
  1388. {
  1389. u64 cyc, tmp;
  1390. MK_INSN_PERF(perf_memory_shl, "shl $1, %edi");
  1391. init_inregs(&(struct regs){ .edi = (u32)&tmp });
  1392. cyc = cycles_in_big_real_mode(&insn_perf_memory_shl);
  1393. print_serial_u32(cyc * 1000 >> PERF_COUNT_SHIFT);
  1394. print_serial(" millicycles/emulated SHL instruction\n");
  1395. }
  1396. static void test_perf_memory_adc(void)
  1397. {
  1398. u64 cyc, tmp;
  1399. MK_INSN_PERF(perf_memory_adc, "adc $1, %edi");
  1400. init_inregs(&(struct regs){ .edi = (u32)&tmp });
  1401. cyc = cycles_in_big_real_mode(&insn_perf_memory_adc);
  1402. print_serial_u32(cyc * 1000 >> PERF_COUNT_SHIFT);
  1403. print_serial(" millicycles/emulated ADC instruction\n");
  1404. }
  1405. void test_dr_mod(void)
  1406. {
  1407. MK_INSN(drmod, "movl %ebx, %dr0\n\t"
  1408. ".byte 0x0f \n\t .byte 0x21 \n\t .byte 0x0\n\t");
  1409. init_inregs(&(struct regs){ .eax = 0xdead, .ebx = 0xaced });
  1410. exec_in_big_real_mode(&insn_drmod);
  1411. report("mov dr with mod bits", R_AX | R_BX, outregs.eax == 0xaced);
  1412. }
  1413. void test_smsw(void)
  1414. {
  1415. MK_INSN(smsw, "movl %cr0, %ebx\n\t"
  1416. "movl %ebx, %ecx\n\t"
  1417. "or $0x40000000, %ebx\n\t"
  1418. "movl %ebx, %cr0\n\t"
  1419. "smswl %eax\n\t"
  1420. "movl %ecx, %cr0\n\t");
  1421. init_inregs(&(struct regs){ .eax = 0x12345678 });
  1422. exec_in_big_real_mode(&insn_smsw);
  1423. report("smsw", R_AX | R_BX | R_CX, outregs.eax == outregs.ebx);
  1424. }
  1425. void test_xadd(void)
  1426. {
  1427. MK_INSN(xadd, "xaddl %eax, %eax\n\t");
  1428. init_inregs(&(struct regs){ .eax = 0x12345678 });
  1429. exec_in_big_real_mode(&insn_xadd);
  1430. report("xadd", R_AX, outregs.eax == inregs.eax * 2);
  1431. }
  1432. void realmode_start(void)
  1433. {
  1434. test_null();
  1435. test_shld();
  1436. test_push_pop();
  1437. test_pusha_popa();
  1438. test_mov_imm();
  1439. test_cmp_imm();
  1440. test_add_imm();
  1441. test_sub_imm();
  1442. test_xor_imm();
  1443. test_io();
  1444. test_eflags_insn();
  1445. test_jcc_short();
  1446. test_jcc_near();
  1447. /* test_call() uses short jump so call it after testing jcc */
  1448. test_call();
  1449. /* long jmp test uses call near so test it after testing call */
  1450. test_long_jmp();
  1451. test_xchg();
  1452. test_iret();
  1453. test_int();
  1454. test_imul();
  1455. test_mul();
  1456. test_div();
  1457. test_idiv();
  1458. test_loopcc();
  1459. test_cbw();
  1460. test_cwd_cdq();
  1461. test_das();
  1462. test_lds_lss();
  1463. test_jcxz();
  1464. test_cpuid();
  1465. test_ss_base_for_esp_ebp();
  1466. test_sgdt_sidt();
  1467. test_lahf();
  1468. test_sahf();
  1469. test_movzx_movsx();
  1470. test_bswap();
  1471. test_aad();
  1472. test_aam();
  1473. test_xlat();
  1474. test_salc();
  1475. test_fninit();
  1476. test_dr_mod();
  1477. test_smsw();
  1478. test_nopl();
  1479. test_xadd();
  1480. test_perf_loop();
  1481. test_perf_mov();
  1482. test_perf_arith();
  1483. test_perf_memory_shl();
  1484. test_perf_memory_adc();
  1485. test_perf_memory_load();
  1486. test_perf_memory_store();
  1487. test_perf_memory_rmw();
  1488. exit(failed);
  1489. }
  1490. unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff };
  1491. struct table_descr r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt };
  1492. asm(
  1493. ".section .init \n\t"
  1494. ".code32 \n\t"
  1495. "mb_magic = 0x1BADB002 \n\t"
  1496. "mb_flags = 0x0 \n\t"
  1497. "# multiboot header \n\t"
  1498. ".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t"
  1499. ".globl start \n\t"
  1500. ".data \n\t"
  1501. ". = . + 4096 \n\t"
  1502. "stacktop: \n\t"
  1503. ".text \n\t"
  1504. "start: \n\t"
  1505. "lgdt r_gdt_descr \n\t"
  1506. "ljmp $8, $1f; 1: \n\t"
  1507. ".code16gcc \n\t"
  1508. "mov $16, %eax \n\t"
  1509. "mov %ax, %ds \n\t"
  1510. "mov %ax, %es \n\t"
  1511. "mov %ax, %fs \n\t"
  1512. "mov %ax, %gs \n\t"
  1513. "mov %ax, %ss \n\t"
  1514. "mov %cr0, %eax \n\t"
  1515. "btc $0, %eax \n\t"
  1516. "mov %eax, %cr0 \n\t"
  1517. "ljmp $0, $realmode_entry \n\t"
  1518. "realmode_entry: \n\t"
  1519. "xor %ax, %ax \n\t"
  1520. "mov %ax, %ds \n\t"
  1521. "mov %ax, %es \n\t"
  1522. "mov %ax, %ss \n\t"
  1523. "mov %ax, %fs \n\t"
  1524. "mov %ax, %gs \n\t"
  1525. "mov $stacktop, %esp\n\t"
  1526. "ljmp $0, $realmode_start \n\t"
  1527. ".code16gcc \n\t"
  1528. );