Loading...
   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
/*
 * Copyright (c) 2000-2007 Apple Computer, Inc. All rights reserved.
 *
 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. The rights granted to you under the License
 * may not be used to create, or enable the creation or redistribution of,
 * unlawful or unlicensed copies of an Apple operating system, or to
 * circumvent, violate, or enable the circumvention or violation of, any
 * terms of an Apple operating system software license agreement.
 * 
 * Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 * 
 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
 */
/* 																							
 	Emulate.s 

	Emulate instructions and traps.

	Lovingly crafted by Bill Angell using traditional methods and only natural or recycled materials.
	No animal products are used other than rendered otter bile and deep fried pork lard.

*/

#include <ppc/asm.h>
#include <ppc/proc_reg.h>
#include <ppc/exception.h>
#include <ppc/cpu_capabilities.h>
#include <mach/machine/vm_param.h>
#include <assym.s>

#define traceInst 30
#define dssAllDone 29

;			General stuff what happens here:
;				1)	All general context saved, interrupts off, translation off
;				2)	Vector and floating point disabled, but there may be live context.
;					This code is responsible for saving and restoring what is used. This
;					includes exception states, java mode, etc.
;				3)	No attempt is made to resolve page faults.  PTE misses are handled
;					automatically, but actual faults (ala copyin/copyout) are not. If 
;					a fault does occur, the exception that caused entry to the emulation
;					routine is remapped to either an instruction or data miss (depending
;					upon the stage detected) and redrived through the exception handler.
;					The only time that an instruction fault can happen is when a different
;					processor removes a mapping between our original fault and when we
;					fetch the assisted instruction. For an assisted instruction, data
;					faults should not occur (except in the MP case).  For a purely
;					emulated instruction, faults can occur.
;
;


			.align	5
			.globl	EXT(Emulate)

LEXT(Emulate)

			bf--	pf64Bitb,emn64					; Skip if not 64-bit
			b		EXT(Emulate64)					; Jump to the 64-bit code...
			
emn64:		mfsprg	r31,0							; Get the per_proc
			lwz		r12,savesrr1+4(r13)				; Get the exception info
			rlwinm.	r0,r12,0,SRR1_PRG_ILL_INS_BIT,SRR1_PRG_ILL_INS_BIT	; Emulation candidate?
			lwz		r30,dgFlags(0)					; Get the flags
			beq+	eExit							; Nope, do not try to emulate...

			rlwinm.	r0,r30,0,enaDiagEMb,enaDiagEMb	; Do we want to try to emulate something?
			mfsprg	r28,2							; Get the processor features
			beq+	eExit							; No emulation allowed...

			rlwinm.	r28,r28,0,pfAltivecb,pfAltivecb	; Do we have Altivec on this machine?
			beq		eNoVect							; Nope, no Altivec...
			
			dssall									; We need to kill streams because we are going to flip to problem state
			sync

eNoVect:	bl		eIFetch							; Get the instruction image
			bne-	eRedriveAsISI					; Go redrive this as an ISI...	

			rlwinm.	r0,r10,0,0,5					; See if we have the "special" op code here
			rlwinm	r20,r10,16,22,31				; Set rS/rD and rA
			bne+	eExit							; Not special op, ignore...

			rlwinm	r0,r10,31,22,31					; Extract the sub op code
			crclr	cr1_eq							; Clear
			rlwimi	r20,r10,14,15,16				; Move bits 29 and 30 of instruction to 15 and 16 of DSISR
			cmplwi	r0,790							; lhbrx?
			rlwimi	r20,r10,8,17,17					; Move bit 25 to bit 17
			cror	cr1_eq,cr1_eq,cr0_eq			; Remember
			cmplwi	r0,534							; lwbrx?
			rlwimi	r20,r10,3,18,21					; Move bit 21-24 to bit 18-21
			cror	cr1_eq,cr1_eq,cr0_eq			; Remember
			cmplwi	r0,918							; sthbrx?
			cror	cr1_eq,cr1_eq,cr0_eq			; Remember
			cmplwi	r0,662							; stwbrx?
			cror	cr1_eq,cr1_eq,cr0_eq			; Remember
			cmplwi	r0,1014							; dcbz?
			cror	cr1_eq,cr1_eq,cr0_eq			; Remember
			cmplwi	r0,533							; lswx?
			cror	cr1_eq,cr1_eq,cr0_eq			; Remember
			cmplwi	r0,661							; stswx?
			cror	cr1_eq,cr1_eq,cr0_eq			; Remember
			bne		cr1_eq,eNotIndex				; Go check non-index forms...

			rlwinm.	r21,r10,19,24,28				; Extract index to rA to build EA
			rlwinm	r22,r10,24,24,28				; Extract index to rB
			addi	r24,r13,saver0+4				; Point to the start of registers
			li		r19,0							; Assume 0 base
			beq		eZeroBase						; Yes...
			lwzx	r19,r24,r21						; Get the base register value
			
eZeroBase:	lwzx	r22,r24,r22						; Get the index value
			add		r22,r22,r19						; Get DAR
			b		eFinishUp						; Done, go finish up...
						
eNotIndex:	cmplwi	r0,725							; stswi?
			cror	cr1_eq,cr1_eq,cr0_eq			; Remember
			cmplwi	r0,597							; lswi?
			cror	cr1_eq,cr1_eq,cr0_eq			; Remember
			bne		cr1,eExit						; Not one we handle...
	
			rlwinm.	r21,r10,19,24,28				; Extract index to rA to build EA
			addi	r24,r13,saver0+4				; Point to the start of registers
			li		r22,0							; Assume 0 base
			beq		eFinishUp						; Yes, it is...
			lwzx	r22,r24,r21						; Get the base register value
			
eFinishUp:	stw		r20,savedsisr(r13)				; Set the DSISR
			li		r11,T_ALIGNMENT					; Get the exception code
			stw		r22,savedar+4(r13)				; Save the DAR
			stw		r11,saveexception(r13)			; Set the exception code
			b		EXT(AlignAssist)				; Go emulate the handler...


eExit:		b		EXT(EmulExit)					; Just return for now...


;
;			Fetch the failing instruction.
;			Image returned in R10 if CR0_EQ is false, otherwise, an ISI should be generated.
;			R1 has the DSISR if access failed.
;

			.align	5

eIFetch:	lwz		r23,savesrr1+4(r13)				; Get old MSR
			mflr	r28								; Save return

			rlwinm	r3,r23,32-MSR_DR_BIT+MSR_IR_BIT,MSR_DR_BIT,MSR_DR_BIT	; Move IR to DR for ifetch
			mfmsr	r30								; Save the MSR for now
			rlwimi	r3,r23,32-MSR_RI_BIT+MSR_DR_BIT,MSR_RI_BIT,MSR_RI_BIT	; Move DR to RI for ifetch
			
			lwz		r23,savesrr0+4(r13)				; Get instruction address
			or		r3,r23,r3						; Turn on the DR and RI bit if translation was on
			
			crset	cr0_eq							; Set this to see if we failed
			mtmsr	r3								; Flip RI and, if IR was set, DR
			isync
			
			lwz		r10,0(r23)						; Fetch the instruction
			
			mtmsr	r30								; Trans and RI off
			isync
			
			mtlr	r28								; Restore the LR
			blr										; Return with instruction image in R10


;
;			Redrive as an ISI
;

eRedriveAsISI:
			lwz		r6,savesrr1+4(r13)				; Get the srr1 value
			lwz		r4,SAVflags(r13)				; Pick up the flags
			li		r11,T_INSTRUCTION_ACCESS		; Set failing instruction fetch code
			rlwimi	r6,r1,0,1,4						; Move the DSISR bits to the SRR1
			oris	r4,r4,hi16(SAVredrive)			; Set the redrive bit
			stw		r11,saveexception(r13)			; Set the replacement code
			stw		r4,SAVflags(r13)				; Set redrive request
			stw		r6,savesrr1+4(r13)				; Set the srr1 value
			b		EXT(EmulExit)					; Bail out to handle ISI...


;
;			This code emulates instructions that have failed because of operand 
;			alignment.  We decode the DSISR to figure out what we need to do.
;
;			DSISR:
;				0001FC00 - Instruction designation
#define iFloat 12
#define iOptype1 15
#define iOptype2 16
#define iOptype3 18
#define iOptype4 19
#define iUpdate 17
#define iStore 20
#define iDouble 21
#define iNotify 22
;				000003E0 - Target/Source register
;				0000001F - Register to update if update form
;

			.align	5
			.globl	EXT(AlignAssist)

LEXT(AlignAssist)
			bf--	pf64Bitb,aan64					; Skip if not 64-bit
			b		EXT(AlignAssist64)				; Jump to the 64-bit code...
			
aan64:		lwz		r20,savedsisr(r13)				; Get the DSISR
			li		r0,0							; Assume we emulate
			mfsprg	r31,0							; Get the per_proc
			mtcrf	0x10,r20						; Put instruction ID in CR for later
			lwz		r21,spcFlags(r31)				; Grab the special flags
			stw		r0,savemisc3(r13)				; Assume that we emulate ok
			mtcrf	0x08,r20						; Put instruction ID in CR for later
			rlwinm.	r0,r21,0,runningVMbit,runningVMbit	; Are we running a VM?
			mtcrf	0x04,r20						; Put instruction ID in CR for later
			lwz		r22,savesrr1+4(r13)				; Get the SRR1
			bne-	aaPassAlong						; We are in a VM, no emulation for alignment exceptions...
			lwz		r19,dgFlags(0)					; Get the diagnostics flags
			crxor	iFloat,iOptype1,iOptype2		; Set this to 0 if both bits are either 0 or 1
			mr		r26,r20							; Save the DSISR
			rlwinm.	r0,r22,0,MSR_SE_BIT,MSR_SE_BIT	; Were we single stepping?
			lwz		r23,savedar+4(r13)				; Pick up the address that we want to access
			crnot	traceInst,cr0_eq				; Remember if trace is on
			
			rlwinm.	r0,r19,0,enaNotifyEMb,enaNotifyEMb	; Should we notify that an alignment exception happened?
			mfmsr	r30								; Save the MSR for now
			crnot	iNotify,cr0_eq					; Remember to tell someone we did this				
			li		r29,emfp0						; Point to work area
			crxor	iFloat,iFloat,iOptype3			; Set true if we have a floating point instruction
			dcbz	r29,r31							; Clear and allocate a cache line for us to work in
			rlwinm	r24,r20,3,24,28					; Get displacement to register to update if update form
			rlwimi	r20,r20,24,28,28				; Move load/store indication to the bottom of index
			rlwinm	r22,r22,0,MSR_DR_BIT,MSR_DR_BIT	; Move rupt DR to DR for ifetch
			rlwimi	r20,r20,26,27,27				; Move single/double indication to just above the bottom
			rlwimi	r22,r22,32-MSR_RI_BIT+MSR_DR_BIT,MSR_RI_BIT,MSR_RI_BIT	; Move DR to RI for i-fetch
			lis		r29,hi16(EXT(aaFPopTable))		; High part of FP branch table
			or		r22,r30,r22						; Set the DR and RI bits if translation was on
			bf-		iFloat,aaNotFloat				; This is not a floating point instruction...
			ori		r29,r29,lo16(EXT(aaFPopTable))	; Low part of FP branch table
			
			rlwimi	r29,r20,0,22,28					; Index into table based upon register||iDouble||iStore
			mtctr	r29								; Get set to call the function	
			bt		iStore,aaFPstore				; This is an FP store...
		
;
;			Here we handle floating point loads
;			

aaFPload:	crset	cr0_eq							; Set this to see if we failed
			mtmsr	r22								; Flip DR, RI
			isync
			
			lwz		r10,0(r23)						; Get the first word
			bf-		cr0_eq,aaLdNotDbl				; Jump out if we DSIed...
			bf		iDouble,aaLdNotDbl				; this is not a double...
			lwz		r11,4(r23)						; Get the second half
			
aaLdNotDbl:	mr		r4,r0							; Save the DAR if we failed the access
			
			mtmsr	r30								; Turn off translation again
			isync
			
			bf-		cr0_eq,aaRedriveAsDSI			; Go redrive this as a DSI...	
			
			stw		r10,emfp0(r31)					; Save the first half
			stw		r11,emfp0+4(r31)				; Save the second half, just in case we need it
			
			bctrl									; Go set the target FP register

			b		aaComExit						; All done, go exit...			
		
;
;			Here we handle floating point stores
;			

			.align	5

aaFPstore:	bctrl									; Go save the source FP register
			
			lwz		r10,emfp0(r31)					; Get first word
			crandc	iDouble,iDouble,iOptype4		; Change to 4-byte access if stfiwx
			lwz		r11,emfp0+4(r31)				; and the second
			bf+		iOptype4,aaNotstfiwx			; This is not a stfiwx...
			mr		r10,r11							; The stfiwx wants to store the second half

aaNotstfiwx:
			crset	cr0_eq							; Set this to see if we failed
			mtmsr	r22								; Flip DR, RI
			isync
			
			stw		r10,0(r23)						; Save the first word
			bf-		cr0_eq,aaStNotDbl				; Jump out if we DSIed...
			bf		iDouble,aaStNotDbl				; this is not a double...
			stw		r11,4(r23)						; Save the second half
			
aaStNotDbl:	mr		r4,r0							; Save the DAR if we failed the access
			mtmsr	r30								; Turn off
			isync
			
			bf-		cr0_eq,aaRedriveAsDSI			; Go redrive this as a DSI...

;
;			Common exit routines
;

aaComExit:	lwz		r10,savesrr0+4(r13)				; Get the failing instruction address
			add		r24,r24,r13						; Offset to update register
			li		r11,T_IN_VAIN					; Assume we are all done
			addi	r10,r10,4						; Step to the next instruction
			bf		iUpdate,aaComExNU				; Skip if not an update form...
			stw		r23,saver0+4(r24)				; Update the target
			
aaComExNU:	lwz		r9,SAVflags(r13)				; Get the flags
			stw		r10,savesrr0+4(r13)				; Set new PC
			bt-		traceInst,aaComExitrd			; We are tracing, go emulate trace...
			bf+		iNotify,aaComExGo				; Nothing special here, go...
	
			li		r11,T_ALIGNMENT					; Set the we just did an alignment exception....
			
aaComExGo:	b		EXT(EmulExit)					; We are done, no tracing on...


;
;			This is not a floating point operation
;
;			The table of these emulation routines is indexed by taking the low order 4 bits of
;			the instruction code in the DSISR and subtracting 7.  If this comes up negative,
;			the instruction is not to be emulated.  Then we add bit 0 of the code * 4.  This
;			gives us a fairly compact and almost unique index.  Both lwm and stmw map to 0 so
;			that one needs to be further reduced, and we end up with holes at a few indexes.
;

			.align	5

aaNotFloat:
			lis		r19,hi16(aaEmTable)				; Point to high part of table address
			rlwinm	r3,r26,24,26,29					; Isolate last 4 bits of op type * 4
			rlwimi	r19,r26,20,27,27				; Get bit 0 of instruction code * 4 into bottom of table base
			addic.	r3,r3,-28						; Subtract 7*4 to adjust index
			ori		r19,r19,lo16(aaEmTable)			; Low part of table address
			blt-	aaPassAlong						; We do not handle any of these (lwarx, stwcx., eciwx, ecowx)...
			add		r19,r19,r3						; Point to emulation routine
			rlwinm	r18,r26,30,24,28				; Get the target/source register displacement

			mtctr	r19								; Set the routine address
			
			bctr									; Go emulate the instruction...

;
;			This is the table of non-floating point emulation routines.
;			It is indexed by the code immediately above.
		
			.align	5							

aaEmTable:
			b		aaLmwStmw						; This for lmw/stmw
			b		aaLswx							; This for lwwx
			b		aaLswi							; This for lswi
			b		aaStswx							; This for stswx
			b		aaStswi							; This for stswi
			b		aaLwbrx							; This for lwbrx
			b		aaPassAlong						; This an invalid index (6)
			b		aaStwbrx						; This for stwbrx
			b		aaPassAlong						; This an invalid index (8)
			b		aaLhbrx							; This for lhbrx
			b		aaPassAlong						; This an invalid index (A)
			b		aaSthbrx						; This for sthbrx
			b		aaDcbz							; This for dcbz
			b		aaPassAlong						; This an invalid index (D)
			b		aaPassAlong						; This an invalid index (E)
			b		aaPassAlong						; This an invalid index (F)


;
;			Here we handle the set up for the lmw and stmw.  After that, we split off to the
;			individual routines.
;
;			Note also that after some set up, all of the string instructions come through here as well.
;
			.align	5
						
aaLmwStmw:
			rlwinm	r17,r18,31,1,29					; Convert doublword based index to words
			li		r28,0							; Set no extra bytes to move (used for string instructions)
			subfic	r17,r17,32*4					; Calculate the length of the transfer

aaLSComm:	addi	r19,r13,saver0+4				; Offset to registers in savearea
			mr		r16,r23							; Make a hunk pointer
			
			bt		iUpdate,aaStmw					; This is the stmw...
			
;
;			Load multiple word
;

aaLmwNxt:	cmplwi	cr1,r17,8*4						; Is there enough to move 8?
			blt-	cr1,aaLmwNxtH					; Not enough for a full hunk...
			subi	r17,r17,8*4						; Back off for another hunk
			
			crset	cr0_eq							; Set this to see if we failed
			mtmsr	r22								; Flip DR, RI
			isync
		
			lwz		r2,0(r16)						; Load word 0
			bf-		cr0_eq,aaLmwB1					; Error, bail...
			lwz		r15,4(r16)						; Load word 1
			bf-		cr0_eq,aaLmwB1					; Error, bail...
			lwz		r14,8(r16)						; Load word 2
			bf-		cr0_eq,aaLmwB1					; Error, bail...
			lwz		r5,12(r16)						; Load word 3
			bf-		cr0_eq,aaLmwB1					; Error, bail...
			lwz		r6,16(r16)						; Load word 4
			bf-		cr0_eq,aaLmwB1					; Error, bail...
			lwz		r7,20(r16)						; Load word 5
			bf-		cr0_eq,aaLmwB1					; Error, bail...
			lwz		r8,24(r16)						; Load word 6
			bf-		cr0_eq,aaLmwB1					; Error, bail...
			lwz		r9,28(r16)						; Load word 7
		
aaLmwB1:	mr		r4,r0							; Remember DAR, jus in case we failed the access
			mtmsr	r30								; Turn off DR, RI
			isync

			bf-		cr0_eq,aaRedriveAsDSI			; We failed, go redrive this as a DSI...

			addi	r16,r16,8*4						; Point up to next input aread
		
			stwx	r2,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			stwx	r15,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			stwx	r14,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			stwx	r5,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			stwx	r6,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			stwx	r7,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			stwx	r8,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			stwx	r9,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed

			b		aaLmwNxt						; Do the next hunk...

			.align	5
			
aaLmwNxtH:	cmplwi	cr1,r17,4*4						; Do we have 4 left?
			blt		cr1,aaLmwL4						; Nope...

			subi	r17,r17,4*4						; Set count properly
			
			crset	cr0_eq							; Set this to see if we failed
			mtmsr	r22								; Flip DR, RI, and maybe PR on
			isync
		
			lwz		r2,0(r16)						; Load word 0
			bf-		cr0_eq,aaLmwB2					; Error, bail...
			lwz		r15,4(r16)						; Load word 1
			bf-		cr0_eq,aaLmwB2					; Error, bail...
			lwz		r14,8(r16)						; Load word 2
			bf-		cr0_eq,aaLmwB2					; Error, bail...
			lwz		r5,12(r16)						; Load word 3
		
aaLmwB2:	mr		r4,r0							; Remember DAR, jus in case we failed the access
			mtmsr	r30								; Turn off DR, RI
			isync

			bf-		cr0_eq,aaRedriveAsDSI			; We failed, go redrive this as a DSI...
		
			addi	r16,r16,4*4						; Point up to next input aread
			
			stwx	r2,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			stwx	r15,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			stwx	r14,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			stwx	r5,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed

aaLmwL4:	or.		r5,r17,r28						; Do we have anything left?
			cmplwi	cr1,r17,(2*4)					; Do we have one, two, or three full words left?
			cmplwi	cr2,r17,0						; Do we have no full words left?
			beq		aaComExit						; Nothing left...

			crset	cr0_eq							; Set this to see if we failed
			mtmsr	r22								; Flip DR, RI, and maybe PR on
			isync

			beq-	cr2,aaLmwBy						; No full words, get bytes...
			
			lwz		r2,0(r16)						; Pick up first word
			bf-		cr0_eq,aaLmwDn					; Read failed, escape...
			addi	r16,r16,4						; Next input location
			blt		cr1,aaLmwBy						; We only had one, we are done...

			lwz		r15,0(r16)						; Pick up second word
			bf-		cr0_eq,aaLmwDn					; Read failed, escape...
			addi	r16,r16,4						; Next input location
			beq		cr1,aaLmwBy						; We had two, we are done...

			lwz		r14,0(r16)						; Load word 3
			addi	r16,r16,4						; Next input location

aaLmwBy:	cmplwi	cr2,r28,0						; Any trailing bytes to do?
			li		r8,0							; Clear second trailing byte
			cmplwi	cr1,r28,2						; Check for 1, 2, or 3
			li		r9,0							; Clear third trailing byte
			beq+	cr2,aaLmwDn						; No trailing bytes...
			
			lbz		r5,0(r16)						; Pick up first trailing byte
			bf-		cr0_eq,aaLmwDn					; Read failed, escape...
			blt		cr1,aaLmwDn						; We only had one, we are done...

			lbz		r8,1(r16)						; Pick up second trailing byte
			bf-		cr0_eq,aaLmwDn					; Read failed, escape...
			beq		cr1,aaLmwDn						; We had two, we are done...

			lbz		r9,2(r16)						; Get last trailing byte
			

aaLmwDn:	rlwinm	r5,r5,24,0,7					; Move first byte to top
			cmplwi	cr2,r17,0						; Any full words to do?
			mr		r4,r0							; Remember DAR, just in case we failed the access
			rlwimi	r9,r8,8,16,23					; Move second byte above third byte
			cmplwi	cr1,r17,(2*4)					; Do we have one, two, or three full words left?
			mr		r3,r30							; Set the normal MSR
			rlwimi	r5,r9,8,8,23					; Move bytes 1 and 2 after 0

			mtmsr	r30								; Turn off DR, RI
			isync

			bf-		cr0_eq,aaRedriveAsDSI			; We failed, go redrive this as a DSI...

			beq-	cr2,aaLmwCb						; No full words, copy bytes...

			stwx	r2,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			blt		cr1,aaLmwCb						; We only had one, we are done...
			
			stwx	r15,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			beq		cr1,aaLmwCb						; We had two, we are done...

			stwx	r14,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed

aaLmwCb:	mr.		r28,r28							; Any trailing bytes to do?
			beq+	aaComExit						; Nope, leave...

			stwx	r5,r19,r18						; Store register
						
			b		aaComExit						; We are done....

;
;			Store multiple word
;

			.align	5

aaStmw:
			crclr	iUpdate							; Make sure we do not think this is an update form

aaStmwNxt:	cmplwi	cr1,r17,8*4						; Is there enough to move 8?
			blt-	cr1,aaStmwNxtH					; Not enough for a full hunk...
			subi	r17,r17,8*4						; Back off for another hunk
		
			lwzx	r2,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			lwzx	r15,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			lwzx	r14,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			lwzx	r5,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			lwzx	r6,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			lwzx	r7,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			lwzx	r8,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			lwzx	r9,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			
			crset	cr0_eq							; Set this to see if we failed
			mtmsr	r22								; Flip DR, RI, and maybe PR on
			isync

			stw		r2,0(r16)						; Store word 0
			bf-		cr0_eq,aaStmwB1					; Error, bail...
			stw		r15,4(r16)						; Store word 1
			bf-		cr0_eq,aaStmwB1					; Error, bail...
			stw		r14,8(r16)						; Store word 2
			bf-		cr0_eq,aaStmwB1					; Error, bail...
			stw		r5,12(r16)						; Store word 3
			bf-		cr0_eq,aaStmwB1					; Error, bail...
			stw		r6,16(r16)						; Store word 4
			bf-		cr0_eq,aaStmwB1					; Error, bail...
			stw		r7,20(r16)						; Store word 5
			bf-		cr0_eq,aaStmwB1					; Error, bail...
			stw		r8,24(r16)						; Store word 6
			bf-		cr0_eq,aaStmwB1					; Error, bail...
			stw		r9,28(r16)						; Store word 7
		
			addi	r16,r16,8*4						; Point up to next output aread
		
		
