forked from amberisvibin/chibi-pc09
realized the emulators were not mine, cant be in the repo
This commit is contained in:
1
emu/c++
1
emu/c++
Submodule emu/c++ deleted from e0754ceba5
@@ -1,4 +0,0 @@
|
||||
mount a transfer
|
||||
mount b disk
|
||||
mount c COBOL
|
||||
go
|
@@ -1,23 +0,0 @@
|
||||
; Program "Call" called by "Testcall"; this is assembler version;
|
||||
; compare with functionally equivalent COBOL version.
|
||||
|
||||
cseg
|
||||
|
||||
ldax b ; read first param: A = text length
|
||||
loop:
|
||||
dcr a ; count down length
|
||||
rm ; finished
|
||||
push psw
|
||||
ldax d ; next byte from second param = text
|
||||
inx d
|
||||
push d
|
||||
mov e,a
|
||||
mvi c,6 ; CP/M function code
|
||||
call 5 ; call CP/M to send character
|
||||
pop d
|
||||
pop psw
|
||||
jmp loop
|
||||
|
||||
; End of demonstration program "Call"
|
||||
|
||||
end
|
@@ -1,26 +0,0 @@
|
||||
000000******************************************************************
|
||||
000000*
|
||||
000000* Program "Call" called by "Testcall"; this is COBOL version;
|
||||
000000* compare with functionally equivalent assembler version.
|
||||
000000*
|
||||
000000******************************************************************
|
||||
000000 Working-storage section.
|
||||
000000 01 temp pic 9(2) comp.
|
||||
000000 01 text-buffer value space.
|
||||
000000 02 tbuf-table pic x occurs 80.
|
||||
000000 Linkage section.
|
||||
000000 01 mess-text.
|
||||
000000 02 mtex-table pic x occurs 80.
|
||||
000000 01 mess-size pic 9(2) comp.
|
||||
000000 Procedure division using mess-size,mess-text.
|
||||
000000 l.
|
||||
000000 move 0 to temp perform move-byte until temp = mess-size.
|
||||
000000 display text-buffer.
|
||||
000000 exit program.
|
||||
000000 move-byte.
|
||||
000000 add 1 to temp move mtex-table (temp) to tbuf-table (temp).
|
||||
000000******************************************************************
|
||||
000000*
|
||||
000000* End of demonstration program "Call"
|
||||
000000*
|
||||
000000******************************************************************
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,240 +0,0 @@
|
||||
000000 IDENTIFICATION DIVISION.
|
||||
000000******************************************************************
|
||||
000000* *
|
||||
000000* COPYRIGHT (C) 1982,1982 MICRO FOCUS LTD. *
|
||||
000000* *
|
||||
000000* MICRO FOCUS LTD. *
|
||||
000000* 58, ACACIA ROAD, *
|
||||
000000* ST. JOHNS WOOD, *
|
||||
000000* LONDON NW8 6AG. *
|
||||
000000* *
|
||||
000000* TEL. 01 722 8843/4/5/6/7 *
|
||||
000000* TELEX 28536 MICROF G *
|
||||
000000* *
|
||||
000000******************************************************************
|
||||
000000*
|
||||
000000 PROGRAM-ID. COMMAND LINE INTERPRETOR.
|
||||
000000 AUTHOR. MICRO FOCUS LTD.
|
||||
000000 INSTALLATION. MICRO FOCUS - SWINDON.
|
||||
000000 DATE-WRITTEN. 6TH DECEMBER 1982.
|
||||
000000 DATE-COMPILED. 6TH DECEMBER 1982.
|
||||
000000*
|
||||
000000 ENVIRONMENT DIVISION.
|
||||
000000 SOURCE-COMPUTER. 8080.
|
||||
000000 OBJECT-COMPUTER. 8080.
|
||||
000000 SPECIAL-NAMES. CONSOLE IS CRT.
|
||||
000000/*****************************************************************
|
||||
000000* *
|
||||
000000* DATA USED BY THE CLI TO STORE THE USER'S INSTRUCTIONS. *
|
||||
000000* *
|
||||
000000******************************************************************
|
||||
000000*
|
||||
000000 DATA DIVISION.
|
||||
000000 WORKING-STORAGE SECTION.
|
||||
000000*
|
||||
000000 01 TEMP PIC 9(2) COMP.
|
||||
000000 01 SUB1 PIC 9(2) COMP.
|
||||
000000 01 SUB2 PIC 9(2) COMP.
|
||||
000000 01 SUB2-SAV PIC 9(2) COMP.
|
||||
000000 01 TMAX PIC 9(2) COMP.
|
||||
000000 01 CHOICE PIC X.
|
||||
000000*
|
||||
000000 01 RTS-ROUTINES.
|
||||
000000 02 POKE-CLI PIC X VALUE X"91".
|
||||
000000 02 CHAIN PIC X VALUE X"84".
|
||||
000000 02 GET-CHAR PIC X VALUE X"D8".
|
||||
000000 02 SOUND-ALARM PIC X VALUE X"E5".
|
||||
000000*
|
||||
000000* DISPLAY LINES
|
||||
000000*
|
||||
000000 01 INIT-LINE.
|
||||
000000 02 INIT-LINE-1 PIC X(68) VALUE "COBOL: A(nimate) C(ompile) D(
|
||||
000000- "rive) F(orms2) Q(uit) R(un) S(witches)".
|
||||
000000 02 FILLER PIC X(4).
|
||||
000000 02 INIT-CHOICE PIC X.
|
||||
000000*
|
||||
000000 01 FILE-QUESTION-LINE.
|
||||
000000 02 FQL-1 PIC X(22) VALUE "Enter name of file to ".
|
||||
000000 02 VERB PIC X(8).
|
||||
000000*
|
||||
000000* COMMAND-LINE COMPONENTS
|
||||
000000*
|
||||
000000 01 SWITCH-AREA.
|
||||
000000 02 FILLER PIC X VALUE "(".
|
||||
000000 02 SWITCHES PIC X(40) VALUE SPACE.
|
||||
000000*
|
||||
000000 01 FILE-NAME PIC X(16).
|
||||
000000*
|
||||
000000 01 CLI-REST PIC X(80).
|
||||
000000*
|
||||
000000 01 WORK-AREA.
|
||||
000000 02 WORK-BYTE PIC 9(2) OCCURS 80 COMP.
|
||||
000000*
|
||||
000000 01 OUTPUT-CLI VALUE SPACE.
|
||||
000000 02 OUT-BYTE PIC 9(2) OCCURS 128 COMP.
|
||||
000000*
|
||||
000000 01 PROG-AREA.
|
||||
000000 02 DRIVE PIC X VALUE SPACE.
|
||||
000000 02 FILLER PIC X VALUE ":".
|
||||
000000 02 PROG-NAME PIC X(16).
|
||||
000000*
|
||||
000000/*****************************************************************
|
||||
000000* *
|
||||
000000* MAIN ENTRY TO CLI PROGRAM. IS USED BY ORDINARY ENTRY TO *
|
||||
000000* COMMAND LINE INTERPRETOR, AS WELL AS BY PROGRAMS WHICH ARE *
|
||||
000000* RETURNING CONTROL TO THE CLI FOR CONTINUATION COMMANDS. *
|
||||
000000* *
|
||||
000000******************************************************************
|
||||
000000*
|
||||
000000 PROCEDURE DIVISION.
|
||||
000000 MAIN-ENTRY.
|
||||
000000*
|
||||
000000* TEST IF SCREEN SHOULD BE CLEARED. IF "X" ON COMMAND LINE, THEN
|
||||
000000* THIS IS A SECOND OR SUBSEQUENT ENTRY, AND THE SCREEN SHOULD
|
||||
000000* NOT BE CLEARED.
|
||||
000000*
|
||||
000000 ACCEPT WORK-AREA FROM CONSOLE.
|
||||
000000 IF WORK-AREA NOT = "X"
|
||||
000000 DISPLAY SPACE.
|
||||
000000 CALL SOUND-ALARM.
|
||||
000000*
|
||||
000000 LOOP.
|
||||
000000 MOVE SPACE TO INIT-CHOICE.
|
||||
000000 DISPLAY INIT-LINE.
|
||||
000000 DISPLAY LOW-VALUE AT 0170.
|
||||
000000 CALL GET-CHAR USING CHOICE.
|
||||
000000 DISPLAY SPACE.
|
||||
000000 MOVE CHOICE TO INIT-CHOICE.
|
||||
000000 DISPLAY INIT-LINE.
|
||||
000000*
|
||||
000000 IF CHOICE = "A" OR "a"
|
||||
000000 MOVE "ANIMATE:" TO VERB
|
||||
000000 MOVE "ANIMATE.COM" TO PROG-NAME
|
||||
000000 GO TO FILE-QUESTION.
|
||||
000000 IF CHOICE = "C" OR "c"
|
||||
000000 MOVE "COMPILE:" TO VERB
|
||||
000000 MOVE "COBOL.COM" TO PROG-NAME
|
||||
000000 GO TO FILE-QUESTION.
|
||||
000000 IF CHOICE = "D" OR "d"
|
||||
000000 GO TO DRIVE-SET.
|
||||
000000 IF CHOICE = "F" OR "f"
|
||||
000000 MOVE "FORMS2.COM" TO PROG-NAME
|
||||
000000 MOVE 0 TO SUB2
|
||||
000000 GO TO LOADER.
|
||||
000000 IF CHOICE = "Q" OR "q"
|
||||
000000 GO TO EXITING.
|
||||
000000 IF CHOICE = "R" OR "r"
|
||||
000000 MOVE "RUN:" TO VERB
|
||||
000000 MOVE "RUN.COM" TO PROG-NAME
|
||||
000000 GO TO FILE-QUESTION.
|
||||
000000 IF CHOICE = "S" OR "s"
|
||||
000000 GO TO SWITCH-SET.
|
||||
000000 CALL SOUND-ALARM.
|
||||
000000 GO TO LOOP.
|
||||
000000*
|
||||
000000/*****************************************************************
|
||||
000000* *
|
||||
000000* CODE TO HANDLE FILENAME OF PROGRAM TO BE COMPILED, ANIMATED *
|
||||
000000* OR EXECUTED. *
|
||||
000000* *
|
||||
000000******************************************************************
|
||||
000000*
|
||||
000000 FILE-QUESTION.
|
||||
000000 MOVE SPACE TO FILE-NAME.
|
||||
000000 DISPLAY FILE-QUESTION-LINE AT 0201.
|
||||
000000 ACCEPT FILE-NAME AT 0232.
|
||||
000000 IF FILE-NAME = SPACES
|
||||
000000 GO TO LOOP.
|
||||
000000*
|
||||
000000 PERFORM CLEAR-LINES.
|
||||
000000 MOVE SPACE TO CLI-REST.
|
||||
000000 DISPLAY "Any further command line ?" AT 0201.
|
||||
000000 ACCEPT CLI-REST AT 0301.
|
||||
000000*
|
||||
000000 MOVE 0 TO SUB2.
|
||||
000000 IF "RUN.COM" = PROG-NAME
|
||||
000000 IF SPACE NOT = SWITCHES
|
||||
000000 MOVE SWITCH-AREA TO WORK-AREA
|
||||
000000 MOVE 41 TO TMAX
|
||||
000000 MOVE 0 TO SUB1
|
||||
000000 PERFORM TRANSFER-BUFFER
|
||||
000000 ADD 1 TO SUB2
|
||||
000000 MOVE 41 TO OUT-BYTE (SUB2).
|
||||
000000 MOVE FILE-NAME TO WORK-AREA.
|
||||
000000 MOVE 0 TO SUB1.
|
||||
000000 MOVE 16 TO TMAX.
|
||||
000000 PERFORM TRANSFER-BUFFER.
|
||||
000000 MOVE CLI-REST TO WORK-AREA.
|
||||
000000 MOVE 0 TO SUB1.
|
||||
000000 MOVE 80 TO TMAX.
|
||||
000000 PERFORM TRANSFER-BUFFER.
|
||||
000000 IF SUB2 > 80
|
||||
000000 GO TO CLI-OVF.
|
||||
000000*
|
||||
000000* COMMAND LINE NOW CREATED, CHAIN TO THE NEXT PROGRAM. THIS
|
||||
000000* IS DONE BY SETTING A COMMAND LINE FOR THE RTS TO EXECUTE.
|
||||
000000*
|
||||
000000 LOADER.
|
||||
000000 CALL POKE-CLI USING SUB2, OUTPUT-CLI.
|
||||
000000 PERFORM CLEAR-LINES.
|
||||
000000 DISPLAY "Loading ..." at 0201.
|
||||
000000 DISPLAY LOW-VALUE AT 0301.
|
||||
000000 IF DRIVE = SPACE
|
||||
000000 CALL CHAIN USING PROG-NAME
|
||||
000000 ELSE
|
||||
000000 CALL CHAIN USING PROG-AREA.
|
||||
000000*
|
||||
000000/*****************************************************************
|
||||
000000* *
|
||||
000000* SUPPORT CLI ROUTINES, USED TO MANIPULATE THE FIELDS BEFORE *
|
||||
000000* CONTROL IS TRANSFERRED TO A SUPPORT PROGRAM. *
|
||||
000000* *
|
||||
000000******************************************************************
|
||||
000000*
|
||||
000000 SWITCH-SET.
|
||||
000000 MOVE SPACE TO SWITCHES.
|
||||
000000 DISPLAY "Switches:" AT 0201.
|
||||
000000 ACCEPT SWITCHES AT 0211.
|
||||
000000 INSPECT SWITCHES REPLACING
|
||||
000000 ALL "(" BY SPACE
|
||||
000000 ALL ")" BY SPACE.
|
||||
000000 GO TO LOOP.
|
||||
000000*
|
||||
000000 DRIVE-SET.
|
||||
000000 DISPLAY "Enter Drive:" AT 0201.
|
||||
000000 ACCEPT DRIVE AT 0214.
|
||||
000000 GO TO LOOP.
|
||||
000000*
|
||||
000000 EXITING.
|
||||
000000 DISPLAY "Returning to CP/M" AT 0201.
|
||||
000000 DISPLAY LOW-VALUE AT 0301.
|
||||
000000 STOP RUN.
|
||||
000000*
|
||||
000000/*****************************************************************
|
||||
000000* *
|
||||
000000* WORK ROUTINES USED TO MANIPULATE THE SCREEN. *
|
||||
000000* *
|
||||
000000******************************************************************
|
||||
000000*
|
||||
000000 CLI-OVF.
|
||||
000000 PERFORM CLEAR-LINES.
|
||||
000000 DISPLAY "Command buffer overflow" AT 0301.
|
||||
000000 GO TO LOOP.
|
||||
000000*
|
||||
000000 CLEAR-LINES.
|
||||
000000 MOVE SPACE TO WORK-AREA.
|
||||
000000 DISPLAY WORK-AREA AT 0201.
|
||||
000000 DISPLAY WORK-AREA AT 0301.
|
||||
000000*
|
||||
000000 TRANSFER-BUFFER.
|
||||
000000 ADD 1 TO SUB1.
|
||||
000000 ADD 1 TO SUB2.
|
||||
000000 MOVE WORK-BYTE (SUB1) TO TEMP.
|
||||
000000 IF TEMP NOT = 32
|
||||
000000 MOVE SUB2 TO SUB2-SAV
|
||||
000000 MOVE TEMP TO OUT-BYTE (SUB2).
|
||||
000000 IF SUB1 < TMAX
|
||||
000000 GO TO TRANSFER-BUFFER.
|
||||
000000 MOVE SUB2-SAV TO SUB2.
|
||||
000000 ADD 1 TO SUB2.
|
||||
000000*
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,160 +0,0 @@
|
||||
Compiler error; consult Technical Support
|
||||
Illegal format : Data-name
|
||||
Illegal format : Literal, or invalid use of ALL
|
||||
Illegal format : Character
|
||||
Data-name not unique
|
||||
Too many data or procedure names declared
|
||||
Illegal character in column 7 or continuation error
|
||||
Nested COPY statement or unknown COPY file specified
|
||||
'.' missing
|
||||
Statement starts in wrong area of source line
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
'.' missing
|
||||
DIVISION missing
|
||||
SECTION missing
|
||||
IDENTIFICATION missing
|
||||
PROGRAM-ID missing
|
||||
AUTHOR missing
|
||||
INSTALLATION missing
|
||||
DATE-WRITTEN missing
|
||||
SECURITY missing
|
||||
ENVIRONMENT missing
|
||||
CONFIGURATION missing
|
||||
SOURCE-COMPUTER missing
|
||||
OBJECT-COMPUTER/SPECIAL-NAMES clause error
|
||||
OBJECT-COMPUTER missing
|
||||
Compiler error; consult Technical Support
|
||||
SPECIAL-NAMES missing
|
||||
SWITCH clause error or system name/mnemonic name error
|
||||
DECIMAL-POINT clause error
|
||||
CONSOLE clause error
|
||||
Illegal currency symbol
|
||||
'.' missing
|
||||
DIVISION missing
|
||||
SECTION missing
|
||||
INPUT-OUTPUT missing
|
||||
FILE-CONTROL missing
|
||||
ASSIGN missing
|
||||
SEQUENTIAL or RELATIVE or INDEXED missing
|
||||
ACCESS missing on indexed/relative file
|
||||
SEQUENTIAL or DYNAMIC missing or > 64 alternate keys
|
||||
Illegal ORGANIZATION/ACCESS/KEY combination
|
||||
Unrecognized phrase in SELECT clause
|
||||
RERUN clause syntax error
|
||||
SAME AREA clause syntax error
|
||||
Missing or illegal file-name
|
||||
DATA DIVISION missing
|
||||
PROCEDURE DIVISION missing or unknown statement
|
||||
Program collating sequence not defined
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
'.' missing
|
||||
DIVISION missing
|
||||
SECTION missing
|
||||
File-name not specified in SELECT stmt or invalid CD name
|
||||
RECORD SIZE integer missing or line sequential rec > 1024 bytes
|
||||
Illegal level no (01-49),01 level reqd,or level hierarachy wrong
|
||||
FD, CD or SD qualification syntax error
|
||||
WORKING-STORAGE missing
|
||||
PROCEDURE DIVISION missing or unknown statement
|
||||
Data description qualifier or '.' missing
|
||||
Incompatible PICTURE clause and qualifiers
|
||||
BLANK illegal with non-numeric data-item
|
||||
PICTURE clause too long
|
||||
VALUE with non-elementary item,wrong data-type or value truncated
|
||||
VALUE in error or illegal for PICTURE type
|
||||
Non-elementary item has FILLER/SYNC/JUST/BLANK clause
|
||||
Preceding item at this level has > 8192 bytes or 0 bytes
|
||||
REDEFINES of unequal fields or different levels
|
||||
Data storage exceeds 64K bytes
|
||||
Compiler error; consult Technical Support
|
||||
Data description qualifier inappropriate or repeated
|
||||
REDEFINES data-name not declared
|
||||
USAGE must be COMP,DISPLAY or INDEX
|
||||
SIGN must be LEADING or TRAILING
|
||||
SYNCHRONIZED must be LEFT or RIGHT
|
||||
JUSTIFIED must be RIGHT
|
||||
BLANK must be ZERO
|
||||
OCCURS must be numeric, non-zero, unsigned or DEPENDING
|
||||
VALUE must be literal, numeric literal or figurative constant
|
||||
PICTURE string has illegal precedence or illegal char
|
||||
INDEXED data-name missing or already declared
|
||||
Numeric-edited PICTURE string is too large
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Unrecognized verb
|
||||
IF....ELSE mismatch
|
||||
Operand has wrong data-type, is not declared or '.' missing
|
||||
Procedure not unique
|
||||
Procedure name same as data-name
|
||||
Name required
|
||||
Wrong combination of data-types
|
||||
Conditional statement not allowed in this context
|
||||
Malformed subscript
|
||||
ACCEPT/DISPLAY wrong or Communications syntax incorrect
|
||||
Illegal syntax used with I-O verb
|
||||
Invalid arithmetic statement
|
||||
Invalid arithmetic expression
|
||||
Compiler error; consult Technical Support
|
||||
Invalid conditional expression
|
||||
IF stmts nested too deep, or too many AFTERs in PERFORM stmt
|
||||
Incorrect structure of PROCEDURE DIVISION
|
||||
Reserved word missing or incorrectly used
|
||||
Too many subscripts in one statement (internal buffer overflow)
|
||||
Too many operands in one statement
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Inter-segment procedure name duplication
|
||||
Unterminated condition at end of source
|
||||
Operand has wrong data-type or not declared
|
||||
Procedure name undeclared
|
||||
INDEX data-name declared twice
|
||||
Bad cursor control : illegal AT clause
|
||||
KEY declaration missing or illegal
|
||||
STATUS declaration missing
|
||||
Bad STATUS record
|
||||
Undefined inter-segment reference or error in ALTERed para
|
||||
PROCEDURE DIVISION in error
|
||||
USING parameter not declared in LINKAGE SECTION
|
||||
USING parameter not level 01 or 77
|
||||
USING parameter used twice in parameter list
|
||||
FD missing
|
||||
Compiler error; consult Technical Support
|
||||
Incorrect structure of PROCEDURE DIVISION
|
||||
Compiler error; consult Technical Support
|
||||
Compiler error; consult Technical Support
|
||||
Too many operands in one statement
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,83 +0,0 @@
|
||||
IDENTIFICATION DIVISION.
|
||||
PROGRAM-ID. PI-CALC.
|
||||
AUTHOR. PF/TR.
|
||||
*
|
||||
ENVIRONMENT DIVISION.
|
||||
CONFIGURATION SECTION.
|
||||
OBJECT-COMPUTER. MDS-800.
|
||||
SPECIAL-NAMES. CONSOLE IS CRT.
|
||||
*
|
||||
DATA DIVISION.
|
||||
WORKING-STORAGE SECTION.
|
||||
*
|
||||
01 SCREEN PIC X(1920).
|
||||
*
|
||||
01 DI-1 REDEFINES SCREEN.
|
||||
02 FILLER PIC X(160).
|
||||
02 DI-TX1 PIC X(160).
|
||||
02 DI-TX2 PIC X(13).
|
||||
02 DI-TERM PIC X(15).
|
||||
02 FILLER PIC X(136).
|
||||
02 DI-TX3 PIC X(6).
|
||||
02 DI-PI PIC X(15).
|
||||
02 FILLER PIC X(1415).
|
||||
*
|
||||
01 DI-2 REDEFINES SCREEN.
|
||||
02 FILLER PIC X(333).
|
||||
02 DI-TERM2 PIC X(15).
|
||||
02 FILLER PIC X(142).
|
||||
02 DI-PI2 PIC X(15).
|
||||
02 FILLER PIC X(1415).
|
||||
*
|
||||
01 WORK-AREA.
|
||||
02 PI PIC S9V9(14).
|
||||
02 TERM PIC S9V9(14).
|
||||
02 W PIC S9V9(14).
|
||||
02 N PIC 9999.
|
||||
02 N1 PIC 9999.
|
||||
02 N2 PIC 9999.
|
||||
02 ED PIC -9.9(12).
|
||||
*
|
||||
01 CONSTANTS.
|
||||
02 TX1 PIC X(17) VALUE "CALCULATION OF PI".
|
||||
02 TX2 PIC X(12) VALUE "NEXT TERM IS".
|
||||
02 TX3 PIC X(5) VALUE "PI IS".
|
||||
*
|
||||
PROCEDURE DIVISION.
|
||||
LA-START.
|
||||
DISPLAY SPACE.
|
||||
MOVE SPACE TO SCREEN.
|
||||
MOVE TX1 TO DI-TX1.
|
||||
MOVE TX2 TO DI-TX2.
|
||||
MOVE TX3 TO DI-TX3.
|
||||
MOVE 0.5 TO ED.
|
||||
MOVE ED TO DI-TERM.
|
||||
MOVE 3 TO ED.
|
||||
MOVE ED TO DI-PI.
|
||||
DISPLAY DI-1.
|
||||
MOVE 0.5 TO PI.
|
||||
MOVE 0.5 TO TERM.
|
||||
MOVE 3 TO N.
|
||||
LOOP.
|
||||
MOVE N TO N2.
|
||||
SUBTRACT 2 FROM N2.
|
||||
MULTIPLY N2 BY N2.
|
||||
MULTIPLY N2 BY TERM.
|
||||
MOVE N TO N1.
|
||||
SUBTRACT 1 FROM N1.
|
||||
MULTIPLY N BY N1.
|
||||
MULTIPLY 4 BY N1.
|
||||
DIVIDE N1 INTO TERM.
|
||||
IF TERM < 0.0000000000001 THEN GO TO HALT.
|
||||
ADD TERM TO PI.
|
||||
MOVE PI TO W.
|
||||
MULTIPLY 6 BY W.
|
||||
MOVE W TO ED.
|
||||
MOVE ED TO DI-PI2.
|
||||
MOVE TERM TO ED.
|
||||
MOVE ED TO DI-TERM2.
|
||||
DISPLAY DI-2.
|
||||
ADD 2 TO N.
|
||||
IF N < 100 GO TO LOOP.
|
||||
HALT.
|
||||
STOP RUN.
|
Binary file not shown.
@@ -1,59 +0,0 @@
|
||||
000010 IDENTIFICATION DIVISION.
|
||||
000020 PROGRAM-ID. STOCK-FILE-SET-UP.
|
||||
000030 AUTHOR. MICRO FOCUS LTD.
|
||||
000040 ENVIRONMENT DIVISION.
|
||||
000050 CONFIGURATION SECTION.
|
||||
000060 SOURCE-COMPUTER. MDS-800.
|
||||
000070 OBJECT-COMPUTER. MDS-800.
|
||||
000075 SPECIAL-NAMES. CONSOLE IS CRT.
|
||||
000080 INPUT-OUTPUT SECTION.
|
||||
000090 FILE-CONTROL.
|
||||
000100 SELECT STOCK-FILE ASSIGN "STOCK.IT"
|
||||
000110 ORGANIZATION INDEXED
|
||||
000120 ACCESS DYNAMIC
|
||||
000130 RECORD KEY STOCK-CODE.
|
||||
000140 DATA DIVISION.
|
||||
000150 FILE SECTION.
|
||||
000160 FD STOCK-FILE; RECORD 32.
|
||||
000170 01 STOCK-ITEM.
|
||||
000180 02 STOCK-CODE PIC X(4).
|
||||
000190 02 PRODUCT-DESC PIC X(24).
|
||||
000200 02 UNIT-SIZE PIC 9(4).
|
||||
000210 WORKING-STORAGE SECTION.
|
||||
000220 01 SCREEN-HEADINGS.
|
||||
000230 02 ASK-CODE PIC X(21) VALUE "STOCK CODE < >".
|
||||
000240 02 FILLER PIC X(59).
|
||||
000250 02 ASK-DESC PIC X(16) VALUE "DESCRIPTION <".
|
||||
000260 02 SI-DESC PIC X(25) VALUE " >".
|
||||
000270 02 FILLER PIC X(39).
|
||||
000280 02 ASK-SIZE PIC X(21) VALUE "UNIT SIZE < >".
|
||||
000290 01 ENTER-IT REDEFINES SCREEN-HEADINGS.
|
||||
000300 02 FILLER PIC X(16).
|
||||
000310 02 CRT-STOCK-CODE PIC X(4).
|
||||
000320 02 FILLER PIC X(76).
|
||||
000330 02 CRT-PROD-DESC PIC X(24).
|
||||
000340 02 FILLER PIC X(56).
|
||||
000350 02 CRT-UNIT-SIZE PIC 9(4).
|
||||
000360 02 FILLER PIC X.
|
||||
000370 PROCEDURE DIVISION.
|
||||
000380 SR1.
|
||||
000390 DISPLAY SPACE.
|
||||
000400 OPEN I-O STOCK-FILE.
|
||||
000410 DISPLAY SCREEN-HEADINGS.
|
||||
000420 NORMAL-INPUT.
|
||||
000430 MOVE SPACE TO ENTER-IT.
|
||||
000440 DISPLAY ENTER-IT.
|
||||
000450 CORRECT-ERROR.
|
||||
000460 ACCEPT ENTER-IT.
|
||||
000470 IF CRT-STOCK-CODE = SPACE GO TO END-IT.
|
||||
000480 IF CRT-UNIT-SIZE NOT NUMERIC GO TO CORRECT-ERROR.
|
||||
000490 MOVE CRT-PROD-DESC TO PRODUCT-DESC.
|
||||
000500 MOVE CRT-UNIT-SIZE TO UNIT-SIZE.
|
||||
000510 MOVE CRT-STOCK-CODE TO STOCK-CODE.
|
||||
000520 WRITE STOCK-ITEM; INVALID GO TO CORRECT-ERROR.
|
||||
000530 GO TO NORMAL-INPUT.
|
||||
000540 END-IT.
|
||||
000550 CLOSE STOCK-FILE.
|
||||
000560 DISPLAY SPACE.
|
||||
000570 DISPLAY "END OF PROGRAM".
|
||||
000580 STOP RUN.
|
@@ -1,119 +0,0 @@
|
||||
IDENTIFICATION DIVISION.
|
||||
PROGRAM-ID. GOODS-IN.
|
||||
AUTHOR. MICRO FOCUS LTD.
|
||||
ENVIRONMENT DIVISION.
|
||||
CONFIGURATION SECTION.
|
||||
SOURCE-COMPUTER. MDS-800.
|
||||
OBJECT-COMPUTER. MDS-800.
|
||||
SPECIAL-NAMES. CONSOLE IS CRT.
|
||||
INPUT-OUTPUT SECTION.
|
||||
FILE-CONTROL.
|
||||
SELECT STOCK-FILE ASSIGN "STOCK.IT"
|
||||
ORGANIZATION INDEXED
|
||||
ACCESS DYNAMIC
|
||||
RECORD KEY STOCK-CODE.
|
||||
SELECT TRANS-FILE
|
||||
ASSIGN "STOCK.TRS"
|
||||
ORGANIZATION SEQUENTIAL.
|
||||
/
|
||||
DATA DIVISION.
|
||||
FILE SECTION.
|
||||
FD STOCK-FILE; RECORD 32.
|
||||
01 STOCK-ITEM.
|
||||
02 STOCK-CODE PIC X(4).
|
||||
02 STOCK-DESCRIPT PIC X(24).
|
||||
02 UNIT-SIZE PIC 9(4).
|
||||
FD TRANS-FILE; RECORD 30.
|
||||
01 TRANS-RECORD.
|
||||
02 TRAN-NO PIC 9(4).
|
||||
02 TF-STOCK-CODE PIC X(4).
|
||||
02 TF-QUANTITY PIC 9(8).
|
||||
02 TF-ORDER-NO PIC X(6).
|
||||
02 TF-DATE PIC X(8).
|
||||
WORKING-STORAGE SECTION.
|
||||
01 STOCK-INWARD-FORM.
|
||||
02 PRG-TITLE PIC X(20) VALUE " GOODS INWARD".
|
||||
02 FILLER PIC X(140).
|
||||
02 CODE-HDNG PIC X(23) VALUE "STOCK CODE < >".
|
||||
02 FILLER PIC X(57).
|
||||
02 ORDER-NO-HDNG PIC X(23) VALUE "ORDER NO < >".
|
||||
02 FILLER PIC X(57).
|
||||
02 DATE-HDNG PIC X(24) VALUE "DELIVERY DATE MM/DD/YY".
|
||||
02 FILLER PIC X(56).
|
||||
02 UNITS-HDNG PIC X(23) VALUE "NO OF UNITS < >".
|
||||
01 STOCK-RECEIPT REDEFINES STOCK-INWARD-FORM.
|
||||
02 FILLER PIC X(178).
|
||||
02 SR-STOCK-CODE PIC X(4).
|
||||
02 FILLER PIC X(74).
|
||||
02 SR-ORDER-NO PIC X(6).
|
||||
02 FILLER PIC X(73).
|
||||
02 SR-DATE.
|
||||
04 SR-MM PIC 99.
|
||||
04 FILLER PIC X.
|
||||
04 SR-DD PIC 99.
|
||||
04 FILLER PIC X.
|
||||
04 SR-YY PIC 99.
|
||||
02 FILLER PIC X(75).
|
||||
02 SR-NO-OF-UNITS PIC 9(4).
|
||||
01 CONFIRM-MSG REDEFINES STOCK-INWARD-FORM.
|
||||
02 FILLER PIC X(184).
|
||||
02 CM-STOCK-DESCRIPT PIC X(24).
|
||||
02 FILLER PIC X(352).
|
||||
02 UNIT-SIZE-HDNG PIC X(18).
|
||||
02 CM-UNIT-SIZE PIC 9(4).
|
||||
02 FILLER PIC X(58).
|
||||
02 QUANTITY-HDNG PIC X(14).
|
||||
02 CM-QUANTITY PIC 9(8).
|
||||
02 FILLER PIC X(58).
|
||||
02 OK-HDNG PIC X(3).
|
||||
02 CM-Y-OR-N PIC X.
|
||||
/
|
||||
PROCEDURE DIVISION.
|
||||
START-PROC.
|
||||
OPEN I-O STOCK-FILE.
|
||||
OPEN OUTPUT TRANS-FILE.
|
||||
DISPLAY SPACE.
|
||||
MOVE 0 TO TRAN-NO.
|
||||
DISPLAY STOCK-INWARD-FORM.
|
||||
GET-INPUT.
|
||||
ACCEPT STOCK-RECEIPT.
|
||||
IF SR-STOCK-CODE = SPACE GO TO END-IT.
|
||||
IF SR-NO-OF-UNITS NOT NUMERIC GO TO INVALID-ENTRY.
|
||||
MOVE SR-STOCK-CODE TO STOCK-CODE.
|
||||
READ STOCK-FILE; INVALID GO TO INVALID-CODE.
|
||||
*VALID ENTRY, CALCULATE AND DISPLAY TOTAL QUANTITY IN TO CONFIRM
|
||||
MOVE STOCK-DESCRIPT TO CM-STOCK-DESCRIPT.
|
||||
MOVE "UNIT SIZE" TO UNIT-SIZE-HDNG.
|
||||
MOVE UNIT-SIZE TO CM-UNIT-SIZE.
|
||||
MOVE "QUANTITY IN" TO QUANTITY-HDNG.
|
||||
MOVE UNIT-SIZE TO TF-QUANTITY.
|
||||
MULTIPLY SR-NO-OF-UNITS BY TF-QUANTITY.
|
||||
MOVE TF-QUANTITY TO CM-QUANTITY.
|
||||
MOVE "OK?" TO OK-HDNG.
|
||||
DISPLAY CONFIRM-MSG.
|
||||
ACCEPT CM-Y-OR-N AT 1004.
|
||||
IF CM-Y-OR-N = "Y" PERFORM WRITE-TRANS.
|
||||
*CLEAR INPUT DATA ON SCREEN
|
||||
MOVE SPACE TO CONFIRM-MSG.
|
||||
MOVE "MM/DD/YY" TO SR-DATE.
|
||||
DISPLAY STOCK-RECEIPT.
|
||||
DISPLAY CONFIRM-MSG.
|
||||
GO TO GET-INPUT.
|
||||
WRITE-TRANS.
|
||||
ADD 1 TO TRAN-NO.
|
||||
MOVE STOCK-CODE TO TF-STOCK-CODE.
|
||||
MOVE SR-ORDER-NO TO TF-ORDER-NO.
|
||||
MOVE GET-INPUT TO TF-DATE.
|
||||
WRITE TRANS-RECORD.
|
||||
INVALID-ENTRY.
|
||||
DISPLAY "NON-NUMERIC NO OF UNITS" AT 0325.
|
||||
GO TO GET-INPUT.
|
||||
INVALID-CODE.
|
||||
DISPLAY "INVALID CODE " AT 0325.
|
||||
GO TO GET-INPUT.
|
||||
END-IT.
|
||||
CLOSE STOCK-FILE.
|
||||
CLOSE TRANS-FILE.
|
||||
DISPLAY SPACE.
|
||||
DISPLAY "END OF PROGRAM".
|
||||
STOP RUN.
|
@@ -1,19 +0,0 @@
|
||||
000000******************************************************************
|
||||
000000*
|
||||
000000* Program "Testcall" to demonstrate L/II COBOL calling mechanism
|
||||
000000*
|
||||
000000******************************************************************
|
||||
000000 Working-storage section.
|
||||
000000 01 progname pic x(4).
|
||||
000000 01 message-size pic 9(2) comp value 60.
|
||||
000000 01 message-text pic x(60) value
|
||||
000000 "This message is sent via a called program to the screen.".
|
||||
000000 Procedure division.
|
||||
000000 move "call" to progname.
|
||||
000000 call progname using message-size,message-text
|
||||
000000 overflow display "call overflowed".
|
||||
000000******************************************************************
|
||||
000000*
|
||||
000000* End of demonstration program "Testcall"
|
||||
000000*
|
||||
000000******************************************************************
|
Binary file not shown.
BIN
emu/yaze/disk
BIN
emu/yaze/disk
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,2 +0,0 @@
|
||||
#!/bin/bash
|
||||
yaze -v
|
@@ -1,3 +0,0 @@
|
||||
#!/bin/bash
|
||||
cd /usr/local/src/yaze-1.14/
|
||||
yaze -v
|
@@ -1,6 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
rm -f disks/drive[ab].cpm
|
||||
ln disks/library/cpm2-1.dsk disks/drivea.cpm
|
||||
ln disks/library/cpm2-2.dsk disks/driveb.cpm
|
||||
cpmsim
|
@@ -1,6 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
rm -f disks/drive[ab].cpm
|
||||
ln disks/library/cpm3-1.dsk disks/drivea.cpm
|
||||
ln disks/library/cpm3-2.dsk disks/driveb.cpm
|
||||
cpmsim
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,6 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
rm -f disks/drive[ab].cpm
|
||||
ln disks/library/mpm-1.dsk disks/drivea.cpm
|
||||
ln disks/library/mpm-2.dsk disks/driveb.cpm
|
||||
cpmsim -h
|
@@ -1,32 +0,0 @@
|
||||
CFLAGS= -O -s
|
||||
|
||||
all: format putsys bin2hex send receive bios.bin boot.bin
|
||||
@echo "done"
|
||||
|
||||
format: format.c
|
||||
cc $(CFLAGS) -o format format.c
|
||||
cp format ..
|
||||
|
||||
putsys: putsys.c
|
||||
cc $(CFLAGS) -o putsys putsys.c
|
||||
|
||||
bin2hex: bin2hex.c
|
||||
cc $(CFLAGS) -o bin2hex bin2hex.c
|
||||
cp bin2hex ..
|
||||
|
||||
send: send.c
|
||||
cc $(CFLAGS) -o send send.c
|
||||
cp send ..
|
||||
|
||||
receive: receive.c
|
||||
cc $(CFLAGS) -o receive receive.c
|
||||
cp receive ..
|
||||
|
||||
bios.bin: bios.asm
|
||||
z80asm -vl -sn -x bios.asm
|
||||
|
||||
boot.bin: boot.asm
|
||||
z80asm -vl -sn boot.asm
|
||||
|
||||
clean:
|
||||
rm -f *.lis bios.bin boot.bin format putsys bin2hex receive send
|
@@ -1,161 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
void help(char *name)
|
||||
{
|
||||
printf("%s - BINARY to Intel HEX file convertor version 1.00\n"\
|
||||
"(c)BCL Vysoke Myto 2001 (benedikt@lphard.cz)\n\n",name);
|
||||
printf("Usage: %s [-option] binfile hexfile\n"\
|
||||
" -l Bytes to read from binary file\n"\
|
||||
" -i Binary file starting offset\n"\
|
||||
" -o Output file offset (where HEX data starts)\n"\
|
||||
" -t Exclude EOF record\n"\
|
||||
" -a Append to end of existing HEX file\n"\
|
||||
" -q Quiet mode (no statistics are printed)\n", name);
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])/*Main routine*/
|
||||
{
|
||||
char *ifile = NULL;
|
||||
char *ofile = NULL;
|
||||
char c;
|
||||
FILE *inp, *outp;
|
||||
int ch,csum;
|
||||
int ofsa = 0;
|
||||
int cnt = 0;
|
||||
struct stat statbuf;
|
||||
long int foffset = 0;
|
||||
long int fsize = 0;
|
||||
long int fsub;
|
||||
long int fpoint = 0;
|
||||
long int adrs = 0;
|
||||
unsigned char quiet = 0;
|
||||
unsigned char eofrec = 0;
|
||||
unsigned char append = 0;
|
||||
|
||||
opterr = 0; //print error message if unknown option
|
||||
|
||||
while ((c = getopt (argc, argv, "l:i:o:taqv")) != -1)
|
||||
switch (c) {
|
||||
case 'l':
|
||||
fsize = atol(optarg);
|
||||
break;
|
||||
case 'i':
|
||||
foffset = atol(optarg);
|
||||
break;
|
||||
case 'o':
|
||||
adrs = atol(optarg);
|
||||
break;
|
||||
case 't':
|
||||
eofrec = 1;
|
||||
break;
|
||||
case 'a':
|
||||
append = 1;
|
||||
break;
|
||||
case 'q':
|
||||
quiet = 1;
|
||||
break;
|
||||
case 'v':
|
||||
printf("%s - BINARY to Intel HEX file convertor version 1.00\n"\
|
||||
"(c)BCL Vysoke Myto 2001 (benedikt@lphard.cz)\n",argv[0]);
|
||||
return 0;
|
||||
case '?':
|
||||
help (argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((argc - optind) != 2) {
|
||||
printf("ERROR: Missing input/output file.\n");
|
||||
help(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
ifile = argv[optind];
|
||||
ofile = argv[optind+1];
|
||||
|
||||
/*Open file check*/
|
||||
if((inp = fopen(ifile, "rb")) == NULL){
|
||||
printf("ERROR: Cannot open input file.\n");
|
||||
return 1;
|
||||
}
|
||||
fseek (inp, foffset, SEEK_SET);
|
||||
|
||||
if (append == 0) {
|
||||
if((outp = fopen(ofile, "wt")) == NULL){
|
||||
printf("ERROR: Cannot open output file.\n");
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if((outp = fopen(ofile, "at")) == NULL){
|
||||
printf("ERROR: Cannot re-open output file.\n");
|
||||
return 1;
|
||||
}
|
||||
fseek (outp, 0, SEEK_END);
|
||||
}
|
||||
|
||||
fstat(fileno(inp), &statbuf);
|
||||
if (quiet == 0) printf("Input file size=%ld\n",statbuf.st_size);
|
||||
if (foffset > statbuf.st_size) {
|
||||
printf("ERROR: Input offset > input file length\n");
|
||||
}
|
||||
if ((fsize == 0) || (fsize > (statbuf.st_size - foffset)))
|
||||
fsize = statbuf.st_size - foffset;
|
||||
|
||||
// fprintf(outp,":020000020000FC\n");/*Start Header*/
|
||||
fsub = fsize - fpoint;
|
||||
if (fsub > 0x20) {
|
||||
fprintf(outp,":20%04X00",adrs);/*Hex line Header*/
|
||||
csum = 0x20 + (adrs>>8) + (adrs & 0xFF);
|
||||
adrs += 0x20;
|
||||
}
|
||||
else {
|
||||
fprintf(outp, ":%02X%04X00", fsub,adrs);/*Hex line Header*/
|
||||
csum = fsub + (adrs>>8) + (adrs & 0xFF);
|
||||
adrs += fsub;
|
||||
}
|
||||
while (fsub > 0){
|
||||
ch = fgetc(inp);
|
||||
fprintf(outp,"%02X",ch);/*Put data*/
|
||||
cnt++; fpoint++;
|
||||
fsub = fsize - fpoint;
|
||||
csum = ch + csum;
|
||||
if((fsub == 0)||(cnt == 0x20)){
|
||||
cnt = 0; csum = 0xFF & (~csum + 1);
|
||||
fprintf(outp,"%02X\n",csum);/*Put checksum*/
|
||||
if(fsub == 0) break;
|
||||
if(adrs > 0xFFFF){
|
||||
ofsa = 0x1000 + ofsa;
|
||||
adrs = 0;
|
||||
fprintf(outp,":02000002%04X",ofsa);/*Change offset address*/
|
||||
csum = 0x02 + 0x02 + (ofsa>>8) + (ofsa & 0xFF);
|
||||
csum = 0xFF & (~csum + 1);
|
||||
fprintf(outp,"%02X\n", csum);
|
||||
}
|
||||
adrs = 0xFFFF & adrs;
|
||||
if (fsub > 0x20) {
|
||||
fprintf(outp,":20%04X00",adrs);/*Next Hex line Header*/
|
||||
csum = 0x20 + (adrs>>8) + (adrs & 0xFF);
|
||||
adrs += 0x20;
|
||||
}
|
||||
else {
|
||||
if(fsub > 0){
|
||||
fprintf(outp, ":%02X%04X00", fsub,adrs);/*Next Hex line Header*/
|
||||
csum = fsub + (adrs>>8) + (adrs & 0xFF);
|
||||
adrs += fsub;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (eofrec == 0) fprintf(outp,":00000001FF\n");/*End footer*/
|
||||
fflush (outp);
|
||||
|
||||
fstat(fileno(outp), &statbuf);
|
||||
if (quiet == 0) printf("Output file size=%ld\n",statbuf.st_size);
|
||||
|
||||
fclose(inp);
|
||||
fclose(outp);
|
||||
return 0;
|
||||
}
|
@@ -1,375 +0,0 @@
|
||||
; CBIOS for Z80-Simulator
|
||||
;
|
||||
; Copyright (C) 1988-2006 by Udo Munk
|
||||
;
|
||||
MSIZE EQU 64 ;cp/m version memory size in kilobytes
|
||||
;
|
||||
; "bias" is address offset from 3400H for memory systems
|
||||
; than 16K (referred to as "b" throughout the text).
|
||||
;
|
||||
BIAS EQU (MSIZE-20)*1024
|
||||
CCP EQU 3400H+BIAS ;base of ccp
|
||||
BDOS EQU CCP+806H ;base of bdos
|
||||
BIOS EQU CCP+1600H ;base of bios
|
||||
CDISK EQU 0004H ;current disk number 0=A,...,15=P
|
||||
IOBYTE EQU 0003H ;intel i/o byte
|
||||
;
|
||||
; I/O ports
|
||||
;
|
||||
CONSTA EQU 0 ;console status port
|
||||
CONDAT EQU 1 ;console data port
|
||||
PRTSTA EQU 2 ;printer status port
|
||||
PRTDAT EQU 3 ;printer data port
|
||||
AUXDAT EQU 5 ;auxiliary data port
|
||||
FDCD EQU 10 ;fdc-port: # of drive
|
||||
FDCT EQU 11 ;fdc-port: # of track
|
||||
FDCS EQU 12 ;fdc-port: # of sector
|
||||
FDCOP EQU 13 ;fdc-port: command
|
||||
FDCST EQU 14 ;fdc-port: status
|
||||
DMAL EQU 15 ;dma-port: dma address low
|
||||
DMAH EQU 16 ;dma-port: dma address high
|
||||
;
|
||||
ORG BIOS ;origin of this program
|
||||
NSECTS EQU (BIOS-CCP)/128 ;warm start sector count
|
||||
;
|
||||
; jump vector for individual subroutines
|
||||
;
|
||||
JP BOOT ;cold start
|
||||
WBOOTE: JP WBOOT ;warm start
|
||||
JP CONST ;console status
|
||||
JP CONIN ;console character in
|
||||
JP CONOUT ;console character out
|
||||
JP LIST ;list character out
|
||||
JP PUNCH ;punch character out
|
||||
JP READER ;reader character out
|
||||
JP HOME ;move head to home position
|
||||
JP SELDSK ;select disk
|
||||
JP SETTRK ;set track number
|
||||
JP SETSEC ;set sector number
|
||||
JP SETDMA ;set dma address
|
||||
JP READ ;read disk
|
||||
JP WRITE ;write disk
|
||||
JP LISTST ;return list status
|
||||
JP SECTRAN ;sector translate
|
||||
;
|
||||
; fixed data tables for four-drive standard
|
||||
; IBM-compatible 8" disks
|
||||
;
|
||||
; disk parameter header for disk 00
|
||||
DPBASE: DEFW TRANS,0000H
|
||||
DEFW 0000H,0000H
|
||||
DEFW DIRBF,DPBLK
|
||||
DEFW CHK00,ALL00
|
||||
; disk parameter header for disk 01
|
||||
DEFW TRANS,0000H
|
||||
DEFW 0000H,0000H
|
||||
DEFW DIRBF,DPBLK
|
||||
DEFW CHK01,ALL01
|
||||
; disk parameter header for disk 02
|
||||
DEFW TRANS,0000H
|
||||
DEFW 0000H,0000H
|
||||
DEFW DIRBF,DPBLK
|
||||
DEFW CHK02,ALL02
|
||||
; disk parameter header for disk 03
|
||||
DEFW TRANS,0000H
|
||||
DEFW 0000H,0000H
|
||||
DEFW DIRBF,DPBLK
|
||||
DEFW CHK03,ALL03
|
||||
;
|
||||
; sector translate vector for the IBM 8" disks
|
||||
;
|
||||
TRANS: DEFB 1,7,13,19 ;sectors 1,2,3,4
|
||||
DEFB 25,5,11,17 ;sectors 5,6,7,8
|
||||
DEFB 23,3,9,15 ;sectors 9,10,11,12
|
||||
DEFB 21,2,8,14 ;sectors 13,14,15,16
|
||||
DEFB 20,26,6,12 ;sectors 17,18,19,20
|
||||
DEFB 18,24,4,10 ;sectors 21,22,23,24
|
||||
DEFB 16,22 ;sectors 25,26
|
||||
;
|
||||
; disk parameter block, common to all IBM 8" disks
|
||||
;
|
||||
DPBLK: DEFW 26 ;sectors per track
|
||||
DEFB 3 ;block shift factor
|
||||
DEFB 7 ;block mask
|
||||
DEFB 0 ;extent mask
|
||||
DEFW 242 ;disk size-1
|
||||
DEFW 63 ;directory max
|
||||
DEFB 192 ;alloc 0
|
||||
DEFB 0 ;alloc 1
|
||||
DEFW 16 ;check size
|
||||
DEFW 2 ;track offset
|
||||
;
|
||||
; fixed data tables for 4MB harddisk
|
||||
;
|
||||
; disk parameter header
|
||||
HDBASE: DEFW HDTRA,0000H
|
||||
DEFW 0000H,0000H
|
||||
DEFW DIRBF,HDBLK
|
||||
DEFW CHKHD,ALLHD
|
||||
;
|
||||
; sector translate vector for the hardisk
|
||||
;
|
||||
HDTRA: DEFB 1,2,3,4,5,6,7,8,9,10
|
||||
DEFB 11,12,13,14,15,16,17,18,19,20
|
||||
DEFB 21,22,23,24,25,26,27,28,29,30
|
||||
DEFB 31,32,33,34,35,36,37,38,39,40
|
||||
DEFB 41,42,43,44,45,46,47,48,49,50
|
||||
DEFB 51,52,53,54,55,56,57,58,59,60
|
||||
DEFB 61,62,63,64,65,66,67,68,69,70
|
||||
DEFB 71,72,73,74,75,76,77,78,79,80
|
||||
DEFB 81,82,83,84,85,86,87,88,89,90
|
||||
DEFB 91,92,93,94,95,96,97,98,99,100
|
||||
DEFB 101,102,103,104,105,106,107,108,109,110
|
||||
DEFB 111,112,113,114,115,116,117,118,119,120
|
||||
DEFB 121,122,123,124,125,126,127,128
|
||||
;
|
||||
; disk parameter block for harddisk
|
||||
;
|
||||
HDBLK: DEFW 128 ;sectors per track
|
||||
DEFB 4 ;block shift factor
|
||||
DEFB 15 ;block mask
|
||||
DEFB 0 ;extent mask
|
||||
DEFW 2039 ;disk size-1
|
||||
DEFW 1023 ;directory max
|
||||
DEFB 255 ;alloc 0
|
||||
DEFB 255 ;alloc 1
|
||||
DEFW 0 ;check size
|
||||
DEFW 0 ;track offset
|
||||
;
|
||||
; signon message
|
||||
;
|
||||
SIGNON: DEFM '64K CP/M Vers. 2.2 (CBIOS V1.1 for Z80SIM, '
|
||||
DEFM 'Copyright 1988-2006 by Udo Munk)'
|
||||
DEFB 13,10,0
|
||||
;
|
||||
; end of fixed tables
|
||||
;
|
||||
; individual subroutines to perform each function
|
||||
; simplest case is to just perform parameter initialization
|
||||
;
|
||||
BOOT: LD SP,80H ;use space below buffer for stack
|
||||
LD HL,SIGNON ;print message
|
||||
BOOTL: LD A,(HL)
|
||||
OR A
|
||||
JP Z,BOOTC
|
||||
LD C,A
|
||||
CALL CONOUT
|
||||
INC HL
|
||||
JP BOOTL
|
||||
BOOTC: XOR A ;zero in the accum
|
||||
LD (IOBYTE),A ;clear the iobyte
|
||||
LD (CDISK),A ;select disk zero
|
||||
JP GOCPM ;initialize and go to cp/m
|
||||
;
|
||||
; simplest case is to read the disk until all sectors loaded
|
||||
;
|
||||
WBOOT: LD SP,80H ;use space below buffer for stack
|
||||
LD C,0 ;select disk 0
|
||||
CALL SELDSK
|
||||
CALL HOME ;go to track 00
|
||||
;
|
||||
LD B,NSECTS ;b counts # of sectors to load
|
||||
LD C,0 ;c has the current track number
|
||||
LD D,2 ;d has the next sector to read
|
||||
; note that we begin by reading track 0, sector 2 since sector 1
|
||||
; contains the cold start loader, which is skipped in a warm start
|
||||
LD HL,CCP ;base of cp/m (initial load point)
|
||||
LOAD1: ;load one more sector
|
||||
PUSH BC ;save sector count, current track
|
||||
PUSH DE ;save next sector to read
|
||||
PUSH HL ;save dma address
|
||||
LD C,D ;get sector address to register c
|
||||
CALL SETSEC ;set sector address from register c
|
||||
POP BC ;recall dma address to b,c
|
||||
PUSH BC ;replace on stack for later recall
|
||||
CALL SETDMA ;set dma address from b,c
|
||||
; drive set to 0, track set, sector set, dma address set
|
||||
CALL READ
|
||||
CP 00H ;any errors?
|
||||
JP NZ,WBOOT ;retry the entire boot if an error occurs
|
||||
; no error, move to next sector
|
||||
POP HL ;recall dma address
|
||||
LD DE,128 ;dma=dma+128
|
||||
ADD HL,DE ;new dma address is in h,l
|
||||
POP DE ;recall sector address
|
||||
POP BC ;recall number of sectors remaining, and current trk
|
||||
DEC B ;sectors=sectors-1
|
||||
JP Z,GOCPM ;transfer to cp/m if all have been loaded
|
||||
; more sectors remain to load, check for track change
|
||||
INC D
|
||||
LD A,D ;sector=27?, if so, change tracks
|
||||
CP 27
|
||||
JP C,LOAD1 ;carry generated if sector<27
|
||||
; end of current track, go to next track
|
||||
LD D,1 ;begin with first sector of next track
|
||||
INC C ;track=track+1
|
||||
; save register state, and change tracks
|
||||
CALL SETTRK ;track address set from register c
|
||||
JP LOAD1 ;for another sector
|
||||
; end of load operation, set parameters and go to cp/m
|
||||
GOCPM:
|
||||
LD A,0C3H ;c3 is a jmp instruction
|
||||
LD (0),A ;for jmp to wboot
|
||||
LD HL,WBOOTE ;wboot entry point
|
||||
LD (1),HL ;set address field for jmp at 0
|
||||
;
|
||||
LD (5),A ;for jmp to bdos
|
||||
LD HL,BDOS ;bdos entry point
|
||||
LD (6),HL ;address field of jump at 5 to bdos
|
||||
;
|
||||
LD BC,80H ;default dma address is 80h
|
||||
CALL SETDMA
|
||||
;
|
||||
EI ;enable the interrupt system
|
||||
LD A,(CDISK) ;get current disk number
|
||||
LD C,A ;send to the ccp
|
||||
JP CCP ;go to cp/m for further processing
|
||||
;
|
||||
;
|
||||
; simple i/o handlers
|
||||
;
|
||||
; console status, return 0ffh if character ready, 00h if not
|
||||
;
|
||||
CONST: IN A,(CONSTA) ;get console status
|
||||
RET
|
||||
;
|
||||
; console character into register a
|
||||
;
|
||||
CONIN: IN A,(CONDAT) ;get character from console
|
||||
RET
|
||||
;
|
||||
; console character output from register c
|
||||
;
|
||||
CONOUT: LD A,C ;get to accumulator
|
||||
OUT (CONDAT),A ;send character to console
|
||||
RET
|
||||
;
|
||||
; list character from register c
|
||||
;
|
||||
LIST: LD A,C ;character to register a
|
||||
OUT (PRTDAT),A
|
||||
RET
|
||||
;
|
||||
; return list status (0 if not ready, 0xff if ready)
|
||||
;
|
||||
LISTST: IN A,(PRTSTA)
|
||||
RET
|
||||
;
|
||||
; punch character from register c
|
||||
;
|
||||
PUNCH: LD A,C ;character to register a
|
||||
OUT (AUXDAT),A
|
||||
RET
|
||||
;
|
||||
; read character into register a from reader device
|
||||
;
|
||||
READER: IN A,(AUXDAT)
|
||||
RET
|
||||
;
|
||||
;
|
||||
; i/o drivers for the disk follow
|
||||
;
|
||||
; move to the track 00 position of current drive
|
||||
; translate this call into a settrk call with parameter 00
|
||||
;
|
||||
HOME: LD C,0 ;select track 0
|
||||
JP SETTRK ;we will move to 00 on first read/write
|
||||
;
|
||||
; select disk given by register C
|
||||
;
|
||||
SELDSK: LD HL,0000H ;error return code
|
||||
LD A,C
|
||||
CP 4 ;must be between 0 and 3
|
||||
JR NC,SELHD ;no carry if 4,5,...
|
||||
; disk number is in the proper range
|
||||
; compute proper disk parameter header address
|
||||
OUT (FDCD),A ;selekt disk drive
|
||||
LD L,A ;L=disk number 0,1,2,3
|
||||
ADD HL,HL ;*2
|
||||
ADD HL,HL ;*4
|
||||
ADD HL,HL ;*8
|
||||
ADD HL,HL ;*16 (size of each header)
|
||||
LD DE,DPBASE
|
||||
ADD HL,DE ;HL=.dpbase(diskno*16)
|
||||
RET
|
||||
SELHD: CP 8 ;select the harddisk?
|
||||
RET NZ ;no, error
|
||||
OUT (FDCD),A ;select disk drive
|
||||
LD HL,HDBASE ;HL=hdbase for harddisk
|
||||
RET
|
||||
;
|
||||
; set track given by register c
|
||||
;
|
||||
SETTRK: LD A,C
|
||||
OUT (FDCT),A
|
||||
RET
|
||||
;
|
||||
; set sector given by register c
|
||||
;
|
||||
SETSEC: LD A,C
|
||||
OUT (FDCS),A
|
||||
RET
|
||||
;
|
||||
; translate the sector given by BC using the
|
||||
; translate table given by DE
|
||||
;
|
||||
SECTRAN:
|
||||
EX DE,HL ;HL=.trans
|
||||
ADD HL,BC ;HL=.trans(sector)
|
||||
LD L,(HL) ;L = trans(sector)
|
||||
LD H,0 ;HL= trans(sector)
|
||||
RET ;with value in HL
|
||||
;
|
||||
; set dma address given by registers b and c
|
||||
;
|
||||
SETDMA: LD A,C ;low order address
|
||||
OUT (DMAL),A
|
||||
LD A,B ;high order address
|
||||
OUT (DMAH),A ;in dma
|
||||
RET
|
||||
;
|
||||
; perform read operation
|
||||
;
|
||||
READ: XOR A ;read command -> A
|
||||
JP WAITIO ;to perform the actual i/o
|
||||
;
|
||||
; perform a write operation
|
||||
;
|
||||
WRITE: LD A,1 ;write command -> A
|
||||
;
|
||||
; enter here from read and write to perform the actual i/o
|
||||
; operation. return a 00h in register a if the operation completes
|
||||
; properly, and 01h if an error occurs during the read or write
|
||||
;
|
||||
; in this case, we have saved the disk number in 'diskno' (0-3)
|
||||
; the track number in 'track' (0-76)
|
||||
; the sector number in 'sector' (1-26)
|
||||
; the dma address in 'dmaad' (0-65535)
|
||||
;
|
||||
WAITIO: OUT (FDCOP),A ;start i/o operation
|
||||
IN A,(FDCST) ;status of i/o operation -> A
|
||||
RET
|
||||
;
|
||||
; the remainder of the CBIOS is reserved uninitialized
|
||||
; data area, and does not need to be a part of the
|
||||
; system memory image (the space must be available,
|
||||
; however, between "begdat" and "enddat").
|
||||
;
|
||||
; scratch ram area for BDOS use
|
||||
;
|
||||
BEGDAT EQU $ ;beginning of data area
|
||||
DIRBF: DEFS 128 ;scratch directory area
|
||||
ALL00: DEFS 31 ;allocation vector 0
|
||||
ALL01: DEFS 31 ;allocation vector 1
|
||||
ALL02: DEFS 31 ;allocation vector 2
|
||||
ALL03: DEFS 31 ;allocation vector 3
|
||||
ALLHD: DEFS 255 ;allocation vector harddisk
|
||||
CHK00: DEFS 16 ;check vector 0
|
||||
CHK01: DEFS 16 ;check vector 1
|
||||
CHK02: DEFS 16 ;check vector 2
|
||||
CHK03: DEFS 16 ;check vector 3
|
||||
CHKHD: DEFS 0 ;check vector harddisk
|
||||
;
|
||||
ENDDAT EQU $ ;end of data area
|
||||
DATSIZ EQU $-BEGDAT ;size of data area
|
||||
END ;of BIOS
|
@@ -1,74 +0,0 @@
|
||||
; CP/M 2.2 boot-loader for Z80-Simulator
|
||||
;
|
||||
; Copyright (C) 1988 by Udo Munk
|
||||
;
|
||||
ORG 0 ; mem base of boot
|
||||
;
|
||||
MSIZE EQU 64 ; mem size in kbytes
|
||||
;
|
||||
BIAS EQU (MSIZE-20)*1024 ; offset from 20k system
|
||||
CCP EQU 3400H+BIAS ; base of the ccp
|
||||
BIOS EQU CCP+1600H ; base of the bios
|
||||
BIOSL EQU 0300H ; length of the bios
|
||||
BOOT EQU BIOS
|
||||
SIZE EQU BIOS+BIOSL-CCP ; size of cp/m system
|
||||
SECTS EQU SIZE/128 ; # of sectors to load
|
||||
;
|
||||
; I/O ports
|
||||
;
|
||||
DRIVE EQU 10 ; fdc-port: # of drive
|
||||
TRACK EQU 11 ; fdc-port: # of track
|
||||
SECTOR EQU 12 ; fdc-port: # of sector
|
||||
FDCOP EQU 13 ; fdc-port: command
|
||||
FDCST EQU 14 ; fdc-port: status
|
||||
DMAL EQU 15 ; dma-port: dma address low
|
||||
DMAH EQU 16 ; dma-port: dma address high
|
||||
;
|
||||
; begin the load operation
|
||||
;
|
||||
COLD: LD BC,2 ; b=track 0, c=sector 2
|
||||
LD D,SECTS ; d=# sectors to load
|
||||
LD HL,CCP ; base transfer address
|
||||
LD A,0 ; select drive A
|
||||
OUT (DRIVE),A
|
||||
;
|
||||
; load the next sector
|
||||
;
|
||||
LSECT: LD A,B ; set track
|
||||
OUT (TRACK),A
|
||||
LD A,C ; set sector
|
||||
OUT (SECTOR),A
|
||||
LD A,L ; set dma address low
|
||||
OUT (DMAL),A
|
||||
LD A,H ; set dma adress high
|
||||
OUT (DMAH),A
|
||||
XOR A ; read sector
|
||||
OUT (FDCOP),A
|
||||
IN A,(FDCST) ; get status of fdc
|
||||
CP 0 ; read successful ?
|
||||
JP Z,CONT ; yes, continue
|
||||
HALT ; no, halt cpu
|
||||
CONT:
|
||||
; go to next sector if load is incomplete
|
||||
DEC D ; sects=sects-1
|
||||
JP Z,BOOT ; head for the bios
|
||||
;
|
||||
; more sectors to load
|
||||
;
|
||||
; we aren't using a stack, so use <sp> as scratch register
|
||||
; to hold the load address increment
|
||||
;
|
||||
LD SP,128 ; 128 bytes per sector
|
||||
ADD HL,SP ; <hl> = <hl> + 128
|
||||
;
|
||||
INC C ; sector = sector + 1
|
||||
LD A,C
|
||||
CP 27 ; last sector of track ?
|
||||
JP C,LSECT ; no, go read another
|
||||
;
|
||||
; end of track, increment to next track
|
||||
;
|
||||
LD C,1 ; sector = 1
|
||||
INC B ; track = track + 1
|
||||
JP LSECT ; for another group
|
||||
END ; of boot loader
|
Binary file not shown.
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* CP/M 2.2 Formats a simulated Disk Drive
|
||||
*
|
||||
* Copyright (C) 1988-2006 by Udo Munk
|
||||
*
|
||||
* History:
|
||||
* 29-APR-88 Development on TARGON/35 with AT&T Unix System V.3
|
||||
* 11-MAR-93 comments in english
|
||||
* 01-OCT-06 modified to compile on modern POSIX OS's
|
||||
* 18-NOV-06 added a second harddisk
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define TRACK 77
|
||||
#define SECTOR 26
|
||||
#define HDTRACK 255
|
||||
#define HDSECTOR 128
|
||||
|
||||
/*
|
||||
* This program is able to format the following disk formats:
|
||||
*
|
||||
* drive A: 8" IBM SS,SD
|
||||
* drive B: 8" IBM SS,SD
|
||||
* drive C: 8" IBM SS,SD
|
||||
* drive D: 8" IBM SS,SD
|
||||
* drive I: 4MB harddisk
|
||||
* drive J: 4MB harddisk
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
register int i;
|
||||
int fd;
|
||||
char drive;
|
||||
static unsigned char sector[128];
|
||||
static char fn[] = "disks/drive?.cpm";
|
||||
static char usage[] = "usage: format a | b | c | d | i | j";
|
||||
|
||||
if (argc != 2) {
|
||||
puts(usage);
|
||||
exit(1);
|
||||
}
|
||||
i = *argv[1];
|
||||
if (argc != 2 ||
|
||||
(i != 'a' && i != 'b' && i != 'c' && i != 'd' && i != 'i'
|
||||
&& i != 'j')) {
|
||||
puts(usage);
|
||||
exit(1);
|
||||
}
|
||||
fn[11] = drive = (char) i;
|
||||
memset((char *) sector, 0xe5, 128);
|
||||
if ((fd = creat(fn, 0644)) == -1) {
|
||||
perror("disk file");
|
||||
exit(1);
|
||||
}
|
||||
if (drive != 'i' && drive != 'j') {
|
||||
for (i = 0; i < TRACK * SECTOR; i++)
|
||||
write(fd, (char *) sector, 128);
|
||||
} else {
|
||||
for (i = 0; i < HDTRACK * HDSECTOR; i++)
|
||||
write(fd, (char *) sector, 128);
|
||||
}
|
||||
close(fd);
|
||||
return(0);
|
||||
}
|
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Write the CP/M systemfiles to system tracks of drive A
|
||||
*
|
||||
* Copyright (C) 1988-2006 by Udo Munk
|
||||
*
|
||||
* History:
|
||||
* 29-APR-88 Development on TARGON/35 with AT&T Unix System V.3
|
||||
* 11-MAR-93 comments in english and ported to COHERENT 4.0
|
||||
* 02-OCT-06 modified to compile on modern POSIX OS's
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <memory.h>
|
||||
|
||||
/*
|
||||
* This program writes the CP/M 2.2 OS from the following files
|
||||
* onto the system tracks of the boot disk (drivea.cpm):
|
||||
*
|
||||
* boot loader boot.bin (Mostek binary format)
|
||||
* CCP cpm.bin (binary format)
|
||||
* BDOS cpm.bin (binary format)
|
||||
* BIOS bios.bin (Mostek binary format)
|
||||
*/
|
||||
int main(void)
|
||||
{
|
||||
unsigned char header[3];
|
||||
unsigned char sector[128];
|
||||
register int i;
|
||||
int fd, drivea, readed;
|
||||
|
||||
/* open drive A for writing */
|
||||
if ((drivea = open("../disks/drivea.cpm", O_WRONLY)) == -1) {
|
||||
perror("file ../disks/drivea.cpm");
|
||||
exit(1);
|
||||
}
|
||||
/* open boot loader (boot.bin) for reading */
|
||||
if ((fd = open("boot.bin", O_RDONLY)) == -1) {
|
||||
perror("file boot.bin");
|
||||
exit(1);
|
||||
}
|
||||
/* read and check 3 byte header */
|
||||
if ((readed = read(fd, (char *) header, 3)) != 3) {
|
||||
perror("file boot.bin");
|
||||
exit(1);
|
||||
}
|
||||
if (header[0] != 0xff || header[1] != 0 || header[2] != 0) {
|
||||
puts("start adress of boot.bin <> 0");
|
||||
exit(0);
|
||||
}
|
||||
/* read boot loader */
|
||||
memset((char *) sector, 0, 128);
|
||||
read(fd, (char *) sector, 128);
|
||||
close(fd);
|
||||
/* and write it to disk in drive A */
|
||||
write(drivea, (char *) sector, 128);
|
||||
/* open CP/M system file (cpm.bin) for reading */
|
||||
if ((fd = open("cpm.bin", O_RDONLY)) == -1) {
|
||||
perror("file cpm.bin");
|
||||
exit(1);
|
||||
}
|
||||
/* position to CCP in cpm.bin, needed if created with SAVE or similar */
|
||||
lseek(fd, (long) 17 * 128, 0);
|
||||
/* read CCP and BDOS from cpm.bin and write them to disk in drive A */
|
||||
for (i = 0; i < 44; i++) {
|
||||
if ((readed = read(fd, (char *) sector, 128)) != 128) {
|
||||
perror("file cpm.bin");
|
||||
exit(1);
|
||||
}
|
||||
write(drivea, (char *) sector, 128);
|
||||
}
|
||||
close(fd);
|
||||
/* open BIOS (bios.bin) for reading */
|
||||
if ((fd = open("bios.bin", O_RDONLY)) == -1) {
|
||||
perror("file bios.bin");
|
||||
exit(1);
|
||||
}
|
||||
/* read and check 3 byte header */
|
||||
if ((readed = read(fd, (char *) header, 3)) != 3) {
|
||||
perror("file bios.bin");
|
||||
exit(1);
|
||||
}
|
||||
if (header[0] != 0xff) {
|
||||
puts("unknown format of bios.bin");
|
||||
exit(0);
|
||||
}
|
||||
/* read BIOS from bios.bin and write it to disk in drive A */
|
||||
i = 0;
|
||||
while ((readed = read(fd, (char *) sector, 128)) == 128) {
|
||||
write(drivea, (char *) sector, 128);
|
||||
i++;
|
||||
if (i == 6) {
|
||||
puts("6 sectors written, can't write any more!");
|
||||
goto stop;
|
||||
}
|
||||
}
|
||||
if (readed > 0) {
|
||||
write(drivea, (char *) sector, 128);
|
||||
}
|
||||
stop:
|
||||
close(fd);
|
||||
close(drivea);
|
||||
return(0);
|
||||
}
|
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Receive a file out of the named pipe "auxout" from CP/M simulation
|
||||
*
|
||||
* Copyright (C) 1988-2006 by Udo Munk
|
||||
*
|
||||
* History:
|
||||
* 05-OKT-88 Development on TARGON/35 with AT&T Unix System V.3
|
||||
* 11-MAR-93 comments in english and ported to COHERENT 4.0
|
||||
* 01-OCT-06 modified to compile on modern POSIX OS's
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
int fdin, fdout;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char c;
|
||||
void int_handler(void);
|
||||
|
||||
if (argc != 2) {
|
||||
puts("usage: receive filname &");
|
||||
exit(1);
|
||||
}
|
||||
if ((fdin = open("auxout", O_RDONLY)) == -1) {
|
||||
perror("pipe auxout");
|
||||
exit(1);
|
||||
}
|
||||
if ((fdout = creat(argv[1], 0644)) == -1) {
|
||||
perror(argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
signal(SIGINT, SIG_IGN);
|
||||
signal(SIGQUIT, SIG_IGN);
|
||||
signal(SIGHUP, int_handler);
|
||||
|
||||
for (;;) {
|
||||
if (read(fdin, &c, 1) == 1)
|
||||
if (c != '\r')
|
||||
write(fdout, &c, 1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
void int_handler(void)
|
||||
{
|
||||
close(fdin);
|
||||
close(fdout);
|
||||
exit(0);
|
||||
}
|
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Sends a file through named pipe "auxin" to the CP/M simulation
|
||||
*
|
||||
* Copyright (C) 1988-2006 by Udo Munk
|
||||
*
|
||||
* History:
|
||||
* 05-OKT-88 Development on TARGON/35 with AT&T Unix System V.3
|
||||
* 11-MAR-93 comments in english and ported to COHERENT 4.0
|
||||
* 01-OCT-06 modified to compile on modern POSIX OS's
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
void sendbuf(int);
|
||||
|
||||
char buf[BUFSIZ];
|
||||
char cr = '\r';
|
||||
int fdout, fdin;
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
register int readed;
|
||||
|
||||
if (argc != 2) {
|
||||
puts("usage: send filname &");
|
||||
exit(1);
|
||||
}
|
||||
if ((fdin = open(argv[1], O_RDONLY)) == -1) {
|
||||
perror(argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
if ((fdout = open("auxin", O_WRONLY)) == -1) {
|
||||
perror("pipe auxin");
|
||||
exit(1);
|
||||
}
|
||||
while ((readed = read(fdin, buf, BUFSIZ)) == BUFSIZ)
|
||||
sendbuf(BUFSIZ);
|
||||
if (readed)
|
||||
sendbuf(readed);
|
||||
close(fdin);
|
||||
close(fdout);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void sendbuf(int size)
|
||||
{
|
||||
register char *s = buf;
|
||||
|
||||
while (s - buf < size) {
|
||||
if (*s == '\n')
|
||||
write(fdout, (char *) &cr, 1);
|
||||
write(fdout, s++, 1);
|
||||
}
|
||||
}
|
@@ -1,13 +0,0 @@
|
||||
CFLAGS= -O -s
|
||||
|
||||
all: putsys boot.bin
|
||||
echo done
|
||||
|
||||
putsys: putsys.c
|
||||
cc $(CFLAGS) -o putsys putsys.c
|
||||
|
||||
boot.bin: boot.asm
|
||||
z80asm -vl -sn -fb boot.asm
|
||||
|
||||
clean:
|
||||
rm -f *.lis putsys boot.bin
|
@@ -1,582 +0,0 @@
|
||||
; CP/M 3 BIOS for Z80-Simulator
|
||||
;
|
||||
; Copyright (C) 1989-2006 by Udo Munk
|
||||
;
|
||||
.Z80
|
||||
;
|
||||
; bdos functions
|
||||
;
|
||||
WARM EQU 0
|
||||
BDOS EQU 5
|
||||
PRINT EQU 9
|
||||
OPEN EQU 15
|
||||
READS EQU 20
|
||||
DMA EQU 26
|
||||
MULTI EQU 44
|
||||
;
|
||||
; i/o ports
|
||||
;
|
||||
CONSTA EQU 0 ;console status port
|
||||
CONDAT EQU 1 ;console data port
|
||||
PRTSTA EQU 2 ;printer status port
|
||||
PRTDAT EQU 3 ;printer data port
|
||||
AUXSTA EQU 4 ;auxilary status port
|
||||
AUXDAT EQU 5 ;auxilary data port
|
||||
FDCD EQU 10 ;fdc-port: # of drive
|
||||
FDCT EQU 11 ;fdc-port: # of track
|
||||
FDCS EQU 12 ;fdc-port: # of sector
|
||||
FDCOP EQU 13 ;fdc-port: command
|
||||
FDCST EQU 14 ;fdc-port: status
|
||||
DMAL EQU 15 ;dma-port: dma address low
|
||||
DMAH EQU 16 ;dma-port: dma address high
|
||||
MMUINI EQU 20 ;initialize mmu
|
||||
MMUSEL EQU 21 ;bank select mmu
|
||||
CLKCMD EQU 25 ;clock command
|
||||
CLKDAT EQU 26 ;clock data
|
||||
;
|
||||
; clock commands
|
||||
;
|
||||
GETSEC EQU 0 ;get seconds
|
||||
GETMIN EQU 1 ;get minutes
|
||||
GETHOU EQU 2 ;get hours
|
||||
GETDAL EQU 3 ;get days low
|
||||
GETDAH EQU 4 ;get days high
|
||||
;
|
||||
; character device mode byte fields
|
||||
;
|
||||
mb$input EQU 00000001B ;device may do input
|
||||
mb$output EQU 00000010B ;device may do output
|
||||
mb$in$out EQU mb$input+mb$output ;device may do both
|
||||
baud$none EQU 0
|
||||
;
|
||||
; external references in scb
|
||||
;
|
||||
EXTRN @civec, @covec, @aovec, @aivec, @lovec, @bnkbf
|
||||
EXTRN @crdma, @crdsk, @fx, @resel, @vinfo, @usrcd
|
||||
EXTRN @ermde, @date, @hour, @min, @sec, @mxtpa
|
||||
;
|
||||
CSEG
|
||||
;
|
||||
; cp/m 3 jump vector for individual subroutines
|
||||
;
|
||||
JP BOOT ;perform cold start initialization
|
||||
WBOOTE: JP WBOOT ;perform warm start initialization
|
||||
JP CONST ;check for console input char ready
|
||||
JP CONIN ;read console character in
|
||||
JP CONOUT ;write console character out
|
||||
JP LIST ;write list character out
|
||||
JP AUXOUT ;write auxiliary output char
|
||||
JP AUXIN ;read auxiliary input char
|
||||
JP HOME ;move head to track 0 on selcted disk
|
||||
JP SELDSK ;select disk drive
|
||||
JP SETTRK ;set track number
|
||||
JP SETSEC ;set sector number
|
||||
JP SETDMA ;set dma address
|
||||
JP READ ;read specified sector
|
||||
JP WRITE ;write specified sector
|
||||
JP LISTST ;return list status
|
||||
JP SECTRAN ;translate logical to physical sector
|
||||
JP CONOST ;return output status of console
|
||||
JP AUXIST ;return input status of aux. port
|
||||
JP AUXOST ;return output status of aux. port
|
||||
JP DEVTBL ;return address of character i/o table
|
||||
JP DEVINI ;initialize character i/o devices
|
||||
JP DRVTBL ;return address of disk drive table
|
||||
JP MULTIO ;set number of sectors to read/write
|
||||
JP FLUSH ;flush deblocking buffers
|
||||
JP MOVE ;memory to memory move
|
||||
JP TIME ;time set/get signal
|
||||
JP SELMEM ;select bank of memory
|
||||
JP SETBNK ;specify bank for dma operation
|
||||
JP XMOVE ;set bank for memory dma transfer
|
||||
JP 0 ;reserved for system implementor
|
||||
JP 0 ;reserved for future use
|
||||
JP 0 ;reserved for future use
|
||||
;
|
||||
; drive table
|
||||
;
|
||||
DRIVES: DW DPH0
|
||||
DW DPH1
|
||||
DW DPH2
|
||||
DW DPH3
|
||||
DW 0
|
||||
DW 0
|
||||
DW 0
|
||||
DW 0
|
||||
DW DPH8
|
||||
DW DPH9
|
||||
DW 0
|
||||
DW 0
|
||||
DW 0
|
||||
DW 0
|
||||
DW 0
|
||||
DW 0
|
||||
;
|
||||
; fixed data tables for IBM-compatible 8" disks
|
||||
;
|
||||
; disk parameter header
|
||||
;
|
||||
DPH0: DEFW TRANS ;sector translation table
|
||||
DB 0,0,0,0,0,0,0,0,0 ;bdos scratch area
|
||||
DB 0 ;media flag
|
||||
DEFW DPB0 ;disk parameter block
|
||||
DEFW 0FFFEH ;checksum vector
|
||||
DEFW 0FFFEH ;allocation vector
|
||||
DEFW 0FFFEH ;directory buffer control block
|
||||
DEFW 0FFFFH ;dtabcb not used
|
||||
DEFW 0FFFEH ;hashing
|
||||
DEFB 0 ;hash bank
|
||||
DPH1: DEFW TRANS ;sector translation table
|
||||
DB 0,0,0,0,0,0,0,0,0 ;bdos scratch area
|
||||
DB 0 ;media flag
|
||||
DEFW DPB0 ;disk parameter block
|
||||
DEFW 0FFFEH ;checksum vector
|
||||
DEFW 0FFFEH ;allocation vector
|
||||
DEFW 0FFFEH ;directory buffer control block
|
||||
DEFW 0FFFFH ;dtabcb not used
|
||||
DEFW 0FFFEH ;hashing
|
||||
DEFB 0 ;hash bank
|
||||
DPH2: DEFW TRANS ;sector translation table
|
||||
DB 0,0,0,0,0,0,0,0,0 ;bdos scratch area
|
||||
DB 0 ;media flag
|
||||
DEFW DPB0 ;disk parameter block
|
||||
DEFW 0FFFEH ;checksum vector
|
||||
DEFW 0FFFEH ;allocation vector
|
||||
DEFW 0FFFEH ;directory buffer control block
|
||||
DEFW 0FFFFH ;dtabcb not used
|
||||
DEFW 0FFFEH ;hashing
|
||||
DEFB 0 ;hash bank
|
||||
DPH3: DEFW TRANS ;sector translation table
|
||||
DB 0,0,0,0,0,0,0,0,0 ;bdos scratch area
|
||||
DB 0 ;media flag
|
||||
DEFW DPB0 ;disk parameter block
|
||||
DEFW 0FFFEH ;checksum vector
|
||||
DEFW 0FFFEH ;allocation vector
|
||||
DEFW 0FFFEH ;directory buffer control block
|
||||
DEFW 0FFFFH ;dtabcb not used
|
||||
DEFW 0FFFEH ;hashing
|
||||
DEFB 0 ;hash bank
|
||||
;
|
||||
; sector translate vector for the IBM 8" disk
|
||||
;
|
||||
TRANS: DEFB 1,7,13,19 ;sectors 1,2,3,4
|
||||
DEFB 25,5,11,17 ;sectors 5,6,7,8
|
||||
DEFB 23,3,9,15 ;sectors 9,10,11,12
|
||||
DEFB 21,2,8,14 ;sectors 13,14,15,16
|
||||
DEFB 20,26,6,12 ;sectors 17,18,19,20
|
||||
DEFB 18,24,4,10 ;sectors 21,22,23,24
|
||||
DEFB 16,22 ;sectors 25,26
|
||||
;
|
||||
; disk parameter block for the IBM 8" disk
|
||||
;
|
||||
DPB0: DEFW 26 ;sectors per track
|
||||
DEFB 3 ;block shift factor
|
||||
DEFB 7 ;block mask
|
||||
DEFB 0 ;extent mask
|
||||
DEFW 242 ;disk size-1
|
||||
DEFW 63 ;directory max
|
||||
DEFB 192 ;alloc 0
|
||||
DEFB 0 ;alloc 1
|
||||
DEFW 16 ;check size
|
||||
DEFW 2 ;track offset
|
||||
DEFB 0,0 ;physical sector size and shift
|
||||
;
|
||||
; fixed data tables for 4mb harddisks
|
||||
;
|
||||
; disk parameter header
|
||||
;
|
||||
DPH8: DEFW HDTRA ;sector translation table
|
||||
DB 0,0,0,0,0,0,0,0,0 ;bdos scratch area
|
||||
DB 0 ;media flag
|
||||
DEFW DPB1 ;disk parameter block
|
||||
DEFW 0FFFEH ;checksum vector
|
||||
DEFW 0FFFEH ;allocation vector
|
||||
DEFW 0FFFEH ;directory buffer control block
|
||||
DEFW 0FFFFH ;dtabcb not used
|
||||
DEFW 0FFFEH ;hashing
|
||||
DEFB 0 ;hash bank
|
||||
DPH9: DEFW HDTRA ;sector translation table
|
||||
DB 0,0,0,0,0,0,0,0,0 ;bdos scratch area
|
||||
DB 0 ;media flag
|
||||
DEFW DPB1 ;disk parameter block
|
||||
DEFW 0FFFEH ;checksum vector
|
||||
DEFW 0FFFEH ;allocation vector
|
||||
DEFW 0FFFEH ;directory buffer control block
|
||||
DEFW 0FFFFH ;dtabcb not used
|
||||
DEFW 0FFFEH ;hashing
|
||||
DEFB 0 ;hash bank
|
||||
;
|
||||
; sector translate vector for 4mb harddisk
|
||||
;
|
||||
HDTRA: DEFB 1,2,3,4,5,6,7,8,9,10
|
||||
DEFB 11,12,13,14,15,16,17,18,19,20
|
||||
DEFB 21,22,23,24,25,26,27,28,29,30
|
||||
DEFB 31,32,33,34,35,36,37,38,39,40
|
||||
DEFB 41,42,43,44,45,46,47,48,49,50
|
||||
DEFB 51,52,53,54,55,56,57,58,59,60
|
||||
DEFB 61,62,63,64,65,66,67,68,69,70
|
||||
DEFB 71,72,73,74,75,76,77,78,79,80
|
||||
DEFB 81,82,83,84,85,86,87,88,89,90
|
||||
DEFB 91,92,93,94,95,96,97,98,99,100
|
||||
DEFB 101,102,103,104,105,106,107,108,109,110
|
||||
DEFB 111,112,113,114,115,116,117,118,119,120
|
||||
DEFB 121,122,123,124,125,126,127,128
|
||||
;
|
||||
; disk parameter block for 4mb harddisk
|
||||
;
|
||||
DPB1: DEFW 128 ;sectors per track
|
||||
DEFB 4 ;block shift factor
|
||||
DEFB 15 ;block mask
|
||||
DEFB 0 ;extent mask
|
||||
DEFW 2039 ;disk size-1
|
||||
DEFW 1023 ;directory max
|
||||
DEFB 255 ;alloc 0
|
||||
DEFB 255 ;alloc 1
|
||||
DEFW 0 ;check size
|
||||
DEFW 0 ;track offset
|
||||
DEFB 0,0 ;physical sector size and shift
|
||||
;
|
||||
; character device table
|
||||
;
|
||||
CHRTBL: DEFB 'CRT '
|
||||
DEFB mb$in$out
|
||||
DEFB baud$none
|
||||
DEFB 'LPT '
|
||||
DEFB mb$output
|
||||
DEFB baud$none
|
||||
DEFB 'PTP '
|
||||
DEFB mb$output
|
||||
DEFB baud$none
|
||||
DEFB 'PTR '
|
||||
DEFB mb$input
|
||||
DEFB baud$none
|
||||
DEFB 0
|
||||
;
|
||||
; signon message
|
||||
;
|
||||
SIGNON: DEFB 13,10
|
||||
DEFM 'BANKED BIOS3 V1.4 for Z80SIM, '
|
||||
DEFM 'Copyright 1989-2006 by Udo Munk'
|
||||
DEFB 13,10
|
||||
DEFB 0
|
||||
;
|
||||
; small stack
|
||||
;
|
||||
DS 8
|
||||
STACK:
|
||||
;
|
||||
; fcb for loading ccp
|
||||
;
|
||||
CCPFCB: DEFB 1,'CCP COM',0,0,0,0
|
||||
DEFB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
CCPREC: DEFB 0,0,0
|
||||
;
|
||||
DSEG
|
||||
;
|
||||
; bios error messages
|
||||
;
|
||||
CCPOER: DEFB 13,10,'BIOS ERROR: cannot open CCP.COM',13,10,'$'
|
||||
CCPIOE: DEFB 13,10,'BIOS ERROR: reading CCP.COM',13,10,'$'
|
||||
;
|
||||
CSEG
|
||||
;
|
||||
DRIVE: DEFB 0 ;drive to select
|
||||
BANK: DEFB 0 ;bank to select for dma
|
||||
;
|
||||
; end of fixed tables
|
||||
;
|
||||
; individual subroutines to perform each function
|
||||
;
|
||||
DSEG
|
||||
;
|
||||
BOOT: LD B,1 ;indicate cold boot
|
||||
;
|
||||
LD HL,8000H
|
||||
LD (@civec),HL ;CONSOLE:=CON for input
|
||||
LD (@covec),HL ;CONSOLE:=CON for output
|
||||
LD HL,4000H
|
||||
LD (@lovec),HL ;LST:=LPT
|
||||
LD HL,2000H
|
||||
LD (@aovec),HL ;AUXOUT:=PTP
|
||||
LD HL,1000H
|
||||
LD (@aivec),HL ;AUXIN:=PTR
|
||||
;
|
||||
LD A,3 ;initialize 3 memory banks
|
||||
OUT (MMUINI),A
|
||||
JP WBOOT1
|
||||
;
|
||||
CSEG
|
||||
;
|
||||
WBOOT: LD B,0 ;indicate warm boot
|
||||
WBOOT1: LD SP,STACK
|
||||
;
|
||||
; initialize low memory jumps in bank 1
|
||||
;
|
||||
LD A,1
|
||||
CALL SELMEM
|
||||
;
|
||||
LD A,0C3H ;jmp instruction
|
||||
LD (WARM),A
|
||||
LD HL,WBOOTE ;warm boot enty point
|
||||
LD (WARM+1),HL
|
||||
LD (BDOS),A
|
||||
LD HL,(@mxtpa) ;bdos entry point
|
||||
LD (BDOS+1),HL
|
||||
;
|
||||
; print message on cold boot
|
||||
;
|
||||
LD A,B
|
||||
OR A
|
||||
JP Z,LDCCP
|
||||
LD HL,SIGNON ;print message
|
||||
WBOOT2: LD A,(HL)
|
||||
OR A
|
||||
JP Z,LDCCP
|
||||
LD C,A
|
||||
CALL CONOUT
|
||||
INC HL
|
||||
JP WBOOT2
|
||||
;
|
||||
; load ccp.com into tpa
|
||||
;
|
||||
LDCCP: XOR A ;initialize fcb
|
||||
LD (CCPFCB+15),A
|
||||
LD HL,0
|
||||
LD (CCPREC),HL
|
||||
LD DE,CCPFCB ;open file ccp.com
|
||||
LD C,OPEN
|
||||
CALL BDOS
|
||||
LD DE,CCPOER
|
||||
INC A
|
||||
JP Z,CCPERR ;print error if file not found
|
||||
LD DE,0100H ;setup DMA to tpa
|
||||
LD C,DMA
|
||||
CALL BDOS
|
||||
LD DE,128 ;read up to 16KB
|
||||
LD C,MULTI
|
||||
CALL BDOS
|
||||
LD DE,CCPFCB ;read the ccp into memory
|
||||
LD C,READS
|
||||
CALL BDOS
|
||||
LD DE,CCPIOE
|
||||
INC A
|
||||
JP NZ,0100H ;start ccp
|
||||
CCPERR: LD C,PRINT ;print error message
|
||||
CALL BDOS
|
||||
HALT
|
||||
;
|
||||
; character i/o drivers
|
||||
;
|
||||
DEVTBL: LD HL,CHRTBL
|
||||
RET
|
||||
;
|
||||
; character device initialization
|
||||
;
|
||||
DEVINI: RET
|
||||
;
|
||||
; console in status, return 0ffh if character ready, 00h if not
|
||||
;
|
||||
CONST: IN A,(CONSTA)
|
||||
RET
|
||||
;
|
||||
; console character input from register a
|
||||
;
|
||||
CONIN: IN A,(CONDAT)
|
||||
RET
|
||||
;
|
||||
; console out status, return 0ffh if ready, 00h if not
|
||||
CONOST: LD A,0FFH ;console out always ready
|
||||
RET
|
||||
;
|
||||
; console character output from register c
|
||||
;
|
||||
CONOUT: LD A,C ;get to accumulator
|
||||
OUT (CONDAT),A ;send character to console
|
||||
RET
|
||||
;
|
||||
; list out status, return 0ffh if ready, 00h if not
|
||||
;
|
||||
LISTST: LD A,0FFH ;list out always ready
|
||||
RET
|
||||
;
|
||||
; list character output from register C
|
||||
;
|
||||
LIST: LD A,C
|
||||
OUT (PRTDAT),A
|
||||
RET
|
||||
;
|
||||
; auxilary input status, 0ffh if ready, 00h if not
|
||||
;
|
||||
AUXIST: XOR A ;never ready, hardware not available yet
|
||||
RET
|
||||
;
|
||||
; auxilary output status, 0ffh if ready, 00h if not
|
||||
;
|
||||
AUXOST: XOR A ;never ready, hadware not available yet
|
||||
RET
|
||||
;
|
||||
; auxilary input
|
||||
;
|
||||
AUXIN: IN A,(AUXDAT)
|
||||
RET
|
||||
;
|
||||
; auxilary output from register c
|
||||
;
|
||||
AUXOUT: LD A,C
|
||||
OUT (AUXDAT),A
|
||||
RET
|
||||
;
|
||||
;
|
||||
; i/o drivers for the disks
|
||||
;
|
||||
DRVTBL: LD HL,DRIVES
|
||||
RET
|
||||
;
|
||||
DSEG
|
||||
;
|
||||
; move to the track 00 position of current drive
|
||||
; translate this call into a settrk call with parameter 00
|
||||
;
|
||||
HOME: LD C,0 ;select track 0
|
||||
JP SETTRK ;we will move to 00 on first read/write
|
||||
;
|
||||
; select disk given by register C
|
||||
;
|
||||
SELDSK: LD HL,0000H ;error return code
|
||||
LD A,C
|
||||
LD (DRIVE),A
|
||||
CP 4 ;disk drive 1-4?
|
||||
JP C,SEL1 ;go
|
||||
CP 8 ;harddisk 1?
|
||||
JP Z,SEL1 ;go
|
||||
CP 9 ;harddisk 2?
|
||||
RET NZ ;no, error
|
||||
; disk number is in the proper range
|
||||
; return proper disk parameter header address
|
||||
SEL1: LD L,C
|
||||
LD H,0
|
||||
ADD HL,HL ;drive index in hl
|
||||
LD BC,DRIVES
|
||||
ADD HL,BC ;get pointer to dph
|
||||
LD A,(HL)
|
||||
INC HL
|
||||
LD H,(HL)
|
||||
LD L,A
|
||||
LD A,(DRIVE)
|
||||
OUT (FDCD),A ;selekt disk drive
|
||||
RET
|
||||
;
|
||||
; set track given by register c
|
||||
;
|
||||
SETTRK: LD A,C
|
||||
OUT (FDCT),A
|
||||
RET
|
||||
;
|
||||
; set sector given by register c
|
||||
;
|
||||
SETSEC: LD A,C
|
||||
OUT (FDCS),A
|
||||
RET
|
||||
;
|
||||
; translate the sector given by bc using the
|
||||
; translate table given by de
|
||||
;
|
||||
SECTRAN:
|
||||
EX DE,HL ;hl=.trans
|
||||
ADD HL,BC ;hl=.trans(sector)
|
||||
LD L,(HL) ;l = trans(sector)
|
||||
LD H,0 ;hl= trans(sector)
|
||||
RET ;with value in HL
|
||||
;
|
||||
; set dma address given by registers b and c
|
||||
;
|
||||
SETDMA: LD A,C ;low order address
|
||||
OUT (DMAL),A
|
||||
LD A,B ;high order address
|
||||
OUT (DMAH),A
|
||||
RET
|
||||
;
|
||||
CSEG
|
||||
;
|
||||
; perform read operation
|
||||
;
|
||||
READ: LD A,(BANK) ;switch to saved bank
|
||||
OUT (MMUSEL),A
|
||||
XOR A ;read command -> A
|
||||
JP WAITIO ;to perform the actual i/o
|
||||
;
|
||||
; perform write operation
|
||||
;
|
||||
WRITE: LD A,(BANK) ;switch to saved bank
|
||||
OUT (MMUSEL),A
|
||||
LD A,1 ;write command -> A
|
||||
;
|
||||
; enter here from read and write to perform the actual i/o
|
||||
; operation. return 00h in register a if the operation completes
|
||||
; properly, and 01h if an error occurs during the read or write
|
||||
;
|
||||
WAITIO: OUT (FDCOP),A ;start i/o operation
|
||||
XOR A ;reselect bank 0
|
||||
OUT (MMUSEL),A
|
||||
IN A,(FDCST) ;status of i/o operation -> A
|
||||
RET
|
||||
;
|
||||
; nothing to do
|
||||
;
|
||||
MULTIO: XOR A
|
||||
RET
|
||||
;
|
||||
; nothing to do
|
||||
;
|
||||
FLUSH: XOR A
|
||||
RET
|
||||
;
|
||||
; memory move
|
||||
;
|
||||
MOVE: EX DE,HL
|
||||
LDIR
|
||||
EX DE,HL
|
||||
RET
|
||||
;
|
||||
; select memory bank
|
||||
SELMEM: OUT (MMUSEL),A
|
||||
RET
|
||||
;
|
||||
; specify memory bank for dma operation
|
||||
SETBNK: LD (BANK),A
|
||||
RET
|
||||
;
|
||||
; xmove not implemented yet, hardware missing
|
||||
;
|
||||
XMOVE: RET
|
||||
;
|
||||
; get/set time
|
||||
;
|
||||
TIME:
|
||||
LD A,C
|
||||
CP 0FFH
|
||||
RET Z ;we cannot set the UNIX time from here
|
||||
LD A,GETSEC ;get seconds
|
||||
OUT (CLKCMD),A
|
||||
IN A,(CLKDAT)
|
||||
LD (@sec),A
|
||||
LD A,GETMIN ;get minutes
|
||||
OUT (CLKCMD),A
|
||||
IN A,(CLKDAT)
|
||||
LD (@min),A
|
||||
LD A,GETHOU ;get hours
|
||||
OUT (CLKCMD),A
|
||||
IN A,(CLKDAT)
|
||||
LD (@hour),A
|
||||
LD A,GETDAL ;get day
|
||||
OUT (CLKCMD),A
|
||||
IN A,(CLKDAT)
|
||||
LD (@date),A
|
||||
LD A,GETDAH
|
||||
OUT (CLKCMD),A
|
||||
IN A,(CLKDAT)
|
||||
LD (@date+1),A
|
||||
RET
|
||||
;
|
||||
ENDDAT EQU $ ;end
|
||||
END ;of BIOS
|
@@ -1,67 +0,0 @@
|
||||
; CP/M 3 boot-loader for Z80-Simulator
|
||||
;
|
||||
; Copyright (C) 1989-2006 by Udo Munk
|
||||
;
|
||||
ORG 0 ; mem base of boot
|
||||
;
|
||||
BOOT EQU 0100H ; cpmldr runs at 0100H
|
||||
SECTS EQU 51 ; # of sectors to load (26 * 2 - 1)
|
||||
;
|
||||
; I/O ports
|
||||
;
|
||||
DRIVE EQU 10 ; fdc-port: # of drive
|
||||
TRACK EQU 11 ; fdc-port: # of track
|
||||
SECTOR EQU 12 ; fdc-port: # of sector
|
||||
FDCOP EQU 13 ; fdc-port: command
|
||||
FDCST EQU 14 ; fdc-port: status
|
||||
DMAL EQU 15 ; dma-port: dma address low
|
||||
DMAH EQU 16 ; dma-port: dma address high
|
||||
;
|
||||
; begin the load operation
|
||||
;
|
||||
COLD: LD BC,2 ; b=track 0, c=sector 2
|
||||
LD D,SECTS ; d=# sectors to load
|
||||
LD HL,BOOT ; base transfer address
|
||||
LD A,0 ; select drive A
|
||||
OUT (DRIVE),A
|
||||
;
|
||||
; load the next sector
|
||||
;
|
||||
LSECT: LD A,B ; set track
|
||||
OUT (TRACK),A
|
||||
LD A,C ; set sector
|
||||
OUT (SECTOR),A
|
||||
LD A,L ; set dma address low
|
||||
OUT (DMAL),A
|
||||
LD A,H ; set dma adress high
|
||||
OUT (DMAH),A
|
||||
XOR A ; read sector
|
||||
OUT (FDCOP),A
|
||||
IN A,(FDCST) ; get status of fdc
|
||||
CP 0 ; read successful ?
|
||||
JP Z,CONT ; yes, continue
|
||||
HALT ; no, halt cpu
|
||||
CONT:
|
||||
; go to next sector if load is incomplete
|
||||
DEC D ; sects=sects-1
|
||||
JP Z,BOOT ; head for the bios
|
||||
;
|
||||
; more sectors to load
|
||||
;
|
||||
; we aren't using a stack, so use <sp> as scratch register
|
||||
; to hold the load address increment
|
||||
;
|
||||
LD SP,128 ; 128 bytes per sector
|
||||
ADD HL,SP ; <hl> = <hl> + 128
|
||||
;
|
||||
INC C ; sector = sector + 1
|
||||
LD A,C
|
||||
CP 27 ; last sector of track ?
|
||||
JP C,LSECT ; no, go read another
|
||||
;
|
||||
; end of track, increment to next track
|
||||
;
|
||||
LD C,1 ; sector = 1
|
||||
INC B ; track = track + 1
|
||||
JP LSECT ; for another group
|
||||
END ; of boot loader
|
Binary file not shown.
@@ -1,212 +0,0 @@
|
||||
; CP/M 3 LDRBIOS for Z80-Simulator
|
||||
;
|
||||
; Copyright (C) 1989-2006 by Udo Munk
|
||||
;
|
||||
.Z80
|
||||
;
|
||||
; I/O ports
|
||||
;
|
||||
CONSTA EQU 0 ;console status port
|
||||
CONDAT EQU 1 ;console data port
|
||||
FDCD EQU 10 ;fdc-port: # of drive
|
||||
FDCT EQU 11 ;fdc-port: # of track
|
||||
FDCS EQU 12 ;fdc-port: # of sector
|
||||
FDCOP EQU 13 ;fdc-port: command
|
||||
FDCST EQU 14 ;fdc-port: status
|
||||
DMAL EQU 15 ;dma-port: dma address low
|
||||
DMAH EQU 16 ;dma-port: dma address high
|
||||
;
|
||||
CSEG
|
||||
;
|
||||
; jump vector for individual subroutines
|
||||
; * needs to be implemented
|
||||
;
|
||||
JP BOOT ; * perform cold start initialization
|
||||
JP WBOOT ; perform warm start initialization
|
||||
JP CONST ; check for console input char ready
|
||||
JP CONIN ; read console character in
|
||||
JP CONOUT ; * write console character out
|
||||
JP LIST ; write list character out
|
||||
JP AUXOUT ; write auxiliary output char
|
||||
JP AUXIN ; read auxiliary input char
|
||||
JP HOME ; * move head to track 0 on selcted disk
|
||||
JP SELDSK ; * select disk drive
|
||||
JP SETTRK ; * set track number
|
||||
JP SETSEC ; * set sector number
|
||||
JP SETDMA ; * set dma address
|
||||
JP READ ; * read specified sector
|
||||
JP WRITE ; write specified sector
|
||||
JP LISTST ; return list status
|
||||
JP SECTRAN ; * translate logical to physical sector
|
||||
JP CONOST ; return output status of console
|
||||
JP AUXIST ; return input status of aux. port
|
||||
JP AUXOST ; return output status of aux. port
|
||||
JP DEVTBL ; return address of character i/o table
|
||||
JP DEVINI ; initialize character i/o devices
|
||||
JP DRVTBL ; return address of disk drive table
|
||||
JP MULTIO ; set number of sectors to read/write
|
||||
JP FLUSH ; flush deblocking buffers
|
||||
JP MOVE ; * memory to memory move
|
||||
JP TIME ; time set/get signal
|
||||
JP SELMEM ; select bank of memory
|
||||
JP SETBNK ; specify bank for dma operation
|
||||
JP XMOVE ; set bank for memory dma transfer
|
||||
JP 0 ; reserved for system implementor
|
||||
JP 0 ; reserved for future use
|
||||
JP 0 ; reserved for future use
|
||||
;
|
||||
; fixed data tables for a IBM-compatible 8" disk
|
||||
;
|
||||
; disk parameter header
|
||||
;
|
||||
DPH0: DEFW TRANS ;sector translation table
|
||||
DB 0,0,0,0,0,0,0,0,0 ;bdos scratch area
|
||||
DB 0 ;media flag
|
||||
DEFW DPB0 ;disk parameter block
|
||||
DEFW 0FFFEH ;checksum vector
|
||||
DEFW 0FFFEH ;allocation vector
|
||||
DEFW 0FFFEH ;directory buffer control block
|
||||
DEFW 0FFFFH ;dtabcb not used
|
||||
DEFW 0FFFFH ;hashing not used
|
||||
DEFB 0 ;hash bank
|
||||
;
|
||||
; sector translate vector for the IBM 8" disk
|
||||
;
|
||||
TRANS: DEFB 1,7,13,19 ;sectors 1,2,3,4
|
||||
DEFB 25,5,11,17 ;sectors 5,6,7,8
|
||||
DEFB 23,3,9,15 ;sectors 9,10,11,12
|
||||
DEFB 21,2,8,14 ;sectors 13,14,15,16
|
||||
DEFB 20,26,6,12 ;sectors 17,18,19,20
|
||||
DEFB 18,24,4,10 ;sectors 21,22,23,24
|
||||
DEFB 16,22 ;sectors 25,26
|
||||
;
|
||||
; disk parameter block for the IBM 8" disk
|
||||
;
|
||||
DPB0: DEFW 26 ;sectors per track
|
||||
DEFB 3 ;block shift factor
|
||||
DEFB 7 ;block mask
|
||||
DEFB 0 ;extent mask
|
||||
DEFW 242 ;disk size-1
|
||||
DEFW 63 ;directory max
|
||||
DEFB 192 ;alloc 0
|
||||
DEFB 0 ;alloc 1
|
||||
DEFW 16 ;check size
|
||||
DEFW 2 ;track offset
|
||||
DEFB 0,0 ;physical sector size and shift
|
||||
;
|
||||
; signon message
|
||||
;
|
||||
SIGNON: DEFB 13,10
|
||||
DEFM 'LDRBIOS3 V1.1 for Z80SIM, '
|
||||
DEFM 'Copyright 1989-2006 by Udo Munk'
|
||||
DEFB 13,10,0
|
||||
;
|
||||
; end of fixed tables
|
||||
;
|
||||
; individual subroutines to perform each function
|
||||
;
|
||||
BOOT: LD HL,SIGNON ;print message
|
||||
BOOTL: LD A,(HL)
|
||||
OR A
|
||||
JP Z,WBOOT
|
||||
LD C,A
|
||||
CALL CONOUT
|
||||
INC HL
|
||||
JP BOOTL
|
||||
;
|
||||
; those are not implemented in loader bios
|
||||
;
|
||||
WBOOT:
|
||||
CONST:
|
||||
CONIN:
|
||||
LIST:
|
||||
AUXOUT:
|
||||
AUXIN:
|
||||
WRITE:
|
||||
LISTST:
|
||||
CONOST:
|
||||
AUXIST:
|
||||
AUXOST:
|
||||
DEVTBL:
|
||||
DEVINI:
|
||||
DRVTBL:
|
||||
MULTIO:
|
||||
FLUSH:
|
||||
TIME:
|
||||
SELMEM:
|
||||
SETBNK:
|
||||
XMOVE: RET
|
||||
;
|
||||
; console character output from register c
|
||||
;
|
||||
CONOUT: LD A,C ;get to accumulator
|
||||
OUT (CONDAT),A ;send character to console
|
||||
RET
|
||||
;
|
||||
;
|
||||
; i/o drivers for the disk follow
|
||||
;
|
||||
; move to the track 00 position of current drive
|
||||
; translate this call into a settrk call with parameter 00
|
||||
;
|
||||
HOME: LD C,0 ;select track 0
|
||||
JP SETTRK ;we will move to 00 on first read/write
|
||||
;
|
||||
; select disk given by register C
|
||||
;
|
||||
SELDSK: LD HL,0000H ;error return code
|
||||
LD A,C
|
||||
CP 0 ;we boot from drive 0 only
|
||||
RET NZ ;return error
|
||||
; disk number is in the proper range
|
||||
; return proper disk parameter header address
|
||||
OUT (FDCD),A ;selekt disk drive
|
||||
LD HL,DPH0
|
||||
RET
|
||||
;
|
||||
; set track given by register c
|
||||
;
|
||||
SETTRK: LD A,C
|
||||
OUT (FDCT),A
|
||||
RET
|
||||
;
|
||||
; set sector given by register c
|
||||
;
|
||||
SETSEC: LD A,C
|
||||
OUT (FDCS),A
|
||||
RET
|
||||
;
|
||||
; translate the sector given by BC using the
|
||||
; translate table given by DE
|
||||
;
|
||||
SECTRAN:
|
||||
EX DE,HL ;hl=.trans
|
||||
ADD HL,BC ;hl=.trans(sector)
|
||||
LD L,(HL) ;l = trans(sector)
|
||||
LD H,0 ;hl= trans(sector)
|
||||
RET ;with value in hl
|
||||
;
|
||||
; set dma address given by registers b and c
|
||||
;
|
||||
SETDMA: LD A,C ;low order address
|
||||
OUT (DMAL),A
|
||||
LD A,B ;high order address
|
||||
OUT (DMAH),A ;in dma
|
||||
RET
|
||||
;
|
||||
; perform read operation
|
||||
;
|
||||
READ: XOR A ;read command -> a
|
||||
OUT (FDCOP),A ;start i/o operation
|
||||
IN A,(FDCST) ;status of i/o operation -> a
|
||||
RET
|
||||
;
|
||||
; memory move
|
||||
;
|
||||
MOVE: EX DE,HL
|
||||
LDIR
|
||||
EX DE,HL
|
||||
RET
|
||||
;
|
||||
ENDDAT EQU $ ;end
|
||||
END ;of bios
|
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Write the CP/M 3 systemfiles to system tracks of drive A
|
||||
*
|
||||
* Copyright (C) 1988-2006 by Udo Munk
|
||||
*
|
||||
* History:
|
||||
* 29-APR-88 Development on TARGON/35 with AT&T Unix System V.3
|
||||
* 11-MAR-93 comments in english and ported to COHERENT 4.0
|
||||
* 02-OCT-06 modified to compile on modern POSIX OS's
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <memory.h>
|
||||
|
||||
/*
|
||||
* This program writes the CP/M 3 OS from the following files
|
||||
* onto the system tracks of the boot disk (drivea.cpm):
|
||||
*
|
||||
* boot loader boot.bin
|
||||
* cpmldr cpmldr.bin
|
||||
*/
|
||||
int main(void)
|
||||
{
|
||||
unsigned char sector[128];
|
||||
register int i;
|
||||
int fd, drivea, readed;
|
||||
|
||||
/* open drive A for writing */
|
||||
if ((drivea = open("../disks/drivea.cpm", O_WRONLY)) == -1) {
|
||||
perror("file ../disks/drivea.cpm");
|
||||
exit(1);
|
||||
}
|
||||
/* open boot loader (boot.bin) for reading */
|
||||
if ((fd = open("boot.bin", O_RDONLY)) == -1) {
|
||||
perror("file boot.bin");
|
||||
exit(1);
|
||||
}
|
||||
/* read boot loader */
|
||||
memset((char *) sector, 0, 128);
|
||||
read(fd, (char *) sector, 128);
|
||||
close(fd);
|
||||
/* and write it to disk in drive A */
|
||||
write(drivea, (char *) sector, 128);
|
||||
/* open CP/M 3 cpmldr file (cpmldr.bin) for reading */
|
||||
if ((fd = open("cpmldr.bin", O_RDONLY)) == -1) {
|
||||
perror("file cpmldr.bin");
|
||||
exit(1);
|
||||
}
|
||||
/* read from cpmldr.bin and write to disk in drive A */
|
||||
while ((readed = read(fd, (char *) sector, 128)) == 128)
|
||||
write(drivea, (char *) sector, 128);
|
||||
write(drivea, (char *) sector, 128);
|
||||
close(fd);
|
||||
close(drivea);
|
||||
return(0);
|
||||
}
|
@@ -1,503 +0,0 @@
|
||||
; MP/M 2 XIOS for Z80-Simulator
|
||||
;
|
||||
; Copyright (C) 1989-2006 by Udo Munk
|
||||
;
|
||||
.Z80
|
||||
CSEG
|
||||
;
|
||||
; i/o ports
|
||||
;
|
||||
CONSTA EQU 0 ;console status port
|
||||
CONDAT EQU 1 ;console data port
|
||||
PRTSTA EQU 2 ;printer status port
|
||||
PRTDAT EQU 3 ;printer data port
|
||||
AUXSTA EQU 4 ;auxilary status port
|
||||
AUXDAT EQU 5 ;auxilary data port
|
||||
FDCD EQU 10 ;fdc-port: # of drive
|
||||
FDCT EQU 11 ;fdc-port: # of track
|
||||
FDCS EQU 12 ;fdc-port: # of sector
|
||||
FDCOP EQU 13 ;fdc-port: command
|
||||
FDCST EQU 14 ;fdc-port: status
|
||||
DMAL EQU 15 ;dma-port: dma address low
|
||||
DMAH EQU 16 ;dma-port: dma address high
|
||||
MMUINI EQU 20 ;initialize mmu
|
||||
MMUSEL EQU 21 ;bank select mmu
|
||||
CLKCMD EQU 25 ;clock command
|
||||
CLKDAT EQU 26 ;clock data
|
||||
TIMER EQU 27 ;interrupt timer
|
||||
;
|
||||
; clock commands
|
||||
;
|
||||
GETSEC EQU 0 ;get seconds
|
||||
GETMIN EQU 1 ;get minutes
|
||||
GETHOU EQU 2 ;get hours
|
||||
GETDAL EQU 3 ;get days low
|
||||
GETDAH EQU 4 ;get days high
|
||||
;
|
||||
BDOS EQU 5 ;bdos calls
|
||||
SETTD EQU 104 ;bdos set time and date
|
||||
;
|
||||
POLL EQU 131 ;xdos poll function
|
||||
PLCI0 EQU 0 ;poll console in #0
|
||||
FLAGSET EQU 133 ;xdos flag set function
|
||||
SYSDATA EQU 154 ;xdos syste data address
|
||||
;
|
||||
; jump vector for individual subroutines
|
||||
;
|
||||
JP COMMONBASE ;commonbase
|
||||
JP WARMSTART ;warm start
|
||||
JP CONST ;console status
|
||||
JP CONIN ;console character in
|
||||
JP CONOUT ;console character out
|
||||
JP LIST ;list character out
|
||||
JP PUNCH ;not used by MP/M 2
|
||||
JP READER ;not used by MP/M 2
|
||||
JP HOME ;move head to home
|
||||
JP SELDSK ;select disk
|
||||
JP SETTRK ;set track numer
|
||||
JP SETSEC ;set sector number
|
||||
JP SETDMA ;set dma address
|
||||
JP READ ;read disk
|
||||
JP WRITE ;write disk
|
||||
JP LISTST ;not used by MP/M 2
|
||||
JP SECTRAN ;sector translate
|
||||
JP SELMEMORY ;select memory
|
||||
JP POLLDEVICE ;poll device
|
||||
JP STARTCLOCK ;start clock
|
||||
JP STOPCLOCK ;stop clock
|
||||
JP EXITREGION ;exit region
|
||||
JP MAXCONSOLE ;maximum console number
|
||||
JP SYSTEMINIT ;system initialization
|
||||
JP IDLE ;idle prozedure
|
||||
;
|
||||
COMMONBASE:
|
||||
JP COLDSTART
|
||||
SWTUSER:
|
||||
JP $-$
|
||||
SWTSYS: JP $-$
|
||||
PDISP: JP $-$
|
||||
XDOS: JP $-$
|
||||
SYSDAT: DEFW $-$
|
||||
;
|
||||
COLDSTART:
|
||||
WARMSTART:
|
||||
LD C,0
|
||||
JP XDOS ;system reset, terminate prozess
|
||||
;
|
||||
; MP/M II V2.0 Console Bios
|
||||
;
|
||||
CONST:
|
||||
CALL PTBLJMP ;compute and jump to handler
|
||||
DW PTSTI0
|
||||
;
|
||||
CONIN:
|
||||
CALL PTBLJMP ;compute and jump to handle
|
||||
DW PTIN0
|
||||
;
|
||||
CONOUT:
|
||||
CALL PTBLJMP ;compute and jump to handler
|
||||
DW PTOUT0
|
||||
;
|
||||
PTSTI0: IN A,(CONSTA) ;console 0 input
|
||||
RET
|
||||
;
|
||||
PTIN0: LD C,POLL ;poll console 0 status in
|
||||
LD E,PLCI0
|
||||
CALL XDOS ;poll console 0
|
||||
IN A,(CONDAT) ;read character
|
||||
AND 7FH ;strip parity
|
||||
RET
|
||||
;
|
||||
PTOUT0: LD A,C ;console 0 output
|
||||
OUT (CONDAT),A
|
||||
RET
|
||||
;
|
||||
PTBLJMP: ;compute and jump to handler
|
||||
LD A,D
|
||||
ADD A,A ;double table index for adress offset
|
||||
POP HL ;return adress of jump table
|
||||
LD E,A
|
||||
LD D,0
|
||||
ADD HL,DE ;table index * 2 + table base
|
||||
LD E,(HL) ;get handler address
|
||||
INC HL
|
||||
LD D,(HL)
|
||||
EX DE,HL
|
||||
JP (HL) ;jump to computed handler
|
||||
;
|
||||
LIST:
|
||||
LD A,C
|
||||
OUT (PRTDAT),A
|
||||
RET
|
||||
;
|
||||
; not used by MP/M 2
|
||||
PUNCH:
|
||||
READER:
|
||||
LISTST:
|
||||
RET
|
||||
;
|
||||
; MP/M II V2.0 Xios
|
||||
;
|
||||
; select/protect memory
|
||||
; BC = address of memory descriptor
|
||||
SELMEMORY:
|
||||
LD HL,3 ;offset memory bank in memory descriptor
|
||||
ADD HL,BC
|
||||
LD A,(HL) ;get bank
|
||||
OUT (MMUSEL),A ;and select it
|
||||
RET
|
||||
;
|
||||
; poll character devices
|
||||
;
|
||||
POLLDEVICE:
|
||||
JP PTSTI0 ;poll console 0 status in
|
||||
;
|
||||
; start clock
|
||||
;
|
||||
STARTCLOCK:
|
||||
LD A,0FFH
|
||||
LD (TICKN),A
|
||||
RET
|
||||
;
|
||||
; stop clock
|
||||
;
|
||||
STOPCLOCK:
|
||||
XOR A
|
||||
LD (TICKN),A
|
||||
RET
|
||||
;
|
||||
; exit region:
|
||||
; enable interrupt if not preempted or in dispatcher
|
||||
;
|
||||
EXITREGION:
|
||||
LD A,(PREEMP)
|
||||
OR A
|
||||
RET NZ
|
||||
EI
|
||||
RET
|
||||
;
|
||||
; maximum console number
|
||||
;
|
||||
MAXCONSOLE:
|
||||
LD A,1
|
||||
RET
|
||||
;
|
||||
; system initialization
|
||||
; C MP/M debugger restart #
|
||||
; DE MP/M entry point for debugger
|
||||
; HL BIOS jump table address
|
||||
;
|
||||
SYSTEMINIT:
|
||||
;
|
||||
;doesn't work
|
||||
PUSH HL
|
||||
LD C,SYSDATA ;get system data page address
|
||||
CALL XDOS
|
||||
CALL SETTOD ;set tod from hardware clock
|
||||
POP HL
|
||||
;
|
||||
LD A,8 ;initialize banked memory
|
||||
OUT (MMUINI),A
|
||||
LD B,A
|
||||
;
|
||||
SYS1: DEC B
|
||||
LD A,B
|
||||
OUT (MMUSEL),A ;select every bank and initialize
|
||||
LD A,0C3H ;jp instruction
|
||||
LD (0),A
|
||||
LD (38H),A
|
||||
LD (1),HL
|
||||
PUSH HL
|
||||
LD HL,INTHND
|
||||
LD (39H),HL
|
||||
POP HL
|
||||
JP NZ,SYS1
|
||||
;
|
||||
LD HL,SIGNON ;print message
|
||||
SYS2: LD A,(HL)
|
||||
OR A
|
||||
JP Z,SYS3
|
||||
OUT (CONDAT),A
|
||||
INC HL
|
||||
JP SYS2
|
||||
;
|
||||
SYS3: IM 1
|
||||
LD A,1 ;enable 20ms interrupt timer
|
||||
OUT (TIMER),A
|
||||
EI
|
||||
RET
|
||||
;
|
||||
; set mp/m tod from hardware clock
|
||||
; hl = tod address
|
||||
;
|
||||
SETTOD: LD A,GETDAL
|
||||
OUT (CLKCMD),A
|
||||
IN A,(CLKDAT)
|
||||
LD (HL),A
|
||||
INC HL
|
||||
LD A,GETDAH
|
||||
OUT (CLKCMD),A
|
||||
IN A,(CLKDAT)
|
||||
LD (HL),A
|
||||
INC HL
|
||||
LD A,GETHOU
|
||||
OUT (CLKCMD),A
|
||||
IN A,(CLKDAT)
|
||||
LD (HL),A
|
||||
INC HL
|
||||
LD A,GETMIN
|
||||
OUT (CLKCMD),A
|
||||
IN A,(CLKDAT)
|
||||
LD (HL),A
|
||||
RET
|
||||
;
|
||||
; idle
|
||||
;
|
||||
IDLE: EI
|
||||
HALT
|
||||
RET
|
||||
;
|
||||
; interrupt handler
|
||||
;
|
||||
INTHND: LD (SVDHL),HL ;save registers
|
||||
POP HL
|
||||
LD (SVDRET),HL
|
||||
PUSH AF
|
||||
LD HL,0
|
||||
ADD HL,SP
|
||||
LD (SVDSP),HL
|
||||
LD SP,INTSTK
|
||||
PUSH DE
|
||||
PUSH BC
|
||||
LD A,0FFH ;set preempted flag
|
||||
LD (PREEMP),A
|
||||
LD A,(TICKN)
|
||||
OR A ;test tick, indicates delayed process
|
||||
JP Z,INTHND1
|
||||
LD C,FLAGSET ;set flag #1 each tick
|
||||
LD E,1
|
||||
CALL XDOS
|
||||
INTHND1:
|
||||
LD HL,CNT50 ;decrement tick counter
|
||||
DEC (HL)
|
||||
JP NZ,INTDONE
|
||||
LD (HL),50 ;set flag #2 each second
|
||||
LD C,FLAGSET
|
||||
LD E,2
|
||||
CALL XDOS
|
||||
INTDONE:
|
||||
XOR A ;clear preempted flag
|
||||
LD (PREEMP),A
|
||||
POP BC ;restore registers
|
||||
POP DE
|
||||
LD HL,(SVDSP)
|
||||
LD SP,HL
|
||||
POP AF
|
||||
LD HL,(SVDRET)
|
||||
PUSH HL
|
||||
LD HL,(PDISP+1) ;dispatch processes
|
||||
PUSH HL
|
||||
LD HL,(SVDHL)
|
||||
RETI
|
||||
;
|
||||
; i/o drivers for disks
|
||||
;
|
||||
; move to the track 00 position of current drive
|
||||
; translate this call into a settrk call with parameter 00
|
||||
;
|
||||
HOME: LD C,0 ;select track 0
|
||||
JP SETTRK ;we will move to 00 on first read/write
|
||||
;
|
||||
; select disk given by register C
|
||||
;
|
||||
SELDSK: LD HL,0000H ;error return code
|
||||
LD A,C
|
||||
CP 4 ;must be between 0 and 3
|
||||
JR NC,SELHD ;no carry if 4,5,...
|
||||
; disk number is in the proper range
|
||||
; compute proper disk parameter header address
|
||||
OUT (FDCD),A ;selekt disk drive
|
||||
LD L,A ;L=disk number 0,1,2,3
|
||||
ADD HL,HL ;*2
|
||||
ADD HL,HL ;*4
|
||||
ADD HL,HL ;*8
|
||||
ADD HL,HL ;*16 (size of each header)
|
||||
LD DE,DPBASE
|
||||
ADD HL,DE ;HL=.dpbase(diskno*16)
|
||||
RET
|
||||
SELHD: CP 8 ;select the harddisk?
|
||||
RET NZ ;no, error
|
||||
OUT (FDCD),A ;select disk drive
|
||||
LD HL,HDBASE ;HL=hdbase for harddisk
|
||||
RET
|
||||
;
|
||||
; set track given by register c
|
||||
;
|
||||
SETTRK: LD A,C
|
||||
OUT (FDCT),A
|
||||
RET
|
||||
;
|
||||
; set sector given by register c
|
||||
;
|
||||
SETSEC: LD A,C
|
||||
OUT (FDCS),A
|
||||
RET
|
||||
;
|
||||
; translate the sector given by BC using the
|
||||
; translate table given by DE
|
||||
;
|
||||
SECTRAN:
|
||||
EX DE,HL ;HL=.trans
|
||||
ADD HL,BC ;HL=.trans(sector)
|
||||
LD L,(HL) ;L = trans(sector)
|
||||
LD H,0 ;HL= trans(sector)
|
||||
RET ;with value in HL
|
||||
;
|
||||
; set dma address given by registers b and c
|
||||
;
|
||||
SETDMA: LD A,C ;low order address
|
||||
OUT (DMAL),A
|
||||
LD A,B ;high order address
|
||||
OUT (DMAH),A ;in dma
|
||||
RET
|
||||
;
|
||||
; perform read operation
|
||||
;
|
||||
READ: XOR A ;read command -> A
|
||||
JP WAITIO ;to perform the actual i/o
|
||||
;
|
||||
; perform a write operation
|
||||
;
|
||||
WRITE: LD A,1 ;write command -> A
|
||||
;
|
||||
; enter here from read and write to perform the actual i/o
|
||||
; operation. return a 00h in register a if the operation completes
|
||||
; properly, and 01h if an error occurs during the read or write
|
||||
;
|
||||
; in this case, we have saved the disk number in 'diskno' (0-3)
|
||||
; the track number in 'track' (0-76)
|
||||
; the sector number in 'sector' (1-26)
|
||||
; the dma address in 'dmaad' (0-65535)
|
||||
;
|
||||
WAITIO: OUT (FDCOP),A ;start i/o operation
|
||||
IN A,(FDCST) ;status of i/o operation -> A
|
||||
RET
|
||||
;
|
||||
; XIOS data segment
|
||||
;
|
||||
SIGNON: DEFB 13,10
|
||||
DEFM 'MP/M 2 XIOS V1.1 for Z80SIM, '
|
||||
DEFM 'Copyright 1989-2006 by Udo Munk'
|
||||
DEFB 13,10,0
|
||||
;
|
||||
TICKN: DEFB 0 ;flag for tick
|
||||
PREEMP: DEFB 0 ;preempted flag
|
||||
TOD: DEFS 4 ;time of day
|
||||
SVDHL: DEFS 2 ;save hl during interrupt
|
||||
SVDRET: DEFS 2 ;save return address during interrupt
|
||||
SVDSP: DEFS 2 ;save sp during interrupt
|
||||
CNT50: DEFB 50 ;50 ticks a 20ms = 1 second
|
||||
;interrupt stack
|
||||
DEFW 0C7C7H,0C7C7H,0C7C7H,0C7C7H
|
||||
DEFW 0C7C7H,0C7C7H,0C7C7H,0C7C7H
|
||||
DEFW 0C7C7H,0C7C7H,0C7C7H,0C7C7H
|
||||
DEFW 0C7C7H,0C7C7H,0C7C7H,0C7C7H
|
||||
INTSTK:
|
||||
;
|
||||
; fixed data tables for four-drive standard
|
||||
; IBM-compatible 8" disks
|
||||
;
|
||||
; disk parameter header for disk 00
|
||||
DPBASE: DEFW TRANS,0000H
|
||||
DEFW 0000H,0000H
|
||||
DEFW DIRBF,DPBLK
|
||||
DEFW CHK00,ALL00
|
||||
; disk parameter header for disk 01
|
||||
DEFW TRANS,0000H
|
||||
DEFW 0000H,0000H
|
||||
DEFW DIRBF,DPBLK
|
||||
DEFW CHK01,ALL01
|
||||
; disk parameter header for disk 02
|
||||
DEFW TRANS,0000H
|
||||
DEFW 0000H,0000H
|
||||
DEFW DIRBF,DPBLK
|
||||
DEFW CHK02,ALL02
|
||||
; disk parameter header for disk 03
|
||||
DEFW TRANS,0000H
|
||||
DEFW 0000H,0000H
|
||||
DEFW DIRBF,DPBLK
|
||||
DEFW CHK03,ALL03
|
||||
;
|
||||
; sector translate vector for the IBM 8" disks
|
||||
;
|
||||
TRANS: DEFB 1,7,13,19 ;sectors 1,2,3,4
|
||||
DEFB 25,5,11,17 ;sectors 5,6,7,8
|
||||
DEFB 23,3,9,15 ;sectors 9,10,11,12
|
||||
DEFB 21,2,8,14 ;sectors 13,14,15,16
|
||||
DEFB 20,26,6,12 ;sectors 17,18,19,20
|
||||
DEFB 18,24,4,10 ;sectors 21,22,23,24
|
||||
DEFB 16,22 ;sectors 25,26
|
||||
;
|
||||
; disk parameter block, common to all IBM 8" disks
|
||||
;
|
||||
DPBLK: DEFW 26 ;sectors per track
|
||||
DEFB 3 ;block shift factor
|
||||
DEFB 7 ;block mask
|
||||
DEFB 0 ;extent mask
|
||||
DEFW 242 ;disk size-1
|
||||
DEFW 63 ;directory max
|
||||
DEFB 192 ;alloc 0
|
||||
DEFB 0 ;alloc 1
|
||||
DEFW 16 ;check size
|
||||
DEFW 2 ;track offset
|
||||
;
|
||||
; fixed data tables for 4MB harddisk
|
||||
;
|
||||
; disk parameter header
|
||||
HDBASE: DEFW HDTRA,0000H
|
||||
DEFW 0000H,0000H
|
||||
DEFW DIRBF,HDBLK
|
||||
DEFW CHKHD,ALLHD
|
||||
;
|
||||
; sector translate vector for the hardisk
|
||||
;
|
||||
HDTRA: DEFB 1,2,3,4,5,6,7,8,9,10
|
||||
DEFB 11,12,13,14,15,16,17,18,19,20
|
||||
DEFB 21,22,23,24,25,26,27,28,29,30
|
||||
DEFB 31,32,33,34,35,36,37,38,39,40
|
||||
DEFB 41,42,43,44,45,46,47,48,49,50
|
||||
DEFB 51,52,53,54,55,56,57,58,59,60
|
||||
DEFB 61,62,63,64,65,66,67,68,69,70
|
||||
DEFB 71,72,73,74,75,76,77,78,79,80
|
||||
DEFB 81,82,83,84,85,86,87,88,89,90
|
||||
DEFB 91,92,93,94,95,96,97,98,99,100
|
||||
DEFB 101,102,103,104,105,106,107,108,109,110
|
||||
DEFB 111,112,113,114,115,116,117,118,119,120
|
||||
DEFB 121,122,123,124,125,126,127,128
|
||||
;
|
||||
; disk parameter block for harddisk
|
||||
;
|
||||
HDBLK: DEFW 128 ;sectors per track
|
||||
DEFB 4 ;block shift factor
|
||||
DEFB 15 ;block mask
|
||||
DEFB 0 ;extent mask
|
||||
DEFW 2039 ;disk size-1
|
||||
DEFW 1023 ;directory max
|
||||
DEFB 255 ;alloc 0
|
||||
DEFB 255 ;alloc 1
|
||||
DEFW 0 ;check size
|
||||
DEFW 0 ;track offset
|
||||
;
|
||||
DIRBF: DEFS 128 ;scratch directory area
|
||||
ALL00: DEFS 31 ;allocation vector 0
|
||||
ALL01: DEFS 31 ;allocation vector 1
|
||||
ALL02: DEFS 31 ;allocation vector 2
|
||||
ALL03: DEFS 31 ;allocation vector 3
|
||||
ALLHD: DEFS 255 ;allocation vector harddisk
|
||||
CHK00: DEFS 16 ;check vector 0
|
||||
CHK01: DEFS 16 ;check vector 1
|
||||
CHK02: DEFS 16 ;check vector 2
|
||||
CHK03: DEFS 16 ;check vector 3
|
||||
CHKHD: DEFS 0 ;check vector harddisk
|
||||
;
|
||||
END
|
@@ -1,177 +0,0 @@
|
||||
; MP/M 2 LDRBIOS for Z80-Simulator
|
||||
;
|
||||
; Copyright (C) 1989-2006 by Udo Munk
|
||||
;
|
||||
ORG 1700H
|
||||
;
|
||||
; I/O ports
|
||||
;
|
||||
CONSTA EQU 0 ;console status port
|
||||
CONDAT EQU 1 ;console data port
|
||||
FDCD EQU 10 ;fdc-port: # of drive
|
||||
FDCT EQU 11 ;fdc-port: # of track
|
||||
FDCS EQU 12 ;fdc-port: # of sector
|
||||
FDCOP EQU 13 ;fdc-port: command
|
||||
FDCST EQU 14 ;fdc-port: status
|
||||
DMAL EQU 15 ;dma-port: dma address low
|
||||
DMAH EQU 16 ;dma-port: dma address high
|
||||
;
|
||||
; jump vector for individual subroutines
|
||||
;
|
||||
JP BOOT ;perform cold start initialization
|
||||
JP WBOOT ;perform warm start initialization
|
||||
JP CONST ;check for console input char ready
|
||||
JP CONIN ;read console character in
|
||||
JP CONOUT ;write console character out
|
||||
JP LIST ;write list character out
|
||||
JP AUXOUT ;write auxiliary output char
|
||||
JP AUXIN ;read auxiliary input char
|
||||
JP HOME ;move head to track 0 on selcted disk
|
||||
JP SELDSK ;select disk drive
|
||||
JP SETTRK ;set track number
|
||||
JP SETSEC ;set sector number
|
||||
JP SETDMA ;set dma address
|
||||
JP READ ;read specified sector
|
||||
JP WRITE ;write specified sector
|
||||
JP LISTST ;return list status
|
||||
JP SECTRAN ;translate logical to physical sector
|
||||
;
|
||||
; fixed data tables for a IBM-compatible 8" disk
|
||||
;
|
||||
; disk parameter header
|
||||
;
|
||||
DPH: DEFW TRANS,0000H
|
||||
DEFW 0000H,0000H
|
||||
DEFW DIRBF,DPBLK
|
||||
DEFW CHK00,ALL00
|
||||
;
|
||||
; sector translate vector for the IBM 8" disk
|
||||
;
|
||||
TRANS: DEFB 1,7,13,19 ;sectors 1,2,3,4
|
||||
DEFB 25,5,11,17 ;sectors 5,6,7,8
|
||||
DEFB 23,3,9,15 ;sectors 9,10,11,12
|
||||
DEFB 21,2,8,14 ;sectors 13,14,15,16
|
||||
DEFB 20,26,6,12 ;sectors 17,18,19,20
|
||||
DEFB 18,24,4,10 ;sectors 21,22,23,24
|
||||
DEFB 16,22 ;sectors 25,26
|
||||
;
|
||||
; disk parameter block for the IBM 8" disk
|
||||
;
|
||||
DPBLK: DEFW 26 ;sectors per track
|
||||
DEFB 3 ;block shift factor
|
||||
DEFB 7 ;block mask
|
||||
DEFB 0 ;extent mask
|
||||
DEFW 242 ;disk size-1
|
||||
DEFW 63 ;directory max
|
||||
DEFB 192 ;alloc 0
|
||||
DEFB 0 ;alloc 1
|
||||
DEFW 16 ;check size
|
||||
DEFW 2 ;track offset
|
||||
;
|
||||
; signon message
|
||||
;
|
||||
SIGNON: DEFB 13,10
|
||||
DEFM 'LDRBIOS V1.0 for Z80SIM, '
|
||||
DEFM 'Copyright 1989-2006 by Udo Munk'
|
||||
DEFB 13,10,0
|
||||
;
|
||||
; end of fixed tables
|
||||
;
|
||||
; individual subroutines to perform each function
|
||||
;
|
||||
BOOT: LD HL,SIGNON ;print message
|
||||
BOOTL: LD A,(HL)
|
||||
OR A
|
||||
JP Z,WBOOT
|
||||
LD C,A
|
||||
CALL CONOUT
|
||||
INC HL
|
||||
JP BOOTL
|
||||
;
|
||||
; those are not implemented in loader bios
|
||||
;
|
||||
WBOOT:
|
||||
CONST:
|
||||
CONIN:
|
||||
LIST:
|
||||
AUXOUT:
|
||||
AUXIN:
|
||||
WRITE:
|
||||
LISTST:
|
||||
RET
|
||||
;
|
||||
; console character output from register c
|
||||
;
|
||||
CONOUT: LD A,C ;get to accumulator
|
||||
OUT (CONDAT),A ;send character to console
|
||||
RET
|
||||
;
|
||||
;
|
||||
; i/o drivers for the disk follow
|
||||
;
|
||||
; move to the track 00 position of current drive
|
||||
; translate this call into a settrk call with parameter 00
|
||||
;
|
||||
HOME: LD C,0 ;select track 0
|
||||
JP SETTRK ;we will move to 00 on first read/write
|
||||
;
|
||||
; select disk given by register C
|
||||
;
|
||||
SELDSK: PUSH BC
|
||||
CALL BOOT ;signon message
|
||||
POP BC
|
||||
LD HL,0000H ;error return code
|
||||
LD A,C
|
||||
CP 0 ;we boot from drive 0 only
|
||||
RET NZ ;return error
|
||||
; disk number is in the proper range
|
||||
; return proper disk parameter header address
|
||||
OUT (FDCD),A ;selekt disk drive
|
||||
LD HL,DPH
|
||||
RET
|
||||
;
|
||||
; set track given by register c
|
||||
;
|
||||
SETTRK: LD A,C
|
||||
OUT (FDCT),A
|
||||
RET
|
||||
;
|
||||
; set sector given by register c
|
||||
;
|
||||
SETSEC: LD A,C
|
||||
OUT (FDCS),A
|
||||
RET
|
||||
;
|
||||
; translate the sector given by BC using the
|
||||
; translate table given by DE
|
||||
;
|
||||
SECTRAN:
|
||||
EX DE,HL ;hl=.trans
|
||||
ADD HL,BC ;hl=.trans(sector)
|
||||
LD L,(HL) ;l = trans(sector)
|
||||
LD H,0 ;hl= trans(sector)
|
||||
RET ;with value in hl
|
||||
;
|
||||
; set dma address given by registers b and c
|
||||
;
|
||||
SETDMA: LD A,C ;low order address
|
||||
OUT (DMAL),A
|
||||
LD A,B ;high order address
|
||||
OUT (DMAH),A ;in dma
|
||||
RET
|
||||
;
|
||||
; perform read operation
|
||||
;
|
||||
READ: XOR A ;read command -> a
|
||||
OUT (FDCOP),A ;start i/o operation
|
||||
IN A,(FDCST) ;status of i/o operation -> a
|
||||
RET
|
||||
;
|
||||
BEGDAT EQU $
|
||||
DIRBF: DEFS 128 ;scratch directory area
|
||||
ALL00: DEFS 31 ;allocation vector
|
||||
CHK00: DEFS 16 ;check vector
|
||||
;
|
||||
ENDDAT EQU $ ;end
|
||||
DATSIZ EQU $-BEGDAT ;size of data area
|
||||
END ;of bios
|
@@ -1,74 +0,0 @@
|
||||
CFLAGS= -O -c -Wall
|
||||
LFLAGS= -s
|
||||
|
||||
OBJ = sim0.o \
|
||||
sim1.o \
|
||||
sim2.o \
|
||||
sim3.o \
|
||||
sim4.o \
|
||||
sim5.o \
|
||||
sim6.o \
|
||||
sim7.o \
|
||||
simctl.o \
|
||||
simint.o \
|
||||
iosim.o \
|
||||
simfun.o \
|
||||
simglb.o
|
||||
|
||||
all: ../auxin ../auxout ../cpmsim
|
||||
@echo "done."
|
||||
|
||||
../auxin:
|
||||
test -f ../auxin || mknod ../auxin p
|
||||
|
||||
../auxout:
|
||||
test -f ../auxout || mknod ../auxout p
|
||||
|
||||
../cpmsim : $(OBJ)
|
||||
cc $(OBJ) $(LFLAGS) -o ../cpmsim
|
||||
|
||||
sim0.c:
|
||||
lnsrc
|
||||
|
||||
sim0.o : sim0.c sim.h simglb.h
|
||||
cc $(CFLAGS) sim0.c
|
||||
|
||||
sim1.o : sim1.c sim.h simglb.h
|
||||
cc $(CFLAGS) sim1.c
|
||||
|
||||
sim2.o : sim2.c sim.h simglb.h
|
||||
cc $(CFLAGS) sim2.c
|
||||
|
||||
sim3.o : sim3.c sim.h simglb.h
|
||||
cc $(CFLAGS) sim3.c
|
||||
|
||||
sim4.o : sim4.c sim.h simglb.h
|
||||
cc $(CFLAGS) sim4.c
|
||||
|
||||
sim5.o : sim5.c sim.h simglb.h
|
||||
cc $(CFLAGS) sim5.c
|
||||
|
||||
sim6.o : sim6.c sim.h simglb.h
|
||||
cc $(CFLAGS) sim6.c
|
||||
|
||||
sim7.o : sim7.c sim.h simglb.h
|
||||
cc $(CFLAGS) sim7.c
|
||||
|
||||
simctl.o : simctl.c sim.h simglb.h
|
||||
cc $(CFLAGS) simctl.c
|
||||
|
||||
simint.o : simint.c sim.h simglb.h
|
||||
cc $(CFLAGS) simint.c
|
||||
|
||||
iosim.o : iosim.c sim.h simglb.h
|
||||
cc $(CFLAGS) iosim.c
|
||||
|
||||
simfun.o : simfun.c sim.h
|
||||
cc $(CFLAGS) simfun.c
|
||||
|
||||
simglb.o : simglb.c sim.h
|
||||
cc $(CFLAGS) simglb.c
|
||||
|
||||
clean:
|
||||
rm -f *.o
|
||||
ulnsrc
|
@@ -1,868 +0,0 @@
|
||||
/*
|
||||
* Z80SIM - a Z80-CPU simulator
|
||||
*
|
||||
* Copyright (C) 1987-2006 by Udo Munk
|
||||
*
|
||||
* This modul contains a complex I/O-simulation for running
|
||||
* CP/M 2, CP/M 3, MP/M...
|
||||
* Please note this this doesn't emulate any hardware which
|
||||
* ever existed, we've got all virtual circuits in here!
|
||||
*
|
||||
* History:
|
||||
* 28-SEP-87 Development on TARGON/35 with AT&T Unix System V.3
|
||||
* 19-MAY-89 Additions for CP/M 3.0 und MP/M
|
||||
* 23-DEC-90 Ported to COHERENT 3.0
|
||||
* 10-JUN-92 Some optimization done
|
||||
* 25-JUN-92 Flush output of stdout only at every OUT to port 0
|
||||
* 25-JUN-92 Comments in english and ported to COHERENT 4.0
|
||||
* 05-OCT-06 modified to compile on modern POSIX OS's
|
||||
* 18-NOV-06 added a second harddisk
|
||||
*/
|
||||
|
||||
/*
|
||||
* This module contains the I/O handlers for a simulation
|
||||
* of the hardware required for a CP/M system.
|
||||
*
|
||||
* Used I/O ports:
|
||||
*
|
||||
* 0 - console status
|
||||
* 1 - console data
|
||||
*
|
||||
* 2 - printer status
|
||||
* 3 - printer data
|
||||
*
|
||||
* 4 - auxilary status
|
||||
* 5 - auxilary data
|
||||
*
|
||||
* 10 - FDC drive
|
||||
* 11 - FDC track
|
||||
* 12 - FDC sector
|
||||
* 13 - FDC command
|
||||
* 14 - FDC status
|
||||
*
|
||||
* 15 - DMA destination address low
|
||||
* 16 - DMA destination address high
|
||||
*
|
||||
* 20 - MMU initialization
|
||||
* 21 - MMU bank select
|
||||
*
|
||||
* 25 - clock command
|
||||
* 26 - clock data
|
||||
* 27 - 20ms timer causing INT, only usable in IM 1
|
||||
*
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include "sim.h"
|
||||
#include "simglb.h"
|
||||
|
||||
/*
|
||||
* Structure to describe a emulated floppy disk drive:
|
||||
* pointer to filename
|
||||
* pointer to file descriptor
|
||||
* number of tracks
|
||||
* number of sectors
|
||||
*/
|
||||
struct dskdef {
|
||||
char *fn;
|
||||
int *fd;
|
||||
unsigned int tracks;
|
||||
unsigned int sectors;
|
||||
};
|
||||
|
||||
static BYTE drive; /* current drive A..P (0..15) */
|
||||
static BYTE track; /* current track (0..255) */
|
||||
static BYTE sector; /* current sektor (0..255) */
|
||||
static BYTE status; /* status of last I/O operation on FDC */
|
||||
static BYTE dmadl; /* current DMA adresse destination low */
|
||||
static BYTE dmadh; /* current DMA adresse destination high */
|
||||
static BYTE clkcmd; /* clock command */
|
||||
static BYTE timer; /* 20ms timer */
|
||||
static int drivea; /* fd for file "drivea.cpm" */
|
||||
static int driveb; /* fd for file "driveb.cpm" */
|
||||
static int drivec; /* fd for file "drivec.cpm" */
|
||||
static int drived; /* fd for file "drived.cpm" */
|
||||
static int drivee; /* fd for file "drivee.cpm" */
|
||||
static int drivef; /* fd for file "drivef.cpm" */
|
||||
static int driveg; /* fd for file "driveg.cpm" */
|
||||
static int driveh; /* fd for file "driveh.cpm" */
|
||||
static int drivei; /* fd for file "drivei.cpm" */
|
||||
static int drivej; /* fd for file "drivej.cpm" */
|
||||
static int drivek; /* fd for file "drivek.cpm" */
|
||||
static int drivel; /* fd for file "drivel.cpm" */
|
||||
static int drivem; /* fd for file "drivem.cpm" */
|
||||
static int driven; /* fd for file "driven.cpm" */
|
||||
static int driveo; /* fd for file "driveo.cpm" */
|
||||
static int drivep; /* fd for file "drivep.cpm" */
|
||||
static int printer; /* fd for file "printer.cpm" */
|
||||
static int auxin; /* fd for pipe "auxin" */
|
||||
static int auxout; /* fd for pipe "auxout" */
|
||||
static int aux_in_eof; /* status of pipe "auxin" (<>0 means EOF) */
|
||||
static int pid_rec; /* PID of the receiving process for auxiliary */
|
||||
static char last_char; /* buffer for 1 character (console status) */
|
||||
|
||||
static struct dskdef disks[16] = {
|
||||
{ "disks/drivea.cpm", &drivea, 77, 26 },
|
||||
{ "disks/driveb.cpm", &driveb, 77, 26 },
|
||||
{ "disks/drivec.cpm", &drivec, 77, 26 },
|
||||
{ "disks/drived.cpm", &drived, 77, 26 },
|
||||
{ "disks/drivee.cpm", &drivee, -1, -1 },
|
||||
{ "disks/drivef.cpm", &drivef, -1, -1 },
|
||||
{ "disks/driveg.cpm", &driveg, -1, -1 },
|
||||
{ "disks/driveh.cpm", &driveh, -1, -1 },
|
||||
{ "disks/drivei.cpm", &drivei, 255, 128 },
|
||||
{ "disks/drivej.cpm", &drivej, 255, 128 },
|
||||
{ "disks/drivek.cpm", &drivek, -1, -1 },
|
||||
{ "disks/drivel.cpm", &drivel, -1, -1 },
|
||||
{ "disks/drivem.cpm", &drivem, -1, -1 },
|
||||
{ "disks/driven.cpm", &driven, -1, -1 },
|
||||
{ "disks/driveo.cpm", &driveo, -1, -1 },
|
||||
{ "disks/drivep.cpm", &drivep, -1, -1 }
|
||||
};
|
||||
|
||||
/*
|
||||
* MMU:
|
||||
* ===
|
||||
*
|
||||
* +--------+
|
||||
* 16KB | common |
|
||||
* +--------+
|
||||
* +--------+ +--------+ .......... +--------+
|
||||
* | | | | | |
|
||||
* 48KB | | | | .......... | |
|
||||
* | bank 0 | | bank 1 | | bank n |
|
||||
* +--------+ +--------+ .......... +--------+
|
||||
*/
|
||||
#define MAXSEG 16 /* max. number of memory banks */
|
||||
#define SEGSIZ 49152 /* size of one bank = 48KBytes */
|
||||
static char *mmu[MAXSEG]; /* MMU with pointers to the banks */
|
||||
static int selbnk; /* current bank */
|
||||
static int maxbnk; /* number of initialized banks */
|
||||
|
||||
/*
|
||||
* Forward declaration of the I/O handlers for all used ports
|
||||
*/
|
||||
static BYTE io_trap(void);
|
||||
static BYTE cond_in(void), cond_out(BYTE), cons_in(void), cons_out(BYTE);
|
||||
static BYTE prtd_in(void), prtd_out(BYTE), prts_in(void), prts_out(BYTE);
|
||||
static BYTE auxd_in(void), auxd_out(BYTE), auxs_in(void), auxs_out(BYTE);
|
||||
static BYTE fdcd_in(void), fdcd_out(BYTE);
|
||||
static BYTE fdct_in(void), fdct_out(BYTE);
|
||||
static BYTE fdcs_in(void), fdcs_out(BYTE);
|
||||
static BYTE fdco_in(void), fdco_out(BYTE);
|
||||
static BYTE fdcx_in(void), fdcx_out(BYTE);
|
||||
static BYTE dmal_in(void), dmal_out(BYTE);
|
||||
static BYTE dmah_in(void), dmah_out(BYTE);
|
||||
static BYTE mmui_in(void), mmui_out(BYTE), mmus_in(void), mmus_out(BYTE);
|
||||
static BYTE clkc_in(void), clkc_out(BYTE), clkd_in(void), clkd_out(BYTE);
|
||||
static BYTE time_in(void), time_out(BYTE);
|
||||
static void int_timer(int);
|
||||
|
||||
static int to_bcd(int), get_date(struct tm *);
|
||||
|
||||
/*
|
||||
* This array contains two function pointer for every
|
||||
* active port, one for input and one for output.
|
||||
*/
|
||||
static BYTE (*port[256][2]) () = {
|
||||
{ cons_in, cons_out }, /* port 0 */
|
||||
{ cond_in, cond_out }, /* port 1 */
|
||||
{ prts_in, prts_out }, /* port 2 */
|
||||
{ prtd_in, prtd_out }, /* port 3 */
|
||||
{ auxs_in, auxs_out }, /* port 4 */
|
||||
{ auxd_in, auxd_out }, /* port 5 */
|
||||
{ io_trap, io_trap }, /* port 6 */
|
||||
{ io_trap, io_trap }, /* port 7 */
|
||||
{ io_trap, io_trap }, /* port 8 */
|
||||
{ io_trap, io_trap }, /* port 9 */
|
||||
{ fdcd_in, fdcd_out }, /* port 10 */
|
||||
{ fdct_in, fdct_out }, /* port 11 */
|
||||
{ fdcs_in, fdcs_out }, /* port 12 */
|
||||
{ fdco_in, fdco_out }, /* port 13 */
|
||||
{ fdcx_in, fdcx_out }, /* port 14 */
|
||||
{ dmal_in, dmal_out }, /* port 15 */
|
||||
{ dmah_in, dmah_out }, /* port 16 */
|
||||
{ io_trap, io_trap }, /* port 17 */
|
||||
{ io_trap, io_trap }, /* port 18 */
|
||||
{ io_trap, io_trap }, /* port 19 */
|
||||
{ mmui_in, mmui_out }, /* port 20 */
|
||||
{ mmus_in, mmus_out }, /* port 21 */
|
||||
{ io_trap, io_trap }, /* port 22 */
|
||||
{ io_trap, io_trap }, /* port 23 */
|
||||
{ io_trap, io_trap }, /* port 24 */
|
||||
{ clkc_in, clkc_out }, /* port 25 */
|
||||
{ clkd_in, clkd_out }, /* port 26 */
|
||||
{ time_in, time_out } /* port 27 */
|
||||
};
|
||||
|
||||
/*
|
||||
* This function initializes the I/O handlers:
|
||||
* 1. Initialize all unused ports with the I/O trap handler.
|
||||
* 2. Initialize the MMU with NULL pointers.
|
||||
* 3. Open the files which emulates the disk drives. The file
|
||||
* for drive A must be opened, or CP/M can't be booted.
|
||||
* Errors for opening one of the other 15 drives results
|
||||
* in a NULL pointer for fd in the dskdef structure,
|
||||
* so that this drive can't be used.
|
||||
* 4. Create and open the file "printer.cpm" for emulation
|
||||
* of a printer.
|
||||
* 5. Fork the process for receiving from the serial port.
|
||||
* 6. Open the named pipes "auxin" and "auxout" for simulation
|
||||
* of a serial port.
|
||||
*/
|
||||
void init_io(void)
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = 28; i <= 255; i++) {
|
||||
port[i][0] = io_trap;
|
||||
port[i][1] = io_trap;
|
||||
}
|
||||
for (i = 0; i < MAXSEG; i++)
|
||||
mmu[i] = NULL;
|
||||
if ((*disks[0].fd = open(disks[0].fn, O_RDWR)) == -1) {
|
||||
perror("file disks/drivea.cpm");
|
||||
exit(1);
|
||||
}
|
||||
for (i = 1; i <= 15; i++)
|
||||
if ((*disks[i].fd = open(disks[i].fn, O_RDWR)) == -1)
|
||||
disks[i].fd = NULL;
|
||||
if ((printer = creat("printer.cpm", 0644)) == -1) {
|
||||
perror("file printer.cpm");
|
||||
exit(1);
|
||||
}
|
||||
pid_rec = fork();
|
||||
switch (pid_rec) {
|
||||
case -1:
|
||||
puts("can't fork");
|
||||
exit(1);
|
||||
case 0:
|
||||
execlp("./receive", "receive", "auxiliary.cpm", (char *) NULL);
|
||||
puts("can't exec receive process");
|
||||
exit(1);
|
||||
}
|
||||
if ((auxin = open("auxin", O_RDONLY | O_NDELAY)) == -1) {
|
||||
perror("pipe auxin");
|
||||
exit(1);
|
||||
}
|
||||
if ((auxout = open("auxout", O_WRONLY)) == -1) {
|
||||
perror("pipe auxout");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function stops the I/O handlers:
|
||||
*
|
||||
* 1. The files emulating the disk drives are closed.
|
||||
* 2. The file "printer.com" emulating a printer is closed.
|
||||
* 3. The named pipes "auxin" and "auxout" are closed.
|
||||
* 4. The receiving process for the serial port is stopped.
|
||||
*/
|
||||
void exit_io(void)
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = 0; i <= 15; i++)
|
||||
if (disks[i].fd != NULL)
|
||||
close(*disks[i].fd);
|
||||
close(printer);
|
||||
close(auxin);
|
||||
close(auxout);
|
||||
kill(pid_rec, SIGHUP);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called for every IN opcode from the
|
||||
* CPU emulation. It calls the right handler for the
|
||||
* port, from which input is wanted.
|
||||
*/
|
||||
BYTE io_in(BYTE adr)
|
||||
{
|
||||
return((*port[adr][0]) ());
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called for every OUT opcode from the
|
||||
* CPU emulation. It calls the right handler for the port,
|
||||
* to which output is wanted.
|
||||
*/
|
||||
BYTE io_out(BYTE adr, BYTE data)
|
||||
{
|
||||
(*port[adr][1]) (data);
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O trap handler
|
||||
*/
|
||||
static BYTE io_trap(void)
|
||||
{
|
||||
if (i_flag) {
|
||||
cpu_error = IOTRAP;
|
||||
cpu_state = STOPPED;
|
||||
}
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read console status:
|
||||
* 0xff : input available
|
||||
* 0x00 : no input available
|
||||
*/
|
||||
static BYTE cons_in(void)
|
||||
{
|
||||
register int flags, readed;
|
||||
|
||||
if (last_char)
|
||||
return((BYTE) 0xff);
|
||||
if (cntl_c)
|
||||
return((BYTE) 0xff);
|
||||
if (cntl_bs)
|
||||
return((BYTE) 0xff);
|
||||
else {
|
||||
flags = fcntl(0, F_GETFL, 0);
|
||||
fcntl(0, F_SETFL, flags | O_NDELAY);
|
||||
readed = read(0, &last_char, 1);
|
||||
fcntl(0, F_SETFL, flags);
|
||||
if (readed == 1)
|
||||
return((BYTE) 0xff);
|
||||
}
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write console status:
|
||||
* no reaction
|
||||
*/
|
||||
static BYTE cons_out(BYTE data)
|
||||
{
|
||||
data = data;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read console data:
|
||||
* read one character from the terminal without echo
|
||||
* and character transformations
|
||||
*/
|
||||
static BYTE cond_in(void)
|
||||
{
|
||||
char c;
|
||||
|
||||
aborted:
|
||||
if (last_char) {
|
||||
c = last_char;
|
||||
last_char = '\0';
|
||||
} else if (cntl_c) {
|
||||
cntl_c--;
|
||||
c = 0x03;
|
||||
} else if (cntl_bs) {
|
||||
cntl_bs--;
|
||||
c = 0x1c;
|
||||
} else if (read(0, &c, 1) != 1) {
|
||||
goto aborted;
|
||||
}
|
||||
return((BYTE) c);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write console data:
|
||||
* the output is written to the terminal
|
||||
*/
|
||||
static BYTE cond_out(BYTE data)
|
||||
{
|
||||
while ((write(fileno(stdout), (char *) &data, 1)) != 1)
|
||||
;
|
||||
fflush(stdout);
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read printer status:
|
||||
* the printer is ready all the time
|
||||
*/
|
||||
static BYTE prts_in(void)
|
||||
{
|
||||
return((BYTE) 0xff);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write printer status:
|
||||
* no reaction
|
||||
*/
|
||||
static BYTE prts_out(BYTE data)
|
||||
{
|
||||
data = data;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read printer data:
|
||||
* always read a 0 from the printer
|
||||
*/
|
||||
static BYTE prtd_in(void)
|
||||
{
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write printer data:
|
||||
* the output is written to file "printer.cpm"
|
||||
*/
|
||||
static BYTE prtd_out(BYTE data)
|
||||
{
|
||||
if (data != '\r')
|
||||
while ((write(printer, (char *) &data, 1)) != 1)
|
||||
;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read aux status:
|
||||
* return EOF status of the aux device
|
||||
*/
|
||||
static BYTE auxs_in(void)
|
||||
{
|
||||
return((BYTE) aux_in_eof);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write aux status:
|
||||
* change EOF status of the aux device
|
||||
*/
|
||||
static BYTE auxs_out(BYTE data)
|
||||
{
|
||||
aux_in_eof = data;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read aux data:
|
||||
* read next byte from pipe "auxin"
|
||||
*/
|
||||
static BYTE auxd_in(void)
|
||||
{
|
||||
char c;
|
||||
|
||||
if (read(auxin, &c, 1) == 1)
|
||||
return((BYTE) c);
|
||||
else {
|
||||
aux_in_eof = 0xff;
|
||||
return((BYTE) 0x1a); /* CP/M EOF */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write aux data:
|
||||
* write output to pipe "auxout"
|
||||
*/
|
||||
static BYTE auxd_out(BYTE data)
|
||||
{
|
||||
if (data != '\r')
|
||||
write(auxout, (char *) &data, 1);
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read FDC drive:
|
||||
* return the current drive
|
||||
*/
|
||||
static BYTE fdcd_in(void)
|
||||
{
|
||||
return((BYTE) drive);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write FDC drive:
|
||||
* set the current drive
|
||||
*/
|
||||
static BYTE fdcd_out(BYTE data)
|
||||
{
|
||||
drive = data;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read FDC track:
|
||||
* return the current track
|
||||
*/
|
||||
static BYTE fdct_in(void)
|
||||
{
|
||||
return((BYTE) track);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write FDC track:
|
||||
* set the current track
|
||||
*/
|
||||
static BYTE fdct_out(BYTE data)
|
||||
{
|
||||
track = data;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read FDC sector
|
||||
* return the current sector
|
||||
*/
|
||||
static BYTE fdcs_in(void)
|
||||
{
|
||||
return((BYTE) sector);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write FDC sector:
|
||||
* set the current sector
|
||||
*/
|
||||
static BYTE fdcs_out(BYTE data)
|
||||
{
|
||||
sector = data;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read FDC command:
|
||||
* always returns 0
|
||||
*/
|
||||
static BYTE fdco_in(void)
|
||||
{
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write FDC command:
|
||||
* transfer one sector in the wanted direction,
|
||||
* 0 = read, 1 = write
|
||||
*
|
||||
* The status byte of the FDC is set as follows:
|
||||
* 0 - ok
|
||||
* 1 - illegal drive
|
||||
* 2 - illegal track
|
||||
* 3 - illegal sector
|
||||
* 4 - seek error
|
||||
* 5 - read error
|
||||
* 6 - write error
|
||||
* 7 - illegal command to FDC
|
||||
*/
|
||||
static BYTE fdco_out(BYTE data)
|
||||
{
|
||||
register long pos;
|
||||
if (disks[drive].fd == NULL) {
|
||||
status = 1;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
if (track > disks[drive].tracks) {
|
||||
status = 2;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
if (sector > disks[drive].sectors) {
|
||||
status = 3;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
pos = (((long)track) * ((long)disks[drive].sectors) + sector - 1) << 7;
|
||||
if (lseek(*disks[drive].fd, pos, 0) == -1L) {
|
||||
status = 4;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
switch (data) {
|
||||
case 0: /* read */
|
||||
if (read(*disks[drive].fd, (char *) ram + (dmadh << 8) +
|
||||
dmadl, 128) != 128)
|
||||
status = 5;
|
||||
else
|
||||
status = 0;
|
||||
break;
|
||||
case 1: /* write */
|
||||
if (write(*disks[drive].fd, (char *) ram + (dmadh << 8) +
|
||||
dmadl, 128) != 128)
|
||||
status = 6;
|
||||
else
|
||||
status = 0;
|
||||
break;
|
||||
default: /* illegal command */
|
||||
status = 7;
|
||||
break;
|
||||
}
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read FDC status:
|
||||
* returns status of last FDC operation,
|
||||
* 0 = ok, else some error
|
||||
*/
|
||||
static BYTE fdcx_in(void)
|
||||
{
|
||||
return((BYTE) status);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write FDC status:
|
||||
* no reaction
|
||||
*/
|
||||
static BYTE fdcx_out(BYTE data)
|
||||
{
|
||||
data = data;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read lower byte of DMA address:
|
||||
* return lower byte of current DMA address
|
||||
*/
|
||||
static BYTE dmal_in(void)
|
||||
{
|
||||
return((BYTE) dmadl);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write lower byte of DMA address:
|
||||
* set lower byte of DMA address
|
||||
*/
|
||||
static BYTE dmal_out(BYTE data)
|
||||
{
|
||||
dmadl = data;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read higher byte of DMA address:
|
||||
* return higher byte of current DMA address
|
||||
*/
|
||||
static BYTE dmah_in(void)
|
||||
{
|
||||
return((BYTE) dmadh);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write higher byte of DMA address:
|
||||
* set higher byte of the DMA address
|
||||
*/
|
||||
static BYTE dmah_out(BYTE data)
|
||||
{
|
||||
dmadh = data;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read MMU initialization:
|
||||
* return number of initialized MMU banks
|
||||
*/
|
||||
static BYTE mmui_in(void)
|
||||
{
|
||||
return((BYTE) maxbnk);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write MMU initialization:
|
||||
* for the FIRST call the memory for the wanted number of banks
|
||||
* is allocated and pointers to the memory is stored in the MMU array
|
||||
*/
|
||||
static BYTE mmui_out(BYTE data)
|
||||
{
|
||||
register int i;
|
||||
|
||||
if (mmu[0] != NULL)
|
||||
return((BYTE) 0);
|
||||
if (data > MAXSEG) {
|
||||
printf("Try to init %d banks, available %d banks\n",
|
||||
data, MAXSEG);
|
||||
exit(1);
|
||||
}
|
||||
for (i = 0; i < data; i++) {
|
||||
if ((mmu[i] = malloc(SEGSIZ)) == NULL) {
|
||||
printf("can't allocate memory for bank %d\n", i+1);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
maxbnk = data;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read MMU bank select:
|
||||
* return current selected MMU bank
|
||||
*/
|
||||
static BYTE mmus_in(void)
|
||||
{
|
||||
return((BYTE) selbnk);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write MMU bank select:
|
||||
* if the current selected bank is not equal the wanted bank,
|
||||
* the current bank is saved. Then the memory of the wanted
|
||||
* bank is copied into the CPU address space and this bank is
|
||||
* set to be the current one now.
|
||||
*/
|
||||
static BYTE mmus_out(BYTE data)
|
||||
{
|
||||
if (data > maxbnk) {
|
||||
printf("Try to select unallocated bank %d\n", data);
|
||||
exit(1);
|
||||
}
|
||||
if (data == selbnk)
|
||||
return((BYTE) 0);
|
||||
memcpy(mmu[selbnk], (char *) ram, SEGSIZ);
|
||||
memcpy((char *) ram, mmu[data], SEGSIZ);
|
||||
selbnk = data;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read clock command:
|
||||
* return last clock command
|
||||
*/
|
||||
static BYTE clkc_in(void)
|
||||
{
|
||||
return(clkcmd);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write clock command:
|
||||
* set the wanted clock command
|
||||
*/
|
||||
static BYTE clkc_out(BYTE data)
|
||||
{
|
||||
clkcmd = data;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read clock data:
|
||||
* dependent from the last clock command the following
|
||||
* informations are given from the system clock:
|
||||
* 0 - seconds in BCD
|
||||
* 1 - minutes in BCD
|
||||
* 2 - hours in BCD
|
||||
* 3 - low byte number of days since 1.1.1978
|
||||
* 4 - high byte number of days since 1.1.1978
|
||||
* for every other clock command a 0 is returned
|
||||
*/
|
||||
static BYTE clkd_in(void)
|
||||
{
|
||||
register struct tm *t;
|
||||
register int val;
|
||||
time_t Time;
|
||||
|
||||
time(&Time);
|
||||
t = localtime(&Time);
|
||||
switch(clkcmd) {
|
||||
case 0: /* seconds in BCD */
|
||||
val = to_bcd(t->tm_sec);
|
||||
break;
|
||||
case 1: /* minutes in BCD */
|
||||
val = to_bcd(t->tm_min);
|
||||
break;
|
||||
case 2: /* hours in BCD */
|
||||
val = to_bcd(t->tm_hour);
|
||||
break;
|
||||
case 3: /* low byte days */
|
||||
val = get_date(t) & 255;
|
||||
break;
|
||||
case 4: /* high byte days */
|
||||
val = get_date(t) >> 8;
|
||||
break;
|
||||
default:
|
||||
val = 0;
|
||||
break;
|
||||
}
|
||||
return((BYTE) val);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write clock data:
|
||||
* under UNIX the system clock only can be set by the
|
||||
* super user, so we do nothing here
|
||||
*/
|
||||
static BYTE clkd_out(BYTE data)
|
||||
{
|
||||
data = data;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an integer to BCD
|
||||
*/
|
||||
static int to_bcd(int val)
|
||||
{
|
||||
register int i = 0;
|
||||
|
||||
while (val >= 10) {
|
||||
i += val / 10;
|
||||
i <<= 4;
|
||||
val %= 10;
|
||||
}
|
||||
i += val;
|
||||
return (i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate number of days since 1.1.1978
|
||||
* The Y2K bug here is intentional, CP/M 3 has a Y2K bug fix
|
||||
*/
|
||||
static int get_date(struct tm *t)
|
||||
{
|
||||
register int i;
|
||||
register int val = 0;
|
||||
|
||||
for (i = 1978; i < 1900 + t->tm_year; i++) {
|
||||
val += 365;
|
||||
if (i % 4 == 0)
|
||||
val++;
|
||||
}
|
||||
val += t->tm_yday + 1;
|
||||
return(val);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write timer
|
||||
*/
|
||||
static BYTE time_out(BYTE data)
|
||||
{
|
||||
static struct itimerval tim;
|
||||
static struct sigaction newact;
|
||||
|
||||
if (data == 1) {
|
||||
timer = 1;
|
||||
newact.sa_handler = int_timer;
|
||||
sigaction(SIGALRM, &newact, NULL);
|
||||
tim.it_value.tv_sec = 0;
|
||||
tim.it_value.tv_usec = 20000;
|
||||
tim.it_interval.tv_sec = 0;
|
||||
tim.it_interval.tv_usec = 20000;
|
||||
setitimer(ITIMER_REAL, &tim, NULL);
|
||||
} else {
|
||||
timer = 0;
|
||||
newact.sa_handler = SIG_IGN;
|
||||
sigaction(SIGALRM, &newact, NULL);
|
||||
tim.it_value.tv_sec = 0;
|
||||
tim.it_value.tv_usec = 0;
|
||||
setitimer(ITIMER_REAL, &tim, NULL);
|
||||
}
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read timer
|
||||
*/
|
||||
static BYTE time_in(void)
|
||||
{
|
||||
return(timer);
|
||||
}
|
||||
|
||||
/*
|
||||
* timer interrupt causes maskerable CPU interrupt
|
||||
*/
|
||||
static void int_timer(int sig)
|
||||
{
|
||||
int_type = INT_INT;
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
# use this to link the common parts of Z80 simulation
|
||||
|
||||
ln ../../z80sim/sim0.c sim0.c
|
||||
ln ../../z80sim/sim1.c sim1.c
|
||||
ln ../../z80sim/sim2.c sim2.c
|
||||
ln ../../z80sim/sim3.c sim3.c
|
||||
ln ../../z80sim/sim4.c sim4.c
|
||||
ln ../../z80sim/sim5.c sim5.c
|
||||
ln ../../z80sim/sim6.c sim6.c
|
||||
ln ../../z80sim/sim7.c sim7.c
|
||||
ln ../../z80sim/simfun.c simfun.c
|
||||
ln ../../z80sim/simint.c simint.c
|
||||
ln ../../z80sim/simglb.c simglb.c
|
||||
ln ../../z80sim/simglb.h simglb.h
|
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* Z80SIM - a Z80-CPU simulator
|
||||
*
|
||||
* Copyright (C) 1987-2006 by Udo Munk
|
||||
*
|
||||
* History:
|
||||
* 28-SEP-87 Develoment on TARGON/35 with AT&T Unix System V.3
|
||||
* 11-JAN-89 Release 1.1
|
||||
* 08-FEB-89 Release 1.2
|
||||
* 13-MAR-89 Release 1.3
|
||||
* 09-FEB-90 Release 1.4 Ported to TARGON/31 M10/30
|
||||
* 23-DEC-90 Release 1.5 Ported to COHERENT 3.0
|
||||
* 10-JUN-92 Release 1.6 long casting problem solved with COHERENT 3.2
|
||||
* and some optimization
|
||||
* 25-JUN-92 Release 1.7 comments in english
|
||||
* 02-OCT-06 Release 1.8 modified to compile on modern POSIX OS's
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following defines may be activated, commented or modified
|
||||
* by user for her/his own purpose.
|
||||
*/
|
||||
#define WANT_INT /* interrupt for MP/M */
|
||||
/*#define WANT_SPC*/ /* CP/M doesn't work with SP over-/underrun */
|
||||
/*#define WANT_PCC*/ /* CP/M doesn't work with PC overrun */
|
||||
/*#define CNTL_C*/ /* don't abort simulation with cntl-c */
|
||||
#define CNTL_BS /* emergency exit with cntl-\ :-) */
|
||||
/*#define CNTL_Z*/ /* don't suspend simulation with cntl-z */
|
||||
#define WANT_TIM /* run length measurement needed to adjust CPU speed */
|
||||
/*#define HISIZE 1000*//* no history */
|
||||
/*#define SBSIZE 10*/ /* no breakpoints */
|
||||
|
||||
/*
|
||||
* The following lines of this file should not be modified by user
|
||||
*/
|
||||
#define COPYR "Copyright (C) 1987-2006 by Udo Munk"
|
||||
#define RELEASE "1.9"
|
||||
|
||||
#define LENCMD 80 /* length of command buffers etc */
|
||||
|
||||
#define S_FLAG 128 /* bit definitions of CPU flags */
|
||||
#define Z_FLAG 64
|
||||
#define N2_FLAG 32
|
||||
#define H_FLAG 16
|
||||
#define N1_FLAG 8
|
||||
#define P_FLAG 4
|
||||
#define N_FLAG 2
|
||||
#define C_FLAG 1
|
||||
|
||||
/* operation of simulated CPU */
|
||||
#define SINGLE_STEP 0 /* single step */
|
||||
#define CONTIN_RUN 1 /* continual run */
|
||||
#define STOPPED 0 /* stop CPU because of error */
|
||||
|
||||
/* causes of error */
|
||||
#define NONE 0 /* no error */
|
||||
#define OPHALT 1 /* HALT op-code trap */
|
||||
#define IOTRAP 2 /* IN/OUT trap */
|
||||
#define OPTRAP1 3 /* illegal 1 byte op-code trap */
|
||||
#define OPTRAP2 4 /* illegal 2 byte op-code trap */
|
||||
#define OPTRAP4 5 /* illegal 4 byte op-code trap */
|
||||
#define USERINT 6 /* user interrupt */
|
||||
|
||||
/* type of CPU interrupt */
|
||||
#define INT_NONE 0
|
||||
#define INT_NMI 1 /* non maskable interrupt */
|
||||
#define INT_INT 2 /* maskable interrupt */
|
||||
|
||||
typedef unsigned short WORD; /* 16 bit unsigned */
|
||||
typedef unsigned char BYTE; /* 8 bit unsigned */
|
||||
|
||||
#ifdef HISIZE
|
||||
struct history { /* structure of a history entry */
|
||||
WORD h_adr; /* address of execution */
|
||||
WORD h_af; /* register AF */
|
||||
WORD h_bc; /* register BC */
|
||||
WORD h_de; /* register DE */
|
||||
WORD h_hl; /* register HL */
|
||||
WORD h_ix; /* register IX */
|
||||
WORD h_iy; /* register IY */
|
||||
WORD h_sp; /* register SP */
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef SBSIZE
|
||||
struct softbreak { /* structure of a breakpoint */
|
||||
WORD sb_adr; /* address of breakpoint */
|
||||
BYTE sb_oldopc; /* op-code at address of breakpoint */
|
||||
int sb_passcount; /* pass counter of breakpoint */
|
||||
int sb_pass; /* no. of pass to break */
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef isxdigit
|
||||
#define isxdigit(c) ((c<='f'&&c>='a')||(c<='F'&&c>='A')||(c<='9'&&c>='0'))
|
||||
#endif
|
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
* Z80SIM - a Z80-CPU simulator
|
||||
*
|
||||
* Copyright (C) 1987-2006 by Udo Munk
|
||||
*
|
||||
* History:
|
||||
* 28-SEP-87 Development on TARGON/35 with AT&T Unix System V.3
|
||||
* 14-MAR-89 new option -l
|
||||
* 23-DEC-90 Ported to COHERENT 3.0
|
||||
* 06-OCT-06 modified to compile on modern POSIX OS's
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include "sim.h"
|
||||
#include "simglb.h"
|
||||
|
||||
extern void cpu(void);
|
||||
|
||||
struct termios old_term, new_term;
|
||||
|
||||
/*
|
||||
* This function gets the CP/M boot sector from first track/sector
|
||||
* of disk drive A (file drivea.cpm) into memory started at 0.
|
||||
* Then the Z80 CPU emulation is started and the system should boot.
|
||||
*/
|
||||
void mon(void)
|
||||
{
|
||||
register int fd;
|
||||
|
||||
if (!l_flag) {
|
||||
if ((fd = open("disks/drivea.cpm", O_RDONLY)) == -1) {
|
||||
perror("file disks/drivea.cpm");
|
||||
return;
|
||||
}
|
||||
if (read(fd, (char *) ram, 128) != 128) {
|
||||
perror("file disks/drivea.cpm");
|
||||
return;
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
tcgetattr(0, &old_term);
|
||||
new_term = old_term;
|
||||
new_term.c_lflag &= ~(ICANON | ECHO);
|
||||
new_term.c_iflag &= ~(IXON | IXANY | IXOFF);
|
||||
new_term.c_iflag &= ~(IGNCR | ICRNL | INLCR);
|
||||
new_term.c_cc[VMIN] = 1;
|
||||
#ifndef CNTL_Z
|
||||
new_term.c_cc[VSUSP] = 0;
|
||||
#endif
|
||||
tcsetattr(0, TCSADRAIN, &new_term);
|
||||
|
||||
cpu_state = CONTIN_RUN;
|
||||
cpu_error = NONE;
|
||||
cpu();
|
||||
|
||||
tcsetattr(0, TCSADRAIN, &old_term);
|
||||
|
||||
switch (cpu_error) {
|
||||
case NONE:
|
||||
break;
|
||||
case OPHALT:
|
||||
printf("\nHALT Op-Code reached at %04x\n",
|
||||
(unsigned int)(PC - ram - 1));
|
||||
break;
|
||||
case IOTRAP:
|
||||
printf("\nI/O Trap at %04x\n", (unsigned int)(PC - ram));
|
||||
break;
|
||||
case OPTRAP1:
|
||||
printf("\nOp-code trap at %04x %02x\n",
|
||||
(unsigned int)(PC - 1 - ram), *(PC - 1));
|
||||
break;
|
||||
case OPTRAP2:
|
||||
printf("\nOp-code trap at %04x %02x %02x\n",
|
||||
(unsigned int)(PC - 2 - ram), *(PC - 2), *(PC - 1));
|
||||
break;
|
||||
case OPTRAP4:
|
||||
printf("\nOp-code trap at %04x %02x %02x %02x %02x\n",
|
||||
(unsigned int)(PC - 4 - ram), *(PC - 4), *(PC - 3),
|
||||
*(PC - 2), *(PC - 1));
|
||||
break;
|
||||
case USERINT:
|
||||
puts("\nUser Interrupt");
|
||||
break;
|
||||
default:
|
||||
printf("\nUnknown error %d\n", cpu_error);
|
||||
break;
|
||||
}
|
||||
}
|
@@ -1,6 +0,0 @@
|
||||
# use this to unlink the common parts of Z80 simulation
|
||||
|
||||
rm sim[0-7].c
|
||||
rm simfun.c
|
||||
rm simint.c
|
||||
rm simglb.[hc]
|
@@ -1,22 +0,0 @@
|
||||
Copyright (c) 1987-2006 Udo Munk
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
@@ -1,85 +0,0 @@
|
||||
Usage:
|
||||
|
||||
z80asm -ofile -f[b|m|h] -l[file] -s[n|a] -x -v -dsymbol ... file ...
|
||||
|
||||
A maximum of 512 source files is allowed. If the filename of a source
|
||||
doesn't have an extension the default extension ".asm" will be
|
||||
concated. Source file names may have a path, the maximum length of
|
||||
a full qualified filename is 2048 characters.
|
||||
For relative paths the extension must be used, because all characters
|
||||
after a "." would be used as extension!
|
||||
|
||||
Option o:
|
||||
To override the default name of the output file. Without this option
|
||||
the name of the output file becomes the name of the input file,
|
||||
but with the extension ".bin". The output file may have a path,
|
||||
the maximum length is limited to 2048 characters.
|
||||
|
||||
Option f:
|
||||
Format of the output file:
|
||||
|
||||
-fb -> binary file
|
||||
-fm -> binary file with Mostek header
|
||||
-fh -> Intel hex
|
||||
|
||||
Option l:
|
||||
Without this option no list file will be generated. With -l a list
|
||||
file with the name of the source file but extension ".lis" will be
|
||||
generated. An optional file name with path (2048 characters maximum)
|
||||
may be added to this option.
|
||||
|
||||
Option s:
|
||||
This option writes the unsorted symbol table (-s), sorted by name (-sn)
|
||||
or sorted by address (-sa) into the list file. This option only works
|
||||
together with option -l.
|
||||
|
||||
Option x:
|
||||
Don't output data in pass 2 into object file for DEFS. This only works
|
||||
if unallocated data isn't followed by any code or initialized data!
|
||||
Usefull for CP/M BIOS's, where unallocated data doesn't need to be
|
||||
part of the system image, if the complete image won't fit on the system
|
||||
tracks.
|
||||
|
||||
Option v:
|
||||
Verbose operation of the assembler.
|
||||
|
||||
Option d:
|
||||
This option predefines symbols with a value of 0.
|
||||
The number of this option is not limited in the command line.
|
||||
|
||||
Pseudo Operations:
|
||||
|
||||
Definition of symbols and allocation of memory:
|
||||
|
||||
ORG <expression> - set program address
|
||||
<symbol> EQU <expression> - define constant symbol
|
||||
<symbol> DEFL <expression> - define variable symbol
|
||||
<symbol> DEFB <exp,'char',..> - write bytes in memory
|
||||
<symbol> DEFW <exp,exp..> - write words (16 bits) in memory
|
||||
<symbol> DEFM <'string'> - write character string in memory
|
||||
<symbol> DEFS <expression> - reserve space in memory
|
||||
|
||||
|
||||
Conditional assembly:
|
||||
|
||||
IFDEF <symbol> - assemble if symbol defined
|
||||
IFNDEF <symbol> - assemble if symbol not defined
|
||||
IFEQ <exp1,exp2> - assemble if equal
|
||||
IFNEQ <exp1,exp2> - assemble if not equal
|
||||
ELSE - else for all conditionals
|
||||
ENDIF - end of conditional assembly
|
||||
|
||||
|
||||
Manipulation of list file:
|
||||
|
||||
PAGE <expression> - number of lines/page
|
||||
EJECT - skip to new page
|
||||
LIST - listing on
|
||||
NOLIST - listing off
|
||||
TITLE <'string'> - define title for page header
|
||||
|
||||
|
||||
Others:
|
||||
|
||||
INCLUDE <filename> - include another source file
|
||||
PRINT <'string'> - print string to stdout in pass one
|
@@ -1,54 +0,0 @@
|
||||
Quickstart to run CP/M and MP/M on the Z80-CPU simulation
|
||||
|
||||
1. Change to directory ~/z80pack/cpmsim/srcsim
|
||||
make
|
||||
make clean
|
||||
This compiles the CPU and hardware emulation needed to run CP/M and MP/M.
|
||||
|
||||
2. Change to directory ~/z80pack/cpmsim/srccpm2
|
||||
make
|
||||
make clean
|
||||
This compiles support programs (see below), installs named pipes and so on.
|
||||
|
||||
3. Make backup copies of your distribution disks!
|
||||
cd ~/z80pack/cpmsim/disks/library
|
||||
cp *.dsk ../backups
|
||||
|
||||
4. Change to directory ~/z80pack/cpmsim
|
||||
cpm2 - run CP/M 2.2
|
||||
cpm3 - run CP/M 3.0
|
||||
mpm - this boots CP/M 2, run command mpm to boot MP/M 2
|
||||
|
||||
Usage of the support programs:
|
||||
|
||||
format: to create an empty disk image for the CP/M simulation.
|
||||
input: format <a | b | c | d | i | j>
|
||||
output: in directory disks files drivea.cpm, driveb.cpm,
|
||||
drivec.cpm, drived.cpm, drivei.cpm and drivej.cpm
|
||||
|
||||
bin2hex:converts binary files to Intel hex.
|
||||
|
||||
receive:This is a process spawned by cpmsim. It reads from the named
|
||||
pipe auxout and writes all input from the pipe to the file,
|
||||
which is given as first argument. cpmsim spawns this process
|
||||
with the output filename auxiliary.cpm. Inside the simulator
|
||||
this pipe is connected to I/O-port 5, which is assigned
|
||||
to the CP/M device PUN:. So everything you write from CP/M
|
||||
to device PUN: goes into the file auxiliary.cpm on the
|
||||
UNIX host.
|
||||
|
||||
send: This process is to send a file from the UNIX host to the
|
||||
simulator. Type send <filename> &, and then run cpmsim.
|
||||
The process writes all data from file into the named pipe
|
||||
auxin, which is also connected to I/O-port 5, which is
|
||||
assigned to the CP/M device RDR:. You may use this to
|
||||
transfer a file from the UNIX host to the simulator.
|
||||
Under CP/M type pip file=RDR: to read the data send from
|
||||
the process on the UNIX host.
|
||||
|
||||
If you use PIP to transfer files between the UNIX host and the
|
||||
simulator, you can only use ASCII files, because pip uses cntl-z
|
||||
for EOF! To transfer a binary file from the UNIX host to the
|
||||
simulator convert it to Intel hex format with bin2hex. This
|
||||
can be converted back to a binary file under CP/M with the LOAD
|
||||
command.
|
Binary file not shown.
@@ -1,41 +0,0 @@
|
||||
CFLAGS = -c -O
|
||||
LFLAGS = -s
|
||||
|
||||
OBJ = z80amain.o \
|
||||
z80atab.o \
|
||||
z80anum.o \
|
||||
z80aout.o \
|
||||
z80arfun.o \
|
||||
z80apfun.o \
|
||||
z80aopc.o \
|
||||
z80aglb.o
|
||||
|
||||
z80asm : $(OBJ)
|
||||
cc $(OBJ) $(LFLAGS) -o z80asm
|
||||
|
||||
z80amain.o : z80amain.c z80a.h z80aglb.h
|
||||
cc $(CFLAGS) z80amain.c
|
||||
|
||||
z80atab.o : z80atab.c z80a.h z80aglb.h
|
||||
cc $(CFLAGS) z80atab.c
|
||||
|
||||
z80anum.o : z80anum.c z80a.h z80aglb.h
|
||||
cc $(CFLAGS) z80anum.c
|
||||
|
||||
z80aout.o : z80aout.c z80a.h z80aglb.h
|
||||
cc $(CFLAGS) z80aout.c
|
||||
|
||||
z80arfun.o : z80arfun.c z80a.h z80aglb.h
|
||||
cc $(CFLAGS) z80arfun.c
|
||||
|
||||
z80apfun.o : z80apfun.c z80a.h z80aglb.h
|
||||
cc $(CFLAGS) z80apfun.c
|
||||
|
||||
z80aopc.o : z80aopc.c z80a.h
|
||||
cc $(CFLAGS) z80aopc.c
|
||||
|
||||
z80aglb.o : z80aglb.c z80a.h
|
||||
cc $(CFLAGS) z80aglb.c
|
||||
|
||||
clean:
|
||||
rm -f core *.o z80asm
|
@@ -1,144 +0,0 @@
|
||||
/*
|
||||
* Z80 - Assembler
|
||||
* Copyright (C) 1987-2006 by Udo Munk
|
||||
*
|
||||
* History:
|
||||
* 17-SEP-1987 Development under Digital Research CP/M 2.2
|
||||
* 28-JUN-1988 Switched to Unix System V.3
|
||||
* 21-OCT-2006 changed to ANSI C for modern POSIX OS's
|
||||
*/
|
||||
|
||||
/*
|
||||
* OS dependant definitions
|
||||
*/
|
||||
#define LENFN 2048 /* max. filename length */
|
||||
#define READA "r" /* file open mode read ascii */
|
||||
#define WRITEA "w" /* file open mode write ascii */
|
||||
#define WRITEB "w" /* file open mode write binary */
|
||||
|
||||
/*
|
||||
* various constants
|
||||
*/
|
||||
#define REL "1.3"
|
||||
#define COPYR "Copyright (C) 1987-2006 by Udo Munk"
|
||||
#define SRCEXT ".asm" /* filenamen extension source */
|
||||
#define OBJEXT ".bin" /* filenamen extension object */
|
||||
#define LSTEXT ".lis" /* filenamen extension listing */
|
||||
#define OUTBIN 1 /* format of object: binary */
|
||||
#define OUTMOS 2 /* Mostek binaer */
|
||||
#define OUTHEX 3 /* Intel hex */
|
||||
#define OUTDEF OUTMOS /* default object format */
|
||||
#define COMMENT ';' /* inline comment character */
|
||||
#define LINCOM '*' /* comment line if in columne 1 */
|
||||
#define LABSEP ':' /* label separator */
|
||||
#define STRSEP '\'' /* string separator */
|
||||
#define ENDFILE "END" /* end of source */
|
||||
#define MAXFN 512 /* max. no. source files */
|
||||
#define MAXLINE 128 /* max. line length source */
|
||||
#define PLENGTH 65 /* default lines/page in listing */
|
||||
#define SYMSIZE 8 /* max. symbol length */
|
||||
#define INCNEST 5 /* max. INCLUDE nesting depth */
|
||||
#define IFNEST 5 /* max IF.. nesting depth */
|
||||
#define HASHSIZE 500 /* max. entries in symbol hash array */
|
||||
#define OPCARRAY 256 /* size of object buffer */
|
||||
#define SYMINC 100 /* start size of sorted symbol array */
|
||||
|
||||
/*
|
||||
* structure opcode table
|
||||
*/
|
||||
struct opc {
|
||||
char *op_name; /* opcode name */
|
||||
int (*op_fun) (); /* function pointer code generation */
|
||||
int op_c1; /* first base opcode*/
|
||||
int op_c2; /* second base opcode */
|
||||
};
|
||||
|
||||
/*
|
||||
* structure operand table
|
||||
*/
|
||||
struct ope {
|
||||
char *ope_name; /* operand name */
|
||||
int ope_sym; /* symbol value operand */
|
||||
};
|
||||
|
||||
/*
|
||||
* structure symbol table entries
|
||||
*/
|
||||
struct sym {
|
||||
char *sym_name; /* symbol name */
|
||||
int sym_wert; /* symbol value */
|
||||
struct sym *sym_next; /* next entry */
|
||||
};
|
||||
|
||||
/*
|
||||
* structure nested INCLUDE's
|
||||
*/
|
||||
struct inc {
|
||||
unsigned inc_line; /* line counter for listing */
|
||||
char *inc_fn; /* filename */
|
||||
FILE *inc_fp; /* file pointer */
|
||||
};
|
||||
|
||||
/*
|
||||
* definition of operand symbols
|
||||
* definitions for registers A, B, C, D, H, L and (HL)
|
||||
* are defined as the bits used in operands and may not
|
||||
* be changed!
|
||||
*/
|
||||
#define REGB 0 /* register B */
|
||||
#define REGC 1 /* register C */
|
||||
#define REGD 2 /* register D */
|
||||
#define REGE 3 /* register E */
|
||||
#define REGH 4 /* register H */
|
||||
#define REGL 5 /* register L */
|
||||
#define REGIHL 6 /* register indirect HL */
|
||||
#define REGA 7 /* register A */
|
||||
#define REGI 8 /* register I */
|
||||
#define REGR 9 /* register R */
|
||||
#define REGAF 10 /* register pair AF */
|
||||
#define REGBC 11 /* register pair BC */
|
||||
#define REGDE 12 /* register pair DE */
|
||||
#define REGHL 13 /* register pair HL */
|
||||
#define REGIX 14 /* register IX */
|
||||
#define REGIY 15 /* register IY */
|
||||
#define REGSP 16 /* register SP */
|
||||
#define REGIBC 17 /* register indirect BC */
|
||||
#define REGIDE 18 /* register indirect DE */
|
||||
#define REGIIX 19 /* register indirect IX */
|
||||
#define REGIIY 20 /* register indirect IY */
|
||||
#define REGISP 21 /* register indirect SP */
|
||||
#define FLGNC 30 /* flag no carry */
|
||||
#define FLGNZ 31 /* flag not zerro */
|
||||
#define FLGZ 32 /* flag zerro */
|
||||
#define FLGM 33 /* flag minus */
|
||||
#define FLGP 34 /* flag plus */
|
||||
#define FLGPE 35 /* flag parrity even */
|
||||
#define FLGPO 36 /* flag parrity odd */
|
||||
#define NOOPERA 98 /* no operand */
|
||||
#define NOREG 99 /* operand isn't register */
|
||||
|
||||
/*
|
||||
* definitions of error numbers for error messages in listfile
|
||||
*/
|
||||
#define E_ILLOPC 0 /* illegal opcode */
|
||||
#define E_ILLOPE 1 /* illegal operand */
|
||||
#define E_MISOPE 2 /* missing operand */
|
||||
#define E_MULSYM 3 /* multiple defined symbol */
|
||||
#define E_UNDSYM 4 /* undefined symbol */
|
||||
#define E_VALOUT 5 /* value out of bounds */
|
||||
#define E_MISPAR 6 /* missing parren */
|
||||
#define E_MISHYP 7 /* missing string separator */
|
||||
#define E_MEMOVR 8 /* memory override (ORG) */
|
||||
#define E_MISIFF 9 /* missing IF at ELSE or ENDIF */
|
||||
#define E_IFNEST 10 /* to many IF's nested */
|
||||
#define E_MISEIF 11 /* missing ENDIF */
|
||||
#define E_INCNEST 12 /* to many INCLUDE's nested */
|
||||
|
||||
/*
|
||||
* definition fatal errors
|
||||
*/
|
||||
#define F_OUTMEM 0 /* out of memory */
|
||||
#define F_USAGE 1 /* usage: .... */
|
||||
#define F_HALT 2 /* assembly halted */
|
||||
#define F_FOPEN 3 /* can't open file */
|
||||
#define F_INTERN 4 /* internal error */
|
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Z80 - Assembler
|
||||
* Copyright (C) 1987-2006 by Udo Munk
|
||||
*
|
||||
* History:
|
||||
* 17-SEP-1987 Development under Digital Research CP/M 2.2
|
||||
* 28-JUN-1988 Switched to Unix System V.3
|
||||
* 21-OCT-2006 changed to ANSI C for modern POSIX OS's
|
||||
*/
|
||||
|
||||
/*
|
||||
* this module contains all global variables other
|
||||
* than CPU specific tables
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "z80a.h"
|
||||
|
||||
char *infiles[MAXFN], /* source filenames */
|
||||
objfn[LENFN + 1], /* object filename */
|
||||
lstfn[LENFN + 1], /* listing filename */
|
||||
*srcfn, /* filename of current processed source file */
|
||||
line[MAXLINE], /* buffer for one line souce */
|
||||
tmp[MAXLINE], /* temporary buffer */
|
||||
label[SYMSIZE+1], /* buffer for label */
|
||||
opcode[MAXLINE], /* buffer for opcode */
|
||||
operand[MAXLINE], /* buffer for operand */
|
||||
ops[OPCARRAY], /* buffer for generated object code */
|
||||
title[MAXLINE]; /* buffer for titel of souce */
|
||||
|
||||
int list_flag, /* flag for option -l */
|
||||
sym_flag, /* flag for option -s */
|
||||
ver_flag, /* flag for option -v */
|
||||
dump_flag, /* flag for option -x */
|
||||
pc, /* programm counter */
|
||||
pass, /* processed pass */
|
||||
iflevel, /* IF nesting level */
|
||||
gencode = 1, /* flag for conditional object code */
|
||||
errors, /* error counter */
|
||||
errnum, /* error number in pass 2 */
|
||||
sd_flag, /* list flag for PSEUDO opcodes */
|
||||
/* = 0: address from <val>, data from <ops> */
|
||||
/* = 1: address from <sd_val>, data from <ops>*/
|
||||
/* = 2: no address, data from <ops> */
|
||||
/* = 3: address from <sd_val>, no data */
|
||||
/* = 4: suppress whole line */
|
||||
sd_val, /* output value for PSEUDO opcodes */
|
||||
prg_adr, /* start address of programm */
|
||||
prg_flag, /* flag for prg_adr valid */
|
||||
out_form = OUTDEF, /* format of object file */
|
||||
symsize; /* size of symarray */
|
||||
|
||||
FILE *srcfp, /* file pointer for current source */
|
||||
*objfp, /* file pointer for object code */
|
||||
*lstfp, /* file pointer for listing */
|
||||
*errfp; /* file pointer for error output */
|
||||
|
||||
unsigned
|
||||
c_line, /* current line no. in current source */
|
||||
s_line, /* line no. counter for listing */
|
||||
p_line, /* no. printed lines on page */
|
||||
ppl = PLENGTH, /* page length */
|
||||
page; /* no. of pages for listing */
|
||||
|
||||
struct sym
|
||||
*symtab[HASHSIZE], /* symbol table */
|
||||
**symarray; /* sorted symbol table */
|
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Z80 - Assembler
|
||||
* Copyright (C) 1987-2006 by Udo Munk
|
||||
*
|
||||
* History:
|
||||
* 17-SEP-1987 Development under Digital Research CP/M 2.2
|
||||
* 28-JUN-1988 Switched to Unix System V.3
|
||||
* 21-OCT-2006 changed to ANSI C for modern POSIX OS's
|
||||
*/
|
||||
|
||||
/*
|
||||
* global variable declarations
|
||||
*/
|
||||
|
||||
extern char *infiles[],
|
||||
objfn[],
|
||||
lstfn[],
|
||||
*srcfn,
|
||||
line[],
|
||||
tmp[],
|
||||
label[],
|
||||
opcode[],
|
||||
operand[],
|
||||
ops[],
|
||||
title[];
|
||||
|
||||
extern int list_flag,
|
||||
sym_flag,
|
||||
ver_flag,
|
||||
dump_flag,
|
||||
pc,
|
||||
pass,
|
||||
iflevel,
|
||||
gencode,
|
||||
errors,
|
||||
errnum,
|
||||
sd_flag,
|
||||
sd_val,
|
||||
prg_adr,
|
||||
prg_flag,
|
||||
out_form,
|
||||
symsize,
|
||||
no_opcodes,
|
||||
no_operands;
|
||||
|
||||
extern FILE *srcfp,
|
||||
*objfp,
|
||||
*lstfp,
|
||||
*errfp;
|
||||
|
||||
extern unsigned c_line,
|
||||
s_line,
|
||||
p_line,
|
||||
ppl,
|
||||
page;
|
||||
|
||||
extern struct sym *symtab[],
|
||||
**symarray;
|
||||
|
||||
extern struct opc opctab[];
|
||||
|
||||
extern struct ope opetab[];
|
@@ -1,503 +0,0 @@
|
||||
/*
|
||||
* Z80 - Assembler
|
||||
* Copyright (C) 1987-2006 by Udo Munk
|
||||
*
|
||||
* History:
|
||||
* 17-SEP-1987 Development under Digital Research CP/M 2.2
|
||||
* 28-JUN-1988 Switched to Unix System V.3
|
||||
* 21-OCT-2006 changed to ANSI C for modern POSIX OS's
|
||||
*/
|
||||
|
||||
/*
|
||||
* main module, handles the options and runs 2 passes over the sources
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "z80a.h"
|
||||
#include "z80aglb.h"
|
||||
|
||||
void init(void), options(int, char *[]);
|
||||
void usage(void), fatal(int, char *);
|
||||
void pass1(void), p1_file(char *);
|
||||
void pass2(void), p2_file(char *);
|
||||
void open_o_files(char *), get_fn(char *, char *, char *);
|
||||
char *get_label(char *, char *);
|
||||
char *get_opcode(char *, char *);
|
||||
char *get_arg(char *, char *);
|
||||
|
||||
extern void asmerr(int);
|
||||
extern void lst_line(int, int);
|
||||
extern void lst_sym(void);
|
||||
extern void lst_sort_sym(int);
|
||||
extern void obj_header(void);
|
||||
extern void obj_end(void);
|
||||
extern void obj_writeb(int);
|
||||
extern struct opc *search_op(char *);
|
||||
extern int put_sym(char *, int);
|
||||
extern void put_label(void);
|
||||
extern int copy_sym(void);
|
||||
extern void n_sort_sym(int);
|
||||
extern void a_sort_sym(int);
|
||||
|
||||
static char *errmsg[] = { /* error messages for fatal() */
|
||||
"out of memory: %s", /* 0 */
|
||||
"usage: z80asm -ofile -f[b|m|h] -l[file] -s[n|a] {-x} -v -dsymbol ... file ...",
|
||||
"Assembly halted", /* 2 */
|
||||
"can't open file %s", /* 3 */
|
||||
"internal error: %s" /* 4 */
|
||||
};
|
||||
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int len;
|
||||
|
||||
init();
|
||||
options(argc, argv);
|
||||
printf("Z80 - Assembler Release %s, %s\n", REL, COPYR);
|
||||
pass1();
|
||||
pass2();
|
||||
if (list_flag) {
|
||||
switch (sym_flag) {
|
||||
case 0: /* no symbol table */
|
||||
break;
|
||||
case 1: /* unsorted symbol table */
|
||||
lst_sym();
|
||||
break;
|
||||
case 2: /* symbol table sorted by name */
|
||||
len = copy_sym();
|
||||
n_sort_sym(len);
|
||||
lst_sort_sym(len);
|
||||
break;
|
||||
case 3: /* symbol table sorted by address */
|
||||
len = copy_sym();
|
||||
a_sort_sym(len);
|
||||
lst_sort_sym(len);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
fclose(lstfp);
|
||||
}
|
||||
return(errors);
|
||||
}
|
||||
|
||||
/*
|
||||
* initialization
|
||||
*/
|
||||
void init(void)
|
||||
{
|
||||
errfp = stdout;
|
||||
}
|
||||
|
||||
/*
|
||||
* process options
|
||||
*/
|
||||
void options(int argc, char *argv[])
|
||||
{
|
||||
register char *s, *t;
|
||||
register int i;
|
||||
|
||||
while (--argc > 0 && (*++argv)[0] == '-')
|
||||
for (s = argv[0]+1; *s != '\0'; s++)
|
||||
switch (*s) {
|
||||
case 'o':
|
||||
case 'O':
|
||||
if (*++s == '\0') {
|
||||
puts("name missing in option -o");
|
||||
usage();
|
||||
}
|
||||
get_fn(objfn, s, OBJEXT);
|
||||
s += (strlen(s) - 1);
|
||||
break;
|
||||
case 'l':
|
||||
case 'L':
|
||||
if (*(s + 1) != '\0') {
|
||||
get_fn(lstfn, ++s, LSTEXT);
|
||||
s += (strlen(s) - 1);
|
||||
}
|
||||
list_flag = 1;
|
||||
break;
|
||||
case 's':
|
||||
case 'S':
|
||||
if (*(s + 1) == '\0')
|
||||
sym_flag = 1;
|
||||
else if ((*(s + 1) == 'n') || (*(s + 1) == 'N'))
|
||||
sym_flag = 2;
|
||||
else if ((*(s + 1) == 'a') || (*(s + 1) == 'A'))
|
||||
sym_flag = 3;
|
||||
else {
|
||||
printf("unknown option -%s\n", s);
|
||||
usage();
|
||||
}
|
||||
s += (strlen(s) - 1);
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
dump_flag = 1;
|
||||
break;
|
||||
case 'f':
|
||||
case 'F':
|
||||
if ((*(s + 1) == 'b') || (*(s + 1) == 'B'))
|
||||
out_form = OUTBIN;
|
||||
else if ((*(s + 1) == 'm') || (*(s + 1) == 'M'))
|
||||
out_form = OUTMOS;
|
||||
else if ((*(s + 1) == 'h') || (*(s + 1) == 'H'))
|
||||
out_form = OUTHEX;
|
||||
else {
|
||||
printf("unknown option -%s\n", s);
|
||||
usage();
|
||||
}
|
||||
s += (strlen(s) - 1);
|
||||
break;
|
||||
case 'd':
|
||||
case 'D':
|
||||
if (*++s == '\0') {
|
||||
puts("name missing in option -d");
|
||||
usage();
|
||||
}
|
||||
t = tmp;
|
||||
while (*s)
|
||||
*t++ = islower(*s) ? toupper(*s++)
|
||||
: *s++;
|
||||
s--;
|
||||
*t = '\0';
|
||||
if (put_sym(tmp, 0))
|
||||
fatal(F_OUTMEM, "symbols");
|
||||
break;
|
||||
case 'v':
|
||||
case 'V':
|
||||
ver_flag = 1;
|
||||
break;
|
||||
default :
|
||||
printf("unknown option %c\n", *s);
|
||||
usage();
|
||||
}
|
||||
i = 0;
|
||||
while ((argc--) && (i < MAXFN)) {
|
||||
if ((infiles[i] = malloc(LENFN + 1)) == NULL)
|
||||
fatal(F_OUTMEM, "filenames");
|
||||
get_fn(infiles[i], *argv++, SRCEXT);
|
||||
i++;
|
||||
}
|
||||
if (i == 0) {
|
||||
printf("no input file given\n");
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* error in options, print usage
|
||||
*/
|
||||
void usage(void)
|
||||
{
|
||||
fatal(F_USAGE, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* print error messages and abort
|
||||
*/
|
||||
void fatal(int i, char *arg)
|
||||
{
|
||||
printf(errmsg[i], arg);
|
||||
putchar('\n');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pass 1:
|
||||
* - process all source files
|
||||
*/
|
||||
void pass1(void)
|
||||
{
|
||||
register int fi;
|
||||
|
||||
pass = 1;
|
||||
pc = 0;
|
||||
fi = 0;
|
||||
if (!ver_flag)
|
||||
puts("Pass 1");
|
||||
open_o_files(infiles[fi]);
|
||||
while (infiles[fi] != NULL) {
|
||||
if (!ver_flag)
|
||||
printf(" Read %s\n", infiles[fi]);
|
||||
p1_file(infiles[fi]);
|
||||
fi++;
|
||||
}
|
||||
if (errors) {
|
||||
fclose(objfp);
|
||||
unlink(objfn);
|
||||
printf("%d error(s)\n", errors);
|
||||
fatal(F_HALT, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Pass 1:
|
||||
* - process one source file
|
||||
*
|
||||
* Input: name of source file
|
||||
*/
|
||||
void p1_file(char *fn)
|
||||
{
|
||||
c_line = 0;
|
||||
srcfn = fn;
|
||||
if ((srcfp = fopen(fn, READA)) == NULL)
|
||||
fatal(F_FOPEN, fn);
|
||||
while (p1_line())
|
||||
;
|
||||
fclose(srcfp);
|
||||
if (iflevel)
|
||||
asmerr(E_MISEIF);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pass 1:
|
||||
* - process one line of source
|
||||
*
|
||||
* Output: 1 line processed
|
||||
* 0 EOF
|
||||
*/
|
||||
int p1_line(void)
|
||||
{
|
||||
register char *p;
|
||||
register int i;
|
||||
register struct opc *op;
|
||||
|
||||
if ((p = fgets(line, MAXLINE, srcfp)) == NULL)
|
||||
return(0);
|
||||
c_line++;
|
||||
p = get_label(label, p);
|
||||
p = get_opcode(opcode, p);
|
||||
p = get_arg(operand, p);
|
||||
if (strcmp(opcode, ENDFILE) == 0)
|
||||
return(0);
|
||||
if (*opcode) {
|
||||
if ((op = search_op(opcode)) != NULL) {
|
||||
i = (*op->op_fun)(op->op_c1, op->op_c2);
|
||||
if (gencode)
|
||||
pc += i;
|
||||
} else
|
||||
asmerr(E_ILLOPC);
|
||||
} else
|
||||
if (*label)
|
||||
put_label();
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pass 2:
|
||||
* - process all source files
|
||||
*/
|
||||
void pass2(void)
|
||||
{
|
||||
register int fi;
|
||||
|
||||
pass = 2;
|
||||
pc = 0;
|
||||
fi = 0;
|
||||
if (!ver_flag)
|
||||
puts("Pass 2");
|
||||
obj_header();
|
||||
while (infiles[fi] != NULL) {
|
||||
if (!ver_flag)
|
||||
printf(" Read %s\n", infiles[fi]);
|
||||
p2_file(infiles[fi]);
|
||||
fi++;
|
||||
}
|
||||
obj_end();
|
||||
fclose(objfp);
|
||||
printf("%d error(s)\n", errors);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pass 2:
|
||||
* - process one source file
|
||||
*
|
||||
* Input: name of source file
|
||||
*/
|
||||
void p2_file(char *fn)
|
||||
{
|
||||
c_line = 0;
|
||||
srcfn = fn;
|
||||
if ((srcfp = fopen(fn, READA)) == NULL)
|
||||
fatal(F_FOPEN, fn);
|
||||
while (p2_line())
|
||||
;
|
||||
fclose(srcfp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pass 2:
|
||||
* - process one line of source
|
||||
*
|
||||
* Output: 1 line processed
|
||||
* 0 EOF
|
||||
*/
|
||||
int p2_line(void)
|
||||
{
|
||||
register char *p;
|
||||
register int op_count;
|
||||
register struct opc *op;
|
||||
|
||||
if ((p = fgets(line, MAXLINE, srcfp)) == NULL)
|
||||
return(0);
|
||||
c_line++;
|
||||
s_line++;
|
||||
p = get_label(label, p);
|
||||
p = get_opcode(opcode, p);
|
||||
p = get_arg(operand, p);
|
||||
if (strcmp(opcode, ENDFILE) == 0) {
|
||||
lst_line(pc, 0);
|
||||
return(0);
|
||||
}
|
||||
if (*opcode) {
|
||||
op = search_op(opcode);
|
||||
op_count = (*op->op_fun)(op->op_c1, op->op_c2);
|
||||
if (gencode) {
|
||||
lst_line(pc, op_count);
|
||||
obj_writeb(op_count);
|
||||
pc += op_count;
|
||||
} else {
|
||||
sd_flag = 2;
|
||||
lst_line(0, 0);
|
||||
}
|
||||
} else {
|
||||
sd_flag = 2;
|
||||
lst_line(0, 0);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* open output files:
|
||||
* input is filename of source file
|
||||
* list and object filenames are build from source filename if
|
||||
* not given by options
|
||||
*/
|
||||
void open_o_files(char *source)
|
||||
{
|
||||
register char *p;
|
||||
|
||||
if (*objfn == '\0')
|
||||
strcpy(objfn, source);
|
||||
if ((p = strrchr(objfn, '.')) != NULL)
|
||||
strcpy(p, OBJEXT);
|
||||
else
|
||||
strcat(objfn, OBJEXT);
|
||||
|
||||
if (out_form == OUTHEX)
|
||||
objfp = fopen(objfn, WRITEA);
|
||||
else
|
||||
objfp = fopen(objfn, WRITEB);
|
||||
if (objfp == NULL)
|
||||
fatal(F_FOPEN, objfn);
|
||||
if (list_flag) {
|
||||
if (*lstfn == '\0')
|
||||
strcpy(lstfn, source);
|
||||
if ((p = strrchr(lstfn, '.')) != NULL)
|
||||
strcpy(p, LSTEXT);
|
||||
else
|
||||
strcat(lstfn, LSTEXT);
|
||||
if ((lstfp = fopen(lstfn, WRITEA)) == NULL)
|
||||
fatal(F_FOPEN, lstfn);
|
||||
errfp = lstfp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* create a filename in "dest" from "src" and "ext"
|
||||
*/
|
||||
void get_fn(char *dest, char *src, char *ext)
|
||||
{
|
||||
register int i;
|
||||
register char *sp, *dp;
|
||||
|
||||
i = 0;
|
||||
sp = src;
|
||||
dp = dest;
|
||||
while ((i++ < LENFN) && (*sp != '\0'))
|
||||
*dp++ = *sp++;
|
||||
*dp = '\0';
|
||||
if ((strrchr(dest,'.') == NULL) &&
|
||||
(strlen(dest) <= (LENFN - strlen(ext))))
|
||||
strcat(dest, ext);
|
||||
}
|
||||
|
||||
/*
|
||||
* get labels, constants and variables from source line
|
||||
* convert names to upper case and truncate length of name
|
||||
*/
|
||||
char *get_label(char *s, char *l)
|
||||
{
|
||||
register int i;
|
||||
|
||||
i = 0;
|
||||
if (*l == LINCOM)
|
||||
goto comment;
|
||||
while (!isspace(*l) && *l != COMMENT && *l != LABSEP && i < SYMSIZE) {
|
||||
*s++ = islower(*l) ? toupper(*l++) : *l++;
|
||||
i++;
|
||||
}
|
||||
comment:
|
||||
*s = '\0';
|
||||
return(l);
|
||||
}
|
||||
|
||||
/*
|
||||
* get opcode into s from source line l
|
||||
* converts to uper case
|
||||
*/
|
||||
char *get_opcode(char *s, char *l)
|
||||
{
|
||||
if (*l == LINCOM)
|
||||
goto comment;
|
||||
while (!isspace(*l) && *l != COMMENT && *l != LABSEP)
|
||||
l++;
|
||||
if (*l == LABSEP)
|
||||
l++;
|
||||
while (*l == ' ' || *l == '\t')
|
||||
l++;
|
||||
while (!isspace(*l) && *l != COMMENT)
|
||||
*s++ = islower(*l) ? toupper(*l++) : *l++;
|
||||
comment:
|
||||
*s = '\0';
|
||||
return(l);
|
||||
}
|
||||
|
||||
/*
|
||||
* get operand into s from source line l
|
||||
* converts to upper case
|
||||
* strings inside of 's are copied without changes
|
||||
*/
|
||||
char *get_arg(char *s, char *l)
|
||||
{
|
||||
if (*l == LINCOM)
|
||||
goto comment;
|
||||
while (*l == ' ' || *l == '\t')
|
||||
l++;
|
||||
while (*l != '\n' && *l != COMMENT) {
|
||||
if (isspace(*l)) {
|
||||
l++;
|
||||
continue;
|
||||
}
|
||||
if (*l != STRSEP) {
|
||||
*s++ = islower(*l) ? toupper(*l) : *l;
|
||||
l++;
|
||||
continue;
|
||||
}
|
||||
*s++ = *l++;
|
||||
if (*(s - 2) == 'F') /* EX AF,AF' !!!!! */
|
||||
continue;
|
||||
while (*l != STRSEP) {
|
||||
if (*l == '\n' || *l == '\0' || *l == COMMENT)
|
||||
goto comment;
|
||||
*s++ = *l++;
|
||||
}
|
||||
*s++ = *l++;
|
||||
}
|
||||
comment:
|
||||
*s = '\0';
|
||||
return(l);
|
||||
}
|
@@ -1,309 +0,0 @@
|
||||
/*
|
||||
* Z80 - Assembler
|
||||
* Copyright (C) 1987-2006 by Udo Munk
|
||||
*
|
||||
* History:
|
||||
* 17-SEP-1987 Development under Digital Research CP/M 2.2
|
||||
* 28-JUN-1988 Switched to Unix System V.3
|
||||
* 21-OCT-2006 changed to ANSI C for modern POSIX OS's
|
||||
*/
|
||||
|
||||
/*
|
||||
* modul with numercial computation and conversion
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "z80a.h"
|
||||
#include "z80aglb.h"
|
||||
|
||||
#ifndef isxdigit
|
||||
#define isxdigit(c) (isdigit(c) || (c>='a' && c<='f') || (c>='A' && c<='F'))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* definitions of operator symbols for expression parser
|
||||
*/
|
||||
#define OPEDEC 1 /* decimal number */
|
||||
#define OPEHEX 2 /* hexadecimal number */
|
||||
#define OPEOCT 3 /* octal number */
|
||||
#define OPEBIN 4 /* binary number */
|
||||
#define OPESUB 5 /* arithmetical - */
|
||||
#define OPEADD 6 /* arithmetical + */
|
||||
#define OPEMUL 7 /* arithmetical * */
|
||||
#define OPEDIV 8 /* arithmetical / */
|
||||
#define OPEMOD 9 /* arithmetical modulo */
|
||||
#define OPESHL 10 /* logical shift left */
|
||||
#define OPESHR 11 /* logical shift right */
|
||||
#define OPELOR 12 /* logical OR */
|
||||
#define OPELAN 13 /* logical AND */
|
||||
#define OPEXOR 14 /* logical XOR */
|
||||
#define OPECOM 15 /* logical complement */
|
||||
#define OPESYM 99 /* symbol */
|
||||
|
||||
extern struct sym *get_sym(char *);
|
||||
extern void asmerr(int);
|
||||
|
||||
/*
|
||||
* recursive expression parser
|
||||
*
|
||||
* Input: pointer to argument rest string
|
||||
*
|
||||
* Output: computed value
|
||||
*/
|
||||
int eval(char *s)
|
||||
{
|
||||
register char *p;
|
||||
register int val;
|
||||
char word[MAXLINE];
|
||||
struct sym *sp;
|
||||
|
||||
val = 0;
|
||||
while (*s) {
|
||||
p = word;
|
||||
if (*s == '(') {
|
||||
s++;
|
||||
while (*s != ')') {
|
||||
if (*s == '\0') {
|
||||
asmerr(E_MISPAR);
|
||||
goto eval_break;
|
||||
}
|
||||
*p++ = *s++;
|
||||
}
|
||||
*p = '\0';
|
||||
s++;
|
||||
val = eval(word);
|
||||
continue;
|
||||
}
|
||||
if (*s == STRSEP) {
|
||||
s++;
|
||||
while (*s != STRSEP) {
|
||||
if (*s == '\n' || *s == '\0') {
|
||||
asmerr(E_MISHYP);
|
||||
goto hyp_error;
|
||||
}
|
||||
*p++ = *s++;
|
||||
}
|
||||
s++;
|
||||
hyp_error:
|
||||
*p = '\0';
|
||||
val = strval(word);
|
||||
continue;
|
||||
}
|
||||
if (isari(*s))
|
||||
*p++ = *s++;
|
||||
else
|
||||
while (!isspace(*s) && !isari(*s) && (*s != '\0'))
|
||||
*p++ = *s++;
|
||||
*p = '\0';
|
||||
switch (get_type(word)) {
|
||||
case OPESYM: /* symbol */
|
||||
if (strcmp(word, "$") == 0) {
|
||||
val = pc;
|
||||
break;
|
||||
}
|
||||
if (strlen(word) > SYMSIZE)
|
||||
word[SYMSIZE] = '\0';
|
||||
if ((sp = get_sym(word)) != NULL)
|
||||
val = sp->sym_wert;
|
||||
else
|
||||
asmerr(E_UNDSYM);
|
||||
break;
|
||||
case OPEDEC: /* decimal number */
|
||||
val = atoi(word);
|
||||
break;
|
||||
case OPEHEX: /* hexadecimal number */
|
||||
val = axtoi(word);
|
||||
break;
|
||||
case OPEBIN: /* binary number */
|
||||
val = abtoi(word);
|
||||
break;
|
||||
case OPEOCT: /* octal number */
|
||||
val = aotoi(word);
|
||||
break;
|
||||
case OPESUB: /* arithmetical - */
|
||||
val -= eval(s);
|
||||
goto eval_break;
|
||||
case OPEADD: /* arithmetical + */
|
||||
val += eval(s);
|
||||
goto eval_break;
|
||||
case OPEMUL: /* arithmetical * */
|
||||
val *= eval(s);
|
||||
goto eval_break;
|
||||
case OPEDIV: /* arithmetical / */
|
||||
val /= eval(s);
|
||||
goto eval_break;
|
||||
case OPEMOD: /* arithmetical modulo */
|
||||
val %= eval(s);
|
||||
goto eval_break;
|
||||
case OPESHL: /* logical shift left */
|
||||
val <<= eval(s);
|
||||
goto eval_break;
|
||||
case OPESHR: /* logical shift right */
|
||||
val >>= eval(s);
|
||||
goto eval_break;
|
||||
case OPELOR: /* logical OR */
|
||||
val |= eval(s);
|
||||
goto eval_break;
|
||||
case OPELAN: /* logical AND */
|
||||
val &= eval(s);
|
||||
goto eval_break;
|
||||
case OPEXOR: /* logical XOR */
|
||||
val ^= eval(s);
|
||||
goto eval_break;
|
||||
case OPECOM: /* logical complement */
|
||||
val = ~(eval(s));
|
||||
goto eval_break;
|
||||
}
|
||||
}
|
||||
eval_break:
|
||||
return(val);
|
||||
}
|
||||
|
||||
/*
|
||||
* get typ of operand
|
||||
*
|
||||
* Input: pointer to string with operand
|
||||
*
|
||||
* Output: operand typ
|
||||
*/
|
||||
int get_type(char *s)
|
||||
{
|
||||
if (isdigit(*s)) { /* numerical operand */
|
||||
if (isdigit(*(s + strlen(s) - 1))) /* decimal number */
|
||||
return(OPEDEC);
|
||||
else if (*(s + strlen(s) - 1) == 'H') /* hexadecimal number */
|
||||
return(OPEHEX);
|
||||
else if (*(s + strlen(s) - 1) == 'B') /* binary number */
|
||||
return(OPEBIN);
|
||||
else if (*(s + strlen(s) - 1) == 'O') /* octal number */
|
||||
return(OPEOCT);
|
||||
} else if (*s == '-') /* arithmetical operand - */
|
||||
return(OPESUB);
|
||||
else if (*s == '+') /* arithmetical operand + */
|
||||
return(OPEADD);
|
||||
else if (*s == '*') /* arithmetical operand * */
|
||||
return(OPEMUL);
|
||||
else if (*s == '/') /* arithmetical operand / */
|
||||
return(OPEDIV);
|
||||
else if (*s == '%') /* arithmetical modulo */
|
||||
return(OPEMOD);
|
||||
else if (*s == '<') /* logical shift left */
|
||||
return(OPESHL);
|
||||
else if (*s == '>') /* logical shift rigth */
|
||||
return(OPESHR);
|
||||
else if (*s == '|') /* logical OR */
|
||||
return(OPELOR);
|
||||
else if (*s == '&') /* logical AND */
|
||||
return(OPELAN);
|
||||
else if (*s == '^') /* logical XOR */
|
||||
return(OPEXOR);
|
||||
else if (*s == '~') /* logical complement */
|
||||
return(OPECOM);
|
||||
return(OPESYM); /* operand is symbol */
|
||||
}
|
||||
|
||||
/*
|
||||
* check a character for arithmetical operators
|
||||
* +, -, *, /, %, <, >, |, &, ~ and ^
|
||||
*/
|
||||
int isari(int c)
|
||||
{
|
||||
return((c) == '+' || (c) == '-' || (c) == '*' ||
|
||||
(c) == '/' || (c) == '%' || (c) == '<' ||
|
||||
(c) == '>' || (c) == '|' || (c) == '&' ||
|
||||
(c) == '~' || (c) == '^');
|
||||
}
|
||||
|
||||
/*
|
||||
* conversion of string with hexadecimal number to integer
|
||||
* format: nnnnH or 0nnnnH if 1st digit > 9
|
||||
*/
|
||||
int axtoi(char *str)
|
||||
{
|
||||
register int num;
|
||||
|
||||
num = 0;
|
||||
while (isxdigit(*str)) {
|
||||
num *= 16;
|
||||
num += *str - ((*str <= '9') ? '0' : '7');
|
||||
str++;
|
||||
}
|
||||
return(num);
|
||||
}
|
||||
|
||||
/*
|
||||
* conversion of string with octal number to integer
|
||||
* format: nnnnO
|
||||
*/
|
||||
int aotoi(char *str)
|
||||
{
|
||||
register int num;
|
||||
|
||||
num = 0;
|
||||
while ('0' <= *str && *str <= '7') {
|
||||
num *= 8;
|
||||
num += (*str++) - '0';
|
||||
}
|
||||
return(num);
|
||||
}
|
||||
|
||||
/*
|
||||
* conversion of string with binary number to integer
|
||||
* format: nnnnnnnnnnnnnnnnB
|
||||
*/
|
||||
int abtoi(char *str)
|
||||
{
|
||||
register int num;
|
||||
|
||||
num = 0;
|
||||
while ('0' <= *str && *str <= '1') {
|
||||
num *= 2;
|
||||
num += (*str++) - '0';
|
||||
}
|
||||
return(num);
|
||||
}
|
||||
|
||||
/*
|
||||
* convert ASCII string to integer
|
||||
*/
|
||||
int strval(char *str)
|
||||
{
|
||||
register int num;
|
||||
|
||||
num = 0;
|
||||
while (*str) {
|
||||
num <<= 8;
|
||||
num += (int) *str++;
|
||||
}
|
||||
return(num);
|
||||
}
|
||||
|
||||
/*
|
||||
* check value for range -256 < value < 256
|
||||
* Output: value if in range, otherwise 0 and error message
|
||||
*/
|
||||
int chk_v1(int i)
|
||||
{
|
||||
if (i >= -255 && i <= 255)
|
||||
return(i);
|
||||
else {
|
||||
asmerr(E_VALOUT);
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* check value for range -128 < value < 128
|
||||
* Output: value if in range, otherwise 0 and error message
|
||||
*/
|
||||
int chk_v2(int i)
|
||||
{
|
||||
if (i >= -127 && i <= 127)
|
||||
return(i);
|
||||
else {
|
||||
asmerr(E_VALOUT);
|
||||
return(0);
|
||||
}
|
||||
}
|
@@ -1,172 +0,0 @@
|
||||
/*
|
||||
* Z80 - Assembler
|
||||
* Copyright (C) 1987-2006 by Udo Munk
|
||||
*
|
||||
* History:
|
||||
* 17-SEP-1987 Development under Digital Research CP/M 2.2
|
||||
* 28-JUN-1988 Switched to Unix System V.3
|
||||
* 21-OCT-2006 changed to ANSI C for modern POSIX OS's
|
||||
*/
|
||||
|
||||
/*
|
||||
* opcode tables
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "z80a.h"
|
||||
|
||||
extern int op_1b(), op_2b(), op_pupo(), op_ex(), op_ld();
|
||||
extern int op_call(), op_ret(), op_jp(), op_jr(), op_djnz(), op_rst();
|
||||
extern int op_add(), op_adc(), op_sub(), op_sbc(), op_cp();
|
||||
extern int op_inc(), op_dec(), op_or(), op_xor(), op_and();
|
||||
extern int op_rl(), op_rr(), op_sla(), op_sra(), op_srl(), op_rlc(), op_rrc();
|
||||
extern int op_out(), op_in(), op_im();
|
||||
extern int op_set(), op_res(), op_bit();
|
||||
extern int op_org(), op_dl(), op_equ();
|
||||
extern int op_ds(), op_db(), op_dw(), op_dm();
|
||||
extern int op_misc();
|
||||
extern int op_cond();
|
||||
extern int op_glob();
|
||||
|
||||
/*
|
||||
* opcode table:
|
||||
* includes entries for all opcodes and pseudo ops other than END
|
||||
* must be sorted in ascending order!
|
||||
*/
|
||||
struct opc opctab[] = {
|
||||
{ "ADC", op_adc, 0, 0 },
|
||||
{ "ADD", op_add, 0, 0 },
|
||||
{ "AND", op_and, 0, 0 },
|
||||
{ "BIT", op_bit, 0, 0 },
|
||||
{ "CALL", op_call, 0, 0 },
|
||||
{ "CCF", op_1b, 0x3f, 0 },
|
||||
{ "CP", op_cp, 0, 0 },
|
||||
{ "CPD", op_2b, 0xed, 0xa9 },
|
||||
{ "CPDR", op_2b, 0xed, 0xb9 },
|
||||
{ "CPI", op_2b, 0xed, 0xa1 },
|
||||
{ "CPIR", op_2b, 0xed, 0xb1 },
|
||||
{ "CPL", op_1b, 0x2f, 0 },
|
||||
{ "DAA", op_1b, 0x27, 0 },
|
||||
{ "DEC", op_dec, 0, 0 },
|
||||
{ "DEFB", op_db, 0, 0 },
|
||||
{ "DEFL", op_dl, 0, 0 },
|
||||
{ "DEFM", op_dm, 0, 0 },
|
||||
{ "DEFS", op_ds, 0, 0 },
|
||||
{ "DEFW", op_dw, 0, 0 },
|
||||
{ "DI", op_1b, 0xf3, 0 },
|
||||
{ "DJNZ", op_djnz, 0, 0 },
|
||||
{ "EI", op_1b, 0xfb, 0 },
|
||||
{ "EJECT", op_misc, 1, 0 },
|
||||
{ "ELSE", op_cond, 98, 0 },
|
||||
{ "ENDIF", op_cond, 99, 0 },
|
||||
{ "EQU", op_equ, 0, 0 },
|
||||
{ "EX", op_ex, 0, 0 },
|
||||
{ "EXTRN", op_glob, 1, 0 },
|
||||
{ "EXX", op_1b, 0xd9, 0 },
|
||||
{ "HALT", op_1b, 0x76, 0 },
|
||||
{ "IFDEF", op_cond, 1, 0 },
|
||||
{ "IFEQ", op_cond, 3, 0 },
|
||||
{ "IFNDEF", op_cond, 2, 0 },
|
||||
{ "IFNEQ", op_cond, 4, 0 },
|
||||
{ "IM", op_im, 0, 0 },
|
||||
{ "IN", op_in, 0, 0 },
|
||||
{ "INC", op_inc, 0, 0 },
|
||||
{ "INCLUDE", op_misc, 6, 0 },
|
||||
{ "IND", op_2b, 0xed, 0xaa },
|
||||
{ "INDR", op_2b, 0xed, 0xba },
|
||||
{ "INI", op_2b, 0xed, 0xa2 },
|
||||
{ "INIR", op_2b, 0xed, 0xb2 },
|
||||
{ "JP", op_jp, 0, 0 },
|
||||
{ "JR", op_jr, 0, 0 },
|
||||
{ "LD", op_ld, 0, 0 },
|
||||
{ "LDD", op_2b, 0xed, 0xa8 },
|
||||
{ "LDDR", op_2b, 0xed, 0xb8 },
|
||||
{ "LDI", op_2b, 0xed, 0xa0 },
|
||||
{ "LDIR", op_2b, 0xed, 0xb0 },
|
||||
{ "LIST", op_misc, 2, 0 },
|
||||
{ "NEG", op_2b, 0xed, 0x44 },
|
||||
{ "NOLIST", op_misc, 3, 0 },
|
||||
{ "NOP", op_1b, 0, 0 },
|
||||
{ "OR", op_or, 0, 0 },
|
||||
{ "ORG", op_org, 0, 0 },
|
||||
{ "OTDR", op_2b, 0xed, 0xbb },
|
||||
{ "OTIR", op_2b, 0xed, 0xb3 },
|
||||
{ "OUT", op_out, 0, 0 },
|
||||
{ "OUTD", op_2b, 0xed, 0xab },
|
||||
{ "OUTI", op_2b, 0xed, 0xa3 },
|
||||
{ "PAGE", op_misc, 4, 0 },
|
||||
{ "POP", op_pupo, 1, 0 },
|
||||
{ "PRINT", op_misc, 5, 0 },
|
||||
{ "PUBLIC", op_glob, 2, 0 },
|
||||
{ "PUSH", op_pupo, 2, 0 },
|
||||
{ "RES", op_res, 0, 0 },
|
||||
{ "RET", op_ret, 0, 0 },
|
||||
{ "RETI", op_2b, 0xed, 0x4d },
|
||||
{ "RETN", op_2b, 0xed, 0x45 },
|
||||
{ "RL", op_rl, 0, 0 },
|
||||
{ "RLA", op_1b, 0x17, 0 },
|
||||
{ "RLC", op_rlc, 0, 0 },
|
||||
{ "RLCA", op_1b, 0x07, 0 },
|
||||
{ "RLD", op_2b, 0xed, 0x6f },
|
||||
{ "RR", op_rr, 0, 0 },
|
||||
{ "RRA", op_1b, 0x1f, 0 },
|
||||
{ "RRC", op_rrc, 0, 0 },
|
||||
{ "RRCA", op_1b, 0x0f, 0 },
|
||||
{ "RRD", op_2b, 0xed, 0x67 },
|
||||
{ "RST", op_rst, 0, 0 },
|
||||
{ "SBC", op_sbc, 0, 0 },
|
||||
{ "SCF", op_1b, 0x37, 0 },
|
||||
{ "SET", op_set, 0, 0 },
|
||||
{ "SLA", op_sla, 0, 0 },
|
||||
{ "SRA", op_sra, 0, 0 },
|
||||
{ "SRL", op_srl, 0, 0 },
|
||||
{ "SUB", op_sub, 0, 0 },
|
||||
{ "TITLE", op_misc, 7, 0 },
|
||||
{ "XOR", op_xor, 0, 0 }
|
||||
};
|
||||
|
||||
/*
|
||||
* compute no. of table entries for search_op()
|
||||
*/
|
||||
int no_opcodes = sizeof(opctab) / sizeof(struct opc);
|
||||
|
||||
/*
|
||||
* table with reserverd operand words: registers and flags
|
||||
* must be sorted in ascending order!
|
||||
*/
|
||||
struct ope opetab[] = {
|
||||
{ "(BC)", REGIBC },
|
||||
{ "(DE)", REGIDE },
|
||||
{ "(HL)", REGIHL },
|
||||
{ "(IX)", REGIIX },
|
||||
{ "(IY)", REGIIY },
|
||||
{ "(SP)", REGISP },
|
||||
{ "A", REGA },
|
||||
{ "AF", REGAF },
|
||||
{ "B", REGB },
|
||||
{ "BC", REGBC },
|
||||
{ "C", REGC },
|
||||
{ "D", REGD },
|
||||
{ "DE", REGDE },
|
||||
{ "E", REGE },
|
||||
{ "H", REGH },
|
||||
{ "HL", REGHL },
|
||||
{ "I", REGI },
|
||||
{ "IX", REGIX },
|
||||
{ "IY", REGIY },
|
||||
{ "L", REGL },
|
||||
{ "M", FLGM },
|
||||
{ "NC", FLGNC },
|
||||
{ "NZ", FLGNZ },
|
||||
{ "P", FLGP },
|
||||
{ "PE", FLGPE },
|
||||
{ "PO", FLGPO },
|
||||
{ "R", REGR },
|
||||
{ "SP", REGSP },
|
||||
{ "Z", FLGZ }
|
||||
};
|
||||
|
||||
/*
|
||||
* compute no. of table entries
|
||||
*/
|
||||
int no_operands = sizeof(opetab) / sizeof(struct ope);
|
@@ -1,360 +0,0 @@
|
||||
/*
|
||||
* Z80 - Assembler
|
||||
* Copyright (C) 1987-2006 by Udo Munk
|
||||
*
|
||||
* History:
|
||||
* 17-SEP-1987 Development under Digital Research CP/M 2.2
|
||||
* 28-JUN-1988 Switched to Unix System V.3
|
||||
* 21-OCT-2006 changed to ANSI C for modern POSIX OS's
|
||||
*/
|
||||
|
||||
/*
|
||||
* module for output functions to list, object and error files
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "z80a.h"
|
||||
#include "z80aglb.h"
|
||||
|
||||
void flush_hex(void);
|
||||
int chksum(void);
|
||||
void btoh(unsigned char, char **);
|
||||
|
||||
extern void fatal(int, char *);
|
||||
|
||||
static char *errmsg[] = { /* error messages for asmerr() */
|
||||
"illegal opcode", /* 0 */
|
||||
"illegal operand", /* 1 */
|
||||
"missing operand", /* 2 */
|
||||
"multiply defined symbol", /* 3 */
|
||||
"undefined symbol", /* 4 */
|
||||
"value out of range", /* 5 */
|
||||
"missing )", /* 6 */
|
||||
"missing string separator", /* 7 */
|
||||
"memory override", /* 8 */
|
||||
"missing IF", /* 9 */
|
||||
"IF nesting to deep", /* 10 */
|
||||
"missing ENDIF", /* 11 */
|
||||
"INCLUDE nesting to deep" /* 12 */
|
||||
};
|
||||
|
||||
#define MAXHEX 32 /* max no bytes/hex record */
|
||||
|
||||
static unsigned short hex_adr; /* current address in hex record */
|
||||
static int hex_cnt; /* current no bytes in hex buffer */
|
||||
|
||||
static unsigned char hex_buf[MAXHEX]; /* buffer for one hex record */
|
||||
static char hex_out[MAXHEX*2+11]; /* ASCII buffer for one hex record */
|
||||
|
||||
/*
|
||||
* print error message to listfile and increase error counter
|
||||
*/
|
||||
void asmerr(int i)
|
||||
{
|
||||
if (pass == 1) {
|
||||
fprintf(errfp, "Error in file: %s Line: %d\n", srcfn, c_line);
|
||||
fprintf(errfp, errmsg[i]);
|
||||
fprintf(errfp, "\n\n");
|
||||
} else
|
||||
errnum = i;
|
||||
errors++;
|
||||
}
|
||||
|
||||
/*
|
||||
* begin new page in listfile
|
||||
*/
|
||||
void lst_header(void)
|
||||
{
|
||||
fprintf(lstfp, "\fZ80-Assembler\t\tRelease %s\t\t\t\tPage %d\n", REL,
|
||||
++page);
|
||||
fprintf(lstfp, "Source file: %s\n", srcfn);
|
||||
fprintf(lstfp, "Title: %s\n", title);
|
||||
p_line = 3;
|
||||
}
|
||||
|
||||
/*
|
||||
* print header for source lines
|
||||
*/
|
||||
void lst_attl(void)
|
||||
{
|
||||
fprintf(lstfp, "\nLOC OBJECT CODE LINE STMT SOURCE CODE\n");
|
||||
p_line += 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* print one line into listfile, if -l option set
|
||||
*/
|
||||
void lst_line(int val, int opanz)
|
||||
{
|
||||
register int i;
|
||||
|
||||
if (!list_flag || sd_flag == 4) {
|
||||
sd_flag = 0;
|
||||
return;
|
||||
}
|
||||
if ((p_line >= ppl) || (c_line == 1)) {
|
||||
lst_header();
|
||||
lst_attl();
|
||||
}
|
||||
switch (sd_flag) {
|
||||
case 0:
|
||||
fprintf(lstfp, "%04x ", val & 0xffff);
|
||||
break;
|
||||
case 1:
|
||||
fprintf(lstfp, "%04x ", sd_val & 0xffff);
|
||||
break;
|
||||
case 2:
|
||||
fprintf(lstfp, " ");
|
||||
break;
|
||||
case 3:
|
||||
fprintf(lstfp, "%04x ", sd_val & 0xffff);
|
||||
goto no_data;
|
||||
default:
|
||||
fatal(F_INTERN, "illegal listflag for function lst_line");
|
||||
break;
|
||||
}
|
||||
if (opanz >= 1) fprintf(lstfp, "%02x ", ops[0] & 0xff);
|
||||
else fprintf(lstfp, " ");
|
||||
if (opanz >= 2) fprintf(lstfp, "%02x ", ops[1] & 0xff);
|
||||
else fprintf(lstfp, " ");
|
||||
if (opanz >= 3) fprintf(lstfp, "%02x ", ops[2] & 0xff);
|
||||
else fprintf(lstfp, " ");
|
||||
if (opanz >= 4) fprintf(lstfp, "%02x ", ops[3] & 0xff);
|
||||
else fprintf(lstfp, " ");
|
||||
no_data:
|
||||
fprintf(lstfp, "%6d %6d %s", c_line, s_line, line);
|
||||
if (errnum) {
|
||||
fprintf(errfp, "=> %s", errmsg[errnum]);
|
||||
putc('\n', errfp);
|
||||
errnum = 0;
|
||||
p_line++;
|
||||
}
|
||||
sd_flag = 0;
|
||||
p_line++;
|
||||
if (opanz > 4 && sd_flag == 0) {
|
||||
opanz -= 4;
|
||||
i = 4;
|
||||
sd_val = val;
|
||||
while (opanz > 0) {
|
||||
if (p_line >= ppl) {
|
||||
lst_header();
|
||||
lst_attl();
|
||||
}
|
||||
s_line++;
|
||||
sd_val += 4;
|
||||
fprintf(lstfp, "%04x ", sd_val & 0xffff);
|
||||
if (opanz-- > 0) fprintf(lstfp, "%02x ",
|
||||
ops[i++] & 0xff);
|
||||
else fprintf(lstfp, " ");
|
||||
if (opanz-- > 0) fprintf(lstfp, "%02x ",
|
||||
ops[i++] & 0xff);
|
||||
else fprintf(lstfp, " ");
|
||||
if (opanz-- > 0) fprintf(lstfp, "%02x ",
|
||||
ops[i++] & 0xff);
|
||||
else fprintf(lstfp, " ");
|
||||
if (opanz-- > 0) fprintf(lstfp, "%02x ",
|
||||
ops[i++] & 0xff);
|
||||
else fprintf(lstfp, " ");
|
||||
fprintf(lstfp, "%6d %6d\n", c_line, s_line);
|
||||
p_line++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* print symbol table into listfile unsorted
|
||||
*/
|
||||
void lst_sym(void)
|
||||
{
|
||||
register int i, j;
|
||||
register struct sym *np;
|
||||
|
||||
p_line = j = 0;
|
||||
strcpy(title,"Symboltable");
|
||||
for (i = 0; i < HASHSIZE; i++) {
|
||||
if (symtab[i] != NULL) {
|
||||
for (np = symtab[i]; np != NULL; np = np->sym_next) {
|
||||
if (p_line == 0) {
|
||||
lst_header();
|
||||
fputs("\n", lstfp);
|
||||
p_line += 1;
|
||||
}
|
||||
fprintf(lstfp, "%-8s %04x\t", np->sym_name,
|
||||
np->sym_wert & 0xffff);
|
||||
if (++j == 4) {
|
||||
fprintf(lstfp, "\n");
|
||||
if (p_line++ >= ppl)
|
||||
p_line = 0;
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* print sorted symbol table into listfile
|
||||
*/
|
||||
void lst_sort_sym(int len)
|
||||
{
|
||||
register int i, j;
|
||||
|
||||
p_line = i = j = 0;
|
||||
strcpy(title, "Symboltable");
|
||||
while (i < len) {
|
||||
if (p_line == 0) {
|
||||
lst_header();
|
||||
fputs("\n", lstfp);
|
||||
p_line += 1;
|
||||
}
|
||||
fprintf(lstfp, "%-8s %04x\t", symarray[i]->sym_name,
|
||||
symarray[i]->sym_wert & 0xffff);
|
||||
if (++j == 4) {
|
||||
fprintf(lstfp, "\n");
|
||||
if (p_line++ >= ppl)
|
||||
p_line = 0;
|
||||
j = 0;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* write header record into object file
|
||||
*/
|
||||
void obj_header(void)
|
||||
{
|
||||
switch (out_form) {
|
||||
case OUTBIN:
|
||||
break;
|
||||
case OUTMOS:
|
||||
putc(0xff, objfp);
|
||||
putc(prg_adr & 0xff, objfp);
|
||||
putc(prg_adr >> 8, objfp);
|
||||
break;
|
||||
case OUTHEX:
|
||||
hex_adr = prg_adr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* write end record into object file
|
||||
*/
|
||||
void obj_end(void)
|
||||
{
|
||||
switch (out_form) {
|
||||
case OUTBIN:
|
||||
break;
|
||||
case OUTMOS:
|
||||
break;
|
||||
case OUTHEX:
|
||||
flush_hex();
|
||||
fprintf(objfp, ":0000000000\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* write opcodes in ops[] into object file
|
||||
*/
|
||||
void obj_writeb(int opanz)
|
||||
{
|
||||
register int i;
|
||||
|
||||
switch (out_form) {
|
||||
case OUTBIN:
|
||||
fwrite(ops, 1, opanz, objfp);
|
||||
break;
|
||||
case OUTMOS:
|
||||
fwrite(ops, 1, opanz, objfp);
|
||||
break;
|
||||
case OUTHEX:
|
||||
for (i = 0; opanz; opanz--) {
|
||||
if (hex_cnt >= MAXHEX)
|
||||
flush_hex();
|
||||
hex_buf[hex_cnt++] = ops[i++];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* write <count> bytes 0xff into object file
|
||||
*/
|
||||
void obj_fill(int count)
|
||||
{
|
||||
switch (out_form) {
|
||||
case OUTBIN:
|
||||
while (count--)
|
||||
putc(0xff, objfp);
|
||||
break;
|
||||
case OUTMOS:
|
||||
while (count--)
|
||||
putc(0xff, objfp);
|
||||
break;
|
||||
case OUTHEX:
|
||||
flush_hex();
|
||||
hex_adr += count;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* create a hex record in ASCII and write into object file
|
||||
*/
|
||||
void flush_hex(void)
|
||||
{
|
||||
char *p;
|
||||
register int i;
|
||||
|
||||
if (!hex_cnt)
|
||||
return;
|
||||
p = hex_out;
|
||||
*p++ = ':';
|
||||
btoh((unsigned char) hex_cnt, &p);
|
||||
btoh((unsigned char) (hex_adr >> 8), &p);
|
||||
btoh((unsigned char) (hex_adr & 0xff), &p);
|
||||
*p++ = '0';
|
||||
*p++ = '0';
|
||||
for (i = 0; i < hex_cnt; i++)
|
||||
btoh(hex_buf[i], &p);
|
||||
btoh((unsigned char) chksum(), &p);
|
||||
*p++ = '\n';
|
||||
*p = '\0';
|
||||
fwrite(hex_out, 1, strlen(hex_out), objfp);
|
||||
hex_adr += hex_cnt;
|
||||
hex_cnt = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* convert unsigned char into ASCII hex and copy to string at p
|
||||
* increase p by 2
|
||||
*/
|
||||
void btoh(unsigned char byte, char **p)
|
||||
{
|
||||
register unsigned char c;
|
||||
|
||||
c = byte >> 4;
|
||||
*(*p)++ = (c < 10) ? (c + '0') : (c - 10 + 'A');
|
||||
c = byte & 0xf;
|
||||
*(*p)++ = (c < 10) ? (c + '0') : (c - 10 + 'A');
|
||||
}
|
||||
|
||||
/*
|
||||
* computer checksum for Intel hex record
|
||||
*/
|
||||
int chksum(void)
|
||||
{
|
||||
register int i, j, sum;
|
||||
|
||||
sum = hex_cnt;
|
||||
sum += hex_adr >> 8;
|
||||
sum += hex_adr & 0xff;
|
||||
for (i = 0; i < hex_cnt; i++) {
|
||||
j = hex_buf[i];
|
||||
sum += j & 0xff;
|
||||
}
|
||||
return (0x100 - (sum & 0xff));
|
||||
}
|
@@ -1,446 +0,0 @@
|
||||
/*
|
||||
* Z80 - Assembler
|
||||
* Copyright (C) 1987-2006 by Udo Munk
|
||||
*
|
||||
* History:
|
||||
* 17-SEP-1987 Development under Digital Research CP/M 2.2
|
||||
* 28-JUN-1988 Switched to Unix System V.3
|
||||
* 22-OCT-2006 changed to ANSI C for modern POSIX OS's
|
||||
*/
|
||||
|
||||
/*
|
||||
* processing of all PSEUDO ops
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "z80a.h"
|
||||
#include "z80aglb.h"
|
||||
|
||||
extern void fatal(int, char *);
|
||||
extern void p1_file(char *);
|
||||
extern void p2_file(char *);
|
||||
extern int eval(char *);
|
||||
extern void asmerr(int);
|
||||
extern void lst_header(void);
|
||||
extern void lst_attl(void);
|
||||
extern void lst_line(int, int);
|
||||
extern void obj_fill(int);
|
||||
extern struct sym *get_sym(char *);
|
||||
extern int put_sym(char *, int);
|
||||
extern void put_label(void);
|
||||
|
||||
/*
|
||||
* ORG
|
||||
*/
|
||||
int op_org(void)
|
||||
{
|
||||
register int i;
|
||||
|
||||
if (!gencode)
|
||||
return(0);
|
||||
i = eval(operand);
|
||||
if (i < pc) {
|
||||
asmerr(E_MEMOVR);
|
||||
return(0);
|
||||
}
|
||||
if (pass == 1) { /* PASS 1 */
|
||||
if (!prg_flag) {
|
||||
prg_adr = i;
|
||||
prg_flag++;
|
||||
}
|
||||
} else { /* PASS 2 */
|
||||
if (++prg_flag > 2)
|
||||
obj_fill(i - pc);
|
||||
sd_flag = 2;
|
||||
}
|
||||
pc = i;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* EQU
|
||||
*/
|
||||
int op_equ(void)
|
||||
{
|
||||
if (!gencode)
|
||||
return(0);
|
||||
if (pass == 1) { /* Pass 1 */
|
||||
if (get_sym(label) == NULL) {
|
||||
sd_val = eval(operand);
|
||||
if (put_sym(label, sd_val))
|
||||
fatal(F_OUTMEM, "symbols");
|
||||
} else
|
||||
asmerr(E_MULSYM);
|
||||
} else { /* Pass 2 */
|
||||
sd_flag = 1;
|
||||
sd_val = eval(operand);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* DEFL
|
||||
*/
|
||||
int op_dl(void)
|
||||
{
|
||||
if (!gencode)
|
||||
return(0);
|
||||
sd_flag = 1;
|
||||
sd_val = eval(operand);
|
||||
if (put_sym(label, sd_val))
|
||||
fatal(F_OUTMEM, "symbols");
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* DEFS
|
||||
*/
|
||||
int op_ds(void)
|
||||
{
|
||||
register int val;
|
||||
|
||||
if (!gencode)
|
||||
return(0);
|
||||
if (pass == 1)
|
||||
if (*label)
|
||||
put_label();
|
||||
sd_val = pc;
|
||||
sd_flag = 3;
|
||||
val = eval(operand);
|
||||
if ((pass == 2) && !dump_flag)
|
||||
obj_fill(val);
|
||||
pc += val;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* DEFB
|
||||
*/
|
||||
int op_db(void)
|
||||
{
|
||||
register int i;
|
||||
register char *p;
|
||||
register char *s;
|
||||
|
||||
if (!gencode)
|
||||
return(0);
|
||||
i = 0;
|
||||
p = operand;
|
||||
if (pass == 1)
|
||||
if (*label)
|
||||
put_label();
|
||||
while (*p) {
|
||||
if (*p == STRSEP) {
|
||||
p++;
|
||||
while (*p != STRSEP) {
|
||||
if (*p == '\n' || *p == '\0') {
|
||||
asmerr(E_MISHYP);
|
||||
goto hyp_error;
|
||||
}
|
||||
ops[i++] = *p++;
|
||||
if (i >= OPCARRAY)
|
||||
fatal(F_INTERN, "Op-Code buffer overflow");
|
||||
}
|
||||
p++;
|
||||
} else {
|
||||
s = tmp;
|
||||
while (*p != ',' && *p != '\0')
|
||||
*s++ = *p++;
|
||||
*s = '\0';
|
||||
ops[i++] = eval(tmp);
|
||||
if (i >= OPCARRAY)
|
||||
fatal(F_INTERN, "Op-Code buffer overflow");
|
||||
}
|
||||
if (*p == ',')
|
||||
p++;
|
||||
}
|
||||
hyp_error:
|
||||
return(i);
|
||||
}
|
||||
|
||||
/*
|
||||
* DEFM
|
||||
*/
|
||||
int op_dm(void)
|
||||
{
|
||||
register int i;
|
||||
register char *p;
|
||||
|
||||
if (!gencode)
|
||||
return(0);
|
||||
i = 0;
|
||||
p = operand;
|
||||
if (pass == 1)
|
||||
if (*label)
|
||||
put_label();
|
||||
if (*p != STRSEP) {
|
||||
asmerr(E_MISHYP);
|
||||
return(0);
|
||||
}
|
||||
p++;
|
||||
while (*p != STRSEP) {
|
||||
if (*p == '\n' || *p == '\0') {
|
||||
asmerr(E_MISHYP);
|
||||
break;
|
||||
}
|
||||
ops[i++] = *p++;
|
||||
if (i >= OPCARRAY)
|
||||
fatal(F_INTERN, "Op-Code buffer overflow");
|
||||
}
|
||||
return(i);
|
||||
}
|
||||
|
||||
/*
|
||||
* DEFW
|
||||
*/
|
||||
int op_dw(void)
|
||||
{
|
||||
register int i, len, temp;
|
||||
register char *p;
|
||||
register char *s;
|
||||
|
||||
if (!gencode)
|
||||
return(0);
|
||||
p = operand;
|
||||
i = len = 0;
|
||||
if (pass == 1)
|
||||
if (*label)
|
||||
put_label();
|
||||
while (*p) {
|
||||
s = tmp;
|
||||
while (*p != ',' && *p != '\0')
|
||||
*s++ = *p++;
|
||||
*s = '\0';
|
||||
if (pass == 2) {
|
||||
temp = eval(tmp);
|
||||
ops[i++] = temp & 0xff;
|
||||
ops[i++] = temp >> 8;
|
||||
if (i >= OPCARRAY)
|
||||
fatal(F_INTERN, "Op-Code buffer overflow");
|
||||
}
|
||||
len += 2;
|
||||
if (*p == ',')
|
||||
p++;
|
||||
}
|
||||
return(len);
|
||||
}
|
||||
|
||||
/*
|
||||
* EJECT, LIST, NOLIST, PAGE, PRINT, TITLE, INCLUDE
|
||||
*/
|
||||
int op_misc(int op_code, int dummy)
|
||||
{
|
||||
register char *p, *d;
|
||||
static char fn[LENFN];
|
||||
static int incnest;
|
||||
static struct inc incl[INCNEST];
|
||||
|
||||
if (!gencode)
|
||||
return(0);
|
||||
sd_flag = 2;
|
||||
switch(op_code) {
|
||||
case 1: /* EJECT */
|
||||
if (pass == 2)
|
||||
p_line = ppl;
|
||||
break;
|
||||
case 2: /* LIST */
|
||||
if (pass == 2)
|
||||
list_flag = 1;
|
||||
break;
|
||||
case 3: /* NOLIST */
|
||||
if (pass == 2)
|
||||
list_flag = 0;
|
||||
break;
|
||||
case 4: /* PAGE */
|
||||
if (pass == 2)
|
||||
ppl = eval(operand);
|
||||
break;
|
||||
case 5: /* PRINT */
|
||||
if (pass == 1) {
|
||||
p = operand;
|
||||
while (*p) {
|
||||
if (*p != STRSEP)
|
||||
putchar(*p++);
|
||||
else
|
||||
p++;
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
break;
|
||||
case 6: /* INCLUDE */
|
||||
if (incnest >= INCNEST) {
|
||||
asmerr(E_INCNEST);
|
||||
break;
|
||||
}
|
||||
incl[incnest].inc_line = c_line;
|
||||
incl[incnest].inc_fn = srcfn;
|
||||
incl[incnest].inc_fp = srcfp;
|
||||
incnest++;
|
||||
p = line;
|
||||
d = fn;
|
||||
while(isspace(*p)) /* ignore white space until INCLUDE */
|
||||
p++;
|
||||
while(!isspace(*p)) /* ignore INCLUDE */
|
||||
p++;
|
||||
while(isspace(*p)) /* ignore white space until filename */
|
||||
p++;
|
||||
while(!isspace(*p) && *p != COMMENT) /* get filename */
|
||||
*d++ = *p++;
|
||||
*d = '\0';
|
||||
if (pass == 1) { /* PASS 1 */
|
||||
if (!ver_flag)
|
||||
printf(" Include %s\n", fn);
|
||||
p1_file(fn);
|
||||
} else { /* PASS 2 */
|
||||
sd_flag = 2;
|
||||
lst_line(0, 0);
|
||||
if (!ver_flag)
|
||||
printf(" Include %s\n", fn);
|
||||
p2_file(fn);
|
||||
}
|
||||
incnest--;
|
||||
c_line = incl[incnest].inc_line;
|
||||
srcfn = incl[incnest].inc_fn;
|
||||
srcfp = incl[incnest].inc_fp;
|
||||
printf(" Resume %s\n", srcfn);
|
||||
if (list_flag && (pass == 2)) {
|
||||
lst_header();
|
||||
lst_attl();
|
||||
}
|
||||
sd_flag = 4;
|
||||
break;
|
||||
case 7: /* TITLE */
|
||||
if (pass == 2) {
|
||||
p = line;
|
||||
d = title;
|
||||
while (isspace(*p)) /* ignore white space until TITLE */
|
||||
p++;
|
||||
while (!isspace(*p)) /* ignore TITLE */
|
||||
p++;
|
||||
while (isspace(*p)) /* ignore white space until text */
|
||||
p++;
|
||||
if (*p == STRSEP)
|
||||
p++;
|
||||
while (*p != '\n' && *p != STRSEP && *p != COMMENT)
|
||||
*d++ = *p++;
|
||||
*d = '\0';
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fatal(F_INTERN, "illegal opcode for function op_misc");
|
||||
break;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* IFDEF, IFNDEF, IFEQ, IFNEQ, ELSE, ENDIF
|
||||
*/
|
||||
int op_cond(int op_code, int dummy)
|
||||
{
|
||||
register char *p, *p1, *p2;
|
||||
static int condnest[IFNEST];
|
||||
|
||||
switch(op_code) {
|
||||
case 1: /* IFDEF */
|
||||
if (iflevel >= IFNEST) {
|
||||
asmerr(E_IFNEST);
|
||||
break;
|
||||
}
|
||||
condnest[iflevel++] = gencode;
|
||||
if (gencode)
|
||||
if (get_sym(operand) == NULL)
|
||||
gencode = 0;
|
||||
break;
|
||||
case 2: /* IFNDEF */
|
||||
if (iflevel >= IFNEST) {
|
||||
asmerr(E_IFNEST);
|
||||
break;
|
||||
}
|
||||
condnest[iflevel++] = gencode;
|
||||
if (gencode)
|
||||
if (get_sym(operand) != NULL)
|
||||
gencode = 0;
|
||||
break;
|
||||
case 3: /* IFEQ */
|
||||
if (iflevel >= IFNEST) {
|
||||
asmerr(E_IFNEST);
|
||||
break;
|
||||
}
|
||||
condnest[iflevel++] = gencode;
|
||||
p = operand;
|
||||
if (!*p || !(p1 = strchr(operand, ','))) {
|
||||
asmerr(E_MISOPE);
|
||||
break;
|
||||
}
|
||||
if (gencode) {
|
||||
p2 = tmp;
|
||||
while (*p != ',')
|
||||
*p2++ = *p++;
|
||||
*p2 = '\0';
|
||||
if (eval(tmp) != eval(++p1))
|
||||
gencode = 0;
|
||||
}
|
||||
break;
|
||||
case 4: /* IFNEQ */
|
||||
if (iflevel >= IFNEST) {
|
||||
asmerr(E_IFNEST);
|
||||
break;
|
||||
}
|
||||
condnest[iflevel++] = gencode;
|
||||
p = operand;
|
||||
if (!*p || !(p1 = strchr(operand, ','))) {
|
||||
asmerr(E_MISOPE);
|
||||
break;
|
||||
}
|
||||
if (gencode) {
|
||||
p2 = tmp;
|
||||
while (*p != ',')
|
||||
*p2++ = *p++;
|
||||
*p2 = '\0';
|
||||
if (eval(tmp) == eval(++p1))
|
||||
gencode = 0;
|
||||
}
|
||||
break;
|
||||
case 98: /* ELSE */
|
||||
if (!iflevel)
|
||||
asmerr(E_MISIFF);
|
||||
else
|
||||
if ((iflevel == 0) || (condnest[iflevel - 1] == 1))
|
||||
gencode = !gencode;
|
||||
break;
|
||||
case 99: /* ENDIF */
|
||||
if (!iflevel)
|
||||
asmerr(E_MISIFF);
|
||||
else
|
||||
gencode = condnest[--iflevel];
|
||||
break;
|
||||
default:
|
||||
fatal(F_INTERN, "illegal opcode for function op_cond");
|
||||
break;
|
||||
}
|
||||
sd_flag = 2;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* EXTRN and PUBLIC
|
||||
*/
|
||||
int op_glob(int op_code, int dummy)
|
||||
{
|
||||
if (!gencode)
|
||||
return(0);
|
||||
sd_flag = 2;
|
||||
switch(op_code) {
|
||||
case 1: /* EXTRN */
|
||||
break;
|
||||
case 2: /* PUBLIC */
|
||||
break;
|
||||
default:
|
||||
fatal(F_INTERN, "illegal opcode for function op_glob");
|
||||
break;
|
||||
}
|
||||
return(0);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,255 +0,0 @@
|
||||
/*
|
||||
* Z80 - Assembler
|
||||
* Copyright (C) 1987-2006 by Udo Munk
|
||||
*
|
||||
* History:
|
||||
* 17-SEP-1987 Development under Digital Research CP/M 2.2
|
||||
* 28-JUN-1988 Switched to Unix System V.3
|
||||
* 22-OCT-2006 changed to ANSI C for modern POSIX OS's
|
||||
*/
|
||||
|
||||
/*
|
||||
* module with table oprations on opcode and symbol tables
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "z80a.h"
|
||||
#include "z80aglb.h"
|
||||
|
||||
extern void fatal(int, char *);
|
||||
extern void asmerr(int);
|
||||
|
||||
/*
|
||||
* binary search in sorted table opctab
|
||||
*
|
||||
* Input: pointer to string with opcode
|
||||
*
|
||||
* Output: pointer to table element, or NULL if not found
|
||||
*/
|
||||
struct opc *search_op(char *op_name)
|
||||
{
|
||||
register int cond;
|
||||
register struct opc *low, *high, *mid;
|
||||
|
||||
low = &opctab[0];
|
||||
high = &opctab[no_opcodes - 1];
|
||||
while (low <= high) {
|
||||
mid = low + (high - low) / 2;
|
||||
if ((cond = strcmp(op_name, mid->op_name)) < 0)
|
||||
high = mid - 1;
|
||||
else if (cond > 0)
|
||||
low = mid + 1;
|
||||
else
|
||||
return(mid);
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* binary search on sorted table opetab
|
||||
*
|
||||
* Input: pointer to string with operand
|
||||
*
|
||||
* Output: symbol for operand, NOOPERA if empty operand,
|
||||
* NOREG if operand not found
|
||||
*/
|
||||
int get_reg(char *s)
|
||||
{
|
||||
register int cond;
|
||||
register struct ope *low, *high, *mid;
|
||||
|
||||
if (s == NULL || *s == '\0')
|
||||
return(NOOPERA);
|
||||
low = &opetab[0];
|
||||
high = &opetab[no_operands - 1];
|
||||
while (low <= high) {
|
||||
mid = low + (high - low) / 2;
|
||||
if ((cond = strcmp(s, mid->ope_name)) < 0)
|
||||
high = mid - 1;
|
||||
else if (cond > 0)
|
||||
low = mid + 1;
|
||||
else
|
||||
return(mid->ope_sym);
|
||||
}
|
||||
return(NOREG);
|
||||
}
|
||||
|
||||
/*
|
||||
* hash search on symbol table symtab
|
||||
*
|
||||
* Input: pointer to string with symbol
|
||||
*
|
||||
* Output: pointer to table element, or NULL if not found
|
||||
*/
|
||||
struct sym *get_sym(char *sym_name)
|
||||
{
|
||||
register struct sym *np;
|
||||
|
||||
for (np = symtab[hash(sym_name)]; np != NULL; np = np->sym_next)
|
||||
if (strcmp(sym_name, np->sym_name) == 0)
|
||||
return(np);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* add symbol to symbol table symtab, or modify existing symbol
|
||||
*
|
||||
* Input: sym_name pointer to string with symbol name
|
||||
* sym_wert value of symbol
|
||||
*
|
||||
* Output: 0 symbol added/modified
|
||||
* 1 out of memory
|
||||
*/
|
||||
int put_sym(char *sym_name, int sym_wert)
|
||||
{
|
||||
struct sym *get_sym();
|
||||
register int hashval;
|
||||
register struct sym *np;
|
||||
|
||||
char *strsave(char *);
|
||||
|
||||
if (!gencode)
|
||||
return(0);
|
||||
if ((np = get_sym(sym_name)) == NULL) {
|
||||
np = (struct sym *) malloc(sizeof (struct sym));
|
||||
if (np == NULL)
|
||||
return(1);
|
||||
if ((np->sym_name = strsave(sym_name)) == NULL)
|
||||
return(1);
|
||||
hashval = hash(sym_name);
|
||||
np->sym_next = symtab[hashval];
|
||||
symtab[hashval] = np;
|
||||
}
|
||||
np->sym_wert = sym_wert;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* add label to symbol table, error if symbol already exists
|
||||
*/
|
||||
void put_label(void)
|
||||
{
|
||||
struct sym *get_sym(char *);
|
||||
|
||||
if (get_sym(label) == NULL) {
|
||||
if (put_sym(label, pc))
|
||||
fatal(F_OUTMEM, "symbols");
|
||||
} else
|
||||
asmerr(E_MULSYM);
|
||||
}
|
||||
|
||||
/*
|
||||
* hash algorithm
|
||||
*
|
||||
* Input: pointer to string with name
|
||||
*
|
||||
* Output: hash value
|
||||
*/
|
||||
int hash(char *name)
|
||||
{
|
||||
register int hashval;
|
||||
|
||||
for (hashval = 0; *name;)
|
||||
hashval += *name++;
|
||||
return(hashval % HASHSIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
* save string into allocated memory
|
||||
*
|
||||
* Input: pointer to string
|
||||
*
|
||||
* Output: pointer to allocated memory with string
|
||||
*/
|
||||
char *strsave(char *s)
|
||||
{
|
||||
register char *p;
|
||||
|
||||
if ((p = malloc((unsigned) strlen(s)+1)) != NULL)
|
||||
strcpy(p, s);
|
||||
return(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* copy whole symbol hast table into allocated pointer array
|
||||
* used for sorting the symbol table later
|
||||
*/
|
||||
int copy_sym(void)
|
||||
{
|
||||
register int i, j;
|
||||
register struct sym *np;
|
||||
|
||||
symarray = (struct sym **) malloc(SYMINC * sizeof(struct sym *));
|
||||
if (symarray == NULL)
|
||||
fatal(F_OUTMEM, "sorting symbol table");
|
||||
symsize = SYMINC;
|
||||
for (i = 0, j = 0; i < HASHSIZE; i++) {
|
||||
if (symtab[i] != NULL) {
|
||||
for (np = symtab[i]; np != NULL; np = np->sym_next) {
|
||||
symarray[j++] = np;
|
||||
if (j == symsize) {
|
||||
symarray = (struct sym **) realloc((char *) symarray, symsize * sizeof(struct sym *) + SYMINC * sizeof(struct sym *));
|
||||
if (symarray == NULL)
|
||||
fatal(F_OUTMEM, "sorting symbol table");
|
||||
symsize += SYMINC;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return(j);
|
||||
}
|
||||
|
||||
/*
|
||||
* sort symbol table by name
|
||||
*/
|
||||
void n_sort_sym(int len)
|
||||
{
|
||||
register int gap, i, j;
|
||||
register struct sym *temp;
|
||||
|
||||
for (gap = len/2; gap > 0; gap /= 2)
|
||||
for (i = gap; i < len; i++)
|
||||
for (j = i-gap; j >= 0; j -= gap) {
|
||||
if (strcmp(symarray[j]->sym_name,
|
||||
symarray[j+gap]->sym_name) <= 0)
|
||||
break;
|
||||
temp = symarray[j];
|
||||
symarray[j] = symarray[j+gap];
|
||||
symarray[j+gap] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sort symbol table by address
|
||||
*/
|
||||
void a_sort_sym(int len)
|
||||
{
|
||||
register int gap, i, j;
|
||||
register struct sym *temp;
|
||||
|
||||
for (gap = len/2; gap > 0; gap /= 2)
|
||||
for (i = gap; i < len; i++)
|
||||
for (j = i-gap; j >= 0; j -= gap) {
|
||||
if (numcmp(symarray[j]->sym_wert,
|
||||
symarray[j+gap]->sym_wert) <= 0)
|
||||
break;
|
||||
temp = symarray[j];
|
||||
symarray[j] = symarray[j+gap];
|
||||
symarray[j+gap] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* compares two 16bit values, result like strcmp()
|
||||
*/
|
||||
int numcmp(int n1, int n2)
|
||||
{
|
||||
if ((unsigned) (n1 & 0xffff) < (unsigned) (n2 & 0xffff))
|
||||
return(-1);
|
||||
else if ((unsigned) (n1 & 0xffff) > (unsigned) (n2 & 0xffff))
|
||||
return(1);
|
||||
else
|
||||
return(0);
|
||||
}
|
@@ -1,70 +0,0 @@
|
||||
# Makefile for Z80-CPU emulator unter UNIX System V
|
||||
|
||||
CFLAGS= -O -c -Wall
|
||||
LFLAGS= -s
|
||||
|
||||
#CFLAGS= -g -c -Wall
|
||||
#LFLAGS=
|
||||
|
||||
OBJ = sim0.o \
|
||||
sim1.o \
|
||||
sim2.o \
|
||||
sim3.o \
|
||||
sim4.o \
|
||||
sim5.o \
|
||||
sim6.o \
|
||||
sim7.o \
|
||||
simctl.o \
|
||||
disas.o \
|
||||
simint.o \
|
||||
iosim.o \
|
||||
simfun.o \
|
||||
simglb.o
|
||||
|
||||
z80sim : $(OBJ)
|
||||
cc $(OBJ) $(LFLAGS) -o z80sim
|
||||
|
||||
sim0.o : sim0.c sim.h simglb.h
|
||||
cc $(CFLAGS) sim0.c
|
||||
|
||||
sim1.o : sim1.c sim.h simglb.h
|
||||
cc $(CFLAGS) sim1.c
|
||||
|
||||
sim2.o : sim2.c sim.h simglb.h
|
||||
cc $(CFLAGS) sim2.c
|
||||
|
||||
sim3.o : sim3.c sim.h simglb.h
|
||||
cc $(CFLAGS) sim3.c
|
||||
|
||||
sim4.o : sim4.c sim.h simglb.h
|
||||
cc $(CFLAGS) sim4.c
|
||||
|
||||
sim5.o : sim5.c sim.h simglb.h
|
||||
cc $(CFLAGS) sim5.c
|
||||
|
||||
sim6.o : sim6.c sim.h simglb.h
|
||||
cc $(CFLAGS) sim6.c
|
||||
|
||||
sim7.o : sim7.c sim.h simglb.h
|
||||
cc $(CFLAGS) sim7.c
|
||||
|
||||
simctl.o : simctl.c sim.h simglb.h
|
||||
cc $(CFLAGS) simctl.c
|
||||
|
||||
disas.o : disas.c
|
||||
cc $(CFLAGS) disas.c
|
||||
|
||||
simint.o : simint.c sim.h simglb.h
|
||||
cc $(CFLAGS) simint.c
|
||||
|
||||
iosim.o : iosim.c sim.h simglb.h
|
||||
cc $(CFLAGS) iosim.c
|
||||
|
||||
simfun.o : simfun.c sim.h
|
||||
cc $(CFLAGS) simfun.c
|
||||
|
||||
simglb.o : simglb.c sim.h
|
||||
cc $(CFLAGS) simglb.c
|
||||
|
||||
clean:
|
||||
rm -f *.o core z80sim
|
@@ -1,883 +0,0 @@
|
||||
/*
|
||||
* Z80 disassembler for Z80-CPU simulator
|
||||
*
|
||||
* Copyright (C) 1989-2006 by Udo Munk
|
||||
*
|
||||
* History:
|
||||
* 06-DEC-89 Development on TARGON/35 with AT&T Unix System V.3
|
||||
* 07-APR-92 forget to implement Op-Codes LD A,R and LD R,A, added
|
||||
* 25-JUN-92 comments in english
|
||||
* 03-OCT-06 changed to ANSI C for modern POSIX OS's
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* Forward declarations
|
||||
*/
|
||||
static int opout(char *, char **);
|
||||
static int nout(char *, unsigned char **);
|
||||
static int iout(char *, unsigned char **);
|
||||
static int rout(char *, char **);
|
||||
static int nnout(char *, unsigned char **);
|
||||
static int inout(char *, unsigned char **);
|
||||
static int cbop(char *, unsigned char **);
|
||||
static int edop(char *, unsigned char **);
|
||||
static int ddfd(char *, unsigned char **);
|
||||
|
||||
/*
|
||||
* Op-code tables
|
||||
*/
|
||||
struct opt {
|
||||
int (*fun) ();
|
||||
char *text;
|
||||
};
|
||||
|
||||
static struct opt optab[256] = {
|
||||
{ opout, "NOP" }, /* 0x00 */
|
||||
{ nnout, "LD\tBC," }, /* 0x01 */
|
||||
{ opout, "LD\t(BC),A" }, /* 0x02 */
|
||||
{ opout, "INC\tBC" }, /* 0x03 */
|
||||
{ opout, "INC\tB" }, /* 0x04 */
|
||||
{ opout, "DEC\tB" }, /* 0x05 */
|
||||
{ nout, "LD\tB," }, /* 0x06 */
|
||||
{ opout, "RLCA" }, /* 0x07 */
|
||||
{ opout, "EX\tAF,AF'" }, /* 0x08 */
|
||||
{ opout, "ADD\tHL,BC" }, /* 0x09 */
|
||||
{ opout, "LD\tA,(BC)" }, /* 0x0a */
|
||||
{ opout, "DEC\tBC" }, /* 0x0b */
|
||||
{ opout, "INC\tC" }, /* 0x0c */
|
||||
{ opout, "DEC\tC" }, /* 0x0d */
|
||||
{ nout, "LD\tC," }, /* 0x0e */
|
||||
{ opout, "RRCA" }, /* 0x0f */
|
||||
{ rout, "DJNZ\t" }, /* 0x10 */
|
||||
{ nnout, "LD\tDE," }, /* 0x11 */
|
||||
{ opout, "LD\t(DE),A" }, /* 0x12 */
|
||||
{ opout, "INC\tDE" }, /* 0x13 */
|
||||
{ opout, "INC\tD" }, /* 0x14 */
|
||||
{ opout, "DEC\tD" }, /* 0x15 */
|
||||
{ nout, "LD\tD," }, /* 0x16 */
|
||||
{ opout, "RLA" }, /* 0x17 */
|
||||
{ rout, "JR\t" }, /* 0x18 */
|
||||
{ opout, "ADD\tHL,DE" }, /* 0x19 */
|
||||
{ opout, "LD\tA,(DE)" }, /* 0x1a */
|
||||
{ opout, "DEC\tDE" }, /* 0x1b */
|
||||
{ opout, "INC\tE" }, /* 0x1c */
|
||||
{ opout, "DEC\tE" }, /* 0x1d */
|
||||
{ nout, "LD\tE," }, /* 0x1e */
|
||||
{ opout, "RRA" }, /* 0x1f */
|
||||
{ rout, "JR\tNZ," }, /* 0x20 */
|
||||
{ nnout, "LD\tHL," }, /* 0x21 */
|
||||
{ inout, "LD\t(%04x),HL" }, /* 0x22 */
|
||||
{ opout, "INC\tHL" }, /* 0x23 */
|
||||
{ opout, "INC\tH" }, /* 0x24 */
|
||||
{ opout, "DEC\tH" }, /* 0x25 */
|
||||
{ nout, "LD\tH," }, /* 0x26 */
|
||||
{ opout, "DAA" }, /* 0x27 */
|
||||
{ rout, "JR\tZ," }, /* 0x28 */
|
||||
{ opout, "ADD\tHL,HL" }, /* 0x29 */
|
||||
{ inout, "LD\tHL,(%04x)" }, /* 0x2a */
|
||||
{ opout, "DEC\tHL" }, /* 0x2b */
|
||||
{ opout, "INC\tL" }, /* 0x2c */
|
||||
{ opout, "DEC\tL" }, /* 0x2d */
|
||||
{ nout, "LD\tL," }, /* 0x2e */
|
||||
{ opout, "CPL" }, /* 0x2f */
|
||||
{ rout, "JR\tNC," }, /* 0x30 */
|
||||
{ nnout, "LD\tSP," }, /* 0x31 */
|
||||
{ inout, "LD\t(%04x),A" }, /* 0x32 */
|
||||
{ opout, "INC\tSP" }, /* 0x33 */
|
||||
{ opout, "INC\t(HL)" }, /* 0x34 */
|
||||
{ opout, "DEC\t(HL)" }, /* 0x35 */
|
||||
{ nout, "LD\t(HL)," }, /* 0x36 */
|
||||
{ opout, "SCF" }, /* 0x37 */
|
||||
{ rout, "JR\tC," }, /* 0x38 */
|
||||
{ opout, "ADD\tHL,SP" }, /* 0x39 */
|
||||
{ inout, "LD\tA,(%04x)" }, /* 0x3a */
|
||||
{ opout, "DEC\tSP" }, /* 0x3b */
|
||||
{ opout, "INC\tA" }, /* 0x3c */
|
||||
{ opout, "DEC\tA" }, /* 0x3d */
|
||||
{ nout, "LD\tA," }, /* 0x3e */
|
||||
{ opout, "CCF" }, /* 0x3f */
|
||||
{ opout, "LD\tB,B" }, /* 0x40 */
|
||||
{ opout, "LD\tB,C" }, /* 0x41 */
|
||||
{ opout, "LD\tB,D" }, /* 0x42 */
|
||||
{ opout, "LD\tB,E" }, /* 0x43 */
|
||||
{ opout, "LD\tB,H" }, /* 0x44 */
|
||||
{ opout, "LD\tB,L" }, /* 0x45 */
|
||||
{ opout, "LD\tB,(HL)" }, /* 0x46 */
|
||||
{ opout, "LD\tB,A" }, /* 0x47 */
|
||||
{ opout, "LD\tC,B" }, /* 0x48 */
|
||||
{ opout, "LD\tC,C" }, /* 0x49 */
|
||||
{ opout, "LD\tC,D" }, /* 0x4a */
|
||||
{ opout, "LD\tC,E" }, /* 0x4b */
|
||||
{ opout, "LD\tC,H" }, /* 0x4c */
|
||||
{ opout, "LD\tC,L" }, /* 0x4d */
|
||||
{ opout, "LD\tC,(HL)" }, /* 0x4e */
|
||||
{ opout, "LD\tC,A" }, /* 0x4f */
|
||||
{ opout, "LD\tD,B" }, /* 0x50 */
|
||||
{ opout, "LD\tD,C" }, /* 0x51 */
|
||||
{ opout, "LD\tD,D" }, /* 0x52 */
|
||||
{ opout, "LD\tD,E" }, /* 0x53 */
|
||||
{ opout, "LD\tD,H" }, /* 0x54 */
|
||||
{ opout, "LD\tD,L" }, /* 0x55 */
|
||||
{ opout, "LD\tD,(HL)" }, /* 0x56 */
|
||||
{ opout, "LD\tD,A" }, /* 0x57 */
|
||||
{ opout, "LD\tE,B" }, /* 0x58 */
|
||||
{ opout, "LD\tE,C" }, /* 0x59 */
|
||||
{ opout, "LD\tE,D" }, /* 0x5a */
|
||||
{ opout, "LD\tE,E" }, /* 0x5b */
|
||||
{ opout, "LD\tE,H" }, /* 0x5c */
|
||||
{ opout, "LD\tE,L" }, /* 0x5d */
|
||||
{ opout, "LD\tE,(HL)" }, /* 0x5e */
|
||||
{ opout, "LD\tE,A" }, /* 0x5f */
|
||||
{ opout, "LD\tH,B" }, /* 0x60 */
|
||||
{ opout, "LD\tH,C" }, /* 0x61 */
|
||||
{ opout, "LD\tH,D" }, /* 0x62 */
|
||||
{ opout, "LD\tH,E" }, /* 0x63 */
|
||||
{ opout, "LD\tH,H" }, /* 0x64 */
|
||||
{ opout, "LD\tH,L" }, /* 0x65 */
|
||||
{ opout, "LD\tH,(HL)" }, /* 0x66 */
|
||||
{ opout, "LD\tH,A" }, /* 0x67 */
|
||||
{ opout, "LD\tL,B" }, /* 0x68 */
|
||||
{ opout, "LD\tL,C" }, /* 0x69 */
|
||||
{ opout, "LD\tL,D" }, /* 0x6a */
|
||||
{ opout, "LD\tL,E" }, /* 0x6b */
|
||||
{ opout, "LD\tL,H" }, /* 0x6c */
|
||||
{ opout, "LD\tL,L" }, /* 0x6d */
|
||||
{ opout, "LD\tL,(HL)" }, /* 0x6e */
|
||||
{ opout, "LD\tL,A" }, /* 0x6f */
|
||||
{ opout, "LD\t(HL),B" }, /* 0x70 */
|
||||
{ opout, "LD\t(HL),C" }, /* 0x71 */
|
||||
{ opout, "LD\t(HL),D" }, /* 0x72 */
|
||||
{ opout, "LD\t(HL),E" }, /* 0x73 */
|
||||
{ opout, "LD\t(HL),H" }, /* 0x74 */
|
||||
{ opout, "LD\t(HL),L" }, /* 0x75 */
|
||||
{ opout, "HALT" }, /* 0x76 */
|
||||
{ opout, "LD\t(HL),A" }, /* 0x77 */
|
||||
{ opout, "LD\tA,B" }, /* 0x78 */
|
||||
{ opout, "LD\tA,C" }, /* 0x79 */
|
||||
{ opout, "LD\tA,D" }, /* 0x7a */
|
||||
{ opout, "LD\tA,E" }, /* 0x7b */
|
||||
{ opout, "LD\tA,H" }, /* 0x7c */
|
||||
{ opout, "LD\tA,L" }, /* 0x7d */
|
||||
{ opout, "LD\tA,(HL)" }, /* 0x7e */
|
||||
{ opout, "LD\tA,A" }, /* 0x7f */
|
||||
{ opout, "ADD\tA,B" }, /* 0x80 */
|
||||
{ opout, "ADD\tA,C" }, /* 0x81 */
|
||||
{ opout, "ADD\tA,D" }, /* 0x82 */
|
||||
{ opout, "ADD\tA,E" }, /* 0x83 */
|
||||
{ opout, "ADD\tA,H" }, /* 0x84 */
|
||||
{ opout, "ADD\tA,L" }, /* 0x85 */
|
||||
{ opout, "ADD\tA,(HL)" }, /* 0x86 */
|
||||
{ opout, "ADD\tA,A" }, /* 0x87 */
|
||||
{ opout, "ADC\tA,B" }, /* 0x88 */
|
||||
{ opout, "ADC\tA,C" }, /* 0x89 */
|
||||
{ opout, "ADC\tA,D" }, /* 0x8a */
|
||||
{ opout, "ADC\tA,E" }, /* 0x8b */
|
||||
{ opout, "ADC\tA,H" }, /* 0x8c */
|
||||
{ opout, "ADC\tA,L" }, /* 0x8d */
|
||||
{ opout, "ADC\tA,(HL)" }, /* 0x8e */
|
||||
{ opout, "ADC\tA,A" }, /* 0x8f */
|
||||
{ opout, "SUB\tB" }, /* 0x90 */
|
||||
{ opout, "SUB\tC" }, /* 0x91 */
|
||||
{ opout, "SUB\tD" }, /* 0x92 */
|
||||
{ opout, "SUB\tE" }, /* 0x93 */
|
||||
{ opout, "SUB\tH" }, /* 0x94 */
|
||||
{ opout, "SUB\tL" }, /* 0x95 */
|
||||
{ opout, "SUB\t(HL)" }, /* 0x96 */
|
||||
{ opout, "SUB\tA" }, /* 0x97 */
|
||||
{ opout, "SBC\tA,B" }, /* 0x98 */
|
||||
{ opout, "SBC\tA,C" }, /* 0x99 */
|
||||
{ opout, "SBC\tA,D" }, /* 0x9a */
|
||||
{ opout, "SBC\tA,E" }, /* 0x9b */
|
||||
{ opout, "SBC\tA,H" }, /* 0x9c */
|
||||
{ opout, "SBC\tA,L" }, /* 0x9d */
|
||||
{ opout, "SBC\tA,(HL)" }, /* 0x9e */
|
||||
{ opout, "SBC\tA,A" }, /* 0x9f */
|
||||
{ opout, "AND\tB" }, /* 0xa0 */
|
||||
{ opout, "AND\tC" }, /* 0xa1 */
|
||||
{ opout, "AND\tD" }, /* 0xa2 */
|
||||
{ opout, "AND\tE" }, /* 0xa3 */
|
||||
{ opout, "AND\tH" }, /* 0xa4 */
|
||||
{ opout, "AND\tL" }, /* 0xa5 */
|
||||
{ opout, "AND\t(HL)" }, /* 0xa6 */
|
||||
{ opout, "AND\tA" }, /* 0xa7 */
|
||||
{ opout, "XOR\tB" }, /* 0xa8 */
|
||||
{ opout, "XOR\tC" }, /* 0xa9 */
|
||||
{ opout, "XOR\tD" }, /* 0xaa */
|
||||
{ opout, "XOR\tE" }, /* 0xab */
|
||||
{ opout, "XOR\tH" }, /* 0xac */
|
||||
{ opout, "XOR\tL" }, /* 0xad */
|
||||
{ opout, "XOR\t(HL)" }, /* 0xae */
|
||||
{ opout, "XOR\tA" }, /* 0xaf */
|
||||
{ opout, "OR\tB" }, /* 0xb0 */
|
||||
{ opout, "OR\tC" }, /* 0xb1 */
|
||||
{ opout, "OR\tD" }, /* 0xb2 */
|
||||
{ opout, "OR\tE" }, /* 0xb3 */
|
||||
{ opout, "OR\tH" }, /* 0xb4 */
|
||||
{ opout, "OR\tL" }, /* 0xb5 */
|
||||
{ opout, "OR\t(HL)" }, /* 0xb6 */
|
||||
{ opout, "OR\tA" }, /* 0xb7 */
|
||||
{ opout, "CP\tB" }, /* 0xb8 */
|
||||
{ opout, "CP\tC" }, /* 0xb9 */
|
||||
{ opout, "CP\tD" }, /* 0xba */
|
||||
{ opout, "CP\tE" }, /* 0xbb */
|
||||
{ opout, "CP\tH" }, /* 0xbc */
|
||||
{ opout, "CP\tL" }, /* 0xbd */
|
||||
{ opout, "CP\t(HL)" }, /* 0xbe */
|
||||
{ opout, "CP\tA" }, /* 0xbf */
|
||||
{ opout, "RET\tNZ" }, /* 0xc0 */
|
||||
{ opout, "POP\tBC" }, /* 0xc1 */
|
||||
{ nnout, "JP\tNZ," }, /* 0xc2 */
|
||||
{ nnout, "JP\t" }, /* 0xc3 */
|
||||
{ nnout, "CALL\tNZ," }, /* 0xc4 */
|
||||
{ opout, "PUSH\tBC" }, /* 0xc5 */
|
||||
{ nout, "ADD\tA," }, /* 0xc6 */
|
||||
{ opout, "RST\t0" }, /* 0xc7 */
|
||||
{ opout, "RET\tZ" }, /* 0xc8 */
|
||||
{ opout, "RET" }, /* 0xc9 */
|
||||
{ nnout, "JP\tZ," }, /* 0xca */
|
||||
{ cbop, "" }, /* 0xcb */
|
||||
{ nnout, "CALL\tZ," }, /* 0xcc */
|
||||
{ nnout, "CALL\t" }, /* 0xcd */
|
||||
{ nout, "ADC\tA," }, /* 0xce */
|
||||
{ opout, "RST\t8" }, /* 0xcf */
|
||||
{ opout, "RET\tNC" }, /* 0xd0 */
|
||||
{ opout, "POP\tDE" }, /* 0xd1 */
|
||||
{ nnout, "JP\tNC," }, /* 0xd2 */
|
||||
{ iout, "OUT\t(%02x),A" }, /* 0xd3 */
|
||||
{ nnout, "CALL\tNC," }, /* 0xd4 */
|
||||
{ opout, "PUSH\tDE" }, /* 0xd5 */
|
||||
{ nout, "SUB\t" }, /* 0xd6 */
|
||||
{ opout, "RST\t10" }, /* 0xd7 */
|
||||
{ opout, "RET\tC" }, /* 0xd8 */
|
||||
{ opout, "EXX" }, /* 0xd9 */
|
||||
{ nnout, "JP\tC," }, /* 0xda */
|
||||
{ iout, "IN\tA,(%02x)" }, /* 0xdb */
|
||||
{ nnout, "CALL\tC," }, /* 0xdc */
|
||||
{ ddfd, "" }, /* 0xdd */
|
||||
{ nout, "SBC\tA," }, /* 0xde */
|
||||
{ opout, "RST\t18" }, /* 0xdf */
|
||||
{ opout, "RET\tPO" }, /* 0xe0 */
|
||||
{ opout, "POP\tHL" }, /* 0xe1 */
|
||||
{ nnout, "JP\tPO," }, /* 0xe2 */
|
||||
{ opout, "EX\t(SP),HL" }, /* 0xe3 */
|
||||
{ nnout, "CALL\tPO," }, /* 0xe4 */
|
||||
{ opout, "PUSH\tHL" }, /* 0xe5 */
|
||||
{ nout, "AND\t" }, /* 0xe6 */
|
||||
{ opout, "RST\t20" }, /* 0xe7 */
|
||||
{ opout, "RET\tPE" }, /* 0xe8 */
|
||||
{ opout, "JP\t(HL)" }, /* 0xe9 */
|
||||
{ nnout, "JP\tPE," }, /* 0xea */
|
||||
{ opout, "EX\tDE,HL" }, /* 0xeb */
|
||||
{ nnout, "CALL\tPE," }, /* 0xec */
|
||||
{ edop, "" }, /* 0xed */
|
||||
{ nout, "XOR\t" }, /* 0xee */
|
||||
{ opout, "RST\t28" }, /* 0xef */
|
||||
{ opout, "RET\tP" }, /* 0xf0 */
|
||||
{ opout, "POP\tAF" }, /* 0xf1 */
|
||||
{ nnout, "JP\tP," }, /* 0xf2 */
|
||||
{ opout, "DI" }, /* 0xf3 */
|
||||
{ nnout, "CALL\tP," }, /* 0xf4 */
|
||||
{ opout, "PUSH\tAF" }, /* 0xf5 */
|
||||
{ nout, "OR\t" }, /* 0xf6 */
|
||||
{ opout, "RST\t30" }, /* 0xf7 */
|
||||
{ opout, "RET\tM" }, /* 0xf8 */
|
||||
{ opout, "LD\tSP,HL" }, /* 0xf9 */
|
||||
{ nnout, "JP\tM," }, /* 0xfa */
|
||||
{ opout, "EI" }, /* 0xfb */
|
||||
{ nnout, "CALL\tM," }, /* 0xfc */
|
||||
{ ddfd, "" }, /* 0xfd */
|
||||
{ nout, "CP\t" }, /* 0xfe */
|
||||
{ opout, "RST\t38" } /* 0xff */
|
||||
};
|
||||
|
||||
static int addr;
|
||||
static char *unkown = "???";
|
||||
static char *reg[] = { "B", "C", "D", "E", "H", "L", "(HL)", "A" };
|
||||
static char *regix = "IX";
|
||||
static char *regiy = "IY";
|
||||
|
||||
/*
|
||||
* The function disass() is the only global function of
|
||||
* this module. The first argument is a pointer to a
|
||||
* unsigned char pointer, which points to the op-code
|
||||
* to disassemble. The output of the disassembly goes
|
||||
* to stdout, terminated by a newline. After the
|
||||
* disassembly the pointer to the op-code will be
|
||||
* increased by the size of the op-code, so that
|
||||
* disass() can be called again.
|
||||
* The secound argument is the (Z80) address of the
|
||||
* op-code to disassemble. It is used to calculate the
|
||||
* destination address of relative jumps.
|
||||
*/
|
||||
void disass(unsigned char **p, int adr)
|
||||
{
|
||||
register int len;
|
||||
|
||||
addr = adr;
|
||||
len = (*optab[**p].fun) (optab[**p].text, p);
|
||||
*p += len;
|
||||
}
|
||||
|
||||
/*
|
||||
* disassemble 1 byte op-codes
|
||||
*/
|
||||
static int opout(char *s, char **p)
|
||||
{
|
||||
puts(s);
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* disassemble 2 byte op-codes of type "Op n"
|
||||
*/
|
||||
static int nout(char *s, unsigned char **p)
|
||||
{
|
||||
printf("%s%02x\n", s, *(*p + 1));
|
||||
return(2);
|
||||
}
|
||||
|
||||
/*
|
||||
* disassemble 2 byte op-codes with indirect addressing
|
||||
*/
|
||||
static int iout(char *s, unsigned char **p)
|
||||
{
|
||||
printf(s, *(*p + 1));
|
||||
putchar('\n');
|
||||
return(2);
|
||||
}
|
||||
|
||||
/*
|
||||
* disassemble 2 byte op-codes with relative addressing
|
||||
*/
|
||||
static int rout(char *s, char **p)
|
||||
{
|
||||
printf("%s%04x\n", s, addr + *(*p + 1) + 2);
|
||||
return(2);
|
||||
}
|
||||
|
||||
/*
|
||||
* disassemble 3 byte op-codes of type "Op nn"
|
||||
*/
|
||||
static int nnout(char *s, unsigned char **p)
|
||||
{
|
||||
register int i;
|
||||
|
||||
i = *(*p + 1) + (*(*p + 2) << 8);
|
||||
printf("%s%04x\n", s, i);
|
||||
return(3);
|
||||
}
|
||||
|
||||
/*
|
||||
* disassemble 3 byte op-codes with indirect addressing
|
||||
*/
|
||||
static int inout(char *s, unsigned char **p)
|
||||
{
|
||||
register int i;
|
||||
|
||||
i = *(*p + 1) + (*(*p + 2) << 8);
|
||||
printf(s, i);
|
||||
putchar('\n');
|
||||
return(3);
|
||||
}
|
||||
|
||||
/*
|
||||
* disassemble multi byte op-codes with prefix 0xcb
|
||||
*/
|
||||
static int cbop(char *s, unsigned char **p)
|
||||
{
|
||||
register int b2;
|
||||
|
||||
b2 = *(*p + 1);
|
||||
if (b2 >= 0x00 && b2 <= 0x07) {
|
||||
printf("RLC\t");
|
||||
printf("%s\n", reg[b2 & 7]);
|
||||
return(2);
|
||||
}
|
||||
if (b2 >= 0x08 && b2 <= 0x0f) {
|
||||
printf("RRC\t");
|
||||
printf("%s\n", reg[b2 & 7]);
|
||||
return(2);
|
||||
}
|
||||
if (b2 >= 0x10 && b2 <= 0x17) {
|
||||
printf("RL\t");
|
||||
printf("%s\n", reg[b2 & 7]);
|
||||
return(2);
|
||||
}
|
||||
if (b2 >= 0x18 && b2 <= 0x1f) {
|
||||
printf("RR\t");
|
||||
printf("%s\n", reg[b2 & 7]);
|
||||
return(2);
|
||||
}
|
||||
if (b2 >= 0x20 && b2 <= 0x27) {
|
||||
printf("SLA\t");
|
||||
printf("%s\n", reg[b2 & 7]);
|
||||
return(2);
|
||||
}
|
||||
if (b2 >= 0x28 && b2 <= 0x2f) {
|
||||
printf("SRA\t");
|
||||
printf("%s\n", reg[b2 & 7]);
|
||||
return(2);
|
||||
}
|
||||
if (b2 >= 0x38 && b2 <= 0x3f) {
|
||||
printf("SRL\t");
|
||||
printf("%s\n", reg[b2 & 7]);
|
||||
return(2);
|
||||
}
|
||||
if (b2 >= 0x40 && b2 <= 0x7f) {
|
||||
printf("BIT\t");
|
||||
printf("%c,", ((b2 >> 3) & 7) + '0');
|
||||
printf("%s\n", reg[b2 & 7]);
|
||||
return(2);
|
||||
}
|
||||
if (b2 >= 0x80 && b2 <= 0xbf) {
|
||||
printf("RES\t");
|
||||
printf("%c,", ((b2 >> 3) & 7) + '0');
|
||||
printf("%s\n", reg[b2 & 7]);
|
||||
return(2);
|
||||
}
|
||||
if (b2 >= 0xc0) {
|
||||
printf("SET\t");
|
||||
printf("%c,", ((b2 >> 3) & 7) + '0');
|
||||
printf("%s\n", reg[b2 & 7]);
|
||||
return(2);
|
||||
}
|
||||
puts(unkown);
|
||||
return(2);
|
||||
}
|
||||
|
||||
/*
|
||||
* disassemble multi byte op-codes with prefix 0xed
|
||||
*/
|
||||
static int edop(char *s, unsigned char **p)
|
||||
{
|
||||
register int b2, i;
|
||||
int len = 2;
|
||||
|
||||
b2 = *(*p + 1);
|
||||
switch (b2) {
|
||||
case 0x40:
|
||||
puts("IN\tB,(C)");
|
||||
break;
|
||||
case 0x41:
|
||||
puts("OUT\t(C),B");
|
||||
break;
|
||||
case 0x42:
|
||||
puts("SBC\tHL,BC");
|
||||
break;
|
||||
case 0x43:
|
||||
i = *(*p + 2) + (*(*p + 3) << 8);
|
||||
printf("LD\t(%04x),BC\n", i);
|
||||
len = 4;
|
||||
break;
|
||||
case 0x44:
|
||||
puts("NEG");
|
||||
break;
|
||||
case 0x45:
|
||||
puts("RETN");
|
||||
break;
|
||||
case 0x46:
|
||||
puts("IM\t0");
|
||||
break;
|
||||
case 0x47:
|
||||
puts("LD\tI,A");
|
||||
break;
|
||||
case 0x48:
|
||||
puts("IN\tC,(C)");
|
||||
break;
|
||||
case 0x49:
|
||||
puts("OUT\t(C),C");
|
||||
break;
|
||||
case 0x4a:
|
||||
puts("ADC\tHL,BC");
|
||||
break;
|
||||
case 0x4b:
|
||||
i = *(*p + 2) + (*(*p + 3) << 8);
|
||||
printf("LD\tBC,(%04x)\n", i);
|
||||
len = 4;
|
||||
break;
|
||||
case 0x4d:
|
||||
puts("RETI");
|
||||
break;
|
||||
case 0x4f:
|
||||
puts("LD\tR,A");
|
||||
break;
|
||||
case 0x50:
|
||||
puts("IN\tD,(C)");
|
||||
break;
|
||||
case 0x51:
|
||||
puts("OUT\t(C),D");
|
||||
break;
|
||||
case 0x52:
|
||||
puts("SBC\tHL,DE");
|
||||
break;
|
||||
case 0x53:
|
||||
i = *(*p + 2) + (*(*p + 3) << 8);
|
||||
printf("LD\t(%04x),DE\n", i);
|
||||
len = 4;
|
||||
break;
|
||||
case 0x56:
|
||||
puts("IM\t1");
|
||||
break;
|
||||
case 0x57:
|
||||
puts("LD\tA,I");
|
||||
break;
|
||||
case 0x58:
|
||||
puts("IN\tE,(C)");
|
||||
break;
|
||||
case 0x59:
|
||||
puts("OUT\t(C),E");
|
||||
break;
|
||||
case 0x5a:
|
||||
puts("ADC\tHL,DE");
|
||||
break;
|
||||
case 0x5b:
|
||||
i = *(*p + 2) + (*(*p + 3) << 8);
|
||||
printf("LD\tDE,(%04x)\n", i);
|
||||
len = 4;
|
||||
break;
|
||||
case 0x5e:
|
||||
puts("IM\t2");
|
||||
break;
|
||||
case 0x5f:
|
||||
puts("LD\tA,R");
|
||||
break;
|
||||
case 0x60:
|
||||
puts("IN\tH,(C)");
|
||||
break;
|
||||
case 0x61:
|
||||
puts("OUT\t(C),H");
|
||||
break;
|
||||
case 0x62:
|
||||
puts("SBC\tHL,HL");
|
||||
break;
|
||||
case 0x67:
|
||||
puts("RRD");
|
||||
break;
|
||||
case 0x68:
|
||||
puts("IN\tL,(C)");
|
||||
break;
|
||||
case 0x69:
|
||||
puts("OUT\t(C),L");
|
||||
break;
|
||||
case 0x6a:
|
||||
puts("ADC\tHL,HL");
|
||||
break;
|
||||
case 0x6f:
|
||||
puts("RLD");
|
||||
break;
|
||||
case 0x72:
|
||||
puts("SBC\tHL,SP");
|
||||
break;
|
||||
case 0x73:
|
||||
i = *(*p + 2) + (*(*p + 3) << 8);
|
||||
printf("LD\t(%04x),SP\n", i);
|
||||
len = 4;
|
||||
break;
|
||||
case 0x78:
|
||||
puts("IN\tA,(C)");
|
||||
break;
|
||||
case 0x79:
|
||||
puts("OUT\t(C),A");
|
||||
break;
|
||||
case 0x7a:
|
||||
puts("ADC\tHL,SP");
|
||||
break;
|
||||
case 0x7b:
|
||||
i = *(*p + 2) + (*(*p + 3) << 8);
|
||||
printf("LD\tSP,(%04x)\n", i);
|
||||
len = 4;
|
||||
break;
|
||||
case 0xa0:
|
||||
puts("LDI");
|
||||
break;
|
||||
case 0xa1:
|
||||
puts("CPI");
|
||||
break;
|
||||
case 0xa2:
|
||||
puts("INI");
|
||||
break;
|
||||
case 0xa3:
|
||||
puts("OUTI");
|
||||
break;
|
||||
case 0xa8:
|
||||
puts("LDD");
|
||||
break;
|
||||
case 0xa9:
|
||||
puts("CPD");
|
||||
break;
|
||||
case 0xaa:
|
||||
puts("IND");
|
||||
break;
|
||||
case 0xab:
|
||||
puts("OUTD");
|
||||
break;
|
||||
case 0xb0:
|
||||
puts("LDIR");
|
||||
break;
|
||||
case 0xb1:
|
||||
puts("CPIR");
|
||||
break;
|
||||
case 0xb2:
|
||||
puts("INIR");
|
||||
break;
|
||||
case 0xb3:
|
||||
puts("OTIR");
|
||||
break;
|
||||
case 0xb8:
|
||||
puts("LDDR");
|
||||
break;
|
||||
case 0xb9:
|
||||
puts("CPDR");
|
||||
break;
|
||||
case 0xba:
|
||||
puts("INDR");
|
||||
break;
|
||||
case 0xbb:
|
||||
puts("OTDR");
|
||||
break;
|
||||
default:
|
||||
puts(unkown);
|
||||
}
|
||||
return(len);
|
||||
}
|
||||
|
||||
/*
|
||||
* disassemble multi byte op-codes with prefix 0xdd and 0xfd
|
||||
*/
|
||||
static int ddfd(char *s, unsigned char **p)
|
||||
{
|
||||
register int b2;
|
||||
register char *ireg;
|
||||
int len = 3;
|
||||
|
||||
if (**p == 0xdd)
|
||||
ireg = regix;
|
||||
else
|
||||
ireg = regiy;
|
||||
b2 = *(*p + 1);
|
||||
if (b2 >= 0x70 && b2 <= 0x77) {
|
||||
printf("LD\t(%s+%02x),%s\n", ireg, *(*p + 2), reg[b2 & 7]);
|
||||
return(3);
|
||||
}
|
||||
switch (b2) {
|
||||
case 0x09:
|
||||
printf("ADD\t%s,BC\n", ireg);
|
||||
len = 2;
|
||||
break;
|
||||
case 0x19:
|
||||
printf("ADD\t%s,DE\n", ireg);
|
||||
len = 2;
|
||||
break;
|
||||
case 0x21:
|
||||
printf("LD\t%s,%04x\n", ireg, *(*p + 2) + (*(*p + 3) << 8));
|
||||
len = 4;
|
||||
break;
|
||||
case 0x22:
|
||||
printf("LD\t(%04x),%s\n", *(*p + 2) + (*(*p + 3) << 8), ireg);
|
||||
len = 4;
|
||||
break;
|
||||
case 0x23:
|
||||
printf("INC\t%s\n", ireg);
|
||||
len = 2;
|
||||
break;
|
||||
case 0x29:
|
||||
if (**p == 0xdd)
|
||||
printf("ADD\tIX,IX\n");
|
||||
else
|
||||
printf("ADD\tIY,IY\n");
|
||||
len = 2;
|
||||
break;
|
||||
case 0x2a:
|
||||
printf("LD\t%s,(%04x)\n", ireg, *(*p + 2) + (*(*p + 3) << 8));
|
||||
len = 4;
|
||||
break;
|
||||
case 0x2b:
|
||||
printf("DEC\t%s\n", ireg);
|
||||
len = 2;
|
||||
break;
|
||||
case 0x34:
|
||||
printf("INC\t(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x35:
|
||||
printf("DEC\t(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x36:
|
||||
printf("LD\t(%s+%02x),%02x\n", ireg, *(*p + 2), *(*p + 3));
|
||||
len = 4;
|
||||
break;
|
||||
case 0x39:
|
||||
printf("ADD\t%s,SP\n", ireg);
|
||||
len = 2;
|
||||
break;
|
||||
case 0x46:
|
||||
printf("LD\tB,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x4e:
|
||||
printf("LD\tC,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x56:
|
||||
printf("LD\tD,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x5e:
|
||||
printf("LD\tE,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x66:
|
||||
printf("LD\tH,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x6e:
|
||||
printf("LD\tL,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x7e:
|
||||
printf("LD\tA,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x86:
|
||||
printf("ADD\tA,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x8e:
|
||||
printf("ADC\tA,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x96:
|
||||
printf("SUB\t(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x9e:
|
||||
printf("SBC\tA,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0xa6:
|
||||
printf("AND\t(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0xae:
|
||||
printf("XOR\t(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0xb6:
|
||||
printf("OR\t(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0xbe:
|
||||
printf("CP\t(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0xcb:
|
||||
switch (*(*p + 3)) {
|
||||
case 0x06:
|
||||
printf("RLC\t(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x0e:
|
||||
printf("RRC\t(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x16:
|
||||
printf("RL\t(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x1e:
|
||||
printf("RR\t(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x26:
|
||||
printf("SLA\t(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x2e:
|
||||
printf("SRA\t(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x3e:
|
||||
printf("SRL\t(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x46:
|
||||
printf("BIT\t0,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x4e:
|
||||
printf("BIT\t1,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x56:
|
||||
printf("BIT\t2,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x5e:
|
||||
printf("BIT\t3,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x66:
|
||||
printf("BIT\t4,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x6e:
|
||||
printf("BIT\t5,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x76:
|
||||
printf("BIT\t6,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x7e:
|
||||
printf("BIT\t7,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x86:
|
||||
printf("RES\t0,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x8e:
|
||||
printf("RES\t1,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x96:
|
||||
printf("RES\t2,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0x9e:
|
||||
printf("RES\t3,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0xa6:
|
||||
printf("RES\t4,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0xae:
|
||||
printf("RES\t5,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0xb6:
|
||||
printf("RES\t6,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0xbe:
|
||||
printf("RES\t7,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0xc6:
|
||||
printf("SET\t0,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0xce:
|
||||
printf("SET\t1,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0xd6:
|
||||
printf("SET\t2,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0xde:
|
||||
printf("SET\t3,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0xe6:
|
||||
printf("SET\t4,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0xee:
|
||||
printf("SET\t5,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0xf6:
|
||||
printf("SET\t6,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
case 0xfe:
|
||||
printf("SET\t7,(%s+%02x)\n", ireg, *(*p + 2));
|
||||
break;
|
||||
default:
|
||||
puts(unkown);
|
||||
}
|
||||
len = 4;
|
||||
break;
|
||||
case 0xe1:
|
||||
printf("POP\t%s\n", ireg);
|
||||
len = 2;
|
||||
break;
|
||||
case 0xe3:
|
||||
printf("EX\t(SP),%s\n", ireg);
|
||||
len = 2;
|
||||
break;
|
||||
case 0xe5:
|
||||
printf("PUSH\t%s\n", ireg);
|
||||
len = 2;
|
||||
break;
|
||||
case 0xe9:
|
||||
printf("JP\t(%s)\n", ireg);
|
||||
len = 2;
|
||||
break;
|
||||
case 0xf9:
|
||||
printf("LD\tSP,%s\n", ireg);
|
||||
len = 2;
|
||||
break;
|
||||
default:
|
||||
puts(unkown);
|
||||
}
|
||||
return(len);
|
||||
}
|
Binary file not shown.
@@ -1,136 +0,0 @@
|
||||
/*
|
||||
* Z80SIM - a Z80-CPU simulator
|
||||
*
|
||||
* Copyright (C) 1987-2006 by Udo Munk
|
||||
*
|
||||
* This modul of the simulator contains a simple terminal I/O
|
||||
* simulation as an example.
|
||||
*
|
||||
* History:
|
||||
* 28-SEP-87 Development on TARGON/35 with AT&T Unix System V.3
|
||||
* 11-JAN-89 Release 1.1
|
||||
* 08-FEB-89 Release 1.2
|
||||
* 13-MAR-89 Release 1.3
|
||||
* 09-FEB-90 Release 1.4 Ported to TARGON/31 M10/30
|
||||
* 20-DEC-90 Release 1.5 Ported to COHERENT 3.0
|
||||
* 10-JUN-92 Release 1.6 long casting problem solved with COHERENT 3.2
|
||||
* and some optimization
|
||||
* 25-JUN-92 Release 1.7 comments in english
|
||||
* 03-OCT-06 Release 1.8 changed to ANSI C for modern POSIX OS's
|
||||
*/
|
||||
|
||||
/*
|
||||
* Sample I/O-handler
|
||||
*
|
||||
* Port 0 input: reads the next byte from stdin
|
||||
* Port 0 output: writes the byte to stdout
|
||||
*
|
||||
* All the other ports are connected to a I/O-trap handler,
|
||||
* I/O to this ports stops the simulation with an I/O error.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "sim.h"
|
||||
#include "simglb.h"
|
||||
|
||||
/*
|
||||
* Forward declarations of the I/O functions
|
||||
* for all port addresses.
|
||||
*/
|
||||
static BYTE io_trap(void);
|
||||
static BYTE p000_in(void);
|
||||
static void p000_out(BYTE);
|
||||
|
||||
/*
|
||||
* This two dimensional array contains function pointers
|
||||
* for every I/O port (0 - 255), to do the needed I/O.
|
||||
* The first entry is for input, the second for output.
|
||||
*/
|
||||
static BYTE (*port[256][2]) () = {
|
||||
{ p000_in, p000_out } /* port 0 */
|
||||
};
|
||||
|
||||
/*
|
||||
* This function is to initiate the I/O devices.
|
||||
* It will be called from the CPU simulation before
|
||||
* any operation with the Z80 is possible.
|
||||
*
|
||||
* In this sample I/O simulation we initialize all
|
||||
* unused port with an error trap handler, so that
|
||||
* simulation stops at I/O on the unused ports.
|
||||
*
|
||||
* See the I/O simulation of CP/M for a more complex
|
||||
* example.
|
||||
*/
|
||||
void init_io(void)
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = 1; i <= 255; i++)
|
||||
port[i][0] = port[i][1] = io_trap;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is to stop the I/O devices. It is
|
||||
* called from the CPU simulation on exit.
|
||||
*
|
||||
* Here is just nothing to do, see the I/O simulation
|
||||
* of CP/M for a more complex example.
|
||||
*/
|
||||
void exit_io(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the main handler for all IN op-codes,
|
||||
* called by the simulator. It calls the input
|
||||
* function for port adr.
|
||||
*/
|
||||
BYTE io_in(BYTE adr)
|
||||
{
|
||||
return((*port[adr][0]) ());
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the main handler for all OUT op-codes,
|
||||
* called by the simulator. It calls the output
|
||||
* function for port adr.
|
||||
*/
|
||||
void io_out(BYTE adr, BYTE data)
|
||||
{
|
||||
(*port[adr][1]) (data);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O trap funtion
|
||||
* This function should be added into all unused
|
||||
* entrys of the port array. It stops the emulation
|
||||
* with an I/O error.
|
||||
*/
|
||||
static BYTE io_trap(void)
|
||||
{
|
||||
if (i_flag) {
|
||||
cpu_error = IOTRAP;
|
||||
cpu_state = STOPPED;
|
||||
}
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O function port 0 read:
|
||||
* Read next byte from stdin.
|
||||
*/
|
||||
static BYTE p000_in(void)
|
||||
{
|
||||
return((BYTE) getchar());
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O function port 0 write:
|
||||
* Write byte to stdout and flush the output.
|
||||
*/
|
||||
static void p000_out(BYTE data)
|
||||
{
|
||||
putchar((int) data);
|
||||
fflush(stdout);
|
||||
}
|
Binary file not shown.
@@ -1,2 +0,0 @@
|
||||
#!/bin/sh
|
||||
./z80sim
|
@@ -1,104 +0,0 @@
|
||||
/*
|
||||
* Z80SIM - a Z80-CPU simulator
|
||||
*
|
||||
* Copyright (C) 1987-2006 by Udo Munk
|
||||
*
|
||||
* This is the configuration I'm using for software testing and debugging
|
||||
*
|
||||
* History:
|
||||
* 28-SEP-87 Development on TARGON/35 with AT&T Unix System V.3
|
||||
* 11-JAN-89 Release 1.1
|
||||
* 08-FEB-89 Release 1.2
|
||||
* 13-MAR-89 Release 1.3
|
||||
* 09-FEB-90 Release 1.4 Ported to TARGON/31 M10/30
|
||||
* 20-DEC-90 Release 1.5 Ported to COHERENT 3.0
|
||||
* 10-JUN-92 Release 1.6 long casting problem solved with COHERENT 3.2
|
||||
* and some optimization
|
||||
* 25-JUN-92 Release 1.7 comments in english
|
||||
* 03-OCT-06 Release 1.8 modified to compile on modern POSIX OS's
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following defines may be activated, commented or modified
|
||||
* by user for her/his own purpose.
|
||||
*/
|
||||
/*#define WANT_INT*/ /* activate CPU's interrupts */
|
||||
#define WANT_SPC /* activate SP over-/underrun handling 0000<->FFFF */
|
||||
#define WANT_PCC /* activate PC overrun handling FFFF->0000 */
|
||||
#define CNTL_C /* cntl-c will stop running emulation */
|
||||
#define CNTL_BS /* cntl-\ will stop running emulation */
|
||||
#define CNTL_Z /* cntl-z will suspend emulator */
|
||||
#define WANT_TIM /* activate runtime measurement */
|
||||
#define HISIZE 100 /* number of entrys in history */
|
||||
#define SBSIZE 4 /* number of software breakpoints */
|
||||
|
||||
/*
|
||||
* The following defines may be modified and activated by
|
||||
* user, to print her/his copyright for a developed system,
|
||||
* which contains the Z80-CPU simulation as a part.
|
||||
*/
|
||||
/*
|
||||
#define USR_COM "XYZ-System Simulation"
|
||||
#define USR_REL "x.y"
|
||||
#define USR_CPR "Copyright (C) 20xx by XYZ"
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following lines of this file should not be modified by user
|
||||
*/
|
||||
#define COPYR "Copyright (C) 1987-2006 by Udo Munk"
|
||||
#define RELEASE "1.9"
|
||||
|
||||
#define LENCMD 80 /* length of command buffers etc */
|
||||
|
||||
#define S_FLAG 128 /* bit definitions of CPU flags */
|
||||
#define Z_FLAG 64
|
||||
#define N2_FLAG 32
|
||||
#define H_FLAG 16
|
||||
#define N1_FLAG 8
|
||||
#define P_FLAG 4
|
||||
#define N_FLAG 2
|
||||
#define C_FLAG 1
|
||||
|
||||
/* operation of simulated CPU */
|
||||
#define SINGLE_STEP 0 /* single step */
|
||||
#define CONTIN_RUN 1 /* continual run */
|
||||
#define STOPPED 0 /* stop CPU because of error */
|
||||
|
||||
/* causes of error */
|
||||
#define NONE 0 /* no error */
|
||||
#define OPHALT 1 /* HALT op-code trap */
|
||||
#define IOTRAP 2 /* IN/OUT trap */
|
||||
#define OPTRAP1 3 /* illegal 1 byte op-code trap */
|
||||
#define OPTRAP2 4 /* illegal 2 byte op-code trap */
|
||||
#define OPTRAP4 5 /* illegal 4 byte op-code trap */
|
||||
#define USERINT 6 /* user interrupt */
|
||||
|
||||
/* type of CPU interrupt */
|
||||
#define INT_NMI 1 /* non maskable interrupt */
|
||||
#define INT_INT 2 /* maskable interrupt */
|
||||
|
||||
typedef unsigned short WORD; /* 16 bit unsigned */
|
||||
typedef unsigned char BYTE; /* 8 bit unsigned */
|
||||
|
||||
#ifdef HISIZE
|
||||
struct history { /* structure of a history entry */
|
||||
WORD h_adr; /* address of execution */
|
||||
WORD h_af; /* register AF */
|
||||
WORD h_bc; /* register BC */
|
||||
WORD h_de; /* register DE */
|
||||
WORD h_hl; /* register HL */
|
||||
WORD h_ix; /* register IX */
|
||||
WORD h_iy; /* register IY */
|
||||
WORD h_sp; /* register SP */
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef SBSIZE
|
||||
struct softbreak { /* structure of a breakpoint */
|
||||
WORD sb_adr; /* address of breakpoint */
|
||||
BYTE sb_oldopc; /* op-code at address of breakpoint */
|
||||
int sb_passcount; /* pass counter of breakpoint */
|
||||
int sb_pass; /* no. of pass to break */
|
||||
};
|
||||
#endif
|
@@ -1,104 +0,0 @@
|
||||
/*
|
||||
* Z80SIM - a Z80-CPU simulator
|
||||
*
|
||||
* Copyright (C) 1987-2006 by Udo Munk
|
||||
*
|
||||
* This is the configuration I'm using for software testing and debugging
|
||||
*
|
||||
* History:
|
||||
* 28-SEP-87 Development on TARGON/35 with AT&T Unix System V.3
|
||||
* 11-JAN-89 Release 1.1
|
||||
* 08-FEB-89 Release 1.2
|
||||
* 13-MAR-89 Release 1.3
|
||||
* 09-FEB-90 Release 1.4 Ported to TARGON/31 M10/30
|
||||
* 20-DEC-90 Release 1.5 Ported to COHERENT 3.0
|
||||
* 10-JUN-92 Release 1.6 long casting problem solved with COHERENT 3.2
|
||||
* and some optimization
|
||||
* 25-JUN-92 Release 1.7 comments in english
|
||||
* 03-OCT-06 Release 1.8 modified to compile on modern POSIX OS's
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following defines may be activated, commented or modified
|
||||
* by user for her/his own purpose.
|
||||
*/
|
||||
/*#define WANT_INT*/ /* activate CPU's interrupts */
|
||||
#define WANT_SPC /* activate SP over-/underrun handling 0000<->FFFF */
|
||||
#define WANT_PCC /* activate PC overrun handling FFFF->0000 */
|
||||
#define CNTL_C /* cntl-c will stop running emulation */
|
||||
#define CNTL_BS /* cntl-\ will stop running emulation */
|
||||
#define CNTL_Z /* cntl-z will suspend emulator */
|
||||
#define WANT_TIM /* activate runtime measurement */
|
||||
#define HISIZE 100 /* number of entrys in history */
|
||||
#define SBSIZE 4 /* number of software breakpoints */
|
||||
|
||||
/*
|
||||
* The following defines may be modified and activated by
|
||||
* user, to print her/his copyright for a developed system,
|
||||
* which contains the Z80-CPU simulation as a part.
|
||||
*/
|
||||
/*
|
||||
#define USR_COM "XYZ-System Simulation"
|
||||
#define USR_REL "x.y"
|
||||
#define USR_CPR "Copyright (C) 20xx by XYZ"
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following lines of this file should not be modified by user
|
||||
*/
|
||||
#define COPYR "Copyright (C) 1987-2006 by Udo Munk"
|
||||
#define RELEASE "1.9"
|
||||
|
||||
#define LENCMD 80 /* length of command buffers etc */
|
||||
|
||||
#define S_FLAG 128 /* bit definitions of CPU flags */
|
||||
#define Z_FLAG 64
|
||||
#define N2_FLAG 32
|
||||
#define H_FLAG 16
|
||||
#define N1_FLAG 8
|
||||
#define P_FLAG 4
|
||||
#define N_FLAG 2
|
||||
#define C_FLAG 1
|
||||
|
||||
/* operation of simulated CPU */
|
||||
#define SINGLE_STEP 0 /* single step */
|
||||
#define CONTIN_RUN 1 /* continual run */
|
||||
#define STOPPED 0 /* stop CPU because of error */
|
||||
|
||||
/* causes of error */
|
||||
#define NONE 0 /* no error */
|
||||
#define OPHALT 1 /* HALT op-code trap */
|
||||
#define IOTRAP 2 /* IN/OUT trap */
|
||||
#define OPTRAP1 3 /* illegal 1 byte op-code trap */
|
||||
#define OPTRAP2 4 /* illegal 2 byte op-code trap */
|
||||
#define OPTRAP4 5 /* illegal 4 byte op-code trap */
|
||||
#define USERINT 6 /* user interrupt */
|
||||
|
||||
/* type of CPU interrupt */
|
||||
#define INT_NMI 1 /* non maskable interrupt */
|
||||
#define INT_INT 2 /* maskable interrupt */
|
||||
|
||||
typedef unsigned short WORD; /* 16 bit unsigned */
|
||||
typedef unsigned char BYTE; /* 8 bit unsigned */
|
||||
|
||||
#ifdef HISIZE
|
||||
struct history { /* structure of a history entry */
|
||||
WORD h_adr; /* address of execution */
|
||||
WORD h_af; /* register AF */
|
||||
WORD h_bc; /* register BC */
|
||||
WORD h_de; /* register DE */
|
||||
WORD h_hl; /* register HL */
|
||||
WORD h_ix; /* register IX */
|
||||
WORD h_iy; /* register IY */
|
||||
WORD h_sp; /* register SP */
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef SBSIZE
|
||||
struct softbreak { /* structure of a breakpoint */
|
||||
WORD sb_adr; /* address of breakpoint */
|
||||
BYTE sb_oldopc; /* op-code at address of breakpoint */
|
||||
int sb_passcount; /* pass counter of breakpoint */
|
||||
int sb_pass; /* no. of pass to break */
|
||||
};
|
||||
#endif
|
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Z80SIM - a Z80-CPU simulator
|
||||
*
|
||||
* Copyright (C) 1987-2006 by Udo Munk
|
||||
*
|
||||
* With this configuration the simulated Z80 runs with the
|
||||
* highest possible speed
|
||||
*
|
||||
* History:
|
||||
* 28-SEP-87 Development on TARGON/35 with AT&T Unix System V.3
|
||||
* 11-JAN-89 Release 1.1
|
||||
* 08-FEB-89 Release 1.2
|
||||
* 13-MAR-89 Release 1.3
|
||||
* 09-FEB-90 Release 1.4 Ported to TARGON/31 M10/30
|
||||
* 20-DEC-90 Release 1.5 Ported to COHERENT 3.0
|
||||
* 10-JUN-92 Release 1.6 long casting problem solved with COHERENT 3.2
|
||||
* and some optimization
|
||||
* 25-JUN-92 Release 1.7 comments in english
|
||||
* 03-OCT-06 Release 1.8 modified to compile on modern POSIX OS's
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following defines may be activated, commented or modified
|
||||
* by user for her/his own purpose.
|
||||
*/
|
||||
/*#define WANT_INT*/ /* activate CPU's interrupts */
|
||||
/*#define WANT_SPC*/ /* activate SP over-/underrun handling 0000<->FFFF */
|
||||
/*#define WANT_PCC*/ /* activate PC overrun handling FFFF->0000 */
|
||||
#define CNTL_C /* cntl-c will stop running emulation */
|
||||
#define CNTL_BS /* cntl-\ will stop running emulation */
|
||||
#define CNTL_Z /* cntl-z will suspend emulator */
|
||||
/*#define WANT_TIM*/ /* activate runtime measurement */
|
||||
/*#define HISIZE 100*/ /* number of entrys in history */
|
||||
/*#define SBSIZE 4*/ /* number of software breakpoints */
|
||||
|
||||
/*
|
||||
* The following defines may be modified and activated by
|
||||
* user, to print her/his copyright for a developed system,
|
||||
* which contains the Z80-CPU simulation as a part.
|
||||
*/
|
||||
/*
|
||||
#define USR_COM "XYZ-System Simulation"
|
||||
#define USR_REL "x.y"
|
||||
#define USR_CPR "Copyright (C) 20xx by XYZ"
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following lines of this file should not be modified by user
|
||||
*/
|
||||
#define COPYR "Copyright (C) 1987-2006 by Udo Munk"
|
||||
#define RELEASE "1.9"
|
||||
|
||||
#define LENCMD 80 /* length of command buffers etc */
|
||||
|
||||
#define S_FLAG 128 /* bit definitions of CPU flags */
|
||||
#define Z_FLAG 64
|
||||
#define N2_FLAG 32
|
||||
#define H_FLAG 16
|
||||
#define N1_FLAG 8
|
||||
#define P_FLAG 4
|
||||
#define N_FLAG 2
|
||||
#define C_FLAG 1
|
||||
|
||||
/* operation of simulated CPU */
|
||||
#define SINGLE_STEP 0 /* single step */
|
||||
#define CONTIN_RUN 1 /* continual run */
|
||||
#define STOPPED 0 /* stop CPU because of error */
|
||||
|
||||
/* causes of error */
|
||||
#define NONE 0 /* no error */
|
||||
#define OPHALT 1 /* HALT op-code trap */
|
||||
#define IOTRAP 2 /* IN/OUT trap */
|
||||
#define OPTRAP1 3 /* illegal 1 byte op-code trap */
|
||||
#define OPTRAP2 4 /* illegal 2 byte op-code trap */
|
||||
#define OPTRAP4 5 /* illegal 4 byte op-code trap */
|
||||
#define USERINT 6 /* user interrupt */
|
||||
|
||||
/* type of CPU interrupt */
|
||||
#define INT_NONE 0
|
||||
#define INT_NMI 1 /* non maskable interrupt */
|
||||
#define INT_INT 2 /* maskable interrupt */
|
||||
|
||||
typedef unsigned short WORD; /* 16 bit unsigned */
|
||||
typedef unsigned char BYTE; /* 8 bit unsigned */
|
||||
|
||||
#ifdef HISIZE
|
||||
struct history { /* structure of a history entry */
|
||||
WORD h_adr; /* address of execution */
|
||||
WORD h_af; /* register AF */
|
||||
WORD h_bc; /* register BC */
|
||||
WORD h_de; /* register DE */
|
||||
WORD h_hl; /* register HL */
|
||||
WORD h_ix; /* register IX */
|
||||
WORD h_iy; /* register IY */
|
||||
WORD h_sp; /* register SP */
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef SBSIZE
|
||||
struct softbreak { /* structure of a breakpoint */
|
||||
WORD sb_adr; /* address of breakpoint */
|
||||
BYTE sb_oldopc; /* op-code at address of breakpoint */
|
||||
int sb_passcount; /* pass counter of breakpoint */
|
||||
int sb_pass; /* no. of pass to break */
|
||||
};
|
||||
#endif
|
@@ -1,202 +0,0 @@
|
||||
/*
|
||||
* Z80SIM - a Z80-CPU simulator
|
||||
*
|
||||
* Copyright (C) 1987-2006 by Udo Munk
|
||||
*
|
||||
* History:
|
||||
* 28-SEP-87 Development on TARGON/35 with AT&T Unix System V.3
|
||||
* 11-JAN-89 Release 1.1
|
||||
* 08-FEB-89 Release 1.2
|
||||
* 13-MAR-89 Release 1.3
|
||||
* 09-FEB-90 Release 1.4 Ported to TARGON/31 M10/30
|
||||
* 20-DEC-90 Release 1.5 Ported to COHERENT 3.0
|
||||
* 10-JUN-92 Release 1.6 long casting problem solved with COHERENT 3.2
|
||||
* and some optimization
|
||||
* 25-JUN-92 Release 1.7 comments in english and ported to COHERENT 4.0
|
||||
* 03-OCT-06 Release 1.8 modified to compile on modern POSIX OS's
|
||||
*/
|
||||
|
||||
/*
|
||||
* This modul contain the 'main()' function of the simulator,
|
||||
* where the options are checked and variables are initialized.
|
||||
* After initialization of the UNIX interrupts ( int_on() )
|
||||
* and initialization of the I/O simulation ( init_io() )
|
||||
* the user interface ( mon() ) is called.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <memory.h>
|
||||
#include "sim.h"
|
||||
#include "simglb.h"
|
||||
|
||||
static void save_core(void), load_core(void);
|
||||
extern void int_on(void), int_off(void), mon(void);
|
||||
extern void init_io(void), exit_io(void);
|
||||
extern int exatoi(char *);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
register char *s, *p;
|
||||
register char *pn = argv[0];
|
||||
|
||||
while (--argc > 0 && (*++argv)[0] == '-')
|
||||
for (s = argv[0] + 1; *s != '\0'; s++)
|
||||
switch (*s) {
|
||||
case 's': /* save core and CPU on exit */
|
||||
s_flag = 1;
|
||||
break;
|
||||
case 'l': /* load core and CPU from file */
|
||||
l_flag = 1;
|
||||
break;
|
||||
case 'h': /* execute HALT opcode */
|
||||
break_flag = 0;
|
||||
break;
|
||||
case 'i': /* trap I/O on unused ports */
|
||||
i_flag = 1;
|
||||
break;
|
||||
case 'm': /* initialize Z80 memory */
|
||||
m_flag = exatoi(s+1);
|
||||
s += strlen(s+1);
|
||||
break;
|
||||
case 'f':
|
||||
f_flag = atoi(s+1);
|
||||
s += strlen(s+1);
|
||||
freq = (float) 1 / (float) f_flag;
|
||||
break;
|
||||
case 'x': /* get filename with Z80 executable */
|
||||
x_flag = 1;
|
||||
s++;
|
||||
p = xfn;
|
||||
while (*s)
|
||||
*p++ = *s++;
|
||||
*p = '\0';
|
||||
s--;
|
||||
break;
|
||||
case '?':
|
||||
goto usage;
|
||||
default:
|
||||
printf("illegal option %c\n", *s);
|
||||
usage: printf("usage:\t%s -s -l -i -h -mn -fn -xfilename\n", pn);
|
||||
puts("\ts = save core and cpu");
|
||||
puts("\tl = load core and cpu");
|
||||
puts("\ti = trap on I/O to unused ports");
|
||||
puts("\th = execute HALT op-code");
|
||||
puts("\tm = init memory with n");
|
||||
puts("\tf = CPU frequenzy n in MHz (not implemented yet)");
|
||||
puts("\tx = load and execute filename");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
putchar('\n');
|
||||
puts("####### ##### ### ##### ### # #");
|
||||
puts(" # # # # # # # # ## ##");
|
||||
puts(" # # # # # # # # # # #");
|
||||
puts(" # ##### # # ##### ##### # # # #");
|
||||
puts(" # # # # # # # # #");
|
||||
puts(" # # # # # # # # # #");
|
||||
puts("####### ##### ### ##### ### # #");
|
||||
printf("\nRelease %s, %s\n", RELEASE, COPYR);
|
||||
#ifdef USR_COM
|
||||
printf("%s Release %s, %s\n", USR_COM, USR_REL, USR_CPR);
|
||||
#endif
|
||||
putchar('\n');
|
||||
fflush(stdout);
|
||||
|
||||
wrk_ram = PC = STACK = ram;
|
||||
memset((char *) ram, m_flag, 32768);
|
||||
memset((char *) ram + 32768, m_flag, 32768);
|
||||
if (l_flag)
|
||||
load_core();
|
||||
int_on();
|
||||
init_io();
|
||||
mon();
|
||||
if (s_flag)
|
||||
save_core();
|
||||
exit_io();
|
||||
int_off();
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function saves the CPU and the memory into the file core.z80
|
||||
*
|
||||
*/
|
||||
static void save_core(void)
|
||||
{
|
||||
int fd;
|
||||
|
||||
if ((fd = open("core.z80", O_WRONLY | O_CREAT, 0600)) == -1) {
|
||||
puts("can't open file core.z80");
|
||||
return;
|
||||
}
|
||||
write(fd, (char *) &A, sizeof(A));
|
||||
write(fd, (char *) &F, sizeof(F));
|
||||
write(fd, (char *) &B, sizeof(B));
|
||||
write(fd, (char *) &C, sizeof(C));
|
||||
write(fd, (char *) &D, sizeof(D));
|
||||
write(fd, (char *) &E, sizeof(E));
|
||||
write(fd, (char *) &H, sizeof(H));
|
||||
write(fd, (char *) &L, sizeof(L));
|
||||
write(fd, (char *) &A_, sizeof(A_));
|
||||
write(fd, (char *) &F_, sizeof(F_));
|
||||
write(fd, (char *) &B_, sizeof(B_));
|
||||
write(fd, (char *) &C_, sizeof(C_));
|
||||
write(fd, (char *) &D_, sizeof(D_));
|
||||
write(fd, (char *) &E_, sizeof(E_));
|
||||
write(fd, (char *) &H_, sizeof(H_));
|
||||
write(fd, (char *) &L_, sizeof(L_));
|
||||
write(fd, (char *) &I, sizeof(I));
|
||||
write(fd, (char *) &IFF, sizeof(IFF));
|
||||
write(fd, (char *) &R, sizeof(R));
|
||||
write(fd, (char *) &PC, sizeof(PC));
|
||||
write(fd, (char *) &STACK, sizeof(STACK));
|
||||
write(fd, (char *) &IX, sizeof(IX));
|
||||
write(fd, (char *) &IY, sizeof(IY));
|
||||
write(fd, (char *) ram, 32768);
|
||||
write(fd, (char *) ram + 32768, 32768);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function loads the CPU and memory from the file core.z80
|
||||
*
|
||||
*/
|
||||
static void load_core(void)
|
||||
{
|
||||
int fd;
|
||||
|
||||
if ((fd = open("core.z80", O_RDONLY)) == -1) {
|
||||
puts("can't open file core.z80");
|
||||
return;
|
||||
}
|
||||
read(fd, (char *) &A, sizeof(A));
|
||||
read(fd, (char *) &F, sizeof(F));
|
||||
read(fd, (char *) &B, sizeof(B));
|
||||
read(fd, (char *) &C, sizeof(C));
|
||||
read(fd, (char *) &D, sizeof(D));
|
||||
read(fd, (char *) &E, sizeof(E));
|
||||
read(fd, (char *) &H, sizeof(H));
|
||||
read(fd, (char *) &L, sizeof(L));
|
||||
read(fd, (char *) &A_, sizeof(A_));
|
||||
read(fd, (char *) &F_, sizeof(F_));
|
||||
read(fd, (char *) &B_, sizeof(B_));
|
||||
read(fd, (char *) &C_, sizeof(C_));
|
||||
read(fd, (char *) &D_, sizeof(D_));
|
||||
read(fd, (char *) &E_, sizeof(E_));
|
||||
read(fd, (char *) &H_, sizeof(H_));
|
||||
read(fd, (char *) &L_, sizeof(L_));
|
||||
read(fd, (char *) &I, sizeof(I));
|
||||
read(fd, (char *) &IFF, sizeof(IFF));
|
||||
read(fd, (char *) &R, sizeof(R));
|
||||
read(fd, (char *) &PC, sizeof(PC));
|
||||
read(fd, (char *) &STACK, sizeof(STACK));
|
||||
read(fd, (char *) &IX, sizeof(IX));
|
||||
read(fd, (char *) &IY, sizeof(IY));
|
||||
read(fd, (char *) ram, 32768);
|
||||
read(fd, (char *) ram + 32768, 32768);
|
||||
close(fd);
|
||||
}
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user