OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 17 to Rev 18
    Reverse comparison

Rev 17 → Rev 18

/eco32/trunk/stdalone/shpart/iolib.c
0,0 → 1,329
/*
* iolib.c -- I/O library
*/
 
 
#include "types.h"
#include "stdarg.h"
#include "iolib.h"
#include "biolib.h"
 
 
/**************************************************************/
 
/* string functions */
 
 
int strlen(char *str) {
int i;
 
i = 0;
while (*str++ != '\0') {
i++;
}
return i;
}
 
 
void strcpy(char *dst, char *src) {
while ((*dst++ = *src++) != '\0') ;
}
 
 
void memcpy(unsigned char *dst, unsigned char *src, unsigned int cnt) {
while (cnt--) {
*dst++ = *src++;
}
}
 
 
/**************************************************************/
 
/* terminal I/O */
 
 
char getchar(void) {
return getc();
}
 
 
void putchar(char c) {
if (c == '\n') {
putchar('\r');
}
putc(c);
}
 
 
void putString(char *s) {
while (*s != '\0') {
putchar(*s++);
}
}
 
 
/**************************************************************/
 
/* get a line from the terminal */
 
 
void getLine(char *prompt, char *line, int max) {
int index;
char c;
 
putString(prompt);
putString(line);
index = strlen(line);
while (1) {
c = getchar();
switch (c) {
case '\r':
putchar('\n');
line[index] = '\0';
return;
case '\b':
case 0x7F:
if (index == 0) {
break;
}
putchar('\b');
putchar(' ');
putchar('\b');
index--;
break;
default:
if (c == '\t') {
c = ' ';
}
if (c < 0x20 || c > 0x7E) {
break;
}
putchar(c);
line[index++] = c;
break;
}
}
}
 
 
/**************************************************************/
 
/* scaled-down version of printf */
 
 
/*
* Count the number of characters needed to represent
* a given number in base 10.
*/
int countPrintn(long n) {
long a;
int res;
 
res = 0;
if (n < 0) {
res++;
n = -n;
}
a = n / 10;
if (a != 0) {
res += countPrintn(a);
}
return res + 1;
}
 
 
/*
* Output a number in base 10.
*/
void printn(long n) {
long a;
 
if (n < 0) {
putchar('-');
n = -n;
}
a = n / 10;
if (a != 0) {
printn(a);
}
putchar(n % 10 + '0');
}
 
 
/*
* Count the number of characters needed to represent
* a given number in a given base.
*/
int countPrintu(unsigned long n, unsigned long b) {
unsigned long a;
int res;
 
res = 0;
a = n / b;
if (a != 0) {
res += countPrintu(a, b);
}
return res + 1;
}
 
 
/*
* Output a number in a given base.
*/
void printu(unsigned long n, unsigned long b, Bool upperCase) {
unsigned long a;
 
a = n / b;
if (a != 0) {
printu(a, b, upperCase);
}
if (upperCase) {
putchar("0123456789ABCDEF"[n % b]);
} else {
putchar("0123456789abcdef"[n % b]);
}
}
 
 
/*
* Output a number of filler characters.
*/
void fill(int numFillers, char filler) {
while (numFillers-- > 0) {
putchar(filler);
}
}
 
 
/*
* Formatted output with a variable argument list.
*/
void vprintf(char *fmt, va_list ap) {
char c;
int n;
long ln;
unsigned int u;
unsigned long lu;
char *s;
Bool negFlag;
char filler;
int width, count;
 
while (1) {
while ((c = *fmt++) != '%') {
if (c == '\0') {
return;
}
putchar(c);
}
c = *fmt++;
if (c == '-') {
negFlag = TRUE;
c = *fmt++;
} else {
negFlag = FALSE;
}
if (c == '0') {
filler = '0';
c = *fmt++;
} else {
filler = ' ';
}
width = 0;
while (c >= '0' && c <= '9') {
width *= 10;
width += c - '0';
c = *fmt++;
}
if (c == 'd') {
n = va_arg(ap, int);
count = countPrintn(n);
if (width > 0 && !negFlag) {
fill(width - count, filler);
}
printn(n);
if (width > 0 && negFlag) {
fill(width - count, filler);
}
} else
if (c == 'u' || c == 'o' || c == 'x' || c == 'X') {
u = va_arg(ap, int);
count = countPrintu(u,
c == 'o' ? 8 : ((c == 'x' || c == 'X') ? 16 : 10));
if (width > 0 && !negFlag) {
fill(width - count, filler);
}
printu(u,
c == 'o' ? 8 : ((c == 'x' || c == 'X') ? 16 : 10),
c == 'X');
if (width > 0 && negFlag) {
fill(width - count, filler);
}
} else
if (c == 'l') {
c = *fmt++;
if (c == 'd') {
ln = va_arg(ap, long);
count = countPrintn(ln);
if (width > 0 && !negFlag) {
fill(width - count, filler);
}
printn(ln);
if (width > 0 && negFlag) {
fill(width - count, filler);
}
} else
if (c == 'u' || c == 'o' || c == 'x' || c == 'X') {
lu = va_arg(ap, long);
count = countPrintu(lu,
c == 'o' ? 8 : ((c == 'x' || c == 'X') ? 16 : 10));
if (width > 0 && !negFlag) {
fill(width - count, filler);
}
printu(lu,
c == 'o' ? 8 : ((c == 'x' || c == 'X') ? 16 : 10),
c == 'X');
if (width > 0 && negFlag) {
fill(width - count, filler);
}
} else {
putchar('l');
putchar(c);
}
} else
if (c == 's') {
s = va_arg(ap, char *);
count = strlen(s);
if (width > 0 && !negFlag) {
fill(width - count, filler);
}
while ((c = *s++) != '\0') {
putchar(c);
}
if (width > 0 && negFlag) {
fill(width - count, filler);
}
} else
if (c == 'c') {
c = va_arg(ap, char);
putchar(c);
} else {
putchar(c);
}
}
}
 
 
/*
* Formatted output.
* This is a scaled-down version of the C library's
* printf. Used to print diagnostic information on
* the console (and optionally to a logfile).
*/
void printf(char *fmt, ...) {
va_list ap;
 
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
}
/eco32/trunk/stdalone/shpart/biolib.c
0,0 → 1,26
/*
* biolib.c -- basic I/O library
*/
 
 
#include "biolib.h"
 
 
char getc(void) {
unsigned int *base;
char c;
 
base = (unsigned int *) 0xF0300000;
while ((*(base + 0) & 1) == 0) ;
c = *(base + 1);
return c;
}
 
 
void putc(char c) {
unsigned int *base;
 
base = (unsigned int *) 0xF0300000;
while ((*(base + 2) & 1) == 0) ;
*(base + 3) = c;
}
/eco32/trunk/stdalone/shpart/start.h
0,0 → 1,21
/*
* start.h -- startup code
*/
 
 
#ifndef _START_H_
#define _START_H_
 
 
typedef int (*ISR)(int irq);
 
 
void enable(void);
void disable(void);
int getMask(void);
void setMask(int mask);
ISR getISR(int irq);
void setISR(int irq, ISR isr);
 
 
#endif /* _START_H_ */
/eco32/trunk/stdalone/shpart/iolib.h
0,0 → 1,21
/*
* iolib.h -- I/O library
*/
 
 
#ifndef _IOLIB_H_
#define _IOLIB_H_
 
 
int strlen(char *str);
void strcpy(char *dst, char *src);
void memcpy(unsigned char *dst, unsigned char *src, unsigned int cnt);
char getchar(void);
void putchar(char c);
void putString(char *s);
void getLine(char *prompt, char *line, int max);
void vprintf(char *fmt, va_list ap);
void printf(char *fmt, ...);
 
 
#endif /* _IOLIB_H_ */
/eco32/trunk/stdalone/shpart/main.c
0,0 → 1,229
/*
* main.c -- show partitions on a disk
*/
 
 
#include "types.h"
#include "stdarg.h"
#include "iolib.h"
#include "start.h"
#include "idedsk.h"
 
 
#define NPE (SECTOR_SIZE / sizeof(PartEntry))
#define DESCR_SIZE 20
 
 
typedef struct {
unsigned long type;
unsigned long start;
unsigned long size;
char descr[DESCR_SIZE];
} PartEntry;
 
PartEntry ptr[NPE];
 
 
/**************************************************************/
 
 
void error(char *fmt, ...) {
va_list ap;
 
va_start(ap, fmt);
printf("Error: ");
vprintf(fmt, ap);
printf(", halting...\n");
va_end(ap);
while (1) ;
}
 
 
/**************************************************************/
 
 
unsigned long getNumber(unsigned char *p) {
return (unsigned long) *(p + 0) << 24 |
(unsigned long) *(p + 1) << 16 |
(unsigned long) *(p + 2) << 8 |
(unsigned long) *(p + 3) << 0;
}
 
 
void convertPartitionTable(PartEntry *e, int n) {
int i;
unsigned char *p;
 
for (i = 0; i < n; i++) {
p = (unsigned char *) &e[i];
e[i].type = getNumber(p + 0);
e[i].start = getNumber(p + 4);
e[i].size = getNumber(p + 8);
}
}
 
 
/**************************************************************/
 
 
static char *exceptionCause[32] = {
/* 00 */ "terminal 0 transmitter interrupt",
/* 01 */ "terminal 0 receiver interrupt",
/* 02 */ "terminal 1 transmitter interrupt",
/* 03 */ "terminal 1 receiver interrupt",
/* 04 */ "keyboard interrupt",
/* 05 */ "unknown interrupt",
/* 06 */ "unknown interrupt",
/* 07 */ "unknown interrupt",
/* 08 */ "disk interrupt",
/* 09 */ "unknown interrupt",
/* 10 */ "unknown interrupt",
/* 11 */ "unknown interrupt",
/* 12 */ "unknown interrupt",
/* 13 */ "unknown interrupt",
/* 14 */ "timer interrupt",
/* 15 */ "unknown interrupt",
/* 16 */ "bus timeout exception",
/* 17 */ "illegal instruction exception",
/* 18 */ "privileged instruction exception",
/* 19 */ "divide instruction exception",
/* 20 */ "trap instruction exception",
/* 21 */ "TLB miss exception",
/* 22 */ "TLB write exception",
/* 23 */ "TLB invalid exception",
/* 24 */ "illegal address exception",
/* 25 */ "privileged address exception",
/* 26 */ "unknown exception",
/* 27 */ "unknown exception",
/* 28 */ "unknown exception",
/* 29 */ "unknown exception",
/* 30 */ "unknown exception",
/* 31 */ "unknown exception"
};
 
 
int defaultISR(int irq) {
printf("\n%s\n", exceptionCause[irq]);
return 0; /* do not skip any instruction */
}
 
 
void initInterrupts(void) {
int i;
 
for (i = 0; i < 32; i++) {
setISR(i, defaultISR);
}
}
 
 
/**************************************************************/
 
 
Bool checkDiskReady(void) {
int tries;
int i;
 
for (tries = 0; tries < 10; tries++) {
for (i = 0; i < 500000; i++) {
if ((*DISK_CTRL & DISK_CTRL_READY) != 0) {
return TRUE;
}
}
printf(".");
}
return FALSE;
}
 
 
unsigned long getDiskSize(void) {
return *DISK_CAP;
}
 
 
Bool readDisk(unsigned long sector,
unsigned int count,
unsigned int *addr) {
unsigned int n;
unsigned int *p;
unsigned int i;
 
while (count != 0) {
n = count > 8 ? 8 : count;
*DISK_SCT = sector;
*DISK_CNT = n;
*DISK_CTRL = DISK_CTRL_STRT;
while ((*DISK_CTRL & DISK_CTRL_DONE) == 0) ;
if (*DISK_CTRL & DISK_CTRL_ERR) {
return FALSE;
}
p = DISK_BUFFER;
for (i = 0; i < n * SECTOR_SIZE / sizeof(unsigned int); i++) {
*addr++ = *p++;
}
sector += n;
count -= n;
}
return TRUE;
}
 
 
/**************************************************************/
 
 
void main(void) {
unsigned long numSectors;
unsigned long partLast;
int i, j;
char c;
 
/* init interrupts */
initInterrupts();
/* check disk ready */
if (!checkDiskReady()) {
error("disk not ready");
}
/* determine disk size */
numSectors = getDiskSize();
printf("Disk has %lu (0x%lX) sectors.\n",
numSectors, numSectors);
if (numSectors < 32) {
error("disk is too small");
}
/* read partition table record */
if (!readDisk(1, 1, (unsigned int *) ptr)) {
error("cannot read partition table from disk");
}
convertPartitionTable(ptr, NPE);
/* show partition table */
printf("Partitions:\n");
printf(" # b type start last size description\n");
for (i = 0; i < NPE; i++) {
if (ptr[i].type != 0) {
partLast = ptr[i].start + ptr[i].size - 1;
} else {
partLast = 0;
}
printf("%2d %s 0x%08lX 0x%08lX 0x%08lX 0x%08lX ",
i,
ptr[i].type & 0x80000000 ? "*" : " ",
ptr[i].type & 0x7FFFFFFF,
ptr[i].start,
partLast,
ptr[i].size);
for (j = 0; j < DESCR_SIZE; j++) {
c = ptr[i].descr[j];
if (c == '\0') {
break;
}
if (c >= 0x20 && c < 0x7F) {
printf("%c", c);
} else {
printf(".");
}
}
printf("\n");
}
/* done */
printf("Halting...\n");
}
/eco32/trunk/stdalone/shpart/biolib.h
0,0 → 1,14
/*
* biolib.h -- basic I/O library
*/
 
 
#ifndef _BIOLIB_H_
#define _BIOLIB_H_
 
 
char getc(void);
void putc(char c);
 
 
#endif /* _BIOLIB_H_ */
/eco32/trunk/stdalone/shpart/end.s
0,0 → 1,19
;
; end.s -- end-of-segment labels
;
 
.export _ecode
.export _edata
.export _ebss
 
.code
.align 4
_ecode:
 
.data
.align 4
_edata:
 
.bss
.align 4
_ebss:
/eco32/trunk/stdalone/shpart/idedsk.h
0,0 → 1,32
/*
* idedsk.h -- IDE disk definitions
*/
 
 
#ifndef _IDEDSK_H_
#define _IDEDSK_H_
 
 
#define SECTOR_SIZE 512
#define WPS (SECTOR_SIZE / sizeof(unsigned int))
 
#define DISK_BASE ((unsigned *) 0xF0400000) /* disk base address */
#define DISK_CTRL (DISK_BASE + 0) /* control/status register */
#define DISK_CNT (DISK_BASE + 1) /* sector count register */
#define DISK_SCT (DISK_BASE + 2) /* disk sector register */
#define DISK_CAP (DISK_BASE + 3) /* disk capacity register */
#define DISK_BUFFER ((unsigned *) 0xF0480000) /* address of disk buffer */
 
#define DISK_CTRL_STRT 0x01 /* a 1 written here starts the disk command */
#define DISK_CTRL_IEN 0x02 /* enable disk interrupt */
#define DISK_CTRL_WRT 0x04 /* command type: 0 = read, 1 = write */
#define DISK_CTRL_ERR 0x08 /* 0 = ok, 1 = error; valid when DONE = 1 */
#define DISK_CTRL_DONE 0x10 /* 1 = disk has finished the command */
#define DISK_CTRL_READY 0x20 /* 1 = capacity valid, disk accepts command */
 
#define DISK_IRQ 8 /* disk interrupt number */
 
#define READY_RETRIES 1000000 /* retries to wait for disk to get ready */
 
 
#endif /* _IDEDSK_H_ */
/eco32/trunk/stdalone/shpart/types.h
0,0 → 1,16
/*
* types.h -- additional types
*/
 
 
#ifndef _TYPES_H_
#define _TYPES_H_
 
 
typedef int Bool;
 
#define FALSE 0
#define TRUE 1
 
 
#endif /* _TYPES_H_ */
/eco32/trunk/stdalone/shpart/stdarg.h
0,0 → 1,41
/*
* stdarg.h -- variable argument lists
*/
 
 
#ifndef _STDARG_H_
#define _STDARG_H_
 
 
typedef char *va_list;
 
 
static float __va_arg_tmp;
 
 
#define va_start(list, start) \
((void)((list) = (sizeof(start)<4 ? \
(char *)((int *)&(start)+1) : (char *)(&(start)+1))))
 
#define __va_arg(list, mode, n) \
(__typecode(mode)==1 && sizeof(mode)==4 ? \
(__va_arg_tmp = *(double *)(&(list += \
((sizeof(double)+n)&~n))[-(int)((sizeof(double)+n)&~n)]), \
*(mode *)&__va_arg_tmp) : \
*(mode *)(&(list += \
((sizeof(mode)+n)&~n))[-(int)((sizeof(mode)+n)&~n)]))
 
#define _bigendian_va_arg(list, mode, n) \
(sizeof(mode)==1 ? *(mode *)(&(list += 4)[-1]) : \
sizeof(mode)==2 ? *(mode *)(&(list += 4)[-2]) : \
__va_arg(list, mode, n))
 
#define va_end(list) ((void)0)
 
#define va_arg(list, mode) \
(sizeof(mode)==8 ? \
*(mode *)(&(list = (char*)(((int)list + 15)&~7U))[-8]) : \
_bigendian_va_arg(list, mode, 3U))
 
 
#endif /* _STDARG_H_ */
/eco32/trunk/stdalone/shpart/Makefile
0,0 → 1,28
#
# Makefile for "shpart", a program to show the partitions on a hard disk
#
 
BUILD = ../../build
 
SRC = start.s main.c iolib.c biolib.c end.s
BIN = shpart.bin
MAP = shpart.map
 
.PHONY: all install run clean
 
all: $(BIN)
 
install: $(BIN)
mkdir -p $(BUILD)/stdalone
cp $(BIN) $(BUILD)/stdalone
cp $(MAP) $(BUILD)/stdalone
 
run: $(BIN)
$(BUILD)/bin/sim -i -t 1 -l $(BIN) -d $(BUILD)/disk/disk.img
 
$(BIN): $(SRC)
$(BUILD)/bin/lcc -A -Wo-kernel \
-Wl-m -Wl$(MAP) -o $(BIN) $(SRC)
 
clean:
rm -f *~ $(BIN) $(MAP)
/eco32/trunk/stdalone/shpart/start.s
0,0 → 1,228
;
; start.s -- startup code
;
 
.import main
.import _ecode
.import _edata
.import _ebss
 
.export _bcode
.export _bdata
.export _bbss
 
.export enable
.export disable
.export getMask
.export setMask
.export getISR
.export setISR
 
.code
_bcode:
 
.data
_bdata:
 
.bss
_bbss:
 
.code
 
; reset arrives here
reset:
j start
 
; interrupts arrive here
intrpt:
j isr
 
; user TLB misses arrive here
userMiss:
j userMiss
 
isr:
add $26,$29,$0 ; sp -> $26
add $27,$1,$0 ; $1 -> $27
add $29,$0,istack ; set stack
sub $29,$29,108
stw $2,$29,0 ; save registers
stw $3,$29,4
stw $4,$29,8
stw $5,$29,12
stw $6,$29,16
stw $7,$29,20
stw $8,$29,24
stw $9,$29,28
stw $10,$29,32
stw $11,$29,36
stw $12,$29,40
stw $13,$29,44
stw $14,$29,48
stw $15,$29,52
stw $16,$29,56
stw $17,$29,60
stw $18,$29,64
stw $19,$29,68
stw $20,$29,72
stw $21,$29,76
stw $22,$29,80
stw $23,$29,84
stw $24,$29,88
stw $25,$29,92
stw $26,$29,96
stw $27,$29,100
stw $31,$29,104
mvfs $4,0 ; $4 = IRQ number
slr $4,$4,16
and $4,$4,0x1F
sll $26,$4,2 ; $26 = 4 * IRQ number
ldw $26,$26,irqsrv ; get addr of service routine
jalr $26 ; call service routine
beq $2,$0,resume ; resume instruction if ISR returned 0
add $30,$30,4 ; else skip offending instruction
resume:
ldw $2,$29,0
ldw $3,$29,4
ldw $4,$29,8
ldw $5,$29,12
ldw $6,$29,16
ldw $7,$29,20
ldw $8,$29,24
ldw $9,$29,28
ldw $10,$29,32
ldw $11,$29,36
ldw $12,$29,40
ldw $13,$29,44
ldw $14,$29,48
ldw $15,$29,52
ldw $16,$29,56
ldw $17,$29,60
ldw $18,$29,64
ldw $19,$29,68
ldw $20,$29,72
ldw $21,$29,76
ldw $22,$29,80
ldw $23,$29,84
ldw $24,$29,88
ldw $25,$29,92
ldw $26,$29,96
ldw $27,$29,100
ldw $31,$29,104
add $1,$27,$0 ; $27 -> $1
add $29,$26,0 ; $26 -> sp
rfx ; return from exception
 
start:
mvfs $8,0
or $8,$8,1 << 27 ; let vector point to RAM
mvts $8,0
add $29,$0,stack ; set sp
add $10,$0,_bdata ; copy data segment
add $8,$0,_edata
sub $9,$8,$10
add $9,$9,_ecode
j cpytest
cpyloop:
ldw $11,$9,0
stw $11,$8,0
cpytest:
sub $8,$8,4
sub $9,$9,4
bgeu $8,$10,cpyloop
add $8,$0,_bbss ; clear bss
add $9,$0,_ebss
j clrtest
clrloop:
stw $0,$8,0
add $8,$8,4
clrtest:
bltu $8,$9,clrloop
jal main ; call 'main'
start1:
j start1 ; loop
 
enable:
mvfs $8,0
or $8,$8,1 << 23
mvts $8,0
jr $31
 
disable:
mvfs $8,0
and $8,$8,~(1 << 23)
mvts $8,0
jr $31
 
getMask:
mvfs $8,0
and $2,$8,0x0000FFFF
jr $31
 
setMask:
mvfs $8,0
and $8,$8,0xFFFF0000
and $4,$4,0x0000FFFF
or $8,$8,$4
mvts $8,0
jr $31
 
getISR:
sll $4,$4,2
ldw $2,$4,irqsrv
jr $31
 
setISR:
sll $4,$4,2
stw $5,$4,irqsrv
jr $31
 
.data
 
; interrupt service routine table
 
.align 4
 
irqsrv:
.word 0 ; 00: terminal 0 transmitter interrupt
.word 0 ; 01: terminal 0 receiver interrupt
.word 0 ; 02: terminal 1 transmitter interrupt
.word 0 ; 03: terminal 1 receiver interrupt
.word 0 ; 04: keyboard interrupt
.word 0 ; 05: unused
.word 0 ; 06: unused
.word 0 ; 07: unused
.word 0 ; 08: disk interrupt
.word 0 ; 09: unused
.word 0 ; 10: unused
.word 0 ; 11: unused
.word 0 ; 12: unused
.word 0 ; 13: unused
.word 0 ; 14: timer interrupt
.word 0 ; 15: unused
.word 0 ; 16: bus timeout exception
.word 0 ; 17: illegal instruction exception
.word 0 ; 18: privileged instruction exception
.word 0 ; 19: divide instruction exception
.word 0 ; 20: trap instruction exception
.word 0 ; 21: TLB miss exception
.word 0 ; 22: TLB write exception
.word 0 ; 23: TLB invalid exception
.word 0 ; 24: illegal address exception
.word 0 ; 25: privileged address exception
.word 0 ; 26: unused
.word 0 ; 27: unused
.word 0 ; 28: unused
.word 0 ; 29: unused
.word 0 ; 30: unused
.word 0 ; 31: unused
 
.bss
 
.align 4
.space 0x800
stack:
 
.align 4
.space 0x800
istack:
/eco32/trunk/stdalone/hello/hello.s
0,0 → 1,54
;
; hello.s -- Hello, world!
;
 
.set tba,0xF0300000 ; terminal base address
.set tos,0xC0010000 ; top of stack
 
; get some addresses listed in the load map
.export reset
.export start
.export out
.export hello
 
; minimal execution environment
reset:
add $29,$0,tos ; setup stack
jal start ; do useful work
reset1:
j reset1 ; halt by looping
 
; main program
start:
sub $29,$29,8 ; create stack frame
stw $31,$29,0 ; save return register
stw $16,$29,4 ; save register variable
add $16,$0,hello ; pointer to string
loop:
ldbu $4,$16,0 ; get char
beq $4,$0,stop ; null - finished
jal out ; output char
add $16,$16,1 ; bump pointer
j loop ; next char
stop:
ldw $31,$29,0 ; restore return register
ldw $16,$29,4 ; restore register variable
add $29,$29,8 ; release stack frame
jr $31 ; return
 
; output a character to the terminal
out:
add $8,$0,tba ; set I/O base address
out1:
ldw $9,$8,8 ; get xmtr status
and $9,$9,1 ; xmtr ready?
beq $9,$0,out1 ; no - wait
stw $4,$8,12 ; send char
jr $31 ; return
 
; a very famous little string...
hello:
.byte 0x0D, 0x0A
.byte "Hello, world!"
.byte 0x0D, 0x0A
.byte 0x0D, 0x0A, 0
/eco32/trunk/stdalone/hello/Makefile
0,0 → 1,32
#
# Makefile for "hello", a program for testing the boot loader
#
 
BUILD = ../../build
 
SRC = hello.s
OBJ = hello.o
BIN = hello.bin
MAP = hello.map
 
.PHONY: all install run clean
 
all: $(BIN)
 
install: $(BIN)
mkdir -p $(BUILD)/stdalone
cp $(BIN) $(BUILD)/stdalone
cp $(MAP) $(BUILD)/stdalone
 
run: $(BIN)
$(BUILD)/bin/sim -i -t 1 -l $(BIN)
 
$(BIN): $(OBJ)
$(BUILD)/bin/ld -h -rc 0xC0000000 \
-m $(MAP) -o $(BIN) $(OBJ)
 
$(OBJ): $(SRC)
$(BUILD)/bin/as -o $(OBJ) $(SRC)
 
