Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <bio.h>
4
#include <mach.h>
5
#define Extern extern
6
#include "power.h"
7
 
8
void	add(ulong);
9
void	addc(ulong);
10
void	adde(ulong);
11
void	addme(ulong);
12
void	addze(ulong);
13
void	and(ulong);
14
void	andc(ulong);
15
void	cmp(ulong);
16
void	cmpl(ulong);
17
void	cntlzw(ulong);
18
void	dcbf(ulong);
19
void	dcbi(ulong);
20
void	dcbst(ulong);
21
void	dcbt(ulong);
22
void	dcbtst(ulong);
23
void	dcbz(ulong);
24
void	divw(ulong);
25
void	divwu(ulong);
26
void	eciwx(ulong);
27
void	ecowx(ulong);
28
void	eieio(ulong);
29
void	eqv(ulong);
30
void	extsb(ulong);
31
void	extsh(ulong);
32
void	icbi(ulong);
33
void	lbzx(ulong);
34
void	lfdx(ulong);
35
void	lfsx(ulong);
36
void	lhax(ulong);
37
void	lhbrx(ulong);
38
void	lhzx(ulong);
39
void	lswi(ulong);
40
void	lswx(ulong);
41
void	lwarx(ulong);
42
void	lwbrx(ulong);
43
void	lwzx(ulong);
44
void	mcrxr(ulong);
45
void	mfcr(ulong);
46
void	mfmsr(ulong);
47
void	mfpmr(ulong);
48
void	mfspr(ulong);
49
void	mfsr(ulong);
50
void	mfsrin(ulong);
51
void	mftb(ulong);
52
void	mftbu(ulong);
53
void	mspr(ulong);
54
void	mtcrf(ulong);
55
void	mtmsr(ulong);
56
void	mtpmr(ulong);
57
void	mtspr(ulong);
58
void	mtsr(ulong);
59
void	mtsrin(ulong);
60
void	mttb(ulong);
61
void	mttbu(ulong);
62
void	mulhw(ulong);
63
void	mulhwu(ulong);
64
void	mullw(ulong);
65
void	nand(ulong);
66
void	neg(ulong);
67
void	nor(ulong);
68
void	or(ulong);
69
void	orc(ulong);
70
void	slbia(ulong);
71
void	slbia(ulong);
72
void	slw(ulong);
73
void	sraw(ulong);
74
void	srawi(ulong);
75
void	srw(ulong);
76
void	stbx(ulong);
77
void	stfdx(ulong);
78
void	stfiwx(ulong);
79
void	stfsx(ulong);
80
void	sthbrx(ulong);
81
void	sthx(ulong);
82
void	stswi(ulong);
83
void	stswx(ulong);
84
void	stwbrx(ulong);
85
void	stwcx(ulong);
86
void	stwx(ulong);
87
void	subf(ulong);
88
void	subfc(ulong);
89
void	subfe(ulong);
90
void	subfme(ulong);
91
void	subfze(ulong);
92
void	sync(ulong);
93
void	tlbie(ulong);
94
void	tw(ulong);
95
void	xor(ulong);
96
 
97
Inst	op31[] = {
98
[0] {cmp, "cmp", Iarith},
99
[4] {tw, "tw", Iarith},
100
[8] {subfc, "subfc", Iarith},
101
[10] {addc, "addc", Iarith},
102
[11] {mulhwu, "mulhwu", Iarith},
103
[19] {mfcr, "mfcr", Iarith},
104
[20] {lwarx, "lwarx", Iload},
105
[23] {lwzx, "lwzx", Iload},
106
[24] {slw, "slw", Ilog},
107
[26] {cntlzw, "cntlzw", Ilog},
108
[28] {and, "and", Ilog},
109
[32] {cmpl, "cmpl", Iarith},
110
[40] {subf, "subf", Iarith},
111
[54] {dcbst, "dcbst", Icontrol},
112
[55] {lwzx, "lwzux", Iload},
113
[60] {andc, "andc", Ilog},
114
[75] {mulhw, "mulhw", Iarith},
115
[83] {0, "mfmsr", Icontrol},
116
[86] {dcbf, "dcbf", Icontrol},
117
[87] {lbzx, "lbzx", Iload},
118
[104] {neg, "neg", Iarith},
119
[115] {0, "mfpmr", Iarith},
120
[119] {lbzx, "lbzux", Iload},
121
[124] {nor, "nor", Iarith},
122
[136] {subfe, "subfe", Iarith},
123
[138] {adde, "adde", Iarith},
124
[144] {mtcrf, "mtcrf", Ireg},
125
[146] {0, "mtmsr", Icontrol},
126
[150] {stwcx, "stwcx.", Istore},
127
[151] {stwx, "stwx", Istore},
128
[178] {0, "mtpmr", Icontrol},
129
[183] {stwx, "stwux", Istore},
130
[200] {subfze, "subfze", Iarith},
131
[202] {addze, "addze", Iarith},
132
[210] {0, "mtsr", Ireg},
133
[215] {stbx, "stbx", Istore},
134
[232] {subfme, "subfme", Iarith},
135
[234] {addme, "addme", Iarith},
136
[235] {mullw, "mullw", Iarith},
137
[242] {0, "mtsrin", Ireg},
138
[246] {dcbtst, "dcbtst", Icontrol},
139
[247] {stbx, "stbux", Istore},
140
[266] {add, "add", Iarith},
141
[275] {0, "mftb", Icontrol},
142
[278] {dcbt, "dcbt", Icontrol},
143
[279] {lhzx, "lhzx", Iload},
144
[284] {eqv, "eqv", Ilog},
145
[306] {0, "tlbie", Icontrol},
146
[307] {0, "mftbu", Icontrol},
147
[310] {0, "eciwx", Icontrol},
148
[311] {lhzx, "lhzux", Iload},
149
[316] {xor, "xor", Ilog},
150
[339] {mspr, "mfspr", Ireg},
151
[343] {lhax, "lhax", Iload},
152
[375] {lhax, "lhaux", Iload},
153
[403] {0, "mttb", Icontrol},
154
[407] {sthx, "sthx", Istore},
155
[412] {orc, "orc", Ilog},
156
[434] {0, "slbia", Iarith},
157
[435] {0, "mttbu", Icontrol},
158
[438] {0, "ecowx", Icontrol},
159
[439] {sthx, "sthux", Istore},
160
[444] {or, "or", Ilog},
161
[459] {divwu, "divwu", Iarith},
162
[467] {mspr, "mtspr", Ireg},
163
[470] {0, "dcbi", Icontrol},
164
[476] {nand, "nand", Ilog},
165
[491] {divw, "divw", Iarith},
166
[498] {0, "slbia", Icontrol},
167
[512] {mcrxr, "mcrxr", Ireg},
168
[533] {lswx, "lswx", Iload},
169
[534] {lwbrx, "lwbrx", Iload},
170
[535] {lfsx, "lfsx", Ifloat},
171
[536] {srw, "srw", Ilog},
172
[567] {lfsx, "lfsux", Ifloat},
173
[595] {0, "mfsr", Iarith},
174
[597] {lswi, "lswi", Iarith},
175
[598] {sync, "sync", Iarith},
176
[599] {lfdx, "lfdx", Ifloat},
177
[631] {lfdx, "lfdux", Ifloat},
178
[659] {0, "mfsrin", Ireg},
179
[661] {stswx, "stswx", Istore},
180
[662] {stwbrx, "stwbrx", Istore},
181
[663] {stfsx, "stfsx", Istore},
182
[695] {stfsx, "stfsux", Istore},
183
[725] {stswi, "stswi", Istore},
184
[727] {stfdx, "stfdx", Istore},
185
[759] {stfdx, "stfdux", Istore},
186
[790] {lhbrx, "lhbrx", Iload},
187
[792] {sraw, "sraw", Ilog},
188
[824] {srawi, "srawi", Ilog},
189
[854] {0, "eieio", Icontrol},
190
[918] {sthbrx, "sthbrx", Istore},
191
[922] {extsh, "extsh", Iarith},
192
[954] {extsb, "extsb", Iarith},
193
[982] {icbi, "icbi", Icontrol},
194
[983] {unimp, "stfiwx", Istore},
195
[1014] {dcbz, "dcbz", Icontrol},
196
};
197
 
198
Inset	ops31 = {op31, nelem(op31)};
199
 
