927 lines
35 KiB
ArmAsm
927 lines
35 KiB
ArmAsm
|
#if defined(JAZZ)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
memtest.s
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains the assembly routine to test memory.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Lluis Abello (lluis) 10-Aug-91
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Executes in kernal mode.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "ksmips.h"
|
|||
|
#include "selfmap.h"
|
|||
|
#include "j4reset.h"
|
|||
|
|
|||
|
|
|||
|
.text
|
|||
|
.set noreorder
|
|||
|
.set noat
|
|||
|
/*++
|
|||
|
VOID
|
|||
|
WriteMemoryAddressTest(
|
|||
|
StartAddress
|
|||
|
Size
|
|||
|
Xor pattern
|
|||
|
)
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will store the address of each location xored with
|
|||
|
the Pattern into each location.
|
|||
|
It packs together two words and does double word stores to
|
|||
|
speed it up.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
a0 - supplies start of memory area to test (must be in KSEG0)
|
|||
|
a1 - supplies length of memory area in bytes
|
|||
|
a2 - supplies the pattern to Xor with.
|
|||
|
|
|||
|
Note: the values of the arguments are preserved.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
This routine returns no value.
|
|||
|
--*/
|
|||
|
LEAF_ENTRY(WriteMemoryAddressTest)
|
|||
|
// add t1,a0,a1 // t1 = last address.
|
|||
|
// xor t0,a0,a2 // t0 value to write
|
|||
|
// move t2,a0 // t2=current address
|
|||
|
//writeaddress:
|
|||
|
// mtc1 t0,f0 // move lower word to cop1
|
|||
|
// addiu t2,t2,4 // compute next address
|
|||
|
// xor t0,t2,a2 // next pattern
|
|||
|
// mtc1 t0,f1 // move upper word to cop1
|
|||
|
// addiu t2,t2,4 // compute next address
|
|||
|
// sdc1 f0,-8(t2) // store even doubleword.
|
|||
|
// xor t0,t2,a2 // next pattern
|
|||
|
// mtc1 t0,f0 // move lower word to cop1
|
|||
|
// addiu t2,t2,4 // compute next address
|
|||
|
// xor t0,t2,a2 // next pattern
|
|||
|
// mtc1 t0,f1 // move upper word to cop1
|
|||
|
// addiu t2,t2,4 // compute next address
|
|||
|
// sdc1 f0,-8(t2) // store odd doubleword.
|
|||
|
// bne t2,t1, writeaddress // check for end condition
|
|||
|
// xor t0,t2,a2 // value to write
|
|||
|
// j ra
|
|||
|
// nop
|
|||
|
|
|||
|
//
|
|||
|
// Enable parity exceptions. To make sure this works.
|
|||
|
//
|
|||
|
li t1,(1 << PSR_CU1) | (1 << PSR_BEV)
|
|||
|
mtc0 t1,psr
|
|||
|
nop
|
|||
|
nop
|
|||
|
|
|||
|
//
|
|||
|
// Create dirty exclusive cache blocks and zero the data.
|
|||
|
//
|
|||
|
mfc0 t5,config // get configuration data
|
|||
|
li t4,16 //
|
|||
|
srl t0,t5,CONFIG_DB // compute data cache line size
|
|||
|
and t0,t0,1 //
|
|||
|
sll t4,t4,t0 // 1st fill size
|
|||
|
li t1,(1 << CONFIG_SC)
|
|||
|
and t0,t5,t1
|
|||
|
beq t0,zero,SecondaryCache // if zero secondary cache
|
|||
|
|
|||
|
PrimaryOnly:
|
|||
|
move t0,a0 // put start address in t0
|
|||
|
addu t9,t0,a1 // compute ending address
|
|||
|
and t8,t4,0x10 // test if 16-byte cache block
|
|||
|
|
|||
|
//
|
|||
|
// Store data using primary data cache only.
|
|||
|
//
|
|||
|
|
|||
|
30: cache CREATE_DIRTY_EXCLUSIVE_D,0(t0) // create cache block
|
|||
|
move t1,t0 // save beginning block address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
mtc1 t5,f0 // move to lower word of double word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
mtc1 t5,f1 // move to upper word of double word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
sdc1 f0,-8(t0) // store double word
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
mtc1 t5,f0 // move to lower word of double word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
mtc1 t5,f1 // move to upper word of double word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
bne zero,t8,40f // if ne, 16-byte cache line
|
|||
|
sdc1 f0,-8(t0) // store double word
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
mtc1 t5,f0 // move to lower word of double word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
mtc1 t5,f1 // move to upper word of double word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
sdc1 f0,-8(t0) // store double word
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
mtc1 t5,f0 // move to lower word of double word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
mtc1 t5,f1 // move to upper word of double word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
sdc1 f0,-8(t0) // store double word
|
|||
|
40: nop
|
|||
|
nop
|
|||
|
cache INDEX_WRITEBACK_INVALIDATE_D,(t1) // Flush out the data
|
|||
|
nop
|
|||
|
bne t0,t9,30b // if ne, more blocks to zero
|
|||
|
nop
|
|||
|
|
|||
|
j ra
|
|||
|
nop
|
|||
|
|
|||
|
//
|
|||
|
// Store data using primary and secondary data caches.
|
|||
|
//
|
|||
|
|
|||
|
SecondaryCache:
|
|||
|
// t4 = primary data cache line size
|
|||
|
srl t0,t5,CONFIG_DC // compute primary data cache size
|
|||
|
and t0,t0,0x7 //
|
|||
|
addu t0,t0,12 //
|
|||
|
li t6,1 //
|
|||
|
sll t6,t6,t0 // t6 = primary data cache size
|
|||
|
srl t0,t5,CONFIG_SB // compute secondary cache line size
|
|||
|
and t0,t0,3 //
|
|||
|
li t8,16 //
|
|||
|
sll t8,t8,t0 // t8 = secondary cache line size
|
|||
|
li t5,SECONDARY_CACHE_SIZE // t5 = secondary cache size
|
|||
|
//
|
|||
|
// Write Back all the dirty data from the primary to the secondary cache.
|
|||
|
//
|
|||
|
li t1,KSEG0_BASE+(1<<20) // get virtual address to index cache
|
|||
|
addu t2,t1,t6 // add cache size
|
|||
|
subu t2,t2,t4 // adjust for cache line size.
|
|||
|
WriteBackPrimary:
|
|||
|
cache INDEX_WRITEBACK_INVALIDATE_D,0(t1) // Invalidate Data cache
|
|||
|
bne t1,t2,WriteBackPrimary // loop
|
|||
|
addu t1,t1,t4 // increment index by cache line
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Write Back all the dirty data from the secondary to memory
|
|||
|
//
|
|||
|
li t1,KSEG0_BASE+(1<<20) // get virtual address to index cache
|
|||
|
addu t2,t1,t5 // add cache size
|
|||
|
subu t2,t2,t8 // adjust for cache line size.
|
|||
|
WriteBackSecondary:
|
|||
|
cache INDEX_WRITEBACK_INVALIDATE_SD,0(t1) // Invalidate Data cache
|
|||
|
bne t1,t2,WriteBackSecondary// loop
|
|||
|
addu t1,t1,t8 // increment index by cache line
|
|||
|
|
|||
|
//
|
|||
|
// Now all the dirty data has been saved. And both primary and secondary
|
|||
|
// Data caches are invalid an clean.
|
|||
|
//
|
|||
|
|
|||
|
move t0,a0 // put start address in t0
|
|||
|
addu t9,t0,a1 // compute ending address
|
|||
|
li t1,16 // If the secondary line is 16
|
|||
|
beq t1,t8,Secondary16 // bytes go do the write
|
|||
|
li t1,32 // If the secondary line is 32
|
|||
|
beq t1,t8,Secondary32 // bytes go do the write
|
|||
|
nop
|
|||
|
.globl Secondary64
|
|||
|
.align 4
|
|||
|
mtc0 zero,taghi
|
|||
|
|
|||
|
Secondary64:
|
|||
|
srl t5,t0,5
|
|||
|
andi t5,t5,0x380
|
|||
|
ori t5,(5 << TAGLO_SSTATE)
|
|||
|
li t2,~KSEG1_BASE
|
|||
|
and t2,t2,t0
|
|||
|
srl t2,t2,17
|
|||
|
sll t2,t2,13
|
|||
|
or t2,t5,t2
|
|||
|
mtc0 t2,taglo
|
|||
|
nop
|
|||
|
nop
|
|||
|
cache INDEX_STORE_TAG_SD,0(t0)// create cache block
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
nop
|
|||
|
cache HIT_WRITEBACK_INVALIDATE_SD,-64(t0) // Flush cache block
|
|||
|
bne t0,t9,Secondary64 // if ne, more data to zero
|
|||
|
nop
|
|||
|
|
|||
|
j ra
|
|||
|
nop
|
|||
|
|
|||
|
Secondary16:
|
|||
|
cache CREATE_DIRTY_EXCLUSIVE_SD,0(t0) // create cache block
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
nop
|
|||
|
cache HIT_WRITEBACK_INVALIDATE_SD,-16(t0) // Flush cache block
|
|||
|
bne t0,t9,Secondary16 // if ne, more data to zero
|
|||
|
nop
|
|||
|
|
|||
|
j ra
|
|||
|
nop
|
|||
|
|
|||
|
Secondary32:
|
|||
|
cache CREATE_DIRTY_EXCLUSIVE_SD,0(t0) // create cache block
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
xor t5,t0,a2 // create pattern to write
|
|||
|
sw t5,0(t0) // store word
|
|||
|
addiu t0,t0,4 // increment address
|
|||
|
nop
|
|||
|
cache HIT_WRITEBACK_INVALIDATE_SD,-32(t0) // Flush cache block
|
|||
|
bne t0,t9,Secondary32 // if ne, more data to zero
|
|||
|
nop
|
|||
|
|
|||
|
j ra
|
|||
|
nop
|
|||
|
|
|||
|
.end WriteMemoryAddressTest
|
|||
|
|
|||
|
/*++
|
|||
|
VOID
|
|||
|
CheckMemoryAddressTest(
|
|||
|
StartAddress
|
|||
|
Size
|
|||
|
Xor pattern
|
|||
|
LedDisplayValue
|
|||
|
)
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will check that each location contains it's address
|
|||
|
xored with the Pattern as written by WriteMemoryAddressTest.
|
|||
|
|
|||
|
Note: the values of the arguments are preserved.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
This routine will check that each location contains it's address
|
|||
|
xored with the Pattern as written by WriteMemoryAddressTest. The memory
|
|||
|
is read cached or non cached according to the address specified by a0.
|
|||
|
Write address test writes allways KSEG1_ADR=KSEG1_ADR ^ KSEG1_XOR
|
|||
|
if a0 is in KSEG0 to read the data cached, then the XOR_PATTERN
|
|||
|
Must be such that:
|
|||
|
KSEG0_ADR ^ KSEG0_XOR = KSEG1_ADR ^ KSEG1_XOR
|
|||
|
Examples:
|
|||
|
|
|||
|
If XorPattern with which WriteMemoryAddressTest was called is KSEG1_PAT
|
|||
|
and the XorPattern this routine needs is KSEG0_PAT:
|
|||
|
KSEG1_XOR Written KSEG0_XOR So that
|
|||
|
0x00000000 0xA0 0x20000000 0x80 ^ 0x20 = 0xA0
|
|||
|
0xFFFFFFFF 0x5F 0xDFFFFFFF 0x80 ^ 0xDF = 0x5F
|
|||
|
0x01010101 0xA1 0x21010101 0x80 ^ 0x21 = 0xA1
|
|||
|
|
|||
|
Note: the values of the arguments are preserved.
|
|||
|
a0 - supplies start of memory area to test
|
|||
|
a1 - supplies length of memory area in bytes
|
|||
|
a2 - supplies the pattern to Xor with.
|
|||
|
a3 - suplies the value to display in the led in case of failure
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
If successful returns a 0, otherwise returns a 1.
|
|||
|
|
|||
|
--*/
|
|||
|
LEAF_ENTRY(CheckMemoryAddressTest)
|
|||
|
move t3,a0 // t3 first address.
|
|||
|
add t2,t3,a1 // last address.
|
|||
|
checkaddress:
|
|||
|
lw t1,0(t3) // load from first location
|
|||
|
xor t0,t3,a2 // first expected value
|
|||
|
bne t1,t0,PatternFail
|
|||
|
addiu t3,t3,4 // compute next address
|
|||
|
lw t1,0(t3) // load from first location
|
|||
|
xor t0,t3,a2 // first expected value
|
|||
|
bne t1,t0,PatternFail
|
|||
|
addiu t3,t3,4 // compute next address
|
|||
|
lw t1,0(t3) // load from first location
|
|||
|
xor t0,t3,a2 // first expected value
|
|||
|
bne t1,t0,PatternFail
|
|||
|
addiu t3,t3,4 // compute next address
|
|||
|
lw t1,0(t3) // load from first location
|
|||
|
xor t0,t3,a2 // first expected value
|
|||
|
bne t1,t0,PatternFail // check last one.
|
|||
|
addiu t3,t3,4 // compute next address
|
|||
|
bne t3,t2, checkaddress // check for end condition
|
|||
|
nop
|
|||
|
j ra // return a zero to the caller
|
|||
|
move v0,zero // set return value to zero.
|
|||
|
PatternFail:
|
|||
|
j ra //
|
|||
|
// addiu v0,zero,1 // return a 1 to the caller
|
|||
|
addu v0,zero,t3 // return failing address to caller
|
|||
|
.end CheckMemoryAddressTest
|
|||
|
|
|||
|
/*++
|
|||
|
VOID
|
|||
|
WriteVideoMemoryAddressTest(
|
|||
|
StartAddress
|
|||
|
Size
|
|||
|
)
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will store the address of each location
|
|||
|
into each location. It packs two double words together
|
|||
|
to do sdc1 and speed it up.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
a0 - supplies start of memory area to test
|
|||
|
a1 - supplies length of memory area in bytes
|
|||
|
|
|||
|
Note: the values of the arguments are preserved.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
This routine returns no value.
|
|||
|
--*/
|
|||
|
LEAF_ENTRY(WriteVideoMemoryAddressTest)
|
|||
|
addu t1,a0,a1 // t1 = last address.
|
|||
|
move t2,a0 // t2=current address
|
|||
|
10:
|
|||
|
mtc1 t2,f0 // move lower word to cop1
|
|||
|
addiu t2,t2,4 // compute next address
|
|||
|
mtc1 t2,f1 // move upper word to cop1
|
|||
|
addiu t2,t2,4 // compute next address
|
|||
|
sdc1 f0,-8(t2) // store even doubleword
|
|||
|
mtc1 t2,f2 // move lower word to cop1
|
|||
|
addiu t2,t2,4 // compute next address
|
|||
|
mtc1 t2,f3 // move upper word to cop1
|
|||
|
addiu t2,t2,4 // compute next address
|
|||
|
bne t2,t1, 10b // check for end condition
|
|||
|
sdc1 f2,-8(t2) // store odd doubleword.
|
|||
|
j ra
|
|||
|
nop
|
|||
|
.end WriteVideoMemoryAddressTest
|
|||
|
/*++
|
|||
|
VOID
|
|||
|
CheckVideoMemoryAddressTest(
|
|||
|
StartAddress
|
|||
|
Size
|
|||
|
)
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will check that each location contains it's address
|
|||
|
xored with the Pattern as written by WriteMemoryAddressTest.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Note: the values of the arguments are preserved.
|
|||
|
a0 - supplies start of memory area to test
|
|||
|
a1 - supplies length of memory area in bytes
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
This routine returns FALSE if no errors are found.
|
|||
|
Otherwise returns true.
|
|||
|
|
|||
|
--*/
|
|||
|
LEAF_ENTRY(CheckVideoMemoryAddressTest)
|
|||
|
addu t2,a0,a1 // compute last address.
|
|||
|
10:
|
|||
|
ldc1 f0,0(a0) // read data
|
|||
|
ldc1 f2,8(a0) // read data
|
|||
|
mfc1 t0,f0 // move from cop
|
|||
|
mfc1 t1,f1 // move from cop
|
|||
|
bne t0,a0,VideoMemoryFail // compare
|
|||
|
addiu a0,a0,4 // inc address for next expected value
|
|||
|
bne t1,a0,VideoMemoryFail // compare.
|
|||
|
mfc1 t0,f2 // move from cop
|
|||
|
mfc1 t1,f3 // move from cop
|
|||
|
addiu a0,a0,4 // inc address for next expected value
|
|||
|
bne t0,a0,VideoMemoryFail // compare
|
|||
|
addiu a0,a0,4 // inc address for next expected value
|
|||
|
bne t1,a0,VideoMemoryFail // compare.
|
|||
|
addiu a0,a0,4
|
|||
|
bne a0,t2,10b
|
|||
|
nop
|
|||
|
j ra // return a zero to the caller
|
|||
|
move v0,zero //
|
|||
|
VideoMemoryFail:
|
|||
|
j ra //
|
|||
|
addiu v0,zero,1 // return a 1 to the caller
|
|||
|
.end CheckVideoMemoryAddressTest
|
|||
|
|
|||
|
.set at
|
|||
|
|
|||
|
LEAF_ENTRY(RomReadMergeWrite)
|
|||
|
mfc0 t5,config // read config
|
|||
|
lui t0,0xa004 // uncached address
|
|||
|
lui t1,0x8004 //8004 // same cached address R4KFIX
|
|||
|
li t6,16 // end of loop counter
|
|||
|
move t2,zero // byte counter
|
|||
|
srl t3,t5,CONFIG_DC // compute data cache size
|
|||
|
and t3,t3,0x7 //
|
|||
|
addu t3,t3,12 //
|
|||
|
li t9,1 //
|
|||
|
sll t9,t9,t3 // t9 = data cache size
|
|||
|
WriteNextByte:
|
|||
|
sw zero,0(t1) // clear memory line
|
|||
|
sw zero,4(t1) // clear memory line
|
|||
|
sw zero,8(t1) // clear memory line
|
|||
|
sw zero,12(t1) // clear memory line
|
|||
|
addu t8,t9,t1 // add cache size to address
|
|||
|
lw zero,0(t8) // Force a replacement of the cache line -> updates memory
|
|||
|
add t4,t0,t2 // compute ith byte address
|
|||
|
nor t5,t2,zero // invert value
|
|||
|
sb t5,0(t4) // write byte <= read/merge/write
|
|||
|
move t3,zero // init read index
|
|||
|
CheckNextByte:
|
|||
|
add t4,t3,t1 // compute cached address
|
|||
|
lb t4,0(t4) // read byte
|
|||
|
beq t3,t2, Inverted // if equal is the inverted value
|
|||
|
nor t5,t2,zero
|
|||
|
move t5,zero // else expect a zero
|
|||
|
Inverted:
|
|||
|
bne t4,t5, Error // compare with what we wrote.
|
|||
|
addiu t3,t3,1 // next byte index
|
|||
|
bne t3,t6,CheckNextByte
|
|||
|
nop
|
|||
|
addiu t2,t2,1 // inc write index
|
|||
|
bne t2,t6,WriteNextByte
|
|||
|
nop
|
|||
|
// do the same storing half words
|
|||
|
move t2,zero // byte counter
|
|||
|
WriteNextHalf:
|
|||
|
sw zero,0(t1) // clear memory line
|
|||
|
sw zero,4(t1) // clear memory line
|
|||
|
sw zero,8(t1) // clear memory line
|
|||
|
sw zero,12(t1) // clear memory line
|
|||
|
addu t8,t9,t1 // add cache size to address
|
|||
|
lw zero,0(t8) // Force a replacement of the cache line -> updates memory
|
|||
|
add t4,t0,t2 // compute ith byte address
|
|||
|
nor t5,t2,zero // invert value
|
|||
|
sh t5,0(t4) // write half <= read/merge/write
|
|||
|
move t3,zero // init read index
|
|||
|
CheckNextHalf:
|
|||
|
add t4,t3,t1 // compute cached address
|
|||
|
lh t4,0(t4) // read half
|
|||
|
beq t3,t2,InvertedHalf // if equal is the inverted value
|
|||
|
nor t5,t2,zero // invert value
|
|||
|
move t5,zero // else expect a zero
|
|||
|
InvertedHalf:
|
|||
|
bne t4,t5, Error // compare with what we wrote.
|
|||
|
addiu t3,t3,2 // next half index
|
|||
|
bne t3,t6,CheckNextHalf
|
|||
|
nop
|
|||
|
addiu t2,t2,2 // inc write index
|
|||
|
bne t2,t6,WriteNextHalf
|
|||
|
nop
|
|||
|
j ra
|
|||
|
move v0,zero // return no errors
|
|||
|
Error:
|
|||
|
sw t4,20(t0)
|
|||
|
j ra
|
|||
|
addiu v0,zero,1 // return errors
|
|||
|
.end RomReadMergeWrite
|
|||
|
.set noat
|
|||
|
/*++
|
|||
|
VOID
|
|||
|
FillVideoMemory(
|
|||
|
StartAddress
|
|||
|
Size
|
|||
|
Pattern
|
|||
|
)
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will fill the given range of video memory with
|
|||
|
the supplied pattern. The fill is done by doing double word
|
|||
|
writes and the range must be 16byte aligned.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
a0 - supplies start of memory area
|
|||
|
a1 - supplies length of memory area
|
|||
|
a2 - supplies the pattern to fill video memory with. (1byte)
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
LEAF_ENTRY(FillVideoMemory)
|
|||
|
andi a2,a2,0xFF // Mask out byte
|
|||
|
sll t0,a2,8 // Shift Byte
|
|||
|
or t0,t0,a2 // or them to make half
|
|||
|
sll a2,t0,16 // shift half
|
|||
|
or a2,t0,a2 // or them to make a word
|
|||
|
addu t0,a0,a1 // compute last address.
|
|||
|
mtc1 a2,f0 // move pattern to cop1
|
|||
|
mtc1 a2,f1 // move pattern to cop1
|
|||
|
10:
|
|||
|
addiu a0,a0,16 // compute next address
|
|||
|
sdc1 f0,-16(a0) // do a store
|
|||
|
bne a0,t0,10b // check for end condition
|
|||
|
sdc1 f0,-8(a0) // do a store
|
|||
|
j ra
|
|||
|
nop
|
|||
|
.end FillVideoMemory
|
|||
|
/*++
|
|||
|
VOID FwVideoScroll(
|
|||
|
PUCHAR StartAddress,
|
|||
|
PUCHAR EndAddress,
|
|||
|
PUCHAR Destination
|
|||
|
);
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine writes the pattern to the specified range of addresses
|
|||
|
doing video pipeline writes on double writes.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
StartAddress - Suplies the range of addresses to be scrolled
|
|||
|
EndAddress - this addresses must be aligned to 256byte boundaries.
|
|||
|
Destination - Suplies the Destination address for the scroll
|
|||
|
(i.e the contents of StartAddress will be moved
|
|||
|
to destination address and so on).
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
.set noreorder
|
|||
|
.set noat
|
|||
|
LEAF_ENTRY(FwVideoScroll)
|
|||
|
ScrollRead:
|
|||
|
ldc1 f0,0x0(a0) // read video
|
|||
|
ldc1 f2,0x8(a0)
|
|||
|
ldc1 f4,0x10(a0)
|
|||
|
ldc1 f6,0x18(a0)
|
|||
|
ldc1 f8,0x20(a0)
|
|||
|
ldc1 f10,0x28(a0)
|
|||
|
ldc1 f12,0x30(a0)
|
|||
|
ldc1 f14,0x38(a0)
|
|||
|
ldc1 f16,0x40(a0)
|
|||
|
ldc1 f18,0x48(a0)
|
|||
|
ldc1 f20,0x50(a0)
|
|||
|
ldc1 f22,0x58(a0)
|
|||
|
ldc1 f24,0x60(a0)
|
|||
|
ldc1 f26,0x68(a0)
|
|||
|
ldc1 f28,0x70(a0)
|
|||
|
ldc1 f30,0x78(a0)
|
|||
|
addiu a0,a0,0x80 // increment source address
|
|||
|
sdc1 f0,0x0(a2) // store them pipelining
|
|||
|
sdc1 f2,0x8(a2)
|
|||
|
sdc1 f4,0x10(a2)
|
|||
|
sdc1 f6,0x18(a2)
|
|||
|
sdc1 f8,0x20(a2)
|
|||
|
sdc1 f10,0x28(a2)
|
|||
|
sdc1 f12,0x30(a2)
|
|||
|
sdc1 f14,0x38(a2)
|
|||
|
sdc1 f16,0x40(a2)
|
|||
|
sdc1 f18,0x48(a2)
|
|||
|
sdc1 f20,0x50(a2)
|
|||
|
sdc1 f22,0x58(a2)
|
|||
|
sdc1 f24,0x60(a2)
|
|||
|
sdc1 f26,0x68(a2)
|
|||
|
sdc1 f28,0x70(a2)
|
|||
|
sdc1 f30,0x78(a2)
|
|||
|
bne a0,a1,ScrollRead // check for last
|
|||
|
addiu a2,a2,0x80 // increment destination
|
|||
|
j ra // return to caller
|
|||
|
nop
|
|||
|
.end FwVideoScroll
|
|||
|
/*++
|
|||
|
VOID
|
|||
|
StoreDoubleWord(
|
|||
|
IN ULONG Address,
|
|||
|
IN PVOID Value
|
|||
|
);
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine writes the value pointed by a1 to the address supplied
|
|||
|
in a0.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
a0 - Address to write double to.
|
|||
|
a1 - pointer to value to write.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
LEAF_ENTRY(StoreDoubleWord)
|
|||
|
ldc1 f0,0(a1)
|
|||
|
nop
|
|||
|
sdc1 f0,0(a0)
|
|||
|
j ra
|
|||
|
nop
|
|||
|
.end StoreDoubleWord
|
|||
|
/*++
|
|||
|
VOID
|
|||
|
LoadDoubleWord(
|
|||
|
IN ULONG Address,
|
|||
|
OUT PVOID Result
|
|||
|
);
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine reads a double from the address suplied in a0 and
|
|||
|
stores the red value in the address supplied by result.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
a0 - Address to read double from.
|
|||
|
a1 - pointer to double to store result.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
LEAF_ENTRY(LoadDoubleWord)
|
|||
|
ldc1 f0,0(a0)
|
|||
|
nop
|
|||
|
sdc1 f0,0(a1)
|
|||
|
j ra
|
|||
|
nop
|
|||
|
.end
|
|||
|
/*++
|
|||
|
VOID
|
|||
|
WildZeroMemory(
|
|||
|
IN ULONG StartAddress,
|
|||
|
IN ULONG Size
|
|||
|
)
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine zeroes the specified range of memory by doing
|
|||
|
cache line writes.
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
a0 - supplies the physical address of the range of memory to
|
|||
|
zero. This address must be a multiple of the Data Cache Size.
|
|||
|
|
|||
|
a1 - supplies length of memory to zero.
|
|||
|
This value must be a multiple of the Data Cache Size.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
LEAF_ENTRY(WildZeroMemory)
|
|||
|
|
|||
|
// TEMPTEMP
|
|||
|
// li t0,KSEG1_BASE // get non-cached base
|
|||
|
// or t0,t0,a0 // physical address in KSEG1
|
|||
|
// addu t1,t0,a1 // end
|
|||
|
// mtc1 zero,f0 // set write pattern
|
|||
|
// mtc1 zero,f1 //
|
|||
|
//
|
|||
|
//10:
|
|||
|
// sdc1 f0,0(t0)
|
|||
|
// addu t0,t0,16
|
|||
|
// bne t0,t1,10b
|
|||
|
// sdc1 f0,-8(t0)
|
|||
|
//
|
|||
|
// li t0,KSEG0_BASE // get cached base
|
|||
|
// or t0,t0,a0 // physical address in KSEG0
|
|||
|
// addu t1,t0,a1 // end
|
|||
|
//10:
|
|||
|
// lw zero,0(t0)
|
|||
|
// addu t0,t0,16
|
|||
|
// bne t0,t1,10b
|
|||
|
// nop
|
|||
|
//
|
|||
|
// j ra
|
|||
|
// nop
|
|||
|
// TEMPTEMP
|
|||
|
|
|||
|
//
|
|||
|
// Create dirty exclusive cache blocks and zero the data.
|
|||
|
//
|
|||
|
|
|||
|
mfc0 t5,config // get configuration data
|
|||
|
li t4,16 //
|
|||
|
srl t0,t5,CONFIG_DB // compute data cache line size
|
|||
|
and t0,t0,1 //
|
|||
|
sll t4,t4,t0 // t4 = 1st fill size
|
|||
|
li t1,(1 << CONFIG_SC)
|
|||
|
and t0,t5,t1
|
|||
|
mtc1 zero,f0 // set write pattern
|
|||
|
mtc1 zero,f1 //
|
|||
|
beq t0,zero,SecondaryWild // if zero secondary cache
|
|||
|
|
|||
|
PrimaryWild:
|
|||
|
li t0,KSEG0_BASE // get cached base
|
|||
|
or t0,t0,a0 // physical address in KSEG0
|
|||
|
addu t9,t0,a1 // compute ending address
|
|||
|
and t8,t4,0x10 // test if 16-byte cache block
|
|||
|
|
|||
|
//
|
|||
|
// Zero data using primary data cache only.
|
|||
|
//
|
|||
|
|
|||
|
30: cache CREATE_DIRTY_EXCLUSIVE_D,0(t0) // create cache block
|
|||
|
move t1,t0 // save beginning block address
|
|||
|
addu t0,t0,t4 // compute next block address
|
|||
|
bne zero,t8,40f // if ne, 16-byte cache line
|
|||
|
sdc1 f0,-16(t0) //
|
|||
|
sdc1 f0,-24(t0) // zero 16 bytes
|
|||
|
sdc1 f0,-32(t0) //
|
|||
|
40: sdc1 f0,-8(t0) // zero 16 bytes
|
|||
|
nop
|
|||
|
nop
|
|||
|
cache INDEX_WRITEBACK_INVALIDATE_D,0(t1) // Flush out the data
|
|||
|
bne t0,t9,30b // if ne, more blocks to zero
|
|||
|
nop
|
|||
|
|
|||
|
j ra
|
|||
|
nop
|
|||
|
|
|||
|
//
|
|||
|
// Zero data using primary and secondary data caches.
|
|||
|
//
|
|||
|
SecondaryWild:
|
|||
|
// t4 = primary data cache line size
|
|||
|
srl t0,t5,CONFIG_DC // compute primary data cache size
|
|||
|
and t0,t0,0x7 //
|
|||
|
addu t0,t0,12 //
|
|||
|
li t6,1 //
|
|||
|
sll t6,t6,t0 // t6 = primary data cache size
|
|||
|
srl t0,t5,CONFIG_SB // compute secondary cache line size
|
|||
|
and t0,t0,3 //
|
|||
|
li t8,16 //
|
|||
|
sll t8,t8,t0 // t8 = secondary cache line size
|
|||
|
li t5,SECONDARY_CACHE_SIZE // t5 = secondary cache size
|
|||
|
//
|
|||
|
// Write Back all the dirty data from the primary to the secondary cache.
|
|||
|
//
|
|||
|
li t1,KSEG0_BASE+(1<<20) // get virtual address to index cache
|
|||
|
addu t2,t1,t6 // add cache size
|
|||
|
subu t2,t2,t4 // adjust for cache line size.
|
|||
|
WriteBackPrimaryW:
|
|||
|
cache INDEX_WRITEBACK_INVALIDATE_D,0(t1) // Invalidate Data cache
|
|||
|
bne t1,t2,WriteBackPrimaryW // loop
|
|||
|
addu t1,t1,t4 // increment index by cache line
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Write Back all the dirty data from the secondary to memory
|
|||
|
//
|
|||
|
li t1,KSEG0_BASE+(1<<20) // get virtual address to index cache
|
|||
|
addu t2,t1,t5 // add cache size
|
|||
|
subu t2,t2,t8 // adjust for cache line size.
|
|||
|
WriteBackSecondaryW:
|
|||
|
cache INDEX_WRITEBACK_INVALIDATE_SD,0(t1) // Invalidate Data cache
|
|||
|
bne t1,t2,WriteBackSecondaryW // loop
|
|||
|
addu t1,t1,t8 // increment index by cache line
|
|||
|
|
|||
|
//
|
|||
|
// Now all the dirty data has been saved. And both primary and secondary
|
|||
|
// Data caches are invalid an clean.
|
|||
|
//
|
|||
|
|
|||
|
li t0,KSEG0_BASE // get cached base
|
|||
|
or t0,t0,a0 // physical address in KSEG0
|
|||
|
addu t9,t0,a1 // compute ending address
|
|||
|
subu t9,t9,t8 // adjust last address
|
|||
|
li t1,16 // If the secondary line is 16
|
|||
|
beq t1,t8,SecondaryW16 // bytes go do the write
|
|||
|
li t1,32 // If the secondary line is 32
|
|||
|
beq t1,t8,SecondaryW32 // bytes go do the write
|
|||
|
nop
|
|||
|
|
|||
|
SecondaryW64:
|
|||
|
cache CREATE_DIRTY_EXCLUSIVE_SD,0(t0) // create cache block
|
|||
|
sdc1 f0,0(t0) // store double word
|
|||
|
sdc1 f0,8(t0) // store double word
|
|||
|
sdc1 f0,16(t0) // store double word
|
|||
|
sdc1 f0,24(t0) // store double word
|
|||
|
sdc1 f0,32(t0) // store double word
|
|||
|
sdc1 f0,40(t0) // store double word
|
|||
|
sdc1 f0,48(t0) // store double word
|
|||
|
sdc1 f0,56(t0) // store double word
|
|||
|
cache HIT_WRITEBACK_INVALIDATE_SD,0(t0) // Flush cache block
|
|||
|
bne t0,t9,SecondaryW64 // if ne, more data to zero
|
|||
|
addiu t0,t0,64
|
|||
|
j ra
|
|||
|
nop
|
|||
|
|
|||
|
SecondaryW32:
|
|||
|
cache CREATE_DIRTY_EXCLUSIVE_SD,0(t0) // create cache block
|
|||
|
sdc1 f0,0(t0) // store double word
|
|||
|
sdc1 f0,8(t0) // store double word
|
|||
|
sdc1 f0,16(t0) // store double word
|
|||
|
sdc1 f0,24(t0) // store double word
|
|||
|
cache HIT_WRITEBACK_INVALIDATE_SD,0(t0) // Flush cache block
|
|||
|
bne t0,t9,SecondaryW32 // if ne, more data to zero
|
|||
|
addiu t0,t0,32
|
|||
|
j ra
|
|||
|
nop
|
|||
|
|
|||
|
SecondaryW16:
|
|||
|
cache CREATE_DIRTY_EXCLUSIVE_SD,0(t0) // create cache block
|
|||
|
sdc1 f0,0(t0) // store double word
|
|||
|
sdc1 f0,8(t0) // store double word
|
|||
|
cache HIT_WRITEBACK_INVALIDATE_SD,0(t0) // Flush cache block
|
|||
|
bne t0,t9,SecondaryW16 // if ne, more data to zero
|
|||
|
addiu t0,t0,16
|
|||
|
j ra
|
|||
|
nop
|
|||
|
|
|||
|
.end WildZeroMemory
|
|||
|
|
|||
|
#endif
|
|||
|
|