OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [arch/] [armnommu/] [mm/] [proc-arm6,7.S] - Rev 199

Go to most recent revision | Compare with Previous | Blame | View Log

/*
 * linux/arch/arm/mm/arm6.S: MMU functions for ARM6
 *
 * (C) 1997 Russell King
 *
 * These are the low level assembler for performing cache and TLB
 * functions on the ARM6 & ARM7.
 */

#include <asm/assembler.h>
#include "../lib/constants.h"
#define current current_set

/*
 * Function: arm6_7_flush_cache_all (void)
 *         : arm6_7_flush_cache_page (unsigned long address, int size, int flags)
 *
 * Params  : address    Area start address
 *         : size       size of area
 *         : flags      b0 = I cache as well
 *
 * Purpose : Flush all cache lines
 */
arm6_7_flush_cache:
                mov     r0, #0
#ifndef NO_MM
                mcr     p15, 0, r0, c7, c0, 0           @ flush cache
#endif
arm6_7_null:
                mov     pc, lr

/*
 * Function: arm6_7_flush_tlb_all (void)
 *
 * Purpose : flush all TLB entries in all caches
 */
arm6_7_flush_tlb_all:
                mov     r0, #0
#ifndef NO_MM
                mcr     p15, 0, r0, c5, c0, 0           @ flush TLB
#endif
                mov     pc, lr

/*
 * Function: arm6_7_flush_tlb_page (unsigned long address, int end, int flags)
 *
 * Params  : address    Area start address
 *         : end        Area end address
 *         : flags      b0 = I cache as well
 *
 * Purpose : flush a TLB entry
*/
arm6_7_flush_tlb_area:
#ifndef NO_MM
1:              mcr     p15, 0, r0, c6, c0, 0           @ flush TLB
                add     r0, r0, #4096
                cmp     r0, r1
                blt     1b
#endif
                mov     pc, lr

LC0:            .word   current


/*
 * Function: arm6_7_switch_to (struct task_struct *prev, struct task_struct *next)
 *
 * Params  : prev       Old task structure
 *         : next       New task structure for process to run
 *
 * Purpose : Perform a task switch, saving the old processes state, and restoring
 *           the new.
 *
 * Notes   : We don't fiddle with the FP registers here - we postpone this until
 *           the new task actually uses FP.  This way, we don't swap FP for tasks
 *           that do not require it.
 */
arm6_7_switch_to:
                stmfd   sp!, {r4 - r10, fp, lr}         @ Store most regs on stack
                mrs     ip, cpsr
                stmfd   sp!, {ip}                       @ Save cpsr_SVC
                str     sp, [r0, #TSS_SAVE]             @ Save sp_SVC
                ldr     r2, LC0
                str     r1, [r2]
                ldr     sp, [r1, #TSS_SAVE]             @ Get saved sp_SVC
#ifndef NO_MM 
                ldr     r0, [r1, #TSS_MEMMAP]           @ Page table pointer
                mov     r1, #0
                mcr     p15, 0, r1, c7, c0, 0           @ flush cache
                mcr     p15, 0, r0, c2, c0, 0           @ update page table ptr
                mcr     p15, 0, r1, c5, c0, 0           @ flush TLBs
#endif
                ldmfd   sp!, {ip}
                msr     spsr, ip                        @ Save tasks CPSR into SPSR for this return
                ldmfd   sp!, {r4 - r10, fp, pc}^                @ Load all regs saved previously

/*
 * Function: arm6_7_data_abort ()
 *
 * Params  : r0 = address of aborted instruction
 *
 * Purpose : obtain information about current aborted instruction
 *
 * Returns : r0 = address of abort
 *         : r1 = FSR
 *         : r2 != 0 if writing
 *         : sp = pointer to registers
 *
 * Notes   : data abort *** NEEDS WORK ***
 */

Lukabttxt:      .ascii  "Unknown data abort code %d [pc=%p, *pc=%p] LR=%p\0"
                .align

msg:            .ascii  "DA*%p=%p\n\0"
                .align

arm6_data_abort:
                ldr     r4, [r0]                        @ read instruction causing problem
                mov     r2, r4, lsr #19                 @ r2 b1 = L
                and     r1, r4, #15 << 24
                add     pc, pc, r1, lsr #22             @ Now branch to the relevent processing routine
                movs    pc, lr
                b       Ldata_unknown
                b       Ldata_unknown
                b       Ldata_unknown
                b       Ldata_unknown
                b       Ldata_earlyldrpost              @ ldr   rd, [rn], #m
                b       Ldata_simple                    @ ldr   rd, [rn, #m]    @ RegVal
                b       Ldata_earlyldrpost              @ ldr   rd, [rn], rm
                b       Ldata_simple                    @ ldr   rd, [rn, rm]
                b       Ldata_ldmstm                    @ ldm*a rn, <rlist>
                b       Ldata_ldmstm                    @ ldm*b rn, <rlist>
                b       Ldata_unknown
                b       Ldata_unknown
                b       Ldata_simple                    @ ldc   rd, [rn], #m    @ Same as ldr   rd, [rn], #m
                b       Ldata_simple                    @ ldc   rd, [rn, #m]
                b       Ldata_unknown
Ldata_unknown:  @ Part of jumptable
                ldr     r3, [sp, #15 * 4]               @ Get PC
                str     r3, [sp, #-4]!
                mov     r1, r1, lsr #2
                mov     r3, r4
                mov     r2, r0
                adr     r0, Lukabttxt
                bl      panic
Lstop:          b       Lstop

arm7_data_abort:
                ldr     r4, [r0]                        @ read instruction causing problem
                mov     r2, r4, lsr #19                 @ r2 b1 = L
                and     r1, r4, #15 << 24
                add     pc, pc, r1, lsr #22             @ Now branch to the relevent processing routine
                movs    pc, lr
                b       Ldata_unknown
                b       Ldata_unknown
                b       Ldata_unknown
                b       Ldata_unknown
                b       Ldata_lateldrpostconst          @ ldr   rd, [rn], #m
                b       Ldata_lateldrpreconst           @ ldr   rd, [rn, #m]    @ RegVal
                b       Ldata_lateldrpostreg            @ ldr   rd, [rn], rm
                b       Ldata_lateldrprereg             @ ldr   rd, [rn, rm]
                b       Ldata_ldmstm                    @ ldm*a rn, <rlist>
                b       Ldata_ldmstm                    @ ldm*b rn, <rlist>
                b       Ldata_unknown
                b       Ldata_unknown
                b       Ldata_simple                    @ ldc   rd, [rn], #m    @ Same as ldr   rd, [rn], #m
                b       Ldata_simple                    @ ldc   rd, [rn, #m]
                b       Ldata_unknown
                b       Ldata_unknown

Ldata_ldmstm:   tst     r4, #1 << 21                    @ check writeback bit
                beq     Ldata_simple

                mov     r7, #0x11
                orr     r7, r7, r7, lsl #8
                and     r0, r4, r7
                and     r1, r4, r7, lsl #1
                add     r0, r0, r1, lsr #1
                and     r1, r4, r7, lsl #2
                add     r0, r0, r1, lsr #2
                and     r1, r4, r7, lsl #3
                add     r0, r0, r1, lsr #3
                add     r0, r0, r0, lsr #8
                add     r0, r0, r0, lsr #4
                and     r7, r0, #15                     @ r7 = no. of registers to transfer.
                and     r5, r4, #15 << 16               @ Get Rn
                ldr     r0, [sp, r5, lsr #14]           @ Get register
                eor     r6, r4, r4, lsl #2
                tst     r6, #1 << 23                    @ Check inc/dec ^ writeback
                rsbeq   r7, r7, #0
                add     r7, r0, r7, lsl #2              @ Do correction (signed)
                str     r7, [sp, r5, lsr #14]           @ Put register

Ldata_simple:   and     r2, r2, #2                      @ check read/write bit
                mrc     p15, 0, r0, c6, c0, 0           @ get FAR
                mrc     p15, 0, r1, c5, c0, 0           @ get FSR
                and     r1, r1, #15
                mov     pc, lr

Ldata_earlyldrpost:
                tst     r2, #4
                and     r2, r2, #2                      @ check read/write bit
                orrne   r2, r2, #1                      @ T bit
                mrc     p15, 0, r0, c6, c0, 0           @ get FAR
                mrc     p15, 0, r1, c5, c0, 0           @ get FSR
                and     r1, r1, #15
                mov     pc, lr

Ldata_lateldrpostconst:
                movs    r1, r4, lsl #20                 @ Get offset
                beq     Ldata_earlyldrpost              @ if offset is zero, no effect
                and     r5, r4, #15 << 16               @ Get Rn
                ldr     r0, [sp, r5, lsr #14]
                tst     r4, #1 << 23                    @ U bit
                subne   r0, r0, r1, lsr #20
                addeq   r0, r0, r1, lsr #20
                str     r0, [sp, r5, lsr #14]           @ Put register
                b       Ldata_earlyldrpost

Ldata_lateldrpreconst:
                tst     r4, #1 << 21                    @ check writeback bit
                movnes  r1, r4, lsl #20                 @ Get offset
                beq     Ldata_simple
                and     r5, r4, #15 << 16               @ Get Rn
                ldr     r0, [sp, r5, lsr #14]
                tst     r4, #1 << 23                    @ U bit
                subne   r0, r0, r1, lsr #20
                addeq   r0, r0, r1, lsr #20
                str     r0, [sp, r5, lsr #14]           @ Put register
                b       Ldata_simple

Ldata_lateldrpostreg:
                and     r5, r4, #15
                ldr     r1, [sp, r5, lsl #2]            @ Get Rm
                mov     r3, r4, lsr #7
                ands    r3, r3, #31
                and     r6, r4, #0x70
                orreq   r6, r6, #8
                add     pc, pc, r6
                mov     r0, r0

                mov     r1, r1, lsl r3                  @ 0: LSL #!0
                b       1f
                b       1f                              @ 1: LSL #0
                mov     r0, r0
                b       1f                              @ 2: MUL?
                mov     r0, r0
                b       1f                              @ 3: MUL?
                mov     r0, r0
                mov     r1, r1, lsr r3                  @ 4: LSR #!0
                b       1f
                mov     r1, r1, lsr #32                 @ 5: LSR #32
                b       1f
                b       1f                              @ 6: MUL?
                mov     r0, r0
                b       1f                              @ 7: MUL?
                mov     r0, r0
                mov     r1, r1, asr r3                  @ 8: ASR #!0
                b       1f
                mov     r1, r1, asr #32                 @ 9: ASR #32
                b       1f
                b       1f                              @ A: MUL?
                mov     r0, r0
                b       1f                              @ B: MUL?
                mov     r0, r0
                mov     r1, r1, ror r3                  @ C: ROR #!0
                b       1f
                mov     r1, r1, rrx                     @ D: RRX
                b       1f
                mov     r0, r0                          @ E: MUL?
                mov     r0, r0
                mov     r0, r0                          @ F: MUL?


1:              and     r5, r4, #15 << 16               @ Get Rn
                ldr     r0, [sp, r5, lsr #14]
                tst     r4, #1 << 23                    @ U bit
                subne   r0, r0, r1
                addeq   r0, r0, r1
                str     r0, [sp, r5, lsr #14]           @ Put register
                b       Ldata_earlyldrpost

Ldata_lateldrprereg:
                tst     r4, #1 << 21                    @ check writeback bit
                beq     Ldata_simple
                and     r5, r4, #15
                ldr     r1, [sp, r5, lsl #2]            @ Get Rm
                mov     r3, r4, lsr #7
                ands    r3, r3, #31
                and     r6, r4, #0x70
                orreq   r6, r6, #8
                add     pc, pc, r6
                mov     r0, r0

                mov     r1, r1, lsl r3                  @ 0: LSL #!0
                b       1f
                b       1f                              @ 1: LSL #0
                mov     r0, r0
                b       1f                              @ 2: MUL?
                mov     r0, r0
                b       1f                              @ 3: MUL?
                mov     r0, r0
                mov     r1, r1, lsr r3                  @ 4: LSR #!0
                b       1f
                mov     r1, r1, lsr #32                 @ 5: LSR #32
                b       1f
                b       1f                              @ 6: MUL?
                mov     r0, r0
                b       1f                              @ 7: MUL?
                mov     r0, r0
                mov     r1, r1, asr r3                  @ 8: ASR #!0
                b       1f
                mov     r1, r1, asr #32                 @ 9: ASR #32
                b       1f
                b       1f                              @ A: MUL?
                mov     r0, r0
                b       1f                              @ B: MUL?
                mov     r0, r0
                mov     r1, r1, ror r3                  @ C: ROR #!0
                b       1f
                mov     r1, r1, rrx                     @ D: RRX
                b       1f
                mov     r0, r0                          @ E: MUL?
                mov     r0, r0
                mov     r0, r0                          @ F: MUL?


1:              and     r5, r4, #15 << 16               @ Get Rn
                ldr     r0, [sp, r5, lsr #14]
                tst     r4, #1 << 23                    @ U bit
                subne   r0, r0, r1
                addeq   r0, r0, r1
                str     r0, [sp, r5, lsr #14]           @ Put register
                b       Ldata_simple

/*
 * Function: arm6_7_check_bugs (void)
 *         : arm6_7_proc_init (void)
 *         : arm6_7_proc_fin (void)
 *
 * Notes   : This processor does not require these
 */
arm6_7_check_bugs:
                mrs     ip, cpsr
                bic     ip, ip, #F_BIT
                msr     cpsr, ip
arm6_7_proc_init:
arm6_7_proc_fin:
                mov     pc, lr

/*
 * Function: arm6_set_pmd ()
 *
 * Params  : r0 = Address to set
 *         : r1 = value to set
 *
 * Purpose : Set a PMD and flush it out of any WB cache
 */
arm6_set_pmd:   and     r2, r1, #3
                teq     r2, #2
                andeq   r2, r1, #8
                orreq   r1, r1, r2, lsl #1              @ Updatable = Cachable
                teq     r2, #1
                orreq   r1, r1, #16                     @ Updatable = 1 if Page table
                str     r1, [r0]
                mov     pc, lr

/*
 * Function: arm7_set_pmd ()
 *
 * Params  : r0 = Address to set
 *         : r1 = value to set
 *
 * Purpose : Set a PMD and flush it out of any WB cache
 */
arm7_set_pmd:
#ifndef NO_MM
        orr     r1, r1, #16                     @ Updatable bit is always set on ARM7
                str     r1, [r0]
#endif
                mov     pc, lr

/*
 * Function: arm6_7_reset
 *
 * Notes   : This sets up everything for a reset
 */
arm6_7_reset:   mrs     r1, cpsr
                orr     r1, r1, #F_BIT|I_BIT
                msr     cpsr, r1
                mov     r0, #0
#ifndef NO_MM
                mcr     p15, 0, r0, c7, c0, 0           @ flush cache
                mcr     p15, 0, r0, c5, c0, 0           @ flush TLB
#endif
                mov     r1, #F_BIT | I_BIT | 3
                mov     pc, lr

/*
 * Purpose : Function pointers used to access above functions - all calls
 *           come through these
 */
arm6_name:      .ascii  "arm6\0"
                .align

                .globl  arm6_processor_functions
arm6_processor_functions:
                .word   arm6_name                       @  0
                .word   arm6_7_switch_to                @  4
                .word   arm6_data_abort         @  8
                .word   arm6_7_check_bugs               @ 12
                .word   arm6_7_proc_init                @ 16
                .word   arm6_7_proc_fin         @ 20

                .word   arm6_7_flush_cache              @ 24
                .word   arm6_7_flush_cache              @ 28
                .word   arm6_7_flush_cache              @ 32
                .word   arm6_7_null                     @ 36
                .word   arm6_7_flush_cache              @ 40
                .word   arm6_7_flush_tlb_all            @ 44
                .word   arm6_7_flush_tlb_area           @ 48
                .word   arm6_set_pmd                    @ 52
                .word   arm6_7_reset                    @ 54

/*
 * Purpose : Function pointers used to access above functions - all calls
 *           come through these
 */
arm7_name:      .ascii  "arm7\0"
                .align

                .globl  arm7_processor_functions
arm7_processor_functions:
                .word   arm7_name                       @  0
                .word   arm6_7_switch_to                @  4
                .word   arm7_data_abort         @  8
                .word   arm6_7_check_bugs               @ 12
                .word   arm6_7_proc_init                @ 16
                .word   arm6_7_proc_fin         @ 20
                .word   arm6_7_flush_cache              @ 24
                .word   arm6_7_flush_cache              @ 28
                .word   arm6_7_flush_cache              @ 32
                .word   arm6_7_null                     @ 36
                .word   arm6_7_flush_cache              @ 40
                .word   arm6_7_flush_tlb_all            @ 44
                .word   arm6_7_flush_tlb_area           @ 48
                .word   arm7_set_pmd                    @ 52
                .word   arm6_7_reset                    @ 54

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.