aaStmwB1:	mr		r4,r0							; Remember DAR, jus in case we failed the access
			mtmsr	r30								; Normal MSR
			isync

			bt-		cr0_eq,aaStmwNxt				; We have more to do and no failed access...
			b		aaRedriveAsDSI					; We failed, go redrive this as a DSI...

			.align	5
			
aaStmwNxtH:	cmplwi	cr1,r17,(4*4)					; Do we have at least 4 left?
			blt		cr1,aaStmwL4					; Nope...
			subi	r17,r17,4*4						; Set count properly

			lwzx	r2,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			lwzx	r15,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			lwzx	r14,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			lwzx	r5,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			
			crset	cr0_eq							; Set this to see if we failed
			mtmsr	r22								; Flip DR, RI
			isync
		
			stw		r2,0(r16)						; Store word 0
			bf-		cr0_eq,aaStmwB2					; Error, bail...
			stw		r15,4(r16)						; Store word 1
			bf-		cr0_eq,aaStmwB2					; Error, bail...
			stw		r14,8(r16)						; Store word 2
			bf-		cr0_eq,aaStmwB2					; Error, bail...
			stw		r5,12(r16)						; Store word 3

			addi	r16,r16,4*4						; Point up to next input aread
		
aaStmwB2:	mr		r4,r0							; Remember DAR, jus in case we failed the access
			mtmsr	r30								; Normal MSR
			isync

			bf-		cr0_eq,aaRedriveAsDSI			; We failed, go redrive this as a DSI...

aaStmwL4:	or.		r5,r17,r28						; Do we have anything left to do?
			cmplwi	cr1,r17,(2*4)					; Do we have one, two, or three left?
			cmplwi	cr2,r17,0						; Do we have no full words left?
			beq		aaComExit						; Nothing left...

			beq-	cr2,aaStmwBy1					; No full words, check out bytes

			lwzx	r2,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			blt		cr1,aaStmwBy1					; We only had one, go save it...
			
			lwzx	r15,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			beq		cr1,aaStmwBy1					; We had two, go save it...
			
			lwzx	r14,r19,r18						; Store register
			addi	r18,r18,8						; Next register
			rlwinm	r18,r18,0,24,28					; Wrap back to 0 if needed
			
aaStmwBy1:	mr.		r28,r28							; Do we have any trailing bytes?
			beq+	aaStmwSt						; Nope...
			
			lwzx	r5,r19,r18						; Yes, pick up one extra register
			
aaStmwSt:	crset	cr0_eq							; Set this to see if we failed
			mtmsr	r22								; Flip DR, RI
			isync

			beq-	cr2,aaStmwBy2					; No words, check trailing bytes...					

			stw		r2,0(r16)						; Save first word
			bf-		cr0_eq,aaStmwDn					; Store failed, escape...
			addi	r16,r16,4						; Bump sink
			blt		cr1,aaStmwBy2					; We only had one, we are done...

			stw		r15,0(r16)						; Save second word
			bf-		cr0_eq,aaStmwDn					; Store failed, escape...
			addi	r16,r16,4						; Bump sink
			beq		cr1,aaStmwBy2					; We had two, we are done...

			stw		r14,0(r16)						; Save third word
			bf-		cr0_eq,aaStmwDn					; Store failed, escape...
			addi	r16,r16,4						; Bump sink
				
aaStmwBy2:	rlwinm	r2,r5,8,24,31					; Get byte 0
			cmplwi	cr2,r28,0						; Any trailing bytes to do?
			rlwinm	r14,r5,24,24,31					; Get byte 3
			li		r8,0							; Clear second trailing byte
			cmplwi	cr1,r28,2						; Check for 1, 2, or 3
			li		r9,0							; Clear third trailing byte
			beq+	cr2,aaStmwDn					; No trailing bytes...
			rlwinm	r15,r5,16,24,31					; Get byte 1

			stb		r2,0(r16)						; Save first byte
			bf-		cr0_eq,aaStmwDn					; Read failed, escape...
			blt		cr1,aaStmwDn					; We only had one, we are done...

			stb		r15,1(r16)						; Save second byte
			bf-		cr0_eq,aaStmwDn					; Read failed, escape...
			beq		cr1,aaStmwDn					; We had two, we are done...

			stb		r14,2(r16)						; Save third byte

aaStmwDn:	mr		r4,r0							; Remember DAR, jus in case we failed the access
			mtmsr	r30								; Normal MSR
			isync

			bf-		cr0_eq,aaRedriveAsDSI			; We failed, go redrive this as a DSI...

			b		aaComExit						; We are done....

	
;
;			Load String Indexed
;

			.align	5
			
aaLswx:		lwz		r17,savexer+4(r13)				; Pick up the XER
			crclr	iUpdate							; Make sure we think this the load form
			rlwinm.	r25,r17,0,25,31					; Get the number of bytes to load
			rlwinm	r28,r17,0,30,31					; Get the number of bytes past an even word
			beq-	aaComExit						; Do nothing if 0 length...
			xor		r17,r25,r28						; Round down to an even word boundary
			b		aaLSComm						; Join up with common load/store code...

	
;
;			Load String Immediate
;

			.align	5

aaLswi:		mr		r9,r23							; Save the DAR
			bl		eIFetch							; Get the instruction image
			bne-	eRedriveAsISI					; Go redrive this as an ISI...	
			rlwinm	r25,r10,21,27,31				; Get the number of bytes to load
			crclr	iUpdate							; Make sure we think this the load form
			subi	r25,r25,1						; Back off by 1
			rlwinm	r25,r25,0,27,31					; Clear back down
			addi	r25,r25,1						; Add back the 1 to convert 0 to 32
			rlwinm	r28,r25,0,30,31					; Get the number of bytes past an even word
			xor		r17,r25,r28						; Round down to an even word boundary
			mr		r23,r9							; Move back the DAR
			b		aaLSComm						; Join up with common load/store code...
	
;
;			Store String Indexed
;

			.align	5

aaStswx:	lwz		r17,savexer+4(r13)				; Pick up the XER
			crclr	iUpdate							; Make sure this is clear in case we have 0 length
			rlwinm.	r25,r17,0,25,31					; Get the number of bytes to load
			rlwinm	r28,r17,0,30,31					; Get the number of bytes past an even word
			beq-	aaComExit						; Do nothing if 0 length...
			xor		r17,r25,r28						; Round down to an even word boundary
			crset	iUpdate							; Make sure we think this the store form
			b		aaLSComm						; Join up with common load/store code...

	
;
;			Store String Immediate
;

			.align	5

aaStswi:	mr		r9,r23							; Save the DAR
			bl		eIFetch							; Get the instruction image
			bne-	eRedriveAsISI					; Go redrive this as an ISI...	
			rlwinm	r25,r10,21,27,31				; Get the number of bytes to load
			crclr	iUpdate							; Make sure we think this the load form
			subi	r25,r25,1						; Back off by 1
			rlwinm	r25,r25,0,27,31					; Clear back down
			addi	r25,r25,1						; Add back the 1 to convert 0 to 32
			rlwinm	r28,r25,21,30,31				; Get the number of bytes past an even word
			xor		r17,r25,r28						; Round down to an even word boundary
			mr		r23,r9							; Move back the DAR
			b		aaLSComm						; Join up with common load/store code...
	

;
;			Load byte-reversed word
;

			.align	5

aaLwbrx:
			add		r18,r18,r13						; Index to source register

			crset	cr0_eq							; Set this to see if we failed
			mtmsr	r22								; Flip DR, RI, and maybe PR on
			isync
		
			lwz		r11,0(r23)						; Load the word
		
			mr		r4,r0							; Save the DAR if we failed the access
			mtmsr	r30								; Restore normal MSR
			isync
			
			bf-		cr0_eq,aaRedriveAsDSI			; We failed, go redrive this as a DSI...
			
			rlwinm	r10,r11,8,0,31					; Get byte 0 to 3 and byte 2 to 1
			rlwimi	r10,r11,24,16,23				; Move byte 1 to byte 2
			rlwimi	r10,r11,24,0,7					; Move byte 3 to byte 0
		
			stw		r10,saver0+4(r18)				; Set the register

			b		aaComExit						; All done, go exit...



;
;			Store byte-reversed word
;

			.align	5

aaStwbrx:
			add		r18,r18,r13						; Index to source register
			lwz		r11,saver0+4(r18)				; Get the register to store

			rlwinm	r10,r11,8,0,31					; Get byte 0 to 3 and byte 2 to 1
			rlwimi	r10,r11,24,16,23				; Move byte 1 to byte 2
			rlwimi	r10,r11,24,0,7					; Move byte 3 to byte 0
			
			crset	cr0_eq							; Set this to see if we failed
			mtmsr	r22								; Flip DR, RI, and maybe PR on
			isync
		
			stw		r10,0(r23)						; Store the reversed halfword
		
			mr		r4,r0							; Save the DAR if we failed the access
			mtmsr	r30								; Restore normal MSR
			isync
			
			bt+		cr0_eq,aaComExit				; All done, go exit...
			b		aaRedriveAsDSI					; We failed, go redrive this as a DSI...	



;
;			Load byte-reversed halfword
;

			.align	5

aaLhbrx:
			add		r18,r18,r13						; Index to source register

			crset	cr0_eq							; Set this to see if we failed
			mtmsr	r22								; Flip DR, RI, and maybe PR on
			isync
		
			lhz		r11,0(r23)						; Load the halfword
		
			mr		r4,r0							; Save the DAR if we failed the access
			mtmsr	r30								; Restore normal MSR
			isync

			bf-		cr0_eq,aaRedriveAsDSI			; We failed, go redrive this as a DSI...
			
			rlwinm	r10,r11,8,16,23					; Rotate bottom byte up one and clear everything else
			rlwimi	r10,r11,24,24,31				; Put old second from bottom into bottom
		
			stw		r10,saver0+4(r18)				; Set the register

			b		aaComExit						; All done, go exit...


;
;			Store byte-reversed halfword
;

			.align	5

aaSthbrx:
			add		r18,r18,r13						; Index to source register
			lwz		r10,saver0+4(r18)				; Get the register to store
			rlwinm	r10,r10,8,0,31					; Rotate bottom byte up one
			rlwimi	r10,r10,16,24,31				; Put old second from bottom into bottom
			
			crset	cr0_eq							; Set this to see if we failed
			mtmsr	r22								; Flip DR, RI, and maybe PR on
			isync
		
			sth		r10,0(r23)						; Store the reversed halfword
		
			mr		r4,r0							; Save the DAR if we failed the access
			mtmsr	r30								; Restore normal MSR
			isync

			bt+		cr0_eq,aaComExit				; All done, go exit...
			b		aaRedriveAsDSI					; We failed, go redrive this as a DSI...	

;
;			Data cache block zero
;

			.align	5

aaDcbz:			
            lwz     r0,savesrr0+4(r13)              ; get instruction address
            li		r4,_COMM_PAGE_BASE_ADDRESS
			rlwinm	r23,r23,0,0,26					; Round EA back to a 32-byte boundary
            sub     r4,r0,r4                        ; compute instruction offset from base of commpage
            cmplwi  r4,_COMM_PAGE_AREA_USED         ; did fault occur in commpage?
            bge+    aaDcbz1                         ; skip if not in commpage
            lwz		r4,savecr(r13)                  ; if we take a dcbz in the commpage...
            rlwinm	r4,r4,0,0,27                    ; ...clear users cr7 as a flag for commpage code
            stw		r4,savecr(r13)
