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, <ch); |
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>>>> "); |
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 < 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 < 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 |