1b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*
2b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  x86 CPU test
3b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *
4b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  Copyright (c) 2003 Fabrice Bellard
5b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *
6b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  This program is free software; you can redistribute it and/or modify
7b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  it under the terms of the GNU General Public License as published by
8b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  the Free Software Foundation; either version 2 of the License, or
9b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  (at your option) any later version.
10b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *
11b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  This program is distributed in the hope that it will be useful,
12b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  GNU General Public License for more details.
15b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *
16b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  You should have received a copy of the GNU General Public License
17b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  along with this program; if not, write to the Free Software
18b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
20b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define _GNU_SOURCE
21b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <stdlib.h>
22b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <stdio.h>
23b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <string.h>
24b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <inttypes.h>
25b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <math.h>
26b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <signal.h>
27b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <setjmp.h>
28b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <errno.h>
29b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <sys/ucontext.h>
30b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <sys/mman.h>
31b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <asm/vm86.h>
32b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
33b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Setting this to 1 creates a very comprehensive test of
34b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   integer condition codes. */
35b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define TEST_INTEGER_VERBOSE 1
36b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
37b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
38b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//#define LINUX_VM86_IOPL_FIX
39b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//#define TEST_P4_FLAGS
40b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
41b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define xglue(x, y) x ## y
42b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define glue(x, y) xglue(x, y)
43b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define stringify(s)	tostring(s)
44b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define tostring(s)	#s
45b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
46b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define CC_C   	0x0001
47b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define CC_P 	0x0004
48b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define CC_A	0x0010
49b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define CC_Z	0x0040
50b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define CC_S    0x0080
51b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define CC_O    0x0800
52b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
53b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define __init_call	__attribute__ ((unused,__section__ (".initcall.init")))
54b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
55b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void *call_start __init_call = NULL;
56b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
57b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)
58b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
59b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP add
60b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386.h"
61b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
62b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP sub
63b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386.h"
64b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
65b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP xor
66b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386.h"
67b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
68b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP and
69b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386.h"
70b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
71b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP or
72b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386.h"
73b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
74b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP cmp
75b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386.h"
76b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
77b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP adc
78b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP_CC
79b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386.h"
80b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
81b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP sbb
82b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP_CC
83b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386.h"
84b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
85b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP inc
86b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP_CC
87b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP1
88b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386.h"
89b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
90b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP dec
91b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP_CC
92b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP1
93b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386.h"
94b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
95b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP neg
96b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP_CC
97b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP1
98b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386.h"
99b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
100b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP not
101b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP_CC
102b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP1
103b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386.h"
104b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
105b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#undef CC_MASK
106b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O)
107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP shl
109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386-shift.h"
110b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
111b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP shr
112b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386-shift.h"
113b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
114b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP sar
115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386-shift.h"
116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP rol
118b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386-shift.h"
119b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP ror
121b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386-shift.h"
122b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
123b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP rcr
124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP_CC
125b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386-shift.h"
126b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
127b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP rcl
128b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP_CC
129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386-shift.h"
130b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
131b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP shld
132b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP_SHIFTD
133b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP_NOBYTE
134b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386-shift.h"
135b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
136b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP shrd
137b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP_SHIFTD
138b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP_NOBYTE
139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386-shift.h"
140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
142b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* XXX: should be more precise ? */
143b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#undef CC_MASK
144b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define CC_MASK (CC_C)
145b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
146b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP bt
147b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP_NOBYTE
148b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386-shift.h"
149b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
150b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP bts
151b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP_NOBYTE
152b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386-shift.h"
153b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
154b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP btr
155b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP_NOBYTE
156b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386-shift.h"
157b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
158b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP btc
159b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP_NOBYTE
160b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386-shift.h"
161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
162b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
163b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* lea test (modrm support) */
164b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define TEST_LEA(STR)\
165b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{\
166b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm("leal " STR ", %0"\
167b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        : "=r" (res)\
168b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
169b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("lea %s = %08x\n", STR, res);\
170b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
171b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
172b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define TEST_LEA16(STR)\
173b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{\
174b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm(".code16 ; .byte 0x67 ; leal " STR ", %0 ; .code32"\
175b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        : "=wq" (res)\
176b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
177b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("lea %s = %08x\n", STR, res);\
178b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
179b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
180b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid test_lea(void)
182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
183b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int eax, ebx, ecx, edx, esi, edi, res;
184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    eax = 0x0001;
185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ebx = 0x0002;
186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ecx = 0x0004;
187b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    edx = 0x0008;
188b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    esi = 0x0010;
189b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    edi = 0x0020;
190b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
191b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("0x4000");
192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
193b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("(%%eax)");
194b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("(%%ebx)");
195b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("(%%ecx)");
196b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("(%%edx)");
197b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("(%%esi)");
198b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("(%%edi)");
199b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
200b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("0x40(%%eax)");
201b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("0x40(%%ebx)");
202b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("0x40(%%ecx)");
203b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("0x40(%%edx)");
204b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("0x40(%%esi)");
205b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("0x40(%%edi)");
206b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
207b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("0x4000(%%eax)");
208b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("0x4000(%%ebx)");
209b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("0x4000(%%ecx)");
210b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("0x4000(%%edx)");
211b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("0x4000(%%esi)");
212b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("0x4000(%%edi)");
213b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
214b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("(%%eax, %%ecx)");
215b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("(%%ebx, %%edx)");
216b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("(%%ecx, %%ecx)");
217b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("(%%edx, %%ecx)");
218b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("(%%esi, %%ecx)");
219b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("(%%edi, %%ecx)");
220b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
221b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("0x40(%%eax, %%ecx)");
222b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("0x4000(%%ebx, %%edx)");
223b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
224b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("(%%ecx, %%ecx, 2)");
225b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("(%%edx, %%ecx, 4)");
226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("(%%esi, %%ecx, 8)");
227b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
228b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("(,%%eax, 2)");
229b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("(,%%ebx, 4)");
230b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("(,%%ecx, 8)");
231b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
232b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("0x40(,%%eax, 2)");
233b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("0x40(,%%ebx, 4)");
234b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("0x40(,%%ecx, 8)");
235b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
236b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
237b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("-10(%%ecx, %%ecx, 2)");
238b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("-10(%%edx, %%ecx, 4)");
239b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("-10(%%esi, %%ecx, 8)");
240b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
241b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("0x4000(%%ecx, %%ecx, 2)");
242b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("0x4000(%%edx, %%ecx, 4)");
243b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LEA("0x4000(%%esi, %%ecx, 8)");
244b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
245b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
246b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define TEST_JCC(JCC, v1, v2)\
247b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{\
248b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int res;\
249b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm("movl $1, %0\n\t"\
250b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        "cmpl %2, %1\n\t"\
251b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        "j" JCC " 1f\n\t"\
252b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        "movl $0, %0\n\t"\
253b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        "1:\n\t"\
254b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        : "=r" (res)\
255b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        : "r" (v1), "r" (v2));\
256b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("%-10s %d\n", "j" JCC, res);\
257b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov\
258b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm("movl $0, %0\n\t"\
259b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        "cmpl %2, %1\n\t"\
260b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        "set" JCC " %b0\n\t"\
261b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        : "=r" (res)\
262b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        : "r" (v1), "r" (v2));\
263b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("%-10s %d\n", "set" JCC, res);\
264b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov {  int one = 1; \
265b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm("movl $0x12345678, %0\n\t"\
266b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        "cmpl %2, %1\n\t"\
267b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        "cmov" JCC "l %3, %0\n\t"\
268b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        : "=r" (res)\
269b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        : "r" (v1), "r" (v2), "m" (one));\
270b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        printf("%-10s R=0x%08x\n", "cmov" JCC "l", res);\
271b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm("movl $0x12345678, %0\n\t"\
272b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        "cmpl %2, %1\n\t"\
273b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        "cmov" JCC "w %w3, %w0\n\t"\
274b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        : "=r" (res)\
275b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        : "r" (v1), "r" (v2), "r" (1));\
276b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        printf("%-10s R=0x%08x\n", "cmov" JCC "w", res);\
277b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } \
278b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
279b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
280b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* various jump tests */
281b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid test_jcc(void)
282b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
283b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("ne", 1, 1);
284b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("ne", 1, 0);
285b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
286b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("e", 1, 1);
287b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("e", 1, 0);
288b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
289b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("l", 1, 1);
290b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("l", 1, 0);
291b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("l", 1, -1);
292b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
293b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("le", 1, 1);
294b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("le", 1, 0);
295b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("le", 1, -1);
296b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
297b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("ge", 1, 1);
298b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("ge", 1, 0);
299b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("ge", -1, 1);
300b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
301b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("g", 1, 1);
302b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("g", 1, 0);
303b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("g", 1, -1);
304b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
305b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("b", 1, 1);
306b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("b", 1, 0);
307b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("b", 1, -1);
308b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
309b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("be", 1, 1);
310b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("be", 1, 0);
311b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("be", 1, -1);
312b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
313b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("ae", 1, 1);
314b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("ae", 1, 0);
315b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("ae", 1, -1);
316b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
317b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("a", 1, 1);
318b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("a", 1, 0);
319b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("a", 1, -1);
320b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
321b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
322b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("p", 1, 1);
323b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("p", 1, 0);
324b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
325b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("np", 1, 1);
326b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("np", 1, 0);
327b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
328b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("o", 0x7fffffff, 0);
329b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("o", 0x7fffffff, -1);
330b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
331b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("no", 0x7fffffff, 0);
332b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("no", 0x7fffffff, -1);
333b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
334b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("s", 0, 1);
335b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("s", 0, -1);
336b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("s", 0, 0);
337b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
338b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("ns", 0, 1);
339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("ns", 0, -1);
340b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_JCC("ns", 0, 0);
341b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
342b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
343b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#undef CC_MASK
344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#ifdef TEST_P4_FLAGS
345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)
346b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#else
347b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define CC_MASK (CC_O | CC_C)
348b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
349b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
350b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP mul
351b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386-muldiv.h"
352b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
353b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP imul
354b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386-muldiv.h"
355b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
356b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid test_imulw2(int op0, int op1)
357b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
358b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int res, s1, s0, flags;
359b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    s0 = op0;
360b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    s1 = op1;
361b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    res = s0;
362b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    flags = 0;
363b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm ("push %4\n\t"
364b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         "popf\n\t"
365b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         "imulw %w2, %w0\n\t"
366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         "pushf\n\t"
367b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         "popl %1\n\t"
368b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         : "=q" (res), "=g" (flags)
369b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         : "q" (s1), "0" (res), "1" (flags));
370b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n",
371b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           "imulw", s0, s1, res, flags & CC_MASK);
372b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
373b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
374b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid test_imull2(int op0, int op1)
375b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
376b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int res, s1, s0, flags;
377b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    s0 = op0;
378b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    s1 = op1;
379b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    res = s0;
380b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    flags = 0;
381b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm ("push %4\n\t"
382b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         "popf\n\t"
383b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         "imull %2, %0\n\t"
384b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         "pushf\n\t"
385b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         "popl %1\n\t"
386b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         : "=q" (res), "=g" (flags)
387b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         : "q" (s1), "0" (res), "1" (flags));
388b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n",
389b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           "imull", s0, s1, res, flags & CC_MASK);
390b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
391b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
392b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define TEST_IMUL_IM(size, size1, op0, op1)\
393b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{\
394b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int res, flags;\
395b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    flags = 0;\
396b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    res = 0;\
397b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm ("push %3\n\t"\
398b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         "popf\n\t"\
399b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         "imul" size " $" #op0 ", %" size1 "2, %" size1 "0\n\t" \
400b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         "pushf\n\t"\
401b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         "popl %1\n\t"\
402b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         : "=r" (res), "=g" (flags)\
403b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         : "r" (op1), "1" (flags), "0" (res));\
404b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n",\
405b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           "imul" size, op0, op1, res, flags & CC_MASK);\
406b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
407b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
408b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
409b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#undef CC_MASK
410b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define CC_MASK (0)
411b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
412b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP div
413b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386-muldiv.h"
414b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
415b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define OP idiv
416b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "test-i386-muldiv.h"
417b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
418b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid test_mul(void)
419b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
420b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_imulb(0x1234561d, 4);
421b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_imulb(3, -4);
422b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_imulb(0x80, 0x80);
423b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_imulb(0x10, 0x10);
424b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
425b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_imulw(0, 0, 0);
426b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_imulw(0, 0xFF, 0xFF);
427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_imulw(0, 0xFF, 0x100);
428b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_imulw(0, 0x1234001d, 45);
429b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_imulw(0, 23, -45);
430b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_imulw(0, 0x8000, 0x8000);
431b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_imulw(0, 0x100, 0x100);
432b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
433b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_imull(0, 0, 0);
434b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_imull(0, 0xFFFF, 0xFFFF);
435b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_imull(0, 0xFFFF, 0x10000);
436b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_imull(0, 0x1234001d, 45);
437b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_imull(0, 23, -45);
438b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_imull(0, 0x80000000, 0x80000000);
439b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_imull(0, 0x10000, 0x10000);
440b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
441b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_mulb(0x1234561d, 4);
442b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_mulb(3, -4);
443b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_mulb(0x80, 0x80);
444b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_mulb(0x10, 0x10);
445b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
446b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_mulw(0, 0x1234001d, 45);
447b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_mulw(0, 23, -45);
448b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_mulw(0, 0x8000, 0x8000);
449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_mulw(0, 0x100, 0x100);
450b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
451b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_mull(0, 0x1234001d, 45);
452b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_mull(0, 23, -45);
453b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_mull(0, 0x80000000, 0x80000000);
454b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_mull(0, 0x10000, 0x10000);
455b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
456b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_imulw2(0x1234001d, 45);
457b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_imulw2(23, -45);
458b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_imulw2(0x8000, 0x8000);
459b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_imulw2(0x100, 0x100);
460b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
461b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_imull2(0x1234001d, 45);
462b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_imull2(23, -45);
463b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_imull2(0x80000000, 0x80000000);
464b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_imull2(0x10000, 0x10000);
465b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
466b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_IMUL_IM("w", "w", 45, 0x1234);
467b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_IMUL_IM("w", "w", -45, 23);
468b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_IMUL_IM("w", "w", 0x8000, 0x80000000);
469b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_IMUL_IM("w", "w", 0x7fff, 0x1000);
470b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
471b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_IMUL_IM("l", "", 45, 0x1234);
472b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_IMUL_IM("l", "", -45, 23);
473b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_IMUL_IM("l", "", 0x8000, 0x80000000);
474b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_IMUL_IM("l", "", 0x7fff, 0x1000);
475b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
476b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_idivb(0x12341678, 0x127e);
477b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_idivb(0x43210123, -5);
478b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_idivb(0x12340004, -1);
479b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
480b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_idivw(0, 0x12345678, 12347);
481b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_idivw(0, -23223, -45);
482b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_idivw(0, 0x12348000, -1);
483b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_idivw(0x12343, 0x12345678, 0x81238567);
484b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
485b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_idivl(0, 0x12345678, 12347);
486b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_idivl(0, -233223, -45);
487b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_idivl(0, 0x80000000, -1);
488b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_idivl(0x12343, 0x12345678, 0x81234567);
489b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
490b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_divb(0x12341678, 0x127e);
491b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_divb(0x43210123, -5);
492b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_divb(0x12340004, -1);
493b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
494b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_divw(0, 0x12345678, 12347);
495b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_divw(0, -23223, -45);
496b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_divw(0, 0x12348000, -1);
497b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_divw(0x12343, 0x12345678, 0x81238567);
498b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
499b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_divl(0, 0x12345678, 12347);
500b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_divl(0, -233223, -45);
501b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_divl(0, 0x80000000, -1);
502b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_divl(0x12343, 0x12345678, 0x81234567);
503b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
504b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
505b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define TEST_BSX(op, size, op0)\
506b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{\
507b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int res, val, resz;\
508b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    val = op0;\
509b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm("xorl %1, %1\n\t"\
510b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        "movl $0x12345678, %0\n\t"\
511b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        #op " %" size "2, %" size "0\n\t" \
512b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        "setz %b1" \
513b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        : "=r" (res), "=q" (resz)\
514b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        : "r" (val));\
515b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("%-10s A=%08x R=%08x %d\n", #op, val, res, resz);\
516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
517b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
518b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid test_bsx(void)
519b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
520b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BSX(bsrw, "w", 0);
521b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BSX(bsrw, "w", 0x12340128);
522b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BSX(bsrl, "", 0);
523b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BSX(bsrl, "", 0x00340128);
524b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BSX(bsfw, "w", 0);
525b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BSX(bsfw, "w", 0x12340128);
526b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BSX(bsfl, "", 0);
527b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BSX(bsfl, "", 0x00340128);
528b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
529b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
530b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/**********************************************/
531b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
532b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid test_fops(double a, double b)
533b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
534b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("a=%f b=%f a+b=%f\n", a, b, a + b);
535b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("a=%f b=%f a-b=%f\n", a, b, a - b);
536b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("a=%f b=%f a*b=%f\n", a, b, a * b);
537b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("a=%f b=%f a/b=%f\n", a, b, a / b);
538b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("a=%f b=%f fmod(a, b)=%f\n", a, b, fmod(a, b));
539b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("a=%f sqrt(a)=%f\n", a, sqrt(a));
540b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("a=%f sin(a)=%f\n", a, sin(a));
541b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("a=%f cos(a)=%f\n", a, cos(a));
542b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("a=%f tan(a)=%f\n", a, tan(a));
543b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("a=%f log(a)=%f\n", a, log(a));
544b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("a=%f exp(a)=%f\n", a, exp(a));
545b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("a=%f b=%f atan2(a, b)=%f\n", a, b, atan2(a, b));
546b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* just to test some op combining */
547b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("a=%f asin(sin(a))=%f\n", a, asin(sin(a)));
548b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("a=%f acos(cos(a))=%f\n", a, acos(cos(a)));
549b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("a=%f atan(tan(a))=%f\n", a, atan(tan(a)));
550b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
551b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
552b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid test_fcmp(double a, double b)
553b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
554b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("(%f<%f)=%d\n",
555b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           a, b, a < b);
556b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("(%f<=%f)=%d\n",
557b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           a, b, a <= b);
558b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("(%f==%f)=%d\n",
559b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           a, b, a == b);
560b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("(%f>%f)=%d\n",
561b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           a, b, a > b);
562b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("(%f<=%f)=%d\n",
563b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           a, b, a >= b);
564b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    {
565b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        unsigned int eflags;
566b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        /* test f(u)comi instruction */
567b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm("fcomi %2, %1\n"
568b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            "pushf\n"
569b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            "pop %0\n"
570b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            : "=r" (eflags)
571b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            : "t" (a), "u" (b));
572b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        printf("fcomi(%f %f)=%08x\n", a, b, eflags & (CC_Z | CC_P | CC_C));
573b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
574b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
575b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
576b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid test_fcvt(double a)
577b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
578b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    float fa;
579b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    long double la;
580b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int16_t fpuc;
581b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int i;
582b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int64_t lla;
583b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int ia;
584b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int16_t wa;
585b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    double ra;
586b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
587b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    fa = a;
588b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    la = a;
589b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("(float)%f = %f\n", a, fa);
590b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("(long double)%f = %Lf\n", a, la);
591b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("a=%016Lx\n", *(long long *)&a);
592b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("la=%016Lx %04x\n", *(long long *)&la,
593b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           *(unsigned short *)((char *)(&la) + 8));
594b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
595b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* test all roundings */
596b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm volatile ("fstcw %0" : "=m" (fpuc));
597b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    for(i=0;i<4;i++) {
598b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        int16_t tmp = (fpuc & ~0x0c00) | (i << 10);
599b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("fldcw %0" : : "m" (tmp));
600b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("fist %0" : "=m" (wa) : "t" (a));
601b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("fistl %0" : "=m" (ia) : "t" (a));
602b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("fistpll %0" : "=m" (lla) : "t" (a) : "st");
603b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("frndint ; fstl %0" : "=m" (ra) : "t" (a));
604b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("fldcw %0" : : "m" (fpuc));
605b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        printf("(short)a = %d\n", wa);
606b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        printf("(int)a = %d\n", ia);
607b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        printf("(int64_t)a = %Ld\n", lla);
608b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        printf("rint(a) = %f\n", ra);
609b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
610b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
611b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
612b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define TEST(N) \
613b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm("fld" #N : "=t" (a)); \
614b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("fld" #N "= %f\n", a);
615b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
616b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid test_fconst(void)
617b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    double a;
619b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST(1);
620b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST(l2t);
621b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST(l2e);
622b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST(pi);
623b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST(lg2);
624b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST(ln2);
625b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST(z);
626b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
627b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
628b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid test_fbcd(double a)
629b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
630b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    unsigned short bcd[5];
631b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    double b;
632b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
633b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm("fbstp %0" : "=m" (bcd[0]) : "t" (a) : "st");
634b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm("fbld %1" : "=t" (b) : "m" (bcd[0]));
635b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("a=%f bcd=%04x%04x%04x%04x%04x b=%f\n",
636b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           a, bcd[4], bcd[3], bcd[2], bcd[1], bcd[0], b);
637b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
638b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
639b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define TEST_ENV(env, save, restore)\
640b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{\
641b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    memset((env), 0xaa, sizeof(*(env)));\
642b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    for(i=0;i<5;i++)\
643b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("fldl %0" : : "m" (dtab[i]));\
644b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm(save " %0\n" : : "m" (*(env)));\
645b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm(restore " %0\n": : "m" (*(env)));\
646b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    for(i=0;i<5;i++)\
647b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("fstpl %0" : "=m" (rtab[i]));\
648b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    for(i=0;i<5;i++)\
649b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        printf("res[%d]=%f\n", i, rtab[i]);\
650b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("fpuc=%04x fpus=%04x fptag=%04x\n",\
651b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           (env)->fpuc,\
652b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           (env)->fpus & 0xff00,\
653b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           (env)->fptag);\
654b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
655b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
656b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid test_fenv(void)
657b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
658b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    struct __attribute__((packed)) {
659b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        uint16_t fpuc;
660b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        uint16_t dummy1;
661b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        uint16_t fpus;
662b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        uint16_t dummy2;
663b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        uint16_t fptag;
664b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        uint16_t dummy3;
665b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        uint32_t ignored[4];
666b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        long double fpregs[8];
667b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    } float_env32;
668b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    struct __attribute__((packed)) {
669b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        uint16_t fpuc;
670b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        uint16_t fpus;
671b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        uint16_t fptag;
672b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        uint16_t ignored[4];
673b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        long double fpregs[8];
674b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    } float_env16;
675b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    double dtab[8];
676b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    double rtab[8];
677b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int i;
678b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
679b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    for(i=0;i<8;i++)
680b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        dtab[i] = i + 1;
681b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
682b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_ENV(&float_env16, "data16 fnstenv", "data16 fldenv");
683b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_ENV(&float_env16, "data16 fnsave", "data16 frstor");
684b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_ENV(&float_env32, "fnstenv", "fldenv");
685b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_ENV(&float_env32, "fnsave", "frstor");
686b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
687b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* test for ffree */
688b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    for(i=0;i<5;i++)
689b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("fldl %0" : : "m" (dtab[i]));
690b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm volatile("ffree %st(2)");
691b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm volatile ("fnstenv %0\n" : : "m" (float_env32));
692b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm volatile ("fninit");
693b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("fptag=%04x\n", float_env32.fptag);
694b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
695b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
696b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
697b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define TEST_FCMOV(a, b, eflags, CC)\
698b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{\
699b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    double res;\
700b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm("push %3\n"\
701b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        "popf\n"\
702b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        "fcmov" CC " %2, %0\n"\
703b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        : "=t" (res)\
704b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        : "0" (a), "u" (b), "g" (eflags));\
705b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("fcmov%s eflags=0x%04x-> %f\n", \
706b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           CC, eflags, res);\
707b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
708b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
709b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid test_fcmov(void)
710b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
711b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    double a, b;
712b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int eflags, i;
713b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
714b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    a = 1.0;
715b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    b = 2.0;
716b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    for(i = 0; i < 4; i++) {
717b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        eflags = 0;
718b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        if (i & 1)
719b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            eflags |= CC_C;
720b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        if (i & 2)
721b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            eflags |= CC_Z;
722b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        TEST_FCMOV(a, b, eflags, "b");
723b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        TEST_FCMOV(a, b, eflags, "e");
724b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        TEST_FCMOV(a, b, eflags, "be");
725b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        TEST_FCMOV(a, b, eflags, "nb");
726b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        TEST_FCMOV(a, b, eflags, "ne");
727b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        TEST_FCMOV(a, b, eflags, "nbe");
728b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
729b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_FCMOV(a, b, 0, "u");
730b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_FCMOV(a, b, CC_P, "u");
731b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_FCMOV(a, b, 0, "nu");
732b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_FCMOV(a, b, CC_P, "nu");
733b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
734b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
735b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid test_floats(void)
736b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
737b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_fops(2, 3);
738b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_fops(1.4, -5);
739b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_fcmp(2, -1);
740b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_fcmp(2, 2);
741b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_fcmp(2, 3);
742b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_fcvt(0.5);
743b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_fcvt(-0.5);
744b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_fcvt(1.0/7.0);
745b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_fcvt(-1.0/9.0);
746b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_fcvt(32768);
747b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_fcvt(-1e20);
748b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_fconst();
749b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    // REINSTATE (maybe): test_fbcd(1234567890123456);
750b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    // REINSTATE (maybe): test_fbcd(-123451234567890);
751b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    // REINSTATE: test_fenv();
752b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    // REINSTATE: test_fcmov();
753b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
754b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
755b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/**********************************************/
756b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if 0
757b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
758b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define TEST_BCD(op, op0, cc_in, cc_mask)\
759b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{\
760b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int res, flags;\
761b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    res = op0;\
762b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    flags = cc_in;\
763b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm ("push %3\n\t"\
764b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         "popf\n\t"\
765b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         #op "\n\t"\
766b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         "pushf\n\t"\
767b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         "popl %1\n\t"\
768b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        : "=a" (res), "=g" (flags)\
769b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        : "0" (res), "1" (flags));\
770b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n",\
771b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           #op, op0, res, cc_in, flags & cc_mask);\
772b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
773b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
774b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid test_bcd(void)
775b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
776b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(daa, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
777b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(daa, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
778b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(daa, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
779b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(daa, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
780b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(daa, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
781b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(daa, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
782b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(daa, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
783b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(daa, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
784b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(daa, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
785b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(daa, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
786b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(daa, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
787b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(daa, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
788b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(daa, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
789b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
790b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(das, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
791b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(das, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
792b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(das, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
793b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(das, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
794b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(das, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
795b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(das, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
796b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(das, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
797b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(das, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
798b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(das, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
799b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(das, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
800b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(das, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
801b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(das, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
802b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(das, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
803b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
804b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(aaa, 0x12340205, CC_A, (CC_C | CC_A));
805b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(aaa, 0x12340306, CC_A, (CC_C | CC_A));
806b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(aaa, 0x1234040a, CC_A, (CC_C | CC_A));
807b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(aaa, 0x123405fa, CC_A, (CC_C | CC_A));
808b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(aaa, 0x12340205, 0, (CC_C | CC_A));
809b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(aaa, 0x12340306, 0, (CC_C | CC_A));
810b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(aaa, 0x1234040a, 0, (CC_C | CC_A));
811b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(aaa, 0x123405fa, 0, (CC_C | CC_A));
812b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
813b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(aas, 0x12340205, CC_A, (CC_C | CC_A));
814b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(aas, 0x12340306, CC_A, (CC_C | CC_A));
815b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(aas, 0x1234040a, CC_A, (CC_C | CC_A));
816b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(aas, 0x123405fa, CC_A, (CC_C | CC_A));
817b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(aas, 0x12340205, 0, (CC_C | CC_A));
818b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(aas, 0x12340306, 0, (CC_C | CC_A));
819b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(aas, 0x1234040a, 0, (CC_C | CC_A));
820b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(aas, 0x123405fa, 0, (CC_C | CC_A));
821b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
822b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(aam, 0x12340547, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
823b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_BCD(aad, 0x12340407, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
824b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
825b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif /* 0 */
826b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
827b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define TEST_XCHG(op, size, opconst)\
828b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{\
829b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int op0, op1;\
830b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    op0 = 0x12345678;\
831b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    op1 = 0xfbca7654;\
832b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm(#op " %" size "0, %" size "1" \
833b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        : "=q" (op0), opconst (op1) \
834b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        : "0" (op0), "1" (op1));\
835b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("%-10s A=%08x B=%08x\n",\
836b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           #op, op0, op1);\
837b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
838b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
839b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define TEST_CMPXCHG(op, size, opconst, eax)\
840b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{\
841b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int op0, op1;\
842b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    op0 = 0x12345678;\
843b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    op1 = 0xfbca7654;\
844b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm(#op " %" size "0, %" size "1" \
845b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        : "=q" (op0), opconst (op1) \
846b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        : "0" (op0), "1" (op1), "a" (eax));\
847b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("%-10s EAX=%08x A=%08x C=%08x\n",\
848b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           #op, eax, op0, op1);\
849b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
850b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
851b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid test_xchg(void)
852b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
853b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_XCHG(xchgl, "", "=q");
854b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_XCHG(xchgw, "w", "=q");
855b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_XCHG(xchgb, "b", "=q");
856b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
857b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_XCHG(xchgl, "", "=m");
858b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_XCHG(xchgw, "w", "=m");
859b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_XCHG(xchgb, "b", "=m");
860b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
861b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if 0
862b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_XCHG(xaddl, "", "=q");
863b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_XCHG(xaddw, "w", "=q");
864b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_XCHG(xaddb, "b", "=q");
865b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
866b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    {
867b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        int res;
868b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        res = 0x12345678;
869b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm("xaddl %1, %0" : "=r" (res) : "0" (res));
870b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        printf("xaddl same res=%08x\n", res);
871b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
872b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
873b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_XCHG(xaddl, "", "=m");
874b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_XCHG(xaddw, "w", "=m");
875b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_XCHG(xaddb, "b", "=m");
876b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
877b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_CMPXCHG(cmpxchgl, "", "=q", 0xfbca7654);
878b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_CMPXCHG(cmpxchgw, "w", "=q", 0xfbca7654);
879b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_CMPXCHG(cmpxchgb, "b", "=q", 0xfbca7654);
880b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
881b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_CMPXCHG(cmpxchgl, "", "=q", 0xfffefdfc);
882b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_CMPXCHG(cmpxchgw, "w", "=q", 0xfffefdfc);
883b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_CMPXCHG(cmpxchgb, "b", "=q", 0xfffefdfc);
884b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
885b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_CMPXCHG(cmpxchgl, "", "=m", 0xfbca7654);
886b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_CMPXCHG(cmpxchgw, "w", "=m", 0xfbca7654);
887b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_CMPXCHG(cmpxchgb, "b", "=m", 0xfbca7654);
888b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
889b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_CMPXCHG(cmpxchgl, "", "=m", 0xfffefdfc);
890b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_CMPXCHG(cmpxchgw, "w", "=m", 0xfffefdfc);
891b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_CMPXCHG(cmpxchgb, "b", "=m", 0xfffefdfc);
892b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if 0
893b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    {
894b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        uint64_t op0, op1, op2;
895b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        int i, eflags;
896b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
897b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        for(i = 0; i < 2; i++) {
898b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            op0 = 0x123456789abcd;
899b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (i == 0)
900b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                op1 = 0xfbca765423456;
901b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            else
902b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                op1 = op0;
903b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            op2 = 0x6532432432434;
904b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            asm("cmpxchg8b %1\n"
905b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                "pushf\n"
906b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                "popl %2\n"
907b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                : "=A" (op0), "=m" (op1), "=g" (eflags)
908b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                : "0" (op0), "m" (op1), "b" ((int)op2), "c" ((int)(op2 >> 32)));
909b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            printf("cmpxchg8b: op0=%016llx op1=%016llx CC=%02x\n",
910b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    op0, op1, eflags & CC_Z);
911b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        }
912b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
913b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
914b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
915b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
916b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/**********************************************/
917b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* segmentation tests */
918b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if 0
919b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <asm/ldt.h>
920b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <linux/unistd.h>
921b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <linux/version.h>
922b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
923b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov_syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount)
924b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
925b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 66)
926b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define modify_ldt_ldt_s user_desc
927b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
928b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
929b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovuint8_t seg_data1[4096];
930b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovuint8_t seg_data2[4096];
931b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
932b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define MK_SEL(n) (((n) << 3) | 7)
933b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
934b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define TEST_LR(op, size, seg, mask)\
935b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{\
936b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int res, res2;\
937b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    res = 0x12345678;\
938b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm (op " %" size "2, %" size "0\n" \
939b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         "movl $0, %1\n"\
940b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         "jnz 1f\n"\
941b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         "movl $1, %1\n"\
942b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         "1:\n"\
943b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         : "=r" (res), "=r" (res2) : "m" (seg), "0" (res));\
944b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf(op ": Z=%d %08x\n", res2, res & ~(mask));\
945b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
946b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
947b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* NOTE: we use Linux modify_ldt syscall */
948b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid test_segs(void)
949b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
950b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    struct modify_ldt_ldt_s ldt;
951b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    long long ldt_table[3];
952b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int res, res2;
953b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    char tmp;
954b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    struct {
955b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        uint32_t offset;
956b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        uint16_t seg;
957b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    } __attribute__((packed)) segoff;
958b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
959b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.entry_number = 1;
960b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.base_addr = (unsigned long)&seg_data1;
961b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12;
962b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.seg_32bit = 1;
963b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.contents = MODIFY_LDT_CONTENTS_DATA;
964b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.read_exec_only = 0;
965b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.limit_in_pages = 1;
966b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.seg_not_present = 0;
967b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.useable = 1;
968b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
969b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
970b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.entry_number = 2;
971b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.base_addr = (unsigned long)&seg_data2;
972b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.limit = (sizeof(seg_data2) + 0xfff) >> 12;
973b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.seg_32bit = 1;
974b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.contents = MODIFY_LDT_CONTENTS_DATA;
975b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.read_exec_only = 0;
976b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.limit_in_pages = 1;
977b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.seg_not_present = 0;
978b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.useable = 1;
979b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
980b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
981b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    modify_ldt(0, &ldt_table, sizeof(ldt_table)); /* read ldt entries */
982b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if 0
983b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    {
984b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        int i;
985b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        for(i=0;i<3;i++)
986b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            printf("%d: %016Lx\n", i, ldt_table[i]);
987b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
988b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
989b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* do some tests with fs or gs */
990b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1)));
991b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
992b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    seg_data1[1] = 0xaa;
993b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    seg_data2[1] = 0x55;
994b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
995b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm volatile ("fs movzbl 0x1, %0" : "=r" (res));
996b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("FS[1] = %02x\n", res);
997b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
998b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm volatile ("pushl %%gs\n"
999b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "movl %1, %%gs\n"
1000b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "gs movzbl 0x1, %0\n"
1001b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "popl %%gs\n"
1002b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  : "=r" (res)
1003b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  : "r" (MK_SEL(2)));
1004b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("GS[1] = %02x\n", res);
1005b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1006b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* tests with ds/ss (implicit segment case) */
1007b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    tmp = 0xa5;
1008b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm volatile ("pushl %%ebp\n\t"
1009b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "pushl %%ds\n\t"
1010b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "movl %2, %%ds\n\t"
1011b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "movl %3, %%ebp\n\t"
1012b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "movzbl 0x1, %0\n\t"
1013b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "movzbl (%%ebp), %1\n\t"
1014b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "popl %%ds\n\t"
1015b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "popl %%ebp\n\t"
1016b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  : "=r" (res), "=r" (res2)
1017b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  : "r" (MK_SEL(1)), "r" (&tmp));
1018b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("DS[1] = %02x\n", res);
1019b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("SS[tmp] = %02x\n", res2);
1020b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1021b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    segoff.seg = MK_SEL(2);
1022b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    segoff.offset = 0xabcdef12;
1023b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm volatile("lfs %2, %0\n\t"
1024b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 "movl %%fs, %1\n\t"
1025b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 : "=r" (res), "=g" (res2)
1026b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 : "m" (segoff));
1027b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("FS:reg = %04x:%08x\n", res2, res);
1028b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1029b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LR("larw", "w", MK_SEL(2), 0x0100);
1030b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LR("larl", "", MK_SEL(2), 0x0100);
1031b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LR("lslw", "w", MK_SEL(2), 0);
1032b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LR("lsll", "", MK_SEL(2), 0);
1033b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1034b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LR("larw", "w", 0xfff8, 0);
1035b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LR("larl", "", 0xfff8, 0);
1036b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LR("lslw", "w", 0xfff8, 0);
1037b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_LR("lsll", "", 0xfff8, 0);
1038b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1039b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
1040b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1041b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if 0
1042b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* 16 bit code test */
1043b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovextern char code16_start, code16_end;
1044b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovextern char code16_func1;
1045b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovextern char code16_func2;
1046b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovextern char code16_func3;
1047b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1048b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid test_code16(void)
1049b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1050b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    struct modify_ldt_ldt_s ldt;
1051b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int res, res2;
1052b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1053b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* build a code segment */
1054b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.entry_number = 1;
1055b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.base_addr = (unsigned long)&code16_start;
1056b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.limit = &code16_end - &code16_start;
1057b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.seg_32bit = 0;
1058b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.contents = MODIFY_LDT_CONTENTS_CODE;
1059b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.read_exec_only = 0;
1060b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.limit_in_pages = 0;
1061b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.seg_not_present = 0;
1062b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.useable = 1;
1063b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
1064b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1065b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* call the first function */
1066b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm volatile ("lcall %1, %2"
1067b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  : "=a" (res)
1068b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  : "i" (MK_SEL(1)), "i" (&code16_func1): "memory", "cc");
1069b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("func1() = 0x%08x\n", res);
1070b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm volatile ("lcall %2, %3"
1071b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  : "=a" (res), "=c" (res2)
1072b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  : "i" (MK_SEL(1)), "i" (&code16_func2): "memory", "cc");
1073b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("func2() = 0x%08x spdec=%d\n", res, res2);
1074b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm volatile ("lcall %1, %2"
1075b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  : "=a" (res)
1076b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  : "i" (MK_SEL(1)), "i" (&code16_func3): "memory", "cc");
1077b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("func3() = 0x%08x\n", res);
1078b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1079b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
1080b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1081b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovextern char func_lret32;
1082b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovextern char func_iret32;
1083b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1084b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid test_misc(void)
1085b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1086b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    char table[256];
1087b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int res, i;
1088b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1089b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if 0
1090b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    // REINSTATE
1091b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    for(i=0;i<256;i++) table[i] = 256 - i;
1092b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    res = 0x12345678;
1093b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm ("xlat" : "=a" (res) : "b" (table), "0" (res));
1094b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("xlat: EAX=%08x\n", res);
1095b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
1096b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if 0
1097b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    // REINSTATE
1098b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm volatile ("pushl %%cs ; call %1"
1099b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  : "=a" (res)
1100b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  : "m" (func_lret32): "memory", "cc");
1101b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("func_lret32=%x\n", res);
1102b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1103b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm volatile ("pushfl ; pushl %%cs ; call %1"
1104b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  : "=a" (res)
1105b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  : "m" (func_iret32): "memory", "cc");
1106b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("func_iret32=%x\n", res);
1107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
1108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* specific popl test */
1109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popl (%%esp) ; popl %0"
1110b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  : "=g" (res));
1111b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("popl esp=%x\n", res);
1112b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if 0
1113b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    // REINSTATE
1114b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* specific popw test */
1115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popw (%%esp) ; addl $2, %%esp ; popl %0"
1116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  : "=g" (res));
1117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("popw esp=%x\n", res);
1118b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
1119b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1121b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovuint8_t str_buffer[4096];
1122b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1123b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define TEST_STRING1(OP, size, DF, REP)\
1124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{\
1125b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int esi, edi, eax, ecx, eflags;\
1126b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov\
1127b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    esi = (long)(str_buffer + sizeof(str_buffer) / 2);\
1128b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    edi = (long)(str_buffer + sizeof(str_buffer) / 2) + 16;\
1129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    eax = 0x12345678;\
1130b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ecx = 17;\
1131b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov\
1132b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm volatile ("pushl $0\n\t"\
1133b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "popf\n\t"\
1134b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  DF "\n\t"\
1135b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  REP #OP size "\n\t"\
1136b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "cld\n\t"\
1137b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "pushf\n\t"\
1138b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "popl %4\n\t"\
1139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  : "=S" (esi), "=D" (edi), "=a" (eax), "=c" (ecx), "=g" (eflags)\
1140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  : "0" (esi), "1" (edi), "2" (eax), "3" (ecx));\
1141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("%-10s ESI=%08x EDI=%08x EAX=%08x ECX=%08x EFL=%04x\n",\
1142b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           REP #OP size, esi, edi, eax, ecx,\
1143b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));\
1144b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1145b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1146b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define TEST_STRING(OP, REP)\
1147b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_STRING1(OP, "b", "", REP);\
1148b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_STRING1(OP, "w", "", REP);\
1149b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_STRING1(OP, "l", "", REP);\
1150b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_STRING1(OP, "b", "std", REP);\
1151b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_STRING1(OP, "w", "std", REP);\
1152b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TEST_STRING1(OP, "l", "std", REP)
1153b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1154b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid test_string(void)
1155b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1156b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int i;
1157b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    for(i = 0;i < sizeof(str_buffer); i++)
1158b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        str_buffer[i] = i + 0x56;
1159b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   TEST_STRING(stos, "");
1160b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   TEST_STRING(stos, "rep ");
1161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // REINSTATE: TEST_STRING(lods, ""); /* to verify stos */
1162b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // REINSTATE: TEST_STRING(lods, "rep ");
1163b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   TEST_STRING(movs, "");
1164b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   TEST_STRING(movs, "rep ");
1165b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // REINSTATE: TEST_STRING(lods, ""); /* to verify stos */
1166b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1167b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* XXX: better tests */
1168b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   TEST_STRING(scas, "");
1169b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // REINSTATE: TEST_STRING(scas, "repz ");
1170b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   TEST_STRING(scas, "repnz ");
1171b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // REINSTATE: TEST_STRING(cmps, "");
1172b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   TEST_STRING(cmps, "repz ");
1173b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // REINSTATE: TEST_STRING(cmps, "repnz ");
1174b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1175b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1176b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* VM86 test */
1177b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if 0
1178b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic inline void set_bit(uint8_t *a, unsigned int bit)
1179b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1180b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    a[bit / 8] |= (1 << (bit % 8));
1181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1183b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg)
1184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    return (uint8_t *)((seg << 4) + (reg & 0xffff));
1186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1187b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1188b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic inline void pushw(struct vm86_regs *r, int val)
1189b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1190b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    r->esp = (r->esp & ~0xffff) | ((r->esp - 2) & 0xffff);
1191b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    *(uint16_t *)seg_to_linear(r->ss, r->esp) = val;
1192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1193b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1194b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#undef __syscall_return
1195b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define __syscall_return(type, res) \
1196b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovdo { \
1197b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	return (type) (res); \
1198b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} while (0)
1199b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1200b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov_syscall2(int, vm86, int, func, struct vm86plus_struct *, v86)
1201b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1202b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovextern char vm86_code_start;
1203b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovextern char vm86_code_end;
1204b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1205b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define VM86_CODE_CS 0x100
1206b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define VM86_CODE_IP 0x100
1207b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1208b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid test_vm86(void)
1209b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1210b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    struct vm86plus_struct ctx;
1211b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    struct vm86_regs *r;
1212b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    uint8_t *vm86_mem;
1213b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int seg, ret;
1214b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1215b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    vm86_mem = mmap((void *)0x00000000, 0x110000,
1216b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    PROT_WRITE | PROT_READ | PROT_EXEC,
1217b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
1218b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (vm86_mem == MAP_FAILED) {
1219b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        printf("ERROR: could not map vm86 memory");
1220b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        return;
1221b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1222b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    memset(&ctx, 0, sizeof(ctx));
1223b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1224b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* init basic registers */
1225b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    r = &ctx.regs;
1226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    r->eip = VM86_CODE_IP;
1227b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    r->esp = 0xfffe;
1228b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    seg = VM86_CODE_CS;
1229b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    r->cs = seg;
1230b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    r->ss = seg;
1231b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    r->ds = seg;
1232b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    r->es = seg;
1233b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    r->fs = seg;
1234b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    r->gs = seg;
1235b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    r->eflags = VIF_MASK;
1236b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1237b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* move code to proper address. We use the same layout as a .com
1238b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       dos program. */
1239b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    memcpy(vm86_mem + (VM86_CODE_CS << 4) + VM86_CODE_IP,
1240b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           &vm86_code_start, &vm86_code_end - &vm86_code_start);
1241b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1242b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* mark int 0x21 as being emulated */
1243b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    set_bit((uint8_t *)&ctx.int_revectored, 0x21);
1244b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1245b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    for(;;) {
1246b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        ret = vm86(VM86_ENTER, &ctx);
1247b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        switch(VM86_TYPE(ret)) {
1248b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        case VM86_INTx:
1249b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            {
1250b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                int int_num, ah, v;
1251b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1252b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                int_num = VM86_ARG(ret);
1253b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                if (int_num != 0x21)
1254b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    goto unknown_int;
1255b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                ah = (r->eax >> 8) & 0xff;
1256b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                switch(ah) {
1257b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                case 0x00: /* exit */
1258b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    goto the_end;
1259b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                case 0x02: /* write char */
1260b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    {
1261b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        uint8_t c = r->edx;
1262b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        putchar(c);
1263b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    }
1264b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    break;
1265b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                case 0x09: /* write string */
1266b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    {
1267b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        uint8_t c, *ptr;
1268b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        ptr = seg_to_linear(r->ds, r->edx);
1269b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        for(;;) {
1270b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            c = *ptr++;
1271b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            if (c == '$')
1272b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                break;
1273b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            putchar(c);
1274b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        }
1275b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        r->eax = (r->eax & ~0xff) | '$';
1276b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    }
1277b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    break;
1278b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                case 0xff: /* extension: write eflags number in edx */
1279b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    v = (int)r->edx;
1280b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#ifndef LINUX_VM86_IOPL_FIX
1281b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    v &= ~0x3000;
1282b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
1283b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    printf("%08x\n", v);
1284b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    break;
1285b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                default:
1286b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                unknown_int:
1287b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    printf("unsupported int 0x%02x\n", int_num);
1288b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    goto the_end;
1289b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                }
1290b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            }
1291b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1292b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        case VM86_SIGNAL:
1293b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* a signal came, we just ignore that */
1294b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1295b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        case VM86_STI:
1296b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
1297b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        default:
1298b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            printf("ERROR: unhandled vm86 return code (0x%x)\n", ret);
1299b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            goto the_end;
1300b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        }
1301b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1302b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov the_end:
1303b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("VM86 end\n");
1304b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    munmap(vm86_mem, 0x110000);
1305b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1306b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
1307b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1308b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* exception tests */
1309b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if 0
1310b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#ifndef REG_EAX
1311b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define REG_EAX EAX
1312b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define REG_EBX EBX
1313b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define REG_ECX ECX
1314b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define REG_EDX EDX
1315b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define REG_ESI ESI
1316b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define REG_EDI EDI
1317b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define REG_EBP EBP
1318b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define REG_ESP ESP
1319b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define REG_EIP EIP
1320b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define REG_EFL EFL
1321b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define REG_TRAPNO TRAPNO
1322b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define REG_ERR ERR
1323b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
1324b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1325b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovjmp_buf jmp_env;
1326b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovint v1;
1327b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovint tab[2];
1328b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1329b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid sig_handler(int sig, siginfo_t *info, void *puc)
1330b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1331b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    struct ucontext *uc = puc;
1332b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1333b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("si_signo=%d si_errno=%d si_code=%d",
1334b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           info->si_signo, info->si_errno, info->si_code);
1335b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf(" si_addr=0x%08lx",
1336b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           (unsigned long)info->si_addr);
1337b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("\n");
1338b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("trapno=0x%02x err=0x%08x",
1340b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           uc->uc_mcontext.gregs[REG_TRAPNO],
1341b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           uc->uc_mcontext.gregs[REG_ERR]);
1342b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf(" EIP=0x%08x", uc->uc_mcontext.gregs[REG_EIP]);
1343b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("\n");
1344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    longjmp(jmp_env, 1);
1345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1346b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1347b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid test_exceptions(void)
1348b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1349b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    struct modify_ldt_ldt_s ldt;
1350b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    struct sigaction act;
1351b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    volatile int val;
1352b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1353b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    act.sa_sigaction = sig_handler;
1354b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    sigemptyset(&act.sa_mask);
1355b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    act.sa_flags = SA_SIGINFO;
1356b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    sigaction(SIGFPE, &act, NULL);
1357b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    sigaction(SIGILL, &act, NULL);
1358b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    sigaction(SIGSEGV, &act, NULL);
1359b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    sigaction(SIGBUS, &act, NULL);
1360b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    sigaction(SIGTRAP, &act, NULL);
1361b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1362b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* test division by zero reporting */
1363b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("DIVZ exception:\n");
1364b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (setjmp(jmp_env) == 0) {
1365b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        /* now divide by zero */
1366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        v1 = 0;
1367b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        v1 = 2 / v1;
1368b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1369b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1370b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("BOUND exception:\n");
1371b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (setjmp(jmp_env) == 0) {
1372b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        /* bound exception */
1373b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        tab[0] = 1;
1374b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        tab[1] = 10;
1375b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("bound %0, %1" : : "r" (11), "m" (tab));
1376b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1377b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1378b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("segment exceptions:\n");
1379b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (setjmp(jmp_env) == 0) {
1380b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        /* load an invalid segment */
1381b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("movl %0, %%fs" : : "r" ((0x1234 << 3) | 1));
1382b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1383b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (setjmp(jmp_env) == 0) {
1384b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        /* null data segment is valid */
1385b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("movl %0, %%fs" : : "r" (3));
1386b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        /* null stack segment */
1387b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("movl %0, %%ss" : : "r" (3));
1388b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1389b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1390b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.entry_number = 1;
1391b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.base_addr = (unsigned long)&seg_data1;
1392b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12;
1393b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.seg_32bit = 1;
1394b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.contents = MODIFY_LDT_CONTENTS_DATA;
1395b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.read_exec_only = 0;
1396b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.limit_in_pages = 1;
1397b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.seg_not_present = 1;
1398b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ldt.useable = 1;
1399b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
1400b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1401b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (setjmp(jmp_env) == 0) {
1402b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        /* segment not present */
1403b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1)));
1404b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1405b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1406b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* test SEGV reporting */
1407b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("PF exception:\n");
1408b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (setjmp(jmp_env) == 0) {
1409b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        val = 1;
1410b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        /* we add a nop to test a weird PC retrieval case */
1411b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("nop");
1412b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        /* now store in an invalid address */
1413b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        *(char *)0x1234 = 1;
1414b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1415b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1416b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* test SEGV reporting */
1417b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("PF exception:\n");
1418b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (setjmp(jmp_env) == 0) {
1419b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        val = 1;
1420b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        /* read from an invalid address */
1421b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        v1 = *(char *)0x1234;
1422b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1423b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1424b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* test illegal instruction reporting */
1425b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("UD2 exception:\n");
1426b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (setjmp(jmp_env) == 0) {
1427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        /* now execute an invalid instruction */
1428b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile("ud2");
1429b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1430b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("lock nop exception:\n");
1431b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (setjmp(jmp_env) == 0) {
1432b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        /* now execute an invalid instruction */
1433b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile("lock nop");
1434b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1435b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1436b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("INT exception:\n");
1437b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (setjmp(jmp_env) == 0) {
1438b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("int $0xfd");
1439b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1440b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (setjmp(jmp_env) == 0) {
1441b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("int $0x01");
1442b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1443b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (setjmp(jmp_env) == 0) {
1444b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile (".byte 0xcd, 0x03");
1445b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1446b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (setjmp(jmp_env) == 0) {
1447b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("int $0x04");
1448b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (setjmp(jmp_env) == 0) {
1450b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("int $0x05");
1451b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1452b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1453b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("INT3 exception:\n");
1454b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (setjmp(jmp_env) == 0) {
1455b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("int3");
1456b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1457b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1458b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("CLI exception:\n");
1459b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (setjmp(jmp_env) == 0) {
1460b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("cli");
1461b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1462b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1463b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("STI exception:\n");
1464b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (setjmp(jmp_env) == 0) {
1465b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("cli");
1466b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1467b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1468b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("INTO exception:\n");
1469b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (setjmp(jmp_env) == 0) {
1470b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        /* overflow exception */
1471b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("addl $1, %0 ; into" : : "r" (0x7fffffff));
1472b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1473b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1474b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("OUTB exception:\n");
1475b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (setjmp(jmp_env) == 0) {
1476b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("outb %%al, %%dx" : : "d" (0x4321), "a" (0));
1477b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1478b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1479b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("INB exception:\n");
1480b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (setjmp(jmp_env) == 0) {
1481b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("inb %%dx, %%al" : "=a" (val) : "d" (0x4321));
1482b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1483b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1484b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("REP OUTSB exception:\n");
1485b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (setjmp(jmp_env) == 0) {
1486b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("rep outsb" : : "d" (0x4321), "S" (tab), "c" (1));
1487b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1488b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1489b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("REP INSB exception:\n");
1490b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (setjmp(jmp_env) == 0) {
1491b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("rep insb" : : "d" (0x4321), "D" (tab), "c" (1));
1492b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1493b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1494b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("HLT exception:\n");
1495b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (setjmp(jmp_env) == 0) {
1496b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("hlt");
1497b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1498b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1499b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("single step exception:\n");
1500b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    val = 0;
1501b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (setjmp(jmp_env) == 0) {
1502b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        asm volatile ("pushf\n"
1503b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      "orl $0x00100, (%%esp)\n"
1504b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      "popf\n"
1505b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      "movl $0xabcd, %0\n"
1506b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      "movl $0x0, %0\n" : "=m" (val) : : "cc", "memory");
1507b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1508b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("val=0x%x\n", val);
1509b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1510b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1511b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* specific precise single step test */
1512b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid sig_trap_handler(int sig, siginfo_t *info, void *puc)
1513b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1514b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    struct ucontext *uc = puc;
1515b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("EIP=0x%08x\n", uc->uc_mcontext.gregs[REG_EIP]);
1516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1517b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1518b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovconst uint8_t sstep_buf1[4] = { 1, 2, 3, 4};
1519b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovuint8_t sstep_buf2[4];
1520b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1521b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid test_single_step(void)
1522b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1523b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    struct sigaction act;
1524b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    volatile int val;
1525b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int i;
1526b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1527b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    val = 0;
1528b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    act.sa_sigaction = sig_trap_handler;
1529b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    sigemptyset(&act.sa_mask);
1530b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    act.sa_flags = SA_SIGINFO;
1531b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    sigaction(SIGTRAP, &act, NULL);
1532b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    asm volatile ("pushf\n"
1533b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "orl $0x00100, (%%esp)\n"
1534b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "popf\n"
1535b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "movl $0xabcd, %0\n"
1536b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1537b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  /* jmp test */
1538b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "movl $3, %%ecx\n"
1539b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "1:\n"
1540b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "addl $1, %0\n"
1541b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "decl %%ecx\n"
1542b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "jnz 1b\n"
1543b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1544b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  /* movsb: the single step should stop at each movsb iteration */
1545b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "movl $sstep_buf1, %%esi\n"
1546b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "movl $sstep_buf2, %%edi\n"
1547b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "movl $0, %%ecx\n"
1548b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "rep movsb\n"
1549b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "movl $3, %%ecx\n"
1550b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "rep movsb\n"
1551b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "movl $1, %%ecx\n"
1552b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "rep movsb\n"
1553b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1554b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  /* cmpsb: the single step should stop at each cmpsb iteration */
1555b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "movl $sstep_buf1, %%esi\n"
1556b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "movl $sstep_buf2, %%edi\n"
1557b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "movl $0, %%ecx\n"
1558b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "rep cmpsb\n"
1559b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "movl $4, %%ecx\n"
1560b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "rep cmpsb\n"
1561b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1562b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  /* getpid() syscall: single step should skip one
1563b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     instruction */
1564b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "movl $20, %%eax\n"
1565b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "int $0x80\n"
1566b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "movl $0, %%eax\n"
1567b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1568b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  /* when modifying SS, trace is not done on the next
1569b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     instruction */
1570b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "movl %%ss, %%ecx\n"
1571b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "movl %%ecx, %%ss\n"
1572b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "addl $1, %0\n"
1573b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "movl $1, %%eax\n"
1574b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "movl %%ecx, %%ss\n"
1575b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "jmp 1f\n"
1576b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "addl $1, %0\n"
1577b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "1:\n"
1578b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "movl $1, %%eax\n"
1579b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "pushl %%ecx\n"
1580b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "popl %%ss\n"
1581b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "addl $1, %0\n"
1582b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "movl $1, %%eax\n"
1583b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1584b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "pushf\n"
1585b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "andl $~0x00100, (%%esp)\n"
1586b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "popf\n"
1587b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  : "=m" (val)
1588b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  :
1589b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  : "cc", "memory", "eax", "ecx", "esi", "edi");
1590b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("val=%d\n", val);
1591b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    for(i = 0; i < 4; i++)
1592b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        printf("sstep_buf2[%d] = %d\n", i, sstep_buf2[i]);
1593b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1594b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1595b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* self modifying code test */
1596b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovuint8_t code[] = {
1597b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    0xb8, 0x1, 0x00, 0x00, 0x00, /* movl $1, %eax */
1598b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    0xc3, /* ret */
1599b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov};
1600b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1601b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovasm("smc_code2:\n"
1602b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    "movl 4(%esp), %eax\n"
1603b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    "movl %eax, smc_patch_addr2 + 1\n"
1604b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    "nop\n"
1605b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    "nop\n"
1606b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    "nop\n"
1607b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    "nop\n"
1608b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    "nop\n"
1609b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    "nop\n"
1610b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    "nop\n"
1611b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    "nop\n"
1612b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    "smc_patch_addr2:\n"
1613b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    "movl $1, %eax\n"
1614b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    "ret\n");
1615b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1616b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef int FuncType(void);
1617b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovextern int smc_code2(int);
1618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid test_self_modifying_code(void)
1619b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1620b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int i;
1621b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1622b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("self modifying code:\n");
1623b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("func1 = 0x%x\n", ((FuncType *)code)());
1624b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    for(i = 2; i <= 4; i++) {
1625b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        code[1] = i;
1626b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        printf("func%d = 0x%x\n", i, ((FuncType *)code)());
1627b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1628b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1629b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* more difficult test : the modified code is just after the
1630b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       modifying instruction. It is forbidden in Intel specs, but it
1631b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       is used by old DOS programs */
1632b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    for(i = 2; i <= 4; i++) {
1633b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        printf("smc_code2(%d) = %d\n", i, smc_code2(i));
1634b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1635b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1636b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1637b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void *call_end __init_call = NULL;
1638b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
1639b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1640b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovint main(int argc, char **argv)
1641b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1642b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    void **ptr;
1643b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    void (*func)(void);
1644b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1645b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if 1
1646b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ptr = &call_start + 1;
1647b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    while (*ptr != NULL) {
1648b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        func = *ptr++;
1649b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        func();
1650b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1651b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
1652b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_bsx();
1653b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_mul();
1654b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_jcc();
1655b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_floats();
1656b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    //test_bcd();
1657b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_xchg();
1658b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_string();
1659b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_misc(); // REINSTATE
1660b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    test_lea();
1661b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    //    test_segs();
1662b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    //test_code16();
1663b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    //test_vm86();
1664b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    //test_exceptions();
1665b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    //test_self_modifying_code();
1666b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    //test_single_step();
1667b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    return 0;
1668b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1669