aaDcbz1:
			crset	cr0_eq							; Set this to see if we failed
			li		r0,0							; Clear this out
			mtmsr	r22								; Flip DR, RI, and maybe PR on
			isync
			
			stw		r0,0(r23)						; Clear word	
			bne-	aaDcbzXit						; Got DSI, we are stopping...	
			stw		r0,4(r23)						; Clear word		
			bne-	aaDcbzXit						; Got DSI, we are stopping...	
			stw		r0,8(r23)						; Clear word		
			bne-	aaDcbzXit						; Got DSI, we are stopping...	
			stw		r0,12(r23)						; Clear word		
			bne-	aaDcbzXit						; Got DSI, we are stopping...	
			stw		r0,16(r23)						; Clear word		
			bne-	aaDcbzXit						; Got DSI, we are stopping...	
			stw		r0,20(r23)						; Clear word		
			bne-	aaDcbzXit						; Got DSI, we are stopping...	
			stw		r0,24(r23)						; Clear word		
			bne-	aaDcbzXit						; Got DSI, we are stopping...	
			stw		r0,28(r23)						; Clear word		
			
aaDcbzXit:	mr		r4,r0							; Save the DAR if we failed the access
			mtmsr	r30								; Restore normal MSR
			isync

			crclr	iUpdate							; Make sure we do not think this is an update form
			
			bt+		cr0_eq,aaComExit				; All done, go exit...
			b		aaRedriveAsDSI					; We failed, go redrive this as a DSI...	


;
;			Unhandled alignment exception, pass it along
;

aaPassAlong:
			li		r0,1							; Indicate that we failed to emulate
			stw		r0,savemisc3(r13)				; Assume that we emulate ok
			b		EXT(EmulExit)					




;
;			We go here to emulate a trace exception after we have handled alignment error
;

			.align	5
			
aaComExitrd:
			lis		r11,hi16(srr1clr)				; Get the bits we need to clear
			oris	r9,r9,hi16(SAVredrive)			; Set the redrive bit
			andc	r12,r12,r11						; Clear what needs to be cleared
			li		r11,T_TRACE						; Set trace interrupt
			stw		r9,SAVflags(r13)				; Set the flags
			stw		r11,saveexception(r13)			; Set the exception code
			b		EXT(EmulExit)					; Exit and do trace interrupt...
			


;
;			Redrive as a DSI

aaRedriveAsDSI:
			mr		r20,r1							; Save the DSISR
			mr		r21,r4
			lwz		r4,SAVflags(r13)				; Pick up the flags
			li		r11,T_DATA_ACCESS				; Set failing data access code
			oris	r4,r4,hi16(SAVredrive)			; Set the redrive bit
			stw		r20,savedsisr(r13)				; Set the DSISR of failed access
			stw		r21,savedar+4(r13)				; Set the address of the failed access
			stw		r11,saveexception(r13)			; Set the replacement code
			stw		r4,SAVflags(r13)				; Set redrive request
			b		EXT(EmulExit)					; Bail out to handle ISI...



;
;			Table of functions to load or store floating point registers
;			This table is indexed reg||size||dir.  That means that each
;			like load/store pair (e.g., lfd f31/stfd f31) are within the same
;			quadword, which is the current ifetch size.  We expect most of the
;			unaligned accesses to be part of copies, therefore, with this
;			organization, we will save the ifetch of the store after the load.
;

			.align	10								; Make sure we are on a 1k boundary
			.globl	EXT(aaFPopTable)
			
