PageRenderTime 75ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/sys/mips/mips/swtch.S

https://github.com/okuoku/freebsd-head
Assembly | 583 lines | 563 code | 20 blank | 0 comment | 9 complexity | 3d27684e47995b51c596067586d60dcd MD5 | raw file
  1. /* $OpenBSD: locore.S,v 1.18 1998/09/15 10:58:53 pefo Exp $ */
  2. /*-
  3. * Copyright (c) 1992, 1993
  4. * The Regents of the University of California. All rights reserved.
  5. *
  6. * This code is derived from software contributed to Berkeley by
  7. * Digital Equipment Corporation and Ralph Campbell.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 4. Neither the name of the University nor the names of its contributors
  18. * may be used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. *
  33. * Copyright (C) 1989 Digital Equipment Corporation.
  34. * Permission to use, copy, modify, and distribute this software and
  35. * its documentation for any purpose and without fee is hereby granted,
  36. * provided that the above copyright notice appears in all copies.
  37. * Digital Equipment Corporation makes no representations about the
  38. * suitability of this software for any purpose. It is provided "as is"
  39. * without express or implied warranty.
  40. *
  41. * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s,
  42. * v 1.1 89/07/11 17:55:04 nelson Exp SPRITE (DECWRL)
  43. * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s,
  44. * v 9.2 90/01/29 18:00:39 shirriff Exp SPRITE (DECWRL)
  45. * from: Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s,
  46. * v 1.1 89/07/10 14:27:41 nelson Exp SPRITE (DECWRL)
  47. *
  48. * from: @(#)locore.s 8.5 (Berkeley) 1/4/94
  49. * JNPR: swtch.S,v 1.6.2.1 2007/09/10 10:36:50 girish
  50. * $FreeBSD$
  51. */
  52. /*
  53. * Contains code that is the first executed at boot time plus
  54. * assembly language support routines.
  55. */
  56. #include "opt_cputype.h"
  57. #include <sys/syscall.h>
  58. #include <machine/asm.h>
  59. #include <machine/cpu.h>
  60. #include <machine/cpuregs.h>
  61. #include <machine/regnum.h>
  62. #include <machine/pte.h>
  63. #include "assym.s"
  64. .set noreorder # Noreorder is default style!
  65. #define SAVE_U_PCB_REG(reg, offs, base) \
  66. REG_S reg, U_PCB_REGS + (SZREG * offs) (base)
  67. #define RESTORE_U_PCB_REG(reg, offs, base) \
  68. REG_L reg, U_PCB_REGS + (SZREG * offs) (base)
  69. #define SAVE_U_PCB_FPREG(reg, offs, base) \
  70. FP_S reg, U_PCB_FPREGS + (SZFPREG * offs) (base)
  71. #define RESTORE_U_PCB_FPREG(reg, offs, base) \
  72. FP_L reg, U_PCB_FPREGS + (SZFPREG * offs) (base)
  73. #define SAVE_U_PCB_FPSR(reg, offs, base) \
  74. REG_S reg, U_PCB_FPREGS + (SZFPREG * offs) (base)
  75. #define RESTORE_U_PCB_FPSR(reg, offs, base) \
  76. REG_L reg, U_PCB_FPREGS + (SZFPREG * offs) (base)
  77. #define SAVE_U_PCB_CONTEXT(reg, offs, base) \
  78. REG_S reg, U_PCB_CONTEXT + (SZREG * offs) (base)
  79. #define RESTORE_U_PCB_CONTEXT(reg, offs, base) \
  80. REG_L reg, U_PCB_CONTEXT + (SZREG * offs) (base)
  81. /*
  82. * Setup for and return to user.
  83. */
  84. LEAF(fork_trampoline)
  85. move a0,s0
  86. move a1,s1
  87. jal _C_LABEL(fork_exit)
  88. move a2,s2 #BDSlot
  89. DO_AST
  90. mfc0 v0, MIPS_COP_0_STATUS
  91. and v0, ~(MIPS_SR_INT_IE)
  92. mtc0 v0, MIPS_COP_0_STATUS # disable interrupts
  93. COP0_SYNC
  94. /*
  95. * The use of k1 for storing the PCB pointer must be done only
  96. * after interrupts are disabled. Otherwise it will get overwritten
  97. * by the interrupt code.
  98. */
  99. .set noat
  100. GET_CPU_PCPU(k1)
  101. PTR_L k1, PC_CURPCB(k1)
  102. RESTORE_U_PCB_REG(t0, MULLO, k1)
  103. RESTORE_U_PCB_REG(t1, MULHI, k1)
  104. mtlo t0
  105. mthi t1
  106. RESTORE_U_PCB_REG(a0, PC, k1)
  107. RESTORE_U_PCB_REG(AT, AST, k1)
  108. RESTORE_U_PCB_REG(v0, V0, k1)
  109. MTC0 a0, MIPS_COP_0_EXC_PC # set return address
  110. RESTORE_U_PCB_REG(v1, V1, k1)
  111. RESTORE_U_PCB_REG(a0, A0, k1)
  112. RESTORE_U_PCB_REG(a1, A1, k1)
  113. RESTORE_U_PCB_REG(a2, A2, k1)
  114. RESTORE_U_PCB_REG(a3, A3, k1)
  115. RESTORE_U_PCB_REG(t0, T0, k1)
  116. RESTORE_U_PCB_REG(t1, T1, k1)
  117. RESTORE_U_PCB_REG(t2, T2, k1)
  118. RESTORE_U_PCB_REG(t3, T3, k1)
  119. RESTORE_U_PCB_REG(ta0, TA0, k1)
  120. RESTORE_U_PCB_REG(ta1, TA1, k1)
  121. RESTORE_U_PCB_REG(ta2, TA2, k1)
  122. RESTORE_U_PCB_REG(ta3, TA3, k1)
  123. RESTORE_U_PCB_REG(s0, S0, k1)
  124. RESTORE_U_PCB_REG(s1, S1, k1)
  125. RESTORE_U_PCB_REG(s2, S2, k1)
  126. RESTORE_U_PCB_REG(s3, S3, k1)
  127. RESTORE_U_PCB_REG(s4, S4, k1)
  128. RESTORE_U_PCB_REG(s5, S5, k1)
  129. RESTORE_U_PCB_REG(s6, S6, k1)
  130. RESTORE_U_PCB_REG(s7, S7, k1)
  131. RESTORE_U_PCB_REG(t8, T8, k1)
  132. RESTORE_U_PCB_REG(t9, T9, k1)
  133. RESTORE_U_PCB_REG(k0, SR, k1)
  134. RESTORE_U_PCB_REG(gp, GP, k1)
  135. RESTORE_U_PCB_REG(s8, S8, k1)
  136. RESTORE_U_PCB_REG(ra, RA, k1)
  137. RESTORE_U_PCB_REG(sp, SP, k1)
  138. li k1, ~MIPS_SR_INT_MASK
  139. and k0, k0, k1
  140. mfc0 k1, MIPS_COP_0_STATUS
  141. and k1, k1, MIPS_SR_INT_MASK
  142. or k0, k0, k1
  143. mtc0 k0, MIPS_COP_0_STATUS # switch to user mode (when eret...)
  144. HAZARD_DELAY
  145. sync
  146. eret
  147. .set at
  148. END(fork_trampoline)
  149. /*
  150. * Update pcb, saving current processor state.
  151. * Note: this only works if pcbp != curproc's pcb since
  152. * cpu_switch() will copy over pcb_context.
  153. *
  154. * savectx(struct pcb *pcbp);
  155. */
  156. LEAF(savectx)
  157. SAVE_U_PCB_CONTEXT(s0, PREG_S0, a0)
  158. SAVE_U_PCB_CONTEXT(s1, PREG_S1, a0)
  159. SAVE_U_PCB_CONTEXT(s2, PREG_S2, a0)
  160. SAVE_U_PCB_CONTEXT(s3, PREG_S3, a0)
  161. mfc0 v0, MIPS_COP_0_STATUS
  162. SAVE_U_PCB_CONTEXT(s4, PREG_S4, a0)
  163. SAVE_U_PCB_CONTEXT(s5, PREG_S5, a0)
  164. SAVE_U_PCB_CONTEXT(s6, PREG_S6, a0)
  165. SAVE_U_PCB_CONTEXT(s7, PREG_S7, a0)
  166. SAVE_U_PCB_CONTEXT(sp, PREG_SP, a0)
  167. SAVE_U_PCB_CONTEXT(s8, PREG_S8, a0)
  168. SAVE_U_PCB_CONTEXT(ra, PREG_RA, a0)
  169. SAVE_U_PCB_CONTEXT(v0, PREG_SR, a0)
  170. SAVE_U_PCB_CONTEXT(gp, PREG_GP, a0)
  171. move v0, ra /* save 'ra' before we trash it */
  172. jal 1f
  173. nop
  174. 1:
  175. SAVE_U_PCB_CONTEXT(ra, PREG_PC, a0)
  176. move ra, v0 /* restore 'ra' before returning */
  177. j ra
  178. move v0, zero
  179. END(savectx)
  180. NON_LEAF(cpu_throw, CALLFRAME_SIZ, ra)
  181. mfc0 t0, MIPS_COP_0_STATUS # t0 = saved status register
  182. nop
  183. nop
  184. and a3, t0, ~(MIPS_SR_INT_IE)
  185. mtc0 a3, MIPS_COP_0_STATUS # Disable all interrupts
  186. ITLBNOPFIX
  187. j mips_sw1 # We're not interested in old
  188. # thread's context, so jump
  189. # right to action
  190. nop # BDSLOT
  191. END(cpu_throw)
  192. /*
  193. * cpu_switch(struct thread *old, struct thread *new, struct mutex *mtx);
  194. * a0 - old
  195. * a1 - new
  196. * a2 - mtx
  197. * Find the highest priority process and resume it.
  198. */
  199. NON_LEAF(cpu_switch, CALLFRAME_SIZ, ra)
  200. mfc0 t0, MIPS_COP_0_STATUS # t0 = saved status register
  201. nop
  202. nop
  203. and a3, t0, ~(MIPS_SR_INT_IE)
  204. mtc0 a3, MIPS_COP_0_STATUS # Disable all interrupts
  205. ITLBNOPFIX
  206. beqz a0, mips_sw1
  207. move a3, a0
  208. PTR_L a0, TD_PCB(a0) # load PCB addr of curproc
  209. SAVE_U_PCB_CONTEXT(sp, PREG_SP, a0) # save old sp
  210. PTR_SUBU sp, sp, CALLFRAME_SIZ
  211. REG_S ra, CALLFRAME_RA(sp)
  212. .mask 0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
  213. SAVE_U_PCB_CONTEXT(s0, PREG_S0, a0) # do a 'savectx()'
  214. SAVE_U_PCB_CONTEXT(s1, PREG_S1, a0)
  215. SAVE_U_PCB_CONTEXT(s2, PREG_S2, a0)
  216. SAVE_U_PCB_CONTEXT(s3, PREG_S3, a0)
  217. SAVE_U_PCB_CONTEXT(s4, PREG_S4, a0)
  218. SAVE_U_PCB_CONTEXT(s5, PREG_S5, a0)
  219. SAVE_U_PCB_CONTEXT(s6, PREG_S6, a0)
  220. SAVE_U_PCB_CONTEXT(s7, PREG_S7, a0)
  221. SAVE_U_PCB_CONTEXT(s8, PREG_S8, a0)
  222. SAVE_U_PCB_CONTEXT(ra, PREG_RA, a0) # save return address
  223. SAVE_U_PCB_CONTEXT(t0, PREG_SR, a0) # save status register
  224. SAVE_U_PCB_CONTEXT(gp, PREG_GP, a0)
  225. jal getpc
  226. nop
  227. getpc:
  228. SAVE_U_PCB_CONTEXT(ra, PREG_PC, a0) # save return address
  229. PTR_S a2, TD_LOCK(a3) # Switchout td_lock
  230. mips_sw1:
  231. #if defined(SMP) && defined(SCHED_ULE)
  232. PTR_LA t0, _C_LABEL(blocked_lock)
  233. blocked_loop:
  234. PTR_L t1, TD_LOCK(a1)
  235. beq t0, t1, blocked_loop
  236. nop
  237. #endif
  238. move s7, a1 # Store newthread
  239. /*
  240. * Switch to new context.
  241. */
  242. GET_CPU_PCPU(a3)
  243. PTR_S a1, PC_CURTHREAD(a3)
  244. PTR_L a2, TD_PCB(a1)
  245. PTR_S a2, PC_CURPCB(a3)
  246. PTR_L v0, TD_KSTACK(a1)
  247. #if defined(__mips_n64)
  248. PTR_LI s0, MIPS_XKSEG_START
  249. #else
  250. PTR_LI s0, MIPS_KSEG2_START # If Uarea addr is below kseg2,
  251. #endif
  252. bltu v0, s0, sw2 # no need to insert in TLB.
  253. PTE_L a1, TD_UPTE + 0(s7) # a1 = u. pte #0
  254. PTE_L a2, TD_UPTE + PTESIZE(s7) # a2 = u. pte #1
  255. /*
  256. * Wiredown the USPACE of newproc in TLB entry#0. Check whether target
  257. * USPACE is already in another place of TLB before that, and if so
  258. * invalidate that TLB entry.
  259. * NOTE: This is hard coded to UPAGES == 2.
  260. * Also, there should be no TLB faults at this point.
  261. */
  262. MTC0 v0, MIPS_COP_0_TLB_HI # VPN = va
  263. HAZARD_DELAY
  264. tlbp # probe VPN
  265. HAZARD_DELAY
  266. mfc0 s0, MIPS_COP_0_TLB_INDEX
  267. HAZARD_DELAY
  268. PTR_LI t1, MIPS_KSEG0_START # invalidate tlb entry
  269. bltz s0, entry0set
  270. nop
  271. sll s0, PAGE_SHIFT + 1
  272. addu t1, s0
  273. MTC0 t1, MIPS_COP_0_TLB_HI
  274. PTE_MTC0 zero, MIPS_COP_0_TLB_LO0
  275. PTE_MTC0 zero, MIPS_COP_0_TLB_LO1
  276. HAZARD_DELAY
  277. tlbwi
  278. HAZARD_DELAY
  279. MTC0 v0, MIPS_COP_0_TLB_HI # set VPN again
  280. entry0set:
  281. /* SMP!! - Works only for unshared TLB case - i.e. no v-cpus */
  282. mtc0 zero, MIPS_COP_0_TLB_INDEX # TLB entry #0
  283. HAZARD_DELAY
  284. PTE_MTC0 a1, MIPS_COP_0_TLB_LO0 # upte[0]
  285. HAZARD_DELAY
  286. PTE_MTC0 a2, MIPS_COP_0_TLB_LO1 # upte[1]
  287. HAZARD_DELAY
  288. tlbwi # set TLB entry #0
  289. HAZARD_DELAY
  290. /*
  291. * Now running on new u struct.
  292. */
  293. sw2:
  294. PTR_L s0, TD_PCB(s7)
  295. RESTORE_U_PCB_CONTEXT(sp, PREG_SP, s0)
  296. PTR_LA t1, _C_LABEL(pmap_activate) # s7 = new proc pointer
  297. jalr t1 # s7 = new proc pointer
  298. move a0, s7 # BDSLOT
  299. /*
  300. * Restore registers and return.
  301. */
  302. move a0, s0
  303. RESTORE_U_PCB_CONTEXT(gp, PREG_GP, a0)
  304. RESTORE_U_PCB_CONTEXT(v0, PREG_SR, a0) # restore kernel context
  305. RESTORE_U_PCB_CONTEXT(ra, PREG_RA, a0)
  306. RESTORE_U_PCB_CONTEXT(s0, PREG_S0, a0)
  307. RESTORE_U_PCB_CONTEXT(s1, PREG_S1, a0)
  308. RESTORE_U_PCB_CONTEXT(s2, PREG_S2, a0)
  309. RESTORE_U_PCB_CONTEXT(s3, PREG_S3, a0)
  310. RESTORE_U_PCB_CONTEXT(s4, PREG_S4, a0)
  311. RESTORE_U_PCB_CONTEXT(s5, PREG_S5, a0)
  312. RESTORE_U_PCB_CONTEXT(s6, PREG_S6, a0)
  313. RESTORE_U_PCB_CONTEXT(s7, PREG_S7, a0)
  314. RESTORE_U_PCB_CONTEXT(s8, PREG_S8, a0)
  315. mfc0 t0, MIPS_COP_0_STATUS
  316. and t0, t0, MIPS_SR_INT_MASK
  317. and v0, v0, ~MIPS_SR_INT_MASK
  318. or v0, v0, t0
  319. mtc0 v0, MIPS_COP_0_STATUS
  320. ITLBNOPFIX
  321. j ra
  322. nop
  323. END(cpu_switch)
  324. /*----------------------------------------------------------------------------
  325. *
  326. * MipsSwitchFPState --
  327. *
  328. * Save the current state into 'from' and restore it from 'to'.
  329. *
  330. * MipsSwitchFPState(from, to)
  331. * struct thread *from;
  332. * struct trapframe *to;
  333. *
  334. * Results:
  335. * None.
  336. *
  337. * Side effects:
  338. * None.
  339. *
  340. *----------------------------------------------------------------------------
  341. */
  342. LEAF(MipsSwitchFPState)
  343. mfc0 t1, MIPS_COP_0_STATUS # Save old SR
  344. li t0, MIPS_SR_COP_1_BIT # enable the coprocessor
  345. mtc0 t0, MIPS_COP_0_STATUS
  346. ITLBNOPFIX
  347. beq a0, zero, 1f # skip save if NULL pointer
  348. nop
  349. /*
  350. * First read out the status register to make sure that all FP operations
  351. * have completed.
  352. */
  353. PTR_L a0, TD_PCB(a0) # get pointer to pcb for proc
  354. cfc1 t0, MIPS_FPU_CSR # stall til FP done
  355. cfc1 t0, MIPS_FPU_CSR # now get status
  356. li t3, ~MIPS_SR_COP_1_BIT
  357. RESTORE_U_PCB_REG(t2, PS, a0) # get CPU status register
  358. SAVE_U_PCB_FPSR(t0, FSR_NUM, a0) # save FP status
  359. and t2, t2, t3 # clear COP_1 enable bit
  360. SAVE_U_PCB_REG(t2, PS, a0) # save new status register
  361. /*
  362. * Save the floating point registers.
  363. */
  364. SAVE_U_PCB_FPREG($f0, F0_NUM, a0)
  365. SAVE_U_PCB_FPREG($f1, F1_NUM, a0)
  366. SAVE_U_PCB_FPREG($f2, F2_NUM, a0)
  367. SAVE_U_PCB_FPREG($f3, F3_NUM, a0)
  368. SAVE_U_PCB_FPREG($f4, F4_NUM, a0)
  369. SAVE_U_PCB_FPREG($f5, F5_NUM, a0)
  370. SAVE_U_PCB_FPREG($f6, F6_NUM, a0)
  371. SAVE_U_PCB_FPREG($f7, F7_NUM, a0)
  372. SAVE_U_PCB_FPREG($f8, F8_NUM, a0)
  373. SAVE_U_PCB_FPREG($f9, F9_NUM, a0)
  374. SAVE_U_PCB_FPREG($f10, F10_NUM, a0)
  375. SAVE_U_PCB_FPREG($f11, F11_NUM, a0)
  376. SAVE_U_PCB_FPREG($f12, F12_NUM, a0)
  377. SAVE_U_PCB_FPREG($f13, F13_NUM, a0)
  378. SAVE_U_PCB_FPREG($f14, F14_NUM, a0)
  379. SAVE_U_PCB_FPREG($f15, F15_NUM, a0)
  380. SAVE_U_PCB_FPREG($f16, F16_NUM, a0)
  381. SAVE_U_PCB_FPREG($f17, F17_NUM, a0)
  382. SAVE_U_PCB_FPREG($f18, F18_NUM, a0)
  383. SAVE_U_PCB_FPREG($f19, F19_NUM, a0)
  384. SAVE_U_PCB_FPREG($f20, F20_NUM, a0)
  385. SAVE_U_PCB_FPREG($f21, F21_NUM, a0)
  386. SAVE_U_PCB_FPREG($f22, F22_NUM, a0)
  387. SAVE_U_PCB_FPREG($f23, F23_NUM, a0)
  388. SAVE_U_PCB_FPREG($f24, F24_NUM, a0)
  389. SAVE_U_PCB_FPREG($f25, F25_NUM, a0)
  390. SAVE_U_PCB_FPREG($f26, F26_NUM, a0)
  391. SAVE_U_PCB_FPREG($f27, F27_NUM, a0)
  392. SAVE_U_PCB_FPREG($f28, F28_NUM, a0)
  393. SAVE_U_PCB_FPREG($f29, F29_NUM, a0)
  394. SAVE_U_PCB_FPREG($f30, F30_NUM, a0)
  395. SAVE_U_PCB_FPREG($f31, F31_NUM, a0)
  396. 1:
  397. /*
  398. * Restore the floating point registers.
  399. */
  400. RESTORE_U_PCB_FPSR(t0, FSR_NUM, a1) # get status register
  401. RESTORE_U_PCB_FPREG($f0, F0_NUM, a1)
  402. RESTORE_U_PCB_FPREG($f1, F1_NUM, a1)
  403. RESTORE_U_PCB_FPREG($f2, F2_NUM, a1)
  404. RESTORE_U_PCB_FPREG($f3, F3_NUM, a1)
  405. RESTORE_U_PCB_FPREG($f4, F4_NUM, a1)
  406. RESTORE_U_PCB_FPREG($f5, F5_NUM, a1)
  407. RESTORE_U_PCB_FPREG($f6, F6_NUM, a1)
  408. RESTORE_U_PCB_FPREG($f7, F7_NUM, a1)
  409. RESTORE_U_PCB_FPREG($f8, F8_NUM, a1)
  410. RESTORE_U_PCB_FPREG($f9, F9_NUM, a1)
  411. RESTORE_U_PCB_FPREG($f10, F10_NUM, a1)
  412. RESTORE_U_PCB_FPREG($f11, F11_NUM, a1)
  413. RESTORE_U_PCB_FPREG($f12, F12_NUM, a1)
  414. RESTORE_U_PCB_FPREG($f13, F13_NUM, a1)
  415. RESTORE_U_PCB_FPREG($f14, F14_NUM, a1)
  416. RESTORE_U_PCB_FPREG($f15, F15_NUM, a1)
  417. RESTORE_U_PCB_FPREG($f16, F16_NUM, a1)
  418. RESTORE_U_PCB_FPREG($f17, F17_NUM, a1)
  419. RESTORE_U_PCB_FPREG($f18, F18_NUM, a1)
  420. RESTORE_U_PCB_FPREG($f19, F19_NUM, a1)
  421. RESTORE_U_PCB_FPREG($f20, F20_NUM, a1)
  422. RESTORE_U_PCB_FPREG($f21, F21_NUM, a1)
  423. RESTORE_U_PCB_FPREG($f22, F22_NUM, a1)
  424. RESTORE_U_PCB_FPREG($f23, F23_NUM, a1)
  425. RESTORE_U_PCB_FPREG($f24, F24_NUM, a1)
  426. RESTORE_U_PCB_FPREG($f25, F25_NUM, a1)
  427. RESTORE_U_PCB_FPREG($f26, F26_NUM, a1)
  428. RESTORE_U_PCB_FPREG($f27, F27_NUM, a1)
  429. RESTORE_U_PCB_FPREG($f28, F28_NUM, a1)
  430. RESTORE_U_PCB_FPREG($f29, F29_NUM, a1)
  431. RESTORE_U_PCB_FPREG($f30, F30_NUM, a1)
  432. RESTORE_U_PCB_FPREG($f31, F31_NUM, a1)
  433. and t0, t0, ~MIPS_FPU_EXCEPTION_BITS
  434. ctc1 t0, MIPS_FPU_CSR
  435. nop
  436. mtc0 t1, MIPS_COP_0_STATUS # Restore the status register.
  437. ITLBNOPFIX
  438. j ra
  439. nop
  440. END(MipsSwitchFPState)
  441. /*----------------------------------------------------------------------------
  442. *
  443. * MipsSaveCurFPState --
  444. *
  445. * Save the current floating point coprocessor state.
  446. *
  447. * MipsSaveCurFPState(td)
  448. * struct thread *td;
  449. *
  450. * Results:
  451. * None.
  452. *
  453. * Side effects:
  454. * machFPCurProcPtr is cleared.
  455. *
  456. *----------------------------------------------------------------------------
  457. */
  458. LEAF(MipsSaveCurFPState)
  459. PTR_L a0, TD_PCB(a0) # get pointer to pcb for thread
  460. mfc0 t1, MIPS_COP_0_STATUS # Disable interrupts and
  461. li t0, MIPS_SR_COP_1_BIT # enable the coprocessor
  462. mtc0 t0, MIPS_COP_0_STATUS
  463. ITLBNOPFIX
  464. GET_CPU_PCPU(a1)
  465. PTR_S zero, PC_FPCURTHREAD(a1) # indicate state has been saved
  466. /*
  467. * First read out the status register to make sure that all FP operations
  468. * have completed.
  469. */
  470. RESTORE_U_PCB_REG(t2, PS, a0) # get CPU status register
  471. li t3, ~MIPS_SR_COP_1_BIT
  472. and t2, t2, t3 # clear COP_1 enable bit
  473. cfc1 t0, MIPS_FPU_CSR # stall til FP done
  474. cfc1 t0, MIPS_FPU_CSR # now get status
  475. SAVE_U_PCB_REG(t2, PS, a0) # save new status register
  476. SAVE_U_PCB_FPSR(t0, FSR_NUM, a0) # save FP status
  477. /*
  478. * Save the floating point registers.
  479. */
  480. SAVE_U_PCB_FPREG($f0, F0_NUM, a0)
  481. SAVE_U_PCB_FPREG($f1, F1_NUM, a0)
  482. SAVE_U_PCB_FPREG($f2, F2_NUM, a0)
  483. SAVE_U_PCB_FPREG($f3, F3_NUM, a0)
  484. SAVE_U_PCB_FPREG($f4, F4_NUM, a0)
  485. SAVE_U_PCB_FPREG($f5, F5_NUM, a0)
  486. SAVE_U_PCB_FPREG($f6, F6_NUM, a0)
  487. SAVE_U_PCB_FPREG($f7, F7_NUM, a0)
  488. SAVE_U_PCB_FPREG($f8, F8_NUM, a0)
  489. SAVE_U_PCB_FPREG($f9, F9_NUM, a0)
  490. SAVE_U_PCB_FPREG($f10, F10_NUM, a0)
  491. SAVE_U_PCB_FPREG($f11, F11_NUM, a0)
  492. SAVE_U_PCB_FPREG($f12, F12_NUM, a0)
  493. SAVE_U_PCB_FPREG($f13, F13_NUM, a0)
  494. SAVE_U_PCB_FPREG($f14, F14_NUM, a0)
  495. SAVE_U_PCB_FPREG($f15, F15_NUM, a0)
  496. SAVE_U_PCB_FPREG($f16, F16_NUM, a0)
  497. SAVE_U_PCB_FPREG($f17, F17_NUM, a0)
  498. SAVE_U_PCB_FPREG($f18, F18_NUM, a0)
  499. SAVE_U_PCB_FPREG($f19, F19_NUM, a0)
  500. SAVE_U_PCB_FPREG($f20, F20_NUM, a0)
  501. SAVE_U_PCB_FPREG($f21, F21_NUM, a0)
  502. SAVE_U_PCB_FPREG($f22, F22_NUM, a0)
  503. SAVE_U_PCB_FPREG($f23, F23_NUM, a0)
  504. SAVE_U_PCB_FPREG($f24, F24_NUM, a0)
  505. SAVE_U_PCB_FPREG($f25, F25_NUM, a0)
  506. SAVE_U_PCB_FPREG($f26, F26_NUM, a0)
  507. SAVE_U_PCB_FPREG($f27, F27_NUM, a0)
  508. SAVE_U_PCB_FPREG($f28, F28_NUM, a0)
  509. SAVE_U_PCB_FPREG($f29, F29_NUM, a0)
  510. SAVE_U_PCB_FPREG($f30, F30_NUM, a0)
  511. SAVE_U_PCB_FPREG($f31, F31_NUM, a0)
  512. mtc0 t1, MIPS_COP_0_STATUS # Restore the status register.
  513. ITLBNOPFIX
  514. j ra
  515. nop
  516. END(MipsSaveCurFPState)
  517. /*
  518. * When starting init, call this to configure the process for user
  519. * mode. This will be inherited by other processes.
  520. */
  521. LEAF_NOPROFILE(prepare_usermode)
  522. j ra
  523. nop
  524. END(prepare_usermode)
  525. /*
  526. * This code is copied the user's stack for returning from signal handlers
  527. * (see sendsig() and sigreturn()). We have to compute the address
  528. * of the sigcontext struct for the sigreturn call.
  529. */
  530. .globl _C_LABEL(sigcode)
  531. _C_LABEL(sigcode):
  532. PTR_ADDU a0, sp, SIGF_UC # address of ucontext
  533. li v0, SYS_sigreturn
  534. # sigreturn (ucp)
  535. syscall
  536. break 0 # just in case sigreturn fails
  537. .globl _C_LABEL(esigcode)
  538. _C_LABEL(esigcode):
  539. .data
  540. .globl szsigcode
  541. szsigcode:
  542. .long esigcode-sigcode
  543. .text