|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - downloadIndex: ┃ T a ┃
Length: 21454 (0x53ce) Types: TextFile Names: »assist.s«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─ ⟦this⟧ »EUUGD11/euug-87hel/sec1/basic/pdp11/assist.s«
/ (c) P. (Rabbit) Cockcroft 1982 / This file contains machine code routines that either can't / be implemented or are very slow in C. / / When the 'shell' command was first added it was noticed that / it would bus-error about five times ( an old form of memory / allocation was being used at the time ) before it started to / do the wait. The reason for this is rather awful. In the call / it uses _nargs to find how many arguments it has got. This is / a routine that will not work in split i and d space, since it tries / to access the text segment. / The routine was thus taken from the C library and has been changed / to need no parameters. It just returns -1 on error or the waited for's / process id. / / pid == -1 if error .globl _wait, cerror wait = 7. _wait: mov r5,-(sp) mov sp,r5 sys wait bec 1f jmp cerror 1: tst 4(r5) beq 1f mov r1,*4(r5) 1: mov (sp)+,r5 rts pc / getch() is used all over the place to get the next character on the line. / It uses 'point' ( _point ) as the pointer to the next character. / It skips over all leading spaces. / It was put into machine code for speed since it does not have to / call csv and cret ( the C subroutine call and return routines ). / this saves a lot of time. It can also be written more efficiently / in machine code. / .text .globl _point , _getch _getch: mov _point,r1 1: cmpb $40,(r1)+ / ignore spaces beq 1b mov r1,_point clr r0 bisb -(r1),r0 rts pc / check() is used by many routines that want to know if there is any / garbage characters after its arguments. e.g. in 'goto' there / should be nothing after the line number. It gives a SYNTAX / error if the next character is not a terminator. / check() was also taken out of C for speed reasons. .globl _point , _check , _elsecount , _error ELSE= 0351 _check: mov _point,r0 1: cmpb $40,(r0)+ beq 1b movb -(r0),r1 beq 1f cmpb r1,$': beq 1f cmpb r1,$ELSE bne 2f tstb _elsecount beq 2f 1: mov r0,_point rts pc 2: mov $1,-(sp) / syntax error jsr pc,_error / startfp() this is called in main to intialise the floating point / hardware if it is used. it is only called once to set up fpfunc() / this routine does nothing in non-floating point hardware machines / .globl _startfp , _fpfunc _startfp: clr _fpfunc rts pc .bss _fpfunc: .=.+2 .text / getop() will convert a number into in ascii form to a binary number / it returns non-zero if the number is ok, with the number in / the union 'res'. It uses the floating point routines (nfp.s) and / some of its storage locations ( areg ) to do the hard work. / If the number will fit into an integer, then the value returned is an / integer, with 'vartype' set accordingly. This convertion to integers / is only operative if the convertion needed is an easy one. / Zero is always returned as an integer. / This routine was written in assembler since it is impossible / to write in C. .globl _getop _getop: jsr r5,csv mov $areg,r0 clr (r0)+ clr (r0)+ clr (r0)+ clr (r0)+ clr aexp clr dpoint clr dflag mov $1,asign clrb _vartype clr count / number of actual digits 1: movb *_point,r4 inc _point cmp r4,$'. bne 4f tst dflag / decimal point bne out1 / already had one so get out of loop inc dflag / set the decimal point flag. br 1b 4: cmp r4,$'0 blt out1 cmp r4,$'9 bgt out1 inc count / we have a digit bit $!07,areg / enough space for another digit bne 2f / no sub $'0,r4 / multiply number by ten mov r4,r2 / and add the new digit. jsr pc,tenmul tst dflag / if we have not had a decimal point beq 1b / don't decrement the significance dec dpoint / counter. br 1b 2: / get here if all digits are filled tst dflag / if decimal point , forget it bne 1b inc dpoint / increment the significance counter br 1b / get some more. out1: tst count / check to see that we have had a digit bne 9f / yes then continue. jmp bad / no goto bad. 9: cmp r4,$'e / do we have an exponent. bne out2 / no. clr count / count number of exponent digits clr r3 / clear exponent value clr r2 / clear exponent sign movb *_point,r4 inc _point cmp r4,$'- / exponents sign bne 1f inc r2 / set the flag br 2f 1: cmp r4,$'+ bne 3f 2: movb *_point,r4 inc _point 3: cmp r4,$'0 / get the exponent digits blt 1f cmp r4,$'9 bgt 1f inc count / we have a digit. sub $'0,r4 cmp r3,$1000. / if the digit would make the exponent blt 7f / greater than ten thousand 3: / for get the following digits movb *_point,r4 / ( we are heading for an overflow ) inc _point cmp r4,$'0 blt 1f cmp r4,$'9 ble 3b br 1f 7: mul $12,r3 / multiply the exponent by ten and add r4,r3 / add the new digit. br 2b / get some more 1: tst r2 / check sign of exponent beq 1f neg r3 1: add r3,dpoint / add the exponent to the decimal tst count / point counter beq bad / check to see if we had any digits out2: dec _point / adjust the character pointer tst dpoint / check to see if number can be ble 1f / multiplied by ten if need be. 2: bit $!07,areg bne 1f / no clr r2 jsr pc,tenmul / multiply by ten dec dpoint bne 2b 1: tst areg / check to see if we have an integer bne 1f tst areg+2 bne 1f tst areg+4 bne 1f tst dpoint bne 2f bit $100000,areg+6 beq 3f 2: tst areg+6 / test for zero bne 1f 3: mov areg+6,_res / yes we have an integer put the movb $1,_vartype / value in 'res' and set 'vartype' inc r0 / stop bad number error, since at this jmp cret / point r0 is zero. 1: mov $56.,aexp / convert to floating point format jsr pc,norm tst dpoint / number wants to be multiplied ble 2f / by ten cmp dpoint,$1000. bgt bad 1: clr r2 jsr pc,tenmul / do it 3: bit $!377,areg / normalise the number bne 1f dec dpoint / decrement the counter bne 1b br 2f 1: mov $areg,r0 / shift right to normalise asr (r0)+ ror (r0)+ ror (r0)+ ror (r0)+ inc aexp cmp aexp,$177 bgt bad br 3b 2: tst dpoint / wants to be divided by ten bge 2f 3: mov $3,r1 1: mov $areg+8,r0 / shift left to save significant asl -(r0) / digits rol -(r0) rol -(r0) rol -(r0) dec aexp sob r1,1b jsr pc,tendiv / divide number by ten 1: bit $200,areg / normalise number bne 1f mov $areg+8,r0 / shift left asl -(r0) rol -(r0) rol -(r0) rol -(r0) dec aexp br 1b 1: inc dpoint bne 3b 2: cmp aexp,$177 / check for overflow bgt bad mov $_res,r2 / return value to 'res' via the floating jmp retng / point return routine, r0 is non-zero bad: clr r0 / bad number , clear r0 jmp cret / return .bss dflag: .=.+2 / temporary space for decimal point counter .text / cmp() is used to compare two numbers , it uses 'vartype' to decide / which kind of variable to test. / The result is -1,0 or 1 , depending on the result of the comparison / .globl _cmp , _vartype _cmp: mov 2(sp),r0 mov 4(sp),r1 tstb _vartype beq 6f cmp (r0)+,(r1)+ blt 4f bgt 3f 5: clr r0 rts pc 3: mov $1,r0 rts pc 4: mov $-1,r0 rts pc / floating point comparisons 6: tst (r0) / straight out of the floating bge 1f / point trap routines tst (r1) bge 1f cmp (r0),(r1) bgt 4b blt 3b 1: cmp (r0)+,(r1)+ bgt 3b blt 4b cmp (r0)+,(r1)+ bne 1f cmp (r0)+,(r1)+ bne 1f cmp (r0)+,(r1)+ beq 5b 1: bhi 3b br 4b / routine to multiply two numbers together. returns zero on overflow / used in dimensio() only. .globl _dimmul _dimmul: mov 2(sp),r1 mul 4(sp),r1 bcc 1f clr r1 1: mov r1,r0 rts pc / The calling routines for the maths functions ( from bas3.c). / The arguments passed to the routines are as follows. / at 6(sp) The operator funtion required. / at 4(sp) The pointer to second parameter and / the location where the result is to be put. / at 2(sp) The pointer to the first parameter. / The jump table is called by the following sequence:- / (*mbin[priority*2+vartype])(&j->r1,&res,j->operator) / / So the values in this table are such that integer and real / types are dealt with separately, and the different types of operators / are also dealt with seperately. / e.g. *, /, mod for reals are dealt with by 'fmdm' / and , or , xor for integers are dealt with by 'andor' / .globl _mbin , csv , cret , _error , _fmul , _fdiv , _fadd , _fsub / jump table for the maths functions / straight from the eval() routine in bas3.c .data _mbin: 0 0 fandor andor comop comop fads ads fmdm mdm fex ex .text / locations from the jump table / integer exponentiation , convert to reals then call the floating / point convertion routines. / ex: mov 2(sp),-(sp) jsr pc,_cvt mov 6(sp),(sp) jsr pc,_cvt tst (sp)+ clrb _vartype fex: jmp _fexp fmdm: cmp $'*,6(sp) / times bne 1f jmp _fmul 1: cmp $'/,6(sp) / div bne 1f jmp _fdiv 1: jmp _fmod / mod mdm: cmp $'*,6(sp) / integer multiply bne 1f mov *2(sp),r0 mul *4(sp),r0 bcs over / overflow br 2f 1: mov *2(sp),r1 / divide or mod sxt r0 div *4(sp),r0 bvs 1f cmp $'/,6(sp) / div bne 2f / no , must be mod. tst r1 bne 3f mov r0,*4(sp) rts pc 2: mov r1,*4(sp) rts pc 1: mov $25.,-(sp) / zero divisor error jsr pc,_error / code to do integer divisions.. etc. 3: mov 2(sp),-(sp) / if the result of the integer division jsr pc,_cvt / is not an integer then convert to mov 6(sp),(sp) / float and call the floationg point jsr pc,_cvt / routine clrb _vartype tst (sp)+ jmp _fdiv fads: / floating add and subtract cmp $'+,6(sp) bne 1f jmp _fadd 1: jmp _fsub ads: mov *2(sp),r1 cmp $'+,6(sp) / add or subtract bne 1f add *4(sp),r1 / add br 2f 1: sub *4(sp),r1 / subtract 2: bvs over1 / branch on overflow mov r1,*4(sp) rts pc over1: tst *2(sp) / move value to 'overfl' sxt r0 over: mov r0,_overfl mov r1,_overfl+2 jmp _over / return via call to 'over' / comparison operators ( float and integer ) / cmp() expects to have only two parameters . So save return address / and so simulate environment. comop: mov (sp)+,comsav / save return address jsr pc,_cmp / call comparison routine mov r0,-(sp) mov 6(sp),-(sp) / call routine to convert jsr pc,_compare / this result into logical result tst (sp)+ mov comsav,(sp) / restore return address rts pc / return .bss comsav: .=.+2 .text / floating logical operators / convert floating types into integers. If the value is non zero / then value has a true (-1) value. / fandor: mov *2(sp),r0 beq 2f mov $-1,r0 2: mov *4(sp),r1 beq 2f mov $-1,r1 2: movb $1,_vartype br 2f / integer logical operators / does a bitwise operaotion on the two numbers ( in r0 , r1 ). / andor: mov *2(sp),r0 mov *4(sp),r1 2: cmpb $356,6(sp) bne 2f com r1 bic r1,r0 br 1f 2: cmp $357,6(sp) bne 2f bis r1,r0 br 1f 2: xor r1,r0 1: mov r0,*4(sp) rts pc / This routine converts a floationg point number into an integers / if the result would overflow then return non zero. / .globl _conv _conv: mov 2(sp),r1 mov (r1)+,r0 beq 3f mov (r1),r1 asl r0 clrb r0 swab r0 sub $200,r0 cmp r0,$20 bge 1f / overflow or underflow sub $8,r0 mov r0,-(sp) / counter mov *4(sp),r0 bic $!0177,r0 bis $200,r0 ashc (sp)+,r0 tst *2(sp) bpl 3f neg r0 3: mov r0,*2(sp) clr r0 rts pc 1: bne 1f cmp *2(sp),$144000 / check for -32768 bne 1f bit r1,$177400 bne 1f mov $-32768.,r0 br 3b 1: rts pc / convert from integer to floating point , this will never fail. / .globl _cvt _cvt: mov r2,-(sp) clr r0 mov *4(sp),r1 beq 4f bpl 1f neg r1 1: mov $220,r2 /counter ashc $8,r0 1: bit $200,r0 bne 1f ashc $1,r0 dec r2 br 1b 1: swab r2 ror r2 tst *4(sp) bpl 1f bis $100000,r2 1: bic $!177,r0 bis r2,r0 4: mov 4(sp),r2 mov r0,(r2)+ mov r1,(r2)+ clr (r2)+ clr (r2)+ mov (sp)+,r2 rts pc / add two numbers used in the 'next' routine / depends on the type of the number. calls error on overflow. / .globl _foreadd _foreadd: add 2(sp),*4(sp) bvs 1f rts pc 1: mov $35.,-(sp) / integer overflow jsr pc,_error / This routine converts a floating point number into decimal / It uses the following algorithm:- / forever{ / If X > 1 then { / X = X / 10 / decpoint++ / continue / } / If X < 0.1 then { / X = X * 10 / decpoint-- / continue / } / } / for i = 1 to 10 do { / digit[i] = int ( X * 10) / X = frac ( X * 10 ) / } / This routine is not very complicated but very fiddly so was one / of the last ones written. / .globl _necvt , tendiv , tenmul _necvt: jsr r5,csv / needs to look like ecvt to clr dpoint / the outside world clr *10.(r5) mov $buf,r3 mov 6(r5),r2 mov r2,mdigit inc r2 mov r2,count tst *4(r5) beq zer bpl 1f inc *10.(r5) / sign part of ecvt 1: mov 4(r5),r2 mov $asign,r0 jsr pc,seta / set up number in areg 1: tst aexp ble 1f mov $3,r1 / number is greater than one 2: mov $areg+8,r0 asl -(r0) / save significant digits rol -(r0) rol -(r0) rol -(r0) dec aexp sob r1,2b jsr pc,tendiv inc dpoint / increment decimal point 2: bit $200,areg bne 1b mov $areg+8,r0 / normalise after the division asl -(r0) rol -(r0) rol -(r0) rol -(r0) dec aexp br 2b 1: cmp aexp,$-3 / number greate than 0.1 bgt 5f blt 2f cmp areg,$314 bgt 5f blt 2f mov $3,r1 mov $areg+2,r0 3: cmp (r0)+,$146314 bhi 5f blo 2f sob r1,3b 2: / no clr r2 jsr pc,tenmul / multiply by ten 3: tstb areg+1 bne 4f dec dpoint br 1b 4: mov $areg,r0 / normalise asr (r0)+ ror (r0)+ ror (r0)+ ror (r0)+ inc aexp br 3b 5: tst aexp / get decimal point in correct place beq 9f 1: mov $areg,r0 asr (r0)+ ror (r0)+ ror (r0)+ ror (r0)+ inc aexp bne 1b 9: clr r2 / get the digits jsr pc,tenmul bic $!377,areg clrb r1 / top word in r1 swab r1 add $'0,r1 movb r1,(r3)+ dec count / got all digits bne 9b br out zer: inc dpoint / deal with zero 1: movb $'0,(r3)+ sob r2,1b out: / correct the last digit mov $buf,r0 add mdigit,r0 movb (r0),r2 add $5,r2 movb r2,(r0) 1: cmpb (r0),$'9 ble 1f / don't correct it movb $'0,(r0) cmp r0,$buf blos 2f incb -(r0) br 1b 2: inc dpoint movb $'1,(r0) / correction has made number a one 1: mov mdigit,r0 / pass values back clrb buf(r0) mov $buf,r0 mov dpoint,*8(r5) jmp cret tenmul: / multiply value in areg by 10 mov $areg+8.,r4 1: mov -(r4),r0 mul $12,r0 bpl 2f add $12,r0 2: add r2,r1 adc r0 mov r1,(r4) mov r0,r2 cmp r4,$areg bne 1b rts pc tendiv: / divide value in areg by 10 mov $areg,r4 clr r0 1: mov (r4),r1 / has to divide by 20 to stop div $24,r0 / multiply thinking there is an asl r0 / overflow cmp r1,$9 ble 2f inc r0 sub $12,r1 2: mov r0,(r4)+ mov r1,r0 cmp r4,$areg+8 bne 1b rts pc .bss mdigit: .=.+2 count: .=.+2 buf: .=.+20. dpoint: .=.+2 .text / convert a long in 'overfl' to a real. uses the floating point / routines. returns via these routines. .globl _over _over: jsr r5,csv clrb _vartype mov _overfl,areg mov _overfl+2,areg+2 clr areg+4 clr areg+6 mov $1,asign mov $32.-8,aexp jmp saret / / put a value into a variable , does the convertions from integer / to real and back as needed. / .globl _putin _putin: cmpb 4(sp),_vartype beq 3f mov $_res,-(sp) tstb 6(sp) beq 2f jsr pc,_conv tst r0 beq 1f mov $35.,(sp) jsr pc,_error / no return 2: jsr pc,_cvt 1: tst (sp)+ 3: mov $_res,r0 mov 2(sp),r1 mov (r0)+,(r1)+ tstb 4(sp) / type of variable that is to be assigned bne 1f / to mov (r0)+,(r1)+ mov (r0)+,(r1)+ mov (r0)+,(r1)+ 1: rts pc / high speed move of variables / can't use floating point moves because of '-0'. .globl _movein _movein: mov 2(sp),r0 mov 4(sp),r1 mov (r0)+,(r1)+ mov (r0)+,(r1)+ mov (r0)+,(r1)+ mov (r0)+,(r1)+ rts pc / puts the value from a variable into 'res'. It might be thought / that 'movein' could be used but it can't for the reason given in / the report. / .globl _getv _getv: mov 2(sp),r0 mov $_res,r1 mov (r0)+,(r1)+ tstb _vartype bne 1f mov (r0)+,(r1)+ mov (r0)+,(r1)+ mov (r0)+,(r1)+ 1: rts pc / move the value in res onto the maths 'stack'. A simple floating / move cannot be used due to the possibility of "minus zero" or / -32768 being in 'res'. This could check 'vartype' but for speed just / does the move. .globl _push _push: mov 2(sp),r1 mov $_res,r0 mov (r0)+,(r1)+ mov (r0)+,(r1)+ mov (r0)+,(r1)+ mov (r0)+,(r1)+ rts pc / negate a number , checks for overflow and for type of number. / .globl _negate _negate: tstb _vartype beq 1f neg _res bvs 2f / negating -32768 rts pc 1: tst _res / stop -0 beq 1f add $100000,_res 1: rts pc 2: mov $044000,_res / 32768 in floating form clr _res+2 clr _res+4 clr _res+6 clrb _vartype rts pc / unary negation .globl _notit _notit: tstb _vartype beq 1f com _res rts pc 1: movb $1,_vartype tst _res bne 1f com _res rts pc 1: clr _res rts pc / routine to dynamically check the stack .globl _checksp _checksp: cmp sp,$160000+1024. blos 1f rts pc 1: mov $44.,(sp) jsr pc,_error / no return