Trailing-Edge
-
PDP-10 Archives
-
decuslib10-02
-
43,50301/starn.doc
There are 2 other files named starn.doc in the archive. Click here to see a list.
TITLE: The Home Handyman's Guide to *1
AUTHOR(S): Richard A. Stone
DEPARTMENT: 18PR02314
LOCATION: Western Electric, ERC, Princeton, N.J.
LOCAL REPORT NUBMER: CC 5409
DATE: May 3, 1973
VERSION: 6.0
ABSTRACT: This manual is designed to be a guide to a
do-it-yourself *1 compiler for a given computer. It is assumed
that the reader is familiar with *1 and SNOBOL 4.
REFERENCES: CC4868, CC5269
INDEXING TERMS: Computers, List Processing, Compilers, *1, SNOBOL
THE HOME HANDYMAN'S GUIDE TO *1
=== ==== ========== ===== == ==
This manual is intended to allow any competent SNOBOL IV programmer to
build his own *1 for any given computer.
The manual is divided into the following sections:
0-METHODOLOGY: How to use this manual
I-USER FUNCTIONS: Functions you must define
II-USER OP FUNCTIONS: Functions you will have to define to
handle operations
III-USER CONVENIENCE FUNCTIONS: Functions that have been found
convenient on various machines
IV-VARIABLES: Variables you will have to use
V-SYSTEM FUNCTION: Functions which you have to use
VI-OPTIMIZATION: The optional efforts to turn out better code.
VII-REENTERABILITY: The optional turning out of reenterable
code.
-APPENDIXES
TABLE OF CONTENTS
-----------------
PAGE ROUTINE SECTION
---- ------- -------
1 METHODOLOGY
3 INIT
4 BEGIN
5 FINISH
6 COMMENT
7 RADIX
8 STATSRT
9 CALLSRT
10 GENCALL
11 GENLOG
12 ASS
13 GENLOAD
14 GETREG
15 TABSTM
16 CKREGD
17 USER OP FUNCTIONS
17 O.movei
21 USER CONVENIENCE FUNCTIONS
22 GENONE
23 GENTWO
24 LOAD.
25 DO.OP
26 STORE.
27 GETROFF
28 ASSCK
29 SIDECK
30 POINT
31 VARIABLES AND REGISTERS USED
33 HANDY FUNCTIONS YOU CAN USE
34 PUT
35 GENLAB
36 FILLTAB
37 ERROR
38 SETTYPE
39 GETTYPE
40 CKTYPE
41 DEC2OCT
42 FLIP
43 GETLAB
44 DS
45 OPTIMIZATION
46 PUTREG
47 OFFREG
48 CLRREG
49 OFFLOC
* * * 1
* * * 11
*** 1 1
******* 1
*** 1
* * * 1
* * * 11111
SECTION 0
---------
METHODOLOGY
-----------
STEP1: Read the section on VARIABLES.
STEP2: Read through the SYSTEM FUNCTIONS to see what functions you can
use.
STEP3: Go through the section on USER FUNCTIONS, one function at a
time. For each function, copy the example for the computer that
is most similar to yours, substituting where appropriate.
Don't worry about optimization or reenterable code yet.
STEP4: Do the same for USER OP FUNCTIONS.
STEP5: Now do the same for user convenience functions. Don't forget to
define them in INIT.
STEP6: You should now have a complete version -- debug it!
STEP7: Now read the section of optimization, and try adding optimization.
STEP8: If you still have the energy, try reenterable code.
NOTE: The Handyman always defines functions, so each section is left via
a return.
* * * 1
* * * 11
*** 1 1
******* 1
*** 1
* * * 1
* * * 11111
SECTION I
---------
USER FUNCTIONS
---- ---------
The functions in this section must be defined by the Handyman.
NAME: INIT
USEAGE: Called at the start of a program to set system variables.
DESCRIPTION:
-Set the following variables:
BSIZE bits/byte
HSIZE bits/half word
WSIZE bits/word
ADDR.WORD Difference in addresses between consecutive words
JUMPLOC table, <symbolic op>=name of op
LOGOP table, <symbolic logical op>=name of logical op
SC special character used in variable names
VER catenated version #, upped each change
R0 register to load the first operand
R1 Register to load the second operand
BASE.REG Register used to optimize a base variable
REENT.REG register used for reentrant
-Define any variables needed
-Define any functions needed
-Set or clear any switches for which you don't like the default.
****************************
** Example for the PDP 10 **
****************************
INIT BSIZE = 8
HSIZE = 18
WSIZE = 36
HALF = 2 ** 18
ADDR.WORD = 1
JUMPLOC = FILLTAB( TABLE(14,5) ,
. 'GOTO,GOTO"<-[,MOVEI"<-,MOVE"+,ADD"-,SUB"!,IOR"'
. '/&/,AND"&,AND"X!,XOR"'
. '/,IDIV"*,IMUL"MOD,MOD"<-<-,LSH"->->,LSHR"'
. '\,LCR"'
. )
LOGOP = FILLTAB( TABLE(11) ,
. '<=,LE"\>,LE">=,GE"\<,GE"<,L"\>=,L"'
. '>,G"\<=,G"=,E"\=,N"<>,A"'
. )
SC = '$'
VER = VER '5 STAR10'
MOVE = 'MOVE'
SW.REG =
SW.DEBUG = '+'
BASE.REG = '5'
R0 = '6' ; R1 = '7'
REENT.REG = '13'
DEFINE('DO.OP()')
DEFINE('GENONE(OP)')
DEFINE('GENONER(OP,R.ADDR)','GENONE')
DEFINE('GENTWO(OP)')
DEFINE('GENTWOI(OP)')
DEFINE('GETROFF(LAB)')
DEFINE('LOAD.R()')
DEFINE('LOAD.R2(R.ADDR,R.F,R1)','LOAD.R')
DEFINE('POINT(ENTRY,ADDR)')
DEFINE('SIDECK(ENTRY)')
DEFINE('STORE.L()')
DEFINE('STORE.L2(R0)','STORE.L')
:(RETURN)
****************************
** Example for the PDP 11 **
****************************
INIT BSIZE = 8
WSIZE = 16
HSIZE = 9999
MAXSIZE = 2 ** 16 - 1
ADDR.WORD = 2
JUMPLOC = FILLTAB( TABLE(14,5) ,
. 'GOTO,GOTO"<-[,MOVA"<-,MOV"+,ADD"-,SUB"!,BIS"'
. '/&/,BIC"&,BIC"X!,XOR"'
. '/,DIV"*,MUL"MOD,MOD"<-<-,ASL"->->,ASR"'
. '\,COM"'
. )
LOGOP = FILLTAB( TABLE(11) ,
. '<=,LE"\>,LE">=,GE"\<,GE"<,LT"\>=,LT"'
. '>,GT"\<=,GT"=,EQ"\=,NE"<>,R"'
. )
SC = '$'
VER = VER '5 STAR11'
MOV = 'MOV'
SW.PIC = '+'
BASE.REG = '%4'
REENT.REG = '%5'
MOVA.PARSE = POS(1) BREAK('(') . OFF
. '(' BREAK(')') . LREG
DEFINE('ASSCK(OP,L.ADDR)')
DEFINE('GETROFF(LAB)')
DEFINE('GENONE(OP)')
DEFINE('GENTWO(OP)')
:(RETURN)
****************************
** Example for the S/360 ***
****************************
INIT BSIZE = 8
HSIZE = 16
WSIZE = 32
ADDR.WORD = 4
JUMPLOC = FILLTAB( TABLE(14,5) ,
. 'GOTO,GOTO"<-[,LA"<-,L"+,A"-,S"!,O"'
. '/&/,N"&,N"X!,X"'
. '/,D"*,M"MOD,MOD"<-<-,SLL"->->,SRL"'
. '\,LCR"'
. )
LOGOP = FILLTAB( TABLE(11) ,
. '<=,NH"\>,NH">=,NL"\<,NL"<,L"\>=,L"'
. '>,H"\<=,H"=,E"\=,NE"<>,"'
. )
SC = '$'
VER = VER '5 STAR360'
SW.REG =
SW.DEBUG = '+'
BASE.REG = '5'
R0 = '6' ; R1 = '7'
REENT.REG = '13'
DEFINE('DO.OP()')
DEFINE('GENONE(OP)')
DEFINE('GENONER(OP,R.ADDR)','GENONE')
DEFINE('GENTWO(OP)')
DEFINE('GETROFF(LAB)')
DEFINE('LOAD.L()')
DEFINE('LOAD.R2(L.ADDR,L.F,R0)','LOAD.L')
DEFINE('STORE.L()')
DEFINE('STORE.L2(R0)','STORE.L')
:(RETURN)
NAME: BEGIN
USEAGE: Called at BEGIN statement.
DESCRIPTION:
-Generate any statements needed at start of a routine.
-It is recommended that BEGIN generate its own label
-Best to ignore the reenterability issue
****************************
** Example for the PDP 10 **
****************************
BEGIN STARTLAB = LABEL
ASSNL('TITLE',STARTLAB)
ASSNL('SUBTTL',' ' VER)
ASSNL('ENTRY',STARTLAB)
ASSNL('RADIX','10')
ASS(STARTLAB,'0')
ASSNL(MOVE,'1,[SIXBIT/' STARTLAB '/]')
IDENT(OPERAND) :S(RETURN)
ASSNL('MOVEM','^O16,' OPERAND) :(RETURN)
****************************
** Example for the PDP 11 **
****************************
BEGIN STARTLAB = LABEL
ASSNL('.TITLE',LABEL)
ASSNL('.GLOBL',LABEL)
GENLAB(LABEL)
( \( IDENT(SW.DEBUG) IDENT(SW.REENT) ) ASSNL(MOV,'%5,-(%6)') )
DIFFER(SW.REENT)
. ASSNL('SUB','$$REENT,%6')
. ASSNL(MOV,'%6,' REENT.REG)
IDENT(OPERAND) :S(RETURN)
OPERAND = DIFFER(SW.REENT)
. GETROFF(OPERAND)
ASSNL(MOV,'%5,' OPERAND)
ASSNL('ADD','#2,' OPERAND)
:(RETURN)
****************************
** Example for the S/360 ***
****************************
BEGIN STARTLAB = LABEL
T1 = SIZE(STARTLAB)
ASS(STARTLAB,'CSECT')
ASSNL('USING','*,15')
L1 = GETLAB()
ASSNL('B',L1)
ASSNL('DC','AL1(' T1 ')')
ASSNL('DC','CL' T1 "'" STARTLAB "'")
DIFFER(SW.REENT) :F(BENR)
DS('$SAVE',72)
ASS(L1,'STM','14,12,12(13)')
ASSNL('LA','2,' STARTLAB '+4095')
ASSNL('USING',STARTLAB '+4095,2')
( DIFFER(OPERAND) ASSNL('BAL','14,$$STORE') )
ASSNL('L','0,$$REENT')
ASSNL('GETMAIN','R,LV=(0)')
STARTOP = DIFFER(OPERAND) OPERAND
ASSNL('ST','13,4(1)')
ASSNL('ST','1,8(13)')
ASSNL('LR','13,1')
ASSNL('LR','1,15')
ASSNL('USING',STARTLAB ',1')
ASSNL('DROP','15')
:(BEBOTH)
BENR ASS('$SAVE','DS','18F')
ASS(L1,'STM','14,12,12(13)')
( DIFFER(OPERAND) ASSNL('ST','1,' OPERAND) )
ASSNL('ST','13,$SAVE+4')
ASSNL('LR','14,13')
ASSNL('LA','13,$SAVE')
ASSNL('USING','$SAVE,13')
ASSNL('ST','13,8(14)')
STARTLAB = '$SAVE'
ASSNL('LA','2,' STARTLAB '+4095')
ASSNL('USING',STARTLAB '+4095,2')
BEBOTH ( DIFFER(SW.DEBUG) ASSNL('CALL','FERRCK') )
:(RETURN)
NAME: FINISH
USEAGE: Called at FINISH statement.
DESCRIPTION:
-Generate any assembly statements to return from routine.
-Again, best to ignore reenterability.
-SAVEDS contains name,size"name,size"... which must be allocated.
-SAVEDC contains name,contents"name,contents"... which must be
defined as a character string.
-Generate any assembly statements for the end of a program.
****************************
** Example for the PDP 10 **
****************************
FINISH ( ASSNL('JRA','^O16,0(^O16)') )
DSLOOP SAVEDS BREAK.TAB = ASS(T1,'BLOCK',T2) :S(DSLOOP)
DCLOOP SAVEDC BREAK.TAB = ASS(T1,'ASCIZ','"' T2 '"') :S(DCLOOP)
FIBOTH ( ASSNL('LIT') ASSNL('END') ) :(RETURN)
****************************
** Example for the PDP 11 **
****************************
FINISH ( DIFFER(SW.REENT) ASSNL('ADD','$$REENT,%6') )
( \( IDENT(SW.DEBUG) IDENT(SW.REENT) ) ASSNL(MOV,'(%6)+,%5') )
ASSNL('RTS','%5')
( DIFFER(SW.REENT) ASS('$$REENT','.WORD',RADIX(TOTSTORE)) )
DSLOOP SAVEDS BREAK.TAB =
. GENLAB(T1) PUT('.=.+' RADIX(T2)) :S(DSLOOP)
DCLOOP SAVEDC BREAK.TAB = ASS(T1,'.ASCIZ','"' T2 '"') :S(DCLOOP)
ASSNL('.END',STARTLAB) :(RETURN)
****************************
** Example for the S/360 ***
****************************
FINISH DIFFER(SW.REENT) :F(FINNR)
ASSNL('LR','1,13')
. ASSNL('L','13,4(13)') ASSNL('L','0,$$REENT')
. ASSNL('FREEMAIN','R,LV=(0),A=(1)')
. ASSNL('LM','14,12,12(13)')
( DIFFER(STARTOP) ASSNL('BR','14')
. ASS('$$STORE','ST','1,' GETROFF(STARTOP)) )
ASSNL('BR','14')
ASSNL('DS','0D')
ASS('$$REENT','DC','A(' TOTSTORE ')')
:(FIBOTH)
FINNR ASSNL('L','13,$SAVE+4')
ASSNL('LM','14,12,12(13)')
ASSNL('BR','14')
ASSNL('DS','0D')
DSLOOP SAVEDS BREAK.TAB =
. ASS(T1,'DS',(T2 / 4) 'F') :S(DSLOOP)
DCLOOP SAVEDC BREAK.TAB = ASS(T1,"DC","C'" T2 "'"
. "," 4 - REMDR(SIZE(T2),4) "X'00'") :S(DCLOOP)
FIBOTH ( ASSNL('LTORG') ASSNL('END') ) :(RETURN)
NAME: COMMENT
USEAGE: Called to put out a comment in STATE.
DESCRIPTION:
-Break off characters off the variable STATE, 70 at a time
and PUT them out as comment.
****************************
** Example for the PDP 10 **
****************************
COMMENT STATE LEN(69) . T1 = PUT(';' T1) :S(COMMENT)
PUT(';' STATE) :(RETURN)
****************************
** Example for the PDP 11 **
****************************
COMMENT STATE LEN(69) . T1 = PUT(';' T1) :S(COMMENT)
PUT(';' STATE) :(RETURN)
****************************
** Example for the S/360 ***
****************************
COMMENT STATE LEN(69) . T1 = PUT('*' T1) :S(COMMENT)
PUT('*' STATE) :(RETURN)
NAME: RADIX
USEAGE: Called to change the variable RADIX into the assembler radix.
DESCRIPTION:
-Convert RADIX to the appropriate radix, or simply return if
decimal is alright.
****************************
** Example for the PDP 10 **
****************************
RADIX :(RETURN)
****************************
** Example for the PDP 11 **
****************************
RADIX RADIX = DEC2OCT(RADIX) :(RETURN)
****************************
** Example for the S/360 ***
****************************
RADIX :(RETURN)
NAME: STATSRT
USEAGE: Called at the start of each statement.
DESCRIPTION:
-If this is an executable statement, put the statement number
into a register when the DEBUG switch is on.
-Generate a label for other than begin
****************************
** Example for the PDP 10 **
****************************
STATSRT DIFFER(SW.DEBUG) \(
. DIFFER(OPCODE,'DO') DIFFER(OPCODE,'IF')
. DIFFER(OPCODE,'IFANY') DIFFER(OPCODE,'CALLS')
. ) ASS(LABEL,'MOVEI','0,' STATENO)
. :S(RETURN)
( DIFFER(OPCODE,'BEGIN') GENLAB(LABEL) ) :(RETURN)
****************************
** Example for the PDP 11 **
****************************
STATSRT DIFFER(SW.DEBUG) \(
. DIFFER(OPCODE,'DO') DIFFER(OPCODE,'IF')
. DIFFER(OPCODE,'IFANY') DIFFER(OPCODE,'CALLS')
. ) ASS(LABEL,MOV,'#' RADIX(STATENO) ',' REENT.REG)
. :S(RETURN)
( DIFFER(OPCODE,'BEGIN') GENLAB(LABEL) ) :(RETURN)
****************************
** Example for the S/360 ***
****************************
STATSRT DIFFER(SW.DEBUG) \(
. DIFFER(OPCODE,'DO') DIFFER(OPCODE,'IF')
. DIFFER(OPCODE,'IFANY') DIFFER(OPCODE,'CALLS')
. ) ASS(LABEL,'LA','0,' STATENO)
. :S(RETURN)
( DIFFER(OPCODE,'BEGIN') GENLAB(LABEL) ) :(RETURN)
NAME: CALLSRT
USEAGE: Called at begin of CALL for reentrancy or machine dependancy
****************************
** Example for the PDP 10 **
****************************
CALLSRT :(RETURN)
****************************
** Example for the PDP 11 **
****************************
CALLSRT DIFFER(SW.REENT) :F(RETURN)
BLOCK = GETLAB()
DS(BLOCK,2) :(RETURN)
****************************
** Example for the S/360 ***
****************************
CALLSRT :(RETURN)
NAME: GENCALL
USEAGE: Called at the end of a CALLS statement.
DESCRIPTION:
-Generate external linkages
-Generate subroutine jump
-Define enough storage for addresses of parameters
-Reentrant stuff is tricky - - forget it
****************************
** Example for the PDP 10 **
****************************
GENCALL CALLLAB = DIFFER(SW.REENT) GETROFF(CALLLAB)
ASSNL('EXTERN',LOC)
ASSNL('JSA','^O16,' LOC)
( NE(NARG,0) ASS(CALLLAB,'BLOCK',NARG) ) :(RETURN)
****************************
** Example for the PDP 11 **
****************************
GENCALL ASSNL('.GLOBL ',LOC)
( NE(NARG) DIFFER(SW.REENT) ) :S(RENCALL)
ASSNL('JSR','%5,' LOC)
EQ(NARG,0) :S(RETURN)
NARG = NARG * 2
ARGLAB = GETLAB()
ASSNL('BR',ARGLAB)
GENLAB(CALLLAB)
PUT('.=.+' RADIX(NARG))
GENLAB(ARGLAB) :(RETURN)
RENCALL L1 = GETLAB() ; L2 = GETLAB()
BLOCK = GETROFF(CALLLAB)
BLOCK POS(0) BREAK('(') . OFF
DS(CALLLAB,NARG * ADDR.WORD)
ASSNL(MOV,'#' NARG ',' BLOCK)
ASSNL('INCB','1+' BLOCK)
( ASSNL(MOV,'#207,2+' (2 * NARG) '+' BLOCK) )
ASSNL('JSR','%7,' L2)
ASSNL('BR',L1)
( ASS(L2,MOV,'%5,-(%6)') )
ASSNL(MOV,'%3,%5')
ASSNL('ADD','#' OFF ',%5')
ASSNL('JMP',LOC)
GENLAB(L1) :(RETURN)
****************************
** Example for the S/360 ***
****************************
GENCALL CALLLAB = DIFFER(SW.REENT) GETROFF(CALLLAB)
( NE(NARG,0) ASSNL('LA','1,' CALLLAB) DS(CALLLAB,NARG * 4) )
ASSNL('CALL',LOC) :(RETURN)
NAME: GENLOG
USEAGE: Called to handle logical operations.
DESCRIPTION:
-Check for type (W, Y, 1, etc) and code a special section for each
****************************
** Example for the PDP 10 **
****************************
GENLOG IDENT(OP,'A') :S(GENLB)
IDENT(L.F,'1') :S(GENL1)
LOAD.R2(L.ADDR,L.F,R0)
( IDENT(R.ADDR,'#0') ASSNL('JUMP' OP,R0 ',' LOC) ) :S(RETURN)
OP = COMPOP()
R.ADDR POS(0) '#' = :F(GENL2)
ASSNL('CAI' OP, R0 ',' R.ADDR) :(GENLB)
GENL2 ( IDENT(R.F,'W') ASSNL('CAM' OP,R0 ',' R.ADDR) ) :S(GENLB)
( LOAD.R() ASSNL('CAM' OP,R0 ',' R1) ) :(GENLB)
GENLB ASSNL('JRST',LOC) :(RETURN)
GENL1 ASSNL(MOVE,R0 ',' L.ADDR)
T1 = TAB.MASK(L.ENTRY)
SIDE = 'TLN'
SIDE = GT(T1,17) 'TRN'
T1 = GT(T1,17) T1 - 18
R.A = R.ADDR ; R.ADDR = '^B1' DUPL('0',17 - T1)
IDENT(R.A,'#1') :S(GENLBT)
DIFFER(R.A,'#0') :S(LOGERR)
OP = IDENT(OP,'E') 'N' :S(GENLBT)
OP = IDENT(OP,'N') 'E' :S(GENLBT)
LOGERR ( ERROR('BIT TESTS SUPPORT ONLY (EQ,NE) FOR (0,1)') ) :S(RETURN)
GENLBT ASSNL(SIDE OP,R0 ',' R.ADDR) :(GENLB)
****************************
** Example for the PDP 11 **
****************************
GENLOG IDENT(OP,'R') :S(GENLB)
IDENT(L.F,'1') :S(GENL1)
( IDENT(R.ADDR,'#0') GENONE('TST') ) :S(GENLB)
( FLIP() GENTWO('CMP') )
GENLB ASSNL('B' OP,LOC) :(RETURN)
GENL1 R.A = R.ADDR ; R.ADDR = '#' TAB.MASK(R.ENTRY)
GENTWO('BIT')
IDENT(R.A,'#0') :S(GENLB)
OP = IDENT(R.A,'#1') IDENT(OP,'EQ') 'NE' :S(GENLB)
OP = IDENT(R.A,'#1') IDENT(OP,'NE') 'EQ' :S(GENLB)
( ERROR('BIT TESTS SUPPORT ONLY (EQ,NE) FOR (0,1)') ) :(RETURN)
****************************
** Example for the S/360 ***
****************************
GENLOG IDENT(OP,'') :S(GENLB)
IDENT(L.F,'1') :S(GENL1)
( DIFFER(R.ADDR,'#0') GENTWO('C') ) :S(GENLB)
DIFFER(R.F,'Y') :S(GENLTR)
( DIFFER(OP,'E') DIFFER(OP,'NE') ) :F(GENL1)
GENLTR R.A = R.ADDR ; R.ADDR = 128
OP = IDENT(OP,'NL') 'E' :S(GENL1A)
OP = IDENT(OP,'L') 'NE' :S(GENL1A)
GENONER('LTR', '#' R0)
GENLB ASSNL('B' OP,LOC) :(RETURN)
GENL1 R.A = R.ADDR ; R.ADDR = TAB.MASK(R.ENTRY)
GENL1A ASSNL('TM',L.ADDR ',' R.ADDR)
IDENT(R.A,'#0') :S(GENLB)
OP = IDENT(R.A,'#1') IDENT(OP,'E') 'NE' :S(GENLB)
OP = IDENT(R.A,'#1') IDENT(OP,'NE') 'E' :S(GENLB)
ERROR('BIT TESTS SUPPORT ONLY (EQ,NE) FOR (0,1)') :(RETURN)
NAME: ASS
USEAGE: Used to put out assembly statements
DESCRIPTION:
-Label is in T1; op code in T2; operand in T3; comment in T4.
-Do whatever is necessary to PUT out a string of assembly code.
-Might have to do something special when there is a label, but
nothing else in the output.
-SAVECOM sometimes contains a leftover comment, that should be
tacked on to the comment field and then nulled out
****************************
** Example for the PDP 10 **
****************************
ASS T1 = IDENT(T2) DIFFER(T1) T1 ':' :S(ASS1)
T1 = DIFFER(T1) T1 ':'
ASS1 T4 = T4 SAVECOM
SAVECOM =
T2 = GE(SIZE(T2),6) T2 ' '
* T3 ',(' = ',0('
T3 = DIFFER(T4) RPAD(T3,24) ';' T4
( PUT( RPAD(T1,8) RPAD(T2,8) T3 ) ) :(RETURN)
****************************
** Example for the PDP 11 **
****************************
ASS T1 = IDENT(T2) DIFFER(T1) T1 '=.' :S(ASS1)
T1 = DIFFER(T1) T1 ':'
ASS1 T4 = T4 SAVECOM
SAVECOM =
T2 = GE(SIZE(T2),5) T2 ' '
T3 = DIFFER(T4) RPAD(T3,20) ';' T4
( PUT( RPAD(T1,10) RPAD(T2,5) T3) ) :(RETURN)
****************************
** Example for the S/360 ***
****************************
ASS T1 = IDENT(T2) DIFFER(T1) T1 ' EQU *' :S(ASS1)
ASS1 T4 = T4 SAVECOM
SAVECOM =
T2 = GE(SIZE(T2),6) T2 ' '
T3 ',(' = ',0('
T3 POS(0) '(' = '0('
T3 = DIFFER(T4) RPAD(T3,20) ' ;' T4
PUT( RPAD(T1,9) RPAD(T2,6) T3 ) :(RETURN)
NAME: GENLOAD
USEAGE: Called to load ADDR into register R.
****************************
** Example for the PDP 10 **
****************************
GENLOAD ASSNL(MOVE,R ',' ADDR) :(RETURN)
****************************
** Example for the PDP 11 **
****************************
GENLOAD ASSNL(MOV,ADDR ',' R) :(RETURN)
****************************
** Example for the S/360 ***
****************************
GENLOAD ASSNL('L',R ',' ADDR) :(RETURN)
NAME: GETREG
USEAGE: Called to return a register for handling a sequence.
DESCRIPTION:
-Returns register number based on:
-WHEN=1 for the right of an op
-WHEN=2 for the left of an op
****************************
** Example for the PDP 10 **
****************************
GETREG GETREG = WHEN + 2 :(RETURN)
****************************
** Example for the PDP 11 **
****************************
GETREG GETREG = '%' (WHEN + 1) :(RETURN)
****************************
** Example for the S/360 ***
****************************
GETREG GETREG = WHEN + 2 :(RETURN)
NAME: TABSTM
USEAGE: Called during *1 definitions to do anything machine
dependent.
DESCRIPTION:
-If there is something funny about the addressing, humor it.
-A mask might have to be set up for bit fields.
****************************
** Example for the PDP 10 **
****************************
TABSTM MASK = CKTYPE(LF,'1') LOW
IDENT(BASE,'REG') DIFFER(SW.REG) PUT('REG=' BASE.REG)
:(RETURN)
****************************
** Example for the PDP 11 **
****************************
TABSTM MASK = CKTYPE(LF,'1') RADIX( 2 ** (WSIZE - LOW - 1) )
IDENT(BASE,'REG') DIFFER(SW.REG) PUT('REG=' BASE.REG)
CKTYPE(LF,'Y') :F(RETURN)
OFF = OFF + 1 - (LOW / BSIZE) :(RETURN)
****************************
** Example for the S/360 ***
****************************
TABSTM MASK = CKTYPE(LF,'1')
. 2 ** (BSIZE - REMDR(LOW,BSIZE) - 1)
MASK = CKTYPE(LF,'Y') 255
OFF = OFF + (LOW / BSIZE) :(RETURN)
NAME: CKREGD
USEAGE: Check for machine dependent optimizaton.
DESCRIPTION:
-RETURN if no optimization is possible.
-FRETURN if optimization is possible, for example, on machines with
indirect addressing:
-If we are not already indirect addressing, and the offset is
zero, reset the BASELOC to the indirect of ADDR.
****************************
** Example for the PDP 10 **
****************************
CKREGD DIFFER(SW.OPT2) :F(RETURN)
ADDR POS(0) '@' :S(RETURN)
BASELOC = EQ(OFF,0) '@' ADDR :F(RETURN)
LREG = :(FRETURN)
****************************
** Example for the PDP 11 **
****************************
CKREGD DIFFER(SW.OPT2) :F(RETURN)
ADDR POS(0) '@' :S(RETURN)
BASELOC = EQ(OFF,0) '@' ADDR :F(RETURN)
LREG = :(FRETURN)
****************************
** Example for the S/360 ***
****************************
CKREGD DIFFER(SW.OPT2) :(RETURN)
* * * 1
* * * 11
*** 1 1
******* 1
*** 1
* * * 1
* * * 11111
SECTION II
----------
USER OP FUNCTIONS
-----------------
This section contains one function for each *1 operation.
NAME: O.movei (for op: <-)
O.move (for op: <-)
O.add (for op: +)
etc.
USEAGE: Called for each op
DESCRIPTION:
-Generates assembly for each op, using
appropriate variables.
-Usually uses GENONE or GENTWO
****************************
** Example for the PDP 10 **
****************************
O.MOVEI OP = MOVE
CKTYPET(TF,'B',R.TYPE) :F(O.MOVE)
( DIFFER(L.F,'W') ERROR('ADDRESS CONSTANTS FOR WORDS ONLY') )
ASSNL('MOVEI',R1 ',' R.ADDR) :(DOMOV)
**
O.MOVE IDENT(L.F,'1') :S(MOV1)
OP = IDENT(L.F,'W') IDENT(R.ADDR,'#0') 'SETZM' :S(O.ONE)
LOAD.R()
DOMOV ( IDENT(L.F,'W') DO.OP() ) :S(RETURN)
STORE.L2(R1) :(RETURN)
MOV1 R.A = R.ADDR
R.ADDR = '#[^B1' DUPL('0',35 - TAB.MASK(L.ENTRY)) ']'
R.F = 'W' ; L.F = 'W'
OP = IDENT(R.A,'#0') 'ANDCA' :S(O.TWO)
OP = IDENT(R.A,'#1') 'IOR' :S(O.TWO)
ERROR('BIT MOVES NOT IMPLEMENTED') :(RETURN)
**
O.GOTO ASSNL('JRST',LEFT) :(RETURN)
**
O.LCR R.ADDR = IDENT(L.F,'W') ASSNL('SETO',R0 ',') :S(LCR1)
( ASSNL('LDB',R0 ',' POINT(L.ENTRY,'[-1]')) )
LCR1 ASSNL('XORM',R0 ',' L.ADDR) :(RETURN)
**
O.LSHR OP = 'LSH'
R.ADDR '#' = '#-' :S(O.LSH)
O.LSH
O.TWOI GENTWOI(OP) :(RETURN)
**
O.ONE GENONE(OP) :(RETURN)
**
O.MOD OP = 'IDIV'
( LOAD.R() DO.OP() STORE.L2(R1) ) :(RETURN)
**
O.ADD OP = IDENT(L.F,'W') IDENT(R.ADDR,'#1') 'AOS' :S(O.ONE)F(O.TWO)
**
O.SUB OP = IDENT(L.F,'W') IDENT(R.ADDR,'#1') 'SOS' :S(O.ONE)F(O.TWO)
**
O.IOR ;O.AND ;O.XOR ;O.IMUL ;O.IDIV
O.TWO GENTWO(OP) :(RETURN)
**
****************************
** Example for the PDP 11 **
****************************
O.MOVA OP = MOV
CKTYPET(TF,'B',R.TYPE) :F(O.TWO)
R.ADDR = '#' R.ADDR
R.ADDR POS(0) '#@' = :S(O.TWO)
R.ADDR MOVA.PARSE :S(REGOFF)
DIFFER(SW.PIC) :F(O.TWO)
R.ADDR POS(0) '#' REM . OFF :F(O.TWO)
OFF = OFF '-.'
LREG = '%7'
REGOFF LREG = '%0'
. DIFFER(SW.REENT SW.PIC)
. ASSNL(MOV,LREG ',%0')
R.ADDR = LREG
( DIFFER(OFF) OFFREG(R.ADDR)
. ASSNL('ADD','#' OFF ',' R.ADDR) ) :(O.TWO)
**
O.ADD OP = IDENT(R.ADDR,'#1') 'INC' :S(O.ONE)F(O.TWOCK)
**
O.SUB OP = IDENT(R.ADDR,'#1') 'DEC' :S(O.ONE)F(O.TWOCK)
**
O.TWOCK IDENT(R.F,'Y') :S(O.40)F(O.TWO)
**
O.BIS :(O.TWO)
**
O.MOV IDENT(L.F,'1') :S(MOV1)
OP = IDENT(R.ADDR,'#0') 'CLR' :S(O.ONE)F(O.TWO)
MOV1 R.A = R.ADDR ; R.ADDR = '#' TAB.MASK(L.ENTRY)
OP = IDENT(R.A,'#0') 'BIC' :S(O.TWO)
OP = IDENT(R.A,'#1') 'BIS' :S(O.TWO)
GENTWO('BIC')
( ASSNL('BIT','#' TAB.MASK(R.ENTRY) ',' R.A) )
LAB = GETLAB()
ASSNL('BEQ',LAB)
( GENTWO('BIS') GENLAB(LAB) ) :(RETURN)
**
O.MUL DIFFER(SW.M40) :S(O.40)
ASSNL(MOV,'#177304,%0')
( ASSCK(MOV,L.ADDR ',(%0)+') )
( ASSCK(MOV,R.ADDR ',(%0)') )
R.ADDR = '-(%0)' ; OP = MOV :(O.TWO)
**
O.MOD
O.DIV DIFFER(SW.M40) :S(O.40)
ASSNL(MOV,'#177304,%0')
( ASSCK(MOV,L.ADDR ',(%0)') )
ASSCK(MOV,R.ADDR ',@#177300')
R.ADDR = '(%0)'
R.ADDR = IDENT(OP,'MOD') '-' R.ADDR
OP = MOV :(O.TWO)
**
O.ASR IDENT(R.ADDR,'#1') :S(O.ONE)
R.ADDR '#' = '#-' :S(O.ASH)
O.ASL IDENT(R.ADDR,'#1') :S(O.ONE)
O.ASH OP = 'ASH'
( IDENT(SW.M40) ERROR('SHIFTING OTHER THAN 1 NOT SUPPORTED')
. ) :S(RETURN)F(O.40)
**
O.BIC ASSCK(MOV,R.ADDR ',%0')
ASSNL('COM','%0')
R.ADDR = '%0' :(O.TWO)
**
O.COM IDENT(L.F,'1') :F(O.ONE)
OP = 'XOR'
R.ADDR = '#' TAB.MASK(L.ENTRY)
L.F = 'W' ; R.F = 'W'
O.XOR DIFFER(SW.M40) :S(O.X40)
ASSCK(MOV,R.ADDR ',%0')
ASSCK('BIC',L.ADDR ',%0')
ASSCK('BIC',R.ADDR ',' L.ADDR)
R.ADDR = '%0' ; OP = 'BIS' :(O.TWO)
O.X40 ASSCK(MOV,R.ADDR ',%0')
ASSCK(OP,'%0,' L.ADDR) :(RETURN)
**
O.40 ASSCK(MOV,L.ADDR ',%0')
R.ADDR = IDENT(R.F,'Y') ASSNL('MOVB',R.ADDR ',%1') '%1'
( IDENT(OP,'MOD') ASSNL('DIV', R.ADDR ',%0')
. ASSCK(MOV,'%1,' L.ADDR) ) :S(RETURN)
ASSNL(OP,R.ADDR ',%0')
ASSCK(MOV,'%0,' L.ADDR) :(RETURN)
**
O.GOTO ASSNL('JMP',LEFT) :(RETURN)
**
O.ONE GENONE(OP) :(RETURN)
**
O.TWO GENTWO(OP) :(RETURN)
**
****************************
** Example for the S/360 ***
****************************
O.LA CKTYPET(TF,'B',R.TYPE) :F(O.L)
ASSNL('LA',R0 ',' R.ADDR)
STORE.L() :(RETURN)
**
O.L IDENT(L.F,'1') :S(MOV1)
( LOAD.R2(R.ADDR,R.F,R0) STORE.L() ) :(RETURN)
MOV1 R.A = R.ADDR ; R.ADDR = TAB.MASK(L.ENTRY)
CR = L.ADDR ',255-' R.ADDR
R.ADDR = L.ADDR ',' R.ADDR
( IDENT(R.A,'#0') ASSNL('NI',CR) ) :S(RETURN)
( IDENT(R.A,'#1') ASSNL('OI',R.ADDR) ) :S(RETURN)
ASSNL('NI',CR)
ASSNL('TM',R.A ',' TAB.MASK(R.ENTRY))
LAB = GETLAB()
ASSNL('BE',LAB)
( ASSNL('OI',R.ADDR) GENLAB(LAB) ) :(RETURN)
**
O.S ( IDENT(R.ADDR,'#1') GENONER('BCTR','#0') ) :S(RETURN)F(O.TWO)
**
O.GOTO ASSNL('B',LEFT) :(RETURN)
**
O.LCR R.ADDR = '#0'
O.SLL
O.SRL
O.ONE GENONE(OP) :(RETURN)
**
O.MOD OP = 'D'
DIFFER(L.F,'W') :S(O.TWO)
( LOAD.L() ASSNL('SRDA',R0 ',32') DO.OP() STORE.L() ) :(RETURN)
**
O.D DIFFER(L.F,'W') :S(O.TWO)
( LOAD.L() ASSNL('SRDA',R0 ',32') DO.OP() STORE.L2(R1) )
. :(RETURN)
**
O.M DIFFER(L.F,'W') :S(O.TWO)
( LOAD.R2(L.ADDR,L.F,R1) DO.OP() STORE.L2(R1) ) :(RETURN)
**
O.A ;O.O ;O.N ;O.X
O.TWO GENTWO(OP) :(RETURN)
**
* * * 1
* * * 11
*** 1 1
******* 1
*** 1
* * * 1
* * * 11111
SECTION III
-----------
USER CONVENIENCE FUNCTIONS
--------------------------
These functions are in no way manditory -- but they represent
functions that have proved convenient for various
implementations.
All functions must be defined in INIT (see INIT for examples).
NAME: GENONE
USAGE: Usually used to handle one operand operations.
DESCRIPTION: (Typically)
-Get the operand into a register, on some machines
(Try to use LOAD.x)
-Do the operation
(Try to use DO.OP)
-Store it away, on some machines
(Try to use STORE.x)
****************************
** Example for the PDP 10 **
****************************
GENONE ( IDENT(L.F,'W') ASSNL(OP,L.ADDR) ) :S(RETURN)
LOAD.R2(L.ADDR,L.F,R0)
ASSNL(OP,R0)
STORE.L()
:(RETURN)
****************************
** Example for the PDP 11 **
****************************
GENONE OP = IDENT(R.F,'Y') OP 'B'
OFFLOC(L.ADDR)
ASSNL(OP,L.ADDR) :(RETURN)
****************************
** Example for the S/360 ***
****************************
GENONE R.ADDR POS(0) '#' = :S(GOTLIT1)
LOAD.R2(R.ADDR,R.F,R1)
R.ADDR = '0(' R1 ')'
GOTLIT1 LOAD.L()
( IDENT(R.F,'Y') ASSNL('SLA',R0 ',24') ASSNL('SRA',R0 ',24') )
ASSNL(OP,R0 ',' R.ADDR)
( DIFFER(OP,'LTR') STORE.L() ) :(RETURN)
NAME: GENTWO
USAGE: Usually used to handle two operand operations.
DESCRIPTION: (Typically)
-Similar to GENONE, except for two operands
****************************
** Example for the PDP 10 **
****************************
GENTWOI R.ADDR POS(0) '#' = :S(GOTLIT1)
R.ADDR '@' :S(GOTIND)
R.ADDR = '@' R.ADDR :(GOTLIT1)
GOTIND LOAD.R()
R.ADDR = '0(' R1 ')'
GOTLIT1 LOAD.R2(L.ADDR,L.F,R0)
ASSNL(OP,R0 ',' R.ADDR)
( IDENT(L.F,'W') ASSNL('MOVEM',R0 ',' L.ADDR) ) :S(RETURN)
STORE.L() :(RETURN)
****************************
** Example for the PDP 11 **
****************************
GENTWO ( DIFFER(OP,'CMP') OFFLOC(L.ADDR) )
OP = IDENT(LR,'YY') OP 'B'
ASSNL(OP,R.ADDR ',' L.ADDR) :(RETURN)
****************************
** Example for the S/360 ***
****************************
GENTWO LOAD.L()
DO.OP()
( DIFFER(OP,'C') STORE.L() ) :(RETURN)
NAME: LOAD.
USAGE: Usually used to handle to first of two operands.
DESCRIPTION: (Typically)
-If your machine needs it, get the operand into a register.
-Many machines have immediate loads which can be used:
-When the operand is a constant (starts with "#")
-Will convert to integer
-And is in some range
-Do the appropriate loads for words, half-words, or bytes
-NOTE: This function might be LOAD.L or LOAD.R or something
flexible that allows registers or addresses to be parameters.
There might also be a need for other functions with even more
flexibility (LOAD.L2, etc.) defined to start at the same
location.
****************************
** Example for the PDP 10 **
****************************
LOAD.R R.ADDR POS(0) '#' = :F(NOTLIT)
R.ADDR = CONVERT(R.ADDR,'INTEGER') :F(NOTINT)
( LT(R.ADDR,HALF) GT(R.ADDR,-HALF) ASSNL('HRREI',R1 ',' R.ADDR)
. ) :S(RETURN)
R.A = R.ADDR / HALF
R.ADDR = REMDR(R.ADDR,HALF)
( LT(R.ADDR,HALF) GT(R.ADDR,-HALF) ASSNL('MOVSI',R1 ',' R.ADDR)
. ) :S(RETURN)
NOTINT ( IDENT(OP,MOVE) ASSNL(MOVE,R1 ',[' R.ADDR ']') ) :S(RETURN)
NOTLIT ( IDENT(R.F,'W') ASSNL(MOVE,R1 ',' R.ADDR) ) :S(RETURN)
( IDENT(R.F,'Y') ASSNL('LDB',R1 ',' POINT(R.ENTRY,R.ADDR)) )
. :S(RETURN)
( IDENT(R.F,'H') ASSNL(SIDECK(R.ENTRY),R1 ',' R.ADDR) )
. :S(RETURN)
:(RETURN)
****************************
** Example for the PDP 11 **
****************************
This function is not used for the PDP 11
****************************
** Example for the S/360 ***
****************************
LOAD.L R.ADDR POS(0) '#' = :F(NOTLIT)
R.ADDR = CONVERT(R.ADDR,'INTEGER') :F(NOTINT)
R.ADDR = L.ADDR
. LE(R.ADDR,4095) GE(R.ADDR,0)
. DIFFER(OP,'C') DIFFER(OP,'S') DIFFER(OP,'D')
. ASSNL('LA',R0 ',' R.ADDR) :S(RETURN)
R.ADDR = '=A(' R.ADDR ')'
R.F = 'W'
NOTINT ( IDENT(OP,'L') ASSNL('L',R0 ',' R.ADDR) ) :S(RETURN)
NOTLIT ( IDENT(L.F,'W') ASSNL('L',R0 ',' L.ADDR) ) :S(RETURN)
( IDENT(L.F,'Y') ASSNL('IC',R0 ',' L.ADDR) ) :S(RETURN)
( IDENT(L.F,'H') ASSNL('LH',R0 ',' L.ADDR) ) :(RETURN)
NAME: DO.OP
USEAGE: Does the operation with the second of two operands.
DESCRIPTION: (Typically)
-If possible, do the operation from the operand to the register.
-You might have to go into a second register and then do the
operation from the second to the first.
****************************
** Example for the PDP 10 **
****************************
DO.OP OFFLOC(L.ADDR)
IDENT(L.F,'W') :F(DO.OPY)
( \(DIFFER(OP,'SUB') DIFFER(OP,'IDIV'))
. ASSNL('EXCH',R1 ',' L.ADDR) )
ASSNL(OP 'M',R1 ',' L.ADDR) :(RETURN)
DO.OPY ( IDENT(L.F,'Y') ASSNL('LDB',R0 ',' POINT(L.ENTRY,L.ADDR))
. ASSNL(OP,R0 ',' R1) ) :S(RETURN)
( IDENT(L.F,'H') ASSNL(SIDECK(L.ENTRY),R0 ',' L.ADDR)
. ASSNL(OP,R0 ',' R1) ) :S(RETURN)
ERROR('UNSUPPORTED MODE') :(RETURN)
****************************
** Example for the PDP 11 **
****************************
This function is not used for the PDP 11
****************************
** Example for the S/360 ***
****************************
DO.OP ( IDENT(R.F,'W') ASSNL(OP,R0 ',' R.ADDR) ) :S(RETURN)
( \(DIFFER(OP,'M') DIFFER(OP,'D') )
. ERROR('NON-WORD MULTIPLY OR DIVIDE NONFUNCTIONAL') )
IDENT(R.F,'Y') :F(DO.OP1)
ASSNL('IC',R1 ',' R.ADDR)
( DIFFER(OP,'L') ASSNL('SLDL',R0 ',24')
. ASSNL('SRA',R0 ',24') ASSNL('SRA',R1 ',24') )
ASSNL(OP 'R',R0 ',' R1) :(RETURN)
DO.OP1 ( IDENT(R.F,'H') ASSNL(OP 'H',R0 ',' R.ADDR) ) :S(RETURN)
ERROR('UNSUPPORTED MODE') :(RETURN)
NAME: STORE.
USEAGE: Store the result away in the first operand.
DESCRIPTION:
-Get the result back out of the register and into storage.
****************************
** Example for the PDP 10 **
****************************
STORE.L OFFLOC(L.ADDR)
IDENT(L.F,'W') :S(RETURN)
( IDENT(L.F,'Y') ASSNL('DPB',R0 ',' POINT(L.ENTRY,L.ADDR))
. ) :S(RETURN)
( IDENT(L.F,'H') ASSNL(SIDECK(R.ENTRY) 'M',R0 ',' L.ADDR)
. ) :S(RETURN)
ERROR('UNSUPPORTED MODE') :(RETURN)
****************************
** Example for the PDP 11 **
****************************
This function is not used for the PDP 11
****************************
** Example for the S/360 ***
****************************
STORE.L OFFLOC(L.ADDR)
( IDENT(L.F,'W') ASSNL('ST',R0 ',' L.ADDR) ) :S(RETURN)
( IDENT(L.F,'Y') ASSNL('STC',R0 ',' L.ADDR) ) :S(RETURN)
( IDENT(L.F,'H') ASSNL('STH',R0 ',' L.ADDR) ) :S(RETURN)
ERROR('UNSUPPORTED MODE') :(RETURN)
NAME: GETROFF
USEAGE: Change an address to register and offset for
reenterability
DESCRIPTION:
-LAB contains the core location name. REENT.REG is the base
address of the reentrant area. REENT.OFF is a table mapping core
locations into offsets within the reentrant area.
****************************
** Example for the PDP 10 **
****************************
GETROFF GETROFF = REENT.OFF<LAB> '(' REENT.REG ')' :(RETURN)
****************************
** Example for the PDP 11 **
****************************
GETROFF GETROFF = REENT.OFF<LAB> '(' REENT.REG ')' :(RETURN)
****************************
** Example for the S/360 ***
****************************
GETROFF GETROFF = REENT.OFF<LAB> '(' REENT.REG ')' :(RETURN)
NAME: ASSCK
USEAGE: Used on the PDP11 to call OFFLOC for optimization
****************************
** Example for the PDP 10 **
****************************
This function is not used for the PDP 10
****************************
** Example for the PDP 11 **
****************************
ASSCK L.ADDR POS(0) BREAK(',') . T1
OFFLOC(T1)
GENONE OP = IDENT(R.F,'Y') OP 'B'
OFFLOC(L.ADDR)
ASSNL(OP,L.ADDR) :(RETURN)
****************************
** Example for the S/360 ***
****************************
This function is not used for the S/360
NAME: SIDECK
USEAGE: Used on the PDP10 to determine appropriate halfword used.
****************************
** Example for the PDP 10 **
****************************
SIDECK SIDECK = 'HRR'
SIDECK = IDENT( TAB.RANGE(ENTRY ) , '0,17' ) 'HLR' :(RETURN)
****************************
** Example for the PDP 11 **
****************************
This function is not used for the PDP 11
****************************
** Example for the S/360 ***
****************************
This function is not used for the S/360
NAME: POINT
USEAGE: Used on the PDP10 to build a pointer for byte operations.
****************************
** Example for the PDP 10 **
****************************
POINT LOW = TAB.RANGE(ENTRY)
LOW ',' REM . HIGH =
POINT = '[ POINT ' (HIGH - LOW + 1) ',' ADDR
. ',' HIGH ']' :(RETURN)
****************************
** Example for the PDP 11 **
****************************
This function is not used for the PDP 11
****************************
** Example for the S/360 ***
****************************
This function is not used for the S/360
* * * 1
* * * 11
*** 1 1
******* 1
*** 1
* * * 1
* * * 11111
SECTION IV
----------
VARIABLES AND REGISTERS USED
----------------------------
This section contains a listing a values that are placed in variables
for your use, and the registers that are used on the destination
machine.
VARIABLE CONTAINS
======== =========
R.ADDR The address of the end of the right sequence
L.ADDR Same for left
R.F Type of right hand sequence
Y bYte
W Word
1 1 bit
L Less than a word (unused)
G Greater than a word (unused)
L.F Same for left
R.ENTRY User defined data type for right with:
TAB.LEN() Length in addresses
TAB.OFF() Offset in addresses
TAB.TYPE() Type
TAB.BASE() Name of physical address
TAB.MASK() Bit position
TAB.RANGE() Number of bits
L.ENTRY Same for left
REGISTER NAME USE
============= ===
none first register to chain thru a sequence (from GETREG)
none second register to chain thru a sequence (from GETREG)
R0 used to load first operand
R1 used to load the second operand
REENT.REG optional register used for reenterable coding
BASE.REG optional register used to optimize based variables
none subroutine call register
* * * 1
* * * 11
*** 1 1
******* 1
*** 1
* * * 1
* * * 11111
SECTION V
---------
HANDY FUNCTIONS YOU CAN USE
---------------------------
These functions are supplied to you for writing your functions. If there
is a function that does what you want, it is highly recommended that you
use it.
NAME: PUT
DEF: DEFINE('PUT(STRING)')
USEAGE: Puts STRING into the punch file
NAME: GENLAB
DEF: DEFINE('GENLAB(LABEL)')
USEAGE: Puts LABEL out as a label.
NAME: FILLTAB
DEF: DEFINE('FILLTAB(FILLTAB,TEMP)')
USEAGE: Fills a table
DESCRIPTION:
-TEMP is a string of the form name,contents"name,contents"... which
is broken up and put in the table FILLTAB.
NAME: ERROR
DEF: DEFINE('ERROR(MESS,ETYPE)')
USEAGE: Puts out an error message
DESCRIPTION: MESS contains the error message
NAME: SETTYPE
DEF: DEFINE('SETTYPE(POS,CHAR)')
USEAGE: Set a particular positon of a type field.
DESCRIPTION:
-The variable TYPE is set
-POS contains the position
NAME: GETTYPE
DEF: DEFINE('GETTYPE(POS)')
USEAGE: Get a type field.
DESCRIPTION:
-Gotten from variable TYPE
-POS contains the position
NAME: CKTYPE
DEF: DEFINE('CKTYPE(POS,CHAR)')
USEAGE: Checks for a type field
DESCRIPTION:
-Check in variable TYPE
-POS contains the position
-CHAR contains the type to be checked for
-RETURN or FRETURN, as appropriate
NAME: DEC2OCT
DEF: DEFINE('DEC2OCT(N)')
USEAGE: Decimal to octal converter
DESCRIPTION:
-N is decimal, and is converted to octal and returned.
NAME: FLIP
DEF: DEFINE('FLIP()')
USEAGE: Interchanges the right and left sides
DESCRIPTION:
-Can be called from the code generators to flip the appropriate
variables.
NAME: GETLAB
DEF: DEFINE('GETLAB()')
USEAGE: Returns a unique label
NAME: DS
DEF: DEFINE('DS(BASE,LEN)')
USEAGE: Called when storage is needed.
DESCRIPTION:
-BASE is the name and LEN is the length.
-Done by tacking onto SAVEDS
* * * 1
* * * 11
*** 1 1
******* 1
*** 1
* * * 1
* * * 11111
SECTION VI
----------
OPTIMIZATION
------------
This section describes the automatic register optimization facilities
available in the *1 system. In general, the machine independent section
maintains knowledge of what is in registers. This is done by the machine
dependent parts calling functions that maintain the information.
NAME: PUTREG
DEF: DEFINE('PUTREG(R,ADDR)')
USEAGE: Called to inform system that register R now contains ADDR.
NAME: OFFREG
DEF: DEFINE('OFFREG(R)')
USEAGE: Called to inform system that register R is now unreliable.
NAME: CLRREG
DEF: DEFINE('CLRREG()')
USEAGE: Called to inform system that all registers are now unreliable.
NAME: OFFLOC
DEF: DEFINE('OFFLOC(LOC)')
USEAGE: Called to inform system that location ADDR has been changed.