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

Subversion Repositories eco32

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /eco32/trunk/monitor
    from Rev 50 to Rev 51
    Reverse comparison

Rev 50 → Rev 51

/monitor/sctio-ser.s File deleted
/monitor/stdarg.h File deleted
/monitor/romlib.h File deleted
/monitor/cpu.h File deleted
/monitor/getline.h File deleted
/monitor/Makefile File deleted
/monitor/common.h File deleted
/monitor/mmu.c File deleted
/monitor/instr.c File deleted
/monitor/serial.s File deleted
/monitor/start.h File deleted
/monitor/boot.c File deleted
/monitor/mmu.h File deleted
/monitor/instr.h File deleted
/monitor/boot.h File deleted
/monitor/start.s File deleted
/monitor/command.c File deleted
/monitor/disasm.c File deleted
/monitor/keyboard.s File deleted
/monitor/asm.c File deleted
/monitor/sctio-ctl.s File deleted
/monitor/command.h File deleted
/monitor/romlib.c File deleted
/monitor/main.c File deleted
/monitor/disasm.h File deleted
/monitor/display.s File deleted
/monitor/asm.h File deleted
/monitor/end.s File deleted
/monitor/cpu.c File deleted
/monitor/getline.c File deleted
/monitor-xess/load.c
0,0 → 1,223
/*
* load.c -- load S-record file from serial line
*/
 
 
#include "common.h"
#include "stdarg.h"
#include "romlib.h"
#include "load.h"
#include "serial.h"
#include "cpu.h"
#include "mmu.h"
 
 
#define NUM_TRIES 10
#define WAIT_DELAY 350000
 
#define SYN ((unsigned char) 's')
#define ACK ((unsigned char) 'a')
 
#define LINE_SIZE 520
 
 
static Byte line[LINE_SIZE];
 
 
static Word getByte(int index) {
Word hi, lo;
 
hi = line[index + 0];
if (hi >= '0' && hi <= '9') {
hi -= '0';
} else
if (hi >= 'A' && hi <= 'F') {
hi -= 'A' - 10;
} else
if (hi >= 'a' && hi <= 'f') {
hi -= 'a' - 10;
} else {
return -1;
}
lo = line[index + 1];
if (lo >= '0' && lo <= '9') {
lo -= '0';
} else
if (lo >= 'A' && lo <= 'F') {
lo -= 'A' - 10;
} else
if (lo >= 'a' && lo <= 'f') {
lo -= 'a' - 10;
} else {
return -1;
}
return (hi << 4) | lo;
}
 
 
static void serialOut(int serno, Word c) {
if (serno == 0) {
ser0out(c);
} else {
ser1out(c);
}
}
 
 
static int serialChk(int serno) {
if (serno == 0) {
return ser0inchk();
} else {
return ser1inchk();
}
}
 
 
static Word serialIn(int serno) {
if (serno == 0) {
return ser0in();
} else {
return ser1in();
}
}
 
 
void load(int serno) {
int i, j;
Bool run;
int type;
int count;
Word chksum;
Word addr;
Byte b;
 
printf("Trying to connect to load server...\n");
for (i = 0; i < NUM_TRIES; i++) {
serialOut(serno, SYN);
for (j = 0; j < WAIT_DELAY; j++) {
if (serialChk(serno) != 0) {
break;
}
}
if (j < WAIT_DELAY) {
break;
}
printf("Request timed out...\n");
}
if (i == NUM_TRIES ||
serialIn(serno) != ACK) {
printf("Unable to establish connection to load server.\n");
return;
}
serialOut(serno, ACK);
printf("Connected to load server.\n");
run = true;
while (run) {
serialOut(serno, 'r');
for (i = 0; i < LINE_SIZE; i++) {
line[i] = serialIn(serno);
if (line[i] == '\n') {
break;
}
}
if (i == LINE_SIZE) {
printf("Error: too many characters in S-record!\n");
break;
}
line[i] = '\0';
printf("%s\n", line);
if (line[0] != 'S') {
printf("Error: malformed S-record!\n");
break;
}
type = line[1];
count = getByte(2);
if (i != 2 * count + 4) {
printf("Error: inconsistent byte count in S-record!\n");
break;
}
chksum = 0;
for (j = 2; j < i; j += 2) {
chksum += getByte(j);
}
if ((chksum & 0xFF) != 0xFF) {
printf("Error: wrong checksum in S-record!\n");
break;
}
switch (type) {
case '0':
/* S0 record: header (skip) */
break;
case '1':
/* S1 record: 2 byte load address + data (load data) */
addr = (getByte( 4) << 8) |
(getByte( 6) << 0);
addr |= 0xC0000000;
for (j = 0; j < count - 3; j++) {
b = getByte(2 * j + 8);
mmuWriteByte(addr + j, b);
}
break;
case '2':
/* S2 record: 3 byte load address + data (load data) */
addr = (getByte( 4) << 16) |
(getByte( 6) << 8) |
(getByte( 8) << 0);
addr |= 0xC0000000;
for (j = 0; j < count - 4; j++) {
b = getByte(2 * j + 10);
mmuWriteByte(addr + j, b);
}
break;
case '3':
/* S3 record: 4 byte load address + data (load data) */
addr = (getByte( 4) << 24) |
(getByte( 6) << 16) |
(getByte( 8) << 8) |
(getByte(10) << 0);
addr |= 0xC0000000;
for (j = 0; j < count - 5; j++) {
b = getByte(2 * j + 12);
mmuWriteByte(addr + j, b);
}
break;
case '5':
/* S5 record: record count (skip) */
break;
case '7':
/* S7 record: 4 byte start address (set PC, stop loading) */
addr = (getByte( 4) << 24) |
(getByte( 6) << 16) |
(getByte( 8) << 8) |
(getByte(10) << 0);
addr |= 0xC0000000;
cpuSetPC(addr);
run = false;
break;
case '8':
/* S8 record: 3 byte start address (set PC, stop loading) */
addr = (getByte( 4) << 16) |
(getByte( 6) << 8) |
(getByte( 8) << 0);
addr |= 0xC0000000;
cpuSetPC(addr);
run = false;
break;
case '9':
/* S9 record: 2 byte start address (set PC, stop loading) */
addr = (getByte( 4) << 8) |
(getByte( 6) << 0);
addr |= 0xC0000000;
cpuSetPC(addr);
run = false;
break;
default:
/* unknown type of S-record */
printf("Error: unknown type of S-record!\n");
run = false;
break;
}
}
serialOut(serno, 'q');
printf("Connection to load server closed.\n");
}
/monitor-xess/load.h
0,0 → 1,13
/*
* load.h -- load S-record file from serial line
*/
 
 
#ifndef _LOAD_H_
#define _LOAD_H_
 
 
void load(int serno);
 
 
#endif /* _LOAD_H_ */
/monitor-xess/Makefile
0,0 → 1,31
#
# Makefile for ECO32 ROM monitor
#
 
BUILD = ../../build
 
SRC = start.s main.c command.c instr.c asm.c disasm.c \
load.c boot.c cpu.c mmu.c getline.c romlib.c \
keyboard.s ../kbdtbls/kbdtbls.s display.s \
serial.s sctio-ctl.s sctio-ser.s end.s
 
.PHONY: all install clean
 
all: monitor.bin monitor.exo
 
install: monitor.bin monitor.exo
mkdir -p $(BUILD)/monitor
cp monitor.bin $(BUILD)/monitor
cp monitor.exo $(BUILD)/monitor
 
monitor.exo: monitor.bin
$(BUILD)/bin/bin2exo -S2 0 monitor.bin monitor.exo
 
monitor.bin: $(SRC)
$(BUILD)/bin/lcc -A -Wo-rom -Wl-rd -Wl0xC03F0000 \
-Wl-m -Wlmonitor.map -o monitor.bin $(SRC)
 
clean:
rm -f *~
rm -f monitor.map monitor.bin
rm -f monitor.exo
/monitor-xess/command.c
0,0 → 1,865
/*
* command.c -- command interpreter
*/
 
 
#include "common.h"
#include "stdarg.h"
#include "romlib.h"
#include "getline.h"
#include "command.h"
#include "asm.h"
#include "disasm.h"
#include "load.h"
#include "boot.h"
#include "cpu.h"
#include "mmu.h"
#include "start.h"
 
 
#define MAX_TOKENS 10
 
 
typedef struct {
char *name;
void (*hlpProc)(void);
void (*cmdProc)(char *tokens[], int n);
} Command;
 
extern Command commands[];
extern int numCommands;
 
 
static void help(void) {
printf("valid commands are:\n");
printf(" help get help\n");
printf(" + add and subtract\n");
printf(" a assemble\n");
printf(" u unassemble\n");
printf(" b set/reset breakpoint\n");
printf(" c continue from breakpoint\n");
printf(" s single-step\n");
printf(" @ show/set PC\n");
printf(" p show/set PSW\n");
printf(" r show/set register\n");
printf(" d dump memory\n");
printf(" mw show/set memory word\n");
printf(" mh show/set memory halfword\n");
printf(" mb show/set memory byte\n");
printf(" t show/set TLB contents\n");
printf(" boot bootstrap from disk\n");
printf("type 'help <cmd>' to get help for <cmd>\n");
}
 
 
static void help00(void) {
printf(" help show a list of commands\n");
printf(" help <cmd> show help for <cmd>\n");
}
 
 
static void help01(void) {
printf(" + <num1> <num2> add and subtract <num1> and <num2>\n");
}
 
 
static void help02(void) {
printf(" a assemble starting at PC\n");
printf(" a <addr> assemble starting at <addr>\n");
}
 
 
static void help03(void) {
printf(" u unassemble 16 instrs starting at PC\n");
printf(" u <addr> unassemble 16 instrs starting at <addr>\n");
printf(" u <addr> <cnt> unassemble <cnt> instrs starting at <addr>\n");
}
 
 
static void help04(void) {
printf(" b reset break\n");
printf(" b <addr> set break at <addr>\n");
}
 
 
static void help05(void) {
printf(" c continue execution\n");
printf(" c <cnt> continue execution <cnt> times\n");
}
 
 
static void help06(void) {
printf(" s single-step one instruction\n");
printf(" s <cnt> single-step <cnt> instructions\n");
}
 
 
static void help07(void) {
printf(" @ show PC\n");
printf(" @ <addr> set PC to <addr>\n");
}
 
 
static void help08(void) {
printf(" p show PSW\n");
printf(" p <data> set PSW to <data>\n");
}
 
 
static void help09(void) {
printf(" r show all registers\n");
printf(" r <reg> show register <reg>\n");
printf(" r <reg> <data> set register <reg> to <data>\n");
}
 
 
static void help10(void) {
printf(" d dump 256 bytes starting at PC\n");
printf(" d <addr> dump 256 bytes starting at <addr>\n");
printf(" d <addr> <cnt> dump <cnt> bytes starting at <addr>\n");
}
 
 
static void help11(void) {
printf(" mw show memory word at PC\n");
printf(" mw <addr> show memory word at <addr>\n");
printf(" mw <addr> <data> set memory word at <addr> to <data>\n");
}
 
 
static void help12(void) {
printf(" mh show memory halfword at PC\n");
printf(" mh <addr> show memory halfword at <addr>\n");
printf(" mh <addr> <data> set memory halfword at <addr> to <data>\n");
}
 
 
static void help13(void) {
printf(" mb show memory byte at PC\n");
printf(" mb <addr> show memory byte at <addr>\n");
printf(" mb <addr> <data> set memory byte at <addr> to <data>\n");
}
 
 
static void help14(void) {
printf(" t show TLB contents\n");
printf(" t <i> show TLB contents at <i>\n");
printf(" t <i> p <data> set TLB contents at <i> to page <data>\n");
printf(" t <i> f <data> set TLB contents at <i> to frame <data>\n");
}
 
 
static void help15(void) {
printf(" boot <n> load and execute first sector of disk <n>\n");
}
 
 
static Bool getHexNumber(char *str, Word *valptr) {
char *end;
 
*valptr = strtoul(str, &end, 16);
return *end == '\0';
}
 
 
static Bool getDecNumber(char *str, int *valptr) {
char *end;
 
*valptr = strtoul(str, &end, 10);
return *end == '\0';
}
 
 
static void showPC(void) {
Word pc, psw;
Word instr;
 
pc = cpuGetPC();
psw = cpuGetPSW();
instr = mmuReadWord(pc);
printf("PC %08X [PC] %08X %s\n",
pc, instr, disasm(instr, pc));
}
 
 
static void showBreak(void) {
Word brk;
 
brk = cpuGetBreak();
printf("Brk ");
if (cpuTestBreak()) {
printf("%08X", brk);
} else {
printf("--------");
}
printf("\n");
}
 
 
static void showPSW(void) {
Word psw;
int i;
 
psw = cpuGetPSW();
printf(" xxxx V UPO IPO IACK MASK\n");
printf("PSW ");
for (i = 31; i >= 0; i--) {
if (i == 27 || i == 26 || i == 23 || i == 20 || i == 15) {
printf(" ");
}
printf("%c", psw & (1 << i) ? '1' : '0');
}
printf("\n");
}
 
 
static void doHelp(char *tokens[], int n) {
int i;
 
if (n == 1) {
help();
} else if (n == 2) {
for (i = 0; i < numCommands; i++) {
if (strcmp(commands[i].name, tokens[1]) == 0) {
(*commands[i].hlpProc)();
return;
}
}
printf("no help available for '%s', sorry\n", tokens[1]);
} else {
help00();
}
}
 
 
static void doArith(char *tokens[], int n) {
Word num1, num2, num3, num4;
 
if (n == 3) {
if (!getHexNumber(tokens[1], &num1)) {
printf("illegal first number\n");
return;
}
if (!getHexNumber(tokens[2], &num2)) {
printf("illegal second number\n");
return;
}
num3 = num1 + num2;
num4 = num1 - num2;
printf("add = %08X, sub = %08X\n", num3, num4);
} else {
help01();
}
}
 
 
static void doAssemble(char *tokens[], int n) {
Word addr;
Word psw;
char prompt[30];
char *line;
char *msg;
Word instr;
 
if (n == 1) {
addr = cpuGetPC();
} else if (n == 2) {
if (!getHexNumber(tokens[1], &addr)) {
printf("illegal address\n");
return;
}
} else {
help02();
return;
}
addr &= ~0x00000003;
psw = cpuGetPSW();
while (1) {
sprintf(prompt, "ASM @ %08X: ", addr);
line = getLine(prompt);
if (*line == '\0' || *line == '\n') {
break;
}
addHist(line);
msg = asmInstr(line, addr, &instr);
if (msg != NULL) {
printf("%s\n", msg);
} else {
mmuWriteWord(addr, instr);
addr += 4;
}
}
}
 
 
static void doUnassemble(char *tokens[], int n) {
Word addr, count;
Word psw;
int i;
Word instr;
 
if (n == 1) {
addr = cpuGetPC();
count = 16;
} else if (n == 2) {
if (!getHexNumber(tokens[1], &addr)) {
printf("illegal address\n");
return;
}
count = 16;
} else if (n == 3) {
if (!getHexNumber(tokens[1], &addr)) {
printf("illegal address\n");
return;
}
if (!getHexNumber(tokens[2], &count)) {
printf("illegal count\n");
return;
}
if (count == 0) {
return;
}
} else {
help03();
return;
}
addr &= ~0x00000003;
psw = cpuGetPSW();
for (i = 0; i < count; i++) {
instr = mmuReadWord(addr);
printf("%08X: %08X %s\n",
addr, instr, disasm(instr, addr));
if (addr + 4 < addr) {
/* wrap-around */
break;
}
addr += 4;
}
}
 
 
static void doBreak(char *tokens[], int n) {
Word addr;
 
if (n == 1) {
cpuResetBreak();
showBreak();
} else if (n == 2) {
if (!getHexNumber(tokens[1], &addr)) {
printf("illegal address\n");
return;
}
addr &= ~0x00000003;
cpuSetBreak(addr);
showBreak();
} else {
help04();
}
}
 
 
static void doContinue(char *tokens[], int n) {
Word count, i;
Word addr;
 
if (n == 1) {
count = 1;
} else if (n == 2) {
if (!getHexNumber(tokens[1], &count) || count == 0) {
printf("illegal count\n");
return;
}
} else {
help05();
return;
}
for (i = 0; i < count; i++) {
cpuRun();
}
addr = cpuGetPC();
printf("Break at %08X\n", addr);
showPC();
}
 
 
static void doStep(char *tokens[], int n) {
Word count, i;
 
if (n == 1) {
count = 1;
} else if (n == 2) {
if (!getHexNumber(tokens[1], &count) || count == 0) {
printf("illegal count\n");
return;
}
} else {
help06();
return;
}
for (i = 0; i < count; i++) {
cpuStep();
}
showPC();
}
 
 
static void doPC(char *tokens[], int n) {
Word addr;
 
if (n == 1) {
showPC();
} else if (n == 2) {
if (!getHexNumber(tokens[1], &addr)) {
printf("illegal address\n");
return;
}
addr &= ~0x00000003;
cpuSetPC(addr);
showPC();
} else {
help07();
}
}
 
 
static void explainPSW(Word data) {
int i;
 
printf("interrupt vector : %s (%s)\n",
data & PSW_V ? "on " : "off",
data & PSW_V ? "RAM" : "ROM");
printf("current user mode : %s (%s)\n",
data & PSW_UM ? "on " : "off",
data & PSW_UM ? "user" : "kernel");
printf("previous user mode : %s (%s)\n",
data & PSW_PUM ? "on " : "off",
data & PSW_PUM ? "user" : "kernel");
printf("old user mode : %s (%s)\n",
data & PSW_OUM ? "on " : "off",
data & PSW_OUM ? "user" : "kernel");
printf("current interrupt enable : %s (%s)\n",
data & PSW_IE ? "on " : "off",
data & PSW_IE ? "enabled" : "disabled");
printf("previous interrupt enable : %s (%s)\n",
data & PSW_PIE ? "on " : "off",
data & PSW_PIE ? "enabled" : "disabled");
printf("old interrupt enable : %s (%s)\n",
data & PSW_OIE ? "on " : "off",
data & PSW_OIE ? "enabled" : "disabled");
printf("last interrupt acknowledged : %02X (%s)\n",
(data & PSW_PRIO_MASK) >> 16,
exceptionToString((data & PSW_PRIO_MASK) >> 16));
for (i = 15; i >= 0; i--) {
printf("%-35s: %s (%s)\n",
exceptionToString(i),
data & (1 << i) ? "on " : "off",
data & (1 << i) ? "enabled" : "disabled");
}
}
 
 
static void doPSW(char *tokens[], int n) {
Word data;
 
if (n == 1) {
data = cpuGetPSW();
showPSW();
explainPSW(data);
} else if (n == 2) {
if (!getHexNumber(tokens[1], &data)) {
printf("illegal data\n");
return;
}
data &= 0x0FFFFFFF;
cpuSetPSW(data);
showPSW();
explainPSW(data);
} else {
help08();
}
}
 
 
static void doRegister(char *tokens[], int n) {
int i, j;
int reg;
Word data;
 
if (n == 1) {
for (i = 0; i < 8; i++) {
for (j = 0; j < 4; j++) {
reg = 8 * j + i;
data = cpuGetReg(reg);
printf("$%-2d %08X ", reg, data);
}
printf("\n");
}
showPSW();
showBreak();
showPC();
} else if (n == 2) {
if (!getDecNumber(tokens[1], &reg) || reg < 0 || reg >= 32) {
printf("illegal register number\n");
return;
}
data = cpuGetReg(reg);
printf("$%-2d %08X\n", reg, data);
} else if (n == 3) {
if (!getDecNumber(tokens[1], &reg) || reg < 0 || reg >= 32) {
printf("illegal register number\n");
return;
}
if (!getHexNumber(tokens[2], &data)) {
printf("illegal data\n");
return;
}
cpuSetReg(reg, data);
} else {
help09();
}
}
 
 
static void doDump(char *tokens[], int n) {
Word addr, count;
Word psw;
Word lo, hi, curr;
int lines, i, j;
Word tmp;
Byte c;
 
if (n == 1) {
addr = cpuGetPC();
count = 16 * 16;
} else if (n == 2) {
if (!getHexNumber(tokens[1], &addr)) {
printf("illegal address\n");
return;
}
count = 16 * 16;
} else if (n == 3) {
if (!getHexNumber(tokens[1], &addr)) {
printf("illegal address\n");
return;
}
if (!getHexNumber(tokens[2], &count)) {
printf("illegal count\n");
return;
}
if (count == 0) {
return;
}
} else {
help10();
return;
}
psw = cpuGetPSW();
lo = addr & ~0x0000000F;
hi = addr + count - 1;
if (hi < lo) {
/* wrap-around */
hi = 0xFFFFFFFF;
}
lines = (hi - lo + 16) >> 4;
curr = lo;
for (i = 0; i < lines; i++) {
printf("%08X: ", curr);
for (j = 0; j < 16; j++) {
tmp = curr + j;
if (tmp < addr || tmp > hi) {
printf(" ");
} else {
c = mmuReadByte(tmp);
printf("%02X", c);
}
printf(" ");
}
printf(" ");
for (j = 0; j < 16; j++) {
tmp = curr + j;
if (tmp < addr || tmp > hi) {
printf(" ");
} else {
c = mmuReadByte(tmp);
if (c >= 32 && c <= 126) {
printf("%c", c);
} else {
printf(".");
}
}
}
printf("\n");
curr += 16;
}
}
 
 
static void doMemoryWord(char *tokens[], int n) {
Word psw;
Word addr;
Word data;
Word tmpData;
 
psw = cpuGetPSW();
if (n == 1) {
addr = cpuGetPC();
data = mmuReadWord(addr);
printf("%08X: %08X\n", addr, data);
} else if (n == 2) {
if (!getHexNumber(tokens[1], &addr)) {
printf("illegal address\n");
return;
}
data = mmuReadWord(addr);
printf("%08X: %08X\n", addr, data);
} else if (n == 3) {
if (!getHexNumber(tokens[1], &addr)) {
printf("illegal address\n");
return;
}
if (!getHexNumber(tokens[2], &tmpData)) {
printf("illegal data\n");
return;
}
data = tmpData;
mmuWriteWord(addr, data);
} else {
help11();
}
}
 
 
static void doMemoryHalf(char *tokens[], int n) {
Word psw;
Word addr;
Half data;
Word tmpData;
 
psw = cpuGetPSW();
if (n == 1) {
addr = cpuGetPC();
data = mmuReadHalf(addr);
printf("%08X: %04X\n", addr, data);
} else if (n == 2) {
if (!getHexNumber(tokens[1], &addr)) {
printf("illegal address\n");
return;
}
data = mmuReadHalf(addr);
printf("%08X: %04X\n", addr, data);
} else if (n == 3) {
if (!getHexNumber(tokens[1], &addr)) {
printf("illegal address\n");
return;
}
if (!getHexNumber(tokens[2], &tmpData)) {
printf("illegal data\n");
return;
}
data = (Half) tmpData;
mmuWriteHalf(addr, data);
} else {
help12();
}
}
 
 
static void doMemoryByte(char *tokens[], int n) {
Word psw;
Word addr;
Byte data;
Word tmpData;
 
psw = cpuGetPSW();
if (n == 1) {
addr = cpuGetPC();
data = mmuReadByte(addr);
printf("%08X: %02X\n", addr, data);
} else if (n == 2) {
if (!getHexNumber(tokens[1], &addr)) {
printf("illegal address\n");
return;
}
data = mmuReadByte(addr);
printf("%08X: %02X\n", addr, data);
} else if (n == 3) {
if (!getHexNumber(tokens[1], &addr)) {
printf("illegal address\n");
return;
}
if (!getHexNumber(tokens[2], &tmpData)) {
printf("illegal data\n");
return;
}
data = (Byte) tmpData;
mmuWriteByte(addr, data);
} else {
help13();
}
}
 
 
static void doTLB(char *tokens[], int n) {
int index;
TLB_Entry tlbEntry;
Word data;
 
if (n == 1) {
for (index = 0; index < TLB_SIZE; index++) {
tlbEntry = mmuGetTLB(index);
printf("TLB[%02d] page %08X frame %08X %c %c\n",
index, tlbEntry.page, tlbEntry.frame,
tlbEntry.write ? 'w' : '-',
tlbEntry.valid ? 'v' : '-');
}
printf("Index(1) %08X\n", mmuGetIndex());
printf("EntryHi(2) %08X\n", mmuGetEntryHi());
printf("EntryLo(3) %08X\n", mmuGetEntryLo());
} else if (n == 2) {
if (!getDecNumber(tokens[1], &index) || index < 0 || index >= TLB_SIZE) {
printf("illegal TLB index\n");
return;
}
tlbEntry = mmuGetTLB(index);
printf("TLB[%02d] page %08X frame %08X %c %c\n",
index, tlbEntry.page, tlbEntry.frame,
tlbEntry.write ? 'w' : '-',
tlbEntry.valid ? 'v' : '-');
} else if (n == 3) {
help14();
} else if (n == 4) {
if (!getDecNumber(tokens[1], &index) || index < 0 || index >= TLB_SIZE) {
printf("illegal TLB index\n");
return;
}
if (!getHexNumber(tokens[3], &data)) {
printf("illegal data\n");
return;
}
tlbEntry = mmuGetTLB(index);
if (strcmp(tokens[2], "p") == 0) {
tlbEntry.page = data & PAGE_MASK;
} else
if (strcmp(tokens[2], "f") == 0) {
tlbEntry.frame = data & PAGE_MASK;
tlbEntry.write = data & TLB_WRITE ? true : false;
tlbEntry.valid = data & TLB_VALID ? true : false;
} else {
printf("TLB selector is not one of 'p' or 'f'\n");
return;
}
mmuSetTLB(index, tlbEntry);
printf("TLB[%02d] page %08X frame %08X %c %c\n",
index, tlbEntry.page, tlbEntry.frame,
tlbEntry.write ? 'w' : '-',
tlbEntry.valid ? 'v' : '-');
} else {
help14();
}
}
 
 
static void doBoot(char *tokens[], int n) {
int dskno;
 
if (n == 2) {
if (!getDecNumber(tokens[1], &dskno) || dskno < 0 || dskno > 1) {
printf("illegal disk number\n");
return;
}
boot(dskno);
} else {
help15();
}
}
 
 
Command commands[] = {
{ "help", help00, doHelp },
{ "+", help01, doArith },
{ "a", help02, doAssemble },
{ "u", help03, doUnassemble },
{ "b", help04, doBreak },
{ "c", help05, doContinue },
{ "s", help06, doStep },
{ "@", help07, doPC },
{ "p", help08, doPSW },
{ "r", help09, doRegister },
{ "d", help10, doDump },
{ "mw", help11, doMemoryWord },
{ "mh", help12, doMemoryHalf },
{ "mb", help13, doMemoryByte },
{ "t", help14, doTLB },
{ "boot", help15, doBoot },
};
 
int numCommands = sizeof(commands) / sizeof(commands[0]);
 
 
static void doCommand(char *line) {
char *tokens[MAX_TOKENS];
int n;
char *p;
int i;
 
n = 0;
p = strtok(line, " \t\n");
while (p != NULL) {
if (n == MAX_TOKENS) {
printf("too many tokens on line\n");
return;
}
tokens[n++] = p;
p = strtok(NULL, " \t\n");
}
if (n == 0) {
return;
}
for (i = 0; i < numCommands; i++) {
if (strcmp(commands[i].name, tokens[0]) == 0) {
(*commands[i].cmdProc)(tokens, n);
return;
}
}
help();
}
 
 
static char *article(char firstLetterOfNoun) {
switch (firstLetterOfNoun) {
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
return "An";
default:
return "A";
}
}
 
 
static void interactiveException(int exception) {
char *what;
 
what = exceptionToString(exception);
printf("\n");
printf("NOTE: %s %s occurred while executing the command.\n",
article(*what), what);
printf(" This event will not alter the state of the CPU.\n");
}
 
 
void execCommand(char *line) {
MonitorState commandState;
 
if (saveState(&commandState)) {
/* initialization */
monitorReturn = &commandState;
doCommand(line);
} else {
/* an exception was thrown */
interactiveException((userContext.psw & PSW_PRIO_MASK) >> 16);
}
monitorReturn = NULL;
}
/monitor-xess/mmu.c
0,0 → 1,104
/*
* mmu.c -- memory and TLB access
*/
 
 
#include "common.h"
#include "stdarg.h"
#include "romlib.h"
#include "mmu.h"
#include "start.h"
 
 
static Word tlbIndex;
static Word tlbEntryHi;
static Word tlbEntryLo;
 
 
Word mmuReadWord(Word vAddr) {
return *(Word *)vAddr;
}
 
 
Half mmuReadHalf(Word vAddr) {
return *(Half *)vAddr;
}
 
 
Byte mmuReadByte(Word vAddr) {
return *(Byte *)vAddr;
}
 
 
void mmuWriteWord(Word vAddr, Word data) {
*(Word *)vAddr = data;
}
 
 
void mmuWriteHalf(Word vAddr, Half data) {
*(Half *)vAddr = data;
}
 
 
void mmuWriteByte(Word vAddr, Byte data) {
*(Byte *)vAddr = data;
}
 
 
Word mmuGetIndex(void) {
return tlbIndex;
}
 
 
void mmuSetIndex(Word value) {
tlbIndex = value;
}
 
 
Word mmuGetEntryHi(void) {
return tlbEntryHi;
}
 
 
void mmuSetEntryHi(Word value) {
tlbEntryHi = value;
}
 
 
Word mmuGetEntryLo(void) {
return tlbEntryLo;
}
 
 
void mmuSetEntryLo(Word value) {
tlbEntryLo = value;
}
 
 
TLB_Entry mmuGetTLB(int index) {
Word hi;
Word lo;
TLB_Entry result;
 
hi = getTLB_HI(index);
lo = getTLB_LO(index);
result.page = hi & PAGE_MASK;
result.frame = lo & PAGE_MASK;
result.write = (lo & TLB_WRITE) ? true : false;
result.valid = (lo & TLB_VALID) ? true : false;
return result;
}
 
 
void mmuSetTLB(int index, TLB_Entry tlbEntry) {
Word flags;
 
flags = 0;
if (tlbEntry.write) {
flags |= TLB_WRITE;
}
if (tlbEntry.valid) {
flags |= TLB_VALID;
}
setTLB(index, tlbEntry.page, tlbEntry.frame | flags);
}
/monitor-xess/instr.c
0,0 → 1,115
/*
* instr.c -- instruction encoding
*/
 
 
#include "common.h"
#include "stdarg.h"
#include "romlib.h"
#include "instr.h"
 
 
/*
* This is the ECO32 machine instruction set.
* The table below needs no particular order
* and may have gaps in the instruction encoding.
*/
Instr instrTbl[] = {
{ "add", FORMAT_RRY, OP_ADD },
{ "sub", FORMAT_RRY, OP_SUB },
{ "mul", FORMAT_RRY, OP_MUL },
{ "mulu", FORMAT_RRX, OP_MULU },
{ "div", FORMAT_RRY, OP_DIV },
{ "divu", FORMAT_RRX, OP_DIVU },
{ "rem", FORMAT_RRY, OP_REM },
{ "remu", FORMAT_RRX, OP_REMU },
{ "and", FORMAT_RRX, OP_AND },
{ "or", FORMAT_RRX, OP_OR },
{ "xor", FORMAT_RRX, OP_XOR },
{ "xnor", FORMAT_RRX, OP_XNOR },
{ "sll", FORMAT_RRX, OP_SLL },
{ "slr", FORMAT_RRX, OP_SLR },
{ "sar", FORMAT_RRX, OP_SAR },
{ "ldhi", FORMAT_RHH, OP_LDHI },
{ "beq", FORMAT_RRB, OP_BEQ },
{ "bne", FORMAT_RRB, OP_BNE },
{ "ble", FORMAT_RRB, OP_BLE },
{ "bleu", FORMAT_RRB, OP_BLEU },
{ "blt", FORMAT_RRB, OP_BLT },
{ "bltu", FORMAT_RRB, OP_BLTU },
{ "bge", FORMAT_RRB, OP_BGE },
{ "bgeu", FORMAT_RRB, OP_BGEU },
{ "bgt", FORMAT_RRB, OP_BGT },
{ "bgtu", FORMAT_RRB, OP_BGTU },
{ "j", FORMAT_J, OP_J },
{ "jr", FORMAT_JR, OP_JR },
{ "jal", FORMAT_J, OP_JAL },
{ "jalr", FORMAT_JR, OP_JALR },
{ "trap", FORMAT_N, OP_TRAP },
{ "rfx", FORMAT_N, OP_RFX },
{ "ldw", FORMAT_RRS, OP_LDW },
{ "ldh", FORMAT_RRS, OP_LDH },
{ "ldhu", FORMAT_RRS, OP_LDHU },
{ "ldb", FORMAT_RRS, OP_LDB },
{ "ldbu", FORMAT_RRS, OP_LDBU },
{ "stw", FORMAT_RRS, OP_STW },
{ "sth", FORMAT_RRS, OP_STH },
{ "stb", FORMAT_RRS, OP_STB },
{ "mvfs", FORMAT_RH, OP_MVFS },
{ "mvts", FORMAT_RH, OP_MVTS },
{ "tbs", FORMAT_N, OP_TBS },
{ "tbwr", FORMAT_N, OP_TBWR },
{ "tbri", FORMAT_N, OP_TBRI },
{ "tbwi", FORMAT_N, OP_TBWI }
};
 
 
Instr *instrCodeTbl[64];
 
 
static int instrCompare(const void *instr1, const void *instr2) {
return strcmp(((Instr *) instr1)->name, ((Instr *) instr2)->name);
}
 
 
void initInstrTable(void) {
int i;
 
/* first sort instruction table alphabetically */
qsort(instrTbl, sizeof(instrTbl)/sizeof(instrTbl[0]),
sizeof(instrTbl[0]), instrCompare);
/* then initialize instruction code table */
for (i = 0; i < 64; i++) {
instrCodeTbl[i] = NULL;
}
for (i = 0; i < sizeof(instrTbl)/sizeof(instrTbl[0]); i++) {
instrCodeTbl[instrTbl[i].opcode] = &instrTbl[i];
if (instrTbl[i].format == FORMAT_RRX ||
instrTbl[i].format == FORMAT_RRY) {
/* enter the immediate variant of this instruction also */
instrCodeTbl[instrTbl[i].opcode + 1] = &instrTbl[i];
}
}
}
 
 
Instr *lookupInstr(char *name) {
int lo, hi, tst;
int res;
 
lo = 0;
hi = sizeof(instrTbl) / sizeof(instrTbl[0]) - 1;
while (lo <= hi) {
tst = (lo + hi) / 2;
res = strcmp(instrTbl[tst].name, name);
if (res == 0) {
return &instrTbl[tst];
}
if (res < 0) {
lo = tst + 1;
} else {
hi = tst - 1;
}
}
return NULL;
}
/monitor-xess/serial.s
0,0 → 1,98
;
; serial.s -- the serial line interface
;
 
;***************************************************************
 
.set ser0base,0xF0300000 ; serial line 0 base address
.set ser1base,0xF0300010 ; serial line 1 base address
 
.export serinit ; initialize serial interface
 
.export ser0inchk ; line 0 input check
.export ser0in ; line 0 input
.export ser0outchk ; line 0 output check
.export ser0out ; line 0 output
 
.export ser1inchk ; line 1 input check
.export ser1in ; line 1 input
.export ser1outchk ; line 1 output check
.export ser1out ; line 1 output
 
;***************************************************************
 
.code
.align 4
 
serinit:
jr $31
 
;***************************************************************
 
.code
.align 4
 
ser0inchk:
add $8,$0,ser0base
ldw $2,$8,0
and $2,$2,1
jr $31
 
ser0in:
add $8,$0,ser0base
ser0in1:
ldw $9,$8,0
and $9,$9,1
beq $9,$0,ser0in1
ldw $2,$8,4
jr $31
 
ser0outchk:
add $8,$0,ser0base
ldw $2,$8,8
and $2,$2,1
jr $31
 
ser0out:
add $8,$0,ser0base
ser0out1:
ldw $9,$8,8
and $9,$9,1
beq $9,$0,ser0out1
stw $4,$8,12
jr $31
 
;***************************************************************
 
.code
.align 4
 
ser1inchk:
add $8,$0,ser1base
ldw $2,$8,0
and $2,$2,1
jr $31
 
ser1in:
add $8,$0,ser1base
ser1in1:
ldw $9,$8,0
and $9,$9,1
beq $9,$0,ser1in1
ldw $2,$8,4
jr $31
 
ser1outchk:
add $8,$0,ser1base
ldw $2,$8,8
and $2,$2,1
jr $31
 
ser1out:
add $8,$0,ser1base
ser1out1:
ldw $9,$8,8
and $9,$9,1
beq $9,$0,ser1out1
stw $4,$8,12
jr $31
/monitor-xess/start.h
0,0 → 1,57
/*
* start.h -- ECO32 ROM monitor startup and support routines
*/
 
 
#ifndef _START_H_
#define _START_H_
 
 
typedef struct {
Word reg[32]; /* general purpose registers */
Word psw; /* PSW */
Word tlbIndex; /* TLB index register */
Word tlbHi; /* TLB EntryHi register */
Word tlbLo; /* TLB EntryLo register */
} UserContext;
 
typedef struct {
Word r31; /* return address */
Word r29; /* stack pointer */
Word r16; /* local variable */
Word r17; /* local variable */
Word r18; /* local variable */
Word r19; /* local variable */
Word r20; /* local variable */
Word r21; /* local variable */
Word r22; /* local variable */
Word r23; /* local variable */
} MonitorState;
 
 
int cinchk(void);
int cin(void);
int coutchk(void);
void cout(char c);
 
int sinchk(void);
int sin(void);
int soutchk(void);
void sout(char c);
 
int dskcap(int dskno);
int dskio(int dskno, char cmd, int sct, Word addr, int nscts);
 
Word getTLB_HI(int index);
Word getTLB_LO(int index);
void setTLB(int index, Word entryHi, Word entryLo);
 
Bool saveState(MonitorState *msp);
 
extern MonitorState *monitorReturn;
extern UserContext userContext;
 
void resume(void);
 
 
#endif /* _START_H_ */
/monitor-xess/boot.c
0,0 → 1,47
/*
* boot.c -- bootstrap from disk
*/
 
 
#include "common.h"
#include "stdarg.h"
#include "romlib.h"
#include "boot.h"
#include "cpu.h"
#include "mmu.h"
#include "start.h"
 
 
void boot(int dskno) {
Word capacity;
Byte sig1, sig2;
 
capacity = dskcap(dskno);
if (capacity == 0) {
printf("Disk not found!\n");
return;
}
printf("Disk with 0x%08X sectors found, booting...\n", capacity);
if (dskio(dskno, 'r', 0, PHYS_BOOT, 1) != 0) {
printf("Disk error!\n");
return;
}
sig1 = mmuReadByte(VIRT_BOOT + 512 - 2);
sig2 = mmuReadByte(VIRT_BOOT + 512 - 1);
if (sig1 != 0x55 || sig2 != 0xAA) {
printf("MBR signature missing!\n");
return;
}
/*
* Boot convention:
* $16 disk number of boot disk
* $17 start sector number of disk or partition to boot
* $18 total number of sectors of disk or partition to boot
*/
cpuSetReg(16, dskno);
cpuSetReg(17, 0);
cpuSetReg(18, capacity);
cpuSetReg(29, TOS_BOOT);
cpuSetPC(VIRT_BOOT);
cpuRun();
}
/monitor-xess/mmu.h
0,0 → 1,45
/*
* mmu.h -- memory and TLB access
*/
 
 
#ifndef _MMU_H_
#define _MMU_H_
 
 
#define TLB_SHFT 5 /* log2 of number of TLB entries */
#define TLB_SIZE (1 << TLB_SHFT) /* total number of TLB entries */
#define TLB_MASK (TLB_SIZE - 1) /* mask for number of TLB entries */
#define TLB_FIXED 4 /* number of fixed TLB entries */
 
#define TLB_WRITE (1 << 1) /* write bit in EntryLo */
#define TLB_VALID (1 << 0) /* valid bit in EntryLo */
 
 
typedef struct {
Word page; /* 20 high-order bits of virtual address */
Word frame; /* 20 high-order bits of physical address */
Bool write; /* must be true to allow writing to the page */
Bool valid; /* must be true for the entry to be valid */
} TLB_Entry;
 
 
Word mmuReadWord(Word vAddr);
Half mmuReadHalf(Word vAddr);
Byte mmuReadByte(Word vAddr);
void mmuWriteWord(Word vAddr, Word data);
void mmuWriteHalf(Word vAddr, Half data);
void mmuWriteByte(Word vAddr, Byte data);
 
Word mmuGetIndex(void);
void mmuSetIndex(Word value);
Word mmuGetEntryHi(void);
void mmuSetEntryHi(Word value);
Word mmuGetEntryLo(void);
void mmuSetEntryLo(Word Value);
 
TLB_Entry mmuGetTLB(int index);
void mmuSetTLB(int index, TLB_Entry tlbEntry);
 
 
#endif /* _MMU_H_ */
/monitor-xess/instr.h
0,0 → 1,125
/*
* instr.h -- instruction encoding
*/
 
 
#ifndef _INSTR_H_
#define _INSTR_H_
 
 
#define FORMAT_N 0 /* no operands */
#define FORMAT_RH 1 /* one register and a half operand */
#define FORMAT_RHH 2 /* one register and a half operand */
/* ATTENTION: high-order 16 bits encoded */
#define FORMAT_RRH 3 /* two registers and a half operand */
#define FORMAT_RRS 4 /* two registers and a signed half operand */
#define FORMAT_RRR 5 /* three register operands */
#define FORMAT_RRX 6 /* either FORMAT_RRR or FORMAT_RRH */
#define FORMAT_RRY 7 /* either FORMAT_RRR or FORMAT_RRS */
#define FORMAT_RRB 8 /* two registers and a 16 bit signed
offset operand */
#define FORMAT_J 9 /* no registers and a 26 bit signed
offset operand */
#define FORMAT_JR 10 /* one register operand */
 
 
#define MASK(n) ((((Word) 1) << n) - 1)
#define SIGN(n) (((Word) 1) << (n - 1))
#define ZEXT16(x) (((Word) (x)) & MASK(16))
#define SEXT16(x) (((Word) (x)) & SIGN(16) ? \
(((Word) (x)) | ~MASK(16)) : \
(((Word) (x)) & MASK(16)))
#define SEXT26(x) (((Word) (x)) & SIGN(26) ? \
(((Word) (x)) | ~MASK(26)) : \
(((Word) (x)) & MASK(26)))
 
 
#define OP_ADD 0x00
#define OP_ADDI 0x01
#define OP_SUB 0x02
#define OP_SUBI 0x03
 
#define OP_MUL 0x04
#define OP_MULI 0x05
#define OP_MULU 0x06
#define OP_MULUI 0x07
#define OP_DIV 0x08
#define OP_DIVI 0x09
#define OP_DIVU 0x0A
#define OP_DIVUI 0x0B
#define OP_REM 0x0C
#define OP_REMI 0x0D
#define OP_REMU 0x0E
#define OP_REMUI 0x0F
 
#define OP_AND 0x10
#define OP_ANDI 0x11
#define OP_OR 0x12
#define OP_ORI 0x13
#define OP_XOR 0x14
#define OP_XORI 0x15
#define OP_XNOR 0x16
#define OP_XNORI 0x17
 
#define OP_SLL 0x18
#define OP_SLLI 0x19
#define OP_SLR 0x1A
#define OP_SLRI 0x1B
#define OP_SAR 0x1C
#define OP_SARI 0x1D
 
#define OP_LDHI 0x1F
 
#define OP_BEQ 0x20
#define OP_BNE 0x21
#define OP_BLE 0x22
#define OP_BLEU 0x23
#define OP_BLT 0x24
#define OP_BLTU 0x25
#define OP_BGE 0x26
#define OP_BGEU 0x27
#define OP_BGT 0x28
#define OP_BGTU 0x29
 
#define OP_J 0x2A
#define OP_JR 0x2B
#define OP_JAL 0x2C
#define OP_JALR 0x2D
 
#define OP_TRAP 0x2E
#define OP_RFX 0x2F
 
#define OP_LDW 0x30
#define OP_LDH 0x31
#define OP_LDHU 0x32
#define OP_LDB 0x33
#define OP_LDBU 0x34
 
#define OP_STW 0x35
#define OP_STH 0x36
#define OP_STB 0x37
 
#define OP_MVFS 0x38
#define OP_MVTS 0x39
#define OP_TBS 0x3A
#define OP_TBWR 0x3B
#define OP_TBRI 0x3C
#define OP_TBWI 0x3D
 
 
typedef struct {
char *name;
int format;
Byte opcode;
} Instr;
 
 
extern Instr instrTbl[];
extern Instr *instrCodeTbl[];
 
 
void initInstrTable(void);
Instr *lookupInstr(char *name);
 
 
#endif /* _INSTR_H_ */
/monitor-xess/boot.h
0,0 → 1,18
/*
* boot.h -- bootstrap from disk
*/
 
 
#ifndef _BOOT_H_
#define _BOOT_H_
 
 
#define PHYS_BOOT 0x00000000 /* where to load the bootstrap */
#define VIRT_BOOT 0xC0000000 /* where to start the bootstrap */
#define TOS_BOOT 0xC0001000 /* top of stack for bootstrap */
 
 
void boot(int dskno);
 
 
#endif /* _BOOT_H_ */
/monitor-xess/start.s
0,0 → 1,389
;
; start.s -- ECO32 ROM monitor startup and support routines
;
 
.set dmapaddr,0xC0000000 ; base of directly mapped addresses
.set stacktop,0xC0400000 ; monitor stack is at top of memory
 
.set PSW,0 ; reg # of PSW
.set TLB_INDEX,1 ; reg # of TLB Index
.set TLB_ENTRY_HI,2 ; reg # of TLB EntryHi
.set TLB_ENTRY_LO,3 ; reg # of TLB EntryLo
.set TLB_ENTRIES,32 ; number of TLB entries
 
.set USER_CONTEXT_SIZE,36*4 ; size of user context
 
;***************************************************************
 
.import _ecode
.import _edata
.import _ebss
 
.import kbdinit
.import kbdinchk
.import kbdin
 
.import dspinit
.import dspoutchk
.import dspout
 
.import serinit
.import ser0inchk
.import ser0in
.import ser0outchk
.import ser0out
 
.import sctcapctl
.import sctioctl
.import sctcapser
.import sctioser
 
.import main
 
.export _bcode
.export _bdata
.export _bbss
 
.export cinchk
.export cin
.export coutchk
.export cout
.export sinchk
.export sin
.export soutchk
.export sout
.export dskcap
.export dskio
 
.export getTLB_HI
.export getTLB_LO
.export setTLB
 
.export saveState
.export monitorReturn
 
.import userContext
.export resume
 
;***************************************************************
 
.code
_bcode:
 
.data
_bdata:
 
.bss
_bbss:
 
;***************************************************************
 
.code
.align 4
 
reset:
j start
 
interrupt:
j isr
 
userMiss:
j umsr
 
;***************************************************************
 
.code
.align 4
 
cinchk:
; j kbdinchk
j ser0inchk
 
cin:
; j kbdin
j ser0in
 
coutchk:
; j dspoutchk
j ser0outchk
 
cout:
; j dspout
j ser0out
 
sinchk:
j ser0inchk
 
sin:
j ser0in
 
soutchk:
j ser0outchk
 
sout:
j ser0out
 
dskcap:
j dcap
 
dskio:
j dio
 
;***************************************************************
 
.code
.align 4
 
start:
; force CPU into a defined state
mvts $0,PSW ; disable interrupts and user mode
 
; initialize TLB
mvts $0,TLB_ENTRY_LO ; invalidate all TLB entries
add $8,$0,dmapaddr ; by impossible virtual page number
add $9,$0,$0
add $10,$0,TLB_ENTRIES
tlbloop:
mvts $8,TLB_ENTRY_HI
mvts $9,TLB_INDEX
tbwi
add $8,$8,0x1000 ; all entries must be different
add $9,$9,1
bne $9,$10,tlbloop
 
; copy data segment
add $10,$0,_bdata ; lowest dst addr to be written to
add $8,$0,_edata ; one above the top dst addr
sub $9,$8,$10 ; $9 = size of data segment
add $9,$9,_ecode ; data is waiting right after code
j cpytest
cpyloop:
ldw $11,$9,0 ; src addr in $9
stw $11,$8,0 ; dst addr in $8
cpytest:
sub $8,$8,4 ; downward
sub $9,$9,4
bgeu $8,$10,cpyloop
 
; clear bss segment
add $8,$0,_bbss ; start with first word of bss
add $9,$0,_ebss ; this is one above the top
j clrtest
clrloop:
stw $0,$8,0 ; dst addr in $8
add $8,$8,4 ; upward
clrtest:
bltu $8,$9,clrloop
 
; now do some useful work
add $29,$0,stacktop ; setup monitor stack
; jal dspinit ; init display
; jal kbdinit ; init keyboard
jal serinit ; init serial interface
jal main ; enter command loop
 
; main should never return
j start ; just to be sure...
 
;***************************************************************
 
; Word getTLB_HI(int index)
getTLB_HI:
mvts $4,TLB_INDEX
tbri
mvfs $2,TLB_ENTRY_HI
jr $31
 
; Word getTLB_LO(int index)
getTLB_LO:
mvts $4,TLB_INDEX
tbri
mvfs $2,TLB_ENTRY_LO
jr $31
 
; void setTLB(int index, Word entryHi, Word entryLo)
setTLB:
mvts $4,TLB_INDEX
mvts $5,TLB_ENTRY_HI
mvts $6,TLB_ENTRY_LO
tbwi
jr $31
 
;***************************************************************
 
; int dskcap(int dskno)
dcap:
bne $4,$0,dcapser
j sctcapctl
dcapser:
j sctcapser
 
; int dskio(int dskno, char cmd, int sct, Word addr, int nscts)
dio:
bne $4,$0,dioser
add $4,$5,$0
add $5,$6,$0
add $6,$7,$0
ldw $7,$29,16
j sctioctl
dioser:
add $4,$5,$0
add $5,$6,$0
add $6,$7,$0
ldw $7,$29,16
j sctioser
 
;***************************************************************
 
.code
.align 4
 
; Bool saveState(MonitorState *msp)
; always return 'true' here
saveState:
stw $31,$4,0*4 ; return address
stw $29,$4,1*4 ; stack pointer
stw $16,$4,2*4 ; local variables
stw $17,$4,3*4
stw $18,$4,4*4
stw $19,$4,5*4
stw $20,$4,6*4
stw $21,$4,7*4
stw $22,$4,8*4
stw $23,$4,9*4
add $2,$0,1
jr $31
 
; load state when re-entering monitor
; this appears as if returning from saveState
; but the return value is 'false' here
loadState:
ldw $8,$0,monitorReturn
beq $8,$0,loadState ; fatal error: monitor state lost
ldw $31,$8,0*4 ; return address
ldw $29,$8,1*4 ; stack pointer
ldw $16,$8,2*4 ; local variables
ldw $17,$8,3*4
ldw $18,$8,4*4
ldw $19,$8,5*4
ldw $20,$8,6*4
ldw $21,$8,7*4
ldw $22,$8,8*4
ldw $23,$8,9*4
add $2,$0,0
jr $31
 
.bss
.align 4
 
; extern MonitorState *monitorReturn
monitorReturn:
.space 4
 
; extern UserContext userContext
userContext:
.space USER_CONTEXT_SIZE
 
;***************************************************************
 
.code
.align 4
 
; void resume(void)
; use userContext to load state
resume:
mvts $0,PSW
add $28,$0,userContext
.nosyn
ldw $8,$28,33*4 ; tlbIndex
mvts $8,TLB_INDEX
ldw $8,$28,34*4 ; tlbWntryHi
mvts $8,TLB_ENTRY_HI
ldw $8,$28,35*4 ; tlbEntryLo
mvts $8,TLB_ENTRY_LO
;ldw $0,$28,0*4 ; registers
ldw $1,$28,1*4
ldw $2,$28,2*4
ldw $3,$28,3*4
ldw $4,$28,4*4
ldw $5,$28,5*4
ldw $6,$28,6*4
ldw $7,$28,7*4
ldw $8,$28,8*4
ldw $9,$28,9*4
ldw $10,$28,10*4
ldw $11,$28,11*4
ldw $12,$28,12*4
ldw $13,$28,13*4
ldw $14,$28,14*4
ldw $15,$28,15*4
ldw $16,$28,16*4
ldw $17,$28,17*4
ldw $18,$28,18*4
ldw $19,$28,19*4
ldw $20,$28,20*4
ldw $21,$28,21*4
ldw $22,$28,22*4
ldw $23,$28,23*4
ldw $24,$28,24*4
ldw $25,$28,25*4
ldw $26,$28,26*4
ldw $27,$28,27*4
;ldw $28,$28,28*4
ldw $29,$28,29*4
ldw $30,$28,30*4
ldw $31,$28,31*4
ldw $28,$28,32*4 ; psw
mvts $28,PSW
rfx
.syn
 
; interrupt entry
; use userContext to store state
isr:
umsr:
.nosyn
ldhi $28,userContext
or $28,$28,userContext
stw $0,$28,0*4 ; registers
stw $1,$28,1*4
stw $2,$28,2*4
stw $3,$28,3*4
stw $4,$28,4*4
stw $5,$28,5*4
stw $6,$28,6*4
stw $7,$28,7*4
stw $8,$28,8*4
stw $9,$28,9*4
stw $10,$28,10*4
stw $11,$28,11*4
stw $12,$28,12*4
stw $13,$28,13*4
stw $14,$28,14*4
stw $15,$28,15*4
stw $16,$28,16*4
stw $17,$28,17*4
stw $18,$28,18*4
stw $19,$28,19*4
stw $20,$28,20*4
stw $21,$28,21*4
stw $22,$28,22*4
stw $23,$28,23*4
stw $24,$28,24*4
stw $25,$28,25*4
stw $26,$28,26*4
stw $27,$28,27*4
stw $28,$28,28*4
stw $29,$28,29*4
stw $30,$28,30*4
stw $31,$28,31*4
mvfs $8,PSW
stw $8,$28,32*4 ; psw
mvfs $8,TLB_INDEX
stw $8,$28,33*4 ; tlbIndex
mvfs $8,TLB_ENTRY_HI
stw $8,$28,34*4 ; tlbEntryHi
mvfs $8,TLB_ENTRY_LO
stw $8,$28,35*4 ; tlbEntryLo
.syn
j loadState
/monitor-xess/asm.c
0,0 → 1,370
/*
* asm.c -- assembler
*/
 
 
#include "common.h"
#include "stdarg.h"
#include "romlib.h"
#include "instr.h"
#include "asm.h"
 
 
#define MAX_TOKENS 10
 
 
static char *msgs[] = {
/* 0 */ "too many tokens on line",
/* 1 */ "empty line",
/* 2 */ "unknown instruction name",
/* 3 */ "unknown instruction format",
/* 4 */ "excess tokens on line",
/* 5 */ "too few operands",
/* 6 */ "illegal register",
/* 7 */ "illegal immediate value",
/* 8 */ "immediate value out of range",
/* 9 */ "target is not aligned",
/* 10 */ "target cannot be reached"
};
 
 
static Bool asmReg(char *token, int *reg) {
char *end;
 
if (*token != '$') {
return false;
}
*reg = strtoul(token + 1, &end, 10);
if (*end != '\0') {
return false;
}
if (*reg < 0 || *reg >= 32) {
return false;
}
return true;
}
 
 
static Bool asmNum(char *token, unsigned int *val) {
char *end;
 
*val = strtoul(token, &end, 16);
return *end == '\0';
}
 
 
char *asmInstr(char *line, Word addr, Word *instrPtr) {
char *tokens[MAX_TOKENS];
int n;
char *p;
Instr *instr;
Word result;
int r1, r2, r3;
unsigned int uimm;
signed int simm;
 
/* separate tokens */
n = 0;
p = strtok(line, " \t\n,");
while (p != NULL) {
if (n == MAX_TOKENS) {
return msgs[0];
}
tokens[n++] = p;
p = strtok(NULL, " \t\n,");
}
if (n == 0) {
return msgs[1];
}
/* lookup mnemonic */
instr = lookupInstr(tokens[0]);
if (instr == NULL) {
return msgs[2];
}
/* do processing according to format */
switch (instr->format) {
case FORMAT_N:
/* no operands (but may get a constant operand) */
if (n > 2) {
return msgs[4];
}
if (n < 1) {
return msgs[5];
}
if (n == 2) {
if (!asmNum(tokens[1], &uimm)) {
return msgs[7];
}
} else {
uimm = 0;
}
result = ((Word) instr->opcode << 26) |
(uimm & MASK(26));
break;
case FORMAT_RH:
/* one register and a half operand */
if (n > 3) {
return msgs[4];
}
if (n < 3) {
return msgs[5];
}
if (!asmReg(tokens[1], &r1)) {
return msgs[6];
}
if (!asmNum(tokens[2], &uimm)) {
return msgs[7];
}
if (uimm >= (unsigned) (1 << 16)) {
return msgs[8];
}
result = ((Word) instr->opcode << 26) |
(r1 << 16) |
(uimm & MASK(16));
break;
case FORMAT_RHH:
/* one register and a half operand */
/* ATTENTION: high-order 16 bits encoded */
if (n > 3) {
return msgs[4];
}
if (n < 3) {
return msgs[5];
}
if (!asmReg(tokens[1], &r1)) {
return msgs[6];
}
if (!asmNum(tokens[2], &uimm)) {
return msgs[7];
}
uimm >>= 16;
if (uimm >= (unsigned) (1 << 16)) {
return msgs[8];
}
result = ((Word) instr->opcode << 26) |
(r1 << 16) |
(uimm & MASK(16));
break;
case FORMAT_RRH:
/* two registers and a half operand */
if (n > 4) {
return msgs[4];
}
if (n < 4) {
return msgs[5];
}
if (!asmReg(tokens[1], &r1)) {
return msgs[6];
}
if (!asmReg(tokens[2], &r2)) {
return msgs[6];
}
if (!asmNum(tokens[3], &uimm)) {
return msgs[7];
}
if (uimm >= (unsigned) (1 << 16)) {
return msgs[8];
}
result = ((Word) instr->opcode << 26) |
(r2 << 21) |
(r1 << 16) |
(uimm & MASK(16));
break;
case FORMAT_RRS:
/* two registers and a signed half operand */
if (n > 4) {
return msgs[4];
}
if (n < 4) {
return msgs[5];
}
if (!asmReg(tokens[1], &r1)) {
return msgs[6];
}
if (!asmReg(tokens[2], &r2)) {
return msgs[6];
}
if (!asmNum(tokens[3], (unsigned int *) &simm)) {
return msgs[7];
}
if (simm >= (signed) (1 << 15) ||
simm < - (signed) (1 << 15)) {
return msgs[8];
}
result = ((Word) instr->opcode << 26) |
(r2 << 21) |
(r1 << 16) |
(simm & MASK(16));
break;
case FORMAT_RRR:
/* three register operands */
if (n > 4) {
return msgs[4];
}
if (n < 4) {
return msgs[5];
}
if (!asmReg(tokens[1], &r1)) {
return msgs[6];
}
if (!asmReg(tokens[2], &r2)) {
return msgs[6];
}
if (!asmReg(tokens[3], &r3)) {
return msgs[6];
}
result = ((Word) instr->opcode << 26) |
(r2 << 21) |
(r3 << 16) |
(r1 << 11);
break;
case FORMAT_RRX:
/* either FORMAT_RRR or FORMAT_RRH */
if (n > 4) {
return msgs[4];
}
if (n < 4) {
return msgs[5];
}
if (!asmReg(tokens[1], &r1)) {
return msgs[6];
}
if (!asmReg(tokens[2], &r2)) {
return msgs[6];
}
if (*tokens[3] == '$') {
/* FORMAT_RRR */
if (!asmReg(tokens[3], &r3)) {
return msgs[6];
}
result = ((Word) instr->opcode << 26) |
(r2 << 21) |
(r3 << 16) |
(r1 << 11);
} else {
/* FORMAT_RRH */
if (!asmNum(tokens[3], &uimm)) {
return msgs[7];
}
if (uimm >= (unsigned) (1 << 16)) {
return msgs[8];
}
result = (((Word) instr->opcode + 1) << 26) |
(r2 << 21) |
(r1 << 16) |
(uimm & MASK(16));
}
break;
case FORMAT_RRY:
/* either FORMAT_RRR or FORMAT_RRS */
if (n > 4) {
return msgs[4];
}
if (n < 4) {
return msgs[5];
}
if (!asmReg(tokens[1], &r1)) {
return msgs[6];
}
if (!asmReg(tokens[2], &r2)) {
return msgs[6];
}
if (*tokens[3] == '$') {
/* FORMAT_RRR */
if (!asmReg(tokens[3], &r3)) {
return msgs[6];
}
result = ((Word) instr->opcode << 26) |
(r2 << 21) |
(r3 << 16) |
(r1 << 11);
} else {
/* FORMAT_RRS */
if (!asmNum(tokens[3], (unsigned int *) &simm)) {
return msgs[7];
}
if (simm >= (signed) (1 << 15) ||
simm < - (signed) (1 << 15)) {
return msgs[8];
}
result = (((Word) instr->opcode + 1) << 26) |
(r2 << 21) |
(r1 << 16) |
(simm & MASK(16));
}
break;
case FORMAT_RRB:
/* two registers and a 16 bit signed offset operand */
if (n > 4) {
return msgs[4];
}
if (n < 4) {
return msgs[5];
}
if (!asmReg(tokens[1], &r1)) {
return msgs[6];
}
if (!asmReg(tokens[2], &r2)) {
return msgs[6];
}
if (!asmNum(tokens[3], (unsigned int *) &simm)) {
return msgs[7];
}
if ((simm & 0x00000003) != 0) {
return msgs[9];
}
simm -= addr + 4;
simm /= 4;
if (simm >= (signed) (1 << 15) ||
simm < - (signed) (1 << 15)) {
return msgs[10];
}
result = ((Word) instr->opcode << 26) |
(r1 << 21) |
(r2 << 16) |
(simm & MASK(16));
break;
case FORMAT_J:
/* no registers and a 26 bit signed offset operand */
if (n > 2) {
return msgs[4];
}
if (n < 2) {
return msgs[5];
}
if (!asmNum(tokens[1], (unsigned int *) &simm)) {
return msgs[7];
}
if ((simm & 0x00000003) != 0) {
return msgs[9];
}
simm -= addr + 4;
simm /= 4;
if (simm >= (signed) (1 << 25) ||
simm < - (signed) (1 << 25)) {
return msgs[10];
}
result = ((Word) instr->opcode << 26) |
(simm & MASK(26));
break;
case FORMAT_JR:
/* one register operand */
if (n > 2) {
return msgs[4];
}
if (n < 2) {
return msgs[5];
}
if (!asmReg(tokens[1], &r1)) {
return msgs[6];
}
result = ((Word) instr->opcode << 26) |
(r1 << 21);
break;
default:
return msgs[3];
}
/* line successfully assembled */
*instrPtr = result;
return NULL;
}
/monitor-xess/keyboard.s
0,0 → 1,140
;
; keyboard.s -- a PC keyboard as input device
;
 
;***************************************************************
 
.set kbdbase,0xF0200000 ; keyboard base address
 
; .import cout
; .import byteout
 
.import xltbl1 ; kbd translation table 1
.import xltbl2 ; kbd translation table 2
 
.export kbdinit ; initialize keyboard
.export kbdinchk ; check if input available
.export kbdin ; do keyboard input
 
;***************************************************************
 
.code
.align 4
 
kbdinit:
jr $31
 
kbdinchk:
add $8,$0,kbdbase
ldw $2,$8,0
and $2,$2,1
jr $31
 
kbdin:
sub $29,$29,12
stw $31,$29,8
stw $16,$29,4
stw $17,$29,0
kbdin0:
jal kbdinp
add $16,$2,$0 ; key1 in $16
add $8,$0,0xF0
bne $16,$8,kbdin2
kbdin1:
jal kbdinp
j kbdin0
kbdin2:
jal kbdinp
add $17,$2,$0 ; key2 in $17
beq $17,$16,kbdin2
add $8,$0,0xF0
beq $17,$8,kbdin3
j kbdin5
kbdin3:
jal kbdinp
bne $2,$16,kbdin2
kbdin4:
add $4,$16,$0
add $5,$0,xltbl1
jal xlat
j kbdx
kbdin5:
jal kbdinp
add $8,$0,0xF0
bne $2,$8,kbdin5
kbdin6:
jal kbdinp
beq $2,$16,kbdin7
beq $2,$17,kbdin9
j kbdin5
kbdin7:
jal kbdinp
add $8,$0,0xF0
bne $2,$8,kbdin7
kbdin8:
jal kbdinp
bne $2,$17,kbdin7
j kbdin11
kbdin9:
jal kbdinp
add $8,$0,0xF0
bne $2,$8,kbdin9
kbdin10:
jal kbdinp
bne $2,$16,kbdin9
j kbdin11
kbdin11:
add $8,$0,0x12 ; left shift key
beq $16,$8,kbdin12
add $8,$0,0x59 ; right shift key
bne $16,$8,kbdin13
kbdin12:
add $4,$17,$0
add $5,$0,xltbl2
jal xlat
j kbdx
kbdin13:
add $4,$16,$0
add $5,$0,xltbl1
jal xlat
j kbdx
kbdx:
ldw $17,$29,0
ldw $16,$29,4
ldw $31,$29,8
add $29,$29,12
jr $31
 
kbdinp:
add $8,$0,kbdbase
kbdinp1:
ldw $9,$8,0
and $9,$9,1
beq $9,$0,kbdinp1
ldw $2,$8,4
add $9,$0,0xE0
beq $2,$9,kbdinp1
add $9,$0,0xE1
beq $2,$9,kbdinp1
jr $31
 
xlat:
sub $29,$29,8
stw $31,$29,4
stw $16,$29,0
and $16,$4,0xFF
add $8,$16,$5
ldbu $2,$8,0
bne $2,$0,xlat1
; add $4,$0,'<'
; jal cout
; add $4,$16,$0
; jal byteout
; add $4,$0,'>'
; jal cout
add $2,$16,$0
xlat1:
ldw $16,$29,0
ldw $31,$29,4
add $29,$29,8
jr $31
/monitor-xess/disasm.c
0,0 → 1,138
/*
* disasm.c -- disassembler
*/
 
 
#include "common.h"
#include "stdarg.h"
#include "romlib.h"
#include "instr.h"
#include "disasm.h"
 
 
static char instrBuffer[100];
 
 
static void disasmN(char *opName, Word immed) {
if (immed == 0) {
sprintf(instrBuffer, "%-7s", opName);
} else {
sprintf(instrBuffer, "%-7s %08X", opName, immed);
}
}
 
 
static void disasmRH(char *opName, int r1, Half immed) {
sprintf(instrBuffer, "%-7s $%d,%04X", opName, r1, immed);
}
 
 
static void disasmRHH(char *opName, int r1, Half immed) {
sprintf(instrBuffer, "%-7s $%d,%08X", opName, r1, (Word) immed << 16);
}
 
 
static void disasmRRH(char *opName, int r1, int r2, Half immed) {
sprintf(instrBuffer, "%-7s $%d,$%d,%04X", opName, r1, r2, immed);
}
 
 
static void disasmRRS(char *opName, int r1, int r2, Half immed) {
sprintf(instrBuffer, "%-7s $%d,$%d,%s%04X", opName, r1, r2,
SIGN(16) & immed ? "-" : "+",
SIGN(16) & immed ? -(signed)SEXT16(immed) : SEXT16(immed));
}
 
 
static void disasmRRR(char *opName, int r1, int r2, int r3) {
sprintf(instrBuffer, "%-7s $%d,$%d,$%d", opName, r1, r2, r3);
}
 
 
static void disasmRRB(char *opName, int r1, int r2, Half offset, Word locus) {
sprintf(instrBuffer, "%-7s $%d,$%d,%08X", opName,
r1, r2, (locus + 4) + (SEXT16(offset) << 2));
}
 
 
static void disasmJ(char *opName, Word offset, Word locus) {
sprintf(instrBuffer, "%-7s %08X", opName,
(locus + 4) + (SEXT26(offset) << 2));
}
 
 
static void disasmJR(char *opName, int r1) {
sprintf(instrBuffer, "%-7s $%d", opName, r1);
}
 
 
char *disasm(Word instr, Word locus) {
Byte opcode;
Instr *ip;
 
opcode = (instr >> 26) & 0x3F;
ip = instrCodeTbl[opcode];
if (ip == NULL) {
disasmN("???", 0);
} else {
switch (ip->format) {
case FORMAT_N:
disasmN(ip->name, instr & 0x03FFFFFF);
break;
case FORMAT_RH:
disasmRH(ip->name, (instr >> 16) & 0x1F, instr & 0x0000FFFF);
break;
case FORMAT_RHH:
disasmRHH(ip->name, (instr >> 16) & 0x1F, instr & 0x0000FFFF);
break;
case FORMAT_RRH:
disasmRRH(ip->name, (instr >> 16) & 0x1F,
(instr >> 21) & 0x1F, instr & 0x0000FFFF);
break;
case FORMAT_RRS:
disasmRRS(ip->name, (instr >> 16) & 0x1F,
(instr >> 21) & 0x1F, instr & 0x0000FFFF);
break;
case FORMAT_RRR:
disasmRRR(ip->name, (instr >> 11) & 0x1F,
(instr >> 21) & 0x1F, (instr >> 16) & 0x1F);
break;
case FORMAT_RRX:
if ((opcode & 1) == 0) {
/* the FORMAT_RRR variant */
disasmRRR(ip->name, (instr >> 11) & 0x1F,
(instr >> 21) & 0x1F, (instr >> 16) & 0x1F);
} else {
/* the FORMAT_RRH variant */
disasmRRH(ip->name, (instr >> 16) & 0x1F,
(instr >> 21) & 0x1F, instr & 0x0000FFFF);
}
break;
case FORMAT_RRY:
if ((opcode & 1) == 0) {
/* the FORMAT_RRR variant */
disasmRRR(ip->name, (instr >> 11) & 0x1F,
(instr >> 21) & 0x1F, (instr >> 16) & 0x1F);
} else {
/* the FORMAT_RRS variant */
disasmRRS(ip->name, (instr >> 16) & 0x1F,
(instr >> 21) & 0x1F, instr & 0x0000FFFF);
}
break;
case FORMAT_RRB:
disasmRRB(ip->name, (instr >> 21) & 0x1F,
(instr >> 16) & 0x1F, instr & 0x0000FFFF, locus);
break;
case FORMAT_J:
disasmJ(ip->name, instr & 0x03FFFFFF, locus);
break;
case FORMAT_JR:
disasmJR(ip->name, (instr >> 21) & 0x1F);
break;
default:
printf("illegal entry in instruction table\n");
break;
}
}
return instrBuffer;
}
/monitor-xess/sctio-ctl.s
0,0 → 1,133
;
; sctio-ctl.s -- disk sector I/O for disk made available by disk controller
;
 
;***************************************************************
 
.set dskbase,0xF0400000 ; disk base address
.set dskctrl,0 ; control register
.set dskcnt,4 ; count register
.set dsksct,8 ; sector register
.set dskcap,12 ; capacity register
.set dskbuf,0x00080000 ; disk buffer
 
.set ctrlstrt,0x01 ; start bit
.set ctrlien,0x02 ; interrupt enable bit
.set ctrlwrt,0x04 ; write bit
.set ctrlerr,0x08 ; error bit
.set ctrldone,0x10 ; done bit
.set ctrlrdy,0x20 ; ready bit
 
.set sctsize,512 ; sector size in bytes
 
.set retries,1000000 ; retries to get disk ready
 
.export sctcapctl ; determine disk capacity
.export sctioctl ; do disk I/O
 
;***************************************************************
 
.code
.align 4
 
sctcapctl:
add $8,$0,retries ; set retry count
add $9,$0,dskbase
sctcap1:
ldw $10,$9,dskctrl
and $10,$10,ctrlrdy ; ready?
bne $10,$0,sctcapok ; yes - jump
sub $8,$8,1
bne $8,$0,sctcap1 ; try again
add $2,$0,0 ; no disk found
j sctcapx
sctcapok:
ldw $2,$9,dskcap ; get disk capacity
sctcapx:
jr $31
 
sctioctl:
sub $29,$29,24
stw $31,$29,20
stw $16,$29,16
stw $17,$29,12
stw $18,$29,8
stw $19,$29,4
stw $20,$29,0
add $16,$4,$0 ; command
add $17,$5,$0 ; sector number
add $18,$6,0xC0000000 ; memory address, virtualized
add $19,$7,$0 ; number of sectors
 
add $8,$0,'r'
beq $16,$8,sctrd
add $8,$0,'w'
beq $16,$8,sctwr
add $2,$0,0xFF ; illegal command
j sctx
 
sctrd:
add $2,$0,$0 ; return ok
beq $19,$0,sctx ; if no (more) sectors
add $8,$0,dskbase
add $9,$0,1
stw $9,$8,dskcnt ; number of sectors
stw $17,$8,dsksct ; sector number on disk
add $9,$0,ctrlstrt
stw $9,$8,dskctrl ; start command
sctrd1:
ldw $2,$8,dskctrl
and $9,$2,ctrldone ; done?
beq $9,$0,sctrd1 ; no - wait
and $9,$2,ctrlerr ; error?
bne $9,$0,sctx ; yes - leave
add $8,$0,dskbase + dskbuf ; transfer data
add $9,$0,sctsize
sctrd2:
ldw $10,$8,0 ; from disk buffer
stw $10,$18,0 ; to memory
add $8,$8,4
add $18,$18,4
sub $9,$9,4
bne $9,$0,sctrd2
add $17,$17,1 ; increment sector number
sub $19,$19,1 ; decrement number of sectors
j sctrd ; next sector
 
sctwr:
add $2,$0,$0 ; return ok
beq $19,$0,sctx ; if no (more) sectors
add $8,$0,dskbase + dskbuf ; transfer data
add $9,$0,sctsize
sctwr1:
ldw $10,$18,0 ; from memory
stw $10,$8,0 ; to disk buffer
add $18,$18,4
add $8,$8,4
sub $9,$9,4
bne $9,$0,sctwr1
add $8,$0,dskbase
add $9,$0,1
stw $9,$8,dskcnt ; number of sectors
stw $17,$8,dsksct ; sector number on disk
add $9,$0,ctrlwrt | ctrlstrt
stw $9,$8,dskctrl ; start command
sctwr2:
ldw $2,$8,dskctrl
and $9,$2,ctrldone ; done?
beq $9,$0,sctwr2 ; no - wait
and $9,$2,ctrlerr ; error?
bne $9,$0,sctx ; yes - leave
add $17,$17,1 ; increment sector number
sub $19,$19,1 ; decrement number of sectors
j sctwr ; next sector
 
sctx:
ldw $20,$29,0
ldw $19,$29,4
ldw $18,$29,8
ldw $17,$29,12
ldw $16,$29,16
ldw $31,$29,20
add $29,$29,24
jr $31
/monitor-xess/command.h
0,0 → 1,13
/*
* command.h -- command interpreter
*/
 
 
#ifndef _COMMAND_H_
#define _COMMAND_H_
 
 
void execCommand(char *line);
 
 
#endif /* _COMMAND_H_ */
/monitor-xess/main.c
0,0 → 1,27
/*
* main.c -- the main program
*/
 
 
#include "common.h"
#include "stdarg.h"
#include "romlib.h"
#include "command.h"
#include "getline.h"
#include "instr.h"
#include "cpu.h"
 
 
int main(void) {
char *line;
 
printf("\n\nECO32 Machine Monitor 1.0\n\n");
initInstrTable();
cpuSetPC(0xC0000000);
while (1) {
line = getLine("ECO32 > ");
addHist(line);
execCommand(line);
}
return 0;
}
/monitor-xess/romlib.c
0,0 → 1,636
/*
* romlib.c -- the ROM library
*/
 
 
#include "common.h"
#include "stdarg.h"
#include "romlib.h"
#include "start.h"
 
 
/**************************************************************/
 
 
/*
* This is only for debugging.
* Place a breakpoint at the very beginning of this routine
* and call it wherever you want to break execution.
*/
void debugBreak(void) {
}
 
 
/**************************************************************/
 
 
/*
* Count the length of a string (without terminating null character).
*/
int strlen(const char *s) {
const char *p;
 
p = s;
while (*p != '\0') {
p++;
}
return p - s;
}
 
 
/*
* Compare two strings.
* Return a number < 0, = 0, or > 0 iff the first string is less
* than, equal to, or greater than the second one, respectively.
*/
int strcmp(const char *s, const char *t) {
while (*s == *t) {
if (*s == '\0') {
return 0;
}
s++;
t++;
}
return *s - *t;
}
 
 
/*
* Copy string t to string s (includes terminating null character).
*/
char *strcpy(char *s, const char *t) {
char *p;
 
p = s;
while ((*p = *t) != '\0') {
p++;
t++;
}
return s;
}
 
 
/*
* Append string t to string s.
*/
char *strcat(char *s, const char *t) {
char *p;
 
p = s;
while (*p != '\0') {
p++;
}
while ((*p = *t) != '\0') {
p++;
t++;
}
return s;
}
 
 
/*
* Locate character c in string s.
*/
char *strchr(const char *s, char c) {
while (*s != c) {
if (*s == '\0') {
return NULL;
}
s++;
}
return (char *) s;
}
 
 
/*
* Extract the next token from the string s, delimited
* by any character from the delimiter string t.
*/
char *strtok(char *s, const char *t) {
static char *p;
char *q;
 
if (s != NULL) {
p = s;
} else {
p++;
}
while (*p != '\0' && strchr(t, *p) != NULL) {
p++;
}
if (*p == '\0') {
return NULL;
}
q = p++;
while (*p != '\0' && strchr(t, *p) == NULL) {
p++;
}
if (*p != '\0') {
*p = '\0';
} else {
p--;
}
return q;
}
 
 
/**************************************************************/
 
 
/*
* Determine if a character is 'white space'.
*/
static Bool isspace(char c) {
Bool res;
 
switch (c) {
case ' ':
case '\f':
case '\n':
case '\r':
case '\t':
case '\v':
res = true;
break;
default:
res = false;
break;
}
return res;
}
 
 
/*
* Check for valid digit, and convert to value.
*/
static Bool checkDigit(char c, int base, int *value) {
if (c >= '0' && c <= '9') {
*value = c - '0';
} else
if (c >= 'A' && c <= 'Z') {
*value = c - 'A' + 10;
} else
if (c >= 'a' && c <= 'z') {
*value = c - 'a' + 10;
} else {
return false;
}
return *value < base;
}
 
 
/*
* Convert initial part of string to unsigned long integer.
*/
unsigned long strtoul(const char *s, char **endp, int base) {
unsigned long res;
int sign;
int digit;
 
res = 0;
while (isspace(*s)) {
s++;
}
if (*s == '+') {
sign = 1;
s++;
} else
if (*s == '-') {
sign = -1;
s++;
} else {
sign = 1;
}
if (base == 0 || base == 16) {
if (*s == '0' &&
(*(s + 1) == 'x' || *(s + 1) == 'X')) {
/* base is 16 */
s += 2;
base = 16;
} else {
/* base is 0 or 16, but number does not start with "0x" */
if (base == 0) {
if (*s == '0') {
s++;
base = 8;
} else {
base = 10;
}
} else {
/* take base as is */
}
}
} else {
/* take base as is */
}
while (checkDigit(*s, base, &digit)) {
res *= base;
res += digit;
s++;
}
if (endp != NULL) {
*endp = (char *) s;
}
return sign * res;
}
 
 
/**************************************************************/
 
 
/*
* Exchange two array items of a given size.
*/
static void xchg(char *p, char *q, int size) {
char t;
 
while (size--) {
t = *p;
*p++ = *q;
*q++ = t;
}
}
 
 
/*
* This is a recursive version of quicksort.
*/
static void sort(char *l, char *r, int size,
int (*cmp)(const void *, const void *)) {
char *i;
char *j;
char *x;
 
i = l;
j = r;
x = l + (((r - l) / size) / 2) * size;
do {
while (cmp(i, x) < 0) {
i += size;
}
while (cmp(x, j) < 0) {
j -= size;
}
if (i <= j) {
/* exchange array elements i and j */
/* attention: update x if it is one of these */
if (x == i) {
x = j;
} else
if (x == j) {
x = i;
}
xchg(i, j, size);
i += size;
j -= size;
}
} while (i <= j);
if (l < j) {
sort(l, j, size, cmp);
}
if (i < r) {
sort(i, r, size, cmp);
}
}
 
 
/*
* External interface for the quicksort algorithm.
*/
void qsort(void *base, int n, int size,
int (*cmp)(const void *, const void*)) {
sort((char *) base, (char *) base + (n - 1) * size, size, cmp);
}
 
 
/**************************************************************/
 
 
/*
* Input a character from the console.
*/
char getchar(void) {
return cin();
}
 
 
/*
* Output a character on the console.
* Replace LF by CR/LF.
*/
void putchar(char c) {
if (c == '\n') {
cout('\r');
}
cout(c);
}
 
 
/*
* Output a string on the console.
* Replace LF by CR/LF.
*/
void puts(const char *s) {
while (*s != '\0') {
putchar(*s);
s++;
}
}
 
 
/**************************************************************/
 
 
/*
* Count the number of characters needed to represent
* a given number in base 10.
*/
static 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.
*/
static void *printn(void *(*emit)(void *, char), void *arg,
int *nchar, long n) {
long a;
 
if (n < 0) {
arg = emit(arg, '-');
(*nchar)++;
n = -n;
}
a = n / 10;
if (a != 0) {
arg = printn(emit, arg, nchar, a);
}
arg = emit(arg, n % 10 + '0');
(*nchar)++;
return arg;
}
 
 
/*
* Count the number of characters needed to represent
* a given number in a given base.
*/
static 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.
*/
static void *printu(void *(*emit)(void *, char), void *arg,
int *nchar, unsigned long n, unsigned long b,
Bool upperCase) {
unsigned long a;
 
a = n / b;
if (a != 0) {
arg = printu(emit, arg, nchar, a, b, upperCase);
}
if (upperCase) {
arg = emit(arg, "0123456789ABCDEF"[n % b]);
(*nchar)++;
} else {
arg = emit(arg, "0123456789abcdef"[n % b]);
(*nchar)++;
}
return arg;
}
 
 
/*
* Output a number of filler characters.
*/
static void *fill(void *(*emit)(void *, char), void *arg,
int *nchar, int numFillers, char filler) {
while (numFillers-- > 0) {
arg = emit(arg, filler);
(*nchar)++;
}
return arg;
}
 
 
/*
* This function does the real work of formatted printing.
*/
static int doPrintf(void *(*emit)(void *, char), void *arg,
const char *fmt, va_list ap) {
int nchar;
char c;
int n;
long ln;
unsigned int u;
unsigned long lu;
char *s;
Bool negFlag;
char filler;
int width, count;
 
nchar = 0;
while (1) {
while ((c = *fmt++) != '%') {
if (c == '\0') {
return nchar;
}
arg = emit(arg, c);
nchar++;
}
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) {
arg = fill(emit, arg, &nchar, width - count, filler);
}
arg = printn(emit, arg, &nchar, n);
if (width > 0 && negFlag) {
arg = fill(emit, arg, &nchar, 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) {
arg = fill(emit, arg, &nchar, width - count, filler);
}
arg = printu(emit, arg, &nchar, u,
c == 'o' ? 8 : ((c == 'x' || c == 'X') ? 16 : 10),
c == 'X');
if (width > 0 && negFlag) {
arg = fill(emit, arg, &nchar, width - count, filler);
}
} else
if (c == 'l') {
c = *fmt++;
if (c == 'd') {
ln = va_arg(ap, long);
count = countPrintn(ln);
if (width > 0 && !negFlag) {
arg = fill(emit, arg, &nchar, width - count, filler);
}
arg = printn(emit, arg, &nchar, ln);
if (width > 0 && negFlag) {
arg = fill(emit, arg, &nchar, 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) {
arg = fill(emit, arg, &nchar, width - count, filler);
}
arg = printu(emit, arg, &nchar, lu,
c == 'o' ? 8 : ((c == 'x' || c == 'X') ? 16 : 10),
c == 'X');
if (width > 0 && negFlag) {
arg = fill(emit, arg, &nchar, width - count, filler);
}
} else {
arg = emit(arg, 'l');
nchar++;
arg = emit(arg, c);
nchar++;
}
} else
if (c == 's') {
s = va_arg(ap, char *);
count = strlen(s);
if (width > 0 && !negFlag) {
arg = fill(emit, arg, &nchar, width - count, filler);
}
while ((c = *s++) != '\0') {
arg = emit(arg, c);
nchar++;
}
if (width > 0 && negFlag) {
arg = fill(emit, arg, &nchar, width - count, filler);
}
} else
if (c == 'c') {
c = va_arg(ap, char);
arg = emit(arg, c);
nchar++;
} else {
arg = emit(arg, c);
nchar++;
}
}
/* never reached */
return 0;
}
 
 
/*
* Emit a character to the console.
*/
static void *emitToConsole(void *dummy, char c) {
putchar(c);
return dummy;
}
 
 
/*
* Formatted output with a variable argument list.
*/
int vprintf(const char *fmt, va_list ap) {
int n;
 
n = doPrintf(emitToConsole, NULL, fmt, ap);
return n;
}
 
 
/*
* Formatted output.
*/
int printf(const char *fmt, ...) {
int n;
va_list ap;
 
va_start(ap, fmt);
n = vprintf(fmt, ap);
va_end(ap);
return n;
}
 
 
/*
* Emit a character to a buffer.
*/
static void *emitToBuffer(void *bufptr, char c) {
*(char *)bufptr = c;
return (char *) bufptr + 1;
}
 
 
/*
* Formatted output into a buffer with a variable argument list.
*/
int vsprintf(char *s, const char *fmt, va_list ap) {
int n;
 
n = doPrintf(emitToBuffer, s, fmt, ap);
s[n] = '\0';
return n;
}
 
 
/*
* Formatted output into a buffer.
*/
int sprintf(char *s, const char *fmt, ...) {
int n;
va_list ap;
 
va_start(ap, fmt);
n = vsprintf(s, fmt, ap);
va_end(ap);
return n;
}
/monitor-xess/display.s
0,0 → 1,225
;
; display.s -- a memory-mapped alphanumerical display
;
 
