singrdk/base/Kernel/Singularity/Isal/arm/context.asm

179 lines
7.7 KiB
NASM
Raw Normal View History

2008-11-17 18:29:00 -05:00
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Microsoft Research Singularity
;;;
;;; Copyright (c) Microsoft Corporation. All rights reserved.
;;;
;;; This file contains x86-specific assembly code related to context save and restore.
;;; The key goal here is to keep this set of code as small as possible, in favor
;;; of portable C++ or C# code.
CODE32
AREA |.text|, CODE, ARM
|defining ?m_Save@Struct_Microsoft_Singularity_Isal_SpillContext@@SA_NPAU1@@Z| EQU 1
|defining ?m_Save@Struct_Microsoft_Singularity_Isal_SpillContext@@SA_NPAU1@PAUStruct_Microsoft_Singularity_Isal_InterruptContext@@@Z| EQU 1
|defining ?m_Resume@Struct_Microsoft_Singularity_Isal_SpillContext@@SAXPAU1@@Z| EQU 1
|defining ?g_ResetCurrent@Struct_Microsoft_Singularity_Isal_SpillContext@@SAXXZ| EQU 1
include hal.inc
;;; Save takes one argument - a context record to save the context in. It saves all the
;;; nonvolatile state (it does not bother saving caller save regs.)
;;;
;;; This function returns true after saving the context. When the context is resumed, control
;;; resumption will occur at the point this function returned, but with a false
;;; return value.
;;;
;;; Calling conventions are normal __fastcall.
;; __fastcall bool SaveContext(Context *context)
LEAF_ENTRY ?m_Save@Struct_Microsoft_Singularity_Isal_SpillContext@@SA_NPAU1@@Z
;; Save the bulk of the registers (r0-r12).
stmia r0, {r0-r12}
;; Save sp and (stale) lr.
str sp, [r0, #Struct_Microsoft_Singularity_Isal_SpillContext___sp]
str lr, [r0, #Struct_Microsoft_Singularity_Isal_SpillContext___lr]
;; Save lr as the pc.
str lr, [r0, #Struct_Microsoft_Singularity_Isal_SpillContext___pc]
;; Save cpsr
mrs r1, cpsr
str r1, [r0, #Struct_Microsoft_Singularity_Isal_SpillContext___cpsr]
;; Overright r0, so the return value contains zero on context resume
ldr r1, =0
str r1, [r0, #Struct_Microsoft_Singularity_Isal_SpillContext___r0]
;; Save stack limit
GET_THREAD_FIELD_ADDR r2, r12, #Struct_Microsoft_Singularity_Isal_ThreadRecord___activeStackLimit
ldr r2, [r2]
str r2, [r0, #Struct_Microsoft_Singularity_Isal_SpillContext___stackLimit]
;; Set spilled flag
ldr r2, [r0, #Struct_Microsoft_Singularity_Isal_SpillContext___spillFlags]
orr r2, r2, #Struct_Microsoft_Singularity_Isal_SpillContext_ContentsSpilled
str r2, [r0, #Struct_Microsoft_Singularity_Isal_SpillContext___spillFlags]
;; return true for initial save
ldr r0, =1
bx lr
LEAF_END
;;; Save takes two arguments - a context record to save the context in, and
;;; an interrupt frame to describe an interruption location.
;;;
;;; Calling conventions are normal __fastcall.
;; __fastcall bool SaveContext(Context *context, InterruptContext *interrupt)
LEAF_ENTRY ?m_Save@Struct_Microsoft_Singularity_Isal_SpillContext@@SA_NPAU1@PAUStruct_Microsoft_Singularity_Isal_InterruptContext@@@Z
;; Pick up registers from the interrupt context
ldr r2, [r1, #Struct_Microsoft_Singularity_Isal_InterruptContext___r0]
str r2, [r0, #Struct_Microsoft_Singularity_Isal_SpillContext___r0]
ldr r2, [r1, #Struct_Microsoft_Singularity_Isal_InterruptContext___r1]
str r2, [r0, #Struct_Microsoft_Singularity_Isal_SpillContext___r1]
ldr r2, [r1, #Struct_Microsoft_Singularity_Isal_InterruptContext___r2]
str r2, [r0, #Struct_Microsoft_Singularity_Isal_SpillContext___r2]
ldr r2, [r1, #Struct_Microsoft_Singularity_Isal_InterruptContext___r3]
str r2, [r0, #Struct_Microsoft_Singularity_Isal_SpillContext___r3]
ldr r2, [r1, #Struct_Microsoft_Singularity_Isal_InterruptContext___r12]
str r2, [r0, #Struct_Microsoft_Singularity_Isal_SpillContext___r12]
ldr r2, [r1, #Struct_Microsoft_Singularity_Isal_InterruptContext___lr]
str r2, [r0, #Struct_Microsoft_Singularity_Isal_SpillContext___lr]
ldr r2, [r1, #Struct_Microsoft_Singularity_Isal_InterruptContext___sp]
str r2, [r0, #Struct_Microsoft_Singularity_Isal_SpillContext___sp]
ldr r2, [r1, #Struct_Microsoft_Singularity_Isal_InterruptContext___pc]
str r2, [r0, #Struct_Microsoft_Singularity_Isal_SpillContext___pc]
ldr r2, [r1, #Struct_Microsoft_Singularity_Isal_InterruptContext___cpsr]
str r2, [r0, #Struct_Microsoft_Singularity_Isal_SpillContext___cpsr]
ldr r2, [r1, #Struct_Microsoft_Singularity_Isal_InterruptContext___instruction]
str r2, [r0, #Struct_Microsoft_Singularity_Isal_SpillContext___instruction]
;; Save the rest of the registers from the current state
add r2, r0, #Struct_Microsoft_Singularity_Isal_SpillContext___r4
stmia r2, {r4-r11}
;; Save stack limit
GET_THREAD_FIELD_ADDR r2, r12, #Struct_Microsoft_Singularity_Isal_ThreadRecord___activeStackLimit
ldr r2, [r2]
str r2, [r0, #Struct_Microsoft_Singularity_Isal_SpillContext___stackLimit]
;; Set spilled flag
ldr r2, [r0, #Struct_Microsoft_Singularity_Isal_SpillContext___spillFlags]
orr r2, r2, #Struct_Microsoft_Singularity_Isal_SpillContext_ContentsSpilled
str r2, [r0, #Struct_Microsoft_Singularity_Isal_SpillContext___spillFlags]
;; We're done
bx lr
LEAF_END
;;; Resume restores the processor state to the state described in the given
;;; context record.
;;;
;;; __fastcall void ResumeContext(Struct_Microsoft_Singularity_Isal_SpillContext *context);
|?m_Resume@Struct_Microsoft_Singularity_Isal_SpillContext@@SAXPAU1@@Z| PROC
;; Switch to supervisor mode so we can get an atomic resume including CPSR.
mrs r1, cpsr
bic r1, r1, #Struct_Microsoft_Singularity_Isal_Arm_ProcessorMode_Mask
orr r1, r1, #Struct_Microsoft_Singularity_Isal_Arm_ProcessorMode_Supervisor
msr cpsr_c, r1
;; Clear spilled flag.
ldr r1, [r0, #Struct_Microsoft_Singularity_Isal_SpillContext___spillFlags]
bic r1, r1, #Struct_Microsoft_Singularity_Isal_SpillContext_ContentsSpilled
str r1, [r0, #Struct_Microsoft_Singularity_Isal_SpillContext___spillFlags]
;; Restore stack limit.
ldr r1, [r0, #Struct_Microsoft_Singularity_Isal_SpillContext___stackLimit]
GET_THREAD_FIELD_ADDR r2, r12, #Struct_Microsoft_Singularity_Isal_ThreadRecord___activeStackLimit
str r1, [r2]
;; Move saved CPSR into SPSR.
ldr r1, [r0, #Struct_Microsoft_Singularity_Isal_SpillContext___cpsr]
msr spsr, r1
;; Restore banked pre-interrupt registers (use R3 as pointer to banked registers).
add r3, r0, #Struct_Microsoft_Singularity_Isal_SpillContext___sp
ldmia r3, {sp,lr}^
;; Resume unbanked pre-interrupt state.
ldmia r0, {r0-r12,pc}^
ENDP
;;; ResetContext resets the current context fp & debug register state to a canonical state
;;; for interrupt handler code. This should only be used after saving the current context.
;;;
;;; Calling conventions are normal __fastcall.
;;;
;;; __fastcall void ResetCurrent();
LEAF_ENTRY ?g_ResetCurrent@Struct_Microsoft_Singularity_Isal_SpillContext@@SAXXZ
bx lr
LEAF_END
END