perm filename MSSNGR.SAI[AID,HE] blob
sn#378664 filedate 1978-09-06 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00007 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 ENTRY
C00004 00003 ! Notes from 10 to 11
C00006 00004 ! INIT, PEEK, POKE, PEEKARRAY, POKEARRAY
C00014 00005 ! GETNOTE, SNDNOTE, SNDN1
C00017 00006 REAL PROCEDURE RFVAL(INTEGER WORD1,WORD2)
C00019 00007 INTERNAL PROCEDURE EVAL(INTEGER ARRAY REQ INTEGER REQLENGTH
C00026 ENDMK
C⊗;
ENTRY;
BEGIN "MSSNGR"
REQUIRE "ABBREV.SAI[AL,HE]" SOURCE_FILE;
! This program is going to be used as a replacement for the more elegant program
ALAID(.SAI) for strict two-way question-answer communication between a program on
the pdp-10 which should use MSSNGR as a load module (e.g. the current AL run time
debugger DEBAL) and another communicating program on the pdp-11 (e.g. ALAID(.PAL)
currently a member of the AL run time system). ;
PROCEDURE COMERR
(STRING MESSG;RECORD_POINTER(ANY_CLASS) CONTXT (NULL_RECORD));
! Non-fatal warnings;
BEGIN
USERERR(0,1,"HAH! "&MESSG);
END;
! Notes from 10 to 11;
DEFINE GETBUF = '1;
DEFINE USEBUF = '2;
DEFINE RELBUF = '3;
! Notes from 11 to 10;
DEFINE BUFALC = '101;
DEFINE TAKBUF = '102;
! Offsets in message buffers;
DEFINE MESID = 0;
DEFINE MESTYP = 2;
DEFINE FROMTEN = '1;
DEFINE FROMELF = '2;
DEFINE REQUEST = '4;
DEFINE RESPONSE = '10;
DEFINE MESLTH = 4;
DEFINE MESBEG = 6;
INTEGER MSGNO; ! Always even, numbers the last message originating at the 10;
DEFINE MAP_OFFSET = "'320000"; ! Converts virtual addresses to physical ones;
DEFINE NOTB10 = "'160000"; ! The notebox from 11 to the 10 (byte address);
DEFINE NOTB11 = "'160020"; ! The notebox from 10 to the 11 (byte address);
DEFINE NOTSIZ = "3"; ! In WORDS!;
! DEFINE OUTTST = "OUTSTR";
DEFINE OUTTST = "! ";
INTEGER BRCHAR; ! Break character;
! Sources:;
DEFINE USER = 1;
DEFINE ELFIE = 2;
! INIT, PEEK, POKE, PEEKARRAY, POKEARRAY;
INTEGER ELFCHAN; ! Channel number for I/O to ELF;
INTERNAL PROCEDURE INIT;
BEGIN "init"
INTEGER COUNT, BRCHAR, EOF, FLAG;
OWN BOOLEAN ONCE; comment INITIALIZE(ONCE←FALSE);
! Only allow one initialization;
IF ONCE
THEN BEGIN
COMERR("INIT called more than once; it initializes itself now.");
RETURN
END
ELSE ONCE ← TRUE;
! Initialize the ELF for output;
ELFCHAN ← GETCHAN;
OPEN(ELFCHAN,"ELF",'17,0,0,COUNT,BRCHAR,EOF);
END "init";
REQUIRE INIT INITIALIZATION[0];
DEFINE MTAPE = "'072000";
INTEGER PROCEDURE PEEK(INTEGER ADR);
BEGIN "peek" ! Returns the ELF word at unibus address ADR;
DEFINE PEEK = "'002000000000";
LABEL PEK1, PEKMTA, PEK3, PEK4, PEK5;
INTEGER ANS, ADR1;
ADR1 ← ADR;
START_CODE;
MOVE 1,ADR1 ; ! Prepare MTAPE data in PEK1;
LSH 1,-1 ;
HRRM 1,PEK1 ;
MOVE 1,ELFCHAN ; ! Prepare MTAPE in PEKMTA;
LSH 1,5 ;
ADDI 1,MTAPE ;
HRLM 1,PEKMTA ;
PEKMTA:
PEK1 ; ! This will become MTAPE ELFCHAN,PEK1;
JRST PEK3 ; ! Error;
JRST PEK4 ; ! OK;
PEK1:
PEEK ;
PEK5:
0 ;
PEK3:
SETOM PEK5 ; ! Error result;
PEK4:
MOVE 1,PEK5 ;
MOVEM 1,ANS ;
END;
IF ANS = -1 THEN COMERR("Couldn't peek at ELF");
RETURN(ANS);
END "peek";
PROCEDURE POKE(INTEGER ADR, CONTENTS);
BEGIN "poke" ! Stores CONTENTS at unibus address ADR;
DEFINE POKE = "'003000000000";
LABEL POK1, POKMTA, POK3, POK4, POK5;
INTEGER ANS, ADR1, CNTS;
ADR1 ← ADR;
CNTS ← CONTENTS;
START_CODE;
MOVE 1,ADR1 ; ! Prepare MTAPE data in POK1;
LSH 1,-1 ;
HRRM 1,POK1 ;
MOVE 1,ELFCHAN ; ! Prepare MTAPE in POKMTA;
LSH 1,5 ;
ADDI 1,MTAPE ;
HRLM 1,POKMTA ;
MOVE 1,CNTS ;
MOVEM 1,POK5 ;
POKMTA:
POK1 ; ! This will become MTAPE ELFCHAN,POK1;
JRST POK3 ; ! Error;
JRST POK4 ; ! OK;
POK1:
POKE ;
POK5:
0 ;
POK3:
SETOM POK5 ; ! Error result;
POK4:
MOVE 1,POK5 ;
MOVEM 1,ANS ;
END;
IF ANS = -1 THEN COMERR("Couldn't poke at ELF");
RETURN;
END "poke";
PROCEDURE POKEARRAY(INTEGER ADR, LTH; INTEGER ARRAY CONTENTS);
BEGIN "pokearray" ! Sends the CONTENTS[0:LTH-1] to unibus address ADR
and higher;
INTEGER ADR1, LTH1, CNTS;
LABEL SND1, SND4, SNDUST, SNDIOW, SNDOUT;
DEFINE USETO = "'075000";
DEFINE OUT = "'057000";
ADR1 ← ADR + MAP_OFFSET;
CNTS ← LOCATION(CONTENTS[0]);
LTH1 ← LTH;
START_CODE;
MOVE 1,ADR1 ; ! Prepare USETO data in SND1;
LSH 1,-1 ;
ADDI 1,'400000 ;
HRRM 1,SND1 ;
MOVE 1,ELFCHAN ; ! Prepare USETO in SNDUST;
LSH 1,5 ;
ADDI 1,USETO ;
HRLM 1,SNDUST ;
SNDUST:
SND1 ; ! This will become USETO ELFCHAN,SND1;
JRST SND4 ; ! OK;
SND1:
'400000000000 ; ! one word transfer, don't grab unibus;
SNDIOW:
0 ; ! Will be IOWD [LTH,CNTS];
SND4:
MOVN 1,LTH1 ; ! Prepare IOWD in SNDIOW;
HRLZM 1,SNDIOW ;
MOVE 1,CNTS ;
SUBI 1,1 ;
HRRM 1,SNDIOW ;
MOVE 1,ELFCHAN ; ! Prepare OUT in SNDOUT;
LSH 1,5 ;
ADDI 1,OUT ;
HRLM 1,SNDOUT ;
SNDOUT:
SNDIOW ; ! This will become OUT ELFCHAN,SNDIOW;
SETZ 1, ; ! Success return;
MOVEM 1,ADR1 ; ! Failure return;
END;
IF ADR1 ≠ 0 THEN COMERR("POKEARRAY failed");
RETURN;
END "pokearray";
PROCEDURE PEEKARRAY(INTEGER ADR, LTH; INTEGER ARRAY CONTENTS);
BEGIN "peekarray" ! Gets the CONTENTS[0:LTH-1] from unibus address ADR
and higher;
INTEGER ADR1, LTH1, CNTS;
LABEL GET1, GET4, GETUST, GETIOW, GETIN;
DEFINE USETI = "'074000";
DEFINE IN = "'056000";
ADR1 ← ADR + MAP_OFFSET;
CNTS ← LOCATION(CONTENTS[0]);
LTH1 ← LTH;
START_CODE;
MOVE 1,ADR1 ; ! Prepare USETI data in GET1;
LSH 1,-1 ;
ADDI 1,'400000 ;
HRRM 1,GET1 ;
MOVE 1,ELFCHAN ; ! Prepare USETI in GETUST;
LSH 1,5 ;
ADDI 1,USETI ;
HRLM 1,GETUST ;
GETUST:
GET1 ; ! This will become USETI ELFCHAN,GET1;
JRST GET4 ; ! OK;
GET1:
'400000000000 ; ! one word transfer, don't grab unibus;
GETIOW:
0 ; ! Will be IOWD [LTH,CNTS];
GET4:
MOVN 1,LTH1 ; ! Prepare IOWD in GETIOW;
HRLZM 1,GETIOW ;
MOVE 1,CNTS ;
SUBI 1,1 ;
HRRM 1,GETIOW ;
MOVE 1,ELFCHAN ; ! Prepare IN in GETIN;
LSH 1,5 ;
ADDI 1,IN ;
HRLM 1,GETIN ;
GETIN:
GETIOW ; ! This will become IN ELFCHAN,GETIOW;
SETZ 1, ; ! Success return;
MOVEM 1,ADR1 ; ! Failure return;
END;
IF ADR1 ≠ 0 THEN COMERR("PEEKARRAY failed");
RETURN;
END "peekarray";
! GETNOTE, SNDNOTE, SNDN1;
DEFINE SLEEP = "'047040000031"; ! The SLEEP UUO;
PROCEDURE GETNOTE (INTEGER ARRAY NOTE);
BEGIN "getnote"
! Listens to the notebox from the 11 and returns the note when it
arrives, in array NOTE[0:NOTSIZ-1];
WHILE TRUE DO
BEGIN "gwaiting"
INTEGER SGNAL, I;
SGNAL ← PEEK(NOTB10);
IF SGNAL = 0
THEN START_CODE "gnotyet"
MOVEI 1,0 ;
SLEEP ; ! Sleep for a tick;
END "gnotyet"
ELSE BEGIN "ggotit"
NOTE[0] ← SGNAL;
FOR I ← 1 STEP 1 UNTIL NOTSIZ-1 DO
NOTE[I] ← PEEK(NOTB10+I+I);
OUTTST(CRLF & "Receiving note: " & CVOS(SGNAL));
POKE(NOTB10,0); ! Clear the note;
RETURN;
END "ggotit";
END "gwaiting";
END "getnote";
PROCEDURE SNDNOTE (INTEGER ARRAY NOTE);
BEGIN "sndnote"
! Sends the note in NOTE[0:NOTSIZ-1] to the 11's notebox as soon
as it is free;
WHILE TRUE DO
BEGIN "swaiting"
INTEGER SGNAL, I;
SGNAL ← PEEK(NOTB11);
IF SGNAL ≠ 0
THEN START_CODE "snotyet"
MOVEI 1,0 ;
SLEEP ; ! Sleep for a tick;
END "snotyet"
ELSE BEGIN "sgotit"
FOR I ← 1 STEP 1 UNTIL NOTSIZ-1 DO
POKE(NOTB11+I+I,NOTE[I]);
POKE(NOTB11,NOTE[0]); ! Set the note's appearance;
RETURN;
END "sgotit"
END "swaiting";
END "sndnote";
PROCEDURE SNDN1(INTEGER ARG0, ARG1 (0), ARG2 (0));
BEGIN "sndn1"
! A little note is to be sent. Send it;
INTEGER ARRAY LNOTE [0:NOTSIZ-1];
LNOTE[0] ← ARG0;
OUTTST(CRLF & "Sending note: " & CVOS(ARG0));
LNOTE[1] ← ARG1;
LNOTE[2] ← ARG2;
SNDNOTE(LNOTE);
END "sndn1";
REAL PROCEDURE RFVAL(INTEGER WORD1,WORD2);
BEGIN
! This procedure gives the real floating point value of a floating point number
in WORD1 and WORD2 with F format of pdp-11.;
REAL X;
INTEGER SIGN,EXPONENT,FRACTION;
! PRINT(CRLF,"WORD1=",CVOS(WORD1)," WORD2=",CVOS(WORD2));
SIGN← WORD1 LSH -15;
EXPONENT← (WORD1 LSH 21) LSH -28 ;
FRACTION← (((WORD1 LAND '177) LOR (IF EXPONENT THEN '200 ELSE 0)) LSH 16) LOR WORD2 ;
IF SIGN=1 THEN BEGIN EXPONENT← LNOT EXPONENT; FRACTION← '100000000 - FRACTION; END;
! PRINT(CRLF,"SIGN=",SIGN," EXPONENT=",CVOS(EXPONENT)," FRACTION=",CVOS(FRACTION));
MEMLOC(X,INTEGER)← SIGN LSH 35 LOR EXPONENT LSH 27 LOR FRACTION LSH 3 ;
! PRINT(CRLF,CVOS(X));
RETURN(X);
END;
INTERNAL PROCEDURE EVAL(INTEGER ARRAY REQ; INTEGER REQLENGTH;
REAL ARRAY ANSWER; REFERENCE INTEGER ANSLENGTH);
! A list of pcodes with proper header(s) is in REQ , we only put ALAID headers
in front of the list and send the whole message to the 11. We then send the 11's
answer as soon as it is available;
BEGIN
INTEGER ARRAY NOTE[0:NOTSIZ-1], MESSAGE[0: 26 MAX REQLENGTH+5];
INTEGER I;
SNDN1(GETBUF,REQLENGTH+6);
GETNOTE(NOTE);
IF NOTE[0] ≠ BUFALC THEN COMERR("Getting a "&CVS(NOTE[0])
&" while expecting a BUFALC (i.e "&CVS(BUFALC)&" )");
IF NOTE[1] ≠ REQLENGTH+6 THEN COMERR("Alocted buffer's length is wrong !");
MESSAGE[MESID % 2]← 1; ! Only one message each time;
MESSAGE[MESTYP % 2]← FROMTEN + REQUEST;
MESSAGE[MESLTH % 2]← REQLENGTH + 3;
! Message keyword is going to be "EVAL ";
MESSAGE[3]← "E" + "V" LSH 8;
MESSAGE[4]← "A" + "L" LSH 8;
MESSAGE[5]← " " + " " LSH 8;
FOR I←1 STEP 1 UNTIL REQLENGTH DO
MESSAGE[I+5]← REQ[I];
! Send the message (REQ) to the 11's allocated buffer;
POKEARRAY(NOTE[2], REQLENGTH+6, MESSAGE);
! Tell the 11 to operate on it;
SNDN1(USEBUF,NOTE[2]);
! See where the 11's answer is;
GETNOTE(NOTE);
IF NOTE[0] ≠ TAKBUF THEN COMERR("Getting a "&CVS(NOTE[0])
&" while expecting a TAKBUF (i.e "&CVS(TAKBUF)&" )");
ANSLENGTH← PEEK(NOTE[1] + MESLTH + MAP_OFFSET);
! Getting the answer ;
PEEKARRAY(NOTE[1],ANSLENGTH,MESSAGE);
ANSLENGTH← ANSLENGTH - 3 ;
FOR I←2 STEP 2 UNTIL ANSLENGTH DO
ANSWER[I LSH -1]← RFVAL(MESSAGE[I+1],MESSAGE[I+2]);
ANSLENGTH← ANSLENGTH LSH -1;
! Tell the 11 we don't need the buffer anymore;
SNDN1(RELBUF,NOTE[1]);
END;
END "MSSNGR"