mirror of
https://github.com/rzzzwilson/pymlac.git
synced 2025-06-10 09:32:41 +00:00
Putting pymlac trace into vimlac
This commit is contained in:
parent
13c0c39da1
commit
6d808fbefd
@ -1,9 +1,9 @@
|
||||
DEVFILES = cpu.o dcpu.o ptrptp.o memory.o kb.o ttyin.o ttyout.o trace.o error.o log.o plist.o bootstrap.o
|
||||
CFILES = cpu.c dcpu.c ptrptp.c memory.c kb.c ttyin.c ttyout.c trace.c error.c log.c plist.c bootstrap.c
|
||||
HFILES = cpu.h dcpu.h ptrptp.h memory.h kb.h ttyin.h ttyout.h trace.h error.h log.h plist.h bootstrap.h
|
||||
DEVFILES = cpu.o dcpu.o ptrptp.o memory.o kb.o ttyin.o ttyout.o trace.o error.o log.o plist.o bootstrap.o display_pbm.o
|
||||
CFILES = cpu.c dcpu.c ptrptp.c memory.c kb.c ttyin.c ttyout.c trace.c error.c log.c plist.c bootstrap.c display_pbm.c
|
||||
HFILES = cpu.h dcpu.h ptrptp.h memory.h kb.h ttyin.h ttyout.h trace.h error.h log.h plist.h bootstrap.h display_pbm.h
|
||||
OFILES = vimlac.o $(DEVFILES)
|
||||
|
||||
CFLAGS=-O2 -Wall -ansi -pedantic -std=c99 -g
|
||||
CFLAGS=-O2 -Wall -pedantic -std=c99 -g
|
||||
|
||||
test: test_cpu
|
||||
rm -f vimlac.log trace.out
|
||||
@ -26,8 +26,9 @@ test_plist: test_plist.c $(DEVFILES) Makefile
|
||||
test_memory: test_memory.c memory.c memory.h Makefile
|
||||
gcc -o test_memory ${CFLAGS} memory.c test_memory.c
|
||||
|
||||
vimlac: $(CFILES)
|
||||
gcc -o vimlac ${CFLAGS} $(DEVFILES) vimlac.c
|
||||
#vimlac: $(CFILES)
|
||||
# gcc -o vimlac ${CFLAGS} $(DEVFILES) vimlac.c
|
||||
|
||||
clean:
|
||||
rm -f *.pyc *.o vimlac test_ptr test_memory *~ _#*#_.*
|
||||
rm -Rf *.dSYM
|
||||
|
||||
180
vimlac/cpu.c
180
vimlac/cpu.c
@ -198,18 +198,20 @@ Description : Emulate the IMLAC LAW/LWC instructions.
|
||||
static int
|
||||
i_LAW_LWC(bool indirect, WORD address)
|
||||
{
|
||||
vlog("i_LAW_LWC");
|
||||
|
||||
/* here 'indirect' selects between LWC and LAW */
|
||||
if (indirect)
|
||||
{
|
||||
/* LWC */
|
||||
r_AC = ~address & WORD_MASK;
|
||||
trace("LWC\t %5.5o", address);
|
||||
trace_cpu("LWC\t %5.5o", address);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* LAW */
|
||||
r_AC = address;
|
||||
trace("LAW\t %5.5o", address);
|
||||
trace_cpu("LAW\t %5.5o", address);
|
||||
}
|
||||
|
||||
return 1;
|
||||
@ -230,7 +232,7 @@ i_JMP(bool indirect, WORD address)
|
||||
|
||||
r_PC = new_address & MEMMASK;
|
||||
|
||||
trace("JMP\t%c%5.5o", (indirect) ? '*' : ' ', address);
|
||||
trace_cpu("JMP\t%c%5.5o", (indirect) ? '*' : ' ', address);
|
||||
|
||||
return (indirect) ? 3 : 2;
|
||||
}
|
||||
@ -250,7 +252,7 @@ i_DAC(bool indirect, WORD address)
|
||||
|
||||
mem_put(new_address, false, r_AC);
|
||||
|
||||
trace("DAC\t%c%5.5o", (indirect) ? '*' : ' ', address);
|
||||
trace_cpu("DAC\t%c%5.5o", (indirect) ? '*' : ' ', address);
|
||||
|
||||
return (indirect) ? 3 : 2;
|
||||
}
|
||||
@ -272,7 +274,7 @@ i_XAM(bool indirect, WORD address)
|
||||
mem_put(new_address, false, r_AC);
|
||||
r_AC = tmp;
|
||||
|
||||
trace("XAM\t%c%5.5o", (indirect) ? '*' : ' ', address);
|
||||
trace_cpu("XAM\t%c%5.5o", (indirect) ? '*' : ' ', address);
|
||||
|
||||
return (indirect) ? 3 : 2;
|
||||
}
|
||||
@ -297,7 +299,7 @@ i_ISZ(bool indirect, WORD address)
|
||||
if (new_value == 0)
|
||||
r_PC = (r_PC + 1) & WORD_MASK;
|
||||
|
||||
trace("ISZ\t%c%5.5o", (indirect) ? '*' : ' ', address);
|
||||
trace_cpu("ISZ\t%c%5.5o", (indirect) ? '*' : ' ', address);
|
||||
|
||||
return (indirect) ? 3 : 2;
|
||||
}
|
||||
@ -318,7 +320,7 @@ i_JMS(bool indirect, WORD address)
|
||||
mem_put(new_address, false, r_PC);
|
||||
r_PC = ++new_address & MEMMASK;
|
||||
|
||||
trace("JMS\t%c%5.5o", (indirect) ? '*' : ' ', address);
|
||||
trace_cpu("JMS\t%c%5.5o", (indirect) ? '*' : ' ', address);
|
||||
|
||||
return (indirect) ? 3 : 2;
|
||||
}
|
||||
@ -338,7 +340,7 @@ i_AND(bool indirect, WORD address)
|
||||
|
||||
r_AC &= mem_get(new_address, false);
|
||||
|
||||
trace("AND\t%c%5.5o", (indirect) ? '*' : ' ', address);
|
||||
trace_cpu("AND\t%c%5.5o", (indirect) ? '*' : ' ', address);
|
||||
|
||||
return (indirect) ? 3 : 2;
|
||||
}
|
||||
@ -358,7 +360,7 @@ i_IOR(bool indirect, WORD address)
|
||||
|
||||
r_AC |= mem_get(new_address, false);
|
||||
|
||||
trace("IOR\t%c%5.5o", (indirect) ? '*' : ' ', address);
|
||||
trace_cpu("IOR\t%c%5.5o", (indirect) ? '*' : ' ', address);
|
||||
|
||||
return (indirect) ? 3 : 2;
|
||||
}
|
||||
@ -378,7 +380,7 @@ i_XOR(bool indirect, WORD address)
|
||||
|
||||
r_AC ^= mem_get(new_address, false);
|
||||
|
||||
trace("XOR\t%c%5.5o", (indirect) ? '*' : ' ', address);
|
||||
trace_cpu("XOR\t%c%5.5o", (indirect) ? '*' : ' ', address);
|
||||
|
||||
return (indirect) ? 3 : 2;
|
||||
}
|
||||
@ -398,7 +400,7 @@ i_LAC(bool indirect, WORD address)
|
||||
|
||||
r_AC = mem_get(new_address, false);
|
||||
|
||||
trace("LAC\t%c%5.5o", (indirect) ? '*' : ' ', address);
|
||||
trace_cpu("LAC\t%c%5.5o", (indirect) ? '*' : ' ', address);
|
||||
|
||||
return (indirect) ? 3 : 2;
|
||||
}
|
||||
@ -423,7 +425,7 @@ i_ADD(bool indirect, WORD address)
|
||||
r_AC &= WORD_MASK;
|
||||
}
|
||||
|
||||
trace("ADD\t%c%5.5o", (indirect) ? '*' : ' ', address);
|
||||
trace_cpu("ADD\t%c%5.5o", (indirect) ? '*' : ' ', address);
|
||||
|
||||
return (indirect) ? 3 : 2;
|
||||
}
|
||||
@ -449,7 +451,7 @@ i_SUB(bool indirect, WORD address)
|
||||
r_AC &= WORD_MASK;
|
||||
}
|
||||
|
||||
trace("SUB\t%c%5.5o", (indirect) ? '*' : ' ', address);
|
||||
trace_cpu("SUB\t%c%5.5o", (indirect) ? '*' : ' ', address);
|
||||
|
||||
return (indirect) ? 3 : 2;
|
||||
}
|
||||
@ -470,7 +472,7 @@ i_SAM(bool indirect, WORD address)
|
||||
if (r_AC == mem_get(new_address, false))
|
||||
r_PC = (r_PC + 1) & WORD_MASK;
|
||||
|
||||
trace("SAM\t%c%5.5o", (indirect) ? '*' : ' ', address);
|
||||
trace_cpu("SAM\t%c%5.5o", (indirect) ? '*' : ' ', address);
|
||||
|
||||
return (indirect) ? 3 : 2;
|
||||
}
|
||||
@ -484,7 +486,7 @@ Description : Decode the 'microcode' instructions.
|
||||
static int
|
||||
microcode(WORD instruction)
|
||||
{
|
||||
char trace_msg[10]; /* little buffer for opcode */
|
||||
char trace_cpu_msg[10]; /* little buffer for opcode */
|
||||
|
||||
/* T1 */
|
||||
if (instruction & 001)
|
||||
@ -519,37 +521,37 @@ microcode(WORD instruction)
|
||||
r_L = (~r_L) & 1;
|
||||
}
|
||||
|
||||
/* do some sort of trace */
|
||||
strcpy(trace_msg, "");
|
||||
/* do some sort of trace_cpu */
|
||||
strcpy(trace_cpu_msg, "");
|
||||
switch (instruction)
|
||||
{
|
||||
case 0100000: strcat(trace_msg, "NOP"); break;
|
||||
case 0100001: strcat(trace_msg, "CLA"); break;
|
||||
case 0100002: strcat(trace_msg, "CMA"); break;
|
||||
case 0100003: strcat(trace_msg, "STA"); break;
|
||||
case 0100004: strcat(trace_msg, "IAC"); break;
|
||||
case 0100005: strcat(trace_msg, "COA"); break;
|
||||
case 0100006: strcat(trace_msg, "CIA"); break;
|
||||
case 0100010: strcat(trace_msg, "CLL"); break;
|
||||
case 0100011: strcat(trace_msg, "CAL"); break;
|
||||
case 0100020: strcat(trace_msg, "CML"); break;
|
||||
case 0100030: strcat(trace_msg, "STL"); break;
|
||||
case 0100040: strcat(trace_msg, "ODA"); break;
|
||||
case 0100041: strcat(trace_msg, "LDA"); break;
|
||||
case 0100000: strcat(trace_cpu_msg, "NOP"); break;
|
||||
case 0100001: strcat(trace_cpu_msg, "CLA"); break;
|
||||
case 0100002: strcat(trace_cpu_msg, "CMA"); break;
|
||||
case 0100003: strcat(trace_cpu_msg, "STA"); break;
|
||||
case 0100004: strcat(trace_cpu_msg, "IAC"); break;
|
||||
case 0100005: strcat(trace_cpu_msg, "COA"); break;
|
||||
case 0100006: strcat(trace_cpu_msg, "CIA"); break;
|
||||
case 0100010: strcat(trace_cpu_msg, "CLL"); break;
|
||||
case 0100011: strcat(trace_cpu_msg, "CAL"); break;
|
||||
case 0100020: strcat(trace_cpu_msg, "CML"); break;
|
||||
case 0100030: strcat(trace_cpu_msg, "STL"); break;
|
||||
case 0100040: strcat(trace_cpu_msg, "ODA"); break;
|
||||
case 0100041: strcat(trace_cpu_msg, "LDA"); break;
|
||||
}
|
||||
|
||||
if ((instruction & 0100000) == 0)
|
||||
{
|
||||
/* bit 0 is clear, it's HLT */
|
||||
cpu_on = false;
|
||||
if (trace_msg[0] != 0)
|
||||
strcat(trace_msg, "+HLT");
|
||||
if (trace_cpu_msg[0] != 0)
|
||||
strcat(trace_cpu_msg, "+HLT");
|
||||
else
|
||||
strcat(trace_msg, "HLT");
|
||||
strcat(trace_cpu_msg, "HLT");
|
||||
}
|
||||
|
||||
strcat(trace_msg, "\t");
|
||||
trace(trace_msg);
|
||||
strcat(trace_cpu_msg, "\t");
|
||||
trace_cpu(trace_cpu_msg);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -564,10 +566,10 @@ Description : Emulate the DSF instruction.
|
||||
static int
|
||||
i_DSF(void)
|
||||
{
|
||||
if (dcpu_on())
|
||||
if (dcpu_running())
|
||||
r_PC = (r_PC + 1) & WORD_MASK;
|
||||
|
||||
trace("DSF\t");
|
||||
trace_cpu("DSF\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -586,7 +588,7 @@ i_HRB(void)
|
||||
{
|
||||
r_AC |= ptr_read();
|
||||
|
||||
trace("HRB\t");
|
||||
trace_cpu("HRB\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -601,10 +603,10 @@ Description : Emulate the DSN instruction.
|
||||
static int
|
||||
i_DSN(void)
|
||||
{
|
||||
if (!dcpu_on())
|
||||
if (!dcpu_running())
|
||||
r_PC = (r_PC + 1) & WORD_MASK;
|
||||
|
||||
trace("DSN\t");
|
||||
trace_cpu("DSN\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -623,7 +625,7 @@ i_HSF(void)
|
||||
if (ptr_ready())
|
||||
r_PC = (r_PC + 1) & WORD_MASK;
|
||||
|
||||
trace("HSF\t");
|
||||
trace_cpu("HSF\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -642,7 +644,7 @@ i_HSN(void)
|
||||
if (!ptr_ready())
|
||||
r_PC = (r_PC + 1) & WORD_MASK;
|
||||
|
||||
trace("HSN\t");
|
||||
trace_cpu("HSN\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -659,7 +661,7 @@ i_KCF(void)
|
||||
{
|
||||
kb_clear_flag();
|
||||
|
||||
trace("KCF\t");
|
||||
trace_cpu("KCF\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -676,7 +678,7 @@ i_KRB(void)
|
||||
{
|
||||
r_AC |= kb_get_char();
|
||||
|
||||
trace("KRB\t");
|
||||
trace_cpu("KRB\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -694,7 +696,7 @@ i_KRC(void)
|
||||
r_AC |= kb_get_char();
|
||||
kb_clear_flag();
|
||||
|
||||
trace("KRC\t");
|
||||
trace_cpu("KRC\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -712,7 +714,7 @@ i_KSF(void)
|
||||
if (kb_ready())
|
||||
r_PC = (r_PC + 1) & WORD_MASK;
|
||||
|
||||
trace("KSF\t");
|
||||
trace_cpu("KSF\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -730,7 +732,7 @@ i_KSN(void)
|
||||
if (!kb_ready())
|
||||
r_PC = (r_PC + 1) & WORD_MASK;
|
||||
|
||||
trace("KSN\t");
|
||||
trace_cpu("KSN\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -747,7 +749,7 @@ i_PPC(void)
|
||||
{
|
||||
ptp_punch(r_AC & 0xff);
|
||||
|
||||
trace("PPC\t");
|
||||
trace_cpu("PPC\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -765,7 +767,7 @@ i_PSF(void)
|
||||
if (ptp_ready())
|
||||
r_PC = (r_PC + 1) & WORD_MASK;
|
||||
|
||||
trace("PSF\t");
|
||||
trace_cpu("PSF\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -788,7 +790,7 @@ i_RAL(int shift)
|
||||
r_AC = ((r_AC << 1) + oldlink) & WORD_MASK;
|
||||
}
|
||||
|
||||
trace("RAL\t %d", shift);
|
||||
trace_cpu("RAL\t %d", shift);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -811,7 +813,7 @@ i_RAR(int shift)
|
||||
r_AC = ((r_AC >> 1) | (oldlink << 15)) & WORD_MASK;
|
||||
}
|
||||
|
||||
trace("RAR\t %d", shift);
|
||||
trace_cpu("RAR\t %d", shift);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -828,7 +830,7 @@ i_RCF(void)
|
||||
{
|
||||
ttyin_clear_flag();
|
||||
|
||||
trace("RCF\t");
|
||||
trace_cpu("RCF\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -845,7 +847,7 @@ i_RRB(void)
|
||||
{
|
||||
r_AC |= ttyin_get_char();
|
||||
|
||||
trace("RRB\t");
|
||||
trace_cpu("RRB\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -863,7 +865,7 @@ i_RRC(void)
|
||||
r_AC |= ttyin_get_char();
|
||||
ttyin_clear_flag();
|
||||
|
||||
trace("RRC\t");
|
||||
trace_cpu("RRC\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -881,7 +883,7 @@ i_RSF(void)
|
||||
if (ttyin_ready())
|
||||
r_PC = (r_PC + 1) & WORD_MASK;
|
||||
|
||||
trace("RSF\t");
|
||||
trace_cpu("RSF\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -899,7 +901,7 @@ i_RSN(void)
|
||||
if (!ttyin_ready())
|
||||
r_PC = (r_PC + 1) & WORD_MASK;
|
||||
|
||||
trace("RSN\t");
|
||||
trace_cpu("RSN\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -919,7 +921,7 @@ i_SAL(int shift)
|
||||
while (shift-- > 0)
|
||||
r_AC = ((r_AC << 1) & WORD_MASK) | oldbit0;
|
||||
|
||||
trace("SAL\t %d", shift);
|
||||
trace_cpu("SAL\t %d", shift);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -941,7 +943,7 @@ i_SAR(int shift)
|
||||
r_AC = (r_AC >> 1) | oldbit0;
|
||||
}
|
||||
|
||||
trace("SAR\t %d", shift);
|
||||
trace_cpu("SAR\t %d", shift);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -959,7 +961,7 @@ i_SSF(void)
|
||||
if (cpu_sync_on)
|
||||
r_PC = (r_PC + 1) & WORD_MASK;
|
||||
|
||||
trace("SSF\t");
|
||||
trace_cpu("SSF\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -977,7 +979,7 @@ i_SSN(void)
|
||||
if (!cpu_sync_on)
|
||||
r_PC = (r_PC + 1) & WORD_MASK;
|
||||
|
||||
trace("SSN\t");
|
||||
trace_cpu("SSN\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -994,7 +996,7 @@ i_TCF(void)
|
||||
{
|
||||
ttyout_clear_flag();
|
||||
|
||||
trace("TCF\t");
|
||||
trace_cpu("TCF\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1012,7 +1014,7 @@ i_TPC(void)
|
||||
ttyout_send(r_AC & 0xff);
|
||||
ttyout_clear_flag();
|
||||
|
||||
trace("TPC\t");
|
||||
trace_cpu("TPC\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1029,7 +1031,7 @@ i_TPR(void)
|
||||
{
|
||||
ttyout_send(r_AC & 0xff);
|
||||
|
||||
trace("TPR\t");
|
||||
trace_cpu("TPR\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1047,7 +1049,7 @@ i_TSF(void)
|
||||
if (ttyout_ready())
|
||||
r_PC = (r_PC + 1) & WORD_MASK;
|
||||
|
||||
trace("TSF\t");
|
||||
trace_cpu("TSF\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1065,7 +1067,7 @@ i_TSN(void)
|
||||
if (!ttyout_ready())
|
||||
r_PC = (r_PC + 1) & WORD_MASK;
|
||||
|
||||
trace("TSN\t");
|
||||
trace_cpu("TSN\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1083,7 +1085,7 @@ i_ASZ(void)
|
||||
if (r_AC == 0)
|
||||
r_PC = (r_PC + 1) & WORD_MASK;
|
||||
|
||||
trace("ASZ\t");
|
||||
trace_cpu("ASZ\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1101,7 +1103,7 @@ i_ASN(void)
|
||||
if (r_AC != 0)
|
||||
r_PC = (r_PC + 1) & WORD_MASK;
|
||||
|
||||
trace("ASN\t");
|
||||
trace_cpu("ASN\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1119,7 +1121,7 @@ i_ASP(void)
|
||||
if ((r_AC & HIGHBITMASK) == 0)
|
||||
r_PC = (r_PC + 1) & WORD_MASK;
|
||||
|
||||
trace("ASP\t");
|
||||
trace_cpu("ASP\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1137,7 +1139,7 @@ i_LSZ(void)
|
||||
if (r_L == 0)
|
||||
r_PC = (r_PC + 1) & WORD_MASK;
|
||||
|
||||
trace("LSZ\t");
|
||||
trace_cpu("LSZ\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1155,7 +1157,7 @@ i_LSN(void)
|
||||
if (r_L != 0)
|
||||
r_PC = (r_PC + 1) & WORD_MASK;
|
||||
|
||||
trace("LSN\t");
|
||||
trace_cpu("LSN\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1173,7 +1175,7 @@ i_ASM(void)
|
||||
if (r_AC & HIGHBITMASK)
|
||||
r_PC = (r_PC + 1) & WORD_MASK;
|
||||
|
||||
trace("ASM\t");
|
||||
trace_cpu("ASM\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1190,7 +1192,7 @@ i_DLA(void)
|
||||
{
|
||||
dcpu_set_PC(r_AC);
|
||||
|
||||
trace("DLA\t");
|
||||
trace_cpu("DLA\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1205,7 +1207,7 @@ Description : Emulate the IMLAC CTB instruction.
|
||||
static int
|
||||
i_CTB(void)
|
||||
{
|
||||
trace("CTB\t");
|
||||
trace_cpu("CTB\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1222,7 +1224,7 @@ i_DOF(void)
|
||||
{
|
||||
dcpu_stop();
|
||||
|
||||
trace("DOF\t");
|
||||
trace_cpu("DOF\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1240,7 +1242,7 @@ i_DON(void)
|
||||
dcpu_set_DRSindex(0);
|
||||
dcpu_start();
|
||||
|
||||
trace("DON\t");
|
||||
trace_cpu("DON\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1257,7 +1259,7 @@ i_HOF(void)
|
||||
{
|
||||
ptr_stop();
|
||||
|
||||
trace("HOF\t");
|
||||
trace_cpu("HOF\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1274,7 +1276,7 @@ i_HON(void)
|
||||
{
|
||||
ptr_start();
|
||||
|
||||
trace("HON\t");
|
||||
trace_cpu("HON\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1289,7 +1291,7 @@ Description : Emulate the IMLAC STB instruction.
|
||||
static int
|
||||
i_STB(void)
|
||||
{
|
||||
trace("STB\t");
|
||||
trace_cpu("STB\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1306,7 +1308,7 @@ i_SCF(void)
|
||||
{
|
||||
Sync40HzOn = false;
|
||||
|
||||
trace("SCF\t");
|
||||
trace_cpu("SCF\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1321,7 +1323,7 @@ Description : Emulate the IMLAC IOS instruction.
|
||||
static int
|
||||
i_IOS(void)
|
||||
{
|
||||
trace("IOS\t");
|
||||
trace_cpu("IOS\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1336,7 +1338,7 @@ Description : Emulate the IMLAC IOT101 instruction.
|
||||
static int
|
||||
i_IOT101(void)
|
||||
{
|
||||
trace("IOT101\t");
|
||||
trace_cpu("IOT101\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1351,7 +1353,7 @@ Description : Emulate the IMLAC IOT111 instruction.
|
||||
static int
|
||||
i_IOT111(void)
|
||||
{
|
||||
trace("IOT111\t");
|
||||
trace_cpu("IOT111\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1365,7 +1367,7 @@ Description : Emulate the IMLAC i_IOT131 instruction.
|
||||
static int
|
||||
i_IOT131(void)
|
||||
{
|
||||
trace("i_IOT131\t");
|
||||
trace_cpu("i_IOT131\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1380,7 +1382,7 @@ Description : Emulate the IMLAC i_IOT132 instruction.
|
||||
static int
|
||||
i_IOT132(void)
|
||||
{
|
||||
trace("i_IOT132\t");
|
||||
trace_cpu("i_IOT132\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1395,7 +1397,7 @@ Description : Emulate the IMLAC IOT134 instruction.
|
||||
static int
|
||||
i_IOT134(void)
|
||||
{
|
||||
trace("IOT134\t");
|
||||
trace_cpu("IOT134\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1410,7 +1412,7 @@ Description : Emulate the IMLAC IOT141 instruction.
|
||||
static int
|
||||
i_IOT141(void)
|
||||
{
|
||||
trace("IOT141\t");
|
||||
trace_cpu("IOT141\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1425,7 +1427,7 @@ Description : Emulate the IMLAC IOF instruction.
|
||||
static int
|
||||
i_IOF(void)
|
||||
{
|
||||
trace("IOF\t");
|
||||
trace_cpu("IOF\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1440,7 +1442,7 @@ Description : Emulate the IMLAC ION instruction.
|
||||
static int
|
||||
i_ION(void)
|
||||
{
|
||||
trace("ION\t");
|
||||
trace_cpu("ION\t");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1629,5 +1631,3 @@ cpu_execute_one(void)
|
||||
|
||||
return 0; /* CAN'T REACH */
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
#ifndef CPU_H
|
||||
#define CPU_H
|
||||
|
||||
#include "vimlac.h"
|
||||
//#include "vimlac.h"
|
||||
|
||||
/******
|
||||
* Exported functions.
|
||||
|
||||
605
vimlac/dcpu.c
605
vimlac/dcpu.c
@ -9,22 +9,56 @@
|
||||
#include "vimlac.h"
|
||||
#include "dcpu.h"
|
||||
#include "memory.h"
|
||||
#include "display_pbm.h"
|
||||
#include "trace.h"
|
||||
|
||||
|
||||
/******
|
||||
* Constants, etc.
|
||||
******/
|
||||
|
||||
#define MSBBITS 6
|
||||
#define LSBBITS 5
|
||||
|
||||
#define MSBMASK 03740
|
||||
#define LSBMASK 037
|
||||
|
||||
// full 11 bits of display addressing
|
||||
#define DMASK 03777
|
||||
// AC bits that set DX or DY
|
||||
#define BITS10 01777
|
||||
|
||||
#define DMSB 03740
|
||||
|
||||
#define DLSB 037
|
||||
|
||||
// display CPU constants - modes
|
||||
#define MODE_NORMAL 0
|
||||
#define MODE_DEIM 1
|
||||
|
||||
// full 11 bits of display addressing
|
||||
#define DMASK 03777
|
||||
// AC bits that set DX or DY
|
||||
#define BITS10 01777
|
||||
#define DMSB 03740
|
||||
#define DLSB 037
|
||||
|
||||
/******
|
||||
* Emulated registers, state, memory, etc.
|
||||
******/
|
||||
|
||||
static WORD r_PC;
|
||||
static WORD Prev_r_PC;
|
||||
static int r_DRSindex;
|
||||
static WORD DPC = 0; // the display PC
|
||||
static WORD Prev_DPC; // the *previous* display PC
|
||||
static WORD DRS[] = {0, 0, 0, 0, 0, 0, 0, 0}; // display CPU stack
|
||||
static int DRSindex; //
|
||||
static int DX; //
|
||||
static int DY; //
|
||||
static float DScale = 4; // display scale (1, 2, 4, 8)
|
||||
int DIB = 0; // ????
|
||||
static BYTE Mode = MODE_NORMAL; // DEIM mode
|
||||
static bool Running = false; // true if display processor is running
|
||||
|
||||
|
||||
/******
|
||||
* Environment stuff. PTR and TTY in and out files, etc
|
||||
******/
|
||||
|
||||
static bool cpu_is_on; /* true if display processor is running */
|
||||
static char DEIM_result[10]; // holds DEIM_decode() result
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
@ -33,24 +67,32 @@ Description : Functions to get/set various registers.
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
|
||||
WORD
|
||||
dcpu_get_PC(void)
|
||||
{
|
||||
return r_PC;
|
||||
return DPC;
|
||||
}
|
||||
|
||||
|
||||
WORD
|
||||
dcpu_get_prev_PC(void)
|
||||
{
|
||||
return Prev_DPC;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
dcpu_set_PC(WORD value)
|
||||
{
|
||||
r_PC = value;
|
||||
DPC = value;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
dcpu_set_DRSindex(int value)
|
||||
{
|
||||
r_DRSindex = value;
|
||||
DRSindex = value;
|
||||
}
|
||||
|
||||
|
||||
@ -63,9 +105,7 @@ Description : Function to handle unrecognized instruction.
|
||||
static void
|
||||
illegal(void)
|
||||
{
|
||||
WORD oldPC = Prev_r_PC & MEMMASK;
|
||||
|
||||
/* memdump(LogOut, oldPC - 8, 16); */
|
||||
WORD oldPC = Prev_DPC & MEMMASK;
|
||||
|
||||
error("INTERNAL ERROR: "
|
||||
"unexpected main processor opcode %06.6o at address %06.6o",
|
||||
@ -73,55 +113,477 @@ illegal(void)
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Decode a DEIM byte into human text.
|
||||
Parameters : byte - the DEIM byte to decode
|
||||
Returns : A string that describes the DEIM byte
|
||||
Comments : Uses the static buffer "DEIM_result".
|
||||
******************************************************************************/
|
||||
char *
|
||||
DEIMdecode(BYTE byte)
|
||||
{
|
||||
// empty the result buffer
|
||||
char *bptr = DEIM_result;
|
||||
*bptr = '\0';
|
||||
|
||||
// now decode the DEIM byte
|
||||
if (byte & 0x80)
|
||||
{
|
||||
if (byte & 0x40)
|
||||
{
|
||||
strcat(bptr, "B");
|
||||
*++bptr = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
strcat(bptr, "D");
|
||||
*++bptr = '\0';
|
||||
if (byte & 0x20)
|
||||
{
|
||||
strcat(bptr, "-");
|
||||
*++bptr = '\0';
|
||||
}
|
||||
|
||||
sprintf(bptr, "%d", (byte >> 3) & 0x03);
|
||||
bptr = DEIM_result + strlen(DEIM_result);
|
||||
|
||||
if (byte & 0x04)
|
||||
{
|
||||
strcat(bptr, "-");
|
||||
*++bptr = '\0';
|
||||
}
|
||||
|
||||
sprintf(bptr, "%d", byte & 0x03);
|
||||
bptr = DEIM_result + strlen(DEIM_result);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (byte == 0111)
|
||||
{
|
||||
strcat(bptr, "N");
|
||||
*++bptr = '\0';
|
||||
}
|
||||
else if (byte == 0151)
|
||||
{
|
||||
strcat(bptr, "R");
|
||||
*++bptr = '\0';
|
||||
}
|
||||
else if (byte == 0171)
|
||||
{
|
||||
strcat(bptr, "F");
|
||||
*++bptr = '\0';
|
||||
}
|
||||
else if (byte == 0200)
|
||||
{
|
||||
strcat(bptr, "P");
|
||||
*++bptr = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(bptr, "A%03o", byte);
|
||||
bptr = DEIM_result + strlen(DEIM_result);
|
||||
}
|
||||
}
|
||||
|
||||
return DEIM_result;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Execute a DEIM instruction byte.
|
||||
Parameters : byte - the DEIM byte to decode
|
||||
: last - 'true' if the last byte in a word
|
||||
Returns : A trace string that describes the DEIM byte
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
|
||||
static
|
||||
char *doDEIMByte(BYTE byte, bool last)
|
||||
{
|
||||
|
||||
char *trace = DEIMdecode(byte);
|
||||
|
||||
if (byte & 0x80) // increment mode
|
||||
{
|
||||
int dx = (byte & 0x18) >> 3; // extract X/Y deltas
|
||||
int dy = (byte & 0x03);
|
||||
|
||||
int prevDX = DX; // save previous position
|
||||
int prevDY = DY;
|
||||
|
||||
if (byte & 0x20) // get dx sign and move X
|
||||
{
|
||||
DX -= dx * DScale;
|
||||
}
|
||||
else
|
||||
{
|
||||
DX += dx * DScale;
|
||||
}
|
||||
|
||||
if (byte & 0x04) // get dy sign and move Y
|
||||
{
|
||||
DY -= dy * DScale;
|
||||
}
|
||||
else
|
||||
{
|
||||
DY += dy * DScale;
|
||||
}
|
||||
|
||||
if (byte & 0x40) // if beam on
|
||||
{
|
||||
display_draw(prevDX, prevDY, DX, DY);
|
||||
}
|
||||
}
|
||||
else // control instructions
|
||||
{
|
||||
if (byte & 0x40) // escape DEIM mode
|
||||
{
|
||||
Mode = MODE_NORMAL;
|
||||
}
|
||||
|
||||
if (byte & 0x20) // DRJM
|
||||
{
|
||||
if (DRSindex <= 0)
|
||||
{
|
||||
illegal();
|
||||
}
|
||||
DRSindex -= 1;
|
||||
DPC = DRS[DRSindex];
|
||||
}
|
||||
|
||||
if (byte & 0x10) // inc X MSB
|
||||
{
|
||||
DX += (1 << LSBBITS);
|
||||
}
|
||||
|
||||
if (byte & 0x08) // clear X LSB
|
||||
{
|
||||
DX &= MSBMASK;
|
||||
}
|
||||
|
||||
if (byte & 0x02) // inc Y MSB
|
||||
{
|
||||
DY += (1 << LSBBITS);
|
||||
}
|
||||
|
||||
if (byte & 0x01) // clear Y LSB
|
||||
{
|
||||
DY &= MSBMASK;
|
||||
}
|
||||
}
|
||||
|
||||
return trace;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : The emulated display CPU instructions.
|
||||
Parameters :
|
||||
Returns : The number of display CPU cycles executed.
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
|
||||
static
|
||||
int i_DDXM(void)
|
||||
{
|
||||
DX -= 040;
|
||||
trace_dcpu("DDXM");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int i_DDYM(void)
|
||||
{
|
||||
DY -= 040;
|
||||
trace_dcpu("DDYM");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int i_DEIM(WORD address)
|
||||
{
|
||||
Mode = MODE_DEIM;
|
||||
trace_dcpu("DEIM %s", doDEIMByte(address & 0377, true));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int i_DHLT(void)
|
||||
{
|
||||
Running = false;
|
||||
trace_dcpu("DHLT");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int i_DHVC(void)
|
||||
{
|
||||
trace_dcpu("DHVC");
|
||||
// TODO: should DO SOMETHING here?
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int i_DIXM(void)
|
||||
{
|
||||
DX += 04000;
|
||||
trace_dcpu("DIXM");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int i_DIYM(void)
|
||||
{
|
||||
DY += 04000;
|
||||
trace_dcpu("DIYM");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int i_DJMP(WORD address)
|
||||
{
|
||||
DPC = MASK_MEM(address + (DIB << 12));
|
||||
trace_dcpu("DJMP %04o", address);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int i_DJMS(WORD address)
|
||||
{
|
||||
if (DRSindex >= 8)
|
||||
{
|
||||
illegal();
|
||||
}
|
||||
DRS[DRSindex] = DPC;
|
||||
DRSindex += 1;
|
||||
DPC = MASK_MEM(address + (DIB << 12));
|
||||
trace_dcpu("DJMS %04o", address);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int i_DLXA(WORD address)
|
||||
{
|
||||
DX = (address & BITS10) << 1;
|
||||
trace_dcpu("DLXA %04o", address);
|
||||
return 1;
|
||||
}
|
||||
static
|
||||
int i_DLYA(WORD address)
|
||||
{
|
||||
DY = (address & BITS10) << 1;
|
||||
trace_dcpu("DLYA %04o", address);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int i_DLVH(WORD word1)
|
||||
{
|
||||
WORD word2 = mem_get(DPC, false);
|
||||
DPC = MASK_MEM(DPC + 1);
|
||||
|
||||
WORD word3 = mem_get(DPC, false);
|
||||
DPC = MASK_MEM(DPC + 1);
|
||||
|
||||
// WORD dotted = word2 & 040000;
|
||||
// WORD beamon = word2 & 020000;
|
||||
WORD negx = word3 & 040000;
|
||||
WORD negy = word3 & 020000;
|
||||
WORD ygtx = word3 & 010000;
|
||||
|
||||
WORD M = word2 & 007777;
|
||||
WORD N = word3 & 007777;
|
||||
|
||||
int prevDX = DX;
|
||||
int prevDY = DY;
|
||||
|
||||
if (ygtx) // M is y, N is x
|
||||
{
|
||||
if (negx)
|
||||
DX -= N;
|
||||
else
|
||||
DX += N;
|
||||
|
||||
if (negy)
|
||||
DY -= M;
|
||||
else
|
||||
DY += M;
|
||||
}
|
||||
else // M is x, N is y
|
||||
{
|
||||
if (negx)
|
||||
DX -= M;
|
||||
else
|
||||
DX += M;
|
||||
|
||||
if (negy)
|
||||
DY -= N;
|
||||
else
|
||||
DY += N;
|
||||
|
||||
//display_draw(prevDX, prevDY, DX, DY, dotted);
|
||||
display_draw(prevDX, prevDY, DX, DY);
|
||||
}
|
||||
|
||||
trace_dcpu("DLVH");
|
||||
return 3;
|
||||
}
|
||||
|
||||
static
|
||||
int i_DRJM(void)
|
||||
{
|
||||
if (DRSindex <= 0)
|
||||
{
|
||||
illegal();
|
||||
}
|
||||
|
||||
DRSindex -= 1;
|
||||
DPC = DRS[DRSindex];
|
||||
trace_dcpu("DRJM");
|
||||
return 1; // FIXME check # cycles used
|
||||
}
|
||||
|
||||
static
|
||||
int i_DSTB(int block)
|
||||
{
|
||||
DIB = block;
|
||||
trace_dcpu("DSTB %d", block);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int i_DSTS(int scale)
|
||||
{
|
||||
if (scale == 0)
|
||||
DScale = 0.5;
|
||||
else if (scale == 1)
|
||||
DScale = 1.0;
|
||||
else if (scale == 2)
|
||||
DScale = 2.0;
|
||||
else if (scale == 3)
|
||||
DScale = 3.0;
|
||||
else
|
||||
illegal();
|
||||
trace_dcpu("DSTS %d", scale);
|
||||
return 1; // FIXME check # cycles used
|
||||
}
|
||||
|
||||
static
|
||||
int page00(WORD instruction)
|
||||
{
|
||||
int cycles = 0;
|
||||
|
||||
if (instruction == 000000) // DHLT
|
||||
cycles = i_DHLT();
|
||||
else if (instruction == 004000) // DNOP
|
||||
{
|
||||
cycles = 1;
|
||||
trace_dcpu("DNOP");
|
||||
}
|
||||
else if (instruction == 004004) // DSTS 0
|
||||
cycles = i_DSTS(0);
|
||||
else if (instruction == 004005) // DSTS 1
|
||||
cycles = i_DSTS(1);
|
||||
else if (instruction == 004006) // DSTS 2
|
||||
cycles = i_DSTS(2);
|
||||
else if (instruction == 004007) // DSTS 3
|
||||
cycles = i_DSTS(3);
|
||||
else if (instruction == 004010) // DSTB 0
|
||||
cycles = i_DSTB(0);
|
||||
else if (instruction == 004011) // DSTB 1
|
||||
cycles = i_DSTB(1);
|
||||
else if (instruction == 004040) // DRJM
|
||||
cycles = i_DRJM();
|
||||
else if (instruction == 004100) // DDYM
|
||||
cycles = i_DDYM();
|
||||
else if (instruction == 004200) // DDXM
|
||||
cycles = i_DDXM();
|
||||
else if (instruction == 004400) // DIYM
|
||||
cycles = i_DIYM();
|
||||
else if (instruction == 005000) // DIXM
|
||||
cycles = i_DIXM();
|
||||
else if (instruction == 006000) // DHVC
|
||||
cycles = i_DHVC();
|
||||
else
|
||||
illegal();
|
||||
|
||||
return cycles;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
Description : Function to execute one display processor instruction.
|
||||
Parameters :
|
||||
Returns :
|
||||
Returns : The number of display CPU cycles executed.
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
int
|
||||
dcpu_execute_one(void)
|
||||
{
|
||||
WORD instruction = 0;
|
||||
bool indirect = false;
|
||||
WORD opcode = 0;
|
||||
WORD address = 0;
|
||||
|
||||
/******
|
||||
* If processor not running, return immediately.
|
||||
******/
|
||||
|
||||
if (!cpu_is_on)
|
||||
return 0;
|
||||
|
||||
/******
|
||||
* Fetch the instruction. Split into initial opcode and address.
|
||||
******/
|
||||
|
||||
Prev_r_PC = r_PC;
|
||||
instruction = mem_get(r_PC++, false);
|
||||
r_PC = r_PC & MEMMASK;
|
||||
|
||||
indirect = (bool) (instruction & 0100000); /* high bit set? */
|
||||
opcode = (instruction >> 11) & 017; /* high 5 bits */
|
||||
address = instruction & 03777; /* low 11 bits */
|
||||
|
||||
/******
|
||||
* Now decode it.
|
||||
******/
|
||||
|
||||
#ifdef JUNK
|
||||
switch (opcode)
|
||||
if (!Running)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
++instruction;
|
||||
indirect = !indirect;
|
||||
++opcode;
|
||||
++address;
|
||||
illegal();
|
||||
|
||||
return 0;
|
||||
//WORD dot = DPC;
|
||||
WORD instruction = mem_get(DPC, false);
|
||||
|
||||
DPC = MASK_MEM(DPC + 1);
|
||||
|
||||
if (Mode == MODE_DEIM)
|
||||
{
|
||||
char *tracestr = doDEIMByte(instruction >> 8, false);
|
||||
|
||||
if (Mode == MODE_DEIM)
|
||||
{
|
||||
strcat(tracestr, ",");
|
||||
strcat(tracestr, doDEIMByte(instruction & 0xff, true));
|
||||
}
|
||||
trace_dcpu("INC %s", tracestr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
WORD opcode = instruction >> 12;
|
||||
WORD address = instruction & 07777;
|
||||
|
||||
if (opcode == 000)
|
||||
{
|
||||
return page00(instruction);
|
||||
}
|
||||
else if (opcode == 001)
|
||||
{
|
||||
return i_DLXA(address);
|
||||
}
|
||||
else if (opcode == 002)
|
||||
{
|
||||
return i_DLYA(address);
|
||||
}
|
||||
else if (opcode == 003)
|
||||
{
|
||||
return i_DEIM(address);
|
||||
}
|
||||
else if (opcode == 004)
|
||||
{
|
||||
return i_DLVH(address);
|
||||
}
|
||||
else if (opcode == 005)
|
||||
{
|
||||
return i_DJMS(address);
|
||||
}
|
||||
else if (opcode == 006)
|
||||
{
|
||||
return i_DJMP(address);
|
||||
}
|
||||
else if (opcode == 007)
|
||||
{
|
||||
illegal();
|
||||
}
|
||||
else
|
||||
{
|
||||
illegal();
|
||||
}
|
||||
|
||||
return 0; // to turn off "control may reach end of non-void function"
|
||||
}
|
||||
|
||||
|
||||
@ -132,9 +594,9 @@ Description : Function to get CPU state.
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
bool
|
||||
dcpu_on(void)
|
||||
dcpu_running(void)
|
||||
{
|
||||
return cpu_is_on;
|
||||
return Running;
|
||||
}
|
||||
|
||||
|
||||
@ -147,7 +609,7 @@ Description : Function to start the CPU.
|
||||
void
|
||||
dcpu_start(void)
|
||||
{
|
||||
cpu_is_on = true;
|
||||
Running = true;
|
||||
}
|
||||
|
||||
|
||||
@ -160,12 +622,12 @@ Description : Function to stop the CPU.
|
||||
void
|
||||
dcpu_stop(void)
|
||||
{
|
||||
cpu_is_on = false;
|
||||
Running = false;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Function to stop the CPU.
|
||||
Description : Function to set the DCPU DRS index.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
@ -173,7 +635,32 @@ Description : Function to stop the CPU.
|
||||
void
|
||||
dcpu_set_drsindex(int index)
|
||||
{
|
||||
r_DRSindex = index;
|
||||
DRSindex = index;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Function to get the display X coord.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
int
|
||||
dcpu_get_x(void)
|
||||
{
|
||||
return DX;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : Function to get the display Y coord.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
int
|
||||
dcpu_get_y(void)
|
||||
{
|
||||
return DY;
|
||||
}
|
||||
|
||||
|
||||
@ -6,19 +6,17 @@
|
||||
#ifndef DCPU_H
|
||||
#define DCPU_H
|
||||
|
||||
#include "vimlac.h"
|
||||
//#include "vimlac.h"
|
||||
|
||||
/******
|
||||
* Exported functions.
|
||||
******/
|
||||
|
||||
void dcpu_start(void);
|
||||
void dcpu_stop(void);
|
||||
int dcpu_execute_one(void);
|
||||
WORD dcpu_get_PC(void);
|
||||
void dcpu_set_PC(WORD value);
|
||||
void dcpu_set_DRSindex(int index);
|
||||
bool dcpu_on(void);
|
||||
|
||||
void dcpu_set_DRSindex(int value);
|
||||
int dcpu_execute_one(void);
|
||||
bool dcpu_running(void);
|
||||
void dcpu_start(void);
|
||||
void dcpu_stop(void);
|
||||
void dcpu_set_drsindex(int index);
|
||||
int dcpu_get_x(void);
|
||||
int dcpu_get_y(void);
|
||||
|
||||
#endif
|
||||
|
||||
164
vimlac/display_pbm.c
Executable file
164
vimlac/display_pbm.c
Executable file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
* A display object that write *.PBM files.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "vimlac.h"
|
||||
#include "display_pbm.h"
|
||||
#include "log.h"
|
||||
|
||||
|
||||
/*****
|
||||
* constants for the display device
|
||||
******/
|
||||
|
||||
#define PBM_EXTENSION "pbm"
|
||||
#define SCALE_MAX_X 1024
|
||||
#define SCALE_MAX_Y 1024
|
||||
|
||||
|
||||
/*****
|
||||
* State variables for the display
|
||||
******/
|
||||
|
||||
static char *pbm_display; // pointer to display array of chars
|
||||
static bool pbm_running = false; // true if display is ON
|
||||
static int pbm_cyclecount = 0; // number of cycles for one instruction execution
|
||||
static int pbm_sync40 = 0; // counter for 40Hz flag
|
||||
static int pbm_file_num = 0; // number of next PBM file to write
|
||||
static bool pbm_dirty = false; // 'true' if buffer unsaved
|
||||
|
||||
void
|
||||
display_reset(void)
|
||||
{
|
||||
for (int i = 0; i < SCALE_MAX_X * SCALE_MAX_Y; ++i)
|
||||
pbm_display[i] = 0;
|
||||
|
||||
// set internal state
|
||||
pbm_running = 0;
|
||||
pbm_cyclecount = 0;
|
||||
pbm_sync40 = 1;
|
||||
pbm_file_num = 0;
|
||||
pbm_dirty = false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
display_init(void)
|
||||
{
|
||||
pbm_display = (char *) malloc(sizeof(bool) * SCALE_MAX_X * SCALE_MAX_Y);
|
||||
display_reset();
|
||||
}
|
||||
|
||||
void
|
||||
display_write(void)
|
||||
{
|
||||
char fname[1024];
|
||||
|
||||
pbm_file_num += 1;
|
||||
sprintf(fname, "pymlac_%06d.pbm", pbm_file_num);
|
||||
printf("fname=%s", fname);
|
||||
FILE *fd = fopen(fname, "w");
|
||||
fprintf(fd, "P1\n");
|
||||
fprintf(fd, "# created by pymlac %s\n", VIMLAC_VERSION);
|
||||
fprintf(fd, "%d %d\n", SCALE_MAX_X, SCALE_MAX_Y);
|
||||
for (int i = 0; i < SCALE_MAX_X * SCALE_MAX_Y; ++i)
|
||||
fprintf(fd, "%d\n", pbm_display[i]);
|
||||
fclose(fd);
|
||||
|
||||
pbm_dirty = false;
|
||||
}
|
||||
|
||||
|
||||
//*********************************************************
|
||||
// Draw a line on the screen.
|
||||
//
|
||||
// x1, y1 start coordinates
|
||||
// x2, y2 end coordinates
|
||||
// dotted True if dotted line, else False (IGNORED)
|
||||
//
|
||||
// Algorithm from:
|
||||
// http://csourcecodes.blogspot.com/2016/06/bresenhams-line-drawing-algorithm-generalized-c-program.html
|
||||
//*********************************************************
|
||||
//
|
||||
void
|
||||
//draw(int x1, int y1, int x2, int y2, dotted=False)
|
||||
display_draw(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
// convert virtual coords to physical
|
||||
x1 /= 2;
|
||||
y1 /= 2;
|
||||
x2 /= 2;
|
||||
y2 /= 2;
|
||||
|
||||
// invert the Y axis
|
||||
y1 = SCALE_MAX_Y - y1;
|
||||
y2 = SCALE_MAX_Y - y2;
|
||||
|
||||
// draw the line (Bresenham algorithm)
|
||||
int x = x1;
|
||||
int y = y1;
|
||||
int dx = abs(x2 - x1);
|
||||
int dy = abs(y2 - y1);
|
||||
int s1, s2;
|
||||
if (x2 > x1)
|
||||
s1 = 1;
|
||||
else
|
||||
s2 = -1;
|
||||
if (y2 > y1)
|
||||
s2 = 1;
|
||||
else
|
||||
s2 = -1;
|
||||
bool swap = false;
|
||||
pbm_display[(y-1)*SCALE_MAX_X + x - 1] = 1;
|
||||
if (dy > dx)
|
||||
{
|
||||
int temp = dx;
|
||||
|
||||
dx = dy;
|
||||
dy = temp;
|
||||
swap = true;
|
||||
}
|
||||
int p = 2*dy - dx;
|
||||
for (int i = 0; i < dx; ++i)
|
||||
{
|
||||
pbm_display[(y-1)*SCALE_MAX_X + x - 1] = 1 ;
|
||||
while (p >= 0)
|
||||
{
|
||||
p = p - 2*dx;
|
||||
if (swap)
|
||||
x += s1;
|
||||
else
|
||||
y += s2;
|
||||
}
|
||||
p = p + 2*dy;
|
||||
if (swap)
|
||||
y += s2;
|
||||
else
|
||||
x += s1;
|
||||
}
|
||||
|
||||
pbm_dirty = true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
display_clear(void)
|
||||
{
|
||||
// clear display, but write display to next PBM file first
|
||||
if (pbm_dirty)
|
||||
display_write();
|
||||
display_reset();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
display_close(void)
|
||||
{
|
||||
if (pbm_dirty)
|
||||
display_write();
|
||||
free(pbm_display);
|
||||
}
|
||||
17
vimlac/display_pbm.h
Executable file
17
vimlac/display_pbm.h
Executable file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Interface for the vimlac PBM display.
|
||||
*/
|
||||
|
||||
#ifndef DISPLAY_PBM_H
|
||||
#define DISPLAY_PBM_H
|
||||
|
||||
|
||||
void display_reset(void);
|
||||
void display_init(void);
|
||||
void display_write(void);
|
||||
void display_draw(int x1, int y1, int x2, int y2);
|
||||
void display_clear(void);
|
||||
void display_close(void);
|
||||
|
||||
|
||||
#endif
|
||||
137
vimlac/trace.c
137
vimlac/trace.c
@ -6,11 +6,17 @@
|
||||
|
||||
#include "vimlac.h"
|
||||
#include "cpu.h"
|
||||
#include "dcpu.h"
|
||||
#include "log.h"
|
||||
|
||||
|
||||
bool TraceFlag = false;
|
||||
bool TraceFlag = true;
|
||||
static char *TraceFile = "trace.out";
|
||||
static FILE *trace_fp = NULL;
|
||||
static char CPU_trace[64];
|
||||
static char DCPU_trace[64];
|
||||
static char CPU_reg_trace[64];
|
||||
static char DCPU_reg_trace[64];
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
@ -44,91 +50,120 @@ trace_close(void)
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Description : printf()-style output routine to RAW screen.
|
||||
* Parameters : like printf()
|
||||
* Description : Prepare a new trace outut.
|
||||
* Parameters :
|
||||
* Returns :
|
||||
* Comments :
|
||||
******************************************************************************/
|
||||
void
|
||||
Emit(char *fmt, ...)
|
||||
trace_start_line(void)
|
||||
{
|
||||
va_list ap;
|
||||
char buff[512];
|
||||
char *chptr;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsprintf(buff, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
for (chptr = buff; *chptr != '\0'; ++chptr)
|
||||
fprintf(trace_fp, "%c", *chptr);
|
||||
|
||||
fflush(trace_fp);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DumpRegs(char *buff)
|
||||
{
|
||||
sprintf(buff, "AC=0%6.6o\tL=%1.1o", cpu_get_AC(), cpu_get_L());
|
||||
}
|
||||
|
||||
void
|
||||
trace_delim(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buff[1024];
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsprintf(buff, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
Emit("%s\n", buff);
|
||||
// set output buffer to empty
|
||||
CPU_trace[0] = 0;
|
||||
DCPU_trace[0] = 0;
|
||||
CPU_reg_trace[0] = 0;
|
||||
DCPU_reg_trace[0] = 0;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : printf()-style trace routine to dump registers.
|
||||
* Description : Write stored data to the trace file.
|
||||
* Parameters :
|
||||
* Returns :
|
||||
* Comments :
|
||||
******************************************************************************/
|
||||
void
|
||||
trace_end_line(void)
|
||||
{
|
||||
fprintf(trace_fp, "%06o: %-20s%-20s %-s %-s\n",
|
||||
cpu_get_prev_PC(), CPU_trace, DCPU_trace,
|
||||
CPU_reg_trace, DCPU_reg_trace);
|
||||
fflush(trace_fp);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : printf()-style trace routine to dump main CPU registers.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void
|
||||
traceRegs(void)
|
||||
trace_regs(void)
|
||||
{
|
||||
static char outbuff[512];
|
||||
TraceFlag = true; // DEBUG
|
||||
|
||||
if (TraceFlag != false)
|
||||
{
|
||||
char emitbuff[512];
|
||||
|
||||
DumpRegs(outbuff);
|
||||
sprintf(emitbuff, "\t;%s", outbuff);
|
||||
Emit(emitbuff);
|
||||
sprintf(CPU_reg_trace, "AC=%06.6o L=%1.1o", cpu_get_AC(), cpu_get_L());
|
||||
vlog(CPU_reg_trace);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : printf()-style trace routine.
|
||||
Description : printf()-style trace routine to dump dislpay CPU registers.
|
||||
Parameters :
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void
|
||||
trace_dregs(void)
|
||||
{
|
||||
TraceFlag = true; // DEBUG
|
||||
|
||||
if (TraceFlag != false)
|
||||
{
|
||||
sprintf(DCPU_reg_trace, "DPC=%06o X=%04o, Y=%04o",
|
||||
dcpu_get_PC(), dcpu_get_x(), dcpu_get_y());
|
||||
vlog(DCPU_reg_trace);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Description : printf()-style trace routine for the CPU.
|
||||
Parameters : like printf()
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void
|
||||
trace(char *fmt, ...)
|
||||
trace_cpu(char *fmt, ...)
|
||||
{
|
||||
static char outbuff[512];
|
||||
TraceFlag = true; // DEBUG
|
||||
|
||||
if (TraceFlag != false)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsprintf(outbuff, fmt, ap);
|
||||
vsprintf(CPU_trace, fmt, ap);
|
||||
va_end(ap);
|
||||
Emit("0%6.6o\t%s", cpu_get_prev_PC(), outbuff);
|
||||
traceRegs();
|
||||
Emit("\n");
|
||||
|
||||
trace_regs();
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
Description : printf()-style trace routine for the display CPU.
|
||||
Parameters : like printf()
|
||||
Returns :
|
||||
Comments :
|
||||
******************************************************************************/
|
||||
void
|
||||
trace_dcpu(char *fmt, ...)
|
||||
{
|
||||
TraceFlag = true; // DEBUG
|
||||
|
||||
if (TraceFlag != false)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsprintf(DCPU_trace, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
trace_dregs();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5,9 +5,16 @@
|
||||
#ifndef TRACE_H
|
||||
#define TRACE_H
|
||||
|
||||
void trace(char *fmt, ...);
|
||||
|
||||
extern bool TraceFlag;
|
||||
|
||||
void trace_open(void);
|
||||
void trace_close(void);
|
||||
void trace_delim(char *fmt, ...);
|
||||
void trace_start_line(void);
|
||||
void trace_end_line(void);
|
||||
void trace_regs(void);
|
||||
void trace_dregs(void);
|
||||
void trace_cpu(char *fmt, ...);
|
||||
void trace_dcpu(char *fmt, ...);
|
||||
|
||||
#endif
|
||||
|
||||
@ -38,9 +38,18 @@
|
||||
#include "memory.h"
|
||||
#include "ptrptp.h"
|
||||
#include "cpu.h"
|
||||
#include "dcpu.h"
|
||||
#include "trace.h"
|
||||
#include "log.h"
|
||||
|
||||
|
||||
//*********************************************************
|
||||
// Conevrt a string to all lower case.
|
||||
//
|
||||
// s the string to convert (in situ)
|
||||
//
|
||||
// Returns the original string pointer.
|
||||
//*********************************************************
|
||||
char *
|
||||
strtolower(char *s)
|
||||
{
|
||||
@ -53,11 +62,13 @@ strtolower(char *s)
|
||||
}
|
||||
|
||||
|
||||
//*********************************************************
|
||||
// Convert a string to an integer value.
|
||||
//
|
||||
// s the string to convert
|
||||
// s the string to convert
|
||||
//
|
||||
// The string may indicate a decimal or octal value.
|
||||
//*********************************************************
|
||||
|
||||
int
|
||||
str2int(char *s)
|
||||
@ -73,21 +84,63 @@ str2int(char *s)
|
||||
}
|
||||
|
||||
|
||||
//*********************************************************
|
||||
// Run the emulator until the main/display CPU have
|
||||
// both stopped.
|
||||
//*********************************************************
|
||||
|
||||
// Trace.init('pymlac.trace', cpu, dcpu)
|
||||
//
|
||||
// cpu.running = True
|
||||
// while cpu.running:
|
||||
// Trace.start()
|
||||
//
|
||||
// log(f'cpu.PC={cpu.PC}')
|
||||
// cycles = cpu.execute_one_instruction()
|
||||
// log(f'start_running: cpu.execute_one_instruction returned {cycles}')
|
||||
// dcycles = dcpu.execute_one_instruction()
|
||||
// log(f'start_running: dcpu.execute_one_instruction returned {dcycles}')
|
||||
// ptrptp.ptr_tick(cycles)
|
||||
// ptrptp.ptp_tick(cycles)
|
||||
// ttyin.tick(cycles)
|
||||
//
|
||||
// Trace.end_line()
|
||||
// Trace.flush()
|
||||
//
|
||||
// Trace.close()
|
||||
|
||||
void
|
||||
run(WORD pc)
|
||||
{
|
||||
cpu_set_PC(pc);
|
||||
cpu_start();
|
||||
while (true)
|
||||
trace_open();
|
||||
|
||||
//while (cpu_running() && dcpu_running())
|
||||
while (cpu_running())
|
||||
{
|
||||
int cycles = cpu_execute_one();
|
||||
if (cycles < 1)
|
||||
break;
|
||||
ptr_tick(cycles);
|
||||
vlog("run: loop, PC=%06o", cpu_get_PC());
|
||||
trace_start_line();
|
||||
|
||||
int cycles = cpu_execute_one();
|
||||
int dcycles = dcpu_execute_one();
|
||||
|
||||
ptr_tick(cycles+dcycles);
|
||||
ptp_tick(cycles+dcycles);
|
||||
// ttyin_tick(cycles);
|
||||
|
||||
trace_end_line();
|
||||
}
|
||||
|
||||
trace_close();
|
||||
}
|
||||
|
||||
|
||||
//*********************************************************
|
||||
// Print some help for the befuddled user.
|
||||
// msg a message to print
|
||||
//*********************************************************
|
||||
|
||||
void
|
||||
usage(char *msg)
|
||||
{
|
||||
@ -127,6 +180,10 @@ usage(char *msg)
|
||||
}
|
||||
|
||||
|
||||
//*********************************************************
|
||||
// Start the emulator.
|
||||
//*********************************************************
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
@ -240,17 +297,21 @@ main(int argc, char *argv[])
|
||||
}
|
||||
address = strtolower(argv[ndx]);
|
||||
ndx += 1;
|
||||
WORD run_pc;
|
||||
if (!STREQ(address, "pc"))
|
||||
{
|
||||
cpu_set_PC(str2int(address));
|
||||
vlog("Running from address %s", address);
|
||||
run_pc = str2int(address);
|
||||
}
|
||||
else
|
||||
{
|
||||
vlog("Running from current PC %06o", cpu_get_PC());
|
||||
run_pc = cpu_get_PC();
|
||||
}
|
||||
// Trace.set_TraceMap(trace_map);
|
||||
// start_running(imlac_cpu, imlac_dcpu, imlac_memory, imlac_ptrptp, imlac_ttyin);
|
||||
run(run_pc);
|
||||
}
|
||||
else if (STREQ(opt, "-s"))
|
||||
{
|
||||
@ -366,17 +427,5 @@ main(int argc, char *argv[])
|
||||
sprintf(buff, "Unrecognized option '%s'", opt);
|
||||
usage(buff);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
// mem_clear(0);
|
||||
// mem_set_rom(PtrROMImage);
|
||||
// ptr_mount("test_add.ptp");
|
||||
// run(040);
|
||||
// run(0100);
|
||||
// mem_save_core("vimlac.core");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -20,6 +20,8 @@
|
||||
typedef unsigned int WORD;
|
||||
typedef unsigned char BYTE;
|
||||
|
||||
#define MEMORY_SIZE 04000
|
||||
|
||||
#define CPU_HERZ 1800000
|
||||
#define MEMMASK 0xffff
|
||||
#define HIGHBITMASK 0x8000
|
||||
@ -33,5 +35,8 @@ typedef unsigned char BYTE;
|
||||
// macro to more reliably compare strings
|
||||
#define STREQ(a, b) ((a) && (strcmp((a), (b)) == 0))
|
||||
|
||||
// macro to mask an address to the address space limits
|
||||
#define MASK_MEM(addr) (addr & (MEMORY_SIZE - 1))
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user