LEXT(aaFPopTable)
			lfs		f0,emfp0(r31)					; Load single variant
			blr

			stfs	f0,emfp0(r31)					; Store single variant
			blr
			
			lfd		f0,emfp0(r31)					; Load double variant
			blr
			
			stfd	f0,emfp0(r31)					; Store double variant
			blr

			lfs		f1,emfp0(r31)					; Load single variant
			blr

			stfs	f1,emfp0(r31)					; Store single variant
			blr
			
			lfd		f1,emfp0(r31)					; Load double variant
			blr
			
			stfd	f1,emfp0(r31)					; Store double variant
			blr

			lfs		f2,emfp0(r31)					; Load single variant
			blr

			stfs	f2,emfp0(r31)					; Store single variant
			blr
			
			lfd		f2,emfp0(r31)					; Load double variant
			blr
			
			stfd	f2,emfp0(r31)					; Store double variant
			blr

			lfs		f3,emfp0(r31)					; Load single variant
			blr

			stfs	f3,emfp0(r31)					; Store single variant
			blr
			
			lfd		f3,emfp0(r31)					; Load double variant
			blr
			
			stfd	f3,emfp0(r31)					; Store double variant
			blr

			lfs		f4,emfp0(r31)					; Load single variant
			blr

			stfs	f4,emfp0(r31)					; Store single variant
			blr
			
			lfd		f4,emfp0(r31)					; Load double variant
			blr
			
			stfd	f4,emfp0(r31)					; Store double variant
			blr

			lfs		f5,emfp0(r31)					; Load single variant
			blr

			stfs	f5,emfp0(r31)					; Store single variant
			blr
			
			lfd		f5,emfp0(r31)					; Load double variant
			blr
			
			stfd	f5,emfp0(r31)					; Store double variant
			blr

			lfs		f6,emfp0(r31)					; Load single variant
			blr

			stfs	f6,emfp0(r31)					; Store single variant
			blr
			
			lfd		f6,emfp0(r31)					; Load double variant
			blr
			
			stfd	f6,emfp0(r31)					; Store double variant
			blr

			lfs		f7,emfp0(r31)					; Load single variant
			blr

			stfs	f7,emfp0(r31)					; Store single variant
			blr
			
			lfd		f7,emfp0(r31)					; Load double variant
			blr
			
			stfd	f7,emfp0(r31)					; Store double variant
			blr

			lfs		f8,emfp0(r31)					; Load single variant
			blr

			stfs	f8,emfp0(r31)					; Store single variant
			blr
			
			lfd		f8,emfp0(r31)					; Load double variant
			blr
			
			stfd	f8,emfp0(r31)					; Store double variant
			blr

			lfs		f9,emfp0(r31)					; Load single variant
			blr

			stfs	f9,emfp0(r31)					; Store single variant
			blr
			
			lfd		f9,emfp0(r31)					; Load double variant
			blr
			
			stfd	f9,emfp0(r31)					; Store double variant
			blr

			lfs		f10,emfp0(r31)					; Load single variant
			blr

			stfs	f10,emfp0(r31)					; Store single variant
			blr
			
			lfd		f10,emfp0(r31)					; Load double variant
			blr
			
			stfd	f10,emfp0(r31)					; Store double variant
			blr

			lfs		f11,emfp0(r31)					; Load single variant
			blr

			stfs	f11,emfp0(r31)					; Store single variant
			blr
			
			lfd		f11,emfp0(r31)					; Load double variant
			blr
			
			stfd	f11,emfp0(r31)					; Store double variant
			blr

			lfs		f12,emfp0(r31)					; Load single variant
			blr

			stfs	f12,emfp0(r31)					; Store single variant
			blr
			
			lfd		f12,emfp0(r31)					; Load double variant
			blr
			
			stfd	f12,emfp0(r31)					; Store double variant
			blr

			lfs		f13,emfp0(r31)					; Load single variant
			blr

			stfs	f13,emfp0(r31)					; Store single variant
			blr
			
			lfd		f13,emfp0(r31)					; Load double variant
			blr
			
			stfd	f13,emfp0(r31)					; Store double variant
			blr

			lfs		f14,emfp0(r31)					; Load single variant
			blr

			stfs	f14,emfp0(r31)					; Store single variant
			blr
			
			lfd		f14,emfp0(r31)					; Load double variant
			blr
			
			stfd	f14,emfp0(r31)					; Store double variant
			blr

			lfs		f15,emfp0(r31)					; Load single variant
			blr

			stfs	f15,emfp0(r31)					; Store single variant
			blr
			
			lfd		f15,emfp0(r31)					; Load double variant
			blr
			
			stfd	f15,emfp0(r31)					; Store double variant
			blr

			lfs		f16,emfp0(r31)					; Load single variant
			blr

			stfs	f16,emfp0(r31)					; Store single variant
			blr
			
			lfd		f16,emfp0(r31)					; Load double variant
			blr
			
			stfd	f16,emfp0(r31)					; Store double variant
			blr

			lfs		f17,emfp0(r31)					; Load single variant
			blr

			stfs	f17,emfp0(r31)					; Store single variant
			blr
			
			lfd		f17,emfp0(r31)					; Load double variant
			blr
			
			stfd	f17,emfp0(r31)					; Store double variant
			blr

			lfs		f18,emfp0(r31)					; Load single variant
			blr

			stfs	f18,emfp0(r31)					; Store single variant
			blr
			
			lfd		f18,emfp0(r31)					; Load double variant
			blr
			
			stfd	f18,emfp0(r31)					; Store double variant
			blr

			lfs		f19,emfp0(r31)					; Load single variant
			blr

			stfs	f19,emfp0(r31)					; Store single variant
			blr
			
			lfd		f19,emfp0(r31)					; Load double variant
			blr
			
			stfd	f19,emfp0(r31)					; Store double variant
			blr

			lfs		f20,emfp0(r31)					; Load single variant
			blr

			stfs	f20,emfp0(r31)					; Store single variant
			blr
			
			lfd		f20,emfp0(r31)					; Load double variant
			blr
			
			stfd	f20,emfp0(r31)					; Store double variant
			blr

			lfs		f21,emfp0(r31)					; Load single variant
			blr

			stfs	f21,emfp0(r31)					; Store single variant
			blr
			
			lfd		f21,emfp0(r31)					; Load double variant
			blr
			
			stfd	f21,emfp0(r31)					; Store double variant
			blr

			lfs		f22,emfp0(r31)					; Load single variant
			blr

			stfs	f22,emfp0(r31)					; Store single variant
			blr
			
			lfd		f22,emfp0(r31)					; Load double variant
			blr
			
			stfd	f22,emfp0(r31)					; Store double variant
			blr

			lfs		f23,emfp0(r31)					; Load single variant
			blr

			stfs	f23,emfp0(r31)					; Store single variant
			blr
			
			lfd		f23,emfp0(r31)					; Load double variant
			blr
			
			stfd	f23,emfp0(r31)					; Store double variant
			blr

			lfs		f24,emfp0(r31)					; Load single variant
			blr

			stfs	f24,emfp0(r31)					; Store single variant
			blr
			
			lfd		f24,emfp0(r31)					; Load double variant
			blr
			
			stfd	f24,emfp0(r31)					; Store double variant
			blr

			lfs		f25,emfp0(r31)					; Load single variant
			blr

			stfs	f25,emfp0(r31)					; Store single variant
			blr
			
			lfd		f25,emfp0(r31)					; Load double variant
			blr
			
			stfd	f25,emfp0(r31)					; Store double variant
			blr

			lfs		f26,emfp0(r31)					; Load single variant
			blr

			stfs	f26,emfp0(r31)					; Store single variant
			blr
			
			lfd		f26,emfp0(r31)					; Load double variant
			blr
			
			stfd	f26,emfp0(r31)					; Store double variant
			blr

			lfs		f27,emfp0(r31)					; Load single variant
			blr

			stfs	f27,emfp0(r31)					; Store single variant
			blr
			
			lfd		f27,emfp0(r31)					; Load double variant
			blr
			
			stfd	f27,emfp0(r31)					; Store double variant
			blr

			lfs		f28,emfp0(r31)					; Load single variant
			blr

			stfs	f28,emfp0(r31)					; Store single variant
			blr
			
			lfd		f28,emfp0(r31)					; Load double variant
			blr
			
			stfd	f28,emfp0(r31)					; Store double variant
			blr

			lfs		f29,emfp0(r31)					; Load single variant
			blr

			stfs	f29,emfp0(r31)					; Store single variant
			blr
			
			lfd		f29,emfp0(r31)					; Load double variant
			blr
			
			stfd	f29,emfp0(r31)					; Store double variant
			blr

			lfs		f30,emfp0(r31)					; Load single variant
			blr

			stfs	f30,emfp0(r31)					; Store single variant
			blr
			
			lfd		f30,emfp0(r31)					; Load double variant
			blr
			
			stfd	f30,emfp0(r31)					; Store double variant
			blr

			lfs		f31,emfp0(r31)					; Load single variant
			blr

			stfs	f31,emfp0(r31)					; Store single variant
			blr
			
			lfd		f31,emfp0(r31)					; Load double variant
			blr
			
			stfd	f31,emfp0(r31)					; Store double variant
			blr