200
void
201
mspr(ulong ir)
202
{
203
	int rd, ra, rb;
204
	ulong *d;
205
	char *n;
206
	char buf[20];
207
 
208
	getarrr(ir);
209
	switch((rb<<5) | ra) {
210
	case 0:
211
		undef(ir);	/* was mq */
212
		return;
213
	case 1:
214
		d = &reg.xer; n = "xer";
215
		break;
216
	case 268:
217
	case 284:
218
		d = &reg.tbl; n = "tbl";
219
		break;
220
	case 269:
221
	case 285:
222
		d = &reg.tbu; n = "tbu";
223
		break;
224
	case 22:
225
		d = &reg.dec; n = "dec";
226
		break;
227
	case 8:
228
		d = &reg.lr; n = "lr";
229
		break;
230
	case 9:
231
		d = &reg.ctr; n = "ctr";
232
		break;
233
	default:
234
		d = 0; sprint(n = buf, "spr%d", rd);
235
		break;
236
	}
237
	if(getxo(ir) == 339) {
238
		if(trace)
239
			itrace("%s\tr%d,%s", ci->name, rd, n);
240
		if(d != nil)
241
			reg.r[rd] = *d;
242
	} else {
243
		if(trace)
244
			itrace("%s\t%s,r%d", ci->name, n, rd);
245
		if(d != nil)
246
			*d = reg.r[rd];
247
	}
248
}
249
 
250
static void
251
setcr(int d, long r)
252
{
253
	int c;
254
 
255
	c = 0;
256
	if(reg.xer & XER_SO)
257
		c |= 1;
258
	if(r == 0)
259
		c |= 2;
260
	else if(r > 0)
261
		c |= 4;
262
	else
263
		c |= 8;
264
	reg.cr = (reg.cr & ~mkCR(d, 0xF)) | mkCR(d, c);
265
}
266
 
267
void
268
addi(ulong ir)
269
{
270
	int rd, ra;
271
	long imm;
272
 
273
	getairr(ir);
274
	if(trace) {
275
		if(ra)
276
			itrace("%s\tr%d,r%d,$0x%lux", ci->name, rd, ra, imm);
277
		else
278
			itrace("li\tr%d,$0x%lux", rd, imm);
279
	}
280
	if(ra)
281
		imm += reg.r[ra];
282
	reg.r[rd] = imm;
283
}
284
 
285
void
286
addis(ulong ir)
287
{
288
	int rd, ra;
289
	long imm;
290
 
291
	getairr(ir);
292
	if(trace) {
293
		if(ra)
294
			itrace("%s\tr%d,r%d,$0x%lux", ci->name, rd, ra, imm);
295
		else
296
			itrace("lis\tr%d,$0x%lux", rd, imm);
297
	}
298
	imm <<= 16;
299
	if(ra)
300
		imm += reg.r[ra];
301
	reg.r[rd] = imm;
302
}
303
 
304
void
305
and(ulong ir)
306
{
307
	int rs, ra, rb;
308
 
309
	getlrrr(ir);
310
	reg.r[ra] = reg.r[rs] & reg.r[rb];
311
	if(trace)
312
		itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
313
	if(ir & 1)
314
		setcr(0, reg.r[ra]);
315
}
316
 
317
void
318
andc(ulong ir)
319
{
320
	int rs, ra, rb;
321
 
322
	getlrrr(ir);
323
	reg.r[ra] = reg.r[rs] & ~reg.r[rb];
324
	if(trace)
325
		itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
326
	if(ir & 1)
327
		setcr(0, reg.r[ra]);
328
}
329
 
330
void
331
andicc(ulong ir)
332
{
333
	int rs, ra;
334
	ulong imm;
335
 
336
	getlirr(ir);
337
	reg.r[ra] = reg.r[rs] & imm;
338
	if(trace)
339
		itrace("%s\tr%d,r%d,$0x%lx", ci->name, ra, rs, imm);
340
	setcr(0, reg.r[ra]);
341
}
342
 
343
void
344
andiscc(ulong ir)
345
{
346
	int rs, ra;
347
	ulong imm;
348
 
349
	getlirr(ir);
350
	reg.r[ra] = reg.r[rs] & (imm<<16);
351
	if(trace)
352
		itrace("%s\tr%d,r%d,$0x%lx", ci->name, ra, rs, imm);
353
	setcr(0, reg.r[ra]);
354
}
355
 
356
void
357
cmpli(ulong ir)
358
{
359
	int rd, ra;
360
	ulong c;
361
	ulong imm, v;
362
 
363
	getairr(ir);
364
	imm &= 0xFFFF;
365
	if(rd & 3)
366
		undef(ir);
367
	rd >>= 2;
368
	v = reg.r[ra];
369
	c = 0;
370
	if(reg.xer & XER_SO)
371
		c |= CRSO;
372
	if(v < imm)
373
		c |= CRLT;
374
	else if(v == imm)
375
		c |= CREQ;
376
	else
377
		c |= CRGT;
378
	c >>= 28;
379
	reg.cr = (reg.cr & ~mkCR(rd, 0xF)) | mkCR(rd, c);
380
	if(trace)
381
		itrace("%s\tcrf%d,r%d,0x%lux [cr=#%x]", ci->name, rd, ra, imm, c);
382
}
383
 
384
void
385
cmp(ulong ir)
386
{
387
	int rd, ra, rb;
388
	ulong c;
389
	long va, vb;
390
 
391
	getarrr(ir);
392
	if(rd & 3)
393
		undef(ir);
394
	rd >>= 2;
395
	c = 0;
396
	if(reg.xer & XER_SO)
397
		c |= CRSO;
398
	va = reg.r[ra];
399
	vb = reg.r[rb];
400
	if(va < vb)
401
		c |= CRLT;
402
	else if(va == vb)
403
		c |= CREQ;
404
	else
405
		c |= CRGT;
406
	c >>= 28;
407
	reg.cr = (reg.cr & ~mkCR(rd, 0xF)) | mkCR(rd, c);
408
	if(trace)
409
		itrace("%s\tcrf%d,r%d,r%d [cr=#%x]", ci->name, rd, ra, rb, c);
410
}
411
 
412
void
413
cmpi(ulong ir)
414
{
415
	int rd, ra;
416
	ulong c;
417
	long imm, v;
418
 
419
	getairr(ir);
420
	if(rd & 3)
421
		undef(ir);
422
	rd >>= 2;
423
	v = reg.r[ra];
424
	c = 0;
425
	if(reg.xer & XER_SO)
426
		c |= CRSO;
427
	if(v < imm)
428
		c |= CRLT;
429
	else if(v == imm)
430
		c |= CREQ;
431
	else
432
		c |= CRGT;
433
	c >>= 28;
434
	reg.cr = (reg.cr & ~mkCR(rd, 0xF)) | mkCR(rd, c);
435
	if(trace)
436
		itrace("%s\tcrf%d,r%d,0x%lux [cr=#%x]", ci->name, rd, ra, imm, c);
437
}
438
 
439
void
440
cmpl(ulong ir)
441
{
442
	int rd, ra, rb;
443
	ulong c;
444
	ulong va, vb;
445
 
446
	getarrr(ir);
447
	if(rd & 3)
448
		undef(ir);
449
	rd >>= 2;
450
	c = 0;
451
	if(reg.xer & XER_SO)
452
		c |= CRSO;
453
	va = reg.r[ra];
454
	vb = reg.r[rb];
455
	if(va < vb)
456
		c |= CRLT;
457
	else if(va == vb)
458
		c |= CREQ;
459
	else
460
		c |= CRGT;
461
	c >>= 28;
462
	reg.cr = (reg.cr & ~mkCR(rd, 0xF)) | mkCR(rd, c);
463
	if(trace)
464
		itrace("%s\tcrf%d,r%d,r%d [cr=#%x]", ci->name, rd, ra, rb, c);
465
}
466
 
467
void
468
cntlzw(ulong ir)
469
{
470
	int rs, ra, rb, n;
471
 
472
	getlrrr(ir);
473
	if(rb)
474
		undef(ir);
475
	for(n=0; n<32 && (reg.r[rs] & (1L<<(31-n))) == 0; n++)
476
		;
477
	reg.r[ra] = n;
478
	if(trace)
479
		itrace("%s%s\tr%d,r%d", ci->name, ir&1?".":"", ra, rs);
480
	if(ir & 1)
481
		setcr(0, reg.r[ra]);
482
}
483
 
484
void
485
eqv(ulong ir)
486
{
487
	int rs, ra, rb;
488
 
489
	getlrrr(ir);
490
	reg.r[ra] = ~(reg.r[rs] ^ reg.r[rb]);
491
	if(trace)
492
		itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
493
	if(ir & 1)
494
		setcr(0, reg.r[ra]);
495
}
496
 
497
void
498
extsb(ulong ir)
499
{
500
	int rs, ra, rb;
501
 
502
	getlrrr(ir);
503
	if(rb)
504
		undef(ir);
505
	reg.r[ra] = (schar)reg.r[rs];
506
	if(trace)
507
		itrace("%s%s\tr%d,r%d", ci->name, ir&1?".":"", ra, rs);
508
	if(ir & 1)
509
		setcr(0, reg.r[ra]);
510
}
511
 
512
void
513
extsh(ulong ir)
514
{
515
	int rs, ra, rb;
516
 
517
	getlrrr(ir);
518
	if(rb)
519
		undef(ir);
520
	reg.r[ra] = (short)reg.r[rs];
521
	if(trace)
522
		itrace("%s%s\tr%d,r%d", ci->name, ir&1?".":"", ra, rs);
523
	if(ir & 1)
524
		setcr(0, reg.r[ra]);
525
}
526
 
527
void
528
add(ulong ir)
529
{
530
	int rd, ra, rb;
531
	uvlong r;
532
 
533
	getarrr(ir);
534
	r = (uvlong)(ulong)reg.r[ra] + (uvlong)(ulong)reg.r[rb];
535
	if(ir & OE) {
536
		reg.xer &= ~XER_OV;
537
		if(r >> 16)
538
			reg.xer |= XER_SO | XER_OV;	/* TO DO: rubbish */
539
	}
540
	reg.r[rd] = (ulong)r;
541
	if(ir & Rc)
542
		setcr(0, reg.r[rd]);
543
	if(trace)
544
		itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra, rb);
545
}
546
 
547
void
548
addc(ulong ir)
549
{
550
	int rd, ra, rb;
551
	ulong v;
552
	uvlong r;
553
 
554
	getarrr(ir);
555
	r = (uvlong)(ulong)reg.r[ra] + (uvlong)(ulong)reg.r[rb];
556
	v = r>>32;
557
	reg.xer &= ~XER_CA;
558
	if(v)
559
		reg.xer |= XER_CA;
560
	if(ir & OE) {
561
		reg.xer &= ~XER_OV;
562
		if(v>>1)
563
			reg.xer |= XER_SO | XER_OV;
564
	}
565
	reg.r[rd] = (ulong)r;
566
	if(ir & Rc)
567
		setcr(0, reg.r[rd]);
568
	if(trace)
569
		itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra, rb);
570
}
571
 
572
void
573
adde(ulong ir)
574
{
575
	int rd, ra, rb;
576
	ulong v;
577
	uvlong r;
578
 
579
	getarrr(ir);
580
	r = (uvlong)(ulong)reg.r[ra] + (uvlong)(ulong)reg.r[rb] + ((reg.xer&XER_CA)!=0);
581
	v = r>>32;
582
	reg.xer &= ~XER_CA;
583
	if(v)
584
		reg.xer |= XER_CA;
585
	if(ir & OE) {
586
		reg.xer &= ~XER_OV;
587
		if(v>>1)
588
			reg.xer |= XER_SO | XER_OV;
589
	}
590
	reg.r[rd] = (ulong)r;
591
	if(ir & Rc)
592
		setcr(0, reg.r[rd]);
593
	if(trace)
594
		itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra, rb);
595
}
596
 
597
void
598
addic(ulong ir)
599
{
600
	int rd, ra;
601
	long imm;
602
	ulong v;
603
	uvlong r;
604
 
605
	getairr(ir);
606
	r = (uvlong)(ulong)reg.r[ra] + (uvlong)(ulong)imm;
607
	v = r>>32;
608
	reg.xer &= ~XER_CA;
609
	if(v)
610
		reg.xer |= XER_CA;
611
	reg.r[rd] = (ulong)r;
612
	if(trace)
613
		itrace("%s\tr%d,r%d,$%ld", ci->name, rd, ra, imm);
614
}
615
 
616
void
617
addiccc(ulong ir)
618
{
619
	int rd, ra;
620
	long imm;
621
	ulong v;
622
	uvlong r;
623
 
624
	getairr(ir);
625
	r = (uvlong)(ulong)reg.r[ra] + (uvlong)(ulong)imm;
626
	v = r>>32;
627
	reg.xer &= ~XER_CA;
628
	if(v)
629
		reg.xer |= XER_CA;
630
	reg.r[rd] = (ulong)r;
631
	setcr(0, reg.r[rd]);
632
	if(trace)
633
		itrace("%s\tr%d,r%d,$%ld", ci->name, rd, ra, imm);
634
}
635
 
636
void
637
addme(ulong ir)
638
{
639
	int rd, ra, rb;
640
	ulong v;
641
	uvlong r;
642
 
643
	getarrr(ir);
644
	if(rb)
645
		undef(ir);
646
	r = (uvlong)(ulong)reg.r[ra] + (uvlong)0xFFFFFFFFU + ((reg.xer&XER_CA)!=0);
647
	v = r>>32;
648
	reg.xer &= ~XER_CA;
649
	if(v)
650
		reg.xer |= XER_CA;
651
	if(ir & OE) {
652
		reg.xer &= ~XER_OV;
653
		if(v>>1)
654
			reg.xer |= XER_SO | XER_OV;
655
	}
656
	reg.r[rd] = (ulong)r;
657
	if(ir & Rc)
658
		setcr(0, reg.r[rd]);
659
	if(trace)
660
		itrace("%s%s%s\tr%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra);
661
}
662
 
663
void
664
addze(ulong ir)
665
{
666
	int rd, ra, rb;
667
	ulong v;
668
	uvlong r;
669
 
670
	getarrr(ir);
671
	if(rb)
672
		undef(ir);
673
	r = (uvlong)(ulong)reg.r[ra] + ((reg.xer&XER_CA)!=0);
674
	v = r>>32;
675
	reg.xer &= ~XER_CA;
676
	if(v)
677
		reg.xer |= XER_CA;
678
	if(ir & OE) {
679
		reg.xer &= ~XER_OV;
680
		if(v>>1)
681
			reg.xer |= XER_SO | XER_OV;
682
	}
683
	reg.r[rd] = (ulong)r;
684
	if(ir & Rc)
685
		setcr(0, reg.r[rd]);
686
	if(trace)
687
		itrace("%s%s%s\tr%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra);
688
}
689
 
690
void
691
divw(ulong ir)
692
{
693
	int rd, ra, rb;
694
 
695
	getarrr(ir);
696
	if(reg.r[rb] != 0 && ((ulong)reg.r[ra] != 0x80000000 || reg.r[rb] != -1))
697
		reg.r[rd] = reg.r[ra]/reg.r[rb];
698
	else if(ir & OE)
699
		reg.xer |= XER_SO | XER_OV;
700
	if(ir & Rc)
701
		setcr(0, reg.r[rd]);
702
	if(trace)
703
		itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra, rb);
704
}
705
 
706
void
707
divwu(ulong ir)
708
{
709
	int rd, ra, rb;
710
 
711
	getarrr(ir);
712
	if(reg.r[rb] != 0)
713
		reg.r[rd] = (ulong)reg.r[ra]/(ulong)reg.r[rb];
714
	else if(ir & OE)
715
		reg.xer |= XER_SO | XER_OV;
716
	if(ir & Rc)
717
		setcr(0, reg.r[rd]);
718
	if(trace)
719
		itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra, rb);
720
}
721
 
722
void
723
mcrxr(ulong ir)
724
{
725
	int rd, ra, rb;
726
 
727
	getarrr(ir);
728
	if(rd & 3 || ra != 0 || rb != 0 || ir & Rc)
729
		undef(ir);
730
	rd >>= 2;
731
	reg.cr = (reg.cr & ~mkCR(rd, 0xF)) | mkCR(rd, reg.xer>>28);
732
	reg.xer &= ~(0xF<<28);
733
}
734
 
735
void
736
mtcrf(ulong ir)
737
{
738
	int rs, crm, i;
739
	ulong m;
740
 
741
	if(ir & ((1<<20)|(1<<11)|Rc))
742
		undef(ir);
743
	rs = (ir>>21)&0x1F;
744
	crm = (ir>>12)&0xFF;
745
	m = 0;
746
	for(i = 0x80; i; i >>= 1) {
747
		m <<= 4;
748
		if(crm & i)
749
			m |= 0xF;
750
	}
751
	reg.cr = (reg.cr & ~m) | (reg.r[rs] & m);
752
}
753
 
754
void
755
mfcr(ulong ir)
756
{
757
	int rd, ra, rb;
758
 
759
	getarrr(ir);
760
	if(ra != 0 || rb != 0 || ir & Rc)
761
		undef(ir);
762
	reg.r[rd] = reg.cr;
763
}
764
 
765
void
766
mulhw(ulong ir)
767
{
768
	int rd, ra, rb;
769
 
770
	getarrr(ir);
771
	reg.r[rd] = ((vlong)(long)reg.r[ra]*(long)reg.r[rb])>>32;
772
	if(ir & Rc)
773
		setcr(0, reg.r[rd]);
774
	if(trace)
775
		itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&Rc?".":"", rd, ra, rb);
776
	/* BUG: doesn't set OV */
777
}
778
 
779
void
780
mulhwu(ulong ir)
781
{
782
	int rd, ra, rb;
783
 
784
	getarrr(ir);
785
	reg.r[rd] = ((uvlong)(ulong)reg.r[ra]*(ulong)reg.r[rb])>>32;
786
	if(ir & Rc)
787
		setcr(0, reg.r[rd]);	/* not sure whether CR setting is signed or unsigned */
788
	if(trace)
789
		itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&Rc?".":"", rd, ra, rb);
790
	/* BUG: doesn't set OV */
791
}
792
 
793
void
794
mullw(ulong ir)
795
{
796
	int rd, ra, rb;
797
 
798
	getarrr(ir);
799
	reg.r[rd] = (uvlong)(ulong)reg.r[ra]*(ulong)reg.r[rb];
800
	if(ir & Rc)
801
		setcr(0, reg.r[rd]);
802
	if(trace)
803
		itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&Rc?".":"", rd, ra, rb);
804
	/* BUG: doesn't set OV */
805
}
806
 
807
void
808
mulli(ulong ir)
809
{
810
	int rd, ra;
811
	long imm;
812
 
813
	getairr(ir);
814
	reg.r[rd] = (uvlong)(ulong)reg.r[ra]*(ulong)imm;
815
	if(trace)
816
		itrace("%s\tr%d,r%d,$%ld", ci->name, rd, ra, imm);
817
}
818
 
819
void
820
nand(ulong ir)
821
{
822
	int rs, ra, rb;
823
 
824
	getlrrr(ir);
825
	reg.r[ra] = ~(reg.r[rs] & reg.r[rb]);
826
	if(ir & Rc)
827
		setcr(0, reg.r[ra]);
828
	if(trace)
829
		itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
830
}
831
 
832
void
833
neg(ulong ir)
834
{
835
	int rd, ra, rb;
836
 
837
	getarrr(ir);
838
	if(rb)
839
		undef(ir);
840
	if(ir & OE)
841
		reg.xer &= ~XER_OV;
842
	if((ulong)reg.r[ra] == 0x80000000) {
843
		if(ir & OE)
844
			reg.xer |= XER_SO | XER_OV;
845
		reg.r[rd] = reg.r[ra];
846
	} else
847
		reg.r[rd] = -reg.r[ra];
848
	if(ir & Rc)
849
		setcr(0, reg.r[rd]);
850
}
851
 
852
void
853
nor(ulong ir)
854
{
855
	int rs, ra, rb;
856
 
857
	getlrrr(ir);
858
	reg.r[ra] = ~(reg.r[rs] | reg.r[rb]);
859
	if(ir & Rc)
860
		setcr(0, reg.r[ra]);
861
	if(trace)
862
		itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
863
}
864
 
865
void
866
or(ulong ir)
867
{
868
	int rs, ra, rb;
869
 
870
	getlrrr(ir);
871
	reg.r[ra] = reg.r[rs] | reg.r[rb];
872
	if(ir & Rc)
873
		setcr(0, reg.r[ra]);
874
	if(trace) {
875
		if(rs == rb)
876
			itrace("mr%s\tr%d,r%d", ir&1?".":"", ra, rs);
877
		else
878
			itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
879
	}
880
}
881
 
882
void
883
orc(ulong ir)
884
{
885
	int rs, ra, rb;
886
 
887
	getlrrr(ir);
888
	reg.r[ra] = reg.r[rs] | ~reg.r[rb];
889
	if(ir & Rc)
890
		setcr(0, reg.r[ra]);
891
	if(trace)
892
		itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
893
}
894
 
895
void
896
ori(ulong ir)
897
{
898
	int rs, ra;
899
	ulong imm;
900
 
901
	getlirr(ir);
902
	reg.r[ra] = reg.r[rs] | imm;
903
	if(trace)
904
		itrace("%s\tr%d,r%d,$0x%lx", ci->name, ra, rs, imm);
905
}
906
 
907
void
908
oris(ulong ir)
909
{
910
	int rs, ra;
911
	ulong imm;
912
 
913
	getlirr(ir);
914
	reg.r[ra] = reg.r[rs] | (imm<<16);
915
	if(trace)
916
		itrace("%s\tr%d,r%d,$0x%lx", ci->name, ra, rs, imm);
917
}
918
 
919
static ulong
920
mkmask(int mb, int me)
921
{
922
	int i;
923
	ulong v;
924
 
925
	if(mb > me)
926
		return mkmask(0, me) | mkmask(mb, 31);
927
	v = 0;
928
	for(i=mb; i<=me; i++)
929
		v |= 1L << (31-i);	/* don't need a loop, but i'm lazy */
930
	return v;
931
}
932
 
933
static ulong
934
rotl(ulong v, int sh)
935
{
936
	if(sh == 0)
937
		return v;
938
	return (v<<sh) | (v>>(32-sh));
939
}
940
 
941
void
942
rlwimi(ulong ir)
943
{
944
	int rs, ra, rb, sh;
945
	ulong m;
946
 
947
	getlrrr(ir);
948
	sh = rb;
949
	m = mkmask((ir>>6)&0x1F, (ir>>1)&0x1F);
950
	reg.r[ra] = (reg.r[ra] & ~m) | (rotl(reg.r[rs], sh) & m);
951
	if(trace)
952
		itrace("%s\tr%d,r%d,%d,#%lux", ci->name, ra, rs, sh, m);
953
	if(ir & 1)
954
		setcr(0, reg.r[ra]);
955
}
956
 
957
void
958
rlwinm(ulong ir)
959
{
960
	int rs, ra, rb, sh;
961
	ulong m;
962
 
963
	getlrrr(ir);
964
	sh = rb;
965
	m = mkmask((ir>>6)&0x1F, (ir>>1)&0x1F);
966
	reg.r[ra] = rotl(reg.r[rs], sh) & m;
967
	if(trace)
968
		itrace("%s%s\tr%d,r%d,%d,#%lux", ci->name, ir&Rc?".":"", ra, rs, sh, m);
969
	if(ir & Rc)
970
		setcr(0, reg.r[ra]);
971
}
972
 
973
void
974
rlwnm(ulong ir)
975
{
976
	int rs, ra, rb, sh;
977
	ulong m;
978
 
979
	getlrrr(ir);
980
	sh = reg.r[rb] & 0x1F;
981
	m = mkmask((ir>>6)&0x1F, (ir>>1)&0x1F);
982
	reg.r[ra] = rotl(reg.r[rs], sh) & m;
983
	if(trace)
984
		itrace("%s\tr%d,r%d,r%d,#%lux", ci->name, ra, rs, rb, m);
985
	if(ir & 1)
986
		setcr(0, reg.r[ra]);
987
}
988
 
989
void
990
slw(ulong ir)
991
{
992
	int rs, ra, rb;
993
	long v;
994
 
995
	getlrrr(ir);
996
	v = reg.r[rb];
997
	if((v & 0x20) == 0) {
998
		v &= 0x1F;
999
		reg.r[ra] = (ulong)reg.r[rs] << v;
1000
	} else
1001
		reg.r[ra] = 0;
1002
	if(ir & Rc)
1003
		setcr(0, reg.r[ra]);
1004
	if(trace)
1005
		itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
1006
}
1007
 