clean:
rm -f *~ $(OBJ) $(BIN) $(MAP)
/eco32/trunk/stdalone/onetask/os/start.h
0,0 → 1,21
/*
* start.h -- startup code
*/
 
 
#ifndef _START_H_
#define _START_H_
 
 
typedef void (*ISR)(int irq, unsigned int *registers);
 
 
void enable(void);
void disable(void);
ISR getISR(int irq);
void setISR(int irq, ISR isr);
void startTask(unsigned int physStackTop);
void setTLB(int index, unsigned int entryHi, unsigned int entryLo);
 
 
#endif /* _START_H_ */
/eco32/trunk/stdalone/onetask/os/main.c
0,0 → 1,250
/*
* main.c -- start the ball rolling
*/
 
 
#include "stdarg.h"
#include "start.h"
 
 
/**************************************************************/
 
 
unsigned char taskCode[] = {
#include "task.dump"
};
 
 
/**************************************************************/
 
 
void putchar(char c) {
unsigned int *base;
 
if (c == '\n') {
putchar('\r');
}
base = (unsigned int *) 0xF0300000;
while ((*(base + 2) & 1) == 0) ;
*(base + 3) = c;
}
 
 
void puts(char *s) {
char c;
 
while ((c = *s++) != '\0') {
putchar(c);
}
}
 
 
void printn(int n) {
int a;
 
if (n < 0) {
putchar('-');
n = -n;
}
a = n / 10;
if (a != 0) {
printn(a);
}
putchar(n % 10 + '0');
}
 
 
void printu(unsigned int n, unsigned int b) {
unsigned int a;
 
a = n / b;
if (a != 0) {
printu(a, b);
}
putchar("0123456789ABCDEF"[n % b]);
}
 
 
void printf(char *fmt, ...) {
va_list ap;
char c;
int n;
unsigned int u;
char *s;
 
va_start(ap, fmt);
while (1) {
while ((c = *fmt++) != '%') {
if (c == '\0') {
va_end(ap);
return;
}
putchar(c);
}
c = *fmt++;
if (c == 'd') {
n = va_arg(ap, int);
printn(n);
} else
if (c == 'u' || c == 'o' || c == 'x') {
u = va_arg(ap, int);
printu(u, c == 'o' ? 8 : (c == 'x' ? 16 : 10));
} else
if (c == 's') {
s = va_arg(ap, char *);
puts(s);
} else {
putchar(c);
}
}
}
 
 
/**************************************************************/
 
 
static char *exceptionCause[32] = {
/* 00 */ "terminal 0 transmitter interrupt",
/* 01 */ "terminal 0 receiver interrupt",
/* 02 */ "terminal 1 transmitter interrupt",
/* 03 */ "terminal 1 receiver interrupt",
/* 04 */ "keyboard interrupt",
/* 05 */ "unknown interrupt",
/* 06 */ "unknown interrupt",
/* 07 */ "unknown interrupt",
/* 08 */ "disk interrupt",
/* 09 */ "unknown interrupt",
/* 10 */ "unknown interrupt",
/* 11 */ "unknown interrupt",
/* 12 */ "unknown interrupt",
/* 13 */ "unknown interrupt",
/* 14 */ "timer interrupt",
/* 15 */ "unknown interrupt",
/* 16 */ "bus timeout exception",
/* 17 */ "illegal instruction exception",
/* 18 */ "privileged instruction exception",
/* 19 */ "divide instruction exception",
/* 20 */ "trap instruction exception",
/* 21 */ "TLB miss exception",
/* 22 */ "TLB write exception",
/* 23 */ "TLB invalid exception",
/* 24 */ "illegal address exception",
/* 25 */ "privileged address exception",
/* 26 */ "unknown exception",
/* 27 */ "unknown exception",
/* 28 */ "unknown exception",
/* 29 */ "unknown exception",
/* 30 */ "unknown exception",
/* 31 */ "unknown exception"
};
 
 
void defaultISR(int irq, unsigned int *registers) {
printf("\n%s\n", exceptionCause[irq]);
}
 
 
void initInterrupts(void) {
int i;
 
for (i = 0; i < 32; i++) {
setISR(i, defaultISR);
}
}
 
 
/**************************************************************/
 
 
void loadTask(unsigned char *code,
int csize, unsigned int physCodeAddr,
int dsize, unsigned int physDataAddr,
int bsize) {
unsigned char *virtLoadAddr;
int i;
 
virtLoadAddr = (unsigned char *) (0xC0000000 | physCodeAddr);
for (i = 0; i < csize; i++) {
*virtLoadAddr++ = *code++;
}
virtLoadAddr = (unsigned char *) (0xC0000000 | physDataAddr);
for (i = 0; i < dsize; i++) {
*virtLoadAddr++ = *code++;
}
for (i = 0; i < bsize; i++) {
*virtLoadAddr++ = '\0';
}
}
 
 
/**************************************************************/
 
 
void trapISR(int irq, unsigned int *registers) {
/* 'putchar' is the only system call yet */
putchar(registers[4]);
/* skip the trap instruction */
registers[30] += 4;
}
 
 
/**************************************************************/
 
 
void flushTLB(void) {
unsigned int invalPage;
int i;
 
invalPage = 0xC0000000;
for (i = 0; i < 32; i++) {
setTLB(i, invalPage, 0);
invalPage += (1 << 12);
}
}
 
 
/**************************************************************/
 
 
unsigned int getNumber(unsigned char *p) {
return (unsigned int) *(p + 0) << 24 |
(unsigned int) *(p + 1) << 16 |
(unsigned int) *(p + 2) << 8 |
(unsigned int) *(p + 3) << 0;
}
 
 
void main(void) {
unsigned int magic;
unsigned int csize;
unsigned int dsize;
unsigned int bsize;
 
printf("\n");
printf("OS: initializing interrupts\n");
initInterrupts();
setISR(20, trapISR);
/* load code at 256 k, data at (256 + 16) k */
printf("OS: loading task\n");
magic = getNumber(taskCode + 0);
csize = getNumber(taskCode + 4);
dsize = getNumber(taskCode + 8);
bsize = getNumber(taskCode + 12);
if (magic != 0x1AA09232) {
printf("Error: Load module is not executable!\n");
while (1) ;
}
printf("(csize = 0x%x, dsize = 0x%x, bsize = 0x%x)\n",
csize, dsize, bsize);
loadTask(taskCode + 8 * sizeof(unsigned int),
csize, 64 << 12,
dsize, 68 << 12,
bsize);
printf("OS: presetting TLB\n");
flushTLB();
setTLB(5, 0x00000000, 64 << 12 | 0x01);
setTLB(27, (csize + 0x00000FFF) & 0xFFFFF000, 68 << 12 | 0x03);
setTLB(22, 0x7FFFF000, 80 << 12 | 0x03);
printf("OS: starting task\n");
startTask(80 << 12); /* stack at (256 + 64) k */
}
/eco32/trunk/stdalone/onetask/os/end.s
0,0 → 1,19
;
; end.s -- end-of-segment labels
;
 
.export _ecode
.export _edata
.export _ebss
 
.code
.align 4
_ecode:
 
.data
.align 4
_edata:
 
.bss
.align 4
_ebss:
/eco32/trunk/stdalone/onetask/os/stdarg.h
0,0 → 1,41
/*
* stdarg.h -- variable argument lists
*/
 
 
#ifndef _STDARG_H_
#define _STDARG_H_
 
 
typedef char *va_list;
 
 
static float __va_arg_tmp;
 
 
#define va_start(list, start) \
((void)((list) = (sizeof(start)<4 ? \
(char *)((int *)&(start)+1) : (char *)(&(start)+1))))
 
#define __va_arg(list, mode, n) \
(__typecode(mode)==1 && sizeof(mode)==4 ? \
(__va_arg_tmp = *(double *)(&(list += \
((sizeof(double)+n)&~n))[-(int)((sizeof(double)+n)&~n)]), \
*(mode *)&__va_arg_tmp) : \
*(mode *)(&(list += \
((sizeof(mode)+n)&~n))[-(int)((sizeof(mode)+n)&~n)]))
 
#define _bigendian_va_arg(list, mode, n) \
(sizeof(mode)==1 ? *(mode *)(&(list += 4)[-1]) : \
sizeof(mode)==2 ? *(mode *)(&(list += 4)[-2]) : \
__va_arg(list, mode, n))
 
#define va_end(list) ((void)0)
 
#define va_arg(list, mode) \
(sizeof(mode)==8 ? \
*(mode *)(&(list = (char*)(((int)list + 15)&~7U))[-8]) : \
_bigendian_va_arg(list, mode, 3U))
 
 
#endif /* _STDARG_H_ */
/eco32/trunk/stdalone/onetask/os/Makefile
0,0 → 1,20
BUILD = ../../../build
 
SRC = start.s main.c end.s
BIN = onetask.bin
MAP = onetask.map
 
all: $(BIN)
 
run: $(BIN)
$(BUILD)/bin/sim -i -t 1 -l $(BIN)
 
$(BIN): $(SRC) task.dump
$(BUILD)/bin/lcc -A -Wo-kernel \
-Wl-m -Wl$(MAP) -o $(BIN) $(SRC)
 
task.dump:
../dump/dump ../task/task task.dump
 
clean:
rm -f *~ task.dump $(BIN) $(MAP)
/eco32/trunk/stdalone/onetask/os/start.s
0,0 → 1,267
;
; start.s -- startup code
;
 
.import main
.import _ecode
.import _edata
.import _ebss
 
.export _bcode
.export _bdata
.export _bbss
 
.export enable
.export disable
.export getISR
.export setISR
.export startTask
.export setTLB
 
.code
_bcode:
 
.data
_bdata:
 
.bss
_bbss:
 
.code
 
; reset arrives here
reset:
j start
 
; interrupts arrive here
intrpt:
j isr
 
; user TLB misses arrive here
userMiss:
j userMiss
 
isr:
add $26,$29,$0 ; sp -> $26
add $27,$1,$0 ; $1 -> $27
add $29,$0,istack ; setup interrupt stack
sub $29,$29,128 ; save registers
stw $2,$29,8
stw $3,$29,12
stw $4,$29,16
stw $5,$29,20
stw $6,$29,24
stw $7,$29,28
stw $8,$29,32
stw $9,$29,36
stw $10,$29,40
stw $11,$29,44
stw $12,$29,48
stw $13,$29,52
stw $14,$29,56
stw $15,$29,60
stw $16,$29,64
stw $17,$29,68
stw $18,$29,72
stw $19,$29,76
stw $20,$29,80
stw $21,$29,84
stw $22,$29,88
stw $23,$29,92
stw $24,$29,96
stw $25,$29,100
stw $26,$29,116 ; this is the task's sp
stw $27,$29,4 ; this is the task's $1
stw $30,$29,120 ; this is the task's resumption address
stw $31,$29,124
add $5,$29,$0 ; $5 = pointer to register array
mvfs $4,0 ; $4 = IRQ number
slr $4,$4,16
and $4,$4,0x1F
sll $26,$4,2 ; $26 = 4 * IRQ number
ldw $26,$26,irqsrv ; get addr of service routine
jalr $26 ; call service routine
j resume ; resume interrupted task if ISR returns
 
; resume a task
resume:
ldw $2,$29,8 ; restore registers
ldw $3,$29,12
ldw $4,$29,16
ldw $5,$29,20
ldw $6,$29,24
ldw $7,$29,28
ldw $8,$29,32
ldw $9,$29,36
ldw $10,$29,40
ldw $11,$29,44
ldw $12,$29,48
ldw $13,$29,52
ldw $14,$29,56
ldw $15,$29,60
ldw $16,$29,64
ldw $17,$29,68
ldw $18,$29,72
ldw $19,$29,76
ldw $20,$29,80
ldw $21,$29,84
ldw $22,$29,88
ldw $23,$29,92
ldw $24,$29,96
ldw $25,$29,100
ldw $26,$29,116 ; this is the task's sp
ldw $27,$29,4 ; this is the task's $1
ldw $30,$29,120 ; this is the task's resumption address
ldw $31,$29,124
add $1,$27,$0 ; $27 -> $1
add $29,$26,$0 ; $26 -> sp
rfx ; return from exception
 
start:
mvfs $8,0
or $8,$8,1 << 27 ; let vector point to RAM
mvts $8,0
add $29,$0,stack ; set sp
add $10,$0,_bdata ; copy data segment
add $8,$0,_edata
sub $9,$8,$10
add $9,$9,_ecode
j cpytest
cpyloop:
ldw $11,$9,0
stw $11,$8,0
cpytest:
sub $8,$8,4
sub $9,$9,4
bgeu $8,$10,cpyloop
add $8,$0,_bbss ; clear bss
add $9,$0,_ebss
j clrtest
clrloop:
stw $0,$8,0
add $8,$8,4
clrtest:
bltu $8,$9,clrloop
jal main ; call 'main'
start1:
j start1 ; loop
 
enable:
mvfs $8,0
or $8,$8,1 << 23
mvts $8,0
jr $31
 
disable:
mvfs $8,0
and $8,$8,~(1 << 23)
mvts $8,0
jr $31
 
getISR:
sll $4,$4,2
ldw $2,$4,irqsrv
jr $31
 
setISR:
sll $4,$4,2
stw $5,$4,irqsrv
jr $31
 
startTask:
or $29,$4,0xC0000000
sub $29,$29,128
stw $0,$29,0 ; preset registers
stw $0,$29,4
stw $0,$29,8
stw $0,$29,12
stw $0,$29,16
stw $0,$29,20
stw $0,$29,24
stw $0,$29,28
stw $0,$29,32
stw $0,$29,36
stw $0,$29,40
stw $0,$29,44
stw $0,$29,48
stw $0,$29,52
stw $0,$29,56
stw $0,$29,60
stw $0,$29,64
stw $0,$29,68
stw $0,$29,72
stw $0,$29,76
stw $0,$29,80
stw $0,$29,84
stw $0,$29,88
stw $0,$29,92
stw $0,$29,96
stw $0,$29,100
stw $0,$29,104
stw $0,$29,108
stw $0,$29,112
add $8,$0,0x80000000
stw $8,$29,116 ; sp
stw $0,$29,120 ; task starts at virtual address 0
stw $0,$29,124
mvfs $8,0
or $8,$8,1 << 25 ; set previous mode to 'user'
mvts $8,0
j resume
 
setTLB:
mvts $4,1 ; set index
mvts $5,2 ; set entryHi
mvts $6,3 ; set entryLo
tbwi ; write TLB entry at index
jr $31
 
.data
 
; interrupt service routine table
 
.align 4
 
irqsrv:
.word 0 ; 00: terminal 0 transmitter interrupt
.word 0 ; 01: terminal 0 receiver interrupt
.word 0 ; 02: terminal 1 transmitter interrupt
.word 0 ; 03: terminal 1 receiver interrupt
.word 0 ; 04: keyboard interrupt
.word 0 ; 05: unused
.word 0 ; 06: unused
.word 0 ; 07: unused
.word 0 ; 08: disk interrupt
.word 0 ; 09: unused
.word 0 ; 10: unused
.word 0 ; 11: unused
.word 0 ; 12: unused
.word 0 ; 13: unused
.word 0 ; 14: timer interrupt
.word 0 ; 15: unused
.word 0 ; 16: bus timeout exception
.word 0 ; 17: illegal instruction exception
.word 0 ; 18: privileged instruction exception
.word 0 ; 19: divide instruction exception
.word 0 ; 20: trap instruction exception
.word 0 ; 21: TLB miss exception
.word 0 ; 22: TLB write exception
.word 0 ; 23: TLB invalid exception
.word 0 ; 24: illegal address exception
.word 0 ; 25: privileged address exception
.word 0 ; 26: unused
.word 0 ; 27: unused
.word 0 ; 28: unused
.word 0 ; 29: unused
.word 0 ; 30: unused
.word 0 ; 31: unused
 
.bss
 
.align 4
.space 0x800
stack:
 
.align 4
.space 0x800
istack:
/eco32/trunk/stdalone/onetask/task/task.c
0,0 → 1,95
/*
* task.c -- a simple task
*/
 
 
#include "putchar.h"
#include "stdarg.h"
 
 
/**************************************************************/
 
 
void puts(char *s) {
char c;
 
while ((c = *s++) != '\0') {
putchar(c);
}
}
 
 
void printn(int n) {
int a;
 
if (n < 0) {
putchar('-');
n = -n;
}
a = n / 10;
if (a != 0) {
printn(a);
}
putchar(n % 10 + '0');
}
 
 
void printu(unsigned int n, unsigned int b) {
unsigned int a;
 
a = n / b;
if (a != 0) {
printu(a, b);
}
putchar("0123456789ABCDEF"[n % b]);
}
 
 
void printf(char *fmt, ...) {
va_list ap;
char c;
int n;
unsigned int u;
char *s;
 
va_start(ap, fmt);
while (1) {
while ((c = *fmt++) != '%') {
if (c == '\0') {
va_end(ap);
return;
}
putchar(c);
}
c = *fmt++;
if (c == 'd') {
n = va_arg(ap, int);
printn(n);
} else
if (c == 'u' || c == 'o' || c == 'x') {
u = va_arg(ap, int);
printu(u, c == 'o' ? 8 : (c == 'x' ? 16 : 10));
} else
if (c == 's') {
s = va_arg(ap, char *);
puts(s);
} else {
putchar(c);
}
}
}
 
 
/**************************************************************/
 
 
void main(void) {
int i;
 
printf("TASK: executing...\n");
i = 0;
while (1) {
printf("TASK: %d\n", i);
i++;
}
}
/eco32/trunk/stdalone/onetask/task/c0.s
0,0 → 1,30
;
; c0.s -- startup code and begin-of-segment labels
;
 
.import main
 
.export _bcode
.export _bdata
.export _bbss
 
.import _ecode
.import _edata
.import _ebss
 
.code
_bcode:
 
.data
_bdata:
 
.bss
_bbss:
 
.code
.align 4
 
start:
jal main ; call 'main' function
stop:
j stop ; just to be sure...
/eco32/trunk/stdalone/onetask/task/c1.s
0,0 → 1,19
;
; c1.s -- end-of-segment labels
;
 
.export _ecode
.export _edata
.export _ebss
 
.code
.align 4
_ecode:
 
.data
.align 4
_edata:
 
.bss
.align 4
_ebss:
/eco32/trunk/stdalone/onetask/task/putchar.s
0,0 → 1,10
;
; putchar.s -- putchar library function
;
 
.code
.export putchar
 
putchar:
trap
jr $31
/eco32/trunk/stdalone/onetask/task/stdarg.h
0,0 → 1,41
/*
* stdarg.h -- variable argument lists
*/
 
 
#ifndef _STDARG_H_
#define _STDARG_H_
 
 
typedef char *va_list;
 
 
static float __va_arg_tmp;
 
 
#define va_start(list, start) \
((void)((list) = (sizeof(start)<4 ? \
(char *)((int *)&(start)+1) : (char *)(&(start)+1))))
 
#define __va_arg(list, mode, n) \
(__typecode(mode)==1 && sizeof(mode)==4 ? \
(__va_arg_tmp = *(double *)(&(list += \
((sizeof(double)+n)&~n))[-(int)((sizeof(double)+n)&~n)]), \
*(mode *)&__va_arg_tmp) : \
*(mode *)(&(list += \
((sizeof(mode)+n)&~n))[-(int)((sizeof(mode)+n)&~n)]))
 
#define _bigendian_va_arg(list, mode, n) \
(sizeof(mode)==1 ? *(mode *)(&(list += 4)[-1]) : \
sizeof(mode)==2 ? *(mode *)(&(list += 4)[-2]) : \
__va_arg(list, mode, n))
 
#define va_end(list) ((void)0)
 
#define va_arg(list, mode) \
(sizeof(mode)==8 ? \
*(mode *)(&(list = (char*)(((int)list + 15)&~7U))[-8]) : \
_bigendian_va_arg(list, mode, 3U))
 
 
#endif /* _STDARG_H_ */
/eco32/trunk/stdalone/onetask/task/putchar.h
0,0 → 1,13
/*
* putchar.h -- putchar library function
*/
 
 
#ifndef _PUTCHAR_H_
#define _PUTCHAR_H_
 
 
void putchar(char c);
 
 
#endif /* _PUTCHAR_H_ */
/eco32/trunk/stdalone/onetask/task/Makefile
0,0 → 1,21
BUILD = ../../../build
 
all: task
 
task: c0.o task.o putchar.o c1.o
$(BUILD)/bin/ld -o task c0.o task.o putchar.o c1.o
 
c0.o: c0.s
$(BUILD)/bin/as -o c0.o c0.s
 
task.o: task.c
$(BUILD)/bin/lcc -A -c -o task.o task.c
 
putchar.o: putchar.s
$(BUILD)/bin/as -o putchar.o putchar.s
 
c1.o: c1.s
$(BUILD)/bin/as -o c1.o c1.s
 
clean:
rm -f *~ c0.o task.o putchar.o c1.o task
/eco32/trunk/stdalone/onetask/dump/dump.c
0,0 → 1,48
/*
* dump.c -- dump a binary file as contents of a C array
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
 
int main(int argc, char *argv[]) {
FILE *infile, *outfile;
int c, n;
 
if (argc != 3) {
printf("Usage: %s <infile> <outfile>\n", argv[0]);
return 1;
}
infile = fopen(argv[1], "rb");
if (infile == NULL) {
printf("Error: cannot open file '%s' for input\n", argv[1]);
return 1;
}
outfile = fopen(argv[2], "wt");
if (outfile == NULL) {
printf("Error: cannot open file '%s' for output\n", argv[2]);
return 1;
}
n = 0;
while (1) {
c = getc(infile);
if (c == EOF) {
break;
}
fprintf(outfile, "0x%02X, ", c);
n++;
if (n == 8) {
n = 0;
fprintf(outfile, "\n");
}
}
if (n != 0) {
fprintf(outfile, "\n");
}
fclose(infile);
fclose(outfile);
return 0;
}
/eco32/trunk/stdalone/onetask/dump/Makefile
0,0 → 1,15
#
# Makefile for dump utility
#
 
.PHONY: all install clean
 
all: dump
 
install: dump
 
dump: dump.c
gcc -m32 -g -Wall -o dump dump.c
 
clean:
rm -f *~ dump
/eco32/trunk/stdalone/onetask/Makefile
0,0 → 1,32
#
# Makefile for "onetask", a tiny OS which runs a single task
#
 
BUILD = ../../build
 
.PHONY: all install run clean
 
all: dump/dump task/task os/onetask.bin
 
install: dump/dump task/task os/onetask.bin
mkdir -p $(BUILD)/stdalone
cp os/onetask.bin $(BUILD)/stdalone
cp os/onetask.map $(BUILD)/stdalone
 
run: dump/dump task/task os/onetask.bin
$(MAKE) -C os run
 
dump/dump:
$(MAKE) -C dump
 
task/task:
$(MAKE) -C task
 
os/onetask.bin:
$(MAKE) -C os
 
clean:
$(MAKE) -C dump clean
$(MAKE) -C task clean
$(MAKE) -C os clean
rm -f *~
/eco32/trunk/stdalone/hello2/main.c
0,0 → 1,29
/*
* main.c -- main program
*/
 
 
void putchar(char c) {
unsigned int *base;
 
if (c == '\n') {
putchar('\r');
}
base = (unsigned int *) 0xF0300000;
while ((*(base + 2) & 1) == 0) ;
*(base + 3) = c;
}
 
 
void puts(char *s) {
char c;
 
while ((c = *s++) != '\0') {
putchar(c);
}
}
 
 
void main(void) {
puts("\nHello, world!\n\n");
}
/eco32/trunk/stdalone/hello2/end.s
0,0 → 1,19
;
; end.s -- end-of-segment labels
;
 
.export _ecode
.export _edata
.export _ebss
 
.code
.align 4
_ecode:
 
.data
.align 4
_edata:
 
.bss
.align 4
_ebss:
/eco32/trunk/stdalone/hello2/Makefile
0,0 → 1,28
#
# Makefile for "hello", a program for testing the boot loader
#
 
BUILD = ../../build
 
SRC = start.s main.c end.s
BIN = hello2.bin
MAP = hello2.map
 
.PHONY: all install run clean
 
all: $(BIN)
 
install: $(BIN)
mkdir -p $(BUILD)/stdalone
cp $(BIN) $(BUILD)/stdalone
cp $(MAP) $(BUILD)/stdalone
 
run: $(BIN)
$(BUILD)/bin/sim -i -t 1 -l $(BIN)
 
$(BIN): $(SRC)
$(BUILD)/bin/lcc -A -Wo-kernel \
-Wl-m -Wl$(MAP) -o $(BIN) $(SRC)
 
clean:
rm -f *~ $(BIN) $(MAP)
/eco32/trunk/stdalone/hello2/start.s
0,0 → 1,70
;
; start.s -- startup code
;
 
.import main
.import _ecode
.import _edata
.import _ebss
 
.export _bcode
.export _bdata
.export _bbss
 
.code
_bcode:
 
.data
_bdata:
 
.bss
_bbss:
 
.code
 
; reset arrives here
reset:
j start
 
; interrupts arrive here
intrpt:
j intrpt
 
; user TLB misses arrive here
userMiss:
j userMiss
 
start:
mvfs $8,0
or $8,$8,1 << 27 ; let vector point to RAM
mvts $8,0
add $29,$0,stack ; set sp
add $10,$0,_bdata ; copy data segment
add $8,$0,_edata
sub $9,$8,$10
add $9,$9,_ecode
j cpytest
cpyloop:
ldw $11,$9,0
stw $11,$8,0
cpytest:
sub $8,$8,4
sub $9,$9,4
bgeu $8,$10,cpyloop
add $8,$0,_bbss ; clear bss
add $9,$0,_ebss
j clrtest
clrloop:
stw $0,$8,0
add $8,$8,4
clrtest:
bltu $8,$9,clrloop
jal main ; call 'main'
start1:
j start1 ; loop
 
.bss
 
.align 4
.space 0x800
stack:
/eco32/trunk/stdalone/dskchk/start.h
0,0 → 1,21
/*
* start.h -- startup code
*/
 
 
#ifndef _START_H_
#define _START_H_
 
 
typedef int (*ISR)(int irq);
 
 
void enable(void);
void disable(void);
int getMask(void);
void setMask(int mask);
ISR getISR(int irq);
void setISR(int irq, ISR isr);
 
 
#endif /* _START_H_ */
/eco32/trunk/stdalone/dskchk/main.c
0,0 → 1,445
/*
* main.c -- start the ball rolling
*/
 
 
#include "stdarg.h"
#include "start.h"
#include "idedsk.h"
 
 
#define NUM_SECTORS 500
#define SECTOR_RANGE 8000
 
