Updated the 5170 BIOS map, updated 8042 info, fixed some 8042 controller commands, made HLT work, and fixed the debugger's history buffer when executing a mix of real-mode and protected-mode instructions
This commit is contained in:
parent
f2627107d5
commit
93b81c47b7
13 changed files with 804 additions and 287 deletions
File diff suppressed because one or more lines are too long
|
|
@ -1,8 +1,24 @@
|
|||
F000:002C @ POST1
|
||||
F000:00A6 @ POST1_TEST01 ; TEST.01: 286 PROCESSOR TEST (REAL MODE)
|
||||
F000:01EE @ POST1_TEST02 ; TEST.02: VERIFY CMOS SHUTDOWN BYTE
|
||||
F000:0213 @ POST1_TEST03 ; TEST.03: ROS CHECKSUM TEST
|
||||
F000:0225 @ POST1_TEST04 ; TEST.04: 8253 CHECK TIMER 1 (ALL BITS ON)
|
||||
F000:025C @ POST1_TEST05 ; TEST.05: 8253 CHECK TIMER 1 (ALL BITS OFF)
|
||||
F000:027B @ POST1_TEST06 ; TEST.06: 8237 DMA 0 INITIALIZATION
|
||||
F000:02C6 @ POST1_TEST07 ; TEST.07: 8237 DMA 1 INITIALIZATION
|
||||
F000:033B @ POST1_TEST08 ; TEST.08: DMA PAGE REGISTER TEST
|
||||
F000:038E @ POST1_TEST09 ; TEST.09: STORAGE REFRESH TEST
|
||||
F000:03A6 @ POST1_TEST10 ; TEST.10: 8042 TESTS
|
||||
F000:03DD @ POST1_GETSW ; GET SWITCH SETTINGS
|
||||
F000:0426 @ POST1_TEST11 ; TEST.11: BASE 64K R/W STORAGE TEST
|
||||
F000:0606 @ POST1_SETMFG ; SET MFG_TST
|
||||
F000:060D @ POST1_TEST11A ; TEST.11A: VERIFY GDT/IDT INSTRUCTIONS
|
||||
F000:06FA @ POST1_TEST12 ; TEST.12: VERIFY CMOS CHECKSUM
|
||||
F000:07E2 @ POST1_TEST13 ; TEST.13: PROTECTED MODE TEST
|
||||
F000:08B7 @ POST1_TEST13A ; TEST.13A: MEMORY SIZE TEST (ABOVE 1024K)
|
||||
F000:0AB4 @ POST1_TEST14 ; TEST.14: INITIALIZE CRT CONTROLLER
|
||||
F000:0B27 @ POST1_TEST15 ; TEST.15: VIDEO LINE TEST
|
||||
F000:0B37 @ POST1_TEST16 ; TEST.16: CRT INTERFACE LINES TEST
|
||||
0C3F +
|
||||
F000:0000 @ POST2 ; TEST.17: 8259 PIC TEST
|
||||
F000:0058 @ POST2_CP27 ; CHECKPOINT 0x27
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
From [http://minuszerodegrees.net/bios/BIOS_5170_10JAN84_6MHZ/README.TXT](http://minuszerodegrees.net/bios/BIOS_5170_10JAN84_6MHZ.zip):
|
||||
From [http://minuszerodegrees.net/bios/BIOS_5170_10JAN84_6MHZ/README.TXT](http://minuszerodegrees.net/bios/):
|
||||
|
||||
This is the first BIOS for the IBM 5170.
|
||||
It is dated 10JAN84.
|
||||
|
|
@ -9,7 +9,7 @@ From [http://minuszerodegrees.net/bios/BIOS_5170_10JAN84_6MHZ/README.TXT](http:/
|
|||
|
||||
8 bit checksum of 6181028 = 36
|
||||
8 bit checksum of 6181029 = CA
|
||||
----
|
||||
--
|
||||
added = 00
|
||||
|
||||
There are two BIN files in this ZIP file:
|
||||
|
|
@ -17,14 +17,17 @@ From [http://minuszerodegrees.net/bios/BIOS_5170_10JAN84_6MHZ/README.TXT](http:/
|
|||
1. BIOS_5170_10JAN84_U27_6181028_27256_6MHZ.BIN --> Use this to create a U27 using a 27256 EPROM (rated at 150nS or faster)
|
||||
2. BIOS_5170_10JAN84_U47_6181029_27256_6MHZ.BIN --> Use this to create a U47 using a 27256 EPROM (rated at 150nS or faster)
|
||||
|
||||
The JSON-encoded ROM image that PCjs uses ([1984-01-10.json]()) was created using the *FileDump* command-line *merge* option:
|
||||
The JSON-encoded ROM image that PCjs uses was created using the *FileDump* command-line *merge* option:
|
||||
|
||||
filedump --file=BIOS_5170_10JAN84_U27_6181028_27256_6MHZ.BIN --merge=BIOS_5170_10JAN84_U47_6181029_27256_6MHZ.BIN --output=1984-01-10.json
|
||||
filedump --file=http://static.pcjs.org/devices/pc/bios/5170/BIOS_5170_10JAN84_U27_6181028_27256_6MHZ.BIN --merge=http://static.pcjs.org/devices/pc/bios/5170/BIOS_5170_10JAN84_U47_6181029_27256_6MHZ.BIN --output=1984-01-10.json --overwrite
|
||||
|
||||
Since a MAP file ([1984-01-10.map]()) exists as well, it is automatically appended to the JSON file ([1984-01-10.json]())
|
||||
when using a ROM input file (or JSON output file) with a matching filename.
|
||||
|
||||
Similarly, to create a binary ROM image (1984-01-10.rom), add *--format=rom* to the command-line. These operations can
|
||||
only be performed using the *FileDump* command-line interface; the *FileDump* API does not support the *merge* option.
|
||||
It is also possible to create a merged binary ROM image ([1984-01-10.rom](http://static.pcjs.org/devices/pc/bios/5170/1984-01-10.rom))
|
||||
by adding *--format=rom* to the command-line (the default is *--format=json*).
|
||||
|
||||
A MAP file [1984-01-10.map]() exists as well, which is automatically appended to the JSON file when using a ROM input
|
||||
file (or JSON output file) with a matching filename. For example:
|
||||
These operations can only be performed using the *FileDump* command-line interface; the *FileDump* API does not support
|
||||
either the *merge* option or the appending of MAP data. For the moment, the API can only dump unadorned ROM images; eg:
|
||||
|
||||
http://www.pcjs.org/api/v1/dump/?file=/devices/pc/bios/5170/1984-01-10.rom
|
||||
http://www.pcjs.org/api/v1/dump/?file=http://static.pcjs.org/devices/pc/bios/5170/1984-01-10.rom
|
||||
|
|
|
|||
10
devices/pc/keyboard/README.md
Normal file
10
devices/pc/keyboard/README.md
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
8042 Keyboard Controller Internals
|
||||
---
|
||||
|
||||
The following documents were obtained from [halicery.com](http://halicery.com/):
|
||||
|
||||
- [8042_INTERN.TXT]()
|
||||
- [8042_1503033.TXT]()
|
||||
- [dasm42.c]()
|
||||
|
||||
Additional information (eg, undocumented 8042 commands) is also available from [OS/2 Museum](http://www.os2museum.com/wp/?p=589).
|
||||
408
devices/pc/keyboard/dasm42.c
Normal file
408
devices/pc/keyboard/dasm42.c
Normal file
|
|
@ -0,0 +1,408 @@
|
|||
#include <stdio.h> // we use printf()
|
||||
|
||||
|
||||
/*
|
||||
Small Intel UPI-41/42 DISASSEMBLER
|
||||
==================================
|
||||
A. Tarpai 2010 (tarpai76 gmail com)
|
||||
|
||||
It was written to look at some 8042 ROM dump code.
|
||||
You can use and modify it for any purpose.
|
||||
I'm happy if you mention me, the author.
|
||||
No warranties (what for?).
|
||||
|
||||
Usage:
|
||||
------
|
||||
Call dasm42() passing a pointer, an offset and number of bytes.
|
||||
Uses 1 external: printf().
|
||||
|
||||
The disassembler is based on the book
|
||||
"Microprocessor Peripherals UPI-41A/41AH/42/42AH User's Manual, INTEL CORPORATION, 1996"
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
static int PC;
|
||||
|
||||
|
||||
/* Operand Addressing Mode writers */
|
||||
|
||||
typedef void (*Tfop)(unsigned char *p);
|
||||
|
||||
static void fopJMP(unsigned char *p) // JMP and CALL: 11-bit absolute address (2K)
|
||||
{
|
||||
printf("$%04X", ((*p<<3)&0x700) | p[1]);
|
||||
}
|
||||
|
||||
static void fopJ(unsigned char *p) // jumps: 8-bit in-page address
|
||||
{
|
||||
printf("$%04X", (PC&0xff00)|p[1]); // TODO!! Jump at page boundary?? PC or PC+2 here?
|
||||
}
|
||||
|
||||
static void fopRx(unsigned char *p) // Register Direct (x=0-7)
|
||||
{
|
||||
printf("R%x", *p&7);
|
||||
}
|
||||
|
||||
static void fopPx(unsigned char *p) // Port Direct (x=[1,2])
|
||||
{
|
||||
printf("P%x", *p&3);
|
||||
}
|
||||
|
||||
static void fopRRx(unsigned char *p) // Indexed @R0 or @R1
|
||||
{
|
||||
printf("@R%x", *p&1);
|
||||
}
|
||||
|
||||
static void fopA(unsigned char *p) // Accumulator
|
||||
{
|
||||
printf("A");
|
||||
}
|
||||
|
||||
static void fopIMM(unsigned char *p) // Immediate 8-bit value
|
||||
{
|
||||
printf("#$%02X", p[1]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
typedef void (*Tfmnop)(unsigned char *p, Tfop fop1, Tfop fop2);
|
||||
|
||||
static void fopJB(unsigned char *p, Tfop fop1, Tfop fop2) // JBx is special (have to complete the mn)
|
||||
{
|
||||
printf("%x ", *p>>5);
|
||||
fopJ(p);
|
||||
}
|
||||
|
||||
static void fmnop2(unsigned char *p, Tfop fop1, Tfop fop2) // 2-operand instructions
|
||||
{
|
||||
printf(" ");
|
||||
fop1(p);
|
||||
printf(",");
|
||||
fop2(p);
|
||||
}
|
||||
|
||||
static void fmnop1(unsigned char *p, Tfop fop1, Tfop fop2) // 1-operand instructions
|
||||
{
|
||||
printf(" ");
|
||||
fop1(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct instr {
|
||||
char *mn;
|
||||
unsigned char opcd;
|
||||
unsigned char opcdmsk;
|
||||
char len;
|
||||
Tfmnop fmnop;
|
||||
Tfop fop1, fop2;
|
||||
};
|
||||
|
||||
|
||||
static struct instr instrs[] = {
|
||||
{ "ADD", 0x68, 0xf8, 1, fmnop2, fopA, fopRx}, // ADD A,Rr Add Register Contents to Accumulator
|
||||
{ "ADD", 0x60, 0xfe, 1, fmnop2, fopA, fopRRx}, // ADD A,@Rr Add Data Memory Contents to Accumulator
|
||||
{ "ADD", 0x03, 0xff, 2, fmnop2, fopA, fopIMM}, // ADD A,Ýdata Add Immediate Data to Accumulator
|
||||
{ "ADDC", 0x78, 0xf8, 1, fmnop2, fopA, fopRx}, // ADDC A,Rr Add Carry and Register Contents to Accumulator
|
||||
{ "ADDC", 0x70, 0xfe, 1, fmnop2, fopA, fopRRx}, // ADDC A,@Rr Add Carry and Data Memory Contents to Accumulator
|
||||
{ "ADDC", 0x13, 0xff, 2, fmnop2, fopA, fopIMM}, // Add Carry and Immediate Data to Accumulator
|
||||
{ "ANL", 0x58, 0xf8, 1, fmnop2, fopA, fopRx}, // AND A,Rr Add Register Contents to Accumulator
|
||||
{ "ANL", 0x50, 0xfe, 1, fmnop2, fopA, fopRRx}, // AND A,@Rr Add Data Memory Contents to Accumulator
|
||||
{ "ANL", 0x53, 0xff, 2, fmnop2, fopA, fopIMM}, // AND A,Ýdata Add Immediate Data to Accumulator
|
||||
{ "ANL", 0x98, 0xfc, 2, fmnop2, fopPx, fopIMM}, // ANL PP,Ýdata Logical AND PORT 1±2 With Immediate Mask
|
||||
{ "ANLD", 0x9C, 0xfc, 1, fmnop2, fopPx, fopA}, // ANLD Pp,A Logical AND Port 4±7 With Accumulator Mask
|
||||
{ "CALL", 0x14, 0x1f, 2, fmnop1, fopJMP},
|
||||
{ "CLR A", 0x27, 0xff, 1, 0}, // CLR A
|
||||
{ "CLR C", 0x97, 0xff, 1, 0}, // CLR C Clear Carry Bit
|
||||
{ "CLR F1", 0xA5, 0xff, 1, 0}, // CLR F1 Clear Flag 1
|
||||
{ "CLR F0", 0x85, 0xff, 1, 0}, // CLR F0 Clear Flag 0
|
||||
{ "CPL A", 0x37, 0xff, 1, 0}, // CPL A Complement Accumulator
|
||||
{ "CPL C", 0xA7, 0xff, 1, 0}, // CPL C Complement Carry Bit
|
||||
{ "CPL F0", 0x95, 0xff, 1, 0}, // CPL F0 COMPLEMENT FLAG 0
|
||||
{ "CPL F1", 0xB5, 0xff, 1, 0}, // CPL F1 COMPLEMENT FLAG 1
|
||||
{ "DA A", 0x57, 0xff, 1, 0}, // DA A Decimal Adjust Accumulator
|
||||
{ "DEC A", 0x07, 0xff, 1, 0}, // DEC A Decrement Accumulator
|
||||
{ "DEC", 0xC8, 0xf8, 1, fmnop1, fopRx}, // DEC Rr Decrement Register
|
||||
{ "DIS I", 0x15, 0xff, 1, 0}, // DIS I Disable IBF Interrupt
|
||||
{ "DIS TCNTI", 0x35, 0xff, 1, 0}, // DIS TCNTI Disable Timer/Counter Interrupt
|
||||
{ "DJNZ", 0xE8, 0xf8, 2, fmnop2, fopRx, fopJ}, // DJNZ Rr, address Decrement Register and Test
|
||||
{ "EN DMA", 0xE5, 0xff, 1, 0}, // EN DMA Enable DMA Handshake Lines
|
||||
{ "EN FLAGS", 0xF5, 0xff, 1, 0 }, // EN FLAGS Enable Master Interrupts
|
||||
{ "EN I", 0x05, 0xff, 1, 0 }, // EN I Enable IBF Interrupt
|
||||
{ "EN TCNTI", 0x25, 0xff, 1, 0}, // EN TCNTI Enable Timer/Counter Interrupt
|
||||
{ "IN A,DBB", 0x22, 0xff, 1, 0}, // IN A,DBB Input Data Bus Buffer Contents to Accumulator
|
||||
{ "IN", 0x08, 0xfc, 1, fmnop2, fopA, fopPx}, // IN A,Pp Input Port 1±2 Data to Accumulator
|
||||
{ "INC A", 0x17, 0xff, 1, 0}, // INC A
|
||||
{ "INC", 0x18, 0xf8, 1, fmnop1, fopRx}, // INC Rr Increment Register
|
||||
{ "INC", 0x10, 0xfe, 1, fmnop1, fopRRx}, // INC @Rr Increment Data Memory Location
|
||||
{ "JB", 0x12, 0x1f, 2, fopJB}, // JBb address Jump If Accumulator Bit is Set
|
||||
{ "JC", 0xF6, 0xff, 2, fmnop1, fopJ }, //
|
||||
{ "JF0", 0xB6, 0xff, 2, fmnop1, fopJ }, //
|
||||
{ "JF1", 0x76, 0xff, 2, fmnop1, fopJ }, //
|
||||
{ "JMP", 0x04, 0x1f, 2, fmnop1, fopJMP},
|
||||
{ "JMPP @A", 0xB3, 0xff, 1, 0 }, // JMPP @A Indirect Jump Within Page
|
||||
{ "JNC", 0xE6, 0xff, 2, fmnop1, fopJ }, //
|
||||
{ "JNIBF", 0xD6, 0xff, 2, fmnop1, fopJ }, //
|
||||
{ "JNT0", 0x26, 0xff, 2, fmnop1, fopJ }, // JNTO address Jump if TEST 0 is Low
|
||||
{ "JNT1", 0x46, 0xff, 2, fmnop1, fopJ }, //
|
||||
{ "JNZ", 0x96, 0xff, 2, fmnop1, fopJ }, //
|
||||
{ "JOBF", 0x86, 0xff, 2, fmnop1, fopJ }, //
|
||||
{ "JTF", 0x16, 0xff, 2, fmnop1, fopJ }, //
|
||||
{ "JT0", 0x36, 0xff, 2, fmnop1, fopJ }, //
|
||||
{ "JT1", 0x56, 0xff, 2, fmnop1, fopJ }, //
|
||||
{ "JZ", 0xC6, 0xff, 2, fmnop1, fopJ }, //
|
||||
{ "MOV", 0x23, 0xff, 2, fmnop2, fopA, fopIMM }, // MOV A,Ýdata Move Immediate Data to Accumulator
|
||||
{ "MOV A,PSW", 0xC7, 0xff, 1, 0}, // MOV A,PSW Move PSW Contents to Accumulator
|
||||
{ "MOV", 0xF8, 0xf8, 1, fmnop2, fopA, fopRx }, // MOV A,Rr Move Register Contents to Accumulator
|
||||
{ "MOV", 0xF0, 0xfe, 1, fmnop2, fopA, fopRRx }, // MOV A,@Rr Move Data Memory Contents to Accumulator
|
||||
{ "MOV A,T", 0x42, 0xff, 1, 0}, // MOV A,T Move Timer/Counter Contents to Accumulator
|
||||
{ "MOV PSW,A", 0xD7, 0xff, 1, 0}, // MOV PSW,A Move Accumulator Contents to PSW
|
||||
{ "MOV", 0xA8, 0xf8, 1, fmnop2, fopRx, fopA }, // MOV Rr,A Move Accumulator Contents to Register
|
||||
{ "MOV", 0xB8, 0xf8, 2, fmnop2, fopRx, fopIMM }, // MOV Rr,Ýdata Move Immediate Data to Register
|
||||
{ "MOV", 0xA0, 0xfe, 1, fmnop2, fopRRx, fopA }, // MOV @Rr,A Move Accumulator Contents to Data Memory
|
||||
{ "MOV", 0xB0, 0xfe, 2, fmnop2, fopRRx, fopIMM }, // MOV @Rr,Ýdata Move Immediate Data to Data Memory
|
||||
{ "MOV STS,A", 0x90, 0xff, 1, 0}, // MOV STS,A Move Accumulator Contents to STS Register
|
||||
{ "MOV T,A", 0x62, 0xff, 1, 0}, // MOV T,A Move Accumulator Contents to Timer/Counter
|
||||
{ "MOVD", 0x0C, 0xfc, 2, fmnop2, fopA, fopPx }, // MOVD A,Pp Move Port 4±7 Data to Accumulator
|
||||
{ "MOVD", 0x3C, 0xfc, 2, fmnop2, fopPx, fopA }, // MOVD Pp,A Move Accumulator Data to Port 4, 5, 6 and 7
|
||||
{ "MOVP A,@A", 0xA3, 0xff, 1, 0}, // MOVP A,@A Move Current Page Data to Accumulator
|
||||
{ "MOVP3 A,@A", 0xE3, 0xff, 1, 0}, // MOVP3 A,@A Move Page 3 Data to Accumulator
|
||||
{ "NOP", 0x00, 0xff, 1, 0},
|
||||
{ "ORL", 0x48, 0xf8, 1, fmnop2, fopA, fopRx}, // ORL A,Rr Logical OR Accumulator With Register Mask
|
||||
{ "ORL", 0x40, 0xfe, 1, fmnop2, fopA, fopRRx}, // ORL A,@Rr Logical OR Accumulator With Memory Mask
|
||||
{ "ORL", 0x43, 0xff, 2, fmnop2, fopA, fopIMM}, // ORL A,ÝData Logical OR Accumulator With Immediate Mask
|
||||
{ "ORL", 0x88, 0xfc, 2, fmnop2, fopPx, fopIMM}, // ORL Pp,Ýdata Logical OR Port 1±2 With Immediate Mask
|
||||
{ "ORLD", 0x8C, 0xfc, 2, fmnop2, fopPx, fopA}, // ORLD Pp,A Logical OR Port 4±7 With Accumulator Mask
|
||||
{ "OUT DBB,A", 0x02, 0xff, 1, 0}, // OUT DBB,A Output Accumulator Contents to Data Bus Buffer
|
||||
{ "OUTL", 0x38, 0xfc, 1, fmnop2, fopPx, fopA }, // OUTL Pp,A Output Accumulator Data to Port 1 and 2
|
||||
{ "RET", 0x83, 0xff, 1, 0}, // RET Return Without PSW Restore
|
||||
{ "RETR", 0x93, 0xff, 1, 0}, // RET Return Without PSW Restore
|
||||
{ "RL A", 0xE7, 0xff, 1, 0}, // RL A Rotate Left Without Carry
|
||||
{ "RLC A", 0xF7, 0xff, 1, 0}, // RLC A Rotate Left Through Carry
|
||||
{ "RR A", 0x77, 0xff, 1, 0}, // RR A Rotate Right Without Carry
|
||||
{ "RRC A", 0x67, 0xff, 1, 0}, // RRC A Rotate Right Through Carry
|
||||
{ "SEL RB0", 0xC5, 0xff, 1, 0}, // SEL RB0 Select Register Bank 0
|
||||
{ "SEL RB1", 0xD5, 0xff, 1, 0}, // SEL RB1 Select Register Bank 1
|
||||
{ "STOP TCNT", 0x65, 0xff, 1, 0}, // STOP TCNT Stop Timer/Event Counter
|
||||
{ "STRT CNT", 0x45, 0xff, 1, 0}, // STRT CNT Start Event Counter
|
||||
{ "STRT T", 0x55, 0xff, 1, 0}, // STRT T Start Timer
|
||||
{ "SWAP A", 0x47, 0xff, 1, 0}, // SWAP A Swap Nibbles Within Accumulator
|
||||
{ "XCH", 0x28, 0xf8, 1, fmnop2, fopA, fopRx}, // XCH ARr Exchange Accumulator-Register Contents
|
||||
{ "XCH", 0x20, 0xfe, 1, fmnop2, fopA, fopRRx}, // XCH A,@Rr Exchange Accumulator and Data Memory Contents
|
||||
{ "XCHD", 0x30, 0xfe, 1, fmnop2, fopA, fopRRx}, // XCHD A,@Rr Exchange Accumulator and Data Memory 4-bit Data
|
||||
{ "XRL", 0xD8, 0xf8, 1, fmnop2, fopA, fopRx}, // XRL A,Rr Logical XOR Accumulator With Register Mask
|
||||
{ "XRL", 0xD0, 0xfe, 1, fmnop2, fopA, fopRRx}, // XRL A,@Rr Logical XOR Accumulator With Memory Mask
|
||||
{ "XRL", 0xD3, 0xff, 2, fmnop2, fopA, fopIMM}, // XRL A,Ýdata, Logical XOR Accumulator With Immediate Mask
|
||||
|
||||
{ "???", 0, 0, 1, 0} // All others (zero-mask will be true - if reached, len=1)
|
||||
};
|
||||
|
||||
|
||||
static int instr1(unsigned char *p)
|
||||
{
|
||||
struct instr *i= instrs;
|
||||
for (; ; i++) {
|
||||
if ((*p & i->opcdmsk) == i->opcd) {
|
||||
printf("%04X: ", PC); // print Program Counter
|
||||
PC+=i->len; // we increment PC as if CPU did for JMP instructions(?)
|
||||
printf("%02X ", p[0]); // write 1 or 2 code bytes
|
||||
if (i->len==2) printf("%02X ", p[1]);
|
||||
else printf(" ");
|
||||
printf("%s", i->mn); // write mnemonic
|
||||
if (i->fmnop) i->fmnop(p, i->fop1, i->fop2); // write 0, 1 or 2 operands
|
||||
printf("\n");
|
||||
return i->len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Extern.
|
||||
Disassemble iNTEL UPI-41/42 machine code
|
||||
of n bytes, from p + offset
|
||||
|
||||
*/
|
||||
|
||||
void dasm42(char *p, int offs, int n)
|
||||
{
|
||||
p+=offs;
|
||||
PC=offs;
|
||||
n+=offs;
|
||||
for (; PC < n;) p+=instr1(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/********** NOTES ****************************************************
|
||||
|
||||
Addressing:
|
||||
- implicite (in instr)
|
||||
- register Rn (0..7)
|
||||
- indexed @Rn (0..1)
|
||||
- A
|
||||
- # (0..$ff)
|
||||
- addr, 1 byte + PC (0..$ffff)
|
||||
|
||||
|
||||
--------------------
|
||||
RAM (DATA) 256 bytes
|
||||
--------------------
|
||||
0..7 R0..R7 BANK0 (Bs in PSW)
|
||||
8..23 STACK (8x16bit) .....
|
||||
24..31 R0..R7 BANK1
|
||||
...... to top: "RAM" .....
|
||||
|
||||
R0, R1 can be index register
|
||||
|
||||
----------------
|
||||
ROM (PROGRAM) 2K
|
||||
----------------
|
||||
RESET: $0000
|
||||
IBR INT: $0003
|
||||
TIMER INT: $0007
|
||||
|
||||
-----------
|
||||
PC - 10-bit (not 11?)
|
||||
-----------
|
||||
PC always points to next instruction.
|
||||
|
||||
----
|
||||
JUMP
|
||||
----
|
||||
a.) absolute address: JMP $35E = aa a9 a8 0 0 1 0 0 a7 a6 a5 a4 a3 a2 a1 a0 (2-byte instr)
|
||||
b.) "relative" (op -> PC-LO): JZ $addr = $C6 $op (2-byte instr)
|
||||
// OK.. "If a conditional JUMP or indirect JUMP begins in location 255 of a page, it must reference a destination on the following page"
|
||||
|
||||
--------
|
||||
PC-stack
|
||||
--------
|
||||
8x16 bits: call/int saves PSW[7..4]&PC[11..0]
|
||||
|
||||
-------------------------
|
||||
PSW - program status word
|
||||
-------------------------
|
||||
7 6 5 4 | 3 | 2 1 0
|
||||
C AC F0 Bs| - | SP
|
||||
|
||||
CALL: push PC&PSW[7..4]
|
||||
RET: pop PC
|
||||
RETR: pop PC&PSW[7..4]
|
||||
|
||||
|
||||
On-chip oscillator
|
||||
------------------
|
||||
1 to 12.5 MHz
|
||||
or external
|
||||
|
||||
-------------------
|
||||
8-bit Timer/Counter
|
||||
-------------------
|
||||
|
||||
Timer-mode
|
||||
- increments on OSC + 32-prescale
|
||||
- START T .. STOP TCNT
|
||||
|
||||
Counter-mode
|
||||
- increments on falling edges on TEST1-pin
|
||||
- START CNT .. STOP TCNT
|
||||
|
||||
- MOV T,A and MOV A,T for reading/writing
|
||||
|
||||
|
||||
Timer/Counter OVERFLOW
|
||||
----------------------
|
||||
fe..ff..00
|
||||
|
||||
1. sets timer flag (TF) - then can be tested by JTF (which clears TF)
|
||||
2. generates IRQ
|
||||
3. EN/DIS TCNTI
|
||||
4. if enabled: CALL $0007 happens
|
||||
|
||||
|
||||
----------
|
||||
INTERRUPTS
|
||||
----------
|
||||
|
||||
IBF:
|
||||
- higher pri
|
||||
- EN/DIS I
|
||||
- CS & RW triggers
|
||||
|
||||
Timer
|
||||
- EN/DIS TCNTI
|
||||
-
|
||||
|
||||
1. IRQ set + disable all interrupts
|
||||
2. CALL 3 (IBF) or 7 (T)
|
||||
3. entering ISR clears IRQ
|
||||
4. ISR
|
||||
5. RETR (re-enables interrupt)
|
||||
|
||||
HOST INTERRUPTS
|
||||
---------------
|
||||
|
||||
EN FLAGS will allocate P24/P25 to OBF/_IBF (only RESET clears it)
|
||||
"These interrupt outputs reflect the internal status of the OBF flag and the IBF inverted flag."
|
||||
"Note, these outputs may be inhibited by writing a '0' to these pins. Reenabling interrupts is done by writing a '1' to these port pins."
|
||||
|
||||
==> so host cpu doesn't have to poll the same bits in STATUS REG (0x64); it can have it as interrupts (this is set in the code after RESET..)
|
||||
|
||||
------------
|
||||
HOST CPU I/O
|
||||
------------
|
||||
|
||||
!!! There are 3 registers in the UPI on the host side !!! (NB. host CPU writes into DBBIN..)
|
||||
|
||||
<--R-- STATUS <--- MOV STS,A + JF0,JF1,JOBF,JNIBF
|
||||
HOST CPU I/O <--R-- DBBOUT <--- OUT DBB,A
|
||||
--W--> DBBIN ---> IN A,DBB
|
||||
|
||||
RD WR A0
|
||||
0 1 0 (0x60) Read DBBOUT register
|
||||
0 1 1 (0x64) Read STATUS register
|
||||
1 0 0 (0x60) Write DBBIN!
|
||||
1 0 1 (0x64) Write DBBIN!
|
||||
|
||||
==> A0-pin simply latches into STATUS-F1-bit on host write, what the UPI can test by JF1 $xx.
|
||||
|
||||
-----------------
|
||||
Data buffers: DBB
|
||||
-----------------
|
||||
|
||||
DBBIN, DBBOUT
|
||||
|
||||
"When CS, A0 and RD are low, the contents of the DBBOUT register is placed on the three-state Data lines D0-D7 and the OBF flag is cleared."
|
||||
"When CS and WR are low, the contents of the system data bus is latched into DBBIN. Also, the IBF flag is set and an interrupt is generated, if enabled."
|
||||
|
||||
--------------------
|
||||
ST - status register
|
||||
--------------------
|
||||
|
||||
= Bus buffer register status word.
|
||||
|
||||
ST7 ST6 ST5 ST4 | F1 F0 | IBF OBF
|
||||
|
||||
ST7-4: user defined, MOV STS,A writes them, UPI doesn't care more about it.
|
||||
F0: user defined (JF0 $xx)
|
||||
F1 = A0-pin (Command/Data)
|
||||
"OBF Output Buffer Full: This flag is automatically set when the UPI-Microcomputer loads the DBBOUT register and is cleared when the master processor reads the data register."
|
||||
"IBF Input Buffer Full: This flag is set when the master processor writes a character to the DBBIN register and is cleared when the UPI INputs the data register contents to its accumulator."
|
||||
|
||||
---------
|
||||
I/O PORTS
|
||||
---------
|
||||
|
||||
2 x 8-bit: P1 and P2
|
||||
OUTL Pn,A
|
||||
IN A,Pn
|
||||
"To use a particular PORT pin as an input, a logic '1' must first be written to that pin."
|
||||
|
||||
*/
|
||||
Loading…
Reference in a new issue