Lots of MACRO-10 improvements, DAKAM now assembles (but does not pass)
This commit is contained in:
parent
3fb3f44384
commit
09dc4dcb9a
13 changed files with 22047 additions and 1758 deletions
10176
apps/pdp10/diags/ka10/dakam/DAKAM.LST.txt
Normal file
10176
apps/pdp10/diags/ka10/dakam/DAKAM.LST.txt
Normal file
File diff suppressed because it is too large
Load diff
5654
apps/pdp10/diags/ka10/dakam/DAKAM.MAC.txt
Normal file
5654
apps/pdp10/diags/ka10/dakam/DAKAM.MAC.txt
Normal file
File diff suppressed because it is too large
Load diff
3738
apps/pdp10/diags/ka10/dakam/DAKAMM.MAC.txt
Normal file
3738
apps/pdp10/diags/ka10/dakam/DAKAMM.MAC.txt
Normal file
File diff suppressed because it is too large
Load diff
154
apps/pdp10/diags/ka10/dakam/DAKAMT.MAC.txt
Normal file
154
apps/pdp10/diags/ka10/dakam/DAKAMT.MAC.txt
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
;DAKAM
|
||||
|
||||
|
||||
MCNVER==0
|
||||
DECVER==2
|
||||
|
||||
|
||||
XLIST
|
||||
DEFINE NAME (MCNVER,DECVER)<
|
||||
|
||||
TITLE DAKAM PDP-10 KA10 BASIC INSTRUCTION DIAGNOSTIC (13) MCNVER,DECVER
|
||||
>
|
||||
LIST
|
||||
LALL
|
||||
|
||||
NAME \MCNVER,\DECVER
|
||||
|
||||
;(BYTE, BLOCK TRANSFER, JFFO AND OTHER BASIC MISCELLANEOUS INSTRUCTIONS)
|
||||
|
||||
;COPYRIGHT 1975,1977
|
||||
;DIGITAL EQUIPMENT CORPORATION
|
||||
;MARLBORO, MASS. 01752
|
||||
|
||||
;JOHN R. KIRCHOFF
|
||||
|
||||
LOC 137
|
||||
MCNVER,,DECVER
|
||||
|
||||
NOSYM
|
||||
SUBTTL DIAGNOSTIC PARAMETERS
|
||||
|
||||
;OPERATOR DEFINITIONS
|
||||
|
||||
OPDEF ER1 [1B8]
|
||||
OPDEF ER2 [2B8]
|
||||
OPDEF ER3 [3B8]
|
||||
OPDEF ER4 [4B8]
|
||||
OPDEF ER5 [5B8]
|
||||
OPDEF ER6 [6B8]
|
||||
OPDEF ER7 [7B8]
|
||||
OPDEF ER10 [10B8]
|
||||
OPDEF ER11 [11B8]
|
||||
OPDEF ER12 [12B8]
|
||||
OPDEF ER13 [13B8]
|
||||
|
||||
LUUO1=ERRMES
|
||||
LUUO2=ERRMES
|
||||
LUUO3=ERRMES
|
||||
LUUO4=ERRMES
|
||||
LUUO5=ERRMES
|
||||
LUUO6=ERRMES
|
||||
LUUO7=ERRMES
|
||||
LUUO10=ERRMES
|
||||
LUUO11=ERRMES
|
||||
LUUO12=ERRMES
|
||||
LUUO13=ERRMES
|
||||
;SUBROUTINE ASSEMBLY DEFINITIONS
|
||||
|
||||
DEBUG=40
|
||||
EXCASB=1
|
||||
USRASB=1
|
||||
KA10=1
|
||||
PGMEND=1
|
||||
ERDIAG=1
|
||||
|
||||
;SPECIAL FEATURE DEFINITIONS
|
||||
|
||||
SADR1=BEGIN
|
||||
SADR2=BEGIN
|
||||
SADR3=BEGIN
|
||||
SADR4=BEGIN
|
||||
SADR5=JRST BEGIN
|
||||
SADR6=JRST BEGIN
|
||||
SADR7=JRST BEGIN
|
||||
SADR8=JRST BEGIN
|
||||
SADR9=JRST BEGIN
|
||||
SADR10=JRST BEGIN
|
||||
SADR11=JRST BEGIN
|
||||
|
||||
;SPECIAL FEATURE PARAMETERS
|
||||
|
||||
PAREA0=0
|
||||
PAREA1=0
|
||||
PAREA2=0
|
||||
PAREA3=SIXBIT/DAKAM/
|
||||
PAREA4=SIXBIT/TMP/
|
||||
PAREA5=0
|
||||
PAREA6=0
|
||||
ITERAT==1000
|
||||
|
||||
;MACROS
|
||||
|
||||
DEFINE SAVEAC (A,B)<
|
||||
MOVEI AC+2,. ;SAVE TEST PC
|
||||
MOVEM AC+2,TESTPC
|
||||
MOVEI AC+2,<AC+2>&17 ;INFORM ERROR ROUTINE WHICH
|
||||
MOVEM AC+2,ERRLOP# ;AC IS USED FOR ITERATION>
|
||||
;SPECIAL INSTRUCTIONS TO ASSEMBLER
|
||||
|
||||
IF1,<BYTBLK=14773> ;BYTBLK BEYOND AC RANGE FOR PASS 1
|
||||
IF1,<BLTBLK=15000> ;BLTBLK BEYOND AC RANGE FOR PASS 1
|
||||
|
||||
;MACROS
|
||||
|
||||
DEFINE GMOV (X1,DATA),<
|
||||
IFLE <X1-20>,<
|
||||
MOVE X1,[DATA] ;PRELOAD X1 WITH DATA>
|
||||
IFG <X1-20>,<
|
||||
MOVE AC+1,[DATA]
|
||||
MOVEM AC+1,X1 ;PRELOAD X1 WITH DATA>>
|
||||
|
||||
DEFINE GCAM (X1,DATA),<
|
||||
SN=SN+1
|
||||
IFG <X1-20>,<
|
||||
MOVE AC-1,X1
|
||||
CAME AC-1,[DATA] ;IS C(X1) = DATA
|
||||
IFIDN <DEST>,<X1>,<
|
||||
ER2 AC-1,SN ;DEST NOT LOADED CORRECTLY>
|
||||
IFDIF <DEST>,<X1>,<
|
||||
ER2 AC-1,SN ;C(X1) WAS CLOBBERED>>
|
||||
IFLE <X1-20>,<
|
||||
CAME X1,[DATA] ;IS C(X1) = DATA
|
||||
IFIDN <DEST>,<X1>,<
|
||||
ER2 X1,SN ;DEST NOT LOADED CORRECTLY>
|
||||
IFDIF <DEST>,<X1>,<
|
||||
ER2 X1,SN ;C(X1) WAS CLOBBERED>>>
|
||||
DEFINE BLTM1 (A1,C1,S1,D1,SC)<
|
||||
;VERIFY THAT BLT WILL TRANSFER A 1 WORD BLOCK OF DATA
|
||||
;WHERE SOURCE AND DESTINATION ARE DIFFERENT
|
||||
;SOURCE DATA = SC
|
||||
|
||||
AC=C1
|
||||
SAVEAC (1,1)
|
||||
SN=A1
|
||||
SRCE=S1 ;1ST LOC OF SOURCE = S1
|
||||
DEST=D1 ;1ST LOC OF DESTINATION = D1
|
||||
SIZ=1 ;BLOCK SIZE = 1 WORD
|
||||
|
||||
G'A1: MOVE AC,[SRCE,,DEST] ;LOAD BLT AC
|
||||
GMOV (SRCE-1,<252525252525>)
|
||||
GMOV (SRCE,<SC>)
|
||||
GMOV (SRCE+1,<770077007700>)
|
||||
GMOV (DEST-1,<070707070707>)
|
||||
GMOV (DEST,<123456765432>)
|
||||
GMOV (DEST+1,<552255225522>)
|
||||
BLT AC,DEST+SIZ-1 ;*BLOCK TRANSFER
|
||||
GCAM (SRCE-1,<252525252525>)
|
||||
GCAM (SRCE,<SC>)
|
||||
GCAM (SRCE+1,<770077007700>)
|
||||
GCAM (DEST-1,<070707070707>)
|
||||
GCAM (DEST,<SC>)
|
||||
GCAM (DEST+1,<552255225522>)
|
||||
JUMPL AC+2,G'A1 ;LOOP ON ERROR>
|
||||
|
||||
430
apps/pdp10/diags/ka10/dakam/README.md
Normal file
430
apps/pdp10/diags/ka10/dakam/README.md
Normal file
|
|
@ -0,0 +1,430 @@
|
|||
---
|
||||
layout: page
|
||||
title: PDP-10 KA10 Basic Instruction Diagnostic #13
|
||||
permalink: /apps/pdp10/diags/ka10/dakam/
|
||||
machines:
|
||||
- id: testka10
|
||||
type: pdp10
|
||||
config: /devices/pdp10/machine/ka10/test/debugger/machine.xml
|
||||
debugger: true
|
||||
commands: a dakam.mac
|
||||
---
|
||||
|
||||
PDP-10 KA10 Basic Instruction Diagnostic #13
|
||||
--------------------------------------------
|
||||
|
||||
The *PDP-10 KA10 Basic Instruction Diagnostic #13* (MAINDEC-10-DAKAM) test code has been extracted from
|
||||
[DAKAMM.MAC](DAKAMM.MAC.txt) [[original](http://pdp-10.trailing-edge.com/klad_sources/01/klad.sources/dakamm.mac.html)] and
|
||||
[DAKAMT.MAC](DAKAMT.MAC.txt) [[original](http://pdp-10.trailing-edge.com/klad_sources/01/klad.sources/dakamt.mac.html)]
|
||||
for use with the [PDP-10 Test Machine with Debugger](/devices/pdp10/machine/ka10/test/debugger/) below.
|
||||
|
||||
This diagnostic "TESTS THE BYTE, BLOCK TRANSFER AND JFFO INSTRUCTIONS."
|
||||
|
||||
Information regarding this diagnostic includes:
|
||||
|
||||
- [Instructions](#dakamtxt)
|
||||
- [History](#dakamhst)
|
||||
- [Source Code](#dakammac)
|
||||
- [MACRO-10 Listing](DAKAM.LST.txt)
|
||||
- [Additional Information](http://archive.pcjs.org/apps/pdp10/diags/ka10/dakam/DAKAM.SEQ.txt)
|
||||
|
||||
{% include machine.html id="testka10" %}
|
||||
|
||||
The Debugger's assemble ("a") command can be used to test the new built-in
|
||||
[MACRO-10 Mini-Assembler](/modules/pdp10/lib/macro10.js), which supports a subset
|
||||
of the [MACRO-10](http://archive.pcjs.org/pubs/dec/pdp10/tops10/02_1973AsmRef_macro.pdf) assembly language.
|
||||
This command:
|
||||
|
||||
a DAKAM.MAC
|
||||
|
||||
will automatically read the [DAKAM.MAC](DAKAM.MAC.txt) source file (a slightly modified copy of [DAKAMM.MAC](DAKAMM.MAC.txt)),
|
||||
assemble it, and then load the binary image at the location specified in the file.
|
||||
|
||||
---
|
||||
|
||||
DAKAM.TXT
|
||||
---------
|
||||
|
||||
```
|
||||
MAINDEC-10-DAKAM.TXT
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
IDENTIFICATION
|
||||
--------------
|
||||
|
||||
PRODUCT CODE: MAINDEC-10-DAKAM-B-D
|
||||
|
||||
PRODUCT NAME: DECSYSTEM10 PDP-10 KA10 BASIC
|
||||
INSTRUCTION DIAGNOSTIC (13)
|
||||
|
||||
FUNCTION: BYTE, BLT, JFFO
|
||||
|
||||
VERSION: 0.2
|
||||
|
||||
DATE RELEASED: JANUARY 1977
|
||||
|
||||
MAINTAINED BY: DIAGNOSTIC ENGINEERING GROUP
|
||||
|
||||
AUTHOR: JOHN R. KIRCHOFF
|
||||
|
||||
COPYRIGHT(C) 1976,1977
|
||||
DIGITAL EQUIPMENT CORPORATION
|
||||
MARLBORO, MASS. 01752
|
||||
|
||||
THIS SOFTWARE IS FURNISHED UNDER A LICENSE FOR USE ONLY
|
||||
ON A SINGLE COMPUTER SYSTEM AND MAY BE COPIED ONLY WITH
|
||||
THE INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE,
|
||||
OR ANY OTHER COPIES THEREOF, MAY NOT BE PROVIDED OR OTHERWISE
|
||||
MADE AVAILABLE TO ANY OTHER PERSON EXECPT FOR USE ON SUCH SYSTEM
|
||||
AND TO ONE WHO AGREES TO THESE LICENSE TERMS. TITLE TO AND
|
||||
OWNERSHIP OF THE SOFTWARE SHALL AT ALL TIMES REMAIN IN DEC.
|
||||
|
||||
THE INFORMATION IN THIS DOCUMENT IS SUBJECT TO CHANGE WITHOUT
|
||||
NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL
|
||||
EQUIPMENT CORPORATION.
|
||||
|
||||
DEC ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
|
||||
SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DEC.
|
||||
|
||||
MAINDEC-10-DAKAM.TXT
|
||||
PAGE 2
|
||||
|
||||
TABLE OF CONTENTS
|
||||
-----------------
|
||||
|
||||
1.0 ABSTRACT
|
||||
|
||||
2.0 REQUIREMENTS
|
||||
|
||||
2.1 EQUIPMENT
|
||||
|
||||
2.2 STORAGE
|
||||
|
||||
2.3 PRELIMINARY PROGRAMS
|
||||
|
||||
3.0 PROGRAM PROCEDURES
|
||||
|
||||
3.1 LOADING PROCEDURE
|
||||
|
||||
3.2 STARTING PROCEDURE
|
||||
|
||||
3.3 OPERATING PROCEDURE
|
||||
|
||||
4.0 DATA SWITCH FUNCTIONS
|
||||
|
||||
5.0 ERRORS
|
||||
|
||||
6.0 ITERATION COUNTER
|
||||
|
||||
7.0 CYCLE TIME
|
||||
|
||||
8.0 OPERATIONAL VARIATIONS
|
||||
|
||||
9.0 MISCELLANEOUS
|
||||
|
||||
10.0 LISTING
|
||||
|
||||
MAINDEC-10-DAKAM.TXT
|
||||
PAGE 3
|
||||
|
||||
1.0 ABSTRACT
|
||||
|
||||
THIS PDP-10 KA10 BASIC INSTRUCTION DIAGNOSTIC IS THE
|
||||
THIRTEENTH IN A SERIES OF PDP-10 KA10 PROCESSOR DIAGNOSTICS.
|
||||
THE DIAGNOSTIC TESTS THE BYTE, BLOCK TRANSFER AND
|
||||
JFFO INSTRUCTIONS.
|
||||
|
||||
2.0 REQUIREMENTS
|
||||
|
||||
2.1 EQUIPMENT
|
||||
|
||||
A PDP-10 KA10 EQUIPPED WITH A MINIMUM OF 32K OF MEMORY
|
||||
|
||||
PAPER TAPE READER
|
||||
CONSOLE TELETYPE
|
||||
DECTAPE
|
||||
LINE PRINTER (OPTIONAL)
|
||||
|
||||
2.2 STORAGE
|
||||
|
||||
THE PROGRAM RUNS WITHIN 32K OF MEMORY.
|
||||
|
||||
2.3 PRELIMINARY PROGRAMS
|
||||
|
||||
PREVIOUS PROCESSOR DIAGNOSTICS
|
||||
|
||||
3.0 PROGRAM PROCEDURES
|
||||
|
||||
3.1 LOADING PROCEDURE
|
||||
|
||||
THIS DIAGNOSTIC REQUIRES THAT THE DECSYSTEM10 SUBROUTINE
|
||||
PROGRAM BE RESIDENT IN THE PDP-10.
|
||||
|
||||
PAPER TAPE - HARDWARE READ-IN (READER DEVICE CODE 104)
|
||||
DECTAPE - LOAD WITH DIAMON (DECTAPE DEVICE CODE 320)
|
||||
TIME SHARING - RUN UNDER DIAMON.
|
||||
|
||||
MAINDEC-10-DAKAM.TXT
|
||||
PAGE 4
|
||||
|
||||
3.2 STARTING PROCEDURE
|
||||
|
||||
A. SELECT OPERATIONAL CONSOLE DATA SWITCH SETTINGS (REFER TO
|
||||
4.0 DATA SWITCH FUNCTIONS).
|
||||
|
||||
B. EXEC MODE
|
||||
|
||||
STAND-ALONE STARTING ADDRESS IS 30000.
|
||||
|
||||
C. USER MODE
|
||||
|
||||
RUN UNDER "DIAMON".
|
||||
IN USER MODE THE FOLLOWING QUESTIONS WILL BE ASKED TO
|
||||
SELECT THE OPERATIONAL SWITCHES:
|
||||
|
||||
TELETYPE SWITCH CONTROL ? 0,S,Y OR N (CR) -
|
||||
|
||||
IF THE OPERATOR TYPES "N", THE ACTUAL CONSOLE
|
||||
SWITCHES ARE USED.
|
||||
|
||||
IF THE OPERATOR TYPES "Y", THE FOLLOWING QUESTIONS
|
||||
ARE ASKED AND THE OPERATOR RESPONDS BY TYPING
|
||||
THE ANSWER AS SIX OCTAL DIGITS REPRESENTING
|
||||
THE DESIRED SWITCH SETTINGS.
|
||||
|
||||
SPECIFY LH SWITCHES IN OCTAL-
|
||||
|
||||
SPECIFY RH SWITCHES IN OCTAL-
|
||||
|
||||
IF THE OPERATOR TYPES "0", ZERO'S ARE USED FOR
|
||||
THE SWITCH SETTINGS.
|
||||
|
||||
IF THE OPERATOR TYPES "S", PREVIOUSLY SET SWITCHES
|
||||
ARE USED. THIS IS ONLY VALID UPON RESTARTING
|
||||
OF AN INTERRUPTED PROGRAM.
|
||||
|
||||
MAINDEC-10-DAKAM.TXT
|
||||
PAGE 5
|
||||
|
||||
3.3 OPERATING PROCEDURE
|
||||
|
||||
A. TO THROUGHLY TEST ALL HARDWARE, ALL TEST CONTROL DATA
|
||||
SWITCHES SHOULD BE SET TO 0.
|
||||
|
||||
B. WHEN DEBUGGING HARDWARE, SET SWITCHES TO 0. ALLOW THE
|
||||
TELETYPE TO PRINT THE ERROR MESSAGES. THIS ALLOWS THE
|
||||
PROGRAM TO RUN A COMPLETE PASS AND THEN THE ERROR MESSAGES
|
||||
MAY BE CORRELATED TO QUICKLY DIAGNOSE THE FAILURE. IF A
|
||||
HARDWARE PROBLEM IS SUCH THAT THE ERROR MESSAGES, AFTER THE
|
||||
FIRST ONE, HAVE NO MEANING (FIRST ERROR CAUSES ALL FOLLOWING
|
||||
TESTS TO FAIL) SET THE LOOP ON ERROR SWITCH AND RESTART THE
|
||||
TEST FROM THE BEGINNING. THE FIRST FAILURE WILL THEN CAUSE
|
||||
THE PROGRAM TO ENTER A LOOP SUITABLE FOR SCOPING.
|
||||
|
||||
THE ERROR MESSAGE USED IN CONJUNCTION WITH THE LISTING AND
|
||||
SCOPING IF NECESSARY SHOULD ALLOW THE FAILING CONPONENT
|
||||
TO BE ISOLATED AND REPLACED AND/OR REPAIRED.
|
||||
|
||||
C. WHEN TAKING MARGINS, SET DATA SWITCHES 'NOPNT' AND 'DING'.
|
||||
THIS WILL INHIBIT PRINTOUT BUT WILL ALLOW THE TELETYPE
|
||||
BELL TO BE RUNG WHEN A ERROR OCCURS. IF THE MARGIN OBTAINED
|
||||
IS UNACCEPTABLE, THE OPERATOR MAY REVERT TO STANDARD SWITCH
|
||||
SETTINGS FOR DEBUGGING PURPOSES.
|
||||
|
||||
D. ERROR INFORMATION MAY BE OBTAINED QUICKLY BY PRINTING
|
||||
ERRORS ON THE LINE PRINTER.
|
||||
|
||||
E. IN THE EVENT OF A PRINT ROUTINE FAILURE THE 'NOPNT' SWITCH
|
||||
AND THE 'ERSTOP' SWITCH MAY BE SET TO INHIBIT PRINTOUT
|
||||
BUT HALT THE PROGRAM POINTING TO THE ERROR.
|
||||
|
||||
MAINDEC-10-DAKAM.TXT
|
||||
PAGE 6
|
||||
|
||||
4.0 DATA SWITCH FUNCTIONS
|
||||
|
||||
SWITCH STATE FUNCTION
|
||||
------ ----- --------
|
||||
|
||||
0 ABORT 0 NORMAL OPERATION
|
||||
1 ABORT AT END OF PASS
|
||||
|
||||
1 RSTART NOT USED
|
||||
|
||||
2 TOTALS NOT USED
|
||||
|
||||
3 NOPNT 0 NORMAL TYPEOUT
|
||||
1 INHIBIT ALL PRINT/TYPEOUT
|
||||
(EXCEPT FORCED)
|
||||
|
||||
4 PNTLPT 0 NORMAL OUTPUT TO TTY
|
||||
1 PRINT ALL DATA ON LPT
|
||||
(LOGICAL DEVICE, USER MODE)
|
||||
|
||||
5 DING 0 NO FUNCTION
|
||||
1 RING TTY BELL ON ERROR
|
||||
|
||||
6 LOOPER 0 PROCEED TO NEXT TEST
|
||||
1 ENTER SCOPE LOOP ON TEST ERROR
|
||||
|
||||
7 ERSTOP 0 NO FUNCTION
|
||||
1 HALT ON TEST ERROR
|
||||
|
||||
8 PALERS 0 PRINT ONLY FIRST ERROR WHEN LOOPING
|
||||
1 PRINT ALL ERRORS, EVEN IF SAME ERROR
|
||||
|
||||
9 RELIAB NOT USED
|
||||
|
||||
10 TXTINH 0 PRINT FULL ERROR MESSAGES.
|
||||
1 INHIBIT COMMENT PORTION OF
|
||||
ERROR MESSAGES.
|
||||
|
||||
11 INHPAG 0 ALLOW PAGING AND TRAP ENABLE
|
||||
1 INHIBIT PAGING AND TRAPPING
|
||||
|
||||
12 MODDVC NOT USED
|
||||
|
||||
13 INHCSH NOT USED
|
||||
|
||||
MAINDEC-10-DAKAM.TXT
|
||||
PAGE 7
|
||||
|
||||
5.0 ERRORS
|
||||
|
||||
ERRORS ARE PRINTED ON THE TTY OR LINE PRINTER. THE ERROR
|
||||
PRINTOUT CONTAINS THE TEST TITLE, THE PC OF THE FAILURE, ERROR
|
||||
NUMBER AND THE CONTENTS OF AN APPLICABLE AC.
|
||||
|
||||
THE PC VALUE IS USEFUL IN RELATING THE FAILURE TO THE LISTING.
|
||||
THE ERROR NUMBER IS PROVIDED SUCH THAT AN ERROR DICTIONARY MAY
|
||||
BE MADE AT SOME FUTURE DATE.
|
||||
|
||||
WHEN THE SCOPE LOOP MODE IS USED THE MI REGISTER WILL COUNT
|
||||
FOR EACH OCCURANCE OF AN ERROR. IF AN AUDIO INDICATION OF
|
||||
A CONTINUING ERROR IS DESIRED THE 'DING' SWITCH MAY BE SET.
|
||||
|
||||
6.0 ITERATION COUNTER
|
||||
|
||||
THE ITERATION COUNT OF THE PROGRAM IS DISPLAYED IN THE MEMORY
|
||||
INDICATORS (MI). THIS COUNT IS A DECREMENTING COUNT AND
|
||||
INITIALLY STARTS AT -1 IN STAND-ALONE OPERATION.
|
||||
|
||||
7.0 CYCLE TIME
|
||||
|
||||
THE CYCLE TIME OF THE PROGRAM IS IN THE MILLISECOND RANGE AND
|
||||
IS THEREFORE SUITABLE FOR TAKING MARGINS, VIBRATION TESTS,
|
||||
ETC.
|
||||
|
||||
MAINDEC-10-DAKAM.TXT
|
||||
PAGE 8
|
||||
|
||||
8.0 OPERATIONAL VARIATIONS
|
||||
|
||||
A. DIAGNOSTIC MONITOR
|
||||
|
||||
THE PROGRAM IS USABLE WITH THE DIAGNOSTIC MONITOR TO PROVIDE
|
||||
RELIABILITY TESTS, ACCEPTANCE TESTS, AND/OR TO PROVIDE A
|
||||
QUICK METHOD OF ISOLATION OF A FAULT TO A PARTICULAR AREA
|
||||
OF THE PROCESSOR. CERTAIN PROCEDURES ARE USED WHEN THE
|
||||
PROGRAM IS USED IN THIS MANNER. THEY ARE:
|
||||
|
||||
1. THE DIAGNOSTIC MONITOR TRANSFERS CONTROL TO THE PROGRAM
|
||||
AND STARTS IT AT LOCATION 30002.
|
||||
|
||||
2. MONCTL - LOCATION 30043 IS USED AS THE DIAGNOSTIC MONITOR
|
||||
CONTROL WORD.
|
||||
LH = 0, STAND-ALONE OPERATION
|
||||
-1, RUNNING UNDER DIAGNOSTIC MONITOR
|
||||
|
||||
RH = RIGHT HALF OF CONSOLE SWITCHES IF UNDER
|
||||
DIAGNOSTIC MONITOR CONTROL.
|
||||
|
||||
B. USER MODE
|
||||
|
||||
TO OUTPUT THE PRINTED ERROR MESSAGES TO A USER SPECIFIED
|
||||
DEVICE IN USER MODE, ASSIGN THE DESIRED OUTPUT DEVICE TO
|
||||
DEVICE NAME 'DEV' AND SET SWITCH 'PNTLPT'. THE PHYSICAL
|
||||
DEVICE USED CAN BE ANY DEVICE THAT CAN ACCEPT ASCII OUTPUT
|
||||
FORMAT SUCH AS LPT, DSK, DTA, ETC. THE CORRESPONDING
|
||||
OUTPUT FILE IS 'DAKAM.TMP'
|
||||
|
||||
EXAMPLE DEVICE ASSIGNMENT:
|
||||
|
||||
.ASSIGN DSK DEV
|
||||
|
||||
IN USER MODE THE PROGRAM WILL MAKE 1000(8) PASSES AND THEN
|
||||
RETURN TO DIAMON COMMAND MODE.
|
||||
|
||||
MAINDEC-10-DAKAM.TXT
|
||||
PAGE 9
|
||||
|
||||
8.0 OPERATIONAL VARIATIONS (CON'T)
|
||||
|
||||
THE OUTPUT FILE (IF USED) MAY THEN BE LISTED BY USING THE
|
||||
NORMAL MONITOR COMMANDS (PRINT, LIST, TYPE, PIP, ETC.).
|
||||
|
||||
IF THE PROGRAM IS ABORTED BEFORE COMPLETION (BY ^C, ETC.) THE
|
||||
OUTPUT FILE MAY BE CLOSED BY USING THE MONITOR 'REENTER'
|
||||
COMMAND.
|
||||
|
||||
C. SYSTEM EXERCISER
|
||||
|
||||
START ADDRESS IS 30003. DATA SWITCHES ARE PRESTORED IN
|
||||
'SWTEXR' LOC 30023.
|
||||
|
||||
9.0 MISCELLANEOUS
|
||||
|
||||
THE NON-EX-MEMORY AND PARITY STOP SWITCHES SHOULD BE RESET
|
||||
(0). THESE ERRORS, ILLEGAL UUO'S AND OTHER ERRORS OF THIS
|
||||
TYPE ARE HANDLED BY PRINTOUT ON THE TELETYPE.
|
||||
|
||||
10.0 LISTING
|
||||
```
|
||||
|
||||
DAKAM.HST
|
||||
---------
|
||||
|
||||
THIS IS A HISTORY OF THE DEVELOPMENT OF MAINDEC-10-DAKAM
|
||||
|
||||
************************************************************************
|
||||
|
||||
PRODUCT CODE: MAINDEC-10-DAKAM
|
||||
|
||||
PRODUCT NAME: BASIC INSTRUCTION DIAGNOSTIC #13
|
||||
|
||||
DATE RELEASED: JANUARY 1977
|
||||
|
||||
VERSION: 0.2
|
||||
|
||||
UPDATE AUTHOR: JOHN R. KIRCHOFF
|
||||
|
||||
CHANGES MADE:
|
||||
|
||||
1. UPGRADE TO ALLOW COMPATABILITY WITH THE SUBROUTINE PACKAGE.
|
||||
|
||||
2. ADD TEST FOR BLT WITH EFFECTIVE ADDRESS LESS THAN CONTENTS OF
|
||||
AC RIGHT.
|
||||
|
||||
************************************************************************
|
||||
|
||||
ORIGINAL VERSION: 0.1
|
||||
|
||||
ORIGINAL AUTHOR: RICHARD MALISKA
|
||||
|
||||
ORIGINAL RELEASE: 16-MAR-72
|
||||
|
||||
************************************************************************
|
||||
|
||||
DAKAM.MAC
|
||||
---------
|
||||
|
||||
[[Download](DAKAM.MAC.txt)]
|
||||
|
||||
{% highlight text %}
|
||||
{% include_relative DAKAM.MAC.txt %}
|
||||
{% endhighlight %}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1652,28 +1652,20 @@ class DebuggerPDP10 extends Debugger {
|
|||
}
|
||||
|
||||
/**
|
||||
* parseInstruction(sOpcode, sOperands, addr, fQuiet, fPrelim)
|
||||
* parseInstruction(sOpcode, sOperands, addr, aUndefined)
|
||||
*
|
||||
* @this {DebuggerPDP10}
|
||||
* @param {string} sOpcode
|
||||
* @param {string} [sOperands]
|
||||
* @param {number} [addr] of memory where this instruction is being assembled
|
||||
* @param {boolean} [fQuiet]
|
||||
* @param {boolean} [fPrelim] (true if this is a preliminary call and error messages should be suppressed)
|
||||
* @param {Array} [aUndefined]
|
||||
* @return {number} (opcode, or -1 if unrecognized instruction)
|
||||
*/
|
||||
parseInstruction(sOpcode, sOperands, addr, fQuiet, fPrelim)
|
||||
parseInstruction(sOpcode, sOperands, addr, aUndefined)
|
||||
{
|
||||
var opCode = -1;
|
||||
var opMask, opNum;
|
||||
|
||||
/*
|
||||
* It's best to always clear sUndefined up front, because the caller won't
|
||||
* necessarily know whether or not we had to call parseExpression() for this
|
||||
* instruction.
|
||||
*/
|
||||
this.sUndefined = null;
|
||||
|
||||
if (!sOpcode) {
|
||||
/*
|
||||
* MACRO-10 also allows instructions to be assembled without an opcode (ie, just an address expression),
|
||||
|
|
@ -1753,21 +1745,22 @@ class DebuggerPDP10 extends Debugger {
|
|||
|
||||
if (opCode >= 0) {
|
||||
if (sOperands) {
|
||||
|
||||
var aOperands = sOperands.split(',');
|
||||
if (aOperands.length > 2) {
|
||||
if (!aUndefined) this.println("too many operands: " + sOperands);
|
||||
aOperands.length = 0;
|
||||
opCode = -1;
|
||||
}
|
||||
|
||||
for (var i = 0; i < aOperands.length; i++) {
|
||||
|
||||
var sOperand = aOperands[i].trim();
|
||||
if (!sOperand) continue;
|
||||
|
||||
if (i > 1) {
|
||||
this.println("too many operands: " + sOperands);
|
||||
opCode = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
var match = sOperand.match(/(@?)([^(]*)\(?([^)]*)\)?/);
|
||||
if (!match) {
|
||||
this.println("unknown operand: " + sOperand);
|
||||
if (!aUndefined) this.println("unknown operand: " + sOperand);
|
||||
opCode = -1;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1782,7 +1775,7 @@ class DebuggerPDP10 extends Debugger {
|
|||
|
||||
sOperand = match[3];
|
||||
if (sOperand) {
|
||||
operand = this.parseExpression(sOperand, fQuiet);
|
||||
operand = this.parseExpression(sOperand, aUndefined);
|
||||
if (operand == undefined) {
|
||||
opCode = -1;
|
||||
break;
|
||||
|
|
@ -1806,7 +1799,7 @@ class DebuggerPDP10 extends Debugger {
|
|||
}
|
||||
}
|
||||
|
||||
var operand = this.parseExpression(sOperand, fQuiet);
|
||||
var operand = this.parseExpression(sOperand, aUndefined);
|
||||
if (operand == undefined) {
|
||||
opCode = -1;
|
||||
break;
|
||||
|
|
@ -1860,7 +1853,7 @@ class DebuggerPDP10 extends Debugger {
|
|||
// }
|
||||
}
|
||||
|
||||
if (opCode < 0 && !fPrelim) {
|
||||
if (opCode < 0 && !aUndefined) {
|
||||
this.println("unknown instruction: " + sOpcode + ' ' + sOperands);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,8 +39,6 @@ if (NODE) {
|
|||
/**
|
||||
* Elements of tblMacros.
|
||||
*
|
||||
* NOTE: The nLine property is not required; it's added for improved error reporting.
|
||||
*
|
||||
* @typedef {{
|
||||
* name:(string),
|
||||
* nOperand:(number),
|
||||
|
|
@ -56,8 +54,6 @@ var Mac;
|
|||
/**
|
||||
* Elements of tblSymbols.
|
||||
*
|
||||
* NOTE: The nLine property is not required; it's added for improved error reporting.
|
||||
*
|
||||
* @typedef {{
|
||||
* name:(string),
|
||||
* value:(number),
|
||||
|
|
@ -127,6 +123,7 @@ class Macro10 {
|
|||
*
|
||||
* Supported options include:
|
||||
*
|
||||
* 'd': leave all symbols in the debugger's variable table
|
||||
* 'p': print the preprocessed resource(s) without assembling them
|
||||
* 'l': print lines as they are parsed
|
||||
*
|
||||
|
|
@ -203,7 +200,7 @@ class Macro10 {
|
|||
this.aWords = []; // filled in by the various genXXX() functions
|
||||
|
||||
/**
|
||||
* This sparse array is indexed by location, and each used entry contains an undefined symbol that
|
||||
* This sparse array is indexed by location, and each used entry contains any undefined symbols that
|
||||
* must be evaluated to fully resolve the word at the corresponding location. NOTE: There's no requirement
|
||||
* that the array be sparse; we could certainly fill each unused entry with null (ie, for locations that
|
||||
* don't require a fixup).
|
||||
|
|
@ -212,6 +209,13 @@ class Macro10 {
|
|||
*/
|
||||
this.aFixups = [];
|
||||
|
||||
/**
|
||||
* This array parallels aFixups, providing context (ie, line numbers) for any fixups that we want to analyze.
|
||||
*
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this.aLineRefs = [];
|
||||
|
||||
this.nLine = 0;
|
||||
this.nError = 0;
|
||||
this.nLiteral = 0; // used to uniquely number literals
|
||||
|
|
@ -396,6 +400,13 @@ class Macro10 {
|
|||
}
|
||||
|
||||
var a = this.dbg.resetVariables();
|
||||
|
||||
/*
|
||||
* Add predefined device codes
|
||||
*/
|
||||
this.addSymbol("APR", 0); // Priority Interrupt
|
||||
this.addSymbol("PI", 4); // Arithmetic Processor
|
||||
|
||||
try {
|
||||
for (let i = 0; i < this.asLines.length; i += 2) {
|
||||
|
||||
|
|
@ -434,104 +445,19 @@ class Macro10 {
|
|||
/*
|
||||
* Process all literals next.
|
||||
*/
|
||||
let nLocationLiterals = this.nLocation;
|
||||
|
||||
for (let i = 0; i < this.aLiterals.length; i++) {
|
||||
/*
|
||||
* Apparently, the time has come to implement "literal collapsing"; I was treating it as just
|
||||
* a nice optimization, but it turns out that DEC has written tests that actually DEPEND on it:
|
||||
*
|
||||
* C26300: HRRZI [135531,,246642] ;PRELOAD AC0 WITH 0,, LITERAL ADDRESS
|
||||
* JRA .+1 ;*JRA SHOULD PLACE C(AC0) INTO AC0
|
||||
* CAIE [135531,,246642] ;PASS IF JRA PLACED C(AC0) INTO AC0
|
||||
* STOP
|
||||
*
|
||||
* If the HRRZI and CAIE instructions don't refer to the same exact literal, the test will fail.
|
||||
* For purposes of this particular test, the values they stuffed into the literals are essentially
|
||||
* gibberish, but the same literal may be used in another test where the values are significant.
|
||||
*
|
||||
* However, I'm still going to keep it simple. In this example from p. 2-8 of the April 1978
|
||||
* MACRO-10 manual, I will NOT be attempting to collapse null words at the end of ASCIZ sequences
|
||||
* with other null words, especially if they were defined before the ASCIZ:
|
||||
*
|
||||
* Literals having the same value are collapsed in MACRO's literal pool.
|
||||
* Thus for the statements:
|
||||
*
|
||||
* PUSH P,[0]
|
||||
* PUSH P,[0]
|
||||
* MOVEI 1,[ASCIZ /TEST1/]
|
||||
*
|
||||
* the same address is shared by the two literals [0], and by the null word
|
||||
* generated at the end of [ASCIZ /TEST1/].
|
||||
*/
|
||||
let lit = this.aLiterals[i];
|
||||
/*
|
||||
* First things first: verify that the literal is one contiguous zero-based set of words (I'm not sure
|
||||
* how it couldn't be, but better safe than sorry).
|
||||
*/
|
||||
let aWords = [];
|
||||
let nWords = 0;
|
||||
lit.aWords.forEach(function(w, nLocation) {
|
||||
if (nLocation === aWords.length) aWords.push(w);
|
||||
nWords++;
|
||||
});
|
||||
if (nWords == aWords.length) {
|
||||
/*
|
||||
* So far, so good. Now we'll simply brute-force-search our way through the existing set of
|
||||
* literals, looking for a complete match.
|
||||
*/
|
||||
for (let nLocation = nLocationLiterals; nLocation + nWords <= this.nLocation; nLocation++) {
|
||||
let n;
|
||||
for (n = 0; n < nWords; n++) {
|
||||
/*
|
||||
* This check requires that the initial values of the words in the literals match AND that
|
||||
* their fixup expressions, if any, match as well. Here again, MACRO-10 may be more aggressive
|
||||
* in either verifying fixup equality or evaluating any fixups that it can immediately, but
|
||||
* but I prefer to leave all fixup evaluation where it is (below), after all literals and then
|
||||
* all variables have been added to the output.
|
||||
*/
|
||||
if (aWords[n] !== this.aWords[nLocation + n] || lit.aFixups[n] != this.aFixups[nLocation]) break;
|
||||
}
|
||||
if (n == nWords) {
|
||||
this.addSymbol(lit.name, nLocation, Macro10.SYMTYPE.LABEL);
|
||||
lit = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lit) {
|
||||
this.addSymbol(lit.name, this.nLocation, Macro10.SYMTYPE.LABEL);
|
||||
lit.aWords.forEach(function(w, nLocation) {
|
||||
macro10.genWord(w, lit.aFixups[nLocation]);
|
||||
});
|
||||
}
|
||||
}
|
||||
this.doLiterals();
|
||||
|
||||
/*
|
||||
* Now add all variable definitions.
|
||||
* Process all variables next.
|
||||
*/
|
||||
for (let i = 0; i < this.aVariables.length; i++) {
|
||||
let name = this.aVariables[i];
|
||||
let macro = this.tblMacros[name];
|
||||
if (!macro) {
|
||||
/*
|
||||
* This is more of an assert(), because it should never happen, regardless of input.
|
||||
*/
|
||||
this.error("missing definition for variable '" + name + "'");
|
||||
continue;
|
||||
}
|
||||
this.parseText(macro.sText);
|
||||
}
|
||||
this.doVariables();
|
||||
|
||||
/*
|
||||
* And last but not least, perform all fixups.
|
||||
*/
|
||||
this.aFixups.forEach(function processFixup(sValue, nLocation) {
|
||||
let value = macro10.parseExpression(sValue, false, nLocation);
|
||||
if (value === undefined) {
|
||||
macro10.error("unable to parse expression '" + sValue + "'");
|
||||
return;
|
||||
}
|
||||
let value = macro10.parseExpression(sValue, undefined, nLocation, macro10.aLineRefs[nLocation]);
|
||||
if (value === undefined) return;
|
||||
value += macro10.aWords[nLocation];
|
||||
macro10.aWords[nLocation] = macro10.truncate(value, nLocation);
|
||||
});
|
||||
|
|
@ -540,7 +466,9 @@ class Macro10 {
|
|||
this.println(err.message);
|
||||
this.nError = -1;
|
||||
}
|
||||
this.dbg.restoreVariables(a);
|
||||
|
||||
if (this.sOptions.indexOf('d') < 0) this.dbg.restoreVariables(a);
|
||||
|
||||
return this.nError;
|
||||
}
|
||||
|
||||
|
|
@ -556,22 +484,7 @@ class Macro10 {
|
|||
*/
|
||||
parseLine(sLine, aParms, aValues, aDefaults)
|
||||
{
|
||||
var i;
|
||||
if (this.nMacroDef) {
|
||||
if (this.nMacroDef == 1) {
|
||||
i = sLine.indexOf(this.chMacroOpen);
|
||||
if (i >= 0) {
|
||||
this.nMacroDef++;
|
||||
sLine = sLine.substr(i+1);
|
||||
} else {
|
||||
this.error("expected " + this.sOperator + " definition in '" + sLine + "'");
|
||||
}
|
||||
}
|
||||
if (this.nMacroDef > 1) {
|
||||
sLine = this.appendMacro(sLine);
|
||||
}
|
||||
if (this.nMacroDef) return true;
|
||||
}
|
||||
var i, matchLine;
|
||||
|
||||
if (this.chASCII != null) {
|
||||
sLine = this.defASCII(sLine);
|
||||
|
|
@ -581,7 +494,7 @@ class Macro10 {
|
|||
var sLabel, sOperator = "", sSeparator, sOperands, sRemainder;
|
||||
|
||||
while (fParse) {
|
||||
var matchLine = sLine.match(this.reLine);
|
||||
matchLine = sLine.match(this.reLine);
|
||||
if (!matchLine || matchLine[5] && matchLine[5].slice(0, 1) != ';') {
|
||||
this.error("failed to parse line '" + sLine + "'");
|
||||
return false;
|
||||
|
|
@ -617,6 +530,22 @@ class Macro10 {
|
|||
}
|
||||
aParms = null;
|
||||
}
|
||||
if (this.nMacroDef) {
|
||||
if (this.nMacroDef == 1) {
|
||||
i = sLine.indexOf(this.chMacroOpen);
|
||||
if (i >= 0) {
|
||||
this.nMacroDef++;
|
||||
sLine = sLine.substr(i+1);
|
||||
} else {
|
||||
this.error("expected " + this.sOperator + " definition in '" + sLine + "'");
|
||||
}
|
||||
}
|
||||
if (this.nMacroDef > 1) {
|
||||
sLine = this.appendMacro(sLine);
|
||||
fParse = true;
|
||||
}
|
||||
if (this.nMacroDef) return true;
|
||||
}
|
||||
}
|
||||
|
||||
sLabel = matchLine[1];
|
||||
|
|
@ -681,6 +610,10 @@ class Macro10 {
|
|||
this.defBLOCK(sOperands);
|
||||
break;
|
||||
|
||||
case Macro10.PSEUDO_OP.BYTE:
|
||||
this.defBYTE(sOperands);
|
||||
break;
|
||||
|
||||
case Macro10.PSEUDO_OP.END:
|
||||
this.defEND(sOperands);
|
||||
break;
|
||||
|
|
@ -689,19 +622,32 @@ class Macro10 {
|
|||
this.defEXP(sOperands);
|
||||
break;
|
||||
|
||||
case Macro10.PSEUDO_OP.LIT:
|
||||
this.doLiterals();
|
||||
break;
|
||||
|
||||
case Macro10.PSEUDO_OP.LOC:
|
||||
this.defLocation(sOperands);
|
||||
break;
|
||||
|
||||
case Macro10.PSEUDO_OP.VAR:
|
||||
this.doVariables();
|
||||
break;
|
||||
|
||||
case Macro10.PSEUDO_OP.XWD:
|
||||
this.defXWD(sOperands);
|
||||
break;
|
||||
|
||||
case Macro10.PSEUDO_OP.DEFINE:
|
||||
case Macro10.PSEUDO_OP.IF1:
|
||||
case Macro10.PSEUDO_OP.IFDEF:
|
||||
case Macro10.PSEUDO_OP.IFDIF:
|
||||
case Macro10.PSEUDO_OP.IFE:
|
||||
case Macro10.PSEUDO_OP.IFG:
|
||||
case Macro10.PSEUDO_OP.IFGE:
|
||||
case Macro10.PSEUDO_OP.IFIDN:
|
||||
case Macro10.PSEUDO_OP.IFL:
|
||||
case Macro10.PSEUDO_OP.IFLE:
|
||||
case Macro10.PSEUDO_OP.IFN:
|
||||
case Macro10.PSEUDO_OP.IFNDEF:
|
||||
case Macro10.PSEUDO_OP.IRP:
|
||||
|
|
@ -711,6 +657,10 @@ class Macro10 {
|
|||
this.defMacro(sOperator, sRemainder);
|
||||
break;
|
||||
|
||||
case Macro10.PSEUDO_OP.PURGE:
|
||||
this.delSymbols(sOperands);
|
||||
break;
|
||||
|
||||
case Macro10.PSEUDO_OP.LALL: // TODO
|
||||
case Macro10.PSEUDO_OP.LIST: // TODO
|
||||
case Macro10.PSEUDO_OP.NOSYM: // TODO
|
||||
|
|
@ -731,8 +681,7 @@ class Macro10 {
|
|||
/**
|
||||
* parseLiteral(name, sText)
|
||||
*
|
||||
* This is like parseText() except that we first set up a new scope, which includes new aWords and aFixups
|
||||
* arrays.
|
||||
* This is like parseText() except that we set up a new scope, including new aWords and aFixups arrays.
|
||||
*
|
||||
* @this {Macro10}
|
||||
* @param {string} name
|
||||
|
|
@ -836,6 +785,7 @@ class Macro10 {
|
|||
|
||||
switch(sOperator) {
|
||||
case Macro10.PSEUDO_OP.IFE:
|
||||
case Macro10.PSEUDO_OP.IFDIF:
|
||||
case Macro10.PSEUDO_OP.IFNDEF:
|
||||
if (!macro.nOperand) {
|
||||
this.parseText(macro.sText);
|
||||
|
|
@ -848,14 +798,28 @@ class Macro10 {
|
|||
}
|
||||
break;
|
||||
|
||||
case Macro10.PSEUDO_OP.IFGE:
|
||||
if (macro.nOperand >= 0) {
|
||||
this.parseText(macro.sText);
|
||||
}
|
||||
break;
|
||||
|
||||
case Macro10.PSEUDO_OP.IFL:
|
||||
if (macro.nOperand < 0) {
|
||||
this.parseText(macro.sText);
|
||||
}
|
||||
break;
|
||||
|
||||
case Macro10.PSEUDO_OP.IFLE:
|
||||
if (macro.nOperand <= 0) {
|
||||
this.parseText(macro.sText);
|
||||
}
|
||||
break;
|
||||
|
||||
case Macro10.PSEUDO_OP.IF1:
|
||||
case Macro10.PSEUDO_OP.IFN:
|
||||
case Macro10.PSEUDO_OP.IFDEF:
|
||||
case Macro10.PSEUDO_OP.IFIDN:
|
||||
if (macro.nOperand) {
|
||||
this.parseText(macro.sText);
|
||||
}
|
||||
|
|
@ -955,6 +919,9 @@ class Macro10 {
|
|||
/**
|
||||
* getExpression(sOperands, sDelim)
|
||||
*
|
||||
* TODO: Add support for IFIDN, IFDIF, IFB and IFNB: if the first non-blank, non-tab character is
|
||||
* a character other than '<', then that becomes the delimiter, allowing angle brackets in the string.
|
||||
*
|
||||
* @this {Macro10}
|
||||
* @param {string} sOperands
|
||||
* @param {string} [sDelim] (eg, comma, closing parenthesis)
|
||||
|
|
@ -996,7 +963,7 @@ class Macro10 {
|
|||
}
|
||||
|
||||
/**
|
||||
* parseExpression(sExp, fPass1, nLocation)
|
||||
* parseExpression(sExp, aUndefined, nLocation, nLine)
|
||||
*
|
||||
* This is a wrapper around the Debugger's parseExpression() function to take care of some
|
||||
* additional requirements we have, such as interpreting a period as the current location and
|
||||
|
|
@ -1005,19 +972,15 @@ class Macro10 {
|
|||
*
|
||||
* @this {Macro10}
|
||||
* @param {string} sExp
|
||||
* @param {boolean|undefined} [fPass1]
|
||||
* @param {Array} [aUndefined]
|
||||
* @param {number|undefined} [nLocation]
|
||||
* @param {number|undefined} [nLine]
|
||||
* @return {number|undefined}
|
||||
*/
|
||||
parseExpression(sExp, fPass1, nLocation)
|
||||
parseExpression(sExp, aUndefined, nLocation, nLine)
|
||||
{
|
||||
var result;
|
||||
/*
|
||||
* Check for the "double comma" syntax that MACRO-10 uses to express a 36-bit value as two 18-bit halves,
|
||||
* and invoke ourselves recursively for each half.
|
||||
*/
|
||||
var match = sExp.match(/^([^,]*),,([^,]*)$/);
|
||||
if (!match) {
|
||||
var result = -1;
|
||||
|
||||
if (nLocation === undefined) {
|
||||
nLocation = (this.nLocationScope >= 0? this.nLocationScope : this.nLocation);
|
||||
}
|
||||
|
|
@ -1027,22 +990,22 @@ class Macro10 {
|
|||
* (or at least assignments), so we check for those in the given expression and convert them to quoted
|
||||
* sequences that the Debugger's parseExpression() understands.
|
||||
*/
|
||||
sExp = sExp.replace(/SIXBIT\s*(\S)(.*?)\1/g, "'$2'").replace(/ASCII\s*(\S)(.*?)\1/g, '"$2"');
|
||||
var sEval = sExp.replace(/SIXBIT\s*(\S)(.*?)\1/g, "'$2'").replace(/ASCII\s*(\S)(.*?)\1/g, '"$2"');
|
||||
|
||||
/*
|
||||
* If this is NOT a first-pass call, then let's not waste time calling parseInstruction(); not only
|
||||
* may it generate redundant error messages, but it shouldn't be necessary, because we should be down
|
||||
* to fixup expressions.
|
||||
*/
|
||||
result = -1;
|
||||
if (fPass1 !== false) {
|
||||
if (aUndefined) {
|
||||
var match;
|
||||
var sOperator = "";
|
||||
var sOperands = sExp;
|
||||
if (match = sExp.match(/^([^\s]+)\s*(.*?)\s*$/)) {
|
||||
var sOperands = sEval;
|
||||
if (match = sEval.match(/^([^\s]+)\s*(.*?)\s*$/)) {
|
||||
sOperator = match[1];
|
||||
sOperands = match[2];
|
||||
}
|
||||
result = this.dbg.parseInstruction(sOperator, sOperands, nLocation, fPass1, true);
|
||||
result = this.dbg.parseInstruction(sOperator, sOperands, nLocation, aUndefined);
|
||||
}
|
||||
|
||||
if (result < 0) {
|
||||
|
|
@ -1054,25 +1017,13 @@ class Macro10 {
|
|||
* Note that the Debugger's parseInstruction() replaces any period not PRECEDED by a decimal
|
||||
* digit with the current address, because our Debuggers' only other interpretation of a period
|
||||
* is as the suffix of a decimal integer, whereas MACRO-10's only other interpretation of a period
|
||||
* is (I think) as the decimal point within a floating-point number, so here we only replace
|
||||
* periods that are not FOLLOWED by a decimal digit.
|
||||
* is (I think) as the decimal point within a floating-point number, so here we only replace periods
|
||||
* that are not FOLLOWED by a decimal digit.
|
||||
*/
|
||||
if (fPass1 === false) fPass1 = undefined;
|
||||
result = this.dbg.parseExpression(sExp.replace(/\.([^0-9]|$)/g, this.dbg.toStrBase(nLocation, -1) + "$1"), fPass1);
|
||||
sEval = sEval.replace(/\.([^0-9]|$)/g, this.dbg.toStrBase(nLocation, -1) + "$1");
|
||||
result = this.dbg.parseExpression(sEval, aUndefined);
|
||||
if (result === undefined) {
|
||||
this.error("unable to parse expression '" + sExp + "'");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var wLeft = match[1]? this.parseExpression(match[1], fPass1, nLocation) : 0;
|
||||
if (wLeft !== undefined) {
|
||||
var wRight = match[2]? this.parseExpression(match[2], fPass1, nLocation) : 0;
|
||||
if (wRight !== undefined) {
|
||||
/*
|
||||
* NOTE: These must be combined as UNSIGNED values, so that's what we tell truncate() to produce.
|
||||
*/
|
||||
result = this.dbg.truncate(wLeft, 18, true) * Math.pow(2, 18) + this.dbg.truncate(wRight, 18, true);
|
||||
}
|
||||
this.error("unable to parse expression '" + sExp + "'", nLine);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
@ -1487,6 +1438,11 @@ class Macro10 {
|
|||
/*
|
||||
* This must be a REPEAT or CONDITIONAL block.
|
||||
*/
|
||||
if (sOperator == Macro10.PSEUDO_OP.IF1) {
|
||||
nOperand = 1;
|
||||
if (sOperands[0] == ',') sOperands = sOperands.substr(1).trim();
|
||||
}
|
||||
else {
|
||||
var sOperand = this.getExpression(sOperands);
|
||||
if (!sOperand) {
|
||||
this.error("missing " + sOperator + " expression '" + sOperands + "'");
|
||||
|
|
@ -1494,9 +1450,16 @@ class Macro10 {
|
|||
}
|
||||
sOperands = sOperands.substr(sOperand.length + 1);
|
||||
sOperand = sOperand.trim();
|
||||
match = sOperands.match(/\s*(<|)([\s\S]*)/i);
|
||||
name = '?' + sOperator;
|
||||
|
||||
if (sOperator == Macro10.PSEUDO_OP.IFDIF || sOperator == Macro10.PSEUDO_OP.IFIDN) {
|
||||
var sOperand2 = this.getExpression(sOperands);
|
||||
if (!sOperand2) {
|
||||
this.error("missing second " + sOperator + " expression '" + sOperands + "'");
|
||||
return sOperands;
|
||||
}
|
||||
sOperands = sOperands.substr(sOperand2.length + 1);
|
||||
sOperand2 = sOperand2.trim();
|
||||
nOperand = (sOperand == sOperand2)? 1 : 0;
|
||||
}
|
||||
if (sOperator == Macro10.PSEUDO_OP.IFDEF || sOperator == Macro10.PSEUDO_OP.IFNDEF) {
|
||||
nOperand = this.isDefined(sOperand)? 1 : 0;
|
||||
} else {
|
||||
|
|
@ -1506,6 +1469,9 @@ class Macro10 {
|
|||
*/
|
||||
nOperand = this.parseExpression(sOperand) || 0;
|
||||
}
|
||||
}
|
||||
match = sOperands.match(/\s*(<|)([\s\S]*)/i);
|
||||
name = '?' + sOperator;
|
||||
iMatch = 1;
|
||||
}
|
||||
|
||||
|
|
@ -1574,19 +1540,16 @@ class Macro10 {
|
|||
this.error("label '" + name + "' redefined");
|
||||
return;
|
||||
}
|
||||
var sUndefined = null;
|
||||
var sUndefined = undefined;
|
||||
if (typeof value == 'string') {
|
||||
/*
|
||||
* We now pass true to parseExpression() to allow at least one undefined symbol to exist in the expression,
|
||||
* which we will record alongside the variable.
|
||||
*/
|
||||
var v = this.parseExpression(value, true);
|
||||
var aUndefined = [];
|
||||
var v = this.parseExpression(value, aUndefined);
|
||||
if (v === undefined) {
|
||||
this.error("parseExpression(" + value + ") failed");
|
||||
this.error("symbol error (" + value + ")");
|
||||
return;
|
||||
}
|
||||
value = v;
|
||||
sUndefined = this.dbg.sUndefined;
|
||||
sUndefined = aUndefined[0];
|
||||
}
|
||||
var sym = this.tblSymbols[name];
|
||||
if (sym) {
|
||||
|
|
@ -1610,13 +1573,61 @@ class Macro10 {
|
|||
defBLOCK(sOperands)
|
||||
{
|
||||
var w = this.parseExpression(sOperands);
|
||||
if (w !== undefined && this.dbg.sUndefined == null && w >= 0 && w <= 0o777777) {
|
||||
if (w !== undefined && w >= 0 && w <= 0o777777) {
|
||||
this.nLocation += w; // while (w--) this.genWord(0);
|
||||
} else {
|
||||
this.error("unrecognized BLOCK expression '" + sOperands + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* defBYTE()
|
||||
*
|
||||
* Processes the BYTE pseudo-op.
|
||||
*
|
||||
* @this {Macro10}
|
||||
* @param {string} sOperands
|
||||
*/
|
||||
defBYTE(sOperands)
|
||||
{
|
||||
var sOperand;
|
||||
var nBits = 0, nValue = 0, nBitsRemaining = 36;
|
||||
|
||||
while (sOperand = this.getExpression(sOperands)) {
|
||||
sOperands = sOperands.substr(sOperand.length).trim();
|
||||
var sValue = sOperand;
|
||||
var match = sOperand.match(/^\((.*)\)\s*(.*)$/);
|
||||
if (match) {
|
||||
if (match[1]) nBits = this.parseExpression("^D" + match[1]);
|
||||
sValue = match[2];
|
||||
}
|
||||
if (!nBits) {
|
||||
/*
|
||||
* According the the 1978 MACRO-10 spec, "If the byte size is 0 or is missing (empty parentheses), a zero word
|
||||
* is generated." I'm not clear exactly on how to interpret this, so I'll make a simplistic assumption for now.
|
||||
*/
|
||||
this.genWord(0);
|
||||
continue;
|
||||
}
|
||||
var v = sValue? this.parseExpression(sValue) : 0;
|
||||
if (v === undefined || nBits < 0 || nBits > 36) {
|
||||
this.error("unexpected BYTE operand: " + sOperand);
|
||||
break;
|
||||
}
|
||||
v = this.dbg.truncate(v, nBits, true);
|
||||
if (nBitsRemaining < nBits) {
|
||||
this.genWord(nValue);
|
||||
nValue = 0;
|
||||
nBitsRemaining = 36;
|
||||
}
|
||||
nValue += v * Math.pow(2, nBitsRemaining - nBits);
|
||||
nBitsRemaining -= nBits;
|
||||
}
|
||||
if (nBitsRemaining < 36) {
|
||||
this.genWord(nValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* defEND()
|
||||
*
|
||||
|
|
@ -1630,7 +1641,7 @@ class Macro10 {
|
|||
if (!sOperands) {
|
||||
this.addrStart = this.addrLoad;
|
||||
} else {
|
||||
this.addrStart = this.parseExpression(sOperands, true);
|
||||
this.addrStart = this.parseExpression(sOperands);
|
||||
if (this.addrStart === undefined) {
|
||||
this.error("unrecognized END expression '" + sOperands + "'");
|
||||
}
|
||||
|
|
@ -1647,9 +1658,10 @@ class Macro10 {
|
|||
*/
|
||||
defEXP(sOperands)
|
||||
{
|
||||
var w = this.parseExpression(sOperands, true);
|
||||
var aUndefined = [];
|
||||
var w = this.parseExpression(sOperands, aUndefined);
|
||||
if (w !== undefined) {
|
||||
this.genWord(w, this.dbg.sUndefined);
|
||||
this.genWord(w, aUndefined[0]);
|
||||
} else {
|
||||
this.error("unrecognized EXP expression '" + sOperands + "'");
|
||||
}
|
||||
|
|
@ -1694,17 +1706,136 @@ class Macro10 {
|
|||
*/
|
||||
defWord(sOperator, sSeparator, sOperands)
|
||||
{
|
||||
var aUndefined = [];
|
||||
var sExp = (sOperator + sSeparator + sOperands).trim();
|
||||
|
||||
var w = this.parseExpression(sExp, true);
|
||||
|
||||
var w = this.parseExpression(sExp, aUndefined);
|
||||
if (w !== undefined) {
|
||||
this.genWord(w, this.dbg.sUndefined);
|
||||
this.genWord(w, aUndefined[0]);
|
||||
} else {
|
||||
this.error("unrecognized word expression '" + sExp + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* delSymbols(sOperands)
|
||||
*
|
||||
* @this {Macro10}
|
||||
* @param {string} sOperands
|
||||
*/
|
||||
delSymbols(sOperands)
|
||||
{
|
||||
var aValues = this.getValues(sOperands);
|
||||
for (var i = 0; i < aValues.length; i++) {
|
||||
this.dbg.delVariable(aValues[i]);
|
||||
delete this.tblSymbols[aValues[i]];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* doLiterals()
|
||||
*
|
||||
* @this {Macro10}
|
||||
*/
|
||||
doLiterals()
|
||||
{
|
||||
let nLocationLiterals = this.nLocation;
|
||||
|
||||
for (let i = 0; i < this.aLiterals.length; i++) {
|
||||
/*
|
||||
* Apparently, the time has come to implement "literal collapsing"; I was treating it as just
|
||||
* a nice optimization, but it turns out that DEC has written tests that actually DEPEND on it:
|
||||
*
|
||||
* C26300: HRRZI [135531,,246642] ;PRELOAD AC0 WITH 0,, LITERAL ADDRESS
|
||||
* JRA .+1 ;*JRA SHOULD PLACE C(AC0) INTO AC0
|
||||
* CAIE [135531,,246642] ;PASS IF JRA PLACED C(AC0) INTO AC0
|
||||
* STOP
|
||||
*
|
||||
* If the HRRZI and CAIE instructions don't refer to the same exact literal, the test will fail.
|
||||
* For purposes of this particular test, the values they stuffed into the literals are essentially
|
||||
* gibberish, but the same literal may be used in another test where the values are significant.
|
||||
*
|
||||
* However, I'm still going to keep it simple. In this example from p. 2-8 of the April 1978
|
||||
* MACRO-10 manual, I will NOT be attempting to collapse null words at the end of ASCIZ sequences
|
||||
* with other null words, especially if they were defined before the ASCIZ:
|
||||
*
|
||||
* Literals having the same value are collapsed in MACRO's literal pool.
|
||||
* Thus for the statements:
|
||||
*
|
||||
* PUSH P,[0]
|
||||
* PUSH P,[0]
|
||||
* MOVEI 1,[ASCIZ /TEST1/]
|
||||
*
|
||||
* the same address is shared by the two literals [0], and by the null word
|
||||
* generated at the end of [ASCIZ /TEST1/].
|
||||
*/
|
||||
let lit = this.aLiterals[i];
|
||||
/*
|
||||
* First things first: verify that the literal is one contiguous zero-based set of words (I'm not sure
|
||||
* how it couldn't be, but better safe than sorry).
|
||||
*/
|
||||
let aWords = [];
|
||||
let nWords = 0;
|
||||
lit.aWords.forEach(function(w, nLocation) {
|
||||
if (nLocation === aWords.length) aWords.push(w);
|
||||
nWords++;
|
||||
});
|
||||
if (nWords == aWords.length) {
|
||||
/*
|
||||
* So far, so good. Now we'll simply brute-force-search our way through the existing set of
|
||||
* literals, looking for a complete match.
|
||||
*/
|
||||
for (let nLocation = nLocationLiterals; nLocation + nWords <= this.nLocation; nLocation++) {
|
||||
let n;
|
||||
for (n = 0; n < nWords; n++) {
|
||||
/*
|
||||
* This check requires that the initial values of the words in the literals match AND that
|
||||
* their fixup expressions, if any, match as well. Here again, MACRO-10 may be more aggressive
|
||||
* in either verifying fixup equality or evaluating any fixups that it can immediately, but
|
||||
* but I prefer to leave all fixup evaluation where it is (below), after all literals and then
|
||||
* all variables have been added to the output.
|
||||
*/
|
||||
if (aWords[n] !== this.aWords[nLocation + n] || lit.aFixups[n] != this.aFixups[nLocation]) break;
|
||||
}
|
||||
if (n == nWords) {
|
||||
this.addSymbol(lit.name, nLocation, Macro10.SYMTYPE.LABEL);
|
||||
lit = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lit) {
|
||||
var macro10 = this;
|
||||
this.addSymbol(lit.name, this.nLocation, Macro10.SYMTYPE.LABEL);
|
||||
lit.aWords.forEach(function(w, nLocation) {
|
||||
macro10.genWord(w, lit.aFixups[nLocation]);
|
||||
});
|
||||
}
|
||||
}
|
||||
this.aLiterals = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* doVariables()
|
||||
*
|
||||
* @this {Macro10}
|
||||
*/
|
||||
doVariables()
|
||||
{
|
||||
for (let i = 0; i < this.aVariables.length; i++) {
|
||||
let name = this.aVariables[i];
|
||||
let macro = this.tblMacros[name];
|
||||
if (!macro) {
|
||||
/*
|
||||
* This is more of an assert(), because it should never happen, regardless of input.
|
||||
*/
|
||||
this.error("missing definition for variable '" + name + "'");
|
||||
continue;
|
||||
}
|
||||
this.parseText(macro.sText);
|
||||
}
|
||||
this.aVariables = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* genASCII()
|
||||
*
|
||||
|
|
@ -1751,16 +1882,17 @@ class Macro10 {
|
|||
}
|
||||
|
||||
/**
|
||||
* genWord(value, sFixup)
|
||||
* genWord(value, sUndefined)
|
||||
*
|
||||
* @this {Macro10}
|
||||
* @param {number} value (default value for the current location)
|
||||
* @param {string|null|undefined} [sFixup] (optional fixup value to evaluate later)
|
||||
* @param {string} [sUndefined] (optional fixup to evaluate later)
|
||||
*/
|
||||
genWord(value, sFixup)
|
||||
genWord(value, sUndefined)
|
||||
{
|
||||
this.aWords[this.nLocation] = this.truncate(value);
|
||||
if (sFixup != null) this.aFixups[this.nLocation] = sFixup;
|
||||
if (sUndefined !== undefined) this.aFixups[this.nLocation] = sUndefined;
|
||||
this.aLineRefs[this.nLocation] = this.nLine;
|
||||
this.nLocation++;
|
||||
}
|
||||
|
||||
|
|
@ -1832,28 +1964,37 @@ Macro10.PSEUDO_OP = {
|
|||
ASCII: "ASCII",
|
||||
ASCIZ: "ASCIZ",
|
||||
BLOCK: "BLOCK",
|
||||
BYTE: "BYTE",
|
||||
DEFINE: "DEFINE",
|
||||
END: "END",
|
||||
EXP: "EXP",
|
||||
IF1: "IF1",
|
||||
IFDEF: "IFDEF",
|
||||
IFDIF: "IFDIF",
|
||||
IFE: "IFE",
|
||||
IFG: "IFG",
|
||||
IFGE: "IFGE",
|
||||
IFIDN: "IFIDN",
|
||||
IFL: "IFL",
|
||||
IFLE: "IFLE",
|
||||
IFN: "IFN",
|
||||
IFNDEF: "IFNDEF",
|
||||
IRP: "IRP",
|
||||
IRPC: "IRPC",
|
||||
LALL: "LALL",
|
||||
LIT: "LIT",
|
||||
LITERAL: "LITERAL", // this is a pseudo-pseudo-op, for internal use only
|
||||
LIST: "LIST",
|
||||
LOC: "LOC",
|
||||
NOSYM: "NOSYM",
|
||||
OPDEF: "OPDEF",
|
||||
PAGE: "PAGE",
|
||||
PURGE: "PURGE",
|
||||
REPEAT: "REPEAT",
|
||||
SIXBIT: "SIXBIT",
|
||||
SUBTTL: "SUBTTL",
|
||||
TITLE: "TITLE",
|
||||
VAR: "VAR",
|
||||
XWD: "XWD",
|
||||
XLIST: "XLIST"
|
||||
};
|
||||
|
|
|
|||
|
|
@ -109,19 +109,6 @@ class Debugger extends Component
|
|||
*/
|
||||
this.nBits = 32;
|
||||
|
||||
/*
|
||||
* sUndefined is set to the last unknown variable that parseExpression() encounters, if if
|
||||
* is called in "quiet mode"; the value used for the variable is zero. This mode was added
|
||||
* for components that need to support expressions containing "fixups" (ie, values that
|
||||
* must be determined later).
|
||||
*
|
||||
* TODO: Only one unknown (fixup) per expression is supported, and we don't indicate what
|
||||
* operation was performed with the value (callers generally assume addition). If a call
|
||||
* encounters more than one undefined value, it will revert to normal error reporting and
|
||||
* return an undefined value for the entire expression.
|
||||
*/
|
||||
this.sUndefined = null;
|
||||
|
||||
this.achGroup = ['{','}'];
|
||||
this.achAddress = ['[',']'];
|
||||
|
||||
|
|
@ -594,6 +581,9 @@ class Debugger extends Component
|
|||
case '||':
|
||||
valNew = (val1 || val2? 1 : 0);
|
||||
break;
|
||||
case ',,':
|
||||
valNew = this.truncate(val1, 18, true) * Math.pow(2, 18) + this.truncate(val2, 18, true);
|
||||
break;
|
||||
case '_':
|
||||
case '^_':
|
||||
valNew = val1;
|
||||
|
|
@ -625,7 +615,7 @@ class Debugger extends Component
|
|||
}
|
||||
|
||||
/**
|
||||
* parseArray(asValues, iValue, iLimit, nBase, fQuiet)
|
||||
* parseArray(asValues, iValue, iLimit, nBase, aUndefined)
|
||||
*
|
||||
* parseExpression() takes a complete expression and divides it into array elements, where even elements
|
||||
* are values (which may be empty if two or more operators appear consecutively) and odd elements are operators.
|
||||
|
|
@ -643,10 +633,10 @@ class Debugger extends Component
|
|||
* @param {number} iValue
|
||||
* @param {number} iLimit
|
||||
* @param {number} nBase
|
||||
* @param {boolean} [fQuiet]
|
||||
* @param {Array|undefined} [aUndefined]
|
||||
* @return {number|undefined}
|
||||
*/
|
||||
parseArray(asValues, iValue, iLimit, nBase, fQuiet)
|
||||
parseArray(asValues, iValue, iLimit, nBase, aUndefined)
|
||||
{
|
||||
var value;
|
||||
var sValue, sOp;
|
||||
|
|
@ -663,7 +653,7 @@ class Debugger extends Component
|
|||
sOp = (iValue < iLimit? asValues[iValue++] : "");
|
||||
|
||||
if (sValue) {
|
||||
v = this.parseValue(sValue, null, fQuiet, nUnary);
|
||||
v = this.parseValue(sValue, null, aUndefined, nUnary);
|
||||
} else {
|
||||
if (sOp == '{') {
|
||||
var cOpen = 1;
|
||||
|
|
@ -677,7 +667,7 @@ class Debugger extends Component
|
|||
if (!--cOpen) break;
|
||||
}
|
||||
}
|
||||
v = this.parseArray(asValues, iStart, iValue-1, this.nBase, fQuiet);
|
||||
v = this.parseArray(asValues, iStart, iValue-1, this.nBase, aUndefined);
|
||||
if (v != null && nUnary) {
|
||||
v = this.parseUnary(v, nUnary);
|
||||
}
|
||||
|
|
@ -730,12 +720,12 @@ class Debugger extends Component
|
|||
}
|
||||
|
||||
if (v === undefined) {
|
||||
if (this.sUndefined == null && fQuiet) {
|
||||
this.sUndefined = sValue;
|
||||
if (aUndefined) {
|
||||
aUndefined.push(sValue);
|
||||
v = 0;
|
||||
} else {
|
||||
fError = true;
|
||||
fQuiet = !fQuiet;
|
||||
aUndefined = [];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -786,7 +776,7 @@ class Debugger extends Component
|
|||
if (!fError) {
|
||||
value = aVals.pop();
|
||||
this.assert(!aVals.length);
|
||||
} else if (fQuiet === false) {
|
||||
} else if (!aUndefined) {
|
||||
this.println("parse error (" + (sValue || sOp) + ")");
|
||||
}
|
||||
|
||||
|
|
@ -795,17 +785,16 @@ class Debugger extends Component
|
|||
}
|
||||
|
||||
/**
|
||||
* parseASCII(sExp, chDelim, nBits, cchMax, fQuiet)
|
||||
* parseASCII(sExp, chDelim, nBits, cchMax)
|
||||
*
|
||||
* @this {Debugger}
|
||||
* @param {string} sExp
|
||||
* @param {string} chDelim
|
||||
* @param {number} nBits
|
||||
* @param {number} cchMax
|
||||
* @param {boolean} [fQuiet] (true for quiet parsing)
|
||||
* @return {string}
|
||||
*/
|
||||
parseASCII(sExp, chDelim, nBits, cchMax, fQuiet)
|
||||
parseASCII(sExp, chDelim, nBits, cchMax)
|
||||
{
|
||||
var i;
|
||||
while ((i = sExp.indexOf(chDelim)) >= 0) {
|
||||
|
|
@ -829,7 +818,7 @@ class Debugger extends Component
|
|||
v = this.truncate(v * Math.pow(2, nBits) + c, nBits * cchMax, true);
|
||||
}
|
||||
if (cch >= 0) {
|
||||
if (fQuiet === false) this.println("parse error (" + sExp + ")");
|
||||
this.println("parse error (" + chDelim + sExp + chDelim + ")");
|
||||
break;
|
||||
} else {
|
||||
sExp = sExp.substr(0, i) + this.toStrBase(v, -1) + sExp.substr(j);
|
||||
|
|
@ -858,15 +847,20 @@ class Debugger extends Component
|
|||
* predecessor is encountered, evaluate, and push the result back onto aVals. Only selected unary
|
||||
* operators are supported (eg, negate and complement); no ternary operators like '?:' are supported.
|
||||
*
|
||||
* fQuiet can be used to pass an array that collects any undefined variables that parseExpression()
|
||||
* encounters; the value of an undefined variable is zero. This mode was added for components that need
|
||||
* to support expressions containing "fixups" (ie, values that must be determined later).
|
||||
*
|
||||
* @this {Debugger}
|
||||
* @param {string|undefined} sExp
|
||||
* @param {boolean} [fQuiet] (true for quiet parsing)
|
||||
* @param {Array|undefined|boolean} [fQuiet]
|
||||
* @return {number|undefined} numeric value, or undefined if sExp contains any undefined or invalid values
|
||||
*/
|
||||
parseExpression(sExp, fQuiet)
|
||||
{
|
||||
var value = undefined;
|
||||
this.sUndefined = null;
|
||||
var fPrint = (fQuiet === false);
|
||||
var aUndefined = Array.isArray(fQuiet)? fQuiet : undefined;
|
||||
|
||||
if (sExp) {
|
||||
|
||||
|
|
@ -888,9 +882,9 @@ class Debugger extends Component
|
|||
* Quoted ASCII characters can have a numeric value, too, which must be converted now, to avoid any
|
||||
* conflicts with the operators below.
|
||||
*/
|
||||
sExp = this.parseASCII(sExp, '"', 7, 5, fQuiet); // MACRO-10 packs up to 5 7-bit ASCII codes into a value
|
||||
sExp = this.parseASCII(sExp, '"', 7, 5); // MACRO-10 packs up to 5 7-bit ASCII codes into a value
|
||||
if (!sExp) return value;
|
||||
sExp = this.parseASCII(sExp, "'", 6, 6, fQuiet); // MACRO-10 packs up to 6 6-bit ASCII (SIXBIT) codes into a value
|
||||
sExp = this.parseASCII(sExp, "'", 6, 6); // MACRO-10 packs up to 6 6-bit ASCII (SIXBIT) codes into a value
|
||||
if (!sExp) return value;
|
||||
|
||||
/*
|
||||
|
|
@ -928,11 +922,11 @@ class Debugger extends Component
|
|||
* to remove spaces entirely, because if an operator-less expression like "A B" was passed in, we would want
|
||||
* that to generate an error; if we converted it to "AB", evaluation might inadvertently succeed.
|
||||
*/
|
||||
var regExp = /({|}|\|\||&&|\||\^!|\^B|\^O|\^D|\^L|\^-|~|\^_|_|&|!=|!|==|>=|>>>|>>|>|<=|<<|<|-|\+|\^\/|\/|\*| )/;
|
||||
var regExp = /({|}|\|\||&&|\||\^!|\^B|\^O|\^D|\^L|\^-|~|\^_|_|&|!=|!|==|>=|>>>|>>|>|<=|<<|<|-|\+|\^\/|\/|\*|,,| )/;
|
||||
sExp = sExp.replace(/(^|[^A-Z0-9$%.])([0-9]+)B/, "$1$2^_").replace(/\s+/g, ' ');
|
||||
var asValues = sExp.split(regExp);
|
||||
value = this.parseArray(asValues, 0, asValues.length, this.nBase, fQuiet);
|
||||
if (value !== undefined && fQuiet === false) {
|
||||
value = this.parseArray(asValues, 0, asValues.length, this.nBase, aUndefined);
|
||||
if (value !== undefined && fPrint) {
|
||||
this.printValue(null, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -1060,13 +1054,15 @@ class Debugger extends Component
|
|||
* @this {Debugger}
|
||||
* @param {string|undefined} sValue
|
||||
* @param {string|null} [sName] is the name of the value, if any
|
||||
* @param {boolean} [fQuiet]
|
||||
* @param {Array|undefined|boolean} [fQuiet]
|
||||
* @param {number} [nUnary] (0 for none, 1 for negate, 2 for complement, 3 for leading zeros)
|
||||
* @return {number|undefined} numeric value, or undefined if sValue is either undefined or invalid
|
||||
*/
|
||||
parseValue(sValue, sName, fQuiet, nUnary = 0)
|
||||
{
|
||||
var value;
|
||||
var aUndefined = Array.isArray(fQuiet)? fQuiet : undefined;
|
||||
|
||||
if (sValue != null) {
|
||||
var iReg = this.getRegIndex(sValue);
|
||||
if (iReg >= 0) {
|
||||
|
|
@ -1076,13 +1072,10 @@ class Debugger extends Component
|
|||
if (value != null) {
|
||||
var sUndefined = this.getVariableFixup(sValue);
|
||||
if (sUndefined) {
|
||||
if (!this.sUndefined) {
|
||||
this.sUndefined = sUndefined;
|
||||
if (aUndefined) {
|
||||
aUndefined.push(sUndefined);
|
||||
} else {
|
||||
if (!fQuiet) {
|
||||
this.println(sValue + " has too many undefined values (" + sUndefined + ',' + this.sUndefined + ")");
|
||||
fQuiet = true;
|
||||
}
|
||||
this.println(sValue + " is undefined (" + sUndefined + ")");
|
||||
value = undefined;
|
||||
}
|
||||
}
|
||||
|
|
@ -1169,14 +1162,18 @@ class Debugger extends Component
|
|||
*/
|
||||
printVariable(sVar)
|
||||
{
|
||||
if (sVar) {
|
||||
return this.printValue(sVar, this.aVariables[sVar].value);
|
||||
}
|
||||
var cVariables = 0;
|
||||
for (sVar in this.aVariables) {
|
||||
this.printValue(sVar, this.aVariables[sVar].value);
|
||||
if (this.aVariables) {
|
||||
if (sVar) {
|
||||
return this.printValue(sVar, this.aVariables[sVar] && this.aVariables[sVar].value);
|
||||
}
|
||||
var aVars = Object.keys(this.aVariables);
|
||||
aVars.sort();
|
||||
for (var i = 0; i < aVars.length; i++) {
|
||||
this.printValue(aVars[i], this.aVariables[aVars[i]].value);
|
||||
cVariables++;
|
||||
}
|
||||
}
|
||||
return cVariables > 0;
|
||||
}
|
||||
|
||||
|
|
@ -1200,6 +1197,10 @@ class Debugger extends Component
|
|||
*/
|
||||
getVariable(sVar)
|
||||
{
|
||||
if (this.aVariables[sVar]) {
|
||||
return this.aVariables[sVar].value;
|
||||
}
|
||||
sVar = sVar.substr(0, 6);
|
||||
return this.aVariables[sVar] && this.aVariables[sVar].value;
|
||||
}
|
||||
|
||||
|
|
@ -1233,7 +1234,7 @@ class Debugger extends Component
|
|||
* @this {Debugger}
|
||||
* @param {string} sVar
|
||||
* @param {number} value
|
||||
* @param {string|null} [sUndefined]
|
||||
* @param {string|undefined} [sUndefined]
|
||||
*/
|
||||
setVariable(sVar, value, sUndefined)
|
||||
{
|
||||
|
|
@ -1317,6 +1318,7 @@ if (DEBUGGER) {
|
|||
'}': 20 // close grouped expression (converted from achGroup[1])
|
||||
};
|
||||
Debugger.aDECOpPrecedence = {
|
||||
',,': 1, // high-word,,low-word
|
||||
'||': 5, // logical OR
|
||||
'&&': 6, // logical AND
|
||||
'!=': 10, // inequality
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue