Files
seta75D 2e8a93c394 Init
2021-10-11 18:20:23 -03:00

219 lines
5.9 KiB
ArmAsm

/* @(#)control.s 1.1 92/07/30 SMI */
/*
* Copyright (c) 1987 by Sun Microsystems, Inc.
*/
/*
* Control space operations for Sun-3 MMU and Virtual Address Cache
*/
#include <sys/param.h>
#include <machine/asm_linkage.h>
#include <machine/mmu.h>
#include "assym.s"
.text
| Get/Set control space data
| u_int
| sun_getcontrol_{byte,long}(space, addr)
| u_int space; /* Control space entry desired */
| addr_t addr; /* Address in that space to get */
#define space sp@(4)
#define addr sp@(8)
ENTRY(sun_getcontrol_byte)
movl addr,d0 | Obtain address
andl #CONTROL_MASK,d0 | Mask off bits
orl space,d0 | Merge control space target
movl d0,a0 | Use as address
moveq #0,d0 | Zero return register
movsb a0@,d0 | to get return value
rts
ENTRY(sun_getcontrol_long)
movl addr,d0 | Obtain address
andl #CONTROL_MASK,d0 | Mask off bits/Get long-word alignment
orl space,d0 | Merge control space target
movl d0,a0 | Use as address
movsl a0@,d0 | to get return value
rts
#undef space
#undef addr
| void
| sun_setcontrol_{byte,long}(space, addr, value)
| u_int space; /* Control space area to set */
| addr_t addr; /* Address within area to set */
| u_int value; /* Value to set */
#define space sp@(4)
#define addr sp@(8)
#define value sp@(12)
ENTRY(sun_setcontrol_byte)
movl addr,d0 | Get address to set
andl #CONTROL_MASK,d0 | Mask off bits
orl space,d0 | Merge control space
movl d0,a0 | Set up for use as address
movl value,d0 | Obtain value
movsb d0,a0@ | Set byte in control space
rts
ENTRY(sun_setcontrol_long)
movl addr,d0 | Get address to set
andl #CONTROL_MASK,d0 | Mask off bits/Get long-word alignment
orl space,d0 | Merge control space
movl d0,a0 | Set up for use as address
movl value,d0 | Obtain value
movsl d0,a0@ | Set longword in control space
rts
#undef space
#undef addr
#undef value
#ifdef VAC
| Init the VAC by invaliding all cache tags.
| We loop through all 64KB to reset the valid bit of each line.
| It DOESN'T turn on cache enable bit in the enable register.
|
| void
| vac_init()
ENTRY(vac_init)
movl #VAC_RWTAG_BASE,a0 | Init base address to R/W VAC tags
movl #VAC_RWTAG_COUNT-1,d0 | Init loop counter to line count
clrl d1 | Value of zero will reset valid bit
0: movsl d1,a0@ | Invalidate this line's tag
addl #VAC_RWTAG_INCRMNT,a0 | Step address and
dbra d0,0b | continue over loop
rts
| VAC (Virtual Address Cache) Flush by Context Match:
| We issue the context flush command VAC_CTXFLUSH_COUNT times.
| Each time we increment flush address by VAC_FLUSH_INCRMNT(2^9).
| Context no. is in the context register.
|
| void
| vac_ctxflush()
ENTRY(vac_ctxflush)
tstl _vac | VAC?
jeq 1f | No
addql #1,_flush_cnt+FM_CTX | Increment statistics
movl #VAC_FLUSH_BASE,a0 | Get flush base initializer
movl #VAC_CTXFLUSH_COUNT-1,d0 | and count of flushes to perform
movb #VAC_CTXFLUSH,d1 | and command to do it
0: movsb d1,a0@ | Do a unit of context flush
addl #VAC_FLUSH_INCRMNT,a0 | Add loop increment
dbra d0,0b | Continue over loop
1: rts
| VAC (Virtual Address Cache) Flush by Segment Match.
| We issue the segment flush command VAC_SEGFLUSH_COUNT times.
| Each time we increment flush address by VAC_FLUSH_INCRMNT(2^9).
|
| void
| vac_segflush(v)
| addr_t v; /* Segment number */
#define v sp@(4)
ENTRY(vac_segflush)
tstl _vac | VAC?
jeq 1f | No
addql #1,_flush_cnt+FM_SEGMENT | Take statistics
movl v,d0 | Get segment virtual address
andl #VAC_SEGMASK,d0 | Mask off segment bits
orl #VAC_FLUSH_BASE,d0 | Turn into control space address
movl d0,a0 | Use value as address
movl #VAC_SEGFLUSH_COUNT-1,d0 | Loop this many of times
movb #VAC_SEGFLUSH,d1 | Get segment flush "command"
0:
movsb d1,a0@ | Do a unit of segment flush
addl #VAC_FLUSH_INCRMNT,a0 | The address of next segment flush
dbra d0,0b | Continue over loop
1:
rts
#undef v
| VAC (Virtual Address Cache) Flush by Page Match
| We issue the page flush command VAC_PAGEFLUSH_COUNT times,
| Each time we increment flush address by VAC_FLUSH_INCRMNT(2^9).
|
| void
| vac_pageflush(vaddr)
| caddr_t v; /* Address of page to be flushed */
#define v sp@(4)
ENTRY(vac_pageflush)
tstl _vac | VAC?
jeq 1f | No
addql #1,_flush_cnt+FM_PAGE | Increment statistics
movl v,d0 | Get flush address
andl #VAC_PAGEMASK,d0 | Mask off page bits
orl #VAC_FLUSH_BASE,d0 | And set base address in control space
movl d0,a0 | Use as an address
moveq #VAC_PAGEFLUSH_COUNT-1,d0| Initialize loop count
movb #VAC_PAGEFLUSH,d1 | Initialize flush "command"
0:
movsb d1,a0@ | Do a unit of page flush
addl #VAC_FLUSH_INCRMNT,a0 | Step to next address
dbra d0,0b | and continue over loop
1:
rts
#undef v
| Flush-by-Page-Match nbytes of bytes starting from vaddr.
| We issue Page Match Flush commands until all nbytes
| are flushed. In Sun-3, each time VAC_FLUSH_INCRMNT (512)
| bytes are flushed.
|
| void
| vac_flush(v, nbytes)
| addr_t v; /* Address at which to start flush */
| int nbytes; /* Number of bytes to flush */
#define v sp@(4)
#define nbytes sp@(8)
ENTRY(vac_flush)
tstl _vac | VAC?
jeq 1f | No
addql #1,_flush_cnt+FM_PARTIAL | Bump statistics
movl v,d1 | Obtain base address
andl #VAC_UNIT_MASK,d1 | and find offset into flush unit
movl nbytes,d0 | Get requested byte count
addl d1,d0 | Actual count is unit + request
addl #VAC_FLUSH_INCRMNT-1,d0 | Initialize loop counter
movl #VAC_FLUSH_LOWBIT,d1 | Get (log2) multiplier
lsrl d1,d0 | Compute VAC units to flush
movl v,d1 | Obtain start address again
andl #VAC_UNIT_ADDRBITS,d1 | Mask to start at unit boundary
orl #VAC_FLUSH_BASE,d1 | Set control space address bits
movl d1,a0 | Prepare to use as address
movb #VAC_PAGEFLUSH,d1 | Initialize page flush "command"
jra 3f | enter into dbra loop
2:
movsb d1,a0@ | do a unit of Page Match Flush
addl #VAC_FLUSH_INCRMNT,a0 | address of next Page Match Flush
3:
dbra d0,2b | decr d0, br if d0 >= 0
1:
rts
#undef v
#undef nbytes
#endif VAC