| 1 | /* |
| 2 | * Copyright (c) 2000-2007 Apple Computer, Inc. All rights reserved. |
| 3 | * |
| 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
| 5 | * |
| 6 | * This file contains Original Code and/or Modifications of Original Code |
| 7 | * as defined in and that are subject to the Apple Public Source License |
| 8 | * Version 2.0 (the 'License'). You may not use this file except in |
| 9 | * compliance with the License. The rights granted to you under the License |
| 10 | * may not be used to create, or enable the creation or redistribution of, |
| 11 | * unlawful or unlicensed copies of an Apple operating system, or to |
| 12 | * circumvent, violate, or enable the circumvention or violation of, any |
| 13 | * terms of an Apple operating system software license agreement. |
| 14 | * |
| 15 | * Please obtain a copy of the License at |
| 16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. |
| 17 | * |
| 18 | * The Original Code and all software distributed under the License are |
| 19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER |
| 20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
| 21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, |
| 22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
| 23 | * Please see the License for the specific language governing rights and |
| 24 | * limitations under the License. |
| 25 | * |
| 26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
| 27 | */ |
| 28 | /* |
| 29 | Emulate.s |
| 30 | |
| 31 | Emulate instructions and traps. |
| 32 | |
| 33 | Lovingly crafted by Bill Angell using traditional methods and only natural or recycled materials. |
| 34 | No animal products are used other than rendered otter bile and deep fried pork lard. |
| 35 | |
| 36 | */ |
| 37 | |
| 38 | #include <ppc/asm.h> |
| 39 | #include <ppc/proc_reg.h> |
| 40 | #include <ppc/exception.h> |
| 41 | #include <ppc/cpu_capabilities.h> |
| 42 | #include <mach/machine/vm_param.h> |
| 43 | #include <assym.s> |
| 44 | |
| 45 | #define traceInst 30 |
| 46 | #define dssAllDone 29 |
| 47 | |
| 48 | ; General stuff what happens here: |
| 49 | ; 1) All general context saved, interrupts off, translation off |
| 50 | ; 2) Vector and floating point disabled, but there may be live context. |
| 51 | ; This code is responsible for saving and restoring what is used. This |
| 52 | ; includes exception states, java mode, etc. |
| 53 | ; 3) No attempt is made to resolve page faults. PTE misses are handled |
| 54 | ; automatically, but actual faults (ala copyin/copyout) are not. If |
| 55 | ; a fault does occur, the exception that caused entry to the emulation |
| 56 | ; routine is remapped to either an instruction or data miss (depending |
| 57 | ; upon the stage detected) and redrived through the exception handler. |
| 58 | ; The only time that an instruction fault can happen is when a different |
| 59 | ; processor removes a mapping between our original fault and when we |
| 60 | ; fetch the assisted instruction. For an assisted instruction, data |
| 61 | ; faults should not occur (except in the MP case). For a purely |
| 62 | ; emulated instruction, faults can occur. |
| 63 | ; |
| 64 | ; |
| 65 | |
| 66 | |
| 67 | .align 5 |
| 68 | .globl EXT(Emulate) |
| 69 | |
| 70 | LEXT(Emulate) |
| 71 | |
| 72 | bf-- pf64Bitb,emn64 ; Skip if not 64-bit |
| 73 | b EXT(Emulate64) ; Jump to the 64-bit code... |
| 74 | |
| 75 | emn64: mfsprg r31,0 ; Get the per_proc |
| 76 | lwz r12,savesrr1+4(r13) ; Get the exception info |
| 77 | rlwinm. r0,r12,0,SRR1_PRG_ILL_INS_BIT,SRR1_PRG_ILL_INS_BIT ; Emulation candidate? |
| 78 | lwz r30,dgFlags(0) ; Get the flags |
| 79 | beq+ eExit ; Nope, do not try to emulate... |
| 80 | |
| 81 | rlwinm. r0,r30,0,enaDiagEMb,enaDiagEMb ; Do we want to try to emulate something? |
| 82 | mfsprg r28,2 ; Get the processor features |
| 83 | beq+ eExit ; No emulation allowed... |
| 84 | |
| 85 | rlwinm. r28,r28,0,pfAltivecb,pfAltivecb ; Do we have Altivec on this machine? |
| 86 | beq eNoVect ; Nope, no Altivec... |
| 87 | |
| 88 | dssall ; We need to kill streams because we are going to flip to problem state |
| 89 | sync |
| 90 | |
| 91 | eNoVect: bl eIFetch ; Get the instruction image |
| 92 | bne- eRedriveAsISI ; Go redrive this as an ISI... |
| 93 | |
| 94 | rlwinm. r0,r10,0,0,5 ; See if we have the "special" op code here |
| 95 | rlwinm r20,r10,16,22,31 ; Set rS/rD and rA |
| 96 | bne+ eExit ; Not special op, ignore... |
| 97 | |
| 98 | rlwinm r0,r10,31,22,31 ; Extract the sub op code |
| 99 | crclr cr1_eq ; Clear |
| 100 | rlwimi r20,r10,14,15,16 ; Move bits 29 and 30 of instruction to 15 and 16 of DSISR |
| 101 | cmplwi r0,790 ; lhbrx? |
| 102 | rlwimi r20,r10,8,17,17 ; Move bit 25 to bit 17 |
| 103 | cror cr1_eq,cr1_eq,cr0_eq ; Remember |
| 104 | cmplwi r0,534 ; lwbrx? |
| 105 | rlwimi r20,r10,3,18,21 ; Move bit 21-24 to bit 18-21 |
| 106 | cror cr1_eq,cr1_eq,cr0_eq ; Remember |
| 107 | cmplwi r0,918 ; sthbrx? |
| 108 | cror cr1_eq,cr1_eq,cr0_eq ; Remember |
| 109 | cmplwi r0,662 ; stwbrx? |
| 110 | cror cr1_eq,cr1_eq,cr0_eq ; Remember |
| 111 | cmplwi r0,1014 ; dcbz? |
| 112 | cror cr1_eq,cr1_eq,cr0_eq ; Remember |
| 113 | cmplwi r0,533 ; lswx? |
| 114 | cror cr1_eq,cr1_eq,cr0_eq ; Remember |
| 115 | cmplwi r0,661 ; stswx? |
| 116 | cror cr1_eq,cr1_eq,cr0_eq ; Remember |
| 117 | bne cr1_eq,eNotIndex ; Go check non-index forms... |
| 118 | |
| 119 | rlwinm. r21,r10,19,24,28 ; Extract index to rA to build EA |
| 120 | rlwinm r22,r10,24,24,28 ; Extract index to rB |
| 121 | addi r24,r13,saver0+4 ; Point to the start of registers |
| 122 | li r19,0 ; Assume 0 base |
| 123 | beq eZeroBase ; Yes... |
| 124 | lwzx r19,r24,r21 ; Get the base register value |
| 125 | |
| 126 | eZeroBase: lwzx r22,r24,r22 ; Get the index value |
| 127 | add r22,r22,r19 ; Get DAR |
| 128 | b eFinishUp ; Done, go finish up... |
| 129 | |
| 130 | eNotIndex: cmplwi r0,725 ; stswi? |
| 131 | cror cr1_eq,cr1_eq,cr0_eq ; Remember |
| 132 | cmplwi r0,597 ; lswi? |
| 133 | cror cr1_eq,cr1_eq,cr0_eq ; Remember |
| 134 | bne cr1,eExit ; Not one we handle... |
| 135 | |
| 136 | rlwinm. r21,r10,19,24,28 ; Extract index to rA to build EA |
| 137 | addi r24,r13,saver0+4 ; Point to the start of registers |
| 138 | li r22,0 ; Assume 0 base |
| 139 | beq eFinishUp ; Yes, it is... |
| 140 | lwzx r22,r24,r21 ; Get the base register value |
| 141 | |
| 142 | eFinishUp: stw r20,savedsisr(r13) ; Set the DSISR |
| 143 | li r11,T_ALIGNMENT ; Get the exception code |
| 144 | stw r22,savedar+4(r13) ; Save the DAR |
| 145 | stw r11,saveexception(r13) ; Set the exception code |
| 146 | b EXT(AlignAssist) ; Go emulate the handler... |
| 147 | |
| 148 | |
| 149 | eExit: b EXT(EmulExit) ; Just return for now... |
| 150 | |
| 151 | |
| 152 | ; |
| 153 | ; Fetch the failing instruction. |
| 154 | ; Image returned in R10 if CR0_EQ is false, otherwise, an ISI should be generated. |
| 155 | ; R1 has the DSISR if access failed. |
| 156 | ; |
| 157 | |
| 158 | .align 5 |
| 159 | |
| 160 | eIFetch: lwz r23,savesrr1+4(r13) ; Get old MSR |
| 161 | mflr r28 ; Save return |
| 162 | |
| 163 | rlwinm r3,r23,32-MSR_DR_BIT+MSR_IR_BIT,MSR_DR_BIT,MSR_DR_BIT ; Move IR to DR for ifetch |
| 164 | mfmsr r30 ; Save the MSR for now |
| 165 | rlwimi r3,r23,32-MSR_RI_BIT+MSR_DR_BIT,MSR_RI_BIT,MSR_RI_BIT ; Move DR to RI for ifetch |
| 166 | |
| 167 | lwz r23,savesrr0+4(r13) ; Get instruction address |
| 168 | or r3,r23,r3 ; Turn on the DR and RI bit if translation was on |
| 169 | |
| 170 | crset cr0_eq ; Set this to see if we failed |
| 171 | mtmsr r3 ; Flip RI and, if IR was set, DR |
| 172 | isync |
| 173 | |
| 174 | lwz r10,0(r23) ; Fetch the instruction |
| 175 | |
| 176 | mtmsr r30 ; Trans and RI off |
| 177 | isync |
| 178 | |
| 179 | mtlr r28 ; Restore the LR |
| 180 | blr ; Return with instruction image in R10 |
| 181 | |
| 182 | |
| 183 | ; |
| 184 | ; Redrive as an ISI |
| 185 | ; |
| 186 | |
| 187 | eRedriveAsISI: |
| 188 | lwz r6,savesrr1+4(r13) ; Get the srr1 value |
| 189 | lwz r4,SAVflags(r13) ; Pick up the flags |
| 190 | li r11,T_INSTRUCTION_ACCESS ; Set failing instruction fetch code |
| 191 | rlwimi r6,r1,0,1,4 ; Move the DSISR bits to the SRR1 |
| 192 | oris r4,r4,hi16(SAVredrive) ; Set the redrive bit |
| 193 | stw r11,saveexception(r13) ; Set the replacement code |
| 194 | stw r4,SAVflags(r13) ; Set redrive request |
| 195 | stw r6,savesrr1+4(r13) ; Set the srr1 value |
| 196 | b EXT(EmulExit) ; Bail out to handle ISI... |
| 197 | |
| 198 | |
| 199 | ; |
| 200 | ; This code emulates instructions that have failed because of operand |
| 201 | ; alignment. We decode the DSISR to figure out what we need to do. |
| 202 | ; |
| 203 | ; DSISR: |
| 204 | ; 0001FC00 - Instruction designation |
| 205 | #define iFloat 12 |
| 206 | #define iOptype1 15 |
| 207 | #define iOptype2 16 |
| 208 | #define iOptype3 18 |
| 209 | #define iOptype4 19 |
| 210 | #define iUpdate 17 |
| 211 | #define iStore 20 |
| 212 | #define iDouble 21 |
| 213 | #define iNotify 22 |
| 214 | ; 000003E0 - Target/Source register |
| 215 | ; 0000001F - Register to update if update form |
| 216 | ; |
| 217 | |
| 218 | .align 5 |
| 219 | .globl EXT(AlignAssist) |
| 220 | |
| 221 | LEXT(AlignAssist) |
| 222 | bf-- pf64Bitb,aan64 ; Skip if not 64-bit |
| 223 | b EXT(AlignAssist64) ; Jump to the 64-bit code... |
| 224 | |
| 225 | aan64: lwz r20,savedsisr(r13) ; Get the DSISR |
| 226 | li r0,0 ; Assume we emulate |
| 227 | mfsprg r31,0 ; Get the per_proc |
| 228 | mtcrf 0x10,r20 ; Put instruction ID in CR for later |
| 229 | lwz r21,spcFlags(r31) ; Grab the special flags |
| 230 | stw r0,savemisc3(r13) ; Assume that we emulate ok |
| 231 | mtcrf 0x08,r20 ; Put instruction ID in CR for later |
| 232 | rlwinm. r0,r21,0,runningVMbit,runningVMbit ; Are we running a VM? |
| 233 | mtcrf 0x04,r20 ; Put instruction ID in CR for later |
| 234 | lwz r22,savesrr1+4(r13) ; Get the SRR1 |
| 235 | bne- aaPassAlong ; We are in a VM, no emulation for alignment exceptions... |
| 236 | lwz r19,dgFlags(0) ; Get the diagnostics flags |
| 237 | crxor iFloat,iOptype1,iOptype2 ; Set this to 0 if both bits are either 0 or 1 |
| 238 | mr r26,r20 ; Save the DSISR |
| 239 | rlwinm. r0,r22,0,MSR_SE_BIT,MSR_SE_BIT ; Were we single stepping? |
| 240 | lwz r23,savedar+4(r13) ; Pick up the address that we want to access |
| 241 | crnot traceInst,cr0_eq ; Remember if trace is on |
| 242 | |
| 243 | rlwinm. r0,r19,0,enaNotifyEMb,enaNotifyEMb ; Should we notify that an alignment exception happened? |
| 244 | mfmsr r30 ; Save the MSR for now |
| 245 | crnot iNotify,cr0_eq ; Remember to tell someone we did this |
| 246 | li r29,emfp0 ; Point to work area |
| 247 | crxor iFloat,iFloat,iOptype3 ; Set true if we have a floating point instruction |
| 248 | dcbz r29,r31 ; Clear and allocate a cache line for us to work in |
| 249 | rlwinm r24,r20,3,24,28 ; Get displacement to register to update if update form |
| 250 | rlwimi r20,r20,24,28,28 ; Move load/store indication to the bottom of index |
| 251 | rlwinm r22,r22,0,MSR_DR_BIT,MSR_DR_BIT ; Move rupt DR to DR for ifetch |
| 252 | rlwimi r20,r20,26,27,27 ; Move single/double indication to just above the bottom |
| 253 | rlwimi r22,r22,32-MSR_RI_BIT+MSR_DR_BIT,MSR_RI_BIT,MSR_RI_BIT ; Move DR to RI for i-fetch |
| 254 | lis r29,hi16(EXT(aaFPopTable)) ; High part of FP branch table |
| 255 | or r22,r30,r22 ; Set the DR and RI bits if translation was on |
| 256 | bf- iFloat,aaNotFloat ; This is not a floating point instruction... |
| 257 | ori r29,r29,lo16(EXT(aaFPopTable)) ; Low part of FP branch table |
| 258 | |
| 259 | rlwimi r29,r20,0,22,28 ; Index into table based upon register||iDouble||iStore |
| 260 | mtctr r29 ; Get set to call the function |
| 261 | bt iStore,aaFPstore ; This is an FP store... |
| 262 | |
| 263 | ; |
| 264 | ; Here we handle floating point loads |
| 265 | ; |
| 266 | |
| 267 | aaFPload: crset cr0_eq ; Set this to see if we failed |
| 268 | mtmsr r22 ; Flip DR, RI |
| 269 | isync |
| 270 | |
| 271 | lwz r10,0(r23) ; Get the first word |
| 272 | bf- cr0_eq,aaLdNotDbl ; Jump out if we DSIed... |
| 273 | bf iDouble,aaLdNotDbl ; this is not a double... |
| 274 | lwz r11,4(r23) ; Get the second half |
| 275 | |
| 276 | aaLdNotDbl: mr r4,r0 ; Save the DAR if we failed the access |
| 277 | |
| 278 | mtmsr r30 ; Turn off translation again |
| 279 | isync |
| 280 | |
| 281 | bf- cr0_eq,aaRedriveAsDSI ; Go redrive this as a DSI... |
| 282 | |
| 283 | stw r10,emfp0(r31) ; Save the first half |
| 284 | stw r11,emfp0+4(r31) ; Save the second half, just in case we need it |
| 285 | |
| 286 | bctrl ; Go set the target FP register |
| 287 | |
| 288 | b aaComExit ; All done, go exit... |
| 289 | |
| 290 | ; |
| 291 | ; Here we handle floating point stores |
| 292 | ; |
| 293 | |
| 294 | .align 5 |
| 295 | |
| 296 | aaFPstore: bctrl ; Go save the source FP register |
| 297 | |
| 298 | lwz r10,emfp0(r31) ; Get first word |
| 299 | crandc iDouble,iDouble,iOptype4 ; Change to 4-byte access if stfiwx |
| 300 | lwz r11,emfp0+4(r31) ; and the second |
| 301 | bf+ iOptype4,aaNotstfiwx ; This is not a stfiwx... |
| 302 | mr r10,r11 ; The stfiwx wants to store the second half |
| 303 | |
| 304 | aaNotstfiwx: |
| 305 | crset cr0_eq ; Set this to see if we failed |
| 306 | mtmsr r22 ; Flip DR, RI |
| 307 | isync |
| 308 | |
| 309 | stw r10,0(r23) ; Save the first word |
| 310 | bf- cr0_eq,aaStNotDbl ; Jump out if we DSIed... |
| 311 | bf iDouble,aaStNotDbl ; this is not a double... |
| 312 | stw r11,4(r23) ; Save the second half |
| 313 | |
| 314 | aaStNotDbl: mr r4,r0 ; Save the DAR if we failed the access |
| 315 | mtmsr r30 ; Turn off |
| 316 | isync |
| 317 | |
| 318 | bf- cr0_eq,aaRedriveAsDSI ; Go redrive this as a DSI... |
| 319 | |
| 320 | ; |
| 321 | ; Common exit routines |
| 322 | ; |
| 323 | |
| 324 | aaComExit: lwz r10,savesrr0+4(r13) ; Get the failing instruction address |
| 325 | add r24,r24,r13 ; Offset to update register |
| 326 | li r11,T_IN_VAIN ; Assume we are all done |
| 327 | addi r10,r10,4 ; Step to the next instruction |
| 328 | bf iUpdate,aaComExNU ; Skip if not an update form... |
| 329 | stw r23,saver0+4(r24) ; Update the target |
| 330 | |
| 331 | aaComExNU: lwz r9,SAVflags(r13) ; Get the flags |
| 332 | stw r10,savesrr0+4(r13) ; Set new PC |
| 333 | bt- traceInst,aaComExitrd ; We are tracing, go emulate trace... |
| 334 | bf+ iNotify,aaComExGo ; Nothing special here, go... |
| 335 | |
| 336 | li r11,T_ALIGNMENT ; Set the we just did an alignment exception.... |
| 337 | |
| 338 | aaComExGo: b EXT(EmulExit) ; We are done, no tracing on... |
| 339 | |
| 340 | |
| 341 | ; |
| 342 | ; This is not a floating point operation |
| 343 | ; |
| 344 | ; The table of these emulation routines is indexed by taking the low order 4 bits of |
| 345 | ; the instruction code in the DSISR and subtracting 7. If this comes up negative, |
| 346 | ; the instruction is not to be emulated. Then we add bit 0 of the code * 4. This |
| 347 | ; gives us a fairly compact and almost unique index. Both lwm and stmw map to 0 so |
| 348 | ; that one needs to be further reduced, and we end up with holes at a few indexes. |
| 349 | ; |
| 350 | |
| 351 | .align 5 |
| 352 | |
| 353 | aaNotFloat: |
| 354 | lis r19,hi16(aaEmTable) ; Point to high part of table address |
| 355 | rlwinm r3,r26,24,26,29 ; Isolate last 4 bits of op type * 4 |
| 356 | rlwimi r19,r26,20,27,27 ; Get bit 0 of instruction code * 4 into bottom of table base |
| 357 | addic. r3,r3,-28 ; Subtract 7*4 to adjust index |
| 358 | ori r19,r19,lo16(aaEmTable) ; Low part of table address |
| 359 | blt- aaPassAlong ; We do not handle any of these (lwarx, stwcx., eciwx, ecowx)... |
| 360 | add r19,r19,r3 ; Point to emulation routine |
| 361 | rlwinm r18,r26,30,24,28 ; Get the target/source register displacement |
| 362 | |
| 363 | mtctr r19 ; Set the routine address |
| 364 | |
| 365 | bctr ; Go emulate the instruction... |
| 366 | |
| 367 | ; |
| 368 | ; This is the table of non-floating point emulation routines. |
| 369 | ; It is indexed by the code immediately above. |
| 370 | |
| 371 | .align 5 |
| 372 | |
| 373 | aaEmTable: |
| 374 | b aaLmwStmw ; This for lmw/stmw |
| 375 | b aaLswx ; This for lwwx |
| 376 | b aaLswi ; This for lswi |
| 377 | b aaStswx ; This for stswx |
| 378 | b aaStswi ; This for stswi |
| 379 | b aaLwbrx ; This for lwbrx |
| 380 | b aaPassAlong ; This an invalid index (6) |
| 381 | b aaStwbrx ; This for stwbrx |
| 382 | b aaPassAlong ; This an invalid index (8) |
| 383 | b aaLhbrx ; This for lhbrx |
| 384 | b aaPassAlong ; This an invalid index (A) |
| 385 | b aaSthbrx ; This for sthbrx |
| 386 | b aaDcbz ; This for dcbz |
| 387 | b aaPassAlong ; This an invalid index (D) |
| 388 | b aaPassAlong ; This an invalid index (E) |
| 389 | b aaPassAlong ; This an invalid index (F) |
| 390 | |
| 391 | |
| 392 | ; |
| 393 | ; Here we handle the set up for the lmw and stmw. After that, we split off to the |
| 394 | ; individual routines. |
| 395 | ; |
| 396 | ; Note also that after some set up, all of the string instructions come through here as well. |
| 397 | ; |
| 398 | .align 5 |
| 399 | |
| 400 | aaLmwStmw: |
| 401 | rlwinm r17,r18,31,1,29 ; Convert doublword based index to words |
| 402 | li r28,0 ; Set no extra bytes to move (used for string instructions) |
| 403 | subfic r17,r17,32*4 ; Calculate the length of the transfer |
| 404 | |
| 405 | aaLSComm: addi r19,r13,saver0+4 ; Offset to registers in savearea |
| 406 | mr r16,r23 ; Make a hunk pointer |
| 407 | |
| 408 | bt iUpdate,aaStmw ; This is the stmw... |
| 409 | |
| 410 | ; |
| 411 | ; Load multiple word |
| 412 | ; |
| 413 | |
| 414 | aaLmwNxt: cmplwi cr1,r17,8*4 ; Is there enough to move 8? |
| 415 | blt- cr1,aaLmwNxtH ; Not enough for a full hunk... |
| 416 | subi r17,r17,8*4 ; Back off for another hunk |
| 417 | |
| 418 | crset cr0_eq ; Set this to see if we failed |
| 419 | mtmsr r22 ; Flip DR, RI |
| 420 | isync |
| 421 | |
| 422 | lwz r2,0(r16) ; Load word 0 |
| 423 | bf- cr0_eq,aaLmwB1 ; Error, bail... |
| 424 | lwz r15,4(r16) ; Load word 1 |
| 425 | bf- cr0_eq,aaLmwB1 ; Error, bail... |
| 426 | lwz r14,8(r16) ; Load word 2 |
| 427 | bf- cr0_eq,aaLmwB1 ; Error, bail... |
| 428 | lwz r5,12(r16) ; Load word 3 |
| 429 | bf- cr0_eq,aaLmwB1 ; Error, bail... |
| 430 | lwz r6,16(r16) ; Load word 4 |
| 431 | bf- cr0_eq,aaLmwB1 ; Error, bail... |
| 432 | lwz r7,20(r16) ; Load word 5 |
| 433 | bf- cr0_eq,aaLmwB1 ; Error, bail... |
| 434 | lwz r8,24(r16) ; Load word 6 |
| 435 | bf- cr0_eq,aaLmwB1 ; Error, bail... |
| 436 | lwz r9,28(r16) ; Load word 7 |
| 437 | |
| 438 | aaLmwB1: mr r4,r0 ; Remember DAR, jus in case we failed the access |
| 439 | mtmsr r30 ; Turn off DR, RI |
| 440 | isync |
| 441 | |
| 442 | bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI... |
| 443 | |
| 444 | addi r16,r16,8*4 ; Point up to next input aread |
| 445 | |
| 446 | stwx r2,r19,r18 ; Store register |
| 447 | addi r18,r18,8 ; Next register |
| 448 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 449 | stwx r15,r19,r18 ; Store register |
| 450 | addi r18,r18,8 ; Next register |
| 451 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 452 | stwx r14,r19,r18 ; Store register |
| 453 | addi r18,r18,8 ; Next register |
| 454 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 455 | stwx r5,r19,r18 ; Store register |
| 456 | addi r18,r18,8 ; Next register |
| 457 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 458 | stwx r6,r19,r18 ; Store register |
| 459 | addi r18,r18,8 ; Next register |
| 460 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 461 | stwx r7,r19,r18 ; Store register |
| 462 | addi r18,r18,8 ; Next register |
| 463 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 464 | stwx r8,r19,r18 ; Store register |
| 465 | addi r18,r18,8 ; Next register |
| 466 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 467 | stwx r9,r19,r18 ; Store register |
| 468 | addi r18,r18,8 ; Next register |
| 469 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 470 | |
| 471 | b aaLmwNxt ; Do the next hunk... |
| 472 | |
| 473 | .align 5 |
| 474 | |
| 475 | aaLmwNxtH: cmplwi cr1,r17,4*4 ; Do we have 4 left? |
| 476 | blt cr1,aaLmwL4 ; Nope... |
| 477 | |
| 478 | subi r17,r17,4*4 ; Set count properly |
| 479 | |
| 480 | crset cr0_eq ; Set this to see if we failed |
| 481 | mtmsr r22 ; Flip DR, RI, and maybe PR on |
| 482 | isync |
| 483 | |
| 484 | lwz r2,0(r16) ; Load word 0 |
| 485 | bf- cr0_eq,aaLmwB2 ; Error, bail... |
| 486 | lwz r15,4(r16) ; Load word 1 |
| 487 | bf- cr0_eq,aaLmwB2 ; Error, bail... |
| 488 | lwz r14,8(r16) ; Load word 2 |
| 489 | bf- cr0_eq,aaLmwB2 ; Error, bail... |
| 490 | lwz r5,12(r16) ; Load word 3 |
| 491 | |
| 492 | aaLmwB2: mr r4,r0 ; Remember DAR, jus in case we failed the access |
| 493 | mtmsr r30 ; Turn off DR, RI |
| 494 | isync |
| 495 | |
| 496 | bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI... |
| 497 | |
| 498 | addi r16,r16,4*4 ; Point up to next input aread |
| 499 | |
| 500 | stwx r2,r19,r18 ; Store register |
| 501 | addi r18,r18,8 ; Next register |
| 502 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 503 | stwx r15,r19,r18 ; Store register |
| 504 | addi r18,r18,8 ; Next register |
| 505 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 506 | stwx r14,r19,r18 ; Store register |
| 507 | addi r18,r18,8 ; Next register |
| 508 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 509 | stwx r5,r19,r18 ; Store register |
| 510 | addi r18,r18,8 ; Next register |
| 511 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 512 | |
| 513 | aaLmwL4: or. r5,r17,r28 ; Do we have anything left? |
| 514 | cmplwi cr1,r17,(2*4) ; Do we have one, two, or three full words left? |
| 515 | cmplwi cr2,r17,0 ; Do we have no full words left? |
| 516 | beq aaComExit ; Nothing left... |
| 517 | |
| 518 | crset cr0_eq ; Set this to see if we failed |
| 519 | mtmsr r22 ; Flip DR, RI, and maybe PR on |
| 520 | isync |
| 521 | |
| 522 | beq- cr2,aaLmwBy ; No full words, get bytes... |
| 523 | |
| 524 | lwz r2,0(r16) ; Pick up first word |
| 525 | bf- cr0_eq,aaLmwDn ; Read failed, escape... |
| 526 | addi r16,r16,4 ; Next input location |
| 527 | blt cr1,aaLmwBy ; We only had one, we are done... |
| 528 | |
| 529 | lwz r15,0(r16) ; Pick up second word |
| 530 | bf- cr0_eq,aaLmwDn ; Read failed, escape... |
| 531 | addi r16,r16,4 ; Next input location |
| 532 | beq cr1,aaLmwBy ; We had two, we are done... |
| 533 | |
| 534 | lwz r14,0(r16) ; Load word 3 |
| 535 | addi r16,r16,4 ; Next input location |
| 536 | |
| 537 | aaLmwBy: cmplwi cr2,r28,0 ; Any trailing bytes to do? |
| 538 | li r8,0 ; Clear second trailing byte |
| 539 | cmplwi cr1,r28,2 ; Check for 1, 2, or 3 |
| 540 | li r9,0 ; Clear third trailing byte |
| 541 | beq+ cr2,aaLmwDn ; No trailing bytes... |
| 542 | |
| 543 | lbz r5,0(r16) ; Pick up first trailing byte |
| 544 | bf- cr0_eq,aaLmwDn ; Read failed, escape... |
| 545 | blt cr1,aaLmwDn ; We only had one, we are done... |
| 546 | |
| 547 | lbz r8,1(r16) ; Pick up second trailing byte |
| 548 | bf- cr0_eq,aaLmwDn ; Read failed, escape... |
| 549 | beq cr1,aaLmwDn ; We had two, we are done... |
| 550 | |
| 551 | lbz r9,2(r16) ; Get last trailing byte |
| 552 | |
| 553 | |
| 554 | aaLmwDn: rlwinm r5,r5,24,0,7 ; Move first byte to top |
| 555 | cmplwi cr2,r17,0 ; Any full words to do? |
| 556 | mr r4,r0 ; Remember DAR, just in case we failed the access |
| 557 | rlwimi r9,r8,8,16,23 ; Move second byte above third byte |
| 558 | cmplwi cr1,r17,(2*4) ; Do we have one, two, or three full words left? |
| 559 | mr r3,r30 ; Set the normal MSR |
| 560 | rlwimi r5,r9,8,8,23 ; Move bytes 1 and 2 after 0 |
| 561 | |
| 562 | mtmsr r30 ; Turn off DR, RI |
| 563 | isync |
| 564 | |
| 565 | bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI... |
| 566 | |
| 567 | beq- cr2,aaLmwCb ; No full words, copy bytes... |
| 568 | |
| 569 | stwx r2,r19,r18 ; Store register |
| 570 | addi r18,r18,8 ; Next register |
| 571 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 572 | blt cr1,aaLmwCb ; We only had one, we are done... |
| 573 | |
| 574 | stwx r15,r19,r18 ; Store register |
| 575 | addi r18,r18,8 ; Next register |
| 576 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 577 | beq cr1,aaLmwCb ; We had two, we are done... |
| 578 | |
| 579 | stwx r14,r19,r18 ; Store register |
| 580 | addi r18,r18,8 ; Next register |
| 581 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 582 | |
| 583 | aaLmwCb: mr. r28,r28 ; Any trailing bytes to do? |
| 584 | beq+ aaComExit ; Nope, leave... |
| 585 | |
| 586 | stwx r5,r19,r18 ; Store register |
| 587 | |
| 588 | b aaComExit ; We are done.... |
| 589 | |
| 590 | ; |
| 591 | ; Store multiple word |
| 592 | ; |
| 593 | |
| 594 | .align 5 |
| 595 | |
| 596 | aaStmw: |
| 597 | crclr iUpdate ; Make sure we do not think this is an update form |
| 598 | |
| 599 | aaStmwNxt: cmplwi cr1,r17,8*4 ; Is there enough to move 8? |
| 600 | blt- cr1,aaStmwNxtH ; Not enough for a full hunk... |
| 601 | subi r17,r17,8*4 ; Back off for another hunk |
| 602 | |
| 603 | lwzx r2,r19,r18 ; Store register |
| 604 | addi r18,r18,8 ; Next register |
| 605 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 606 | lwzx r15,r19,r18 ; Store register |
| 607 | addi r18,r18,8 ; Next register |
| 608 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 609 | lwzx r14,r19,r18 ; Store register |
| 610 | addi r18,r18,8 ; Next register |
| 611 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 612 | lwzx r5,r19,r18 ; Store register |
| 613 | addi r18,r18,8 ; Next register |
| 614 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 615 | lwzx r6,r19,r18 ; Store register |
| 616 | addi r18,r18,8 ; Next register |
| 617 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 618 | lwzx r7,r19,r18 ; Store register |
| 619 | addi r18,r18,8 ; Next register |
| 620 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 621 | lwzx r8,r19,r18 ; Store register |
| 622 | addi r18,r18,8 ; Next register |
| 623 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 624 | lwzx r9,r19,r18 ; Store register |
| 625 | addi r18,r18,8 ; Next register |
| 626 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 627 | |
| 628 | crset cr0_eq ; Set this to see if we failed |
| 629 | mtmsr r22 ; Flip DR, RI, and maybe PR on |
| 630 | isync |
| 631 | |
| 632 | stw r2,0(r16) ; Store word 0 |
| 633 | bf- cr0_eq,aaStmwB1 ; Error, bail... |
| 634 | stw r15,4(r16) ; Store word 1 |
| 635 | bf- cr0_eq,aaStmwB1 ; Error, bail... |
| 636 | stw r14,8(r16) ; Store word 2 |
| 637 | bf- cr0_eq,aaStmwB1 ; Error, bail... |
| 638 | stw r5,12(r16) ; Store word 3 |
| 639 | bf- cr0_eq,aaStmwB1 ; Error, bail... |
| 640 | stw r6,16(r16) ; Store word 4 |
| 641 | bf- cr0_eq,aaStmwB1 ; Error, bail... |
| 642 | stw r7,20(r16) ; Store word 5 |
| 643 | bf- cr0_eq,aaStmwB1 ; Error, bail... |
| 644 | stw r8,24(r16) ; Store word 6 |
| 645 | bf- cr0_eq,aaStmwB1 ; Error, bail... |
| 646 | stw r9,28(r16) ; Store word 7 |
| 647 | |
| 648 | addi r16,r16,8*4 ; Point up to next output aread |
| 649 | |
| 650 | |
| 651 | aaStmwB1: mr r4,r0 ; Remember DAR, jus in case we failed the access |
| 652 | mtmsr r30 ; Normal MSR |
| 653 | isync |
| 654 | |
| 655 | bt- cr0_eq,aaStmwNxt ; We have more to do and no failed access... |
| 656 | b aaRedriveAsDSI ; We failed, go redrive this as a DSI... |
| 657 | |
| 658 | .align 5 |
| 659 | |
| 660 | aaStmwNxtH: cmplwi cr1,r17,(4*4) ; Do we have at least 4 left? |
| 661 | blt cr1,aaStmwL4 ; Nope... |
| 662 | subi r17,r17,4*4 ; Set count properly |
| 663 | |
| 664 | lwzx r2,r19,r18 ; Store register |
| 665 | addi r18,r18,8 ; Next register |
| 666 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 667 | lwzx r15,r19,r18 ; Store register |
| 668 | addi r18,r18,8 ; Next register |
| 669 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 670 | lwzx r14,r19,r18 ; Store register |
| 671 | addi r18,r18,8 ; Next register |
| 672 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 673 | lwzx r5,r19,r18 ; Store register |
| 674 | addi r18,r18,8 ; Next register |
| 675 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 676 | |
| 677 | crset cr0_eq ; Set this to see if we failed |
| 678 | mtmsr r22 ; Flip DR, RI |
| 679 | isync |
| 680 | |
| 681 | stw r2,0(r16) ; Store word 0 |
| 682 | bf- cr0_eq,aaStmwB2 ; Error, bail... |
| 683 | stw r15,4(r16) ; Store word 1 |
| 684 | bf- cr0_eq,aaStmwB2 ; Error, bail... |
| 685 | stw r14,8(r16) ; Store word 2 |
| 686 | bf- cr0_eq,aaStmwB2 ; Error, bail... |
| 687 | stw r5,12(r16) ; Store word 3 |
| 688 | |
| 689 | addi r16,r16,4*4 ; Point up to next input aread |
| 690 | |
| 691 | aaStmwB2: mr r4,r0 ; Remember DAR, jus in case we failed the access |
| 692 | mtmsr r30 ; Normal MSR |
| 693 | isync |
| 694 | |
| 695 | bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI... |
| 696 | |
| 697 | aaStmwL4: or. r5,r17,r28 ; Do we have anything left to do? |
| 698 | cmplwi cr1,r17,(2*4) ; Do we have one, two, or three left? |
| 699 | cmplwi cr2,r17,0 ; Do we have no full words left? |
| 700 | beq aaComExit ; Nothing left... |
| 701 | |
| 702 | beq- cr2,aaStmwBy1 ; No full words, check out bytes |
| 703 | |
| 704 | lwzx r2,r19,r18 ; Store register |
| 705 | addi r18,r18,8 ; Next register |
| 706 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 707 | blt cr1,aaStmwBy1 ; We only had one, go save it... |
| 708 | |
| 709 | lwzx r15,r19,r18 ; Store register |
| 710 | addi r18,r18,8 ; Next register |
| 711 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 712 | beq cr1,aaStmwBy1 ; We had two, go save it... |
| 713 | |
| 714 | lwzx r14,r19,r18 ; Store register |
| 715 | addi r18,r18,8 ; Next register |
| 716 | rlwinm r18,r18,0,24,28 ; Wrap back to 0 if needed |
| 717 | |
| 718 | aaStmwBy1: mr. r28,r28 ; Do we have any trailing bytes? |
| 719 | beq+ aaStmwSt ; Nope... |
| 720 | |
| 721 | lwzx r5,r19,r18 ; Yes, pick up one extra register |
| 722 | |
| 723 | aaStmwSt: crset cr0_eq ; Set this to see if we failed |
| 724 | mtmsr r22 ; Flip DR, RI |
| 725 | isync |
| 726 | |
| 727 | beq- cr2,aaStmwBy2 ; No words, check trailing bytes... |
| 728 | |
| 729 | stw r2,0(r16) ; Save first word |
| 730 | bf- cr0_eq,aaStmwDn ; Store failed, escape... |
| 731 | addi r16,r16,4 ; Bump sink |
| 732 | blt cr1,aaStmwBy2 ; We only had one, we are done... |
| 733 | |
| 734 | stw r15,0(r16) ; Save second word |
| 735 | bf- cr0_eq,aaStmwDn ; Store failed, escape... |
| 736 | addi r16,r16,4 ; Bump sink |
| 737 | beq cr1,aaStmwBy2 ; We had two, we are done... |
| 738 | |
| 739 | stw r14,0(r16) ; Save third word |
| 740 | bf- cr0_eq,aaStmwDn ; Store failed, escape... |
| 741 | addi r16,r16,4 ; Bump sink |
| 742 | |
| 743 | aaStmwBy2: rlwinm r2,r5,8,24,31 ; Get byte 0 |
| 744 | cmplwi cr2,r28,0 ; Any trailing bytes to do? |
| 745 | rlwinm r14,r5,24,24,31 ; Get byte 3 |
| 746 | li r8,0 ; Clear second trailing byte |
| 747 | cmplwi cr1,r28,2 ; Check for 1, 2, or 3 |
| 748 | li r9,0 ; Clear third trailing byte |
| 749 | beq+ cr2,aaStmwDn ; No trailing bytes... |
| 750 | rlwinm r15,r5,16,24,31 ; Get byte 1 |
| 751 | |
| 752 | stb r2,0(r16) ; Save first byte |
| 753 | bf- cr0_eq,aaStmwDn ; Read failed, escape... |
| 754 | blt cr1,aaStmwDn ; We only had one, we are done... |
| 755 | |
| 756 | stb r15,1(r16) ; Save second byte |
| 757 | bf- cr0_eq,aaStmwDn ; Read failed, escape... |
| 758 | beq cr1,aaStmwDn ; We had two, we are done... |
| 759 | |
| 760 | stb r14,2(r16) ; Save third byte |
| 761 | |
| 762 | aaStmwDn: mr r4,r0 ; Remember DAR, jus in case we failed the access |
| 763 | mtmsr r30 ; Normal MSR |
| 764 | isync |
| 765 | |
| 766 | bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI... |
| 767 | |
| 768 | b aaComExit ; We are done.... |
| 769 | |
| 770 | |
| 771 | ; |
| 772 | ; Load String Indexed |
| 773 | ; |
| 774 | |
| 775 | .align 5 |
| 776 | |
| 777 | aaLswx: lwz r17,savexer+4(r13) ; Pick up the XER |
| 778 | crclr iUpdate ; Make sure we think this the load form |
| 779 | rlwinm. r25,r17,0,25,31 ; Get the number of bytes to load |
| 780 | rlwinm r28,r17,0,30,31 ; Get the number of bytes past an even word |
| 781 | beq- aaComExit ; Do nothing if 0 length... |
| 782 | xor r17,r25,r28 ; Round down to an even word boundary |
| 783 | b aaLSComm ; Join up with common load/store code... |
| 784 | |
| 785 | |
| 786 | ; |
| 787 | ; Load String Immediate |
| 788 | ; |
| 789 | |
| 790 | .align 5 |
| 791 | |
| 792 | aaLswi: mr r9,r23 ; Save the DAR |
| 793 | bl eIFetch ; Get the instruction image |
| 794 | bne- eRedriveAsISI ; Go redrive this as an ISI... |
| 795 | rlwinm r25,r10,21,27,31 ; Get the number of bytes to load |
| 796 | crclr iUpdate ; Make sure we think this the load form |
| 797 | subi r25,r25,1 ; Back off by 1 |
| 798 | rlwinm r25,r25,0,27,31 ; Clear back down |
| 799 | addi r25,r25,1 ; Add back the 1 to convert 0 to 32 |
| 800 | rlwinm r28,r25,0,30,31 ; Get the number of bytes past an even word |
| 801 | xor r17,r25,r28 ; Round down to an even word boundary |
| 802 | mr r23,r9 ; Move back the DAR |
| 803 | b aaLSComm ; Join up with common load/store code... |
| 804 | |
| 805 | ; |
| 806 | ; Store String Indexed |
| 807 | ; |
| 808 | |
| 809 | .align 5 |
| 810 | |
| 811 | aaStswx: lwz r17,savexer+4(r13) ; Pick up the XER |
| 812 | crclr iUpdate ; Make sure this is clear in case we have 0 length |
| 813 | rlwinm. r25,r17,0,25,31 ; Get the number of bytes to load |
| 814 | rlwinm r28,r17,0,30,31 ; Get the number of bytes past an even word |
| 815 | beq- aaComExit ; Do nothing if 0 length... |
| 816 | xor r17,r25,r28 ; Round down to an even word boundary |
| 817 | crset iUpdate ; Make sure we think this the store form |
| 818 | b aaLSComm ; Join up with common load/store code... |
| 819 | |
| 820 | |
| 821 | ; |
| 822 | ; Store String Immediate |
| 823 | ; |
| 824 | |
| 825 | .align 5 |
| 826 | |
| 827 | aaStswi: mr r9,r23 ; Save the DAR |
| 828 | bl eIFetch ; Get the instruction image |
| 829 | bne- eRedriveAsISI ; Go redrive this as an ISI... |
| 830 | rlwinm r25,r10,21,27,31 ; Get the number of bytes to load |
| 831 | crclr iUpdate ; Make sure we think this the load form |
| 832 | subi r25,r25,1 ; Back off by 1 |
| 833 | rlwinm r25,r25,0,27,31 ; Clear back down |
| 834 | addi r25,r25,1 ; Add back the 1 to convert 0 to 32 |
| 835 | rlwinm r28,r25,21,30,31 ; Get the number of bytes past an even word |
| 836 | xor r17,r25,r28 ; Round down to an even word boundary |
| 837 | mr r23,r9 ; Move back the DAR |
| 838 | b aaLSComm ; Join up with common load/store code... |
| 839 | |
| 840 | |
| 841 | ; |
| 842 | ; Load byte-reversed word |
| 843 | ; |
| 844 | |
| 845 | .align 5 |
| 846 | |
| 847 | aaLwbrx: |
| 848 | add r18,r18,r13 ; Index to source register |
| 849 | |
| 850 | crset cr0_eq ; Set this to see if we failed |
| 851 | mtmsr r22 ; Flip DR, RI, and maybe PR on |
| 852 | isync |
| 853 | |
| 854 | lwz r11,0(r23) ; Load the word |
| 855 | |
| 856 | mr r4,r0 ; Save the DAR if we failed the access |
| 857 | mtmsr r30 ; Restore normal MSR |
| 858 | isync |
| 859 | |
| 860 | bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI... |
| 861 | |
| 862 | rlwinm r10,r11,8,0,31 ; Get byte 0 to 3 and byte 2 to 1 |
| 863 | rlwimi r10,r11,24,16,23 ; Move byte 1 to byte 2 |
| 864 | rlwimi r10,r11,24,0,7 ; Move byte 3 to byte 0 |
| 865 | |
| 866 | stw r10,saver0+4(r18) ; Set the register |
| 867 | |
| 868 | b aaComExit ; All done, go exit... |
| 869 | |
| 870 | |
| 871 | |
| 872 | ; |
| 873 | ; Store byte-reversed word |
| 874 | ; |
| 875 | |
| 876 | .align 5 |
| 877 | |
| 878 | aaStwbrx: |
| 879 | add r18,r18,r13 ; Index to source register |
| 880 | lwz r11,saver0+4(r18) ; Get the register to store |
| 881 | |
| 882 | rlwinm r10,r11,8,0,31 ; Get byte 0 to 3 and byte 2 to 1 |
| 883 | rlwimi r10,r11,24,16,23 ; Move byte 1 to byte 2 |
| 884 | rlwimi r10,r11,24,0,7 ; Move byte 3 to byte 0 |
| 885 | |
| 886 | crset cr0_eq ; Set this to see if we failed |
| 887 | mtmsr r22 ; Flip DR, RI, and maybe PR on |
| 888 | isync |
| 889 | |
| 890 | stw r10,0(r23) ; Store the reversed halfword |
| 891 | |
| 892 | mr r4,r0 ; Save the DAR if we failed the access |
| 893 | mtmsr r30 ; Restore normal MSR |
| 894 | isync |
| 895 | |
| 896 | bt+ cr0_eq,aaComExit ; All done, go exit... |
| 897 | b aaRedriveAsDSI ; We failed, go redrive this as a DSI... |
| 898 | |
| 899 | |
| 900 | |
| 901 | ; |
| 902 | ; Load byte-reversed halfword |
| 903 | ; |
| 904 | |
| 905 | .align 5 |
| 906 | |
| 907 | aaLhbrx: |
| 908 | add r18,r18,r13 ; Index to source register |
| 909 | |
| 910 | crset cr0_eq ; Set this to see if we failed |
| 911 | mtmsr r22 ; Flip DR, RI, and maybe PR on |
| 912 | isync |
| 913 | |
| 914 | lhz r11,0(r23) ; Load the halfword |
| 915 | |
| 916 | mr r4,r0 ; Save the DAR if we failed the access |
| 917 | mtmsr r30 ; Restore normal MSR |
| 918 | isync |
| 919 | |
| 920 | bf- cr0_eq,aaRedriveAsDSI ; We failed, go redrive this as a DSI... |
| 921 | |
| 922 | rlwinm r10,r11,8,16,23 ; Rotate bottom byte up one and clear everything else |
| 923 | rlwimi r10,r11,24,24,31 ; Put old second from bottom into bottom |
| 924 | |
| 925 | stw r10,saver0+4(r18) ; Set the register |
| 926 | |
| 927 | b aaComExit ; All done, go exit... |
| 928 | |
| 929 | |
| 930 | ; |
| 931 | ; Store byte-reversed halfword |
| 932 | ; |
| 933 | |
| 934 | .align 5 |
| 935 | |
| 936 | aaSthbrx: |
| 937 | add r18,r18,r13 ; Index to source register |
| 938 | lwz r10,saver0+4(r18) ; Get the register to store |
| 939 | rlwinm r10,r10,8,0,31 ; Rotate bottom byte up one |
| 940 | rlwimi r10,r10,16,24,31 ; Put old second from bottom into bottom |
| 941 | |
| 942 | crset cr0_eq ; Set this to see if we failed |
| 943 | mtmsr r22 ; Flip DR, RI, and maybe PR on |
| 944 | isync |
| 945 | |
| 946 | sth r10,0(r23) ; Store the reversed halfword |
| 947 | |
| 948 | mr r4,r0 ; Save the DAR if we failed the access |
| 949 | mtmsr r30 ; Restore normal MSR |
| 950 | isync |
| 951 | |
| 952 | bt+ cr0_eq,aaComExit ; All done, go exit... |
| 953 | b aaRedriveAsDSI ; We failed, go redrive this as a DSI... |
| 954 | |
| 955 | ; |
| 956 | ; Data cache block zero |
| 957 | ; |
| 958 | |
| 959 | .align 5 |
| 960 | |
| 961 | aaDcbz: |
| 962 | lwz r0,savesrr0+4(r13) ; get instruction address |
| 963 | li r4,_COMM_PAGE_BASE_ADDRESS |
| 964 | rlwinm r23,r23,0,0,26 ; Round EA back to a 32-byte boundary |
| 965 | sub r4,r0,r4 ; compute instruction offset from base of commpage |
| 966 | cmplwi r4,_COMM_PAGE_AREA_USED ; did fault occur in commpage? |
| 967 | bge+ aaDcbz1 ; skip if not in commpage |
| 968 | lwz r4,savecr(r13) ; if we take a dcbz in the commpage... |
| 969 | rlwinm r4,r4,0,0,27 ; ...clear users cr7 as a flag for commpage code |
| 970 | stw r4,savecr(r13) |
| 971 | aaDcbz1: |
| 972 | crset cr0_eq ; Set this to see if we failed |
| 973 | li r0,0 ; Clear this out |
| 974 | mtmsr r22 ; Flip DR, RI, and maybe PR on |
| 975 | isync |
| 976 | |
| 977 | stw r0,0(r23) ; Clear word |
| 978 | bne- aaDcbzXit ; Got DSI, we are stopping... |
| 979 | stw r0,4(r23) ; Clear word |
| 980 | bne- aaDcbzXit ; Got DSI, we are stopping... |
| 981 | stw r0,8(r23) ; Clear word |
| 982 | bne- aaDcbzXit ; Got DSI, we are stopping... |
| 983 | stw r0,12(r23) ; Clear word |
| 984 | bne- aaDcbzXit ; Got DSI, we are stopping... |
| 985 | stw r0,16(r23) ; Clear word |
| 986 | bne- aaDcbzXit ; Got DSI, we are stopping... |
| 987 | stw r0,20(r23) ; Clear word |
| 988 | bne- aaDcbzXit ; Got DSI, we are stopping... |
| 989 | stw r0,24(r23) ; Clear word |
| 990 | bne- aaDcbzXit ; Got DSI, we are stopping... |
| 991 | stw r0,28(r23) ; Clear word |
| 992 | |
| 993 | aaDcbzXit: mr r4,r0 ; Save the DAR if we failed the access |
| 994 | mtmsr r30 ; Restore normal MSR |
| 995 | isync |
| 996 | |
| 997 | crclr iUpdate ; Make sure we do not think this is an update form |
| 998 | |
| 999 | bt+ cr0_eq,aaComExit ; All done, go exit... |
| 1000 | b aaRedriveAsDSI ; We failed, go redrive this as a DSI... |
| 1001 | |
| 1002 | |
| 1003 | ; |
| 1004 | ; Unhandled alignment exception, pass it along |
| 1005 | ; |
| 1006 | |
| 1007 | aaPassAlong: |
| 1008 | li r0,1 ; Indicate that we failed to emulate |
| 1009 | stw r0,savemisc3(r13) ; Assume that we emulate ok |
| 1010 | b EXT(EmulExit) |
| 1011 | |
| 1012 | |
| 1013 | |
| 1014 | |
| 1015 | ; |
| 1016 | ; We go here to emulate a trace exception after we have handled alignment error |
| 1017 | ; |
| 1018 | |
| 1019 | .align 5 |
| 1020 | |
| 1021 | aaComExitrd: |
| 1022 | lis r11,hi16(srr1clr) ; Get the bits we need to clear |
| 1023 | oris r9,r9,hi16(SAVredrive) ; Set the redrive bit |
| 1024 | andc r12,r12,r11 ; Clear what needs to be cleared |
| 1025 | li r11,T_TRACE ; Set trace interrupt |
| 1026 | stw r9,SAVflags(r13) ; Set the flags |
| 1027 | stw r11,saveexception(r13) ; Set the exception code |
| 1028 | b EXT(EmulExit) ; Exit and do trace interrupt... |
| 1029 | |
| 1030 | |
| 1031 | |
| 1032 | ; |
| 1033 | ; Redrive as a DSI |
| 1034 | |
| 1035 | aaRedriveAsDSI: |
| 1036 | mr r20,r1 ; Save the DSISR |
| 1037 | mr r21,r4 |
| 1038 | lwz r4,SAVflags(r13) ; Pick up the flags |
| 1039 | li r11,T_DATA_ACCESS ; Set failing data access code |
| 1040 | oris r4,r4,hi16(SAVredrive) ; Set the redrive bit |
| 1041 | stw r20,savedsisr(r13) ; Set the DSISR of failed access |
| 1042 | stw r21,savedar+4(r13) ; Set the address of the failed access |
| 1043 | stw r11,saveexception(r13) ; Set the replacement code |
| 1044 | stw r4,SAVflags(r13) ; Set redrive request |
| 1045 | b EXT(EmulExit) ; Bail out to handle ISI... |
| 1046 | |
| 1047 | |
| 1048 | |
| 1049 | ; |
| 1050 | ; Table of functions to load or store floating point registers |
| 1051 | ; This table is indexed reg||size||dir. That means that each |
| 1052 | ; like load/store pair (e.g., lfd f31/stfd f31) are within the same |
| 1053 | ; quadword, which is the current ifetch size. We expect most of the |
| 1054 | ; unaligned accesses to be part of copies, therefore, with this |
| 1055 | ; organization, we will save the ifetch of the store after the load. |
| 1056 | ; |
| 1057 | |
| 1058 | .align 10 ; Make sure we are on a 1k boundary |
| 1059 | .globl EXT(aaFPopTable) |
| 1060 | |
| 1061 | LEXT(aaFPopTable) |
| 1062 | lfs f0,emfp0(r31) ; Load single variant |
| 1063 | blr |
| 1064 | |
| 1065 | stfs f0,emfp0(r31) ; Store single variant |
| 1066 | blr |
| 1067 | |
| 1068 | lfd f0,emfp0(r31) ; Load double variant |
| 1069 | blr |
| 1070 | |
| 1071 | stfd f0,emfp0(r31) ; Store double variant |
| 1072 | blr |
| 1073 | |
| 1074 | lfs f1,emfp0(r31) ; Load single variant |
| 1075 | blr |
| 1076 | |
| 1077 | stfs f1,emfp0(r31) ; Store single variant |
| 1078 | blr |
| 1079 | |
| 1080 | lfd f1,emfp0(r31) ; Load double variant |
| 1081 | blr |
| 1082 | |
| 1083 | stfd f1,emfp0(r31) ; Store double variant |
| 1084 | blr |
| 1085 | |
| 1086 | lfs f2,emfp0(r31) ; Load single variant |
| 1087 | blr |
| 1088 | |
| 1089 | stfs f2,emfp0(r31) ; Store single variant |
| 1090 | blr |
| 1091 | |
| 1092 | lfd f2,emfp0(r31) ; Load double variant |
| 1093 | blr |
| 1094 | |
| 1095 | stfd f2,emfp0(r31) ; Store double variant |
| 1096 | blr |
| 1097 | |
| 1098 | lfs f3,emfp0(r31) ; Load single variant |
| 1099 | blr |
| 1100 | |
| 1101 | stfs f3,emfp0(r31) ; Store single variant |
| 1102 | blr |
| 1103 | |
| 1104 | lfd f3,emfp0(r31) ; Load double variant |
| 1105 | blr |
| 1106 | |
| 1107 | stfd f3,emfp0(r31) ; Store double variant |
| 1108 | blr |
| 1109 | |
| 1110 | lfs f4,emfp0(r31) ; Load single variant |
| 1111 | blr |
| 1112 | |
| 1113 | stfs f4,emfp0(r31) ; Store single variant |
| 1114 | blr |
| 1115 | |
| 1116 | lfd f4,emfp0(r31) ; Load double variant |
| 1117 | blr |
| 1118 | |
| 1119 | stfd f4,emfp0(r31) ; Store double variant |
| 1120 | blr |
| 1121 | |
| 1122 | lfs f5,emfp0(r31) ; Load single variant |
| 1123 | blr |
| 1124 | |
| 1125 | stfs f5,emfp0(r31) ; Store single variant |
| 1126 | blr |
| 1127 | |
| 1128 | lfd f5,emfp0(r31) ; Load double variant |
| 1129 | blr |
| 1130 | |
| 1131 | stfd f5,emfp0(r31) ; Store double variant |
| 1132 | blr |
| 1133 | |
| 1134 | lfs f6,emfp0(r31) ; Load single variant |
| 1135 | blr |
| 1136 | |
| 1137 | stfs f6,emfp0(r31) ; Store single variant |
| 1138 | blr |
| 1139 | |
| 1140 | lfd f6,emfp0(r31) ; Load double variant |
| 1141 | blr |
| 1142 | |
| 1143 | stfd f6,emfp0(r31) ; Store double variant |
| 1144 | blr |
| 1145 | |
| 1146 | lfs f7,emfp0(r31) ; Load single variant |
| 1147 | blr |
| 1148 | |
| 1149 | stfs f7,emfp0(r31) ; Store single variant |
| 1150 | blr |
| 1151 | |
| 1152 | lfd f7,emfp0(r31) ; Load double variant |
| 1153 | blr |
| 1154 | |
| 1155 | stfd f7,emfp0(r31) ; Store double variant |
| 1156 | blr |
| 1157 | |
| 1158 | lfs f8,emfp0(r31) ; Load single variant |
| 1159 | blr |
| 1160 | |
| 1161 | stfs f8,emfp0(r31) ; Store single variant |
| 1162 | blr |
| 1163 | |
| 1164 | lfd f8,emfp0(r31) ; Load double variant |
| 1165 | blr |
| 1166 | |
| 1167 | stfd f8,emfp0(r31) ; Store double variant |
| 1168 | blr |
| 1169 | |
| 1170 | lfs f9,emfp0(r31) ; Load single variant |
| 1171 | blr |
| 1172 | |
| 1173 | stfs f9,emfp0(r31) ; Store single variant |
| 1174 | blr |
| 1175 | |
| 1176 | lfd f9,emfp0(r31) ; Load double variant |
| 1177 | blr |
| 1178 | |
| 1179 | stfd f9,emfp0(r31) ; Store double variant |
| 1180 | blr |
| 1181 | |
| 1182 | lfs f10,emfp0(r31) ; Load single variant |
| 1183 | blr |
| 1184 | |
| 1185 | stfs f10,emfp0(r31) ; Store single variant |
| 1186 | blr |
| 1187 | |
| 1188 | lfd f10,emfp0(r31) ; Load double variant |
| 1189 | blr |
| 1190 | |
| 1191 | stfd f10,emfp0(r31) ; Store double variant |
| 1192 | blr |
| 1193 | |
| 1194 | lfs f11,emfp0(r31) ; Load single variant |
| 1195 | blr |
| 1196 | |
| 1197 | stfs f11,emfp0(r31) ; Store single variant |
| 1198 | blr |
| 1199 | |
| 1200 | lfd f11,emfp0(r31) ; Load double variant |
| 1201 | blr |
| 1202 | |
| 1203 | stfd f11,emfp0(r31) ; Store double variant |
| 1204 | blr |
| 1205 | |
| 1206 | lfs f12,emfp0(r31) ; Load single variant |
| 1207 | blr |
| 1208 | |
| 1209 | stfs f12,emfp0(r31) ; Store single variant |
| 1210 | blr |
| 1211 | |
| 1212 | lfd f12,emfp0(r31) ; Load double variant |
| 1213 | blr |
| 1214 | |
| 1215 | stfd f12,emfp0(r31) ; Store double variant |
| 1216 | blr |
| 1217 | |
| 1218 | lfs f13,emfp0(r31) ; Load single variant |
| 1219 | blr |
| 1220 | |
| 1221 | stfs f13,emfp0(r31) ; Store single variant |
| 1222 | blr |
| 1223 | |
| 1224 | lfd f13,emfp0(r31) ; Load double variant |
| 1225 | blr |
| 1226 | |
| 1227 | stfd f13,emfp0(r31) ; Store double variant |
| 1228 | blr |
| 1229 | |
| 1230 | lfs f14,emfp0(r31) ; Load single variant |
| 1231 | blr |
| 1232 | |
| 1233 | stfs f14,emfp0(r31) ; Store single variant |
| 1234 | blr |
| 1235 | |
| 1236 | lfd f14,emfp0(r31) ; Load double variant |
| 1237 | blr |
| 1238 | |
| 1239 | stfd f14,emfp0(r31) ; Store double variant |
| 1240 | blr |
| 1241 | |
| 1242 | lfs f15,emfp0(r31) ; Load single variant |
| 1243 | blr |
| 1244 | |
| 1245 | stfs f15,emfp0(r31) ; Store single variant |
| 1246 | blr |
| 1247 | |
| 1248 | lfd f15,emfp0(r31) ; Load double variant |
| 1249 | blr |
| 1250 | |
| 1251 | stfd f15,emfp0(r31) ; Store double variant |
| 1252 | blr |
| 1253 | |
| 1254 | lfs f16,emfp0(r31) ; Load single variant |
| 1255 | blr |
| 1256 | |
| 1257 | stfs f16,emfp0(r31) ; Store single variant |
| 1258 | blr |
| 1259 | |
| 1260 | lfd f16,emfp0(r31) ; Load double variant |
| 1261 | blr |
| 1262 | |
| 1263 | stfd f16,emfp0(r31) ; Store double variant |
| 1264 | blr |
| 1265 | |
| 1266 | lfs f17,emfp0(r31) ; Load single variant |
| 1267 | blr |
| 1268 | |
| 1269 | stfs f17,emfp0(r31) ; Store single variant |
| 1270 | blr |
| 1271 | |
| 1272 | lfd f17,emfp0(r31) ; Load double variant |
| 1273 | blr |
| 1274 | |
| 1275 | stfd f17,emfp0(r31) ; Store double variant |
| 1276 | blr |
| 1277 | |
| 1278 | lfs f18,emfp0(r31) ; Load single variant |
| 1279 | blr |
| 1280 | |
| 1281 | stfs f18,emfp0(r31) ; Store single variant |
| 1282 | blr |
| 1283 | |
| 1284 | lfd f18,emfp0(r31) ; Load double variant |
| 1285 | blr |
| 1286 | |
| 1287 | stfd f18,emfp0(r31) ; Store double variant |
| 1288 | blr |
| 1289 | |
| 1290 | lfs f19,emfp0(r31) ; Load single variant |
| 1291 | blr |
| 1292 | |
| 1293 | stfs f19,emfp0(r31) ; Store single variant |
| 1294 | blr |
| 1295 | |
| 1296 | lfd f19,emfp0(r31) ; Load double variant |
| 1297 | blr |
| 1298 | |
| 1299 | stfd f19,emfp0(r31) ; Store double variant |
| 1300 | blr |
| 1301 | |
| 1302 | lfs f20,emfp0(r31) ; Load single variant |
| 1303 | blr |
| 1304 | |
| 1305 | stfs f20,emfp0(r31) ; Store single variant |
| 1306 | blr |
| 1307 | |
| 1308 | lfd f20,emfp0(r31) ; Load double variant |
| 1309 | blr |
| 1310 | |
| 1311 | stfd f20,emfp0(r31) ; Store double variant |
| 1312 | blr |
| 1313 | |
| 1314 | lfs f21,emfp0(r31) ; Load single variant |
| 1315 | blr |
| 1316 | |
| 1317 | stfs f21,emfp0(r31) ; Store single variant |
| 1318 | blr |
| 1319 | |
| 1320 | lfd f21,emfp0(r31) ; Load double variant |
| 1321 | blr |
| 1322 | |
| 1323 | stfd f21,emfp0(r31) ; Store double variant |
| 1324 | blr |
| 1325 | |
| 1326 | lfs f22,emfp0(r31) ; Load single variant |
| 1327 | blr |
| 1328 | |
| 1329 | stfs f22,emfp0(r31) ; Store single variant |
| 1330 | blr |
| 1331 | |
| 1332 | lfd f22,emfp0(r31) ; Load double variant |
| 1333 | blr |
| 1334 | |
| 1335 | stfd f22,emfp0(r31) ; Store double variant |
| 1336 | blr |
| 1337 | |
| 1338 | lfs f23,emfp0(r31) ; Load single variant |
| 1339 | blr |
| 1340 | |
| 1341 | stfs f23,emfp0(r31) ; Store single variant |
| 1342 | blr |
| 1343 | |
| 1344 | lfd f23,emfp0(r31) ; Load double variant |
| 1345 | blr |
| 1346 | |
| 1347 | stfd f23,emfp0(r31) ; Store double variant |
| 1348 | blr |
| 1349 | |
| 1350 | lfs f24,emfp0(r31) ; Load single variant |
| 1351 | blr |
| 1352 | |
| 1353 | stfs f24,emfp0(r31) ; Store single variant |
| 1354 | blr |
| 1355 | |
| 1356 | lfd f24,emfp0(r31) ; Load double variant |
| 1357 | blr |
| 1358 | |
| 1359 | stfd f24,emfp0(r31) ; Store double variant |
| 1360 | blr |
| 1361 | |
| 1362 | lfs f25,emfp0(r31) ; Load single variant |
| 1363 | blr |
| 1364 | |
| 1365 | stfs f25,emfp0(r31) ; Store single variant |
| 1366 | blr |
| 1367 | |
| 1368 | lfd f25,emfp0(r31) ; Load double variant |
| 1369 | blr |
| 1370 | |
| 1371 | stfd f25,emfp0(r31) ; Store double variant |
| 1372 | blr |
| 1373 | |
| 1374 | lfs f26,emfp0(r31) ; Load single variant |
| 1375 | blr |
| 1376 | |
| 1377 | stfs f26,emfp0(r31) ; Store single variant |
| 1378 | blr |
| 1379 | |
| 1380 | lfd f26,emfp0(r31) ; Load double variant |
| 1381 | blr |
| 1382 | |
| 1383 | stfd f26,emfp0(r31) ; Store double variant |
| 1384 | blr |
| 1385 | |
| 1386 | lfs f27,emfp0(r31) ; Load single variant |
| 1387 | blr |
| 1388 | |
| 1389 | stfs f27,emfp0(r31) ; Store single variant |
| 1390 | blr |
| 1391 | |
| 1392 | lfd f27,emfp0(r31) ; Load double variant |
| 1393 | blr |
| 1394 | |
| 1395 | stfd f27,emfp0(r31) ; Store double variant |
| 1396 | blr |
| 1397 | |
| 1398 | lfs f28,emfp0(r31) ; Load single variant |
| 1399 | blr |
| 1400 | |
| 1401 | stfs f28,emfp0(r31) ; Store single variant |
| 1402 | blr |
| 1403 | |
| 1404 | lfd f28,emfp0(r31) ; Load double variant |
| 1405 | blr |
| 1406 | |
| 1407 | stfd f28,emfp0(r31) ; Store double variant |
| 1408 | blr |
| 1409 | |
| 1410 | lfs f29,emfp0(r31) ; Load single variant |
| 1411 | blr |
| 1412 | |
| 1413 | stfs f29,emfp0(r31) ; Store single variant |
| 1414 | blr |
| 1415 | |
| 1416 | lfd f29,emfp0(r31) ; Load double variant |
| 1417 | blr |
| 1418 | |
| 1419 | stfd f29,emfp0(r31) ; Store double variant |
| 1420 | blr |
| 1421 | |
| 1422 | lfs f30,emfp0(r31) ; Load single variant |
| 1423 | blr |
| 1424 | |
| 1425 | stfs f30,emfp0(r31) ; Store single variant |
| 1426 | blr |
| 1427 | |
| 1428 | lfd f30,emfp0(r31) ; Load double variant |
| 1429 | blr |
| 1430 | |
| 1431 | stfd f30,emfp0(r31) ; Store double variant |
| 1432 | blr |
| 1433 | |
| 1434 | lfs f31,emfp0(r31) ; Load single variant |
| 1435 | blr |
| 1436 | |
| 1437 | stfs f31,emfp0(r31) ; Store single variant |
| 1438 | blr |
| 1439 | |
| 1440 | lfd f31,emfp0(r31) ; Load double variant |
| 1441 | blr |
| 1442 | |
| 1443 | stfd f31,emfp0(r31) ; Store double variant |
| 1444 | blr |
| 1445 | |