;***************************************************************
 
.set dspbase,0xF0100000 ; display base address
 
.export dspinit ; initialize display
.export dspoutchk ; check for output possible
.export dspout ; do display output
 
;***************************************************************
 
.code
.align 4
 
; initialize display
dspinit:
sub $29,$29,4
stw $31,$29,0
jal clrscr
add $8,$0,scrrow
stw $0,$8,0
add $8,$0,scrcol
stw $0,$8,0
jal calcp
jal stcrs
ldw $31,$29,0
add $29,$29,4
jr $31
 
; check if a character can be written
dspoutchk:
add $2,$0,1
jr $31
 
; output a character on the display
dspout:
sub $29,$29,8
stw $31,$29,4
stw $16,$29,0
and $16,$4,0xFF
jal rmcrs
add $8,$0,' '
bltu $16,$8,dspout2
add $8,$0,scrptr
ldw $9,$8,0
or $16,$16,0x07 << 8
stw $16,$9,0
add $9,$9,4
stw $9,$8,0
add $8,$0,scrcol
ldw $9,$8,0
add $9,$9,1
stw $9,$8,0
add $10,$0,80
bne $9,$10,dspout1
jal docr
jal dolf
dspout1:
jal stcrs
ldw $16,$29,0
ldw $31,$29,4
add $29,$29,8
jr $31
 
dspout2:
add $8,$0,0x0D
bne $16,$8,dspout3
jal docr
j dspout1
 
dspout3:
add $8,$0,0x0A
bne $16,$8,dspout4
jal dolf
j dspout1
 
dspout4:
add $8,$0,0x08
bne $16,$8,dspout5
jal dobs
j dspout1
 
dspout5:
j dspout1
 
; do carriage return
docr:
sub $29,$29,4
stw $31,$29,0
add $8,$0,scrcol
stw $0,$8,0
jal calcp
ldw $31,$29,0
add $29,$29,4
jr $31
 
; do linefeed
dolf:
sub $29,$29,4
stw $31,$29,0
add $8,$0,scrrow
ldw $9,$8,0
add $10,$0,29
beq $9,$10,dolf1
add $9,$9,1
stw $9,$8,0
jal calcp
j dolf2
dolf1:
jal scrscr
dolf2:
ldw $31,$29,0
add $29,$29,4
jr $31
 
; do backspace
dobs:
sub $29,$29,4
stw $31,$29,0
add $8,$0,scrcol
ldw $9,$8,0
beq $9,$0,dobs1
sub $9,$9,1
stw $9,$8,0
jal calcp
dobs1:
ldw $31,$29,0
add $29,$29,4
jr $31
 
; remove cursor
rmcrs:
add $8,$0,scrptr
ldw $8,$8,0
add $9,$0,scrchr
ldw $10,$9,0
stw $10,$8,0
jr $31
 
; set cursor
stcrs:
add $8,$0,scrptr
ldw $8,$8,0
add $9,$0,scrchr
ldw $10,$8,0
stw $10,$9,0
add $10,$0,(0x87 << 8) | '_'
stw $10,$8,0
jr $31
 
; calculate screen pointer based on row and column
calcp:
add $9,$0,dspbase
add $8,$0,scrrow
ldw $10,$8,0
sll $10,$10,7+2
add $9,$9,$10
add $8,$0,scrcol
ldw $10,$8,0
sll $10,$10,0+2
add $9,$9,$10
add $8,$0,scrptr
stw $9,$8,0
jr $31
 
; clear screen
clrscr:
add $11,$0,(0x07 << 8) | ' '
add $8,$0,dspbase
add $9,$0,30
clrscr1:
add $10,$0,80
clrscr2:
stw $11,$8,0
add $8,$8,4
sub $10,$10,1
bne $10,$0,clrscr2
add $8,$8,(128-80)*4
sub $9,$9,1
bne $9,$0,clrscr1
jr $31
 
; scroll screen
scrscr:
add $8,$0,dspbase
add $9,$0,29
scrscr1:
add $10,$0,80
scrscr2:
ldw $11,$8,128*4
stw $11,$8,0
add $8,$8,4
sub $10,$10,1
bne $10,$0,scrscr2
add $8,$8,(128-80)*4
sub $9,$9,1
bne $9,$0,scrscr1
add $11,$0,(0x07 << 8) | ' '
add $10,$0,80
scrscr3:
stw $11,$8,0
add $8,$8,4
sub $10,$10,1
bne $10,$0,scrscr3
jr $31
 
;***************************************************************
 
.bss
.align 4
 
scrptr:
.word 0
 
scrrow:
.word 0
 
scrcol:
.word 0
 
scrchr:
.word 0
/monitor-xess/disasm.h
0,0 → 1,13
/*
* disasm.h -- disassembler
*/
 
 
#ifndef _DISASM_H_
#define _DISASM_H_
 
 
char *disasm(Word instr, Word locus);
 
 
#endif /* _DISASM_H_ */
/monitor-xess/asm.h
0,0 → 1,13
/*
* asm.h -- assembler
*/
 
 
#ifndef _ASM_H_
#define _ASM_H_
 
 
char *asmInstr(char *line, Word addr, Word *instrPtr);
 
 
#endif /* _ASM_H_ */
/monitor-xess/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:
/monitor-xess/getline.c
0,0 → 1,136
/*
* getline.c -- line input
*/
 
 
#include "common.h"
#include "stdarg.h"
#include "romlib.h"
#include "getline.h"
 
 
#define MAX_HISTORY 100
 
 
static char history[MAX_HISTORY][80];
static int historyIndex; /* next line to be written */
 
 
/*
* Get a line from the console.
*/
char *getLine(char *prompt) {
static char line[80];
int index;
int historyPointer;
char c;
int i;
 
printf(prompt);
index = 0;
historyPointer = historyIndex;
while (1) {
c = getchar();
switch (c) {
case '\r':
putchar('\n');
line[index] = '\0';
return line;
case '\b':
case 0x7F:
if (index == 0) {
break;
}
putchar('\b');
putchar(' ');
putchar('\b');
index--;
break;
case 'P' & ~0x40:
if (historyPointer == historyIndex) {
line[index] = '\0';
strcpy(history[historyIndex], line);
}
i = historyPointer - 1;
if (i == -1) {
i = MAX_HISTORY - 1;
}
if (i == historyIndex) {
putchar('\a');
break;
}
if (history[i][0] == '\0') {
putchar('\a');
break;
}
historyPointer = i;
strcpy(line, history[historyPointer]);
printf("\r");
for (i = 0; i < 79; i++) {
printf(" ");
}
printf("\r");
printf(prompt);
printf(line);
index = strlen(line);
break;
case 'N' & ~0x40:
if (historyPointer == historyIndex) {
putchar('\a');
break;
}
i = historyPointer + 1;
if (i == MAX_HISTORY) {
i = 0;
}
historyPointer = i;
strcpy(line, history[historyPointer]);
printf("\r");
for (i = 0; i < 79; i++) {
printf(" ");
}
printf("\r");
printf(prompt);
printf(line);
index = strlen(line);
break;
default:
if (c == '\t') {
c = ' ';
}
if (c < 0x20 || c > 0x7E) {
break;
}
putchar(c);
line[index++] = c;
break;
}
}
/* never reached */
return NULL;
}
 
 
/*
* Add a line to the history.
* Don't do this if the line is empty, or if its
* contents exactly match the previous line.
*/
void addHist(char *line) {
int lastWritten;
 
if (*line == '\0') {
return;
}
lastWritten = historyIndex - 1;
if (lastWritten == -1) {
lastWritten = MAX_HISTORY - 1;
}
if (strcmp(history[lastWritten], line) == 0) {
return;
}
strcpy(history[historyIndex], line);
if (++historyIndex == MAX_HISTORY) {
historyIndex = 0;
}
}
/monitor-xess/cpu.c
0,0 → 1,367
/*
* cpu.c -- execute instructions
*/
 
 
#include "common.h"
#include "stdarg.h"
#include "romlib.h"
#include "instr.h"
#include "cpu.h"
#include "mmu.h"
#include "start.h"
 
 
#define RR(n) r[n]
#define WR(n,d) ((void) ((n) != 0 ? r[n] = (d) : (d)))
 
#define BREAK (OP_TRAP << 26)
 
 
/**************************************************************/
 
 
static Word pc; /* program counter */
static Word psw; /* processor status word */
static Word r[32]; /* general purpose registers */
 
