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/monitor/common
    from Rev 57 to Rev 59
    Reverse comparison

Rev 57 → Rev 59

/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);
}
/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;
}
/serial.s
0,0 → 1,98
;
; serial.s -- the serial line interface
;
 
;***************************************************************
 
.set ser0base,0xF0300000 ; serial line 0 base address
.set ser1base,0xF0301000 ; 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
/start.h
0,0 → 1,62
/*
* 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);
 
void setISR(Word ptr);
void setUMSR(Word ptr);
extern Word isrPtr;
extern Word umsrPtr;
 
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_ */
/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();
}
/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_ */
/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_ */
/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_ */
/command.c
0,0 → 1,887
/*
* 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(" load load from serial line\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(" load <n> load an S-record file from serial line <n>\n");
}
 
 
static void help16(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 doLoad(char *tokens[], int n) {
int serno;
 
if (n == 2) {
if (!getDecNumber(tokens[1], &serno) || serno < 0 || serno > 1) {
printf("illegal serial line number\n");
return;
}
load(serno);
} else {
help15();
}
}
 
 
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 {
help16();
}
}
 
 
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 },
{ "load", help15, doLoad },
{ "boot", help16, 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;
}
/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");
}
/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;
}
/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;
}
/keyboard.s
0,0 → 1,149
;
; 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 ; key 1 in $16
add $8,$0,0xF0
bne $16,$8,kbdin2
kbdin1:
jal kbdinp
j kbdin0
kbdin2:
jal kbdinp
add $17,$2,$0 ; key 2 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 ; use key 1
add $5,$0,xltbl1 ; with translation table 1
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
beq $16,$8,kbdin12
add $8,$0,0x14 ; ctrl key
beq $16,$8,kbdin14
j kbdin13
kbdin12:
add $4,$17,$0 ; use key 2
add $5,$0,xltbl2 ; with translation table 2
jal xlat
j kbdx
kbdin13:
add $4,$16,$0 ; use key 1
add $5,$0,xltbl1 ; with translation table 1
jal xlat
j kbdx
kbdin14:
add $4,$17,$0 ; use key 2
add $5,$0,xltbl1 ; with translation table 1
jal xlat
and $2,$2,0xFF-0x60 ; then reset bits 0x60
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 ; wait until character ready
ldw $2,$8,4 ; get character
add $9,$0,0xE0
beq $2,$9,kbdinp1 ; ignore E0 prefix
add $9,$0,0xE1
beq $2,$9,kbdinp1 ; as well as E1 prefix
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
/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
/command.h
0,0 → 1,13
/*
* command.h -- command interpreter
*/
 
 
#ifndef _COMMAND_H_
#define _COMMAND_H_
 
 
void execCommand(char *line);
 
 
#endif /* _COMMAND_H_ */
/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_ */
/main.c
0,0 → 1,28
/*
* 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.3\n\n");
initInstrTable();
cpuSetPC(0xC0010000);
cpuSetPSW(0x08000000);
while (1) {
line = getLine("ECO32 > ");
addHist(line);
execCommand(line);
}
return 0;
}
/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;
}
/serial.h
0,0 → 1,21
/*
* serial.s -- the serial line interface
*/
 
 
#ifndef _SERIAL_H_
#define _SERIAL_H_
 
 
int ser0inchk(void);
int ser0in(void);
int ser0outchk(void);
void ser0out(int c);
 
int ser1inchk(void);
int ser1in(void);
int ser1outchk(void);
void ser1out(int c);
 
 
#endif /* _SERIAL_H_ */
/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
/disasm.h
0,0 → 1,13
/*
* disasm.h -- disassembler
*/
 
 
#ifndef _DISASM_H_
#define _DISASM_H_
 
 
char *disasm(Word instr, Word locus);
 
 
#endif /* _DISASM_H_ */
/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_ */
/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:
/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 20
 
 
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;
}
}
/cpu.c
0,0 → 1,369
/*
* 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 */ "serial line 0 xmt interrupt",
/* 1 */ "serial line 0 rcv interrupt",
/* 2 */ "serial line 1 xmt interrupt",
/* 3 */ "serial line 1 rcv 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 0 interrupt",
/* 15 */ "timer 1 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:
/* this should never happen */
printf("cannot compute condition code %d\n", cc);
break;
}
return false;
}
 
 
void cpuStep(void) {
Word instr;
int opcode;
int reg1, reg2;
Half immed;
Word offset;
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;
switch (stepType[opcode]) {
case 1:
/* next instruction follows current one immediately */
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) & 0xFFFFFFFC;
break;
default:
printf("cannot single-step instruction with opcode 0x%02X\n",
opcode);
return;
}
nextInstr = mmuReadWord(nextAddr);
mmuWriteWord(nextAddr, BREAK);
for (i = 0; i < 32; i++) {
userContext.reg[i] = RR(i);
}
userContext.reg[30] = pc;
userContext.psw = psw;
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;
mmuSetIndex(userContext.tlbIndex);
mmuSetEntryHi(userContext.tlbHi);
mmuSetEntryLo(userContext.tlbLo);
mmuWriteWord(nextAddr, nextInstr);
if (nextAddr == pc) {
return;
}
if ((psw & PSW_PRIO_MASK) >> 16 == 21 &&
(mmuGetEntryHi() & 0x80000000) == 0) {
/* TLB user miss */
if (umsrPtr == 0x00000000) {
printf("unexpected TLB user miss exception occurred\n");
return;
}
pc = umsrPtr;
} else {
/* any other exception */
if (isrPtr == 0x00000000) {
printf("unexpected %s occurred\n",
exceptionToString((psw & PSW_PRIO_MASK) >> 16));
return;
}
pc = isrPtr;
}
}
 
 
void cpuRun(void) {
Word instr;
int i;
MonitorState runState;
MonitorState *origReturn;
 
if (breakSet && breakAddr == pc) {
/* single-step one instruction */
cpuStep();
}
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;
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;
mmuSetIndex(userContext.tlbIndex);
mmuSetEntryHi(userContext.tlbHi);
mmuSetEntryLo(userContext.tlbLo);
if (breakSet) {
mmuWriteWord(breakAddr, instr);
}
if (breakSet && breakAddr == pc) {
return;
}
if ((psw & PSW_PRIO_MASK) >> 16 == 21 &&
(mmuGetEntryHi() & 0x80000000) == 0) {
/* TLB user miss */
if (umsrPtr == 0x00000000) {
printf("unexpected TLB user miss exception occurred\n");
return;
}
pc = umsrPtr;
} else {
/* any other exception */
if (isrPtr == 0x00000000) {
printf("unexpected %s occurred\n",
exceptionToString((psw & PSW_PRIO_MASK) >> 16));
return;
}
pc = isrPtr;
}
}
}
/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
/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_ */
/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_ */
/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_ */
/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);
 
void cpuStep(void);
void cpuRun(void);
 
 
#endif /* _CPU_H_ */
/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_ */

powered by: WebSVN 2.1.0

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