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