static Bool breakSet; /* breakpoint set if true */
static Word breakAddr; /* if breakSet, this is where */
 
 
/**************************************************************/
 
 
Word cpuGetPC(void) {
return pc;
}
 
 
void cpuSetPC(Word addr) {
pc = addr;
}
 
 
Word cpuGetReg(int regnum) {
return RR(regnum & 0x1F);
}
 
 
void cpuSetReg(int regnum, Word value) {
WR(regnum & 0x1F, value);
}
 
 
Word cpuGetPSW(void) {
return psw;
}
 
 
void cpuSetPSW(Word value) {
psw = value;
}
 
 
Bool cpuTestBreak(void) {
return breakSet;
}
 
 
Word cpuGetBreak(void) {
return breakAddr;
}
 
 
void cpuSetBreak(Word addr) {
breakAddr = addr;
breakSet = true;
}
 
 
void cpuResetBreak(void) {
breakSet = false;
}
 
 
/**************************************************************/
 
 
static char *cause[32] = {
/* 0 */ "terminal 0 transmitter interrupt",
/* 1 */ "terminal 0 receiver interrupt",
/* 2 */ "terminal 1 transmitter interrupt",
/* 3 */ "terminal 1 receiver interrupt",
/* 4 */ "keyboard interrupt",
/* 5 */ "unknown interrupt",
/* 6 */ "unknown interrupt",
/* 7 */ "unknown interrupt",
/* 8 */ "disk interrupt",
/* 9 */ "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"
};
 
 
char *exceptionToString(int exception) {
if (exception < 0 ||
exception >= sizeof(cause)/sizeof(cause[0])) {
return "<exception number out of bounds>";
}
return cause[exception];
}
 
 
/**************************************************************/
 
 
static Byte stepType[64] = {
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
/* 0x00 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* 0x10 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* 0x20 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 4, 3, 4, 1, 0,
/* 0x30 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};
 
 
static Bool evalCond(int cc, Word a, Word b) {
switch (cc) {
case 0:
/* equal */
if (a == b) {
return true;
}
break;
case 1:
/* not equal */
if (a != b) {
return true;
}
break;
case 2:
/* less or equal (signed) */
if ((signed int) a <= (signed int) b) {
return true;
}
break;
case 3:
/* less or equal (unsigned) */
if (a <= b) {
return true;
}
break;
case 4:
/* less than (signed) */
if ((signed int) a < (signed int) b) {
return true;
}
break;
case 5:
/* less than (unsigned) */
if (a < b) {
return true;
}
break;
case 6:
/* greater or equal (signed) */
if ((signed int) a >= (signed int) b) {
return true;
}
break;
case 7:
/* greater or equal (unsigned) */
if (a >= b) {
return true;
}
break;
case 8:
/* greater than (signed) */
if ((signed int) a > (signed int) b) {
return true;
}
break;
case 9:
/* greater than (unsigned) */
if (a > b) {
return true;
}
break;
default:
printf("cannot compute condition code %d\n", cc);
break;
}
return false;
}
 
 
Bool cpuStep(void) {
Word instr;
int opcode;
int reg1, reg2;
Half immed;
Word offset;
Bool canStep;
Word nextAddr;
Word nextInstr;
int i;
MonitorState stepState;
MonitorState *origReturn;
 
instr = mmuReadWord(pc);
opcode = (instr >> 26) & 0x3F;
reg1 = (instr >> 21) & 0x1F;
reg2 = (instr >> 16) & 0x1F;
immed = instr & 0x0000FFFF;
offset = instr & 0x03FFFFFF;
canStep = true;
switch (stepType[opcode]) {
case 1:
/* next instruction follows current one */
nextAddr = pc + 4;
break;
case 2:
/* next instruction conditionally reached by PC relative branch */
nextAddr = pc + 4;
if (evalCond(opcode - OP_BEQ, RR(reg1), RR(reg2))) {
nextAddr += SEXT16(immed) << 2;
}
break;
case 3:
/* next instruction reached by PC relative jump */
nextAddr = pc + 4 + (SEXT26(offset) << 2);
break;
case 4:
/* next instruction reached by jump to register contents */
nextAddr = RR(reg1);
break;
default:
printf("cannot single-step instruction with opcode 0x%02X\n",
opcode);
canStep = false;
break;
}
if (!canStep) {
return false;
}
nextInstr = mmuReadWord(nextAddr);
mmuWriteWord(nextAddr, BREAK);
for (i = 0; i < 32; i++) {
userContext.reg[i] = RR(i);
}
userContext.reg[30] = pc;
userContext.psw = psw & ~PSW_V;
userContext.tlbIndex = mmuGetIndex();
userContext.tlbHi = mmuGetEntryHi();
userContext.tlbLo = mmuGetEntryLo();
if (saveState(&stepState)) {
origReturn = monitorReturn;
monitorReturn = &stepState;
resume();
}
monitorReturn = origReturn;
for (i = 0; i < 32; i++) {
WR(i, userContext.reg[i]);
}
pc = userContext.reg[30];
psw = userContext.psw | (psw & PSW_V);
mmuSetIndex(userContext.tlbIndex);
mmuSetEntryHi(userContext.tlbHi);
mmuSetEntryLo(userContext.tlbLo);
mmuWriteWord(nextAddr, nextInstr);
if (nextAddr == pc) {
return true;
}
if ((psw & PSW_V) == 0) {
printf("unexpected %s occurred\n",
exceptionToString((psw & PSW_PRIO_MASK) >> 16));
return false;
}
if ((psw & PSW_PRIO_MASK) >> 16 == 21 &&
(mmuGetEntryHi() & 0x80000000) == 0) {
pc = 0xC0000008;
} else {
pc = 0xC0000004;
}
return true;
}
 
 
Bool cpuRun(void) {
Word instr;
int i;
MonitorState runState;
MonitorState *origReturn;
 
if (breakSet && breakAddr == pc) {
/* single-step one instruction */
if (!cpuStep()) {
return false;
}
}
while (1) {
if (breakSet) {
instr = mmuReadWord(breakAddr);
mmuWriteWord(breakAddr, BREAK);
}
for (i = 0; i < 32; i++) {
userContext.reg[i] = RR(i);
}
userContext.reg[30] = pc;
userContext.psw = psw & ~PSW_V;
userContext.tlbIndex = mmuGetIndex();
userContext.tlbHi = mmuGetEntryHi();
userContext.tlbLo = mmuGetEntryLo();
if (saveState(&runState)) {
origReturn = monitorReturn;
monitorReturn = &runState;
resume();
}
monitorReturn = origReturn;
for (i = 0; i < 32; i++) {
WR(i, userContext.reg[i]);
}
pc = userContext.reg[30];
psw = userContext.psw | (psw & PSW_V);
mmuSetIndex(userContext.tlbIndex);
mmuSetEntryHi(userContext.tlbHi);
mmuSetEntryLo(userContext.tlbLo);
if (breakSet) {
mmuWriteWord(breakAddr, instr);
}
if (breakSet && breakAddr == pc) {
return true;
}
if ((psw & PSW_V) == 0) {
printf("unexpected %s occurred\n",
exceptionToString((psw & PSW_PRIO_MASK) >> 16));
return false;
}
if ((psw & PSW_PRIO_MASK) >> 16 == 21 &&
(mmuGetEntryHi() & 0x80000000) == 0) {
pc = 0xC0000008;
} else {
pc = 0xC0000004;
}
}
/* never reached */
return false;
}
/monitor-xess/sctio-ser.s
0,0 → 1,200
;
; sctio-ser.s -- disk sector I/O for disk made available by serial interface
;
 
;***************************************************************
 
.export sctcapser ; determine disk capacity
.export sctioser ; do disk I/O
 
.import ser1in
.import ser1out
.import ser1inchk
.import puts
 
; constants for communication with disk server
.set SYN,0x16 ; to initiate the three-way handshake
.set ACK,0x06 ; acknowledgement for handshake
.set RESULT_OK,0x00 ; server successfully executed cmd
; everything else means error
 
.set WAIT_DELAY,800000 ; count for delay loop
 
;***************************************************************
 
.code
.align 4
 
sctcapser:
sub $29,$29,16
stw $16,$29,0
stw $17,$29,4
stw $18,$29,8
stw $31,$29,12
add $4,$0,trymsg ; say what we are doing
jal puts
add $18,$0,$0 ; capacity == 0 if disk not present
add $16,$0,10 ; 10 tries to get a connection
handshake1:
sub $16,$16,1
add $4,$0,SYN
jal ser1out ; send SYN
add $17,$0,WAIT_DELAY ; wait for ACK
handshake2:
sub $17,$17,1
jal ser1inchk
bne $2,$0,handshake3
bne $17,$0,handshake2
add $4,$0,timeoutmsg
jal puts
bne $16,$0,handshake1
add $4,$0,frustratedmsg
jal puts
j sctcapx
handshake3:
jal ser1in
add $8,$0,ACK
bne $2,$8,sctcapx
; we got an ACK so we return it
add $4,$0,ACK
jal ser1out
 
; ask it for its capacity
add $4,$0,'c'
jal ser1out ; request
jal ser1in ; first byte of response
bne $2,$0,sctcapx ; exit if error
 
; all is well and the server will give us the capacity
add $16,$0,4 ; 4 bytes to read
sctcap1:
sll $18,$18,8
jal ser1in
or $18,$18,$2 ; most significant byte first
sub $16,$16,1
bne $16,$0,sctcap1
 
; return value is in $18
sctcapx:
add $2,$0,$18
ldw $16,$29,0
ldw $17,$29,4
ldw $18,$29,8
ldw $31,$29,12
add $29,$29,16
jr $31
 
.data
.align 4
 
trymsg:
.byte "Trying to connect to disk server..."
.byte 0x0A, 0
 
timeoutmsg:
.byte "Request timed out..."
.byte 0x0A, 0
 
frustratedmsg:
.byte "Unable to establish connection to disk server."
.byte 0x0A, 0
 
.code
.align 4
 
sctioser:
sub $29,$29,24
stw $16,$29,0
stw $17,$29,4
stw $18,$29,8
stw $19,$29,12
stw $20,$29,16
stw $31,$29,20
add $16,$0,$4 ; command
add $17,$0,$5 ; start at sector
add $8,$0,0xc0000000
or $18,$8,$6 ; memory address (logicalized)
add $19,$0,$7 ; number of sectors
 
; switch over command
add $8,$0,'r'
beq $8,$16,sctior ; read
add $8,$0,'w'
beq $8,$16,sctiow ; write
; unknown command
add $2,$0,1 ; value != 0 signifies error
j sctiox
 
; read from disk
sctior:
sctior1: ; loop over number of sectors
beq $19,$0,sctiorsuc ; successful return
sub $19,$19,1
; read a sector
add $4,$0,'r'
jal ser1out
; send sector number
add $20,$0,32 ; 4 bytes
sctior2:
sub $20,$20,8
slr $4,$17,$20
and $4,$4,0xff
jal ser1out
bne $20,$0,sctior2
add $17,$17,1
; get answer
jal ser1in
bne $2,$0,sctiox ; $2 != 0 so we use it as return code
; read data
add $20,$0,512
sctior3:
sub $20,$20,1
jal ser1in
stb $2,$18,0
add $18,$18,1
bne $20,$0,sctior3
j sctior1
sctiorsuc:
add $2,$0,$0
j sctiox
 
; write to disk
sctiow:
sctiow1: ; loop over number of sectors
beq $19,$0,sctiowsuc ; successful return
sub $19,$19,1
; write a sector
add $4,$0,'w'
jal ser1out
; send sector number
add $20,$0,32 ; 4 bytes
sctiow2:
sub $20,$20,8
slr $4,$17,$20
and $4,$4,0xff
jal ser1out
bne $20,$0,sctiow2
add $17,$17,1
; write data
add $20,$0,512
sctiow3:
sub $20,$20,1
ldbu $4,$18,0
jal ser1out
add $18,$18,1
bne $20,$0,sctiow3
; get answer
jal ser1in
bne $2,$0,sctiox
j sctiow1
sctiowsuc:
add $2,$0,$0
sctiox:
ldw $16,$29,0
ldw $17,$29,4
ldw $18,$29,8
ldw $19,$29,12
ldw $20,$29,16
ldw $31,$29,20
add $29,$29,24
jr $31
/monitor-xess/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_ */
/monitor-xess/romlib.h
0,0 → 1,34
/*
* romlib.h -- the ROM library
*/
 
 
#ifndef _ROMLIB_H_
#define _ROMLIB_H_
 
 
void debugBreak(void);
 
int strlen(const char *s);
int strcmp(const char *s, const char *t);
char *strcpy(char *s, const char *t);
char *strcat(char *s, const char *t);
char *strchr(const char *s, char c);
char *strtok(char *s, const char *t);
 
unsigned long strtoul(const char *s, char **endp, int base);
 
void qsort(void *base, int n, int size,
int (*cmp)(const void *, const void *));
 
char getchar(void);
void putchar(char c);
void puts(const char *s);
 
int vprintf(const char *fmt, va_list ap);
int printf(const char *fmt, ...);
int vsprintf(char *s, const char *fmt, va_list ap);
int sprintf(char *s, const char *fmt, ...);
 
 
#endif /* _ROMLIB_H_ */
/monitor-xess/getline.h
0,0 → 1,14
/*
* getline.h -- line input
*/
 
 
#ifndef _GETLINE_H_
#define _GETLINE_H_
 
 
char *getLine(char *prompt);
void addHist(char *line);
 
 
#endif /* _GETLINE_H_ */
/monitor-xess/cpu.h
0,0 → 1,40
/*
* cpu.h -- execute instructions
*/
 
 
#ifndef _CPU_H_
#define _CPU_H_
 
 
#define PSW_V 0x08000000 /* interrupt vector bit in PSW */
#define PSW_UM 0x04000000 /* user mode enable bit in PSW */
#define PSW_PUM 0x02000000 /* previous value of PSW_UM */
#define PSW_OUM 0x01000000 /* old value of PSW_UM */
#define PSW_IE 0x00800000 /* interrupt enable bit in PSW */
#define PSW_PIE 0x00400000 /* previous value of PSW_IE */
#define PSW_OIE 0x00200000 /* old value of PSW_IE */
#define PSW_PRIO_MASK 0x001F0000 /* bits to encode IRQ prio in PSW */
 
 
Word cpuGetPC(void);
void cpuSetPC(Word addr);
 
Word cpuGetReg(int regnum);
void cpuSetReg(int regnum, Word value);
 
Word cpuGetPSW(void);
void cpuSetPSW(Word value);
 
Bool cpuTestBreak(void);
Word cpuGetBreak(void);
void cpuSetBreak(Word addr);
void cpuResetBreak(void);
 
char *exceptionToString(int exception);
 
Bool cpuStep(void);
Bool cpuRun(void);
 
 
#endif /* _CPU_H_ */
/monitor-xess/common.h
0,0 → 1,27
/*
* common.h -- common definitions
*/
 
 
#ifndef _COMMON_H_
#define _COMMON_H_
 
 
#define PAGE_SHIFT 12 /* log2 of page size */
#define PAGE_SIZE (1 << PAGE_SHIFT) /* page size in bytes */
#define OFFSET_MASK (PAGE_SIZE - 1) /* mask for offset in page */
#define PAGE_MASK (~OFFSET_MASK) /* mask for page number */
 
 
typedef enum { false, true } Bool; /* truth values */
 
 
typedef unsigned int Word; /* 32 bit quantities */
typedef unsigned short Half; /* 16 bit quantities */
typedef unsigned char Byte; /* 8 bit quantities */
 
 
#define NULL ((void *) 0)
 
 
#endif /* _COMMON_H_ */
/Makefile
4,7 → 4,7
 
BUILD = ../build
 
DIRS = kbdtbls monitor loadserv
DIRS = kbdtbls monitor-xess monitor-digilent loadserv
 
.PHONY: all install clean
 

powered by: WebSVN 2.1.0

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