#define NUM_BLOCKS 300
#define BLOCK_RANGE 1000
 
 
/**************************************************************/
 
 
#define RAND_MAX 0x7FFF
 
 
static unsigned long randomNumber = 1;
 
 
void srand(int seed) {
randomNumber = seed;
}
 
 
int rand(void) {
randomNumber = randomNumber * 1103515245 + 12345;
return (unsigned int)(randomNumber >> 16) & RAND_MAX;
}
 
 
/**************************************************************/
 
 
void putchar(char c) {
unsigned int *base;
 
if (c == '\n') {
putchar('\r');
}
base = (unsigned int *) 0xF0300000;
while ((*(base + 2) & 1) == 0) ;
*(base + 3) = c;
}
 
 
void puts(char *s) {
char c;
 
while ((c = *s++) != '\0') {
putchar(c);
}
}
 
 
void printn(int n) {
int a;
 
if (n < 0) {
putchar('-');
n = -n;
}
a = n / 10;
if (a != 0) {
printn(a);
}
putchar(n % 10 + '0');
}
 
 
void printu(unsigned int n, unsigned int b) {
unsigned int a;
 
a = n / b;
if (a != 0) {
printu(a, b);
}
putchar("0123456789ABCDEF"[n % b]);
}
 
 
void printf(char *fmt, ...) {
va_list ap;
char c;
int n;
unsigned int u;
char *s;
 
va_start(ap, fmt);
while (1) {
while ((c = *fmt++) != '%') {
if (c == '\0') {
va_end(ap);
return;
}
putchar(c);
}
c = *fmt++;
if (c == 'd') {
n = va_arg(ap, int);
printn(n);
} else
if (c == 'u' || c == 'o' || c == 'x') {
u = va_arg(ap, int);
printu(u, c == 'o' ? 8 : (c == 'x' ? 16 : 10));
} else
if (c == 's') {
s = va_arg(ap, char *);
puts(s);
} else {
putchar(c);
}
}
}
 
 
/**************************************************************/
 
 
static char *exceptionCause[32] = {
/* 00 */ "terminal 0 transmitter interrupt",
/* 01 */ "terminal 0 receiver interrupt",
/* 02 */ "terminal 1 transmitter interrupt",
/* 03 */ "terminal 1 receiver interrupt",
/* 04 */ "keyboard interrupt",
/* 05 */ "unknown interrupt",
/* 06 */ "unknown interrupt",
/* 07 */ "unknown interrupt",
/* 08 */ "disk interrupt",
/* 09 */ "unknown interrupt",
/* 10 */ "unknown interrupt",
/* 11 */ "unknown interrupt",
/* 12 */ "unknown interrupt",
/* 13 */ "unknown interrupt",
/* 14 */ "timer interrupt",
/* 15 */ "unknown interrupt",
/* 16 */ "bus timeout exception",
/* 17 */ "illegal instruction exception",
/* 18 */ "privileged instruction exception",
/* 19 */ "divide instruction exception",
/* 20 */ "trap instruction exception",
/* 21 */ "TLB miss exception",
/* 22 */ "TLB write exception",
/* 23 */ "TLB invalid exception",
/* 24 */ "illegal address exception",
/* 25 */ "privileged address exception",
/* 26 */ "unknown exception",
/* 27 */ "unknown exception",
/* 28 */ "unknown exception",
/* 29 */ "unknown exception",
/* 30 */ "unknown exception",
/* 31 */ "unknown exception"
};
 
 
int defaultISR(int irq) {
printf("\n%s\n", exceptionCause[irq]);
return 0; /* do not skip any instruction */
}
 
 
void initInterrupts(void) {
int i;
 
for (i = 0; i < 32; i++) {
setISR(i, defaultISR);
}
}
 
 
/**************************************************************/
 
 
#define TIMER_CTRL ((unsigned *) 0xF0000000)
#define TIMER_DIV ((unsigned *) 0xF0000004)
 
 
int hundredth = 0;
 
 
int clockISR(int irq) {
*TIMER_CTRL = 2;
hundredth++;
return 0;
}
 
 
void initClock(void) {
setISR(14, clockISR);
*TIMER_DIV = 10;
*TIMER_CTRL = 2;
setMask(1 << 14);
enable();
}
 
 
/**************************************************************/
 
 
void checkDisk1(void) {
unsigned res;
 
printf("\nIs the disk present?\n");
res = *DISK_CTRL;
printf("yes, CTRL = 0x%x\n", res);
}
 
 
void checkDisk2(void) {
int start;
int ready;
 
printf("\nDoes the disk get ready?\n");
start = hundredth;
ready = 0;
while (start + 10 * 100 > hundredth) {
if (*DISK_CTRL & DISK_CTRL_READY) {
ready = hundredth;
break;
}
}
if (ready == 0) {
printf("disk did not get ready\n");
} else {
printf("disk got ready after %d/100 seconds\n", ready - start);
}
}
 
 
void checkDisk3(void) {
int errors;
int seed;
unsigned int *p;
int i, j;
 
printf("\nDisk sector buffer read/write\n");
errors = 0;
srand(321);
for (i = 0; i < NUM_SECTORS; i++) {
seed = rand();
srand(seed);
p = DISK_BUFFER;
for (j = 0; j < WPS; j++) {
*p++ = rand();
}
srand(seed);
p = DISK_BUFFER;
for (j = 0; j < WPS; j++) {
if (*p++ != rand()) {
errors++;
break;
}
}
}
printf("%d errors in %d sectors\n", errors, NUM_SECTORS);
}
 
 
void checkDisk4(void) {
int sector;
unsigned int *p;
int i, j;
int start, done;
int errors;
 
printf("\nRandom sector read/write, polled\n");
printf("writing...\n");
srand(321);
for (i = 0; i < NUM_SECTORS; i++) {
sector = rand() % SECTOR_RANGE;
p = DISK_BUFFER;
for (j = 0; j < WPS; j++) {
*p++ = sector + j;
}
*DISK_SCT = sector;
*DISK_CNT = 1;
*DISK_CTRL = *DISK_CTRL
& ~(DISK_CTRL_DONE | DISK_CTRL_ERR)
| (DISK_CTRL_WRT | DISK_CTRL_STRT);
start = hundredth;
done = 0;
while (start + 2 * 100 > hundredth) {
if (*DISK_CTRL & DISK_CTRL_DONE) {
done = hundredth;
break;
}
}
if (done == 0) {
printf("disk did not complete a sector write command\n");
return;
}
}
printf("reading...\n");
errors = 0;
srand(321);
for (i = 0; i < NUM_SECTORS; i++) {
sector = rand() % SECTOR_RANGE;
*DISK_SCT = sector;
*DISK_CNT = 1;
*DISK_CTRL = *DISK_CTRL
& ~(DISK_CTRL_DONE | DISK_CTRL_ERR | DISK_CTRL_WRT)
| DISK_CTRL_STRT;
start = hundredth;
done = 0;
while (start + 2 * 100 > hundredth) {
if (*DISK_CTRL & DISK_CTRL_DONE) {
done = hundredth;
break;
}
}
if (done == 0) {
printf("disk did not complete a sector read command\n");
return;
}
p = DISK_BUFFER;
for (j = 0; j < WPS; j++) {
if (*p++ != sector + j) {
errors++;
break;
}
}
}
printf("%d errors in %d sectors (range 0..%d)\n",
errors, NUM_SECTORS, SECTOR_RANGE);
}
 
 
void checkDisk5(void) {
int errors;
int seed;
unsigned int *p;
int i, j;
 
printf("\nDisk block buffer read/write\n");
errors = 0;
srand(321);
for (i = 0; i < NUM_BLOCKS; i++) {
seed = rand();
srand(seed);
p = DISK_BUFFER;
for (j = 0; j < WPB; j++) {
*p++ = rand();
}
srand(seed);
p = DISK_BUFFER;
for (j = 0; j < WPB; j++) {
if (*p++ != rand()) {
errors++;
break;
}
}
}
printf("%d errors in %d blocks\n", errors, NUM_BLOCKS);
}
 
 
void checkDisk6(void) {
int block;
unsigned int *p;
int i, j;
int start, done;
int errors;
 
printf("\nRandom block read/write, polled\n");
printf("writing...\n");
srand(321);
for (i = 0; i < NUM_BLOCKS; i++) {
block = rand() % BLOCK_RANGE;
p = DISK_BUFFER;
for (j = 0; j < WPB; j++) {
*p++ = block + j;
}
*DISK_SCT = 8 * block;
*DISK_CNT = 8;
*DISK_CTRL = *DISK_CTRL
& ~(DISK_CTRL_DONE | DISK_CTRL_ERR)
| (DISK_CTRL_WRT | DISK_CTRL_STRT);
start = hundredth;
done = 0;
while (start + 2 * 100 > hundredth) {
if (*DISK_CTRL & DISK_CTRL_DONE) {
done = hundredth;
break;
}
}
if (done == 0) {
printf("disk did not complete a block write command\n");
return;
}
}
printf("reading...\n");
errors = 0;
srand(321);
for (i = 0; i < NUM_BLOCKS; i++) {
block = rand() % BLOCK_RANGE;
*DISK_SCT = 8 * block;
*DISK_CNT = 8;
*DISK_CTRL = *DISK_CTRL
& ~(DISK_CTRL_DONE | DISK_CTRL_ERR | DISK_CTRL_WRT)
| DISK_CTRL_STRT;
start = hundredth;
done = 0;
while (start + 2 * 100 > hundredth) {
if (*DISK_CTRL & DISK_CTRL_DONE) {
done = hundredth;
break;
}
}
if (done == 0) {
printf("disk did not complete a block read command\n");
return;
}
p = DISK_BUFFER;
for (j = 0; j < WPB; j++) {
if (*p++ != block + j) {
errors++;
break;
}
}
}
printf("%d errors in %d blocks (range 0..%d)\n",
errors, NUM_BLOCKS, BLOCK_RANGE);
}
 
 
/**************************************************************/
 
 
void main(void) {
initInterrupts();
initClock();
checkDisk1();
checkDisk2();
checkDisk3();
checkDisk4();
checkDisk5();
checkDisk6();
printf("\nHalting...\n");
}
/eco32/trunk/stdalone/dskchk/end.s
0,0 → 1,19
;
; end.s -- end-of-segment labels
;
 
.export _ecode
.export _edata
.export _ebss
 
.code
.align 4
_ecode:
 
.data
.align 4
_edata:
 
.bss
.align 4
_ebss:
/eco32/trunk/stdalone/dskchk/idedsk.h
0,0 → 1,34
/*
* idedsk.h -- IDE disk definitions
*/
 
 
#ifndef _IDEDSK_H_
#define _IDEDSK_H_
 
 
#define SECTOR_SIZE 512
#define WPS (SECTOR_SIZE / sizeof(unsigned int))
#define BLOCK_SIZE 4096
#define WPB (BLOCK_SIZE / sizeof(unsigned int))
 
#define DISK_BASE ((unsigned *) 0xF0400000) /* disk base address */
#define DISK_CTRL (DISK_BASE + 0) /* control/status register */
#define DISK_CNT (DISK_BASE + 1) /* sector count register */
#define DISK_SCT (DISK_BASE + 2) /* disk sector register */
#define DISK_CAP (DISK_BASE + 3) /* disk capacity register */
#define DISK_BUFFER ((unsigned *) 0xF0480000) /* address of disk buffer */
 
#define DISK_CTRL_STRT 0x01 /* a 1 written here starts the disk command */
#define DISK_CTRL_IEN 0x02 /* enable disk interrupt */
#define DISK_CTRL_WRT 0x04 /* command type: 0 = read, 1 = write */
#define DISK_CTRL_ERR 0x08 /* 0 = ok, 1 = error; valid when DONE = 1 */
#define DISK_CTRL_DONE 0x10 /* 1 = disk has finished the command */
#define DISK_CTRL_READY 0x20 /* 1 = capacity valid, disk accepts command */
 
#define DISK_IRQ 8 /* disk interrupt number */
 
#define READY_RETRIES 1000000 /* retries to wait for disk to get ready */
 
 
#endif /* _IDEDSK_H_ */
/eco32/trunk/stdalone/dskchk/stdarg.h
0,0 → 1,41
/*
* stdarg.h -- variable argument lists
*/
 
 
#ifndef _STDARG_H_
#define _STDARG_H_
 
 
typedef char *va_list;
 
 
static float __va_arg_tmp;
 
 
#define va_start(list, start) \
((void)((list) = (sizeof(start)<4 ? \
(char *)((int *)&(start)+1) : (char *)(&(start)+1))))
 
#define __va_arg(list, mode, n) \
(__typecode(mode)==1 && sizeof(mode)==4 ? \
(__va_arg_tmp = *(double *)(&(list += \
((sizeof(double)+n)&~n))[-(int)((sizeof(double)+n)&~n)]), \
*(mode *)&__va_arg_tmp) : \
*(mode *)(&(list += \
((sizeof(mode)+n)&~n))[-(int)((sizeof(mode)+n)&~n)]))
 
#define _bigendian_va_arg(list, mode, n) \
(sizeof(mode)==1 ? *(mode *)(&(list += 4)[-1]) : \
sizeof(mode)==2 ? *(mode *)(&(list += 4)[-2]) : \
__va_arg(list, mode, n))
 
#define va_end(list) ((void)0)
 
#define va_arg(list, mode) \
(sizeof(mode)==8 ? \
*(mode *)(&(list = (char*)(((int)list + 15)&~7U))[-8]) : \
_bigendian_va_arg(list, mode, 3U))
 
 
#endif /* _STDARG_H_ */
/eco32/trunk/stdalone/dskchk/Makefile
0,0 → 1,28
#
# Makefile for "dskchk", a program to check the hard disk interface
#
 
BUILD = ../../build
 
SRC = start.s main.c end.s
BIN = dskchk.bin
MAP = dskchk.map
 
.PHONY: all install run clean
 
all: $(BIN)
 
install: $(BIN)
mkdir -p $(BUILD)/stdalone
cp $(BIN) $(BUILD)/stdalone
cp $(MAP) $(BUILD)/stdalone
 
run: $(BIN)
$(BUILD)/bin/sim -i -t 1 -l $(BIN) -d $(BUILD)/disk/disk.img
 
$(BIN): $(SRC)
$(BUILD)/bin/lcc -A -Wo-kernel \
-Wl-m -Wl$(MAP) -o $(BIN) $(SRC)
 
clean:
rm -f *~ $(BIN) $(MAP)
/eco32/trunk/stdalone/dskchk/start.s
0,0 → 1,228
;
; start.s -- startup code
;
 
.import main
.import _ecode
.import _edata
.import _ebss
 
.export _bcode
.export _bdata
.export _bbss
 
.export enable
.export disable
.export getMask
.export setMask
.export getISR
.export setISR
 
.code
_bcode:
 
.data
_bdata:
 
.bss
_bbss:
 
.code
 
; reset arrives here
reset:
j start
 
; interrupts arrive here
intrpt:
j isr
 
; user TLB misses arrive here
userMiss:
j userMiss
 
isr:
add $26,$29,$0 ; sp -> $26
add $27,$1,$0 ; $1 -> $27
add $29,$0,istack ; set stack
sub $29,$29,108
stw $2,$29,0 ; save registers
stw $3,$29,4
stw $4,$29,8
stw $5,$29,12
stw $6,$29,16
stw $7,$29,20
stw $8,$29,24
stw $9,$29,28
stw $10,$29,32
stw $11,$29,36
stw $12,$29,40
stw $13,$29,44
stw $14,$29,48
stw $15,$29,52
stw $16,$29,56
stw $17,$29,60
stw $18,$29,64
stw $19,$29,68
stw $20,$29,72
stw $21,$29,76
stw $22,$29,80
stw $23,$29,84
stw $24,$29,88
stw $25,$29,92
stw $26,$29,96
stw $27,$29,100
stw $31,$29,104
mvfs $4,0 ; $4 = IRQ number
slr $4,$4,16
and $4,$4,0x1F
sll $26,$4,2 ; $26 = 4 * IRQ number
ldw $26,$26,irqsrv ; get addr of service routine
jalr $26 ; call service routine
beq $2,$0,resume ; resume instruction if ISR returned 0
add $30,$30,4 ; else skip offending instruction
resume:
ldw $2,$29,0
ldw $3,$29,4
ldw $4,$29,8
ldw $5,$29,12
ldw $6,$29,16
ldw $7,$29,20
ldw $8,$29,24
ldw $9,$29,28
ldw $10,$29,32
ldw $11,$29,36
ldw $12,$29,40
ldw $13,$29,44
ldw $14,$29,48
ldw $15,$29,52
ldw $16,$29,56
ldw $17,$29,60
ldw $18,$29,64
ldw $19,$29,68
ldw $20,$29,72
ldw $21,$29,76
ldw $22,$29,80
ldw $23,$29,84
ldw $24,$29,88
ldw $25,$29,92
ldw $26,$29,96
ldw $27,$29,100
ldw $31,$29,104
add $1,$27,$0 ; $27 -> $1
add $29,$26,0 ; $26 -> sp
rfx ; return from exception
 
start:
mvfs $8,0
or $8,$8,1 << 27 ; let vector point to RAM
mvts $8,0
add $29,$0,stack ; set sp
add $10,$0,_bdata ; copy data segment
add $8,$0,_edata
sub $9,$8,$10
add $9,$9,_ecode
j cpytest
cpyloop:
ldw $11,$9,0
stw $11,$8,0
cpytest:
sub $8,$8,4
sub $9,$9,4
bgeu $8,$10,cpyloop
add $8,$0,_bbss ; clear bss
add $9,$0,_ebss
j clrtest
clrloop:
stw $0,$8,0
add $8,$8,4
clrtest:
bltu $8,$9,clrloop
jal main ; call 'main'
start1:
j start1 ; loop
 
enable:
mvfs $8,0
or $8,$8,1 << 23
mvts $8,0
jr $31
 
disable:
mvfs $8,0
and $8,$8,~(1 << 23)
mvts $8,0
jr $31
 
getMask:
mvfs $8,0
and $2,$8,0x0000FFFF
jr $31
 
setMask:
mvfs $8,0
and $8,$8,0xFFFF0000
and $4,$4,0x0000FFFF
or $8,$8,$4
mvts $8,0
jr $31
 
getISR:
sll $4,$4,2
ldw $2,$4,irqsrv
jr $31
 
setISR:
sll $4,$4,2
stw $5,$4,irqsrv
jr $31
 
.data
 
; interrupt service routine table
 
.align 4
 
irqsrv:
.word 0 ; 00: terminal 0 transmitter interrupt
.word 0 ; 01: terminal 0 receiver interrupt
.word 0 ; 02: terminal 1 transmitter interrupt
.word 0 ; 03: terminal 1 receiver interrupt
.word 0 ; 04: keyboard interrupt
.word 0 ; 05: unused
.word 0 ; 06: unused
.word 0 ; 07: unused
.word 0 ; 08: disk interrupt
.word 0 ; 09: unused
.word 0 ; 10: unused
.word 0 ; 11: unused
.word 0 ; 12: unused
.word 0 ; 13: unused
.word 0 ; 14: timer interrupt
.word 0 ; 15: unused
.word 0 ; 16: bus timeout exception
.word 0 ; 17: illegal instruction exception
.word 0 ; 18: privileged instruction exception
.word 0 ; 19: divide instruction exception
.word 0 ; 20: trap instruction exception
.word 0 ; 21: TLB miss exception
.word 0 ; 22: TLB write exception
.word 0 ; 23: TLB invalid exception
.word 0 ; 24: illegal address exception
.word 0 ; 25: privileged address exception
.word 0 ; 26: unused
.word 0 ; 27: unused
.word 0 ; 28: unused
.word 0 ; 29: unused
.word 0 ; 30: unused
.word 0 ; 31: unused
 
.bss
 
.align 4
.space 0x800
stack:
 
.align 4
.space 0x800
istack:
/eco32/trunk/stdalone/memsize/start.h
0,0 → 1,19
/*
* start.h -- startup code
*/
 
 
#ifndef _START_H_
#define _START_H_
 
 
typedef int (*ISR)(int irq);
 
 
void enable(void);
void disable(void);
ISR getISR(int irq);
void setISR(int irq, ISR isr);
 
 
#endif /* _START_H_ */
/eco32/trunk/stdalone/memsize/main.c
0,0 → 1,194
/*
* main.c -- start the ball rolling
*/
 
 
#include "stdarg.h"
#include "start.h"
 
 
/**************************************************************/
 
 
void putchar(char c) {
unsigned int *base;
 
if (c == '\n') {
putchar('\r');
}
base = (unsigned int *) 0xF0300000;
while ((*(base + 2) & 1) == 0) ;
*(base + 3) = c;
}
 
 
void puts(char *s) {
char c;
 
while ((c = *s++) != '\0') {
putchar(c);
}
}
 
 
void printn(int n) {
int a;
 
if (n < 0) {
putchar('-');
n = -n;
}
a = n / 10;
if (a != 0) {
printn(a);
}
putchar(n % 10 + '0');
}
 
 
void printu(unsigned int n, unsigned int b) {
unsigned int a;
 
a = n / b;
if (a != 0) {
printu(a, b);
}
putchar("0123456789ABCDEF"[n % b]);
}
 
 
void printf(char *fmt, ...) {
va_list ap;
char c;
int n;
unsigned int u;
char *s;
 
va_start(ap, fmt);
while (1) {
while ((c = *fmt++) != '%') {
if (c == '\0') {
va_end(ap);
return;
}
putchar(c);
}
c = *fmt++;
if (c == 'd') {
n = va_arg(ap, int);
printn(n);
} else
if (c == 'u' || c == 'o' || c == 'x') {
u = va_arg(ap, int);
printu(u, c == 'o' ? 8 : (c == 'x' ? 16 : 10));
} else
if (c == 's') {
s = va_arg(ap, char *);
puts(s);
} else {
putchar(c);
}
}
}
 
 
/**************************************************************/
 
 
static char *exceptionCause[32] = {
/* 00 */ "terminal 0 transmitter interrupt",
/* 01 */ "terminal 0 receiver interrupt",
/* 02 */ "terminal 1 transmitter interrupt",
/* 03 */ "terminal 1 receiver interrupt",
/* 04 */ "keyboard interrupt",
/* 05 */ "unknown interrupt",
/* 06 */ "unknown interrupt",
/* 07 */ "unknown interrupt",
/* 08 */ "disk interrupt",
/* 09 */ "unknown interrupt",
/* 10 */ "unknown interrupt",
/* 11 */ "unknown interrupt",
/* 12 */ "unknown interrupt",
/* 13 */ "unknown interrupt",
/* 14 */ "timer interrupt",
/* 15 */ "unknown interrupt",
/* 16 */ "bus timeout exception",
/* 17 */ "illegal instruction exception",
/* 18 */ "privileged instruction exception",
/* 19 */ "divide instruction exception",
/* 20 */ "trap instruction exception",
/* 21 */ "TLB miss exception",
/* 22 */ "TLB write exception",
/* 23 */ "TLB invalid exception",
/* 24 */ "illegal address exception",
/* 25 */ "privileged address exception",
/* 26 */ "unknown exception",
/* 27 */ "unknown exception",
/* 28 */ "unknown exception",
/* 29 */ "unknown exception",
/* 30 */ "unknown exception",
/* 31 */ "unknown exception"
};
 
 
int defaultISR(int irq) {
printf("\n%s\n", exceptionCause[irq]);
return 0; /* do not skip any instruction */
}
 
 
void initInterrupts(void) {
int i;
 
for (i = 0; i < 32; i++) {
setISR(i, defaultISR);
}
}
 
 
/**************************************************************/
 
 
static int busTimeoutSeen;
 
 
int busTimeoutISR(int irq) {
busTimeoutSeen = 1;
return 1; /* skip offending instruction */
}
 
 
int memsize(void) {
unsigned char *ptr;
unsigned char b;
ISR oldService;
 
busTimeoutSeen = 0;
oldService = getISR(16);
setISR(16, busTimeoutISR);
ptr = (unsigned char *) 0xC0000000;
while (1) {
b = *ptr;
if (busTimeoutSeen) {
break;
}
ptr += (1 << 12);
}
setISR(16, oldService);
return (ptr - (unsigned char *) 0xC0000000) >> 12;
}
 
 
/**************************************************************/
 
 
void main(void) {
int numberPages;
 
initInterrupts();
printf("\n");
printf("Probing memory...\n");
numberPages = memsize();
printf("Memory size = %d pages * 4 Kbytes\n", numberPages);
printf("Halting...\n");
}
/eco32/trunk/stdalone/memsize/end.s
0,0 → 1,19
;
; end.s -- end-of-segment labels
;
 
.export _ecode
.export _edata
.export _ebss
 
.code
.align 4
_ecode:
 
.data
.align 4
_edata:
 
.bss
.align 4
_ebss:
/eco32/trunk/stdalone/memsize/stdarg.h
0,0 → 1,41
/*
* stdarg.h -- variable argument lists
*/
 
 
#ifndef _STDARG_H_
#define _STDARG_H_
 
 
typedef char *va_list;
 
 
static float __va_arg_tmp;
 
 
#define va_start(list, start) \
((void)((list) = (sizeof(start)<4 ? \
(char *)((int *)&(start)+1) : (char *)(&(start)+1))))
 
#define __va_arg(list, mode, n) \
(__typecode(mode)==1 && sizeof(mode)==4 ? \
(__va_arg_tmp = *(double *)(&(list += \
((sizeof(double)+n)&~n))[-(int)((sizeof(double)+n)&~n)]), \
*(mode *)&__va_arg_tmp) : \
*(mode *)(&(list += \
((sizeof(mode)+n)&~n))[-(int)((sizeof(mode)+n)&~n)]))
 
#define _bigendian_va_arg(list, mode, n) \
(sizeof(mode)==1 ? *(mode *)(&(list += 4)[-1]) : \
sizeof(mode)==2 ? *(mode *)(&(list += 4)[-2]) : \
__va_arg(list, mode, n))
 
#define va_end(list) ((void)0)
 
#define va_arg(list, mode) \
(sizeof(mode)==8 ? \
*(mode *)(&(list = (char*)(((int)list + 15)&~7U))[-8]) : \
_bigendian_va_arg(list, mode, 3U))
 
 
#endif /* _STDARG_H_ */
/eco32/trunk/stdalone/memsize/Makefile
0,0 → 1,28
#
# Makefile for "memsize", a program to determine the memory size
#
 
BUILD = ../../build
 
SRC = start.s main.c end.s
BIN = memsize.bin
MAP = memsize.map
 
.PHONY: all install run clean
 
all: $(BIN)
 
install: $(BIN)
mkdir -p $(BUILD)/stdalone
cp $(BIN) $(BUILD)/stdalone
cp $(MAP) $(BUILD)/stdalone
 
run: $(BIN)
$(BUILD)/bin/sim -i -t 1 -l $(BIN)
 
$(BIN): $(SRC)
$(BUILD)/bin/lcc -A -Wo-kernel \
-Wl-m -Wl$(MAP) -o $(BIN) $(SRC)
 
clean:
rm -f *~ $(BIN) $(MAP)
/eco32/trunk/stdalone/memsize/start.s
0,0 → 1,213
;
; start.s -- startup code
;
 
.import main
.import _ecode
.import _edata
.import _ebss
 
.export _bcode
.export _bdata
.export _bbss
 
.export enable
.export disable
.export getISR
.export setISR
 
.code
_bcode:
 
.data
_bdata:
 
.bss
_bbss:
 
.code
 
; reset arrives here
reset:
j start
 
; interrupts arrive here
intrpt:
j isr
 
; user TLB misses arrive here
userMiss:
j userMiss
 
isr:
add $26,$29,$0 ; sp -> $26
add $27,$1,$0 ; $1 -> $27
add $29,$0,istack ; set stack
sub $29,$29,108
stw $2,$29,0 ; save registers
stw $3,$29,4
stw $4,$29,8
stw $5,$29,12
stw $6,$29,16
stw $7,$29,20
stw $8,$29,24
stw $9,$29,28
stw $10,$29,32
stw $11,$29,36
stw $12,$29,40
stw $13,$29,44
stw $14,$29,48
stw $15,$29,52
stw $16,$29,56
stw $17,$29,60
stw $18,$29,64
stw $19,$29,68
stw $20,$29,72
stw $21,$29,76
stw $22,$29,80
stw $23,$29,84
stw $24,$29,88
stw $25,$29,92
stw $26,$29,96
stw $27,$29,100
stw $31,$29,104
mvfs $4,0 ; $4 = IRQ number
slr $4,$4,16
and $4,$4,0x1F
sll $26,$4,2 ; $26 = 4 * IRQ number
ldw $26,$26,irqsrv ; get addr of service routine
jalr $26 ; call service routine
beq $2,$0,resume ; resume instruction if ISR returned 0
add $30,$30,4 ; else skip offending instruction
resume:
ldw $2,$29,0
ldw $3,$29,4
ldw $4,$29,8
ldw $5,$29,12
ldw $6,$29,16
ldw $7,$29,20
ldw $8,$29,24
ldw $9,$29,28
ldw $10,$29,32
ldw $11,$29,36
ldw $12,$29,40
ldw $13,$29,44
ldw $14,$29,48
ldw $15,$29,52
ldw $16,$29,56
ldw $17,$29,60
ldw $18,$29,64
ldw $19,$29,68
ldw $20,$29,72
ldw $21,$29,76
ldw $22,$29,80
ldw $23,$29,84
ldw $24,$29,88
ldw $25,$29,92
ldw $26,$29,96
ldw $27,$29,100
ldw $31,$29,104
add $1,$27,$0 ; $27 -> $1
add $29,$26,0 ; $26 -> sp
rfx ; return from exception
 
start:
mvfs $8,0
or $8,$8,1 << 27 ; let vector point to RAM
mvts $8,0
add $29,$0,stack ; set sp
add $10,$0,_bdata ; copy data segment
add $8,$0,_edata
sub $9,$8,$10
add $9,$9,_ecode
j cpytest
cpyloop:
ldw $11,$9,0
stw $11,$8,0
cpytest:
sub $8,$8,4
sub $9,$9,4
bgeu $8,$10,cpyloop
add $8,$0,_bbss ; clear bss
add $9,$0,_ebss
j clrtest
clrloop:
stw $0,$8,0
add $8,$8,4
clrtest:
bltu $8,$9,clrloop
jal main ; call 'main'
start1:
j start1 ; loop
 
enable:
mvfs $8,0
or $8,$8,1 << 23
mvts $8,0
jr $31
 
disable:
mvfs $8,0
and $8,$8,~(1 << 23)
mvts $8,0
jr $31
 
getISR:
sll $4,$4,2
ldw $2,$4,irqsrv
jr $31
 
setISR:
sll $4,$4,2
stw $5,$4,irqsrv
jr $31
 
.data
 
; interrupt service routine table
 
.align 4
 
irqsrv:
.word 0 ; 00: terminal 0 transmitter interrupt
.word 0 ; 01: terminal 0 receiver interrupt
.word 0 ; 02: terminal 1 transmitter interrupt
.word 0 ; 03: terminal 1 receiver interrupt
.word 0 ; 04: keyboard interrupt
.word 0 ; 05: unused
.word 0 ; 06: unused
.word 0 ; 07: unused
.word 0 ; 08: disk interrupt
.word 0 ; 09: unused
.word 0 ; 10: unused
.word 0 ; 11: unused
.word 0 ; 12: unused
.word 0 ; 13: unused
.word 0 ; 14: timer interrupt
.word 0 ; 15: unused
.word 0 ; 16: bus timeout exception
.word 0 ; 17: illegal instruction exception
.word 0 ; 18: privileged instruction exception
.word 0 ; 19: divide instruction exception
.word 0 ; 20: trap instruction exception
.word 0 ; 21: TLB miss exception
.word 0 ; 22: TLB write exception
.word 0 ; 23: TLB invalid exception
.word 0 ; 24: illegal address exception
.word 0 ; 25: privileged address exception
.word 0 ; 26: unused
.word 0 ; 27: unused
.word 0 ; 28: unused
.word 0 ; 29: unused
.word 0 ; 30: unused
.word 0 ; 31: unused
 
.bss
 
.align 4
.space 0x800
stack:
 
.align 4
.space 0x800
istack:
/eco32/trunk/stdalone/twotasks-1/os/start.h
0,0 → 1,23
/*
* start.h -- startup code
*/
 
 
#ifndef _START_H_
#define _START_H_
 
 
typedef void (*ISR)(int irq, unsigned int *registers);
 
 
void enable(void);
void disable(void);
void orMask(unsigned int mask);
void andMask(unsigned int mask);
ISR getISR(int irq);
void setISR(int irq, ISR isr);
void startTask(void);
void setTLB(int index, unsigned int entryHi, unsigned int entryLo);
 
 
#endif /* _START_H_ */
/eco32/trunk/stdalone/twotasks-1/os/main.c
0,0 → 1,345
/*
* main.c -- start the ball rolling
*/
 
 
#include "stdarg.h"
#include "start.h"
 
 
/**************************************************************/
 
 
int currentTask;
unsigned int *currentStkTop;
 
 
/**************************************************************/
 
 
unsigned int task0Stack[256];
unsigned int *task0StkTop = task0Stack + 256;
 
 
unsigned char task1Code[] = {
#include "task1.dump"
};
 
unsigned int task1Stack[256];
unsigned int *task1StkTop = task1Stack + 256;
 
 
unsigned char task2Code[] = {
#include "task2.dump"
};
 
unsigned int task2Stack[256];
unsigned int *task2StkTop = task2Stack + 256;
 
 
/**************************************************************/
 
 
void putchar(char c) {
unsigned int *base;
 
if (c == '\n') {
putchar('\r');
}
base = (unsigned int *) 0xF0300000;
while ((*(base + 2) & 1) == 0) ;
*(base + 3) = c;
}
 
 
void puts(char *s) {
char c;
 
while ((c = *s++) != '\0') {
putchar(c);
}
}
 
 
void printn(int n) {
int a;
 
if (n < 0) {
putchar('-');
n = -n;
}
a = n / 10;
if (a != 0) {
printn(a);
}
putchar(n % 10 + '0');
}
 
 
void printu(unsigned int n, unsigned int b) {
unsigned int a;
 
a = n / b;
if (a != 0) {
printu(a, b);
}
putchar("0123456789ABCDEF"[n % b]);
}
 
 
void printf(char *fmt, ...) {
va_list ap;
char c;
int n;
unsigned int u;
char *s;
 
va_start(ap, fmt);
while (1) {
while ((c = *fmt++) != '%') {
if (c == '\0') {
va_end(ap);
return;
}
putchar(c);
}
c = *fmt++;
if (c == 'd') {
n = va_arg(ap, int);
printn(n);
} else
if (c == 'u' || c == 'o' || c == 'x') {
u = va_arg(ap, int);
printu(u, c == 'o' ? 8 : (c == 'x' ? 16 : 10));
} else
if (c == 's') {
s = va_arg(ap, char *);
puts(s);
} else {
putchar(c);
}
}
}
 
 
/**************************************************************/
 
 
static char *exceptionCause[32] = {
/* 00 */ "terminal 0 transmitter interrupt",
/* 01 */ "terminal 0 receiver interrupt",
/* 02 */ "terminal 1 transmitter interrupt",
/* 03 */ "terminal 1 receiver interrupt",
/* 04 */ "keyboard interrupt",
/* 05 */ "unknown interrupt",
/* 06 */ "unknown interrupt",
/* 07 */ "unknown interrupt",
/* 08 */ "disk interrupt",
/* 09 */ "unknown interrupt",
/* 10 */ "unknown interrupt",
/* 11 */ "unknown interrupt",
/* 12 */ "unknown interrupt",
/* 13 */ "unknown interrupt",
/* 14 */ "timer interrupt",
/* 15 */ "unknown interrupt",
/* 16 */ "bus timeout exception",
/* 17 */ "illegal instruction exception",
/* 18 */ "privileged instruction exception",
/* 19 */ "divide instruction exception",
/* 20 */ "trap instruction exception",
/* 21 */ "TLB miss exception",
/* 22 */ "TLB write exception",
/* 23 */ "TLB invalid exception",
/* 24 */ "illegal address exception",
/* 25 */ "privileged address exception",
/* 26 */ "unknown exception",
/* 27 */ "unknown exception",
/* 28 */ "unknown exception",
/* 29 */ "unknown exception",
/* 30 */ "unknown exception",
/* 31 */ "unknown exception"
};
 
 
void defaultISR(int irq, unsigned int *registers) {
printf("\n%s\n", exceptionCause[irq]);
}
 
 
void initInterrupts(void) {
int i;
 
for (i = 0; i < 32; i++) {
setISR(i, defaultISR);
}
}
 
 
/**************************************************************/
 
 
unsigned int getNumber(unsigned char *p) {
return (unsigned int) *(p + 0) << 24 |
(unsigned int) *(p + 1) << 16 |
(unsigned int) *(p + 2) << 8 |
(unsigned int) *(p + 3) << 0;
}
 
 
void loadTask(unsigned char *code,
unsigned int physCodeAddr,
unsigned int physDataAddr) {
unsigned int magic;
unsigned int csize;
unsigned int dsize;
unsigned int bsize;
unsigned char *virtLoadAddr;
int i;
 
magic = getNumber(code);
code += sizeof(unsigned int);
csize = getNumber(code);
code += sizeof(unsigned int);
dsize = getNumber(code);
code += sizeof(unsigned int);
bsize = getNumber(code);
code += sizeof(unsigned int);
if (magic != 0x1AA09232) {
printf("Error: Load module is not executable!\n");
while (1) ;
}
code += 4 * sizeof(unsigned int);
printf("(csize = 0x%x, dsize = 0x%x, bsize = 0x%x)\n",
csize, dsize, bsize);
virtLoadAddr = (unsigned char *) (0xC0000000 | physCodeAddr);
for (i = 0; i < csize; i++) {
*virtLoadAddr++ = *code++;
}
virtLoadAddr = (unsigned char *) (0xC0000000 | physDataAddr);
for (i = 0; i < dsize; i++) {
*virtLoadAddr++ = *code++;
}
for (i = 0; i < bsize; i++) {
*virtLoadAddr++ = '\0';
}
}
 
 
/**************************************************************/
 
 
void trapISR(int irq, unsigned int *registers) {
/* 'putchar' is the only system call yet */
putchar(registers[4]);
/* skip the trap instruction */
registers[30] += 4;
}
 
 
/**************************************************************/
 
 
void missISR(int irq, unsigned int *registers) {
if (currentTask == 1) {
setTLB(5, 0x00000000, 64 << 12 | 0x01); /* code at 256 k */
setTLB(27, 0x00001000, 68 << 12 | 0x03); /* data at 272 k */
setTLB(22, 0x7FFFF000, 80 << 12 | 0x03); /* user-mode stack at 320 k */
} else if (currentTask == 2) {
setTLB(5, 0x00000000, 96 << 12 | 0x01); /* code at 384 k */
setTLB(27, 0x00001000, 100 << 12 | 0x03); /* data at 400 k */
setTLB(22, 0x7FFFF000, 112 << 12 | 0x03); /* user-mode stack at 448 k */
}
}
 
 
void flushTLB(void) {
unsigned int invalPage;
int i;
 
invalPage = 0xC0000000;
for (i = 0; i < 32; i++) {
setTLB(i, invalPage, 0);
invalPage += (1 << 12);
}
}
 
 
/**************************************************************/
 
 
void initTimer(void) {
unsigned int *timerBase;
 
timerBase = (unsigned int *) 0xF0000000;
*(timerBase + 1) = 1000;
*timerBase = 2;
orMask(1 << 14);
}
 
 
int task1Started = 0;
int task2Started = 0;
 
 
void timerISR(int irq, unsigned int *registers) {
unsigned int *timerBase;
 
timerBase = (unsigned int *) 0xF0000000;
*timerBase = 2;
printf(">|<");
if (currentTask == 0) {
if (!task1Started) {
/* load & start task1 */
printf("\nOS: loading task1\n");
loadTask(task1Code, 64 << 12, 68 << 12);
printf("OS: starting task1\n");
task1Started = 1;
currentTask = 1;
currentStkTop = task1StkTop;
flushTLB();
startTask();
}
} else if (currentTask == 1) {
if (!task2Started) {
/* load & start task2 */
printf("\nOS: loading task2\n");
loadTask(task2Code, 96 << 12, 100 << 12);
printf("OS: starting task2\n");
task2Started = 1;
currentTask = 2;
currentStkTop = task2StkTop;
flushTLB();
startTask();
} else {
/* switch tasks */
currentTask = 2;
currentStkTop = task2StkTop;
flushTLB();
}
} else if (currentTask == 2) {
/* switch tasks */
currentTask = 1;
currentStkTop = task1StkTop;
flushTLB();
}
}
 
 
/**************************************************************/
 
 
void main(void) {
currentTask = 0;
currentStkTop = task0StkTop;
printf("\n");
printf("OS: initializing interrupts\n");
initInterrupts();
setISR(20, trapISR);
setISR(21, missISR);
setISR(14, timerISR);
printf("OS: initializing timer\n");
initTimer();
printf("OS: waiting for interrupt...\n");
enable();
while (1) ;
}
/eco32/trunk/stdalone/twotasks-1/os/end.s
0,0 → 1,19
;
; end.s -- end-of-segment labels
;
 
.export _ecode
.export _edata
.export _ebss
 
.code
.align 4
_ecode:
 
.data
.align 4
_edata:
 
.bss
.align 4
_ebss:
/eco32/trunk/stdalone/twotasks-1/os/stdarg.h
0,0 → 1,41
/*
* stdarg.h -- variable argument lists
*/
 
 
#ifndef _STDARG_H_
#define _STDARG_H_
 
 
typedef char *va_list;
 
 
static float __va_arg_tmp;
 
 
#define va_start(list, start) \
((void)((list) = (sizeof(start)<4 ? \
(char *)((int *)&(start)+1) : (char *)(&(start)+1))))
 
#define __va_arg(list, mode, n) \
(__typecode(mode)==1 && sizeof(mode)==4 ? \
(__va_arg_tmp = *(double *)(&(list += \
((sizeof(double)+n)&~n))[-(int)((sizeof(double)+n)&~n)]), \
*(mode *)&__va_arg_tmp) : \
*(mode *)(&(list += \
((sizeof(mode)+n)&~n))[-(int)((sizeof(mode)+n)&~n)]))
 
#define _bigendian_va_arg(list, mode, n) \
(sizeof(mode)==1 ? *(mode *)(&(list += 4)[-1]) : \
sizeof(mode)==2 ? *(mode *)(&(list += 4)[-2]) : \
__va_arg(list, mode, n))
 
#define va_end(list) ((void)0)
 
#define va_arg(list, mode) \
(sizeof(mode)==8 ? \
*(mode *)(&(list = (char*)(((int)list + 15)&~7U))[-8]) : \
_bigendian_va_arg(list, mode, 3U))
 
 
#endif /* _STDARG_H_ */
/eco32/trunk/stdalone/twotasks-1/os/Makefile
0,0 → 1,23
BUILD = ../../../build
 
SRC = start.s main.c end.s
BIN = twotasks-1.bin
MAP = twotasks-1.map
 
all: $(BIN)
 
run: $(BIN)
$(BUILD)/bin/sim -i -t 1 -l $(BIN)
 
$(BIN): $(SRC) task1.dump task2.dump
$(BUILD)/bin/lcc -A -Wo-kernel \
-Wl-m -Wl$(MAP) -o $(BIN) $(SRC)
 
task1.dump:
../dump/dump ../task1/task1 task1.dump
 
task2.dump:
../dump/dump ../task2/task2 task2.dump
 
clean:
rm -f *~ task1.dump task2.dump $(BIN) $(MAP)
/eco32/trunk/stdalone/twotasks-1/os/start.s
0,0 → 1,278
;
; start.s -- startup code
;
 
.import main
.import task0StkTop
.import currentStkTop
.import _ecode
.import _edata
.import _ebss
 
.export _bcode
.export _bdata
.export _bbss
 
.export enable
.export disable
.export orMask
.export andMask
.export getISR
.export setISR
.export startTask
.export setTLB
 
.code
_bcode:
 
.data
_bdata:
 
.bss
_bbss:
 
.code
 
; reset arrives here
reset:
j start
 
; interrupts arrive here
intrpt:
j isr
 
; user TLB misses arrive here
userMiss:
j isr
 
isr:
add $26,$29,$0 ; sp -> $26
add $27,$1,$0 ; $1 -> $27
ldw $29,$0,currentStkTop ; setup kernel mode stack
sub $29,$29,128 ; save registers
stw $2,$29,8
stw $3,$29,12
stw $4,$29,16
stw $5,$29,20
stw $6,$29,24
stw $7,$29,28
stw $8,$29,32
stw $9,$29,36
stw $10,$29,40
stw $11,$29,44
stw $12,$29,48
stw $13,$29,52
stw $14,$29,56
stw $15,$29,60
stw $16,$29,64
stw $17,$29,68
stw $18,$29,72
stw $19,$29,76
stw $20,$29,80
stw $21,$29,84
stw $22,$29,88
stw $23,$29,92
stw $24,$29,96
stw $25,$29,100
stw $26,$29,116 ; this is the task's sp
stw $27,$29,4 ; this is the task's $1
stw $30,$29,120 ; this is the task's resumption addr
stw $31,$29,124
add $5,$29,$0 ; $5 = pointer to register array
mvfs $4,0 ; $4 = IRQ number
slr $4,$4,16
and $4,$4,0x1F
sll $26,$4,2 ; $26 = 4 * IRQ number
ldw $26,$26,irqsrv ; get addr of service routine
jalr $26 ; call service routine
j resume ; resume task if ISR returns
 
; resume a task
resume:
ldw $29,$0,currentStkTop ; setup kernel mode stack
sub $29,$29,128 ; restore registers
ldw $2,$29,8
ldw $3,$29,12
ldw $4,$29,16
ldw $5,$29,20
ldw $6,$29,24
ldw $7,$29,28
ldw $8,$29,32
ldw $9,$29,36
ldw $10,$29,40
ldw $11,$29,44
ldw $12,$29,48
ldw $13,$29,52
ldw $14,$29,56
ldw $15,$29,60
ldw $16,$29,64
ldw $17,$29,68
ldw $18,$29,72
ldw $19,$29,76
ldw $20,$29,80
ldw $21,$29,84
ldw $22,$29,88
ldw $23,$29,92
ldw $24,$29,96
ldw $25,$29,100
ldw $26,$29,116 ; this is the task's sp
ldw $27,$29,4 ; this is the task's $1
ldw $30,$29,120 ; this is the task's resumption addr
ldw $31,$29,124
add $1,$27,$0 ; $27 -> $1
add $29,$26,$0 ; $26 -> sp
rfx ; return from exception
 
start:
mvfs $8,0
or $8,$8,1 << 27 ; let vector point to RAM
mvts $8,0
add $10,$0,_bdata ; copy data segment
add $8,$0,_edata
sub $9,$8,$10
add $9,$9,_ecode
j cpytest
cpyloop:
ldw $11,$9,0
stw $11,$8,0
cpytest:
sub $8,$8,4
sub $9,$9,4
bgeu $8,$10,cpyloop
add $8,$0,_bbss ; clear bss
add $9,$0,_ebss
j clrtest
clrloop:
stw $0,$8,0
add $8,$8,4
clrtest:
bltu $8,$9,clrloop
ldw $29,$0,task0StkTop ; setup kernel mode stack for task 0
jal main ; call 'main'
start1:
j start1 ; loop
 
enable:
mvfs $8,0
or $8,$8,1 << 23
mvts $8,0
jr $31
 
disable:
mvfs $8,0
and $8,$8,~(1 << 23)
mvts $8,0
jr $31
 
orMask:
mvfs $8,0
and $4,$4,0x0000FFFF ; use lower 16 bits only
or $8,$8,$4
mvts $8,0
jr $31
 
andMask:
mvfs $8,0
or $4,$4,0xFFFF0000 ; use lower 16 bits only
and $8,$8,$4
mvts $8,0
jr $31
 
getISR:
sll $4,$4,2
ldw $2,$4,irqsrv
jr $31
 
setISR:
sll $4,$4,2
stw $5,$4,irqsrv
jr $31
 
startTask:
ldw $29,$0,currentStkTop ; setup kernel mode stack
sub $29,$29,128
stw $0,$29,0 ; preset registers
stw $0,$29,4
stw $0,$29,8
stw $0,$29,12
stw $0,$29,16
stw $0,$29,20
stw $0,$29,24
stw $0,$29,28
stw $0,$29,32
stw $0,$29,36
stw $0,$29,40
stw $0,$29,44
stw $0,$29,48
stw $0,$29,52
stw $0,$29,56
stw $0,$29,60
stw $0,$29,64
stw $0,$29,68
stw $0,$29,72
stw $0,$29,76
stw $0,$29,80
stw $0,$29,84
stw $0,$29,88
stw $0,$29,92
stw $0,$29,96
stw $0,$29,100
stw $0,$29,104
stw $0,$29,108
stw $0,$29,112
add $8,$0,0x80000000
stw $8,$29,116 ; sp
stw $0,$29,120 ; task starts at virtual addr 0
stw $0,$29,124
mvfs $8,0
or $8,$8,1 << 25 ; set previous mode to 'user'
or $8,$8,1 << 22 ; and enable interrupts
mvts $8,0
j resume
 
setTLB:
mvts $4,1 ; set index
mvts $5,2 ; set entryHi
mvts $6,3 ; set entryLo
tbwi ; write TLB entry at index
jr $31
 
.data
 
; interrupt service routine table
 
.align 4
 
irqsrv:
.word 0 ; 00: terminal 0 transmitter interrupt
.word 0 ; 01: terminal 0 receiver interrupt
.word 0 ; 02: terminal 1 transmitter interrupt
.word 0 ; 03: terminal 1 receiver interrupt
.word 0 ; 04: keyboard interrupt
.word 0 ; 05: unused
.word 0 ; 06: unused
.word 0 ; 07: unused
.word 0 ; 08: disk interrupt
.word 0 ; 09: unused
.word 0 ; 10: unused
.word 0 ; 11: unused
.word 0 ; 12: unused
.word 0 ; 13: unused
.word 0 ; 14: timer interrupt
.word 0 ; 15: unused
.word 0 ; 16: bus timeout exception
.word 0 ; 17: illegal instruction exception
.word 0 ; 18: privileged instruction exception
.word 0 ; 19: divide instruction exception
.word 0 ; 20: trap instruction exception
.word 0 ; 21: TLB miss exception
.word 0 ; 22: TLB write exception
.word 0 ; 23: TLB invalid exception
.word 0 ; 24: illegal address exception
.word 0 ; 25: privileged address exception
.word 0 ; 26: unused
.word 0 ; 27: unused
.word 0 ; 28: unused
.word 0 ; 29: unused
.word 0 ; 30: unused
.word 0 ; 31: unused
/eco32/trunk/stdalone/twotasks-1/task1/c0.s
0,0 → 1,30
;
; c0.s -- startup code and begin-of-segment labels
;
 
.import main
 
.export _bcode
.export _bdata
.export _bbss
 
.import _ecode
.import _edata
.import _ebss
 
.code
_bcode:
 
.data
_bdata:
 
.bss
_bbss:
 
.code
.align 4
 
start:
jal main ; call 'main' function
stop:
j stop ; just to be sure...
/eco32/trunk/stdalone/twotasks-1/task1/c1.s
0,0 → 1,19
;
; c1.s -- end-of-segment labels
;
 
.export _ecode
.export _edata
.export _ebss
 
.code
.align 4
_ecode:
 
.data
.align 4
_edata:
 
.bss
.align 4
_ebss:
/eco32/trunk/stdalone/twotasks-1/task1/task1.c
0,0 → 1,95
/*
* task1.c -- a simple task
*/
 
 
#include "putchar.h"
#include "stdarg.h"
 
 
/**************************************************************/
 
 
void puts(char *s) {
char c;
 
while ((c = *s++) != '\0') {
putchar(c);
}
}
 
 
void printn(int n) {
int a;
 
if (n < 0) {
putchar('-');
n = -n;
}
a = n / 10;
if (a != 0) {
printn(a);
}
putchar(n % 10 + '0');
}
 
 
void printu(unsigned int n, unsigned int b) {
unsigned int a;
 
a = n / b;
if (a != 0) {
printu(a, b);
}
putchar("0123456789ABCDEF"[n % b]);
}
 
 
void printf(char *fmt, ...) {
va_list ap;
char c;
int n;
unsigned int u;
char *s;
 
va_start(ap, fmt);
while (1) {
while ((c = *fmt++) != '%') {
if (c == '\0') {
va_end(ap);
return;
}
putchar(c);
}
c = *fmt++;
if (c == 'd') {
n = va_arg(ap, int);
printn(n);
} else
if (c == 'u' || c == 'o' || c == 'x') {
u = va_arg(ap, int);
printu(u, c == 'o' ? 8 : (c == 'x' ? 16 : 10));
} else
if (c == 's') {
s = va_arg(ap, char *);
puts(s);
} else {
putchar(c);
}
}
}
 
 
/**************************************************************/
 
 
void main(void) {
int i;
 
printf("TASK1: executing...\n");
i = 0;
while (1) {
printf("TASK1: %d\n", i);
i++;
}
}
/eco32/trunk/stdalone/twotasks-1/task1/putchar.s
0,0 → 1,10
;
; putchar.s -- putchar library function
;
 
.code
.export putchar
 
putchar:
trap
jr $31
/eco32/trunk/stdalone/twotasks-1/task1/stdarg.h
0,0 → 1,41
/*
* stdarg.h -- variable argument lists
*/
 
 
#ifndef _STDARG_H_
#define _STDARG_H_
 
 
typedef char *va_list;
 
 
static float __va_arg_tmp;
 
 
#define va_start(list, start) \
((void)((list) = (sizeof(start)<4 ? \
(char *)((int *)&(start)+1) : (char *)(&(start)+1))))
 
#define __va_arg(list, mode, n) \
(__typecode(mode)==1 && sizeof(mode)==4 ? \
(__va_arg_tmp = *(double *)(&(list += \
((sizeof(double)+n)&~n))[-(int)((sizeof(double)+n)&~n)]), \
*(mode *)&__va_arg_tmp) : \
*(mode *)(&(list += \
((sizeof(mode)+n)&~n))[-(int)((sizeof(mode)+n)&~n)]))
 
#define _bigendian_va_arg(list, mode, n) \
(sizeof(mode)==1 ? *(mode *)(&(list += 4)[-1]) : \
sizeof(mode)==2 ? *(mode *)(&(list += 4)[-2]) : \
__va_arg(list, mode, n))
 
#define va_end(list) ((void)0)
 
#define va_arg(list, mode) \
(sizeof(mode)==8 ? \
*(mode *)(&(list = (char*)(((int)list + 15)&~7U))[-8]) : \
_bigendian_va_arg(list, mode, 3U))
 
 
#endif /* _STDARG_H_ */
/eco32/trunk/stdalone/twotasks-1/task1/putchar.h
0,0 → 1,13
/*
* putchar.h -- putchar library function
*/
 
 
#ifndef _PUTCHAR_H_
#define _PUTCHAR_H_
 
 
void putchar(char c);
 
 
#endif /* _PUTCHAR_H_ */
/eco32/trunk/stdalone/twotasks-1/task1/Makefile
0,0 → 1,21
BUILD = ../../../build
 
all: task1
 
task1: c0.o task1.o putchar.o c1.o
$(BUILD)/bin/ld -o task1 c0.o task1.o putchar.o c1.o
 
c0.o: c0.s
$(BUILD)/bin/as -o c0.o c0.s
 
task1.o: task1.c
$(BUILD)/bin/lcc -A -c -o task1.o task1.c
 
putchar.o: putchar.s
$(BUILD)/bin/as -o putchar.o putchar.s
 
c1.o: c1.s
$(BUILD)/bin/as -o c1.o c1.s
 
clean:
rm -f *~ c0.o task1.o putchar.o c1.o task1
/eco32/trunk/stdalone/twotasks-1/task2/c0.s
0,0 → 1,30
;
; c0.s -- startup code and begin-of-segment labels
;
 
