old-cross-binutils/gdb/nlm/alpha-io.S
1994-03-25 01:38:12 +00:00

875 lines
20 KiB
ArmAsm

/*
* Copyright (C) 1993, 1994 by
* Digital Equipment Corporation, Maynard, Massachusetts.
* All rights reserved.
*
* This software is furnished under a license and may be used and copied
* only in accordance of the terms of such license and with the
* inclusion of the above copyright notice. This software or any other
* copies thereof may not be provided or otherwise made available to any
* other person. No title to and ownership of the software is hereby
* transferred.
*
* The information in this software is subject to change without notice
* and should not be construed as a commitment by Digital Equipment
* Corporation.
*
* Digital assumes no responsibility for the use or reliability of its
* software on equipment which is not supplied by Digital.
*
*/
/*#include "kxalpha.h"*/
#include "alpha-regdef.h"
#define LEAF_ENTRY(NAME) .text ; .align 4 ; .globl NAME ; .ent NAME, 0 ; NAME: ; .frame sp, 0, ra ; .prologue 0 ;
#define PICIACKADR 0xfffffc0100000000
#define EISABAD 0xfffffc0200000000
#define EISABIO 0xfffffc0300000000
#define EISA_SHIFT 7
#define EISA_BYTE_ADJ 0x80
#define EISA_WORD_ADJ 0x100
#define EISA_LONG_ADJ 0x200
#define HALF_USEC 75
#define ONE_USEC 150
LEAF_ENTRY(flush_i_cache)
call_pal 0x86 // IMB
ret zero, (ra) // return
.end outportb
//++
//
// VOID
// { outportX
// ULONG port
// ULONG data
// )
// X variants are:
//
// b - byte 8 bits
// w - word 16 bits
// t - tri-byte 24 bits
// l - long 32 bits
//
//
// Routine Description:
//
// This function uses the 64-bit super-page to write data to a port
// of the EISA bus for JENSEN. Only AT (ISA) cycles are supported.
//
// Arguments:
//
// port (a0) - port address on the EISA to which to write data
// data (a1) - data to write to the port.
//
//
// Return Value:
//
// None.
//
//--
//+
// outportb
//--
LEAF_ENTRY(outportb)
//
// generate super-page address of EISA base address
// upper bits must be sign extension of bit 42
// va<42:41> = 10 (binary) for super-page address
//
and a0,3,t0 // get byte index from address
insbl a1,t0,t5 // put byte in proper position
and a0,0x1ffffff,t1 // 25 bit mask
ldiq t0,EISABIO // get EISA IO base address
sll t1, 7, a0 // shift 7 for EISA
bis t0,a0,t0 // t0 = address of EISA
stl t5, 0(t0) // write data to port
mb // guarantee write ordering
ret zero, (ra) // return
.end outportb
//+
// outportw
//--
LEAF_ENTRY(outportw)
//
// generate super-page address of EISA base address
// upper bits must be sign extension of bit 42
// va<42:41> = 10 (binary) for super-page address
//
and a0,3,t0 // get byte index from address
inswl a1,t0,t5 // put byte in proper position
and a0,0x1ffffff,t1 // 25 bit mask
ldiq t0,EISABIO // get EISA IO base address
or t0,0x20,t0 // t0 = ffff fc03 0000 0020 - word
sll t1, 7, a0 // shift 7 for EISA
bis t0,a0,t0 // t0 = address of EISA
stl t5, 0(t0) // write data to port
mb // guarantee write ordering
ret zero, (ra) // return
.end outportw
//+
// outportl
//--
LEAF_ENTRY(outportl)
//
// generate super-page address of EISA base address
// upper bits must be sign extension of bit 42
// va<42:41> = 10 (binary) for super-page address
//
and a0,0x1ffffff,t1 // 25 bit mask
ldiq t0,EISABIO // get EISA IO base address
or t0,0x60,t0 // t0 = ffff fc03 0000 0060 - long
sll t1, 7, a0 // shift 7 for EISA
bis t0,a0,t0 // t0 = address of EISA
stl a1, 0(t0) // write data to port
mb // guarantee write ordering
ret zero, (ra) // return
.end outportl
//+
// vgastl
//--
LEAF_ENTRY(vgastl)
//
// generate super-page address of EISA base address
// upper bits must be sign extension of bit 42
// va<42:41> = 10 (binary) for super-page address
//
sra a0, 3, t0 // right shift addr by 3
and t0, 3, t1 // and addr with 3
s8addq t1, zero, t2 // multiply by 8
sll a1, t2, t3 // left shift data
sll a0, 4, t4 // left shift addr by 4
lda t0,0xfc00 // t0 = 0000 0000 0000 0c00
ldah t0,-1(t0) // t0 = ffff ffff ffff 0c00
sll t0,32,t0 // t0 = ffff fc00 0000 0000
or t0,t4,t4 // make io address
stl t3, 0(t4) // store data
mb // guarantee write ordering
ret zero, (ra) // return
.end vgastl
//++
//
// ULONG
// inportX(
// ULONG port
// )
//
// X variants are:
//
// b - byte 8 bits
// w - word 16 bits
// t - tri-byte 24 bits
// l - long 32 bits
//
// Routine Description:
//
// This function uses the 64-bit super-page to read data from an EISA
// port for JENSEN.
//
// Arguments:
//
// port (a0) - EISA port number.
//
// Return Value:
//
// data (v0) - the data read and only the low byte is valid
//
//--
//+
// inportb
//--
LEAF_ENTRY(inportb)
//
// generate super-page address of EISA, base address
// upper bits must be sign extension of bit 42
// va<42:41> = 10 (binary) for super-page address
//
and a0,0x1ffffff,t1 // 25 bit mask
ldiq t0,EISABIO // get EISA IO base address
sll t1, 7, t2 // shift 7 for EISA
bis t0,t2,t0 // t0 = address of EISA
ldl v0, 0(t0) // get EISA IO byte
and a0,0x3,t1 // setup word shift count
extbl v0,t1,v0 // put into low byte
ret zero, (ra) // return
.end inportb
//+
// inportw
//--
LEAF_ENTRY(inportw)
//
// generate super-page address of vti, base address
// upper bits must be sign extension of bit 42
// va<42:41> = 10 (binary) for super-page address
//
and a0,0x1ffffff,t1 // 25 bit mask
ldiq t0,EISABIO // get EISA IO base addr
or t0,0x20,t0 // t0 = ffff fc03 0000 0020 - word
sll t1, 7, t2 // shift 7 for EISA
bis t0,t2,t0 // t0 = address of EISA
ldl v0, 0(t0) // load EISA word
and a0,0x3,t1 // setup shift count
extwl v0,t1,v0 // put into low word
ret zero, (ra) // return
.end inportw
//+
// inportl
//--
LEAF_ENTRY(inportl)
//
// generate super-page address of vti, base address
// upper bits must be sign extension of bit 42
// va<42:41> = 10 (binary) for super-page address
//
and a0,0x1ffffff,t1 // 25 bit mask
ldiq t0,EISABIO // get EISA IO base address
or t0,0x60,t0 // t0 = ffff fc03 0000 0060
sll t1, 7, t2 // shift 7 for EISA
bis t0,t2,t0 // t0 = address of EISA
ldl v0, 0(t0) // load EISA word
ret zero, (ra) // return
.end inportl
//+
// vgaldl
//--
LEAF_ENTRY(vgaldl)
//
// generate super-page address of EISA base address
// upper bits must be sign extension of bit 42
// va<42:41> = 10 (binary) for super-page address
//
sll a0, 4, t5 // left shift address by 4
lda t0,0xfc00 // t0 = 0000 0000 0000 fc00
ldah t0,-1(t0) // t0 = ffff ffff ffff fc00
sll t0,32,t0 // t0 = ffff fc00 0000 0000
or t0,t5,t0 // make io address
ldl t4, 0(t0) // load data
sra a0, 3, t1 // right shift addr by 3
and t1, 3, t2 // and addr with 3
s8addq t2, zero, t3 // multiply by 8
srl t4, t3, v0 // right shift data
ret zero, (ra) // return
.end vgaldl
//+
// inIack
//--
LEAF_ENTRY(inIack)
//
// get Iack from pic, need two to get the vector
//
ldiq t0,PICIACKADR
ldl v0,0(t0) // load data
and v0,0xff,v0 // make it a byte
ret zero, (ra) // return
.end inIack
LEAF_ENTRY(outmemb)
//
// generate super-page address of EISA base address
// upper bits must be sign extension of bit 42
// va<42:41> = 10 (binary) for super-page address
//
and a0,3,t0 // get byte index from address
insbl a1,t0,t5 // put byte in proper position
and a0,0x1ffffff,t1 // 25 bit mask
ldiq t0,EISABAD // get EISA address
sll t1, 7, a0 // shift 7 for EISA
bis t0,a0,t0 // t0 = address of EISA
stl t5, 0(t0) // write data to port
ret zero, (ra) // return
.end outmemb
LEAF_ENTRY(outmemw)
//
// generate super-page address of EISA base address
// upper bits must be sign extension of bit 42
// va<42:41> = 10 (binary) for super-page address
//
and a0,3,t0 // get byte index from address
inswl a1,t0,t5 // put byte in proper position
and a0,0x1ffffff,t1 // 25 bit mask
ldiq t0,EISABAD // get EISA address
or t0,0x20,t0 // t0 = ffff fc02 0000 0020 - word
sll t1, 7, a0 // shift 7 for EISA
bis t0,a0,t0 // t0 = address of EISA
stl t5, 0(t0) // write data to port
ret zero, (ra) // return
.end outmemw
LEAF_ENTRY(outmeml)
//
// generate super-page address of EISA base address
// upper bits must be sign extension of bit 42
// va<42:41> = 10 (binary) for super-page address
//
and a0,0x1ffffff,t1 // 25 bit mask
ldiq t0,EISABAD // get EISA address
or t0,0x60,t0 // t0 = ffff fc02 0000 0060 - long
sll t1, 7, a0 // shift 7 for EISA
bis t0,a0,t0 // t0 = address of EISA
stl a1, 0(t0) // write data to port
ret zero, (ra) // return
.end outmeml
LEAF_ENTRY(outbuffb)
/* Arguments:
a0 address of destination buffer (byte aligned).
a1 address of source buffer in memory (byte aligned)
a2 Number of bytes to move (Count).
*/
//
// generate super-page address of EISA base address
// upper bits must be sign extension of bit 42
// va<42:41> = 10 (binary) for super-page address
//
beq a2, donewb // leave if nothing to do
ldiq t0,EISABAD // get EISA address
and a0,3,t3 // get byte index from dst address
and a0,0x1ffffff,t1 // 25 bit mask
sll t1,EISA_SHIFT,t4 // shift 7 for EISA
bis t0,t4,t0 // t0 = address of EISA
loopwb:
ldq_u t1, 0(a1) // get src data
subl a2, 1, a2 // decrement count
extbl t1, a1,t1 // extract byte
addl a1, 1, a1 // point ot next src address
insbl t1,t3,t1 // insert byte in proper place
stl t1, 0(t0) // write data to EISA memory
addq t0,EISA_BYTE_ADJ, t0 // increment EISA memory pointer
addl t3,1,t3 // increment index
and t3,3,t3 // mask off overflow
bne a2, loopwb
donewb:
ret zero, (ra)
.end outbuffb
LEAF_ENTRY(outbuffw)
/* Arguments:
a0 address of destination buffer (word aligned), eisa.
a1 address of source buffer in memory (word aligned)
a2 Number of words to move (Count).
*/
//
// generate super-page address of EISA base address
// upper bits must be sign extension of bit 42
// va<42:41> = 10 (binary) for super-page address
//
beq a2, doneww // leave if nothing to do
ldiq t0,EISABAD // get EISA address
or t0,0x20,t0 // t0 = ffff fc02 0000 0020 - word
and a0,3,t3 // get word index from dst address
and a0,0x1ffffff,t1 // 25 bit mask
sll t1,EISA_SHIFT,t4 // shift 7 for EISA
bis t0,t4,t0 // t0 = address of EISA
loopww:
ldq_u t1, 0(a1) // get src data
subl a2, 1, a2 // decrement count
extwl t1, a1,t1 // extract word
addl a1, 2, a1 // point ot next src address
inswl t1,t3,t1 // insert in proper place
stl t1, 0(t0) // write data to EISA memory
addq t0,EISA_WORD_ADJ, t0 // increment EISA memory pointer
addl t3,2,t3 // increment index
and t3,3,t3 // mask off overflow
bne a2, loopww
doneww:
ret zero, (ra)
.end outbuffw
LEAF_ENTRY(outbuffl)
/* Arguments:
a0 address of destination buffer (long aligned), eisa.
a1 address of source buffer in memory (long aligned)
a2 Number of longs to move (Count).
*/
//
// generate super-page address of EISA base address
// upper bits must be sign extension of bit 42
// va<42:41> = 10 (binary) for super-page address
//
beq a2, donewl // leave if nothing to do
ldiq t0,EISABAD // get EISA address
or t0,0x60,t0 // t0 = ffff fc02 0000 0060 - long
and a0,0x1ffffff,t1 // 25 bit mask
sll t1,EISA_SHIFT,t4 // shift 7 for EISA
bis t0,t4,t0 // t0 = address of EISA
loopwl:
ldl t1, 0(a1) // get src data
subl a2, 1, a2 // decrement count
stl t1, 0(t0) // write data to EISA memory
addl a1, 4, a1 // point ot next src address
addq t0,EISA_LONG_ADJ, t0 // increment EISA memory pointer
bne a2, loopwl
donewl:
ret zero, (ra)
.end outbuffw
LEAF_ENTRY(inmemb)
//
// generate super-page address of EISA, base address
// upper bits must be sign extension of bit 42
// va<42:41> = 10 (binary) for super-page address
//
and a0,0x1ffffff,t1 // 25 bit mask
ldiq t0,EISABAD // get EISA address
sll t1, 7, t2 // shift 7 for EISA
bis t0,t2,t0 // t0 = address of EISA
ldl v0, 0(t0) // get EISA byte
and a0,0x3,t1 // setup word shift count
extbl v0,t1,v0 // put into low byte
ret zero, (ra) // return
.end inmemb
LEAF_ENTRY(inmemw)
//
// generate super-page address of EISA, base address
// upper bits must be sign extension of bit 42
// va<42:41> = 10 (binary) for super-page address
//
and a0,0x1ffffff,t1 // 25 bit mask
ldiq t0,EISABAD // get EISA base addr
or t0,0x20,t0 // t0 = ffff fc02 0000 0020 - word
sll t1, 7, t2 // shift 7 for EISA
bis t0,t2,t0 // t0 = address of EISA
ldl v0, 0(t0) // get EISA short
and a0,0x3,t1 // setup byte shift count
extwl v0,t1,v0 // put into low word
ret zero, (ra) // return
.end inmemw
LEAF_ENTRY(inmeml)
//
// generate super-page address of EISA, base address
// upper bits must be sign extension of bit 42
// va<42:41> = 10 (binary) for super-page address
//
and a0,0x1ffffff,t1 // 25 bit mask
ldiq t0,EISABAD // get EISA base address
or t0,0x60,t0 // t0 = ffff fc02 0000 0060 - long
sll t1, 7, t2 // shift 7 for EISA
bis t0,t2,t0 // t0 = address of EISA
ldl v0, 0(t0) // get EISA 4 bytes
ret zero, (ra) // return
.end inmeml
LEAF_ENTRY(inbuffb)
/*
Arguments:
a0 source buffer in eisa bus memory.
a1 destination buffer in memory.
a2 Number of bytes to move (Count).
*/
//
// generate super-page address of EISA, base address
// upper bits must be sign extension of bit 42
// va<42:41> = 10 (binary) for super-page address
//
beq a2, donerb // leave if nothing to do
ldiq t0,EISABAD // get EISA base address
and a0,3,t3 // get byte index from src address
and a0,0x1ffffff,t1 // 25 bit mask
sll t1, EISA_SHIFT, t4 // shift 7 for EISA
bis t0,t4,t0 // t0 = address of EISA
looprb:
ldl t1, 0(t0) // get EISA 4 bytes
subl a2, 1, a2 // decrement byte count
extbl t1, t3, t1 // extract byte
addq t0, EISA_BYTE_ADJ, t0 // increment EISA address
stb t1, 0(a1) // assembler preserves the memory
// behind the newly stored byte
addl a1, 1, a1 // increment memory pointer
addl t3, 1, t3 // point to next byte in long
and t3, 3, t3 // get new index
bne a2, looprb
donerb:
ret zero, (ra) // return
.end inbuffb
LEAF_ENTRY(inbuffw)
/*
Arguments:
a0 source buffer in eisa bus memory.
a1 destination buffer in memory.
a2 Number of words to move (Count).
*/
//
// generate super-page address of EISA, base address
// upper bits must be sign extension of bit 42
// va<42:41> = 10 (binary) for super-page address
//
beq a2, donerw // leave if nothing to do
ldiq t0,EISABAD // get EISA base address
or t0,0x20,t0 // t0 = ffff fc02 0000 0020 - word
and a0,3,t3 // get byte index from src address
and a0,0x1ffffff,t1 // 25 bit mask
sll t1, EISA_SHIFT, t4 // shift 7 for EISA
bis t0,t4,t0 // t0 = address of EISA
looprw:
ldl t1, 0(t0) // get EISA 4 bytes
subl a2, 1, a2 // decrement word count
extwl t1, t3, t1 // extract word
addq t0, EISA_WORD_ADJ, t0 // increment EISA address
stw t1, 0(a1) // store in dst memory
addl a1, 2, a1 // increment memory pointer
addl t3, 2, t3 // point to next word in long
and t3, 3, t3 // get new index
bne a2, looprw
donerw:
ret zero, (ra) // return
.end inbuffw
LEAF_ENTRY(inbuffl)
/*
Arguments:
a0 source buffer in eisa bus memory.
a1 destination buffer in memory.
a2 Number of longs to move (Count).
*/
//
// generate super-page address of EISA, base address
// upper bits must be sign extension of bit 42
// va<42:41> = 10 (binary) for super-page address
//
beq a2, donerl // leave if nothing to do
ldiq t0,EISABAD // get EISA base address
or t0,0x60,t0 // t0 = ffff fc02 0000 0060 - long
and a0,0x1ffffff,t1 // 25 bit mask
sll t1, EISA_SHIFT, t4 // shift 7 for EISA
bis t0,t4,t0 // t0 = address of EISA
looprl:
ldl v0, 0(t0) // get EISA 4 bytes
subl a2, 1, a2 // decrement long count
stl v0, 0(a1) // store in dst memory
addl a1, 4, a1 // increment memory pointer
addq t0, EISA_LONG_ADJ, t0 // increment EISA address
bne a2, looprl
donerl:
ret zero, (ra) // return
.end inbuffl
LEAF_ENTRY(inctl)
//
// generate super-page address of EISA, base address
// upper bits must be sign extension of bit 42
// va<42:41> = 10 (binary) for super-page address
//
lda t0,0xfc01 // t0 = 0000 0000 0000 fc01
ldah t0,-1(t0) // t0 = ffff ffff ffff fc01
sll t0,32,t0 // t0 = ffff fc01 0000 0000
bis t0,0xe0000000,t0 // t0 = ffff fc01 e000 0000
ldl v0, 0(t0) // get EISA byte
and v0,0xff,v0
ret zero, (ra) // return
.end inctl
//++
//
// VOID
// outVti(
// ULONG port
// ULONG data
// )
//
// Routine Description:
//
// This function uses the 64-bit super-page to write data to a port
// of the on-board VTI combo chip for JENSEN.
//
// Arguments:
//
// port (a0) - port number on VTI chip to which to write data
// data (a1) - data to write to the port, only low byte is significant
// to the VTI
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(outVti)
//
// generate super-page address of vti, base address
// N.B. - upper bits must be sign extension of bit 42
// va<42:41> = 10 (binary) for super-page address
//
lda t0, 0xc01c(zero) // t0 = 0000 0000 0000 c01c
ldah t0, -1(t0) // t0 = ffff ffff ffff c01c
sll t0, 28, t0 // t0 = ffff fc01 c000 0000
//
// Shift in the port number to generate the port address we
// wish to access
// N.B. - access width is always zero = byte access for VTI
//
sll a0, 9, a0 // a0 << 9
bis t0, a0, t0 // t0 = address of VTI port
//
// Do the port write, guarantee that subsequent writes (and reads)
// are ordered with respect to this write and return to caller
//
stl a1, 0(t0) // write data to port
mb // guarantee write ordering
ret zero, (ra) // return
.end outVti
//++
//
// ULONG
// inVti(
// ULONG port
// )
//
// Routine Description:
//
// This function uses the 64-bit super-page to read data from a port
// of the on-board VTI combo chip for JENSEN.
//
// Arguments:
//
// port (a0) - port number on VTI chip to which to write data
//
// Return Value:
//
// data (v0) - the data read from the VTI chip, only the low byte will
// be valid
//
//--
LEAF_ENTRY(inVti)
//
// generate super-page address of vti, base address
// N.B. - upper bits must be sign extension of bit 42
// va<42:41> = 10 (binary) for super-page address
//
lda t0, 0xc01c(zero) // t0 = 0000 0000 0000 c01c
ldah t0, -1(t0) // t0 = ffff ffff ffff c01c
sll t0, 28, t0 // t0 = ffff fc01 c000 0000
//
// Shift in the port number to generate the port address we
// wish to access
// N.B. - access width for VTI is always 0 = byte access
//
sll a0, 9, a0 // a0 << 9
bis t0, a0, t0 // t0 = address of VTI port
//
// Do the super-page i/o access and return data to caller
//
ldl v0, 0(t0) // read data from port
and v0, 0xff, v0
ret zero, (ra) // return
.end inVti
LEAF_ENTRY(delay_us)
bis zero, ONE_USEC, t1
rpcc t0 /* RCC T0, read cycle counter */
loop0: rpcc t2 /* RCC T2, read cycle counter */
subl t2, t0, t2 /* check for wrapping */
bge t2, over0 /* check, and see if negative */
ornot t0, zero, t4 /* calculate the offset */
zap t4, 0xf0, t4
cmplt t4, t1, t2
beq t2, done0
subl t1, t4, t1 /* adjust the counter */
and zero, t0, t0 /* set t0 to zero */
over0: cmplt t2, t1, t2 /* compare these for usec timer */
bne t2, loop0 /* stay in... */
done0: ret zero, (ra)
.end delay_us
LEAF_ENTRY(delay_500ns)
bis zero, HALF_USEC, t1
rpcc t0 /* RCC T0, read cycle counter */
loop1: rpcc t2 /* RCC T2, read cycle counter */
subl t2, t0, t2 /* check for wrapping */
bge t2, over1 /* check, and see if negative */
ornot t0, zero, t4 /* calculate the offset */
zap t4, 0xf0, t4
cmplt t4, t1, t2
beq t2, done1
subl t1, t4, t1 /* adjust the counter */
and zero, t0, t0 /* set t0 to zero */
over1: cmplt t2, t1, t2 /* compare these for usec timer */
bne t2, loop1 /* stay in... */
done1: ret zero, (ra)
.end delay_500ns