Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:51

0001 /*
0002 
0003 Based upon IDT provided code with the following release:
0004 
0005 This source code has been made available to you by IDT on an AS-IS
0006 basis. Anyone receiving this source is licensed under IDT copyrights
0007 to use it in any way he or she deems fit, including copying it,
0008 modifying it, compiling it, and redistributing it either with or
0009 without modifications.  No license under IDT patents or patent
0010 applications is to be implied by the copyright license.
0011 
0012 Any user of this software should understand that IDT cannot provide
0013 technical support for this software and will not be responsible for
0014 any consequences resulting from the use of this software.
0015 
0016 Any person who transfers this source code or any derivative work must
0017 include the IDT copyright notice, this paragraph, and the preceeding
0018 two paragraphs in the transferred software.
0019 
0020 COPYRIGHT IDT CORPORATION 1996
0021 LICENSED MATERIAL - PROGRAM PROPERTY OF IDT
0022 
0023 */
0024 
0025 /************************************************************************
0026 **
0027 **  idtmem.s - memory and cache functions
0028 **
0029 **  Copyright 1991 Integrated Device Technology, Inc.
0030 **  All Rights Reserved
0031 **
0032 **************************************************************************/
0033 
0034 /*
0035  * 950313: Ketan fixed bugs in mfc0/mtc0 hazards, and removed hack
0036  * to set mem_size.
0037  */
0038 
0039 #include <rtems/mips/iregdef.h>
0040 #include <rtems/mips/idtcpu.h>
0041 #include <rtems/asm.h>
0042 
0043     .data
0044 mem_size:
0045     .word   0
0046 dcache_size:
0047     .word   0
0048 icache_size:
0049 #if __mips == 1
0050     .word   MINCACHE
0051 #endif
0052 #if __mips == 3
0053     .word   0
0054 #endif
0055 
0056 #if __mips == 3
0057     .data
0058 scache_size:
0059     .word   0
0060 icache_linesize:
0061     .word   0
0062 dcache_linesize:
0063     .word   0
0064 scache_linesize:
0065     .word   0
0066 #endif
0067 
0068         .text
0069 
0070 #if __mips == 1
0071 #define CONFIGFRM ((2*4)+4)
0072 
0073 /*************************************************************************
0074 **
0075 ** Config_Dcache() -- determine size of Data cache
0076 **
0077 **************************************************************************/
0078 
0079 FRAME(config_Dcache,sp, CONFIGFRM, ra)
0080     .set    noreorder
0081     subu    sp,CONFIGFRM
0082     sw  ra,CONFIGFRM-4(sp)  /* save return address */
0083     sw  s0,4*4(sp)      /* save s0 in first regsave slot */
0084     mfc0    s0,C0_SR        /* save SR */
0085     nop
0086     mtc0    zero,C0_SR      /* disable interrupts */
0087     .set    reorder
0088     jal _size_cache     /* returns Data cache size in v0 */
0089     sw  v0, dcache_size     /* save it */
0090     and     s0, ~SR_PE      /* do not clear PE */
0091     .set    noreorder
0092     mtc0    s0,C0_SR        /* restore SR */
0093     nop
0094     .set    reorder
0095     lw  s0, 4*4(sp)     /* restore s0 */
0096     lw  ra,CONFIGFRM-4(sp)  /* restore ra */
0097     addu    sp,CONFIGFRM        /* pop stack */
0098     j   ra
0099 ENDFRAME(config_Dcache)
0100 
0101 /*************************************************************************
0102 **
0103 ** Config_Icache() -- determine size of Instruction cache
0104 **            MUST be run in uncached mode/handled in idt_csu.s
0105 **
0106 **************************************************************************/
0107 
0108 FRAME(config_Icache,sp, CONFIGFRM, ra)
0109     .set    noreorder
0110     subu    sp,CONFIGFRM
0111     sw  ra,CONFIGFRM-4(sp)  /* save return address */
0112     sw  s0,4*4(sp)      /* save s0 in first regsave slot */
0113     mfc0    s0,C0_SR        /* save SR */
0114     nop
0115     mtc0    zero, C0_SR     /* disable interrupts */
0116     li  v0,SR_SWC       /* swap caches/disable ints  */
0117     mtc0    v0,C0_SR
0118     nop
0119     .set    reorder
0120     jal _size_cache     /* returns instruction cache size */
0121     .set    noreorder
0122     mtc0    zero,C0_SR      /* swap back caches */
0123     nop
0124     and s0,~SR_PE       /* do not inadvertantly clear PE */
0125     mtc0    s0,C0_SR        /* restore SR */
0126     nop
0127     .set    reorder
0128     sw  v0, icache_size     /* save it AFTER caches back */
0129     lw  s0,4*4(sp)      /* restore s0 */
0130     lw  ra,CONFIGFRM-4(sp)  /* restore ra */
0131     addu    sp,CONFIGFRM        /* pop stack */
0132     j   ra
0133 ENDFRAME(config_Icache)
0134 
0135 /************************************************************************
0136 **
0137 ** _size_cache()
0138 ** returns cache size in v0
0139 **
0140 ************************************************************************/
0141 
0142 FRAME(_size_cache,sp,0,ra)
0143     .set    noreorder
0144     mfc0    t0,C0_SR        /* save current sr */
0145     nop
0146     and t0,~SR_PE       /* do not inadvertently clear PE */
0147     or  v0,t0,SR_ISC        /* isolate cache */
0148     mtc0    v0,C0_SR
0149     /*
0150      * First check if there is a cache there at all
0151      */
0152     move    v0,zero
0153     li  v1,0xa5a5a5a5       /* distinctive pattern */
0154     sw  v1,K0BASE       /* try to write into cache */
0155     lw  t1,K0BASE       /* try to read from cache */
0156     nop
0157     mfc0    t2,C0_SR
0158     nop
0159     .set    reorder
0160     and t2,SR_CM
0161     bne t2,zero,3f      /* cache miss, must be no cache */
0162     bne v1,t1,3f        /* data not equal -> no cache */
0163     /*
0164      * Clear cache size boundries to known state.
0165      */
0166     li  v0,MINCACHE
0167 1:
0168     sw  zero,K0BASE(v0)
0169     sll v0,1
0170     ble v0,MAXCACHE,1b
0171 
0172     li  v0,-1
0173     sw  v0,K0BASE(zero)     /* store marker in cache */
0174     li  v0,MINCACHE     /* MIN cache size */
0175 
0176 2:  lw  v1,K0BASE(v0)       /* Look for marker */
0177     bne v1,zero,3f      /* found marker */
0178     sll v0,1            /* cache size * 2 */
0179     ble v0,MAXCACHE,2b      /* keep looking */
0180     move    v0,zero         /* must be no cache */
0181     .set    noreorder
0182 3:  mtc0    t0,C0_SR        /* restore sr */
0183     j   ra
0184     nop
0185 ENDFRAME(_size_cache)
0186     .set    reorder
0187 
0188 #define FLUSHFRM (2*4)
0189 
0190 /***************************************************************************
0191 **
0192 ** flush_Dcache() -  flush entire Data cache
0193 **
0194 ****************************************************************************/
0195 FRAME(flush_Dcache,sp,FLUSHFRM,ra)
0196     lw      t2, dcache_size
0197     .set    noreorder
0198     mfc0    t3,C0_SR        /* save SR */
0199     nop
0200     and t3,~SR_PE       /* dont inadvertently clear PE */
0201     beq t2,zero,_Dflush_done    /* no D cache, get out! */
0202     nop
0203     li  v0, SR_ISC      /* isolate cache */
0204     mtc0    v0, C0_SR
0205     nop
0206     .set    reorder
0207     li  t0,K0BASE       /* set loop registers  */
0208     or  t1,t0,t2
0209 
0210 2:  sb  zero,0(t0)
0211     sb  zero,4(t0)
0212     sb  zero,8(t0)
0213     sb  zero,12(t0)
0214     sb  zero,16(t0)
0215     sb  zero,20(t0)
0216     sb  zero,24(t0)
0217     addu    t0,32
0218     sb  zero,-4(t0)
0219     bne t0,t1,2b
0220 
0221     .set    noreorder
0222 _Dflush_done:
0223     mtc0    t3,C0_SR        /* restore Status Register */
0224     .set    reorder
0225     j   ra
0226 ENDFRAME(flush_Dcache)
0227 
0228 /***************************************************************************
0229 **
0230 ** flush_Icache() -  flush entire Instruction cache
0231 **
0232 **  NOTE: Icache can only be flushed/cleared when uncached
0233 **        Code forces into uncached memory regardless of calling mode
0234 **
0235 ****************************************************************************/
0236 FRAME(flush_Icache,sp,FLUSHFRM,ra)
0237     lw  t1,icache_size
0238     .set    noreorder
0239     mfc0    t3,C0_SR        /* save SR */
0240     nop
0241     la  v0,1f
0242     li  v1,K1BASE
0243     or  v0,v1
0244     j   v0          /* force into non-cached space */
0245     nop
0246 1:
0247     and t3,~SR_PE       /* dont inadvertently clear PE */
0248     beq t1,zero,_Iflush_done    /* no i-cache get out */
0249     nop
0250     li  v0,SR_ISC|SR_SWC    /* disable intr, isolate and swap */
0251     mtc0    v0,C0_SR
0252     li  t0,K0BASE
0253     .set    reorder
0254     or  t1,t0,t1
0255 
0256 1:  sb  zero,0(t0)
0257     sb  zero,4(t0)
0258     sb  zero,8(t0)
0259     sb  zero,12(t0)
0260     sb  zero,16(t0)
0261     sb  zero,20(t0)
0262     sb  zero,24(t0)
0263     addu    t0,32
0264     sb  zero,-4(t0)
0265     bne t0,t1,1b
0266     .set    noreorder
0267 _Iflush_done:
0268     mtc0    t3,C0_SR        /* un-isolate, enable interrupts */
0269     .set    reorder
0270     j   ra
0271 ENDFRAME(flush_Icache)
0272 
0273 /**************************************************************************
0274 **
0275 ** clear_Dcache(base_addr, byte_count) - flush portion of Data cache
0276 **
0277 **      a0 = base address of portion to be cleared
0278 **      a1 = byte count of length
0279 **
0280 ***************************************************************************/
0281 FRAME(clear_Dcache,sp,0,ra)
0282 
0283     lw      t2, dcache_size     /* Data cache size */
0284     .set    noreorder
0285     mfc0    t3,C0_SR        /* save SR */
0286     nop
0287     and t3,~SR_PE       /* dont inadvertently clear PE */
0288     nop
0289     nop
0290     .set    reorder
0291     /*
0292      * flush data cache
0293      */
0294 
0295     .set    noreorder
0296     nop
0297     li  v0,SR_ISC       /* isolate data cache */
0298     mtc0    v0,C0_SR
0299     .set    reorder
0300     bltu    t2,a1,1f        /* cache is smaller than region */
0301     move    t2,a1
0302 1:  addu    t2,a0           /* ending address + 1 */
0303     move    t0,a0
0304 
0305 1:  sb  zero,0(t0)
0306     sb  zero,4(t0)
0307     sb  zero,8(t0)
0308     sb  zero,12(t0)
0309     sb  zero,16(t0)
0310     sb  zero,20(t0)
0311     sb  zero,24(t0)
0312     addu    t0,32
0313     sb  zero,-4(t0)
0314     bltu    t0,t2,1b
0315 
0316     .set    noreorder
0317     mtc0    t3,C0_SR        /* un-isolate, enable interrupts */
0318     nop
0319     .set    reorder
0320     j   ra
0321 ENDFRAME(clear_Dcache)
0322 
0323 /**************************************************************************
0324 **
0325 ** clear_Icache(base_addr, byte_count) - flush portion of Instruction cache
0326 **
0327 **      a0 = base address of portion to be cleared
0328 **      a1 = byte count of length
0329 **
0330 **  NOTE: Icache can only be flushed/cleared when uncached
0331 **        Code forces into uncached memory regardless of calling mode
0332 **
0333 ***************************************************************************/
0334 FRAME(clear_Icache,sp,0,ra)
0335 
0336     lw      t1, icache_size     /* Instruction cache size */
0337     /*
0338      * flush text cache
0339      */
0340     .set    noreorder
0341     mfc0    t3,C0_SR        /* save SR */
0342     nop
0343     la  v0,1f
0344     li  v1,K1BASE
0345     or  v0,v1
0346     j   v0          /* force into non-cached space */
0347     nop
0348 1:
0349     and t3,~SR_PE       /* dont inadvertently clear PE */
0350     nop
0351     nop
0352     li  v0,SR_ISC|SR_SWC    /* disable intr, isolate and swap */
0353     mtc0    v0,C0_SR
0354     .set    reorder
0355     bltu    t1,a1,1f        /* cache is smaller than region */
0356     move    t1,a1
0357 1:  addu    t1,a0           /* ending address + 1 */
0358     move    t0,a0
0359 
0360     sb  zero,0(t0)
0361     sb  zero,4(t0)
0362     sb  zero,8(t0)
0363     sb  zero,12(t0)
0364     sb  zero,16(t0)
0365     sb  zero,20(t0)
0366     sb  zero,24(t0)
0367     addu    t0,32
0368     sb  zero,-4(t0)
0369     bltu    t0,t1,1b
0370     .set    noreorder
0371     mtc0    t3,C0_SR        /* un-isolate, enable interrupts */
0372     nop
0373     nop
0374     nop             /* allow time for caches to swap */
0375     .set    reorder
0376     j   ra
0377 ENDFRAME(clear_Icache)
0378 
0379 /**************************************************************************
0380 **
0381 **  get_mem_conf - get memory configuration
0382 **
0383 ***************************************************************************/
0384 
0385 FRAME(get_mem_conf,sp,0,ra)
0386 
0387     lw  t6, mem_size
0388     sw  t6, 0(a0)
0389     lw  t7, icache_size
0390     sw  t7, 4(a0)
0391     lw  t8, dcache_size
0392     sw  t8, 8(a0)
0393     j   ra
0394 
0395 ENDFRAME(get_mem_conf)
0396 #endif /* __mips == 1 */
0397 
0398 #if __mips == 3
0399 #define LEAF(label) FRAME(label,sp,0,ra)
0400 #define XLEAF(label) \
0401     .globl label ; \
0402 label:
0403 
0404 /*
0405  * cacheop macro to automate cache operations
0406  * first some helpers...
0407  */
0408 #define _mincache(size, maxsize) \
0409     bltu    size,maxsize,8f ;   \
0410     move    size,maxsize ;      \
0411 8:
0412 
0413 #define _align(tmp, minaddr, maxaddr, linesize) \
0414     subu    tmp,linesize,1 ;    \
0415     not tmp ;           \
0416     and minaddr,tmp ;       \
0417     addu    maxaddr,-1 ;        \
0418     and maxaddr,tmp
0419 
0420 /* This is a bit of a hack really because it relies on minaddr=a0 */
0421 #define _doop1(op1) \
0422     cache   op1,0(a0)
0423 
0424 #define _doop2(op1, op2) \
0425     cache   op1,0(a0) ;     \
0426     cache   op2,0(a0)
0427 
0428 /* specials for cache initialisation */
0429 #define _doop1lw1(op1) \
0430     cache   op1,0(a0) ;     \
0431     lw  zero,0(a0) ;        \
0432     cache   op1,0(a0)
0433 
0434 #define _doop121(op1,op2) \
0435     cache   op1,0(a0) ;     \
0436     nop;                \
0437     cache   op2,0(a0) ;     \
0438     nop;                \
0439     cache   op1,0(a0)
0440 
0441 #define _oploopn(minaddr, maxaddr, linesize, tag, ops) \
0442     .set    noreorder ;     \
0443 7:  _doop##tag##ops ;       \
0444     bne     minaddr,maxaddr,7b ;    \
0445     addu    minaddr,linesize ;  \
0446     .set    reorder
0447 
0448 /* finally the cache operation macros */
0449 #define icacheopn(kva, n, cache_size, cache_linesize, tag, ops) \
0450     _mincache(n, cache_size);   \
0451     blez    n,9f ;          \
0452     addu    n,kva ;         \
0453     _align(t1, kva, n, cache_linesize) ; \
0454     _oploopn(kva, n, cache_linesize, tag, ops) ; \
0455 9:
0456 
0457 #define vcacheopn(kva, n, cache_size, cache_linesize, tag, ops) \
0458     blez    n,9f ;          \
0459     addu    n,kva ;         \
0460     _align(t1, kva, n, cache_linesize) ; \
0461     _oploopn(kva, n, cache_linesize, tag, ops) ; \
0462 9:
0463 
0464 #define icacheop(kva, n, cache_size, cache_linesize, op) \
0465     icacheopn(kva, n, cache_size, cache_linesize, 1, (op))
0466 
0467 #define vcacheop(kva, n, cache_size, cache_linesize, op) \
0468     vcacheopn(kva, n, cache_size, cache_linesize, 1, (op))
0469 
0470     .text
0471 
0472 /*
0473  * static void _size_cache()    R4000
0474  *
0475  * Internal routine to determine cache sizes by looking at R4000 config
0476  * register.  Sizes are returned in registers, as follows:
0477  *  t2  icache size
0478  *  t3  dcache size
0479  *  t6  scache size
0480  *  t4  icache line size
0481  *  t5  dcache line size
0482  *  t7  scache line size
0483  */
0484 LEAF(_size_cache)
0485     mfc0    t0,C0_CONFIG
0486 
0487     and t1,t0,CFG_ICMASK
0488     srl t1,CFG_ICSHIFT
0489     li  t2,0x1000
0490     sll t2,t1
0491 
0492     and t1,t0,CFG_DCMASK
0493     srl t1,CFG_DCSHIFT
0494     li  t3,0x1000
0495     sll t3,t1
0496 
0497     li  t4,32
0498     and t1,t0,CFG_IB
0499     bnez    t1,1f
0500     li  t4,16
0501 1:
0502 
0503     li  t5,32
0504     and t1,t0,CFG_DB
0505     bnez    t1,1f
0506     li  t5,16
0507 1:
0508 
0509     move    t6,zero         # default to no scache
0510     move    t7,zero         #
0511 
0512     and t1,t0,CFG_C_UNCACHED    # test config register
0513     bnez    t1,1f           # no scache if uncached/non-coherent
0514 
0515     li  t6,0x100000     # assume 1Mb scache <<-NOTE
0516     and t1,t0,CFG_SBMASK
0517     srl t1,CFG_SBSHIFT
0518     li  t7,16
0519     sll t7,t1
0520 1:  j   ra
0521 ENDFRAME(_size_cache)
0522 
0523 /*
0524  * void config_cache()   R4000
0525  *
0526  * Work out size of I, D & S caches, assuming they are already initialised.
0527  */
0528 LEAF(config_cache)
0529     lw  t0,icache_size
0530     bgtz    t0,8f           # already known?
0531     move    v0,ra
0532     bal _size_cache
0533     move    ra,v0
0534 
0535     sw  t2,icache_size
0536     sw  t3,dcache_size
0537     sw  t6,scache_size
0538     sw  t4,icache_linesize
0539     sw  t5,dcache_linesize
0540     sw  t7,scache_linesize
0541 8:  j   ra
0542 ENDFRAME(config_cache)
0543 
0544 /*
0545  * void _init_cache()   R4000
0546  */
0547 LEAF(_init_cache)
0548     /*
0549      * First work out the sizes
0550      */
0551     move    v0,ra
0552     bal _size_cache
0553     move    ra,v0
0554 
0555     /*
0556      * The caches may be in an indeterminate state,
0557      * so we force good parity into them by doing an
0558      * invalidate, load/fill, invalidate for each line.
0559      */
0560 
0561     /* disable all i/u and cache exceptions */
0562     mfc0    v0,C0_SR
0563     and v1,v0,~SR_IE
0564     or  v1,SR_DE
0565     mtc0    v1,C0_SR
0566 
0567     mtc0    zero,C0_TAGLO
0568     mtc0    zero,C0_TAGHI
0569 
0570     /* assume bottom of RAM will generate good parity for the cache */
0571     li  a0,PHYS_TO_K0(0)
0572     move    a2,t2       # icache_size
0573     move    a3,t4       # icache_linesize
0574     move    a1,a2
0575     icacheopn(a0,a1,a2,a3,121,(Index_Store_Tag_I,Fill_I))
0576 
0577     li  a0,PHYS_TO_K0(0)
0578     move    a2,t3       # dcache_size
0579     move    a3,t5       # dcache_linesize
0580     move    a1,a2
0581     icacheopn(a0,a1,a2,a3,1lw1,(Index_Store_Tag_D))
0582 
0583     /* assume unified I & D in scache <<-NOTE */
0584     blez    t6,1f
0585     li  a0,PHYS_TO_K0(0)
0586     move    a2,t6
0587     move    a3,t7
0588     move    a1,a2
0589     icacheopn(a0,a1,a2,a3,1lw1,(Index_Store_Tag_SD))
0590 
0591 1:  mtc0    v0,C0_SR
0592     j   ra
0593 ENDFRAME(_init_cache)
0594 
0595 /*
0596  * void flush_cache (void)   R4000
0597  *
0598  * Flush and invalidate all caches
0599  */
0600 LEAF(flush_cache)
0601     /* secondary cacheops do all the work if present */
0602     lw  a2,scache_size
0603     blez    a2,1f
0604     lw  a3,scache_linesize
0605     li  a0,PHYS_TO_K0(0)
0606     move    a1,a2
0607     icacheop(a0,a1,a2,a3,Index_Writeback_Inv_SD)
0608     b   2f
0609 
0610 1:
0611     lw  a2,icache_size
0612     blez    a2,2f
0613     lw  a3,icache_linesize
0614     li  a0,PHYS_TO_K0(0)
0615     move    a1,a2
0616     icacheop(a0,a1,a2,a3,Index_Invalidate_I)
0617 
0618     lw  a2,dcache_size
0619     lw  a3,dcache_linesize
0620     li  a0,PHYS_TO_K0(0)
0621     move    a1,a2
0622     icacheop(a0,a1,a2,a3,Index_Writeback_Inv_D)
0623 
0624 2:  j   ra
0625 ENDFRAME(flush_cache)
0626 
0627 /*
0628  * void flush_cache_nowrite (void)   R4000
0629  *
0630  * Invalidate all caches
0631  */
0632 LEAF(flush_cache_nowrite)
0633     mfc0    v0,C0_SR
0634     and v1,v0,~SR_IE
0635     mtc0    v1,C0_SR
0636 
0637     mtc0    zero,C0_TAGLO
0638     mtc0    zero,C0_TAGHI
0639 
0640     lw  a2,icache_size
0641     blez    a2,2f
0642     lw  a3,icache_linesize
0643     li  a0,PHYS_TO_K0(0)
0644     move    a1,a2
0645     icacheop(a0,a1,a2,a3,Index_Invalidate_I)
0646 
0647     lw  a2,dcache_size
0648     lw  a3,dcache_linesize
0649     li  a0,PHYS_TO_K0(0)
0650     move    a1,a2
0651     icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
0652 
0653     lw  a2,scache_size
0654     blez    a2,2f
0655     lw  a3,scache_linesize
0656     li  a0,PHYS_TO_K0(0)
0657     move    a1,a2
0658     icacheop(a0,a1,a2,a3,Index_Store_Tag_SD)
0659 
0660 2:  mtc0    v0,C0_SR
0661     j   ra
0662 ENDFRAME(flush_cache_nowrite)
0663 
0664 /*
0665  * void clean_cache (unsigned kva, size_t n)   R4000
0666  *
0667  * Writeback and invalidate address range in all caches
0668  */
0669 LEAF(clean_cache)
0670 XLEAF(clear_cache)
0671 
0672     /* secondary cacheops do all the work (if fitted) */
0673     lw  a2,scache_size
0674     blez    a2,1f
0675     lw  a3,scache_linesize
0676     vcacheop(a0,a1,a2,a3,Hit_Writeback_Inv_SD)
0677     b   2f
0678 
0679 1:  lw  a2,icache_size
0680     blez    a2,2f
0681     lw  a3,icache_linesize
0682     /* save kva & n for subsequent loop */
0683     move    t8,a0
0684     move    t9,a1
0685     vcacheop(a0,a1,a2,a3,Hit_Invalidate_I)
0686 
0687     lw  a2,dcache_size
0688     lw  a3,dcache_linesize
0689     /* restore kva & n */
0690     move    a0,t8
0691     move    a1,t9
0692     vcacheop(a0,a1,a2,a3,Hit_Writeback_Inv_D)
0693 
0694 2:  j   ra
0695 ENDFRAME(clean_cache)
0696 
0697 /*
0698  * void clean_dcache (unsigned kva, size_t n)   R4000
0699  *
0700  * Writeback and invalidate address range in primary data cache
0701  */
0702 LEAF(clean_dcache)
0703     lw  a2,dcache_size
0704     blez    a2,2f
0705     lw  a3,dcache_linesize
0706 
0707     vcacheop(a0,a1,a2,a3,Hit_Writeback_Inv_D)
0708 
0709 2:  j   ra
0710 ENDFRAME(clean_dcache)
0711 
0712 /*
0713  * void clean_dcache_indexed (unsigned kva, size_t n)   R4000
0714  *
0715  * Writeback and invalidate indexed range in primary data cache
0716  */
0717 LEAF(clean_dcache_indexed)
0718     lw  a2,dcache_size
0719     blez    a2,2f
0720     lw  a3,dcache_linesize
0721 
0722 #ifdef CPU_ORION
0723     srl a2,1            # do one set (half cache) at a time
0724     move    t8,a0           # save kva & n
0725     move    t9,a1
0726     icacheop(a0,a1,a2,a3,Index_Writeback_Inv_D)
0727 
0728     addu    a0,t8,a2        # do next set
0729     move    a1,t9           # restore n
0730 #endif
0731     icacheop(a0,a1,a2,a3,Index_Writeback_Inv_D)
0732 
0733 2:  j   ra
0734 ENDFRAME(clean_dcache_indexed)
0735 
0736 /*
0737  * void clean_dcache_nowrite (unsigned kva, size_t n)   R4000
0738  *
0739  * Invalidate an address range in primary data cache
0740  */
0741 LEAF(clean_dcache_nowrite)
0742     lw  a2,dcache_size
0743     blez    a2,2f
0744     lw  a3,dcache_linesize
0745 
0746     vcacheop(a0,a1,a2,a3,Hit_Invalidate_D)
0747 
0748 2:  j   ra
0749 ENDFRAME(clean_dcache_nowrite)
0750 
0751 /*
0752  * void clean_dcache_nowrite_indexed (unsigned kva, size_t n)   R4000
0753  *
0754  * Invalidate indexed range in primary data cache
0755  */
0756 LEAF(clean_dcache_nowrite_indexed)
0757     mfc0    v0,C0_SR
0758     and v1,v0,~SR_IE
0759     mtc0    v1,C0_SR
0760 
0761     mtc0    zero,C0_TAGLO
0762     mtc0    zero,C0_TAGHI
0763 
0764     lw  a2,dcache_size
0765     blez    a2,2f
0766     lw  a3,dcache_linesize
0767 
0768 #ifdef CPU_ORION
0769     srl a2,1            # do one set (half cache) at a time
0770     move    t8,a0           # save kva & n
0771     move    t9,a1
0772     icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
0773 
0774     addu    a0,t8,a2        # do next set
0775     move    a1,t9           # restore n
0776 #endif
0777     icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
0778 
0779 2:  mtc0    v0,C0_SR
0780     j   ra
0781 ENDFRAME(clean_dcache_nowrite_indexed)
0782 
0783 /*
0784  * void clean_icache (unsigned kva, size_t n)   R4000
0785  *
0786  * Invalidate address range in primary instruction cache
0787  */
0788 LEAF(clean_icache)
0789     lw  a2,icache_size
0790     blez    a2,2f
0791     lw  a3,icache_linesize
0792 
0793     vcacheop(a0,a1,a2,a3,Hit_Invalidate_I)
0794 
0795 2:  j   ra
0796 ENDFRAME(clean_icache)
0797 
0798 /*
0799  * void clean_icache_indexed (unsigned kva, size_t n)   R4000
0800  *
0801  * Invalidate indexed range in primary instruction cache
0802  */
0803 LEAF(clean_icache_indexed)
0804     lw  a2,icache_size
0805     blez    a2,2f
0806     lw  a3,icache_linesize
0807 
0808 #ifdef CPU_ORION
0809     srl a2,1            # do one set (half cache) at a time
0810     move    t8,a0           # save kva & n
0811     move    t9,a1
0812     icacheop(a0,a1,a2,a3,Index_Invalidate_I)
0813 
0814     addu    a0,t8,a2        # do next set
0815     move    a1,t9           # restore n
0816 #endif
0817     icacheop(a0,a1,a2,a3,Index_Invalidate_I)
0818 
0819 2:  j   ra
0820 ENDFRAME(clean_icache_indexed)
0821 
0822 /*
0823  * void clean_scache (unsigned kva, size_t n)   R4000
0824  *
0825  * Writeback and invalidate address range in secondary cache
0826  */
0827 LEAF(clean_scache)
0828     lw  a2,scache_size
0829     blez    a2,2f
0830     lw  a3,scache_linesize
0831     vcacheop(a0,a1,a2,a3,Hit_Writeback_Inv_SD)
0832 
0833 2:  j   ra
0834 ENDFRAME(clean_scache)
0835 
0836 /*
0837  * void clean_scache_indexed (unsigned kva, size_t n)   R4000
0838  *
0839  * Writeback and invalidate indexed range in secondary cache
0840  */
0841 LEAF(clean_scache_indexed)
0842     lw  a2,scache_size
0843     blez    a2,2f
0844     lw  a3,scache_linesize
0845 
0846     icacheop(a0,a1,a2,a3,Index_Writeback_Inv_SD)
0847 
0848 2:  j   ra
0849 ENDFRAME(clean_scache_indexed)
0850 
0851 /*
0852  * void clean_scache_nowrite (unsigned kva, size_t n)   R4000
0853  *
0854  * Invalidate an address range in secondary cache
0855  */
0856 LEAF(clean_scache_nowrite)
0857     lw  a2,scache_size
0858     blez    a2,2f
0859     lw  a3,scache_linesize
0860 
0861     vcacheop(a0,a1,a2,a3,Hit_Invalidate_SD)
0862 
0863 2:  j   ra
0864 ENDFRAME(clean_scache_nowrite)
0865 
0866 /*
0867  * void clean_scache_nowrite_indexed (unsigned kva, size_t n)   R4000
0868  *
0869  * Invalidate indexed range in secondary cache
0870  */
0871 LEAF(clean_scache_nowrite_indexed)
0872     mfc0    v0,C0_SR
0873     and v1,v0,~SR_IE
0874     mtc0    v1,C0_SR
0875 
0876     mtc0    zero,C0_TAGLO
0877     mtc0    zero,C0_TAGHI
0878 
0879     lw  a2,scache_size
0880     blez    a2,2f
0881     lw  a3,scache_linesize
0882 
0883     icacheop(a0,a1,a2,a3,Index_Store_Tag_SD)
0884 
0885 2:  mtc0    v0,C0_SR
0886     j   ra
0887 ENDFRAME(clean_scache_nowrite_indexed)
0888 
0889 /**************************************************************************
0890 **
0891 **  get_mem_conf - get memory configuration  R4000
0892 **
0893 ***************************************************************************/
0894 
0895 FRAME(get_mem_conf,sp,0,ra)
0896 
0897     lw  t6, mem_size
0898     sw  t6, 0(a0)
0899     lw  t7, icache_size
0900     sw  t7, 4(a0)
0901     lw  t8, dcache_size
0902     sw  t8, 8(a0)
0903     lw  t7, scache_size
0904     sw  t7, 12(a0)
0905     j   ra
0906 
0907 ENDFRAME(get_mem_conf)
0908 
0909 #endif /* __mips == 3 */
0910 
0911 /*
0912  * void set_mem_size (mem_size)
0913  *
0914  * config_memory()'s memory size gets written into mem_size here.
0915  * Now we don't need to call config_cache() with memory size - New to IDTC6.0
0916  */
0917 FRAME(set_memory_size,sp,0,ra)
0918     sw  a0, mem_size
0919     j   ra
0920 ENDFRAME(set_memory_size)