Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'libgloss/doc/porting.texi')
-rw-r--r--libgloss/doc/porting.texi2053
1 files changed, 2053 insertions, 0 deletions
diff --git a/libgloss/doc/porting.texi b/libgloss/doc/porting.texi
new file mode 100644
index 000000000..babc22eea
--- /dev/null
+++ b/libgloss/doc/porting.texi
@@ -0,0 +1,2053 @@
+\input texinfo @c -*- Texinfo -*-
+@setfilename porting.info
+@settitle Embed with GNU
+
+@c
+@c This file documents the process of porting the GNU tools to an
+@c embedded environment.
+@c
+
+@finalout
+@setchapternewpage off
+@iftex
+@raggedbottom
+@global@parindent=0pt
+@end iftex
+
+@titlepage
+@title Embed With GNU
+@subtitle Porting The GNU Tools To Embedded Systems
+@sp 4
+@subtitle Spring 1995
+@subtitle Very *Rough* Draft
+@author Rob Savoye - Cygnus Support
+@page
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1993, 1994, 1995 Cygnus Support
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end titlepage
+
+@ifinfo
+@format
+START-INFO-DIR-ENTRY
+* Embed with GNU: (porting-). Embed with GNU
+END-INFO-DIR-ENTRY
+@end format
+Copyright (c) 1993, 1994, 1995 Cygnus Support
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+
+@node Top
+@top Embed with GNU
+
+@end ifinfo
+@strong{Rough Draft}
+
+The goal of this document is to gather all the information needed to
+port the GNU tools to a new embedded target in one place. This will
+duplicate some info found in the other manual for the GNU tools, but
+this should be all you'll need.
+
+@menu
+* Libgloss:: Libgloss, a library of board support packages.
+* GCC:: Porting GCC/G++ to a new embedded target.
+* Libraries:: Making Newlib run on an new embedded target.
+* GDB:: Making GDB understand a new back end.
+* Binutils:: Using the GNU binary utilities.
+* Code Listings:: Listings of the commented source code from the
+ text.
+@end menu
+
+@node Libgloss, GCC, Top, Top
+@chapter Libgloss
+Libgloss is a library for all the details that usually get glossed over.
+This library refers to things like startup code, and usually I/O support
+for @code{gcc} and @code{C library}. The C library used through out
+this manual is @code{newlib}. Newlib is a ANSI conforming C library
+developed by Cygnus Support. Libgloss could easily be made to
+support other C libraries, and it can be used standalone as well. The
+standalone configuration is typically used when bringing up new
+hardware, or on small systems.
+
+For a long time, these details were part of newlib. This approach worked
+well when a complete tool chain only had to support one system. A tool
+chain refers to the series of compiler passes required to produce a
+binary file that will run on an embedded system. For C, the passes are
+cpp, gcc, gas, ld. Cpp is the preprocessor, which process all the header
+files and macros. Gcc is the compiler, which produces assembler from the
+processed C files. Gas assembles the code into object files, and then ld
+combines the object files and binds the code to addresses and produces
+the final executable image.
+
+Most of the time a tool chain does only have to support one target
+execution environment. An example of this would be a tool chain for the
+AMD 29k processor family. All of the execution environments for this
+processor are have the same interface, the same memory map, and the same
+I/O code. In this case all of the support code is in newlib/sys/FIXME.
+Libgloss's creation was forced initially be the @code{cpu32} processor
+family. There are many different execution environments for this line,
+and they vary wildly. newlib itself has only has a few dependencies that
+it needs for each target. These are explained later in this doc. The
+hardware dependent part of newlib was reorganized into a separate
+directory structure within newlib called the stub dirs. It was initially
+called this because most of the routines newlib needs for a target were
+simple stubs that do nothing, but return a value to the application. They
+only exist so the linker can produce a final executable image. This work
+was done during the early part of 1993.
+
+After a while it became apparent that this approach of isolating the
+hardware and systems files together made sense. Around this same time
+the stub dirs were made to run standalone, mostly so it could also be
+used to support GDB's remote debugging needs. At this time it was
+decided to move the stub dirs out of newlib and into it's own separate
+library so it could be used standalone, and be included in various other
+GNU tools without having to bring in all of newlib, which is large. The
+new library is called Libgloss, for Gnu Low-level OS support.
+
+@menu
+* Supported targets:: What targets libgloss currently
+ supports.
+* Building libgloss:: How to configure and built libgloss
+ for a target.
+@end menu
+
+@node Supported targets, Building libgloss, Libgloss, Libgloss
+@subsection Supported Targets
+Currently libgloss is being used for the following targets:
+
+@menu
+* Sparclite:: Fujitsu's sparclite.
+* CPU32:: Various m68k based targets.
+* Mips:: Mips code based targets.
+* PA-RISC:: Precision Risc Organization..
+@end menu
+
+@node Sparclite, CPU32, , Supported targets
+@subsection Sparclite Targets Supported
+@c FIXME: put links to the docs in etc/targetdoc
+This is for the Fujitsu Sparclite family of processors. Currently this
+covers the ex930, ex931, ex932, ex933, and the ex934. In addition to the
+I/O code a startup file, this has a GDB debug-stub that gets linked into
+your application. This is an exception handler style debug stub. For
+more info, see the section on Porting GDB. @ref{GDB,,Porting GDB}.
+
+The Fujitsu eval boards use a host based terminal program to load and
+execute programs on the target. This program, @code{pciuh} is relatively
+new (in 1994) and it replaced the previous ROM monitor which had the
+shell in the ROM. GDB uses the the GDB remote protocol, the relevant
+source files from the gdb sources are remote-sparcl.c. The debug stub is
+part of libgloss and is called sparcl-stub.c.
+
+@node CPU32, Mips, Sparclite, Supported targets
+@subsection Motorola CPU32 Targets supported
+This refers to Motorola's m68k based CPU32 processor family. The crt0.S
+startup file should be usable with any target environment, and it's
+mostly just the I/O code and linker scripts that vary. Currently there
+is support for the Motorola MVME line of 6U VME boards and IDP
+line of eval boards. All of the
+Motorola VME boards run @code{Bug}, a ROM based debug monitor.
+This monitor has the feature of using user level traps to do I/O, so
+this code should be portable to other MVME boards with little if any
+change. The startup file also can remain unchanged. About the only thing
+that varies is the address for where the text section begins. This can
+be accomplished either in the linker script, or on the command line
+using the @samp{-Ttext [address]}.
+
+@c FIXME: Intermetrics or ISI wrote rom68k ?
+There is also support for the @code{rom68k} monitor as shipped on
+Motorola's IDP eval board line. This code should be portable across the
+range of CPU's the board supports. There is also GDB support for this
+target environment in the GDB source tree. The relevant files are
+gdb/monitor.c, monitor.h, and rom58k-rom.c. The usage of these files is
+discussed in the GDB section.
+
+@node Mips, PA-RISC, CPU32, Supported targets
+@subsection Mips core Targets Supported
+The Crt0 startup file should run on any mips target that doesn't require
+additional hardware initialization. The I/O code so far only supports a
+custom LSI33k based RAID disk controller board. It should easy to
+change to support the IDT line of eval boards. Currently the two
+debugging protocols supported by GDB for mips targets is IDT's mips
+debug protocol, and a customized hybrid of the standard GDB remote
+protocol and GDB's standard ROM monitor support. Included here is the
+debug stub for the hybrid monitor. This supports the LSI33k processor,
+and only has support for the GDB protocol commands @code{g}, @code{G},
+@code{m}, @code{M}, which basically only supports the register and
+memory reading and writing commands. This is part of libgloss and is
+called lsi33k-stub.c.
+
+The crt0.S should also work on the IDT line of eval boards, but has only
+been run on the LSI33k for now. There is no I/O support for the IDT eval
+board at this time. The current I/O code is for a customized version of
+LSI's @code{pmon} ROM monitor. This uses entry points into the monitor,
+and should easily port to other versions of the pmon monitor. Pmon is
+distributed in source by LSI.
+
+@node PA-RISC, , Mips, Supported targets
+@subsection PA-RISC Targets Supported
+This supports the various boards manufactured by the HP-PRO consortium.
+This is a group of companies all making variations on the PA-RISC
+processor. Currently supported are ports to the WinBond @samp{Cougar}
+board based around their w89k version of the PA. Also supported is the
+Oki op50n processor.
+
+There is also included, but never built an unfinished port to the HP 743
+board. This board is the main CPU board for the HP700 line of industrial
+computers. This target isn't exactly an embedded system, in fact it's
+really only designed to load and run HP-UX. Still, the crt0.S and I/O
+code are fully working. It is included mostly because their is a barely
+functioning exception handler GDB debug stub, and I hope somebody could
+use it. The other PRO targets all use GDB's ability to talk to ROM
+monitors directly, so it doesn't need a debug stub. There is also a
+utility that will produce a bootable file by HP's ROM monitor. This is
+all included in the hopes somebody else will finish it. :-)
+
+Both the WinBond board and the Oki board download srecords. The WinBond
+board also has support for loading the SOM files as produced by the
+native compiler on HP-UX. WinBond supplies a set of DOS programs that
+will allow the loading of files via a bidirectional parallel port. This
+has never been tested with the output of GNU SOM, as this manual is
+mostly for Unix based systems.
+
+@node Building libgloss, , Supported targets, Libgloss
+@subsection Configuring and building libgloss.
+
+Libgloss uses an autoconf based script to configure. Autoconf scripts
+are portable shell scripts that are generated from a configure.in file.
+Configure input scripts are based themselves on m4. Most configure
+scripts run a series of tests to determine features the various
+supported features of the target. For features that can't be determined
+by a feature test, a makefile fragment is merged in. The configure
+process leaves creates a Makefile in the build directory. For libgloss,
+there are only a few configure options of importance. These are --target
+and --srcdir.
+
+Typically libgloss is built in a separate tree just for objects. In this
+manner, it's possible to have a single source tree, and multiple object
+trees. If you only need to configure for a single target environment,
+then you can configure in the source tree. The argument for --target is
+a config string. It's usually safest to use the full canonical opposed
+to the target alias. So, to configure for a CPU32 (m68k) with a separate
+source tree, use:
+
+@smallexample
+../src/libgloss/configure --verbose --target m68k-coff
+@end smallexample
+
+The configure script is in the source tree. When configure is invoked
+it will determine it's own source tree, so the --srcdir is would be
+redundant here.
+
+Once libgloss is configured, @code{make} is sufficient to build it. The
+default values for @code{Makefiles} are typically correct for all
+supported systems. The test cases in the testsuite will also built
+automatically as opposed to a @code{make check}, where test binaries
+aren't built till test time. This is mostly cause the libgloss
+testsuites are the last thing built when building the entire GNU source
+tree, so it's a good test of all the other compilation passes.
+
+The default values for the Makefiles are set in the Makefile fragment
+merged in during configuration. This fragment typically has rules like
+
+@smallexample
+CC_FOR_TARGET = `if [ -f $$@{OBJROOT@}/gcc/xgcc ] ; \
+ then echo $@{OBJROOT@}/gcc/xgcc -B$@{OBJROOT@}/gcc/ ; \
+ else t='$@{program_transform_name@}'; echo gcc | sed -e '' $$t ; fi`
+@end smallexample
+
+Basically this is a runtime test to determine whether there are freshly
+built executables for the other main passes of the GNU tools. If there
+isn't an executable built in the same object tree, then
+@emph{transformed}the generic tool name (like gcc) is transformed to the
+name typically used in GNU cross compilers. The names are
+typically based on the target's canonical name, so if you've configured
+for @code{m68k-coff} the transformed name is @code{m68k-coff-gcc} in
+this case. If you install with aliases or rename the tools, this won't
+work, and it will always look for tools in the path. You can force the a
+different name to work by reconfiguring with the
+@code{--program-transform-name} option to configure. This option takes a
+sed script like this @code{-e s,^,m68k-coff-,} which produces tools
+using the standard names (at least here at Cygnus).
+
+The search for the other GNU development tools is exactly the same idea.
+This technique gets messier when build options like @code{-msoft-float}
+support are used. The Makefile fragments set the @code{MUTILIB}
+variable, and if it is set, the search path is modified. If the linking
+is done with an installed cross compiler, then none of this needs to be
+used. This is done so libgloss will build automatically with a fresh,
+and uninstalled object tree. It also makes it easier to debug the other
+tools using libgloss's test suites.
+
+@node GCC, Libraries, Libgloss, Top
+@chapter Porting GCC
+
+Porting GCC requires two things, neither of which has anything to do
+with GCC. If GCC already supports a processor type, then all the work in
+porting GCC is really a linker issue. All GCC has to do is produce
+assembler output in the proper syntax. Most of the work is done by the
+linker, which is described elsewhere.
+
+Mostly all GCC does is format the command line for the linker pass. The
+command line for GCC is set in the various config subdirectories of gcc.
+The options of interest to us are @code{CPP_SPEC} and
+@code{STARTFILE_SPEC}. CPP_SPEC sets the builtin defines for your
+environment. If you support multiple environments with the same
+processor, then OS specific defines will need to be elsewhere.
+@c FIXME: Check these names
+
+@code{STARTFILE_SPEC}
+
+Once you have linker support, GCC will be able to produce a fully linked
+executable image. The only @emph{part} of GCC that the linker wants is a
+crt0.o, and a memory map. If you plan on running any programs that do
+I/O of any kind, you'll need to write support for the C library, which
+is described elsewhere.
+
+@menu
+* Overview:: An overview as to the compilation passes.
+* Options:: Useful GCC options for embedded systems.
+@end menu
+
+@node Overview, Options, , GCC
+@subsection Compilation passes
+
+GCC by itself only compiles the C or C++ code into assembler. Typically
+GCC invokes all the passes required for you. These passes are cpp, cc1,
+gas, ld. @code{cpp} is the C preprocessor. This will merge in the
+include files, expand all macros definitions, and process all the
+@code{#ifdef} sections. To see the output of ccp, invoke gcc with the
+@code{-E} option, and the preprocessed file will be printed on the
+stdout. cc1 is the actual compiler pass that produces the assembler for
+the processed file. GCC is actually only a driver program for all the
+compiler passes. It will format command line options for the other passes.
+The usual command line GCC uses for the final link phase will have LD
+link in the startup code and additional libraries by default.
+
+GNU AS started it's life to only function as a compiler pass, but
+these days it can also be used as a source level assembler. When used as
+a source level assembler, it has a companion assembler preprocessor
+called @code{gasp}. This has a syntax similar to most other assembler
+macros packages. GAS emits a relocatable object file from the assembler
+source. The object file contains the executable part of the application,
+and debug symbols.
+
+LD is responsible for resolving the addresses and symbols to something
+that will be fully self-contained. Some RTOS's use relocatable object
+file formats like @code{a.out}, but more commonly the final image will
+only use absolute addresses for symbols. This enables code to be burned
+into PROMS as well. Although LD can produce an executable image, there
+is usually a hidden object file called @code{crt0.o} that is required as
+startup code. With this startup code and a memory map, the executable
+image will actually run on the target environment. @ref{Crt0,,Startup
+Files}.
+
+The startup code usually defines a special symbol like @code{_start}
+that is the default base address for the application, and the first
+symbol in the executable image. If you plan to use any routines from the
+standard C library, you'll also need to implement the functions that
+this library is dependent on. @ref{Libraries,,Porting Newlib}.
+
+@node Options, , Overview, GCC
+@c FIXME: Need stuff here about -fpic, -Ttext, etc...
+
+Options for the various development tools are covered in more detail
+elsewhere. Still, the amount of options can be an overwhelming amount of
+stuff, so the options most suited to embedded systems are summarized
+here. If you use GCC as the main driver for all the passes, most of the
+linker options can be passed directly to the compiler. There are also
+GCC options that control how the GCC driver formats the command line
+arguments for the linker.
+
+@menu
+* GCC Options:: Options for the compiler.
+* GAS Options:: Options for the assembler.
+* LD Options:: Options for the linker.
+@end menu
+
+@node GCC Options, GAS Options, , Options
+Most of the GCC options that we're interested control how the GCC driver
+formats the options for the linker pass.
+
+@c FIXME: this section is still under work.
+@table @code
+@item -nostartfiles
+@item -nostdlib
+@item -Xlinker
+Pass the next option directly to the linker.
+
+@item -v
+@item -fpic
+@end table
+
+@node GAS Options, LD Options, GCC Options, Options
+@c FIXME: Needs stuff here
+
+@node LD Options, , GAS Options, Options
+@c FIXME: Needs stuff here
+
+
+@node Libraries, GDB, GCC, Top
+@chapter Porting newlib
+
+@menu
+* Crt0:: Crt0.S.
+* Linker Scripts:: Linker scripts for memory management.
+* What to do now:: Tricks for manipulating formats.
+* Libc:: Making libc work.
+@end menu
+
+@node Crt0, Linker Scripts, , Libraries
+@section Crt0, the main startup file
+
+To make a program that has been compiled with GCC to run, you
+need to write some startup code. The initial piece of startup code is
+called a crt0. (C RunTime 0) This is usually written in assembler, and
+it's object gets linked in first, and bootstraps the rest of the
+application when executed. This file needs to do the following things.
+
+@enumerate
+@item
+Initialize anything that needs it. This init section varies. If you are
+developing an application that gets download to a ROM monitor, then
+there is usually no need for any special initialization. The ROM monitor
+handles it for you.
+
+If you plan to burn your code in a ROM, then the crt0 typically has to
+do all the hardware initialization that is required to run an
+application. This can include things like initializing serial ports or
+run a memory check. It all depends on the hardware.
+
+@item
+Zero the BSS section. This is for uninitialized data. All the addresses in
+this section need to be initialized to zero so that programs that forget
+to check new variables default value will get unpredictable results.
+
+@item
+Call main()
+This is what basically starts things running. If your ROM monitor
+supports it, then first setup argc and argv for command line arguments
+and an environment pointer. Then branch to main(). For G++ the the main
+routine gets a branch to __main inserted by the code generator at the
+very top. __main() is used by G++ to initialize it's internal tables.
+__main() then returns back to your original main() and your code gets
+executed.
+
+@item
+Call exit()
+After main() has returned, you need to cleanup things and return control
+of the hardware from the application. On some hardware, there is nothing
+to return to, especially if your program is in ROM. Sometimes the best
+thing to do in this case is do a hardware reset, or branch back to the
+start address all over again.
+
+When there is a ROM monitor present, usually a user trap can be called
+and then the ROM takes over. Pick a safe vector with no side
+effects. Some ROMs have a builtin trap handler just for this case.
+@end enumerate
+portable between all the m68k based boards we have here.
+@ref{crt0.S,,Example Crt0.S}.
+
+
+@smallexample
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+@end smallexample
+These we'll use later.
+
+@smallexample
+/* These are predefined by new versions of GNU cpp. */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+/* Use the right prefix for global labels. */
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+@end smallexample
+
+These macros are to make this code portable between both @emph{COFF} and
+@emph{a.out}. @emph{COFF} always has an @var{_ (underline)} prepended on
+the front of all global symbol names. @emph{a.out} has none.
+
+@smallexample
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+/* 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)
+@end smallexample
+
+This is for portability between assemblers. Some register names have a
+@var{%} or @var{$} prepended to the register name.
+
+@smallexample
+/*
+ * Set up some room for a stack. We just grab a chunk of memory.
+ */
+ .set stack_size, 0x2000
+ .comm SYM (stack), stack_size
+@end smallexample
+
+Set up space for the stack. This can also be done in the linker script,
+but it typically gets done here.
+
+@smallexample
+/*
+ * Define an empty environment.
+ */
+ .data
+ .align 2
+SYM (environ):
+ .long 0
+@end smallexample
+
+Set up an empty space for the environment. This is bogus on any most ROM
+monitor, but we setup a valid address for it, and pass it to main. At
+least that way if an application checks for it, it won't crash.
+
+@smallexample
+ .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
+@end smallexample
+
+Setup a few global symbols that get used elsewhere. @var{__bss_start}
+needs to be unchanged, as it's setup by the linker script.
+
+@smallexample
+/*
+ * 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
+@end smallexample
+
+The global symbol @code{start} is used by the linker as the default
+address to use for the @code{.text} section. then it zeros the
+@code{.bss} section so the uninitialized data will all be cleared. Some
+programs have wild side effects from having the .bss section let
+uncleared. Particularly it causes problems with some implementations of
+@code{malloc}.
+
+@smallexample
+/*
+ * 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@@-
+@end smallexample
+
+Setup the environment pointer and jump to @code{main()}. When
+@code{main()} returns, it drops down to the @code{exit} routine below.
+
+@smallexample
+/*
+ * _exit -- Exit from the application. Normally we cause a user trap
+ * to return to the ROM monitor for another run.
+ */
+SYM (exit):
+ trap #0
+@end smallexample
+
+Implementing @code{exit} here is easy. Both the @code{rom68k} and @code{bug}
+can handle a user caused exception of @code{zero} with no side effects.
+Although the @code{bug} monitor has a user caused trap that will return
+control to the ROM monitor, this solution has been more portable.
+
+@node Linker Scripts, What to do now, Crt0, Libraries
+@section Linker scripts for memory management
+
+The linker script sets up the memory map of an application. It also
+sets up default values for variables used elsewhere by sbrk() and the
+crt0. These default variables are typically called @code{_bss_start} and
+@code{_end}.
+
+For G++, the constructor and destructor tables must also be setup here.
+The actual section names vary depending on the object file format. For
+@code{a.out} and @code{coff}, the three main sections are @code{.text},
+@code{.data}, and @code{.bss}.
+
+Now that you have an image, you can test to make sure it got the
+memory map right. You can do this by having the linker create a memory
+map (by using the @code{-Map} option), or afterwards by using @code{nm} to
+check a few critical addresses like @code{start}, @code{bss_end}, and
+@code{_etext}.
+
+Here's a breakdown of a linker script for a m68k based target board.
+See the file @code{libgloss/m68k/idp.ld}, or go to the appendixes in
+the end of the manual. @ref{idp.ld,,Example Linker Script}.
+
+@smallexample
+STARTUP(crt0.o)
+OUTPUT_ARCH(m68k)
+INPUT(idp.o)
+SEARCH_DIR(.)
+__DYNAMIC = 0;
+@end smallexample
+
+The @code{STARTUP} command loads the file specified so that it's
+first. In this case it also doubles to load the file as well, because
+the m68k-coff configuration defaults to not linking in the crt0.o by
+default. It assumes that the developer probably has their own crt0.o.
+This behavior is controlled in the config file for each architecture.
+It's a macro called @code{STARTFILE_SPEC}, and if it's set to
+@code{null}, then when @code{gcc} formats it's command line, it doesn't
+add @code{crto.o}. Any file name can be specified here, but the default
+is always @code{crt0.o}.
+
+Course if you only use @code{ld} to link, then the control of whether or
+not to link in @code{crt0.o} is done on the command line. If you have
+multiple crto files, then you can leave this out all together, and link
+in the @code{crt0.o} in the makefile, or by having different linker
+scripts. Sometimes this is done for initializing floating point
+optionally, or to add device support.
+
+The @code{OUTPUT_ARCH} sets architecture the output file is for.
+
+@code{INPUT} loads in the file specified. In this case, it's a relocated
+library that contains the definitions for the low-level functions need
+by libc.a. This could have also been specified on the command line, but
+as it's always needed, it might as well be here as a default.
+@code{SEARCH_DIR} specifies the path to look for files, and
+@code{_DYNAMIC} means in this case there are no shared libraries.
+
+@c FIXME: Check the linker manual to make sure this is accurate.
+@smallexample
+/*
+ * 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
+@}
+@end smallexample
+
+This specifies a name for a section that can be referred to later in the
+script. In this case, it's only a pointer to the beginning of free RAM
+space, with an upper limit at 2M. If the output file exceeds the upper
+limit, it will produce an error message.
+
+@smallexample
+/*
+ * 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)
+ @}
+@end smallexample
+
+Set up the @code{.text} section. In a @code{COFF} file, .text is where
+all the actual instructions are. This also sets up the @emph{CONTRUCTOR}
+and the @emph{DESTRUCTOR} tables for @code{G++}. Notice that the section
+description redirects itself to the @emph{ram} variable setup earlier.
+
+@smallexample
+ .talias : @{ @} > ram
+ .data : @{
+ *(.data)
+ CONSTRUCTORS
+ _edata = .;
+ @} > ram
+@end smallexample
+
+Setup the @code{.data} section. In a @code{coff} file, this is where all
+he initialized data goes. @code{CONSTRUCTORS} is a special command used
+by @code{ld}.
+
+@smallexample
+ .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 ]
+ @}
+@}
+@end smallexample
+
+Setup the @code{.bss} section. In a @code{COFF} file, this is where
+unitialized data goes. The symbols @code{_bss_start} and @code{_end}
+are setup here for use by the @code{crt0.o} when it zero's the
+@code{.bss} section.
+
+
+@node What to do now, Libc, Linker Scripts, Libraries
+@section What to do when you have a binary image
+
+A few ROM monitors load binary images, typically @code{a.out}, but most all
+will load an @code{srecord}. An srecord is an ASCII representation of a binary
+image. At it's simplest, an srecord is an address, followed by a byte
+count, followed by the bytes, and a 2's compliment checksum. A whole
+srecord file has an optional @emph{start} record, and a required @emph{end}
+record. To make an srecord from a binary image, the GNU @code{objcopy} program
+is used. This will read the image and make an srecord from it. To do
+this, invoke objcopy like this: @code{objcopy -O srec infile outfile}. Most
+PROM burners also read srecords or a similar format. Use @code{objdump -i} to
+get a list of support object files types for your architecture.
+
+@node Libc, , What to do now, Libraries
+@section Libraries
+
+This describes @code{newlib}, a freely available libc replacement. Most
+applications use calls in the standard C library. When initially linking
+in libc.a, several I/O functions are undefined. If you don't plan on
+doing any I/O, then you're OK, otherwise they need to be created. These
+routines are read, write, open, close. sbrk, and kill. Open & close
+don't need to be fully supported unless you have a filesystems, so
+typically they are stubbed out. Kill is also a stub, since you can't do
+process control on an embedded system.
+
+Sbrk() is only needed by applications that do dynamic memory
+allocation. It's uses the symbol @code{_end} that is setup in the linker
+script. It also requires a compile time option to set the upper size
+limit on the heap space. This leaves us with read and write, which are
+required for serial I/O. Usually these two routines are written in C,
+and call a lower level function for the actual I/O operation. These two
+lowest level I/O primitives are inbyte() and outbyte(), and are also
+used by GDB back ends if you've written an exception handler. Some
+systems also implement a havebyte() for input as well.
+
+Other commonly included functions are routines for manipulating
+LED's on the target (if they exist) or low level debug help. Typically a
+putnum() for printing words and bytes as a hex number is helpful, as
+well as a low-level print() to output simple strings.
+
+As libg++ uses the I/O routines in libc.a, if read and write work,
+then libg++ will also work with no additional changes.
+
+@menu
+* I/O Support:: Functions that make serial I/O work.
+* Memory Support:: Memory support.
+* Misc Support:: Other needed functions.
+* Debugging:: Useful Debugging Functions
+@end menu
+
+@node I/O Support, Memory Support, , Libc
+@subsection Making I/O work
+
+@node Memory Support, Misc Support, I/O Support, Libc
+@subsection Routines for dynamic memory allocation
+To support using any of the memory functions, you need to implement
+sbrk(). @code{malloc()}, @code{calloc()}, and @code{realloc()} all call
+@code{sbrk()} at there lowest level. @code{caddr_t} is defined elsewhere
+as @code{char *}. @code{RAMSIZE} is presently a compile time option. All
+this does is move a pointer to heap memory and check for the upper
+limit. @ref{glue.c,,Example libc support code}. @code{sbrk()} returns a
+pointer to the previous value before more memory was allocated.
+
+@smallexample
+/* _end is set in the linker command file *
+extern caddr_t _end;/
+
+/* just in case, most boards have at least some memory */
+#ifndef RAMSIZE
+# define RAMSIZE (caddr_t)0x100000
+#endif
+
+/*
+ * 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);
+ @}
+@}
+@end smallexample
+
+@node Misc Support, Debugging, Memory Support, Libc
+@subsection Misc support routines
+
+These are called by @code{newlib} but don't apply to the embedded
+environment. @code{isatty()} is self explanatory. @code{kill()} doesn't
+apply either in an environment withno process control, so it justs
+exits, which is a similar enough behavior. @code{getpid()} can safely
+return any value greater than 1. The value doesn't effect anything in
+@code{newlib} because once again there is no process control.
+
+@smallexample
+/*
+ * 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);
+@}
+
+/*
+ * 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;
+@}
+@end smallexample
+
+@node Debugging, , Misc Support, Libc
+@subsection Useful debugging functions
+
+There are always a few useful functions for debugging your project in
+progress. I typically implement a simple @code{print()} routine that
+runs standalone in liblgoss, with no @code{newlib} support. The I/O
+function @code{outbyte()} can also be used for low level debugging. Many
+times print will work when there are problems that cause @code{printf()} to
+cause an exception. @code{putnum()} is just to print out values in hex
+so they are easier to read.
+
+@smallexample
+/*
+ * 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;
+@}
+@end smallexample
+
+If there are LEDs on the board, they can also be put to use for
+debugging when the serial I/O code is being written. I usually implement
+a @code{zylons()} function, which strobes the LEDS (if there is more
+than one) in sequence, creating a rotating effect. This is convenient
+between I/O to see if the target is still alive. Another useful LED
+function is @code{led_putnum()}, which takes a digit and displays it as
+a bit pattern or number. These usually have to be written in assembler
+for each target board. Here are a number of C based routines that may be
+useful.
+
+@code{led_putnum()} puts a number on a single digit segmented
+LED display. This LED is set by setting a bit mask to an address, where
+1 turns the segment off, and 0 turns it on. There is also a little
+decimal point on the LED display, so it gets the leftmost bit. The other
+bits specify the segment location. The bits look like:
+
+@smallexample
+ [d.p | g | f | e | d | c | b | a ] is the byte.
+@end smallexample
+
+The locations are set up as:
+
+@smallexample
+ a
+ -----
+ f | | b
+ | g |
+ -----
+ | |
+ e | | c
+ -----
+ d
+@end smallexample
+
+This takes a number that's already been converted to a string, and
+prints it.
+
+@smallexample
+#define LED_ADDR 0xd00003
+
+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 );
+ @}
+@}
+@end smallexample
+
+
+@node GDB, Binutils, Libraries, Top
+@chapter Writing a new GDB backend
+
+Typically, either the low-level I/O routines are used for debugging, or
+LEDs, if present. It is much easier to use GDb for debugging an
+application. There are several different techniques used to have GDB work
+remotely. Commonly more than one kind of GDB interface is used to cober
+a wide variety of development needs.
+
+The most common style of GDB backend is an exception handler for
+breakpoints. This is also called a @emph{gdb stub}, and is requires the
+two additional lines of init code in your @code{main()} routine. The GDB
+stubs all use the GDB @emph{remote protocol}. When the application gets a
+breakpoint exception, it communicates to GDB on the host.
+
+Another common style of interfacing GDB to a target is by using an
+existing ROM monitor. These break down into two main kinds, a similar
+protocol to the GDB remote protocol, and an interface that uses the ROM
+monitor directly. This kind has GDB simulating a human operator, and all
+GDB does is work as a command formatter and parser.
+
+@menu
+* GNU remote protocol:: The standard remote protocol.
+* Exception handler:: A linked in exception handler.
+* ROM monitors:: Using a ROM monitor as a backend.
+* Other remote protocols:: Adding support for new protocols.
+@end menu
+
+@node GNU remote protocol, Exception handler, ,GDB
+@section The standard remote protocol
+
+The standard remote protocol is a simple, packet based scheme. A debug
+packet whose contents are @emph{<data>} is encapsulated for transmission
+in the form:
+
+@smallexample
+ $ <data> # CSUM1 CSUM2
+@end smallexample
+
+@emph{<data>} must be ASCII alphanumeric and cannot include characters
+@code{$} or @code{#}. If @emph{<data>} starts with two characters
+followed by @code{:}, then the existing stubs interpret this as a
+sequence number. For example, the command @code{g} is used to read the
+values of the registers. So, a packet to do this would look like
+
+@smallexample
+ $g#67
+@end smallexample
+
+@emph{CSUM1} and @emph{CSUM2} are an ascii representation in hex of an
+8-bit checksum of @emph{<data>}, the most significant nibble is sent first.
+the hex digits 0-9,a-f are used.
+
+A simple protocol is used when communicating with the target. This is
+mainly to give a degree of error handling over the serial cable. For
+each packet transmitted successfully, the target responds with a
+@code{+} (@code{ACK}). If there was a transmission error, then the target
+responds with a @code{-} (@code{NAK}). An error is determined when the
+checksum doesn't match the calculated checksum for that data record.
+Upon reciept of the @code{ACK}, @code{GDB} can then transmit the next
+packet.
+
+Here is a list of the main functions that need to be supported. Each data
+packet is a command with a set number of bytes in the command packet.
+Most commands either return data, or respond with a @code{NAK}. Commands
+that don't return data respond with an @code{ACK}. All data values are
+ascii hex digits. Every byte needs two hex digits to represent t. This
+means that a byte with the value @samp{7} becomes @samp{07}. On a 32 bit
+machine this works out to 8 characters per word. All of the bytes in a
+word are stored in the target byte order. When writing the host side of
+the GDB protocol, be careful of byte order, and make sure that the code
+will run on both big and little endian hosts and produce the same answers.
+
+These functions are the minimum required to make a GDB backend work. All
+other commands are optional, and not supported by all GDB backends.
+
+@table @samp
+@item read registers @code{g}
+
+returns @code{XXXXXXXX...}
+
+Registers are in the internal order for GDB, and the bytes in a register
+are in the same order the machine uses. All values are in sequence
+starting with register 0. All registers are listed in the same packet. A
+sample packet would look like @code{$g#}.
+
+@item write registers @code{GXXXXXXXX...}
+@code{XXXXXXXX} is the value to set the register to. Registers are in
+the internal order for GDB, and the bytes in a register are in the same
+order the machine uses. All values are in sequence starting with
+register 0. All registers values are listed in the same packet. A sample
+packet would look like @code{$G000000001111111122222222...#}
+
+returns @code{ACK} or @code{NAK}
+
+@item read memory @code{mAAAAAAAA,LLLL}
+@code{AAAAAAAA} is address, @code{LLLL} is length. A sample packet would
+look like @code{$m00005556,0024#}. This would request 24 bytes starting
+at address @emph{00005556}
+
+returns @code{XXXXXXXX...}
+@code{XXXXXXXX} is the memory contents. Fewer bytes than requested will
+be returned if only part of the data can be read. This can be determined
+by counting the values till the end of packet @code{#} is seen and
+comparing that with the total count of bytes that was requested.
+
+@item write memory @code{MAAAAAAAA,LLLL:XXXXXXXX}
+@code{AAAAAAAA} is the starting address, @code{LLLL} is the number of
+bytes to be written, and @code{XXXXXXXX} is value to be written. A
+sample packet would look like
+@code{$M00005556,0024:101010101111111100000000...#}
+
+returns @code{ACK} or @code{NAK} for an error. @code{NAK} is also
+returned when only part of the data is written.
+
+@item continue @code{cAAAAAAAAA}
+@code{AAAAAAAA} is address to resume execution at. If @code{AAAAAAAA} is
+omitted, resume at the curent address of the @code{pc} register.
+
+returns the same replay as @code{last signal}. There is no immediate
+replay to @code{cont} until the next breakpoint is reached, and the
+program stops executing.
+
+@item step sAA..AA
+@code{AA..AA} is address to resume
+If @code{AA..AA} is omitted, resume at same address.
+
+returns the same replay as @code{last signal}. There is no immediate
+replay to @code{step} until the next breakpoint is reached, and the
+program stops executing.
+
+@item last signal @code{?}
+
+This returns one of the following:
+
+@itemize @bullet
+@item @code{SAA}
+Where @code{AA} is the number of the last signal.
+Exceptions on the target are converted to the most similar Unix style
+signal number, like @code{SIGSEGV}. A sample response of this type would
+look like @code{$S05#}.
+
+@item TAAnn:XXXXXXXX;nn:XXXXXXXX;nn:XXXXXXXX;
+@code{AA} is the signal number.
+@code{nn} is the register number.
+@code{XXXXXXXX} is the register value.
+
+@item WAA
+The process exited, and @code{AA} is the exit status. This is only
+applicable for certains sorts of targets.
+
+@end itemize
+
+These are used in some GDB backends, but not all.
+
+@item write reg @code{Pnn=XXXXXXXX}
+Write register @code{nn} with value @code{XXXXXXXX}.
+
+returns @code{ACK} or @code{NAK}
+
+@item kill request k
+
+@item toggle debug d
+toggle debug flag (see 386 & 68k stubs)
+
+@item reset r
+reset -- see sparc stub.
+
+@item reserved @code{other}
+On other requests, the stub should ignore the request and send an empty
+response @code{$#<checksum>}. This way we can extend the protocol and GDB
+can tell whether the stub it is talking to uses the old or the new.
+
+@item search @code{tAA:PP,MM}
+Search backwards starting at address @code{AA} for a match with pattern
+PP and mask @code{MM}. @code{PP} and @code{MM} are 4 bytes.
+
+@item general query @code{qXXXX}
+Request info about XXXX.
+
+@item general set @code{QXXXX=yyyy}
+Set value of @code{XXXX} to @code{yyyy}.
+
+@item query sect offs @code{qOffsets}
+Get section offsets. Reply is @code{Text=xxx;Data=yyy;Bss=zzz}
+
+@item console output Otext
+Send text to stdout. The text gets display from the target side of the
+serial connection.
+
+@end table
+
+Responses can be run-length encoded to save space. A @code{*}means that
+the next character is an ASCII encoding giving a repeat count which
+stands for that many repetitions of the character preceding the @code{*}.
+The encoding is n+29, yielding a printable character where n >=3
+(which is where run length encoding starts to win). You can't use a
+value of where n >126 because it's only a two byte value. An example
+would be a @code{0*03} means the same thing as @code{0000}.
+
+@node Exception handler, ROM monitors, GNU remote protocol, GDB
+@section A linked in exception handler
+
+A @emph{GDB stub} consists of two parts, support for the exception
+handler, and the exception handler itself. The exception handler needs
+to communicate to GDB on the host whenever there is a breakpoint
+exception. When GDB starts a program running on the target, it's polling
+the serial port during execution looking for any debug packets. So when
+a breakpoint occurs, the exception handler needs to save state, and send
+a GDB remote protocol packet to GDB on the host. GDB takes any output
+that isn't a debug command packet and displays it in the command window.
+
+Support for the exception handler varies between processors, but the
+minimum supported functions are those needed by GDB. These are functions
+to support the reading and writing of registers, the reading and writing
+of memory, start execution at an address, single step, and last signal.
+Sometimes other functions for adjusting the baud rate, or resetting the
+hardware are implemented.
+
+Once GDB gets the command packet from the breakpoint, it will read a few
+registers and memory locations an then wait for the user. When the user
+types @code{run} or @code{continue} a @code{continue} command is issued
+to the backend, and control returns from the breakpoint routine to the
+application.
+
+@node ROM monitors, Other remote protocols, Exception handler, GDB
+@section Using a ROM monitor as a backend
+GDB also can mimic a human user and use a ROM monitors normal debug
+commands as a backend. This consists mostly of sending and parsing
+@code{ASCII} strings. All the ROM monitor interfaces share a common set
+of routines in @code{gdb/monitor.c}. This supports adding new ROM
+monitor interfaces by filling in a structure with the common commands
+GDB needs. GDb already supports several command ROM monitors, including
+Motorola's @code{Bug} monitor for their VME boards, and the Rom68k
+monitor by Integrated Systems, Inc. for various m68k based boards. GDB
+also supports the custom ROM monitors on the WinBond and Oki PA based
+targets. There is builtin support for loading files to ROM monitors
+specifically. GDB can convert a binary into an srecord and then load it
+as an ascii file, or using @code{xmodem}.
+
+@c FIXME: do I need trademark somethings here ? Is Integrated the right
+@c company?
+
+@node Other remote protocols, ,ROM monitors, GDB
+@section Adding support for new protocols
+@c FIXME: write something here
+
+@node Binutils, Code Listings, GDB, Top
+
+@node Code Listings, idp.ld, Binutils, Top
+@appendix Code Listings
+
+@menu
+* idp.ld:: A m68k linker script.
+* crt0.S:: Crt0.S for an m68k.
+* glue.c:: C based support for for Stdio functions.
+* mvme.S:: Rom monitor based I/O support in assembler.
+* io.c:: C based for memory mapped I/O.
+* leds.c:: C based LED routines.
+@end menu
+
+@node idp.ld, crt0.S, Code Listings, Code Listings
+@section Linker script for the IDP board
+
+This is the linker script script that is used on the Motorola IDP board.
+
+@example
+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 ]
+ @}
+@}
+@end example
+
+@node crt0.S, glue.c, idp.ld, Code Listings
+@section crt0.S - The startup file
+
+@example
+/*
+ * 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
+@end example
+
+@node glue.c, mvme.S, crt0.S, Code Listings
+@section C based "glue" code.
+
+@example
+
+/*
+ * 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;
+@}
+@end example
+
+@node mvme.S, io.c, glue.c, Code Listings
+@section I/O assembler code sample
+
+@example
+/*
+ * 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
+
+@end example
+
+@node io.c, leds.c, mvme.S, Code Listings
+@section I/O code sample
+
+@example
+#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));
+@}
+@end example
+
+@node leds.c, ,io.c, Code Listings
+@section Led control sample
+
+@example
+/*
+ * 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 );
+ @}
+@}
+@end example
+
+@page
+@contents
+@c second page break makes sure right-left page alignment works right
+@c with a one-page toc, even though we don't have setchapternewpage odd.
+@page
+@bye