xref: /plan9-contrib/sys/src/cmd/aux/realemu/xec.c (revision ccaec48a6a7d481d90233fb80c88e608b0a02604)
1*ccaec48aSDavid du Colombier #include <u.h>
2*ccaec48aSDavid du Colombier #include <libc.h>
3*ccaec48aSDavid du Colombier #include "dat.h"
4*ccaec48aSDavid du Colombier #include "fns.h"
5*ccaec48aSDavid du Colombier 
6*ccaec48aSDavid du Colombier #define sign(s)	(1UL<<((s)-1))
7*ccaec48aSDavid du Colombier #define mask(s) (sign(s)|(sign(s)-1))
8*ccaec48aSDavid du Colombier 
9*ccaec48aSDavid du Colombier static void
push(Iarg * sp,Iarg * a)10*ccaec48aSDavid du Colombier push(Iarg *sp, Iarg *a)
11*ccaec48aSDavid du Colombier {
12*ccaec48aSDavid du Colombier 	Iarg *p;
13*ccaec48aSDavid du Colombier 
14*ccaec48aSDavid du Colombier 	p = amem(sp->cpu, a->len, RSS, ar(sp));
15*ccaec48aSDavid du Colombier 	p->off -= a->len;
16*ccaec48aSDavid du Colombier 	p->off &= mask(sp->len*8);
17*ccaec48aSDavid du Colombier 	aw(p, ar(a));
18*ccaec48aSDavid du Colombier 	aw(sp, p->off);
19*ccaec48aSDavid du Colombier }
20*ccaec48aSDavid du Colombier 
21*ccaec48aSDavid du Colombier static void
pop(Iarg * sp,Iarg * a)22*ccaec48aSDavid du Colombier pop(Iarg *sp, Iarg *a)
23*ccaec48aSDavid du Colombier {
24*ccaec48aSDavid du Colombier 	Iarg *p;
25*ccaec48aSDavid du Colombier 
26*ccaec48aSDavid du Colombier 	p = amem(sp->cpu, a->len, RSS, ar(sp));
27*ccaec48aSDavid du Colombier 	aw(a, ar(p));
28*ccaec48aSDavid du Colombier 	aw(sp, p->off + a->len);
29*ccaec48aSDavid du Colombier }
30*ccaec48aSDavid du Colombier 
31*ccaec48aSDavid du Colombier static void
jump(Iarg * to)32*ccaec48aSDavid du Colombier jump(Iarg *to)
33*ccaec48aSDavid du Colombier {
34*ccaec48aSDavid du Colombier 	Cpu *cpu;
35*ccaec48aSDavid du Colombier 
36*ccaec48aSDavid du Colombier 	cpu = to->cpu;
37*ccaec48aSDavid du Colombier 	switch(to->atype){
38*ccaec48aSDavid du Colombier 	default:
39*ccaec48aSDavid du Colombier 		abort();
40*ccaec48aSDavid du Colombier 	case AMp:
41*ccaec48aSDavid du Colombier 		to = afar(to, 1, to->len);
42*ccaec48aSDavid du Colombier 	case AAp:
43*ccaec48aSDavid du Colombier 		cpu->reg[RCS] = to->seg;
44*ccaec48aSDavid du Colombier 	case AJb:
45*ccaec48aSDavid du Colombier 	case AJv:
46*ccaec48aSDavid du Colombier 		cpu->reg[RIP] = to->off;
47*ccaec48aSDavid du Colombier 		break;
48*ccaec48aSDavid du Colombier 	case AEv:
49*ccaec48aSDavid du Colombier 		cpu->reg[RIP] = ar(to);
50*ccaec48aSDavid du Colombier 		break;
51*ccaec48aSDavid du Colombier 	}
52*ccaec48aSDavid du Colombier }
53*ccaec48aSDavid du Colombier 
54*ccaec48aSDavid du Colombier static void
opcall(Cpu * cpu,Inst * i)55*ccaec48aSDavid du Colombier opcall(Cpu *cpu, Inst *i)
56*ccaec48aSDavid du Colombier {
57*ccaec48aSDavid du Colombier 	Iarg *sp;
58*ccaec48aSDavid du Colombier 
59*ccaec48aSDavid du Colombier 	sp = areg(cpu, cpu->slen, RSP);
60*ccaec48aSDavid du Colombier 	switch(i->a1->atype){
61*ccaec48aSDavid du Colombier 	default:
62*ccaec48aSDavid du Colombier 		abort();
63*ccaec48aSDavid du Colombier 	case AAp:
64*ccaec48aSDavid du Colombier 	case AMp:
65*ccaec48aSDavid du Colombier 		push(sp, areg(cpu, i->olen, RCS));
66*ccaec48aSDavid du Colombier 	case AJv:
67*ccaec48aSDavid du Colombier 	case AEv:
68*ccaec48aSDavid du Colombier 		push(sp, areg(cpu, i->olen, RIP));
69*ccaec48aSDavid du Colombier 		break;
70*ccaec48aSDavid du Colombier 	}
71*ccaec48aSDavid du Colombier 	jump(i->a1);
72*ccaec48aSDavid du Colombier }
73*ccaec48aSDavid du Colombier 
74*ccaec48aSDavid du Colombier static void
opint(Cpu * cpu,Inst * i)75*ccaec48aSDavid du Colombier opint(Cpu *cpu, Inst *i)
76*ccaec48aSDavid du Colombier {
77*ccaec48aSDavid du Colombier 	cpu->trap = ar(i->a1);
78*ccaec48aSDavid du Colombier 	longjmp(cpu->jmp, 1);
79*ccaec48aSDavid du Colombier }
80*ccaec48aSDavid du Colombier 
81*ccaec48aSDavid du Colombier static void
opiret(Cpu * cpu,Inst * i)82*ccaec48aSDavid du Colombier opiret(Cpu *cpu, Inst *i)
83*ccaec48aSDavid du Colombier {
84*ccaec48aSDavid du Colombier 	Iarg *sp;
85*ccaec48aSDavid du Colombier 
86*ccaec48aSDavid du Colombier 	if(i->olen != 2)
87*ccaec48aSDavid du Colombier 		trap(cpu, EBADOP);
88*ccaec48aSDavid du Colombier 	sp = areg(cpu, cpu->slen, RSP);
89*ccaec48aSDavid du Colombier 	pop(sp, areg(cpu, 2, RIP));
90*ccaec48aSDavid du Colombier 	pop(sp, areg(cpu, 2, RCS));
91*ccaec48aSDavid du Colombier 	pop(sp, areg(cpu, 2, RFL));
92*ccaec48aSDavid du Colombier }
93*ccaec48aSDavid du Colombier 
94*ccaec48aSDavid du Colombier static void
opret(Cpu * cpu,Inst * i)95*ccaec48aSDavid du Colombier opret(Cpu *cpu, Inst *i)
96*ccaec48aSDavid du Colombier {
97*ccaec48aSDavid du Colombier 	Iarg *sp;
98*ccaec48aSDavid du Colombier 	ulong c;
99*ccaec48aSDavid du Colombier 
100*ccaec48aSDavid du Colombier 	sp = areg(cpu, cpu->slen, RSP);
101*ccaec48aSDavid du Colombier 	pop(sp, areg(cpu, i->olen, RIP));
102*ccaec48aSDavid du Colombier 	if(c = ar(i->a1))
103*ccaec48aSDavid du Colombier 		aw(sp, ar(sp) + c);
104*ccaec48aSDavid du Colombier }
105*ccaec48aSDavid du Colombier 
106*ccaec48aSDavid du Colombier static void
opretf(Cpu * cpu,Inst * i)107*ccaec48aSDavid du Colombier opretf(Cpu *cpu, Inst *i)
108*ccaec48aSDavid du Colombier {
109*ccaec48aSDavid du Colombier 	Iarg *sp;
110*ccaec48aSDavid du Colombier 	ulong c;
111*ccaec48aSDavid du Colombier 
112*ccaec48aSDavid du Colombier 	sp = areg(cpu, cpu->slen, RSP);
113*ccaec48aSDavid du Colombier 	pop(sp, areg(cpu, i->olen, RIP));
114*ccaec48aSDavid du Colombier 	pop(sp, areg(cpu, i->olen, RCS));
115*ccaec48aSDavid du Colombier 	if(c = ar(i->a1))
116*ccaec48aSDavid du Colombier 		aw(sp, ar(sp) + c);
117*ccaec48aSDavid du Colombier }
118*ccaec48aSDavid du Colombier 
119*ccaec48aSDavid du Colombier static void
openter(Cpu * cpu,Inst * i)120*ccaec48aSDavid du Colombier openter(Cpu *cpu, Inst *i)
121*ccaec48aSDavid du Colombier {
122*ccaec48aSDavid du Colombier 	Iarg *sp, *bp;
123*ccaec48aSDavid du Colombier 	ulong oframe, nframe;
124*ccaec48aSDavid du Colombier 	int j, n;
125*ccaec48aSDavid du Colombier 
126*ccaec48aSDavid du Colombier 	sp = areg(cpu, cpu->slen, RSP);
127*ccaec48aSDavid du Colombier 	bp = areg(cpu, cpu->slen, RBP);
128*ccaec48aSDavid du Colombier 	push(sp, bp);
129*ccaec48aSDavid du Colombier 	oframe = ar(bp);
130*ccaec48aSDavid du Colombier 	nframe = ar(sp);
131*ccaec48aSDavid du Colombier 	n = ar(i->a2) % 32;
132*ccaec48aSDavid du Colombier 	if(n > 0){
133*ccaec48aSDavid du Colombier 		for(j=1; j<n; j++){
134*ccaec48aSDavid du Colombier 			aw(bp, oframe - i->olen*j);
135*ccaec48aSDavid du Colombier 			push(sp, bp);
136*ccaec48aSDavid du Colombier 		}
137*ccaec48aSDavid du Colombier 		push(sp, acon(cpu, i->olen, nframe));
138*ccaec48aSDavid du Colombier 	}
139*ccaec48aSDavid du Colombier 	aw(bp, nframe);
140*ccaec48aSDavid du Colombier 	aw(sp, nframe - ar(i->a1));
141*ccaec48aSDavid du Colombier }
142*ccaec48aSDavid du Colombier 
143*ccaec48aSDavid du Colombier static void
opleave(Cpu * cpu,Inst * i)144*ccaec48aSDavid du Colombier opleave(Cpu *cpu, Inst *i)
145*ccaec48aSDavid du Colombier {
146*ccaec48aSDavid du Colombier 	Iarg *sp;
147*ccaec48aSDavid du Colombier 
148*ccaec48aSDavid du Colombier 	sp = areg(cpu, cpu->slen, RSP);
149*ccaec48aSDavid du Colombier 	aw(sp, ar(areg(cpu, cpu->slen, RBP)));
150*ccaec48aSDavid du Colombier 	pop(sp, areg(cpu, i->olen, RBP));
151*ccaec48aSDavid du Colombier }
152*ccaec48aSDavid du Colombier 
153*ccaec48aSDavid du Colombier static void
oppush(Cpu * cpu,Inst * i)154*ccaec48aSDavid du Colombier oppush(Cpu *cpu, Inst *i)
155*ccaec48aSDavid du Colombier {
156*ccaec48aSDavid du Colombier 	Iarg *sp;
157*ccaec48aSDavid du Colombier 
158*ccaec48aSDavid du Colombier 	sp = areg(cpu, cpu->slen, RSP);
159*ccaec48aSDavid du Colombier 	if(i->a1->len == 1)	/* 0x6A push imm8 */
160*ccaec48aSDavid du Colombier 		push(sp, acon(cpu, i->olen, ar(i->a1)));
161*ccaec48aSDavid du Colombier 	else
162*ccaec48aSDavid du Colombier 		push(sp, i->a1);
163*ccaec48aSDavid du Colombier }
164*ccaec48aSDavid du Colombier 
165*ccaec48aSDavid du Colombier static void
oppop(Cpu * cpu,Inst * i)166*ccaec48aSDavid du Colombier oppop(Cpu *cpu, Inst *i)
167*ccaec48aSDavid du Colombier {
168*ccaec48aSDavid du Colombier 	pop(areg(cpu, cpu->slen, RSP), i->a1);
169*ccaec48aSDavid du Colombier }
170*ccaec48aSDavid du Colombier 
171*ccaec48aSDavid du Colombier static void
oppusha(Cpu * cpu,Inst * i)172*ccaec48aSDavid du Colombier oppusha(Cpu *cpu, Inst *i)
173*ccaec48aSDavid du Colombier {
174*ccaec48aSDavid du Colombier 	Iarg *sp, *osp;
175*ccaec48aSDavid du Colombier 
176*ccaec48aSDavid du Colombier 	sp = areg(cpu, cpu->slen, RSP);
177*ccaec48aSDavid du Colombier 	osp = acon(cpu, i->olen, ar(sp));
178*ccaec48aSDavid du Colombier 	push(sp, areg(cpu, i->olen, RAX));
179*ccaec48aSDavid du Colombier 	push(sp, areg(cpu, i->olen, RCX));
180*ccaec48aSDavid du Colombier 	push(sp, areg(cpu, i->olen, RDX));
181*ccaec48aSDavid du Colombier 	push(sp, areg(cpu, i->olen, RBX));
182*ccaec48aSDavid du Colombier 	push(sp, osp);
183*ccaec48aSDavid du Colombier 	push(sp, areg(cpu, i->olen, RBP));
184*ccaec48aSDavid du Colombier 	push(sp, areg(cpu, i->olen, RSI));
185*ccaec48aSDavid du Colombier 	push(sp, areg(cpu, i->olen, RDI));
186*ccaec48aSDavid du Colombier }
187*ccaec48aSDavid du Colombier 
188*ccaec48aSDavid du Colombier static void
oppopa(Cpu * cpu,Inst * i)189*ccaec48aSDavid du Colombier oppopa(Cpu *cpu, Inst *i)
190*ccaec48aSDavid du Colombier {
191*ccaec48aSDavid du Colombier 	Iarg *sp;
192*ccaec48aSDavid du Colombier 
193*ccaec48aSDavid du Colombier 	sp = areg(cpu, cpu->slen, RSP);
194*ccaec48aSDavid du Colombier 	pop(sp, areg(cpu, i->olen, RDI));
195*ccaec48aSDavid du Colombier 	pop(sp, areg(cpu, i->olen, RSI));
196*ccaec48aSDavid du Colombier 	pop(sp, areg(cpu, i->olen, RBP));
197*ccaec48aSDavid du Colombier 	pop(sp, areg(cpu, i->olen, RBX));	// RSP
198*ccaec48aSDavid du Colombier 	pop(sp, areg(cpu, i->olen, RBX));
199*ccaec48aSDavid du Colombier 	pop(sp, areg(cpu, i->olen, RDX));
200*ccaec48aSDavid du Colombier 	pop(sp, areg(cpu, i->olen, RCX));
201*ccaec48aSDavid du Colombier 	pop(sp, areg(cpu, i->olen, RAX));
202*ccaec48aSDavid du Colombier }
203*ccaec48aSDavid du Colombier 
204*ccaec48aSDavid du Colombier static void
oppushf(Cpu * cpu,Inst * i)205*ccaec48aSDavid du Colombier oppushf(Cpu *cpu, Inst *i)
206*ccaec48aSDavid du Colombier {
207*ccaec48aSDavid du Colombier 	push(areg(cpu, cpu->slen, RSP), areg(cpu, i->olen, RFL));
208*ccaec48aSDavid du Colombier }
209*ccaec48aSDavid du Colombier 
210*ccaec48aSDavid du Colombier static void
oppopf(Cpu * cpu,Inst * i)211*ccaec48aSDavid du Colombier oppopf(Cpu *cpu, Inst *i)
212*ccaec48aSDavid du Colombier {
213*ccaec48aSDavid du Colombier 	ulong *f, o;
214*ccaec48aSDavid du Colombier 
215*ccaec48aSDavid du Colombier 	f = cpu->reg + RFL;
216*ccaec48aSDavid du Colombier 	o = *f;
217*ccaec48aSDavid du Colombier 	pop(areg(cpu, cpu->slen, RSP), areg(cpu, i->olen, RFL));
218*ccaec48aSDavid du Colombier 	*f &= ~(VM|RF);
219*ccaec48aSDavid du Colombier 	*f |= (o & (VM|RF));
220*ccaec48aSDavid du Colombier }
221*ccaec48aSDavid du Colombier 
222*ccaec48aSDavid du Colombier static void
oplahf(Cpu * cpu,Inst * i)223*ccaec48aSDavid du Colombier oplahf(Cpu *cpu, Inst *i)
224*ccaec48aSDavid du Colombier {
225*ccaec48aSDavid du Colombier 	aw(i->a1, cpu->reg[RFL]);
226*ccaec48aSDavid du Colombier }
227*ccaec48aSDavid du Colombier 
228*ccaec48aSDavid du Colombier static void
opsahf(Cpu * cpu,Inst * i)229*ccaec48aSDavid du Colombier opsahf(Cpu *cpu, Inst *i)
230*ccaec48aSDavid du Colombier {
231*ccaec48aSDavid du Colombier 	enum { MASK = SF|ZF|AF|PF|CF };
232*ccaec48aSDavid du Colombier 	ulong *f;
233*ccaec48aSDavid du Colombier 
234*ccaec48aSDavid du Colombier 	f = cpu->reg + RFL;
235*ccaec48aSDavid du Colombier 	*f &= ~MASK;
236*ccaec48aSDavid du Colombier 	*f |= (ar(i->a1) & MASK);
237*ccaec48aSDavid du Colombier }
238*ccaec48aSDavid du Colombier 
239*ccaec48aSDavid du Colombier static void
opcli(Cpu * cpu,Inst *)240*ccaec48aSDavid du Colombier opcli(Cpu *cpu, Inst *)
241*ccaec48aSDavid du Colombier {
242*ccaec48aSDavid du Colombier 	cpu->reg[RFL] &= ~IF;
243*ccaec48aSDavid du Colombier }
244*ccaec48aSDavid du Colombier 
245*ccaec48aSDavid du Colombier static void
opsti(Cpu * cpu,Inst *)246*ccaec48aSDavid du Colombier opsti(Cpu *cpu, Inst *)
247*ccaec48aSDavid du Colombier {
248*ccaec48aSDavid du Colombier 	cpu->reg[RFL] |= IF;
249*ccaec48aSDavid du Colombier }
250*ccaec48aSDavid du Colombier 
251*ccaec48aSDavid du Colombier static void
opcld(Cpu * cpu,Inst *)252*ccaec48aSDavid du Colombier opcld(Cpu *cpu, Inst *)
253*ccaec48aSDavid du Colombier {
254*ccaec48aSDavid du Colombier 	cpu->reg[RFL] &= ~DF;
255*ccaec48aSDavid du Colombier }
256*ccaec48aSDavid du Colombier 
257*ccaec48aSDavid du Colombier static void
opstd(Cpu * cpu,Inst *)258*ccaec48aSDavid du Colombier opstd(Cpu *cpu, Inst *)
259*ccaec48aSDavid du Colombier {
260*ccaec48aSDavid du Colombier 	cpu->reg[RFL] |= DF;
261*ccaec48aSDavid du Colombier }
262*ccaec48aSDavid du Colombier 
263*ccaec48aSDavid du Colombier static void
opclc(Cpu * cpu,Inst *)264*ccaec48aSDavid du Colombier opclc(Cpu *cpu, Inst *)
265*ccaec48aSDavid du Colombier {
266*ccaec48aSDavid du Colombier 	cpu->reg[RFL] &= ~CF;
267*ccaec48aSDavid du Colombier }
268*ccaec48aSDavid du Colombier 
269*ccaec48aSDavid du Colombier static void
opstc(Cpu * cpu,Inst *)270*ccaec48aSDavid du Colombier opstc(Cpu *cpu, Inst *)
271*ccaec48aSDavid du Colombier {
272*ccaec48aSDavid du Colombier 	cpu->reg[RFL] |= CF;
273*ccaec48aSDavid du Colombier }
274*ccaec48aSDavid du Colombier 
275*ccaec48aSDavid du Colombier static void
opcmc(Cpu * cpu,Inst *)276*ccaec48aSDavid du Colombier opcmc(Cpu *cpu, Inst *)
277*ccaec48aSDavid du Colombier {
278*ccaec48aSDavid du Colombier 	cpu->reg[RFL] ^= CF;
279*ccaec48aSDavid du Colombier }
280*ccaec48aSDavid du Colombier 
281*ccaec48aSDavid du Colombier static void
parity(ulong * f,ulong r)282*ccaec48aSDavid du Colombier parity(ulong *f, ulong r)
283*ccaec48aSDavid du Colombier {
284*ccaec48aSDavid du Colombier 	static ulong tab[8] = {
285*ccaec48aSDavid du Colombier 		0x96696996,
286*ccaec48aSDavid du Colombier 		0x69969669,
287*ccaec48aSDavid du Colombier 		0x69969669,
288*ccaec48aSDavid du Colombier 		0x96696996,
289*ccaec48aSDavid du Colombier 		0x69969669,
290*ccaec48aSDavid du Colombier 		0x96696996,
291*ccaec48aSDavid du Colombier 		0x96696996,
292*ccaec48aSDavid du Colombier 		0x69969669,
293*ccaec48aSDavid du Colombier 	};
294*ccaec48aSDavid du Colombier 	r &= 0xFF;
295*ccaec48aSDavid du Colombier 	if((tab[r/32] >> (r%32)) & 1)
296*ccaec48aSDavid du Colombier 		*f &= ~PF;
297*ccaec48aSDavid du Colombier 	else
298*ccaec48aSDavid du Colombier 		*f |= PF;
299*ccaec48aSDavid du Colombier }
300*ccaec48aSDavid du Colombier 
301*ccaec48aSDavid du Colombier static ulong
test(ulong * f,long r,int s)302*ccaec48aSDavid du Colombier test(ulong *f, long r, int s)
303*ccaec48aSDavid du Colombier {
304*ccaec48aSDavid du Colombier 	*f &= ~(CF|SF|ZF|OF|PF);
305*ccaec48aSDavid du Colombier 	r &= mask(s);
306*ccaec48aSDavid du Colombier 	if(r == 0)
307*ccaec48aSDavid du Colombier 		*f |= ZF;
308*ccaec48aSDavid du Colombier 	if(r & sign(s))
309*ccaec48aSDavid du Colombier 		*f |= SF;
310*ccaec48aSDavid du Colombier 	parity(f, r);
311*ccaec48aSDavid du Colombier 	return r;
312*ccaec48aSDavid du Colombier }
313*ccaec48aSDavid du Colombier 
314*ccaec48aSDavid du Colombier static void
opshl(Cpu * cpu,Inst * i)315*ccaec48aSDavid du Colombier opshl(Cpu *cpu, Inst *i)
316*ccaec48aSDavid du Colombier {
317*ccaec48aSDavid du Colombier 	ulong *f, r, a, h;
318*ccaec48aSDavid du Colombier 	int s, n;
319*ccaec48aSDavid du Colombier 
320*ccaec48aSDavid du Colombier 	if((n = ar(i->a2) & 31) == 0)
321*ccaec48aSDavid du Colombier 		return;
322*ccaec48aSDavid du Colombier 	s = i->a1->len*8;
323*ccaec48aSDavid du Colombier 	a = ar(i->a1);
324*ccaec48aSDavid du Colombier 	f = cpu->reg + RFL;
325*ccaec48aSDavid du Colombier 	r = test(f, a<<n, s);
326*ccaec48aSDavid du Colombier 	h = sign(s);
327*ccaec48aSDavid du Colombier 	aw(i->a1, r);
328*ccaec48aSDavid du Colombier 	if((a<<(n-1)) & h)
329*ccaec48aSDavid du Colombier 		*f |= CF;
330*ccaec48aSDavid du Colombier 	if(n == 1 && ((a^r) & h))
331*ccaec48aSDavid du Colombier 		*f |= OF;
332*ccaec48aSDavid du Colombier }
333*ccaec48aSDavid du Colombier 
334*ccaec48aSDavid du Colombier static void
opshr(Cpu * cpu,Inst * i)335*ccaec48aSDavid du Colombier opshr(Cpu *cpu, Inst *i)
336*ccaec48aSDavid du Colombier {
337*ccaec48aSDavid du Colombier 	ulong *f, a;
338*ccaec48aSDavid du Colombier 	int s, n;
339*ccaec48aSDavid du Colombier 
340*ccaec48aSDavid du Colombier 	if((n = ar(i->a2) & 31) == 0)
341*ccaec48aSDavid du Colombier 		return;
342*ccaec48aSDavid du Colombier 	s = i->a1->len*8;
343*ccaec48aSDavid du Colombier 	a = ar(i->a1);
344*ccaec48aSDavid du Colombier 	f = cpu->reg + RFL;
345*ccaec48aSDavid du Colombier 	aw(i->a1, test(f, a>>n, s));
346*ccaec48aSDavid du Colombier 	if(a & sign(n))
347*ccaec48aSDavid du Colombier 		*f |= CF;
348*ccaec48aSDavid du Colombier 	if(n == 1 && (a & sign(s)))
349*ccaec48aSDavid du Colombier 		*f |= OF;
350*ccaec48aSDavid du Colombier }
351*ccaec48aSDavid du Colombier 
352*ccaec48aSDavid du Colombier static void
opsar(Cpu * cpu,Inst * i)353*ccaec48aSDavid du Colombier opsar(Cpu *cpu, Inst *i)
354*ccaec48aSDavid du Colombier {
355*ccaec48aSDavid du Colombier 	ulong *f;
356*ccaec48aSDavid du Colombier 	long a;
357*ccaec48aSDavid du Colombier 	int n;
358*ccaec48aSDavid du Colombier 
359*ccaec48aSDavid du Colombier 	if((n = ar(i->a2) & 31) == 0)
360*ccaec48aSDavid du Colombier 		return;
361*ccaec48aSDavid du Colombier 	a = ars(i->a1);
362*ccaec48aSDavid du Colombier 	f = cpu->reg + RFL;
363*ccaec48aSDavid du Colombier 	aw(i->a1, test(f, a>>n, i->a1->len*8));
364*ccaec48aSDavid du Colombier 	if(a & sign(n))
365*ccaec48aSDavid du Colombier 		*f |= CF;
366*ccaec48aSDavid du Colombier }
367*ccaec48aSDavid du Colombier 
368*ccaec48aSDavid du Colombier static void
opshld(Cpu * cpu,Inst * i)369*ccaec48aSDavid du Colombier opshld(Cpu *cpu, Inst *i)
370*ccaec48aSDavid du Colombier {
371*ccaec48aSDavid du Colombier 	ulong *f, a;
372*ccaec48aSDavid du Colombier 	int s, n;
373*ccaec48aSDavid du Colombier 
374*ccaec48aSDavid du Colombier 	if((n = ar(i->a3) & 31) == 0)
375*ccaec48aSDavid du Colombier 		return;
376*ccaec48aSDavid du Colombier 	s = i->a1->len*8;
377*ccaec48aSDavid du Colombier 	a = ar(i->a1);
378*ccaec48aSDavid du Colombier 	f = cpu->reg + RFL;
379*ccaec48aSDavid du Colombier 	aw(i->a1, test(f, (a<<n)|(ar(i->a2)>>(s-n)), s));
380*ccaec48aSDavid du Colombier 	if((a<<(n-1)) & sign(s))
381*ccaec48aSDavid du Colombier 		*f |= CF;
382*ccaec48aSDavid du Colombier }
383*ccaec48aSDavid du Colombier 
384*ccaec48aSDavid du Colombier static void
opshrd(Cpu * cpu,Inst * i)385*ccaec48aSDavid du Colombier opshrd(Cpu *cpu, Inst *i)
386*ccaec48aSDavid du Colombier {
387*ccaec48aSDavid du Colombier 	ulong *f, a;
388*ccaec48aSDavid du Colombier 	int s, n;
389*ccaec48aSDavid du Colombier 
390*ccaec48aSDavid du Colombier 	if((n = ar(i->a3) & 31) == 0)
391*ccaec48aSDavid du Colombier 		return;
392*ccaec48aSDavid du Colombier 	s = i->a1->len*8;
393*ccaec48aSDavid du Colombier 	a = ar(i->a1);
394*ccaec48aSDavid du Colombier 	f = cpu->reg + RFL;
395*ccaec48aSDavid du Colombier 	aw(i->a1, test(f, (a>>n)|(ar(i->a2)<<(s-n)), s));
396*ccaec48aSDavid du Colombier 	if(a & sign(n))
397*ccaec48aSDavid du Colombier 		*f |= CF;
398*ccaec48aSDavid du Colombier }
399*ccaec48aSDavid du Colombier 
400*ccaec48aSDavid du Colombier 
401*ccaec48aSDavid du Colombier static void
oprcl(Cpu * cpu,Inst * i)402*ccaec48aSDavid du Colombier oprcl(Cpu *cpu, Inst *i)
403*ccaec48aSDavid du Colombier {
404*ccaec48aSDavid du Colombier 	ulong *f, a, r;
405*ccaec48aSDavid du Colombier 	int s, n;
406*ccaec48aSDavid du Colombier 
407*ccaec48aSDavid du Colombier 	s = i->a1->len*8;
408*ccaec48aSDavid du Colombier 	n = ar(i->a2) % (s+1);
409*ccaec48aSDavid du Colombier 	a = ar(i->a1);
410*ccaec48aSDavid du Colombier 	r = (a<<n) | ((a>>(s-n))>>1);
411*ccaec48aSDavid du Colombier 	f = cpu->reg + RFL;
412*ccaec48aSDavid du Colombier 	if(*f & CF)
413*ccaec48aSDavid du Colombier 		r |= sign(n);
414*ccaec48aSDavid du Colombier 	aw(i->a1, r);
415*ccaec48aSDavid du Colombier 	*f &= ~(CF|OF);
416*ccaec48aSDavid du Colombier 	if((a>>(s-n)) & 1)
417*ccaec48aSDavid du Colombier 		*f |= CF;
418*ccaec48aSDavid du Colombier 	if((a ^ r) & sign(s))
419*ccaec48aSDavid du Colombier 		*f |= OF;
420*ccaec48aSDavid du Colombier 	parity(f, r);
421*ccaec48aSDavid du Colombier }
422*ccaec48aSDavid du Colombier 
423*ccaec48aSDavid du Colombier static void
oprcr(Cpu * cpu,Inst * i)424*ccaec48aSDavid du Colombier oprcr(Cpu *cpu, Inst *i)
425*ccaec48aSDavid du Colombier {
426*ccaec48aSDavid du Colombier 	ulong *f, a, r, h;
427*ccaec48aSDavid du Colombier 	int s, n;
428*ccaec48aSDavid du Colombier 
429*ccaec48aSDavid du Colombier 	s = i->a1->len*8;
430*ccaec48aSDavid du Colombier 	n = ar(i->a2) % (s+1);
431*ccaec48aSDavid du Colombier 	a = ar(i->a1);
432*ccaec48aSDavid du Colombier 	h = a<<(s-n);
433*ccaec48aSDavid du Colombier 	r = (a>>n) | (h<<1);
434*ccaec48aSDavid du Colombier 	f = cpu->reg + RFL;
435*ccaec48aSDavid du Colombier 	if(*f & CF)
436*ccaec48aSDavid du Colombier 		r |= 1<<(s-n);
437*ccaec48aSDavid du Colombier 	aw(i->a1, r);
438*ccaec48aSDavid du Colombier 	*f &= ~(CF|OF);
439*ccaec48aSDavid du Colombier 	if(h & sign(s))
440*ccaec48aSDavid du Colombier 		*f |= CF;
441*ccaec48aSDavid du Colombier 	if((a ^ r) & sign(s))
442*ccaec48aSDavid du Colombier 		*f |= OF;
443*ccaec48aSDavid du Colombier 	parity(f, r);
444*ccaec48aSDavid du Colombier }
445*ccaec48aSDavid du Colombier 
446*ccaec48aSDavid du Colombier static void
oprol(Cpu * cpu,Inst * i)447*ccaec48aSDavid du Colombier oprol(Cpu *cpu, Inst *i)
448*ccaec48aSDavid du Colombier {
449*ccaec48aSDavid du Colombier 	ulong *f, a, r;
450*ccaec48aSDavid du Colombier 	int s, n;
451*ccaec48aSDavid du Colombier 
452*ccaec48aSDavid du Colombier 	s = i->a1->len*8;
453*ccaec48aSDavid du Colombier 	n = ar(i->a2) & (s-1);
454*ccaec48aSDavid du Colombier 	a = ar(i->a1);
455*ccaec48aSDavid du Colombier 	r = (a<<n) | (a>>(s-n));
456*ccaec48aSDavid du Colombier 	f = cpu->reg + RFL;
457*ccaec48aSDavid du Colombier 	aw(i->a1, r);
458*ccaec48aSDavid du Colombier 	*f &= ~(CF|OF);
459*ccaec48aSDavid du Colombier 	if(r & 1)
460*ccaec48aSDavid du Colombier 		*f |= CF;
461*ccaec48aSDavid du Colombier 	if((a ^ r) & sign(s))
462*ccaec48aSDavid du Colombier 		*f |= OF;
463*ccaec48aSDavid du Colombier 	parity(f, r);
464*ccaec48aSDavid du Colombier }
465*ccaec48aSDavid du Colombier 
466*ccaec48aSDavid du Colombier static void
opror(Cpu * cpu,Inst * i)467*ccaec48aSDavid du Colombier opror(Cpu *cpu, Inst *i)
468*ccaec48aSDavid du Colombier {
469*ccaec48aSDavid du Colombier 	ulong *f, a, r;
470*ccaec48aSDavid du Colombier 	int s, n;
471*ccaec48aSDavid du Colombier 
472*ccaec48aSDavid du Colombier 	s = i->a1->len*8;
473*ccaec48aSDavid du Colombier 	n = ar(i->a2) & (s-1);
474*ccaec48aSDavid du Colombier 	a = ar(i->a1);
475*ccaec48aSDavid du Colombier 	r = (a>>n) | (a<<(s-n));
476*ccaec48aSDavid du Colombier 	aw(i->a1, r);
477*ccaec48aSDavid du Colombier 	f = cpu->reg + RFL;
478*ccaec48aSDavid du Colombier 	*f &= ~(CF|OF);
479*ccaec48aSDavid du Colombier 	if(r & sign(s))
480*ccaec48aSDavid du Colombier 		*f |= CF;
481*ccaec48aSDavid du Colombier 	if((a ^ r) & sign(s))
482*ccaec48aSDavid du Colombier 		*f |= OF;
483*ccaec48aSDavid du Colombier 	parity(f, r);
484*ccaec48aSDavid du Colombier }
485*ccaec48aSDavid du Colombier 
486*ccaec48aSDavid du Colombier static void
opbittest(Cpu * cpu,Inst * i)487*ccaec48aSDavid du Colombier opbittest(Cpu *cpu, Inst *i)
488*ccaec48aSDavid du Colombier {
489*ccaec48aSDavid du Colombier 	ulong a, m;
490*ccaec48aSDavid du Colombier 	int n, s;
491*ccaec48aSDavid du Colombier 	Iarg *x;
492*ccaec48aSDavid du Colombier 
493*ccaec48aSDavid du Colombier 	n = ar(i->a2);
494*ccaec48aSDavid du Colombier 	x = i->a1;
495*ccaec48aSDavid du Colombier 	s = x->len*8;
496*ccaec48aSDavid du Colombier 	if(x->tag == TMEM){
497*ccaec48aSDavid du Colombier 		x = adup(x);
498*ccaec48aSDavid du Colombier 		x->off += (n / s) * x->len;
499*ccaec48aSDavid du Colombier 		x->off &= mask(i->alen*8);
500*ccaec48aSDavid du Colombier 	}
501*ccaec48aSDavid du Colombier 	a = ar(x);
502*ccaec48aSDavid du Colombier 	n &= s-1;
503*ccaec48aSDavid du Colombier 	m = 1<<n;
504*ccaec48aSDavid du Colombier 	if(a & m)
505*ccaec48aSDavid du Colombier 		cpu->reg[RFL] |= CF;
506*ccaec48aSDavid du Colombier 	else
507*ccaec48aSDavid du Colombier 		cpu->reg[RFL] &= ~CF;
508*ccaec48aSDavid du Colombier 	switch(i->op){
509*ccaec48aSDavid du Colombier 	case OBT:
510*ccaec48aSDavid du Colombier 		break;
511*ccaec48aSDavid du Colombier 	case OBTS:
512*ccaec48aSDavid du Colombier 		aw(x, a | m);
513*ccaec48aSDavid du Colombier 		break;
514*ccaec48aSDavid du Colombier 	case OBTR:
515*ccaec48aSDavid du Colombier 		aw(x, a & ~m);
516*ccaec48aSDavid du Colombier 		break;
517*ccaec48aSDavid du Colombier 	case OBTC:
518*ccaec48aSDavid du Colombier 		aw(x, a ^ m);
519*ccaec48aSDavid du Colombier 		break;
520*ccaec48aSDavid du Colombier 	}
521*ccaec48aSDavid du Colombier }
522*ccaec48aSDavid du Colombier 
523*ccaec48aSDavid du Colombier static void
opbitscan(Cpu * cpu,Inst * i)524*ccaec48aSDavid du Colombier opbitscan(Cpu *cpu, Inst *i)
525*ccaec48aSDavid du Colombier {
526*ccaec48aSDavid du Colombier 	ulong a;
527*ccaec48aSDavid du Colombier 
528*ccaec48aSDavid du Colombier 	if((a = ar(i->a2)) == 0)
529*ccaec48aSDavid du Colombier 		cpu->reg[RFL] |= ZF;
530*ccaec48aSDavid du Colombier 	else {
531*ccaec48aSDavid du Colombier 		int j;
532*ccaec48aSDavid du Colombier 
533*ccaec48aSDavid du Colombier 		if(i->op == OBSF){
534*ccaec48aSDavid du Colombier 			for(j = 0; (a & (1<<j)) == 0; j++)
535*ccaec48aSDavid du Colombier 				;
536*ccaec48aSDavid du Colombier 		} else {
537*ccaec48aSDavid du Colombier 			for(j = i->a2->len*8-1; (a & (1<<j)) == 0; j--)
538*ccaec48aSDavid du Colombier 				;
539*ccaec48aSDavid du Colombier 		}
540*ccaec48aSDavid du Colombier 		aw(i->a1, j);
541*ccaec48aSDavid du Colombier 		cpu->reg[RFL] &= ~ZF;
542*ccaec48aSDavid du Colombier 	}
543*ccaec48aSDavid du Colombier }
544*ccaec48aSDavid du Colombier 
545*ccaec48aSDavid du Colombier static void
opand(Cpu * cpu,Inst * i)546*ccaec48aSDavid du Colombier opand(Cpu *cpu, Inst *i)
547*ccaec48aSDavid du Colombier {
548*ccaec48aSDavid du Colombier 	aw(i->a1, test(cpu->reg + RFL, ars(i->a1) & ars(i->a2), i->a1->len*8));
549*ccaec48aSDavid du Colombier }
550*ccaec48aSDavid du Colombier 
551*ccaec48aSDavid du Colombier static void
opor(Cpu * cpu,Inst * i)552*ccaec48aSDavid du Colombier opor(Cpu *cpu, Inst *i)
553*ccaec48aSDavid du Colombier {
554*ccaec48aSDavid du Colombier 	aw(i->a1, test(cpu->reg + RFL, ars(i->a1) | ars(i->a2), i->a1->len*8));
555*ccaec48aSDavid du Colombier }
556*ccaec48aSDavid du Colombier 
557*ccaec48aSDavid du Colombier static void
opxor(Cpu * cpu,Inst * i)558*ccaec48aSDavid du Colombier opxor(Cpu *cpu, Inst *i)
559*ccaec48aSDavid du Colombier {
560*ccaec48aSDavid du Colombier 	aw(i->a1, test(cpu->reg + RFL, ars(i->a1) ^ ars(i->a2), i->a1->len*8));
561*ccaec48aSDavid du Colombier }
562*ccaec48aSDavid du Colombier 
563*ccaec48aSDavid du Colombier static void
opnot(Cpu *,Inst * i)564*ccaec48aSDavid du Colombier opnot(Cpu *, Inst *i)
565*ccaec48aSDavid du Colombier {
566*ccaec48aSDavid du Colombier 	aw(i->a1, ~ar(i->a1));
567*ccaec48aSDavid du Colombier }
568*ccaec48aSDavid du Colombier 
569*ccaec48aSDavid du Colombier static void
optest(Cpu * cpu,Inst * i)570*ccaec48aSDavid du Colombier optest(Cpu *cpu, Inst *i)
571*ccaec48aSDavid du Colombier {
572*ccaec48aSDavid du Colombier 	test(cpu->reg + RFL, ars(i->a1) & ars(i->a2), i->a1->len*8);
573*ccaec48aSDavid du Colombier }
574*ccaec48aSDavid du Colombier 
575*ccaec48aSDavid du Colombier static ulong
add(ulong * f,long a,long b,int c,int s)576*ccaec48aSDavid du Colombier add(ulong *f, long a, long b, int c, int s)
577*ccaec48aSDavid du Colombier {
578*ccaec48aSDavid du Colombier 	ulong r, cc, m, n;
579*ccaec48aSDavid du Colombier 
580*ccaec48aSDavid du Colombier 	*f &= ~(AF|CF|SF|ZF|OF|PF);
581*ccaec48aSDavid du Colombier 
582*ccaec48aSDavid du Colombier 	n = sign(s);
583*ccaec48aSDavid du Colombier 	m = mask(s);
584*ccaec48aSDavid du Colombier 	r = a + b + c;
585*ccaec48aSDavid du Colombier 	r &= m;
586*ccaec48aSDavid du Colombier 	if(r == 0)
587*ccaec48aSDavid du Colombier 		*f |= ZF;
588*ccaec48aSDavid du Colombier 	if(r & n)
589*ccaec48aSDavid du Colombier 		*f |= SF;
590*ccaec48aSDavid du Colombier 	cc = (a & b) | (~r & (a | b));
591*ccaec48aSDavid du Colombier 	if(cc & n)
592*ccaec48aSDavid du Colombier 		*f |= CF;
593*ccaec48aSDavid du Colombier 	if((cc ^ (cc >> 1)) & (n>>1))
594*ccaec48aSDavid du Colombier 		*f |= OF;
595*ccaec48aSDavid du Colombier 	parity(f, r);
596*ccaec48aSDavid du Colombier 	return r;
597*ccaec48aSDavid du Colombier }
598*ccaec48aSDavid du Colombier 
599*ccaec48aSDavid du Colombier static ulong
sub(ulong * f,long a,long b,int c,int s)600*ccaec48aSDavid du Colombier sub(ulong *f, long a, long b, int c, int s)
601*ccaec48aSDavid du Colombier {
602*ccaec48aSDavid du Colombier 	ulong r, bc, n;
603*ccaec48aSDavid du Colombier 
604*ccaec48aSDavid du Colombier 	*f &= ~(AF|CF|SF|ZF|OF|PF);
605*ccaec48aSDavid du Colombier 
606*ccaec48aSDavid du Colombier 	r = a - b - c;
607*ccaec48aSDavid du Colombier 	n = sign(s);
608*ccaec48aSDavid du Colombier 	r &= mask(s);
609*ccaec48aSDavid du Colombier 	if(r == 0)
610*ccaec48aSDavid du Colombier 		*f |= ZF;
611*ccaec48aSDavid du Colombier 	if(r & n)
612*ccaec48aSDavid du Colombier 		*f |= SF;
613*ccaec48aSDavid du Colombier 	a = ~a;
614*ccaec48aSDavid du Colombier 	bc = (a & b) | (r & (a | b));
615*ccaec48aSDavid du Colombier 	if(bc & n)
616*ccaec48aSDavid du Colombier 		*f |= CF;
617*ccaec48aSDavid du Colombier 	if((bc ^ (bc >> 1)) & (n>>1))
618*ccaec48aSDavid du Colombier 		*f |= OF;
619*ccaec48aSDavid du Colombier 	parity(f, r);
620*ccaec48aSDavid du Colombier 	return r;
621*ccaec48aSDavid du Colombier }
622*ccaec48aSDavid du Colombier 
623*ccaec48aSDavid du Colombier static void
opadd(Cpu * cpu,Inst * i)624*ccaec48aSDavid du Colombier opadd(Cpu *cpu, Inst *i)
625*ccaec48aSDavid du Colombier {
626*ccaec48aSDavid du Colombier 	aw(i->a1, add(cpu->reg + RFL, ars(i->a1), ars(i->a2), 0, i->a1->len*8));
627*ccaec48aSDavid du Colombier }
628*ccaec48aSDavid du Colombier 
629*ccaec48aSDavid du Colombier static void
opadc(Cpu * cpu,Inst * i)630*ccaec48aSDavid du Colombier opadc(Cpu *cpu, Inst *i)
631*ccaec48aSDavid du Colombier {
632*ccaec48aSDavid du Colombier 	ulong *f = cpu->reg + RFL;
633*ccaec48aSDavid du Colombier 
634*ccaec48aSDavid du Colombier 	aw(i->a1, add(f, ars(i->a1), ars(i->a2), (*f & CF) != 0, i->a1->len*8));
635*ccaec48aSDavid du Colombier }
636*ccaec48aSDavid du Colombier 
637*ccaec48aSDavid du Colombier static void
opsub(Cpu * cpu,Inst * i)638*ccaec48aSDavid du Colombier opsub(Cpu *cpu, Inst *i)
639*ccaec48aSDavid du Colombier {
640*ccaec48aSDavid du Colombier 	aw(i->a1, sub(cpu->reg + RFL, ars(i->a1), ars(i->a2), 0, i->a1->len*8));
641*ccaec48aSDavid du Colombier }
642*ccaec48aSDavid du Colombier 
643*ccaec48aSDavid du Colombier static void
opsbb(Cpu * cpu,Inst * i)644*ccaec48aSDavid du Colombier opsbb(Cpu *cpu, Inst *i)
645*ccaec48aSDavid du Colombier {
646*ccaec48aSDavid du Colombier 	ulong *f = cpu->reg + RFL;
647*ccaec48aSDavid du Colombier 
648*ccaec48aSDavid du Colombier 	aw(i->a1, sub(f, ars(i->a1), ars(i->a2), (*f & CF) != 0, i->a1->len*8));
649*ccaec48aSDavid du Colombier }
650*ccaec48aSDavid du Colombier 
651*ccaec48aSDavid du Colombier static void
opneg(Cpu * cpu,Inst * i)652*ccaec48aSDavid du Colombier opneg(Cpu *cpu, Inst *i)
653*ccaec48aSDavid du Colombier {
654*ccaec48aSDavid du Colombier 	aw(i->a1, sub(cpu->reg + RFL, 0, ars(i->a1), 0, i->a1->len*8));
655*ccaec48aSDavid du Colombier }
656*ccaec48aSDavid du Colombier 
657*ccaec48aSDavid du Colombier static void
opcmp(Cpu * cpu,Inst * i)658*ccaec48aSDavid du Colombier opcmp(Cpu *cpu, Inst *i)
659*ccaec48aSDavid du Colombier {
660*ccaec48aSDavid du Colombier 	sub(cpu->reg + RFL, ars(i->a1), ars(i->a2), 0, i->a1->len*8);
661*ccaec48aSDavid du Colombier }
662*ccaec48aSDavid du Colombier 
663*ccaec48aSDavid du Colombier static void
opinc(Cpu * cpu,Inst * i)664*ccaec48aSDavid du Colombier opinc(Cpu *cpu, Inst *i)
665*ccaec48aSDavid du Colombier {
666*ccaec48aSDavid du Colombier 	ulong *f, o;
667*ccaec48aSDavid du Colombier 
668*ccaec48aSDavid du Colombier 	f = cpu->reg + RFL;
669*ccaec48aSDavid du Colombier 	o = *f;
670*ccaec48aSDavid du Colombier 	aw(i->a1, add(f, ars(i->a1), 1, 0, i->a1->len*8));
671*ccaec48aSDavid du Colombier 	*f = (*f & ~CF) | (o & CF);
672*ccaec48aSDavid du Colombier }
673*ccaec48aSDavid du Colombier 
674*ccaec48aSDavid du Colombier static void
opdec(Cpu * cpu,Inst * i)675*ccaec48aSDavid du Colombier opdec(Cpu *cpu, Inst *i)
676*ccaec48aSDavid du Colombier {
677*ccaec48aSDavid du Colombier 	ulong *f, o;
678*ccaec48aSDavid du Colombier 
679*ccaec48aSDavid du Colombier 	f = cpu->reg + RFL;
680*ccaec48aSDavid du Colombier 	o = *f;
681*ccaec48aSDavid du Colombier 	aw(i->a1, sub(f, ars(i->a1), 1, 0, i->a1->len*8));
682*ccaec48aSDavid du Colombier 	*f = (*f & ~CF) | (o & CF);
683*ccaec48aSDavid du Colombier }
684*ccaec48aSDavid du Colombier 
685*ccaec48aSDavid du Colombier static void
opmul(Cpu * cpu,Inst * i)686*ccaec48aSDavid du Colombier opmul(Cpu *cpu, Inst *i)
687*ccaec48aSDavid du Colombier {
688*ccaec48aSDavid du Colombier 	Iarg *la, *ha;
689*ccaec48aSDavid du Colombier 	ulong l, h, m;
690*ccaec48aSDavid du Colombier 	uvlong r;
691*ccaec48aSDavid du Colombier 	int s;
692*ccaec48aSDavid du Colombier 
693*ccaec48aSDavid du Colombier 	s = i->a2->len*8;
694*ccaec48aSDavid du Colombier 	m = mask(s);
695*ccaec48aSDavid du Colombier 	r = ar(i->a2) * ar(i->a3);
696*ccaec48aSDavid du Colombier 	l = r & m;
697*ccaec48aSDavid du Colombier 	h = (r >> s) & m;
698*ccaec48aSDavid du Colombier 	if(i->a1->atype != AAX)
699*ccaec48aSDavid du Colombier 		abort();
700*ccaec48aSDavid du Colombier 	la = areg(cpu, i->a2->len, RAX);
701*ccaec48aSDavid du Colombier 	if(s == 8){
702*ccaec48aSDavid du Colombier 		ha = adup(la);
703*ccaec48aSDavid du Colombier 		ha->tag |= TH;
704*ccaec48aSDavid du Colombier 	} else
705*ccaec48aSDavid du Colombier 		ha = areg(cpu, i->a2->len, RDX);
706*ccaec48aSDavid du Colombier 	aw(la, l);
707*ccaec48aSDavid du Colombier 	aw(ha, h);
708*ccaec48aSDavid du Colombier 	if(h)
709*ccaec48aSDavid du Colombier 		cpu->reg[RFL] |= (CF|OF);
710*ccaec48aSDavid du Colombier 	else
711*ccaec48aSDavid du Colombier 		cpu->reg[RFL] &= ~(CF|OF);
712*ccaec48aSDavid du Colombier }
713*ccaec48aSDavid du Colombier 
714*ccaec48aSDavid du Colombier static void
opimul(Cpu * cpu,Inst * i)715*ccaec48aSDavid du Colombier opimul(Cpu *cpu, Inst *i)
716*ccaec48aSDavid du Colombier {
717*ccaec48aSDavid du Colombier 	ulong l, h, m, n;
718*ccaec48aSDavid du Colombier 	vlong r;
719*ccaec48aSDavid du Colombier 	int s;
720*ccaec48aSDavid du Colombier 
721*ccaec48aSDavid du Colombier 	s = i->a2->len*8;
722*ccaec48aSDavid du Colombier 	m = mask(s);
723*ccaec48aSDavid du Colombier 	n = sign(s);
724*ccaec48aSDavid du Colombier 	r = ars(i->a2) * ars(i->a3);
725*ccaec48aSDavid du Colombier 	h = (r >> s) & m;
726*ccaec48aSDavid du Colombier 	l = r & m;
727*ccaec48aSDavid du Colombier 	if(i->a1->atype == AAX){
728*ccaec48aSDavid du Colombier 		Iarg *la, *ha;
729*ccaec48aSDavid du Colombier 
730*ccaec48aSDavid du Colombier 		la = areg(cpu, i->a2->len, RAX);
731*ccaec48aSDavid du Colombier 		if(s == 8){
732*ccaec48aSDavid du Colombier 			ha = adup(la);
733*ccaec48aSDavid du Colombier 			ha->tag |= TH;
734*ccaec48aSDavid du Colombier 		}else
735*ccaec48aSDavid du Colombier 			ha = areg(cpu, i->a2->len, RDX);
736*ccaec48aSDavid du Colombier 		aw(la, l);
737*ccaec48aSDavid du Colombier 		aw(ha, h);
738*ccaec48aSDavid du Colombier 	} else
739*ccaec48aSDavid du Colombier 		aw(i->a1, l);
740*ccaec48aSDavid du Colombier 	if((r > (vlong)n-1) || (r < -(vlong)n))
741*ccaec48aSDavid du Colombier 		cpu->reg[RFL] |= (CF|OF);
742*ccaec48aSDavid du Colombier 	else
743*ccaec48aSDavid du Colombier 		cpu->reg[RFL] &= ~(CF|OF);
744*ccaec48aSDavid du Colombier }
745*ccaec48aSDavid du Colombier 
746*ccaec48aSDavid du Colombier static void
opdiv(Cpu * cpu,Inst * i)747*ccaec48aSDavid du Colombier opdiv(Cpu *cpu, Inst *i)
748*ccaec48aSDavid du Colombier {
749*ccaec48aSDavid du Colombier 	Iarg *qa, *ra;
750*ccaec48aSDavid du Colombier 	uvlong n, q;
751*ccaec48aSDavid du Colombier 	ulong m, r, d;
752*ccaec48aSDavid du Colombier 	int s;
753*ccaec48aSDavid du Colombier 
754*ccaec48aSDavid du Colombier 	s = i->a1->len*8;
755*ccaec48aSDavid du Colombier 	m = mask(s);
756*ccaec48aSDavid du Colombier 	d = ar(i->a1);
757*ccaec48aSDavid du Colombier 	if(d == 0)
758*ccaec48aSDavid du Colombier 		trap(cpu, EDIV0);
759*ccaec48aSDavid du Colombier 	if(s == 8){
760*ccaec48aSDavid du Colombier 		qa = areg(cpu, 1, RAX);
761*ccaec48aSDavid du Colombier 		ra = adup(qa);
762*ccaec48aSDavid du Colombier 		ra->tag |= TH;
763*ccaec48aSDavid du Colombier 	} else {
764*ccaec48aSDavid du Colombier 		qa = areg(cpu, i->olen, RAX);
765*ccaec48aSDavid du Colombier 		ra = areg(cpu, i->olen, RDX);
766*ccaec48aSDavid du Colombier 	}
767*ccaec48aSDavid du Colombier 	n = (uvlong)ar(ra)<<s | (uvlong)ar(qa);
768*ccaec48aSDavid du Colombier 	q = n/d;
769*ccaec48aSDavid du Colombier 	if(q > m)
770*ccaec48aSDavid du Colombier 		trap(cpu, EDIV0);
771*ccaec48aSDavid du Colombier 	r = n%d;
772*ccaec48aSDavid du Colombier 	aw(ra, r);
773*ccaec48aSDavid du Colombier 	aw(qa, q);
774*ccaec48aSDavid du Colombier }
775*ccaec48aSDavid du Colombier 
776*ccaec48aSDavid du Colombier static void
opidiv(Cpu * cpu,Inst * i)777*ccaec48aSDavid du Colombier opidiv(Cpu *cpu, Inst *i)
778*ccaec48aSDavid du Colombier {
779*ccaec48aSDavid du Colombier 	Iarg *qa, *ra;
780*ccaec48aSDavid du Colombier 	vlong n, q, min, max;
781*ccaec48aSDavid du Colombier 	long r, d;
782*ccaec48aSDavid du Colombier 	int s;
783*ccaec48aSDavid du Colombier 
784*ccaec48aSDavid du Colombier 	s = i->a1->len*8;
785*ccaec48aSDavid du Colombier 	d = ars(i->a1);
786*ccaec48aSDavid du Colombier 	if(d == 0)
787*ccaec48aSDavid du Colombier 		trap(cpu, EDIV0);
788*ccaec48aSDavid du Colombier 	if(s == 8){
789*ccaec48aSDavid du Colombier 		qa = areg(cpu, 1, RAX);
790*ccaec48aSDavid du Colombier 		ra = adup(qa);
791*ccaec48aSDavid du Colombier 		ra->tag |= TH;
792*ccaec48aSDavid du Colombier 	} else {
793*ccaec48aSDavid du Colombier 		qa = areg(cpu, i->olen, RAX);
794*ccaec48aSDavid du Colombier 		ra = areg(cpu, i->olen, RDX);
795*ccaec48aSDavid du Colombier 	}
796*ccaec48aSDavid du Colombier 	n = (vlong)ars(ra)<<s | (uvlong)ars(qa);
797*ccaec48aSDavid du Colombier 	q = n/d;
798*ccaec48aSDavid du Colombier 	r = n%d;
799*ccaec48aSDavid du Colombier 
800*ccaec48aSDavid du Colombier 	max = sign(s)-1;
801*ccaec48aSDavid du Colombier 	min = ~max;
802*ccaec48aSDavid du Colombier 
803*ccaec48aSDavid du Colombier 	if(q > max || q < min)
804*ccaec48aSDavid du Colombier 		trap(cpu, EDIV0);
805*ccaec48aSDavid du Colombier 
806*ccaec48aSDavid du Colombier 	aw(ra, r);
807*ccaec48aSDavid du Colombier 	aw(qa, q);
808*ccaec48aSDavid du Colombier }
809*ccaec48aSDavid du Colombier 
810*ccaec48aSDavid du Colombier static int
cctrue(Cpu * cpu,Inst * i)811*ccaec48aSDavid du Colombier cctrue(Cpu *cpu, Inst *i)
812*ccaec48aSDavid du Colombier {
813*ccaec48aSDavid du Colombier 	enum { SO = 1<<16,	/* pseudo-flag SF != OF */ };
814*ccaec48aSDavid du Colombier 	static ulong test[] = {
815*ccaec48aSDavid du Colombier 		OF,	/* JO, JNO */
816*ccaec48aSDavid du Colombier 		CF,	/* JC, JNC */
817*ccaec48aSDavid du Colombier 		ZF,	/* JZ, JNZ */
818*ccaec48aSDavid du Colombier 		CF|ZF,	/* JBE,JA  */
819*ccaec48aSDavid du Colombier 		SF,	/* JS, JNS */
820*ccaec48aSDavid du Colombier 		PF,	/* JP, JNP */
821*ccaec48aSDavid du Colombier 		SO,	/* JL, JGE */
822*ccaec48aSDavid du Colombier 		SO|ZF,	/* JLE,JG  */
823*ccaec48aSDavid du Colombier 	};
824*ccaec48aSDavid du Colombier 	ulong f, t;
825*ccaec48aSDavid du Colombier 	uchar c;
826*ccaec48aSDavid du Colombier 
827*ccaec48aSDavid du Colombier 	c = i->code;
828*ccaec48aSDavid du Colombier 	switch(c){
829*ccaec48aSDavid du Colombier 	case 0xE3:	/* JCXZ */
830*ccaec48aSDavid du Colombier 		return ar(areg(cpu, i->alen, RCX)) == 0;
831*ccaec48aSDavid du Colombier 	case 0xEB:	/* JMP */
832*ccaec48aSDavid du Colombier 	case 0xE9:
833*ccaec48aSDavid du Colombier 	case 0xEA:
834*ccaec48aSDavid du Colombier 	case 0xFF:
835*ccaec48aSDavid du Colombier 		return 1;
836*ccaec48aSDavid du Colombier 	default:
837*ccaec48aSDavid du Colombier 		f = cpu->reg[RFL];
838*ccaec48aSDavid du Colombier 		if(((f&SF)!=0) ^ ((f&OF)!=0))
839*ccaec48aSDavid du Colombier 			f |= SO;
840*ccaec48aSDavid du Colombier 		t = test[(c>>1)&7];
841*ccaec48aSDavid du Colombier 		return ((t&f) != 0) ^ (c&1);
842*ccaec48aSDavid du Colombier 	}
843*ccaec48aSDavid du Colombier }
844*ccaec48aSDavid du Colombier 
845*ccaec48aSDavid du Colombier static void
opjump(Cpu * cpu,Inst * i)846*ccaec48aSDavid du Colombier opjump(Cpu *cpu, Inst *i)
847*ccaec48aSDavid du Colombier {
848*ccaec48aSDavid du Colombier 	if(cctrue(cpu, i))
849*ccaec48aSDavid du Colombier 		jump(i->a1);
850*ccaec48aSDavid du Colombier }
851*ccaec48aSDavid du Colombier 
852*ccaec48aSDavid du Colombier static void
opset(Cpu * cpu,Inst * i)853*ccaec48aSDavid du Colombier opset(Cpu *cpu, Inst *i)
854*ccaec48aSDavid du Colombier {
855*ccaec48aSDavid du Colombier 	aw(i->a1, cctrue(cpu, i));
856*ccaec48aSDavid du Colombier }
857*ccaec48aSDavid du Colombier 
858*ccaec48aSDavid du Colombier static void
oploop(Cpu * cpu,Inst * i)859*ccaec48aSDavid du Colombier oploop(Cpu *cpu, Inst *i)
860*ccaec48aSDavid du Colombier {
861*ccaec48aSDavid du Colombier 	Iarg *cx;
862*ccaec48aSDavid du Colombier 	ulong c;
863*ccaec48aSDavid du Colombier 
864*ccaec48aSDavid du Colombier 	switch(i->op){
865*ccaec48aSDavid du Colombier 	default:
866*ccaec48aSDavid du Colombier 		abort();
867*ccaec48aSDavid du Colombier 	case OLOOPNZ:
868*ccaec48aSDavid du Colombier 		if(cpu->reg[RFL] & ZF)
869*ccaec48aSDavid du Colombier 			return;
870*ccaec48aSDavid du Colombier 		break;
871*ccaec48aSDavid du Colombier 	case OLOOPZ:
872*ccaec48aSDavid du Colombier 		if((cpu->reg[RFL] & ZF) == 0)
873*ccaec48aSDavid du Colombier 			return;
874*ccaec48aSDavid du Colombier 		break;
875*ccaec48aSDavid du Colombier 	case OLOOP:
876*ccaec48aSDavid du Colombier 		break;
877*ccaec48aSDavid du Colombier 	}
878*ccaec48aSDavid du Colombier 	cx = areg(cpu, i->alen, RCX);
879*ccaec48aSDavid du Colombier 	c = ar(cx) - 1;
880*ccaec48aSDavid du Colombier 	aw(cx, c);
881*ccaec48aSDavid du Colombier 	if(c)
882*ccaec48aSDavid du Colombier 		jump(i->a1);
883*ccaec48aSDavid du Colombier }
884*ccaec48aSDavid du Colombier 
885*ccaec48aSDavid du Colombier static void
oplea(Cpu *,Inst * i)886*ccaec48aSDavid du Colombier oplea(Cpu *, Inst *i)
887*ccaec48aSDavid du Colombier {
888*ccaec48aSDavid du Colombier 	aw(i->a1, i->a2->off);
889*ccaec48aSDavid du Colombier }
890*ccaec48aSDavid du Colombier 
891*ccaec48aSDavid du Colombier static void
opmov(Cpu *,Inst * i)892*ccaec48aSDavid du Colombier opmov(Cpu *, Inst *i)
893*ccaec48aSDavid du Colombier {
894*ccaec48aSDavid du Colombier 	aw(i->a1, ar(i->a2));
895*ccaec48aSDavid du Colombier }
896*ccaec48aSDavid du Colombier 
897*ccaec48aSDavid du Colombier static void
opcbw(Cpu * cpu,Inst * i)898*ccaec48aSDavid du Colombier opcbw(Cpu *cpu, Inst *i)
899*ccaec48aSDavid du Colombier {
900*ccaec48aSDavid du Colombier 	aw(areg(cpu, i->olen, RAX), ars(areg(cpu, i->olen>>1, RAX)));
901*ccaec48aSDavid du Colombier }
902*ccaec48aSDavid du Colombier 
903*ccaec48aSDavid du Colombier static void
opcwd(Cpu * cpu,Inst * i)904*ccaec48aSDavid du Colombier opcwd(Cpu *cpu, Inst *i)
905*ccaec48aSDavid du Colombier {
906*ccaec48aSDavid du Colombier 	aw(areg(cpu, i->olen, RDX), ars(areg(cpu, i->olen, RAX))>>(i->olen*8-1));
907*ccaec48aSDavid du Colombier }
908*ccaec48aSDavid du Colombier 
909*ccaec48aSDavid du Colombier static void
opmovsx(Cpu *,Inst * i)910*ccaec48aSDavid du Colombier opmovsx(Cpu *, Inst *i)
911*ccaec48aSDavid du Colombier {
912*ccaec48aSDavid du Colombier 	aw(i->a1, ars(i->a2));
913*ccaec48aSDavid du Colombier }
914*ccaec48aSDavid du Colombier 
915*ccaec48aSDavid du Colombier static void
opxchg(Cpu *,Inst * i)916*ccaec48aSDavid du Colombier opxchg(Cpu *, Inst *i)
917*ccaec48aSDavid du Colombier {
918*ccaec48aSDavid du Colombier 	ulong x;
919*ccaec48aSDavid du Colombier 
920*ccaec48aSDavid du Colombier 	x = ar(i->a1);
921*ccaec48aSDavid du Colombier 	aw(i->a1, ar(i->a2));
922*ccaec48aSDavid du Colombier 	aw(i->a2, x);
923*ccaec48aSDavid du Colombier }
924*ccaec48aSDavid du Colombier 
925*ccaec48aSDavid du Colombier static void
oplfp(Cpu *,Inst * i)926*ccaec48aSDavid du Colombier oplfp(Cpu *, Inst *i)
927*ccaec48aSDavid du Colombier {
928*ccaec48aSDavid du Colombier 	Iarg *p;
929*ccaec48aSDavid du Colombier 
930*ccaec48aSDavid du Colombier 	p = afar(i->a3, i->olen, i->olen);
931*ccaec48aSDavid du Colombier 	aw(i->a1, p->seg);
932*ccaec48aSDavid du Colombier 	aw(i->a2, p->off);
933*ccaec48aSDavid du Colombier }
934*ccaec48aSDavid du Colombier 
935*ccaec48aSDavid du Colombier static void
opbound(Cpu * cpu,Inst * i)936*ccaec48aSDavid du Colombier opbound(Cpu *cpu, Inst *i)
937*ccaec48aSDavid du Colombier {
938*ccaec48aSDavid du Colombier 	ulong p, s, e;
939*ccaec48aSDavid du Colombier 
940*ccaec48aSDavid du Colombier 	p = ar(i->a1);
941*ccaec48aSDavid du Colombier 	s = ar(i->a2);
942*ccaec48aSDavid du Colombier 	e = ar(i->a3);
943*ccaec48aSDavid du Colombier 	if((p < s) || (p >= e))
944*ccaec48aSDavid du Colombier 		trap(cpu, EBOUND);
945*ccaec48aSDavid du Colombier }
946*ccaec48aSDavid du Colombier 
947*ccaec48aSDavid du Colombier static void
opxlat(Cpu * cpu,Inst * i)948*ccaec48aSDavid du Colombier opxlat(Cpu *cpu, Inst *i)
949*ccaec48aSDavid du Colombier {
950*ccaec48aSDavid du Colombier 	aw(i->a1, ar(amem(cpu, i->a1->len, i->sreg, ar(areg(cpu, i->alen, i->a2->reg)) + ar(i->a1))));
951*ccaec48aSDavid du Colombier }
952*ccaec48aSDavid du Colombier 
953*ccaec48aSDavid du Colombier static void
opcpuid(Cpu * cpu,Inst *)954*ccaec48aSDavid du Colombier opcpuid(Cpu *cpu, Inst *)
955*ccaec48aSDavid du Colombier {
956*ccaec48aSDavid du Colombier 	static struct {
957*ccaec48aSDavid du Colombier 		ulong level;
958*ccaec48aSDavid du Colombier 
959*ccaec48aSDavid du Colombier 		ulong ax;
960*ccaec48aSDavid du Colombier 		ulong bx;
961*ccaec48aSDavid du Colombier 		ulong cx;
962*ccaec48aSDavid du Colombier 		ulong dx;
963*ccaec48aSDavid du Colombier 	} tab[] = {
964*ccaec48aSDavid du Colombier 		0,
965*ccaec48aSDavid du Colombier 			5,
966*ccaec48aSDavid du Colombier 			0x756e6547, /* Genu */
967*ccaec48aSDavid du Colombier 			0x6c65746e, /* ntel */
968*ccaec48aSDavid du Colombier 			0x49656e69, /* ineI */
969*ccaec48aSDavid du Colombier 		1,
970*ccaec48aSDavid du Colombier 			4<<8,
971*ccaec48aSDavid du Colombier 			0x00000000,
972*ccaec48aSDavid du Colombier 			0x00000000,
973*ccaec48aSDavid du Colombier 			0x00000000,
974*ccaec48aSDavid du Colombier 		2,
975*ccaec48aSDavid du Colombier 			0x00000000,
976*ccaec48aSDavid du Colombier 			0x00000000,
977*ccaec48aSDavid du Colombier 			0x00000000,
978*ccaec48aSDavid du Colombier 			0x00000000,
979*ccaec48aSDavid du Colombier 		3,
980*ccaec48aSDavid du Colombier 			0x00000000,
981*ccaec48aSDavid du Colombier 			0x00000000,
982*ccaec48aSDavid du Colombier 			0x00000000,
983*ccaec48aSDavid du Colombier 			0x00000000,
984*ccaec48aSDavid du Colombier 	};
985*ccaec48aSDavid du Colombier 
986*ccaec48aSDavid du Colombier 	int i;
987*ccaec48aSDavid du Colombier 
988*ccaec48aSDavid du Colombier 	for(i=0; i<nelem(tab); i++){
989*ccaec48aSDavid du Colombier 		if(tab[i].level == cpu->reg[RAX]){
990*ccaec48aSDavid du Colombier 			cpu->reg[RAX] = tab[i].ax;
991*ccaec48aSDavid du Colombier 			cpu->reg[RBX] = tab[i].bx;
992*ccaec48aSDavid du Colombier 			cpu->reg[RCX] = tab[i].cx;
993*ccaec48aSDavid du Colombier 			cpu->reg[RDX] = tab[i].dx;
994*ccaec48aSDavid du Colombier 			return;
995*ccaec48aSDavid du Colombier 		}
996*ccaec48aSDavid du Colombier 	}
997*ccaec48aSDavid du Colombier 	trap(cpu, EBADOP);
998*ccaec48aSDavid du Colombier }
999*ccaec48aSDavid du Colombier 
1000*ccaec48aSDavid du Colombier static void
opmovs(Cpu * cpu,Inst * i)1001*ccaec48aSDavid du Colombier opmovs(Cpu *cpu, Inst *i)
1002*ccaec48aSDavid du Colombier {
1003*ccaec48aSDavid du Colombier 	Iarg *cx, *d, *s;
1004*ccaec48aSDavid du Colombier 	ulong c, m;
1005*ccaec48aSDavid du Colombier 	int n;
1006*ccaec48aSDavid du Colombier 
1007*ccaec48aSDavid du Colombier 	m = mask(i->alen*8);
1008*ccaec48aSDavid du Colombier 	d = adup(i->a1);
1009*ccaec48aSDavid du Colombier 	s = adup(i->a2);
1010*ccaec48aSDavid du Colombier 	n = s->len;
1011*ccaec48aSDavid du Colombier 	if(cpu->reg[RFL] & DF)
1012*ccaec48aSDavid du Colombier 		n = -n;
1013*ccaec48aSDavid du Colombier 	if(i->rep){
1014*ccaec48aSDavid du Colombier 		cx = areg(cpu, i->alen, RCX);
1015*ccaec48aSDavid du Colombier 		c = ar(cx);
1016*ccaec48aSDavid du Colombier 	} else {
1017*ccaec48aSDavid du Colombier 		cx = nil;
1018*ccaec48aSDavid du Colombier 		c = 1;
1019*ccaec48aSDavid du Colombier 	}
1020*ccaec48aSDavid du Colombier 	while(c){
1021*ccaec48aSDavid du Colombier 		aw(d, ar(s));
1022*ccaec48aSDavid du Colombier 		d->off += n;
1023*ccaec48aSDavid du Colombier 		d->off &= m;
1024*ccaec48aSDavid du Colombier 		s->off += n;
1025*ccaec48aSDavid du Colombier 		s->off &= m;
1026*ccaec48aSDavid du Colombier 		c--;
1027*ccaec48aSDavid du Colombier 	}
1028*ccaec48aSDavid du Colombier 	aw(areg(cpu, i->alen, RDI), d->off);
1029*ccaec48aSDavid du Colombier 	aw(areg(cpu, i->alen, RSI), s->off);
1030*ccaec48aSDavid du Colombier 	if(cx)
1031*ccaec48aSDavid du Colombier 		aw(cx, 0);
1032*ccaec48aSDavid du Colombier }
1033*ccaec48aSDavid du Colombier 
1034*ccaec48aSDavid du Colombier static void
oplods(Cpu * cpu,Inst * i)1035*ccaec48aSDavid du Colombier oplods(Cpu *cpu, Inst *i)
1036*ccaec48aSDavid du Colombier {
1037*ccaec48aSDavid du Colombier 	Iarg *cx, *s;
1038*ccaec48aSDavid du Colombier 	ulong c, m;
1039*ccaec48aSDavid du Colombier 	int n;
1040*ccaec48aSDavid du Colombier 
1041*ccaec48aSDavid du Colombier 	m = mask(i->alen*8);
1042*ccaec48aSDavid du Colombier 	s = adup(i->a2);
1043*ccaec48aSDavid du Colombier 	n = s->len;
1044*ccaec48aSDavid du Colombier 	if(cpu->reg[RFL] & DF)
1045*ccaec48aSDavid du Colombier 		n = -n;
1046*ccaec48aSDavid du Colombier 	if(i->rep){
1047*ccaec48aSDavid du Colombier 		cx = areg(cpu, i->alen, RCX);
1048*ccaec48aSDavid du Colombier 		c = ar(cx);
1049*ccaec48aSDavid du Colombier 	} else {
1050*ccaec48aSDavid du Colombier 		cx = nil;
1051*ccaec48aSDavid du Colombier 		c = 1;
1052*ccaec48aSDavid du Colombier 	}
1053*ccaec48aSDavid du Colombier 	if(c){
1054*ccaec48aSDavid du Colombier 		s->off += n*(c-1);
1055*ccaec48aSDavid du Colombier 		s->off &= m;
1056*ccaec48aSDavid du Colombier 		aw(i->a1, ar(s));
1057*ccaec48aSDavid du Colombier 		s->off += n;
1058*ccaec48aSDavid du Colombier 		s->off &= m;
1059*ccaec48aSDavid du Colombier 	}
1060*ccaec48aSDavid du Colombier 	aw(areg(cpu, i->alen, RSI), s->off);
1061*ccaec48aSDavid du Colombier 	if(cx)
1062*ccaec48aSDavid du Colombier 		aw(cx, 0);
1063*ccaec48aSDavid du Colombier }
1064*ccaec48aSDavid du Colombier 
1065*ccaec48aSDavid du Colombier static void
opstos(Cpu * cpu,Inst * i)1066*ccaec48aSDavid du Colombier opstos(Cpu *cpu, Inst *i)
1067*ccaec48aSDavid du Colombier {
1068*ccaec48aSDavid du Colombier 	Iarg *cx, *d;
1069*ccaec48aSDavid du Colombier 	ulong c, a, m;
1070*ccaec48aSDavid du Colombier 	int n;
1071*ccaec48aSDavid du Colombier 
1072*ccaec48aSDavid du Colombier 	m = mask(i->alen*8);
1073*ccaec48aSDavid du Colombier 	d = adup(i->a1);
1074*ccaec48aSDavid du Colombier 	n = d->len;
1075*ccaec48aSDavid du Colombier 	if(cpu->reg[RFL] & DF)
1076*ccaec48aSDavid du Colombier 		n = -n;
1077*ccaec48aSDavid du Colombier 	if(i->rep){
1078*ccaec48aSDavid du Colombier 		cx = areg(cpu, i->alen, RCX);
1079*ccaec48aSDavid du Colombier 		c = ar(cx);
1080*ccaec48aSDavid du Colombier 	} else {
1081*ccaec48aSDavid du Colombier 		cx = nil;
1082*ccaec48aSDavid du Colombier 		c = 1;
1083*ccaec48aSDavid du Colombier 	}
1084*ccaec48aSDavid du Colombier 	a = ar(i->a2);
1085*ccaec48aSDavid du Colombier 	while(c){
1086*ccaec48aSDavid du Colombier 		aw(d, a);
1087*ccaec48aSDavid du Colombier 		d->off += n;
1088*ccaec48aSDavid du Colombier 		d->off &= m;
1089*ccaec48aSDavid du Colombier 		c--;
1090*ccaec48aSDavid du Colombier 	}
1091*ccaec48aSDavid du Colombier 	aw(areg(cpu, i->alen, RDI), d->off);
1092*ccaec48aSDavid du Colombier 	if(cx)
1093*ccaec48aSDavid du Colombier 		aw(cx, c);
1094*ccaec48aSDavid du Colombier }
1095*ccaec48aSDavid du Colombier 
1096*ccaec48aSDavid du Colombier static int
repcond(ulong * f,int rep)1097*ccaec48aSDavid du Colombier repcond(ulong *f, int rep)
1098*ccaec48aSDavid du Colombier {
1099*ccaec48aSDavid du Colombier 	if(rep == OREPNE)
1100*ccaec48aSDavid du Colombier 		return (*f & ZF) == 0;
1101*ccaec48aSDavid du Colombier 	return (*f & ZF) != 0;
1102*ccaec48aSDavid du Colombier }
1103*ccaec48aSDavid du Colombier 
1104*ccaec48aSDavid du Colombier static void
opscas(Cpu * cpu,Inst * i)1105*ccaec48aSDavid du Colombier opscas(Cpu *cpu, Inst *i)
1106*ccaec48aSDavid du Colombier {
1107*ccaec48aSDavid du Colombier 	Iarg *cx, *d;
1108*ccaec48aSDavid du Colombier 	ulong *f, c, m;
1109*ccaec48aSDavid du Colombier 	long a;
1110*ccaec48aSDavid du Colombier 	int n, z;
1111*ccaec48aSDavid du Colombier 
1112*ccaec48aSDavid du Colombier 	m = mask(i->alen*8);
1113*ccaec48aSDavid du Colombier 	d = adup(i->a1);
1114*ccaec48aSDavid du Colombier 	n = d->len;
1115*ccaec48aSDavid du Colombier 	z = n*8;
1116*ccaec48aSDavid du Colombier 	f = cpu->reg + RFL;
1117*ccaec48aSDavid du Colombier 	if(*f & DF)
1118*ccaec48aSDavid du Colombier 		n = -n;
1119*ccaec48aSDavid du Colombier 	if(i->rep){
1120*ccaec48aSDavid du Colombier 		cx = areg(cpu, i->alen, RCX);
1121*ccaec48aSDavid du Colombier 		c = ar(cx);
1122*ccaec48aSDavid du Colombier 	} else {
1123*ccaec48aSDavid du Colombier 		cx = nil;
1124*ccaec48aSDavid du Colombier 		c = 1;
1125*ccaec48aSDavid du Colombier 	}
1126*ccaec48aSDavid du Colombier 	a = ars(i->a2);
1127*ccaec48aSDavid du Colombier 	while(c){
1128*ccaec48aSDavid du Colombier 		sub(f, a, ars(d), 0, z);
1129*ccaec48aSDavid du Colombier 		d->off += n;
1130*ccaec48aSDavid du Colombier 		d->off &= m;
1131*ccaec48aSDavid du Colombier 		c--;
1132*ccaec48aSDavid du Colombier 		if(!repcond(f, i->rep))
1133*ccaec48aSDavid du Colombier 			break;
1134*ccaec48aSDavid du Colombier 	}
1135*ccaec48aSDavid du Colombier 	aw(areg(cpu, i->alen, RDI), d->off);
1136*ccaec48aSDavid du Colombier 	if(cx)
1137*ccaec48aSDavid du Colombier 		aw(cx, c);
1138*ccaec48aSDavid du Colombier }
1139*ccaec48aSDavid du Colombier 
1140*ccaec48aSDavid du Colombier static void
opcmps(Cpu * cpu,Inst * i)1141*ccaec48aSDavid du Colombier opcmps(Cpu *cpu, Inst *i)
1142*ccaec48aSDavid du Colombier {
1143*ccaec48aSDavid du Colombier 	Iarg *cx, *s, *d;
1144*ccaec48aSDavid du Colombier 	ulong *f, c, m;
1145*ccaec48aSDavid du Colombier 	int n, z;
1146*ccaec48aSDavid du Colombier 
1147*ccaec48aSDavid du Colombier 	m = mask(i->alen*8);
1148*ccaec48aSDavid du Colombier 	d = adup(i->a1);
1149*ccaec48aSDavid du Colombier 	s = adup(i->a2);
1150*ccaec48aSDavid du Colombier 	n = s->len;
1151*ccaec48aSDavid du Colombier 	z = n*8;
1152*ccaec48aSDavid du Colombier 	f = cpu->reg + RFL;
1153*ccaec48aSDavid du Colombier 	if(*f & DF)
1154*ccaec48aSDavid du Colombier 		n = -n;
1155*ccaec48aSDavid du Colombier 	if(i->rep){
1156*ccaec48aSDavid du Colombier 		cx = areg(cpu, i->alen, RCX);
1157*ccaec48aSDavid du Colombier 		c = ar(cx);
1158*ccaec48aSDavid du Colombier 	} else {
1159*ccaec48aSDavid du Colombier 		cx = nil;
1160*ccaec48aSDavid du Colombier 		c = 1;
1161*ccaec48aSDavid du Colombier 	}
1162*ccaec48aSDavid du Colombier 	while(c){
1163*ccaec48aSDavid du Colombier 		sub(f, ars(s), ars(d), 0, z);
1164*ccaec48aSDavid du Colombier 		s->off += n;
1165*ccaec48aSDavid du Colombier 		s->off &= m;
1166*ccaec48aSDavid du Colombier 		d->off += n;
1167*ccaec48aSDavid du Colombier 		d->off &= m;
1168*ccaec48aSDavid du Colombier 		c--;
1169*ccaec48aSDavid du Colombier 		if(!repcond(f, i->rep))
1170*ccaec48aSDavid du Colombier 			break;
1171*ccaec48aSDavid du Colombier 	}
1172*ccaec48aSDavid du Colombier 	aw(areg(cpu, i->alen, RDI), d->off);
1173*ccaec48aSDavid du Colombier 	aw(areg(cpu, i->alen, RSI), s->off);
1174*ccaec48aSDavid du Colombier 	if(cx)
1175*ccaec48aSDavid du Colombier 		aw(cx, c);
1176*ccaec48aSDavid du Colombier }
1177*ccaec48aSDavid du Colombier 
1178*ccaec48aSDavid du Colombier static void
opin(Cpu * cpu,Inst * i)1179*ccaec48aSDavid du Colombier opin(Cpu *cpu, Inst *i)
1180*ccaec48aSDavid du Colombier {
1181*ccaec48aSDavid du Colombier 	Bus *io;
1182*ccaec48aSDavid du Colombier 
1183*ccaec48aSDavid du Colombier 	io = cpu->port;
1184*ccaec48aSDavid du Colombier 	aw(i->a1, io->r(io->aux, ar(i->a2) & 0xFFFF, i->a1->len));
1185*ccaec48aSDavid du Colombier }
1186*ccaec48aSDavid du Colombier 
1187*ccaec48aSDavid du Colombier static void
opout(Cpu * cpu,Inst * i)1188*ccaec48aSDavid du Colombier opout(Cpu *cpu, Inst *i)
1189*ccaec48aSDavid du Colombier {
1190*ccaec48aSDavid du Colombier 	Bus *io;
1191*ccaec48aSDavid du Colombier 
1192*ccaec48aSDavid du Colombier 	io = cpu->port;
1193*ccaec48aSDavid du Colombier 	io->w(io->aux, ar(i->a1) & 0xFFFF, ar(i->a2), i->a2->len);
1194*ccaec48aSDavid du Colombier }
1195*ccaec48aSDavid du Colombier 
1196*ccaec48aSDavid du Colombier static void
opnop(Cpu *,Inst *)1197*ccaec48aSDavid du Colombier opnop(Cpu *, Inst *)
1198*ccaec48aSDavid du Colombier {
1199*ccaec48aSDavid du Colombier }
1200*ccaec48aSDavid du Colombier 
1201*ccaec48aSDavid du Colombier static void
ophlt(Cpu * cpu,Inst *)1202*ccaec48aSDavid du Colombier ophlt(Cpu *cpu, Inst *)
1203*ccaec48aSDavid du Colombier {
1204*ccaec48aSDavid du Colombier 	trap(cpu, EHALT);
1205*ccaec48aSDavid du Colombier }
1206*ccaec48aSDavid du Colombier 
1207*ccaec48aSDavid du Colombier static void (*exctab[NUMOP])(Cpu *cpu, Inst*) = {
1208*ccaec48aSDavid du Colombier 	[OINT] = opint,
1209*ccaec48aSDavid du Colombier 	[OIRET] = opiret,
1210*ccaec48aSDavid du Colombier 
1211*ccaec48aSDavid du Colombier 	[OCALL] = opcall,
1212*ccaec48aSDavid du Colombier 	[OJUMP] = opjump,
1213*ccaec48aSDavid du Colombier 	[OSET] = opset,
1214*ccaec48aSDavid du Colombier 
1215*ccaec48aSDavid du Colombier 	[OLOOP] = oploop,
1216*ccaec48aSDavid du Colombier 	[OLOOPZ] = oploop,
1217*ccaec48aSDavid du Colombier 	[OLOOPNZ] = oploop,
1218*ccaec48aSDavid du Colombier 
1219*ccaec48aSDavid du Colombier 	[ORET] = opret,
1220*ccaec48aSDavid du Colombier 	[ORETF] = opretf,
1221*ccaec48aSDavid du Colombier 
1222*ccaec48aSDavid du Colombier 	[OENTER] = openter,
1223*ccaec48aSDavid du Colombier 	[OLEAVE] = opleave,
1224*ccaec48aSDavid du Colombier 
1225*ccaec48aSDavid du Colombier 	[OPUSH] = oppush,
1226*ccaec48aSDavid du Colombier 	[OPOP] = oppop,
1227*ccaec48aSDavid du Colombier 
1228*ccaec48aSDavid du Colombier 	[OPUSHF] = oppushf,
1229*ccaec48aSDavid du Colombier 	[OPOPF] = oppopf,
1230*ccaec48aSDavid du Colombier 	[OLAHF] = oplahf,
1231*ccaec48aSDavid du Colombier 	[OSAHF] = opsahf,
1232*ccaec48aSDavid du Colombier 
1233*ccaec48aSDavid du Colombier 	[OPUSHA] = oppusha,
1234*ccaec48aSDavid du Colombier 	[OPOPA] = oppopa,
1235*ccaec48aSDavid du Colombier 
1236*ccaec48aSDavid du Colombier 	[OCLI] = opcli,
1237*ccaec48aSDavid du Colombier 	[OSTI] = opsti,
1238*ccaec48aSDavid du Colombier 	[OCLC] = opclc,
1239*ccaec48aSDavid du Colombier 	[OSTC] = opstc,
1240*ccaec48aSDavid du Colombier 	[OCMC] = opcmc,
1241*ccaec48aSDavid du Colombier 	[OCLD] = opcld,
1242*ccaec48aSDavid du Colombier 	[OSTD] = opstd,
1243*ccaec48aSDavid du Colombier 
1244*ccaec48aSDavid du Colombier 	[OSHL] = opshl,
1245*ccaec48aSDavid du Colombier 	[OSHR] = opshr,
1246*ccaec48aSDavid du Colombier 	[OSAR] = opsar,
1247*ccaec48aSDavid du Colombier 
1248*ccaec48aSDavid du Colombier 	[OSHLD] = opshld,
1249*ccaec48aSDavid du Colombier 	[OSHRD] = opshrd,
1250*ccaec48aSDavid du Colombier 
1251*ccaec48aSDavid du Colombier 	[ORCL] = oprcl,
1252*ccaec48aSDavid du Colombier 	[ORCR] = oprcr,
1253*ccaec48aSDavid du Colombier 	[OROL] = oprol,
1254*ccaec48aSDavid du Colombier 	[OROR] = opror,
1255*ccaec48aSDavid du Colombier 
1256*ccaec48aSDavid du Colombier 	[OBT] = opbittest,
1257*ccaec48aSDavid du Colombier 	[OBTS] = opbittest,
1258*ccaec48aSDavid du Colombier 	[OBTR] = opbittest,
1259*ccaec48aSDavid du Colombier 	[OBTC] = opbittest,
1260*ccaec48aSDavid du Colombier 
1261*ccaec48aSDavid du Colombier 	[OBSF] = opbitscan,
1262*ccaec48aSDavid du Colombier 	[OBSR] = opbitscan,
1263*ccaec48aSDavid du Colombier 
1264*ccaec48aSDavid du Colombier 	[OAND] = opand,
1265*ccaec48aSDavid du Colombier 	[OOR] = opor,
1266*ccaec48aSDavid du Colombier 	[OXOR] = opxor,
1267*ccaec48aSDavid du Colombier 	[ONOT] = opnot,
1268*ccaec48aSDavid du Colombier 	[OTEST] = optest,
1269*ccaec48aSDavid du Colombier 
1270*ccaec48aSDavid du Colombier 	[OADD] = opadd,
1271*ccaec48aSDavid du Colombier 	[OADC] = opadc,
1272*ccaec48aSDavid du Colombier 	[OSUB] = opsub,
1273*ccaec48aSDavid du Colombier 	[OSBB] = opsbb,
1274*ccaec48aSDavid du Colombier 	[ONEG] = opneg,
1275*ccaec48aSDavid du Colombier 	[OCMP] = opcmp,
1276*ccaec48aSDavid du Colombier 
1277*ccaec48aSDavid du Colombier 	[OINC] = opinc,
1278*ccaec48aSDavid du Colombier 	[ODEC] = opdec,
1279*ccaec48aSDavid du Colombier 
1280*ccaec48aSDavid du Colombier 	[OMUL] = opmul,
1281*ccaec48aSDavid du Colombier 	[OIMUL] = opimul,
1282*ccaec48aSDavid du Colombier 	[ODIV] = opdiv,
1283*ccaec48aSDavid du Colombier 	[OIDIV] = opidiv,
1284*ccaec48aSDavid du Colombier 
1285*ccaec48aSDavid du Colombier 	[OLEA] = oplea,
1286*ccaec48aSDavid du Colombier 	[OMOV] = opmov,
1287*ccaec48aSDavid du Colombier 	[OCBW] = opcbw,
1288*ccaec48aSDavid du Colombier 	[OCWD] = opcwd,
1289*ccaec48aSDavid du Colombier 	[OMOVZX] = opmov,
1290*ccaec48aSDavid du Colombier 	[OMOVSX] = opmovsx,
1291*ccaec48aSDavid du Colombier 	[OXCHG] = opxchg,
1292*ccaec48aSDavid du Colombier 	[OLFP] = oplfp,
1293*ccaec48aSDavid du Colombier 	[OBOUND] = opbound,
1294*ccaec48aSDavid du Colombier 	[OXLAT] = opxlat,
1295*ccaec48aSDavid du Colombier 
1296*ccaec48aSDavid du Colombier 	[OCPUID] = opcpuid,
1297*ccaec48aSDavid du Colombier 
1298*ccaec48aSDavid du Colombier 	[OMOVS] = opmovs,
1299*ccaec48aSDavid du Colombier 	[OLODS] = oplods,
1300*ccaec48aSDavid du Colombier 	[OSTOS] = opstos,
1301*ccaec48aSDavid du Colombier 	[OSCAS] = opscas,
1302*ccaec48aSDavid du Colombier 	[OCMPS] = opcmps,
1303*ccaec48aSDavid du Colombier 
1304*ccaec48aSDavid du Colombier 	[OIN] = opin,
1305*ccaec48aSDavid du Colombier 	[OOUT] = opout,
1306*ccaec48aSDavid du Colombier 
1307*ccaec48aSDavid du Colombier 	[ONOP] = opnop,
1308*ccaec48aSDavid du Colombier 	[OHLT] = ophlt,
1309*ccaec48aSDavid du Colombier };
1310*ccaec48aSDavid du Colombier 
1311*ccaec48aSDavid du Colombier void
trap(Cpu * cpu,int e)1312*ccaec48aSDavid du Colombier trap(Cpu *cpu, int e)
1313*ccaec48aSDavid du Colombier {
1314*ccaec48aSDavid du Colombier 	cpu->reg[RIP] = cpu->oldip;
1315*ccaec48aSDavid du Colombier 	cpu->trap = e;
1316*ccaec48aSDavid du Colombier 	longjmp(cpu->jmp, 1);
1317*ccaec48aSDavid du Colombier }
1318*ccaec48aSDavid du Colombier 
1319*ccaec48aSDavid du Colombier int
intr(Cpu * cpu,int v)1320*ccaec48aSDavid du Colombier intr(Cpu *cpu, int v)
1321*ccaec48aSDavid du Colombier {
1322*ccaec48aSDavid du Colombier 	Iarg *sp, *ip, *cs, *iv;
1323*ccaec48aSDavid du Colombier 
1324*ccaec48aSDavid du Colombier 	if(v < 0 || v > 0xff || cpu->olen != 2)
1325*ccaec48aSDavid du Colombier 		return -1;
1326*ccaec48aSDavid du Colombier 
1327*ccaec48aSDavid du Colombier 	sp = areg(cpu, cpu->slen, RSP);
1328*ccaec48aSDavid du Colombier 	cs = areg(cpu, 2, RCS);
1329*ccaec48aSDavid du Colombier 	ip = areg(cpu, 2, RIP);
1330*ccaec48aSDavid du Colombier 
1331*ccaec48aSDavid du Colombier 	iv = amem(cpu, 2, R0S, v * 4);
1332*ccaec48aSDavid du Colombier 
1333*ccaec48aSDavid du Colombier 	push(sp, areg(cpu, 2, RFL));
1334*ccaec48aSDavid du Colombier 	push(sp, cs);
1335*ccaec48aSDavid du Colombier 	push(sp, ip);
1336*ccaec48aSDavid du Colombier 
1337*ccaec48aSDavid du Colombier 	cpu->reg[RIP] = ar(iv);
1338*ccaec48aSDavid du Colombier 	iv->off += 2;
1339*ccaec48aSDavid du Colombier 	cpu->reg[RCS] = ar(iv);
1340*ccaec48aSDavid du Colombier 	return 0;
1341*ccaec48aSDavid du Colombier }
1342*ccaec48aSDavid du Colombier 
1343*ccaec48aSDavid du Colombier int
xec(Cpu * cpu,int n)1344*ccaec48aSDavid du Colombier xec(Cpu *cpu, int n)
1345*ccaec48aSDavid du Colombier {
1346*ccaec48aSDavid du Colombier 	if(setjmp(cpu->jmp))
1347*ccaec48aSDavid du Colombier 		return cpu->trap;
1348*ccaec48aSDavid du Colombier 	while(n--){
1349*ccaec48aSDavid du Colombier 		void (*f)(Cpu *, Inst *);
1350*ccaec48aSDavid du Colombier 		Iarg *ip;
1351*ccaec48aSDavid du Colombier 		Inst i;
1352*ccaec48aSDavid du Colombier 
1353*ccaec48aSDavid du Colombier 		cpu->ic++;
1354*ccaec48aSDavid du Colombier 
1355*ccaec48aSDavid du Colombier 		ip = amem(cpu, 1, RCS, cpu->oldip = cpu->reg[RIP]);
1356*ccaec48aSDavid du Colombier 		decode(ip, &i);
1357*ccaec48aSDavid du Colombier 		cpu->reg[RIP] = ip->off;
1358*ccaec48aSDavid du Colombier 		if((f = exctab[i.op]) == nil)
1359*ccaec48aSDavid du Colombier 			trap(cpu, EBADOP);
1360*ccaec48aSDavid du Colombier 		f(cpu, &i);
1361*ccaec48aSDavid du Colombier 	}
1362*ccaec48aSDavid du Colombier 	return n;
1363*ccaec48aSDavid du Colombier }
1364