1/* 2 * Copyright 2006-2010, Ingo Weinhold <ingo_weinhold@gmx.de>. 3 * All rights reserved. Distributed under the terms of the MIT License. 4 * 5 * Copyright 2003, Travis Geiselbrecht. All rights reserved. 6 * Distributed under the terms of the NewOS License. 7 */ 8 9 10#include "asm_defs.h" 11#include "asm_offsets.h" 12 13#define MSR_EXCEPTIONS_ENABLED 15 14 15.text 16 17// TODO: FIXME 18FUNCTION(reboot): 19 b . 20FUNCTION_END(reboot) 21 22 23/* void arch_int_enable_interrupts(void) */ 24FUNCTION(arch_int_enable_interrupts): 25 mfmsr %r3 // load msr 26 27 li %r4, 1 28 insrwi %r3, %r4, 1, 31 - MSR_EXCEPTIONS_ENABLED 29 // sets bit 15, EE 30 31 mtmsr %r3 // put it back into the msr 32 isync 33 blr 34FUNCTION_END(arch_int_enable_interrupts) 35 36 37/* int arch_int_disable_interrupts(void) 38 * r3 39 */ 40FUNCTION(arch_int_disable_interrupts): 41 mfmsr %r4 // load msr 42 43 mr %r3, %r4 // save old state 44 rlwinm %r4, %r4, 0, 32 - MSR_EXCEPTIONS_ENABLED, 30 - MSR_EXCEPTIONS_ENABLED 45 // clears bit 15, EE 46 47 mtmsr %r4 // put it back into the msr 48 isync 49 blr 50FUNCTION_END(arch_int_disable_interrupts) 51 52 53/* void arch_int_restore_interrupts(int oldState) 54 * r3 55 */ 56FUNCTION(arch_int_restore_interrupts): 57 mfmsr %r4 58 59 rlwimi %r4, %r3, 0, 31 - MSR_EXCEPTIONS_ENABLED, 31 - MSR_EXCEPTIONS_ENABLED 60 // clear or set bit 15, EE to the same state as in r3, oldState 61 62 mtmsr %r4 63 isync 64 blr 65FUNCTION_END(arch_int_restore_interrupts) 66 67 68/* bool arch_int_are_interrupts_enabled(void) */ 69FUNCTION(arch_int_are_interrupts_enabled): 70 mfmsr %r3 // load msr 71 extrwi %r3, %r3, 1, 31 - MSR_EXCEPTIONS_ENABLED 72 // mask out the EE bit 73 blr 74FUNCTION_END(arch_int_are_interrupts_enabled) 75 76 77// TODO: FIXME 78FUNCTION(dbg_save_registers): 79 blr 80FUNCTION_END(dbg_save_registers) 81 82/* long long get_time_base(void) */ 83FUNCTION(get_time_base): 841: 85 mftbu %r3 // get the upper time base register 86 mftb %r4 // get the lower time base register 87 mftbu %r5 // get the upper again 88 cmpw %r5, %r3 // see if it changed while we were reading the lower 89 bne- 1b // if so, repeat 90 blr 91FUNCTION_END(get_time_base) 92 93 94/* void getibats(int bats[8]); */ 95FUNCTION(getibats): 96 mfibatu %r0,0 97 stw %r0,0(%r3) 98 mfibatl %r0,0 99 stwu %r0,4(%r3) 100 mfibatu %r0,1 101 stwu %r0,4(%r3) 102 mfibatl %r0,1 103 stwu %r0,4(%r3) 104 mfibatu %r0,2 105 stwu %r0,4(%r3) 106 mfibatl %r0,2 107 stwu %r0,4(%r3) 108 mfibatu %r0,3 109 stwu %r0,4(%r3) 110 mfibatl %r0,3 111 stwu %r0,4(%r3) 112 blr 113FUNCTION_END(getibats) 114 115 116// void setibats(int bats[8]); 117FUNCTION(setibats): 118 lwz %r0,0(%r3) 119 mtibatu 0,%r0 120 isync 121 lwzu %r0,4(%r3) 122 mtibatl 0,%r0 123 isync 124 lwzu %r0,4(%r3) 125 mtibatu 1,%r0 126 isync 127 lwzu %r0,4(%r3) 128 mtibatl 1,%r0 129 isync 130 lwzu %r0,4(%r3) 131 mtibatu 2,%r0 132 isync 133 lwzu %r0,4(%r3) 134 mtibatl 2,%r0 135 isync 136 lwzu %r0,4(%r3) 137 mtibatu 3,%r0 138 isync 139 lwzu %r0,4(%r3) 140 mtibatl 3,%r0 141 isync 142 143 blr 144FUNCTION_END(setibats) 145 146 147// void getdbats(int bats[8]); 148FUNCTION(getdbats): 149 mfdbatu %r0,0 150 stw %r0,0(%r3) 151 mfdbatl %r0,0 152 stwu %r0,4(%r3) 153 mfdbatu %r0,1 154 stwu %r0,4(%r3) 155 mfdbatl %r0,1 156 stwu %r0,4(%r3) 157 mfdbatu %r0,2 158 stwu %r0,4(%r3) 159 mfdbatl %r0,2 160 stwu %r0,4(%r3) 161 mfdbatu %r0,3 162 stwu %r0,4(%r3) 163 mfdbatl %r0,3 164 stwu %r0,4(%r3) 165 blr 166FUNCTION_END(getdbats) 167 168 169// void setdbats(int bats[8]); 170FUNCTION(setdbats): 171 lwz %r0,0(%r3) 172 mtdbatu 0,%r0 173 lwzu %r0,4(%r3) 174 mtdbatl 0,%r0 175 lwzu %r0,4(%r3) 176 mtdbatu 1,%r0 177 lwzu %r0,4(%r3) 178 mtdbatl 1,%r0 179 lwzu %r0,4(%r3) 180 mtdbatu 2,%r0 181 lwzu %r0,4(%r3) 182 mtdbatl 2,%r0 183 lwzu %r0,4(%r3) 184 mtdbatu 3,%r0 185 lwzu %r0,4(%r3) 186 mtdbatl 3,%r0 187 sync 188 189 blr 190FUNCTION_END(setdbats) 191 192 193// unsigned int gethid0(); 194FUNCTION(gethid0): 195 mfspr %r3, 1008 196 blr 197FUNCTION_END(gethid0) 198 199 200// void sethid0(unsigned int val); 201FUNCTION(sethid0): 202 isync 203 mtspr 1008, %r3 204 isync 205 blr 206FUNCTION_END(sethid0) 207 208 209// unsigned int getl2cr(); 210FUNCTION(getl2cr): 211 mfspr %r3, 1017 212 blr 213FUNCTION_END(getl2cr) 214 215 216// void setl2cr(unsigned int val); 217FUNCTION(setl2cr): 218 isync 219 mtspr 1017, %r3 220 isync 221 blr 222FUNCTION_END(setl2cr) 223 224 225// void ppc_context_switch(addr_t *old_sp, addr_t new_sp); 226FUNCTION(ppc_context_switch): 227 228 // regs to push on the stack: f13-f31, r13-r31, cr, r2, lr 229 230 // push the old regs we need to save on the stack 231 // f31-13 232 stfdu %f31, -8(%r1) 233 stfdu %f30, -8(%r1) 234 stfdu %f29, -8(%r1) 235 stfdu %f28, -8(%r1) 236 stfdu %f27, -8(%r1) 237 stfdu %f26, -8(%r1) 238 stfdu %f25, -8(%r1) 239 stfdu %f24, -8(%r1) 240 stfdu %f23, -8(%r1) 241 stfdu %f22, -8(%r1) 242 stfdu %f21, -8(%r1) 243 stfdu %f20, -8(%r1) 244 stfdu %f19, -8(%r1) 245 stfdu %f18, -8(%r1) 246 stfdu %f17, -8(%r1) 247 stfdu %f16, -8(%r1) 248 stfdu %f15, -8(%r1) 249 stfdu %f14, -8(%r1) 250 stfdu %f13, -8(%r1) 251 252 // r31-13, r2 253 stwu %r31, -4(%r1) 254 stwu %r30, -4(%r1) 255 stwu %r29, -4(%r1) 256 stwu %r28, -4(%r1) 257 stwu %r27, -4(%r1) 258 stwu %r26, -4(%r1) 259 stwu %r25, -4(%r1) 260 stwu %r24, -4(%r1) 261 stwu %r23, -4(%r1) 262 stwu %r22, -4(%r1) 263 stwu %r21, -4(%r1) 264 stwu %r20, -4(%r1) 265 stwu %r19, -4(%r1) 266 stwu %r18, -4(%r1) 267 stwu %r17, -4(%r1) 268 stwu %r16, -4(%r1) 269 stwu %r15, -4(%r1) 270 stwu %r14, -4(%r1) 271 stwu %r13, -4(%r1) 272 stwu %r2, -4(%r1) 273 274 // CR and LR 275 mfcr %r0 276 stwu %r0, -4(%r1) 277 mflr %r0 278 stwu %r0, -4(%r1) 279 280 // save the old stack pointer 281 stwu %r1, 0(%r3) 282 283 // restore the new stack pointer 284 mr %r1, %r4 285 286 // restore the new regs 287 // LR and CR 288 lwz %r0, 0(%r1) 289 mtlr %r0 290 lwzu %r0, 4(%r1) 291 mtcr %r0 292 293 // r2, r13-31 294 lwzu %r2, 4(%r1) 295 lwzu %r13, 4(%r1) 296 lwzu %r14, 4(%r1) 297 lwzu %r15, 4(%r1) 298 lwzu %r16, 4(%r1) 299 lwzu %r17, 4(%r1) 300 lwzu %r18, 4(%r1) 301 lwzu %r19, 4(%r1) 302 lwzu %r20, 4(%r1) 303 lwzu %r21, 4(%r1) 304 lwzu %r22, 4(%r1) 305 lwzu %r23, 4(%r1) 306 lwzu %r24, 4(%r1) 307 lwzu %r25, 4(%r1) 308 lwzu %r26, 4(%r1) 309 lwzu %r27, 4(%r1) 310 lwzu %r28, 4(%r1) 311 lwzu %r29, 4(%r1) 312 lwzu %r30, 4(%r1) 313 lwzu %r31, 4(%r1) 314 315 // f13-31 316 lfdu %f13, 4(%r1) 317 lfdu %f14, 8(%r1) 318 lfdu %f15, 8(%r1) 319 lfdu %f16, 8(%r1) 320 lfdu %f17, 8(%r1) 321 lfdu %f18, 8(%r1) 322 lfdu %f19, 8(%r1) 323 lfdu %f20, 8(%r1) 324 lfdu %f21, 8(%r1) 325 lfdu %f22, 8(%r1) 326 lfdu %f23, 8(%r1) 327 lfdu %f24, 8(%r1) 328 lfdu %f25, 8(%r1) 329 lfdu %f26, 8(%r1) 330 lfdu %f27, 8(%r1) 331 lfdu %f28, 8(%r1) 332 lfdu %f29, 8(%r1) 333 lfdu %f30, 8(%r1) 334 lfdu %f31, 8(%r1) 335 336 addi %r1, %r1, 8 337 338 blr 339FUNCTION_END(ppc_context_switch) 340 341 342// ppc_kernel_thread_root(): parameters in r13-r15, the functions to call 343// (in that order). The function is used when spawing threads. It usually calls 344// an initialization function, the actual thread function, and a function that 345// destroys the thread. 346FUNCTION(ppc_kernel_thread_root): 347 mtlr %r13 348 blrl 349 mtlr %r14 350 blrl 351 mtlr %r15 352 blrl 353 354 // We should never get here. If we do, it's time to enter the kernel 355 // debugger (without a message at the moment). 356 li %r3, 0 357 b kernel_debugger 358FUNCTION_END(ppc_kernel_thread_root) 359 360 361/*! \fn void arch_debug_call_with_fault_handler(cpu_ent* cpu, 362 jmp_buf jumpBuffer, void (*function)(void*), void* parameter) 363 364 Called by debug_call_with_fault_handler() to do the dirty work of setting 365 the fault handler and calling the function. If the function causes a page 366 fault, the arch_debug_call_with_fault_handler() calls longjmp() with the 367 given \a jumpBuffer. Otherwise it returns normally. 368 369 debug_call_with_fault_handler() has already saved the CPU's fault_handler 370 and fault_handler_stack_pointer and will reset them later, so 371 arch_debug_call_with_fault_handler() doesn't need to care about it. 372 373 \param cpu The \c cpu_ent for the current CPU. 374 \param jumpBuffer Buffer to be used for longjmp(). 375 \param function The function to be called. 376 \param parameter The parameter to be passed to the function to be called. 377*/ 378FUNCTION(arch_debug_call_with_fault_handler): 379 // prolog: setup stack frame (16-byte aligned) 380 mflr %r0 381 stw %r0, 4(%r1) // store LR 382 stwu %r1, -16(%r1) // store back chain 383 stw %r4, 8(%r1) // store jumpBuffer 384 385 // set cpu->fault_handler_stack_pointer 386 stw %r1, CPU_ENT_fault_handler_stack_pointer(%r3) 387 388 // set cpu->fault_handler 389 lis %r11, 1f@ha 390 ori %r11, %r11, 1f@l 391 stw %r11, CPU_ENT_fault_handler(%r3) 392 393 // call the given function 394 mr %r3, %r6 395 mtlr %r5 396 blrl 397 398 // epilog: restore stack frame 399 lwz %r0, 16 + 4(%r1) // load LR 400 mtlr %r0 401 addi %r1, %r1, 16 // restore SP 402 403 blr 404 405 // fault -- return via longjmp(jumpBuffer, 1) 4061: 407 lwz %r3, 8(%r1) // load jumpBuffer 408 409 // call longjmp 410 li %r4, 1 411 lis %r0, longjmp@ha 412 ori %r0, %r0, longjmp@l 413 mtlr %r0 414 blr 415FUNCTION_END(arch_debug_call_with_fault_handler) 416 417 418/* status_t arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr_t *faultHandler) */ 419FUNCTION(_arch_cpu_user_memcpy): 420 // TODO 421 blr 422FUNCTION_END(_arch_cpu_user_memcpy) 423 424 425/* status_t arch_cpu_user_memset(void *to, char c, size_t count, addr_t *faultHandler) */ 426FUNCTION(_arch_cpu_user_memset): 427 // TODO 428 blr 429FUNCTION_END(_arch_cpu_user_memset) 430 431 432/* ssize_t arch_cpu_user_strlcpy(void *to, const void *from, size_t size, addr_t *faultHandler) */ 433FUNCTION(_arch_cpu_user_strlcpy): 434 // TODO 435 blr 436FUNCTION_END(_arch_cpu_user_strlcpy) 437 438