The Prime Generator Algorithm


       DEF  PRIME
 
       AORG >2800             * SLOW MEMORY
 
IDLEWS EQU  >8300             * IDLE WORKSPACE
FASTWS EQU  >83B6             * HIGHEST POSSIBLE WORKSPACE
MSKREG EQU  >83C2             * MASK-REGISTER FOR INTERRUPT
USRINT EQU  >83C4             * USER-INTERRUPT
TIMER  EQU  >83D6             * TIMER-REGISTER
DISPLY EQU  >8366             * DISPLAY IN FAST MEMORY
PRIM   EQU  >8300             * PRIME-KERNEL IN FAST MEMORY
 
VDPPOS EQU  0                 * SCREEN POSITION
WRTDAT EQU  1                 * VDP-WRITE DATA
WRTADR EQU  2                 * VDP-WRITE ADDRESS
RDDATA EQU  3                 * VDP-READ DATA
PRIMEH EQU  4                 * PRIME NUMBER HIGH
PRIMEL EQU  5                 * PRIME NUMBER LOW
T0     EQU  6                 * TEMP. REG. >83C2 !
T1     EQU  7                 * TEMP. REG. >83C4 !
T2     EQU  8                 * TEMP. REG.
MEMPOS EQU  T2                * POINTER INTO DYNAMIC TABLE
TMPPTR EQU  9                 * TEMP. POINTER
DIV10  EQU  10                * FIXED NUMBER 10 FOR FASTER CALC.
CRU    EQU  12                * CRU-BASE REGISTER
OFFIDX EQU  CRU               * OFFSET INDEX
D0     EQU  13                * TEMP. REGISTERS FOR DISPLAY
D1     EQU  14                * DITO
D2     EQU  15                * DITO
RDPOS  EQU  D1                * TEMP. REG. FOR SCROLL READ POSITION
WRTPOS EQU  D2                * DITO BUT FOR WRITE POSITION
 
OFFCNT EQU  5760              * (2-1)x(3-1)x(5-1)x(7-1)x(11-1)x(13-1)
OFFSET EQU  >A000             * MEMORY START
DYNTBL EQU  OFFCNT*2+OFFSET   * POSITION OF DYNAMIC-TABLE OFFCNT WORDS LATER
 
FPRIME DATA 2,3,5,7,11,13     * FIRST PRIMES FOR OFFSET-TABLE
FPRMLA EQU  $
 
TIME   DATA >5078             * ONE HOUR
MASK   DATA >6000             * NO SPRITES, NO SOUND, ONLY QUIT
D10000 DATA 10000
 
NUMBER DATA >0038,>4444,>4444,>4438
       DATA >0010,>3010,>1010,>1038
       DATA >0038,>4404,>0810,>207C
       DATA >0038,>4404,>1804,>4438
       DATA >0008,>1828,>487C,>0808
       DATA >007C,>4078,>0404,>4438
       DATA >0018,>2040,>7844,>4438
       DATA >007C,>0408,>1020,>2020
       DATA >0038,>4444,>3844,>4438
       DATA >0038,>4444,>3C04,>0830
       DATA >0000,>0000,>0000,>0000
 
*-----------------------------+ SCROLL-ROUTINE / SLOW MEMORY
SCRDAT SETO T0                ! SET THE INTERRUPT-MASK TO CHECK ONLY FOR THE
       LI   T1,INT            ! USER-INTERRUPT
       MOV  @>8378,D1         ! SAVE >8378 AND >837A BECAUSE I HAVE CODE AT
       MOV  @>837A,D2         ! THIS LOCATIONS AND THE INTERRUPT ALTER THIS
       LIMI 1                 ! LOCATIONS
       LIMI 0                 ! INT. ON/OFF
       MOV  D1,@>8378         ! RESTORE THEM
       MOV  D2,@>837A         !
       LI   RDPOS,>20         ! PREPARE SOME REGISTERS FOR SCROLLING THE
       LI   WRTPOS,>4000      ! SCREEN
       LI   VDPPOS,>42E6      !
       MOVB @RDPOS*2+FASTWS+1,*WRTADR
       MOVB RDPOS,*WRTADR     !
       LI   TMPPTR,SCROLL+>D00
*-----------------------------+
       MOVB *RDDATA,*TMPPTR+  !
       MOVB @WRTPOS*2+FASTWS+1,*WRTADR
       MOVB WRTPOS,*WRTADR    !
       LI   TMPPTR,SCROLL+>D00
       MOVB *TMPPTR+,*WRTDAT  !
       RT                     !
*-----------------------------+
 
*******************************
*                             *
*      INTERRUPT-ROUTINE      *
*      FOR WATCHDOG-TIMER     *
*                             *
*******************************
INT    C    @TIMER,@TIME      * ANY TIME LEFT?
       JHE  READY             * NO! -> TERMINATE
       CLR  CRU               * CRU-BASE
       SBZ  0                 * CONTROL-MASK ON
       SBZ  1                 * EXT. INT OFF
       SBZ  2                 * VDP INT OFF
       SBO  3                 * TIMER INT ON
       RT                     * THAT'S IT!
 
