home *** CD-ROM | disk | FTP | other *** search
- Subject: v07i077: A BASIC Interpreter, Part05/06
- Newsgroups: mod.sources
- Approved: mirror!rs
-
- Submitted by: phil@Cs.Ucl.AC.UK
- Mod.sources: Volume 7, Issue 77
- Archive-name: basic/Part05
-
- # Shar file shar05 (of 6)
- #
- # This is a shell archive containing the following files :-
- # pdp11/assist.s
- # pdp11/conf.h
- # pdp11/fpassist.s
- # pdp11/lfunc.s
- # pdp11/nfp.s
- # pdp11/term.c
- # pyramid/Makefile
- # ------------------------------
- # This is a shell archive, shar, format file.
- # To unarchive, feed this text into /bin/sh in the directory
- # you wish the files to be in.
-
- echo x - pdp11/assist.s 1>&2
- sed 's/^X//' > pdp11/assist.s << 'End of pdp11/assist.s'
- X/ (c) P. (Rabbit) Cockcroft 1982
- X/ This file contains machine code routines that either can't
- X/ be implemented or are very slow in C.
- X/
- X
- X/ When the 'shell' command was first added it was noticed that
- X/ it would bus-error about five times ( an old form of memory
- X/ allocation was being used at the time ) before it started to
- X/ do the wait. The reason for this is rather awful. In the call
- X/ it uses _nargs to find how many arguments it has got. This is
- X/ a routine that will not work in split i and d space, since it tries
- X/ to access the text segment.
- X/ The routine was thus taken from the C library and has been changed
- X/ to need no parameters. It just returns -1 on error or the waited for's
- X/ process id.
- X/
- X/ pid == -1 if error
- X
- X.globl _wait, cerror
- X
- Xwait = 7.
- X
- X_wait:
- X mov r5,-(sp)
- X mov sp,r5
- X sys wait
- X bec 1f
- X jmp cerror
- X1:
- X tst 4(r5)
- X beq 1f
- X mov r1,*4(r5)
- X1:
- X mov (sp)+,r5
- X rts pc
- X
- X/ getch() is used all over the place to get the next character on the line.
- X/ It uses 'point' ( _point ) as the pointer to the next character.
- X/ It skips over all leading spaces.
- X/ It was put into machine code for speed since it does not have to
- X/ call csv and cret ( the C subroutine call and return routines ).
- X/ this saves a lot of time. It can also be written more efficiently
- X/ in machine code.
- X/
- X
- X.text
- X.globl _point , _getch
- X
- X_getch:
- X mov _point,r1
- X1: cmpb $40,(r1)+ / ignore spaces
- X beq 1b
- X mov r1,_point
- X clr r0
- X bisb -(r1),r0
- X rts pc
- X
- X/ check() is used by many routines that want to know if there is any
- X/ garbage characters after its arguments. e.g. in 'goto' there
- X/ should be nothing after the line number. It gives a SYNTAX
- X/ error if the next character is not a terminator.
- X/ check() was also taken out of C for speed reasons.
- X
- X.globl _point , _check , _elsecount , _error
- X
- XELSE= 0351
- X
- X_check:
- X mov _point,r0
- X1: cmpb $40,(r0)+
- X beq 1b
- X movb -(r0),r1
- X beq 1f
- X cmpb r1,$':
- X beq 1f
- X cmpb r1,$ELSE
- X bne 2f
- X tstb _elsecount
- X beq 2f
- X1: mov r0,_point
- X rts pc
- X2: mov $1,-(sp) / syntax error
- X jsr pc,_error
- X
- X/ startfp() this is called in main to intialise the floating point
- X/ hardware if it is used. it is only called once to set up fpfunc()
- X/ this routine does nothing in non-floating point hardware machines
- X/
- X.globl _startfp , _fpfunc
- X
- X_startfp:
- X clr _fpfunc
- X rts pc
- X
- X.bss
- X_fpfunc: .=.+2
- X.text
- X
- X/ getop() will convert a number into in ascii form to a binary number
- X/ it returns non-zero if the number is ok, with the number in
- X/ the union 'res'. It uses the floating point routines (nfp.s) and
- X/ some of its storage locations ( areg ) to do the hard work.
- X/ If the number will fit into an integer, then the value returned is an
- X/ integer, with 'vartype' set accordingly. This convertion to integers
- X/ is only operative if the convertion needed is an easy one.
- X/ Zero is always returned as an integer.
- X/ This routine was written in assembler since it is impossible
- X/ to write in C.
- X
- X.globl _getop
- X_getop:
- X jsr r5,csv
- X mov $areg,r0
- X clr (r0)+
- X clr (r0)+
- X clr (r0)+
- X clr (r0)+
- X clr aexp
- X clr dpoint
- X clr dflag
- X mov $1,asign
- X clrb _vartype
- X clr count / number of actual digits
- X1: movb *_point,r4
- X inc _point
- X cmp r4,$'.
- X bne 4f
- X tst dflag / decimal point
- X bne out1 / already had one so get out of loop
- X inc dflag / set the decimal point flag.
- X br 1b
- X4:
- X cmp r4,$'0
- X blt out1
- X cmp r4,$'9
- X bgt out1
- X inc count / we have a digit
- X bit $!07,areg / enough space for another digit
- X bne 2f / no
- X sub $'0,r4 / multiply number by ten
- X mov r4,r2 / and add the new digit.
- X jsr pc,tenmul
- X tst dflag / if we have not had a decimal point
- X beq 1b / don't decrement the significance
- X dec dpoint / counter.
- X br 1b
- X2: / get here if all digits are filled
- X tst dflag / if decimal point , forget it
- X bne 1b
- X inc dpoint / increment the significance counter
- X br 1b / get some more.
- Xout1:
- X tst count / check to see that we have had a digit
- X bne 9f / yes then continue.
- X jmp bad / no goto bad.
- X9: cmp r4,$'e / do we have an exponent.
- X bne out2 / no.
- X clr count / count number of exponent digits
- X clr r3 / clear exponent value
- X clr r2 / clear exponent sign
- X movb *_point,r4
- X inc _point
- X cmp r4,$'- / exponents sign
- X bne 1f
- X inc r2 / set the flag
- X br 2f
- X1: cmp r4,$'+
- X bne 3f
- X2: movb *_point,r4
- X inc _point
- X3:
- X cmp r4,$'0 / get the exponent digits
- X blt 1f
- X cmp r4,$'9
- X bgt 1f
- X inc count / we have a digit.
- X sub $'0,r4
- X cmp r3,$1000. / if the digit would make the exponent
- X blt 7f / greater than ten thousand
- X3: / for get the following digits
- X movb *_point,r4 / ( we are heading for an overflow )
- X inc _point
- X cmp r4,$'0
- X blt 1f
- X cmp r4,$'9
- X ble 3b
- X br 1f
- X7:
- X mul $12,r3 / multiply the exponent by ten and
- X add r4,r3 / add the new digit.
- X br 2b / get some more
- X1:
- X tst r2 / check sign of exponent
- X beq 1f
- X neg r3
- X1: add r3,dpoint / add the exponent to the decimal
- X tst count / point counter
- X beq bad / check to see if we had any digits
- Xout2:
- X dec _point / adjust the character pointer
- X tst dpoint / check to see if number can be
- X ble 1f / multiplied by ten if need be.
- X2: bit $!07,areg
- X bne 1f / no
- X clr r2
- X jsr pc,tenmul / multiply by ten
- X dec dpoint
- X bne 2b
- X1:
- X tst areg / check to see if we have an integer
- X bne 1f
- X tst areg+2
- X bne 1f
- X tst areg+4
- X bne 1f
- X tst dpoint
- X bne 2f
- X bit $100000,areg+6
- X beq 3f
- X2: tst areg+6 / test for zero
- X bne 1f
- X3: mov areg+6,_res / yes we have an integer put the
- X movb $1,_vartype / value in 'res' and set 'vartype'
- X inc r0 / stop bad number error, since at this
- X jmp cret / point r0 is zero.
- X1:
- X mov $56.,aexp / convert to floating point format
- X jsr pc,norm
- X tst dpoint / number wants to be multiplied
- X ble 2f / by ten
- X cmp dpoint,$1000.
- X bgt bad
- X1: clr r2
- X jsr pc,tenmul / do it
- X3: bit $!377,areg / normalise the number
- X bne 1f
- X dec dpoint / decrement the counter
- X bne 1b
- X br 2f
- X1: mov $areg,r0 / shift right to normalise
- X asr (r0)+
- X ror (r0)+
- X ror (r0)+
- X ror (r0)+
- X inc aexp
- X cmp aexp,$177
- X bgt bad
- X br 3b
- X2:
- X tst dpoint / wants to be divided by ten
- X bge 2f
- X3: mov $3,r1
- X1: mov $areg+8,r0 / shift left to save significant
- X asl -(r0) / digits
- X rol -(r0)
- X rol -(r0)
- X rol -(r0)
- X dec aexp
- X sob r1,1b
- X jsr pc,tendiv / divide number by ten
- X1: bit $200,areg / normalise number
- X bne 1f
- X mov $areg+8,r0 / shift left
- X asl -(r0)
- X rol -(r0)
- X rol -(r0)
- X rol -(r0)
- X dec aexp
- X br 1b
- X1: inc dpoint
- X bne 3b
- X2:
- X cmp aexp,$177 / check for overflow
- X bgt bad
- X mov $_res,r2 / return value to 'res' via the floating
- X jmp retng / point return routine, r0 is non-zero
- Xbad: clr r0 / bad number , clear r0
- X jmp cret / return
- X
- X.bss
- Xdflag: .=.+2 / temporary space for decimal point counter
- X
- X.text
- X
- X/ cmp() is used to compare two numbers , it uses 'vartype' to decide
- X/ which kind of variable to test.
- X/ The result is -1,0 or 1 , depending on the result of the comparison
- X/
- X
- X.globl _cmp , _vartype
- X
- X_cmp: mov 2(sp),r0
- X mov 4(sp),r1
- X tstb _vartype
- X beq 6f
- X cmp (r0)+,(r1)+
- X blt 4f
- X bgt 3f
- X5: clr r0
- X rts pc
- X3: mov $1,r0
- X rts pc
- X4: mov $-1,r0
- X rts pc
- X / floating point comparisons
- X6: tst (r0) / straight out of the floating
- X bge 1f / point trap routines
- X tst (r1)
- X bge 1f
- X cmp (r0),(r1)
- X bgt 4b
- X blt 3b
- X1:
- X cmp (r0)+,(r1)+
- X bgt 3b
- X blt 4b
- X cmp (r0)+,(r1)+
- X bne 1f
- X cmp (r0)+,(r1)+
- X bne 1f
- X cmp (r0)+,(r1)+
- X beq 5b
- X1:
- X bhi 3b
- X br 4b
- X
- X/ routine to multiply two numbers together. returns zero on overflow
- X/ used in dimensio() only.
- X
- X.globl _dimmul
- X
- X_dimmul:
- X mov 2(sp),r1
- X mul 4(sp),r1
- X bcc 1f
- X clr r1
- X1: mov r1,r0
- X rts pc
- X
- X/ The calling routines for the maths functions ( from bas3.c).
- X/ The arguments passed to the routines are as follows.
- X/ at 6(sp) The operator funtion required.
- X/ at 4(sp) The pointer to second parameter and
- X/ the location where the result is to be put.
- X/ at 2(sp) The pointer to the first parameter.
- X
- X/ The jump table is called by the following sequence:-
- X/ (*mbin[priority*2+vartype])(&j->r1,&res,j->operator)
- X/
- X/ So the values in this table are such that integer and real
- X/ types are dealt with separately, and the different types of operators
- X/ are also dealt with seperately.
- X/ e.g. *, /, mod for reals are dealt with by 'fmdm'
- X/ and , or , xor for integers are dealt with by 'andor'
- X/
- X
- X.globl _mbin , csv , cret , _error , _fmul , _fdiv , _fadd , _fsub
- X
- X/ jump table for the maths functions
- X/ straight from the eval() routine in bas3.c
- X
- X.data
- X_mbin: 0
- X 0
- X fandor
- X andor
- X comop
- X comop
- X fads
- X ads
- X fmdm
- X mdm
- X fex
- X ex
- X.text
- X
- X/ locations from the jump table
- X/ integer exponentiation , convert to reals then call the floating
- X/ point convertion routines.
- X/
- X
- Xex: mov 2(sp),-(sp)
- X jsr pc,_cvt
- X mov 6(sp),(sp)
- X jsr pc,_cvt
- X tst (sp)+
- X clrb _vartype
- Xfex: jmp _fexp
- X
- X
- Xfmdm:
- X cmp $'*,6(sp) / times
- X bne 1f
- X jmp _fmul
- X1:
- X cmp $'/,6(sp) / div
- X bne 1f
- X jmp _fdiv
- X1:
- X jmp _fmod / mod
- X
- X
- Xmdm: cmp $'*,6(sp) / integer multiply
- X bne 1f
- X mov *2(sp),r0
- X mul *4(sp),r0
- X bcs over / overflow
- X br 2f
- X1: mov *2(sp),r1 / divide or mod
- X sxt r0
- X div *4(sp),r0
- X bvs 1f
- X cmp $'/,6(sp) / div
- X bne 2f / no , must be mod.
- X tst r1
- X bne 3f
- X mov r0,*4(sp)
- X rts pc
- X2: mov r1,*4(sp)
- X rts pc
- X1: mov $25.,-(sp) / zero divisor error
- X jsr pc,_error
- X / code to do integer divisions.. etc.
- X3: mov 2(sp),-(sp) / if the result of the integer division
- X jsr pc,_cvt / is not an integer then convert to
- X mov 6(sp),(sp) / float and call the floationg point
- X jsr pc,_cvt / routine
- X clrb _vartype
- X tst (sp)+
- X jmp _fdiv
- X
- Xfads: / floating add and subtract
- X cmp $'+,6(sp)
- X bne 1f
- X jmp _fadd
- X1:
- X jmp _fsub
- X
- X
- Xads: mov *2(sp),r1
- X cmp $'+,6(sp) / add or subtract
- X bne 1f
- X add *4(sp),r1 / add
- X br 2f
- X1: sub *4(sp),r1 / subtract
- X2: bvs over1 / branch on overflow
- X mov r1,*4(sp)
- X rts pc
- X
- Xover1: tst *2(sp) / move value to 'overfl'
- X sxt r0
- Xover: mov r0,_overfl
- X mov r1,_overfl+2
- X jmp _over / return via call to 'over'
- X
- X/ comparison operators ( float and integer )
- X/ cmp() expects to have only two parameters . So save return address
- X/ and so simulate environment.
- X
- Xcomop: mov (sp)+,comsav / save return address
- X jsr pc,_cmp / call comparison routine
- X mov r0,-(sp)
- X mov 6(sp),-(sp) / call routine to convert
- X jsr pc,_compare / this result into logical result
- X tst (sp)+
- X mov comsav,(sp) / restore return address
- X rts pc / return
- X.bss
- Xcomsav: .=.+2
- X.text
- X
- X/ floating logical operators
- X/ convert floating types into integers. If the value is non zero
- X/ then value has a true (-1) value.
- X/
- X
- Xfandor:
- X mov *2(sp),r0
- X beq 2f
- X mov $-1,r0
- X2: mov *4(sp),r1
- X beq 2f
- X mov $-1,r1
- X2: movb $1,_vartype
- X br 2f
- X
- X/ integer logical operators
- X/ does a bitwise operaotion on the two numbers ( in r0 , r1 ).
- X/
- X
- Xandor:
- X mov *2(sp),r0
- X mov *4(sp),r1
- X2: cmpb $356,6(sp)
- X bne 2f
- X com r1
- X bic r1,r0
- X br 1f
- X2: cmp $357,6(sp)
- X bne 2f
- X bis r1,r0
- X br 1f
- X2: xor r1,r0
- X1: mov r0,*4(sp)
- X rts pc
- X
- X/ This routine converts a floationg point number into an integers
- X/ if the result would overflow then return non zero.
- X/
- X
- X.globl _conv
- X
- X_conv:
- X mov 2(sp),r1
- X mov (r1)+,r0
- X beq 3f
- X mov (r1),r1
- X asl r0
- X clrb r0
- X swab r0
- X sub $200,r0
- X cmp r0,$20
- X bge 1f / overflow or underflow
- X sub $8,r0
- X mov r0,-(sp) / counter
- X mov *4(sp),r0
- X bic $!0177,r0
- X bis $200,r0
- X ashc (sp)+,r0
- X tst *2(sp)
- X bpl 3f
- X neg r0
- X3:
- X mov r0,*2(sp)
- X clr r0
- X rts pc
- X
- X1: bne 1f
- X cmp *2(sp),$144000 / check for -32768
- X bne 1f
- X bit r1,$177400
- X bne 1f
- X mov $-32768.,r0
- X br 3b
- X1: rts pc
- X
- X
- X/ convert from integer to floating point , this will never fail.
- X/
- X
- X.globl _cvt
- X_cvt: mov r2,-(sp)
- X clr r0
- X mov *4(sp),r1
- X beq 4f
- X bpl 1f
- X neg r1
- X1: mov $220,r2 /counter
- X ashc $8,r0
- X1: bit $200,r0
- X bne 1f
- X ashc $1,r0
- X dec r2
- X br 1b
- X1: swab r2
- X ror r2
- X tst *4(sp)
- X bpl 1f
- X bis $100000,r2
- X1: bic $!177,r0
- X bis r2,r0
- X4: mov 4(sp),r2
- X mov r0,(r2)+
- X mov r1,(r2)+
- X clr (r2)+
- X clr (r2)+
- X mov (sp)+,r2
- X rts pc
- X
- X/ add two numbers used in the 'next' routine
- X/ depends on the type of the number. calls error on overflow.
- X/
- X
- X.globl _foreadd
- X_foreadd:
- X add 2(sp),*4(sp)
- X bvs 1f
- X rts pc
- X1: mov $35.,-(sp) / integer overflow
- X jsr pc,_error
- X
- X/ This routine converts a floating point number into decimal
- X/ It uses the following algorithm:-
- X/ forever{
- X/ If X > 1 then {
- X/ X = X / 10
- X/ decpoint++
- X/ continue
- X/ }
- X/ If X < 0.1 then {
- X/ X = X * 10
- X/ decpoint--
- X/ continue
- X/ }
- X/ }
- X/ for i = 1 to 10 do {
- X/ digit[i] = int ( X * 10)
- X/ X = frac ( X * 10 )
- X/ }
- X/ This routine is not very complicated but very fiddly so was one
- X/ of the last ones written.
- X/
- X
- X
- X.globl _necvt , tendiv , tenmul
- X
- X_necvt: jsr r5,csv / needs to look like ecvt to
- X clr dpoint / the outside world
- X clr *10.(r5)
- X mov $buf,r3
- X mov 6(r5),r2
- X mov r2,mdigit
- X inc r2
- X mov r2,count
- X tst *4(r5)
- X beq zer
- X bpl 1f
- X inc *10.(r5) / sign part of ecvt
- X1: mov 4(r5),r2
- X mov $asign,r0
- X jsr pc,seta / set up number in areg
- X1: tst aexp
- X ble 1f
- X mov $3,r1 / number is greater than one
- X2: mov $areg+8,r0
- X asl -(r0) / save significant digits
- X rol -(r0)
- X rol -(r0)
- X rol -(r0)
- X dec aexp
- X sob r1,2b
- X jsr pc,tendiv
- X inc dpoint / increment decimal point
- X2: bit $200,areg
- X bne 1b
- X mov $areg+8,r0 / normalise after the division
- X asl -(r0)
- X rol -(r0)
- X rol -(r0)
- X rol -(r0)
- X dec aexp
- X br 2b
- X1:
- X cmp aexp,$-3 / number greate than 0.1
- X bgt 5f
- X blt 2f
- X cmp areg,$314
- X bgt 5f
- X blt 2f
- X mov $3,r1
- X mov $areg+2,r0
- X3: cmp (r0)+,$146314
- X bhi 5f
- X blo 2f
- X sob r1,3b
- X2: / no
- X clr r2
- X jsr pc,tenmul / multiply by ten
- X3: tstb areg+1
- X bne 4f
- X dec dpoint
- X br 1b
- X4:
- X mov $areg,r0 / normalise
- X asr (r0)+
- X ror (r0)+
- X ror (r0)+
- X ror (r0)+
- X inc aexp
- X br 3b
- X5:
- X tst aexp / get decimal point in correct place
- X beq 9f
- X1: mov $areg,r0
- X asr (r0)+
- X ror (r0)+
- X ror (r0)+
- X ror (r0)+
- X inc aexp
- X bne 1b
- X9:
- X clr r2 / get the digits
- X jsr pc,tenmul
- X bic $!377,areg
- X clrb r1 / top word in r1
- X swab r1
- X add $'0,r1
- X movb r1,(r3)+
- X dec count / got all digits
- X bne 9b
- X br out
- X
- Xzer: inc dpoint / deal with zero
- X1: movb $'0,(r3)+
- X sob r2,1b
- Xout: / correct the last digit
- X mov $buf,r0
- X add mdigit,r0
- X movb (r0),r2
- X add $5,r2
- X movb r2,(r0)
- X1:
- X cmpb (r0),$'9
- X ble 1f / don't correct it
- X movb $'0,(r0)
- X cmp r0,$buf
- X blos 2f
- X incb -(r0)
- X br 1b
- X2:
- X inc dpoint
- X movb $'1,(r0) / correction has made number a one
- X1:
- X mov mdigit,r0 / pass values back
- X clrb buf(r0)
- X mov $buf,r0
- X mov dpoint,*8(r5)
- X jmp cret
- X
- Xtenmul: / multiply value in areg by 10
- X mov $areg+8.,r4
- X1: mov -(r4),r0
- X mul $12,r0
- X bpl 2f
- X add $12,r0
- X2: add r2,r1
- X adc r0
- X mov r1,(r4)
- X mov r0,r2
- X cmp r4,$areg
- X bne 1b
- X rts pc
- X
- Xtendiv: / divide value in areg by 10
- X mov $areg,r4
- X clr r0
- X1: mov (r4),r1 / has to divide by 20 to stop
- X div $24,r0 / multiply thinking there is an
- X asl r0 / overflow
- X cmp r1,$9
- X ble 2f
- X inc r0
- X sub $12,r1
- X2: mov r0,(r4)+
- X mov r1,r0
- X cmp r4,$areg+8
- X bne 1b
- X rts pc
- X
- X .bss
- Xmdigit: .=.+2
- Xcount: .=.+2
- Xbuf: .=.+20.
- Xdpoint: .=.+2
- X .text
- X
- X/ convert a long in 'overfl' to a real. uses the floating point
- X/ routines. returns via these routines.
- X
- X.globl _over
- X_over:
- X jsr r5,csv
- X clrb _vartype
- X mov _overfl,areg
- X mov _overfl+2,areg+2
- X clr areg+4
- X clr areg+6
- X mov $1,asign
- X mov $32.-8,aexp
- X jmp saret
- X
- X/
- X/ put a value into a variable , does the convertions from integer
- X/ to real and back as needed.
- X/
- X
- X.globl _putin
- X_putin: cmpb 4(sp),_vartype
- X beq 3f
- X mov $_res,-(sp)
- X tstb 6(sp)
- X beq 2f
- X jsr pc,_conv
- X tst r0
- X beq 1f
- X mov $35.,(sp)
- X jsr pc,_error / no return
- X2: jsr pc,_cvt
- X1: tst (sp)+
- X3: mov $_res,r0
- X mov 2(sp),r1
- X mov (r0)+,(r1)+
- X tstb 4(sp) / type of variable that is to be assigned
- X bne 1f / to
- X mov (r0)+,(r1)+
- X mov (r0)+,(r1)+
- X mov (r0)+,(r1)+
- X1: rts pc
- X
- X/ high speed move of variables
- X/ can't use floating point moves because of '-0'.
- X
- X.globl _movein
- X_movein: mov 2(sp),r0
- X mov 4(sp),r1
- X mov (r0)+,(r1)+
- X mov (r0)+,(r1)+
- X mov (r0)+,(r1)+
- X mov (r0)+,(r1)+
- X rts pc
- X
- X/ puts the value from a variable into 'res'. It might be thought
- X/ that 'movein' could be used but it can't for the reason given in
- X/ the report.
- X/
- X
- X.globl _getv
- X_getv: mov 2(sp),r0
- X mov $_res,r1
- X mov (r0)+,(r1)+
- X tstb _vartype
- X bne 1f
- X mov (r0)+,(r1)+
- X mov (r0)+,(r1)+
- X mov (r0)+,(r1)+
- X1: rts pc
- X
- X/ move the value in res onto the maths 'stack'. A simple floating
- X/ move cannot be used due to the possibility of "minus zero" or
- X/ -32768 being in 'res'. This could check 'vartype' but for speed just
- X/ does the move.
- X
- X.globl _push
- X_push: mov 2(sp),r1
- X mov $_res,r0
- X mov (r0)+,(r1)+
- X mov (r0)+,(r1)+
- X mov (r0)+,(r1)+
- X mov (r0)+,(r1)+
- X rts pc
- X
- X/ negate a number , checks for overflow and for type of number.
- X/
- X
- X.globl _negate
- X_negate:
- X tstb _vartype
- X beq 1f
- X neg _res
- X bvs 2f / negating -32768
- X rts pc
- X1: tst _res / stop -0
- X beq 1f
- X add $100000,_res
- X1: rts pc
- X2:
- X mov $044000,_res / 32768 in floating form
- X clr _res+2
- X clr _res+4
- X clr _res+6
- X clrb _vartype
- X rts pc
- X
- X/ unary negation
- X
- X.globl _notit
- X
- X_notit: tstb _vartype
- X beq 1f
- X com _res
- X rts pc
- X1: movb $1,_vartype
- X tst _res
- X bne 1f
- X com _res
- X rts pc
- X1: clr _res
- X rts pc
- X
- X/ routine to dynamically check the stack
- X.globl _checksp
- X
- X_checksp:
- X cmp sp,$160000+1024.
- X blos 1f
- X rts pc
- X1: mov $44.,(sp)
- X jsr pc,_error / no return
- End of pdp11/assist.s
- chmod u=rw-,g=r,o=r pdp11/assist.s
- echo x - pdp11/conf.h 1>&2
- sed 's/^X//' > pdp11/conf.h << 'End of pdp11/conf.h'
- X/*
- X * BASIC by Phil Cockcroft
- X */
- X/*
- X * Configuration file for a pdp11
- X */
- X/*
- X * hardware specific. Can't change MAXMEM upwards
- X */
- X
- X#define MAXMEM (memp)0160000 /* max data address on a pdp11 */
- X#define MEMINC 1023 /* size of memory increments - 1 */
- X
- X/*
- X * various options.
- X */
- X
- X#define V7
- X#define UCB_NTTY
- X#define LKEYWORDS
- X#define LNAMES
- X#define RENUMB
- X#define SCOMMS
- X#define BERK
- X
- X#ifdef BERK
- X#define BLOCKSIZ 1024
- X#else
- X#define BLOCKSIZ 512
- X#endif
- X
- X/*
- X * terminal specific options
- X */
- X#define DEFPAGE 80 /* default page width */
- X#define DEFLENGTH 24 /* default page length */
- X#define CTRLINT 03 /* ctrl -c - sig int */
- X#define CTRLQUIT 034 /* ctrl - \ FS sig quit */
- X
- X/* #define V7 */ /* define for v7 */
- X/* #define SOFTFP */ /* define if not got fp hardware */
- X/* #define V6C */ /* if got V6 compiler (no structure assignments ) */
- X/* #define BERK */ /* define if got Berkley tty driver ( not v6 ) */
- X/* #define UCB_NTTY */ /* if got the new driver ..... */
- X
- X/* #define NOEDIT /* define if don't want editing ever ! */
- X /* NB basic -e will still turn on editing */
- X /* basic -x will still turn off editing */
- X
- X/* #define LKEYWORDS /* define this if you want to have variable names which*/
- X /* contain commands this is like the later versions of */
- X /* microsoft but not like the orignal version */
- X /* it wastes more space since you have to have some */
- X /* spaces in to distinguish keywords */
- X
- X/* #define RENUMB /* define if you want to put the code for renumbering */
- X /* in. It works but is very wasteful of space. If you */
- X /* are short of space then don't use it. */
- X
- X/* #define LNAMES /* define if you want long variables names. This only */
- X /* slows it down by a small fraction */
- X
- X/* #define _BLOCKED /* This is a switch to allow block mode files */
- X /* don't define it here look below for where it is done*/
- X /* in the file handling bits */
- X/* #define SCOMMS /* to allow shortened command names e.g. l. -> list */
- X /* this might cause some problems with overwriting of */
- X /* core but I think they have all been solved */
- End of pdp11/conf.h
- chmod u=rw-,g=r,o=r pdp11/conf.h
- echo x - pdp11/fpassist.s 1>&2
- sed 's/^X//' > pdp11/fpassist.s << 'End of pdp11/fpassist.s'
- X/ (c) P. (Rabbit) Cockcroft 1982
- X
- X.globl _wait, cerror
- X
- Xwait = 7.
- X
- X_wait:
- X mov r5,-(sp)
- X mov sp,r5
- X sys wait
- X bec 1f
- X jmp cerror
- X1:
- X tst 4(r5)
- X beq 1f
- X mov r1,*4(5)
- X1:
- X mov (sp)+,r5
- X rts pc
- X
- X/ getch() is used all over the place to get the next character on the line.
- X/ It uses 'point' ( _point ) as the pointer to the next character.
- X/ It skips over all leading spaces.
- X/ It was put into machine code for speed since it does not have to
- X/ call csv and cret ( the C subroutine call and return routines ).
- X/ this saves a lot of time. It can also be written more efficiently
- X/ in machine code.
- X/
- X
- X.text
- X.globl _point , _getch
- X
- X_getch:
- X mov _point,r1
- X1: cmpb $40,(r1)+ / ignore spaces
- X beq 1b
- X mov r1,_point
- X clr r0
- X bisb -(r1),r0
- X rts pc
- X
- X/ check() is used by many routines that want to know if there is any
- X/ garbage characters after its arguments. e.g. in 'goto' there
- X/ should be nothing after the line number. It gives a SYNTAX
- X/ error if the next character is not a terminator.
- X/ check() was also taken out of C for speed reasons.
- X
- X.globl _point , _check , _elsecount , _error
- X
- XELSE= 0351
- X
- X_check:
- X mov _point,r0
- X1: cmpb $40,(r0)+
- X beq 1b
- X movb -(r0),r1
- X beq 1f
- X cmpb r1,$':
- X beq 1f
- X cmpb r1,$ELSE
- X bne 2f
- X tstb _elsecount
- X beq 2f
- X1: mov r0,_point
- X rts pc
- X2: mov $1,-(sp) / syntax error
- X jsr pc,_error
- X
- X/ startfp() this is called in main to intialise the floating point
- X/ hardware if it is used. it is only called once to set up fpfunc()
- X/ this routine does nothing in non-floating point hardware machines.
- X/
- X
- X .globl _startfp , _fpfunc
- X
- Xldfps = 0170100 ^ tst
- X
- X_startfp:
- X mov $fpcrash,_fpfunc
- X ldfps $1200
- X rts pc
- X.bss
- X_fpfunc: .=.+2
- X.text
- X
- Xfpcrash:
- X mov $34.,-(sp)
- X jsr pc,_error / no return
- X
- X/ cmp() is used to compare two numbers , it uses 'vartype' to decide
- X/ which kind of variable to test.
- X/ The result is -1,0 or 1 , depending on the result of the comparison
- X/
- X
- X.globl _cmp , _vartype
- X
- X_cmp:
- X tstb _vartype
- X beq 6f
- X cmp *2(sp),*4(sp)
- X1:
- X blt 4f
- X bgt 3f
- X5: clr r0
- X rts pc
- X3: mov $1,r0
- X rts pc
- X4: mov $-1,r0
- X rts pc
- X / floating point comparisons
- X6: movf *4(sp),fr0
- X cmpf *2(sp),fr0
- X cfcc
- X br 1b
- X
- X
- X/ routine to multiply two numbers together. returns zero on overflow
- X/ used in dimensio() only.
- X
- X.globl _dimmul
- X
- X_dimmul:
- X mov 2(sp),r1
- X mul 4(sp),r1
- X bcc 1f
- X clr r1
- X1: mov r1,r0
- X rts pc
- X
- X.globl _mbin
- X
- X/ jump table for the maths functions
- X/ straight from the eval() routine in bas3.c
- X
- X.data
- X_mbin: 0
- X 0
- X fandor
- X andor
- X comop
- X comop
- X fads
- X ads
- X fmdm
- X mdm
- X fex
- X ex
- X.text
- X
- X/ locations from the jump table
- X/ integer exponentiation , convert to reals then call the floating
- X/ point convertion routines.
- X/
- X.globl _exp , _log
- X
- Xexp: movf fr0,-(sp)
- X jsr pc,_exp
- X tstf (sp)+
- X rts pc
- X
- Xlog: movf fr0,-(sp)
- X jsr pc,_log
- X tstf (sp)+
- X rts pc
- X
- X
- Xex: movif *2(sp),fr0
- X movif *4(sp),fr1
- X movf fr1,*4(sp)
- X clrb _vartype
- X br 1f
- Xfex:
- X movf *2(sp),fr0
- X1:
- X tstf fr0
- X cfcc
- X beq 1f
- X bmi 2f
- X jsr pc,log / call log
- X mulf *4(sp),fr0
- X1:
- X jsr pc,exp / exponentiate
- X bes 1f
- X movf fr0,*4(sp)
- X rts pc
- X1: mov $40.,-(sp) / overflow in ^
- X jsr pc,_error
- X2: mov $41.,-(sp) / negative value to ^
- X jsr pc,_error
- X
- Xfmdm:
- X movf *2(sp),fr0
- X cmp $52,6(sp) / times
- X bne 1f
- X mulf *4(sp),fr0
- X movf fr0,*4(sp)
- X rts pc
- X1:
- X movf *4(sp),fr2
- X cfcc
- X beq zerodiv
- X divf fr2,fr0
- X cmp $'/,6(sp) / div
- X beq 1f
- X modf $040200,fr0 / mod
- X mulf fr2,fr0
- X1:
- X movf fr0,*4(sp)
- X rts pc
- X
- X
- Xmdm: cmp $52,6(sp) / integer multiply
- X bne 1f
- X mov *2(sp),r0
- X mul *4(sp),r0
- X bcs over / overflow
- X br 2f
- X1: mov *2(sp),r1 / divide or mod
- X sxt r0
- X div *4(sp),r0
- X bvs 1f
- X cmp $57,6(sp) / div
- X bne 2f / no , must be mod.
- X tst r1
- X bne 3f
- X mov r0,r1
- X2: mov r1,*4(sp)
- X rts pc
- X1:
- Xzerodiv:
- X mov $25.,-(sp) / zero divisor error
- X jsr pc,_error
- X / code to do integer divisions.. etc.
- X3: movif *2(sp),fr0
- X movif *4(sp),fr1
- X divf fr1,fr0
- X movf fr0,*4(sp)
- X clrb _vartype
- X rts pc
- X
- Xfads: / floating add and subtract
- X movf *2(sp),fr0
- X cmp $53,6(sp)
- X bne 1f
- X
- X addf *4(sp),fr0
- X movf fr0,*4(sp)
- X rts pc
- X1:
- X subf *4(sp),fr0
- X movf fr0,*4(sp)
- X rts pc
- X
- X
- Xads: mov *2(sp),r1
- X cmp $53,6(sp) / add or subtract
- X bne 1f
- X add *4(sp),r1 / add
- X br 2f
- X1: sub *4(sp),r1 / subtract
- X2: bvs over1 / branch on overflow
- X mov r1,*4(sp)
- X rts pc
- X
- Xover1: tst *2(sp) / move value to 'overfl'
- X sxt r0
- Xover: mov r0,_overfl
- X mov r1,_overfl+2
- X jmp _over / return via call to 'over'
- X
- X/ comparison operators ( float and integer )
- X/ cmp() expects to have only two parameters . So save return address
- X/ and so simulate environment.
- X
- Xcomop: mov (sp)+,comsav / save return address
- X jsr pc,_cmp / call comparison routine
- X mov r0,-(sp)
- X mov 6(sp),-(sp) / call routine to convert
- X jsr pc,_compare / this result into logical result
- X tst (sp)+
- X mov comsav,(sp) / restore return address
- X rts pc / return
- X.bss
- Xcomsav: .=.+2
- X.text
- X
- X/ floating logical operators
- X/ convert floating types into integers. If the value is non zero
- X/ then value has a true (-1) value.
- X/
- X
- Xfandor:
- X mov *2(sp),r0
- X beq 2f
- X mov $-1,r0
- X2: mov *4(sp),r1
- X beq 2f
- X mov $-1,r1
- X2: movb $1,_vartype
- X br 2f
- X
- X/ integer logical operators
- X/ does a bitwise operaotion on the two numbers ( in r0 , r1 ).
- X/
- X
- Xandor:
- X mov *2(sp),r0
- X mov *4(sp),r1
- X2: cmpb $356,6(sp)
- X bne 2f
- X com r1
- X bic r1,r0
- X br 1f
- X2: cmp $357,6(sp)
- X bne 2f
- X bis r1,r0
- X br 1f
- X2: xor r1,r0
- X1: mov r0,*4(sp)
- X rts pc
- X
- X/ This routine converts a floationg point number into an integers
- X/ if the result would overflow then return non zero.
- X/
- X
- X.globl _conv
- X
- X_conv:
- X movf *2(sp),fr0
- X movfi fr0,r0
- X cfcc
- X bcs 1f
- X mov r0,*2(sp)
- X clr r0
- X rts pc
- X1:
- X mov $1,r0
- X rts pc
- X
- X
- X/ add two numbers used in the 'next' routine
- X/ depends on the type of the number. calls error on overflow.
- X/
- X
- X.globl _foreadd
- X_foreadd:
- X add 2(sp),*4(sp)
- X bvs 1f
- X rts pc
- X1: mov $35.,-(sp) / integer overflow
- X jsr pc,_error
- X
- X/ convert a long in 'overfl' to a real. uses the floating point
- X/ routines. returns via these routines.
- X
- X.globl _over
- X_over:
- X setl
- X movif _overfl,fr0
- X clrb _vartype
- X movf fr0,*4(sp)
- X seti
- X rts pc
- X/
- X/ put a value into a variable , does the convertions from integer
- X/ to real and back as needed.
- X/
- X
- X.globl _putin
- X_putin: cmpb 4(sp),_vartype
- X beq 1f
- X tstb 4(sp)
- X beq 2f
- X movf _res,fr0
- X movfi fr0,r0
- X cfcc
- X bes 3f
- X mov r0,*2(sp)
- X rts pc
- X3:
- X mov $35.,-(sp)
- X jsr pc,*$_error / no return
- X2:
- X movif _res,fr0
- X movf fr0,*2(sp)
- X rts pc
- X1:
- X tstb 4(sp)
- X bne 1f
- X movf _res,fr0
- X movf fr0,*2(sp)
- X rts pc
- X1:
- X mov _res,*2(sp)
- X rts pc
- X
- X/ high speed move of variables
- X/ can't use floating point moves because of '-0'.
- X
- X.globl _movein
- X_movein: mov 2(sp),r0
- X mov 4(sp),r1
- X mov (r0)+,(r1)+
- X mov (r0)+,(r1)+
- X mov (r0)+,(r1)+
- X mov (r0)+,(r1)+
- X rts pc
- X
- X/ puts the value from a variable into 'res'. It might be thought
- X/ that 'movein' could be used but it can't for the reason given in
- X/ the report.
- X/
- X
- X.globl _getv
- X_getv: mov 2(sp),r0
- X mov $_res,r1
- X mov (r0)+,(r1)+
- X tstb _vartype
- X bne 1f
- X mov (r0)+,(r1)+
- X mov (r0)+,(r1)+
- X mov (r0)+,(r1)+
- X1: rts pc
- X
- X/ move the value in res onto the maths 'stack'. A simple floating
- X/ move cannot be used due to the possibility of "minus zero" or
- X/ -32768 being in 'res'. This could check 'vartype' but for speed just
- X/ does the move.
- X
- X.globl _push
- X_push: mov 2(sp),r1
- X mov $_res,r0
- X mov (r0)+,(r1)+
- X mov (r0)+,(r1)+
- X mov (r0)+,(r1)+
- X mov (r0)+,(r1)+
- X rts pc
- X
- X/ negate a number , checks for overflow and for type of number.
- X/
- X
- X.globl _negate
- X_negate:
- X tstb _vartype
- X beq 1f
- X neg _res
- X bvs 2f / negating -32768
- X rts pc
- X1: tst _res / stop -0
- X beq 1f
- X add $100000,_res
- X1:
- X rts pc
- X2:
- X mov $044000,_res / 32768 in floating form
- X clr _res+2
- X clr _res+4
- X clr _res+6
- X clrb _vartype
- X rts pc
- X
- X/ unary negation
- X
- X.globl _notit
- X
- X_notit: tstb _vartype
- X beq 1f
- X com _res
- X rts pc
- X1: movb $1,_vartype
- X tst _res
- X bne 1f
- X com _res
- X rts pc
- X1: clr _res
- X rts pc
- X
- X/ routine to dynamically check the stack
- X
- X.globl _checksp
- X
- X_checksp:
- X cmp sp,$160000+1024.
- X blos 1f
- X rts pc
- X1: mov $44.,(sp) / expression too complex
- X jsr pc,_error / no return
- End of pdp11/fpassist.s
- chmod u=rw-,g=r,o=r pdp11/fpassist.s
- echo x - pdp11/lfunc.s 1>&2
- sed 's/^X//' > pdp11/lfunc.s << 'End of pdp11/lfunc.s'
- X/ (c) P. (Rabbit) Cockcroft 1982
- X/ This file contains the routines to implement the some of the
- X/ more complex mathematical functions.
- X/ It currently contains the code for sqrt() , log() and exp()
- X
- X/ The sqrt() routine is based on the the standard Newtonian method.
- X/ It uses mull and divv from nfp.s
- X
- X.globl _sqrt , sqrt
- X/
- X/ for ( i = 0 ; i < 6 ; i++ )
- X/ areg = ( areg + creg / areg ) >> 1 ;
- X/
- X
- X_sqrt:
- X jsr r5,csv
- X mov 4(r5),r2
- X mov $asign,r0
- X jsr pc,seta
- X jsr pc,sqrt
- X mov 4(r5),r2
- X mov $asign,r0
- X jmp retng
- X
- X
- X/ value in areg
- X
- Xsqrt:
- X tst asign / test for zero
- X bne 1f
- X rts pc
- X1:
- X bit $1,aexp / sort out the exponent
- X beq 1f
- X mov $areg,r0 / shifting as need be
- X asr (r0)+
- X ror (r0)+
- X ror (r0)+
- X ror (r0)+
- X inc aexp
- X1:
- X mov $asign,r0 / save in creg
- X mov $csign,r1
- X mov $6,r2
- X1:
- X mov (r0)+,(r1)+
- X sob r2,1b
- X
- X asr aexp / initial guess in areg
- X mov $6.,-(sp) / number of iterations
- X
- X / main loop starts here
- X5:
- X mov $4,r2
- X mov $areg,r0
- X mov $breg,r1 / set up to do the division
- X1: / areg/breg
- X mov (r0)+,(r1)+
- X sob r2,1b
- X mov $4,r2
- X mov $creg,r0
- X mov $areg,r1
- X1:
- X mov (r0)+,(r1)+
- X sob r2,1b
- X jsr pc,divv / the division
- X1: mov $areg+8,r0 / add result to old value
- X mov $breg+8,r1
- X jsr pc,addm
- X mov $areg,r0 / divide by two
- X asr (r0)+
- X ror (r0)+
- X ror (r0)+
- X ror (r0)+
- X dec (sp) / decrement iteration counter
- X bne 5b
- X tst (sp)+
- X jsr pc,norm / normalise result
- X rts pc
- X
- X/ The routines below handle the log and exp functions
- X/ They return zero if there is an error or on overflow
- X/ these routines are almost totally incomprehensible but the algorithms
- X/ are discussed in the report.
- X
- X
- X ITER=11. / loop count
- X
- X.globl _log
- X_log:
- X jsr r5,csv
- X mov 4(r5),r2
- X mov $asign,r0
- X jsr pc,seta
- X jsr pc,log
- X mov 4(r5),r2
- X mov $asign,r0
- X jmp retng
- X
- X.globl log
- X
- Xlog:
- X clr pt
- X mov $creg,r0
- X clr (r0)+
- X clr (r0)+
- X clr (r0)+
- X clr (r0)+
- X1:
- X mov pt,r1
- X mov r1,r4
- X mul $3,r1
- X mov r1,pt1
- X3:
- X mov $areg,r0
- X mov $breg,r1
- X jsr pc,movm
- X mov pt1,r1
- X beq 5f
- X mov $breg,r0
- X jsr pc,shiftl
- X5:
- X mov $breg+8,r0
- X mov $areg+8,r1
- X jsr pc,addm
- X cmp breg,$400
- X bhi 2f
- X blo 5f
- X tst breg+2
- X bne 2f
- X tst breg+4
- X bne 2f
- X tst breg+6
- X bne 2f
- X5:
- X mov $areg,r1
- X mov $breg,r0
- X jsr pc,movm
- X mov pt,r1
- X ash $3,r1
- X add $logtable+8,r1
- X mov $creg+8,r0
- X jsr pc,addm
- X br 3b
- X2:
- X inc pt
- X cmp pt,$ITER
- X blt 1b / first loop finished
- X
- X sub $400,areg
- X mov $creg+8,r1
- X mov $areg+8,r0
- X jsr pc,subm
- X
- X mov aexp,r4 / deal with the exponent
- X beq 3f
- X bmi 2f
- X1:
- X mov $logtable+8,r1 /log2n
- X mov $areg+8,r0
- X jsr pc,addm
- X dec r4
- X bne 1b
- X br 3f
- X2:
- X mov $logtable+8,r1 /log2n
- X mov $areg+8,r0
- X jsr pc,subm
- X inc r4
- X bne 2b
- X3:
- X tst areg
- X bpl 1f
- X mov $areg+8,r0
- X jsr pc,negat
- X neg asign
- X1:
- X clr aexp
- X jsr pc,norm
- X rts pc
- X
- X
- X.globl _exp
- X
- X_exp:
- X jsr r5,csv
- X mov 4(r5),r2
- X mov $asign,r0
- X jsr pc,seta
- X jsr pc,exp
- X bec 1f
- X clr r0
- X jmp cret
- X1:
- X mov 4(r5),r2
- X mov $asign,r0
- X jmp retng
- X
- X.globl exp
- X
- Xexp: clr cexp
- X tst aexp / test of exponent.
- X bmi 1f
- X beq 5f
- X cmp aexp,$7
- X ble 4f
- X sec
- X rts pc
- X4:
- X mov $areg+8,r0
- X asl -(r0)
- X rol -(r0)
- X rol -(r0)
- X rol -(r0)
- X dec aexp
- X bne 4b
- X4:
- X tstb areg+1
- X beq 5f
- X mov $logtable+8,r1
- X mov $areg+8,r0
- X jsr pc,subm
- X inc cexp
- X br 4b
- X5: mov $logtable+8,r1
- X mov $areg+8,r0
- X jsr pc,subm
- X tst areg
- X bpl 3f
- X mov $logtable+8,r1
- X mov $areg+8,r0
- X jsr pc,addm
- X br 5f
- X3: inc cexp
- X br 5f
- X1:
- X mov $areg,r0
- X mov aexp,r1
- X neg r1
- X jsr pc,shiftl
- X
- X5: mov $1,r4 / main loop starts here
- X3:
- X clrb count(r4)
- X mov r4,r1
- X ash $3,r1
- X add $logtable+8,r1
- X mov r1,r3
- X2:
- X mov $areg+8,r0
- X jsr pc,subm
- X tst areg
- X bmi 1f
- X incb count(r4)
- X mov r3,r1
- X br 2b
- X1:
- X mov r3,r1
- X mov $areg+8,r0
- X jsr pc,addm
- X inc r4
- X cmp r4,$ITER
- X blt 3b / end of first loop
- X6:
- X
- X add $400,areg
- X mov $1,pt
- X1:
- X mov pt,r1
- X mul $3,r1
- X mov r1,pt1
- X2:
- X mov pt,r4
- X tstb count(r4)
- X beq 2f
- X decb count(r4)
- X mov $areg,r0
- X mov $breg,r1
- X jsr pc,movm
- X mov pt1,r1
- X beq 5f
- X mov $breg,r0
- X jsr pc,shiftl
- X5:
- X mov $breg+8,r1
- X mov $areg+8,r0
- X jsr pc,addm
- X br 2b
- X2:
- X inc pt
- X cmp pt,$ITER
- X blt 1b
- X tst asign
- X bne 3f
- X inc asign
- X3:
- X mov cexp,aexp
- X jsr pc,norm
- X tst asign
- X bpl 1f
- X jsr pc,recip
- X neg asign
- X1:
- X cmp aexp,$177
- X ble 1f
- X sec
- X rts pc
- X1:
- X clc
- X rts pc
- X
- X.globl recip
- Xrecip:
- X mov $areg,r0 / return reciprical of areg
- X mov $breg,r1 / done by division
- X jsr pc,movm
- X mov $200,areg
- X clr areg+2
- X clr areg+4
- X clr areg+6
- X jsr pc,divv
- X neg aexp
- X inc aexp
- X jsr pc,norm
- X rts pc
- X
- X
- X.bss
- Xcount: .=.+12. / counters for the log and exp functs.
- Xpt: .=.+2
- Xpt1: .=.+2
- X
- X.globl logtable
- X
- X.data
- X / log2n is in fact the first entry in logtable
- X
- Xlogtable:
- X 000261; 071027; 173721; 147572
- X 000036; 023407; 067052; 171341
- X 000003; 174025; 013037; 100174
- X 000000; 077740; 005246; 126103
- X 000000; 007777; 100005; 052425
- X 000000; 000777; 177000; 001252
- X 000000; 000077; 177770; 000001
- X 000000; 000007; 177777; 160000
- X 000000; 000000; 177777; 177600
- X 000000; 000000; 017777; 177777
- X 000000; 000000; 001777; 177777
- X.text
- X
- X.globl _fexp
- X_fexp: jsr r5,csv / do exponentiation
- X mov 4(r5),r2
- X mov $asign,r0
- X jsr pc,seta
- X tst asign / deal with 0^x
- X beq 1f
- X bmi 2f
- X jsr pc,log / call log
- X mov 6(r5),r2
- X mov $bsign,r0
- X jsr pc,seta
- X jsr pc,mull / multiply
- X add bexp,aexp
- X dec aexp
- X jsr pc,xorsign
- X jsr pc,norm
- X1:
- X jsr pc,exp / exponentiate
- X bes 1f
- X mov 6(r5),r2
- X jmp retng
- X1: mov $40.,-(sp) / overflow in ^
- X jsr pc,_error
- X2: mov $41.,-(sp) / negative value to ^
- X jsr pc,_error
- X
- X/ trig functions that are not as yet implemented
- X/ put in as place holders. Calls error with illegal function
- X
- X.globl _sin , _cos , _atan
- X_sin:
- X_cos:
- X_atan:
- X mov $11.,-(sp)
- X jsr pc,_error
- X
- X/ These routines do quad precision arithmetic and are called by many of
- X/ the higher mathematical functions. These are usually called with the
- X/ addresses of the operands in r0 and r1. (r0 is usually destination )
- X
- X.globl addm , subm , movm , shiftl , negat
- X
- Xaddm:
- X mov $4,r2 / add quad length
- X clc
- X1:
- X adc -(r0)
- X bcs 3f
- X add -(r1),(r0)
- X sob r2,1b
- X rts pc
- X3:
- X add -(r1),(r0)
- X sec
- X sob r2,1b
- X rts pc
- X
- X
- Xsubm: / subtract quad length
- X mov $4,r2
- X clc
- X1:
- X sbc -(r0)
- X bcs 3f
- X sub -(r1),(r0)
- X sob r2,1b
- X rts pc
- X3:
- X sub -(r1),(r0)
- X sec
- X sob r2,1b
- X rts pc
- X
- Xshiftl: / a misnomer
- X mov r5,-(sp) / it actually shifts right
- X mov r1,r5 / the number of places in r1
- X mov (r0)+,r1
- X mov (r0)+,r2
- X mov (r0)+,r3
- X mov (r0)+,r4
- X1:
- X asr r1
- X ror r2
- X ror r3
- X ror r4
- X sob r5,1b
- X mov r4,-(r0)
- X mov r3,-(r0)
- X mov r2,-(r0)
- X mov r1,-(r0)
- X mov (sp)+,r5
- X rts pc
- X
- Xmovm: / quad move - the parameters are the
- X mov (r0)+,(r1)+ / other way around
- X mov (r0)+,(r1)+
- X mov (r0)+,(r1)+
- X mov (r0)+,(r1)+
- X rts pc
- X
- X
- Xnegat: / quad negation
- X mov $4,r1
- X clc
- X1:
- X adc -(r0)
- X bcs 2f
- X neg (r0)
- X2:
- X sob r1,1b
- X rts pc
- End of pdp11/lfunc.s
- chmod u=rw-,g=r,o=r pdp11/lfunc.s
- echo x - pdp11/nfp.s 1>&2
- sed 's/^X//' > pdp11/nfp.s << 'End of pdp11/nfp.s'
- X/ (c) P. (Rabbit) Cockcroft 1982
- X/ this file contains all the floating point routines to execute the four
- X/ basic mathematical functions. Also routines for exponentiation and the
- X/ floating mod function.
- X/
- X/ These routines are the same as used in the floating point simulator
- X/ but have been changed to make them more flexible and to enable the use
- X/ of C calling and return conventions.
- X/ They have also been modified so that they use instructions in the
- X/ extended arithmetic option for the PDP-11's e.g. sob's.
- X/
- X
- X/ It is expected that during the reading of these routines that the
- X/ general principles behind floating point work and the general operation
- X/ of the floating point interpreter are understood.
- X
- X/ definiton of all global variables.
- X
- X.globl _fadd , _fsub , _fmul , _fdiv , csv , cret , areg , asign , aexp
- X.globl seta , retng , norm , saret , divv , bsign , breg , bexp , retb , reta
- X.globl csign , creg , cexp , mull , xorsign
- X
- X/ All the standard mathematical functions expect the second argument to
- X/ be the place where the result is to be put. This is exactly how they are
- X/ called from the eval() routine. ( via mbin ).
- X
- X
- X_fadd: jsr r5,csv / save the registers
- X jsr pc,setab / set up the parameters (in areg and breg)
- X br 1f
- X
- X_fsub: jsr r5,csv
- X jsr pc,setab
- X neg bsign
- X1:
- X tst bsign / test for adding zero
- X beq reta
- X tst asign
- X beq retb
- X mov areg+8,r1 / compare the exponents
- X sub breg+8,r1
- X blt 1f
- X beq 2f
- X cmp r1,$56. / test for underflows
- X bge reta
- X mov $breg,r0
- X br 4f
- X1:
- X neg r1
- X cmp r1,$56.
- X bge retb
- X mov $areg,r0
- X4:
- X mov r1,-(sp)
- X mov (r0)+,r1
- X mov (r0)+,r2
- X mov (r0)+,r3
- X mov (r0)+,r4
- X add (sp),(r0)
- X1:
- X asr r1 / shift the required value
- X ror r2
- X ror r3
- X ror r4
- X dec (sp)
- X bgt 1b
- X mov r4,-(r0)
- X mov r3,-(r0)
- X mov r2,-(r0)
- X mov r1,-(r0)
- X tst (sp)+
- X2:
- X mov $areg+8,r1
- X mov $breg+8,r2
- X mov $4,r0
- X cmp asign,bsign / compare sign of arguments
- X bne 4f
- X clc
- X1:
- X adc -(r1) / signs are equal so add
- X bcs 3f
- X add -(r2),(r1)
- X sob r0,1b
- X br 5f
- X3:
- X add -(r2),(r1)
- X sec
- X sob r0,1b
- X br 5f
- X4:
- X clc
- X1:
- X sbc -(r1) / signs are not so subtract
- X bcs 3f
- X sub -(r2),(r1)
- X sob r0,1b
- X br 5f
- X3:
- X sub -(r2),(r1)
- X sec
- X sob r0,1b
- Xsaret: / return of a signed areg
- X mov $areg,r1
- X5:
- X tst (r1) / is it negative
- X bge 3f
- X mov $areg+8,r1
- X mov $4,r0
- X clc
- X1:
- X adc -(r1) / yes then make positive
- X bcs 2f
- X neg (r1)
- X2:
- X sob r0,1b
- X neg -(r1) / negate sign of areg
- X3:
- Xcreta:
- X
- X jsr pc,norm / normalise result
- X br reta
- X
- Xretb:
- X mov $bsign,r1
- X mov $asign,r2
- X mov $6,r0
- X1:
- X mov (r1)+,(r2)+
- X sob r0,1b
- Xreta:
- X mov 6(r5),r2 / get return address
- Xretng:
- X mov $asign,r0 / convert into normal representation
- X tst (r0)
- X beq unflo
- X mov aexp,r1 / check for overflow
- X cmp r1,$177
- X bgt ovflo
- X cmp r1,$-177
- X blt unflo / check for overflow
- X add $200,r1
- X swab r1
- X clc
- X ror r1
- X tst (r0)+
- X bge 1f
- X bis $100000,r1
- X1:
- X bic $!177,(r0)
- X bis (r0)+,r1
- X mov r1,(r2)+
- X mov (r0)+,(r2)+
- X mov (r0)+,(r2)+
- X mov (r0)+,(r2)+
- X jmp cret
- Xunflo: / return zero on underflow
- X clr (r2)+
- X clr (r2)+
- X clr (r2)+
- X clr (r2)+
- X jmp cret
- X
- X.globl _error
- Xovflo:
- X mov $34.,-(sp) / call error on overflow
- X jsr pc,_error
- Xzerodiv:
- X mov $25.,-(sp) / call error for zero divisor
- X jsr pc,_error
- X
- X_fdiv: jsr r5,csv
- X jsr pc,setab / setup parameters
- X tst bsign / check for zero divisor
- X beq zerodiv
- X sub bexp,aexp
- X jsr pc,xorsign / set the signs correctly
- X jsr pc,divv / call the division routine
- X jmp creta / jump to return
- X
- Xdivv:
- X mov r5,-(sp) / this routine is taken straight
- X mov $areg,r0 / out of the floating point
- X mov (r0),r1 / interpreter. If you have enough
- X clr (r0)+ / time, try to find out how it
- X mov (r0),r2 / works.
- X clr (r0)+
- X mov (r0),r3
- X clr (r0)+
- X mov (r0),r4
- X clr (r0)+
- X mov $areg,r5
- X mov $400,-(sp) / ??????
- X1:
- X mov $breg,r0
- X cmp (r0)+,r1
- X blt 2f
- X bgt 3f
- X cmp (r0)+,r2
- X blo 2f
- X bhi 3f
- X cmp (r0)+,r3
- X blo 2f
- X bhi 3f
- X cmp (r0)+,r4
- X bhi 3f
- X2:
- X mov $breg,r0
- X sub (r0)+,r1
- X clr -(sp)
- X sub (r0)+,r2
- X adc (sp)
- X clr -(sp)
- X sub (r0)+,r3
- X adc (sp)
- X sub (r0)+,r4
- X sbc r3
- X adc (sp)
- X sub (sp)+,r2
- X adc (sp)
- X sub (sp)+,r1
- X bis (sp),(r5)
- X3:
- X asl r4
- X rol r3
- X rol r2
- X rol r1
- X clc
- X ror (sp)
- X bne 1b
- X mov $100000,(sp)
- X add $2,r5
- X cmp r5,$areg+8
- X blo 1b
- X tst (sp)+
- X mov (sp)+,r5
- X rts pc
- X
- X_fmul: jsr r5,csv / almost same as _fdiv
- X jsr pc,setab
- X add bexp,aexp
- X dec aexp
- X jsr pc,xorsign
- X jsr pc,mull
- X jmp creta
- Xmull:
- X mov r5,-(sp) / also taken from the interpreter
- X mov $breg+8,r5
- X clr r0
- X clr r1
- X clr r2
- X clr r3
- X clr r4
- X1:
- X asl r0
- X bne 2f
- X inc r0
- X tst -(r5)
- X2:
- X cmp r0,$400
- X bne 2f
- X cmp r5,$breg
- X bhi 2f
- X mov $areg,r0
- X mov r1,(r0)+
- X mov r2,(r0)+
- X mov r3,(r0)+
- X mov r4,(r0)+
- X mov (sp)+,r5
- X rts pc
- X2:
- X clc
- X ror r1
- X ror r2
- X ror r3
- X ror r4
- X bit r0,(r5)
- X beq 1b
- X mov r0,-(sp)
- X mov $areg,r0
- X add (r0)+,r1
- X clr -(sp)
- X add (r0)+,r2
- X adc (sp)
- X clr -(sp)
- X add (r0)+,r3
- X adc (sp)
- X add (r0)+,r4
- X adc r3
- X adc (sp)
- X add (sp)+,r2
- X adc (sp)
- X add (sp)+,r1
- X mov (sp)+,r0
- X br 1b
- X
- X.globl _integ
- X_integ:
- X jsr r5,csv
- X mov 4(r5),r2
- X mov $asign,r0
- X jsr pc,seta
- X clr r0
- X mov $200,r1
- X clr r2
- X1:
- X cmp r0,aexp
- X blt 2f
- X bic r1,areg(r2)
- X2:
- X inc r0
- X clc
- X ror r1
- X bne 1b
- X mov $100000,r1
- X add $2,r2
- X cmp r2,$8
- X blt 1b
- X mov 4(r5),r2
- X jmp retng
- X
- X
- X.globl _fmod
- X_fmod:
- X jsr r5,csv / this routine cheats.
- X jsr pc,setab
- X jsr pc,divv / the function 'a mod b' ==
- X sub bexp,aexp
- X jsr pc,norm
- X clr r0 / count
- X mov $200,r1 / bit
- X clr r2 / reg offset
- X1:
- X cmp r0,aexp
- X bge 2f / in fraction
- X bic r1,areg(r2) / this bit of code is taken from
- X2: / the f.p. interpreter's mod function
- X inc r0 / N.B. this does not do the same thing
- X clc / as _fmod.
- X ror r1
- X bne 1b
- X mov $100000,r1
- X add $2,r2
- X cmp r2,$8
- X blt 1b
- X jsr pc,norm
- X jsr pc,mull
- X add bexp,aexp
- X dec aexp
- X jmp creta
- X
- Xxorsign:
- X cmp asign,bsign
- X beq 1f
- X mov $-1,asign
- X rts pc
- X1:
- X mov $1,asign
- X rts pc
- X
- Xsetab:
- X mov $asign,r0 / set up both areg and breg
- X mov 4(r5),r2
- X jsr pc,seta
- X mov 6(r5),r2
- X mov $bsign,r0
- X
- Xseta:
- X clr (r0) / set up one register
- X mov (r2)+,r1
- X mov r1,-(sp)
- X beq 1f
- X blt 2f
- X inc (r0)+
- X br 3f
- X2:
- X dec (r0)+
- X3:
- X bic $!177,r1
- X bis $200,r1
- X br 2f
- X1:
- X clr (r0)+
- X2:
- X mov r1,(r0)+
- X mov (r2)+,(r0)+
- X mov (r2)+,(r0)+
- X mov (r2)+,(r0)+
- X mov (sp)+,r1
- X asl r1
- X clrb r1
- X swab r1
- X sub $200,r1
- X mov r1,(r0)+ / exp
- X rts pc
- X
- Xnorm:
- X mov $areg,r0 / normalise the areg
- X mov (r0)+,r1
- X mov r1,-(sp)
- X mov (r0)+,r2
- X bis r2,(sp)
- X mov (r0)+,r3
- X bis r3,(sp)
- X mov (r0)+,r4
- X bis r4,(sp)+
- X bne 1f
- X clr asign
- X rts pc
- X1:
- X bit $!377,r1
- X beq 1f
- X clc
- X ror r1
- X ror r2
- X ror r3
- X ror r4
- X inc (r0)
- X br 1b
- X1:
- X bit $200,r1
- X bne 1f
- X asl r4
- X rol r3
- X rol r2
- X rol r1
- X dec (r0)
- X br 1b
- X1:
- X mov r4,-(r0)
- X mov r3,-(r0)
- X mov r2,-(r0)
- X mov r1,-(r0)
- X rts pc
- X
- X.bss
- Xasign: .=.+2 / the areg - sign
- Xareg: .=.+8 / - mantissa
- Xaexp: .=.+2 / - exponent
- Xbsign: .=.+2 / the breg
- Xbreg: .=.+8
- Xbexp: .=.+2
- Xcsign: .=.+2 / the creg - this register was added so that other functions
- Xcreg: .=.+8 / could use this set up. e.g. sqrt()
- Xcexp: .=.+2 / it could be that when sin() is implemented a
- X / fourth register might be needed
- End of pdp11/nfp.s
- chmod u=rw-,g=r,o=r pdp11/nfp.s
- echo x - pdp11/term.c 1>&2
- sed 's/^X//' > pdp11/term.c << 'End of pdp11/term.c'
- X/*
- X * BASIC by Phil Cockcroft
- X */
- X/*
- X * machine dependent terminal interface
- X */
- X
- X#include "pdp11/conf.h"
- X#ifdef V7
- X#include <sgtty.h>
- X#endif
- X
- X#ifndef V7
- X
- Xstruct term { /* the structure for the terms */
- X char _j[4]; /* system call */
- X int flags; /* most of it is not needed */
- X char __j[4];
- X char width,length;
- X int ___j[8];
- X } nterm, oterm;
- X
- X#else
- X
- X#ifndef SCOPE
- X#define SCOPE 0
- X#endif
- X
- X#ifdef TIOCOSTP
- X#undef TIOCSLPN
- X#endif
- X
- X#ifdef TIOCSLPN
- Xstruct lsgttyb osttyb,nsttyb;
- X#undef TIOCGETP
- X#undef TIOCSETN
- X#define TIOCGETP TIOCGLPG
- X#define TIOCSETN TIOCSLPN
- X#else
- Xstruct sgttyb osttyb,nsttyb;
- X#endif
- Xstruct tchars ntchr,otchr;
- X#ifdef UCB_NTTY
- Xstruct ltchars nltchr,oltchr;
- X#endif
- X
- X#endif
- X
- Xextern int ter_width;
- Xextern char noedit;
- X
- Xstatic int got_mode;
- X
- Xsetu_term()
- X{
- X register i;
- X#ifdef V7
- X char *p, *getenv();
- X
- X p = getenv("TERM");
- X ioctl(0,TIOCGETP,&osttyb);
- X nsttyb=osttyb;
- X#ifdef TIOCSLPN
- X osttyb.lsg_length = DEFLENGTH;
- X nsttyb.lsg_length = 0;
- X if(ter_width <= 0)
- X ter_width = osttyb.lsg_width & 0377;
- X osttyb.lsg_width = DEFPAGE;
- X nsttyb.lsg_width = 0;
- X#endif
- X#ifdef TIOCOSTP
- X osttyb.sg_length = DEFLENGTH;
- X nsttyb.sg_length = 0;
- X if(ter_width <= 0)
- X ter_width = osttyb.sg_width & 0377;
- X osttyb.sg_width = DEFPAGE;
- X nsttyb.sg_width = 0;
- X#endif
- X ioctl(0,TIOCGETC,&otchr);
- X ntchr = otchr; /* do we need this ??? */
- X if(p && strcmp(p, "ucl7009") == 0){
- X ntchr.t_startc = -1;
- X ntchr.t_stopc = -1;
- X }
- X ntchr.t_brkc = -1;
- X ntchr.t_eofc = -1;
- X ntchr.t_intrc = CTRLINT;
- X ntchr.t_quitc = CTRLQUIT;
- X#ifdef TIOCSLPN
- X i = osttyb.lsg_flags & ( LCASE | XTABS);
- X nsttyb.lsg_flags = CBREAK | ANYP | i;
- X osttyb.lsg_flags = ECHO | ANYP | CRMOD | SCOPE | i;
- X#else
- X i = osttyb.sg_flags & ( LCASE | XTABS);
- X nsttyb.sg_flags = CBREAK | ANYP | i;
- X osttyb.sg_flags = ECHO | ANYP | CRMOD | SCOPE | i;
- X#endif
- X
- X#ifdef UCB_NTTY
- X ioctl(0,TIOCGLTC,&oltchr);
- X nltchr = oltchr; /* is this needed ?? */
- X nltchr.t_suspc = -1;
- X nltchr.t_dsuspc = -1;
- X nltchr.t_rprntc = -1;
- X nltchr.t_flushc = -1;
- X nltchr.t_werasc = -1;
- X nltchr.t_lnextc = -1;
- X#endif
- X#else
- X terms(0,('t'<<8)+2,&oterm);
- X#ifndef V6C
- X nterm = oterm;
- X#else
- X terms(0,('t'<<8)+2,&nterm);
- X#endif
- X nterm.width=0;
- X nterm.length=0;
- X i= oterm.flags & 04;
- X nterm.flags= 040340 |i;
- X if(ter_width <= 0)
- X ter_width = oterm.width & 0377;
- X oterm.width=0;
- X oterm.length=DEFLENGTH;
- X oterm.flags= 0730 | i;
- X#endif
- X if(ter_width <= 0)
- X ter_width=DEFPAGE;
- X got_mode = 1;
- X}
- X
- Xset_term()
- X{
- X if(noedit || !got_mode)
- X return;
- X#ifdef V7
- X ioctl(0,TIOCSETN,&nsttyb);
- X ioctl(0,TIOCSETC,&ntchr);
- X#ifdef UCB_NTTY
- X ioctl(0,TIOCSLTC,&nltchr);
- X#endif
- X#else
- X terms(0,('t'<<8)+3,&nterm);
- X#endif
- X}
- X
- Xrset_term(type)
- X{
- X
- X if(noedit || !got_mode)
- X return;
- X#ifdef V7
- X#ifdef TIOCOSTP
- X if(type)
- X osttyb.sg_width=ter_width;
- X#endif
- X#ifdef TIOCSLPN
- X if(type)
- X osttyb.lsg_width=ter_width;
- X#endif
- X ioctl(0,TIOCSETN,&osttyb);
- X ioctl(0,TIOCSETC,&otchr);
- X#ifdef UCB_NTTY
- X ioctl(0,TIOCSLTC,&oltchr);
- X#endif
- X#else
- X if(type)
- X oterm.width=ter_width;
- X terms(0,('t'<<8)+3,&oterm); /* reset terminal modes */
- X#endif
- X}
- End of pdp11/term.c
- chmod u=rw-,g=r,o=r pdp11/term.c
- echo x - pyramid/Makefile 1>&2
- sed 's/^X//' > pyramid/Makefile << 'End of pyramid/Makefile'
- X# Makefile for a pyramid
- X
- X# which cursor file we want.
- X# can be ucl or ukc
- XCURSOR = ucl
- X
- Xbasic: bas1.o bas2.o bas3.o bas4.o bas5.o bas6.o bas7.o bas8.o \
- X bas9.o cursor.o termcap.o assist.o term.o
- X cc -O bas1.o bas2.o bas3.o bas4.o bas5.o bas6.o bas7.o \
- X bas8.o bas9.o cursor.o termcap.o assist.o term.o -lm -ltermcap -o basic
- X
- Xclean:
- X rm -f *.o *.s cursor.c term.c
- X
- Xassist.o: bas.h assist.c
- X cc -O -c -Dpyramid assist.c
- X
- Xtermcap.o: bas.h termcap.c cursor.c
- X cc -O -c -Dpyramid termcap.c
- X
- Xcursor.c: cursor/cursor.c.${CURSOR}
- X cp cursor/cursor.c.${CURSOR} cursor.c
- X
- Xcursor.o: cursor.c
- X cc -O -c -Dpyramid cursor.c
- X
- Xterm.o: term.c
- X cc -O -c -Dpyramid term.c
- X
- Xterm.c: pyramid/term.c pyramid/conf.h
- X cp pyramid/term.c term.c
- X
- X.c.o:
- X cc -O -c -Dpyramid -DBSD42 $*.c
- X
- Xbas.h: pyramid/conf.h
- X
- Xbas1.o: bas1.c bas.h
- Xbas2.o: bas2.c bas.h
- Xbas3.o: bas3.c bas.h
- Xbas4.o: bas4.c bas.h
- Xbas5.o: bas5.c bas.h
- Xbas6.o: bas6.c bas.h
- Xbas7.o: bas7.c bas.h
- Xbas7.c: cursor.c
- Xbas8.o: bas8.c bas.h
- Xbas9.o: bas9.c bas.h
- End of pyramid/Makefile
- chmod u=rw-,g=r,o=r pyramid/Makefile
-
-