This is the linker script script that is used on the Motorola IDP board.
STARTUP(crt0.o) OUTPUT_ARCH(m68k) INPUT(idp.o) SEARCH_DIR(.) __DYNAMIC = 0; /* * Setup the memory map of the MC68ec0x0 Board (IDP) * stack grows up towards high memory. This works for * both the rom68k and the mon68k monitors. */ MEMORY { ram : ORIGIN = 0x10000, LENGTH = 2M } /* * stick everything in ram (of course) */ SECTIONS { .text : { CREATE_OBJECT_SYMBOLS *(.text) etext = .; __CTOR_LIST__ = .; LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) *(.ctors) LONG(0) __CTOR_END__ = .; __DTOR_LIST__ = .; LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) *(.dtors) LONG(0) __DTOR_END__ = .; *(.lit) *(.shdata) } > ram .shbss SIZEOF(.text) + ADDR(.text) : { *(.shbss) } .talias : { } > ram .data : { *(.data) CONSTRUCTORS _edata = .; } > ram .bss SIZEOF(.data) + ADDR(.data) : { __bss_start = ALIGN(0x8); *(.bss) *(COMMON) end = ALIGN(0x8); _end = ALIGN(0x8); __end = ALIGN(0x8); } .mstack : { } > ram .rstack : { } > ram .stab . (NOLOAD) : { [ .stab ] } .stabstr . (NOLOAD) : { [ .stabstr ] } }
/* * crt0.S -- startup file for m68k-coff * */ .title "crt0.S for m68k-coff" /* These are predefined by new versions of GNU cpp. */ #ifndef __USER_LABEL_PREFIX__ #define __USER_LABEL_PREFIX__ _ #endif #ifndef __REGISTER_PREFIX__ #define __REGISTER_PREFIX__ #endif /* ANSI concatenation macros. */ #define CONCAT1(a, b) CONCAT2(a, b) #define CONCAT2(a, b) a ## b /* Use the right prefix for global labels. */ #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) /* Use the right prefix for registers. */ #define REG(x) CONCAT1 (__REGISTER_PREFIX__, x) #define d0 REG (d0) #define d1 REG (d1) #define d2 REG (d2) #define d3 REG (d3) #define d4 REG (d4) #define d5 REG (d5) #define d6 REG (d6) #define d7 REG (d7) #define a0 REG (a0) #define a1 REG (a1) #define a2 REG (a2) #define a3 REG (a3) #define a4 REG (a4) #define a5 REG (a5) #define a6 REG (a6) #define fp REG (fp) #define sp REG (sp) /* * Set up some room for a stack. We just grab a chunk of memory. */ .set stack_size, 0x2000 .comm SYM (stack), stack_size /* * Define an empty environment. */ .data .align 2 SYM (environ): .long 0 .align 2 .text .global SYM (stack) .global SYM (main) .global SYM (exit) /* * This really should be __bss_start, not SYM (__bss_start). */ .global __bss_start /* * start -- set things up so the application will run. */ SYM (start): link a6, #-8 moveal #SYM (stack) + stack_size, sp /* * zerobss -- zero out the bss section */ moveal #__bss_start, a0 moveal #SYM (end), a1 1: movel #0, (a0) leal 4(a0), a0 cmpal a0, a1 bne 1b /* * Call the main routine from the application to get it going. * main (argc, argv, environ) * We pass argv as a pointer to NULL. */ pea 0 pea SYM (environ) pea sp@(4) pea 0 jsr SYM (main) movel d0, sp@- /* * _exit -- Exit from the application. Normally we cause a user trap * to return to the ROM monitor for another run. */ SYM (exit): trap #0
/* * glue.c -- all the code to make GCC and the libraries run on * a bare target board. These should work with any * target if inbyte() and outbyte() exist. */ #include <sys/types.h> #include <sys/stat.h> #include <errno.h> #ifndef NULL #define NULL 0 #endif /* FIXME: this is a hack till libc builds */ __main() { return; } #undef errno int errno; extern caddr_t _end; /* _end is set in the linker command file */ extern int outbyte(); extern unsigned char inbyte(); extern int havebyte(); /* just in case, most boards have at least some memory */ #ifndef RAMSIZE # define RAMSIZE (caddr_t)0x100000 #endif /* * read -- read bytes from the serial port. Ignore fd, since * we only have stdin. */ int read(fd, buf, nbytes) int fd; char *buf; int nbytes; { int i = 0; for (i = 0; i < nbytes; i++) { *(buf + i) = inbyte(); if ((*(buf + i) == '\n') || (*(buf + i) == '\r')) { (*(buf + i)) = 0; break; } } return (i); } /* * write -- write bytes to the serial port. Ignore fd, since * stdout and stderr are the same. Since we have no filesystem, * open will only return an error. */ int write(fd, buf, nbytes) int fd; char *buf; int nbytes; { int i; for (i = 0; i < nbytes; i++) { if (*(buf + i) == '\n') { outbyte ('\r'); } outbyte (*(buf + i)); } return (nbytes); } /* * open -- open a file descriptor. We don't have a filesystem, so * we return an error. */ int open(buf, flags, mode) char *buf; int flags; int mode; { errno = EIO; return (-1); } /* * close -- close a file descriptor. We don't need * to do anything, but pretend we did. */ int close(fd) int fd; { return (0); } /* * sbrk -- changes heap size size. Get nbytes more * RAM. We just increment a pointer in what's * left of memory on the board. */ caddr_t sbrk(nbytes) int nbytes; { static caddr_t heap_ptr = NULL; caddr_t base; if (heap_ptr == NULL) { heap_ptr = (caddr_t)&_end; } if ((RAMSIZE - heap_ptr) >= 0) { base = heap_ptr; heap_ptr += nbytes; return (base); } else { errno = ENOMEM; return ((caddr_t)-1); } } /* * isatty -- returns 1 if connected to a terminal device, * returns 0 if not. Since we're hooked up to a * serial port, we'll say yes and return a 1. */ int isatty(fd) int fd; { return (1); } /* * lseek -- move read/write pointer. Since a serial port * is non-seekable, we return an error. */ off_t lseek(fd, offset, whence) int fd; off_t offset; int whence; { errno = ESPIPE; return ((off_t)-1); } /* * fstat -- get status of a file. Since we have no file * system, we just return an error. */ int fstat(fd, buf) int fd; struct stat *buf; { errno = EIO; return (-1); } /* * getpid -- only one process, so just return 1. */ #define __MYPID 1 int getpid() { return __MYPID; } /* * kill -- go out via exit... */ int kill(pid, sig) int pid; int sig; { if(pid == __MYPID) _exit(sig); return 0; } /* * print -- do a raw print of a string */ int print(ptr) char *ptr; { while (*ptr) { outbyte (*ptr++); } } /* * putnum -- print a 32 bit number in hex */ int putnum (num) unsigned int num; { char buffer[9]; int count; char *bufptr = buffer; int digit; for (count = 7 ; count >= 0 ; count--) { digit = (num >> (count * 4)) & 0xf; if (digit <= 9) *bufptr++ = (char) ('0' + digit); else *bufptr++ = (char) ('a' - 10 + digit); } *bufptr = (char) 0; print (buffer); return; }
/* * mvme.S -- board support for m68k */ .title "mvme.S for m68k-coff" /* These are predefined by new versions of GNU cpp. */ #ifndef __USER_LABEL_PREFIX__ #define __USER_LABEL_PREFIX__ _ #endif #ifndef __REGISTER_PREFIX__ #define __REGISTER_PREFIX__ #endif /* ANSI concatenation macros. */ #define CONCAT1(a, b) CONCAT2(a, b) #define CONCAT2(a, b) a ## b /* Use the right prefix for global labels. */ #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) /* Use the right prefix for registers. */ #define REG(x) CONCAT1 (__REGISTER_PREFIX__, x) #define d0 REG (d0) #define d1 REG (d1) #define d2 REG (d2) #define d3 REG (d3) #define d4 REG (d4) #define d5 REG (d5) #define d6 REG (d6) #define d7 REG (d7) #define a0 REG (a0) #define a1 REG (a1) #define a2 REG (a2) #define a3 REG (a3) #define a4 REG (a4) #define a5 REG (a5) #define a6 REG (a6) #define fp REG (fp) #define sp REG (sp) #define vbr REG (vbr) .align 2 .text .global SYM (_exit) .global SYM (outln) .global SYM (outbyte) .global SYM (putDebugChar) .global SYM (inbyte) .global SYM (getDebugChar) .global SYM (havebyte) .global SYM (exceptionHandler) .set vbr_size, 0x400 .comm SYM (vbr_table), vbr_size /* * inbyte -- get a byte from the serial port * d0 - contains the byte read in */ .align 2 SYM (getDebugChar): /* symbol name used by m68k-stub */ SYM (inbyte): link a6, #-8 trap #15 .word inchr moveb sp@, d0 extbl d0 unlk a6 rts /* * outbyte -- sends a byte out the serial port * d0 - contains the byte to be sent */ .align 2 SYM (putDebugChar): /* symbol name used by m68k-stub */ SYM (outbyte): link fp, #-4 moveb fp@(11), sp@ trap #15 .word outchr unlk fp rts /* * outln -- sends a string of bytes out the serial port with a CR/LF * a0 - contains the address of the string's first byte * a1 - contains the address of the string's last byte */ .align 2 SYM (outln): link a6, #-8 moveml a0/a1, sp@ trap #15 .word outln unlk a6 rts /* * outstr -- sends a string of bytes out the serial port without a CR/LF * a0 - contains the address of the string's first byte * a1 - contains the address of the string's last byte */ .align 2 SYM (outstr): link a6, #-8 moveml a0/a1, sp@ trap #15 .word outstr unlk a6 rts /* * havebyte -- checks to see if there is a byte in the serial port, * returns 1 if there is a byte, 0 otherwise. */ SYM (havebyte): trap #15 .word instat beqs empty movel #1, d0 rts empty: movel #0, d0 rts /* * These constants are for the MVME-135 board's boot monitor. They * are used with a TRAP #15 call to access the monitor's I/O routines. * they must be in the word following the trap call. */ .set inchr, 0x0 .set instat, 0x1 .set inln, 0x2 .set readstr, 0x3 .set readln, 0x4 .set chkbrk, 0x5 .set outchr, 0x20 .set outstr, 0x21 .set outln, 0x22 .set write, 0x23 .set writeln, 0x24 .set writdln, 0x25 .set pcrlf, 0x26 .set eraseln, 0x27 .set writd, 0x28 .set sndbrk, 0x29 .set tm_ini, 0x40 .set dt_ini, 0x42 .set tm_disp, 0x43 .set tm_rd, 0x44 .set redir, 0x60 .set redir_i, 0x61 .set redir_o, 0x62 .set return, 0x63 .set bindec, 0x64 .set changev, 0x67 .set strcmp, 0x68 .set mulu32, 0x69 .set divu32, 0x6A .set chk_sum, 0x6B
#include "w89k.h" /* * outbyte -- shove a byte out the serial port. We wait till the byte */ int outbyte(byte) unsigned char byte; { while ((inp(RS232REG) & TRANSMIT) == 0x0) { } ; return (outp(RS232PORT, byte)); } /* * inbyte -- get a byte from the serial port */ unsigned char inbyte() { while ((inp(RS232REG) & RECEIVE) == 0x0) { }; return (inp(RS232PORT)); }
/* * leds.h -- control the led's on a Motorola mc68ec0x0 board. */ #ifndef __LEDS_H__ #define __LEDS_H__ #define LED_ADDR 0xd00003 #define LED_0 ~0x1 #define LED_1 ~0x2 #define LED_2 ~0x4 #define LED_3 ~0x8 #define LED_4 ~0x10 #define LED_5 ~0x20 #define LED_6 ~0x40 #define LED_7 ~0x80 #define LEDS_OFF 0xff #define LEDS_ON 0x0 #define FUDGE(x) ((x >= 0xa && x <= 0xf) ? (x + 'a') & 0x7f : (x + '0') & 0x7f) extern void led_putnum( char ); #endif /* __LEDS_H__ */ /* * leds.c -- control the led's on a Motorola mc68ec0x0 (IDP)board. */ #include "leds.h" void zylons(); void led_putnum(); /* * led_putnum -- print a hex number on the LED. the value of num must be a char with * the ascii value. ie... number 0 is '0', a is 'a', ' ' (null) clears * the led display. * Setting the bit to 0 turns it on, 1 turns it off. * the LED's are controlled by setting the right bit mask in the base * address. * The bits are: * [d.p | g | f | e | d | c | b | a ] is the byte. * * The locations are: * * a * ----- * f | | b * | g | * ----- * | | * e | | c * ----- * d . d.p (decimal point) */ void led_putnum ( num ) char num; { static unsigned char *leds = (unsigned char *)LED_ADDR; static unsigned char num_bits [18] = { 0xff, /* clear all */ 0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x98, /* numbers 0-9 */ 0x98, 0x20, 0x3, 0x27, 0x21, 0x4, 0xe /* letters a-f */ }; if (num >= '0' && num <= '9') num = (num - '0') + 1; if (num >= 'a' && num <= 'f') num = (num - 'a') + 12; if (num == ' ') num = 0; *leds = num_bits[num]; } /* * zylons -- draw a rotating pattern. NOTE: this function never returns. */ void zylons() { unsigned char *leds = (unsigned char *)LED_ADDR; unsigned char curled = 0xfe; while (1) { *leds = curled; curled = (curled >> 1) | (curled << 7); delay ( 200 ); } }
Go to the first, previous, next, last section, table of contents.