From d1b101b3ebe60254565c3416f3313ff498b91f39 Mon Sep 17 00:00:00 2001 From: Adam Sampson Date: Mon, 9 Apr 2018 23:25:06 +0100 Subject: [PATCH] Reformat FACTOR disassembly to match RZ;FACTOR 26. @larsbrinkhoff found the source for a slightly later version of FACTOR. This produces the same binary as my original disassembly, but matches RZ's source where possible, for easier comparison. --- src/sysen3/factor.100 | 299 ------------------------------------------ src/sysen3/factor.101 | 289 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 289 insertions(+), 299 deletions(-) delete mode 100644 src/sysen3/factor.100 create mode 100644 src/sysen3/factor.101 diff --git a/src/sysen3/factor.100 b/src/sysen3/factor.100 deleted file mode 100644 index 028d46b2..00000000 --- a/src/sysen3/factor.100 +++ /dev/null @@ -1,299 +0,0 @@ -;Factor integers using trial division -*-MIDAS-*- -;This was reconstructed in 2018 from AI:SYS1;TS FACTOR, dated 1977-09-27. - -Z=0 -A=1 -B=2 -C=3 -D=4 -DV=5 -E=5 -P=6 - -TTYI=1 -TTYO=2 -FILEI=3 -.KILL TTYI, TTYO, FILEI - -;This is the inner loop of the trial division code - it's loaded into -;the registers to speed it up. -LOC 7 -;CD is the number being tested. E is the candidate factor. -;The TRC/ADDI self-modifying code means that it alternates between -;adding 2 and 4 to E on each iteration, so the factors it tries are -;5, 7, 11, 13, 17, 19, 23, 25... i.e. it skips multiples of 2 and 3. -;(See for more about this sequence.) -TEST: TRC INCR,6 ;Complement the 2 and 4 bits in ADDI below -INCR: ADDI E,2 ;Next candidate; modified by TEST/NO3 -RETEST: MOVE Z,C - MOVE B,D - IDIV Z,E ;Z := Z div E; A := Z mod E - DIV A,E ;A := AB div E; B := AB mod E - CAMLE E,A - JUMPE Z,PRIME ;No more factors to try, so CD is prime - JUMPN B,TEST ;Not divisible by E; try the next candidate -;That's the end of the registers; the instruction below is at 20. - JRST FOUND ;Found a factor (but CD may still be composite) - -;Entry point -LOC 100 -G0: -PDLL: MOVE P,[777700,,PDL] - .OPEN TTYI,[10+.UAI,,'TTY] ;Open in "DDT mode" (don't echo CR etc.) - .VALUE 0 - .OPEN TTYO,[.UAO,,'TTY] - .VALUE 0 -DECIMA: MOVEI C,10. ;Base 10 input by default -RADSET: MOVEM C,RADX -RESET: PUSHJ P,PROMPT -ZBC: SETZB B,C ;BC holds current value; clear it -LOOP: PUSHJ P,TYI ;Read key and dispatch appropriately - CAIN A,177 ;RUBOUT - JRST RESET - CAIN A,"R - JRST RADSET - CAIN A,"D - JRST DECIMA - CAIE A,": - CAIN A,"* - JRST TIMES - CAIN A,"? - JRST INFO - CAIN A,"C - JRST CLIST - CAIN A,"Q - JRST QUERY - CAIN A,"N - JRST LOAD - CAIE A,"; - CAIN A,"+ - JRST PLUS - CAIN A,"- - JRST MINUS - CAIN A,"L - JRST LARGE - CAIN A,"F - JRST FACTOR - CAIN A,40 ;space - JRST STM2 - CAIN A,"/ - JRST DIVIDE - CAIN A,"^ - JRST POWER - CAIN A,"= - JRST EQUAL - CAIL A,"0 - CAILE A,"9 - JRST HUH ;Not recognised - IMUL B,RADX ;A digit - add it to BC - MUL C,RADX - ADDI D,777720(A) - TLZE D,400000 - AOS C - ADD B,C - MOVE C,D - JRST LOOP - -INFO: PUSHJ P,INFOPN ;Show the whole info file - .IOT FILEI,A - JUMPLE A,RESET - .IOT TTYO,A - JRST .-3 - -INFOPN: ;Open the info file - .SUSET [.SSNAM,,[SIXBIT/.INFO./]] - .OPEN FILEI,[.UAI,,'DSK ? SIXBIT/FACTOR/ ? SIXBIT/ORDER/] - JRST INFLOS - POPJ P, - -INFLOS: SUB P,[1,,1] ;Info file can't be opened - MOVE B,[440700,,[ASCIZ/CAN'T OPEN INFO FILE/]] - JRST Q3 - -QUERY: PUSHJ P,INFOPN ;Look up a key in the info file - .IOT TTYI,B ;Get a key - CAIL B,"0 ;Digit? - CAILE B,"9 - JRST Q0 - MOVE B,[440700,,[ASCIZ/ DIGIT/]] - JRST Q3 -Q0: .IOT FILEI,A ;Skip chars until LF - JUMPL A,Q1 - CAIE A,12 - JRST Q0 - .IOT FILEI,A ;Read first char - CAME A,B ;Is it the key we're after? - JRST Q0 ;No - try next line - .IOT FILEI,A ;Read second char - JUMPL A,Q1 - CAIE 1,11 ;Is it tab? - JRST Q0 ;No - try next line - JRST Q2+1 ;Found it! - -Q2: .IOT FILEI,A ;Copy from file to tty until newline - .IOT TTYO,A - CAIE A,12 - JRST Q2 - .IOT FILEI,A ;Does next line start with tab? - CAIN 1,11 - JRST Q2+1 ;Yes - print it too - JRST RESET - -CLIST: ;List all keys we know about - SKIPA B,[440700,,[ASCIZ~ RD:*;+-/^NLF =QC?~]] -Q1: ;Key not found in info file - MOVE B,[440700,,[ASCIZ/ IGNORED/]] -Q3: ILDB 1,2 ;Print the ASCIZ string in B - JUMPE A,RESET - .IOT TTYO,A - JRST Q3 - -LOAD: MOVE B,M1 ;N - current value := arg - MOVE C,M2 - JRST LOOP - -POWER: MOVEI Z,777777(C) ;^ - power - MOVE A,M2 - SETZ B, - MOVE C,A -POW1: IMUL B,A - MUL C,A - ADD B,C - MOVE C,D - SOJG Z,POW1 - JRST STM2 - -DIVIDE: MOVE A,C ;/ - divide - MOVE B,M1 - MOVE D,M2 - IDIV B,A - DIV C,A - JRST STM2 - -TIMES: IMUL B,M2 ;* or : - multiply - MOVE A,C - IMUL A,M1 - MUL C,M2 - ADD B,C - ADD B,A - TLZ B,400000 - MOVEM D,M2 - MOVEM B,M1 - JRST ZBC - -MINUS: MOVNS C ;- - subtract - ADD C,[400000,,] - AOS B - MOVNS B -PLUS: ADD C,M2 ;+ - add - ADD B,M1 - TLZE C,400000 - AOS B -STM2: PUSHJ P,STM - JRST ZBC - -LARGE: MOVE B,L1 ;L - current value := largest factor - MOVE C,L2 - JRST STM2 - -STM: MOVEM B,M1 ;space - arg := current value - MOVEM C,M2 - POPJ P, - -EQUAL: MOVE A,M1 ;= - print current value - MOVE B,M2 - PUSHJ P,SPRAB - JRST RESET - -FACTOR: SKIPN C ;F - factor arg - SKIPE B - PUSHJ P,STM ;Arg isn't 0; set current value from arg - MOVE D,M1 ;Put number being factored into DE - MOVE E,M2 -TEST2: JUMPN D,.+3 ;Is DE small? - CAIG E,3 - JRST SPRIME ; DE < 3 - no need to factor - TRNE E,1 ;Is DE divisible by 2? - JRST ODD ; No - ASHC D,777777 ;Take out a factor of 2 - MOVEI B,2 -PRB: SETZM A - PUSHJ P,SPRAB ;Print factor - JRST TEST2 ;... and factor again - -ODD: MOVE A,D ;Is DE divisible by 3? - MOVE C,E - IDIVI A,3 - DIVI B,3 - JUMPN C,NO3 ; No - MOVE D,A ;Take out a factor of 3 - MOVE E,B - MOVEI B,3 - JRST PRB ;Print and factor again - -NO3: MOVE C,D ;Not divisible by 2 or 3: start trial division - MOVE D,E - MOVEI E,5 ;First factor to try - HRRI INCR,4 ;Set next trial division step size - JRST RETEST ;... and jump into code in registers - -FOUND: MOVE D,A ;Trial division found a factor - SETZM A - MOVE B,E - PUSHJ P,SPRAB ;Print it - MOVE C,Z - JRST RETEST ;... and keep looking (starting from existing E) - -SPRIME: MOVE C,D ;DE was a trivial prime to start with - MOVE D,E -PRIME: MOVEM C,L1 ;Found the largest prime factor; save it - MOVEM D,L2 - MOVE A,C - MOVE B,D - PUSHJ P,SPRAB ;Print it - JRST RESET ;Done! - -SPRAB: PUSHJ P,SPACE ;Print a space, then... -PRAB: MOVE C,B ;Print number in AB in decimal - IDIVI A,10. - DIVI B,10. - HRLM 3,(P) - SKIPN B - SKIPE A - PUSHJ P,PRAB - HLRZ 1,(P) - ADDI 1,60 - JRST TYO - -SPACE: PUSH P,A ;Print space - MOVEI A,40 - PUSHJ P,TYO - POP P,A - POPJ P, - -HUH: MOVEI A,"? ;Print ? - PUSHJ P,TYO - JRST LOOP - -PROMPT: PUSHJ P,CR ;Print prompt - MOVEI A,"# - PUSHJ P,TYO -CR: MOVEI A,15 ;Print CRLF - CR - PUSHJ P,TYO - MOVEI A,12 ;LF -TYO: .IOT TTYO,A ;Print character in A - POPJ P, - -TYI: .IOT TTYI,A ;Read character into A - POPJ P, - -PDL: BLOCK 65. -RADX: BLOCK 1 ;Input radix (output is always decimal) -L1: BLOCK 1 ;L1/L2 holds largest factor found -L2: BLOCK 1 -M1: BLOCK 1 ;M1/M2 holds arg -M2: BLOCK 1 - -CONSTA - -END G0 diff --git a/src/sysen3/factor.101 b/src/sysen3/factor.101 new file mode 100644 index 00000000..867eeded --- /dev/null +++ b/src/sysen3/factor.101 @@ -0,0 +1,289 @@ +;Factor integers using trial division -*-MIDAS-*- +;This was reconstructed in 2018 from AI:SYS1;TS FACTOR, dated 1977-09-27. + +TITLE FACTOR + +Z=0 +A=1 +B=2 +C=3 +D=4 +E=5 +DV=5 +P=6 + +.MLLIT==1 + +TYIC==1 +TYOC==2 +INFOC==3 + +PDLL=100 + + LOC 7 +TEST: TRC .+1,6 +INCR: ADDI DV,2 +RETEST: MOVE Z,C + MOVE B,D + IDIV Z,DV + DIV A,DV + CAMLE DV,A + JUMPE Z,PRIME + JUMPN B,TEST + JRST FOUND + + LOC 100 +G0: MOVE P,[-PDLL,,PDL] + .OPEN TYIC,[10,,(SIXBIT /TTY/)] ;Open in "DDT mode" (don't echo CR etc.) + .VALUE 0 + .OPEN TYOC,[1,,(SIXBIT /TTY/)] + .VALUE 0 +DECIMA: MOVEI C,10. +RADSET: MOVEM C,RADX' +RESET: PUSHJ P,PROMPT +ZBC: SETZB B,C + +LOOP: PUSHJ P,TYI + CAIN A,177 ;RUBOUT + JRST RESET + CAIN A,"R + JRST RADSET + CAIN A,"D + JRST DECIMA + CAIE A,": + CAIN A,"* + JRST TIMES + CAIN A,"? + JRST INFO + CAIN A,"C + JRST CLIST + CAIN A,"Q + JRST QUERY + CAIN A,"N + JRST LOAD + CAIE A,"; + CAIN A,"+ + JRST PLUS + CAIN A,"- + JRST MINUS + CAIN A,"L + JRST LARGE + CAIN A,"F + JRST FACTOR + CAIN A,40 ;space + JRST STM2 + CAIN A,"/ + JRST DIVIDE + CAIN A,"^ + JRST POWER + CAIN A,"= + JRST EQUAL + CAIL A,"0 + CAILE A,"9 + JRST HUH ;Not recognised + IMUL B,RADX + MUL C,RADX + ADDI D,-"0(A) + TLZE D,400000 + AOS C + ADD B,C + MOVE C,D + JRST LOOP + +INFO: PUSHJ P,INFOPN + .IOT INFOC,1 + JUMPLE A,RESET + .IOT TYOC,1 + JRST INFO+1 + +INFOPN: .SUSET [.SSNAM,,[SIXBIT/.INFO./]] + .OPEN INFOC,[.UAI,,'DSK ? SIXBIT/FACTOR/ ? SIXBIT/ORDER/] + JRST INFLOS + POPJ P, + +INFLOS: SUB P,[1,,1] + MOVE B,[440700,,[ASCIZ \CAN'T OPEN INFO FILE\]] + JRST Q3 + +QUERY: PUSHJ P,INFOPN + .IOT TYIC,2 + CAIL 2,"0 + CAILE 2,"9 + JRST Q0 + MOVE 2,[440700,,[ASCIZ/ DIGIT/]] + JRST Q3 +Q0: .IOT INFOC,1 + JUMPL A,Q1 + CAIE 1,12 ;LINE FEED + JRST Q0 + .IOT INFOC,1 + CAME 1,2 + JRST Q0 + .IOT INFOC,1 + JUMPL 1,Q1 + CAIE 1,11 ;TAB + JRST Q0 + JRST .+2 +Q2: .IOT INFOC,1 + .IOT TYOC,1 + CAIE 1,12 ;LINE FEED? + JRST Q2 + .IOT INFOC,1 + CAIN 1,11 ;TAB? + JRST Q2+1 + JRST RESET + +CLIST: SKIPA 2,[440700,,[ASCIZ 7 RD:*;+-/^NLF =QC?7]] +Q1: MOVE 2,[440700,,[ASCIZ/ IGNORED/]] +Q3: ILDB 1,2 + JUMPE 1,RESET + .IOT 2,1 + JRST .-3 + +LOAD: MOVE B,M1 + MOVE C,M2 + JRST LOOP + +POWER: MOVEI Z,-1(C) + MOVE A,M2 + SETZ B, + MOVE C,A +POW1: IMUL B,A + MUL C,A + ADD B,C + MOVE C,D + SOJG Z,POW1 + JRST STM2 + +DIVIDE: MOVE A,C + MOVE B,M1 + MOVE D,M2 + IDIV B,A + DIV C,A + JRST STM2 + +TIMES: IMUL B,M2 + MOVE A,C + IMUL A,M1 + MUL C,M2 + ADD B,C + ADD B,A + TLZ B,400000 + MOVEM D,M2 + MOVEM B,M1 + JRST ZBC + +MINUS: MOVNS C + ADD C,[SETZ] + AOS B + MOVNS B +PLUS: ADD C,M2 + ADD B,M1 + TLZE C,400000 + AOS B +STM2: PUSHJ P,STM + JRST ZBC + +LARGE: MOVE B,L1' + MOVE C,L2' + JRST STM2 + +STM: MOVEM B,M1' + MOVEM C,M2' + POPJ P, + +EQUAL: MOVE A,M1 + MOVE B,M2 + PUSHJ P,SPRAB + JRST RESET + +FACTOR: SKIPN C + SKIPE B + PUSHJ P,STM + MOVE D,M1 + MOVE DV,M2 +TEST2: JUMPN D,.+3 + CAIG DV,3 + JRST SPRIME + TRNE DV,1 + JRST ODD + ASHC D,-1 + MOVEI B,2 +PRB: SETZM A + PUSHJ P,SPRAB + JRST TEST2 +ODD: MOVE A,D + MOVE C,DV + IDIVI A,3 + DIVI B,3 + JUMPN C,NO3 + MOVE D,A + MOVE DV,B + MOVEI B,3 + JRST PRB +NO3: MOVE C,D + MOVE D,DV + MOVEI DV,5 + HRRI INCR,4 + JRST RETEST + +FOUND: MOVE D,A + SETZM A + MOVE B,DV + PUSHJ P,SPRAB + MOVE C,Z + JRST RETEST + +SPRIME: MOVE C,D + MOVE D,DV + +PRIME: MOVEM C,L1 + MOVEM D,L2 + MOVE A,C + MOVE B,D + PUSHJ P,SPRAB + JRST RESET + +SPRAB: PUSHJ P,SPACE +PRAB: MOVE C,B + IDIVI A,10. + DIVI B,10. + HRLM C,(P) + SKIPN B + SKIPE A + PUSHJ P,PRAB + HLRZ A,(P) + ADDI A,"0 + JRST TYO + +SPACE: PUSH P,A + MOVEI A,40 + PUSHJ P,TYO + POP P,A + POPJ P, + +HUH: MOVEI A,"? + PUSHJ P,TYO + JRST LOOP + +PROMPT: PUSHJ P,CR + MOVEI A,"# + PUSHJ P,TYO + +CR: MOVEI A,15 + PUSHJ P,TYO + MOVEI A,12 + +TYO: .IOT TYOC,A + POPJ P, + +TYI: .IOT TYIC,A + POPJ P, + +PDL: BLOCK PDLL+1 + +VARIABLES +CONSTANTS + + END G0 +