.import main
 
.export _bcode
.export _bdata
.export _bbss
 
.import _ecode
.import _edata
.import _ebss
 
.code
_bcode:
 
.data
_bdata:
 
.bss
_bbss:
 
.code
.align 4
 
start:
jal main ; call 'main' function
stop:
j stop ; just to be sure...
/eco32/trunk/stdalone/twotasks-1/task2/c1.s
0,0 → 1,19
;
; c1.s -- end-of-segment labels
;
 
.export _ecode
.export _edata
.export _ebss
 
.code
.align 4
_ecode:
 
.data
.align 4
_edata:
 
.bss
.align 4
_ebss:
/eco32/trunk/stdalone/twotasks-1/task2/task2.c
0,0 → 1,95
/*
* task2.c -- a simple task
*/
 
 
#include "putchar.h"
#include "stdarg.h"
 
 
/**************************************************************/
 
 
void puts(char *s) {
char c;
 
while ((c = *s++) != '\0') {
putchar(c);
}
}
 
 
void printn(int n) {
int a;
 
if (n < 0) {
putchar('-');
n = -n;
}
a = n / 10;
if (a != 0) {
printn(a);
}
putchar(n % 10 + '0');
}
 
 
void printu(unsigned int n, unsigned int b) {
unsigned int a;
 
a = n / b;
if (a != 0) {
printu(a, b);
}
putchar("0123456789ABCDEF"[n % b]);
}
 
 
void printf(char *fmt, ...) {
va_list ap;
char c;
int n;
unsigned int u;
char *s;
 
va_start(ap, fmt);
while (1) {
while ((c = *fmt++) != '%') {
if (c == '\0') {
va_end(ap);
return;
}
putchar(c);
}
c = *fmt++;
if (c == 'd') {
n = va_arg(ap, int);
printn(n);
} else
if (c == 'u' || c == 'o' || c == 'x') {
u = va_arg(ap, int);
printu(u, c == 'o' ? 8 : (c == 'x' ? 16 : 10));
} else
if (c == 's') {
s = va_arg(ap, char *);
puts(s);
} else {
putchar(c);
}
}
}
 
 
/**************************************************************/
 
 
void main(void) {
int i;
 
printf("TASK2: executing...\n");
i = 0;
while (1) {
printf("TASK2: %d\n", i);
i++;
}
}
/eco32/trunk/stdalone/twotasks-1/task2/putchar.s
0,0 → 1,10
;
; putchar.s -- putchar library function
;
 
.code
.export putchar
 
putchar:
trap
jr $31
/eco32/trunk/stdalone/twotasks-1/task2/stdarg.h
0,0 → 1,41
/*
* stdarg.h -- variable argument lists
*/
 
 
#ifndef _STDARG_H_
#define _STDARG_H_
 
 
typedef char *va_list;
 
 
static float __va_arg_tmp;
 
 
#define va_start(list, start) \
((void)((list) = (sizeof(start)<4 ? \
(char *)((int *)&(start)+1) : (char *)(&(start)+1))))
 
#define __va_arg(list, mode, n) \
(__typecode(mode)==1 && sizeof(mode)==4 ? \
(__va_arg_tmp = *(double *)(&(list += \
((sizeof(double)+n)&~n))[-(int)((sizeof(double)+n)&~n)]), \
*(mode *)&__va_arg_tmp) : \
*(mode *)(&(list += \
((sizeof(mode)+n)&~n))[-(int)((sizeof(mode)+n)&~n)]))
 
#define _bigendian_va_arg(list, mode, n) \
(sizeof(mode)==1 ? *(mode *)(&(list += 4)[-1]) : \
sizeof(mode)==2 ? *(mode *)(&(list += 4)[-2]) : \
__va_arg(list, mode, n))
 
#define va_end(list) ((void)0)
 
#define va_arg(list, mode) \
(sizeof(mode)==8 ? \
*(mode *)(&(list = (char*)(((int)list + 15)&~7U))[-8]) : \
_bigendian_va_arg(list, mode, 3U))
 
 
#endif /* _STDARG_H_ */
/eco32/trunk/stdalone/twotasks-1/task2/putchar.h
0,0 → 1,13
/*
* putchar.h -- putchar library function
*/
 
 
#ifndef _PUTCHAR_H_
#define _PUTCHAR_H_
 
 
void putchar(char c);
 
 
#endif /* _PUTCHAR_H_ */
/eco32/trunk/stdalone/twotasks-1/task2/Makefile
0,0 → 1,21
BUILD = ../../../build
 
all: task2
 
task2: c0.o task2.o putchar.o c1.o
$(BUILD)/bin/ld -o task2 c0.o task2.o putchar.o c1.o
 
c0.o: c0.s
$(BUILD)/bin/as -o c0.o c0.s
 
task2.o: task2.c
$(BUILD)/bin/lcc -A -c -o task2.o task2.c
 
putchar.o: putchar.s
$(BUILD)/bin/as -o putchar.o putchar.s
 
c1.o: c1.s
$(BUILD)/bin/as -o c1.o c1.s
 
clean:
rm -f *~ c0.o task2.o putchar.o c1.o task2
/eco32/trunk/stdalone/twotasks-1/dump/dump.c
0,0 → 1,48
/*
* dump.c -- dump a binary file as contents of a C array
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
 
int main(int argc, char *argv[]) {
FILE *infile, *outfile;
int c, n;
 
if (argc != 3) {
printf("Usage: %s <infile> <outfile>\n", argv[0]);
return 1;
}
infile = fopen(argv[1], "rb");
if (infile == NULL) {
printf("Error: cannot open file '%s' for input\n", argv[1]);
return 1;
}
outfile = fopen(argv[2], "wt");
if (outfile == NULL) {
printf("Error: cannot open file '%s' for output\n", argv[2]);
return 1;
}
n = 0;
while (1) {
c = getc(infile);
if (c == EOF) {
break;
}
fprintf(outfile, "0x%02X, ", c);
n++;
if (n == 8) {
n = 0;
fprintf(outfile, "\n");
}
}
if (n != 0) {
fprintf(outfile, "\n");
}
fclose(infile);
fclose(outfile);
return 0;
}
/eco32/trunk/stdalone/twotasks-1/dump/Makefile
0,0 → 1,15
#
# Makefile for dump utility
#
 
.PHONY: all install clean
 
all: dump
 
install: dump
 
dump: dump.c
gcc -m32 -g -Wall -o dump dump.c
 
clean:
rm -f *~ dump
/eco32/trunk/stdalone/twotasks-1/Makefile
0,0 → 1,37
#
# Makefile for "twotasks-1", a tiny OS which runs two tasks
# (with fixed TLB entries and no page tables)
#
 
BUILD = ../../build
 
.PHONY: all install run clean
 
all: dump/dump task1/task1 task2/task2 os/twotasks-1.bin
 
install: dump/dump task1/task1 task2/task2 os/twotasks-1.bin
mkdir -p $(BUILD)/stdalone
cp os/twotasks-1.bin $(BUILD)/stdalone
cp os/twotasks-1.map $(BUILD)/stdalone
 
run: dump/dump task1/task1 task2/task2 os/twotasks-1.bin
$(MAKE) -C os run
 
dump/dump:
$(MAKE) -C dump
 
task1/task1:
$(MAKE) -C task1
 
task2/task2:
$(MAKE) -C task2
 
os/twotasks-1.bin:
$(MAKE) -C os
 
clean:
$(MAKE) -C dump clean
$(MAKE) -C task1 clean
$(MAKE) -C task2 clean
$(MAKE) -C os clean
rm -f *~
/eco32/trunk/stdalone/wrtmbr/mbr/mbr.s
0,0 → 1,54
;
; mbr.s -- the master boot record
;
 
.set tba,0xF0300000 ; terminal base address
.set tos,0xC0001000 ; top of stack
 
start:
add $29,$0,tos ; set stackpointer
jal msgout ; output message
stop:
j stop ; halt by looping
 
msgout:
sub $29,$29,8 ; allocate stack frame
stw $31,$29,0 ; save return register
stw $16,$29,4 ; save local variable
add $16,$0,msg ; pointer to string
loop:
ldbu $4,$16,0 ; get char
beq $4,$0,exit ; null - finished
jal out ; output char
add $16,$16,1 ; bump pointer
j loop ; next char
exit:
ldw $31,$29,0 ; restore return register
ldw $16,$29,4 ; restore local variable
add $29,$29,8 ; release stack frame
jr $31 ; return
 
out:
add $8,$0,tba ; set I/O base address
out1:
ldw $9,$8,8 ; get xmtr status
and $9,$9,1 ; xmtr ready?
beq $9,$0,out1 ; no - wait
stw $4,$8,12 ; send char
jr $31 ; return
 
msg:
.byte 0x0D, 0x0A
.byte "Error: This is the default MBR, "
.byte "which cannot load anything."
.byte 0x0D, 0x0A
.byte "Please replace the disk, or "
.byte "write an operating system onto it."
.byte 0x0D, 0x0A
.byte "Execution halted."
.byte 0x0D, 0x0A
.byte 0x0D, 0x0A, 0
 
.locate 512-2
sign:
.byte 0x55, 0xAA
/eco32/trunk/stdalone/wrtmbr/mbr/dump.c
0,0 → 1,48
/*
* dump.c -- dump a binary file as contents of a C array
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
 
int main(int argc, char *argv[]) {
FILE *infile, *outfile;
int c, n;
 
if (argc != 3) {
printf("Usage: %s <infile> <outfile>\n", argv[0]);
return 1;
}
infile = fopen(argv[1], "rb");
if (infile == NULL) {
printf("Error: cannot open file '%s' for input\n", argv[1]);
return 1;
}
outfile = fopen(argv[2], "wt");
if (outfile == NULL) {
printf("Error: cannot open file '%s' for output\n", argv[2]);
return 1;
}
n = 0;
while (1) {
c = getc(infile);
if (c == EOF) {
break;
}
fprintf(outfile, "0x%02X, ", c);
n++;
if (n == 8) {
n = 0;
fprintf(outfile, "\n");
}
}
if (n != 0) {
fprintf(outfile, "\n");
}
fclose(infile);
fclose(outfile);
return 0;
}
/eco32/trunk/stdalone/wrtmbr/mbr/Makefile
0,0 → 1,24
#
# Makefile for assembling the default master boot record
#
 
BUILD = ../../../build
 
.PHONY: all clean
 
all: mbr.dump
 
mbr.dump: dump mbr.bin
./dump mbr.bin mbr.dump
 
dump: dump.c
gcc -m32 -g -Wall -o dump dump.c
 
mbr.bin: mbr.o
$(BUILD)/bin/ld -h -rc 0xC0000000 -o mbr.bin mbr.o
 
mbr.o: mbr.s
$(BUILD)/bin/as -o mbr.o mbr.s
 
clean:
rm -f *~ dump mbr.o mbr.bin mbr.dump
/eco32/trunk/stdalone/wrtmbr/start.h
0,0 → 1,19
/*
* start.h -- startup code
*/
 
 
#ifndef _START_H_
#define _START_H_
 
 
typedef int (*ISR)(int irq);
 
 
void enable(void);
void disable(void);
ISR getISR(int irq);
void setISR(int irq, ISR isr);
 
 
#endif /* _START_H_ */
/eco32/trunk/stdalone/wrtmbr/main.c
0,0 → 1,312
/*
* main.c -- start the ball rolling
*/
 
 
#include "stdarg.h"
#include "start.h"
 
 
#define SCT_SIZE 512 /* in bytes */
 
#define DISK_BASE 0xF0400000
 
#define DISK_CTRL 0 /* word offset from DISK_BASE */
#define DISK_CNT 1 /* ditto */
#define DISK_SCT 2 /* ditto */
#define DISK_CAP 3 /* ditto */
 
#define DISK_BUF_STRT 0x00020000 /* word offset from DISK_BASE */
#define DISK_BUF_SIZE 0x00000400 /* in words */
 
#define DISK_CTRL_STRT 0x01
#define DISK_CTRL_IEN 0x02
#define DISK_CTRL_WRT 0x04
#define DISK_CTRL_ERR 0x08
#define DISK_CTRL_DONE 0x10
#define DISK_CTRL_RDY 0x20
 
 
/**************************************************************/
 
 
void putchar(char c) {
unsigned int *base;
 
if (c == '\n') {
putchar('\r');
}
base = (unsigned int *) 0xF0300000;
while ((*(base + 2) & 1) == 0) ;
*(base + 3) = c;
}
 
 
void puts(char *s) {
char c;
 
while ((c = *s++) != '\0') {
putchar(c);
}
}
 
 
void printn(int n) {
int a;
 
if (n < 0) {
putchar('-');
n = -n;
}
a = n / 10;
if (a != 0) {
printn(a);
}
putchar(n % 10 + '0');
}
 
 
void printu(unsigned int n, unsigned int b) {
unsigned int a;
 
a = n / b;
if (a != 0) {
printu(a, b);
}
putchar("0123456789ABCDEF"[n % b]);
}
 
 
void printf(char *fmt, ...) {
va_list ap;
char c;
int n;
unsigned int u;
char *s;
 
va_start(ap, fmt);
while (1) {
while ((c = *fmt++) != '%') {
if (c == '\0') {
va_end(ap);
return;
}
putchar(c);
}
c = *fmt++;
if (c == 'd') {
n = va_arg(ap, int);
printn(n);
} else
if (c == 'u' || c == 'o' || c == 'x') {
u = va_arg(ap, int);
printu(u, c == 'o' ? 8 : (c == 'x' ? 16 : 10));
} else
if (c == 's') {
s = va_arg(ap, char *);
puts(s);
} else {
putchar(c);
}
}
}
 
 
/**************************************************************/
 
 
static char *exceptionCause[32] = {
/* 00 */ "terminal 0 transmitter interrupt",
/* 01 */ "terminal 0 receiver interrupt",
/* 02 */ "terminal 1 transmitter interrupt",
/* 03 */ "terminal 1 receiver interrupt",
/* 04 */ "keyboard interrupt",
/* 05 */ "unknown interrupt",
/* 06 */ "unknown interrupt",
/* 07 */ "unknown interrupt",
/* 08 */ "disk interrupt",
/* 09 */ "unknown interrupt",
/* 10 */ "unknown interrupt",
/* 11 */ "unknown interrupt",
/* 12 */ "unknown interrupt",
/* 13 */ "unknown interrupt",
/* 14 */ "timer interrupt",
/* 15 */ "unknown interrupt",
/* 16 */ "bus timeout exception",
/* 17 */ "illegal instruction exception",
/* 18 */ "privileged instruction exception",
/* 19 */ "divide instruction exception",
/* 20 */ "trap instruction exception",
/* 21 */ "TLB miss exception",
/* 22 */ "TLB write exception",
/* 23 */ "TLB invalid exception",
/* 24 */ "illegal address exception",
/* 25 */ "privileged address exception",
/* 26 */ "unknown exception",
/* 27 */ "unknown exception",
/* 28 */ "unknown exception",
/* 29 */ "unknown exception",
/* 30 */ "unknown exception",
/* 31 */ "unknown exception"
};
 
 
int defaultISR(int irq) {
printf("\n%s\n", exceptionCause[irq]);
return 0; /* do not skip any instruction */
}
 
 
void initInterrupts(void) {
int i;
 
for (i = 0; i < 32; i++) {
setISR(i, defaultISR);
}
}
 
 
/**************************************************************/
 
 
/* the MBR buffer need not be word-aligned */
unsigned char mbr[SCT_SIZE] = {
#include "mbr/mbr.dump"
};
 
/* the following two buffers must be word-aligned */
unsigned int wrBuf[SCT_SIZE / sizeof(unsigned int)];
unsigned int rdBuf[SCT_SIZE / sizeof(unsigned int)];
 
 
void copyMBR(void) {
unsigned char *p;
unsigned char *q;
int i;
 
p = (unsigned char *) wrBuf;
q = (unsigned char *) mbr;
for (i = 0; i < SCT_SIZE; i++) {
*p++ = *q++;
}
}
 
 
int compareMBR(void) {
unsigned char *p;
unsigned char *q;
int i;
 
p = (unsigned char *) rdBuf;
q = (unsigned char *) mbr;
for (i = 0; i < SCT_SIZE; i++) {
if (*p++ != *q++) {
return 0;
}
}
return 1;
}
 
 
void clearCtrl(void) {
unsigned int *p;
int i;
 
p = (unsigned int *) DISK_BASE + DISK_BUF_STRT;
for (i = 0; i < DISK_BUF_SIZE; i++) {
*p++ = 0;
}
}
 
 
void copyToCtrl(void) {
unsigned int *p;
unsigned int *q;
int i;
 
p = (unsigned int *) DISK_BASE + DISK_BUF_STRT;
q = (unsigned int *) wrBuf;
for (i = 0; i < SCT_SIZE / sizeof(unsigned int); i++) {
*p++ = *q++;
}
}
 
 
void copyFromCtrl(void) {
unsigned int *p;
unsigned int *q;
int i;
 
p = (unsigned int *) rdBuf;
q = (unsigned int *) DISK_BASE + DISK_BUF_STRT;
for (i = 0; i < SCT_SIZE / sizeof(unsigned int); i++) {
*p++ = *q++;
}
}
 
 
int checkDiskReady(void) {
unsigned int *p;
int tries;
int i;
 
p = (unsigned int *) DISK_BASE;
for (tries = 0; tries < 10; tries++) {
for (i = 0; i < 500000; i++) {
if ((*(p + DISK_CTRL) & DISK_CTRL_RDY) != 0) {
return 1;
}
}
printf(".");
}
return 0;
}
 
 
void writeMBR(void) {
unsigned int *p;
 
p = (unsigned int *) DISK_BASE;
*(p + DISK_CNT) = 1;
*(p + DISK_SCT) = 0;
*(p + DISK_CTRL) = DISK_CTRL_WRT | DISK_CTRL_STRT;
while ((*(p + DISK_CTRL) & DISK_CTRL_DONE) == 0) ;
}
 
 
void readMBR(void) {
unsigned int *p;
 
p = (unsigned int *) DISK_BASE;
*(p + DISK_CNT) = 1;
*(p + DISK_SCT) = 0;
*(p + DISK_CTRL) = DISK_CTRL_STRT;
while ((*(p + DISK_CTRL) & DISK_CTRL_DONE) == 0) ;
}
 
 
void main(void) {
initInterrupts();
printf("Checking disk ready...");
if (!checkDiskReady()) {
printf(" disk not ready\n");
} else {
printf(" ok\n");
printf("Writing MBR...\n");
copyMBR();
clearCtrl();
copyToCtrl();
writeMBR();
printf("Reading MBR...\n");
clearCtrl();
readMBR();
copyFromCtrl();
printf("Comparing MBR...");
if (!compareMBR()) {
printf(" error\n");
} else {
printf(" ok\n");
}
}
printf("Halting...\n");
}
/eco32/trunk/stdalone/wrtmbr/end.s
0,0 → 1,19
;
; end.s -- end-of-segment labels
;
 
.export _ecode
.export _edata
.export _ebss
 
.code
.align 4
_ecode:
 
.data
.align 4
_edata:
 
.bss
.align 4
_ebss:
/eco32/trunk/stdalone/wrtmbr/stdarg.h
0,0 → 1,41
/*
* stdarg.h -- variable argument lists
*/
 
 
#ifndef _STDARG_H_
#define _STDARG_H_
 
 
typedef char *va_list;
 
 
static float __va_arg_tmp;
 
 
#define va_start(list, start) \
((void)((list) = (sizeof(start)<4 ? \
(char *)((int *)&(start)+1) : (char *)(&(start)+1))))
 
#define __va_arg(list, mode, n) \
(__typecode(mode)==1 && sizeof(mode)==4 ? \
(__va_arg_tmp = *(double *)(&(list += \
((sizeof(double)+n)&~n))[-(int)((sizeof(double)+n)&~n)]), \
*(mode *)&__va_arg_tmp) : \
*(mode *)(&(list += \
((sizeof(mode)+n)&~n))[-(int)((sizeof(mode)+n)&~n)]))
 
#define _bigendian_va_arg(list, mode, n) \
(sizeof(mode)==1 ? *(mode *)(&(list += 4)[-1]) : \
sizeof(mode)==2 ? *(mode *)(&(list += 4)[-2]) : \
__va_arg(list, mode, n))
 
#define va_end(list) ((void)0)
 
#define va_arg(list, mode) \
(sizeof(mode)==8 ? \
*(mode *)(&(list = (char*)(((int)list + 15)&~7U))[-8]) : \
_bigendian_va_arg(list, mode, 3U))
 
 
#endif /* _STDARG_H_ */
/eco32/trunk/stdalone/wrtmbr/Makefile
0,0 → 1,32
#
# Makefile for "wrtmbr", a program to write a dummy MBR to the disk
#
 
BUILD = ../../build
 
SRC = start.s main.c end.s
BIN = wrtmbr.bin
MAP = wrtmbr.map
 
.PHONY: all install run clean
 
all: $(BIN)
 
install: $(BIN)
mkdir -p $(BUILD)/stdalone
cp $(BIN) $(BUILD)/stdalone
cp $(MAP) $(BUILD)/stdalone
 
run: $(BIN)
$(BUILD)/bin/sim -i -t 1 -l $(BIN) -d $(BUILD)/disk/disk.img
 
$(BIN): $(SRC) mbr/mbr.dump
$(BUILD)/bin/lcc -A -Wo-kernel \
-Wl-m -Wl$(MAP) -o $(BIN) $(SRC)
 
mbr/mbr.dump:
$(MAKE) -C mbr
 
clean:
$(MAKE) -C mbr clean
rm -f *~ $(BIN) $(MAP)
/eco32/trunk/stdalone/wrtmbr/start.s
0,0 → 1,213
;
; start.s -- startup code
;
 
.import main
.import _ecode
.import _edata
.import _ebss
 
.export _bcode
.export _bdata
.export _bbss
 
.export enable
.export disable
.export getISR
.export setISR
 
.code
_bcode:
 
.data
_bdata:
 
.bss
_bbss:
 
.code
 
; reset arrives here
reset:
j start
 
; interrupts arrive here
intrpt:
j isr
 
; user TLB misses arrive here
userMiss:
j userMiss
 
isr:
add $26,$29,$0 ; sp -> $26
add $27,$1,$0 ; $1 -> $27
add $29,$0,istack ; set stack
sub $29,$29,108
stw $2,$29,0 ; save registers
stw $3,$29,4
stw $4,$29,8
stw $5,$29,12
stw $6,$29,16
stw $7,$29,20
stw $8,$29,24
stw $9,$29,28
stw $10,$29,32
stw $11,$29,36
stw $12,$29,40
stw $13,$29,44
stw $14,$29,48
stw $15,$29,52
stw $16,$29,56
stw $17,$29,60
stw $18,$29,64
stw $19,$29,68
stw $20,$29,72
stw $21,$29,76
stw $22,$29,80
stw $23,$29,84
stw $24,$29,88
stw $25,$29,92
stw $26,$29,96
stw $27,$29,100
stw $31,$29,104
mvfs $4,0 ; $4 = IRQ number
slr $4,$4,16
and $4,$4,0x1F
sll $26,$4,2 ; $26 = 4 * IRQ number
ldw $26,$26,irqsrv ; get addr of service routine
jalr $26 ; call service routine
beq $2,$0,resume ; resume instruction if ISR returned 0
add $30,$30,4 ; else skip offending instruction
resume:
ldw $2,$29,0
ldw $3,$29,4
ldw $4,$29,8
ldw $5,$29,12
ldw $6,$29,16
ldw $7,$29,20
ldw $8,$29,24
ldw $9,$29,28
ldw $10,$29,32
ldw $11,$29,36
ldw $12,$29,40
ldw $13,$29,44
ldw $14,$29,48
ldw $15,$29,52
ldw $16,$29,56
ldw $17,$29,60
ldw $18,$29,64
ldw $19,$29,68
ldw $20,$29,72
ldw $21,$29,76
ldw $22,$29,80
ldw $23,$29,84
ldw $24,$29,88
ldw $25,$29,92
ldw $26,$29,96
ldw $27,$29,100
ldw $31,$29,104
add $1,$27,$0 ; $27 -> $1
add $29,$26,0 ; $26 -> sp
rfx ; return from exception
 
start:
mvfs $8,0
or $8,$8,1 << 27 ; let vector point to RAM
mvts $8,0
add $29,$0,stack ; set sp
add $10,$0,_bdata ; copy data segment
add $8,$0,_edata
sub $9,$8,$10
add $9,$9,_ecode
j cpytest
cpyloop:
ldw $11,$9,0
stw $11,$8,0
cpytest:
sub $8,$8,4
sub $9,$9,4
bgeu $8,$10,cpyloop
add $8,$0,_bbss ; clear bss
add $9,$0,_ebss
j clrtest
clrloop:
stw $0,$8,0
add $8,$8,4
clrtest:
bltu $8,$9,clrloop
jal main ; call 'main'
start1:
j start1 ; loop
 
enable:
mvfs $8,0
or $8,$8,1 << 23
mvts $8,0
jr $31
 
disable:
mvfs $8,0
and $8,$8,~(1 << 23)
mvts $8,0
jr $31
 
getISR:
sll $4,$4,2
ldw $2,$4,irqsrv
jr $31
 
setISR:
sll $4,$4,2
stw $5,$4,irqsrv
jr $31
 
.data
 
; interrupt service routine table
 
.align 4
 
irqsrv:
.word 0 ; 00: terminal 0 transmitter interrupt
.word 0 ; 01: terminal 0 receiver interrupt
.word 0 ; 02: terminal 1 transmitter interrupt
.word 0 ; 03: terminal 1 receiver interrupt
.word 0 ; 04: keyboard interrupt
.word 0 ; 05: unused
.word 0 ; 06: unused
.word 0 ; 07: unused
.word 0 ; 08: disk interrupt
.word 0 ; 09: unused
.word 0 ; 10: unused
.word 0 ; 11: unused
.word 0 ; 12: unused
.word 0 ; 13: unused
.word 0 ; 14: timer interrupt
.word 0 ; 15: unused
.word 0 ; 16: bus timeout exception
.word 0 ; 17: illegal instruction exception
.word 0 ; 18: privileged instruction exception
.word 0 ; 19: divide instruction exception
.word 0 ; 20: trap instruction exception
.word 0 ; 21: TLB miss exception
.word 0 ; 22: TLB write exception
.word 0 ; 23: TLB invalid exception
.word 0 ; 24: illegal address exception
.word 0 ; 25: privileged address exception
.word 0 ; 26: unused
.word 0 ; 27: unused
.word 0 ; 28: unused
.word 0 ; 29: unused
.word 0 ; 30: unused
.word 0 ; 31: unused
 
.bss
 
.align 4
.space 0x800
stack:
 
.align 4
.space 0x800
istack:
/eco32/trunk/stdalone/Makefile
0,0 → 1,27
#
# Makefile for building standalone test programs
# (which are to be loaded from disk by a boot-loader)
#
 
BUILD = ../build
 
DIRS = hello hello2 memsize onetask twotasks-1 twotasks-2 \
wrtmbr dskchk mkpart shpart
 
.PHONY: all install clean
 
all:
for i in $(DIRS) ; do \
$(MAKE) -C $$i all ; \
done
 
