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
|
/*
* Creation Date: <2001/01/30 00:22:35 samuel>
* Time-stamp: <2001/06/24 14:48:02 samuel>
*
* <entry.S>
*
* Emulator/mac switching
*
* Copyright (C) 2001 Samuel Rydh (samuel@ibrium.se)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation
*
*/
#include "multiplexer.h"
/* Short note about DEC. Due to the kernel implementation of the DEC
* exception handler (and get_time_of_day) in the 2.3/2.4 kernel, we
* must try to maintain coherency between DEC and TB. In any case,
* we must NEVER let DEC tick faster than TB, or get_time_of_day will
* occasionally return bogus values (the result is usually
* misbehaving X).
*/
/************************************************************************/
/* Mac Entry */
/************************************************************************/
.macro ENTRY_TEST i n
.if \n-\i
lwz r4,ST_ENTRY_MAGIC+\i*4(r1)
cmpw r7,r4
lwz r5,ST_KVARS_PH+\i*4(r1)
beq+ 66f
ENTRY_TEST (\i+1),\n
.endif
.endm
.macro B_ISMOL label
ENTRY_TEST 0,MAX_NUM_SESSIONS
b 67f
66:
cmpwi cr1,r5,0
mr r1,r5
beq- cr1,67f
b \label
67:
.endm
////////////////////////////////////////////////////////////////////
// mac_entry_test
//
// mac_mode: r4,r5 = MOL_ENTRY_RX_MAGIC
// r6 = call_kernel return point (if initializing)
// r7 = session magic
mac_entry_test:
cmpwi cr0,r4,MOL_ENTRY_R4_MAGIC // MOL switch magic.
cmpwi cr1,r5,MOL_ENTRY_R5_MAGIC // Also gives us a couple of extra regs.
crand eq,eq,cr1*4+eq
SET_SESSION_TABLE r1
beq+ 1f
cmpwi cr0,r4,MOL_INITIALIZE_R4_MAGIC
cmpwi cr1,r5,MOL_INITIALIZE_R5_MAGIC
crand eq,eq,cr1*4+eq
bne+ 2f
B_ISMOL mac_entry_initialize // M: r4,r5
b 3f
1:
B_ISMOL mac_entry // M: r4,r5
b 3f
2:
mtcr r3 // Restore registers
mfsprg1 r1
mfsprg0 r3
b continue_trap_0x700
3: // XXX FIXME
b 2b
//////////////////////////////////////////////////////////
// mac_entry_initialize
//
// Run once in order to store certain things (segment
// registers and NIP)
//
// r6 emulator return point after 'call_kernel'
//
// Safe to modify: r0-r12, lr, ctr
mac_entry_initialize:
// Save emulator return point (skip over illegal inst)
mfsrr0 r5
addi r5,r5,4
stw r5,K_EMULATOR_NIP(r1) // This sets the return point once and for all
stw r2,K_EMULATOR_TOC(r1) // r2==TOC (not on linux though)
stw r6,K_EMULATOR_KCALL_NIP(r1) // Return point after 'call_kernel'
mfsrr1 r6
mfsprg1 r3
stw r6,K_EMULATOR_MSR(r1) // we want to return through mac_exit
stw r3,K_EMULATOR_STACK(r1)
lwz r3,xFLAG_BITS(r1) // Best to initialize the flag bits
mtcr r3
#if 0 // DEBUG DEBUG DEBUG
crset FBIT_CheckFlags
crset FBIT_RecalcDecInt
#endif
addi r3,r1,K_EMULATOR_SR // Save segment registers
SAVE_SEGMENT_REGS r3, /**/ r4,r5
SAVE_IBATS K_IBAT0U_SAVE, /**/ r3 // And save linux BAT registers
SAVE_DBATS K_DBAT0U_SAVE, /**/ r3
bl initialize_spr_table
bl initialize_msr_sr_table
bl _msr_altered // ALERT: modifies srr1. Reloads segment registers(!)
addi r3,r1,K_EMULATOR_SR
LOAD_SEGMENT_REGS r3, /**/ r4,r5
li r3,RVEC_EXIT
b exit_
//////////////////////////////////////////////////////////
// mac_entry
//
// sprg1 emulator stack
// srr1 emulator msr
// r13-r31 mac gprs
// fr14-fr31 mac fp registers
// fr0-fr12 mac fp registers (see xFPU_STATE)
//
// This function gives the 'mac' the control over the
// processor.
mac_entry:
TRACE(0x1111, "mac_entry")
// Save emulator registers (r1,msr) and restore flag bits
mfsprg1 r3
lwz r4,xFLAG_BITS(r1)
stw r3,K_EMULATOR_STACK(r1)
mfsrr1 r6
mtcr r4
stw r6,K_EMULATOR_MSR(r1) // The MSR_FP/MSR_VEC bits are of interest...
// Setup mac-environment
lwz r0,xNIP(r1) // Set NIP
lwz r2,x_MSR(r1) // The FPU bit should always be disabled here...
mtsrr0 r0 // srr0 is used by prepare_splitmode
rlwinm r2,r2,0,7,5 // We always clear MSR_VEC
stw r2,x_MSR(r1) // (enabling MSR_VEC is relatively cheap)
mtsrr1 r2
bl set_mac_context // M: r0,r2-r12,XER
bl set_mol_dec
RESTORE_MIDDLE_REGS // Loads r6-r12, ctr, xer
b exception_return // Loads r0-r5, lr, cr
// All returns to mac-mode goes through this function
exception_return:
lwz r3,K_RELOAD_SR(r1) // Do we need to reload segment registers & dbat0?
cmpwi r3,0
bnel- reload_sr // M: r3-r5
bt FBIT_CheckFlags,check_flags // M: r0,r2-r5
1: lwz r2,xLINK(r1)
lwz r0,xCR(r1)
mtlr r2
lwz r3,xGPR3(r1)
lwz r4,xGPR4(r1)
mfcr r2 // Save flag bits
lwz r5,xGPR5(r1)
stw r2,xFLAG_BITS(r1)
mtcr r0
lwz r2,xGPR2(r1)
lwz r0,xGPR0(r1)
lwz r1,xGPR1(r1)
rfi
// May modify r0,r2-r5. The call order is important.
check_flags:
// btl FBIT_Exception, throw_exception
// btl FBIT_MsrModified, msr_modified
btl FBIT_RecalcDecInt, recalc_int_stamp // M: r0,r2-r5
crclr FBIT_CheckFlags
b 1b
throw_exception:
blr
msr_modified:
blr
/************************************************************************/
/* Exit Mac-Mode Paths */
/************************************************************************/
// THESE ARE _ALL_ THE POSSIBLE EXIT PATHS. KEEP IT THAT WAY
// OR HAVE A *VERY GOOD* REASON TO INTRODUCE A NEW ONE.
/////////////////////////////////////////////////////////
// fixup_fpu
//
// Save fpscr and fpr13 and clear the MSR_FP bit.
// Restore the emulator fpscr value.
//
// modifies: r7,r8 (turns on MSR_FP if FP is set in x_MSR)
fixup_fpu:
lwz r7,xFPU_STATE(r1)
cmpwi r7,FPU_STATE_IN_USE // Are we the owner of the FPU?
bnelr
lwz r7,x_MSR(r1)
rlwinm r8,r7,0,19,17 // Clear MSR_FP bit
stw r8,x_MSR(r1)
mfmsr r7 // Temporary enable FPU in order to
ori r8,r7,MSR_FP // save fpscr and fpr13
mtmsr r8
isync
stfd fr13,xFPR13(r1)
mffs fr13
stfd fr13,xFPSCR-4(r1)
li r7,FPU_STATE_DIRTY
lfd fr13,xEMULATOR_FPSCR-4(r1) // We must restore FPSCR before since the emulator might
mtfsf 0xff,fr13 // use the FPU at any time, for instance in a signal handler.
stw r7,xFPU_STATE(r1) // Go to FPU_STATE_DIRTY
blr
////////////////////////////////////////////////////////
// PREPARE_ERET
//
// M: r0-r2, r9-r11 (r1 is modified)
.macro PREP_ERET nip_variable
btl FBIT_MolDecLoaded, set_kernel_dec // M: r0,r2,r9-r11
lwz r10,\nip_variable(r1)
mfcr r9
lwz r11,K_EMULATOR_MSR(r1)
mtsrr0 r10
lwz r2,K_EMULATOR_TOC(r1)
stw r9,xFLAG_BITS(r1)
lwz r1,K_EMULATOR_STACK(r1)
mtsrr1 r11
.endm
////////////////////////////////////////////////////////
// mac_exit (return to emulator)
// r3 RVEC return code
//
// On stack: nip, ctr, lr, xer, r0-r12
// In registers: r13-r31
mac_exit:
TRACE(0x2220, "mac_exit")
bl fixup_fpu // M: r7,r8
bl set_emulator_context // M: r0,r2,r7-r11,XER
exit_:
PREP_ERET K_EMULATOR_NIP // M: r0-r2,r9-r11
rfi
////////////////////////////////////////////////////////
// take_exception (take a linux exception)
//
// On stack: nip, ctr, lr, xer, r0-r12
// In registers: r13-r31
take_exception:
TRACE(0x2221, "take_exception")
mflr r12
bl fixup_fpu // M: r7,r8
bl set_emulator_context // M: r0,r2,r7-r11,XER
PREP_ERET K_EMULATOR_NIP // M: r0-r2,r9-r11
mtlr r12
li r3,RVEC_NOP
blr
//////////////////////////////////////////////////////////////
// call_kernel (call mol kernel routine)
// r3 kernel routine
// r4..r6 args
//
// On stack: nip, ctr, lr, xer, r0-r12
// In registers: r13-r31
call_kernel_save:
bl save_middle_regs // saves r6-r11, nip, ctr, xer
call_kernel:
bl fixup_fpu // M: r7,r8
bl set_emulator_context // M: r0,r2,r7-r11,XER
TRACE(0x2222, "call_kernel")
lwz r8,K_KERNEL_VARS(r1) // r8 = kvars (lvptr)
PREP_ERET K_EMULATOR_KCALL_NIP // M: r0-r2,r9-r11
li r0,__NR_multiplexer
mr r7,r3
li r3,fCallKernelFunc // r4,r5,r6 args, r7=function, r8=kvars
b continue_trap_0xc00 // fake a syscall
/************************************************************************/
/* Set Mac/Emulator Context */
/************************************************************************/
//////////////////////////////////////////////////////////////
// set_mac_context [r0,r2-r12, ctr, --->XER<---]
//
// - load segr 0-15 with mac context
// - clear BATs
//
// Currently unmodified r8-r12, ctr
set_mac_context:
li r4,0 // segment registers are soon up to date
lwz r3,K_PREPARE_SPLITMODE(r1)
stw r4,K_RELOAD_SR(r1)
cmpwi r3,0
beq+ 1f
mflr r2
bl prepare_splitmode // mod. r0,r3-r5
mtlr r2
1:
// Save and setup SPRG2 (magic) and SPRG3 (mol stack)
mfsprg2 r6
mfsprg3 r7
stw r6,K_EMULATOR_SPRG2(r1)
stw r7,K_EMULATOR_SPRG3(r1)
li r2,MOL_SPRG2_MAGIC
mtsprg3 r1
mtsprg2 r2
// Load segment registers
lwz r3,K_CUR_SR_BASE(r1)
LOAD_SEGMENT_REGS r3, /**/ r4,r5
li r4,0
mtspr IBAT0U,r4
mtspr IBAT1U,r4
mtspr IBAT2U,r4
mtspr IBAT3U,r4
lwz r3,K_DBAT0L(r1)
lwz r5,K_DBAT0U(r1)
mtspr DBAT0L,r3
mtspr DBAT0U,r5
mtspr DBAT1U,r4
mtspr DBAT2U,r4
mtspr DBAT3U,r4
blr
///////////////////////////////////////////////////////////////
// set_emulator_context [r0,r2,r7-r11,cr, --->XER<---]
//
// - load segr 0-15 with emulator context
// - restore BATs
// - restore DEC register
set_emulator_context:
lwz r0,K_EMULATOR_SPRG2(r1)
lwz r2,K_EMULATOR_SPRG3(r1)
mtsprg2 r0
mtsprg3 r2
// Restore segment registers
addi r8,r1,K_EMULATOR_SR
LOAD_SEGMENT_REGS r8, /**/ r2,r10
// BATS, r11 = linux DEC
lwz r7,K_IBAT0U_SAVE(r1)
mtspr IBAT0U,r7
lwz r2,K_IBAT1U_SAVE(r1)
mtspr IBAT1U,r2
lwz r7,K_IBAT2U_SAVE(r1)
mtspr IBAT2U,r7
lwz r2,K_IBAT3U_SAVE(r1)
mtspr IBAT3U,r2
lwz r7,K_DBAT0U_SAVE(r1)
mtspr DBAT0U,r7
lwz r7,K_DBAT0L_SAVE(r1) // must also restore lower bat...
mtspr DBAT0L,r7
lwz r2,K_DBAT1U_SAVE(r1)
mtspr DBAT1U,r2
lwz r7,K_DBAT2U_SAVE(r1)
mtspr DBAT2U,r7
lwz r2,K_DBAT3U_SAVE(r1)
mtspr DBAT3U,r2
blr
/************************************************************************/
/* Reload Segment Registers */
/************************************************************************/
//////////////////////////////////////////////////////////////
// reload_sr
//
// - loads segr 0-15 with mac context [modifies r3-r5]
// - reloads DBAT0 (used for splitmode)
//
// Modifies: r3-r5
reload_sr:
li r3,0 // segment registers are soon up to date
stw r3,K_RELOAD_SR(r1)
lwz r4,K_CUR_SR_BASE(r1)
LOAD_SEGMENT_REGS r4, /**/ r3,r5
lwz r3,K_DBAT0L(r1) // reload DBAT0
lwz r4,K_DBAT0U(r1)
mtspr DBAT0L,r3
mtspr DBAT0U,r4
blr
|