READY  LWPI IDLEWS            * SWITCH TO A NEUTRAL WORKSPACE
       CLR  CRU               * SET CRU-BASE ADDRESS
       SBZ  0                 * TMS9901 -> MASK ON
       SBO  1                 * ENABLE EXT. INT
       SBO  2                 * ENABLE VDP INT
       SBZ  3                 * DISABLE THE TIMER
       MOV  @MASK,@MSKREG     * LET THE INT-ROUTINE CHECK ONLY FOR "QUIT"
       CLR  @USRINT           * YET NO USER-ROUTINE AVAILABLE
       SETO @TIMER            * SWITCH OFF THE SCREEN-SAVER
       LIMI 1                 * INTERRUPTS ON
ORACLE JMP  ORACLE            * WAIT FOR THE ORACLE...
 
*******************************
*                             *
*      MAIN PROGRAM           *
*                             *
*******************************
PRIME  LWPI FASTWS
       LI   T0,SCROLL         * COMPLETE THE PROGRAM WITH THE SCROLL-ROUTINE
       LI   T1,SCRDAT
       LI   T2,26
INTROL MOV  *T1+,*T0+
       DEC  T2
       JNE  INTROL
       LI   T2,>2DF
RDLOP  MOV  *T1,*T0+
       DEC  T2
       JNE  RDLOP
       MOV  *T1+,*T0+
       MOV  *T1+,*T0+
       MOV  *T1+,*T0+
       MOV  *T1+,*T0+
       MOV  *T1+,*T0+
       MOV  *T1+,*T0+
       LI   T2,>2DF
WRTLOP MOV  *T1,*T0+
       DEC  T2
       JNE  WRTLOP
       MOV  *T1+,*T0+
       MOV  *T1,*T0
 
*******************************
*                             *
*    COPY THE PRIME-KERNEL    *
*                             *
*******************************
       LI   T0,PRIM
       LI   T1,PRIMOK
       LI   T2,SCROLL-PRIMOK
TRANSF MOV  *T1+,*T0+
       DECT T2
       JNE  TRANSF
 
*******************************
*                             *
*    MAKE THE OFFSET-TABLE    *
*                             *
*******************************
       LI   D0,1              * LAST "PRIME" (WHICH IS NONE)
       MOV  @FPRIME,D1        * FIRST NUMBER TO BE CHECKED
       LI   D2,FPRIME         * POINTER TO PRIME-DIVISORS
       LI   T2,OFFSET         * POINTER TO OFFSET-TABLE
OFFLOP CLR  T0                * CHECK IF THE NUMBER IS DIVIDEABLE
       MOV  D1,T1
       DIV  *D2+,T0
       MOV  T1,T1
       JEQ  OFFNXT            * YES, BAD NUMBER TAKE THE NEXT ONE
       CI   D2,FPRMLA         * ALL DIVISORS CHECKED?
       JNE  OFFLOP
       MOV  D1,*T2            * OK, THIS ONE IS GREAT!
       S    D0,*T2+           * BUILD THE OFFSET
       MOV  D1,D0             * MOVE THE NEW TO THE LAST ONE
OFFNXT LI   D2,FPRIME         * RESTORE THE POINTER TO THE PRIME-DIVISORS
       INC  D1                * TAKE THE NEXT POTENTIAL NUMBER
       CI   T2,DYNTBL         * TABLE FULL?
       JNE  OFFLOP            * NO, WE HAVE TO WORK
 
*******************************
*                             *
*      SET UP THE TIMER       *
*                             *
*******************************
       CLR  @TIMER            * OK, NOW INITILIZE THE TIMER
       CLR  CRU               * CRU-BASE
       LI   T0,>7FFF          * LOAD MASK WITH HIGHEST VALUE
       LDCR T0,15             * YIELDING A ~0.35 SEC. INTERVALL
 
       LI   WRTDAT,>8C00      * PRESET REGISTER
       LI   WRTADR,>8C02
       LI   RDDATA,>8800
       LI   VDPPOS,>42E6
       LI   DIV10,10
 
*******************************
*                             *
*      REDEFINE THE NUMBERS   *
*                             *
*******************************
       LI   T0,>58            * DEFINE THE CHARS WE NEED
       LI   T1,>4800
       CLR  *WRTADR
       MOVB T1,*WRTADR
       LI   T2,NUMBER
CHARS  MOVB *T2+,*WRTDAT
       DEC  T0
       JNE  CHARS
 
*******************************
*                             *
*      CLEAR THE SCREEN       *
*                             *
*******************************
       LI   T0,>64            * CLEAR SCREEN WITH ONE ADDITIONAL LINE
       LI   T1,>4000
       CLR  *WRTADR
       MOVB T1,*WRTADR
       LI   T2,>A00           * THIS CHAR IS "BLANK"