1008
void
1009
sraw(ulong ir)
1010
{
1011
	int rs, ra, rb;
1012
	long v;
1013
 
1014
	getlrrr(ir);
1015
	v = reg.r[rb];
1016
	if((v & 0x20) == 0) {
1017
		v &= 0x1F;
1018
		if(reg.r[rs]&SIGNBIT && v)
1019
			reg.r[ra] = reg.r[rs]>>v | ~((1<<(32-v))-1);
1020
		else
1021
			reg.r[ra] = reg.r[rs]>>v;
1022
	} else
1023
		reg.r[ra] = reg.r[rs]&SIGNBIT? ~0: 0;
1024
	if(ir & Rc)
1025
		setcr(0, reg.r[ra]);
1026
	if(trace)
1027
		itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
1028
}
1029
 
1030
void
1031
srawi(ulong ir)
1032
{
1033
	int rs, ra, rb;
1034
	long v;
1035
 
1036
	getlrrr(ir);
1037
	v = rb;
1038
	if((v & 0x20) == 0) {
1039
		v &= 0x1F;
1040
		if(reg.r[rs]&SIGNBIT && v)
1041
			reg.r[ra] = reg.r[rs]>>v | ~((1<<(32-v))-1);
1042
		else
1043
			reg.r[ra] = reg.r[rs]>>v;
1044
	} else
1045
		reg.r[ra] = reg.r[rs]&SIGNBIT? ~0: 0;
1046
	if(ir & Rc)
1047
		setcr(0, reg.r[ra]);
1048
	if(trace)
1049
		itrace("%s%s\tr%d,r%d,$%d", ci->name, ir&1?".":"", ra, rs, v);
1050
}
1051
 
1052
void
1053
srw(ulong ir)
1054
{
1055
	int rs, ra, rb;
1056
	long v;
1057
 
1058
	getlrrr(ir);
1059
	v = reg.r[rb];
1060
	if((v & 0x20) == 0)
1061
		reg.r[ra] = (ulong)reg.r[rs] >> (v&0x1F);
1062
	else
1063
		reg.r[ra] = 0;
1064
	if(ir & Rc)
1065
		setcr(0, reg.r[ra]);
1066
	if(trace)
1067
		itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
1068
}
1069
 
1070
void
1071
subf(ulong ir)
1072
{
1073
	int rd, ra, rb;
1074
	uvlong r;
1075
 
1076
	getarrr(ir);
1077
	r = (uvlong)((ulong)~reg.r[ra]) + (uvlong)(ulong)reg.r[rb] + 1;
1078
	if(ir & OE) {
1079
		reg.xer &= ~XER_OV;
1080
		if(r >> 16)
1081
			reg.xer |= XER_SO | XER_OV;
1082
	}
1083
	reg.r[rd] = (ulong)r;
1084
	if(ir & Rc)
1085
		setcr(0, reg.r[rd]);
1086
	if(trace)
1087
		itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra, rb);
1088
}
1089
 
1090
void
1091
subfc(ulong ir)
1092
{
1093
	int rd, ra, rb;
1094
	ulong v;
1095
	uvlong r;
1096
 
1097
	getarrr(ir);
1098
	r = (uvlong)((ulong)~reg.r[ra]) + (uvlong)(ulong)reg.r[rb] + 1;
1099
	v = r>>32;
1100
	reg.xer &= ~XER_CA;
1101
	if(v)
1102
		reg.xer |= XER_CA;
1103
	if(ir & OE) {
1104
		reg.xer &= ~XER_OV;
1105
		if(v>>1)
1106
			reg.xer |= XER_SO | XER_OV;
1107
	}
1108
	reg.r[rd] = (ulong)r;
1109
	if(ir & Rc)
1110
		setcr(0, reg.r[rd]);
1111
	if(trace)
1112
		itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra, rb);
1113
}
1114
 
1115
void
1116
subfe(ulong ir)
1117
{
1118
	int rd, ra, rb;
1119
	ulong v;
1120
	uvlong r;
1121
 
1122
	getarrr(ir);
1123
	r = (uvlong)((ulong)~reg.r[ra]) + (uvlong)(ulong)reg.r[rb] + ((reg.xer&XER_CA)!=0);
1124
	v = r>>32;
1125
	reg.xer &= ~XER_CA;
1126
	if(v)
1127
		reg.xer |= XER_CA;
1128
	if(ir & OE) {
1129
		reg.xer &= ~XER_OV;
1130
		if(v>>1)
1131
			reg.xer |= XER_SO | XER_OV;
1132
	}
1133
	reg.r[rd] = (ulong)r;
1134
	if(ir & Rc)
1135
		setcr(0, reg.r[rd]);
1136
	if(trace)
1137
		itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra, rb);
1138
}
1139
 
1140
void
1141
subfic(ulong ir)
1142
{
1143
	int rd, ra;
1144
	long imm;
1145
	ulong v;
1146
	uvlong r;
1147
 
1148
	getairr(ir);
1149
	r = (uvlong)((ulong)~reg.r[ra]) + (uvlong)(ulong)imm + 1;
1150
	v = r>>32;
1151
	reg.xer &= ~XER_CA;
1152
	if(v)
1153
		reg.xer |= XER_CA;
1154
	reg.r[rd] = (ulong)r;
1155
	if(trace)
1156
		itrace("%s\tr%d,r%d,$%ld", ci->name, rd, ra, imm);
1157
}
1158
 
