Commit b3a4bd82 authored by Hellwig Geisse's avatar Hellwig Geisse
Browse files

add RISC5 simulator

parent f722c5dc
......@@ -3,7 +3,7 @@ Current status of development
1) RISC5 simulator
sim-RISC5 tbd
sim-RISC5 done
2) Project Oberon V2 on RISC5 simulator
kit/install/sim tbd
# Makefile for Oberon RISC5 simulator
BUILD = ../build
CC = gcc
CFLAGS = -g -Wall -I./getline -I/usr/X11R7/include
LDFLAGS = -g -L./getline -L/usr/X11R7/lib -Wl,-rpath -Wl,/usr/X11R7/lib
LDLIBS = -lgetline -lX11 -lpthread -lm
SRCS = sim.c common.c muldiv.c fpu.c graph.c
OBJS = $(patsubst %.c,%.o,$(SRCS))
BIN = sim-RISC5
all: $(BIN)
install: $(BIN)
mkdir -p $(BUILD)/bin
cp $(BIN) $(BUILD)/bin
$(MAKE) -C getline
$(BIN): $(OBJS) getline/libgetline.a
$(CC) $(LDFLAGS) -o $(BIN) $(OBJS) $(LDLIBS)
%.o: %.c
$(CC) $(CFLAGS) -o $@ -c $<
$(CC) -MM -MG $(CFLAGS) $(SRCS) >depend.mak
-include depend.mak
$(MAKE) -C getline clean
rm -f *~ $(OBJS) $(BIN) depend.mak
* common.c -- common definitions and functions
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "common.h"
#include "graph.h"
void error(char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
printf("Error: ");
vprintf(fmt, ap);
* common.h -- common definitions and functions
#ifndef _COMMON_H_
#define _COMMON_H_
typedef enum { false = 0, true = 1 } Bool;
typedef unsigned int Word;
typedef unsigned char Byte;
void error(char *fmt, ...);
#endif /* _COMMON_H_ */
* fpu.c -- floating-point unit
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <fenv.h>
#include "common.h"
#include "fpu.h"
typedef union {
Word w;
float f;
} FP_Union;
Word fpAdd(Word x, Word y, Bool sub) {
FP_Union X, Y, Z;
X.w = x;
Y.w = y;
if (sub) {
Z.f = X.f - Y.f;
} else {
Z.f = X.f + Y.f;
return Z.w;
Word fpMul(Word x, Word y) {
FP_Union X, Y, Z;
X.w = x;
Y.w = y;
Z.f = X.f * Y.f;
return Z.w;
Word fpDiv(Word x, Word y) {
FP_Union X, Y, Z;
X.w = x;
Y.w = y;
Z.f = X.f / Y.f;
return Z.w;
Word fpFlt(Word x) {
FP_Union Z;
Z.f = (float) (int) x;
return Z.w;
Word fpFlr(Word x) {
FP_Union X;
X.w = x;
return (Word) (int) floorf(X.f);
Word fpGetFlags(void) {
fexcept_t fe;
Word flags;
fegetexceptflag(&fe, FE_ALL_EXCEPT);
flags = ((fe & FE_DIVBYZERO) ? _FP_I_FLAG : 0) |
((fe & FE_INEXACT) ? _FP_X_FLAG : 0) |
((fe & FE_INVALID) ? _FP_V_FLAG : 0) |
((fe & FE_OVERFLOW) ? _FP_O_FLAG : 0) |
((fe & FE_UNDERFLOW) ? _FP_U_FLAG : 0);
return flags;
void fpClrFlags(void) {
* fpu.h -- floating-point unit
#ifndef _FPU_H_
#define _FPU_H_
#define _FP_V_FLAG 0x10 /* invalid */
#define _FP_I_FLAG 0x08 /* infinite */
#define _FP_O_FLAG 0x04 /* overflow */
#define _FP_U_FLAG 0x02 /* underflow */
#define _FP_X_FLAG 0x01 /* inexact */
Word fpAdd(Word x, Word y, Bool sub);
Word fpMul(Word x, Word y);
Word fpDiv(Word x, Word y);
Word fpFlt(Word x);
Word fpFlr(Word x);
Word fpGetFlags(void);
void fpClrFlags(void);
#endif /* _FPU_H_ */
Changes by HG
* renamed getline to gl_getline
Changes from last patch (v38i004 in comp.sources.misc)
* added djgpp support on PCs
* cleanup up __unix__ ifdefs
* added __STDC__ prototypes in header file
* change makefile to build an archive and testgl
* added retry on interrupted read()s
* fixed GO32 keymapping to handles arrow keys properly
Changes from last release (v37i050 in comp.sources.misc)
* Added support for AIX, XENIX, TurboC, gcc (EMX) under OS/2
* Added ^U (kill line) functionality
* Added ESC-B/ESC-F backward/forward one word functionality
* Made it possible to preload history with gl_histadd() before calling
Changes from last release (v28i056 in comp.sources.misc)
* type-ahead saved in BSD mode (was OK in SYSV and POSIX)
* fixed POSIX mode bug and enabled termios use if POSIX defined.
* allow caller to supply a prompt width calculation function so that the
caller can embed escape sequences into the prompt (see gl_strwidth in
the man page).
* added a getline.h header file for inclusion into the caller.
* man page added, thanks to DaviD W. Sanderson (
Changes from previous release (v25i056 and patch v26i092)
* The user no longer calls gl_init() and gl_cleanup(), getline() sets
required terminal modes on entry and resets before returning. This
was necessary to capture changes in terminal modes that the main
program might be making.
* Getline() now looks to see which characters are bound to signal
generation, and when these characters are seen getline() resets
terminal modes before passing on the signal. If the signal handler
returns to getline(), the screen is automatically updated and editing
can continue.
* The toggle key for overwrite mode has been moved from ^G to ^O
* All code is now classic rather than ANSI C, so any compiler should
be able to handle it.
* ^Y now yanks back previously kill'ed (^K) text starting at the
current location.
* ^R/^S begin reverse and forward incremental searches through the
history list.
* The programmer must add buffers onto the history list by calling
gl_addhist(char *buffer). This function makes copies of the buffer
and adds them to the history list if the buffer is not a blank line
and if the buffer is different than the last item saved (so the
program need not check for these conditions)
* The main program can specify the screen width to use with a call to
gl_setwidth(int width)
* Getline now insists that both the input and output are connected to
a terminal. If this is not the case, an error message is written and
the program is terminated. The main program should check for this
case and use buffered IO (stdio) for non-interactive sessions.
# Makefile for the getline library
CC = gcc
LDLIBS = -lgetline
.PHONY: all install clean
all: libgetline.a testgl
install: libgetline.a testgl
testgl: libgetline.a testgl.o
$(CC) $(LDFLAGS) $(CFLAGS) -o testgl testgl.o $(LDLIBS)
libgetline.a: getline.o
ar cr libgetline.a getline.o
%.o: %.c
$(CC) $(CFLAGS) -o $@ -c $<
rm -f *~ *.o *.a testgl
*************************** Motivation **********************************
Many interactive programs read input line by line, but would like to
provide line editing and history functionality to the end-user that
runs the program.
The input-edit package provides that functionality. As far as the
programmer is concerned, the program only asks for the next line
of input. However, until the user presses the RETURN key they can use
emacs-style line editing commands and can traverse the history of lines
previously typed.
Other packages, such as GNU's readline, have greater capability but are
also substantially larger. Input-edit is small, since it uses neither
stdio nor any termcap features, and is also quite portable. It only uses
\b to backspace and \007 to ring the bell on errors. Since it cannot
edit multiple lines it scrolls long lines left and right on the same line.
Input edit uses classic (not ANSI) C, and should run on any Unix
system (BSD, SYSV or POSIX), PC's under DOS with MSC, TurboC or djgpp,
PC's under OS/2 with gcc (EMX), or Vax/VMS. Porting the package to new
systems basicaly requires code to read a character when it is typed without
echoing it, everything else should be OK.
I have run the package on:
DECstation 5000, Ultrix 4.3 with cc 2.1 and gcc 2.3.3
Sun Sparc 2, SunOS 4.1.1, with cc
SGI Iris, IRIX System V.3, with cc
PC using DOS with MSC
The description below is broken into two parts, the end-user (editing)
interface and the programmer interface. Send bug reports, fixes and
enhancements to:
Chris Thewalt (
Thanks to the following people who have provided enhancements and fixes:
Ron Ueberschaer, Christoph Keller, Scott Schwartz, Steven List,
DaviD W. Sanderson, Goran Bostrom, Michael Gleason, Glenn Kasten,
Edin Hodzic, Eric J Bivona, Kai Uwe Rommel, Danny Quah, Ulrich Betzler
PS: I don't have, and don't want to add, a vi mode, sorry.
************************** End-User Interface ***************************
Entering printable keys generally inserts new text into the buffer (unless
in overwrite mode, see below). Other special keys can be used to modify
the text in the buffer. In the description of the keys below, ^n means
Control-n, or holding the CONTROL key down while pressing "n". Errors
will ring the terminal bell.
^A/^E : Move cursor to beginning/end of the line.
^F/^B : Move cursor forward/backward one character.
ESC-F : Move cursor forward one word.
ESC-B : Move cursor backward one word.
^D : Delete the character under the cursor.
^H, DEL : Delete the character to the left of the cursor.
^K : Kill from the cursor to the end of line.
^L : Redraw current line.
^O : Toggle overwrite/insert mode. Initially in insert mode. Text
added in overwrite mode (including yanks) overwrite
existing text, while insert mode does not overwrite.
^P/^N : Move to previous/next item on history list.
^R/^S : Perform incremental reverse/forward search for string on
the history list. Typing normal characters adds to the current
search string and searches for a match. Typing ^R/^S marks
the start of a new search, and moves on to the next match.
Typing ^H or DEL deletes the last character from the search
string, and searches from the starting location of the last search.
Therefore, repeated DEL's appear to unwind to the match nearest
the point at which the last ^R or ^S was typed. If DEL is
repeated until the search string is empty the search location
begins from the start of the history list. Typing ESC or
any other editing character accepts the current match and
loads it into the buffer, terminating the search.
^T : Toggle the characters under and to the left of the cursor.
^U : Deletes the entire line
^Y : Yank previously killed text back at current location. Note that
this will overwrite or insert, depending on the current mode.
TAB : By default adds spaces to buffer to get to next TAB stop
(just after every 8th column), although this may be rebound by the
programmer, as described below.
NL, CR : returns current buffer to the program.
DOS and ANSI terminal arrow key sequences are recognized, and act like:
up : same as ^P
down : same as ^N
left : same as ^B
right : same as ^F
************************** Programmer Interface ***************************
The programmer accesses input-edit through these functions, and optionally
through three additional function pointer hooks. The four functions are:
char *gl_getline(char *prompt)
Prints the prompt and allows the user to edit the current line. A
pointer to the line is returned when the user finishes by
typing a newline or a return. Unlike GNU readline, the returned
pointer points to a static buffer, so it should not be free'd, and
the buffer contains the newline character. The user enters an
end-of-file by typing ^D on an empty line, in which case the
first character of the returned buffer is '\0'. Getline never
returns a NULL pointer. The getline functions sets terminal modes
needed to make it work, and resets them before returning to the
caller. The getline function also looks for characters that would
generate a signal, and resets the terminal modes before raising the
signal condition. If the signal handler returns to getline,
the screen is automatically redrawn and editing can continue.
Getline now requires both the input and output stream be connected
to the terminal (not redirected) so the main program should check
to make sure this is true. If input or output have been redirected
the main program should use buffered IO (stdio) rather than
the slow 1 character read()s that getline uses.
void gl_setwidth(int width)
Set the width of the terminal to the specified width. The default
width is 80 characters, so this function need only be called if the
width of the terminal is not 80. Since horizontal scrolling is
controlled by this parameter it is important to get it right.
void gl_histadd(char *buf)
The gl_histadd function checks to see if the buf is not empty or
whitespace, and also checks to make sure it is different than
the last saved buffer to avoid repeats on the history list.
If the buf is a new non-blank string a copy is made and saved on
the history list, so the caller can re-use the specified buf.
void gl_strwidth(size_t (*func)())
The gl_strwidth function allows the caller to supply a pointer to
a prompt width calculation function (strlen by default). This
allows the caller to embed escape sequences in the prompt and then
tell getline how many screen spaces the prompt will take up.
The main loop in testgl.c, included in this directory, shows how the
input-edit package can be used:
extern char *gl_getline();
extern void gl_histadd();
char *p;
do {
p = gl_getline("PROMPT>>>> ");
fputs(p, stdout);
} while (*p != 0);
In order to allow the main program to have additional access to the buffer,
to implement things such as completion or auto-indent modes, three
function pointers can be bound to user functions to modify the buffer as
described below. By default gl_in_hook and gl_out_hook are set to NULL,
and gl_tab_hook is bound to a function that inserts spaces until the next
logical tab stop is reached. The user can reassign any of these pointers
to other functions. Each of the functions bound to these hooks receives
the current buffer as the first argument, and must return the location of
the leftmost change made in the buffer. If the buffer isn't modified the
functions should return -1. When the hook function returns the screen is
updated to reflect any changes made by the user function.
int (*gl_in_hook)(char *buf)
If gl_in_hook is non-NULL the function is called each time a new
buffer is loaded. It is called when getline is entered, with an
empty buffer, it is called each time a new buffer is loaded from
the history with ^P or ^N, and it is called when an incremental
search string is accepted (when the search is terminated). The
buffer can be modified and will be redrawn upon return to getline().
int (*gl_out_hook)(char *buf)
If gl_out_hook is non-NULL it is called when a line has been
completed by the user entering a newline or return. The buffer
handed to the hook does not yet have the newline appended. If the
buffer is modified the screen is redrawn before getline returns the
buffer to the caller.
int (*gl_tab_hook)(char *buf, int prompt_width, int *cursor_loc)
If gl_tab_hook is non-NULL, it is called whenever a tab is typed.
In addition to receiving the buffer, the current prompt width is
given (needed to do tabbing right) and a pointer to the cursor
offset is given, where a 0 offset means the first character in the
line. Not only does the cursor_loc tell the programmer where the
TAB was received, but it can be reset so that the cursor will end
up at the specified location after the screen is redrawn.
.\" Note that in silly ol' [nt]roff, even trailing white space is
.\" significant. I went through and eliminated it.
.\" I adopted a convention of using a bold 'getline' when referring to
.\" the whole package, but an italic 'getline' when referring to the
.\" specific function.
.\" Note that in [nt]roff that "-" is a hyphen, while "\-" is a dash.
.\" I adjusted some source text lines to keep them short (I keep line
.\" numbers turned on in vi, so I only have 72 cols w/o wrapping).
.\" It's too bad that getline() doesn't realloc() the buffer as
.\" necessary. Then it could have an unlimited input line length.
.\" Note that .RI et al are limited in how many args they can take.
.\" I corrected gl_addhist to gl_histadd, which is what is actually
.\" used! Perhaps it really should be gl_addhist, to preserve the
.\" gl_<verb><object> pattern in the other function names.
.\" I tried to rephrase certain sections to avoid the passive voice.
.\" I find the active voice much easier to understand, since I can tell
.\" more easily what acts on what.
getline \- command-line editing library with history
.RI "char *gl_getline(char *" prompt );
.RI "void gl_histadd(char *" line );
.RI "void gl_setwidth(int " width );
.RI "void gl_strwidth(int " (*width_func)() );
.RI "extern int (*gl_in_hook)(char *" buf );
.RI "extern int (*gl_out_hook)(char *" buf );
.RI "extern int (*gl_tab_hook)(char *" buf ,
.RI "int " prompt_width ", int *" cursor_loc );
.B getline
package is a set of library routines that implement
an editable command-line history.
.B "Programming Interface"
.I getline
returns a pointer to a line of text read from the user,
prompting the user with the specified
.IR prompt .
The pointer refers to a static buffer allocated by the
.B getline
Clients may assume that the pointer
.I getline
returns is always the same, and is never NULL.
The buffer
.I getline
returns to the caller contains the terminating newline character,
except on end of file,
in which case the first character in the buffer is 0
.RB ( NUL ).
File descriptors 0 and 1 must be connected to the terminal
(not redirected),
so the caller should check for this condition (using
.IR isatty (\|))
and call stdio routines if the session is not interactive.
.I gl_histadd
adds the given
.I line
to the
.B getline
history list if the
.I line
is not empty and if it is different from the last line
in the history list
(so the caller need not check for these conditions).
.I gl_histadd
makes its own copies of all the lines it adds to the history list.
This is so the caller can reuse the buffer it supplies to
.IR gl_histadd .
.I gl_setwidth
specifies the terminal
.I width
to use for horizontal scrolling.
The default value is 80 columns,
and it is important to properly specify the
.I width
or lines may wrap inadvertently.
.I gl_strwidth
allows the application program to supply a prompt string width calculation
function that returns the number of screen positions used by the argument
By default strlen is used, but if the prompt contains escape sequences the user
can bind a function that returns the actual number of screen postitions
used by the argument string, not including the escape characters.
In addition to the function call interface,
.B getline
has three externally accessible function pointers
that act as hooks if bound to user-defined functions.
.B getline
supplies each of the functions with a pointer to the current buffer
as the first argument,
and expects the return value to be the index
of the first change the function made in the buffer
(or \-1 if the function did not alter the buffer).
After the functions return,
.B getline
updates the screen as necessary.
.\" DWS comment --
Note that the functions may not alter the size of the buffer.
Indeed, they do not even know how large the buffer is!
.I getline
.I gl_in_hook
(initially NULL)
each time it loads a new buffer.
More precisely, this is
at the first call to
.I getline
(with an empty buffer)
each time the user enters a new buffer from the history list (with
.B ^P
.BR ^N )
when the user accepts an incremental search string
(when the user terminates the search).
.I getline
.I gl_out_hook
(initially NULL)
when a line has been completed by the user entering a
.RB (\| ^J \|)
.RB (\| ^M \|).