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

Subversion Repositories eco32

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 7 to Rev 8
    Reverse comparison

Rev 7 → Rev 8

/eco32/trunk/sim/screen
0,0 → 1,30
" ",
" ",
" ",
" ",
" ",
" ",
" S i m p l e C h a r a c t e r D i s p l a y ",
" ",
" ",
" ",
" 3 0 L i n e s x 8 0 C h a r a c t e r s ",
" ",
" ",
" ",
" ",
" ",
" ",
" U n i v e r s i t y ",
" ",
" o f ",
" ",
" A p p l i e d S c i e n c e s ",
" ",
" G i e s s e n ",
" ",
" ",
" ",
" ",
" ",
" ",
/eco32/trunk/sim/mmu.c
0,0 → 1,307
/*
* mmu.c -- MMU simulation
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
 
#include "common.h"
#include "console.h"
#include "error.h"
#include "except.h"
#include "cpu.h"
#include "mmu.h"
#include "memory.h"
 
 
static Bool debugUse = false;
static Bool debugWrite = false;
 
 
static TLB_Entry tlb[TLB_SIZE];
static Word tlbIndex;
static Word tlbEntryHi;
static Word tlbEntryLo;
static Word tlbBadAddr;
 
 
static int assoc(Word page) {
int n, i;
 
n = -1;
for (i = 0; i < TLB_SIZE; i++) {
if (tlb[i].page == page) {
n = i;
}
}
return n;
}
 
 
static void assocDelay(void) {
int n, i;
 
/* simulate delay introduced by assoc when using mapped
addresses but not experienced with unmapped addresses */
n = -1;
for (i = 0; i < TLB_SIZE; i++) {
if (tlb[i].page == 0) {
n = i;
}
}
}
 
 
static Word v2p(Word vAddr, Bool userMode, Bool writing) {
Word pAddr;
Word page, offset;
int index;
 
if (debugUse) {
cPrintf("**** vAddr = 0x%08X", vAddr);
}
if ((vAddr & 0x80000000) != 0 && userMode) {
/* trying to access a privileged address from user mode */
tlbBadAddr = vAddr;
throwException(EXC_PRV_ADDRESS);
}
if ((vAddr & 0xC0000000) == 0xC0000000) {
/* unmapped address space */
assocDelay();
pAddr = vAddr & ~0xC0000000;
} else {
/* mapped address space */
page = vAddr & PAGE_MASK;
offset = vAddr & OFFSET_MASK;
index = assoc(page);
if (index == -1) {
/* TLB miss exception */
tlbBadAddr = vAddr;
tlbEntryHi = page;
throwException(EXC_TLB_MISS);
}
if (!tlb[index].valid) {
/* TLB invalid exception */
tlbBadAddr = vAddr;
tlbEntryHi = page;
throwException(EXC_TLB_INVALID);
}
if (!tlb[index].write && writing) {
/* TLB write exception */
tlbBadAddr = vAddr;
tlbEntryHi = page;
throwException(EXC_TLB_WRITE);
}
pAddr = tlb[index].frame | offset;
}
if (debugUse) {
cPrintf(", pAddr = 0x%08X ****\n", pAddr);
}
return pAddr;
}
 
 
Word mmuReadWord(Word vAddr, Bool userMode) {
if ((vAddr & 3) != 0) {
/* throw illegal address exception */
tlbBadAddr = vAddr;
throwException(EXC_ILL_ADDRESS);
}
return memoryReadWord(v2p(vAddr, userMode, false));
}
 
 
Half mmuReadHalf(Word vAddr, Bool userMode) {
if ((vAddr & 1) != 0) {
/* throw illegal address exception */
tlbBadAddr = vAddr;
throwException(EXC_ILL_ADDRESS);
}
return memoryReadHalf(v2p(vAddr, userMode, false));
}
 
 
Byte mmuReadByte(Word vAddr, Bool userMode) {
return memoryReadByte(v2p(vAddr, userMode, false));
}
 
 
void mmuWriteWord(Word vAddr, Word data, Bool userMode) {
if ((vAddr & 3) != 0) {
/* throw illegal address exception */
tlbBadAddr = vAddr;
throwException(EXC_ILL_ADDRESS);
}
memoryWriteWord(v2p(vAddr, userMode, true), data);
}
 
 
void mmuWriteHalf(Word vAddr, Half data, Bool userMode) {
if ((vAddr & 1) != 0) {
/* throw illegal address exception */
tlbBadAddr = vAddr;
throwException(EXC_ILL_ADDRESS);
}
memoryWriteHalf(v2p(vAddr, userMode, true), data);
}
 
 
void mmuWriteByte(Word vAddr, Byte data, Bool userMode) {
memoryWriteByte(v2p(vAddr, userMode, true), data);
}
 
 
Word mmuGetIndex(void) {
return tlbIndex;
}
 
 
void mmuSetIndex(Word value) {
tlbIndex = value & TLB_MASK;
}
 
 
Word mmuGetEntryHi(void) {
return tlbEntryHi;
}
 
 
void mmuSetEntryHi(Word value) {
tlbEntryHi = value & PAGE_MASK;
}
 
 
Word mmuGetEntryLo(void) {
return tlbEntryLo;
}
 
 
void mmuSetEntryLo(Word value) {
tlbEntryLo = value & (PAGE_MASK | TLB_WRITE | TLB_VALID);
}
 
 
Word mmuGetBadAddr(void) {
return tlbBadAddr;
}
 
 
void mmuSetBadAddr(Word value) {
tlbBadAddr = value;
}
 
 
void mmuTbs(void) {
int index;
 
index = assoc(tlbEntryHi & PAGE_MASK);
if (index == -1) {
tlbIndex = 0x80000000;
} else {
tlbIndex = index;
}
}
 
 
void mmuTbwr(void) {
int index;
 
/* choose a random index, but don't touch fixed entries */
do {
index = rand() & TLB_MASK;
} while (index < TLB_FIXED);
tlb[index].page = tlbEntryHi & PAGE_MASK;
tlb[index].frame = tlbEntryLo & PAGE_MASK;
tlb[index].write = tlbEntryLo & TLB_WRITE ? true : false;
tlb[index].valid = tlbEntryLo & TLB_VALID ? true : false;
if (debugWrite) {
cPrintf("**** TLB[%02d] <- 0x%08X 0x%08X %c %c ****\n",
index, tlb[index].page, tlb[index].frame,
tlb[index].write ? 'w' : '-',
tlb[index].valid ? 'v' : '-');
}
}
 
 
void mmuTbri(void) {
int index;
 
index = tlbIndex & TLB_MASK;
tlbEntryHi = tlb[index].page;
tlbEntryLo = tlb[index].frame;
if (tlb[index].write) {
tlbEntryLo |= TLB_WRITE;
}
if (tlb[index].valid) {
tlbEntryLo |= TLB_VALID;
}
}
 
 
void mmuTbwi(void) {
int index;
 
index = tlbIndex & TLB_MASK;
tlb[index].page = tlbEntryHi & PAGE_MASK;
tlb[index].frame = tlbEntryLo & PAGE_MASK;
tlb[index].write = tlbEntryLo & TLB_WRITE ? true : false;
tlb[index].valid = tlbEntryLo & TLB_VALID ? true : false;
if (debugWrite) {
cPrintf("**** TLB[%02d] <- 0x%08X 0x%08X %c %c ****\n",
index, tlb[index].page, tlb[index].frame,
tlb[index].write ? 'w' : '-',
tlb[index].valid ? 'v' : '-');
}
}
 
 
TLB_Entry mmuGetTLB(int index) {
return tlb[index & TLB_MASK];
}
 
 
void mmuSetTLB(int index, TLB_Entry tlbEntry) {
index &= TLB_MASK;
tlb[index] = tlbEntry;
if (debugWrite) {
cPrintf("**** TLB[%02d] <- 0x%08X 0x%08X %c %c ****\n",
index, tlb[index].page, tlb[index].frame,
tlb[index].write ? 'w' : '-',
tlb[index].valid ? 'v' : '-');
}
}
 
 
void mmuReset(void) {
int i;
 
cPrintf("Resetting MMU...\n");
for (i = 0; i < TLB_SIZE; i++) {
tlb[i].page = rand() & PAGE_MASK;
tlb[i].frame = rand() & PAGE_MASK;
tlb[i].write = rand() & 0x1000 ? true : false;
tlb[i].valid = rand() & 0x1000 ? true : false;
if (debugWrite) {
cPrintf("**** TLB[%02d] <- 0x%08X 0x%08X %c %c ****\n",
i, tlb[i].page, tlb[i].frame,
tlb[i].write ? 'w' : '-',
tlb[i].valid ? 'v' : '-');
}
}
tlbIndex = rand() & TLB_MASK;
tlbEntryHi = rand() & PAGE_MASK;
tlbEntryLo = rand() & (PAGE_MASK | TLB_WRITE | TLB_VALID);
tlbBadAddr = rand();
}
 
 
void mmuInit(void) {
mmuReset();
}
 
 
void mmuExit(void) {
}
/eco32/trunk/sim/instr.c
0,0 → 1,119
/*
* instr.c -- instruction encoding
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#include "common.h"
#include "console.h"
#include "error.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;
}
/eco32/trunk/sim/output.c
0,0 → 1,75
/*
* output.c -- output to file on host system
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#include "common.h"
#include "console.h"
#include "error.h"
#include "output.h"
 
 
static FILE *outputFile;
 
 
Word outputRead(Word addr) {
if (outputFile == NULL) {
/* output device not installed */
error("output device not installed");
}
/* output device always returns 0 on read */
return 0;
}
 
 
void outputWrite(Word addr, Word data) {
char c;
 
if (outputFile == NULL) {
/* output device not installed */
error("output device not installed");
}
c = data;
if (fwrite(&c, 1, 1, outputFile) != 1) {
error("write error on output device");
}
}
 
 
void outputReset(void) {
if (outputFile == NULL) {
/* output device not installed */
return;
}
cPrintf("Resetting output device...\n");
fseek(outputFile, 0, SEEK_SET);
}
 
 
void outputInit(char *outputFileName) {
if (outputFileName == NULL) {
/* do not install output device */
outputFile = NULL;
} else {
/* try to install output device */
outputFile = fopen(outputFileName, "wb");
if (outputFile == NULL) {
error("cannot open output device file '%s'", outputFileName);
}
setvbuf(outputFile, NULL, _IONBF, 0);
}
outputReset();
}
 
 
void outputExit(void) {
if (outputFile == NULL) {
/* output device not installed */
return;
}
fclose(outputFile);
}
/eco32/trunk/sim/console.c
0,0 → 1,55
/*
* console.c -- the simulator's operator console
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <signal.h>
 
#include "common.h"
#include "console.h"
#include "error.h"
#include "cpu.h"
 
#include "getline.h"
 
 
static void (*oldSigIntHandler)(int signum);
 
 
static void newSigIntHandler(int signum) {
signal(SIGINT, newSigIntHandler);
cpuHalt();
}
 
 
char *cGetLine(char *prompt) {
return gl_getline(prompt);
}
 
 
void cAddHist(char *line) {
gl_histadd(line);
}
 
 
void cPrintf(char *format, ...) {
va_list ap;
 
va_start(ap, format);
vprintf(format, ap);
va_end(ap);
}
 
 
void cInit(void) {
oldSigIntHandler = signal(SIGINT, newSigIntHandler);
}
 
 
void cExit(void) {
signal(SIGINT, oldSigIntHandler);
}
/eco32/trunk/sim/grsplash
0,0 → 1,237
0x13484, 0x0000D, 0x0000B, 0x00008, 0x00011, 0x00008, 0x0000F, 0x00006,
0x0000C, 0x00007, 0x0021F, 0x0000D, 0x00009, 0x0000C, 0x0000D, 0x0000C,
0x0000C, 0x00008, 0x00009, 0x0000A, 0x0021E, 0x0000D, 0x00007, 0x0000F,
0x0000A, 0x0000F, 0x0000A, 0x0000A, 0x00007, 0x0000C, 0x0021D, 0x0000D,
0x00006, 0x00012, 0x00007, 0x00012, 0x00007, 0x0000C, 0x00005, 0x0000E,
0x0021C, 0x0000D, 0x00005, 0x00008, 0x00004, 0x00007, 0x00006, 0x00008,
0x00004, 0x00007, 0x00007, 0x00005, 0x00002, 0x00005, 0x00005, 0x00005,
0x00004, 0x00005, 0x0021C, 0x00005, 0x0000D, 0x00006, 0x00008, 0x00006,
0x00005, 0x00006, 0x00008, 0x00006, 0x00006, 0x00004, 0x00004, 0x00004,
0x00005, 0x00004, 0x00006, 0x00005, 0x0021B, 0x00005, 0x0000C, 0x00005,
0x0000B, 0x00006, 0x00003, 0x00005, 0x0000B, 0x00006, 0x0000D, 0x00004,
0x00005, 0x00004, 0x00006, 0x00005, 0x0021B, 0x00005, 0x0000B, 0x00006,
0x00013, 0x00006, 0x0000C, 0x00005, 0x0000C, 0x00005, 0x00004, 0x00005,
0x00007, 0x00004, 0x0021B, 0x00005, 0x0000B, 0x00005, 0x00014, 0x00005,
0x0000E, 0x00005, 0x00009, 0x00007, 0x00004, 0x00005, 0x00006, 0x00005,
0x0021B, 0x00005, 0x0000B, 0x00005, 0x00014, 0x00005, 0x0000E, 0x00005,
0x00008, 0x00007, 0x00010, 0x00005, 0x0021B, 0x0000C, 0x00004, 0x00004,
0x00015, 0x00004, 0x0000F, 0x00005, 0x00008, 0x00007, 0x00010, 0x00005,
0x0021B, 0x0000C, 0x00004, 0x00004, 0x00015, 0x00004, 0x00010, 0x00004,
0x00008, 0x00008, 0x0000E, 0x00005, 0x0021C, 0x0000C, 0x00004, 0x00004,
0x00015, 0x00004, 0x00010, 0x00004, 0x00008, 0x00009, 0x0000C, 0x00005,
0x0021D, 0x0000C, 0x00004, 0x00004, 0x00015, 0x00004, 0x00010, 0x00004,
0x0000C, 0x00006, 0x0000A, 0x00006, 0x0021D, 0x00005, 0x0000B, 0x00004,
0x00015, 0x00004, 0x0000F, 0x00005, 0x0000D, 0x00005, 0x00009, 0x00006,
0x0021E, 0x00005, 0x0000B, 0x00005, 0x00014, 0x00005, 0x0000E, 0x00005,
0x0000D, 0x00005, 0x00008, 0x00006, 0x0021F, 0x00005, 0x0000B, 0x00005,
0x00014, 0x00005, 0x0000D, 0x00005, 0x0000F, 0x00004, 0x00007, 0x00005,
0x00221, 0x00005, 0x0000C, 0x00005, 0x0000C, 0x00005, 0x00003, 0x00005,
0x0000C, 0x00005, 0x00003, 0x00004, 0x00007, 0x00005, 0x00005, 0x00006,
0x00222, 0x00005, 0x0000C, 0x00006, 0x0000A, 0x00006, 0x00003, 0x00006,
0x0000A, 0x00006, 0x00003, 0x00005, 0x00006, 0x00005, 0x00004, 0x00006,
0x00223, 0x00005, 0x0000D, 0x00007, 0x00006, 0x00007, 0x00005, 0x00007,
0x00006, 0x00007, 0x00004, 0x00005, 0x00006, 0x00005, 0x00003, 0x00006,
0x00224, 0x0000D, 0x00006, 0x00012, 0x00007, 0x00012, 0x00006, 0x00006,
0x00002, 0x00006, 0x00004, 0x0000F, 0x0021B, 0x0000D, 0x00007, 0x00010,
0x00009, 0x00010, 0x00007, 0x0000D, 0x00005, 0x0000F, 0x0021B, 0x0000D,
0x00008, 0x0000E, 0x0000B, 0x0000E, 0x00009, 0x0000B, 0x00006, 0x0000F,
0x0021B, 0x0000D, 0x0000A, 0x0000A, 0x0000F, 0x0000A, 0x0000D, 0x00008,
0x00007, 0x0000F, 0x0B5C6, 0x0000D, 0x0003B, 0x00008, 0x0001E, 0x00004,
0x00035, 0x00006, 0x0000C, 0x00006, 0x0002B, 0x00005, 0x00004, 0x00004,
0x00189, 0x0000D, 0x00039, 0x0000C, 0x0001C, 0x00004, 0x00035, 0x00006,
0x0000C, 0x00006, 0x0002B, 0x00005, 0x00004, 0x00004, 0x00189, 0x0000D,
0x00038, 0x0000F, 0x0001A, 0x00004, 0x00035, 0x00007, 0x0000B, 0x00006,
0x0002B, 0x00005, 0x00004, 0x00004, 0x00189, 0x0000D, 0x00037, 0x00011,
0x00019, 0x00004, 0x00035, 0x00007, 0x0000A, 0x00007, 0x0002B, 0x00005,
0x00004, 0x00004, 0x00189, 0x0000D, 0x00036, 0x00007, 0x00004, 0x00008,
0x00018, 0x00004, 0x00035, 0x00007, 0x0000A, 0x00007, 0x00034, 0x00004,
0x0018E, 0x00004, 0x00039, 0x00006, 0x00008, 0x00007, 0x00017, 0x00004,
0x00035, 0x00008, 0x00009, 0x00007, 0x00034, 0x00004, 0x0018E, 0x00004,
0x00006, 0x00004, 0x00001, 0x00003, 0x00002, 0x00005, 0x00007, 0x00004,
0x00008, 0x00008, 0x00008, 0x00006, 0x0000B, 0x00005, 0x00008, 0x00007,
0x00008, 0x00004, 0x00009, 0x00007, 0x00008, 0x00004, 0x00001, 0x00003,
0x00015, 0x00008, 0x00008, 0x00008, 0x00009, 0x00007, 0x00008, 0x00004,
0x00002, 0x00007, 0x00006, 0x00005, 0x00002, 0x00008, 0x00008, 0x00007,
0x00008, 0x00004, 0x00001, 0x00003, 0x0016D, 0x00004, 0x00006, 0x00008,
0x00002, 0x00005, 0x00007, 0x00004, 0x00007, 0x0000A, 0x00007, 0x00005,
0x00017, 0x0000B, 0x00006, 0x00004, 0x00007, 0x0000B, 0x00006, 0x00008,
0x00015, 0x00008, 0x00008, 0x00008, 0x00007, 0x0000B, 0x00006, 0x0000E,
0x00005, 0x00005, 0x00002, 0x00008, 0x00006, 0x0000B, 0x00006, 0x00008,
0x0016D, 0x00004, 0x00006, 0x00008, 0x00002, 0x00005, 0x00007, 0x00004,
0x00005, 0x0000D, 0x00005, 0x00005, 0x00017, 0x0000D, 0x00005, 0x00004,
0x00006, 0x0000D, 0x00005, 0x00008, 0x00015, 0x00004, 0x00001, 0x00004,
0x00006, 0x00004, 0x00001, 0x00004, 0x00006, 0x0000D, 0x00005, 0x0000F,
0x00004, 0x00005, 0x00002, 0x00008, 0x00005, 0x0000D, 0x00005, 0x00008,
0x0016D, 0x00004, 0x00006, 0x00008, 0x00002, 0x00005, 0x00007, 0x00004,
0x00004, 0x0000F, 0x00004, 0x00005, 0x00016, 0x0000F, 0x00004, 0x00004,
0x00005, 0x0000F, 0x00004, 0x00008, 0x00015, 0x00004, 0x00001, 0x00004,
0x00006, 0x00004, 0x00001, 0x00004, 0x00005, 0x0000F, 0x00004, 0x0000F,
0x00004, 0x00005, 0x00002, 0x00008, 0x00004, 0x0000F, 0x00004, 0x00008,
0x0016D, 0x00004, 0x00006, 0x00006, 0x00004, 0x00005, 0x00007, 0x00004,
0x00004, 0x00005, 0x00006, 0x00005, 0x00003, 0x00005, 0x00015, 0x00006,
0x00005, 0x00006, 0x00003, 0x00004, 0x00004, 0x00006, 0x00005, 0x00006,
0x00003, 0x00006, 0x00017, 0x00004, 0x00002, 0x00004, 0x00005, 0x00004,
0x00001, 0x00004, 0x00004, 0x00006, 0x00005, 0x00006, 0x00003, 0x00006,
0x00005, 0x00005, 0x00003, 0x00005, 0x00004, 0x00004, 0x00005, 0x00006,
0x00005, 0x00006, 0x00003, 0x00006, 0x0016F, 0x00004, 0x00006, 0x00005,
0x00005, 0x00005, 0x00007, 0x00004, 0x00003, 0x00005, 0x00008, 0x00004,
0x00003, 0x00004, 0x00016, 0x00005, 0x00007, 0x00005, 0x00003, 0x00004,
0x00004, 0x00005, 0x00007, 0x00005, 0x00003, 0x00005, 0x00018, 0x00004,
0x00002, 0x00004, 0x00004, 0x00004, 0x00002, 0x00004, 0x00004, 0x00005,
0x00007, 0x00005, 0x00003, 0x00005, 0x00006, 0x00005, 0x00003, 0x00005,
0x00004, 0x00004, 0x00005, 0x00005, 0x00007, 0x00005, 0x00003, 0x00005,
0x00170, 0x00004, 0x00006, 0x00005, 0x00005, 0x00005, 0x00007, 0x00004,
0x00003, 0x00005, 0x00009, 0x00004, 0x00002, 0x00004, 0x00015, 0x00005,
0x00009, 0x00004, 0x00003, 0x00004, 0x00003, 0x00005, 0x00009, 0x00004,
0x00003, 0x00005, 0x00018, 0x00004, 0x00002, 0x00004, 0x00004, 0x00004,
0x00002, 0x00004, 0x00004, 0x00004, 0x00009, 0x00005, 0x00002, 0x00005,
0x00007, 0x00004, 0x00003, 0x00005, 0x00004, 0x00004, 0x00004, 0x00005,
0x00009, 0x00004, 0x00003, 0x00005, 0x00170, 0x00004, 0x00006, 0x00004,
0x00006, 0x00005, 0x00007, 0x00004, 0x00003, 0x00012, 0x00002, 0x00005,
0x00014, 0x00005, 0x00009, 0x00005, 0x00002, 0x00004, 0x00003, 0x00005,
0x00009, 0x00005, 0x00002, 0x00004, 0x00019, 0x00004, 0x00003, 0x00004,
0x00003, 0x00004, 0x00002, 0x00004, 0x00003, 0x00005, 0x00009, 0x00005,
0x00002, 0x00005, 0x00007, 0x00004, 0x00003, 0x00005, 0x00004, 0x00004,
0x00004, 0x00005, 0x00009, 0x00005, 0x00002, 0x00004, 0x00171, 0x00004,
0x00006, 0x00004, 0x00006, 0x00005, 0x00007, 0x00004, 0x00003, 0x00012,
0x00002, 0x00005, 0x00014, 0x00004, 0x0000A, 0x00005, 0x00002, 0x00004,
0x00003, 0x00004, 0x0000A, 0x00005, 0x00002, 0x00004, 0x00019, 0x00004,
0x00003, 0x00004, 0x00002, 0x00004, 0x00003, 0x00004, 0x00003, 0x00005,
0x0000A, 0x00004, 0x00002, 0x00005, 0x00007, 0x00004, 0x00003, 0x00005,
0x00004, 0x00004, 0x00004, 0x00004, 0x0000A, 0x00005, 0x00002, 0x00004,
0x00171, 0x00004, 0x00006, 0x00004, 0x00006, 0x00005, 0x00007, 0x00004,
0x00003, 0x00012, 0x00002, 0x00005, 0x00014, 0x00004, 0x0000A, 0x00005,
0x00002, 0x00004, 0x00003, 0x00004, 0x0000A, 0x00005, 0x00002, 0x00004,
0x00019, 0x00004, 0x00003, 0x00004, 0x00002, 0x00004, 0x00003, 0x00004,
0x00003, 0x00005, 0x0000A, 0x00004, 0x00002, 0x00005, 0x00007, 0x00004,
0x00003, 0x00005, 0x00004, 0x00004, 0x00004, 0x00004, 0x0000A, 0x00005,
0x00002, 0x00004, 0x00171, 0x00004, 0x00006, 0x00004, 0x00006, 0x00005,
0x00007, 0x00004, 0x00003, 0x00012, 0x00003, 0x00005, 0x00013, 0x00005,
0x00009, 0x00005, 0x00002, 0x00004, 0x00003, 0x00005, 0x00009, 0x00005,
0x00002, 0x00004, 0x00019, 0x00004, 0x00004, 0x00004, 0x00001, 0x00004,
0x00003, 0x00004, 0x00003, 0x00005, 0x00009, 0x00005, 0x00002, 0x00005,
0x00007, 0x00004, 0x00003, 0x00005, 0x00004, 0x00004, 0x00004, 0x00005,
0x00009, 0x00005, 0x00002, 0x00004, 0x00171, 0x00004, 0x00006, 0x00004,
0x00006, 0x00005, 0x00007, 0x00004, 0x00003, 0x00004, 0x00011, 0x00005,
0x0000C, 0x00005, 0x00002, 0x00005, 0x00009, 0x00004, 0x00003, 0x00004,
0x00003, 0x00005, 0x00009, 0x00004, 0x00003, 0x00004, 0x00019, 0x00004,
0x00004, 0x00008, 0x00004, 0x00004, 0x00004, 0x00004, 0x00009, 0x00005,
0x00002, 0x00005, 0x00007, 0x00004, 0x00003, 0x00005, 0x00004, 0x00004,
0x00004, 0x00005, 0x00009, 0x00004, 0x00003, 0x00004, 0x00171, 0x00004,
0x00006, 0x00004, 0x00006, 0x00005, 0x00006, 0x00005, 0x00003, 0x00005,
0x00011, 0x00006, 0x00009, 0x00006, 0x00003, 0x00004, 0x00008, 0x00005,
0x00003, 0x00004, 0x00004, 0x00004, 0x00008, 0x00005, 0x00003, 0x00004,
0x00019, 0x00004, 0x00004, 0x00008, 0x00004, 0x00004, 0x00004, 0x00005,
0x00008, 0x00005, 0x00002, 0x00005, 0x00007, 0x00004, 0x00003, 0x00005,
0x00004, 0x00004, 0x00005, 0x00004, 0x00008, 0x00005, 0x00003, 0x00004,
0x00171, 0x00004, 0x00006, 0x00004, 0x00007, 0x00005, 0x00005, 0x00005,
0x00004, 0x00005, 0x00006, 0x00005, 0x00005, 0x00008, 0x00005, 0x00007,
0x00004, 0x00005, 0x00006, 0x00006, 0x00003, 0x00004, 0x00004, 0x00005,
0x00006, 0x00006, 0x00003, 0x00004, 0x00019, 0x00004, 0x00005, 0x00007,
0x00004, 0x00004, 0x00004, 0x00006, 0x00006, 0x00005, 0x00003, 0x00005,
0x00007, 0x00004, 0x00003, 0x00005, 0x00004, 0x00004, 0x00005, 0x00005,
0x00006, 0x00006, 0x00003, 0x00004, 0x00171, 0x00004, 0x00006, 0x00004,
0x00007, 0x00006, 0x00002, 0x00007, 0x00004, 0x00007, 0x00002, 0x00007,
0x00006, 0x00012, 0x00006, 0x00006, 0x00002, 0x00007, 0x00004, 0x00004,
0x00005, 0x00006, 0x00002, 0x00007, 0x00004, 0x00004, 0x00019, 0x00004,
0x00005, 0x00006, 0x00005, 0x00004, 0x00005, 0x00007, 0x00002, 0x00006,
0x00004, 0x00005, 0x00007, 0x00004, 0x00003, 0x00005, 0x00004, 0x00004,
0x00006, 0x00006, 0x00002, 0x00007, 0x00004, 0x00004, 0x00171, 0x00004,
0x00006, 0x00004, 0x00007, 0x0000F, 0x00005, 0x0000E, 0x00008, 0x00010,
0x00008, 0x0000D, 0x00005, 0x00004, 0x00006, 0x0000D, 0x00005, 0x00004,
0x00019, 0x00004, 0x00005, 0x00006, 0x00005, 0x00004, 0x00006, 0x0000D,
0x00005, 0x00005, 0x00007, 0x00004, 0x00003, 0x00005, 0x00004, 0x00004,
0x00007, 0x0000D, 0x00005, 0x00004, 0x00171, 0x00004, 0x00006, 0x00004,
0x00008, 0x0000E, 0x00006, 0x0000C, 0x0000B, 0x0000D, 0x0000A, 0x0000B,
0x00006, 0x00004, 0x00007, 0x0000B, 0x00006, 0x00004, 0x00019, 0x00004,
0x00006, 0x00005, 0x00005, 0x00004, 0x00007, 0x0000B, 0x00006, 0x00005,
0x00007, 0x00004, 0x00003, 0x00005, 0x00004, 0x00004, 0x00008, 0x0000B,
0x00006, 0x00004, 0x00171, 0x00004, 0x00006, 0x00004, 0x00009, 0x00008,
0x00001, 0x00004, 0x00008, 0x00009, 0x0000D, 0x0000A, 0x0000D, 0x00009,
0x00007, 0x00004, 0x00008, 0x00009, 0x00007, 0x00004, 0x00019, 0x00004,
0x00006, 0x00004, 0x00006, 0x00004, 0x00008, 0x00009, 0x00007, 0x00005,
0x00007, 0x00004, 0x00003, 0x00005, 0x00004, 0x00004, 0x00009, 0x00009,
0x00007, 0x00004, 0x0C213, 0x00005, 0x0000F, 0x00003, 0x00009, 0x00007,
0x00035, 0x00003, 0x0000A, 0x00006, 0x0000B, 0x00007, 0x0002F, 0x00007,
0x0000C, 0x00006, 0x001B6, 0x00006, 0x0000E, 0x00004, 0x00008, 0x0000A,
0x00032, 0x00004, 0x00009, 0x00008, 0x00009, 0x0000A, 0x0002C, 0x00009,
0x00009, 0x0000A, 0x001B4, 0x00005, 0x0000E, 0x00005, 0x00007, 0x0000C,
0x00030, 0x00005, 0x00008, 0x0000A, 0x00007, 0x0000C, 0x0002A, 0x0000B,
0x00007, 0x0000C, 0x001B2, 0x00005, 0x0000F, 0x00005, 0x00006, 0x0000E,
0x0002F, 0x00005, 0x00007, 0x0000C, 0x00005, 0x0000E, 0x00029, 0x0000C,
0x00005, 0x0000E, 0x001B0, 0x00006, 0x0000E, 0x00006, 0x00006, 0x00005,
0x00004, 0x00005, 0x0002E, 0x00006, 0x00007, 0x00004, 0x00003, 0x00005,
0x00005, 0x00005, 0x00004, 0x00005, 0x00028, 0x00005, 0x00003, 0x00005,
0x00005, 0x00005, 0x00004, 0x00005, 0x001B0, 0x00005, 0x0000E, 0x00007,
0x00005, 0x00005, 0x00006, 0x00004, 0x0002D, 0x00007, 0x00006, 0x00005,
0x00004, 0x00004, 0x00004, 0x00005, 0x00006, 0x00004, 0x00028, 0x00005,
0x00003, 0x00005, 0x00004, 0x00005, 0x00006, 0x00004, 0x001AF, 0x00005,
0x0000F, 0x00007, 0x00005, 0x00005, 0x00006, 0x00005, 0x0000B, 0x00005,
0x00006, 0x00004, 0x00012, 0x00007, 0x00006, 0x00005, 0x00004, 0x00004,
0x00004, 0x00005, 0x00006, 0x00005, 0x0000B, 0x00005, 0x00006, 0x00004,
0x00016, 0x00004, 0x00004, 0x00005, 0x00006, 0x00005, 0x001AD, 0x00006,
0x0000E, 0x00008, 0x00005, 0x00004, 0x00007, 0x00005, 0x0000B, 0x00005,
0x00005, 0x00005, 0x00011, 0x00008, 0x00006, 0x00005, 0x00004, 0x00004,
0x00004, 0x00004, 0x00007, 0x00005, 0x0000B, 0x00005, 0x00005, 0x00005,
0x00015, 0x00005, 0x00004, 0x00004, 0x00007, 0x00005, 0x001AD, 0x00005,
0x0000E, 0x00009, 0x00005, 0x00004, 0x00007, 0x00005, 0x0000C, 0x00005,
0x00004, 0x00005, 0x00010, 0x00009, 0x00007, 0x00005, 0x00002, 0x00005,
0x00004, 0x00004, 0x00007, 0x00005, 0x0000C, 0x00005, 0x00004, 0x00005,
0x00013, 0x00007, 0x00004, 0x00004, 0x00007, 0x00005, 0x001AC, 0x0000B,
0x00009, 0x00004, 0x00001, 0x00004, 0x00005, 0x00004, 0x00007, 0x00005,
0x0000D, 0x00005, 0x00002, 0x00005, 0x00011, 0x00004, 0x00001, 0x00004,
0x00007, 0x0000C, 0x00004, 0x00004, 0x00007, 0x00005, 0x0000D, 0x00005,
0x00002, 0x00005, 0x00013, 0x00007, 0x00010, 0x00005, 0x001AB, 0x0000D,
0x00007, 0x00004, 0x00002, 0x00004, 0x00005, 0x00004, 0x00007, 0x00005,
0x0000D, 0x00005, 0x00001, 0x00005, 0x00011, 0x00004, 0x00002, 0x00004,
0x00008, 0x0000A, 0x00005, 0x00004, 0x00007, 0x00005, 0x0000D, 0x00005,
0x00001, 0x00005, 0x00014, 0x00007, 0x0000F, 0x00005, 0x001AC, 0x0000E,
0x00005, 0x00005, 0x00002, 0x00004, 0x00005, 0x00004, 0x00007, 0x00005,
0x0000E, 0x0000A, 0x00010, 0x00005, 0x00002, 0x00004, 0x00007, 0x0000B,
0x00005, 0x00004, 0x00007, 0x00005, 0x0000E, 0x0000A, 0x00014, 0x00008,
0x0000D, 0x00006, 0x001AB, 0x00007, 0x00002, 0x00006, 0x00005, 0x00004,
0x00003, 0x00004, 0x00005, 0x00004, 0x00007, 0x00005, 0x0000F, 0x00008,
0x00011, 0x00004, 0x00003, 0x00004, 0x00006, 0x0000D, 0x00004, 0x00004,
0x00007, 0x00005, 0x0000F, 0x00008, 0x00015, 0x00009, 0x0000B, 0x00006,
0x001AC, 0x00005, 0x00006, 0x00005, 0x00003, 0x00004, 0x00004, 0x00004,
0x00005, 0x00004, 0x00007, 0x00005, 0x0000F, 0x00007, 0x00011, 0x00004,
0x00004, 0x00004, 0x00006, 0x00005, 0x00003, 0x00006, 0x00003, 0x00004,
0x00007, 0x00005, 0x0000F, 0x00007, 0x0001A, 0x00005, 0x0000A, 0x00006,
0x001AD, 0x00005, 0x00006, 0x00005, 0x00002, 0x00005, 0x00004, 0x00004,
0x00005, 0x00004, 0x00007, 0x00005, 0x00010, 0x00006, 0x00010, 0x00005,
0x00004, 0x00004, 0x00005, 0x00005, 0x00005, 0x00005, 0x00003, 0x00004,
0x00007, 0x00005, 0x00010, 0x00006, 0x0001B, 0x00005, 0x00008, 0x00006,
0x001AE, 0x00004, 0x00008, 0x00004, 0x00002, 0x00004, 0x00005, 0x00004,
0x00005, 0x00004, 0x00007, 0x00005, 0x00010, 0x00006, 0x00010, 0x00004,
0x00005, 0x00004, 0x00005, 0x00005, 0x00006, 0x00005, 0x00002, 0x00004,
0x00007, 0x00005, 0x00010, 0x00006, 0x0001B, 0x00005, 0x00007, 0x00006,
0x001AF, 0x00004, 0x00008, 0x00004, 0x00001, 0x00005, 0x00005, 0x00005,
0x00004, 0x00004, 0x00007, 0x00005, 0x0000F, 0x00008, 0x0000E, 0x00005,
0x00005, 0x00005, 0x00004, 0x00004, 0x00007, 0x00005, 0x00002, 0x00004,
0x00007, 0x00005, 0x0000F, 0x00008, 0x0001A, 0x00005, 0x00006, 0x00006,
0x001B0, 0x00004, 0x00007, 0x00005, 0x00001, 0x00011, 0x00002, 0x00005,
0x00006, 0x00005, 0x0000E, 0x00009, 0x0000E, 0x00011, 0x00002, 0x00004,
0x00007, 0x00005, 0x00002, 0x00005, 0x00006, 0x00005, 0x0000E, 0x00009,
0x0000F, 0x00004, 0x00007, 0x00005, 0x00005, 0x00006, 0x001B1, 0x00005,
0x00006, 0x00005, 0x00001, 0x00011, 0x00002, 0x00005, 0x00006, 0x00005,
0x0000E, 0x0000A, 0x0000D, 0x00011, 0x00002, 0x00005, 0x00006, 0x00005,
0x00002, 0x00005, 0x00006, 0x00005, 0x0000E, 0x0000A, 0x0000E, 0x00004,
0x00007, 0x00005, 0x00004, 0x00006, 0x001B2, 0x00005, 0x00006, 0x00004,
0x00002, 0x00011, 0x00002, 0x00005, 0x00005, 0x00005, 0x0000E, 0x00005,
0x00002, 0x00005, 0x0000C, 0x00011, 0x00002, 0x00005, 0x00005, 0x00005,
0x00003, 0x00005, 0x00005, 0x00005, 0x0000E, 0x00005, 0x00002, 0x00005,
0x0000D, 0x00005, 0x00005, 0x00005, 0x00004, 0x00006, 0x001B4, 0x00006,
0x00002, 0x00006, 0x0000C, 0x00005, 0x00005, 0x00006, 0x00002, 0x00006,
0x0000D, 0x00005, 0x00003, 0x00005, 0x00016, 0x00005, 0x00005, 0x00006,
0x00002, 0x00006, 0x00004, 0x00006, 0x00002, 0x00006, 0x0000D, 0x00005,
0x00003, 0x00005, 0x0000D, 0x00007, 0x00002, 0x00006, 0x00003, 0x00010,
0x001AB, 0x0000D, 0x0000D, 0x00004, 0x00007, 0x0000C, 0x0000E, 0x00005,
0x00004, 0x00005, 0x00015, 0x00004, 0x00007, 0x0000C, 0x00006, 0x0000C,
0x0000E, 0x00005, 0x00004, 0x00005, 0x0000D, 0x0000D, 0x00004, 0x00010,
0x001AC, 0x0000B, 0x0000E, 0x00004, 0x00007, 0x0000B, 0x0000E, 0x00005,
0x00005, 0x00006, 0x00014, 0x00004, 0x00008, 0x0000A, 0x00007, 0x0000B,
0x0000E, 0x00005, 0x00005, 0x00006, 0x0000D, 0x0000B, 0x00005, 0x00010,
0x001AE, 0x00008, 0x0000F, 0x00004, 0x00009, 0x00008, 0x0000E, 0x00006,
0x00006, 0x00005, 0x00014, 0x00004, 0x00009, 0x00008, 0x0000A, 0x00008,
0x0000E, 0x00006, 0x00006, 0x00005, 0x0000E, 0x00009, 0x00006, 0x00010,
0x154DC
/eco32/trunk/sim/mmu.h
0,0 → 1,56
/*
* mmu.h -- MMU simulation
*/
 
 
#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, Bool userMode);
Half mmuReadHalf(Word vAddr, Bool userMode);
Byte mmuReadByte(Word vAddr, Bool userMode);
void mmuWriteWord(Word vAddr, Word data, Bool userMode);
void mmuWriteHalf(Word vAddr, Half data, Bool userMode);
void mmuWriteByte(Word vAddr, Byte data, Bool userMode);
 
Word mmuGetIndex(void);
void mmuSetIndex(Word value);
Word mmuGetEntryHi(void);
void mmuSetEntryHi(Word value);
Word mmuGetEntryLo(void);
void mmuSetEntryLo(Word value);
Word mmuGetBadAddr(void);
void mmuSetBadAddr(Word value);
 
void mmuTbs(void);
void mmuTbwr(void);
void mmuTbri(void);
void mmuTbwi(void);
 
TLB_Entry mmuGetTLB(int index);
void mmuSetTLB(int index, TLB_Entry tlbEntry);
 
void mmuReset(void);
void mmuInit(void);
void mmuExit(void);
 
 
#endif /* _MMU_H_ */
/eco32/trunk/sim/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_ */
/eco32/trunk/sim/output.h
0,0 → 1,18
/*
* output.h -- output to file on host system
*/
 
 
#ifndef _OUTPUT_H_
#define _OUTPUT_H_
 
 
Word outputRead(Word addr);
void outputWrite(Word addr, Word data);
 
void outputReset(void);
void outputInit(char *outputFileName);
void outputExit(void);
 
 
#endif /* _OUTPUT_H_ */
/eco32/trunk/sim/getline/testgl.c
0,0 → 1,17
#include <stdio.h>
#include "getline.h"
 
main()
/*
* just echo user input lines, letting user edit them and move through
* history list
*/
{
char *p;
 
do {
p = gl_getline("PROMPT>>>> ");
gl_histadd(p);
fputs(p, stdout);
} while (*p != 0);
}
/eco32/trunk/sim/getline/getline.c
0,0 → 1,1125
#ifndef lint
static char rcsid[] =
"$Id: getline.c,v 3.11 1993/12/02 15:54:31 thewalt Exp thewalt $";
static char *copyright = "Copyright (C) 1991, 1992, 1993, Chris Thewalt";
#endif
 
/*
* Copyright (C) 1991, 1992, 1993 by Chris Thewalt (thewalt@ce.berkeley.edu)
*
* Permission to use, copy, modify, and distribute this software
* for any purpose and without fee is hereby granted, provided
* that the above copyright notices appear in all copies and that both the
* copyright notice and this permission notice appear in supporting
* documentation. This software is provided "as is" without express or
* implied warranty.
*
* Thanks to the following people who have provided enhancements and fixes:
* Ron Ueberschaer, Christoph Keller, Scott Schwartz, Steven List,
* DaviD W. Sanderson, Goran Bostrom, Michael Gleason, Glenn Kasten,
* Edin Hodzic, Eric J Bivona, Kai Uwe Rommel, Danny Quah, Ulrich Betzler
*/
 
#include "getline.h"
static int gl_tab(); /* forward reference needed for gl_tab_hook */
 
/******************** imported interface *********************************/
 
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <signal.h>
 
extern int isatty();
extern void *malloc();
extern void free();
 
/********************* exported interface ********************************/
 
char *gl_getline(); /* read a line of input */
void gl_setwidth(); /* specify width of screen */
void gl_histadd(); /* adds entries to hist */
void gl_strwidth(); /* to bind gl_strlen */
 
int (*gl_in_hook)() = 0;
int (*gl_out_hook)() = 0;
int (*gl_tab_hook)() = gl_tab;
 
/******************** internal interface *********************************/
 
#define BUF_SIZE 1024
 
static int gl_init_done = -1; /* terminal mode flag */
static int gl_termw = 80; /* actual terminal width */
static int gl_scroll = 27; /* width of EOL scrolling region */
static int gl_width = 0; /* net size available for input */
static int gl_extent = 0; /* how far to redraw, 0 means all */
static int gl_overwrite = 0; /* overwrite mode */
static int gl_pos, gl_cnt = 0; /* position and size of input */
static char gl_buf[BUF_SIZE]; /* input buffer */
static char gl_killbuf[BUF_SIZE]=""; /* killed text */
static char *gl_prompt; /* to save the prompt string */
static char gl_intrc = 0; /* keyboard SIGINT char */
static char gl_quitc = 0; /* keyboard SIGQUIT char */
static char gl_suspc = 0; /* keyboard SIGTSTP char */
static char gl_dsuspc = 0; /* delayed SIGTSTP char */
static int gl_search_mode = 0; /* search mode flag */
 
static void gl_init(); /* prepare to edit a line */
static void gl_cleanup(); /* to undo gl_init */
static void gl_char_init(); /* get ready for no echo input */
static void gl_char_cleanup(); /* undo gl_char_init */
static size_t (*gl_strlen)() = (size_t(*)())strlen;
/* returns printable prompt width */
 
static void gl_addchar(); /* install specified char */
static void gl_del(); /* del, either left (-1) or cur (0) */
static void gl_error(); /* write error msg and die */
static void gl_fixup(); /* fixup state variables and screen */
static int gl_getc(); /* read one char from terminal */
static void gl_kill(); /* delete to EOL */
static void gl_newline(); /* handle \n or \r */
static void gl_putc(); /* write one char to terminal */
static void gl_puts(); /* write a line to terminal */
static void gl_redraw(); /* issue \n and redraw all */
static void gl_transpose(); /* transpose two chars */
static void gl_yank(); /* yank killed text */
static void gl_word(); /* move a word */
 
static void hist_init(); /* initializes hist pointers */
static char *hist_next(); /* return ptr to next item */
static char *hist_prev(); /* return ptr to prev item */
static char *hist_save(); /* makes copy of a string, without NL */
 
static void search_addchar(); /* increment search string */
static void search_term(); /* reset with current contents */
static void search_back(); /* look back for current string */
static void search_forw(); /* look forw for current string */
 
/************************ nonportable part *********************************/
 
extern int write();
extern void exit();
 
#ifdef unix
#ifndef __unix__
#define __unix__
#endif /* not __unix__ */
#endif /* unix */
 
#ifdef _IBMR2
#ifndef __unix__
#define __unix__
#endif
#endif
 
#ifdef __GO32__
#include <pc.h>
#undef MSDOS
#undef __unix__
#endif
 
#ifdef MSDOS
#include <bios.h>
#endif
 
#ifdef __unix__
#ifndef __convexc__
extern int read();
extern int kill();
extern int ioctl();
#endif /* not __convexc__ */
#ifdef POSIX /* use POSIX interface */
#include <termios.h>
struct termios new_termios, old_termios;
#else /* not POSIX */
#include <sys/ioctl.h>
#ifdef M_XENIX /* does not really use bsd terminal interface */
#undef TIOCSETN
#endif /* M_XENIX */
#ifdef TIOCSETN /* use BSD interface */
#include <sgtty.h>
struct sgttyb new_tty, old_tty;
struct tchars tch;
struct ltchars ltch;
#else /* use SYSV interface */
#include <termio.h>
struct termio new_termio, old_termio;
#endif /* TIOCSETN */
#endif /* POSIX */
#endif /* __unix__ */
 
#ifdef vms
#include <descrip.h>
#include <ttdef.h>
#include <iodef.h>
#include unixio
static int setbuff[2]; /* buffer to set terminal attributes */
static short chan = -1; /* channel to terminal */
struct dsc$descriptor_s descrip; /* VMS descriptor */
#endif
 
static void
gl_char_init() /* turn off input echo */
{
#ifdef __unix__
#ifdef POSIX
tcgetattr(0, &old_termios);
gl_intrc = old_termios.c_cc[VINTR];
gl_quitc = old_termios.c_cc[VQUIT];
#ifdef VSUSP
gl_suspc = old_termios.c_cc[VSUSP];
#endif
#ifdef VDSUSP
gl_dsuspc = old_termios.c_cc[VDSUSP];
#endif
new_termios = old_termios;
new_termios.c_iflag &= ~(BRKINT|ISTRIP|IXON|IXOFF);
new_termios.c_iflag |= (IGNBRK|IGNPAR);
new_termios.c_lflag &= ~(ICANON|ISIG|IEXTEN|ECHO);
new_termios.c_cc[VMIN] = 1;
new_termios.c_cc[VTIME] = 0;
tcsetattr(0, TCSANOW, &new_termios);
#else /* not POSIX */
#ifdef TIOCSETN /* BSD */
ioctl(0, TIOCGETC, &tch);
ioctl(0, TIOCGLTC, &ltch);
gl_intrc = tch.t_intrc;
gl_quitc = tch.t_quitc;
gl_suspc = ltch.t_suspc;
gl_dsuspc = ltch.t_dsuspc;
ioctl(0, TIOCGETP, &old_tty);
new_tty = old_tty;
new_tty.sg_flags |= RAW;
new_tty.sg_flags &= ~ECHO;
ioctl(0, TIOCSETN, &new_tty);
#else /* SYSV */
ioctl(0, TCGETA, &old_termio);
gl_intrc = old_termio.c_cc[VINTR];
gl_quitc = old_termio.c_cc[VQUIT];
new_termio = old_termio;
new_termio.c_iflag &= ~(BRKINT|ISTRIP|IXON|IXOFF);
new_termio.c_iflag |= (IGNBRK|IGNPAR);
new_termio.c_lflag &= ~(ICANON|ISIG|ECHO);
new_termio.c_cc[VMIN] = 1;
new_termio.c_cc[VTIME] = 0;
ioctl(0, TCSETA, &new_termio);
#endif /* TIOCSETN */
#endif /* POSIX */
#endif /* __unix__ */
 
#ifdef vms
descrip.dsc$w_length = strlen("tt:");
descrip.dsc$b_dtype = DSC$K_DTYPE_T;
descrip.dsc$b_class = DSC$K_CLASS_S;
descrip.dsc$a_pointer = "tt:";
(void)sys$assign(&descrip,&chan,0,0);
(void)sys$qiow(0,chan,IO$_SENSEMODE,0,0,0,setbuff,8,0,0,0,0);
setbuff[1] |= TT$M_NOECHO;
(void)sys$qiow(0,chan,IO$_SETMODE,0,0,0,setbuff,8,0,0,0,0);
#endif /* vms */
}
 
static void
gl_char_cleanup() /* undo effects of gl_char_init */
{
#ifdef __unix__
#ifdef POSIX
tcsetattr(0, TCSANOW, &old_termios);
#else /* not POSIX */
#ifdef TIOCSETN /* BSD */
ioctl(0, TIOCSETN, &old_tty);
#else /* SYSV */
ioctl(0, TCSETA, &old_termio);
#endif /* TIOCSETN */
#endif /* POSIX */
#endif /* __unix__ */
 
#ifdef vms
setbuff[1] &= ~TT$M_NOECHO;
(void)sys$qiow(0,chan,IO$_SETMODE,0,0,0,setbuff,8,0,0,0,0);
sys$dassgn(chan);
chan = -1;
#endif
}
 
#if MSDOS || __EMX__ || __GO32__
int pc_keymap(c)
int c;
{
switch (c) {
case 72: c = 16; /* up -> ^P */
break;
case 80: c = 14; /* down -> ^N */
break;
case 75: c = 2; /* left -> ^B */
break;
case 77: c = 6; /* right -> ^F */
break;
default: c = 0; /* make it garbage */
}
return c;
}
#endif /* MSDOS || __EMX__ || __GO32__ */
 
static int
gl_getc()
/* get a character without echoing it to screen */
{
int c;
#ifdef __unix__
char ch;
#endif
 
#ifdef __unix__
while ((c = read(0, &ch, 1)) == -1) {
if (errno != EINTR)
break;
}
c = (ch <= 0)? -1 : ch;
#endif /* __unix__ */
#ifdef MSDOS
c = _bios_keybrd(_NKEYBRD_READ);
#endif /* MSDOS */
#ifdef __GO32__
c = getkey () ;
if (c > 255) c = pc_keymap(c & 0377);
#endif /* __GO32__ */
#ifdef __TURBOC__
while(!bioskey(1))
;
c = bioskey(0);
#endif
#if MSDOS || __TURBOC__
if ((c & 0377) == 224) {
c = pc_keymap((c >> 8) & 0377);
} else {
c &= 0377;
}
#endif /* MSDOS || __TURBOC__ */
#ifdef __EMX__
c = _read_kbd(0, 1, 0);
if (c == 224 || c == 0) {
c = pc_keymap(_read_kbd(0, 1, 0));
} else {
c &= 0377;
}
#endif
#ifdef vms
if(chan < 0) {
c='\0';
}
(void)sys$qiow(0,chan,IO$_TTYREADALL,0,0,0,&c,1,0,0,0,0);
c &= 0177; /* get a char */
#endif
return c;
}
 
static void
gl_putc(c)
int c;
{
char ch = c;
 
write(1, &ch, 1);
if (ch == '\n') {
ch = '\r';
write(1, &ch, 1); /* RAW mode needs '\r', does not hurt */
}
}
 
/******************** fairly portable part *********************************/
 
static void
gl_puts(buf)
char *buf;
{
int len;
if (buf) {
len = strlen(buf);
write(1, buf, len);
}
}
 
static void
gl_error(buf)
char *buf;
{
int len = strlen(buf);
 
gl_cleanup();
write(2, buf, len);
exit(1);
}
 
static void
gl_init()
/* set up variables and terminal */
{
if (gl_init_done < 0) { /* -1 only on startup */
hist_init();
}
if (isatty(0) == 0 || isatty(1) == 0)
gl_error("\n*** Error: getline(): not interactive, use stdio.\n");
gl_char_init();
gl_init_done = 1;
}
 
static void
gl_cleanup()
/* undo effects of gl_init, as necessary */
{
if (gl_init_done > 0)
gl_char_cleanup();
gl_init_done = 0;
}
 
void
gl_setwidth(w)
int w;
{
if (w > 20) {
gl_termw = w;
gl_scroll = w / 3;
} else {
gl_error("\n*** Error: minimum screen width is 21\n");
}
}
 
char *
gl_getline(prompt)
char *prompt;
{
int c, loc, tmp;
 
#ifdef __unix__
int sig;
#endif
 
gl_init();
gl_prompt = (prompt)? prompt : "";
gl_buf[0] = 0;
if (gl_in_hook)
gl_in_hook(gl_buf);
gl_fixup(gl_prompt, -2, BUF_SIZE);
while ((c = gl_getc()) >= 0) {
gl_extent = 0; /* reset to full extent */
if (isprint(c)) {
if (gl_search_mode)
search_addchar(c);
else
gl_addchar(c);
} else {
if (gl_search_mode) {
if (c == '\033' || c == '\016' || c == '\020') {
search_term();
c = 0; /* ignore the character */
} else if (c == '\010' || c == '\177') {
search_addchar(-1); /* unwind search string */
c = 0;
} else if (c != '\022' && c != '\023') {
search_term(); /* terminate and handle char */
}
}
switch (c) {
case '\n': case '\r': /* newline */
gl_newline();
gl_cleanup();
return gl_buf;
/*NOTREACHED*/
break;
case '\001': gl_fixup(gl_prompt, -1, 0); /* ^A */
break;
case '\002': gl_fixup(gl_prompt, -1, gl_pos-1); /* ^B */
break;
case '\004': /* ^D */
if (gl_cnt == 0) {
gl_buf[0] = 0;
gl_cleanup();
gl_putc('\n');
return gl_buf;
} else {
gl_del(0);
}
break;
case '\005': gl_fixup(gl_prompt, -1, gl_cnt); /* ^E */
break;
case '\006': gl_fixup(gl_prompt, -1, gl_pos+1); /* ^F */
break;
case '\010': case '\177': gl_del(-1); /* ^H and DEL */
break;
case '\t': /* TAB */
if (gl_tab_hook) {
tmp = gl_pos;
loc = gl_tab_hook(gl_buf, gl_strlen(gl_prompt), &tmp);
if (loc >= 0 || tmp != gl_pos)
gl_fixup(gl_prompt, loc, tmp);
}
break;
case '\013': gl_kill(gl_pos); /* ^K */
break;
case '\014': gl_redraw(); /* ^L */
break;
case '\016': /* ^N */
strcpy(gl_buf, hist_next());
if (gl_in_hook)
gl_in_hook(gl_buf);
gl_fixup(gl_prompt, 0, BUF_SIZE);
break;
case '\017': gl_overwrite = !gl_overwrite; /* ^O */
break;
case '\020': /* ^P */
strcpy(gl_buf, hist_prev());
if (gl_in_hook)
gl_in_hook(gl_buf);
gl_fixup(gl_prompt, 0, BUF_SIZE);
break;
case '\022': search_back(1); /* ^R */
break;
case '\023': search_forw(1); /* ^S */
break;
case '\024': gl_transpose(); /* ^T */
break;
case '\025': gl_kill(0); /* ^U */
break;
case '\031': gl_yank(); /* ^Y */
break;
case '\033': /* ansi arrow keys */
c = gl_getc();
if (c == '[') {
switch(c = gl_getc()) {
case 'A': /* up */
strcpy(gl_buf, hist_prev());
if (gl_in_hook)
gl_in_hook(gl_buf);
gl_fixup(gl_prompt, 0, BUF_SIZE);
break;
case 'B': /* down */
strcpy(gl_buf, hist_next());
if (gl_in_hook)
gl_in_hook(gl_buf);
gl_fixup(gl_prompt, 0, BUF_SIZE);
break;
case 'C': gl_fixup(gl_prompt, -1, gl_pos+1); /* right */
break;
case 'D': gl_fixup(gl_prompt, -1, gl_pos-1); /* left */
break;
default: gl_putc('\007'); /* who knows */
break;
}
} else if (c == 'f' || c == 'F') {
gl_word(1);
} else if (c == 'b' || c == 'B') {
gl_word(-1);
} else
gl_putc('\007');
break;
default: /* check for a terminal signal */
#ifdef __unix__
if (c > 0) { /* ignore 0 (reset above) */
sig = 0;
#ifdef SIGINT
if (c == gl_intrc)
sig = SIGINT;
#endif
#ifdef SIGQUIT
if (c == gl_quitc)
sig = SIGQUIT;
#endif
#ifdef SIGTSTP
if (c == gl_suspc || c == gl_dsuspc)
sig = SIGTSTP;
#endif
if (sig != 0) {
gl_cleanup();
kill(0, sig);
gl_init();
gl_redraw();
c = 0;
}
}
#endif /* __unix__ */
if (c > 0)
gl_putc('\007');
break;
}
}
}
gl_cleanup();
gl_buf[0] = 0;
return gl_buf;
}
 
static void
gl_addchar(c)
int c;
/* adds the character c to the input buffer at current location */
{
int i;
 
if (gl_cnt >= BUF_SIZE - 1)
gl_error("\n*** Error: getline(): input buffer overflow\n");
if (gl_overwrite == 0 || gl_pos == gl_cnt) {
for (i=gl_cnt; i >= gl_pos; i--)
gl_buf[i+1] = gl_buf[i];
gl_buf[gl_pos] = c;
gl_fixup(gl_prompt, gl_pos, gl_pos+1);
} else {
gl_buf[gl_pos] = c;
gl_extent = 1;
gl_fixup(gl_prompt, gl_pos, gl_pos+1);
}
}
 
static void
gl_yank()
/* adds the kill buffer to the input buffer at current location */
{
int i, len;
 
len = strlen(gl_killbuf);
if (len > 0) {
if (gl_overwrite == 0) {
if (gl_cnt + len >= BUF_SIZE - 1)
gl_error("\n*** Error: getline(): input buffer overflow\n");
for (i=gl_cnt; i >= gl_pos; i--)
gl_buf[i+len] = gl_buf[i];
for (i=0; i < len; i++)
gl_buf[gl_pos+i] = gl_killbuf[i];
gl_fixup(gl_prompt, gl_pos, gl_pos+len);
} else {
if (gl_pos + len > gl_cnt) {
if (gl_pos + len >= BUF_SIZE - 1)
gl_error("\n*** Error: getline(): input buffer overflow\n");
gl_buf[gl_pos + len] = 0;
}
for (i=0; i < len; i++)
gl_buf[gl_pos+i] = gl_killbuf[i];
gl_extent = len;
gl_fixup(gl_prompt, gl_pos, gl_pos+len);
}
} else
gl_putc('\007');
}
 
static void
gl_transpose()
/* switch character under cursor and to left of cursor */
{
int c;
 
if (gl_pos > 0 && gl_cnt > gl_pos) {
c = gl_buf[gl_pos-1];
gl_buf[gl_pos-1] = gl_buf[gl_pos];
gl_buf[gl_pos] = c;
gl_extent = 2;
gl_fixup(gl_prompt, gl_pos-1, gl_pos);
} else
gl_putc('\007');
}
 
static void
gl_newline()
/*
* Cleans up entire line before returning to caller. A \n is appended.
* If line longer than screen, we redraw starting at beginning
*/
{
int change = gl_cnt;
int len = gl_cnt;
int loc = gl_width - 5; /* shifts line back to start position */
 
if (gl_cnt >= BUF_SIZE - 1)
gl_error("\n*** Error: getline(): input buffer overflow\n");
if (gl_out_hook) {
change = gl_out_hook(gl_buf);
len = strlen(gl_buf);
}
if (loc > len)
loc = len;
gl_fixup(gl_prompt, change, loc); /* must do this before appending \n */
gl_buf[len] = '\n';
gl_buf[len+1] = '\0';
gl_putc('\n');
}
 
static void
gl_del(loc)
int loc;
/*
* Delete a character. The loc variable can be:
* -1 : delete character to left of cursor
* 0 : delete character under cursor
*/
{
int i;
 
if ((loc == -1 && gl_pos > 0) || (loc == 0 && gl_pos < gl_cnt)) {
for (i=gl_pos+loc; i < gl_cnt; i++)
gl_buf[i] = gl_buf[i+1];
gl_fixup(gl_prompt, gl_pos+loc, gl_pos+loc);
} else
gl_putc('\007');
}
 
static void
gl_kill(pos)
int pos;
/* delete from pos to the end of line */
{
if (pos < gl_cnt) {
strcpy(gl_killbuf, gl_buf + pos);
gl_buf[pos] = '\0';
gl_fixup(gl_prompt, pos, pos);
} else
gl_putc('\007');
}
 
static void
gl_word(direction)
int direction;
/* move forward or backword one word */
{
int pos = gl_pos;
 
if (direction > 0) { /* forward */
while (!isspace(gl_buf[pos]) && pos < gl_cnt)
pos++;
while (isspace(gl_buf[pos]) && pos < gl_cnt)
pos++;
} else { /* backword */
if (pos > 0)
pos--;
while (isspace(gl_buf[pos]) && pos > 0)
pos--;
while (!isspace(gl_buf[pos]) && pos > 0)
pos--;
if (pos < gl_cnt && isspace(gl_buf[pos])) /* move onto word */
pos++;
}
gl_fixup(gl_prompt, -1, pos);
}
 
static void
gl_redraw()
/* emit a newline, reset and redraw prompt and current input line */
{
if (gl_init_done > 0) {
gl_putc('\n');
gl_fixup(gl_prompt, -2, gl_pos);
}
}
 
static void
gl_fixup(prompt, change, cursor)
char *prompt;
int change, cursor;
/*
* This function is used both for redrawing when input changes or for
* moving within the input line. The parameters are:
* prompt: compared to last_prompt[] for changes;
* change : the index of the start of changes in the input buffer,
* with -1 indicating no changes, -2 indicating we're on
* a new line, redraw everything.
* cursor : the desired location of the cursor after the call.
* A value of BUF_SIZE can be used to indicate the cursor should
* move just past the end of the input line.
*/
{
static int gl_shift; /* index of first on screen character */
static int off_right; /* true if more text right of screen */
static int off_left; /* true if more text left of screen */
static char last_prompt[80] = "";
int left = 0, right = -1; /* bounds for redraw */
int pad; /* how much to erase at end of line */
int backup; /* how far to backup before fixing */
int new_shift; /* value of shift based on cursor */
int extra; /* adjusts when shift (scroll) happens */
int i;
int new_right = -1; /* alternate right bound, using gl_extent */
int l1, l2;
 
if (change == -2) { /* reset */
gl_pos = gl_cnt = gl_shift = off_right = off_left = 0;
gl_putc('\r');
gl_puts(prompt);
strcpy(last_prompt, prompt);
change = 0;
gl_width = gl_termw - gl_strlen(prompt);
} else if (strcmp(prompt, last_prompt) != 0) {
l1 = gl_strlen(last_prompt);
l2 = gl_strlen(prompt);
gl_cnt = gl_cnt + l1 - l2;
strcpy(last_prompt, prompt);
gl_putc('\r');
gl_puts(prompt);
gl_pos = gl_shift;
gl_width = gl_termw - l2;
change = 0;
}
pad = (off_right)? gl_width - 1 : gl_cnt - gl_shift; /* old length */
backup = gl_pos - gl_shift;
if (change >= 0) {
gl_cnt = strlen(gl_buf);
if (change > gl_cnt)
change = gl_cnt;
}
if (cursor > gl_cnt) {
if (cursor != BUF_SIZE) /* BUF_SIZE means end of line */
gl_putc('\007');
cursor = gl_cnt;
}
if (cursor < 0) {
gl_putc('\007');
cursor = 0;
}
if (off_right || (off_left && cursor < gl_shift + gl_width - gl_scroll / 2))
extra = 2; /* shift the scrolling boundary */
else
extra = 0;
new_shift = cursor + extra + gl_scroll - gl_width;
if (new_shift > 0) {
new_shift /= gl_scroll;
new_shift *= gl_scroll;
} else
new_shift = 0;
if (new_shift != gl_shift) { /* scroll occurs */
gl_shift = new_shift;
off_left = (gl_shift)? 1 : 0;
off_right = (gl_cnt > gl_shift + gl_width - 1)? 1 : 0;
left = gl_shift;
new_right = right = (off_right)? gl_shift + gl_width - 2 : gl_cnt;
} else if (change >= 0) { /* no scroll, but text changed */
if (change < gl_shift + off_left) {
left = gl_shift;
} else {
left = change;
backup = gl_pos - change;
}
off_right = (gl_cnt > gl_shift + gl_width - 1)? 1 : 0;
right = (off_right)? gl_shift + gl_width - 2 : gl_cnt;
new_right = (gl_extent && (right > left + gl_extent))?
left + gl_extent : right;
}
pad -= (off_right)? gl_width - 1 : gl_cnt - gl_shift;
pad = (pad < 0)? 0 : pad;
if (left <= right) { /* clean up screen */
for (i=0; i < backup; i++)
gl_putc('\b');
if (left == gl_shift && off_left) {
gl_putc('$');
left++;
}
for (i=left; i < new_right; i++)
gl_putc(gl_buf[i]);
gl_pos = new_right;
if (off_right && new_right == right) {
gl_putc('$');
gl_pos++;
} else {
for (i=0; i < pad; i++) /* erase remains of prev line */
gl_putc(' ');
gl_pos += pad;
}
}
i = gl_pos - cursor; /* move to final cursor location */
if (i > 0) {
while (i--)
gl_putc('\b');
} else {
for (i=gl_pos; i < cursor; i++)
gl_putc(gl_buf[i]);
}
gl_pos = cursor;
}
 
static int
gl_tab(buf, offset, loc)
char *buf;
int offset;
int *loc;
/* default tab handler, acts like tabstops every 8 cols */
{
int i, count, len;
 
len = strlen(buf);
count = 8 - (offset + *loc) % 8;
for (i=len; i >= *loc; i--)
buf[i+count] = buf[i];
for (i=0; i < count; i++)
buf[*loc+i] = ' ';
i = *loc;
*loc = i + count;
return i;
}
 
/******************* strlen stuff **************************************/
 
void gl_strwidth(func)
size_t (*func)();
{
if (func != 0) {
gl_strlen = func;
}
}
 
/******************* History stuff **************************************/
 
#ifndef HIST_SIZE
#define HIST_SIZE 100
#endif
 
static int hist_pos = 0, hist_last = 0;
static char *hist_buf[HIST_SIZE];
 
static void
hist_init()
{
int i;
 
hist_buf[0] = "";
for (i=1; i < HIST_SIZE; i++)
hist_buf[i] = (char *)0;
}
 
void
gl_histadd(buf)
char *buf;
{
static char *prev = 0;
char *p = buf;
int len;
 
/* in case we call gl_histadd() before we call gl_getline() */
if (gl_init_done < 0) { /* -1 only on startup */
hist_init();
gl_init_done = 0;
}
while (*p == ' ' || *p == '\t' || *p == '\n')
p++;
if (*p) {
len = strlen(buf);
if (strchr(p, '\n')) /* previously line already has NL stripped */
len--;
if (prev == 0 || strlen(prev) != len ||
strncmp(prev, buf, len) != 0) {
hist_buf[hist_last] = hist_save(buf);
prev = hist_buf[hist_last];
hist_last = (hist_last + 1) % HIST_SIZE;
if (hist_buf[hist_last] && *hist_buf[hist_last]) {
free(hist_buf[hist_last]);
}
hist_buf[hist_last] = "";
}
}
hist_pos = hist_last;
}
 
static char *
hist_prev()
/* loads previous hist entry into input buffer, sticks on first */
{
char *p = 0;
int next = (hist_pos - 1 + HIST_SIZE) % HIST_SIZE;
 
if (hist_buf[hist_pos] != 0 && next != hist_last) {
hist_pos = next;
p = hist_buf[hist_pos];
}
if (p == 0) {
p = "";
gl_putc('\007');
}
return p;
}
 
static char *
hist_next()
/* loads next hist entry into input buffer, clears on last */
{
char *p = 0;
 
if (hist_pos != hist_last) {
hist_pos = (hist_pos+1) % HIST_SIZE;
p = hist_buf[hist_pos];
}
if (p == 0) {
p = "";
gl_putc('\007');
}
return p;
}
 
static char *
hist_save(p)
char *p;
/* makes a copy of the string */
{
char *s = 0;
int len = strlen(p);
char *nl = strchr(p, '\n');
 
if (nl) {
if ((s = malloc(len)) != 0) {
strncpy(s, p, len-1);
s[len-1] = 0;
}
} else {
if ((s = malloc(len+1)) != 0) {
strcpy(s, p);
}
}
if (s == 0)
gl_error("\n*** Error: hist_save() failed on malloc\n");
return s;
}
 
/******************* Search stuff **************************************/
 
static char search_prompt[101]; /* prompt includes search string */
static char search_string[100];
static int search_pos = 0; /* current location in search_string */
static int search_forw_flg = 0; /* search direction flag */
static int search_last = 0; /* last match found */
 
static void
search_update(c)
int c;
{
if (c == 0) {
search_pos = 0;
search_string[0] = 0;
search_prompt[0] = '?';
search_prompt[1] = ' ';
search_prompt[2] = 0;
} else if (c > 0) {
search_string[search_pos] = c;
search_string[search_pos+1] = 0;
search_prompt[search_pos] = c;
search_prompt[search_pos+1] = '?';
search_prompt[search_pos+2] = ' ';
search_prompt[search_pos+3] = 0;
search_pos++;
} else {
if (search_pos > 0) {
search_pos--;
search_string[search_pos] = 0;
search_prompt[search_pos] = '?';
search_prompt[search_pos+1] = ' ';
search_prompt[search_pos+2] = 0;
} else {
gl_putc('\007');
hist_pos = hist_last;
}
}
}
 
static void
search_addchar(c)
int c;
{
char *loc;
 
search_update(c);
if (c < 0) {
if (search_pos > 0) {
hist_pos = search_last;
} else {
gl_buf[0] = 0;
hist_pos = hist_last;
}
strcpy(gl_buf, hist_buf[hist_pos]);
}
if ((loc = strstr(gl_buf, search_string)) != 0) {
gl_fixup(search_prompt, 0, loc - gl_buf);
} else if (search_pos > 0) {
if (search_forw_flg) {
search_forw(0);
} else {
search_back(0);
}
} else {
gl_fixup(search_prompt, 0, 0);
}
}
 
static void
search_term()
{
gl_search_mode = 0;
if (gl_buf[0] == 0) /* not found, reset hist list */
hist_pos = hist_last;
if (gl_in_hook)
gl_in_hook(gl_buf);
gl_fixup(gl_prompt, 0, gl_pos);
}
 
static void
search_back(new_search)
int new_search;
{
int found = 0;
char *p, *loc;
 
search_forw_flg = 0;
if (gl_search_mode == 0) {
search_last = hist_pos = hist_last;
search_update(0);
gl_search_mode = 1;
gl_buf[0] = 0;
gl_fixup(search_prompt, 0, 0);
} else if (search_pos > 0) {
while (!found) {
p = hist_prev();
if (*p == 0) { /* not found, done looking */
gl_buf[0] = 0;
gl_fixup(search_prompt, 0, 0);
found = 1;
} else if ((loc = strstr(p, search_string)) != 0) {
strcpy(gl_buf, p);
gl_fixup(search_prompt, 0, loc - p);
if (new_search)
search_last = hist_pos;
found = 1;
}
}
} else {
gl_putc('\007');
}
}
 
static void
search_forw(new_search)
int new_search;
{
int found = 0;
char *p, *loc;
 
search_forw_flg = 1;
if (gl_search_mode == 0) {
search_last = hist_pos = hist_last;
search_update(0);
gl_search_mode = 1;
gl_buf[0] = 0;
gl_fixup(search_prompt, 0, 0);
} else if (search_pos > 0) {
while (!found) {
p = hist_next();
if (*p == 0) { /* not found, done looking */
gl_buf[0] = 0;
gl_fixup(search_prompt, 0, 0);
found = 1;
} else if ((loc = strstr(p, search_string)) != 0) {
strcpy(gl_buf, p);
gl_fixup(search_prompt, 0, loc - p);
if (new_search)
search_last = hist_pos;
found = 1;
}
}
} else {
gl_putc('\007');
}
}
/eco32/trunk/sim/getline/CHANGES
0,0 → 1,59
Changes by HG
* renamed getline to gl_getline
 
Changes from last patch (v38i004 in comp.sources.misc)
* added djgpp support on PCs
* cleanup up __unix__ ifdefs
* added __STDC__ prototypes in header file
* change makefile to build an archive and testgl
* added retry on interrupted read()s
* fixed GO32 keymapping to handles arrow keys properly
 
Changes from last release (v37i050 in comp.sources.misc)
* Added support for AIX, XENIX, TurboC, gcc (EMX) under OS/2
* Added ^U (kill line) functionality
* Added ESC-B/ESC-F backward/forward one word functionality
* Made it possible to preload history with gl_histadd() before calling
getline()
 
Changes from last release (v28i056 in comp.sources.misc)
 
* type-ahead saved in BSD mode (was OK in SYSV and POSIX)
* fixed POSIX mode bug and enabled termios use if POSIX defined.
* allow caller to supply a prompt width calculation function so that the
caller can embed escape sequences into the prompt (see gl_strwidth in
the man page).
* added a getline.h header file for inclusion into the caller.
* man page added, thanks to DaviD W. Sanderson (dws@cs.wisc.edu)
 
 
Changes from previous release (v25i056 and patch v26i092)
 
* The user no longer calls gl_init() and gl_cleanup(), getline() sets
required terminal modes on entry and resets before returning. This
was necessary to capture changes in terminal modes that the main
program might be making.
* Getline() now looks to see which characters are bound to signal
generation, and when these characters are seen getline() resets
terminal modes before passing on the signal. If the signal handler
returns to getline(), the screen is automatically updated and editing
can continue.
* The toggle key for overwrite mode has been moved from ^G to ^O
* All code is now classic rather than ANSI C, so any compiler should
be able to handle it.
* ^Y now yanks back previously kill'ed (^K) text starting at the
current location.
* ^R/^S begin reverse and forward incremental searches through the
history list.
* The programmer must add buffers onto the history list by calling
gl_addhist(char *buffer). This function makes copies of the buffer
and adds them to the history list if the buffer is not a blank line
and if the buffer is different than the last item saved (so the
program need not check for these conditions)
* The main program can specify the screen width to use with a call to
gl_setwidth(int width)
* Getline now insists that both the input and output are connected to
a terminal. If this is not the case, an error message is written and
the program is terminated. The main program should check for this
case and use buffered IO (stdio) for non-interactive sessions.
 
/eco32/trunk/sim/getline/getline.3
0,0 → 1,376
.\" Note that in silly ol' [nt]roff, even trailing white space is
.\" significant. I went through and eliminated it.
.\" I adopted a convention of using a bold 'getline' when referring to
.\" the whole package, but an italic 'getline' when referring to the
.\" specific function.
.\" Note that in [nt]roff that "-" is a hyphen, while "\-" is a dash.
.\" I adjusted some source text lines to keep them short (I keep line
.\" numbers turned on in vi, so I only have 72 cols w/o wrapping).
.\" It's too bad that getline() doesn't realloc() the buffer as
.\" necessary. Then it could have an unlimited input line length.
.\" Note that .RI et al are limited in how many args they can take.
.\" I corrected gl_addhist to gl_histadd, which is what is actually
.\" used! Perhaps it really should be gl_addhist, to preserve the
.\" gl_<verb><object> pattern in the other function names.
.\" I tried to rephrase certain sections to avoid the passive voice.
.\" I find the active voice much easier to understand, since I can tell
.\" more easily what acts on what.
.TH GETLINE 3
.SH NAME
getline \- command-line editing library with history
.SH SYNOPSIS
.RI "char *gl_getline(char *" prompt );
.PP
.RI "void gl_histadd(char *" line );
.br
.RI "void gl_setwidth(int " width );
.br
.RI "void gl_strwidth(int " (*width_func)() );
.PP
.RI "extern int (*gl_in_hook)(char *" buf );
.br
.RI "extern int (*gl_out_hook)(char *" buf );
.br
.RI "extern int (*gl_tab_hook)(char *" buf ,
.RI "int " prompt_width ", int *" cursor_loc );
.SH DESCRIPTION
The
.B getline
package is a set of library routines that implement
an editable command-line history.
.PP
.B "Programming Interface"
.br
.I getline
returns a pointer to a line of text read from the user,
prompting the user with the specified
.IR prompt .
The pointer refers to a static buffer allocated by the
.B getline
package.
Clients may assume that the pointer
.I getline
returns is always the same, and is never NULL.
The buffer
.I getline
returns to the caller contains the terminating newline character,
except on end of file,
in which case the first character in the buffer is 0
.RB ( NUL ).
File descriptors 0 and 1 must be connected to the terminal
(not redirected),
so the caller should check for this condition (using
.IR isatty (\|))
and call stdio routines if the session is not interactive.
.PP
.I gl_histadd
adds the given
.I line
to the
.B getline
history list if the
.I line
is not empty and if it is different from the last line
in the history list
(so the caller need not check for these conditions).
.I gl_histadd
makes its own copies of all the lines it adds to the history list.
This is so the caller can reuse the buffer it supplies to
.IR gl_histadd .
.PP
.I gl_setwidth
specifies the terminal
.I width
to use for horizontal scrolling.
The default value is 80 columns,
and it is important to properly specify the
.I width
or lines may wrap inadvertently.
.PP
.I gl_strwidth
allows the application program to supply a prompt string width calculation
function that returns the number of screen positions used by the argument
string.
By default strlen is used, but if the prompt contains escape sequences the user
can bind a function that returns the actual number of screen postitions
used by the argument string, not including the escape characters.
.PP
In addition to the function call interface,
.B getline
has three externally accessible function pointers
that act as hooks if bound to user-defined functions.
.B getline
supplies each of the functions with a pointer to the current buffer
as the first argument,
and expects the return value to be the index
of the first change the function made in the buffer
(or \-1 if the function did not alter the buffer).
After the functions return,
.B getline
updates the screen as necessary.
.\"-------
.\" DWS comment --
.\"-------
Note that the functions may not alter the size of the buffer.
Indeed, they do not even know how large the buffer is!
.PP
.I getline
calls
.I gl_in_hook
(initially NULL)
each time it loads a new buffer.
More precisely, this is
.TP
\(bu
at the first call to
.I getline
(with an empty buffer)
.TP
\(bu
each time the user enters a new buffer from the history list (with
.B ^P
or
.BR ^N )
.TP
\(bu
when the user accepts an incremental search string
(when the user terminates the search).
.PP
.I getline
calls
.I gl_out_hook
(initially NULL)
when a line has been completed by the user entering a
.B NEWLINE
.RB (\| ^J \|)
or
.B RETURN
.RB (\| ^M \|).
The buffer
.I gl_out_hook
sees does not yet have the newline appended, and
.I gl_out_hook
should not add a newline.
.PP
.I getline
calls
.I gl_tab_hook
whenever the user types a
.BR TAB .
In addition to the buffer,
.I getline
supplies the current
.I prompt_width
(presumably needed for tabbing calculations) and
.IR cursor_loc ,
a pointer to the cursor location.
.RI ( *cursor_loc
\(eq 0 corresponds to the first character in the buffer)
.I *cursor_loc
tells
.I gl_tab_hook
where the
.B TAB
was typed.
Note that when it redraws the screen,
.I getline
will honor any change
.I gl_tab_hook
may make to
.IR *cursor_loc .
.\"-------
.\" DWS comment --
.\"-------
Note also that
.I prompt_width
may not correspond to the actual width of
.I prompt
on the screen if
.I prompt
contains escape sequences.
.I gl_tab_hook
is initially bound to the
.B getline
internal static function
.IR gl_tab ,
which acts like a normal
.B TAB
key by inserting spaces.
.PP
.B "User Interface"
.br
.\"-------
.\" I adapted the prologue to this section from the ksh man page (dws).
.\"-------
To edit, the user moves the cursor to the point needing correction and
then inserts or deletes characters or words as needed.
All the editing commands are control characters,
which typed by holding the
CTRL key down while typing another character.
Control characters are indicated below as the caret
.RB (\| ^ \|)
followed by another character,
such as
.BR ^A .
.PP
All edit commands operate from any place on the line,
not just at the beginning.
.PP
These are the
.I getline
key bindings.
.\"-------
.\" Tt - max width of tag
.\" Tw - max width of tag + spacing to the paragraph
.\" Tp - special .TP, with the best indent for the editing command
.\" descriptions.
.\" The first version of Tp prints the tags left-justified.
.\" The second version of Tp prints the tags as follows:
.\" If one argument is given, it is printed right-justified.
.\" If two arguments are given, the first is printed left-justified
.\" and the second is printed right-justified.
.\"-------
.nr Tt \w'BACKSPACE'
.nr Tw \w'BACKSPACE\0\0\0'
.\" .de Tp
.\" .TP \n(Twu
.\" \fB\\$1\fR
.\" ..
.de Tp
.TP \n(Twu
.if \\n(.$=1 \h@\n(Ttu-\w'\fB\\$1\fR'u@\fB\\$1\fR
.if \\n(.$=2 \fB\\$1\fR\h@\n(Ttu-\w'\fB\\$1\\$2\fR'u@\fB\\$2\fR
..
.PP
.\"-------
.\" Set interparagraph spacing to zero so binding descriptions are
.\" kept together.
.\"-------
.PD 0
.Tp "^A"
Move cursor to beginning of line.
.Tp "^B"
Move cursor left (back) 1 column.
.Tp ESC-B
Move cursor back one word.
.Tp "^D"
Delete the character under the cursor.
.Tp "^E"
Move cursor to end of line.
.Tp "^F"
Move cursor right (forward) 1 column.
.Tp ESC-F
Move cursor forward one word.
.Tp "^H"
Delete the character left of the cursor.@
.Tp "^I"
Jump to next tab stop (may be redefined by the program).
.Tp "^J"
Return the current line.
.Tp "^K"
Kill from cursor to the end of the line (see
.BR "^Y" \|).
.Tp "^L"
Redisplay current line.
.Tp "^M"
Return the current line.
.Tp "^N"
Fetches next line from the history list.
.Tp "^O"
Toggle overwrite/insert mode, initially in insert mode.
.Tp "^P"
Fetches previous line from the history list.
.Tp "^R"
Begin a reverse incremental search through history list.
Each printing character typed adds to the search substring
(initially empty), and
.B getline
finds and displays the first matching location.
Typing
.B ^R
again marks the current starting location and begins a new
search for the current substring.
Typing
.B ^H
or
.B DEL
deletes the last character from the search string,
and
.B getline
restarts the search from the last starting location.
Repeated
.B ^H
or
.B DEL
characters therefore appear to unwind the search to the match nearest
the point where the user last typed
.B ^R
or
.BR ^S .
Typing
.B ^H
or
.B DEL
until the search string is empty causes
.B getline
to reset the start of the search to the beginning of the history list.
Typing
.B ESC
or any other editing character accepts the current match
and terminates the search.
.Tp "^S"
Begin a forward incremental search through the history list.
The behavior is like that of
.B ^R
but in the opposite direction through the history list.
.Tp "^T"
Transpose current and previous character.
.Tp "^U"
Kill the entire line (see
.BR "^Y" \|).
.Tp "^Y"
Yank previously killed text back at current location.
.Tp BACKSPACE
Delete the character left of the cursor.
.Tp DEL
Delete the character left of the cursor.
.Tp RETURN
Return the current line.
.Tp TAB
Jump to next tab stop (may be redefined by the program).
.\"-------
.\" Restore default interparagraph spacing.
.\"-------
.PD
.PP
.B getline
recognizes DOS and ANSI arrow keys.
They cause the following actions:
.B up
is the same as
.BR ^P ,
.B down
is the same as
.BR ^N ,
.B left
is the same as
.BR ^P ,
and
.B right
is the same as
.BR ^F .
.SH AUTHORS
.PP
Program by
Christopher R. Thewalt (thewalt\|@ce.berkeley.edu)
.PP
Original man page by
DaviD W. Sanderson (dws\|@cs.wisc.edu)
and Christopher R. Thewalt
.SH COPYRIGHT
\&
.br
.if n (C)
.if t \s+8\v'+2p'\fB\(co\fR\v'-2p'\s0
\s+2Copyright 1992,1993 by Christopher R. Thewalt and DaviD W. Sanderson\s0
(but freely redistributable)
/eco32/trunk/sim/getline/index.html
0,0 → 1,210
<HTML><HEAD>
<TITLE>Index of /usr/skunk/src/Tools/getline</TITLE>
</HEAD><BODY>
<H1>Index of /usr/skunk/src/Tools/getline</H1>
<PRE><IMG SRC="/icons/blank.xbm" ALT=" "> Name Last modified Size Description
<HR>
<IMG SRC="/icons/back.xbm" ALT="[DIR]"> <A HREF="/usr/skunk/src/Tools/">Parent Directory</A> 01-Aug-95 06:43 -
<IMG SRC="/icons/unknown.xbm" ALT="[ ]"> <A HREF="CHANGES">CHANGES</A> 03-May-95 10:08 3k
<IMG SRC="/icons/unknown.xbm" ALT="[ ]"> <A HREF="Makefile">Makefile</A> 21-Jun-95 05:42 1k
<IMG SRC="/icons/unknown.xbm" ALT="[ ]"> <A HREF="getline.3">getline.3</A> 03-May-95 10:08 9k
<IMG SRC="/icons/unknown.xbm" ALT="[ ]"> <A HREF="getline.c">getline.c</A> 03-May-95 10:08 28k
<IMG SRC="/icons/unknown.xbm" ALT="[ ]"> <A HREF="getline.h">getline.h</A> 03-May-95 10:08 1k
<IMG SRC="/icons/unknown.xbm" ALT="[ ]"> <A HREF="testgl.c">testgl.c</A> 03-May-95 10:08 1k
</PRE><HR>
<PRE>
*************************** Motivation **********************************
 
Many interactive programs read input line by line, but would like to
provide line editing and history functionality to the end-user that
runs the program.
 
The input-edit package provides that functionality. As far as the
programmer is concerned, the program only asks for the next line
of input. However, until the user presses the RETURN key they can use
emacs-style line editing commands and can traverse the history of lines
previously typed.
 
Other packages, such as GNU's readline, have greater capability but are
also substantially larger. Input-edit is small, since it uses neither
stdio nor any termcap features, and is also quite portable. It only uses
\b to backspace and \007 to ring the bell on errors. Since it cannot
edit multiple lines it scrolls long lines left and right on the same line.
 
Input edit uses classic (not ANSI) C, and should run on any Unix
system (BSD, SYSV or POSIX), PC's under DOS with MSC, TurboC or djgpp,
PC's under OS/2 with gcc (EMX), or Vax/VMS. Porting the package to new
systems basicaly requires code to read a character when it is typed without
echoing it, everything else should be OK.
 
I have run the package on:
 
DECstation 5000, Ultrix 4.3 with cc 2.1 and gcc 2.3.3
Sun Sparc 2, SunOS 4.1.1, with cc
SGI Iris, IRIX System V.3, with cc
PC using DOS with MSC
 
The description below is broken into two parts, the end-user (editing)
interface and the programmer interface. Send bug reports, fixes and
enhancements to:
 
Chris Thewalt (thewalt@ce.berkeley.edu)
5/3/93
 
Thanks to the following people who have provided enhancements and fixes:
Ron Ueberschaer, Christoph Keller, Scott Schwartz, Steven List,
DaviD W. Sanderson, Goran Bostrom, Michael Gleason, Glenn Kasten,
Edin Hodzic, Eric J Bivona, Kai Uwe Rommel, Danny Quah, Ulrich Betzler
 
PS: I don't have, and don't want to add, a vi mode, sorry.
 
************************** End-User Interface ***************************
 
Entering printable keys generally inserts new text into the buffer (unless
in overwrite mode, see below). Other special keys can be used to modify
the text in the buffer. In the description of the keys below, ^n means
Control-n, or holding the CONTROL key down while pressing "n". Errors
will ring the terminal bell.
 
^A/^E : Move cursor to beginning/end of the line.
^F/^B : Move cursor forward/backward one character.
ESC-F : Move cursor forward one word.
ESC-B : Move cursor backward one word.
^D : Delete the character under the cursor.
^H, DEL : Delete the character to the left of the cursor.
^K : Kill from the cursor to the end of line.
^L : Redraw current line.
^O : Toggle overwrite/insert mode. Initially in insert mode. Text
added in overwrite mode (including yanks) overwrite
existing text, while insert mode does not overwrite.
^P/^N : Move to previous/next item on history list.
^R/^S : Perform incremental reverse/forward search for string on
the history list. Typing normal characters adds to the current
search string and searches for a match. Typing ^R/^S marks
the start of a new search, and moves on to the next match.
Typing ^H or DEL deletes the last character from the search
string, and searches from the starting location of the last search.
Therefore, repeated DEL's appear to unwind to the match nearest
the point at which the last ^R or ^S was typed. If DEL is
repeated until the search string is empty the search location
begins from the start of the history list. Typing ESC or
any other editing character accepts the current match and
loads it into the buffer, terminating the search.
^T : Toggle the characters under and to the left of the cursor.
^U : Deletes the entire line
^Y : Yank previously killed text back at current location. Note that
this will overwrite or insert, depending on the current mode.
TAB : By default adds spaces to buffer to get to next TAB stop
(just after every 8th column), although this may be rebound by the
programmer, as described below.
NL, CR : returns current buffer to the program.
 
DOS and ANSI terminal arrow key sequences are recognized, and act like:
 
up : same as ^P
down : same as ^N
left : same as ^B
right : same as ^F
 
************************** Programmer Interface ***************************
 
The programmer accesses input-edit through these functions, and optionally
through three additional function pointer hooks. The four functions are:
 
char *gl_getline(char *prompt)
 
Prints the prompt and allows the user to edit the current line. A
pointer to the line is returned when the user finishes by
typing a newline or a return. Unlike GNU readline, the returned
pointer points to a static buffer, so it should not be free'd, and
the buffer contains the newline character. The user enters an
end-of-file by typing ^D on an empty line, in which case the
first character of the returned buffer is '\0'. Getline never
returns a NULL pointer. The getline functions sets terminal modes
needed to make it work, and resets them before returning to the
caller. The getline function also looks for characters that would
generate a signal, and resets the terminal modes before raising the
signal condition. If the signal handler returns to getline,
the screen is automatically redrawn and editing can continue.
Getline now requires both the input and output stream be connected
to the terminal (not redirected) so the main program should check
to make sure this is true. If input or output have been redirected
the main program should use buffered IO (stdio) rather than
the slow 1 character read()s that getline uses.
 
void gl_setwidth(int width)
 
Set the width of the terminal to the specified width. The default
width is 80 characters, so this function need only be called if the
width of the terminal is not 80. Since horizontal scrolling is
controlled by this parameter it is important to get it right.
 
void gl_histadd(char *buf)
 
The gl_histadd function checks to see if the buf is not empty or
whitespace, and also checks to make sure it is different than
the last saved buffer to avoid repeats on the history list.
If the buf is a new non-blank string a copy is made and saved on
the history list, so the caller can re-use the specified buf.
 
void gl_strwidth(size_t (*func)())
The gl_strwidth function allows the caller to supply a pointer to
a prompt width calculation function (strlen by default). This
allows the caller to embed escape sequences in the prompt and then
tell getline how many screen spaces the prompt will take up.
 
The main loop in testgl.c, included in this directory, shows how the
input-edit package can be used:
 
extern char *getline();
extern void gl_histadd();
main()
{
char *p;
do {
p = getline("PROMPT&gt;&gt;&gt;&gt; ");
gl_histadd(p);
fputs(p, stdout);
} while (*p != 0);
}
 
In order to allow the main program to have additional access to the buffer,
to implement things such as completion or auto-indent modes, three
function pointers can be bound to user functions to modify the buffer as
described below. By default gl_in_hook and gl_out_hook are set to NULL,
and gl_tab_hook is bound to a function that inserts spaces until the next
logical tab stop is reached. The user can reassign any of these pointers
to other functions. Each of the functions bound to these hooks receives
the current buffer as the first argument, and must return the location of
the leftmost change made in the buffer. If the buffer isn't modified the
functions should return -1. When the hook function returns the screen is
updated to reflect any changes made by the user function.
 
int (*gl_in_hook)(char *buf)
 
If gl_in_hook is non-NULL the function is called each time a new
buffer is loaded. It is called when getline is entered, with an
empty buffer, it is called each time a new buffer is loaded from
the history with ^P or ^N, and it is called when an incremental
search string is accepted (when the search is terminated). The
buffer can be modified and will be redrawn upon return to getline().
 
int (*gl_out_hook)(char *buf)
 
If gl_out_hook is non-NULL it is called when a line has been
completed by the user entering a newline or return. The buffer
handed to the hook does not yet have the newline appended. If the
buffer is modified the screen is redrawn before getline returns the
buffer to the caller.
 
int (*gl_tab_hook)(char *buf, int prompt_width, int *cursor_loc)
 
If gl_tab_hook is non-NULL, it is called whenever a tab is typed.
In addition to receiving the buffer, the current prompt width is
given (needed to do tabbing right) and a pointer to the cursor
offset is given, where a 0 offset means the first character in the
line. Not only does the cursor_loc tell the programmer where the
TAB was received, but it can be reset so that the cursor will end
up at the specified location after the screen is redrawn.
</PRE>
</BODY></HTML>
/eco32/trunk/sim/getline/Makefile
0,0 → 1,26
#
# Makefile for the getline library
#
 
CC = gcc -m32
CFLAGS = -O -DPOSIX
LDFLAGS = -L.
LDLIBS = -lgetline
 
.PHONY: all install clean
 
all: libgetline.a testgl
 
install: libgetline.a testgl
 
testgl: libgetline.a testgl.o
$(CC) $(LDFLAGS) $(CFLAGS) -o testgl testgl.o $(LDLIBS)
 
libgetline.a: getline.o
ar cr libgetline.a getline.o
 
%.o: %.c
$(CC) $(CFLAGS) -o $@ -c $<
 
clean:
rm -f *~ *.o *.a testgl
/eco32/trunk/sim/getline/README
0,0 → 1,194
 
*************************** Motivation **********************************
 
Many interactive programs read input line by line, but would like to
provide line editing and history functionality to the end-user that
runs the program.
 
The input-edit package provides that functionality. As far as the
programmer is concerned, the program only asks for the next line
of input. However, until the user presses the RETURN key they can use
emacs-style line editing commands and can traverse the history of lines
previously typed.
 
Other packages, such as GNU's readline, have greater capability but are
also substantially larger. Input-edit is small, since it uses neither
stdio nor any termcap features, and is also quite portable. It only uses
\b to backspace and \007 to ring the bell on errors. Since it cannot
edit multiple lines it scrolls long lines left and right on the same line.
 
Input edit uses classic (not ANSI) C, and should run on any Unix
system (BSD, SYSV or POSIX), PC's under DOS with MSC, TurboC or djgpp,
PC's under OS/2 with gcc (EMX), or Vax/VMS. Porting the package to new
systems basicaly requires code to read a character when it is typed without
echoing it, everything else should be OK.
 
I have run the package on:
 
DECstation 5000, Ultrix 4.3 with cc 2.1 and gcc 2.3.3
Sun Sparc 2, SunOS 4.1.1, with cc
SGI Iris, IRIX System V.3, with cc
PC using DOS with MSC
 
The description below is broken into two parts, the end-user (editing)
interface and the programmer interface. Send bug reports, fixes and
enhancements to:
 
Chris Thewalt (thewalt@ce.berkeley.edu)
5/3/93
 
Thanks to the following people who have provided enhancements and fixes:
Ron Ueberschaer, Christoph Keller, Scott Schwartz, Steven List,
DaviD W. Sanderson, Goran Bostrom, Michael Gleason, Glenn Kasten,
Edin Hodzic, Eric J Bivona, Kai Uwe Rommel, Danny Quah, Ulrich Betzler
 
PS: I don't have, and don't want to add, a vi mode, sorry.
 
************************** End-User Interface ***************************
 
Entering printable keys generally inserts new text into the buffer (unless
in overwrite mode, see below). Other special keys can be used to modify
the text in the buffer. In the description of the keys below, ^n means
Control-n, or holding the CONTROL key down while pressing "n". Errors
will ring the terminal bell.
 
^A/^E : Move cursor to beginning/end of the line.
^F/^B : Move cursor forward/backward one character.
ESC-F : Move cursor forward one word.
ESC-B : Move cursor backward one word.
^D : Delete the character under the cursor.
^H, DEL : Delete the character to the left of the cursor.
^K : Kill from the cursor to the end of line.
^L : Redraw current line.
^O : Toggle overwrite/insert mode. Initially in insert mode. Text
added in overwrite mode (including yanks) overwrite
existing text, while insert mode does not overwrite.
^P/^N : Move to previous/next item on history list.
^R/^S : Perform incremental reverse/forward search for string on
the history list. Typing normal characters adds to the current
search string and searches for a match. Typing ^R/^S marks
the start of a new search, and moves on to the next match.
Typing ^H or DEL deletes the last character from the search
string, and searches from the starting location of the last search.
Therefore, repeated DEL's appear to unwind to the match nearest
the point at which the last ^R or ^S was typed. If DEL is
repeated until the search string is empty the search location
begins from the start of the history list. Typing ESC or
any other editing character accepts the current match and
loads it into the buffer, terminating the search.
^T : Toggle the characters under and to the left of the cursor.
^U : Deletes the entire line
^Y : Yank previously killed text back at current location. Note that
this will overwrite or insert, depending on the current mode.
TAB : By default adds spaces to buffer to get to next TAB stop
(just after every 8th column), although this may be rebound by the
programmer, as described below.
NL, CR : returns current buffer to the program.
 
DOS and ANSI terminal arrow key sequences are recognized, and act like:
 
up : same as ^P
down : same as ^N
left : same as ^B
right : same as ^F
 
************************** Programmer Interface ***************************
 
The programmer accesses input-edit through these functions, and optionally
through three additional function pointer hooks. The four functions are:
 
char *gl_getline(char *prompt)
 
Prints the prompt and allows the user to edit the current line. A
pointer to the line is returned when the user finishes by
typing a newline or a return. Unlike GNU readline, the returned
pointer points to a static buffer, so it should not be free'd, and
the buffer contains the newline character. The user enters an
end-of-file by typing ^D on an empty line, in which case the
first character of the returned buffer is '\0'. Getline never
returns a NULL pointer. The getline functions sets terminal modes
needed to make it work, and resets them before returning to the
caller. The getline function also looks for characters that would
generate a signal, and resets the terminal modes before raising the
signal condition. If the signal handler returns to getline,
the screen is automatically redrawn and editing can continue.
Getline now requires both the input and output stream be connected
to the terminal (not redirected) so the main program should check
to make sure this is true. If input or output have been redirected
the main program should use buffered IO (stdio) rather than
the slow 1 character read()s that getline uses.
 
void gl_setwidth(int width)
 
Set the width of the terminal to the specified width. The default
width is 80 characters, so this function need only be called if the
width of the terminal is not 80. Since horizontal scrolling is
controlled by this parameter it is important to get it right.
 
void gl_histadd(char *buf)
 
The gl_histadd function checks to see if the buf is not empty or
whitespace, and also checks to make sure it is different than
the last saved buffer to avoid repeats on the history list.
If the buf is a new non-blank string a copy is made and saved on
the history list, so the caller can re-use the specified buf.
 
void gl_strwidth(size_t (*func)())
The gl_strwidth function allows the caller to supply a pointer to
a prompt width calculation function (strlen by default). This
allows the caller to embed escape sequences in the prompt and then
tell getline how many screen spaces the prompt will take up.
 
The main loop in testgl.c, included in this directory, shows how the
input-edit package can be used:
 
extern char *gl_getline();
extern void gl_histadd();
main()
{
char *p;
do {
p = gl_getline("PROMPT>>>> ");
gl_histadd(p);
fputs(p, stdout);
} while (*p != 0);
}
 
In order to allow the main program to have additional access to the buffer,
to implement things such as completion or auto-indent modes, three
function pointers can be bound to user functions to modify the buffer as
described below. By default gl_in_hook and gl_out_hook are set to NULL,
and gl_tab_hook is bound to a function that inserts spaces until the next
logical tab stop is reached. The user can reassign any of these pointers
to other functions. Each of the functions bound to these hooks receives
the current buffer as the first argument, and must return the location of
the leftmost change made in the buffer. If the buffer isn't modified the
functions should return -1. When the hook function returns the screen is
updated to reflect any changes made by the user function.
 
int (*gl_in_hook)(char *buf)
 
If gl_in_hook is non-NULL the function is called each time a new
buffer is loaded. It is called when getline is entered, with an
empty buffer, it is called each time a new buffer is loaded from
the history with ^P or ^N, and it is called when an incremental
search string is accepted (when the search is terminated). The
buffer can be modified and will be redrawn upon return to getline().
 
int (*gl_out_hook)(char *buf)
 
If gl_out_hook is non-NULL it is called when a line has been
completed by the user entering a newline or return. The buffer
handed to the hook does not yet have the newline appended. If the
buffer is modified the screen is redrawn before getline returns the
buffer to the caller.
 
int (*gl_tab_hook)(char *buf, int prompt_width, int *cursor_loc)
 
If gl_tab_hook is non-NULL, it is called whenever a tab is typed.
In addition to receiving the buffer, the current prompt width is
given (needed to do tabbing right) and a pointer to the cursor
offset is given, where a 0 offset means the first character in the
line. Not only does the cursor_loc tell the programmer where the
TAB was received, but it can be reset so that the cursor will end
up at the specified location after the screen is redrawn.
/eco32/trunk/sim/getline/getline.h
0,0 → 1,35
#ifndef GETLINE_H
#define GETLINE_H
 
/* unix systems can #define POSIX to use termios, otherwise
* the bsd or sysv interface will be used
*/
 
#if __STDC__ > 0
#include <stddef.h>
 
typedef size_t (*gl_strwidth_proc)(char *);
 
char *gl_getline(char *); /* read a line of input */
void gl_setwidth(int); /* specify width of screen */
void gl_histadd(char *); /* adds entries to hist */
void gl_strwidth(gl_strwidth_proc); /* to bind gl_strlen */
 
extern int (*gl_in_hook)(char *);
extern int (*gl_out_hook)(char *);
extern int (*gl_tab_hook)(char *, int, int *);
 
#else /* not __STDC__ */
 
char *gl_getline();
void gl_setwidth();
void gl_histadd();
void gl_strwidth();
 
extern int (*gl_in_hook)();
extern int (*gl_out_hook)();
extern int (*gl_tab_hook)();
 
#endif /* __STDC__ */
 
#endif /* GETLINE_H */
/eco32/trunk/sim/console.h
0,0 → 1,18
/*
* console.h -- the simulator's operator console
*/
 
 
#ifndef _CONSOLE_H_
#define _CONSOLE_H_
 
 
char *cGetLine(char *prompt);
void cAddHist(char *line);
void cPrintf(char *format, ...);
 
void cInit(void);
void cExit(void);
 
 
#endif /* _CONSOLE_H_ */
/eco32/trunk/sim/dspkbd.c
0,0 → 1,906
/*
* display.c -- display controller simulation
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
 
#include "common.h"
#include "console.h"
#include "error.h"
#include "except.h"
#include "cpu.h"
#include "timer.h"
#include "dspkbd.h"
 
 
static Bool debug = false;
static Bool debugKeycode = false;
static volatile Bool installed = false;
 
 
static void blinkScreen(void);
 
static void keyPressed(unsigned int xKeycode);
static void keyReleased(unsigned int xKeycode);
 
 
/**************************************************************/
/**************************************************************/
 
/* common definitions, global variables */
 
 
#include <pthread.h>
#include <unistd.h>
#include <time.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
 
 
#define WINDOW_SIZE_X 640
#define WINDOW_SIZE_Y 480
#define WINDOW_POS_X 100
#define WINDOW_POS_Y 100
 
 
#define C2B(c,ch) (((((c) & 0xFF) * ch.scale) >> 8) * ch.factor)
#define RGB2PIXEL(r,g,b) (C2B(r, vga.red) | \
C2B(g, vga.green) | \
C2B(b, vga.blue))
 
 
typedef struct {
unsigned long scale;
unsigned long factor;
} ColorChannel;
 
 
typedef struct {
int argc;
char **argv;
Display *display;
Window win;
GC gc;
XImage *image;
ColorChannel red, green, blue;
XExposeEvent expose;
XClientMessageEvent shutdown;
} VGA;
 
 
static VGA vga;
 
 
/**************************************************************/
 
/* monitor server */
 
 
static ColorChannel mask2channel(unsigned long mask) {
unsigned long f;
ColorChannel ch;
 
if (mask == 0) {
error("color mask is 0 in mask2channel");
}
for (f = 1; (mask & 1) == 0; f <<= 1) {
mask >>= 1;
}
ch.factor = f;
ch.scale = mask + 1;
while ((mask & 1) != 0) {
mask >>= 1;
}
if (mask != 0) {
error("scattered color mask bits in mask2channel");
}
return ch;
}
 
 
static void initMonitor(int argc, char *argv[]) {
int screenNum;
Window rootWin;
XVisualInfo visualTemp;
XVisualInfo *visualInfo;
int visualCount;
int bestMatch;
int bestDepth;
Visual *visual;
int i;
unsigned long pixel;
int x, y;
Colormap colormap;
XSetWindowAttributes attrib;
XSizeHints *sizeHints;
XWMHints *wmHints;
XClassHint *classHints;
XTextProperty windowName;
XGCValues gcValues;
 
/* connect to X server */
if (XInitThreads() == 0) {
error("no thread support for X11");
}
vga.display = XOpenDisplay(NULL);
if (vga.display == NULL) {
error("cannot connect to X server");
}
screenNum = DefaultScreen(vga.display);
rootWin = RootWindow(vga.display, screenNum);
/* find TrueColor visual */
visualTemp.screen = screenNum;
visualTemp.class = TrueColor;
visualInfo = XGetVisualInfo(vga.display,
VisualClassMask | VisualScreenMask,
&visualTemp, &visualCount);
if (visualInfo == NULL || visualCount == 0) {
error("no TrueColor visual found");
}
bestMatch = 0;
bestDepth = visualInfo[0].depth;
visual = visualInfo[0].visual;
for (i = 1; i < visualCount; i++) {
if (visualInfo[i].depth > bestDepth) {
bestMatch = i;
bestDepth = visualInfo[i].depth;
visual = visualInfo[i].visual;
}
}
/* build color channels */
vga.red = mask2channel(visualInfo[bestMatch].red_mask);
vga.green = mask2channel(visualInfo[bestMatch].green_mask);
vga.blue = mask2channel(visualInfo[bestMatch].blue_mask);
/* create and initialize image */
vga.image = XCreateImage(vga.display, visual, bestDepth, ZPixmap,
0, NULL, WINDOW_SIZE_X, WINDOW_SIZE_Y, 32, 0);
if (vga.image == NULL) {
error("cannot allocate image");
}
vga.image->data = malloc(vga.image->height * vga.image->bytes_per_line);
if (vga.image->data == NULL) {
error("cannot allocate image memory");
}
pixel = RGB2PIXEL(0, 0, 0);
for (y = 0; y < WINDOW_SIZE_Y; y++) {
for (x = 0; x < WINDOW_SIZE_X; x++) {
XPutPixel(vga.image, x, y, pixel);
}
}
/* allocate a colormap */
colormap = XCreateColormap(vga.display, rootWin, visual, AllocNone);
/* create the window */
attrib.colormap = colormap;
attrib.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask;
attrib.background_pixel = RGB2PIXEL(0, 0, 0);
attrib.border_pixel = RGB2PIXEL(0, 0, 0);
vga.win =
XCreateWindow(vga.display, rootWin,
WINDOW_POS_X, WINDOW_POS_Y,
WINDOW_SIZE_X, WINDOW_SIZE_Y,
0, bestDepth, InputOutput, visual,
CWEventMask | CWColormap | CWBackPixel | CWBorderPixel,
&attrib);
/* give hints to window manager */
sizeHints = XAllocSizeHints();
wmHints = XAllocWMHints();
classHints = XAllocClassHint();
if (sizeHints == NULL ||
wmHints == NULL ||
classHints == NULL) {
error("hint allocation failed");
}
sizeHints->flags = PMinSize | PMaxSize;
sizeHints->min_width = WINDOW_SIZE_X;
sizeHints->min_height = WINDOW_SIZE_Y;
sizeHints->max_width = WINDOW_SIZE_X;
sizeHints->max_height = WINDOW_SIZE_Y;
wmHints->flags = StateHint | InputHint;
wmHints->input = True;
wmHints->initial_state = NormalState;
classHints->res_name = "ECO32";
classHints->res_class = "ECO32";
if (XStringListToTextProperty(&classHints->res_name, 1, &windowName) == 0) {
error("property allocation failed");
}
XSetWMProperties(vga.display, vga.win, &windowName, NULL,
argv, argc, sizeHints, wmHints, classHints);
/* create a GC */
vga.gc = XCreateGC(vga.display, vga.win, 0, &gcValues);
/* finally get the window displayed */
XMapWindow(vga.display, vga.win);
/* prepare expose event */
vga.expose.type = Expose;
vga.expose.display = vga.display;
vga.expose.window = vga.win;
vga.expose.x = 0;
vga.expose.y = 0;
vga.expose.width = WINDOW_SIZE_X;
vga.expose.height = WINDOW_SIZE_Y;
vga.expose.count = 0;
/* prepare shutdown event */
vga.shutdown.type = ClientMessage;
vga.shutdown.display = vga.display;
vga.shutdown.window = vga.win;
vga.shutdown.message_type = XA_WM_COMMAND;
vga.shutdown.format = 32;
vga.shutdown.data.l[0] = 0xDEADBEEF;
/* say that the graphics controller is installed */
XSync(vga.display, False);
installed = true;
}
 
 
static void exitMonitor(void) {
XFreeGC(vga.display, vga.gc);
XUnmapWindow(vga.display, vga.win);
XDestroyWindow(vga.display, vga.win);
XDestroyImage(vga.image);
XCloseDisplay(vga.display);
installed = false;
}
 
 
static int ioErrorHandler(Display *display) {
error("connection to monitor window lost");
/* never reached */
return 0;
}
 
 
static void *server(void *ignore) {
Bool run;
XEvent event;
 
initMonitor(vga.argc, vga.argv);
XSetIOErrorHandler(ioErrorHandler);
run = true;
while (run) {
XNextEvent(vga.display, &event);
switch (event.type) {
case Expose:
blinkScreen();
XPutImage(vga.display, vga.win, vga.gc, vga.image,
event.xexpose.x, event.xexpose.y,
event.xexpose.x, event.xexpose.y,
event.xexpose.width, event.xexpose.height);
break;
case ClientMessage:
if (event.xclient.message_type == XA_WM_COMMAND &&
event.xclient.format == 32 &&
event.xclient.data.l[0] == 0xDEADBEEF) {
run = false;
}
break;
case KeyPress:
keyPressed(event.xkey.keycode);
break;
case KeyRelease:
keyReleased(event.xkey.keycode);
break;
default:
break;
}
}
exitMonitor();
return NULL;
}
 
 
/**************************************************************/
 
/* refresh timer */
 
 
static Bool refreshRunning = false;
static Bool blink = false;
 
 
static void *refresh(void *ignore) {
static int blinkCounter = 0;
struct timespec delay;
 
while (refreshRunning) {
if (++blinkCounter == 5) {
blinkCounter = 0;
blink = !blink;
}
XSendEvent(vga.display, vga.win, False, 0, (XEvent *) &vga.expose);
XFlush(vga.display);
delay.tv_sec = 0;
delay.tv_nsec = 100 * 1000 * 1000;
nanosleep(&delay, &delay);
}
return NULL;
}
 
 
/**************************************************************/
 
/* server interface */
 
 
static int myArgc = 1;
static char *myArgv[] = {
"eco32",
NULL
};
 
 
static void vgaInit(void) {
pthread_attr_t attr;
pthread_t thread;
 
/* start monitor server in a separate thread */
vga.argc = myArgc;
vga.argv = myArgv;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (pthread_create(&thread, &attr, server, NULL) != 0) {
error("cannot start monitor server");
}
while (!installed) sleep(1);
/* start refresh timer in another thread */
refreshRunning = true;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (pthread_create(&thread, &attr, refresh, NULL) != 0) {
error("cannot start refresh timer");
}
}
 
 
static void vgaExit(void) {
refreshRunning = false;
sleep(1);
XSendEvent(vga.display, vga.win, False, 0, (XEvent *) &vga.shutdown);
XSync(vga.display, False);
while (installed) sleep(1);
}
 
 
static void vgaWrite(int x, int y, int r, int g, int b) {
XPutPixel(vga.image, x, y, RGB2PIXEL(r, g, b));
}
 
 
/**************************************************************/
/**************************************************************/
 
 
#define CELL_SIZE_X 8
#define CELL_SIZE_Y 16
 
#define TEXT_SIZE_X (WINDOW_SIZE_X / CELL_SIZE_X)
#define TEXT_SIZE_Y (WINDOW_SIZE_Y / CELL_SIZE_Y)
 
 
static Half text[TEXT_SIZE_Y][TEXT_SIZE_X];
 
static Byte font[] = {
#include "font"
};
 
 
static void updateCharacter(int x, int y, Half c) {
int xx, yy;
int i, j;
Byte pixels;
int r, g, b;
 
xx = x * CELL_SIZE_X;
yy = y * CELL_SIZE_Y;
for (j = 0; j < CELL_SIZE_Y; j++) {
pixels = font[(c & 0x00FF) * CELL_SIZE_Y + j];
for (i = 0; i < CELL_SIZE_X; i++) {
if ((pixels & (1 << (CELL_SIZE_X - 1 - i))) != 0 &&
!((c & 0x8000) != 0 && blink)) {
/* foreground */
if (c & 0x0800) {
/* intensify bit is on */
r = (c & 0x0400) ? 255 : 73;
g = (c & 0x0200) ? 255 : 73;
b = (c & 0x0100) ? 255 : 73;
} else {
/* intensify bit is off */
r = (c & 0x0400) ? 146 : 0;
g = (c & 0x0200) ? 146 : 0;
b = (c & 0x0100) ? 146 : 0;
}
} else {
/* background */
r = (c & 0x4000) ? 146 : 0;
g = (c & 0x2000) ? 146 : 0;
b = (c & 0x1000) ? 146 : 0;
}
vgaWrite(xx + i, yy + j, r, g, b);
}
}
}
 
 
static void blinkScreen(void) {
static Bool previousBlink = false;
int x, y;
Half c;
 
if (previousBlink == blink) {
/* blink state didn't change, nothing to do */
return;
}
previousBlink = blink;
for (y = 0; y < TEXT_SIZE_Y; y++) {
for (x = 0; x < TEXT_SIZE_X; x++) {
/* update the character if it is blinking */
c = text[y][x];
if (c & 0x8000) {
updateCharacter(x, y, c);
}
}
}
}
 
 
static Half readCharAndAttr(int x, int y) {
return text[y][x];
}
 
 
static void writeCharAndAttr(int x, int y, Half c) {
text[y][x] = c;
updateCharacter(x, y, c);
}
 
 
static char *screen[] = {
#include "screen"
};
 
 
static void loadSplashScreen(void) {
int x, y;
char *p;
 
for (y = 0; y < TEXT_SIZE_Y; y++) {
p = screen[y];
for (x = 0; x < TEXT_SIZE_X; x++) {
writeCharAndAttr(x, y, (Half) 0x0700 | (Half) *p);
p++;
}
}
}
 
 
/**************************************************************/
 
 
Word displayRead(Word addr) {
int x, y;
Word data;
 
if (debug) {
cPrintf("\n**** DISPLAY READ from 0x%08X", addr);
}
if (!installed) {
throwException(EXC_BUS_TIMEOUT);
}
x = (addr >> 2) & ((1 << 7) - 1);
y = (addr >> 9) & ((1 << 5) - 1);
if (x >= TEXT_SIZE_X || y >= TEXT_SIZE_Y) {
throwException(EXC_BUS_TIMEOUT);
}
data = readCharAndAttr(x, y);
if (debug) {
cPrintf(", data = 0x%08X ****\n", data);
}
return data;
}
 
 
void displayWrite(Word addr, Word data) {
int x, y;
 
if (debug) {
cPrintf("\n**** DISPLAY WRITE to 0x%08X, data = 0x%08X ****\n",
addr, data);
}
if (!installed) {
throwException(EXC_BUS_TIMEOUT);
}
x = (addr >> 2) & ((1 << 7) - 1);
y = (addr >> 9) & ((1 << 5) - 1);
if (x >= TEXT_SIZE_X || y >= TEXT_SIZE_Y) {
throwException(EXC_BUS_TIMEOUT);
}
writeCharAndAttr(x, y, data);
}
 
 
void displayReset(void) {
if (!installed) {
return;
}
cPrintf("Resetting Display...\n");
loadSplashScreen();
}
 
 
void displayInit(void) {
if (!installed) {
vgaInit();
}
displayReset();
}
 
 
void displayExit(void) {
if (!installed) {
return;
}
vgaExit();
}
 
 
/**************************************************************/
/**************************************************************/
 
 
#define MAX_MAKE 2
#define MAX_BREAK 3
 
 
typedef struct {
unsigned int xKeycode;
int pcNumMake;
Byte pcKeyMake[MAX_MAKE];
int pcNumBreak;
Byte pcKeyBreak[MAX_BREAK];
} Keycode;
 
 
static Keycode kbdCodeTbl[] = {
{ 0x09, 1, { 0x76, 0x00 }, 2, { 0xF0, 0x76, 0x00 } },
{ 0x43, 1, { 0x05, 0x00 }, 2, { 0xF0, 0x05, 0x00 } },
{ 0x44, 1, { 0x06, 0x00 }, 2, { 0xF0, 0x06, 0x00 } },
{ 0x45, 1, { 0x04, 0x00 }, 2, { 0xF0, 0x04, 0x00 } },
{ 0x46, 1, { 0x0C, 0x00 }, 2, { 0xF0, 0x0C, 0x00 } },
{ 0x47, 1, { 0x03, 0x00 }, 2, { 0xF0, 0x03, 0x00 } },
{ 0x48, 1, { 0x0B, 0x00 }, 2, { 0xF0, 0x0B, 0x00 } },
{ 0x49, 1, { 0x83, 0x00 }, 2, { 0xF0, 0x83, 0x00 } },
{ 0x4A, 1, { 0x0A, 0x00 }, 2, { 0xF0, 0x0A, 0x00 } },
{ 0x4B, 1, { 0x01, 0x00 }, 2, { 0xF0, 0x01, 0x00 } },
{ 0x4C, 1, { 0x09, 0x00 }, 2, { 0xF0, 0x09, 0x00 } },
{ 0x5F, 1, { 0x78, 0x00 }, 2, { 0xF0, 0x78, 0x00 } },
{ 0x60, 1, { 0x07, 0x00 }, 2, { 0xF0, 0x07, 0x00 } },
/*------------------------------------------------*/
{ 0x31, 1, { 0x0E, 0x00 }, 2, { 0xF0, 0x0E, 0x00 } },
{ 0x0A, 1, { 0x16, 0x00 }, 2, { 0xF0, 0x16, 0x00 } },
{ 0x0B, 1, { 0x1E, 0x00 }, 2, { 0xF0, 0x1E, 0x00 } },
{ 0x0C, 1, { 0x26, 0x00 }, 2, { 0xF0, 0x26, 0x00 } },
{ 0x0D, 1, { 0x25, 0x00 }, 2, { 0xF0, 0x25, 0x00 } },
{ 0x0E, 1, { 0x2E, 0x00 }, 2, { 0xF0, 0x2E, 0x00 } },
{ 0x0F, 1, { 0x36, 0x00 }, 2, { 0xF0, 0x36, 0x00 } },
{ 0x10, 1, { 0x3D, 0x00 }, 2, { 0xF0, 0x3D, 0x00 } },
{ 0x11, 1, { 0x3E, 0x00 }, 2, { 0xF0, 0x3E, 0x00 } },
{ 0x12, 1, { 0x46, 0x00 }, 2, { 0xF0, 0x46, 0x00 } },
{ 0x13, 1, { 0x45, 0x00 }, 2, { 0xF0, 0x45, 0x00 } },
{ 0x14, 1, { 0x4E, 0x00 }, 2, { 0xF0, 0x4E, 0x00 } },
{ 0x15, 1, { 0x55, 0x00 }, 2, { 0xF0, 0x55, 0x00 } },
{ 0x16, 1, { 0x66, 0x00 }, 2, { 0xF0, 0x66, 0x00 } },
/*------------------------------------------------*/
{ 0x17, 1, { 0x0D, 0x00 }, 2, { 0xF0, 0x0D, 0x00 } },
{ 0x18, 1, { 0x15, 0x00 }, 2, { 0xF0, 0x15, 0x00 } },
{ 0x19, 1, { 0x1D, 0x00 }, 2, { 0xF0, 0x1D, 0x00 } },
{ 0x1A, 1, { 0x24, 0x00 }, 2, { 0xF0, 0x24, 0x00 } },
{ 0x1B, 1, { 0x2D, 0x00 }, 2, { 0xF0, 0x2D, 0x00 } },
{ 0x1C, 1, { 0x2C, 0x00 }, 2, { 0xF0, 0x2C, 0x00 } },
{ 0x1D, 1, { 0x35, 0x00 }, 2, { 0xF0, 0x35, 0x00 } },
{ 0x1E, 1, { 0x3C, 0x00 }, 2, { 0xF0, 0x3C, 0x00 } },
{ 0x1F, 1, { 0x43, 0x00 }, 2, { 0xF0, 0x43, 0x00 } },
{ 0x20, 1, { 0x44, 0x00 }, 2, { 0xF0, 0x44, 0x00 } },
{ 0x21, 1, { 0x4D, 0x00 }, 2, { 0xF0, 0x4D, 0x00 } },
{ 0x22, 1, { 0x54, 0x00 }, 2, { 0xF0, 0x54, 0x00 } },
{ 0x23, 1, { 0x5B, 0x00 }, 2, { 0xF0, 0x5B, 0x00 } },
{ 0x24, 1, { 0x5A, 0x00 }, 2, { 0xF0, 0x5A, 0x00 } },
/*------------------------------------------------*/
{ 0x42, 1, { 0x58, 0x00 }, 2, { 0xF0, 0x58, 0x00 } },
{ 0x26, 1, { 0x1C, 0x00 }, 2, { 0xF0, 0x1C, 0x00 } },
{ 0x27, 1, { 0x1B, 0x00 }, 2, { 0xF0, 0x1B, 0x00 } },
{ 0x28, 1, { 0x23, 0x00 }, 2, { 0xF0, 0x23, 0x00 } },
{ 0x29, 1, { 0x2B, 0x00 }, 2, { 0xF0, 0x2B, 0x00 } },
{ 0x2A, 1, { 0x34, 0x00 }, 2, { 0xF0, 0x34, 0x00 } },
{ 0x2B, 1, { 0x33, 0x00 }, 2, { 0xF0, 0x33, 0x00 } },
{ 0x2C, 1, { 0x3B, 0x00 }, 2, { 0xF0, 0x3B, 0x00 } },
{ 0x2D, 1, { 0x42, 0x00 }, 2, { 0xF0, 0x42, 0x00 } },
{ 0x2E, 1, { 0x4B, 0x00 }, 2, { 0xF0, 0x4B, 0x00 } },
{ 0x2F, 1, { 0x4C, 0x00 }, 2, { 0xF0, 0x4C, 0x00 } },
{ 0x30, 1, { 0x52, 0x00 }, 2, { 0xF0, 0x52, 0x00 } },
{ 0x33, 1, { 0x5D, 0x00 }, 2, { 0xF0, 0x5D, 0x00 } },
/*------------------------------------------------*/
{ 0x32, 1, { 0x12, 0x00 }, 2, { 0xF0, 0x12, 0x00 } },
{ 0x5E, 1, { 0x61, 0x00 }, 2, { 0xF0, 0x61, 0x00 } },
{ 0x34, 1, { 0x1A, 0x00 }, 2, { 0xF0, 0x1A, 0x00 } },
{ 0x35, 1, { 0x22, 0x00 }, 2, { 0xF0, 0x22, 0x00 } },
{ 0x36, 1, { 0x21, 0x00 }, 2, { 0xF0, 0x21, 0x00 } },
{ 0x37, 1, { 0x2A, 0x00 }, 2, { 0xF0, 0x2A, 0x00 } },
{ 0x38, 1, { 0x32, 0x00 }, 2, { 0xF0, 0x32, 0x00 } },
{ 0x39, 1, { 0x31, 0x00 }, 2, { 0xF0, 0x31, 0x00 } },
{ 0x3A, 1, { 0x3A, 0x00 }, 2, { 0xF0, 0x3A, 0x00 } },
{ 0x3B, 1, { 0x41, 0x00 }, 2, { 0xF0, 0x41, 0x00 } },
{ 0x3C, 1, { 0x49, 0x00 }, 2, { 0xF0, 0x49, 0x00 } },
{ 0x3D, 1, { 0x4A, 0x00 }, 2, { 0xF0, 0x4A, 0x00 } },
{ 0x3E, 1, { 0x59, 0x00 }, 2, { 0xF0, 0x59, 0x00 } },
/*------------------------------------------------*/
{ 0x25, 1, { 0x14, 0x00 }, 2, { 0xF0, 0x14, 0x00 } },
{ 0x73, 2, { 0xE0, 0x1F }, 3, { 0xE0, 0xF0, 0x1F } },
{ 0x40, 1, { 0x11, 0x00 }, 2, { 0xF0, 0x11, 0x00 } },
{ 0x41, 1, { 0x29, 0x00 }, 2, { 0xF0, 0x29, 0x00 } },
{ 0x71, 2, { 0xE0, 0x11 }, 3, { 0xE0, 0xF0, 0x11 } },
{ 0x74, 2, { 0xE0, 0x27 }, 3, { 0xE0, 0xF0, 0x27 } },
{ 0x75, 2, { 0xE0, 0x2F }, 3, { 0xE0, 0xF0, 0x2F } },
{ 0x6D, 2, { 0xE0, 0x14 }, 3, { 0xE0, 0xF0, 0x14 } },
/*------------------------------------------------*/
{ 0x6A, 2, { 0xE0, 0x70 }, 3, { 0xE0, 0xF0, 0x70 } },
{ 0x61, 2, { 0xE0, 0x6C }, 3, { 0xE0, 0xF0, 0x6C } },
{ 0x63, 2, { 0xE0, 0x7D }, 3, { 0xE0, 0xF0, 0x7D } },
{ 0x6B, 2, { 0xE0, 0x71 }, 3, { 0xE0, 0xF0, 0x71 } },
{ 0x67, 2, { 0xE0, 0x69 }, 3, { 0xE0, 0xF0, 0x69 } },
{ 0x69, 2, { 0xE0, 0x7A }, 3, { 0xE0, 0xF0, 0x7A } },
{ 0x62, 2, { 0xE0, 0x75 }, 3, { 0xE0, 0xF0, 0x75 } },
{ 0x64, 2, { 0xE0, 0x6B }, 3, { 0xE0, 0xF0, 0x6B } },
{ 0x68, 2, { 0xE0, 0x72 }, 3, { 0xE0, 0xF0, 0x72 } },
{ 0x66, 2, { 0xE0, 0x74 }, 3, { 0xE0, 0xF0, 0x74 } },
/*------------------------------------------------*/
{ 0x4D, 1, { 0x77, 0x00 }, 2, { 0xF0, 0x77, 0x00 } },
{ 0x70, 2, { 0xE0, 0x4A }, 3, { 0xE0, 0xF0, 0x4A } },
{ 0x3F, 1, { 0x7C, 0x00 }, 2, { 0xF0, 0x7C, 0x00 } },
{ 0x52, 1, { 0x7B, 0x00 }, 2, { 0xF0, 0x7B, 0x00 } },
{ 0x4F, 1, { 0x6C, 0x00 }, 2, { 0xF0, 0x6C, 0x00 } },
{ 0x50, 1, { 0x75, 0x00 }, 2, { 0xF0, 0x75, 0x00 } },
{ 0x51, 1, { 0x7D, 0x00 }, 2, { 0xF0, 0x7D, 0x00 } },
{ 0x56, 1, { 0x79, 0x00 }, 2, { 0xF0, 0x79, 0x00 } },
{ 0x53, 1, { 0x6B, 0x00 }, 2, { 0xF0, 0x6B, 0x00 } },
{ 0x54, 1, { 0x73, 0x00 }, 2, { 0xF0, 0x73, 0x00 } },
{ 0x55, 1, { 0x74, 0x00 }, 2, { 0xF0, 0x74, 0x00 } },
{ 0x57, 1, { 0x69, 0x00 }, 2, { 0xF0, 0x69, 0x00 } },
{ 0x58, 1, { 0x72, 0x00 }, 2, { 0xF0, 0x72, 0x00 } },
{ 0x59, 1, { 0x7A, 0x00 }, 2, { 0xF0, 0x7A, 0x00 } },
{ 0x6C, 2, { 0xE0, 0x5A }, 3, { 0xE0, 0xF0, 0x5A } },
{ 0x5A, 1, { 0x70, 0x00 }, 2, { 0xF0, 0x70, 0x00 } },
{ 0x5B, 1, { 0x71, 0x00 }, 2, { 0xF0, 0x71, 0x00 } },
};
 
 
static int keycodeCompare(const void *code1, const void *code2) {
return ((Keycode *) code1)->xKeycode - ((Keycode *) code2)->xKeycode;
}
 
 
static void initKeycode(void) {
qsort(kbdCodeTbl, sizeof(kbdCodeTbl)/sizeof(kbdCodeTbl[0]),
sizeof(kbdCodeTbl[0]), keycodeCompare);
}
 
 
static Keycode *lookupKeycode(unsigned int xKeycode) {
int lo, hi, tst;
int res;
 
lo = 0;
hi = sizeof(kbdCodeTbl) / sizeof(kbdCodeTbl[0]) - 1;
while (lo <= hi) {
tst = (lo + hi) / 2;
res = kbdCodeTbl[tst].xKeycode - xKeycode;
if (res == 0) {
return &kbdCodeTbl[tst];
}
if (res < 0) {
lo = tst + 1;
} else {
hi = tst - 1;
}
}
return NULL;
}
 
 
/**************************************************************/
 
 
#define KBD_BUF_MAX 100
#define KBD_BUF_NEXT(p) (((p) + 1) % KBD_BUF_MAX)
 
 
static Byte kbdBuf[KBD_BUF_MAX];
static int kbdBufWritePtr;
static int kbdBufReadPtr;
 
 
static void kbdBufInit(void) {
initKeycode();
kbdBufWritePtr = 0;
kbdBufReadPtr = 0;
}
 
 
static int kbdBufFree(void) {
if (kbdBufReadPtr <= kbdBufWritePtr) {
return KBD_BUF_MAX - (kbdBufWritePtr - kbdBufReadPtr) - 1;
} else {
return (kbdBufReadPtr - kbdBufWritePtr) - 1;
}
}
 
 
static void keyPressed(unsigned int xKeycode) {
Keycode *p;
int i;
 
if (debugKeycode) {
cPrintf("**** KEY PRESSED: 0x%08X ****\n", xKeycode);
}
p = lookupKeycode(xKeycode);
if (p == NULL) {
/* keycode not found */
return;
}
if (kbdBufFree() < (MAX_MAKE + MAX_BREAK) * 4) {
/* buffer full */
return;
}
for (i = 0; i < p->pcNumMake; i++) {
kbdBuf[kbdBufWritePtr] = p->pcKeyMake[i];
kbdBufWritePtr = KBD_BUF_NEXT(kbdBufWritePtr);
}
}
 
 
static void keyReleased(unsigned int xKeycode) {
Keycode *p;
int i;
 
if (debugKeycode) {
cPrintf("**** KEY RELEASED: 0x%08X ****\n", xKeycode);
}
p = lookupKeycode(xKeycode);
if (p == NULL) {
/* keycode not found */
return;
}
if (kbdBufFree() < MAX_BREAK * 4) {
/* buffer full */
return;
}
for (i = 0; i < p->pcNumBreak; i++) {
kbdBuf[kbdBufWritePtr] = p->pcKeyBreak[i];
kbdBufWritePtr = KBD_BUF_NEXT(kbdBufWritePtr);
}
}
 
 
/**************************************************************/
 
 
static Word kbdCtrl;
static Word kbdData;
 
 
static void kbdCallback(int dev) {
if (debug) {
cPrintf("\n**** KEYBOARD CALLBACK ****\n");
}
timerStart(KEYBOARD_MSEC, kbdCallback, dev);
if (kbdBufWritePtr == kbdBufReadPtr) {
/* no character ready */
return;
}
/* any character typed */
kbdData = kbdBuf[kbdBufReadPtr];
kbdBufReadPtr = KBD_BUF_NEXT(kbdBufReadPtr);
kbdCtrl |= KEYBOARD_RDY;
if (kbdCtrl & KEYBOARD_IEN) {
/* raise keyboard interrupt */
cpuSetInterrupt(IRQ_KEYBOARD);
}
}
 
 
Word keyboardRead(Word addr) {
Word data;
 
if (debug) {
cPrintf("\n**** KEYBOARD READ from 0x%08X", addr);
}
if (!installed) {
throwException(EXC_BUS_TIMEOUT);
}
if (addr == KEYBOARD_CTRL) {
data = kbdCtrl;
} else
if (addr == KEYBOARD_DATA) {
kbdCtrl &= ~KEYBOARD_RDY;
if (kbdCtrl & KEYBOARD_IEN) {
/* lower keyboard interrupt */
cpuResetInterrupt(IRQ_KEYBOARD);
}
data = kbdData;
} else {
/* illegal register */
throwException(EXC_BUS_TIMEOUT);
}
if (debug) {
cPrintf(", data = 0x%08X ****\n", data);
}
return data;
}
 
 
void keyboardWrite(Word addr, Word data) {
if (debug) {
cPrintf("\n**** KEYBOARD WRITE to 0x%08X, data = 0x%08X ****\n",
addr, data);
}
if (!installed) {
throwException(EXC_BUS_TIMEOUT);
}
if (addr == KEYBOARD_CTRL) {
if (data & KEYBOARD_IEN) {
kbdCtrl |= KEYBOARD_IEN;
} else {
kbdCtrl &= ~KEYBOARD_IEN;
}
if (data & KEYBOARD_RDY) {
kbdCtrl |= KEYBOARD_RDY;
} else {
kbdCtrl &= ~KEYBOARD_RDY;
}
if ((kbdCtrl & KEYBOARD_IEN) != 0 &&
(kbdCtrl & KEYBOARD_RDY) != 0) {
/* raise keyboard interrupt */
cpuSetInterrupt(IRQ_KEYBOARD);
} else {
/* lower keyboard interrupt */
cpuResetInterrupt(IRQ_KEYBOARD);
}
} else
if (addr == KEYBOARD_DATA) {
/* this register is read-only */
throwException(EXC_BUS_TIMEOUT);
} else {
/* illegal register */
throwException(EXC_BUS_TIMEOUT);
}
}
 
 
void keyboardReset(void) {
if (!installed) {
return;
}
cPrintf("Resetting Keyboard...\n");
kbdBufInit();
kbdCtrl = 0;
kbdData = 0;
timerStart(KEYBOARD_MSEC, kbdCallback, 0);
}
 
 
void keyboardInit(void) {
if (!installed) {
vgaInit();
}
keyboardReset();
}
 
 
void keyboardExit(void) {
if (!installed) {
return;
}
vgaExit();
}
/eco32/trunk/sim/term.c
0,0 → 1,316
/*
* term.c -- terminal simulation
*/
 
 
#ifdef __linux__
#define _XOPEN_SOURCE
#endif
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
 
#include "common.h"
#include "console.h"
#include "error.h"
#include "except.h"
#include "cpu.h"
#include "timer.h"
#include "term.h"
 
 
/**************************************************************/
 
 
static Bool debug = false;
 
 
typedef struct {
pid_t pid;
FILE *in;
FILE *out;
Word rcvrCtrl;
Word rcvrData;
int rcvrIRQ;
Word xmtrCtrl;
Word xmtrData;
int xmtrIRQ;
} Terminal;
 
 
static Terminal terminals[MAX_NTERMS];
static int numTerminals;
 
 
/**************************************************************/
 
 
static void rcvrCallback(int dev) {
int c;
 
if (debug) {
cPrintf("\n**** TERM RCVR CALLBACK ****\n");
}
timerStart(TERM_RCVR_MSEC, rcvrCallback, dev);
c = fgetc(terminals[dev].in);
if (c == EOF) {
/* no character typed */
return;
}
/* any character typed */
terminals[dev].rcvrData = c & 0xFF;
terminals[dev].rcvrCtrl |= TERM_RCVR_RDY;
if (terminals[dev].rcvrCtrl & TERM_RCVR_IEN) {
/* raise terminal rcvr interrupt */
cpuSetInterrupt(terminals[dev].rcvrIRQ);
}
}
 
 
static void xmtrCallback(int dev) {
if (debug) {
cPrintf("\n**** TERM XMTR CALLBACK ****\n");
}
fputc(terminals[dev].xmtrData & 0xFF, terminals[dev].out);
terminals[dev].xmtrCtrl |= TERM_XMTR_RDY;
if (terminals[dev].xmtrCtrl & TERM_XMTR_IEN) {
/* raise terminal xmtr interrupt */
cpuSetInterrupt(terminals[dev].xmtrIRQ);
}
}
 
 
/**************************************************************/
 
 
Word termRead(Word addr) {
int dev, reg;
Word data;
 
if (debug) {
cPrintf("\n**** TERM READ from 0x%08X", addr);
}
dev = addr >> 4;
if (dev >= numTerminals) {
/* illegal device */
throwException(EXC_BUS_TIMEOUT);
}
reg = addr & 0x0F;
if (reg == TERM_RCVR_CTRL) {
data = terminals[dev].rcvrCtrl;
} else
if (reg == TERM_RCVR_DATA) {
terminals[dev].rcvrCtrl &= ~TERM_RCVR_RDY;
if (terminals[dev].rcvrCtrl & TERM_RCVR_IEN) {
/* lower terminal rcvr interrupt */
cpuResetInterrupt(terminals[dev].rcvrIRQ);
}
data = terminals[dev].rcvrData;
} else
if (reg == TERM_XMTR_CTRL) {
data = terminals[dev].xmtrCtrl;
} else
if (reg == TERM_XMTR_DATA) {
/* this register is write-only */
throwException(EXC_BUS_TIMEOUT);
} else {
/* illegal register */
throwException(EXC_BUS_TIMEOUT);
}
if (debug) {
cPrintf(", data = 0x%08X ****\n", data);
}
return data;
}
 
 
void termWrite(Word addr, Word data) {
int dev, reg;
 
if (debug) {
cPrintf("\n**** TERM WRITE to 0x%08X, data = 0x%08X ****\n",
addr, data);
}
dev = addr >> 4;
if (dev >= numTerminals) {
/* illegal device */
throwException(EXC_BUS_TIMEOUT);
}
reg = addr & 0x0F;
if (reg == TERM_RCVR_CTRL) {
if (data & TERM_RCVR_IEN) {
terminals[dev].rcvrCtrl |= TERM_RCVR_IEN;
} else {
terminals[dev].rcvrCtrl &= ~TERM_RCVR_IEN;
}
if (data & TERM_RCVR_RDY) {
terminals[dev].rcvrCtrl |= TERM_RCVR_RDY;
} else {
terminals[dev].rcvrCtrl &= ~TERM_RCVR_RDY;
}
if ((terminals[dev].rcvrCtrl & TERM_RCVR_IEN) != 0 &&
(terminals[dev].rcvrCtrl & TERM_RCVR_RDY) != 0) {
/* raise terminal rcvr interrupt */
cpuSetInterrupt(terminals[dev].rcvrIRQ);
} else {
/* lower terminal rcvr interrupt */
cpuResetInterrupt(terminals[dev].rcvrIRQ);
}
} else
if (reg == TERM_RCVR_DATA) {
/* this register is read-only */
throwException(EXC_BUS_TIMEOUT);
} else
if (reg == TERM_XMTR_CTRL) {
if (data & TERM_XMTR_IEN) {
terminals[dev].xmtrCtrl |= TERM_XMTR_IEN;
} else {
terminals[dev].xmtrCtrl &= ~TERM_XMTR_IEN;
}
if (data & TERM_XMTR_RDY) {
terminals[dev].xmtrCtrl |= TERM_XMTR_RDY;
} else {
terminals[dev].xmtrCtrl &= ~TERM_XMTR_RDY;
}
if ((terminals[dev].xmtrCtrl & TERM_XMTR_IEN) != 0 &&
(terminals[dev].xmtrCtrl & TERM_XMTR_RDY) != 0) {
/* raise terminal xmtr interrupt */
cpuSetInterrupt(terminals[dev].xmtrIRQ);
} else {
/* lower terminal xmtr interrupt */
cpuResetInterrupt(terminals[dev].xmtrIRQ);
}
} else
if (reg == TERM_XMTR_DATA) {
terminals[dev].xmtrData = data & 0xFF;
terminals[dev].xmtrCtrl &= ~TERM_XMTR_RDY;
if (terminals[dev].xmtrCtrl & TERM_XMTR_IEN) {
/* lower terminal xmtr interrupt */
cpuResetInterrupt(terminals[dev].xmtrIRQ);
}
timerStart(TERM_XMTR_MSEC, xmtrCallback, dev);
} else {
/* illegal register */
throwException(EXC_BUS_TIMEOUT);
}
}
 
 
/**************************************************************/
 
 
void termReset(void) {
int i;
 
cPrintf("Resetting Terminals...\n");
for (i = 0; i < numTerminals; i++) {
terminals[i].rcvrCtrl = 0;
terminals[i].rcvrData = 0;
terminals[i].rcvrIRQ = IRQ_TERM_0_RCVR + 2 * i;
timerStart(TERM_RCVR_MSEC, rcvrCallback, i);
terminals[i].xmtrCtrl = TERM_XMTR_RDY;
terminals[i].xmtrData = 0;
terminals[i].xmtrIRQ = IRQ_TERM_0_XMTR + 2 * i;
}
}
 
 
static int openPty(int *master, int *slave, char *name) {
/* try to open master */
strcpy(name, "/dev/ptmx");
*master = open(name, O_RDWR | O_NONBLOCK);
if (*master < 0) {
/* open failed */
return -1;
}
grantpt(*master);
unlockpt(*master);
/* master opened, try to open slave */
strcpy(name, ptsname(*master));
*slave = open(name, O_RDWR | O_NONBLOCK);
if (*slave < 0) {
/* open failed, close master */
close(*master);
return -1;
}
/* all is well */
return 0;
}
 
 
static void makeRaw(struct termios *tp) {
tp->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
tp->c_oflag &= ~OPOST;
tp->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
tp->c_cflag &= ~(CSIZE|PARENB);
tp->c_cflag |= CS8;
}
 
 
void termInit(int numTerms) {
int master, slave;
char ptyName[100];
char ptyTitle[100];
struct termios termios;
int i;
 
numTerminals = numTerms;
for (i = 0; i < numTerminals; i++) {
/* open pseudo terminal */
if (openPty(&master, &slave, ptyName) < 0) {
error("cannot open pseudo terminal %d", i);
}
if (debug) {
cPrintf("pseudo terminal '%s': master fd = %d, slave fd = %d\n",
ptyName, master, slave);
}
/* set mode to raw */
tcgetattr(slave, &termios);
makeRaw(&termios);
tcsetattr(slave, TCSANOW, &termios);
/* fork and exec a new xterm */
terminals[i].pid = fork();
if (terminals[i].pid < 0) {
error("cannot fork xterm process %d", i);
}
if (terminals[i].pid == 0) {
/* terminal process */
setpgid(0, 0);
close(2);
close(master);
sprintf(ptyName, "-Sab%d", slave);
sprintf(ptyTitle, "ECO32 Terminal %d", i);
execlp("xterm", "xterm", "-title", ptyTitle, ptyName, NULL);
error("cannot exec xterm process %d", i);
}
fcntl(master, F_SETFL, O_NONBLOCK);
terminals[i].in = fdopen(master, "r");
setvbuf(terminals[i].in, NULL, _IONBF, 0);
terminals[i].out = fdopen(master, "w");
setvbuf(terminals[i].out, NULL, _IONBF, 0);
/* skip the window id written by xterm */
while (fgetc(terminals[i].in) != '\n') ;
}
termReset();
}
 
 
void termExit(void) {
int i;
 
/* kill and wait for all xterm processes */
for (i = 0; i < numTerminals; i++) {
if (terminals[i].pid > 0) {
kill(terminals[i].pid, SIGKILL);
waitpid(terminals[i].pid, NULL, 0);
}
}
}
/eco32/trunk/sim/dspkbd.h
0,0 → 1,34
/*
* dspkbd.h -- display & keyboard controller simulation
*/
 
 
#ifndef _DSPKBD_H_
#define _DSPKBD_H_
 
 
Word displayRead(Word addr);
void displayWrite(Word addr, Word data);
 
void displayReset(void);
void displayInit(void);
void displayExit(void);
 
 
#define KEYBOARD_CTRL 0 /* keyboard control register */
#define KEYBOARD_DATA 4 /* keyboard data register */
 
#define KEYBOARD_RDY 0x01 /* keyboard has a character */
#define KEYBOARD_IEN 0x02 /* enable keyboard interrupt */
#define KEYBOARD_MSEC 20 /* input checking interval */
 
 
Word keyboardRead(Word addr);
void keyboardWrite(Word addr, Word data);
 
void keyboardReset(void);
void keyboardInit(void);
void keyboardExit(void);
 
 
#endif /* _DSPKBD_H_ */
/eco32/trunk/sim/term.h
0,0 → 1,32
/*
* term.h -- terminal simulation
*/
 
 
#ifndef _TERM_H_
#define _TERM_H_
 
 
#define TERM_RCVR_CTRL 0 /* receiver control register */
#define TERM_RCVR_DATA 4 /* receiver data register */
#define TERM_XMTR_CTRL 8 /* transmitter control register */
#define TERM_XMTR_DATA 12 /* transmitter data register */
 
#define TERM_RCVR_RDY 0x01 /* receiver has a character */
#define TERM_RCVR_IEN 0x02 /* enable receiver interrupt */
#define TERM_RCVR_MSEC 20 /* input checking interval */
 
#define TERM_XMTR_RDY 0x01 /* transmitter accepts a character */
#define TERM_XMTR_IEN 0x02 /* enable transmitter interrupt */
#define TERM_XMTR_MSEC 8 /* output speed */
 
 
Word termRead(Word addr);
void termWrite(Word addr, Word data);
 
void termReset(void);
void termInit(int numTerms);
void termExit(void);
 
 
#endif /* _TERM_H_ */
/eco32/trunk/sim/disasm.c
0,0 → 1,141
/*
* disasm.c -- disassembler
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#include "common.h"
#include "console.h"
#include "error.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 ? -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:
error("illegal entry in instruction table");
}
}
return instrBuffer;
}
/eco32/trunk/sim/disasm.h
0,0 → 1,13
/*
* disasm.h -- disassembler
*/
 
 
#ifndef _DISASM_H_
#define _DISASM_H_
 
 
char *disasm(Word instr, Word locus);
 
 
#endif /* _DISASM_H_ */
/eco32/trunk/sim/cpu.c
0,0 → 1,657
/*
* cpu.c -- CPU simulation
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
 
#include "common.h"
#include "console.h"
#include "error.h"
#include "except.h"
#include "instr.h"
#include "cpu.h"
#include "mmu.h"
#include "timer.h"
 
 
/**************************************************************/
 
 
#define RR(n) r[n]
#define WR(n,d) ((void) ((n) != 0 ? r[n] = (d) : (d)))
 
#define V (psw & PSW_V)
#define UM (psw & PSW_UM)
#define PUM (psw & PSW_PUM)
#define OUM (psw & PSW_OUM)
#define IE (psw & PSW_IE)
#define PIE (psw & PSW_PIE)
#define OIE (psw & PSW_OIE)
 
 
/**************************************************************/
 
 
static Bool debugIRQ = false; /* set to true if debugging IRQs */
 
static Word pc; /* program counter */
static Word psw; /* processor status word */
static Word r[32]; /* general purpose registers */
 
static int instrCount; /* counts instrs for timer tick */
static unsigned irqPending; /* one bit for each pending IRQ */
 
static Bool breakSet; /* breakpoint set if true */
static Word breakAddr; /* if breakSet, this is where */
 
static Word total; /* counts total number of instrs */
 
static Bool run; /* CPU runs continuously if true */
 
static Word startAddr; /* start of ROM (or start of RAM, */
/* in case a program was loaded) */
 
 
/**************************************************************/
 
 
static void handleRealTimeTasks(void) {
/* handle 'real-time' tasks */
if (++instrCount == INSTRS_PER_MSEC) {
instrCount = 0;
timerTick();
}
}
 
 
static void handleInterrupts(void) {
unsigned irqMask;
unsigned irqSeen;
int priority;
 
/* handle exceptions and interrupts */
if (irqPending == 0) {
/* no exception or interrupt pending */
return;
}
/* at least one exception or interrupt is pending */
irqMask = ~PSW_IRQ_MASK | (psw & PSW_IRQ_MASK);
if (debugIRQ) {
cPrintf("**** IRQ = 0x%08X ****\n", irqPending);
cPrintf("**** MASK = 0x%08X ****\n", irqMask);
}
irqSeen = irqPending & irqMask;
if (irqSeen == 0) {
/* none that gets through */
return;
}
/* determine the one with the highest priority */
for (priority = 31; priority >= 0; priority--) {
if ((irqSeen & ((unsigned) 1 << priority)) != 0) {
/* highest priority among visible ones found */
break;
}
}
/* acknowledge exception, or interrupt if enabled */
if (priority >= 16 || IE != 0) {
if (priority >= 16) {
/* clear corresponding bit in irqPending vector */
/* only done for exceptions, since interrupts are level-sensitive */
irqPending &= ~((unsigned) 1 << priority);
}
/* copy and reset interrupt enable bit in PSW */
if (PIE != 0) {
psw |= PSW_OIE;
} else {
psw &= ~PSW_OIE;
}
if (IE != 0) {
psw |= PSW_PIE;
} else {
psw &= ~PSW_PIE;
}
psw &= ~PSW_IE;
/* copy and reset user mode enable bit in PSW */
if (PUM != 0) {
psw |= PSW_OUM;
} else {
psw &= ~PSW_OUM;
}
if (UM != 0) {
psw |= PSW_PUM;
} else {
psw &= ~PSW_PUM;
}
psw &= ~PSW_UM;
/* reflect priority in PSW */
psw &= ~PSW_PRIO_MASK;
psw |= priority << PSW_PRIO_SHFT;
/* save interrupt return address and start service routine */
WR(30, pc);
if (V == 0) {
/* exceptions and interrupts are vectored to ROM */
pc = 0xC0000000 | ROM_BASE;
} else {
/* exceptions and interrupts are vectored to RAM */
pc = 0xC0000000;
}
if (priority == EXC_TLB_MISS &&
(mmuGetBadAddr() & 0x80000000) == 0) {
/* user TLB miss exception */
pc |= 0x00000008;
} else {
/* any other exception or interrupt */
pc |= 0x00000004;
}
}
}
 
 
static void execNextInstruction(void) {
Word instr;
Word next;
int op, reg1, reg2, reg3;
Half immed;
Word offset;
int scnt;
Word smsk;
Word aux;
 
/* count the instruction */
total++;
/* fetch the instruction */
instr = mmuReadWord(pc, UM);
/* decode the instruction */
op = (instr >> 26) & 0x3F;
reg1 = (instr >> 21) & 0x1F;
reg2 = (instr >> 16) & 0x1F;
reg3 = (instr >> 11) & 0x1F;
immed = instr & 0x0000FFFF;
offset = instr & 0x03FFFFFF;
next = pc + 4;
/* execute the instruction */
switch (op) {
case OP_ADD:
WR(reg3, (signed int) RR(reg1) + (signed int) RR(reg2));
break;
case OP_ADDI:
WR(reg2, (signed int) RR(reg1) + (signed int) SEXT16(immed));
break;
case OP_SUB:
WR(reg3, (signed int) RR(reg1) - (signed int) RR(reg2));
break;
case OP_SUBI:
WR(reg2, (signed int) RR(reg1) - (signed int) SEXT16(immed));
break;
case OP_MUL:
WR(reg3, (signed int) RR(reg1) * (signed int) RR(reg2));
break;
case OP_MULI:
WR(reg2, (signed int) RR(reg1) * (signed int) SEXT16(immed));
break;
case OP_MULU:
WR(reg3, RR(reg1) * RR(reg2));
break;
case OP_MULUI:
WR(reg2, RR(reg1) * ZEXT16(immed));
break;
case OP_DIV:
if (RR(reg2) == 0) {
throwException(EXC_DIVIDE);
}
WR(reg3, (signed int) RR(reg1) / (signed int) RR(reg2));
break;
case OP_DIVI:
if (SEXT16(immed) == 0) {
throwException(EXC_DIVIDE);
}
WR(reg2, (signed int) RR(reg1) / (signed int) SEXT16(immed));
break;
case OP_DIVU:
if (RR(reg2) == 0) {
throwException(EXC_DIVIDE);
}
WR(reg3, RR(reg1) / RR(reg2));
break;
case OP_DIVUI:
if (SEXT16(immed) == 0) {
throwException(EXC_DIVIDE);
}
WR(reg2, RR(reg1) / ZEXT16(immed));
break;
case OP_REM:
if (RR(reg2) == 0) {
throwException(EXC_DIVIDE);
}
WR(reg3, (signed int) RR(reg1) % (signed int) RR(reg2));
break;
case OP_REMI:
if (SEXT16(immed) == 0) {
throwException(EXC_DIVIDE);
}
WR(reg2, (signed int) RR(reg1) % (signed int) SEXT16(immed));
break;
case OP_REMU:
if (RR(reg2) == 0) {
throwException(EXC_DIVIDE);
}
WR(reg3, RR(reg1) % RR(reg2));
break;
case OP_REMUI:
if (SEXT16(immed) == 0) {
throwException(EXC_DIVIDE);
}
WR(reg2, RR(reg1) % ZEXT16(immed));
break;
case OP_AND:
WR(reg3, RR(reg1) & RR(reg2));
break;
case OP_ANDI:
WR(reg2, RR(reg1) & ZEXT16(immed));
break;
case OP_OR:
WR(reg3, RR(reg1) | RR(reg2));
break;
case OP_ORI:
WR(reg2, RR(reg1) | ZEXT16(immed));
break;
case OP_XOR:
WR(reg3, RR(reg1) ^ RR(reg2));
break;
case OP_XORI:
WR(reg2, RR(reg1) ^ ZEXT16(immed));
break;
case OP_XNOR:
WR(reg3, ~(RR(reg1) ^ RR(reg2)));
break;
case OP_XNORI:
WR(reg2, ~(RR(reg1) ^ ZEXT16(immed)));
break;
case OP_SLL:
scnt = RR(reg2) & 0x1F;
WR(reg3, RR(reg1) << scnt);
break;
case OP_SLLI:
scnt = immed & 0x1F;
WR(reg2, RR(reg1) << scnt);
break;
case OP_SLR:
scnt = RR(reg2) & 0x1F;
WR(reg3, RR(reg1) >> scnt);
break;
case OP_SLRI:
scnt = immed & 0x1F;
WR(reg2, RR(reg1) >> scnt);
break;
case OP_SAR:
scnt = RR(reg2) & 0x1F;
smsk = (RR(reg1) & 0x80000000 ? ~(((Word) 0xFFFFFFFF) >> scnt) : 0);
WR(reg3, smsk | (RR(reg1) >> scnt));
break;
case OP_SARI:
scnt = immed & 0x1F;
smsk = (RR(reg1) & 0x80000000 ? ~(((Word) 0xFFFFFFFF) >> scnt) : 0);
WR(reg2, smsk | (RR(reg1) >> scnt));
break;
case OP_LDHI:
WR(reg2, ZEXT16(immed) << 16);
break;
case OP_BEQ:
if (RR(reg1) == RR(reg2)) {
next += SEXT16(immed) << 2;
}
break;
case OP_BNE:
if (RR(reg1) != RR(reg2)) {
next += SEXT16(immed) << 2;
}
break;
case OP_BLE:
if ((signed int) RR(reg1) <= (signed int) RR(reg2)) {
next += SEXT16(immed) << 2;
}
break;
case OP_BLEU:
if (RR(reg1) <= RR(reg2)) {
next += SEXT16(immed) << 2;
}
break;
case OP_BLT:
if ((signed int) RR(reg1) < (signed int) RR(reg2)) {
next += SEXT16(immed) << 2;
}
break;
case OP_BLTU:
if (RR(reg1) < RR(reg2)) {
next += SEXT16(immed) << 2;
}
break;
case OP_BGE:
if ((signed int) RR(reg1) >= (signed int) RR(reg2)) {
next += SEXT16(immed) << 2;
}
break;
case OP_BGEU:
if (RR(reg1) >= RR(reg2)) {
next += SEXT16(immed) << 2;
}
break;
case OP_BGT:
if ((signed int) RR(reg1) > (signed int) RR(reg2)) {
next += SEXT16(immed) << 2;
}
break;
case OP_BGTU:
if (RR(reg1) > RR(reg2)) {
next += SEXT16(immed) << 2;
}
break;
case OP_J:
next += SEXT26(offset) << 2;
break;
case OP_JR:
next = RR(reg1);
break;
case OP_JAL:
WR(31, next);
next += SEXT26(offset) << 2;
break;
case OP_JALR:
aux = RR(reg1);
WR(31, next);
next = aux;
break;
case OP_TRAP:
throwException(EXC_TRAP);
break;
case OP_RFX:
if (UM != 0) {
throwException(EXC_PRV_INSTRCT);
}
if (PIE != 0) {
psw |= PSW_IE;
} else {
psw &= ~PSW_IE;
}
if (OIE != 0) {
psw |= PSW_PIE;
} else {
psw &= ~PSW_PIE;
}
if (PUM != 0) {
psw |= PSW_UM;
} else {
psw &= ~PSW_UM;
}
if (OUM != 0) {
psw |= PSW_PUM;
} else {
psw &= ~PSW_PUM;
}
next = RR(30);
break;
case OP_LDW:
WR(reg2, mmuReadWord(RR(reg1) + SEXT16(immed), UM));
break;
case OP_LDH:
WR(reg2, (signed int) (signed short)
mmuReadHalf(RR(reg1) + SEXT16(immed), UM));
break;
case OP_LDHU:
WR(reg2, mmuReadHalf(RR(reg1) + SEXT16(immed), UM));
break;
case OP_LDB:
WR(reg2, (signed int) (signed char)
mmuReadByte(RR(reg1) + SEXT16(immed), UM));
break;
case OP_LDBU:
WR(reg2, mmuReadByte(RR(reg1) + SEXT16(immed), UM));
break;
case OP_STW:
mmuWriteWord(RR(reg1) + SEXT16(immed), RR(reg2), UM);
break;
case OP_STH:
mmuWriteHalf(RR(reg1) + SEXT16(immed), RR(reg2), UM);
break;
case OP_STB:
mmuWriteByte(RR(reg1) + SEXT16(immed), RR(reg2), UM);
break;
case OP_MVFS:
switch (immed) {
case 0:
WR(reg2, psw);
break;
case 1:
WR(reg2, mmuGetIndex());
break;
case 2:
WR(reg2, mmuGetEntryHi());
break;
case 3:
WR(reg2, mmuGetEntryLo());
break;
case 4:
WR(reg2, mmuGetBadAddr());
break;
default:
throwException(EXC_ILL_INSTRCT);
break;
}
break;
case OP_MVTS:
if (UM != 0) {
throwException(EXC_PRV_INSTRCT);
}
switch (immed) {
case 0:
psw = RR(reg2);
break;
case 1:
mmuSetIndex(RR(reg2));
break;
case 2:
mmuSetEntryHi(RR(reg2));
break;
case 3:
mmuSetEntryLo(RR(reg2));
break;
case 4:
mmuSetBadAddr(RR(reg2));
break;
default:
throwException(EXC_ILL_INSTRCT);
break;
}
break;
case OP_TBS:
if (UM != 0) {
throwException(EXC_PRV_INSTRCT);
}
mmuTbs();
break;
case OP_TBWR:
if (UM != 0) {
throwException(EXC_PRV_INSTRCT);
}
mmuTbwr();
break;
case OP_TBRI:
if (UM != 0) {
throwException(EXC_PRV_INSTRCT);
}
mmuTbri();
break;
case OP_TBWI:
if (UM != 0) {
throwException(EXC_PRV_INSTRCT);
}
mmuTbwi();
break;
default:
throwException(EXC_ILL_INSTRCT);
break;
}
/* update PC */
pc = next;
}
 
 
/**************************************************************/
 
 
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;
}
 
 
Word cpuGetIRQ(void) {
return irqPending;
}
 
 
Bool cpuTestBreak(void) {
return breakSet;
}
 
 
Word cpuGetBreak(void) {
return breakAddr;
}
 
 
void cpuSetBreak(Word addr) {
breakAddr = addr;
breakSet = true;
}
 
 
void cpuResetBreak(void) {
breakSet = false;
}
 
 
Word cpuGetTotal(void) {
return total;
}
 
 
void cpuStep(void) {
jmp_buf myEnvironment;
int exception;
 
exception = setjmp(myEnvironment);
if (exception == 0) {
/* initialization */
pushEnvironment(&myEnvironment);
handleRealTimeTasks();
execNextInstruction();
handleInterrupts();
} else {
/* an exception was thrown */
cpuSetInterrupt(exception);
handleInterrupts();
}
popEnvironment();
}
 
 
void cpuRun(void) {
jmp_buf myEnvironment;
int exception;
 
run = true;
exception = setjmp(myEnvironment);
if (exception == 0) {
/* initialization */
pushEnvironment(&myEnvironment);
} else {
/* an exception was thrown */
cpuSetInterrupt(exception);
handleInterrupts();
if (breakSet && pc == breakAddr) {
run = false;
}
}
while (run) {
handleRealTimeTasks();
execNextInstruction();
handleInterrupts();
if (breakSet && pc == breakAddr) {
run = false;
}
}
popEnvironment();
}
 
 
void cpuHalt(void) {
run = false;
}
 
 
void cpuSetInterrupt(int priority) {
irqPending |= ((unsigned) 1 << priority);
}
 
 
void cpuResetInterrupt(int priority) {
irqPending &= ~((unsigned) 1 << priority);
}
 
 
void cpuReset(void) {
int i;
 
cPrintf("Resetting CPU...\n");
/* most registers are in a random state */
for (i = 1; i < 32; i++) {
r[i] = rand();
}
/* but not all */
pc = startAddr;
r[0] = 0;
psw = 0;
/* reset simulator control variables */
instrCount = 0;
irqPending = 0;
total = 0;
}
 
 
void cpuInit(Word initialPC) {
startAddr = initialPC;
cpuReset();
}
 
 
void cpuExit(void) {
}
/eco32/trunk/sim/except.c
0,0 → 1,44
/*
* except.c -- exception handling
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
 
#include "error.h"
#include "except.h"
 
 
#define MAX_ENV_NEST_DEPTH 10
 
 
static jmp_buf *environments[MAX_ENV_NEST_DEPTH];
static int currentEnvironment = -1;
 
 
void throwException(int exception) {
if (currentEnvironment < 0) {
error("exception %d thrown while no environment active", exception);
}
longjmp(*environments[currentEnvironment], exception);
}
 
 
void pushEnvironment(jmp_buf *environment) {
if (currentEnvironment == MAX_ENV_NEST_DEPTH - 1) {
error("too many environments active");
}
currentEnvironment++;
environments[currentEnvironment] = environment;
}
 
 
void popEnvironment(void) {
if (currentEnvironment < 0) {
error("cannot pop environment - none active");
}
currentEnvironment--;
}
/eco32/trunk/sim/error.c
0,0 → 1,45
/*
* error.c -- error handler
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
 
#include "common.h"
#include "console.h"
#include "error.h"
#include "cpu.h"
#include "mmu.h"
#include "memory.h"
#include "timer.h"
#include "dspkbd.h"
#include "term.h"
#include "disk.h"
#include "output.h"
#include "graph.h"
 
 
void error(char *fmt, ...) {
va_list ap;
 
cpuExit();
mmuExit();
memoryExit();
timerExit();
displayExit();
keyboardExit();
termExit();
diskExit();
outputExit();
graphExit();
cExit();
va_start(ap, fmt);
fprintf(stderr, "Error: ");
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
exit(1);
}
/eco32/trunk/sim/disk.c
0,0 → 1,253
/*
* disk.c -- disk simulation
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
 
#include "common.h"
#include "console.h"
#include "error.h"
#include "except.h"
#include "cpu.h"
#include "timer.h"
#include "disk.h"
 
 
static Bool debug = false;
 
static FILE *diskImage;
static long totalSectors;
 
static Word diskCtrl;
static Word diskCnt;
static Word diskSct;
static Word diskCap;
 
static Byte diskBuffer[8 * SECTOR_SIZE];
 
static long lastSct;
 
 
static Word readWord(Byte *p) {
Word data;
 
data = ((Word) *(p + 0)) << 24 |
((Word) *(p + 1)) << 16 |
((Word) *(p + 2)) << 8 |
((Word) *(p + 3)) << 0;
return data;
}
 
 
static void writeWord(Byte *p, Word data) {
*(p + 0) = (Byte) (data >> 24);
*(p + 1) = (Byte) (data >> 16);
*(p + 2) = (Byte) (data >> 8);
*(p + 3) = (Byte) (data >> 0);
}
 
 
static void diskCallback(int n) {
int numScts;
 
if (debug) {
cPrintf("\n**** DISK CALLBACK, n = %d ****\n", n);
}
if (n == 0) {
/* startup time expired */
diskCap = totalSectors;
diskCtrl |= DISK_READY;
return;
}
/* disk read or write */
numScts = ((diskCnt - 1) & 0x07) + 1;
if (diskCap != 0 &&
diskSct < diskCap &&
diskSct + numScts <= diskCap) {
/* do the transfer */
if (fseek(diskImage, diskSct * SECTOR_SIZE, SEEK_SET) != 0) {
error("cannot position to sector in disk image");
}
if (diskCtrl & DISK_WRT) {
/* buffer --> disk */
if (fwrite(diskBuffer, SECTOR_SIZE, numScts, diskImage) != numScts) {
error("cannot write to disk image");
}
} else {
/* disk --> buffer */
if (fread(diskBuffer, SECTOR_SIZE, numScts, diskImage) != numScts) {
error("cannot read from disk image");
}
}
lastSct = (long) diskSct + (long) numScts - 1;
} else {
/* sectors requested exceed disk capacity */
/* or we have no disk at all */
diskCtrl |= DISK_ERR;
}
diskCtrl &= ~DISK_STRT;
diskCtrl |= DISK_DONE;
if (diskCtrl & DISK_IEN) {
/* raise disk interrupt */
cpuSetInterrupt(IRQ_DISK);
}
}
 
 
Word diskRead(Word addr) {
Word data;
 
if (debug) {
cPrintf("\n**** DISK READ from 0x%08X", addr);
}
if (addr == DISK_CTRL) {
data = diskCtrl;
} else
if (addr == DISK_CNT) {
data = diskCnt;
} else
if (addr == DISK_SCT) {
data = diskSct;
} else
if (addr == DISK_CAP) {
data = diskCap;
} else
if (addr & 0x80000) {
/* buffer access */
data = readWord(diskBuffer + (addr & 0x0FFC));
} else {
/* illegal register */
throwException(EXC_BUS_TIMEOUT);
}
if (debug) {
cPrintf(", data = 0x%08X ****\n", data);
}
return data;
}
 
 
void diskWrite(Word addr, Word data) {
long delta;
 
if (debug) {
cPrintf("\n**** DISK WRITE to 0x%08X, data = 0x%08X ****\n",
addr, data);
}
if (addr == DISK_CTRL) {
if (data & DISK_WRT) {
diskCtrl |= DISK_WRT;
} else {
diskCtrl &= ~DISK_WRT;
}
if (data & DISK_IEN) {
diskCtrl |= DISK_IEN;
} else {
diskCtrl &= ~DISK_IEN;
}
if (data & DISK_STRT) {
diskCtrl |= DISK_STRT;
diskCtrl &= ~DISK_ERR;
diskCtrl &= ~DISK_DONE;
/* only start a disk operation if disk is present */
if (diskCap != 0) {
delta = labs((long) diskSct - lastSct);
if (delta > diskCap) {
delta = diskCap;
}
timerStart(DISK_DELAY + (delta * DISK_SEEK) / diskCap,
diskCallback, 1);
}
} else {
diskCtrl &= ~DISK_STRT;
if (data & DISK_ERR) {
diskCtrl |= DISK_ERR;
} else {
diskCtrl &= ~DISK_ERR;
}
if (data & DISK_DONE) {
diskCtrl |= DISK_DONE;
} else {
diskCtrl &= ~DISK_DONE;
}
}
if ((diskCtrl & DISK_IEN) != 0 &&
(diskCtrl & DISK_DONE) != 0) {
/* raise disk interrupt */
cpuSetInterrupt(IRQ_DISK);
} else {
/* lower disk interrupt */
cpuResetInterrupt(IRQ_DISK);
}
} else
if (addr == DISK_CNT) {
diskCnt = data;
} else
if (addr == DISK_SCT) {
diskSct = data;
} else
if (addr == DISK_CAP) {
/* this register is read-only */
throwException(EXC_BUS_TIMEOUT);
} else
if (addr & 0x80000) {
/* buffer access */
writeWord(diskBuffer + (addr & 0x0FFC), data);
} else {
/* illegal register */
throwException(EXC_BUS_TIMEOUT);
}
}
 
 
void diskReset(void) {
cPrintf("Resetting Disk...\n");
diskCtrl = 0;
diskCnt = 0;
diskSct = 0;
diskCap = 0;
lastSct = 0;
if (totalSectors != 0) {
cPrintf("Disk of size %ld sectors (%ld bytes) installed.\n",
totalSectors, totalSectors * SECTOR_SIZE);
timerStart(DISK_STARTUP, diskCallback, 0);
}
}
 
 
void diskInit(char *diskImageName) {
long numBytes;
 
if (diskImageName == NULL) {
/* do not install disk */
diskImage = NULL;
totalSectors = 0;
} else {
/* try to install disk */
diskImage = fopen(diskImageName, "r+b");
if (diskImage == NULL) {
error("cannot open disk image '%s'", diskImageName);
}
fseek(diskImage, 0, SEEK_END);
numBytes = ftell(diskImage);
fseek(diskImage, 0, SEEK_SET);
if (numBytes % SECTOR_SIZE != 0) {
error("disk image '%s' does not contain an integral number of sectors",
diskImageName);
}
totalSectors = numBytes / SECTOR_SIZE;
}
diskReset();
}
 
 
void diskExit(void) {
if (diskImage == NULL) {
/* disk not installed */
return;
}
fclose(diskImage);
}
/eco32/trunk/sim/cpu.h
0,0 → 1,60
/*
* cpu.h -- CPU simulation
*/
 
 
#ifndef _CPU_H_
#define _CPU_H_
 
 
#define IRQ_TIMER 14 /* timer interrupt */
#define IRQ_DISK 8 /* disk interrupt */
#define IRQ_KEYBOARD 4 /* keyboard interrupt */
#define IRQ_TERM_1_RCVR 3 /* terminal 1 receiver interrupt */
#define IRQ_TERM_1_XMTR 2 /* terminal 1 transmitter interrupt */
#define IRQ_TERM_0_RCVR 1 /* terminal 0 receiver interrupt */
#define IRQ_TERM_0_XMTR 0 /* terminal 0 transmitter interrupt */
 
#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 */
#define PSW_PRIO_SHFT 16 /* shift count to reach these bits */
#define PSW_IRQ_MASK 0x0000FFFF /* IRQ mask bits */
 
 
Word cpuGetPC(void);
void cpuSetPC(Word addr);
 
Word cpuGetReg(int regnum);
void cpuSetReg(int regnum, Word value);
 
Word cpuGetPSW(void);
void cpuSetPSW(Word value);
 
Word cpuGetIRQ(void);
 
Bool cpuTestBreak(void);
Word cpuGetBreak(void);
void cpuSetBreak(Word addr);
void cpuResetBreak(void);
 
Word cpuGetTotal(void);
 
void cpuStep(void);
void cpuRun(void);
void cpuHalt(void);
 
void cpuSetInterrupt(int priority);
void cpuResetInterrupt(int priority);
 
void cpuReset(void);
void cpuInit(Word initialPC);
void cpuExit(void);
 
 
#endif /* _CPU_H_ */
/eco32/trunk/sim/Makefile
0,0 → 1,42
#
# Makefile for ECO32 simulator
#
 
BUILD = ../build
 
CC = gcc -m32
CFLAGS = -g -Wall -I./getline -I/usr/X11R7/include
LDFLAGS = -g -L./getline -L/usr/X11R7/lib -Wl,-rpath -Wl,/usr/X11R7/lib
LDLIBS = -lgetline -lX11 -lpthread -lm
 
SRCS = main.c console.c error.c except.c command.c \
instr.c asm.c disasm.c cpu.c mmu.c memory.c \
timer.c dspkbd.c term.c disk.c output.c graph.c
OBJS = $(patsubst %.c,%.o,$(SRCS))
BIN = sim
 
.PHONY: all install clean
 
all: $(BIN)
 
install: $(BIN)
mkdir -p $(BUILD)/bin
cp $(BIN) $(BUILD)/bin
 
getline/libgetline.a:
$(MAKE) -C getline
 
$(BIN): $(OBJS) getline/libgetline.a
$(CC) $(LDFLAGS) -o $(BIN) $(OBJS) $(LDLIBS)
 
%.o: %.c
$(CC) $(CFLAGS) -o $@ -c $<
 
depend.mak:
$(CC) -MM -MG $(CFLAGS) $(SRCS) > depend.mak
 
-include depend.mak
 
clean:
$(MAKE) -C getline clean
rm -f *~ $(OBJS) $(BIN) depend.mak
/eco32/trunk/sim/except.h
0,0 → 1,27
/*
* except.h -- exception handling
*/
 
 
#ifndef _EXCEPT_H_
#define _EXCEPT_H_
 
 
#define EXC_BUS_TIMEOUT 16 /* bus timeout exception */
#define EXC_ILL_INSTRCT 17 /* illegal instruction exception */
#define EXC_PRV_INSTRCT 18 /* privileged instruction exception */
#define EXC_DIVIDE 19 /* divide instruction exception */
#define EXC_TRAP 20 /* trap instruction exception */
#define EXC_TLB_MISS 21 /* TLB miss exception */
#define EXC_TLB_WRITE 22 /* TLB write exception */
#define EXC_TLB_INVALID 23 /* TLB invalid exception */
#define EXC_ILL_ADDRESS 24 /* illegal address exception */
#define EXC_PRV_ADDRESS 25 /* privileged address exception */
 
 
void throwException(int exception);
void pushEnvironment(jmp_buf *environment);
void popEnvironment(void);
 
 
#endif /* _EXCEPT_H_ */
/eco32/trunk/sim/error.h
0,0 → 1,13
/*
* error.h -- error handler
*/
 
 
#ifndef _ERROR_H_
#define _ERROR_H_
 
 
void error(char *fmt, ...);
 
 
#endif /* _ERROR_H_ */
/eco32/trunk/sim/disk.h
0,0 → 1,37
/*
* disk.h -- disk simulation
*/
 
 
#ifndef _DISK_H_
#define _DISK_H_
 
 
#define SECTOR_SIZE 512 /* sector size in bytes */
 
#define DISK_CTRL 0 /* control register */
#define DISK_CNT 4 /* sector count register */
#define DISK_SCT 8 /* disk sector register */
#define DISK_CAP 12 /* disk capacity register */
 
#define DISK_STRT 0x01 /* a 1 written here starts the disk command */
#define DISK_IEN 0x02 /* enable disk interrupt */
#define DISK_WRT 0x04 /* command type: 0 = read, 1 = write */
#define DISK_ERR 0x08 /* 0 = ok, 1 = error; valid when DONE = 1 */
#define DISK_DONE 0x10 /* 1 = disk has finished the command */
#define DISK_READY 0x20 /* 1 = capacity valid, disk accepts command */
 
#define DISK_DELAY 10 /* seek start/settle + rotational delay */
#define DISK_SEEK 50 /* full disk seek time */
#define DISK_STARTUP 1000 /* disk startup time (until DISK_READY) */
 
 
Word diskRead(Word addr);
void diskWrite(Word addr, Word data);
 
void diskReset(void);
void diskInit(char *diskImageName);
void diskExit(void);
 
 
#endif /* _DISK_H_ */
/eco32/trunk/sim/graph.c
0,0 → 1,468
/*
* graph.c -- graphics controller simulation
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
 
#include "common.h"
#include "console.h"
#include "error.h"
#include "except.h"
#include "graph.h"
 
 
static Bool debug = false;
static volatile Bool installed = false;
 
 
/**************************************************************/
/**************************************************************/
 
/* common definitions, global variables */
 
 
#include <pthread.h>
#include <unistd.h>
#include <time.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
 
 
#define WINDOW_SIZE_X 640
#define WINDOW_SIZE_Y 480
#define WINDOW_POS_X 100
#define WINDOW_POS_Y 100
 
 
#define C2B(c,ch) (((((c) & 0xFF) * ch.scale) >> 8) * ch.factor)
#define RGB2PIXEL(r,g,b) (C2B(r, vga.red) | \
C2B(g, vga.green) | \
C2B(b, vga.blue))
 
 
typedef struct {
unsigned long scale;
unsigned long factor;
} ColorChannel;
 
 
typedef struct {
int argc;
char **argv;
Display *display;
Window win;
GC gc;
XImage *image;
ColorChannel red, green, blue;
XExposeEvent expose;
XClientMessageEvent shutdown;
} VGA;
 
 
static VGA vga;
 
 
/**************************************************************/
 
/* monitor server */
 
 
static ColorChannel mask2channel(unsigned long mask) {
unsigned long f;
ColorChannel ch;
 
if (mask == 0) {
error("color mask is 0 in mask2channel");
}
for (f = 1; (mask & 1) == 0; f <<= 1) {
mask >>= 1;
}
ch.factor = f;
ch.scale = mask + 1;
while ((mask & 1) != 0) {
mask >>= 1;
}
if (mask != 0) {
error("scattered color mask bits in mask2channel");
}
return ch;
}
 
 
static void initMonitor(int argc, char *argv[]) {
int screenNum;
Window rootWin;
XVisualInfo visualTemp;
XVisualInfo *visualInfo;
int visualCount;
int bestMatch;
int bestDepth;
Visual *visual;
int i;
unsigned long pixel;
int x, y;
Colormap colormap;
XSetWindowAttributes attrib;
XSizeHints *sizeHints;
XWMHints *wmHints;
XClassHint *classHints;
XTextProperty windowName;
XGCValues gcValues;
 
/* connect to X server */
if (XInitThreads() == 0) {
error("no thread support for X11");
}
vga.display = XOpenDisplay(NULL);
if (vga.display == NULL) {
error("cannot connect to X server");
}
screenNum = DefaultScreen(vga.display);
rootWin = RootWindow(vga.display, screenNum);
/* find TrueColor visual */
visualTemp.screen = screenNum;
visualTemp.class = TrueColor;
visualInfo = XGetVisualInfo(vga.display,
VisualClassMask | VisualScreenMask,
&visualTemp, &visualCount);
if (visualInfo == NULL || visualCount == 0) {
error("no TrueColor visual found");
}
bestMatch = 0;
bestDepth = visualInfo[0].depth;
visual = visualInfo[0].visual;
for (i = 1; i < visualCount; i++) {
if (visualInfo[i].depth > bestDepth) {
bestMatch = i;
bestDepth = visualInfo[i].depth;
visual = visualInfo[i].visual;
}
}
/* build color channels */
vga.red = mask2channel(visualInfo[bestMatch].red_mask);
vga.green = mask2channel(visualInfo[bestMatch].green_mask);
vga.blue = mask2channel(visualInfo[bestMatch].blue_mask);
/* create and initialize image */
vga.image = XCreateImage(vga.display, visual, bestDepth, ZPixmap,
0, NULL, WINDOW_SIZE_X, WINDOW_SIZE_Y, 32, 0);
if (vga.image == NULL) {
error("cannot allocate image");
}
vga.image->data = malloc(vga.image->height * vga.image->bytes_per_line);
if (vga.image->data == NULL) {
error("cannot allocate image memory");
}
pixel = RGB2PIXEL(0, 0, 0);
for (y = 0; y < WINDOW_SIZE_Y; y++) {
for (x = 0; x < WINDOW_SIZE_X; x++) {
XPutPixel(vga.image, x, y, pixel);
}
}
/* allocate a colormap */
colormap = XCreateColormap(vga.display, rootWin, visual, AllocNone);
/* create the window */
attrib.colormap = colormap;
attrib.event_mask = ExposureMask;
attrib.background_pixel = RGB2PIXEL(0, 0, 0);
attrib.border_pixel = RGB2PIXEL(0, 0, 0);
vga.win =
XCreateWindow(vga.display, rootWin,
WINDOW_POS_X, WINDOW_POS_Y,
WINDOW_SIZE_X, WINDOW_SIZE_Y,
0, bestDepth, InputOutput, visual,
CWEventMask | CWColormap | CWBackPixel | CWBorderPixel,
&attrib);
/* give hints to window manager */
sizeHints = XAllocSizeHints();
wmHints = XAllocWMHints();
classHints = XAllocClassHint();
if (sizeHints == NULL ||
wmHints == NULL ||
classHints == NULL) {
error("hint allocation failed");
}
sizeHints->flags = PMinSize | PMaxSize;
sizeHints->min_width = WINDOW_SIZE_X;
sizeHints->min_height = WINDOW_SIZE_Y;
sizeHints->max_width = WINDOW_SIZE_X;
sizeHints->max_height = WINDOW_SIZE_Y;
wmHints->flags = StateHint | InputHint;
wmHints->input = True;
wmHints->initial_state = NormalState;
classHints->res_name = "ECO32";
classHints->res_class = "ECO32";
if (XStringListToTextProperty(&classHints->res_name, 1, &windowName) == 0) {
error("property allocation failed");
}
XSetWMProperties(vga.display, vga.win, &windowName, NULL,
argv, argc, sizeHints, wmHints, classHints);
/* create a GC */
vga.gc = XCreateGC(vga.display, vga.win, 0, &gcValues);
/* finally get the window displayed */
XMapWindow(vga.display, vga.win);
/* prepare expose event */
vga.expose.type = Expose;
vga.expose.display = vga.display;
vga.expose.window = vga.win;
vga.expose.x = 0;
vga.expose.y = 0;
vga.expose.width = WINDOW_SIZE_X;
vga.expose.height = WINDOW_SIZE_Y;
vga.expose.count = 0;
/* prepare shutdown event */
vga.shutdown.type = ClientMessage;
vga.shutdown.display = vga.display;
vga.shutdown.window = vga.win;
vga.shutdown.message_type = XA_WM_COMMAND;
vga.shutdown.format = 32;
vga.shutdown.data.l[0] = 0xDEADBEEF;
/* say that the graphics controller is installed */
XSync(vga.display, False);
installed = true;
}
 
 
static void exitMonitor(void) {
XFreeGC(vga.display, vga.gc);
XUnmapWindow(vga.display, vga.win);
XDestroyWindow(vga.display, vga.win);
XDestroyImage(vga.image);
XCloseDisplay(vga.display);
installed = false;
}
 
 
static int ioErrorHandler(Display *display) {
error("connection to monitor window lost");
/* never reached */
return 0;
}
 
 
static void *server(void *ignore) {
Bool run;
XEvent event;
 
initMonitor(vga.argc, vga.argv);
XSetIOErrorHandler(ioErrorHandler);
run = true;
while (run) {
XNextEvent(vga.display, &event);
switch (event.type) {
case Expose:
XPutImage(vga.display, vga.win, vga.gc, vga.image,
event.xexpose.x, event.xexpose.y,
event.xexpose.x, event.xexpose.y,
event.xexpose.width, event.xexpose.height);
break;
case ClientMessage:
if (event.xclient.message_type == XA_WM_COMMAND &&
event.xclient.format == 32 &&
event.xclient.data.l[0] == 0xDEADBEEF) {
run = false;
}
break;
default:
break;
}
}
exitMonitor();
return NULL;
}
 
 
/**************************************************************/
 
/* refresh timer */
 
 
static Bool refreshRunning = false;
 
 
static void *refresh(void *ignore) {
struct timespec delay;
 
while (refreshRunning) {
XSendEvent(vga.display, vga.win, False, 0, (XEvent *) &vga.expose);
XFlush(vga.display);
delay.tv_sec = 0;
delay.tv_nsec = 100 * 1000 * 1000;
nanosleep(&delay, &delay);
}
return NULL;
}
 
 
/**************************************************************/
 
/* server interface */
 
 
static int myArgc = 1;
static char *myArgv[] = {
"eco32",
NULL
};
 
 
static void vgaInit(void) {
pthread_attr_t attr;
pthread_t thread;
 
/* start monitor server in a separate thread */
vga.argc = myArgc;
vga.argv = myArgv;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (pthread_create(&thread, &attr, server, NULL) != 0) {
error("cannot start monitor server");
}
while (!installed) sleep(1);
/* start refresh timer in another thread */
refreshRunning = true;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (pthread_create(&thread, &attr, refresh, NULL) != 0) {
error("cannot start refresh timer");
}
}
 
 
static void vgaExit(void) {
refreshRunning = false;
sleep(1);
XSendEvent(vga.display, vga.win, False, 0, (XEvent *) &vga.shutdown);
XSync(vga.display, False);
while (installed) sleep(1);
}
 
 
static void vgaWrite(int x, int y, int r, int g, int b) {
XPutPixel(vga.image, x, y, RGB2PIXEL(r, g, b));
}
 
 
/**************************************************************/
/**************************************************************/
 
 
#define BACKGROUND 0
#define FOREGROUND 1
 
 
static int colors[2] = {
0x007CD4D6, /* background */
0x00000000 /* foreground */
};
 
 
static int splashData[] = {
#include "grsplash"
};
 
 
static void loadSplashScreen(void) {
int sum, i;
int count;
int plane;
int x, y;
int r, g, b;
 
/* check splash data */
sum = 0;
for (i = 0; i < sizeof(splashData)/sizeof(splashData[0]); i++) {
sum += splashData[i];
}
if (sum != WINDOW_SIZE_X * WINDOW_SIZE_Y) {
return;
}
/* display splash data */
count = 0;
plane = FOREGROUND;
i = 0;
for (y = 0; y < WINDOW_SIZE_Y; y++) {
for (x = 0; x < WINDOW_SIZE_X; x++) {
while (count == 0) {
plane = (plane == BACKGROUND ? FOREGROUND : BACKGROUND);
r = (colors[plane] >> 16) & 0xFF;
g = (colors[plane] >> 8) & 0xFF;
b = (colors[plane] >> 0) & 0xFF;
count = splashData[i++];
}
count--;
vgaWrite(x, y, r, g, b);
}
}
}
 
 
/**************************************************************/
 
 
Word graphRead(Word addr) {
Word data;
 
if (debug) {
cPrintf("\n**** GRAPH READ from 0x%08X", addr);
}
if (!installed) {
throwException(EXC_BUS_TIMEOUT);
}
if (addr >= WINDOW_SIZE_X * WINDOW_SIZE_Y * 4) {
throwException(EXC_BUS_TIMEOUT);
}
/* the frame buffer memory yields 0 on every read */
data = 0;
if (debug) {
cPrintf(", data = 0x%08X ****\n", data);
}
return data;
}
 
 
void graphWrite(Word addr, Word data) {
if (debug) {
cPrintf("\n**** GRAPH WRITE to 0x%08X, data = 0x%08X ****\n",
addr, data);
}
if (!installed) {
throwException(EXC_BUS_TIMEOUT);
}
if (addr >= WINDOW_SIZE_X * WINDOW_SIZE_Y * 4) {
throwException(EXC_BUS_TIMEOUT);
}
/* write to frame buffer memory */
vgaWrite((addr >> 2) % WINDOW_SIZE_X,
(addr >> 2) / WINDOW_SIZE_X,
(data >> 16) & 0xFF,
(data >> 8) & 0xFF,
(data >> 0) & 0xFF);
}
 
 
void graphReset(void) {
if (!installed) {
return;
}
cPrintf("Resetting Graphics...\n");
loadSplashScreen();
}
 
 
void graphInit(void) {
vgaInit();
graphReset();
}
 
 
void graphExit(void) {
if (!installed) {
return;
}
vgaExit();
}
/eco32/trunk/sim/graph.h
0,0 → 1,18
/*
* graph.h -- graphics controller simulation
*/
 
 
#ifndef _GRAPH_H_
#define _GRAPH_H_
 
 
Word graphRead(Word addr);
void graphWrite(Word addr, Word data);
 
void graphReset(void);
void graphInit(void);
void graphExit(void);
 
 
#endif /* _GRAPH_H_ */
/eco32/trunk/sim/memory.c
0,0 → 1,277
/*
* memory.c -- physical memory simulation
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
 
#include "common.h"
#include "console.h"
#include "error.h"
#include "except.h"
#include "cpu.h"
#include "memory.h"
#include "timer.h"
#include "dspkbd.h"
#include "term.h"
#include "disk.h"
#include "output.h"
#include "graph.h"
 
 
static Byte *rom;
static Byte *mem;
static unsigned int memSize;
static FILE *romImage;
static unsigned int romSize;
static FILE *progImage;
static unsigned int progSize;
 
 
Word memoryReadWord(Word pAddr) {
Word data;
 
if (pAddr <= memSize - 4) {
data = ((Word) *(mem + pAddr + 0)) << 24 |
((Word) *(mem + pAddr + 1)) << 16 |
((Word) *(mem + pAddr + 2)) << 8 |
((Word) *(mem + pAddr + 3)) << 0;
return data;
}
if (pAddr >= ROM_BASE &&
pAddr <= ROM_BASE + ROM_SIZE - 4) {
data = ((Word) *(rom + (pAddr - ROM_BASE) + 0)) << 24 |
((Word) *(rom + (pAddr - ROM_BASE) + 1)) << 16 |
((Word) *(rom + (pAddr - ROM_BASE) + 2)) << 8 |
((Word) *(rom + (pAddr - ROM_BASE) + 3)) << 0;
return data;
}
if ((pAddr & IO_DEV_MASK) == TIMER_BASE) {
data = timerRead(pAddr & IO_REG_MASK);
return data;
}
if ((pAddr & IO_DEV_MASK) == DISPLAY_BASE) {
data = displayRead(pAddr & IO_REG_MASK);
return data;
}
if ((pAddr & IO_DEV_MASK) == KEYBOARD_BASE) {
data = keyboardRead(pAddr & IO_REG_MASK);
return data;
}
if ((pAddr & IO_DEV_MASK) == TERM_BASE) {
data = termRead(pAddr & IO_REG_MASK);
return data;
}
if ((pAddr & IO_DEV_MASK) == DISK_BASE) {
data = diskRead(pAddr & IO_REG_MASK);
return data;
}
if ((pAddr & IO_DEV_MASK) == OUTPUT_BASE) {
data = outputRead(pAddr & IO_REG_MASK);
return data;
}
if ((pAddr & IO_DEV_MASK) >= GRAPH_BASE) {
data = graphRead(pAddr & IO_GRAPH_MASK);
return data;
}
/* throw bus timeout exception */
throwException(EXC_BUS_TIMEOUT);
/* not reached */
data = 0;
return data;
}
 
 
Half memoryReadHalf(Word pAddr) {
Half data;
 
if (pAddr <= memSize - 2) {
data = ((Half) *(mem + pAddr + 0)) << 8 |
((Half) *(mem + pAddr + 1)) << 0;
return data;
}
if (pAddr >= ROM_BASE &&
pAddr <= ROM_BASE + ROM_SIZE - 2) {
data = ((Half) *(rom + (pAddr - ROM_BASE) + 0)) << 8 |
((Half) *(rom + (pAddr - ROM_BASE) + 1)) << 0;
return data;
}
/* throw bus timeout exception */
throwException(EXC_BUS_TIMEOUT);
/* not reached */
data = 0;
return data;
}
 
 
Byte memoryReadByte(Word pAddr) {
Byte data;
 
if (pAddr <= memSize - 1) {
data = ((Byte) *(mem + pAddr + 0)) << 0;
return data;
}
if (pAddr >= ROM_BASE &&
pAddr <= ROM_BASE + ROM_SIZE - 1) {
data = ((Byte) *(rom + (pAddr - ROM_BASE) + 0)) << 0;
return data;
}
/* throw bus timeout exception */
throwException(EXC_BUS_TIMEOUT);
/* not reached */
data = 0;
return data;
}
 
 
void memoryWriteWord(Word pAddr, Word data) {
if (pAddr <= memSize - 4) {
*(mem + pAddr + 0) = (Byte) (data >> 24);
*(mem + pAddr + 1) = (Byte) (data >> 16);
*(mem + pAddr + 2) = (Byte) (data >> 8);
*(mem + pAddr + 3) = (Byte) (data >> 0);
return;
}
if ((pAddr & IO_DEV_MASK) == TIMER_BASE) {
timerWrite(pAddr & IO_REG_MASK, data);
return;
}
if ((pAddr & IO_DEV_MASK) == DISPLAY_BASE) {
displayWrite(pAddr & IO_REG_MASK, data);
return;
}
if ((pAddr & IO_DEV_MASK) == KEYBOARD_BASE) {
keyboardWrite(pAddr & IO_REG_MASK, data);
return;
}
if ((pAddr & IO_DEV_MASK) == TERM_BASE) {
termWrite(pAddr & IO_REG_MASK, data);
return;
}
if ((pAddr & IO_DEV_MASK) == DISK_BASE) {
diskWrite(pAddr & IO_REG_MASK, data);
return;
}
if ((pAddr & IO_DEV_MASK) == OUTPUT_BASE) {
outputWrite(pAddr & IO_REG_MASK, data);
return;
}
if ((pAddr & IO_DEV_MASK) >= GRAPH_BASE) {
graphWrite(pAddr & IO_GRAPH_MASK, data);
return;
}
/* throw bus timeout exception */
throwException(EXC_BUS_TIMEOUT);
}
 
 
void memoryWriteHalf(Word pAddr, Half data) {
if (pAddr <= memSize - 2) {
*(mem + pAddr + 0) = (Byte) (data >> 8);
*(mem + pAddr + 1) = (Byte) (data >> 0);
return;
}
/* throw bus timeout exception */
throwException(EXC_BUS_TIMEOUT);
}
 
 
void memoryWriteByte(Word pAddr, Byte data) {
if (pAddr <= memSize - 1) {
*(mem + pAddr + 0) = (Byte) (data >> 0);
return;
}
/* throw bus timeout exception */
throwException(EXC_BUS_TIMEOUT);
}
 
 
void memoryReset(void) {
unsigned int i;
 
cPrintf("Resetting Memory...\n");
for (i = 0; i < memSize; i++) {
mem[i] = rand();
}
cPrintf("%6d MB RAM installed", memSize / M);
if (progImage != NULL) {
fseek(progImage, 0, SEEK_SET);
if (fread(mem, progSize, 1, progImage) != 1) {
error("cannot read program image file");
}
cPrintf(", %d bytes loaded", progSize);
}
cPrintf(".\n");
for (i = 0; i < ROM_SIZE; i++) {
rom[i] = 0xFF;
}
if (romImage != NULL) {
fseek(romImage, 0, SEEK_SET);
if (fread(rom, romSize, 1, romImage) != 1) {
error("cannot read ROM image file");
}
cPrintf("%6d KB ROM installed, %d bytes programmed.\n",
ROM_SIZE / K, romSize);
}
}
 
 
void memoryInit(unsigned int memorySize,
char *progImageName,
char *romImageName) {
/* allocate RAM */
memSize = memorySize;
mem = malloc(memSize);
if (mem == NULL) {
error("cannot allocate RAM");
}
/* possibly load program image */
if (progImageName == NULL) {
/* no program to load */
progImage = NULL;
} else {
/* load program */
progImage = fopen(progImageName, "rb");
if (progImage == NULL) {
error("cannot open program file '%s'", progImageName);
}
fseek(progImage, 0, SEEK_END);
progSize = ftell(progImage);
if (progSize > memSize) {
error("program file too big");
}
/* do actual loading of image in memoryReset() */
}
/* allocate ROM */
rom = malloc(ROM_SIZE);
if (rom == NULL) {
error("cannot allocate ROM");
}
/* possibly load ROM image */
if (romImageName == NULL) {
/* no ROM to plug in */
romImage = NULL;
} else {
/* plug in ROM */
romImage = fopen(romImageName, "rb");
if (romImage == NULL) {
error("cannot open ROM image '%s'", romImageName);
}
fseek(romImage, 0, SEEK_END);
romSize = ftell(romImage);
if (romSize > ROM_SIZE) {
error("ROM image too big");
}
/* do actual loading of image in memoryReset() */
}
memoryReset();
}
 
 
void memoryExit(void) {
free(mem);
free(rom);
}
/eco32/trunk/sim/memory.h
0,0 → 1,24
/*
* memory.h -- physical memory simulation
*/
 
 
#ifndef _MEMORY_H_
#define _MEMORY_H_
 
 
Word memoryReadWord(Word pAddr);
Half memoryReadHalf(Word pAddr);
Byte memoryReadByte(Word pAddr);
void memoryWriteWord(Word pAddr, Word data);
void memoryWriteHalf(Word pAddr, Half data);
void memoryWriteByte(Word pAddr, Byte data);
 
void memoryReset(void);
void memoryInit(unsigned int memorySize,
char *progImageName,
char *romImageName);
void memoryExit(void);
 
 
#endif /* _MEMORY_H_ */
/eco32/trunk/sim/command.c
0,0 → 1,852
/*
* command.c -- command interpreter
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
 
#include "common.h"
#include "console.h"
#include "error.h"
#include "except.h"
#include "command.h"
#include "asm.h"
#include "disasm.h"
#include "cpu.h"
#include "mmu.h"
#include "memory.h"
#include "timer.h"
#include "dspkbd.h"
#include "term.h"
#include "disk.h"
#include "graph.h"
 
 
#define MAX_TOKENS 10
 
 
static Bool quit;
 
 
static void help(void) {
cPrintf("valid commands are:\n");
cPrintf(" + <num1> <num2> add and subtract <num1> and <num2>\n");
cPrintf(" a assemble starting at PC\n");
cPrintf(" a <addr> assemble starting at <addr>\n");
cPrintf(" u unassemble 16 instrs starting at PC\n");
cPrintf(" u <addr> unassemble 16 instrs starting at <addr>\n");
cPrintf(" u <addr> <cnt> unassemble <cnt> instrs starting at <addr>\n");
cPrintf(" b reset break\n");
cPrintf(" b <addr> set break at <addr>\n");
cPrintf(" c continue execution\n");
cPrintf(" c <cnt> continue execution <cnt> times\n");
cPrintf(" s single-step one instruction\n");
cPrintf(" s <cnt> single-step <cnt> instructions\n");
cPrintf(" @ show PC\n");
cPrintf(" @ <addr> set PC to <addr>\n");
cPrintf(" p show PSW\n");
cPrintf(" p <data> set PSW to <data>\n");
cPrintf(" r show all registers\n");
cPrintf(" r <reg> show register <reg>\n");
cPrintf(" r <reg> <data> set register <reg> to <data>\n");
cPrintf(" d dump 256 bytes starting at PC\n");
cPrintf(" d <addr> dump 256 bytes starting at <addr>\n");
cPrintf(" d <addr> <cnt> dump <cnt> bytes starting at <addr>\n");
cPrintf(" mw show memory word at PC\n");
cPrintf(" mw <addr> show memory word at <addr>\n");
cPrintf(" mw <addr> <data> set memory word at <addr> to <data>\n");
cPrintf(" mh show memory halfword at PC\n");
cPrintf(" mh <addr> show memory halfword at <addr>\n");
cPrintf(" mh <addr> <data> set memory halfword at <addr> to <data>\n");
cPrintf(" mb show memory byte at PC\n");
cPrintf(" mb <addr> show memory byte at <addr>\n");
cPrintf(" mb <addr> <data> set memory byte at <addr> to <data>\n");
cPrintf(" t show TLB contents\n");
cPrintf(" t <i> show TLB contents at <i>\n");
cPrintf(" t <i> p <data> set TLB contents at <i> to page <data>\n");
cPrintf(" t <i> f <data> set TLB contents at <i> to frame <data>\n");
cPrintf(" i initialize hardware\n");
cPrintf(" q quit simulator\n");
}
 
 
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"
};
 
 
static char *exceptionToString(int exception) {
if (exception < 0 ||
exception >= sizeof(cause)/sizeof(cause[0])) {
error("exception number out of bounds");
}
return cause[exception];
}
 
 
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, psw & PSW_UM);
cPrintf("PC %08X [PC] %08X %s\n",
pc, instr, disasm(instr, pc));
}
 
 
static void showBreakAndTotal(void) {
Word brk;
Word tot;
 
brk = cpuGetBreak();
tot = cpuGetTotal();
cPrintf("Brk ");
if (cpuTestBreak()) {
cPrintf("%08X", brk);
} else {
cPrintf("--------");
}
cPrintf(" Total %08X instructions\n", tot);
}
 
 
static void showIRQ(void) {
Word irq;
int i;
 
irq = cpuGetIRQ();
cPrintf("IRQ ");
for (i = 15; i >= 0; i--) {
cPrintf("%c", irq & (1 << i) ? '1' : '0');
}
cPrintf("\n");
}
 
 
static void showPSW(void) {
Word psw;
int i;
 
psw = cpuGetPSW();
cPrintf(" xxxx V UPO IPO IACK MASK\n");
cPrintf("PSW ");
for (i = 31; i >= 0; i--) {
if (i == 27 || i == 26 || i == 23 || i == 20 || i == 15) {
cPrintf(" ");
}
cPrintf("%c", psw & (1 << i) ? '1' : '0');
}
cPrintf("\n");
}
 
 
static void doArith(char *tokens[], int n) {
Word num1, num2, num3, num4;
 
if (n == 3) {
if (!getHexNumber(tokens[1], &num1)) {
cPrintf("illegal first number\n");
return;
}
if (!getHexNumber(tokens[2], &num2)) {
cPrintf("illegal second number\n");
return;
}
num3 = num1 + num2;
num4 = num1 - num2;
cPrintf("add = %08X, sub = %08X\n", num3, num4);
} else {
help();
}
}
 
 
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)) {
cPrintf("illegal address\n");
return;
}
} else {
help();
return;
}
addr &= ~0x00000003;
psw = cpuGetPSW();
while (1) {
sprintf(prompt, "ASM @ %08X: ", addr);
line = cGetLine(prompt);
if (*line == '\0' || *line == '\n') {
break;
}
cAddHist(line);
msg = asmInstr(line, addr, &instr);
if (msg != NULL) {
cPrintf("%s\n", msg);
} else {
mmuWriteWord(addr, instr, psw & PSW_UM);
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)) {
cPrintf("illegal address\n");
return;
}
count = 16;
} else if (n == 3) {
if (!getHexNumber(tokens[1], &addr)) {
cPrintf("illegal address\n");
return;
}
if (!getHexNumber(tokens[2], &count)) {
cPrintf("illegal count\n");
return;
}
if (count == 0) {
return;
}
} else {
help();
return;
}
addr &= ~0x00000003;
psw = cpuGetPSW();
for (i = 0; i < count; i++) {
instr = mmuReadWord(addr, psw & PSW_UM);
cPrintf("%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();
showBreakAndTotal();
} else if (n == 2) {
if (!getHexNumber(tokens[1], &addr)) {
cPrintf("illegal address\n");
return;
}
addr &= ~0x00000003;
cpuSetBreak(addr);
showBreakAndTotal();
} else {
help();
}
}
 
 
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) {
cPrintf("illegal count\n");
return;
}
} else {
help();
return;
}
cPrintf("CPU is running, press ^C to interrupt...\n");
for (i = 0; i < count; i++) {
cpuRun();
}
addr = cpuGetPC();
cPrintf("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) {
cPrintf("illegal count\n");
return;
}
} else {
help();
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)) {
cPrintf("illegal address\n");
return;
}
addr &= ~0x00000003;
cpuSetPC(addr);
showPC();
} else {
help();
}
}
 
 
static void explainPSW(Word data) {
int i;
 
cPrintf("interrupt vector : %s (%s)\n",
data & PSW_V ? "on " : "off",
data & PSW_V ? "RAM" : "ROM");
cPrintf("current user mode : %s (%s)\n",
data & PSW_UM ? "on " : "off",
data & PSW_UM ? "user" : "kernel");
cPrintf("previous user mode : %s (%s)\n",
data & PSW_PUM ? "on " : "off",
data & PSW_PUM ? "user" : "kernel");
cPrintf("old user mode : %s (%s)\n",
data & PSW_OUM ? "on " : "off",
data & PSW_OUM ? "user" : "kernel");
cPrintf("current interrupt enable : %s (%s)\n",
data & PSW_IE ? "on " : "off",
data & PSW_IE ? "enabled" : "disabled");
cPrintf("previous interrupt enable : %s (%s)\n",
data & PSW_PIE ? "on " : "off",
data & PSW_PIE ? "enabled" : "disabled");
cPrintf("old interrupt enable : %s (%s)\n",
data & PSW_OIE ? "on " : "off",
data & PSW_OIE ? "enabled" : "disabled");
cPrintf("last interrupt acknowledged : %02X (%s)\n",
(data & PSW_PRIO_MASK) >> 16,
exceptionToString((data & PSW_PRIO_MASK) >> 16));
for (i = 15; i >= 0; i--) {
cPrintf("%-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();
showIRQ();
explainPSW(data);
} else if (n == 2) {
if (!getHexNumber(tokens[1], &data)) {
cPrintf("illegal data\n");
return;
}
data &= 0x0FFFFFFF;
cpuSetPSW(data);
showPSW();
showIRQ();
explainPSW(data);
} else {
help();
}
}
 
 
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);
cPrintf("$%-2d %08X ", reg, data);
}
cPrintf("\n");
}
showPSW();
showIRQ();
showBreakAndTotal();
showPC();
} else if (n == 2) {
if (!getDecNumber(tokens[1], &reg) || reg < 0 || reg >= 32) {
cPrintf("illegal register number\n");
return;
}
data = cpuGetReg(reg);
cPrintf("$%-2d %08X\n", reg, data);
} else if (n == 3) {
if (!getDecNumber(tokens[1], &reg) || reg < 0 || reg >= 32) {
cPrintf("illegal register number\n");
return;
}
if (!getHexNumber(tokens[2], &data)) {
cPrintf("illegal data\n");
return;
}
cpuSetReg(reg, data);
} else {
help();
}
}
 
 
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)) {
cPrintf("illegal address\n");
return;
}
count = 16 * 16;
} else if (n == 3) {
if (!getHexNumber(tokens[1], &addr)) {
cPrintf("illegal address\n");
return;
}
if (!getHexNumber(tokens[2], &count)) {
cPrintf("illegal count\n");
return;
}
if (count == 0) {
return;
}
} else {
help();
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++) {
cPrintf("%08X: ", curr);
for (j = 0; j < 16; j++) {
tmp = curr + j;
if (tmp < addr || tmp > hi) {
cPrintf(" ");
} else {
c = mmuReadByte(tmp, psw & PSW_UM);
cPrintf("%02X", c);
}
cPrintf(" ");
}
cPrintf(" ");
for (j = 0; j < 16; j++) {
tmp = curr + j;
if (tmp < addr || tmp > hi) {
cPrintf(" ");
} else {
c = mmuReadByte(tmp, psw & PSW_UM);
if (c >= 32 && c <= 126) {
cPrintf("%c", c);
} else {
cPrintf(".");
}
}
}
cPrintf("\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, psw & PSW_UM);
cPrintf("%08X: %08X\n", addr, data);
} else if (n == 2) {
if (!getHexNumber(tokens[1], &addr)) {
cPrintf("illegal address\n");
return;
}
data = mmuReadWord(addr, psw & PSW_UM);
cPrintf("%08X: %08X\n", addr, data);
} else if (n == 3) {
if (!getHexNumber(tokens[1], &addr)) {
cPrintf("illegal address\n");
return;
}
if (!getHexNumber(tokens[2], &tmpData)) {
cPrintf("illegal data\n");
return;
}
data = tmpData;
mmuWriteWord(addr, data, psw & PSW_UM);
} else {
help();
}
}
 
 
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, psw & PSW_UM);
cPrintf("%08X: %04X\n", addr, data);
} else if (n == 2) {
if (!getHexNumber(tokens[1], &addr)) {
cPrintf("illegal address\n");
return;
}
data = mmuReadHalf(addr, psw & PSW_UM);
cPrintf("%08X: %04X\n", addr, data);
} else if (n == 3) {
if (!getHexNumber(tokens[1], &addr)) {
cPrintf("illegal address\n");
return;
}
if (!getHexNumber(tokens[2], &tmpData)) {
cPrintf("illegal data\n");
return;
}
data = (Half) tmpData;
mmuWriteHalf(addr, data, psw & PSW_UM);
} else {
help();
}
}
 
 
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, psw & PSW_UM);
cPrintf("%08X: %02X\n", addr, data);
} else if (n == 2) {
if (!getHexNumber(tokens[1], &addr)) {
cPrintf("illegal address\n");
return;
}
data = mmuReadByte(addr, psw & PSW_UM);
cPrintf("%08X: %02X\n", addr, data);
} else if (n == 3) {
if (!getHexNumber(tokens[1], &addr)) {
cPrintf("illegal address\n");
return;
}
if (!getHexNumber(tokens[2], &tmpData)) {
cPrintf("illegal data\n");
return;
}
data = (Byte) tmpData;
mmuWriteByte(addr, data, psw & PSW_UM);
} else {
help();
}
}
 
 
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);
cPrintf("TLB[%02d] page %08X frame %08X %c %c\n",
index, tlbEntry.page, tlbEntry.frame,
tlbEntry.write ? 'w' : '-',
tlbEntry.valid ? 'v' : '-');
}
cPrintf("Index(1) %08X\n", mmuGetIndex());
cPrintf("EntryHi(2) %08X\n", mmuGetEntryHi());
cPrintf("EntryLo(3) %08X\n", mmuGetEntryLo());
cPrintf("BadAddr(4) %08X\n", mmuGetBadAddr());
} else if (n == 2) {
if (!getDecNumber(tokens[1], &index) || index < 0 || index >= TLB_SIZE) {
cPrintf("illegal TLB index\n");
return;
}
tlbEntry = mmuGetTLB(index);
cPrintf("TLB[%02d] page %08X frame %08X %c %c\n",
index, tlbEntry.page, tlbEntry.frame,
tlbEntry.write ? 'w' : '-',
tlbEntry.valid ? 'v' : '-');
} else if (n == 3) {
help();
} else if (n == 4) {
if (!getDecNumber(tokens[1], &index) || index < 0 || index >= TLB_SIZE) {
cPrintf("illegal TLB index\n");
return;
}
if (!getHexNumber(tokens[3], &data)) {
cPrintf("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 {
cPrintf("TLB selector is not one of 'p' or 'f'\n");
return;
}
mmuSetTLB(index, tlbEntry);
cPrintf("TLB[%02d] page %08X frame %08X %c %c\n",
index, tlbEntry.page, tlbEntry.frame,
tlbEntry.write ? 'w' : '-',
tlbEntry.valid ? 'v' : '-');
} else {
help();
}
}
 
 
static void doInit(char *tokens[], int n) {
if (n == 1) {
timerReset();
displayReset();
keyboardReset();
termReset();
diskReset();
graphReset();
memoryReset();
mmuReset();
cpuReset();
} else {
help();
}
}
 
 
static void doQuit(char *tokens[], int n) {
if (n == 1) {
quit = true;
} else {
help();
}
}
 
 
typedef struct {
char *name;
void (*cmdProc)(char *tokens[], int n);
} Command;
 
 
static Command commands[] = {
{ "+", doArith },
{ "a", doAssemble },
{ "u", doUnassemble },
{ "b", doBreak },
{ "c", doContinue },
{ "s", doStep },
{ "@", doPC },
{ "p", doPSW },
{ "r", doRegister },
{ "d", doDump },
{ "mw", doMemoryWord },
{ "mh", doMemoryHalf },
{ "mb", doMemoryByte },
{ "t", doTLB },
{ "i", doInit },
{ "q", doQuit }
};
 
 
static Bool 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) {
cPrintf("too many tokens on line\n");
return false;
}
tokens[n++] = p;
p = strtok(NULL, " \t\n");
}
if (n == 0) {
return false;
}
quit = false;
for (i = 0; i < sizeof(commands)/sizeof(commands[0]); i++) {
if (strcmp(commands[i].name, tokens[0]) == 0) {
(*commands[i].cmdProc)(tokens, n);
return quit;
}
}
help();
return false;
}
 
 
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);
cPrintf("\n");
cPrintf("NOTE: %s %s occurred while executing the command.\n",
article(*what), what);
cPrintf(" This event will not alter the state of the CPU.\n");
}
 
 
Bool execCommand(char *line) {
jmp_buf myEnvironment;
int exception;
Bool quit;
 
exception = setjmp(myEnvironment);
if (exception == 0) {
/* initialization */
pushEnvironment(&myEnvironment);
quit = doCommand(line);
} else {
/* an exception was thrown */
interactiveException(exception);
quit = false;
}
popEnvironment();
return quit;
}
/eco32/trunk/sim/timer.c
0,0 → 1,204
/*
* timer.c -- timer simulation
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
 
#include "common.h"
#include "console.h"
#include "error.h"
#include "except.h"
#include "cpu.h"
#include "timer.h"
 
 
#define TIME_WRAP 1000000 /* avoid overflow of current time */
 
 
typedef struct timer {
struct timer *next;
int alarm;
void (*callback)(int param);
int param;
} Timer;
 
 
static Bool debug = false;
 
static Timer *activeTimers = NULL;
static Timer *freeTimers = NULL;
 
static int currentTime = 0;
 
static Word timerCtrl = 0x00000000;
static Word timerDivisor = 0xFFFFFFFF;
static Word timerCounter = 0xFFFFFFFF;
 
 
Word timerRead(Word addr) {
Word data;
 
if (debug) {
cPrintf("\n**** TIMER READ from 0x%08X", addr);
}
if (addr == TIMER_CTRL) {
data = timerCtrl;
} else
if (addr == TIMER_DIVISOR) {
data = timerDivisor;
} else {
/* illegal register */
throwException(EXC_BUS_TIMEOUT);
}
if (debug) {
cPrintf(", data = 0x%08X ****\n", data);
}
return data;
}
 
 
void timerWrite(Word addr, Word data) {
if (debug) {
cPrintf("\n**** TIMER WRITE to 0x%08X, data = 0x%08X ****\n",
addr, data);
}
if (addr == TIMER_CTRL) {
if (data & TIMER_IEN) {
timerCtrl |= TIMER_IEN;
} else {
timerCtrl &= ~TIMER_IEN;
}
if (data & TIMER_EXP) {
timerCtrl |= TIMER_EXP;
} else {
timerCtrl &= ~TIMER_EXP;
}
if ((timerCtrl & TIMER_IEN) != 0 &&
(timerCtrl & TIMER_EXP) != 0) {
/* raise timer interrupt */
cpuSetInterrupt(IRQ_TIMER);
} else {
/* lower timer interrupt */
cpuResetInterrupt(IRQ_TIMER);
}
} else
if (addr == TIMER_DIVISOR) {
timerDivisor = data;
timerCounter = data;
} else {
/* illegal register */
throwException(EXC_BUS_TIMEOUT);
}
}
 
 
void timerTick(void) {
Timer *timer;
void (*callback)(int param);
int param;
 
/* increment current time, avoid overflow */
if (++currentTime == TIME_WRAP) {
currentTime -= TIME_WRAP;
timer = activeTimers;
while (timer != NULL) {
timer->alarm -= TIME_WRAP;
timer = timer->next;
}
}
/* check whether any simulation timer expired */
while (activeTimers != NULL &&
currentTime >= activeTimers->alarm) {
timer = activeTimers;
activeTimers = timer->next;
callback = timer->callback;
param = timer->param;
timer->next = freeTimers;
freeTimers = timer;
(*callback)(param);
}
/* decrement counter and check if an interrupt must be raised */
if (--timerCounter == 0) {
timerCounter = timerDivisor;
timerCtrl |= TIMER_EXP;
if (timerCtrl & TIMER_IEN) {
/* raise timer interrupt */
cpuSetInterrupt(IRQ_TIMER);
}
}
}
 
 
void timerStart(int msec, void (*callback)(int param), int param) {
Timer *timer;
Timer *p;
 
if (freeTimers == NULL) {
error("out of timers");
}
timer = freeTimers;
freeTimers = timer->next;
timer->alarm = currentTime + msec;
timer->callback = callback;
timer->param = param;
if (activeTimers == NULL ||
timer->alarm < activeTimers->alarm) {
/* link into front of active timers queue */
timer->next = activeTimers;
activeTimers = timer;
} else {
/* link elsewhere into active timers queue */
p = activeTimers;
while (p->next != NULL &&
p->next->alarm <= timer->alarm) {
p = p->next;
}
timer->next = p->next;
p->next = timer;
}
}
 
 
void timerReset(void) {
Timer *timer;
 
cPrintf("Resetting Timer...\n");
while (activeTimers != NULL) {
timer = activeTimers;
activeTimers = timer->next;
timer->next = freeTimers;
freeTimers = timer;
}
}
 
 
void timerInit(void) {
Timer *timer;
int i;
 
for (i = 0; i < NUMBER_TIMERS; i++) {
timer = malloc(sizeof(Timer));
if (timer == NULL) {
error("cannot allocate simulation timers");
}
timer->next = freeTimers;
freeTimers = timer;
}
timerReset();
}
 
 
void timerExit(void) {
Timer *timer;
 
timerReset();
while (freeTimers != NULL) {
timer = freeTimers;
freeTimers = timer->next;
free(timer);
}
}
/eco32/trunk/sim/asm.c
0,0 → 1,374
/*
* asm.c -- assembler
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#include "common.h"
#include "console.h"
#include "error.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;
}
/eco32/trunk/sim/command.h
0,0 → 1,13
/*
* command.h -- command interpreter
*/
 
 
#ifndef _COMMAND_H_
#define _COMMAND_H_
 
 
Bool execCommand(char *line);
 
 
#endif /* _COMMAND_H_ */
/eco32/trunk/sim/main.c
0,0 → 1,193
/*
* main.c -- ECO32 simulator
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#include "common.h"
#include "console.h"
#include "error.h"
#include "command.h"
#include "instr.h"
#include "cpu.h"
#include "mmu.h"
#include "memory.h"
#include "timer.h"
#include "dspkbd.h"
#include "term.h"
#include "disk.h"
#include "output.h"
#include "graph.h"
 
 
static void usage(char *myself) {
fprintf(stderr, "Usage: %s\n", myself);
fprintf(stderr, " [-i] set interactive mode\n");
fprintf(stderr, " [-m <n>] install n MB of RAM (1-%d)\n",
RAM_SIZE_MAX / M);
fprintf(stderr, " [-l <prog>] set program file name\n");
fprintf(stderr, " [-r <rom>] set ROM image file name\n");
fprintf(stderr, " [-d <disk>] set disk image file name\n");
fprintf(stderr, " [-t <n>] connect n terminals (0-%d)\n",
MAX_NTERMS);
fprintf(stderr, " [-g] install graphics controller\n");
fprintf(stderr, " [-c] install console\n");
fprintf(stderr, " [-o <file>] bind output device to file\n");
fprintf(stderr, "The options -l and -r are mutually exclusive.\n");
fprintf(stderr, "If both are omitted, interactive mode is assumed.\n");
exit(1);
}
 
 
int main(int argc, char *argv[]) {
int i;
char *argp;
char *endp;
Bool interactive;
int memSize;
char *progName;
char *romName;
char *diskName;
int numTerms;
Bool graphics;
Bool console;
char *outputName;
Word initialPC;
char command[20];
char *line;
 
interactive = false;
memSize = RAM_SIZE_DFL / M;
progName = NULL;
romName = NULL;
diskName = NULL;
numTerms = 0;
graphics = false;
console = false;
outputName = NULL;
for (i = 1; i < argc; i++) {
argp = argv[i];
if (*argp != '-') {
usage(argv[0]);
}
argp++;
switch (*argp) {
case 'i':
interactive = true;
break;
case 'm':
if (i == argc - 1) {
usage(argv[0]);
}
memSize = strtol(argv[++i], &endp, 10);
if (*endp != '\0' ||
memSize <= 0 ||
memSize > RAM_SIZE_MAX / M) {
usage(argv[0]);
}
break;
case 'l':
if (i == argc - 1 || progName != NULL || romName != NULL) {
usage(argv[0]);
}
progName = argv[++i];
break;
case 'r':
if (i == argc - 1 || romName != NULL || progName != NULL) {
usage(argv[0]);
}
romName = argv[++i];
break;
case 'd':
if (i == argc - 1 || diskName != NULL) {
usage(argv[0]);
}
diskName = argv[++i];
break;
case 't':
if (i == argc - 1) {
usage(argv[0]);
}
numTerms = strtol(argv[++i], &endp, 10);
if (*endp != '\0' ||
numTerms < 0 ||
numTerms > MAX_NTERMS) {
usage(argv[0]);
}
break;
case 'g':
graphics = true;
break;
case 'c':
console = true;
break;
case 'o':
if (i == argc - 1 || outputName != NULL) {
usage(argv[0]);
}
outputName = argv[++i];
break;
default:
usage(argv[0]);
}
}
cInit();
cPrintf("ECO32 Simulator started\n");
if (progName == NULL && romName == NULL && !interactive) {
cPrintf("Neither a program to load nor a system ROM was\n");
cPrintf("specified, so interactive mode is assumed.\n");
interactive = true;
}
initInstrTable();
timerInit();
if (console) {
displayInit();
keyboardInit();
}
termInit(numTerms);
diskInit(diskName);
outputInit(outputName);
if (graphics) {
graphInit();
}
memoryInit(memSize * M, progName, romName);
mmuInit();
if (progName != NULL) {
initialPC = 0xC0000000;
} else {
initialPC = 0xC0000000 | ROM_BASE;
}
cpuInit(initialPC);
if (!interactive) {
cPrintf("Start executing...\n");
strcpy(command, "c\n");
execCommand(command);
} else {
while (1) {
line = cGetLine("ECO32 > ");
if (*line == '\0') {
break;
}
cAddHist(line);
if (execCommand(line)) {
break;
}
}
}
cpuExit();
mmuExit();
memoryExit();
timerExit();
displayExit();
keyboardExit();
termExit();
diskExit();
outputExit();
graphExit();
cPrintf("ECO32 Simulator finished\n");
cExit();
return 0;
}
/eco32/trunk/sim/timer.h
0,0 → 1,30
/*
* timer.h -- timer simulation
*/
 
 
#ifndef _TIMER_H_
#define _TIMER_H_
 
 
#define TIMER_CTRL 0 /* timer control register */
#define TIMER_DIVISOR 4 /* timer divisor register */
 
#define TIMER_EXP 0x01 /* timer has expired */
#define TIMER_IEN 0x02 /* enable timer interrupt */
 
#define NUMBER_TIMERS 20 /* total number of simulation timers */
 
 
Word timerRead(Word addr);
void timerWrite(Word addr, Word data);
 
void timerTick(void);
void timerStart(int msec, void (*callback)(int param), int param);
 
void timerReset(void);
void timerInit(void);
void timerExit(void);
 
 
#endif /* _TIMER_H_ */
/eco32/trunk/sim/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_ */
/eco32/trunk/sim/font
0,0 → 1,769
/* 8x16 */
/* 0x00 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x01 */
0x00, 0x00, 0x7E, 0x81, 0xA5, 0x81, 0x81, 0xBD,
0x99, 0x81, 0x81, 0x7E, 0x00, 0x00, 0x00, 0x00,
/* 0x02 */
0x00, 0x00, 0x7E, 0xFF, 0xDB, 0xFF, 0xFF, 0xC3,
0xE7, 0xFF, 0xFF, 0x7E, 0x00, 0x00, 0x00, 0x00,
/* 0x03 */
0x00, 0x00, 0x00, 0x00, 0x6C, 0xFE, 0xFE, 0xFE,
0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
/* 0x04 */
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7C, 0xFE,
0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x05 */
0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0xE7, 0xE7,
0xE7, 0x99, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
/* 0x06 */
0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF,
0x7E, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
/* 0x07 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C,
0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x08 */
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC3,
0xC3, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 0x09 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x42,
0x42, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x0A */
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x99, 0xBD,
0xBD, 0x99, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 0x0B */
0x00, 0x00, 0x1E, 0x0E, 0x1A, 0x32, 0x78, 0xCC,
0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00,
/* 0x0C */
0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C,
0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
/* 0x0D */
0x00, 0x00, 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x30,
0x30, 0x70, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00,
/* 0x0E */
0x00, 0x00, 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x63,
0x63, 0x67, 0xE7, 0xE6, 0xC0, 0x00, 0x00, 0x00,
/* 0x0F */
0x00, 0x00, 0x00, 0x18, 0x18, 0xDB, 0x3C, 0xE7,
0x3C, 0xDB, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
/* 0x10 */
0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFE, 0xF8,
0xF0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00,
/* 0x11 */
0x00, 0x02, 0x06, 0x0E, 0x1E, 0x3E, 0xFE, 0x3E,
0x1E, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
/* 0x12 */
0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18,
0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00,
/* 0x13 */
0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
/* 0x14 */
0x00, 0x00, 0x7F, 0xDB, 0xDB, 0xDB, 0x7B, 0x1B,
0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, 0x00, 0x00,
/* 0x15 */
0x00, 0x7C, 0xC6, 0x60, 0x38, 0x6C, 0xC6, 0xC6,
0x6C, 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00, 0x00,
/* 0x16 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFE, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00,
/* 0x17 */
0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18,
0x18, 0x7E, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00,
/* 0x18 */
0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
/* 0x19 */
0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00,
/* 0x1A */
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0C, 0xFE,
0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x1B */
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xFE,
0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x1C */
0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0,
0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x1D */
0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6C, 0xFE,
0x6C, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x1E */
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7C,
0x7C, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x1F */
0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x7C, 0x7C,
0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x20 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x21 */
0x00, 0x00, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x18,
0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
/* 0x22 */
0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x23 */
0x00, 0x00, 0x00, 0x6C, 0x6C, 0xFE, 0x6C, 0x6C,
0x6C, 0xFE, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00,
/* 0x24 */
0x18, 0x18, 0x7C, 0xC6, 0xC2, 0xC0, 0x7C, 0x06,
0x86, 0xC6, 0x7C, 0x18, 0x18, 0x00, 0x00, 0x00,
/* 0x25 */
0x00, 0x00, 0x00, 0x00, 0xC2, 0xC6, 0x0C, 0x18,
0x30, 0x60, 0xC6, 0x86, 0x00, 0x00, 0x00, 0x00,
/* 0x26 */
0x00, 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x76, 0xDC,
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
/* 0x27 */
0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x28 */
0x00, 0x00, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00,
/* 0x29 */
0x00, 0x00, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x0C,
0x0C, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
/* 0x2A */
0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3C, 0xFF,
0x3C, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x2B */
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E,
0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x2C */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
/* 0x2D */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x2E */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
/* 0x2F */
0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0C, 0x18,
0x30, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00,
/* 0x30 */
0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xCE, 0xD6, 0xD6,
0xE6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
/* 0x31 */
0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00,
/* 0x32 */
0x00, 0x00, 0x7C, 0xC6, 0x06, 0x0C, 0x18, 0x30,
0x60, 0xC0, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00,
/* 0x33 */
0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06, 0x3C, 0x06,
0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
/* 0x34 */
0x00, 0x00, 0x0C, 0x1C, 0x3C, 0x6C, 0xCC, 0xFE,
0x0C, 0x0C, 0x0C, 0x1E, 0x00, 0x00, 0x00, 0x00,
/* 0x35 */
0x00, 0x00, 0xFE, 0xC0, 0xC0, 0xC0, 0xFC, 0x0E,
0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
/* 0x36 */
0x00, 0x00, 0x38, 0x60, 0xC0, 0xC0, 0xFC, 0xC6,
0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
/* 0x37 */
0x00, 0x00, 0xFE, 0xC6, 0x06, 0x06, 0x0C, 0x18,
0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
/* 0x38 */
0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0xC6,
0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
/* 0x39 */
0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7E, 0x06,
0x06, 0x06, 0x0C, 0x78, 0x00, 0x00, 0x00, 0x00,
/* 0x3A */
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x3B */
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
/* 0x3C */
0x00, 0x00, 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60,
0x30, 0x18, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00,
/* 0x3D */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00,
0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x3E */
0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0C, 0x06,
0x0C, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
/* 0x3F */
0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x0C, 0x18, 0x18,
0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
/* 0x40 */
0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xDE, 0xDE,
0xDE, 0xDC, 0xC0, 0x7C, 0x00, 0x00, 0x00, 0x00,
/* 0x41 */
0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE,
0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
/* 0x42 */
0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x66,
0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00,
/* 0x43 */
0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xC0,
0xC0, 0xC2, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00,
/* 0x44 */
0x00, 0x00, 0xF8, 0x6C, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x6C, 0xF8, 0x00, 0x00, 0x00, 0x00,
/* 0x45 */
0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68,
0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00,
/* 0x46 */
0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68,
0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00,
/* 0x47 */
0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xDE,
0xC6, 0xC6, 0x66, 0x3A, 0x00, 0x00, 0x00, 0x00,
/* 0x48 */
0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6,
0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
/* 0x49 */
0x00, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
/* 0x4A */
0x00, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00,
/* 0x4B */
0x00, 0x00, 0xE6, 0x66, 0x6C, 0x6C, 0x78, 0x78,
0x6C, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00,
/* 0x4C */
0x00, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x60, 0x60,
0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00,
/* 0x4D */
0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6,
0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
/* 0x4E */
0x00, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE, 0xCE,
0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
/* 0x4F */
0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0xC6,
0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00,
/* 0x50 */
0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x60,
0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00,
/* 0x51 */
0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
0xC6, 0xD6, 0xDE, 0x7C, 0x0C, 0x0E, 0x00, 0x00,
/* 0x52 */
0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x6C,
0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00,
/* 0x53 */
0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x60, 0x38, 0x0C,
0x06, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
/* 0x54 */
0x00, 0x00, 0x7E, 0x7E, 0x5A, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
/* 0x55 */
0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
/* 0x56 */
0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
0xC6, 0x6C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
/* 0x57 */
0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6,
0xD6, 0xFE, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00,
/* 0x58 */
0x00, 0x00, 0xC6, 0xC6, 0x6C, 0x6C, 0x38, 0x38,
0x6C, 0x6C, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
/* 0x59 */
0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18,
0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
/* 0x5A */
0x00, 0x00, 0xFE, 0xC6, 0x86, 0x0C, 0x18, 0x30,
0x60, 0xC2, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00,
/* 0x5B */
0x00, 0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x3C, 0x00, 0x00, 0x00, 0x00,
/* 0x5C */
0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0x70, 0x38,
0x1C, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
/* 0x5D */
0x00, 0x00, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
0x0C, 0x0C, 0x0C, 0x3C, 0x00, 0x00, 0x00, 0x00,
/* 0x5E */
0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x5F */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00,
/* 0x60 */
0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x61 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C,
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
/* 0x62 */
0x00, 0x00, 0xE0, 0x60, 0x60, 0x78, 0x6C, 0x66,
0x66, 0x66, 0x66, 0xDC, 0x00, 0x00, 0x00, 0x00,
/* 0x63 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0,
0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
/* 0x64 */
0x00, 0x00, 0x1C, 0x0C, 0x0C, 0x3C, 0x6C, 0xCC,
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
/* 0x65 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xFE,
0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
/* 0x66 */
0x00, 0x00, 0x38, 0x6C, 0x64, 0x60, 0xF0, 0x60,
0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00,
/* 0x67 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC,
0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xCC, 0x78, 0x00,
/* 0x68 */
0x00, 0x00, 0xE0, 0x60, 0x60, 0x6C, 0x76, 0x66,
0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00,
/* 0x69 */
0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18,
0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
/* 0x6A */
0x00, 0x00, 0x06, 0x06, 0x00, 0x0E, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3C, 0x00,
/* 0x6B */
0x00, 0x00, 0xE0, 0x60, 0x60, 0x66, 0x6C, 0x78,
0x78, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00,
/* 0x6C */
0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
/* 0x6D */
0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xFE, 0xD6,
0xD6, 0xD6, 0xD6, 0xD6, 0x00, 0x00, 0x00, 0x00,
/* 0x6E */
0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
/* 0x6F */
0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6,
0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
/* 0x70 */
0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66,
0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00,
/* 0x71 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC,
0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0x0C, 0x1E, 0x00,
/* 0x72 */
0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x76, 0x62,
0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00,
/* 0x73 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x60,
0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
/* 0x74 */
0x00, 0x00, 0x10, 0x30, 0x30, 0xFC, 0x30, 0x30,
0x30, 0x30, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00,
/* 0x75 */
0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC,
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
/* 0x76 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66,
0x66, 0x66, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00,
/* 0x77 */
0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6,
0xD6, 0xD6, 0xFE, 0x6C, 0x00, 0x00, 0x00, 0x00,
/* 0x78 */
0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38,
0x38, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00,
/* 0x79 */
0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6,
0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0xF8, 0x00,
/* 0x7A */
0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xCC, 0x18,
0x30, 0x60, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00,
/* 0x7B */
0x00, 0x00, 0x0E, 0x18, 0x18, 0x18, 0x70, 0x18,
0x18, 0x18, 0x18, 0x0E, 0x00, 0x00, 0x00, 0x00,
/* 0x7C */
0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18,
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
/* 0x7D */
0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0E, 0x18,
0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00,
/* 0x7E */
0x00, 0x00, 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x7F */
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6,
0xC6, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0x80 */
0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xC0,
0xC2, 0x66, 0x3C, 0x0C, 0x06, 0x7C, 0x00, 0x00,
/* 0x81 */
0x00, 0x00, 0xCC, 0xCC, 0x00, 0xCC, 0xCC, 0xCC,
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
/* 0x82 */
0x00, 0x0C, 0x18, 0x30, 0x00, 0x7C, 0xC6, 0xFE,
0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
/* 0x83 */
0x00, 0x10, 0x38, 0x6C, 0x00, 0x78, 0x0C, 0x7C,
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
/* 0x84 */
0x00, 0x00, 0xCC, 0xCC, 0x00, 0x78, 0x0C, 0x7C,
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
/* 0x85 */
0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0C, 0x7C,
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
/* 0x86 */
0x00, 0x38, 0x6C, 0x38, 0x00, 0x78, 0x0C, 0x7C,
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
/* 0x87 */
0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x60, 0x60,
0x66, 0x3C, 0x0C, 0x06, 0x3C, 0x00, 0x00, 0x00,
/* 0x88 */
0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C, 0xC6, 0xFE,
0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
/* 0x89 */
0x00, 0x00, 0xC6, 0xC6, 0x00, 0x7C, 0xC6, 0xFE,
0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
/* 0x8A */
0x00, 0x60, 0x30, 0x18, 0x00, 0x7C, 0xC6, 0xFE,
0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
/* 0x8B */
0x00, 0x00, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18,
0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
/* 0x8C */
0x00, 0x18, 0x3C, 0x66, 0x00, 0x38, 0x18, 0x18,
0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
/* 0x8D */
0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18,
0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
/* 0x8E */
0x00, 0xC6, 0xC6, 0x10, 0x38, 0x6C, 0xC6, 0xC6,
0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
/* 0x8F */
0x38, 0x6C, 0x38, 0x00, 0x38, 0x6C, 0xC6, 0xC6,
0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
/* 0x90 */
0x18, 0x30, 0x60, 0x00, 0xFE, 0x66, 0x60, 0x7C,
0x60, 0x60, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00,
/* 0x91 */
0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x76, 0x36,
0x7E, 0xD8, 0xD8, 0x6E, 0x00, 0x00, 0x00, 0x00,
/* 0x92 */
0x00, 0x00, 0x3E, 0x6C, 0xCC, 0xCC, 0xFE, 0xCC,
0xCC, 0xCC, 0xCC, 0xCE, 0x00, 0x00, 0x00, 0x00,
/* 0x93 */
0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C, 0xC6, 0xC6,
0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
/* 0x94 */
0x00, 0x00, 0xC6, 0xC6, 0x00, 0x7C, 0xC6, 0xC6,
0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
/* 0x95 */
0x00, 0x60, 0x30, 0x18, 0x00, 0x7C, 0xC6, 0xC6,
0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
/* 0x96 */
0x00, 0x30, 0x78, 0xCC, 0x00, 0xCC, 0xCC, 0xCC,
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
/* 0x97 */
0x00, 0x60, 0x30, 0x18, 0x00, 0xCC, 0xCC, 0xCC,
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
/* 0x98 */
0x00, 0x00, 0xC6, 0xC6, 0x00, 0xC6, 0xC6, 0xC6,
0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0x78, 0x00,
/* 0x99 */
0x00, 0xC6, 0xC6, 0x00, 0x38, 0x6C, 0xC6, 0xC6,
0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00,
/* 0x9A */
0x00, 0xC6, 0xC6, 0x00, 0xC6, 0xC6, 0xC6, 0xC6,
0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
/* 0x9B */
0x00, 0x18, 0x18, 0x3C, 0x66, 0x60, 0x60, 0x60,
0x66, 0x3C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
/* 0x9C */
0x00, 0x38, 0x6C, 0x64, 0x60, 0xF0, 0x60, 0x60,
0x60, 0x60, 0xE6, 0xFC, 0x00, 0x00, 0x00, 0x00,
/* 0x9D */
0x00, 0x00, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18,
0x7E, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
/* 0x9E */
0x00, 0xF8, 0xCC, 0xCC, 0xF8, 0xC4, 0xCC, 0xDE,
0xCC, 0xCC, 0xCC, 0xC6, 0x00, 0x00, 0x00, 0x00,
/* 0x9F */
0x00, 0x0E, 0x1B, 0x18, 0x18, 0x18, 0x7E, 0x18,
0x18, 0x18, 0x18, 0x18, 0xD8, 0x70, 0x00, 0x00,
/* 0xA0 */
0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0C, 0x7C,
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
/* 0xA1 */
0x00, 0x0C, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18,
0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
/* 0xA2 */
0x00, 0x18, 0x30, 0x60, 0x00, 0x7C, 0xC6, 0xC6,
0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
/* 0xA3 */
0x00, 0x18, 0x30, 0x60, 0x00, 0xCC, 0xCC, 0xCC,
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
/* 0xA4 */
0x00, 0x00, 0x76, 0xDC, 0x00, 0xDC, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
/* 0xA5 */
0x76, 0xDC, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE,
0xCE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
/* 0xA6 */
0x00, 0x3C, 0x6C, 0x6C, 0x3E, 0x00, 0x7E, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xA7 */
0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x7C, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xA8 */
0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60,
0xC0, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
/* 0xA9 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC0,
0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xAA */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x06,
0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xAB */
0x00, 0xC0, 0xC0, 0xC2, 0xC6, 0xCC, 0x18, 0x30,
0x60, 0xCE, 0x93, 0x06, 0x0C, 0x1F, 0x00, 0x00,
/* 0xAC */
0x00, 0xC0, 0xC0, 0xC2, 0xC6, 0xCC, 0x18, 0x30,
0x66, 0xCE, 0x9A, 0x3F, 0x06, 0x0F, 0x00, 0x00,
/* 0xAD */
0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18,
0x3C, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00,
/* 0xAE */
0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x66, 0xCC,
0x66, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xAF */
0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x66, 0x33,
0x66, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xB0 */
0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
/* 0xB1 */
0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
/* 0xB2 */
0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77,
0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77,
/* 0xB3 */
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
/* 0xB4 */
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
/* 0xB5 */
0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0xF8,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
/* 0xB6 */
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xF6,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
/* 0xB7 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
/* 0xB8 */
0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0xF8,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
/* 0xB9 */
0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x06, 0xF6,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
/* 0xBA */
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
/* 0xBB */
0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x06, 0xF6,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
/* 0xBC */
0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x06, 0xFE,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xBD */
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFE,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xBE */
0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0xF8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xBF */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
/* 0xC0 */
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xC1 */
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xC2 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
/* 0xC3 */
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
/* 0xC4 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xC5 */
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
/* 0xC6 */
0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x1F,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
/* 0xC7 */
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
/* 0xC8 */
0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3F,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xC9 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x30, 0x37,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
/* 0xCA */
0x36, 0x36, 0x36, 0x36, 0x36, 0xF7, 0x00, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xCB */
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xF7,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
/* 0xCC */
0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
/* 0xCD */
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xCE */
0x36, 0x36, 0x36, 0x36, 0x36, 0xF7, 0x00, 0xF7,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
/* 0xCF */
0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xD0 */
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xD1 */
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
/* 0xD2 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
/* 0xD3 */
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3F,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xD4 */
0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x1F,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xD5 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x1F,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
/* 0xD6 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
/* 0xD7 */
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFF,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
/* 0xD8 */
0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0xFF,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
/* 0xD9 */
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xDA */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
/* 0xDB */
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 0xDC */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
/* 0xDD */
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
/* 0xDE */
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
/* 0xDF */
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xE0 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0xD8,
0xD8, 0xD8, 0xDC, 0x76, 0x00, 0x00, 0x00, 0x00,
/* 0xE1 */
0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xC6, 0xFC,
0xC6, 0xC6, 0xFC, 0xC0, 0xC0, 0xC0, 0x00, 0x00,
/* 0xE2 */
0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC0, 0xC0, 0xC0,
0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00,
/* 0xE3 */
0x00, 0x00, 0x00, 0x00, 0x80, 0xFE, 0x6C, 0x6C,
0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00,
/* 0xE4 */
0x00, 0x00, 0x00, 0xFE, 0xC6, 0x60, 0x30, 0x18,
0x30, 0x60, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00,
/* 0xE5 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xD8, 0xD8,
0xD8, 0xD8, 0xD8, 0x70, 0x00, 0x00, 0x00, 0x00,
/* 0xE6 */
0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66,
0x66, 0x7C, 0x60, 0x60, 0xC0, 0x00, 0x00, 0x00,
/* 0xE7 */
0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
/* 0xE8 */
0x00, 0x00, 0x00, 0x7E, 0x18, 0x3C, 0x66, 0x66,
0x66, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00,
/* 0xE9 */
0x00, 0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xFE,
0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00,
/* 0xEA */
0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0x6C,
0x6C, 0x6C, 0x6C, 0xEE, 0x00, 0x00, 0x00, 0x00,
/* 0xEB */
0x00, 0x00, 0x1E, 0x30, 0x18, 0x0C, 0x3E, 0x66,
0x66, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00,
/* 0xEC */
0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xDB, 0xDB,
0xDB, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xED */
0x00, 0x00, 0x00, 0x03, 0x06, 0x7E, 0xCF, 0xDB,
0xF3, 0x7E, 0x60, 0xC0, 0x00, 0x00, 0x00, 0x00,
/* 0xEE */
0x00, 0x00, 0x1C, 0x30, 0x60, 0x60, 0x7C, 0x60,
0x60, 0x60, 0x30, 0x1C, 0x00, 0x00, 0x00, 0x00,
/* 0xEF */
0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6,
0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
/* 0xF0 */
0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE,
0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xF1 */
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18,
0x18, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
/* 0xF2 */
0x00, 0x00, 0x00, 0x30, 0x18, 0x0C, 0x06, 0x0C,
0x18, 0x30, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00,
/* 0xF3 */
0x00, 0x00, 0x00, 0x0C, 0x18, 0x30, 0x60, 0x30,
0x18, 0x0C, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00,
/* 0xF4 */
0x00, 0x00, 0x0E, 0x1B, 0x1B, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
/* 0xF5 */
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0xD8, 0xD8, 0xD8, 0x70, 0x00, 0x00, 0x00, 0x00,
/* 0xF6 */
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7E,
0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xF7 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0x00,
0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xF8 */
0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xF9 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xFA */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xFB */
0x00, 0x0F, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xEC,
0x6C, 0x6C, 0x3C, 0x1C, 0x00, 0x00, 0x00, 0x00,
/* 0xFC */
0x00, 0xD8, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xFD */
0x00, 0x70, 0x98, 0x30, 0x60, 0xC8, 0xF8, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xFE */
0x00, 0x00, 0x00, 0x00, 0x7C, 0x7C, 0x7C, 0x7C,
0x7C, 0x7C, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 0xFF */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/eco32/trunk/sim/common.h
0,0 → 1,51
/*
* common.h -- common definitions
*/
 
 
#ifndef _COMMON_H_
#define _COMMON_H_
 
 
#define K 1024 /* Kilo */
#define M (K * K) /* Mega */
 
#define RAM_BASE 0x00000000 /* physical RAM base address */
#define RAM_SIZE_MAX (512 * M) /* maximum RAM size */
#define RAM_SIZE_DFL (4 * M) /* default RAM size */
#define ROM_BASE 0x20000000 /* physical ROM base address */
#define ROM_SIZE_MAX (256 * M) /* maximum ROM size */
#define ROM_SIZE (256 * K) /* actual ROM size */
#define IO_BASE 0x30000000 /* physical I/O base address */
#define IO_SIZE_MAX (256 * M) /* maximum I/O size */
 
#define IO_DEV_MASK 0x3FF00000 /* I/O device mask */
#define IO_REG_MASK 0x000FFFFF /* I/O register mask */
#define IO_GRAPH_MASK 0x003FFFFF /* I/O graphics mask */
 
#define TIMER_BASE 0x30000000 /* physical timer base address */
#define DISPLAY_BASE 0x30100000 /* physical display base address */
#define KEYBOARD_BASE 0x30200000 /* physical keyboard base address */
#define TERM_BASE 0x30300000 /* physical terminal base address */
#define MAX_NTERMS 2 /* max number of terminals */
#define DISK_BASE 0x30400000 /* physical disk base address */
#define OUTPUT_BASE 0x3F000000 /* physical output device address */
#define GRAPH_BASE 0x3FC00000 /* physical grahics base address */
/* extends to end of address space */
 
#define PAGE_SIZE (4 * K) /* size of a page and a page frame */
#define OFFSET_MASK (PAGE_SIZE - 1) /* mask for offset within a page */
#define PAGE_MASK (~OFFSET_MASK) /* mask for page number */
 
#define INSTRS_PER_MSEC 1700 /* average execution speed */
 
 
typedef enum { false, true } Bool; /* truth values */
 
 
typedef unsigned char Byte; /* 8 bit quantities */
typedef unsigned short Half; /* 16 bit quantities */
typedef unsigned int Word; /* 32 bit quantities */
 
 
#endif /* _COMMON_H_ */
/eco32/trunk/Makefile
4,7 → 4,7
 
VERSION = 0.23
 
DIRS = doc binutils
DIRS = doc binutils sim
BUILD = `pwd`/build
 
.PHONY: all compiler builddir clean dist

powered by: WebSVN 2.1.0

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