1159
void
1160
subfme(ulong ir)
1161
{
1162
	int rd, ra, rb;
1163
	ulong v;
1164
	uvlong r;
1165
 
1166
	getarrr(ir);
1167
	if(rb)
1168
		undef(ir);
1169
	r = (uvlong)((ulong)~reg.r[ra]) + (uvlong)0xFFFFFFFFU + ((reg.xer&XER_CA)!=0);
1170
	v = r>>32;
1171
	reg.xer &= ~XER_CA;
1172
	if(v)
1173
		reg.xer |= XER_CA;
1174
	if(ir & OE) {
1175
		reg.xer &= ~XER_OV;
1176
		if(v>>1)
1177
			reg.xer |= XER_SO | XER_OV;
1178
	}
1179
	reg.r[rd] = (ulong)r;
1180
	if(ir & Rc)
1181
		setcr(0, reg.r[rd]);
1182
	if(trace)
1183
		itrace("%s%s%s\tr%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra);
1184
}
1185
 
1186
void
1187
subfze(ulong ir)
1188
{
1189
	int rd, ra, rb;
1190
	ulong v;
1191
	uvlong r;
1192
 
1193
	getarrr(ir);
1194
	if(rb)
1195
		undef(ir);
1196
	r = (uvlong)((ulong)~reg.r[ra]) + ((reg.xer&XER_CA)!=0);
1197
	v = r>>32;
1198
	reg.xer &= ~XER_CA;
1199
	if(v)
1200
		reg.xer |= XER_CA;
1201
	if(ir & OE) {
1202
		reg.xer &= ~XER_OV;
1203
		if(v>>1)
1204
			reg.xer |= XER_SO | XER_OV;
1205
	}
1206
	reg.r[rd] = (ulong)r;
1207
	if(ir & Rc)
1208
		setcr(0, reg.r[rd]);
1209
	if(trace)
1210
		itrace("%s%s%s\tr%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra);
1211
}
1212
 
1213
void
1214
xor(ulong ir)
1215
{
1216
	int rs, ra, rb;
1217
 
1218
	getlrrr(ir);
1219
	reg.r[ra] = reg.r[rs] ^ reg.r[rb];
1220
	if(trace)
1221
		itrace("%s\tr%d,r%d,r%d", ci->name, ra, rs, rb);
1222
}
1223
 
1224
void
1225
xori(ulong ir)
1226
{
1227
	int rs, ra;
1228
	ulong imm;
1229
 
1230
	getlirr(ir);
1231
	reg.r[ra] = reg.r[rs] ^ imm;
1232
	if(trace)
1233
		itrace("%s\tr%d,r%d,$0x%lx", ci->name, ra, rs, imm);
1234
}
1235
 
1236
void
1237
xoris(ulong ir)
1238
{
1239
	int rs, ra;
1240
	ulong imm;
1241
 
1242
	getlirr(ir);
1243
	reg.r[ra] = reg.r[rs] ^ (imm<<16);
1244
	if(trace)
1245
		itrace("%s\tr%d,r%d,$0x%lx", ci->name, ra, rs, imm);
1246
}
1247
 
1248
void
1249
lwz(ulong ir)
1250
{
1251
	ulong ea;
1252
	int ra, rd, upd;
1253
	long imm;
1254
 
1255
	getairr(ir);
1256
	ea = imm;
1257
	upd = (ir&(1L<<26))!=0;
1258
	if(ra) {
1259
		ea += reg.r[ra];
1260
		if(upd)
1261
			reg.r[ra] = ea;
1262
	} else {
1263
		if(upd)
1264
			undef(ir);
1265
	}
1266
	if(trace)
1267
		itrace("%s\tr%d,%ld(r%d) ea=%lux", ci->name, rd, imm, ra, ea);
1268
 
1269
	reg.r[rd] = getmem_w(ea);
1270
}
1271
 
1272
void
1273
lwzx(ulong ir)
1274
{
1275
	ulong ea;
1276
	int rb, ra, rd, upd;
1277
 
1278
	getarrr(ir);
1279
	ea = reg.r[rb];
1280
	upd = getxo(ir)==55;
1281
	if(ra) {
1282
		ea += reg.r[ra];
1283
		if(upd)
1284
			reg.r[ra] = ea;
1285
		if(trace)
1286
			itrace("%s\tr%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
1287
	} else {
1288
		if(upd)
1289
			undef(ir);
1290
		if(trace)
1291
			itrace("%s\tr%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
1292
	}
1293
 
1294
	reg.r[rd] = getmem_w(ea);
1295
}
1296
 
1297
void
1298
lwarx(ulong ir)
1299
{
1300
	lwzx(ir);
1301
}
1302
 
1303
void
1304
lbz(ulong ir)
1305
{
1306
	ulong ea;
1307
	int ra, rd, upd;
1308
	long imm;
1309
 
1310
	getairr(ir);
1311
	ea = imm;
1312
	upd = (ir&(1L<<26))!=0;
1313
	if(ra) {
1314
		ea += reg.r[ra];
1315
		if(upd)
1316
			reg.r[ra] = ea;
1317
	} else {
1318
		if(upd)
1319
			undef(ir);
1320
	}
1321
	if(trace)
1322
		itrace("%s\tr%d,%ld(r%d) ea=%lux", ci->name, rd, imm, ra, ea);
1323
 
1324
	reg.r[rd] = getmem_b(ea);
1325
}
1326
 
1327
void
1328
lbzx(ulong ir)
1329
{
1330
	ulong ea;
1331
	int rb, ra, rd, upd;
1332
 
1333
	getarrr(ir);
1334
	ea = reg.r[rb];
1335
	upd = getxo(ir)==119;
1336
	if(ra) {
1337
		ea += reg.r[ra];
1338
		if(upd)
1339
			reg.r[ra] = ea;
1340
		if(trace)
1341
			itrace("%s\tr%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
1342
	} else {
1343
		if(upd)
1344
			undef(ir);
1345
		if(trace)
1346
			itrace("%s\tr%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
1347
	}
1348
 
1349
	reg.r[rd] = getmem_b(ea);
1350
}
1351
 
1352
void
1353
stw(ulong ir)
1354
{
1355
	ulong ea;
1356
	int ra, rd, upd;
1357
	long imm;
1358
 
1359
	getairr(ir);
1360
	ea = imm;
1361
	upd = (ir&(1L<<26))!=0;
1362
	if(ra) {
1363
		ea += reg.r[ra];
1364
		if(upd)
1365
			reg.r[ra] = ea;
1366
	} else {
1367
		if(upd)
1368
			undef(ir);
1369
	}
1370
	if(trace)
1371
		itrace("%s\tr%d,%ld(r%d) #%lux=#%lux (%ld)",
1372
					ci->name, rd, imm, ra, ea, reg.r[rd], reg.r[rd]);
1373
	putmem_w(ea, reg.r[rd]);
1374
 
1375
}
1376
 
1377
void
1378
stwx(ulong ir)
1379
{
1380
	ulong ea;
1381
	int ra, rd, upd, rb;
1382
 
1383
	getarrr(ir);
1384
	ea = reg.r[rb];
1385
	upd = getxo(ir)==183;
1386
	if(ra) {
1387
		ea += reg.r[ra];
1388
		if(upd)
1389
			reg.r[ra] = ea;
1390
		if(trace)
1391
			itrace("%s\tr%d,(r%d+r%d) #%lux=#%lux (%ld)",
1392
					ci->name, rd, ra, rb, ea, reg.r[rd], reg.r[rd]);
1393
	} else {
1394
		if(upd)
1395
			undef(ir);
1396
		if(trace)
1397
			itrace("%s\tr%d,(r%d) #%lux=#%lux (%ld)",
1398
					ci->name, rd, rb, ea, reg.r[rd], reg.r[rd]);
1399
	}
1400
	putmem_w(ea, reg.r[rd]);
1401
 
1402
}
1403
 
1404
void
1405
stwcx(ulong ir)
1406
{
1407
	ulong ea;
1408
	int ra, rd, rb;
1409
 
1410
	if((ir & Rc) == 0)
1411
		undef(ir);
1412
	getarrr(ir);
1413
	ea = reg.r[rb];
1414
	if(ra) {
1415
		ea += reg.r[ra];
1416
		if(trace)
1417
			itrace("%s\tr%d,(r%d+r%d) #%lux=#%lux (%ld)",
1418
					ci->name, rd, ra, rb, ea, reg.r[rd], reg.r[rd]);
1419
	} else {
1420
		if(trace)
1421
			itrace("%s\tr%d,(r%d) #%lux=#%lux (%ld)",
1422
					ci->name, rd, rb, ea, reg.r[rd], reg.r[rd]);
1423
	}
1424
	putmem_w(ea, reg.r[rd]);	/* assume a reservation exists; store succeeded */
1425
	setcr(0, 0);
1426
 
1427
}
1428
 
1429
void
1430
stb(ulong ir)
1431
{
1432
	ulong ea;
1433
	int ra, rd, upd, v;
1434
	long imm;
1435
 
1436
	getairr(ir);
1437
	ea = imm;
1438
	upd = (ir&(1L<<26))!=0;
1439
	if(ra) {
1440
		ea += reg.r[ra];
1441
		if(upd)
1442
			reg.r[ra] = ea;
1443
	} else {
1444
		if(upd)
1445
			undef(ir);
1446
	}
1447
	v = reg.r[rd] & 0xFF;
1448
	if(trace)
1449
		itrace("%s\tr%d,%ld(r%d) #%lux=#%lux (%ld)",
1450
					ci->name, rd, imm, ra, ea, v, v);
1451
	putmem_b(ea, v);
1452
}
1453
 
1454
void
1455
stbx(ulong ir)
1456
{
1457
	ulong ea;
1458
	int ra, rd, upd, rb, v;
1459
 
1460
	getarrr(ir);
1461
	ea = reg.r[rb];
1462
	upd = getxo(ir)==247;
1463
	v = reg.r[rd] & 0xFF;
1464
	if(ra) {
1465
		ea += reg.r[ra];
1466
		if(upd)
1467
			reg.r[ra] = ea;
1468
		if(trace)
1469
			itrace("%s\tr%d,(r%d+r%d) #%lux=#%lux (%ld)",
1470
					ci->name, rd, ra, rb, ea, v, v);
1471
	} else {
1472
		if(upd)
1473
			undef(ir);
1474
		if(trace)
1475
			itrace("%s\tr%d,(r%d) #%lux=#%lux (%ld)",
1476
					ci->name, rd, rb, ea, v, v);
1477
	}
1478
	putmem_b(ea, v);
1479
 
1480
}
1481
 
1482
void
1483
lhz(ulong ir)
1484
{
1485
	ulong ea;
1486
	int imm, ra, rd, upd;
1487
 
1488
	getairr(ir);
1489
	ea = imm;
1490
	upd = (ir&(1L<<26))!=0;
1491
	if(ra) {
1492
		ea += reg.r[ra];
1493
		if(upd)
1494
			reg.r[ra] = ea;
1495
	} else {
1496
		if(upd)
1497
			undef(ir);
1498
	}
1499
	if(trace)
1500
		itrace("%s\tr%d,%ld(r%d) ea=%lux", ci->name, rd, imm, ra, ea);
1501
 
1502
	reg.r[rd] = getmem_h(ea);
1503
}
1504
 
1505
void
1506
lhzx(ulong ir)
1507
{
1508
	ulong ea;
1509
	int rb, ra, rd, upd;
1510
 
1511
	getarrr(ir);
1512
	ea = reg.r[rb];
1513
	upd = getxo(ir)==311;
1514
	if(ra) {
1515
		ea += reg.r[ra];
1516
		if(upd)
1517
			reg.r[ra] = ea;
1518
		if(trace)
1519
			itrace("%s\tr%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
1520
	} else {
1521
		if(upd)
1522
			undef(ir);
1523
		if(trace)
1524
			itrace("%s\tr%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
1525
	}
1526
 
1527
	reg.r[rd] = getmem_h(ea);
1528
}
1529
 
1530
void
1531
lha(ulong ir)
1532
{
1533
	ulong ea;
1534
	int imm, ra, rd, upd;
1535
 
1536
	getairr(ir);
1537
	ea = imm;
1538
	upd = (ir&(1L<<26))!=0;
1539
	if(ra) {
1540
		ea += reg.r[ra];
1541
		if(upd)
1542
			reg.r[ra] = ea;
1543
	} else {
1544
		if(upd)
1545
			undef(ir);
1546
	}
1547
	if(trace)
1548
		itrace("%s\tr%d,%ld(r%d) ea=%lux", ci->name, rd, imm, ra, ea);
1549
 
1550
	reg.r[rd] = (short)getmem_h(ea);
1551
}
1552
 
1553
void
1554
lhax(ulong ir)
1555
{
1556
	ulong ea;
1557
	int rb, ra, rd, upd;
1558
 
1559
	getarrr(ir);
1560
	ea = reg.r[rb];
1561
	upd = getxo(ir)==311;
1562
	if(ra) {
1563
		ea += reg.r[ra];
1564
		if(upd)
1565
			reg.r[ra] = ea;
1566
		if(trace)
1567
			itrace("%s\tr%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
1568
	} else {
1569
		if(upd)
1570
			undef(ir);
1571
		if(trace)
1572
			itrace("%s\tr%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
1573
	}
1574
 
1575
	reg.r[rd] = (short)getmem_h(ea);
1576
}
1577
 
1578
void
1579
lhbrx(ulong ir)
1580
{
1581
	ulong ea;
1582
	int rb, ra, rd;
1583
	ulong v;
1584
 
1585
	getarrr(ir);
1586
	ea = reg.r[rb];
1587
	if(ra) {
1588
		ea += reg.r[ra];
1589
		if(trace)
1590
			itrace("%s\tr%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
1591
	} else {
1592
		if(trace)
1593
			itrace("%s\tr%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
1594
	}
1595
	v = getmem_h(ea);
1596
 
1597
	reg.r[rd] = ((v&0xFF)<<8)|(v&0xFF);
1598
}
1599
 
1600
void
1601
sth(ulong ir)
1602
{
1603
	ulong ea;
1604
	int imm, ra, rd, upd, v;
1605
 
1606
	getairr(ir);
1607
	ea = imm;
1608
	upd = (ir&(1L<<26))!=0;
1609
	if(ra) {
1610
		ea += reg.r[ra];
1611
		if(upd)
1612
			reg.r[ra] = ea;
1613
	} else {
1614
		if(upd)
1615
			undef(ir);
1616
	}
1617
	v = reg.r[rd] & 0xFFFF;
1618
	if(trace)
1619
		itrace("%s\tr%d,%ld(r%d) #%lux=#%lux (%ld)",
1620
					ci->name, rd, imm, ra, ea, v, v);
1621
	putmem_h(ea, v);
1622
 
1623
}
1624
 
1625
void
1626
sthx(ulong ir)
1627
{
1628
	ulong ea;
1629
	int ra, rd, upd, rb, v;
1630
 
1631
	getarrr(ir);
1632
	ea = reg.r[rb];
1633
	upd = getxo(ir)==247;
1634
	v = reg.r[rd] & 0xFFFF;
1635
	if(ra) {
1636
		ea += reg.r[ra];
1637
		if(upd)
1638
			reg.r[ra] = ea;
1639
		if(trace)
1640
			itrace("%s\tr%d,(r%d+r%d) #%lux=#%lux (%ld)",
1641
					ci->name, rd, ra, rb, ea, v, v);
1642
	} else {
1643
		if(upd)
1644
			undef(ir);
1645
		if(trace)
1646
			itrace("%s\tr%d,(r%d) #%lux=#%lux (%ld)",
1647
					ci->name, rd, rb, ea, v, v);
1648
	}
1649
	putmem_h(ea, v);
1650
}
1651
 
1652
void
1653
sthbrx(ulong ir)
1654
{
1655
	ulong ea;
1656
	int ra, rd, rb;
1657
	ulong v;
1658
 
1659
	getarrr(ir);
1660
	ea = reg.r[rb];
1661
	v = reg.r[rd];
1662
	v = ((v&0xFF)<<8)|(v&0xFF);
1663
	if(ra) {
1664
		ea += reg.r[ra];
1665
		if(trace)
1666
			itrace("%s\tr%d,(r%d+r%d) #%lux=#%lux (%ld)",
1667
					ci->name, rd, ra, rb, ea, v, v);
1668
	} else {
1669
		if(trace)
1670
			itrace("%s\tr%d,(r%d) #%lux=#%lux (%ld)",
1671
					ci->name, rd, rb, ea, v, v);
1672
	}
1673
	putmem_h(ea, v);
1674
}
1675
 
1676
void
1677
lwbrx(ulong ir)
1678
{
1679
	ulong ea;
1680
	int rb, ra, rd, i;
1681
	ulong v;
1682
 
1683
	getarrr(ir);
1684
	if(ir & Rc)
1685
		undef(ir);
1686
	ea = reg.r[rb];
1687
	if(ra) {
1688
		ea += reg.r[ra];
1689
		if(trace)
1690
			itrace("%s\tr%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
1691
	} else {
1692
		if(trace)
1693
			itrace("%s\tr%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
1694
	}
1695
	v = 0;
1696
	for(i = 0; i < 4; i++)
1697
		v = v>>8 | getmem_b(ea++);	/* assume unaligned load is allowed */
1698
	reg.r[rd] = v;
1699
}
1700
 
1701
void
1702
stwbrx(ulong ir)
1703
{
1704
	ulong ea;
1705
	int rb, ra, rd, i;
1706
	ulong v;
1707
 
1708
	getarrr(ir);
1709
	if(ir & Rc)
1710
		undef(ir);
1711
	ea = reg.r[rb];
1712
	if(ra) {
1713
		ea += reg.r[ra];
1714
		if(trace)
1715
			itrace("%s\tr%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
1716
	} else {
1717
		if(trace)
1718
			itrace("%s\tr%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
1719
	}
1720
	v = 0;
1721
	for(i = 0; i < 4; i++) {
1722
		putmem_b(ea++, v & 0xFF);	/* assume unaligned store is allowed */
1723
		v >>= 8;
1724
	}
1725
}
1726
 
1727
void
1728
lswi(ulong ir)
1729
{
1730
	ulong ea;
1731
	int rb, ra, rd, n, i, r, b;
1732
 
1733
	getarrr(ir);
1734
	if(ir & Rc)
1735
		undef(ir);
1736
	n = rb;
1737
	if(n == 0)
1738
		n = 32;
1739
	ea = 0;
1740
	if(ra) {
1741
		ea += reg.r[ra];
1742
		if(trace)
1743
			itrace("%s\tr%d,(r%d),%d ea=%lux", ci->name, rd, ra, n, ea);
1744
	} else {
1745
		if(trace)
1746
			itrace("%s\tr%d,(0),%d ea=0", ci->name, rd, n);
1747
	}
1748
	i = -1;
1749
	r = rd-1;
1750
	while(--n >= 0) {
1751
		if(i < 0) {
1752
			r = (r+1)&0x1F;
1753
			if(ra == 0 || r != ra)
1754
				reg.r[r] = 0;
1755
			i = 24;
1756
		}
1757
		b = getmem_b(ea++);
1758
		if(ra == 0 || r != ra)
1759
			reg.r[r] = (reg.r[r] & ~(0xFF<<i)) | (b << i);
1760
		i -= 8;
1761
	}
1762
}
1763
 
1764
void
1765
lswx(ulong ir)
1766
{
1767
	ulong ea;
1768
	int rb, ra, rd, n, i, r, b;
1769
 
1770
	getarrr(ir);
1771
	if(ir & Rc)
1772
		undef(ir);
1773
	n = reg.xer & 0x7F;
1774
	ea = reg.r[rb];
1775
	if(ra) {
1776
		ea += reg.r[ra];
1777
		if(trace)
1778
			itrace("%s\tr%d,(r%d+r%d) ea=%lux n=%d", ci->name, rd, ra, rb, ea, n);
1779
	} else {
1780
		if(trace)
1781
			itrace("%s\tr%d,(r%d) ea=%lux n=%d", ci->name, rd, rb, ea, n);
1782
	}
1783
	i = -1;
1784
	r = rd-1;
1785
	while(--n >= 0) {
1786
		if(i < 0) {
1787
			r = (r+1)&0x1F;
1788
			if((ra == 0 || r != ra) && r != rb)
1789
				reg.r[r] = 0;
1790
			i = 24;
1791
		}
1792
		b = getmem_b(ea++);
1793
		if((ra == 0 || r != ra) && r != rb)
1794
			reg.r[r] = (reg.r[r] & ~(0xFF<<i)) | (b << i);
1795
		i -= 8;
1796
	}
1797
}
1798
 
1799
void
1800
stswx(ulong ir)
1801
{
1802
	ulong ea;
1803
	int rb, ra, rd, n, i, r;
1804
 
1805
	getarrr(ir);
1806
	if(ir & Rc)
1807
		undef(ir);
1808
	n = reg.xer & 0x7F;
1809
	ea = reg.r[rb];
1810
	if(ra) {
1811
		ea += reg.r[ra];
1812
		if(trace)
1813
			itrace("%s\tr%d,(r%d+r%d) ea=%lux n=%d", ci->name, rd, ra, rb, ea, n);
1814
	} else {
1815
		if(trace)
1816
			itrace("%s\tr%d,(r%d) ea=%lux n=%d", ci->name, rd, rb, ea, n);
1817
	}
1818
	i = -1;
1819
	r = rd-1;
1820
	while(--n >= 0) {
1821
		if(i < 0) {
1822
			r = (r+1)&0x1F;
1823
			i = 24;
1824
		}
1825
		putmem_b(ea++, (reg.r[r]>>i)&0xFF);
1826
		i -= 8;
1827
	}
1828
}
1829
 
1830
void
1831
stswi(ulong ir)
1832
{
1833
	ulong ea;
1834
	int rb, ra, rd, n, i, r;
1835
 
1836
	getarrr(ir);
1837
	if(ir & Rc)
1838
		undef(ir);
1839
	n = rb;
1840
	if(n == 0)
1841
		n = 32;
1842
	ea = 0;
1843
	if(ra) {
1844
		ea += reg.r[ra];
1845
		if(trace)
1846
			itrace("%s\tr%d,(r%d),%d ea=%lux", ci->name, rd, ra, n, ea);
1847
	} else {
1848
		if(trace)
1849
			itrace("%s\tr%d,(0),%d ea=0", ci->name, rd, n);
1850
	}
1851
	i = -1;
1852
	r = rd-1;
1853
	while(--n >= 0) {
1854
		if(i < 0) {
1855
			r = (r+1)&0x1F;
1856
			i = 24;
1857
		}
1858
		putmem_b(ea++, (reg.r[r]>>i)&0xFF);
1859
		i -= 8;
1860
	}
1861
}
1862
 
1863
void
1864
lmw(ulong ir)
1865
{
1866
	ulong ea;
1867
	int ra, rd, r;
1868
	long imm;
1869
 
1870
	getairr(ir);
1871
	ea = imm;
1872
	if(ra)
1873
		ea += reg.r[ra];
1874
	if(trace)
1875
		itrace("%s\tr%d,%ld(r%d) ea=%lux", ci->name, rd, imm, ra, ea);
1876
 
1877
	for(r = rd; r <= 31; r++) {
1878
		if(r != 0 && r != rd)
1879
			reg.r[rd] = getmem_w(ea);
1880
		ea += 4;
1881
	}
1882
}
1883
 
1884
void
1885
stmw(ulong ir)
1886
{
1887
	ulong ea;
1888
	int ra, rd, r;
1889
	long imm;
1890
 
1891
	getairr(ir);
1892
	ea = imm;
1893
	if(ra)
1894
		ea += reg.r[ra];
1895
	if(trace)
1896
		itrace("%s\tr%d,%ld(r%d) ea=%lux", ci->name, rd, imm, ra, ea);
1897
 
1898
	for(r = rd; r <= 31; r++) {
1899
		putmem_w(ea, reg.r[rd]);
1900
		ea += 4;
1901
	}
1902
}
1903
 
1904
void
1905
twi(ulong ir)
1906
{
1907
	int rd, ra;
1908
	long a, imm;
1909
 
1910
	getairr(ir);
1911
	a = reg.r[ra];
1912
	if(trace)
1913
		itrace("twi\t#%.2x,r%d,$0x%lux (%ld)", rd, ra, imm, imm);
1914
	if(a < imm && rd&0x10 ||
1915
	   a > imm && rd&0x08 ||
1916
	   a == imm && rd&0x04 ||
1917
	   (ulong)a < imm && rd&0x02 ||
1918
	   (ulong)a > imm && rd&0x01) {
1919
		Bprint(bioout, "program_exception (trap type)\n");
1920
		longjmp(errjmp, 0);
1921
	}
1922
}
1923
 
1924
void
1925
tw(ulong ir)
1926
{
1927
	int rd, ra, rb;
1928
	long a, b;
1929
 
1930
	getarrr(ir);
1931
	a = reg.r[ra];
1932
	b = reg.r[rb];
1933
	if(trace)
1934
		itrace("tw\t#%.2x,r%d,r%d", rd, ra, rb);
1935
	if(a < b && rd&0x10 ||
1936
	   a > b && rd&0x08 ||
1937
	   a == b && rd&0x04 ||
1938
	   (ulong)a < b && rd&0x02 ||
1939
	   (ulong)a > b && rd&0x01) {
1940
		Bprint(bioout, "program_exception (trap type)\n");
1941
		longjmp(errjmp, 0);
1942
	}
1943
}
1944
 
1945
void
1946
sync(ulong ir)
1947
{
1948
	USED(ir);
1949
	if(trace)
1950
		itrace("sync");
1951
}
1952
 
1953
void
1954
icbi(ulong ir)
1955
{
1956
	int rd, ra, rb;
1957
 
1958
	if(ir & Rc)
1959
		undef(ir);
1960
	getarrr(ir);
1961
	USED(rd);
1962
	if(trace)
1963
		itrace("%s\tr%d,r%d", ci->name, ra, rb);
1964
}
1965
 
1966
void
1967
dcbf(ulong ir)
1968
{
1969
	int rd, ra, rb;
1970
 
1971
	if(ir & Rc)
1972
		undef(ir);
1973
	getarrr(ir);
1974
	USED(rd);
1975
	if(trace)
1976
		itrace("%s\tr%d,r%d", ci->name, ra, rb);
1977
}
1978
 
1979
void
1980
dcbst(ulong ir)
1981
{
1982
	int rd, ra, rb;
1983
 
1984
	if(ir & Rc)
1985
		undef(ir);
1986
	getarrr(ir);
1987
	USED(rd);
1988
	if(trace)
1989
		itrace("%s\tr%d,r%d", ci->name, ra, rb);
1990
}
1991
 
1992
void
1993
dcbt(ulong ir)
1994
{
1995
	int rd, ra, rb;
1996
 
1997
	if(ir & Rc)
1998
		undef(ir);
1999
	getarrr(ir);
2000
	USED(rd);
2001
	if(trace)
2002
		itrace("%s\tr%d,r%d", ci->name, ra, rb);
2003
}
2004
 
2005
void
2006
dcbtst(ulong ir)
2007
{
2008
	int rd, ra, rb;
2009
 
2010
	if(ir & Rc)
2011
		undef(ir);
2012
	getarrr(ir);
2013
	USED(rd);
2014
	if(trace)
2015
		itrace("%s\tr%d,r%d", ci->name, ra, rb);
2016
}
2017
 
2018
void
2019
dcbz(ulong ir)
2020
{
2021
	int rd, ra, rb;
2022
 
2023
	if(ir & Rc)
2024
		undef(ir);
2025
	getarrr(ir);
2026
	USED(rd);
2027
	if(trace)
2028
		itrace("%s\tr%d,r%d", ci->name, ra, rb);
2029
}