20000317 sourceware import
This commit is contained in:
388
libgloss/sparc/salib.c
Normal file
388
libgloss/sparc/salib.c
Normal file
@ -0,0 +1,388 @@
|
||||
/* Stand-alone library for SPARClite
|
||||
*
|
||||
* Copyright (c) 1995 Cygnus Support
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice is included verbatim in any distributions. No written agreement,
|
||||
* license, or royalty fee is required for any of the authorized uses.
|
||||
* Modifications to this software may be copyrighted by their authors
|
||||
* and need not follow the licensing terms described here, provided that
|
||||
* the new terms are clearly indicated on the first page of each file where
|
||||
* they apply.
|
||||
*/
|
||||
|
||||
#include "sparclite.h"
|
||||
#include "asm.h"
|
||||
|
||||
/* LED blinking pattern can be changed by modifying __led_algorithm. */
|
||||
|
||||
enum ledtype
|
||||
{
|
||||
led_marching, /* marching pattern, only one led on at a time */
|
||||
led_random, /* pseudo-random pattern */
|
||||
led_blinking, /* all leds blink on and off */
|
||||
led_none /* leds off all the time */
|
||||
};
|
||||
|
||||
enum ledtype __led_algorithm = led_marching;
|
||||
|
||||
|
||||
/* Pointer to hook for outbyte, set by stub's exception handler. */
|
||||
void (*__outbyte_hook) (int c);
|
||||
|
||||
#ifdef SL931
|
||||
#define SDTR_BASE 0x200
|
||||
#define SDTR_ASI 1
|
||||
#define SDTR_SHIFT 0
|
||||
#else
|
||||
#define SDTR_BASE 0x10000000
|
||||
#define SDTR_ASI 4
|
||||
#define SDTR_SHIFT 16
|
||||
#endif
|
||||
|
||||
#define get_uart_status(PORT) \
|
||||
(read_asi (SDTR_ASI, SDTR_BASE + 0x24 + (PORT) * 0x10) >> SDTR_SHIFT)
|
||||
|
||||
#define xmt_char(PORT, C) \
|
||||
write_asi (SDTR_ASI, SDTR_BASE + 0x20 + (PORT) * 0x10, (C) << SDTR_SHIFT)
|
||||
|
||||
#define rcv_char(PORT) \
|
||||
(read_asi (SDTR_ASI, SDTR_BASE + 0x20 + (PORT) * 0x10) >> SDTR_SHIFT)
|
||||
|
||||
void putDebugChar();
|
||||
|
||||
#if 0
|
||||
void
|
||||
set_uart (cmd)
|
||||
int cmd;
|
||||
{
|
||||
write_asi (SDTR_ASI, SDTR_BASE + 0x24, cmd << SDTR_SHIFT);
|
||||
}
|
||||
|
||||
void
|
||||
set_timer_3 (val)
|
||||
int val;
|
||||
{
|
||||
write_asi (SDTR_ASI, SDTR_BASE + 0x78, val << SDTR_SHIFT);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
asm("
|
||||
.text
|
||||
.align 4
|
||||
|
||||
! Register window overflow handler. Come here when save would move us
|
||||
! into the invalid window. This routine runs with traps disabled, and
|
||||
! must be careful not to touch the condition codes, as PSR is never
|
||||
! restored.
|
||||
!
|
||||
! We are called with %l0 = wim, %l1 = pc, %l2 = npc
|
||||
|
||||
.globl " STRINGSYM(win_ovf) "
|
||||
" STRINGSYM(win_ovf) ":
|
||||
mov %g1, %l3 ! Save g1, we use it to hold the wim
|
||||
srl %l0, 1, %g1 ! Rotate wim right
|
||||
sll %l0, __WINSIZE-1, %l0
|
||||
or %l0, %g1, %g1
|
||||
|
||||
save %g0, %g0, %g0 ! Slip into next window
|
||||
mov %g1, %wim ! Install the new wim
|
||||
|
||||
std %l0, [%sp + 0 * 4] ! save L & I registers
|
||||
std %l2, [%sp + 2 * 4]
|
||||
std %l4, [%sp + 4 * 4]
|
||||
std %l6, [%sp + 6 * 4]
|
||||
|
||||
std %i0, [%sp + 8 * 4]
|
||||
std %i2, [%sp + 10 * 4]
|
||||
std %i4, [%sp + 12 * 4]
|
||||
std %i6, [%sp + 14 * 4]
|
||||
|
||||
restore ! Go back to trap window.
|
||||
mov %l3, %g1 ! Restore %g1
|
||||
|
||||
jmpl %l1, %g0
|
||||
rett %l2
|
||||
|
||||
! Register window underflow handler. Come here when restore would move us
|
||||
! into the invalid window. This routine runs with traps disabled, and
|
||||
! must be careful not to touch the condition codes, as PSR is never
|
||||
! restored.
|
||||
!
|
||||
! We are called with %l0 = wim, %l1 = pc, %l2 = npc
|
||||
|
||||
.globl " STRINGSYM(win_unf) "
|
||||
" STRINGSYM(win_unf) ":
|
||||
sll %l0, 1, %l3 ! Rotate wim left
|
||||
srl %l0, __WINSIZE-1, %l0
|
||||
or %l0, %l3, %l0
|
||||
|
||||
mov %l0, %wim ! Install the new wim
|
||||
|
||||
restore ! User's window
|
||||
restore ! His caller's window
|
||||
|
||||
ldd [%sp + 0 * 4], %l0 ! restore L & I registers
|
||||
ldd [%sp + 2 * 4], %l2
|
||||
ldd [%sp + 4 * 4], %l4
|
||||
ldd [%sp + 6 * 4], %l6
|
||||
|
||||
ldd [%sp + 8 * 4], %i0
|
||||
ldd [%sp + 10 * 4], %i2
|
||||
ldd [%sp + 12 * 4], %i4
|
||||
ldd [%sp + 14 * 4], %i6
|
||||
|
||||
save %g0, %g0, %g0 ! Back to trap window
|
||||
save %g0, %g0, %g0
|
||||
|
||||
jmpl %l1, %g0
|
||||
rett %l2
|
||||
|
||||
! Read the TBR.
|
||||
|
||||
.globl " STRINGSYM(rdtbr) "
|
||||
" STRINGSYM(rdtbr) ":
|
||||
retl
|
||||
mov %tbr, %o0
|
||||
|
||||
");
|
||||
|
||||
extern unsigned long rdtbr();
|
||||
|
||||
void
|
||||
die(val)
|
||||
int val;
|
||||
{
|
||||
static unsigned char *leds = (unsigned char *)0x02000003;
|
||||
|
||||
*leds = val;
|
||||
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
/* Each entry in the trap vector occupies four words. */
|
||||
|
||||
struct trap_entry
|
||||
{
|
||||
unsigned sethi_filler:10;
|
||||
unsigned sethi_imm22:22;
|
||||
unsigned jmpl_filler:19;
|
||||
unsigned jmpl_simm13:13;
|
||||
unsigned long filler[2];
|
||||
};
|
||||
|
||||
extern struct trap_entry fltr_proto;
|
||||
asm ("
|
||||
.data
|
||||
.globl " STRINGSYM(fltr_proto) "
|
||||
.align 4
|
||||
" STRINGSYM(fltr_proto) ": ! First level trap routine prototype
|
||||
sethi 0, %l0
|
||||
jmpl 0+%l0, %g0
|
||||
nop
|
||||
nop
|
||||
|
||||
.text
|
||||
.align 4
|
||||
");
|
||||
|
||||
/* Setup trap TT to go to ROUTINE. If TT is between 0 and 255 inclusive, the
|
||||
normal trap vector will be used. If TT is 256, then it's for the SPARClite
|
||||
DSU, and that always vectors off to 255 unrelocated.
|
||||
*/
|
||||
|
||||
void
|
||||
exceptionHandler (tt, routine)
|
||||
int tt;
|
||||
unsigned long routine;
|
||||
{
|
||||
struct trap_entry *tb; /* Trap vector base address */
|
||||
|
||||
if (tt != 256)
|
||||
tb = (struct trap_entry *) (rdtbr() & ~0xfff);
|
||||
else
|
||||
{
|
||||
tt = 255;
|
||||
tb = (struct trap_entry *) 0;
|
||||
}
|
||||
|
||||
tb[tt] = fltr_proto;
|
||||
|
||||
tb[tt].sethi_imm22 = routine >> 10;
|
||||
tb[tt].jmpl_simm13 = routine & 0x3ff;
|
||||
}
|
||||
|
||||
void
|
||||
update_leds()
|
||||
{
|
||||
static unsigned char *leds = (unsigned char *)0x02000003;
|
||||
static enum ledtype prev_algorithm = led_none;
|
||||
|
||||
if (prev_algorithm != __led_algorithm)
|
||||
{
|
||||
*leds = 0xff; /* turn the LEDs off */
|
||||
prev_algorithm = __led_algorithm;
|
||||
}
|
||||
|
||||
switch (__led_algorithm)
|
||||
{
|
||||
case led_marching:
|
||||
{
|
||||
static unsigned char curled = 1;
|
||||
static unsigned char dir = 0;
|
||||
|
||||
*leds = ~curled;
|
||||
|
||||
if (dir)
|
||||
curled <<= 1;
|
||||
else
|
||||
curled >>= 1;
|
||||
|
||||
if (curled == 0)
|
||||
{
|
||||
if (dir)
|
||||
curled = 0x80;
|
||||
else
|
||||
curled = 1;
|
||||
dir = ~dir;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case led_random:
|
||||
{
|
||||
static unsigned int next = 0;
|
||||
*leds = next & 0xff;
|
||||
next = (next * 1103515245 + 12345) & 0x7fff;
|
||||
break;
|
||||
}
|
||||
|
||||
case led_blinking:
|
||||
{
|
||||
static unsigned char next = 0;
|
||||
*leds = next;
|
||||
next = ~next;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* 1/5th of a second? */
|
||||
|
||||
#define LEDTIME (20000000 / 500)
|
||||
|
||||
unsigned long ledtime = LEDTIME;
|
||||
|
||||
int
|
||||
inbyte()
|
||||
{
|
||||
return (getDebugChar());
|
||||
}
|
||||
|
||||
int
|
||||
getDebugChar()
|
||||
{
|
||||
unsigned long countdown = ledtime;
|
||||
|
||||
update_leds();
|
||||
|
||||
while (1)
|
||||
{
|
||||
if ((get_uart_status(0) & 2) != 0) break;
|
||||
|
||||
if (countdown-- == 0)
|
||||
{
|
||||
countdown = ledtime;
|
||||
update_leds();
|
||||
}
|
||||
}
|
||||
|
||||
return rcv_char(0);
|
||||
}
|
||||
|
||||
/* Output one character to the serial port */
|
||||
void
|
||||
outbyte(c)
|
||||
int c;
|
||||
{
|
||||
if (__outbyte_hook)
|
||||
__outbyte_hook (c);
|
||||
else
|
||||
putDebugChar(c);
|
||||
}
|
||||
|
||||
void
|
||||
putDebugChar(c)
|
||||
int c;
|
||||
{
|
||||
update_leds();
|
||||
|
||||
while ((get_uart_status(0) & 1) == 0) ;
|
||||
|
||||
xmt_char(0, c);
|
||||
}
|
||||
|
||||
#if 0
|
||||
int
|
||||
write(fd, data, length)
|
||||
int fd;
|
||||
unsigned char *data;
|
||||
int length;
|
||||
{
|
||||
int olength = length;
|
||||
|
||||
while (length--)
|
||||
putDebugChar(*data++);
|
||||
|
||||
return olength;
|
||||
}
|
||||
|
||||
int
|
||||
read(fd, data, length)
|
||||
int fd;
|
||||
unsigned char *data;
|
||||
int length;
|
||||
{
|
||||
int olength = length;
|
||||
int c;
|
||||
|
||||
while (length--)
|
||||
*data++ = getDebugChar();
|
||||
|
||||
return olength;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set the baud rate for the serial port, returns 0 for success,
|
||||
-1 otherwise */
|
||||
|
||||
#if 0
|
||||
int
|
||||
set_baud_rate(baudrate)
|
||||
int baudrate;
|
||||
{
|
||||
/* Convert baud rate to uart clock divider */
|
||||
switch (baudrate)
|
||||
{
|
||||
case 38400:
|
||||
baudrate = 16;
|
||||
break;
|
||||
case 19200:
|
||||
baudrate = 33;
|
||||
break;
|
||||
case 9600:
|
||||
baudrate = 65;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
set_timer_3(baudrate); /* Set it */
|
||||
}
|
||||
#endif
|
Reference in New Issue
Block a user