CLRSCR MOVB T2,*WRTDAT
       MOVB T2,*WRTDAT
       MOVB T2,*WRTDAT
       MOVB T2,*WRTDAT
       MOVB T2,*WRTDAT
       MOVB T2,*WRTDAT
       MOVB T2,*WRTDAT
       MOVB T2,*WRTDAT
       DEC  T0
       JNE  CLRSCR
 
*******************************
*                             *
*      PRIME-ROUTINE          *
*                             *
*******************************
       LI   MEMPOS,FPRIME     * POINTER TO FIRST PRIME
       CLR  PRIMEH            * CLR HIGH WORD
DISPRM MOV  *MEMPOS+,PRIMEL
       BL   @DISPLY           * SHOW THE PRIME
       CI   MEMPOS,FPRMLA     * READY?
       JNE  DISPRM
       LI   OFFIDX,OFFSET     * POINTER TO OFFSETS
       MOV  *OFFIDX+,PRIMEL
       INC  PRIMEL
       LI   MEMPOS,DYNTBL     * LOW MEM FOR PRIMES
       B    @PRIM
 
*-----------------------------+
PRIMOK MOV  PRIMEL,*MEMPOS+   ! DIVE INTO THE PRIME KERNEL AND MAKE THE
       BL   @DISPLY           ! FIRST 6536 PRIMES IN 16 BIT
PRIMKO CI   OFFIDX,DYNTBL     !
       JNE  PRIMAD            !
       LI   OFFIDX,OFFSET     !
PRIMAD A    *OFFIDX+,PRIMEL   !
       JOC  PRIM32            !
PRIMLP LI   TMPPTR,DYNTBL     !
PRIMCK MOV  *TMPPTR,T0        !
       MPY  T0,T0             !
       MOV  T0,T0             !
       JNE  PRIMOK            !
       C    T1,PRIMEL         !
       JH   PRIMOK            !
       MOV  PRIMEL,T1         !
       DIV  *TMPPTR+,T0       !
       MOV  T1,T1             !
       JNE  PRIMCK            !
       JMP  PRIMKO            !
PRIM32 INC  PRIMEH            !
PRM32L LI   TMPPTR,DYNTBL     !
PRM32C MOV  *TMPPTR,T0        !
       MPY  T0,T0             !
       C    T0,PRIMEH         !
       JL   PRMCON            !
       JH   PRM32Y            !
       C    T1,PRIMEL         !
       JH   PRM32Y            !
PRMCON CLR  T0                !
       MOV  PRIMEH,T1         !
       DIV  *TMPPTR,T0        !
       MOV  PRIMEL,T2         !
       DIV  *TMPPTR+,T1       !
       MOV  T2,T2             !
       JNE  PRM32C            !
       JMP  PRM32N            !
PRM32Y BL   @DISPLY           !
PRM32N CI   OFFIDX,DYNTBL     !
       JNE  PRM32M            !
       LI   OFFIDX,OFFSET     !
PRM32M A    *OFFIDX+,PRIMEL   !
       JNC  PRM32L            !
       JMP  PRIM32            !
*-----------------------------+
       MOV  VDPPOS,TMPPTR     ! DISPLAY-ROUTINE
       MOV  PRIMEH,T0         !
       MOV  PRIMEL,T1         !
       DIV  @D10000,T0        ! SPLIT THE NUMBER IN TWO PARTS
       MOV  T1,D1             !
       MOV  T0,T0             !
       JEQ  DIS16L            !
       LI   D2,4              !
DIS32L CLR  D0                ! SHOW THE LOWER PART IF WE HAVE A 32-BIT
       DIV  DIV10,D0          ! VALUE
       MOVB @TMPPTR*2+FASTWS+1,*WRTADR
       MOVB TMPPTR,*WRTADR    !
       MOVB @D1*2+FASTWS+1,*WRTDAT
       DEC  TMPPTR            !
       MOV  D0,D1             !
       DEC  D2                !
       JNE  DIS32L            !
       MOV  T0,D1             !
DIS16L CLR  D0                ! SHOW THE SECOND WORD IN CASE OF A 32-BIT
       DIV  DIV10,D0          ! VALUE
       MOVB @TMPPTR*2+FASTWS+1,*WRTADR
       MOVB TMPPTR,*WRTADR    !
       MOVB @D1*2+FASTWS+1,*WRTDAT
       DEC  TMPPTR            !
       MOV  D0,D1             !
       JNE  DIS16L            !
       AI   VDPPOS,8          ! ADVANCE TO THE  NEXT SCREEN POSITION
       CI   VDPPOS,>4306      ! WAS IT THE LAST?
       JEQ  NEWLIN            ! YES! SO WE HAVE TO SCROLL
       RT                     !
*-----------------------------+
NEWLIN B    @SCROLL
 
SCROLL EQU  $                 * THE PROGRAM EXPAND THE CODE BY ITSELF!
 
       END  PRIME
    

eMail:Koplien@TU-Harburg.d400.DE

© Dr. Henry Koplien