install:
for i in $(DIRS) ; do \
$(MAKE) -C $$i install ; \
done
 
clean:
for i in $(DIRS) ; do \
$(MAKE) -C $$i clean ; \
done
rm -f *~
/eco32/trunk/stdalone/mkpart/iolib.c
0,0 → 1,329
/*
* iolib.c -- I/O library
*/
 
 
#include "types.h"
#include "stdarg.h"
#include "iolib.h"
#include "biolib.h"
 
 
/**************************************************************/
 
/* string functions */
 
 
int strlen(char *str) {
int i;
 
i = 0;
while (*str++ != '\0') {
i++;
}
return i;
}
 
 
void strcpy(char *dst, char *src) {
while ((*dst++ = *src++) != '\0') ;
}
 
 
void memcpy(unsigned char *dst, unsigned char *src, unsigned int cnt) {
while (cnt--) {
*dst++ = *src++;
}
}
 
 
/**************************************************************/
 
/* terminal I/O */
 
 
char getchar(void) {
return getc();
}
 
 
void putchar(char c) {
if (c == '\n') {
putchar('\r');
}
putc(c);
}
 
 
void putString(char *s) {
while (*s != '\0') {
putchar(*s++);
}
}
 
 
/**************************************************************/
 
/* get a line from the terminal */
 
 
void getLine(char *prompt, char *line, int max) {
int index;
char c;
 
putString(prompt);
putString(line);
index = strlen(line);
while (1) {
c = getchar();
switch (c) {
case '\r':
putchar('\n');
line[index] = '\0';
return;
case '\b':
case 0x7F:
if (index == 0) {
break;
}
putchar('\b');
putchar(' ');
putchar('\b');
index--;
break;
default:
if (c == '\t') {
c = ' ';
}
if (c < 0x20 || c > 0x7E) {
break;
}
putchar(c);
line[index++] = c;
break;
}
}
}
 
 
/**************************************************************/
 
/* scaled-down version of printf */
 
 
/*
* Count the number of characters needed to represent
* a given number in base 10.
*/
int countPrintn(long n) {
long a;
int res;
 
res = 0;
if (n < 0) {
res++;
n = -n;
}
a = n / 10;
if (a != 0) {
res += countPrintn(a);
}
return res + 1;
}
 
 
/*
* Output a number in base 10.
*/
void printn(long n) {
long a;
 
if (n < 0) {
putchar('-');
n = -n;
}
a = n / 10;
if (a != 0) {
printn(a);
}
putchar(n % 10 + '0');
}
 
 
/*
* Count the number of characters needed to represent
* a given number in a given base.
*/
int countPrintu(unsigned long n, unsigned long b) {
unsigned long a;
int res;
 
res = 0;
a = n / b;
if (a != 0) {
res += countPrintu(a, b);
}
return res + 1;
}
 
 
/*
* Output a number in a given base.
*/
void printu(unsigned long n, unsigned long b, Bool upperCase) {
unsigned long a;
 
a = n / b;
if (a != 0) {
printu(a, b, upperCase);
}
if (upperCase) {
putchar("0123456789ABCDEF"[n % b]);
} else {
putchar("0123456789abcdef"[n % b]);
}
}
 
 
/*
* Output a number of filler characters.
*/
void fill(int numFillers, char filler) {
while (numFillers-- > 0) {
putchar(filler);
}
}
 
 
/*
* Formatted output with a variable argument list.
*/
void vprintf(char *fmt, va_list ap) {
char c;
int n;
long ln;
unsigned int u;
unsigned long lu;
char *s;
Bool negFlag;
char filler;
int width, count;
 
while (1) {
while ((c = *fmt++) != '%') {
if (c == '\0') {
return;
}
putchar(c);
}
c = *fmt++;
if (c == '-') {
negFlag = TRUE;
c = *fmt++;
} else {
negFlag = FALSE;
}
if (c == '0') {
filler = '0';
c = *fmt++;
} else {
filler = ' ';
}
width = 0;
while (c >= '0' && c <= '9') {
width *= 10;
width += c - '0';
c = *fmt++;
}
if (c == 'd') {
n = va_arg(ap, int);
count = countPrintn(n);
if (width > 0 && !negFlag) {
fill(width - count, filler);
}
printn(n);
if (width > 0 && negFlag) {
fill(width - count, filler);
}
} else
if (c == 'u' || c == 'o' || c == 'x' || c == 'X') {
u = va_arg(ap, int);
count = countPrintu(u,
c == 'o' ? 8 : ((c == 'x' || c == 'X') ? 16 : 10));
if (width > 0 && !negFlag) {
fill(width - count, filler);
}
printu(u,
c == 'o' ? 8 : ((c == 'x' || c == 'X') ? 16 : 10),
c == 'X');
if (width > 0 && negFlag) {
fill(width - count, filler);
}
} else
if (c == 'l') {
c = *fmt++;
if (c == 'd') {
ln = va_arg(ap, long);
count = countPrintn(ln);
if (width > 0 && !negFlag) {
fill(width - count, filler);
}
printn(ln);
if (width > 0 && negFlag) {
fill(width - count, filler);
}
} else
if (c == 'u' || c == 'o' || c == 'x' || c == 'X') {
lu = va_arg(ap, long);
count = countPrintu(lu,
c == 'o' ? 8 : ((c == 'x' || c == 'X') ? 16 : 10));
if (width > 0 && !negFlag) {
fill(width - count, filler);
}
printu(lu,
c == 'o' ? 8 : ((c == 'x' || c == 'X') ? 16 : 10),
c == 'X');
if (width > 0 && negFlag) {
fill(width - count, filler);
}
} else {
putchar('l');
putchar(c);
}
} else
if (c == 's') {
s = va_arg(ap, char *);
count = strlen(s);
if (width > 0 && !negFlag) {
fill(width - count, filler);
}
while ((c = *s++) != '\0') {
putchar(c);
}
if (width > 0 && negFlag) {
fill(width - count, filler);
}
} else
if (c == 'c') {
c = va_arg(ap, char);
putchar(c);
} else {
putchar(c);
}
}
}
 
 
/*
* Formatted output.
* This is a scaled-down version of the C library's
* printf. Used to print diagnostic information on
* the console (and optionally to a logfile).
*/
void printf(char *fmt, ...) {
va_list ap;
 
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
}
/eco32/trunk/stdalone/mkpart/biolib.c
0,0 → 1,26
/*
* biolib.c -- basic I/O library
*/
 
 
#include "biolib.h"
 
 
char getc(void) {
unsigned int *base;
char c;
 
base = (unsigned int *) 0xF0300000;
while ((*(base + 0) & 1) == 0) ;
c = *(base + 1);
return c;
}
 
 
void putc(char c) {
unsigned int *base;
 
base = (unsigned int *) 0xF0300000;
while ((*(base + 2) & 1) == 0) ;
*(base + 3) = c;
}
/eco32/trunk/stdalone/mkpart/start.h
0,0 → 1,21
/*
* start.h -- startup code
*/
 
 
#ifndef _START_H_
#define _START_H_
 
 
typedef int (*ISR)(int irq);
 
 
void enable(void);
void disable(void);
int getMask(void);
void setMask(int mask);
ISR getISR(int irq);
void setISR(int irq, ISR isr);
 
 
#endif /* _START_H_ */
/eco32/trunk/stdalone/mkpart/iolib.h
0,0 → 1,21
/*
* iolib.h -- I/O library
*/
 
 
#ifndef _IOLIB_H_
#define _IOLIB_H_
 
 
int strlen(char *str);
void strcpy(char *dst, char *src);
void memcpy(unsigned char *dst, unsigned char *src, unsigned int cnt);
char getchar(void);
void putchar(char c);
void putString(char *s);
void getLine(char *prompt, char *line, int max);
void vprintf(char *fmt, va_list ap);
void printf(char *fmt, ...);
 
 
#endif /* _IOLIB_H_ */
/eco32/trunk/stdalone/mkpart/dump/dump.c
0,0 → 1,48
/*
* dump.c -- dump a binary file as contents of a C array
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
 
int main(int argc, char *argv[]) {
FILE *infile, *outfile;
int c, n;
 
if (argc != 3) {
printf("Usage: %s <infile> <outfile>\n", argv[0]);
return 1;
}
infile = fopen(argv[1], "rb");
if (infile == NULL) {
printf("Error: cannot open file '%s' for input\n", argv[1]);
return 1;
}
outfile = fopen(argv[2], "wt");
if (outfile == NULL) {
printf("Error: cannot open file '%s' for output\n", argv[2]);
return 1;
}
n = 0;
while (1) {
c = getc(infile);
if (c == EOF) {
break;
}
fprintf(outfile, "0x%02X, ", c);
n++;
if (n == 8) {
n = 0;
fprintf(outfile, "\n");
}
}
if (n != 0) {
fprintf(outfile, "\n");
}
fclose(infile);
fclose(outfile);
return 0;
}
/eco32/trunk/stdalone/mkpart/dump/Makefile
0,0 → 1,15
#
# Makefile for dump utility
#
 
.PHONY: all install clean
 
all: dump
 
install: dump
 
dump: dump.c
gcc -m32 -g -Wall -o dump dump.c
 
clean:
rm -f *~ dump
/eco32/trunk/stdalone/mkpart/main.c
0,0 → 1,222
/*
* main.c -- program to write the partition table
* and the bootblock on a hard disk
*/
 
 
#include "types.h"
#include "stdarg.h"
#include "iolib.h"
#include "start.h"
#include "idedsk.h"
 
 
/**************************************************************/
 
 
void error(char *fmt, ...) {
va_list ap;
 
va_start(ap, fmt);
printf("Error: ");
vprintf(fmt, ap);
printf(", halting...\n");
va_end(ap);
while (1) ;
}
 
 
/**************************************************************/
 
 
/*
* the boot block byte array need not be word-aligned
*/
unsigned char mboot[32 * SECTOR_SIZE] = {
#include "mboot.dump"
};
 
 
/*
* the write buffer must be word-aligned
*/
unsigned int wrBuf[32 * SECTOR_SIZE / sizeof(unsigned int)];
 
 
/*
* copy byte array to write buffer
*/
void copyBootBlock(void) {
unsigned char *p;
unsigned char *q;
int i;
 
p = (unsigned char *) wrBuf;
q = (unsigned char *) mboot;
for (i = 0; i < 32 * SECTOR_SIZE; i++) {
*p++ = *q++;
}
}
 
 
/**************************************************************/
 
 
static char *exceptionCause[32] = {
/* 00 */ "terminal 0 transmitter interrupt",
/* 01 */ "terminal 0 receiver interrupt",
/* 02 */ "terminal 1 transmitter interrupt",
/* 03 */ "terminal 1 receiver interrupt",
/* 04 */ "keyboard interrupt",
/* 05 */ "unknown interrupt",
/* 06 */ "unknown interrupt",
/* 07 */ "unknown interrupt",
/* 08 */ "disk interrupt",
/* 09 */ "unknown interrupt",
/* 10 */ "unknown interrupt",
/* 11 */ "unknown interrupt",
/* 12 */ "unknown interrupt",
/* 13 */ "unknown interrupt",
/* 14 */ "timer interrupt",
/* 15 */ "unknown interrupt",
/* 16 */ "bus timeout exception",
/* 17 */ "illegal instruction exception",
/* 18 */ "privileged instruction exception",
/* 19 */ "divide instruction exception",
/* 20 */ "trap instruction exception",
/* 21 */ "TLB miss exception",
/* 22 */ "TLB write exception",
/* 23 */ "TLB invalid exception",
/* 24 */ "illegal address exception",
/* 25 */ "privileged address exception",
/* 26 */ "unknown exception",
/* 27 */ "unknown exception",
/* 28 */ "unknown exception",
/* 29 */ "unknown exception",
/* 30 */ "unknown exception",
/* 31 */ "unknown exception"
};
 
 
int defaultISR(int irq) {
printf("\n%s\n", exceptionCause[irq]);
return 0; /* do not skip any instruction */
}
 
 
void initInterrupts(void) {
int i;
 
for (i = 0; i < 32; i++) {
setISR(i, defaultISR);
}
}
 
 
/**************************************************************/
 
 
Bool checkDiskReady(void) {
int tries;
int i;
 
for (tries = 0; tries < 10; tries++) {
for (i = 0; i < 500000; i++) {
if ((*DISK_CTRL & DISK_CTRL_READY) != 0) {
return TRUE;
}
}
printf(".");
}
return FALSE;
}
 
 
unsigned long getDiskSize(void) {
return *DISK_CAP;
}
 
 
Bool readDisk(unsigned long sector,
unsigned int count,
unsigned int *addr) {
unsigned int n;
unsigned int *p;
unsigned int i;
 
while (count != 0) {
n = count > 8 ? 8 : count;
*DISK_SCT = sector;
*DISK_CNT = n;
*DISK_CTRL = DISK_CTRL_STRT;
while ((*DISK_CTRL & DISK_CTRL_DONE) == 0) ;
if (*DISK_CTRL & DISK_CTRL_ERR) {
return FALSE;
}
p = DISK_BUFFER;
for (i = 0; i < n * SECTOR_SIZE / sizeof(unsigned int); i++) {
*addr++ = *p++;
}
sector += n;
count -= n;
}
return TRUE;
}
 
 
Bool writeDisk(unsigned long sector,
unsigned int count,
unsigned int *addr) {
unsigned int n;
unsigned int *p;
unsigned int i;
 
while (count != 0) {
n = count > 8 ? 8 : count;
p = DISK_BUFFER;
for (i = 0; i < n * SECTOR_SIZE / sizeof(unsigned int); i++) {
*p++ = *addr++;
}
*DISK_SCT = sector;
*DISK_CNT = n;
*DISK_CTRL = DISK_CTRL_WRT | DISK_CTRL_STRT;
while ((*DISK_CTRL & DISK_CTRL_DONE) == 0) ;
if (*DISK_CTRL & DISK_CTRL_ERR) {
return FALSE;
}
sector += n;
count -= n;
}
return TRUE;
}
 
 
/**************************************************************/
 
 
void main(void) {
unsigned long numSectors;
 
/* init interrupts */
initInterrupts();
/* check disk ready */
if (!checkDiskReady()) {
error("disk not ready");
}
/* determine disk size */
numSectors = getDiskSize();
printf("Disk has %lu (0x%lX) sectors.\n",
numSectors, numSectors);
if (numSectors < 32) {
error("disk is too small");
}
/* copy boot block to write buffer */
copyBootBlock();
/* write boot block to disk */
printf("Writing boot block to disk...\n");
if (!writeDisk(0, 32, wrBuf)) {
error("cannot write boot block to disk");
}
/* done */
printf("Halting...\n");
}
/eco32/trunk/stdalone/mkpart/biolib.h
0,0 → 1,14
/*
* biolib.h -- basic I/O library
*/
 
 
#ifndef _BIOLIB_H_
#define _BIOLIB_H_
 
 
char getc(void);
void putc(char c);
 
 
#endif /* _BIOLIB_H_ */
/eco32/trunk/stdalone/mkpart/end.s
0,0 → 1,19
;
; end.s -- end-of-segment labels
;
 
.export _ecode
.export _edata
.export _ebss
 
.code
.align 4
_ecode:
 
.data
.align 4
_edata:
 
.bss
.align 4
_ebss:
/eco32/trunk/stdalone/mkpart/mkmboot/stage1/mbr.s
0,0 → 1,127
;
; mbr.s -- the master boot record
;
 
; Runtime environment:
;
; This code must be loaded and started at 0xC0000000.
; It allocates a stack from 0xC0001000 downwards. So
; it must run within 4K (code + data + stack).
;
; This code expects the disk number of the boot disk
; in $16, the start sector of the disk or partition
; to be booted in $17 and its size in $18.
;
; The boot manager, which is loaded by this code,
; must be in standalone (headerless) executable
; format, stored at absolute disk sectors 2..31,
; and gets loaded and started at 0xC00F0000.
 
.set stacktop,0xC0001000 ; top of stack
.set loadaddr,0xC00F0000 ; where to load the boot manager
 
.set cout,0xE0000018 ; ROM console output
.set dskio,0xE0000030 ; ROM disk I/O
 
; reset arrives here
reset:
j start
 
; interrupts arrive here
intrpt:
j userMiss
 
; user TLB misses arrive here
userMiss:
add $4,$0,intmsg ; we do not expect any interrupt
jal msgout
j halt
 
; load the boot manager and start it
start:
add $29,$0,stacktop ; setup stack
add $4,$0,strtmsg ; say what is going on
jal msgout
add $4,$0,2 ; start loading with sector 2
add $5,$0,loadaddr ; where to load the boot manager
and $5,$5,0x3FFFFFFF ; convert to physical address
add $6,$0,30 ; 30 sectors to load
jal rdsct
add $8,$0,loadaddr ; start executing the boot manager
jr $8
 
; read disk sectors
; $4 start sector number (disk or partition relative)
; $5 transfer address
; $6 number of sectors
rdsct:
sub $29,$29,32
stw $31,$29,20
stw $6,$29,16 ; sector count
add $7,$5,$0 ; transfer address
add $6,$4,$17 ; relative sector -> absolute
add $5,$0,'r' ; command
add $4,$0,$16 ; disk number
add $8,$0,dskio
jalr $8
bne $2,$0,rderr ; error?
ldw $31,$29,20
add $29,$29,32
jr $31
 
; disk read error
rderr:
add $4,$0,dremsg
jal msgout
j halt
 
; output message
; $4 pointer to string
msgout:
sub $29,$29,8
stw $31,$29,4
stw $16,$29,0
add $16,$4,0 ; $16: pointer to string
msgout1:
ldbu $4,$16,0 ; get character
beq $4,$0,msgout2 ; done?
jal chrout ; output character
add $16,$16,1 ; bump pointer
j msgout1 ; continue
msgout2:
ldw $16,$29,0
ldw $31,$29,4
add $29,$29,8
jr $31
 
; output character
; $4 character
chrout:
sub $29,$29,4
stw $31,$29,0
add $8,$0,cout
jalr $8
ldw $31,$29,0
add $29,$29,4
jr $31
 
; halt execution by looping
halt:
add $4,$0,hltmsg
jal msgout
halt1:
j halt1
 
; messages
intmsg:
.byte "unexpected interrupt", 0x0D, 0x0A, 0
strtmsg:
.byte "MBR executing...", 0x0D, 0x0A, 0
dremsg:
.byte "disk read error", 0x0D, 0x0A, 0
hltmsg:
.byte "bootstrap halted", 0x0D, 0x0A, 0
 
; boot record signature
.locate 512-2
.byte 0x55, 0xAA
/eco32/trunk/stdalone/mkpart/mkmboot/stage1/Makefile
0,0 → 1,16
#
# Makefile to build the master boot record
#
 
BUILD = ../../../../build
 
all: mbr.bin
 
mbr.bin: mbr.o
$(BUILD)/bin/ld -h -rc 0xC0000000 -o mbr.bin mbr.o
 
mbr.o: mbr.s
$(BUILD)/bin/as -o mbr.o mbr.s
 
clean:
rm -f *~ mbr.o mbr.bin
/eco32/trunk/stdalone/mkpart/mkmboot/stage2/iolib.s
0,0 → 1,26
;
; iolib.s -- a very small library of I/O routines
;
 
.set cin,0xE0000010
.set cout,0xE0000018
.set dskio,0xE0000030
 
.export getc
.export putc
.export rwscts
 
.code
.align 4
 
getc:
add $8,$0,cin
jr $8
 
putc:
add $8,$0,cout
jr $8
 
rwscts:
add $8,$0,dskio
jr $8
/eco32/trunk/stdalone/mkpart/mkmboot/stage2/c0.s
0,0 → 1,58
;
; c0.s -- startup code and begin-of-segment labels
;
 
.import main
 
.import _ecode
.import _edata
.import _ebss
 
.export _bcode
.export _bdata
.export _bbss
 
.import bootDisk
.import startSector
.import numSectors
 
.code
_bcode:
 
start:
add $10,$0,_bdata ; copy data segment
add $8,$0,_edata
sub $9,$8,$10
add $9,$9,_ecode
j cpytest
cpyloop:
ldw $11,$9,0
stw $11,$8,0
cpytest:
sub $8,$8,4
sub $9,$9,4
bgeu $8,$10,cpyloop
add $8,$0,_bbss ; clear bss segment
add $9,$0,_ebss
j clrtest
clrloop:
stw $0,$8,0
add $8,$8,4
clrtest:
bltu $8,$9,clrloop
add $29,$0,0xC0100000 ; setup stack
stw $16,$0,bootDisk ; make arguments available
stw $17,$0,startSector
stw $18,$0,numSectors
jal main ; call 'main' function
ldw $16,$0,bootDisk ; setup arguments for next stage
ldw $17,$0,startSector
ldw $18,$0,numSectors
add $31,$0,0xC0000000 ; jump to loaded program
jr $31
 
.data
_bdata:
 
.bss
_bbss:
/eco32/trunk/stdalone/mkpart/mkmboot/stage2/c1.s
0,0 → 1,19
;
; c1.s -- end-of-segment labels
;
 
.export _ecode
.export _edata
.export _ebss
 
.code
.align 4
_ecode:
 
.data
.align 4
_edata:
 
.bss
.align 4
_ebss:
/eco32/trunk/stdalone/mkpart/mkmboot/stage2/boot.c
0,0 → 1,267
/*
* boot.c -- second stage bootstrap (the boot manager)
*/
 
 
#include "stdarg.h"
#include "iolib.h"
 
 
#define DEFAULT_PARTITION "0" /* default boot partition number */
 
#define LINE_SIZE 80
#define SECTOR_SIZE 512
#define NPE (SECTOR_SIZE / sizeof(PartEntry))
#define DESCR_SIZE 20
 
 
unsigned int bootDisk = 0; /* gets loaded by previous stage */
unsigned int startSector = 0; /* gets loaded by previous stage */
unsigned int numSectors = 0; /* gets loaded by previous stage */
 
 
typedef struct {
unsigned long type;
unsigned long start;
unsigned long size;
char descr[DESCR_SIZE];
} PartEntry;
 
PartEntry ptr[NPE];
 
 
int strlen(char *str) {
int i;
 
i = 0;
while (*str++ != '\0') {
i++;
}
return i;
}
 
 
void strcpy(char *dst, char *src) {
while ((*dst++ = *src++) != '\0') ;
}
 
 
char getchar(void) {
return getc();
}
 
 
void putchar(char c) {
if (c == '\n') {
putchar('\r');
}
putc(c);
}
 
 
void puts(char *s) {
char c;
 
while ((c = *s++) != '\0') {
putchar(c);
}
}
 
 
void getline(char *prompt, char *line, int n) {
int i;
char c;
 
puts(prompt);
puts(line);
i = strlen(line);
while (i < n - 1) {
c = getchar();
if (c >= ' ' && c < 0x7F) {
putchar(c);
line[i] = c;
i++;
} else
if (c == '\r') {
putchar('\n');
line[i] = '\0';
i = n - 1;
} else
if (c == '\b' || c == 0x7F) {
if (i > 0) {
putchar('\b');
putchar(' ');
putchar('\b');
i--;
}
}
}
line[n - 1] = '\0';
}
 
 
int countPrintn(long n) {
long a;
int res;
 
res = 0;
if (n < 0) {
res++;
n = -n;
}
a = n / 10;
if (a != 0) {
res += countPrintn(a);
}
return res + 1;
}
 
 
void printn(long n) {
long a;
 
if (n < 0) {
putchar('-');
n = -n;
}
a = n / 10;
if (a != 0) {
printn(a);
}
putchar(n % 10 + '0');
}
 
 
void printf(char *fmt, ...) {
va_list ap;
char c;
int n;
unsigned int u;
char *s;
char filler;
int width, count, i;
 
va_start(ap, fmt);
while (1) {
while ((c = *fmt++) != '%') {
if (c == '\0') {
va_end(ap);
return;
}
putchar(c);
}
c = *fmt++;
if (c == '0') {
filler = '0';
c = *fmt++;
} else {
filler = ' ';
}
width = 0;
if (c >= '0' && c <= '9') {
width = c - '0';
c = *fmt++;
}
if (c == 'd') {
n = va_arg(ap, int);
if (width > 0) {
count = countPrintn(n);
for (i = 0; i < width - count; i++) {
putchar(filler);
}
}
printn(n);
} else
if (c == 's') {
s = va_arg(ap, char *);
puts(s);
} else
if (c == 'c') {
c = va_arg(ap, char);
putchar(c);
} else {
putchar(c);
}
}
}
 
 
void halt(void) {
printf("bootstrap halted\n");
while (1) ;
}
 
 
void readDisk(unsigned int sector, unsigned char *buffer, int count) {
int result;
 
if (sector + count > numSectors) {
printf("sector number exceeds disk or partition size\n");
halt();
}
result = rwscts(bootDisk, 'r', sector + startSector,
(unsigned int) buffer & 0x3FFFFFFF, count);
if (result != 0) {
printf("disk read error\n");
halt();
}
}
 
 
int main(void) {
int i;
char line[LINE_SIZE];
char *p;
int part;
 
printf("Bootstrap manager executing...\n");
strcpy(line, DEFAULT_PARTITION);
readDisk(1, (unsigned char *) ptr, 1);
while (1) {
printf("\nPartitions:\n");
printf(" # | b | description\n");
printf("---+---+----------------------\n");
for (i = 0; i < NPE; i++) {
if (ptr[i].type != 0) {
printf("%2d | %s | %s\n",
i, ptr[i].type & 0x80000000 ? "*" : " ", ptr[i].descr);
}
}
getline("\nBoot #: ", line, LINE_SIZE);
part = 0;
if (line[0] == '\0') {
continue;
}
p = line;
while (*p >= '0' && *p <= '9') {
part = part * 10 + (*p - '0');
p++;
}
if (*p != '\0' || part < 0 || part > 15) {
printf("illegal partition number\n");
continue;
}
if ((ptr[part].type & 0x7FFFFFFF) == 0) {
printf("partition %d does not contain a file system\n", part);
continue;
}
if ((ptr[part].type & 0x80000000) == 0) {
printf("partition %d is not bootable\n", part);
continue;
}
/* load boot sector of selected partition */
readDisk(ptr[part].start, (unsigned char *) 0xC0000000, 1);
/* check for signature */
if ((*((unsigned char *) 0xC0000000 + SECTOR_SIZE - 2) != 0x55) ||
(*((unsigned char *) 0xC0000000 + SECTOR_SIZE - 1) != 0xAA)) {
printf("boot sector of partition %d has no signature\n", part);
continue;
}
/* we have a valid boot sector, leave loop */
break;
}
/* boot manager finished, now go executing loaded boot sector */
startSector = ptr[part].start;
numSectors = ptr[part].size;
return 0;
}
/eco32/trunk/stdalone/mkpart/mkmboot/stage2/iolib.h
0,0 → 1,15
/*
* iolib.h -- a very small library of I/O routines
*/
 
 
#ifndef _IOLIB_H_
#define _IOLIB_H_
 
 
char getc(void);
void putc(char c);
int rwscts(int dskno, int cmd, int sector, int addr, int count);
 
 
#endif /* _IOLIB_H_ */
/eco32/trunk/stdalone/mkpart/mkmboot/stage2/stdarg.h
0,0 → 1,41
/*
* stdarg.h -- variable argument lists
*/
 
 
#ifndef _STDARG_H_
#define _STDARG_H_
 
 
typedef char *va_list;
 
 
static float __va_arg_tmp;
 
 
#define va_start(list, start) \
((void)((list) = (sizeof(start)<4 ? \
(char *)((int *)&(start)+1) : (char *)(&(start)+1))))
 
#define __va_arg(list, mode, n) \
(__typecode(mode)==1 && sizeof(mode)==4 ? \
(__va_arg_tmp = *(double *)(&(list += \
((sizeof(double)+n)&~n))[-(int)((sizeof(double)+n)&~n)]), \
*(mode *)&__va_arg_tmp) : \
*(mode *)(&(list += \
((sizeof(mode)+n)&~n))[-(int)((sizeof(mode)+n)&~n)]))
 
#define _bigendian_va_arg(list, mode, n) \
(sizeof(mode)==1 ? *(mode *)(&(list += 4)[-1]) : \
sizeof(mode)==2 ? *(mode *)(&(list += 4)[-2]) : \
__va_arg(list, mode, n))
 
#define va_end(list) ((void)0)
 
#define va_arg(list, mode) \
(sizeof(mode)==8 ? \
*(mode *)(&(list = (char*)(((int)list + 15)&~7U))[-8]) : \
_bigendian_va_arg(list, mode, 3U))
 
 
#endif /* _STDARG_H_ */
/eco32/trunk/stdalone/mkpart/mkmboot/stage2/Makefile
0,0 → 1,26
#
# Makefile to build the boot manager
#
 
BUILD = ../../../../build
 
all: boot.bin
 
boot.bin: c0.o boot.o iolib.o c1.o
$(BUILD)/bin/ld -h -rc 0xC00F0000 -o boot.bin \
c0.o boot.o iolib.o c1.o
 
c0.o: c0.s
$(BUILD)/bin/as -o c0.o c0.s
 
boot.o: boot.c
$(BUILD)/bin/lcc -A -c -o boot.o boot.c
 
iolib.o: iolib.s
$(BUILD)/bin/as -o iolib.o iolib.s
 
c1.o: c1.s
$(BUILD)/bin/as -o c1.o c1.s
 
clean:
rm -f *~ c0.o boot.o iolib.o c1.o boot.bin
/eco32/trunk/stdalone/mkpart/mkmboot/Makefile
0,0 → 1,24
#
# Makefile to build the master boot block (with an empty partition table)
#
 
BUILD = ../../../build
 
.PHONY: all clean
 
all: mbootblk
 
mbootblk: stage1/mbr.bin stage2/boot.bin
dd if=/dev/zero of=./zeroes bs=512 count=1
cat stage1/mbr.bin zeroes stage2/boot.bin >mbootblk
 
stage1/mbr.bin:
$(MAKE) -C stage1
 
stage2/boot.bin:
$(MAKE) -C stage2
 
clean:
$(MAKE) -C stage1 clean
$(MAKE) -C stage2 clean
rm -f *~ zeroes mbootblk
/eco32/trunk/stdalone/mkpart/mkptbl/disk.part
0,0 → 1,41
#
# disk.part -- disk partitioning configuration file
#
 
# This file consists of partition table entries, one per line
# (empty or comment lines are also allowed). Each entry is in
# the following form:
#
# partition boot type start last description
#
# partition:
# possible values 0..15
# indicates partition number
# different entries need not be sorted in any way
# no two entries may have the same partition number
# boot:
# '*' means that the partition can be booted
# leave this blank if the partition cannot be booted
# more than one partition may be bootable
# type:
# possible values 0..0x7FFFFFFF
# indicates partition type
# 0x0000 = partition table entry not used
# 0x0058 = EOS32 file system partition
# 0x0059 = EOS32 swap space partition
# 0x00A9 = NetBSD partition
# start:
# sector number where partition starts (0-based)
# no partition may start below sector 32
# last:
# last sector of partition (0-based)
# partitions must not overlap
# description:
# max. 512 / 16 - 12 = 20 characters (includes trailing 0)
# this may be displayed during bootstrap
 
0 * 0x0058 32 131071 "EOS32 root"
1 0x0058 131072 393215 "EOS32 usr"
2 0x0059 393216 524287 "EOS32 swap"
3 0x0058 524288 1048575 "EOS32 home"
4 * 0x00A9 2097152 33554431 "NetBSD 6.0"
/eco32/trunk/stdalone/mkpart/mkptbl/mkptbl.c
0,0 → 1,275
/*
* mkptbl.c -- make partition table
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
 
 
#define SECTOR_SIZE 512
#define NPE (SECTOR_SIZE / sizeof(PartEntry))
#define DESCR_SIZE 20
 
#define LINE_SIZE 100
 
 
typedef struct {
unsigned long type;
unsigned long start;
unsigned long size;
char descr[DESCR_SIZE];
} PartEntry;
 
PartEntry ptr[NPE];
 
 
void error(char *fmt, ...) {
va_list ap;
 
va_start(ap, fmt);
printf("Error: ");
vprintf(fmt, ap);
printf("\n");
va_end(ap);
exit(1);
}
 
 
void convertNumber(unsigned char *p, unsigned long val) {
*(p + 0) = val >> 24;
*(p + 1) = val >> 16;
*(p + 2) = val >> 8;
*(p + 3) = val >> 0;
}
 
 
void convertPartitionTable(PartEntry *e, int n) {
int i;
unsigned char *p;
 
for (i = 0; i < n; i++) {
p = (unsigned char *) &e[i];
convertNumber(p + 0, e[i].type);
convertNumber(p + 4, e[i].start);
convertNumber(p + 8, e[i].size);
}
}
 
 
int parseNumber(char **pc, unsigned long *pi) {
char *p;
unsigned int base, dval;
unsigned long n;
 
p = *pc;
while (*p == ' ' || *p == '\t') {
p++;
}
if (*p == '\0' || *p == '\n') {
printf("Error: number is missing!\n");
return 0;
}
base = 10;
if (*p == '0') {
p++;
if (*p != '\0' && *p != '\n') {
if (*p == 'x' || *p == 'X') {
base = 16;
p++;
} else {
base = 8;
}
}
}
n = 0;
while ((*p >= '0' && *p <= '9') ||
(*p >= 'a' && *p <= 'f') ||
(*p >= 'A' && *p <= 'F')) {
if (*p >= '0' && *p <= '9') {
dval = (*p - '0');
} else
if (*p >= 'a' && *p <= 'f') {
dval = (*p - 'a' + 10);
} else
if (*p >= 'A' && *p <= 'F') {
dval = (*p - 'A' + 10);
}
if (dval >= base) {
printf("Error: digit value %d is illegal in number base %d\n",
dval, base);
return 0;
}
n *= base;
n += dval;
p++;
}
while (*p == ' ' || *p == '\t') {
p++;
}
*pc = p;
*pi = n;
return 1;
}
 
 
int parseString(char **pc, char *dst) {
char *p;
 
p = *pc;
while (*p == ' ' || *p == '\t') {
p++;
}
if (*p != '\"') {
return 0;
}
p++;
while (*p != '\"' && *p != '\0' && *p != '\n') {
*dst++ = *p++;
}
if (*p != '\"') {
return 0;
}
p++;
while (*p == ' ' || *p == '\t') {
p++;
}
*pc = p;
*dst = '\0';
return 1;
}
 
 
int main(int argc, char *argv[]) {
char *confName;
char *outName;
FILE *conf;
FILE *out;
char line[LINE_SIZE];
char *p;
int lineNumber;
unsigned long partNum;
unsigned long bootable;
unsigned long partType;
unsigned long partStart;
unsigned long partLast;
unsigned long partSize;
char descr[LINE_SIZE];
 
/* check command line arguments */
if (argc != 3) {
printf("Usage: %s <configuration file> <output file>\n", argv[0]);
exit(1);
}
confName = argv[1];
outName = argv[2];
/* create partition table */
conf = fopen(confName, "rt");
if (conf == NULL) {
error("cannot open configuration file '%s'", confName);
}
lineNumber = 0;
/* handle partition table entries */
while (fgets(line, LINE_SIZE, conf) != NULL) {
lineNumber++;
p = line;
while (*p == ' ' || *p == '\t') {
p++;
}
if (*p == '\0' || *p == '\n' || *p == '#') {
continue;
}
if (!parseNumber(&p, &partNum)) {
error("cannot read partition number in config file '%s', line %d",
confName, lineNumber);
}
if (partNum >= 16) {
error("illegal partition number in config file '%s', line %d",
confName, lineNumber);
}
if (*p == '*') {
p++;
bootable = 0x80000000;
} else {
bootable = 0x00000000;
}
if (!parseNumber(&p, &partType)) {
error("cannot read partition type in config file '%s', line %d",
confName, lineNumber);
}
if ((partType & 0x80000000) != 0) {
error("illegal partition type in config file '%s', line %d",
confName, lineNumber);
}
if (!parseNumber(&p, &partStart)) {
error("cannot read start sector in config file '%s', line %d",
confName, lineNumber);
}
if (partStart < 32) {
error("illegal start sector in config file '%s', line %d",
confName, lineNumber);
}
if (!parseNumber(&p, &partLast)) {
error("cannot read last sector in config file '%s', line %d",
confName, lineNumber);
}
if (partLast < partStart) {
error("illegal last sector in config file '%s', line %d",
confName, lineNumber);
}
partSize = partLast - partStart + 1;
if (!parseString(&p, descr)) {
error("cannot read description in config file '%s', line %d",
confName, lineNumber);
}
if (strlen(descr) >= DESCR_SIZE) {
error("description too long in config file '%s', line %d",
confName, lineNumber);
}
if (partType != 0) {
ptr[partNum].type = bootable | partType;
ptr[partNum].start = partStart;
ptr[partNum].size = partSize;
memset(ptr[partNum].descr, 0, DESCR_SIZE);
strcpy(ptr[partNum].descr, descr);
} else {
ptr[partNum].type = 0;
ptr[partNum].start = 0;
ptr[partNum].size = 0;
memset(ptr[partNum].descr, 0, DESCR_SIZE);
}
}
fclose(conf);
/* next, show partition table */
printf("Partitions:\n");
printf(" # b type start last size description\n");
for (partNum = 0; partNum < NPE; partNum++) {
if (ptr[partNum].type != 0) {
partLast = ptr[partNum].start + ptr[partNum].size - 1;
} else {
partLast = 0;
}
printf("%2lu %s 0x%08lX 0x%08lX 0x%08lX 0x%08lX %s\n",
partNum,
ptr[partNum].type & 0x80000000 ? "*" : " ",
ptr[partNum].type & 0x7FFFFFFF,
ptr[partNum].start,
partLast,
ptr[partNum].size,
ptr[partNum].descr);
}
/* finally, write partition table to output file */
convertPartitionTable(ptr, NPE);
out = fopen(outName, "wb");
if (out == NULL) {
error("cannot open output file '%s'", outName);
}
if (fwrite(ptr, 1, SECTOR_SIZE, out) != SECTOR_SIZE) {
error("cannot write partition table to output file '%s'", outName);
}
fclose(out);
/* done */
return 0;
}
/eco32/trunk/stdalone/mkpart/mkptbl/Makefile
0,0 → 1,14
#
# Makefile for generating a partition table
#
 
all: parttbl
 
parttbl: mkptbl disk.part
./mkptbl disk.part parttbl
 
mkptbl: mkptbl.c
gcc -m32 -g -Wall -o mkptbl mkptbl.c
 
clean:
rm -f *~ mkptbl parttbl
/eco32/trunk/stdalone/mkpart/idedsk.h
0,0 → 1,32
/*
* idedsk.h -- IDE disk definitions
*/
 
 
#ifndef _IDEDSK_H_
#define _IDEDSK_H_
 
 
#define SECTOR_SIZE 512
#define WPS (SECTOR_SIZE / sizeof(unsigned int))
 
#define DISK_BASE ((unsigned *) 0xF0400000) /* disk base address */
#define DISK_CTRL (DISK_BASE + 0) /* control/status register */
#define DISK_CNT (DISK_BASE + 1) /* sector count register */
#define DISK_SCT (DISK_BASE + 2) /* disk sector register */
#define DISK_CAP (DISK_BASE + 3) /* disk capacity register */
#define DISK_BUFFER ((unsigned *) 0xF0480000) /* address of disk buffer */
 
#define DISK_CTRL_STRT 0x01 /* a 1 written here starts the disk command */
#define DISK_CTRL_IEN 0x02 /* enable disk interrupt */
#define DISK_CTRL_WRT 0x04 /* command type: 0 = read, 1 = write */
#define DISK_CTRL_ERR 0x08 /* 0 = ok, 1 = error; valid when DONE = 1 */
#define DISK_CTRL_DONE 0x10 /* 1 = disk has finished the command */
#define DISK_CTRL_READY 0x20 /* 1 = capacity valid, disk accepts command */
 
#define DISK_IRQ 8 /* disk interrupt number */
 
#define READY_RETRIES 1000000 /* retries to wait for disk to get ready */
 
 
#endif /* _IDEDSK_H_ */
/eco32/trunk/stdalone/mkpart/stdarg.h
0,0 → 1,41
/*
* stdarg.h -- variable argument lists
*/
 
 
#ifndef _STDARG_H_
#define _STDARG_H_
 
 
typedef char *va_list;
 
 
static float __va_arg_tmp;
 
 
#define va_start(list, start) \
((void)((list) = (sizeof(start)<4 ? \
(char *)((int *)&(start)+1) : (char *)(&(start)+1))))
 
#define __va_arg(list, mode, n) \
(__typecode(mode)==1 && sizeof(mode)==4 ? \
(__va_arg_tmp = *(double *)(&(list += \
((sizeof(double)+n)&~n))[-(int)((sizeof(double)+n)&~n)]), \
*(mode *)&__va_arg_tmp) : \
*(mode *)(&(list += \
((sizeof(mode)+n)&~n))[-(int)((sizeof(mode)+n)&~n)]))
 
#define _bigendian_va_arg(list, mode, n) \
(sizeof(mode)==1 ? *(mode *)(&(list += 4)[-1]) : \
sizeof(mode)==2 ? *(mode *)(&(list += 4)[-2]) : \
__va_arg(list, mode, n))
 
#define va_end(list) ((void)0)
 
#define va_arg(list, mode) \
(sizeof(mode)==8 ? \
*(mode *)(&(list = (char*)(((int)list + 15)&~7U))[-8]) : \
_bigendian_va_arg(list, mode, 3U))
 
 
#endif /* _STDARG_H_ */
/eco32/trunk/stdalone/mkpart/types.h
0,0 → 1,16
/*
* types.h -- additional types
*/
 
 
#ifndef _TYPES_H_
#define _TYPES_H_
 
 
typedef int Bool;
 
#define FALSE 0
#define TRUE 1
 
 
#endif /* _TYPES_H_ */
/eco32/trunk/stdalone/mkpart/Makefile
0,0 → 1,49
#
# Makefile for "mkpart", a program to write the partition table
# and the bootblock on a hard disk
#
 
BUILD = ../../build
 
SRC = start.s main.c iolib.c biolib.c end.s
BIN = mkpart.bin
MAP = mkpart.map
 
.PHONY: all install run clean
 
all: $(BIN)
 
install: $(BIN)
mkdir -p $(BUILD)/stdalone
cp $(BIN) $(BUILD)/stdalone
cp $(MAP) $(BUILD)/stdalone
 
run: $(BIN)
$(BUILD)/bin/sim -i -t 1 -l $(BIN) -d $(BUILD)/disk/disk.img
 
$(BIN): $(SRC) mboot.dump
$(BUILD)/bin/lcc -A -Wo-kernel \
-Wl-m -Wl$(MAP) -o $(BIN) $(SRC)
 
mboot.dump: dump/dump mboot
./dump/dump mboot mboot.dump
 
dump/dump:
$(MAKE) -C dump all
 
mboot: mkmboot/mbootblk mkptbl/parttbl
dd if=/dev/zero of=mboot bs=512 count=32
dd if=mkmboot/mbootblk of=mboot bs=512 conv=notrunc
dd if=mkptbl/parttbl of=mboot bs=512 seek=1 conv=notrunc
 
mkptbl/parttbl:
$(MAKE) -C mkptbl all
 
mkmboot/mbootblk:
$(MAKE) -C mkmboot all
 
clean:
$(MAKE) -C dump clean
$(MAKE) -C mkptbl clean
$(MAKE) -C mkmboot clean
rm -f *~ mboot mboot.dump $(BIN) $(MAP)
/eco32/trunk/stdalone/mkpart/start.s
0,0 → 1,228
;
; start.s -- startup code
;
 
.import main
.import _ecode
.import _edata
.import _ebss
 
.export _bcode
.export _bdata
.export _bbss
 
.export enable
.export disable
.export getMask
.export setMask
.export getISR
.export setISR
 
.code
_bcode:
 
.data
_bdata:
 
.bss
_bbss:
 
.code
 
; reset arrives here
reset:
j start
 
; interrupts arrive here
intrpt:
j isr
 
; user TLB misses arrive here
userMiss:
j userMiss
 
isr:
add $26,$29,$0 ; sp -> $26
add $27,$1,$0 ; $1 -> $27
add $29,$0,istack ; set stack
sub $29,$29,108
stw $2,$29,0 ; save registers
stw $3,$29,4
stw $4,$29,8
stw $5,$29,12
stw $6,$29,16
stw $7,$29,20
stw $8,$29,24
stw $9,$29,28
stw $10,$29,32
stw $11,$29,36
stw $12,$29,40
stw $13,$29,44
stw $14,$29,48
stw $15,$29,52
stw $16,$29,56
stw $17,$29,60
stw $18,$29,64
stw $19,$29,68
stw $20,$29,72
stw $21,$29,76
stw $22,$29,80
stw $23,$29,84
stw $24,$29,88
stw $25,$29,92
stw $26,$29,96
stw $27,$29,100
stw $31,$29,104
mvfs $4,0 ; $4 = IRQ number
slr $4,$4,16
and $4,$4,0x1F
sll $26,$4,2 ; $26 = 4 * IRQ number
ldw $26,$26,irqsrv ; get addr of service routine
jalr $26 ; call service routine
beq $2,$0,resume ; resume instruction if ISR returned 0
add $30,$30,4 ; else skip offending instruction
resume:
ldw $2,$29,0
ldw $3,$29,4
ldw $4,$29,8
ldw $5,$29,12
ldw $6,$29,16
ldw $7,$29,20
ldw $8,$29,24
ldw $9,$29,28
ldw $10,$29,32
ldw $11,$29,36
ldw $12,$29,40
ldw $13,$29,44
ldw $14,$29,48
ldw $15,$29,52
ldw $16,$29,56
ldw $17,$29,60
ldw $18,$29,64
ldw $19,$29,68
ldw $20,$29,72
ldw $21,$29,76
ldw $22,$29,80
ldw $23,$29,84
ldw $24,$29,88
ldw $25,$29,92
ldw $26,$29,96
ldw $27,$29,100
ldw $31,$29,104
add $1,$27,$0 ; $27 -> $1
add $29,$26,0 ; $26 -> sp
rfx ; return from exception
 
start:
mvfs $8,0
or $8,$8,1 << 27 ; let vector point to RAM
mvts $8,0
add $29,$0,stack ; set sp
add $10,$0,_bdata ; copy data segment
add $8,$0,_edata
sub $9,$8,$10
add $9,$9,_ecode
j cpytest
cpyloop:
ldw $11,$9,0
stw $11,$8,0
cpytest:
sub $8,$8,4
sub $9,$9,4
bgeu $8,$10,cpyloop
add $8,$0,_bbss ; clear bss
add $9,$0,_ebss
j clrtest
clrloop:
stw $0,$8,0
add $8,$8,4
clrtest:
bltu $8,$9,clrloop
jal main ; call 'main'
start1:
j start1 ; loop
 
enable:
mvfs $8,0
or $8,$8,1 << 23
mvts $8,0
jr $31
 
disable:
mvfs $8,0
and $8,$8,~(1 << 23)
mvts $8,0
jr $31
 
getMask:
mvfs $8,0
and $2,$8,0x0000FFFF
jr $31
 
setMask:
mvfs $8,0
and $8,$8,0xFFFF0000
and $4,$4,0x0000FFFF
or $8,$8,$4
mvts $8,0
jr $31
 
getISR:
sll $4,$4,2
ldw $2,$4,irqsrv
jr $31
 
setISR:
sll $4,$4,2
stw $5,$4,irqsrv
jr $31
 
.data
 
; interrupt service routine table
 
.align 4
 
irqsrv:
.word 0 ; 00: terminal 0 transmitter interrupt
.word 0 ; 01: terminal 0 receiver interrupt
.word 0 ; 02: terminal 1 transmitter interrupt
.word 0 ; 03: terminal 1 receiver interrupt
.word 0 ; 04: keyboard interrupt
.word 0 ; 05: unused
.word 0 ; 06: unused
.word 0 ; 07: unused
.word 0 ; 08: disk interrupt
.word 0 ; 09: unused
.word 0 ; 10: unused
.word 0 ; 11: unused
.word 0 ; 12: unused
.word 0 ; 13: unused
.word 0 ; 14: timer interrupt
.word 0 ; 15: unused
.word 0 ; 16: bus timeout exception
.word 0 ; 17: illegal instruction exception
.word 0 ; 18: privileged instruction exception
.word 0 ; 19: divide instruction exception
.word 0 ; 20: trap instruction exception
.word 0 ; 21: TLB miss exception
.word 0 ; 22: TLB write exception
.word 0 ; 23: TLB invalid exception
.word 0 ; 24: illegal address exception
.word 0 ; 25: privileged address exception
.word 0 ; 26: unused
.word 0 ; 27: unused
.word 0 ; 28: unused
.word 0 ; 29: unused
.word 0 ; 30: unused
.word 0 ; 31: unused
 
.bss
 
.align 4
.space 0x800
stack:
 
.align 4
.space 0x800
istack:
/eco32/trunk/stdalone/twotasks-2/os/start.h
0,0 → 1,23
/*
* start.h -- startup code
*/
 
 
#ifndef _START_H_
#define _START_H_
 
 
typedef void (*ISR)(int irq, unsigned int *registers);
 
 
void enable(void);
void disable(void);
void orMask(unsigned int mask);
void andMask(unsigned int mask);
ISR getISR(int irq);
void setISR(int irq, ISR isr);
void startTask(void);
void setTLB(int index, unsigned int entryHi, unsigned int entryLo);
 
 
#endif /* _START_H_ */
/eco32/trunk/stdalone/twotasks-2/os/main.c
0,0 → 1,369
/*
* main.c -- start the ball rolling
*/
 
 
#include "stdarg.h"
#include "start.h"
 
 
/**************************************************************/
 
 
int currentTask;
unsigned int **currentPageDir;
unsigned int *currentStkTop;
 
 
/**************************************************************/
 
 
unsigned int task0Stack[256];
unsigned int *task0StkTop = task0Stack + 256;
 
 
unsigned char task1Code[] = {
#include "task1.dump"
};
 
unsigned int task1Stack[256];
unsigned int *task1StkTop = task1Stack + 256;
 
unsigned int **task1PageDir;
 
 
unsigned char task2Code[] = {
#include "task2.dump"
};
 
unsigned int task2Stack[256];
unsigned int *task2StkTop = task2Stack + 256;
 
unsigned int **task2PageDir;
 
 
/**************************************************************/
 
 
unsigned int pageTablePool[10][1024];
int nextPageTable = 0;
 
 
unsigned int *allocPageTable(void) {
unsigned int *pageTable;
int i;
 
pageTable = pageTablePool[nextPageTable++];
for (i = 0; i < 1024; i++) {
pageTable[i] = 0;
}
return pageTable;
}
 
 
/**************************************************************/
 
 
void putchar(char c) {
unsigned int *base;
 
if (c == '\n') {
putchar('\r');
}
base = (unsigned int *) 0xF0300000;
while ((*(base + 2) & 1) == 0) ;
*(base + 3) = c;
}
 
 
void puts(char *s) {
char c;
 
while ((c = *s++) != '\0') {
putchar(c);
}
}
 
 
void printn(int n) {
int a;
 
if (n < 0) {
putchar('-');
n = -n;
}
a = n / 10;
if (a != 0) {
printn(a);
}
putchar(n % 10 + '0');
}
 
 
void printu(unsigned int n, unsigned int b) {
unsigned int a;
 
a = n / b;
if (a != 0) {
printu(a, b);
}
putchar("0123456789ABCDEF"[n % b]);
}
 
 
void printf(char *fmt, ...) {
va_list ap;
char c;
int n;
unsigned int u;
char *s;
 
va_start(ap, fmt);
while (1) {
while ((c = *fmt++) != '%') {
if (c == '\0') {
va_end(ap);
return;
}
putchar(c);
}
c = *fmt++;
if (c == 'd') {
n = va_arg(ap, int);
printn(n);
} else
if (c == 'u' || c == 'o' || c == 'x') {
u = va_arg(ap, int);
printu(u, c == 'o' ? 8 : (c == 'x' ? 16 : 10));
} else
if (c == 's') {
s = va_arg(ap, char *);
puts(s);
} else {
putchar(c);
}
}
}
 
 
/**************************************************************/
 
 
static char *exceptionCause[32] = {
/* 00 */ "terminal 0 transmitter interrupt",
/* 01 */ "terminal 0 receiver interrupt",
/* 02 */ "terminal 1 transmitter interrupt",
/* 03 */ "terminal 1 receiver interrupt",
/* 04 */ "keyboard interrupt",
/* 05 */ "unknown interrupt",
/* 06 */ "unknown interrupt",
/* 07 */ "unknown interrupt",
/* 08 */ "disk interrupt",
/* 09 */ "unknown interrupt",
/* 10 */ "unknown interrupt",
/* 11 */ "unknown interrupt",
/* 12 */ "unknown interrupt",
/* 13 */ "unknown interrupt",
/* 14 */ "timer interrupt",
/* 15 */ "unknown interrupt",
/* 16 */ "bus timeout exception",
/* 17 */ "illegal instruction exception",
/* 18 */ "privileged instruction exception",
/* 19 */ "divide instruction exception",
/* 20 */ "trap instruction exception",
/* 21 */ "TLB miss exception",
/* 22 */ "TLB write exception",
/* 23 */ "TLB invalid exception",
/* 24 */ "illegal address exception",
/* 25 */ "privileged address exception",
/* 26 */ "unknown exception",
/* 27 */ "unknown exception",
/* 28 */ "unknown exception",
/* 29 */ "unknown exception",
/* 30 */ "unknown exception",
/* 31 */ "unknown exception"
};
 
 
void defaultISR(int irq, unsigned int *registers) {
printf("\n%s\n", exceptionCause[irq]);
}
 
 
void initInterrupts(void) {
int i;
 
for (i = 0; i < 32; i++) {
setISR(i, defaultISR);
}
}
 
 
/**************************************************************/
 
 
unsigned int getNumber(unsigned char *p) {
return (unsigned int) *(p + 0) << 24 |
(unsigned int) *(p + 1) << 16 |
(unsigned int) *(p + 2) << 8 |
(unsigned int) *(p + 3) << 0;
}
 
 
unsigned int **loadTask(unsigned char *code,
unsigned int physCodeAddr,
unsigned int physDataAddr,
unsigned int physStackAddr) {
unsigned int magic;
unsigned int csize;
unsigned int dsize;
unsigned int bsize;
unsigned char *virtLoadAddr;
int i;
unsigned int **pageDir;
 
magic = getNumber(code);
code += sizeof(unsigned int);
csize = getNumber(code);
code += sizeof(unsigned int);
dsize = getNumber(code);
code += sizeof(unsigned int);
bsize = getNumber(code);
code += sizeof(unsigned int);
if (magic != 0x1AA09232) {
printf("Error: Load module is not executable!\n");
while (1) ;
}
code += 4 * sizeof(unsigned int);
printf("(csize = 0x%x, dsize = 0x%x, bsize = 0x%x)\n",
csize, dsize, bsize);
virtLoadAddr = (unsigned char *) (0xC0000000 | physCodeAddr);
for (i = 0; i < csize; i++) {
*virtLoadAddr++ = *code++;
}
virtLoadAddr = (unsigned char *) (0xC0000000 | physDataAddr);
for (i = 0; i < dsize; i++) {
*virtLoadAddr++ = *code++;
}
for (i = 0; i < bsize; i++) {
*virtLoadAddr++ = '\0';
}
/* allocate a page directory and two page tables */
pageDir = (unsigned int **) allocPageTable();
pageDir[0] = allocPageTable();
pageDir[0][0] = physCodeAddr | 0x01;
pageDir[0][1] = physDataAddr | 0x03;
pageDir[511] = allocPageTable();
pageDir[511][1023] = physStackAddr | 0x03;
return pageDir;
}
 
 
/**************************************************************/
 
 
void trapISR(int irq, unsigned int *registers) {
/* 'putchar' is the only system call yet */
putchar(registers[4]);
/* skip the trap instruction */
registers[30] += 4;
}
 
 
/**************************************************************/
 
 
void flushTLB(void) {
unsigned int invalPage;
int i;
 
invalPage = 0xC0000000;
for (i = 0; i < 32; i++) {
setTLB(i, invalPage, 0);
invalPage += (1 << 12);
}
}
 
 
/**************************************************************/
 
 
void initTimer(void) {
unsigned int *timerBase;
 
timerBase = (unsigned int *) 0xF0000000;
*(timerBase + 1) = 1000;
*timerBase = 2;
orMask(1 << 14);
}
 
 
int task1Started = 0;
int task2Started = 0;
 
 
void timerISR(int irq, unsigned int *registers) {
unsigned int *timerBase;
 
timerBase = (unsigned int *) 0xF0000000;
*timerBase = 2;
printf(">|<");
if (currentTask == 0) {
if (!task1Started) {
/* load & start task1 */
printf("\nOS: loading task1\n");
task1PageDir = loadTask(task1Code, 64 << 12, 68 << 12, 80 << 12);
printf("OS: starting task1\n");
task1Started = 1;
currentTask = 1;
currentPageDir = task1PageDir;
currentStkTop = task1StkTop;
flushTLB();
startTask();
}
} else if (currentTask == 1) {
if (!task2Started) {
/* load & start task2 */
printf("\nOS: loading task2\n");
task2PageDir = loadTask(task2Code, 96 << 12, 100 << 12, 112 << 12);
printf("OS: starting task2\n");
task2Started = 1;
currentTask = 2;
currentPageDir = task2PageDir;
currentStkTop = task2StkTop;
flushTLB();
startTask();
} else {
/* switch tasks */
currentTask = 2;
currentPageDir = task2PageDir;
currentStkTop = task2StkTop;
flushTLB();
}
} else if (currentTask == 2) {
/* switch tasks */
currentTask = 1;
currentPageDir = task1PageDir;
currentStkTop = task1StkTop;
flushTLB();
}
}
 
 
/**************************************************************/
 
 
void main(void) {
currentTask = 0;
currentStkTop = task0StkTop;
printf("\n");
printf("OS: initializing interrupts\n");
initInterrupts();
setISR(20, trapISR);
setISR(14, timerISR);
printf("OS: initializing timer\n");
initTimer();
printf("OS: waiting for interrupt...\n");
enable();
while (1) ;
}
/eco32/trunk/stdalone/twotasks-2/os/end.s
0,0 → 1,19
;
; end.s -- end-of-segment labels
;
 
.export _ecode
.export _edata
.export _ebss
 
.code
.align 4
_ecode:
 
.data
.align 4
_edata:
 
.bss
.align 4
_ebss:
/eco32/trunk/stdalone/twotasks-2/os/stdarg.h
0,0 → 1,41
/*
* stdarg.h -- variable argument lists
*/
 
 
#ifndef _STDARG_H_
#define _STDARG_H_
 
 
typedef char *va_list;
 
 
static float __va_arg_tmp;
 
 
#define va_start(list, start) \
((void)((list) = (sizeof(start)<4 ? \
(char *)((int *)&(start)+1) : (char *)(&(start)+1))))
 
#define __va_arg(list, mode, n) \
(__typecode(mode)==1 && sizeof(mode)==4 ? \
(__va_arg_tmp = *(double *)(&(list += \
((sizeof(double)+n)&~n))[-(int)((sizeof(double)+n)&~n)]), \
*(mode *)&__va_arg_tmp) : \
*(mode *)(&(list += \
((sizeof(mode)+n)&~n))[-(int)((sizeof(mode)+n)&~n)]))
 
#define _bigendian_va_arg(list, mode, n) \
(sizeof(mode)==1 ? *(mode *)(&(list += 4)[-1]) : \
sizeof(mode)==2 ? *(mode *)(&(list += 4)[-2]) : \
__va_arg(list, mode, n))
 
#define va_end(list) ((void)0)
 
#define va_arg(list, mode) \
(sizeof(mode)==8 ? \
*(mode *)(&(list = (char*)(((int)list + 15)&~7U))[-8]) : \
_bigendian_va_arg(list, mode, 3U))
 
 
#endif /* _STDARG_H_ */
/eco32/trunk/stdalone/twotasks-2/os/Makefile
0,0 → 1,23
BUILD = ../../../build
 
SRC = start.s main.c end.s
BIN = twotasks-2.bin
MAP = twotasks-2.map
 
all: $(BIN)
 
run: $(BIN)
$(BUILD)/bin/sim -i -t 1 -l $(BIN)
 
$(BIN): $(SRC) task1.dump task2.dump
$(BUILD)/bin/lcc -A -Wo-kernel \
-Wl-m -Wl$(MAP) -o $(BIN) $(SRC)
 
task1.dump:
../dump/dump ../task1/task1 task1.dump
 
task2.dump:
../dump/dump ../task2/task2 task2.dump
 
clean:
rm -f *~ task1.dump task2.dump $(BIN) $(MAP)
/eco32/trunk/stdalone/twotasks-2/os/start.s
0,0 → 1,294
;
; start.s -- startup code
;
 
.import main
.import task0StkTop
.import currentStkTop
.import currentPageDir
.import _ecode
.import _edata
.import _ebss
 
.export _bcode
.export _bdata
.export _bbss
 
.export enable
.export disable
.export orMask
.export andMask
.export getISR
.export setISR
.export startTask
.export setTLB
 
.code
_bcode:
 
.data
_bdata:
 
.bss
_bbss:
 
.code
 
; reset arrives here
reset:
j start
 
; interrupts arrive here
intrpt:
j isr
 
; user TLB misses arrive here
userMiss:
add $27,$1,$0
ldw $26,$0,currentPageDir
mvfs $1,2
slr $1,$1,20
and $1,$1,0xFFC
add $26,$26,$1
ldw $26,$26,0
mvfs $1,2
slr $1,$1,10
and $1,$1,0xFFC
add $26,$26,$1
ldw $26,$26,0
mvts $26,3 ; entryLow
tbwr
add $1,$27,$0
rfx
 
isr:
add $26,$29,$0 ; sp -> $26
add $27,$1,$0 ; $1 -> $27
ldw $29,$0,currentStkTop ; setup kernel mode stack
sub $29,$29,128 ; save registers
stw $2,$29,8
stw $3,$29,12
stw $4,$29,16
stw $5,$29,20
stw $6,$29,24
stw $7,$29,28
stw $8,$29,32
stw $9,$29,36
stw $10,$29,40
stw $11,$29,44
stw $12,$29,48
stw $13,$29,52
stw $14,$29,56
stw $15,$29,60
stw $16,$29,64
stw $17,$29,68
stw $18,$29,72
stw $19,$29,76
stw $20,$29,80
stw $21,$29,84
stw $22,$29,88
stw $23,$29,92
stw $24,$29,96
stw $25,$29,100
stw $26,$29,116 ; this is the task's sp
stw $27,$29,4 ; this is the task's $1
stw $30,$29,120 ; this is the task's resumption addr
stw $31,$29,124
add $5,$29,$0 ; $5 = pointer to register array
mvfs $4,0 ; $4 = IRQ number
slr $4,$4,16
and $4,$4,0x1F
sll $26,$4,2 ; $26 = 4 * IRQ number
ldw $26,$26,irqsrv ; get addr of service routine
jalr $26 ; call service routine
j resume ; resume task if ISR returns
 
; resume a task
resume:
ldw $29,$0,currentStkTop ; setup kernel mode stack
sub $29,$29,128 ; restore registers
ldw $2,$29,8
ldw $3,$29,12
ldw $4,$29,16
ldw $5,$29,20
ldw $6,$29,24
ldw $7,$29,28
ldw $8,$29,32
ldw $9,$29,36
ldw $10,$29,40
ldw $11,$29,44
ldw $12,$29,48
ldw $13,$29,52
ldw $14,$29,56
ldw $15,$29,60
ldw $16,$29,64
ldw $17,$29,68
ldw $18,$29,72
ldw $19,$29,76
ldw $20,$29,80
ldw $21,$29,84
ldw $22,$29,88
ldw $23,$29,92
ldw $24,$29,96
ldw $25,$29,100
ldw $26,$29,116 ; this is the task's sp
ldw $27,$29,4 ; this is the task's $1
ldw $30,$29,120 ; this is the task's resumption addr
ldw $31,$29,124
add $1,$27,$0 ; $27 -> $1
add $29,$26,$0 ; $26 -> sp
rfx ; return from exception
 
start:
mvfs $8,0
or $8,$8,1 << 27 ; let vector point to RAM
mvts $8,0
add $10,$0,_bdata ; copy data segment
add $8,$0,_edata
sub $9,$8,$10
add $9,$9,_ecode
j cpytest
cpyloop:
ldw $11,$9,0
stw $11,$8,0
cpytest:
sub $8,$8,4
sub $9,$9,4
bgeu $8,$10,cpyloop
add $8,$0,_bbss ; clear bss
add $9,$0,_ebss
j clrtest
clrloop:
stw $0,$8,0
add $8,$8,4
clrtest:
bltu $8,$9,clrloop
ldw $29,$0,task0StkTop ; setup kernel mode stack for task 0
jal main ; call 'main'
start1:
j start1 ; loop
 
enable:
mvfs $8,0
or $8,$8,1 << 23
mvts $8,0
jr $31
 
disable:
mvfs $8,0
and $8,$8,~(1 << 23)
mvts $8,0
jr $31
 
orMask:
mvfs $8,0
and $4,$4,0x0000FFFF ; use lower 16 bits only
or $8,$8,$4
mvts $8,0
jr $31
 
andMask:
mvfs $8,0
or $4,$4,0xFFFF0000 ; use lower 16 bits only
and $8,$8,$4
mvts $8,0
jr $31
 
getISR:
sll $4,$4,2
ldw $2,$4,irqsrv
jr $31
 
setISR:
sll $4,$4,2
stw $5,$4,irqsrv
jr $31
 
startTask:
ldw $29,$0,currentStkTop ; setup kernel mode stack
sub $29,$29,128
stw $0,$29,0 ; preset registers
stw $0,$29,4
stw $0,$29,8
stw $0,$29,12
stw $0,$29,16
stw $0,$29,20
stw $0,$29,24
stw $0,$29,28
stw $0,$29,32
stw $0,$29,36
stw $0,$29,40
stw $0,$29,44
stw $0,$29,48
stw $0,$29,52
stw $0,$29,56
stw $0,$29,60
stw $0,$29,64
stw $0,$29,68
stw $0,$29,72
stw $0,$29,76
stw $0,$29,80
stw $0,$29,84
stw $0,$29,88
stw $0,$29,92
stw $0,$29,96
stw $0,$29,100
stw $0,$29,104
stw $0,$29,108
stw $0,$29,112
add $8,$0,0x80000000
stw $8,$29,116 ; sp
stw $0,$29,120 ; task starts at virtual addr 0
stw $0,$29,124
mvfs $8,0
or $8,$8,1 << 25 ; set previous mode to 'user'
or $8,$8,1 << 22 ; and enable interrupts
mvts $8,0
j resume
 
setTLB:
mvts $4,1 ; set index
mvts $5,2 ; set entryHi
mvts $6,3 ; set entryLo
tbwi ; write TLB entry at index
jr $31
 
.data
 
; interrupt service routine table
 
.align 4
 
irqsrv:
.word 0 ; 00: terminal 0 transmitter interrupt
.word 0 ; 01: terminal 0 receiver interrupt
.word 0 ; 02: terminal 1 transmitter interrupt
.word 0 ; 03: terminal 1 receiver interrupt
.word 0 ; 04: keyboard interrupt
.word 0 ; 05: unused
.word 0 ; 06: unused
.word 0 ; 07: unused
.word 0 ; 08: disk interrupt
.word 0 ; 09: unused
.word 0 ; 10: unused
.word 0 ; 11: unused
.word 0 ; 12: unused
.word 0 ; 13: unused
.word 0 ; 14: timer interrupt
.word 0 ; 15: unused
.word 0 ; 16: bus timeout exception
.word 0 ; 17: illegal instruction exception
.word 0 ; 18: privileged instruction exception
.word 0 ; 19: divide instruction exception
.word 0 ; 20: trap instruction exception
.word 0 ; 21: TLB miss exception
.word 0 ; 22: TLB write exception
.word 0 ; 23: TLB invalid exception
.word 0 ; 24: illegal address exception
.word 0 ; 25: privileged address exception
.word 0 ; 26: unused
.word 0 ; 27: unused
.word 0 ; 28: unused
.word 0 ; 29: unused
.word 0 ; 30: unused
.word 0 ; 31: unused
/eco32/trunk/stdalone/twotasks-2/task1/c0.s
0,0 → 1,30
;
; c0.s -- startup code and begin-of-segment labels
;
 
.import main
 
.export _bcode
.export _bdata
.export _bbss
 
.import _ecode
.import _edata
.import _ebss
 
.code
_bcode:
 
.data
_bdata:
 
.bss
_bbss:
 
.code
.align 4
 
start:
jal main ; call 'main' function
stop:
j stop ; just to be sure...
/eco32/trunk/stdalone/twotasks-2/task1/c1.s
0,0 → 1,19
;
; c1.s -- end-of-segment labels
;
 
.export _ecode
.export _edata
.export _ebss
 
.code
.align 4
_ecode:
 
.data
.align 4
_edata:
 
.bss
.align 4
_ebss:
/eco32/trunk/stdalone/twotasks-2/task1/task1.c
0,0 → 1,95
/*
* task1.c -- a simple task
*/
 
 
#include "putchar.h"
#include "stdarg.h"
 
 
/**************************************************************/
 
 
void puts(char *s) {
char c;
 
while ((c = *s++) != '\0') {
putchar(c);
}
}
 
 
void printn(int n) {
int a;
 
if (n < 0) {
putchar('-');
n = -n;
}
a = n / 10;
if (a != 0) {
printn(a);
}
putchar(n % 10 + '0');
}
 
 
void printu(unsigned int n, unsigned int b) {
unsigned int a;
 
a = n / b;
if (a != 0) {
printu(a, b);
}
putchar("0123456789ABCDEF"[n % b]);
}
 
 
void printf(char *fmt, ...) {
va_list ap;
char c;
int n;
unsigned int u;
char *s;
 
va_start(ap, fmt);
while (1) {
while ((c = *fmt++) != '%') {
if (c == '\0') {
va_end(ap);
return;
}
putchar(c);
}
c = *fmt++;
if (c == 'd') {
n = va_arg(ap, int);
printn(n);
} else
if (c == 'u' || c == 'o' || c == 'x') {
u = va_arg(ap, int);
printu(u, c == 'o' ? 8 : (c == 'x' ? 16 : 10));
} else
if (c == 's') {
s = va_arg(ap, char *);
puts(s);
} else {
putchar(c);
}
}
}
 
 
/**************************************************************/
 
 
void main(void) {
int i;
 
printf("TASK1: executing...\n");
i = 0;
while (1) {
printf("TASK1: %d\n", i);
i++;
}
}
/eco32/trunk/stdalone/twotasks-2/task1/putchar.s
0,0 → 1,10
;
; putchar.s -- putchar library function
;
 
.code
.export putchar
 
putchar:
trap
jr $31
/eco32/trunk/stdalone/twotasks-2/task1/stdarg.h
0,0 → 1,41
/*
* stdarg.h -- variable argument lists
*/
 
 
#ifndef _STDARG_H_
#define _STDARG_H_
 
 
typedef char *va_list;
 
 
static float __va_arg_tmp;
 
 
#define va_start(list, start) \
((void)((list) = (sizeof(start)<4 ? \
(char *)((int *)&(start)+1) : (char *)(&(start)+1))))
 
#define __va_arg(list, mode, n) \
(__typecode(mode)==1 && sizeof(mode)==4 ? \
(__va_arg_tmp = *(double *)(&(list += \
((sizeof(double)+n)&~n))[-(int)((sizeof(double)+n)&~n)]), \
*(mode *)&__va_arg_tmp) : \
*(mode *)(&(list += \
((sizeof(mode)+n)&~n))[-(int)((sizeof(mode)+n)&~n)]))
 
#define _bigendian_va_arg(list, mode, n) \
(sizeof(mode)==1 ? *(mode *)(&(list += 4)[-1]) : \
sizeof(mode)==2 ? *(mode *)(&(list += 4)[-2]) : \
__va_arg(list, mode, n))
 
#define va_end(list) ((void)0)
 
#define va_arg(list, mode) \
(sizeof(mode)==8 ? \
*(mode *)(&(list = (char*)(((int)list + 15)&~7U))[-8]) : \
_bigendian_va_arg(list, mode, 3U))
 
 
#endif /* _STDARG_H_ */
/eco32/trunk/stdalone/twotasks-2/task1/putchar.h
0,0 → 1,13
/*
* putchar.h -- putchar library function
*/
 
 
#ifndef _PUTCHAR_H_
#define _PUTCHAR_H_
 
 
void putchar(char c);
 
 
#endif /* _PUTCHAR_H_ */
/eco32/trunk/stdalone/twotasks-2/task1/Makefile
0,0 → 1,21
BUILD = ../../../build
 
all: task1
 
task1: c0.o task1.o putchar.o c1.o
$(BUILD)/bin/ld -o task1 c0.o task1.o putchar.o c1.o
 
c0.o: c0.s
$(BUILD)/bin/as -o c0.o c0.s
 
task1.o: task1.c
$(BUILD)/bin/lcc -A -c -o task1.o task1.c
 
putchar.o: putchar.s
$(BUILD)/bin/as -o putchar.o putchar.s
 
c1.o: c1.s
$(BUILD)/bin/as -o c1.o c1.s
 
clean:
rm -f *~ c0.o task1.o putchar.o c1.o task1
/eco32/trunk/stdalone/twotasks-2/task2/c0.s
0,0 → 1,30
;
; c0.s -- startup code and begin-of-segment labels
;
 
.import main
 
.export _bcode
.export _bdata
.export _bbss
 
.import _ecode
.import _edata
.import _ebss
 
.code
_bcode:
 
.data
_bdata:
 
.bss
_bbss:
 
.code
.align 4
 
start:
jal main ; call 'main' function
stop:
j stop ; just to be sure...
/eco32/trunk/stdalone/twotasks-2/task2/c1.s
0,0 → 1,19
;
; c1.s -- end-of-segment labels
;
 
.export _ecode
.export _edata
.export _ebss
 
.code
.align 4
_ecode:
 
.data
.align 4
_edata:
 
.bss
.align 4
_ebss:
/eco32/trunk/stdalone/twotasks-2/task2/task2.c
0,0 → 1,95
/*
* task2.c -- a simple task
*/
 
 
#include "putchar.h"
#include "stdarg.h"
 
 
/**************************************************************/
 
 
void puts(char *s) {
char c;
 
while ((c = *s++) != '\0') {
putchar(c);
}
}
 
 
void printn(int n) {
int a;
 
if (n < 0) {
putchar('-');
n = -n;
}
a = n / 10;
if (a != 0) {
printn(a);
}
putchar(n % 10 + '0');
}
 
 
void printu(unsigned int n, unsigned int b) {
unsigned int a;
 
a = n / b;
if (a != 0) {
printu(a, b);
}
putchar("0123456789ABCDEF"[n % b]);
}
 
 
void printf(char *fmt, ...) {
va_list ap;
char c;
int n;
unsigned int u;
char *s;
 
va_start(ap, fmt);
while (1) {
while ((c = *fmt++) != '%') {
if (c == '\0') {
va_end(ap);
return;
}
putchar(c);
}
c = *fmt++;
if (c == 'd') {
n = va_arg(ap, int);
printn(n);
} else
if (c == 'u' || c == 'o' || c == 'x') {
u = va_arg(ap, int);
printu(u, c == 'o' ? 8 : (c == 'x' ? 16 : 10));
} else
if (c == 's') {
s = va_arg(ap, char *);
puts(s);
} else {
putchar(c);
}
}
}
 
 
/**************************************************************/
 
 
void main(void) {
int i;
 
printf("TASK2: executing...\n");
i = 0;
while (1) {
printf("TASK2: %d\n", i);
i++;
}
}
/eco32/trunk/stdalone/twotasks-2/task2/putchar.s
0,0 → 1,10
;
; putchar.s -- putchar library function
;
 
.code
.export putchar
 
putchar:
trap
jr $31
/eco32/trunk/stdalone/twotasks-2/task2/stdarg.h
0,0 → 1,41
/*
* stdarg.h -- variable argument lists
*/
 
 
#ifndef _STDARG_H_
#define _STDARG_H_
 
 
typedef char *va_list;
 
 
static float __va_arg_tmp;
 
 
#define va_start(list, start) \
((void)((list) = (sizeof(start)<4 ? \
(char *)((int *)&(start)+1) : (char *)(&(start)+1))))
 
#define __va_arg(list, mode, n) \
(__typecode(mode)==1 && sizeof(mode)==4 ? \
(__va_arg_tmp = *(double *)(&(list += \
((sizeof(double)+n)&~n))[-(int)((sizeof(double)+n)&~n)]), \
*(mode *)&__va_arg_tmp) : \
*(mode *)(&(list += \
((sizeof(mode)+n)&~n))[-(int)((sizeof(mode)+n)&~n)]))
 
#define _bigendian_va_arg(list, mode, n) \
(sizeof(mode)==1 ? *(mode *)(&(list += 4)[-1]) : \
sizeof(mode)==2 ? *(mode *)(&(list += 4)[-2]) : \
__va_arg(list, mode, n))
 
#define va_end(list) ((void)0)
 
#define va_arg(list, mode) \
(sizeof(mode)==8 ? \
*(mode *)(&(list = (char*)(((int)list + 15)&~7U))[-8]) : \
_bigendian_va_arg(list, mode, 3U))
 
 
#endif /* _STDARG_H_ */
/eco32/trunk/stdalone/twotasks-2/task2/putchar.h
0,0 → 1,13
/*
* putchar.h -- putchar library function
*/
 
 
#ifndef _PUTCHAR_H_
#define _PUTCHAR_H_
 
 
void putchar(char c);
 
 
#endif /* _PUTCHAR_H_ */
/eco32/trunk/stdalone/twotasks-2/task2/Makefile
0,0 → 1,21
BUILD = ../../../build
 
all: task2
 
task2: c0.o task2.o putchar.o c1.o
$(BUILD)/bin/ld -o task2 c0.o task2.o putchar.o c1.o
 
c0.o: c0.s
$(BUILD)/bin/as -o c0.o c0.s
 
task2.o: task2.c
$(BUILD)/bin/lcc -A -c -o task2.o task2.c
 
putchar.o: putchar.s
$(BUILD)/bin/as -o putchar.o putchar.s
 
c1.o: c1.s
$(BUILD)/bin/as -o c1.o c1.s
 
clean:
rm -f *~ c0.o task2.o putchar.o c1.o task2
/eco32/trunk/stdalone/twotasks-2/dump/dump.c
0,0 → 1,48
/*
* dump.c -- dump a binary file as contents of a C array
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
 
int main(int argc, char *argv[]) {
FILE *infile, *outfile;
int c, n;
 
if (argc != 3) {
printf("Usage: %s <infile> <outfile>\n", argv[0]);
return 1;
}
infile = fopen(argv[1], "rb");
if (infile == NULL) {
printf("Error: cannot open file '%s' for input\n", argv[1]);
return 1;
}
outfile = fopen(argv[2], "wt");
if (outfile == NULL) {
printf("Error: cannot open file '%s' for output\n", argv[2]);
return 1;
}
n = 0;
while (1) {
c = getc(infile);
if (c == EOF) {
break;
}
fprintf(outfile, "0x%02X, ", c);
n++;
if (n == 8) {
n = 0;
fprintf(outfile, "\n");
}
}
if (n != 0) {
fprintf(outfile, "\n");
}
fclose(infile);
fclose(outfile);
return 0;
}
/eco32/trunk/stdalone/twotasks-2/dump/Makefile
0,0 → 1,15
#
# Makefile for dump utility
#
 
.PHONY: all install clean
 
all: dump
 
install: dump
 
dump: dump.c
gcc -m32 -g -Wall -o dump dump.c
 
clean:
rm -f *~ dump
/eco32/trunk/stdalone/twotasks-2/Makefile
0,0 → 1,37
#
# Makefile for "twotasks-2", a tiny OS which runs two tasks
# (with randomly written TLB entries and real page tables)
#
 
BUILD = ../../build
 
.PHONY: all install run clean
 
all: dump/dump task1/task1 task2/task2 os/twotasks-2.bin
 
install: dump/dump task1/task1 task2/task2 os/twotasks-2.bin
mkdir -p $(BUILD)/stdalone
cp os/twotasks-2.bin $(BUILD)/stdalone
cp os/twotasks-2.map $(BUILD)/stdalone
 
run: dump/dump task1/task1 task2/task2 os/twotasks-2.bin
$(MAKE) -C os run
 
dump/dump:
$(MAKE) -C dump
 
task1/task1:
$(MAKE) -C task1
 
task2/task2:
$(MAKE) -C task2
 
os/twotasks-2.bin:
$(MAKE) -C os
 
clean:
$(MAKE) -C dump clean
$(MAKE) -C task1 clean
$(MAKE) -C task2 clean
$(MAKE) -C os clean
rm -f *~
/eco32/trunk/Makefile
4,7 → 4,7
 
VERSION = 0.22
 
DIRS = doc binutils sim simtest fpga hwtests monitor disk
DIRS = doc binutils sim simtest fpga hwtests monitor disk stdalone
BUILD = `pwd`/build
 
.PHONY: all compiler builddir clean dist

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.