📄 salib.c
字号:
/* 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 0voidset_uart (cmd) int cmd;{ write_asi (SDTR_ASI, SDTR_BASE + 0x24, cmd << SDTR_SHIFT);}voidset_timer_3 (val) int val;{ write_asi (SDTR_ASI, SDTR_BASE + 0x78, val << SDTR_SHIFT);}#endifasm(" .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();voiddie(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.*/voidexceptionHandler (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;}voidupdate_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;intinbyte(){ return (getDebugChar());}intgetDebugChar(){ 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 */voidoutbyte(c) int c;{ if (__outbyte_hook) __outbyte_hook (c); else putDebugChar(c);}voidputDebugChar(c) int c;{ update_leds(); while ((get_uart_status(0) & 1) == 0) ; xmt_char(0, c);}#if 0intwrite(fd, data, length) int fd; unsigned char *data; int length;{ int olength = length; while (length--) putDebugChar(*data++); return olength;}intread(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 0intset_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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -