source: trunk/libs/newlib/src/libgloss/sparc/salib.c @ 444

Last change on this file since 444 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 7.1 KB
Line 
1/* Stand-alone library for SPARClite
2 *
3 * Copyright (c) 1995 Cygnus Support
4 *
5 * The authors hereby grant permission to use, copy, modify, distribute,
6 * and license this software and its documentation for any purpose, provided
7 * that existing copyright notices are retained in all copies and that this
8 * notice is included verbatim in any distributions. No written agreement,
9 * license, or royalty fee is required for any of the authorized uses.
10 * Modifications to this software may be copyrighted by their authors
11 * and need not follow the licensing terms described here, provided that
12 * the new terms are clearly indicated on the first page of each file where
13 * they apply.
14 */
15
16#include "sparclite.h"
17#include "asm.h"
18
19/* LED blinking pattern can be changed by modifying __led_algorithm. */
20
21enum ledtype
22{
23  led_marching,         /* marching pattern, only one led on at a time */
24  led_random,           /* pseudo-random pattern */
25  led_blinking,         /* all leds blink on and off */
26  led_none              /* leds off all the time */
27};
28
29enum ledtype __led_algorithm = led_marching;
30
31
32/* Pointer to hook for outbyte, set by stub's exception handler.  */
33void (*__outbyte_hook) (int c);
34
35#ifdef SL931
36#define SDTR_BASE 0x200
37#define SDTR_ASI 1
38#define SDTR_SHIFT 0
39#else
40#define SDTR_BASE 0x10000000
41#define SDTR_ASI 4
42#define SDTR_SHIFT 16
43#endif
44
45#define get_uart_status(PORT) \
46  (read_asi (SDTR_ASI, SDTR_BASE + 0x24 + (PORT) * 0x10) >> SDTR_SHIFT)
47
48#define xmt_char(PORT, C) \
49  write_asi (SDTR_ASI, SDTR_BASE + 0x20 + (PORT) * 0x10, (C) << SDTR_SHIFT)
50
51#define rcv_char(PORT) \
52  (read_asi (SDTR_ASI, SDTR_BASE + 0x20 + (PORT) * 0x10) >> SDTR_SHIFT)
53
54void putDebugChar();
55
56#if 0
57void
58set_uart (cmd)
59     int cmd;
60{
61  write_asi (SDTR_ASI, SDTR_BASE + 0x24, cmd << SDTR_SHIFT);
62}
63
64void
65set_timer_3 (val)
66     int val;
67{
68  write_asi (SDTR_ASI, SDTR_BASE + 0x78, val << SDTR_SHIFT);
69}
70#endif
71
72
73asm("
74        .text
75        .align 4
76
77! Register window overflow handler.  Come here when save would move us
78! into the invalid window.  This routine runs with traps disabled, and
79! must be careful not to touch the condition codes, as PSR is never
80! restored.
81!
82! We are called with %l0 = wim, %l1 = pc, %l2 = npc
83
84        .globl " STRINGSYM(win_ovf) "
85" STRINGSYM(win_ovf) ":
86        mov     %g1, %l3                ! Save g1, we use it to hold the wim
87        srl     %l0, 1, %g1             ! Rotate wim right
88        sll     %l0, __WINSIZE-1, %l0
89        or      %l0, %g1, %g1
90
91        save    %g0, %g0, %g0           ! Slip into next window
92        mov     %g1, %wim               ! Install the new wim
93
94        std     %l0, [%sp + 0 * 4]      ! save L & I registers
95        std     %l2, [%sp + 2 * 4]
96        std     %l4, [%sp + 4 * 4]
97        std     %l6, [%sp + 6 * 4]
98
99        std     %i0, [%sp + 8 * 4]
100        std     %i2, [%sp + 10 * 4]
101        std     %i4, [%sp + 12 * 4]
102        std     %i6, [%sp + 14 * 4]
103
104        restore                         ! Go back to trap window.
105        mov     %l3, %g1                ! Restore %g1
106
107        jmpl    %l1,  %g0
108        rett    %l2
109
110! Register window underflow handler.  Come here when restore would move us
111! into the invalid window.  This routine runs with traps disabled, and
112! must be careful not to touch the condition codes, as PSR is never
113! restored.
114!
115! We are called with %l0 = wim, %l1 = pc, %l2 = npc
116
117        .globl " STRINGSYM(win_unf) "
118" STRINGSYM(win_unf) ":
119        sll     %l0, 1, %l3             ! Rotate wim left
120        srl     %l0, __WINSIZE-1, %l0
121        or      %l0, %l3, %l0
122
123        mov     %l0, %wim               ! Install the new wim
124
125        restore                         ! User's window
126        restore                         ! His caller's window
127
128        ldd     [%sp + 0 * 4], %l0      ! restore L & I registers
129        ldd     [%sp + 2 * 4], %l2
130        ldd     [%sp + 4 * 4], %l4
131        ldd     [%sp + 6 * 4], %l6
132
133        ldd     [%sp + 8 * 4], %i0
134        ldd     [%sp + 10 * 4], %i2
135        ldd     [%sp + 12 * 4], %i4
136        ldd     [%sp + 14 * 4], %i6
137
138        save    %g0, %g0, %g0           ! Back to trap window
139        save    %g0, %g0, %g0
140
141        jmpl    %l1,  %g0
142        rett    %l2
143
144! Read the TBR.
145
146        .globl " STRINGSYM(rdtbr) "
147" STRINGSYM(rdtbr) ":
148        retl
149        mov     %tbr, %o0
150
151");
152
153extern unsigned long rdtbr();
154
155void
156die(val)
157     int val;
158{
159  static unsigned char *leds = (unsigned char *)0x02000003;
160
161  *leds = val;
162
163  while (1) ;
164}
165
166/* Each entry in the trap vector occupies four words. */
167
168struct trap_entry
169{
170  unsigned sethi_filler:10;
171  unsigned sethi_imm22:22;
172  unsigned jmpl_filler:19;
173  unsigned jmpl_simm13:13;
174  unsigned long filler[2];
175};
176
177extern struct trap_entry fltr_proto;
178asm ("
179        .data
180        .globl " STRINGSYM(fltr_proto) "
181        .align 4
182" STRINGSYM(fltr_proto) ":                      ! First level trap routine prototype
183        sethi 0, %l0
184        jmpl 0+%l0, %g0
185        nop
186        nop
187
188        .text
189        .align 4
190");
191
192/* Setup trap TT to go to ROUTINE.  If TT is between 0 and 255 inclusive, the
193   normal trap vector will be used.  If TT is 256, then it's for the SPARClite
194   DSU, and that always vectors off to 255 unrelocated.
195*/
196
197void
198exceptionHandler (tt, routine)
199     int tt;
200     unsigned long routine;
201{
202  struct trap_entry *tb;        /* Trap vector base address */
203
204  if (tt != 256)
205    tb = (struct trap_entry *) (rdtbr() & ~0xfff);
206  else
207    {
208      tt = 255;
209      tb = (struct trap_entry *) 0;
210    }
211
212  tb[tt] = fltr_proto;
213
214  tb[tt].sethi_imm22 = routine >> 10;
215  tb[tt].jmpl_simm13 = routine & 0x3ff;
216}
217
218void
219update_leds()
220{
221  static unsigned char *leds = (unsigned char *)0x02000003;
222  static enum ledtype prev_algorithm = led_none;
223
224  if (prev_algorithm != __led_algorithm)
225    {
226       *leds = 0xff;    /* turn the LEDs off */
227       prev_algorithm = __led_algorithm;
228    }
229
230  switch (__led_algorithm)
231    {
232    case led_marching:
233      {
234        static unsigned char curled = 1;
235        static unsigned char dir = 0;
236
237        *leds = ~curled;
238
239        if (dir)
240          curled <<= 1;
241        else
242          curled >>= 1;
243
244        if (curled == 0)
245          {
246            if (dir)
247              curled = 0x80;
248            else
249              curled = 1;
250            dir = ~dir;
251          }
252        break;
253      }
254
255    case led_random:
256      {
257        static unsigned int next = 0;
258        *leds = next & 0xff;
259        next = (next * 1103515245 + 12345) & 0x7fff;
260        break;
261      }
262
263    case led_blinking:
264      {
265        static unsigned char next = 0;
266        *leds = next;
267        next = ~next;
268        break;
269      }
270
271    default:
272      break;
273    }
274}
275
276 /* 1/5th of a second? */
277
278#define LEDTIME (20000000 / 500)
279
280unsigned long ledtime = LEDTIME;
281
282int
283inbyte()
284{
285        return (getDebugChar());
286}
287
288int
289getDebugChar()
290{
291  unsigned long countdown = ledtime;
292
293  update_leds();
294
295  while (1)
296    {
297      if ((get_uart_status(0) & 2) != 0) break;
298
299      if (countdown-- == 0)
300        {
301          countdown = ledtime;
302          update_leds();
303        }
304    }
305
306  return rcv_char(0);
307}
308
309/* Output one character to the serial port */
310void
311outbyte(c)
312    int c;
313{
314  if (__outbyte_hook)
315    __outbyte_hook (c);
316  else
317    putDebugChar(c);
318}
319
320void
321putDebugChar(c)
322     int c;
323{
324  update_leds();
325
326  while ((get_uart_status(0) & 1) == 0) ;
327
328  xmt_char(0, c);
329}
330
331#if 0
332int
333write(fd, data, length)
334     int fd;
335     unsigned char *data;
336     int length;
337{
338  int olength = length;
339
340  while (length--)
341    putDebugChar(*data++);
342
343  return olength;
344}
345
346int
347read(fd, data, length)
348     int fd;
349     unsigned char *data;
350     int length;
351{
352  int olength = length;
353  int c;
354
355  while (length--)
356    *data++ = getDebugChar();
357
358  return olength;
359}
360#endif
361
362/* Set the baud rate for the serial port, returns 0 for success,
363   -1 otherwise */
364
365#if 0
366int
367set_baud_rate(baudrate)
368     int baudrate;
369{
370  /* Convert baud rate to uart clock divider */
371  switch (baudrate)
372    {
373    case 38400:
374      baudrate = 16;
375      break;
376    case 19200:
377      baudrate = 33;
378      break;
379    case 9600:
380      baudrate = 65;
381      break;
382    default:
383      return -1;
384    }
385
386  set_timer_3(baudrate);        /* Set it */
387}
388#endif
Note: See TracBrowser for help on using the repository browser.