⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 suppasm.s

📁 ARM入门的好帮手.包含了从简单到相对较复杂的程序.
💻 S
📖 第 1 页 / 共 4 页
字号:
        TTL     Angel assembler support routines                    > suppasm.s        ; ---------------------------------------------------------------------        ; This source files holds the general assembler routines        ; needed by Angel.        ;        ; $Revision: 1.21.6.3 $        ;   $Author: rivimey $        ;     $Date: 1997/12/19 15:54:54 $        ;        ; Copyright Advanced RISC Machines Limited, 1995.        ; All Rights Reserved        ;        ; ---------------------------------------------------------------------        GET     listopts.s              ; standard listing control        GET     lolevel.s               ; generic ARM definitions        GET     macros.s                ; standard assembler support        GET     target.s                ; target specific definitions        ; ---------------------------------------------------------------------        AREA    |C$$Code$$InterruptSupport|,CODE,READONLY        KEEP        [       ({CONFIG} = 26)        ASSERT  (1 = 0) ; This code has been written for 32bit mode only        ]        IF CACHE_SUPPORTED <> 0          EXPORT Cache_IBR        ENDIF        ; ---------------------------------------------------------------------        ; The following is a word which gets set to either ADP_CPU_LE or        ; ADP_CPU_BE at assemble time.  It can then be used by Angel to        ; tell the host what the endianess of the system is.        EXPORT  angel_Endianess    IMPORT set_led    IMPORT clear_led    IF :DEF: AT91_AIC_IRQ    IMPORT In_Int    ENDIF    angel_Endianess        IF :DEF: ICEMAN2          DCD  ADP_CPU_LE | ADP_CPU_BE ;          DCD  0        ELSE          IF {ENDIAN} = "big"            DCD ADP_CPU_BE            DCD ADP_CPU_BigEndian          ELSE            IF {ENDIAN} = "little"              DCD ADP_CPU_LE              DCD 0            ELSE              ! ERROR - could not detect endianess            ENDIF          ENDIF        ENDIF                ; This is the veneer for the late startup SWI        EXPORT  Angel_LateStartupAngel_LateStartup        MOV     a2, a1          ; preserve type        LDR     a1, =angel_SWIreason_LateStartup        DCD     angel_SWI_ARM        MOV     pc, lr        IMPORT  angel_IntHandler        ; Table of Interrupt handlers        IMPORT  Angel_MutexSharedTempRegBlocks        IMPORT  angel_GhostCount        IMPORT  HandlerSWI        IMPORT  Angel_StackBase          IF :DEF: ICEMAN_LEVEL_3 :LOR: (:DEF: MINIMAL_ANGEL :LAND: MINIMAL_ANGEL<>0)        ; Do not include an Undef Handler for ICEMan  ELSE        IMPORT  HandlerUndef  ENDIF        ; This is the lowest level interrupt handler which is installed        ; statically. It can be put on either the IRQ or FIQ vector as        ; required for a particular board (or both if you really want !)        EXPORT  angel_DeviceInterruptHandlerangel_DeviceInterruptHandler        STMFD sp!, {r0}        ; Disable FIQ's if necessary        IF (FIQ_SAFETYLEVEL < FIQ_NeverUsesSerialiser_DoesNotReschedule)          MRS   r0, CPSR          ORR   r0, r0, #IRQDisable + FIQDisable          MSR   CPSR_cxsf, r0        ENDIF        ; Save the state of the callee into a regblock        ; This means r0-r15, cpsr and if appropriate spsr        ;        ; Can do r0-r7, pc, cpsr for all modes        LDR   r0, =Angel_MutexSharedTempRegBlocks        ADD   r0, r0, #Angel_RegBlock_R0offset + (1*4)        STMIA r0, {r1-r7}       ; r1-r7 are never banked        SUB   r0, r0, #Angel_RegBlock_R0offset + (1*4)        LDMFD sp!, {r1}        STR   r1, [r0, #Angel_RegBlock_R0offset] ; original r0        MRS   r1, SPSR        STR   r1, [r0, #Angel_RegBlock_CPSRoffset] ; original cpsr        ;; We only adjust lr if we are not using the veneer   IF :DEF: AT91_AIC_IRQ     IF AT91_AIC_IRQ = 2    NOP     ELSE        SUB   r14, r14, #4      ; Adjust lr (works for ARM and Thumb)     ENDIF   ELSE      SUB   r14, r14, #4      ; Adjust lr (works for ARM and Thumb)   ENDIF                STR   r14, [r0, #Angel_RegBlock_R0offset + (15*4)] ; pc        ; Accessing other modes depends on the mode        AND   r1, r1, #ModeMask        CMP   r1, #USRmode        BEQ   InterruptedInUSRMode        CMP   r1, #SYSmode        BEQ   InterruptedInUSRMode        ; Deal with non USR mode case        MRS   r3, cpsr        IF (FIQ_SAFETYLEVEL >= FIQ_NeverUsesSerialiser_DoesNotReschedule)          ORR r1, r1, #IRQDisable          ORR r3, r3, #IRQDisable        ELSE          ORR r1, r1, #IRQDisable + FIQDisable          ORR r3, r3, #IRQDisable + FIQDisable        ENDIF        MSR   CPSR_cxsf, r1        ; Now we are in the appropriate mode        ADD   r0, r0, #Angel_RegBlock_R0offset + (8*4)        STMIA r0, {r8-r14}      ; r8-r14 may be banked - now saved        SUB   r0, r0, #Angel_RegBlock_R0offset + (8*4)        MRS   r2, SPSR        STR   r2, [r0, #Angel_RegBlock_SPSRoffset]        ; Get back into original interrupt mode (IRQ or FIQ)        MSR   cpsr_cxsf, r3    ;; small test routine to set the led    ;;MOV   r2, r14     ; save the lr into an apcs reg    ;;LDR   r0, =LED2   ; LED to set    ;;BL    set_led    ;;MOV   r14, r2                IF HANDLE_INTERRUPTS_ON_FIQ <> 0          ; Nasty case code - check to see if we have interrupted the first          ; few instructions of the SWI handler or UND handler!!!          ; which includes the vectors themselves !!!  This is necessary          ; because on entry to SWI and UNDEF handlers FIQ is still enabled.          ; It is therefore highly recommendsed that FIQ is not used to          ; handle Angel Device interrupts, as this is a significant overhead          ; and is also really quite unpleasant!          CMP   r14, #0x1c          BCC   ReallyNastyCase          LDR   r3, =HandlerSWI          CMP   r14, r3          BCC   CheckUNDHandler ; interrupted pc < HandlerSWI          ADD   r3, r3, #60          CMP   r14, r3          BHI   CheckUNDHandler ; interrupted pc >> HandlerSWI          B     ReallyNastyCaseCheckUNDHandler  IF :DEF: ICEMAN_LEVEL_3 :LOR: (:DEF: MINIMAL_ANGEL :LAND: MINIMAL_ANGEL<>0)          B     RegsNowSaved3   ; skip this bit  ELSE          LDR   r3, =HandlerUndef          CMP   r14, r3          BCC   RegsNowSaved3   ; interrupted pc < HandlerSWI          ADD   r3, r3, #60          CMP   r14, r3          BHI   RegsNowSaved3   ; interrupted pc >> HandlerSWI  ENDIF          ; This is the really really nasty case - ignore the interrupt          ; and resume the SWI Handler with IRQ and FIQ disabled !!!          ; Why oh Why isn't FIQ disabled on entry to SWI's ??ReallyNastyCase          MRS   r3, spsr          ORR   r3, r3, #IRQDisable + FIQDisable          MSR   spsr, r3          B     ReturnFromIntHandler        ELSE    ; HANDLE_INTERRUPTS_ON_FIQ <> 0          B     RegsNowSaved3        ENDIF   ; HANDLE_INTERRUPTS_ON_FIQ <> 0InterruptedInUSRMode        ; We need to do this slightly differently depending on whether        ; this is an IRQ or FIQ based interrupt handler ...        ADD   r0, r0, #Angel_RegBlock_R0offset + (8*4)        MRS   r3, cpsr        AND   r3, r3, #ModeMask        CMP   r3, #IRQmode        BNE   FIQModeCaseIRQModeCase        STMIA r0, {r8-r12}      ; r8-r12 are not banked between USR and IRQ        ADD   r0, r0, #(13*4) - (8*4)      IF :DEF: STRONGARM_REV1OR2        MCR   MMUCP, 0, r0, c0, c0, 0      ENDIF        STMIA r0, {r13,r14}^    ; Store out the USR r13 and r14        SUB   r0, r0, #Angel_RegBlock_R0offset + (13*4)        B     RegsNowSaved3FIQModeCase      IF :DEF: STRONGARM_REV1OR2        MCR   MMUCP, 0, r0, c0, c0, 0      ENDIF        STMIA r0, {r8-r14}^     ; r8-r14 are banked between USR and FIQ        SUB   r0, r0, #Angel_RegBlock_R0offset + (8*4)RegsNowSaved3        LDR   r1, =angel_GhostCountGetSrc     IF :DEF: AT91_AIC_IRQ     IF AT91_AIC_IRQ = 1    ;   LDR   r0, =In_Int   ; Set up the interrupt flag;   MOV   r4, #1        ; Set to 1 only;   STR   r4, [r0]     ENDIF   ENDIF        GETSOURCE       r0, lr        ; Get the interrupt vector index in r0        CMN   r0, #1                  ; Check for Ghost Interrupt        BEQ   GhostInterrupt          ; It's a Ghost        CMP   r0, #DE_NUM_INT_HANDLERS; Check if a valid source index        BGE   UnrecognisedSource      ; Unrecognised source        LDR   lr, =angel_IntHandler   ; Reference the handlers vector        ADD   lr, lr, r0, LSL #3      ; lr = angel_IntHandler + r0 * 8        LDMIA lr, {r4, r5}            ; and load the required func pointer                                      ; and data into r4 and r5        MOV   lr, #0        STR   lr, [r1]                ; clear count of ghost interrupts        MOV   r1, r5        TEQ   r4, #0        BEQ   UnrecognisedSource      ; No handler attached for source        ; r0 = interrupt vector index, set up above        ; r1 = data from table, set up above        ; r2 = empty_stack (stack is currently empty)        ; r3 not used        ;        ; r4 = address of Interrupt handler, which may return but        ;      WON'T return if it calls the serialiser.        ; We can now call the APCS-3 handler for this source:        MOV   r2, sp        MOV   r3, #0        MOV   fp,#0x00000000          ; start of call-frame        ; Set up sl for the appropriate stack (depends on mode)        MRS   r5, cpsr        AND   r5, r5, #ModeMask        LDR   sl, =Angel_StackBase        LDR   sl, [sl]        CMP   r5, #IRQmode        ADDEQ sl, sl, #Angel_IRQStackLimitOffset ; No APCS_STACKGUARD space        ADDNE sl, sl, #Angel_FIQStackLimitOffset ; No APCS_STACKGUARD space        ; It is assumed that the handler function called will execute        ; within the interrupt handler stack allocation, and the code        ; will not manipulate the interrupt mask status, or the SPSR        ; register:        LDR   lr, =ReturnFromIntHandler  ; generate return address        MOV   pc, r4                     ; call handler functionUnrecognisedSourceReturnFromIntHandler        ; We will only get here if the interrupt handler did not need        ; to grab the serialiser lock.        ; We won't have interrupted an FIQ, so r0-r12 will not be banked        ; so we have to reinstate these before returning.   IF :DEF: AT91_AIC_IRQ     IF AT91_AIC_IRQ = 1    ;; Signify an end of interrupt to the AIC    ;; The following is a test to see if the EICR has already been    ;; Written to.    ;   LDR  r0, =In_Int    ;   LDR  r0, [r0]    ;   TST  r0, #1    ;   LDREQ r0, =INT_EICR ;  End of Interrupt Control Register    ;   STREQ r0, [r0]      ; Any value is valid         ENDIF   ENDIF        ; Assume that SPSR has not been corrupted.        LDR   r14, =Angel_MutexSharedTempRegBlocks        ADD   r14, r14, #Angel_RegBlock_R0offset        LDMIA r14, {r0-r12}        ADD   r14, r14, #4*15   ; Where the PC is stored       IF :DEF: AT91_AIC_IRQ     IF AT91_AIC_IRQ = 2        LDMIA r14, {pc} ;use the veneer to return correctly using ^     ELSE        LDMIA r14, {pc}^     ENDIF   ELSE        LDMIA r14, {pc}^           ENDIF            ; And now the interuptee executes in whatever mode it was in ..        ;        ; it is possible to get ghost interrupts - ignore these, unless        ; too many of them stack up        ;        ; r1 = &angel_GhostInterrupt        ;GhostInterrupt        LDR     r0, [r1]        ADD     r0, r0, #1        CMP     r0, #5        STR     r0, [r1]        BLT     ReturnFromIntHandlerTooManyGhosts        ADR     a1, ghosterrmsg        B       __rt_asm_fatalerrorghosterrmsg        DCB     "Too Many Ghost Interrupts\n"        ALIGN        ; ---------------------------------------------------------------------        AREA    |C$$Code$$LibrarySupport|,CODE,READONLY        KEEP        ; Angel is designed *NOT* to require any of the standard ANSI        ; 'C' library, since it lives beneath the library.  This means        ; that we need to provide our own versions of certain standard        ; routines:        EXPORT __rt_memcpy        GBLS  SLA                       ; shift towards low address end        GBLS  SHA                       ; shift towards high address end [ {ENDIAN} = "big"SLA     SETS "LSL"SHA     SETS "LSR" |                                      ; assume little-endianSLA     SETS "LSR"SHA     SETS "LSL" ] [ {TRUE}       ; new, fast memcpy        GET objmacs.ssrc     RN    a2dst     RN    a1n       RN    a3tmp1    RN    a4tmp3    RN    ip        Function __rt_memcpy, leaf        CMP     src, dst        BLO     CopyDown

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -