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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [sw/] [tests/] [or1200/] [sim/] [or1200-dsxinsn.S] - Rev 868

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

/*
        Test correct delay-slot exception bit (DSX) behavior on
        instruction-fetch related exceptions.

        The only case where DSX is set on instruction-fetch related
        exception is when instructions in delay slots occur in a new
        page which needs to be mapped.

        In this test we will trigger an instruction MMU miss for an
        instruction in a delay slot. To do this, we need to have a
        branch instruction as the very last instruction of a page,
        with the delay slot instruction being on a new unmapped page.
        
        Set r10 to hold whether we are expecting SR[DSX] to be set or
        not. Exceptions will advance the PC by 0x8 to step over both
        the jump/branch and instruction causing an exception.

        Julius Baxter <juliusbaxter@gmail.com>
        
*/
//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2012 Authors and OPENCORES.ORG                 ////
////                                                              ////
//// This source file may be used and distributed without         ////
//// restriction provided that this copyright statement is not    ////
//// removed from the file and that any derivative work contains  ////
//// the original copyright notice and the associated disclaimer. ////
////                                                              ////
//// This source file is free software; you can redistribute it   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any   ////
//// later version.                                               ////
////                                                              ////
//// This source is distributed in the hope that it will be       ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// details.                                                     ////
////                                                              ////
//// You should have received a copy of the GNU Lesser General    ////
//// Public License along with this source; if not, download it   ////
//// from http://www.opencores.org/lgpl.shtml                     ////
////                                                              ////
//////////////////////////////////////////////////////////////////////

#include "spr-defs.h"
#include "board.h"
        
/* =================================================== [ exceptions ] === */
        .section .vectors, "ax"


/* ---[ 0x100: RESET exception ]----------------------------------------- */
        .org 0x100      
        l.movhi r0, 0
        /* Clear status register */
        l.ori   r1, r0, SPR_SR_SM
        l.mtspr r0, r1, SPR_SR
        /* Clear timer  */
        l.mtspr r0, r0, SPR_TTMR
        /* Init the stack */
        .global stack
        l.movhi r1, hi(stack)
        l.ori   r1, r1, lo(stack)
        l.addi  r2, r0, -3
        l.and   r1, r1, r2
        /* Jump to program initialisation code */
        .global _start
        l.movhi r4, hi(_start)
        l.ori   r4, r4, lo(_start)
        l.jr    r4
        l.nop
  
/* ---[ 0x200: BUS error ]------------------------------------------------ */
        .org 0x200
        l.j     test_fail
        l.nop
        
/* ---[ 0x600: ALIGN error ]------------------------------------------------ */
        .org 0x600
        l.j     test_fail
        l.nop
        
/* ---[ 0x700: ILLEGAL INSN exception ]------------------------------------- */
        .org 0x700
        l.j     test_fail
        l.nop

/* ---[ 0x900: DTLB exception ]--------------------------------------------- */
        .org 0x900
        l.j     test_fail
        l.nop

/* ---[ 0xa00: itlb miss ]---------------------------------------------- */
        .org 0xa00

        /* First check if we're expecting a miss in a delay slot - check r10 */
        l.mfspr r3,r0,SPR_EEAR_BASE     /* Get EPC */                           
        l.nop   2                       /* Report PC for diagnostic purpose */  
        /* Check SR[DSX] was as expected */                                     
        l.mfspr r8,r0,SPR_SR            /* Get SR */                            
        l.andi  r8,r8,SPR_SR_DSX        /* Clear all bits except DSX */         
        l.xor   r8,r8,r10               /* r8 will be >0 if error */            
        l.sfne  r8,r0                                                           
        l.bf    test_fail                                                       
        l.nop                                                                   
        
        /* Simple itlb miss handler - install 1-1 mappings on misses */
        l.mfspr r12,r0,SPR_EEAR_BASE /* Get the PC of the exception */
        l.srli  r13,r12,13 /* Get the page number, divide by 8K, store in r13 */
        /* Set up the match registers */
        l.movhi r14,hi(SPR_ITLBMR_VPN)
        l.ori   r14,r14,lo(SPR_ITLBMR_VPN)
        l.and   r14,r12,r14 /* Mask in the VPN */
        l.ori   r15,r14,SPR_ITLBMR_V /* Set this match as valid */
        /* Write it into the appropriate match register, way 0 only */
        l.mtspr r13,r15,SPR_ITLBMR_BASE(0)
        /* Set up the translate register - no restrictions */
        l.ori   r15,r14,ITLB_PR_NOLIMIT
        /* Write it into the appropriate translate register  */
        l.mtspr r13,r15,SPR_ITLBTR_BASE(0)
        /* MMU setup should now be complete, let's go back */
        l.rfe   
        
/* ---[ 0xe00: TRAP error ]------------------------------------------------ */
        .org 0xe00
        l.j     test_fail
        l.nop
        
/* =================================================== [ text section ] === */
        .section  .text

/* =================================================== [ start ] === */ 

        .global _start
_start:
        /* First initialise the instruction MMU */
        
        l.mfspr r3,r0,SPR_IMMUCFGR
        l.andi  r4,r3,SPR_IMMUCFGR_NTS
        l.srli  r4,r4,SPR_IMMUCFGR_NTS_OFF
        l.ori   r6,r0,1
        l.sll   r3,r6,r4
        
        /* Setup the IMMU's TLBs - invalidate them */
        l.movhi r4, hi(SPR_ITLBMR_BASE(0))
        l.ori r4, r4, lo(SPR_ITLBMR_BASE(0))

        /* ITLB invalidate loop */
1:
        l.mtspr r4, r0, 0x0
        l.addi r4, r4, 0x1
        l.sfeq r3, r0
        l.bnf 1b
        l.addi r3, r3, -1

        /* Enable MMU - we should get a miss for this page */
        l.movhi r10,0 /* Clear r10 - not expecting to be in a delay slot
                        when this TLB miss occurs */
        
        .extern lo_immu_en
        /* Now enable the IMMU */
        l.movhi r4, hi(lo_immu_en)
        l.ori r4, r4, lo(lo_immu_en)
        l.jalr r4
        l.nop

        /* Copy the 2 instructions from the ljr9_function function to
        places which should cause TLB misses in the delay slot */
        l.movhi r6,hi(ljr9_function)
        l.ori   r6,r6,lo(ljr9_function)

        /* r13 should have the page number we're in from the TLB miss we caused
        when enabling the immu. Take that and add 16 to determine the page
        boundary we'll play with */
        l.addi  r4,r13,16

        /* Calculate the physical address for this page */
        l.slli  r8,r4,13

        /* Copy our function to the last 2 instructions of the page before */
        l.lwz   r1,0(r6)
        l.sw    -8(r8),r1
        l.lwz   r1,4(r6)
        l.sw    -4(r8),r1

        /* Call it - we should _not_ have DSX set on the itbl miss */
        l.movhi r10,0
        l.addi  r1,r8,-8

        /* Report value */
        l.or    r3,r1,r1
        l.nop   2

        l.jalr  r1
        l.nop
        
        /* Tests finish */

        /* Now do what we've done for the miss but put delay slot instruction
        in the new page */

        /* Calculate the physical address for this page */
        l.slli  r8,r4,13

        /* Copy our function to the last 2 instructions of the page before */
        l.lwz   r1,0(r6)
        l.sw    -4(r8),r1
        l.lwz   r1,4(r6)
        l.sw    0(r8),r1

        /* Clear insn cache for this area (need to if it's enabled so we
        don't get the cached instructions from the previous test) */
        l.mtspr r0,r8,SPR_ICBIR
        l.addi  r1,r8,-4
        l.mtspr r0,r1,SPR_ICBIR

        /* Jump to (r8-0x4) - we _should_ have DSX set on the itbl miss as
        the jump instruction will be on the last instruction of the previous
        page (already mapped in ITLB) and the delay slot will be the first
        instruction on the next page, which is unmapped at this stage and
        should cause an ITLB miss*/
        l.ori   r10,r0,SPR_SR_DSX
        l.addi  r1,r8,-4

        /* Report value */
        l.or    r3,r1,r1
        l.nop   2

        l.jalr  r1
        l.nop
        

        /* TODO - track and check the number of TLB misses we should
        have incurred */
        
        /* Check if IC present and skip enabling otherwise */
        l.mfspr r3,r0,SPR_UPR
        l.andi  r4,r3,SPR_UPR_ICP
        l.sfeq  r4,r0
        l.bf    test_ok
        l.nop
        
        /* Now repeat the tests with caches enabled if they weren't */
        l.mfspr r1,r0,SPR_SR
        l.andi  r1,r1,SPR_SR_ICE
        l.sfeq  r0,r1  /* Set flag if caches not enabled */
        l.bf    restart_with_caches_enabled
        l.nop
        
test_ok:
        l.movhi r3,0x8000
        l.ori   r3,r3,0x000d
        l.nop   2
        l.or    r3,r0,r0
        l.nop   1

test_fail:
        l.movhi r3,0xbaaa
        l.ori   r3,r3,0xaaad
        l.nop   2
        l.ori   r3,r0,1
        l.nop   1

restart_with_caches_enabled:
        
        /* Disable IMMU before restart*/
        l.mfspr r3,r0,SPR_SR
        l.xori  r3,r3,SPR_SR_IME
        l.mtspr r0,r3,SPR_ESR_BASE
        l.movhi r9,hi(.L1)
        l.ori   r9,r9,lo(.L1)
        l.mtspr r0,r9,SPR_EPCR_BASE
        l.rfe
.L1:    
        l.jal   _cache_init
        l.nop

        /* Actually we won't want dcache enabled as we'll be reading
        and writing instructions around the shop so will not want them
        being cached */
        l.mfspr r3,r0,SPR_SR
        l.xori  r3,r3,SPR_SR_DCE
        l.mtspr r0,r3,SPR_SR
        
        l.j     _start
        l.nop

        /* A simple function, which we will copy the instructions of
        to different parts of memory */
ljr9_function:
        l.jr    r9
        l.nop

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.