home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / ddjmag / ddj9105.zip / CO_GRAPH.ASC < prev    next >
Text File  |  1991-04-08  |  20KB  |  585 lines

  1. _A COPROCESSOR FOR A COPROCESSOR?_
  2. by Warren Davis and Kan Yabumoto
  3.  
  4. [LISTING ONE]
  5.  
  6. /* C program to perform display of Mandelbrot set. Needs to be 
  7. linked with a module containing the initialize() and put_pixel() */
  8.  
  9. int   screenx, screeny;   /*  These values represent the size of the display */
  10.               /*  screen in pixels. They are initialized in the  */
  11.               /*  initialize() routine called by main().         */
  12.  
  13. /*****************************************************************************
  14. compute_fractal is the heart of our program. Four parameters are passed 
  15. from main() representing two two complex numbers. The first two parameters, 
  16. base_R and base_I, are the real and imaginary portions of upper left corner 
  17. of the screen screen in the complex plane. The last two, span_R and span_I, 
  18. give the size of the area of the complex plane visible on the screen. 
  19. SOME BACKGROUND... This routine computes successive iterations of the equation,
  20. (An = An-1 ** 2) + C where A and C are complex numbers, and C represents a 
  21. point in the complex plane. The initial value of A is 0+0i, and when the 
  22. magnitude of A becomes greater than 2.0, it will be considered that series 
  23. will eventually diverge. The color of pixel at C becomes the number of 
  24. iterations before divergence. If after 256 iterations, there is no divergence,
  25. color 0 is written. The color is used as an index into color palette of the 
  26. display board. COMPLEX ARITHMETIC... For those of you a little rusty on your 
  27. complex arithmetic, the following formulas are supplied...
  28. If W and Z are complex numbers, then each has two parts, real and imaginary.  
  29. (i.e. W = W_real + W_imag * i). W + Z means  (W_real + Z_real) + (W_imag + 
  30. Z_imag) * i W * W means   (W_real * W_real) - (W_imag * W_imag)  + 
  31. (2 * W_real * W_imag) * i.  The magnitude of Z would be  SQRT((Z_real * 
  32. Z_real) + (Z_imag * Z_imag))
  33. ****************************************************************************/
  34.  
  35. void compute_fractal(float BaseR, float BaseI, float SpanR, float SpanI)
  36. {
  37. register float   AR, AI;   /*  Real and Imaginary components of A */
  38. register float   ConstR, ConstI;/* Real and Imaginary components of C */
  39. register float   DeltaR, DeltaI;        /* increment values for C */
  40. register float   ARsqr, AIsqr;            /* squares of AR and AI */
  41. register int     row, col, color;         /****   See NOTE 1   ****/
  42.  
  43. DeltaR = SpanR / (float)screenx;
  44. DeltaI = SpanI / (float)screeny;
  45.  
  46. ConstI = BaseI;
  47. for (row=0; row < screeny; row++)   {       /* Scan top to bottom */
  48.     ConstR = BaseR;
  49.     for (col=0; col < screenx; col++)   {   /* Scan left to right */
  50.         AR = AI = ARsqr = AIsqr = 0.0F;   /****   See NOTE 2   ****/
  51.         for (color = 256; --color > 0;)   {/* Find color for this C */
  52.             AI = (AR * AI * 2.0F) + ConstI;   /* Compute next     */
  53.             AR = ARsqr - AIsqr + ConstR;      /*   iteration of A */
  54.  
  55.             if ( ((ARsqr = AR * AR) + (AIsqr = AI * AI))  > 4.0F )
  56.                     break;                /****   See NOTE 3   ****/
  57.             }
  58.         put_pixel(color,col,row);/* Write color to display buffer. */
  59.         ConstR += DeltaR;
  60.         }
  61.     ConstI += DeltaI;
  62.     }
  63. }
  64.  
  65. /* NOTE 1: We declare everything to be register variables. For some processors
  66. this may not have much of an effect, but on others (like the 34020 and 34082) 
  67. you may be surprised. 
  68. NOTE 2: For each point on the screen, we begin computing iterations of the 
  69. Mandelbrot equation. The initial value of A is 0+0i. Since the values  
  70. A_real*A_real and A_imag*A_imag are used in computing both the next iteration 
  71. of A and its magnitude, we maintain these values as separate variables so the 
  72. multiplications need only be computed once.
  73. NOTE 3: For our magnitude comparison, we actually compare the SQUARE of the 
  74. magnitude against the square of our divergence value. This saves us from 
  75. computing a square root.
  76. */
  77.  
  78. /****************************************************************************
  79. The main() function serves only to pass initial values to compute_fractal. We 
  80. will leave the initialize() routine to be a "black box". Interested 
  81. programmers may want to write their own routine for whatever display board is 
  82. available. The values used in this test program show the familiar picture of 
  83. the Mandelbrot set. By varying these numbers, you can obtain some breathtaking 
  84. fractal landscapes. 
  85.  ***************************************************************************/
  86.  
  87. main()
  88. {
  89. float origin_R,origin_I,size_R,size_I;
  90.  
  91. /*  The initialize() routine must initialize display board, clear display 
  92. buffer, load a table of 256 colors into color palette, and set global 
  93. variables, screenx and screeny. If successful, it returns 0. If it encounters 
  94. any problems it returns a non-zero value. */
  95.  
  96. if (initialize()) return(1);
  97.  
  98. origin_R = -4.0;      /*  origin represents the upper left corner of */
  99. origin_I = -3.0;      /*         the screen.                         */
  100. size_R = 8.0;         /*  size   represents the domain of the screen */
  101. size_I = 6.0;         /*         in the complex plane.               */
  102.  
  103. compute_fractal(origin_R,origin_I,size_R,size_I);
  104. }
  105.  
  106.  
  107. [LISTING TWO]
  108.  
  109. ******************************************************************************
  110. *  Assembly code generated by TMS340 C Compiler using the -mc option for 
  111. *  generating coprocessor instructions.  
  112. ******************************************************************************
  113. ;  gspac -mc -v20 mandel.gc mandel.if 
  114. ;  gspcg -o -c -v20 -o mandel.if mandel.asm mandel.tmp 
  115.    .version    20
  116.    .ieeefl
  117. FP .set   A13
  118. STK.set   A14
  119.    .file  "mandel.gc"
  120.    .globl _screenx
  121.    .globl _screeny
  122.  
  123.    .sym   _compute_fractal,_compute_fractal,32,2,0
  124.    .globl _compute_fractal
  125.  
  126.    .func  50
  127. ;>>>> void compute_fractal(float BaseR,float BaseI,float SpanR,
  128.                            float SpanI)
  129. ;>>>> register float   AR, AI, ConstR, ConstI;
  130. ;>>>> register float   ARsqr, AIsqr, DeltaI, DeltaR;
  131. ;>>>> register int     row,col,color;
  132. ******************************************************
  133. * FUNCTION DEF : _compute_fractal
  134. ******************************************************
  135. _compute_fractal:
  136.    MMTM   SP,A7,A9,A10,A11,FP
  137.    SUBI   448,SP
  138.    MOVE   SP,A11
  139.    MOVD   RA5,*A11+,4
  140.    MOVD   RB6,*A11+,3
  141.    MOVE   STK,FP
  142.    ADDK   32,STK
  143.    MOVE   SP,*STK+,1    ;; DEBUGGER TRACEBACK AID
  144.    .sym   _BaseR,-32,6,9,32
  145.    .sym   _BaseI,-64,6,9,32
  146.    .sym   _SpanR,-96,6,9,32
  147.    .sym   _SpanI,-128,6,9,32
  148.    .sym   _AR,32,6,4,32
  149.    .sym   _AI,33,6,4,32
  150.    .sym   _ConstR,30,6,4,32
  151.    .sym   _ConstI,31,6,4,32
  152.    .sym   _ARsqr,28,6,4,32
  153.    .sym   _AIsqr,29,6,4,32
  154.    .sym   _DeltaR,26,6,4,32
  155.    .sym   _DeltaI,0,6,1,32
  156.    .sym   _row,9,4,4,32
  157.    .sym   _col,10,4,4,32
  158.    .sym   _color,11,4,4,32
  159.  
  160.    .line  9
  161. ;>>>> DeltaR = SpanR / (float)screenx;
  162.    MOVE   @_screenx,A7,1
  163.    MOVE   A7,RA0          ; screenx --> RA0
  164.    CVIF   RA0,RB0         ; convert RA0 from int to float, put in RB0
  165.    MOVE   FP,A7
  166.    SUBI   96,A7
  167.  
  168.    MOVF   *A7+,RA0        ; move parameter SpanR --> RA0
  169.    DIVF   RA0,RB0,RB0     ; RA0 / RB0 --> RB0.  Result is DeltaR
  170.    ADDI   64,A7
  171.    MOVF   RB0,*A7+        ; Store DeltaR as a local variable.
  172.  
  173.    .line  10
  174. ;>>>> DeltaI = SpanI / (float)screeny;
  175.    MOVE   @_screeny,A7,1    
  176.    MOVE   A7,RA1            ; screeny --> RA1
  177.    CVIF   RA1,RB1           ; convert to float and put in RB1
  178.    MOVE   FP,A7
  179.    SUBI   128,A7
  180.    MOVF   *A7+,RA1          ; get SpanI
  181.    DIVF   RA1,RB1,RA5       ; compute DeltaI and LEAVE IN RA5!!! 
  182.                                  ;  DeltaI is used as a register variable!
  183.    .line  12
  184. ;>>>> ConstI = BaseI;
  185.    ADDK   32,A7
  186.    MOVF   *A7+,RB7        ; BaseI --> ConstI (RB7)
  187.  
  188.    .line  13
  189. ;>>>> for (row=0; row < screeny; row++)   { 
  190. ; NOTICE here that both ConstI and row are used as register variables. Yet 
  191. ;  ConstI, which is a float, is kept in a 34082 register and row, which is an 
  192. ;  int, is kept in a 34020 register! The C compiler is smart enough to know 
  193. ;  which variables should be maintained on which processor!
  194. ;
  195.    CLRS   A9                ; 0 --> row (A9)
  196.    MOVE   @_screeny,A7,1    
  197.    CMP    A7,A9
  198.    JRGE   L2
  199.  
  200. L1:
  201.    .line  15
  202. ;>>>>     ConstR = BaseR;
  203.    MOVE   FP,A7
  204.    SUBK   32,A7
  205.    MOVF   *A7+,RA7        ; BaseR --> ConstR (RA7)
  206.  
  207.    .line  16
  208. ;>>>>     for (col=0; col < screenx; col++)   {   
  209.    CLRS   A10             ; 0 --> col (A10)
  210.    MOVE   @_screenx,A7,1
  211.    CMP    A7,A10
  212.    JRGE   L4
  213.  
  214. L3:
  215.    .line  18
  216. ;>>>>         AR = AI = ARsqr = AIsqr = 0.0F;
  217.    CLRF   RB6             ; clear AIsqr (RB6)
  218.    MOVF   RB6,RA6         ; clear ARsqr (RA6)
  219.    MOVF   RB6,RB8         ; clear AI (RB8)
  220.  
  221.    MOVF   RB6,RA8         ; clear AR (RA8)
  222.  
  223.    .line  20
  224. ;>>>>         for (color = 256; --color > 0;)
  225.    MOVI   256,A11         
  226.    SUBK   1,A11           ; 255 --> color (A11)
  227.    JRLE   L6
  228.  
  229. L5:
  230.    .line  22
  231. ;>>>>             AI =  (AR * AI * 2.0F) + ConstI;
  232.    MPYF   RA8,RB8,RA0     ; AR * AI --> RA0
  233.    TWOF   RB0             ; 2.0F --> RB0
  234.    MPYF   RA0,RB0,RA0     ; AR * AR * 2.0 --> RA0
  235.    ADDF   RA0,RB7,RB8     ; RA0 + ConstR --> AI (RB8)
  236.  
  237.    .line  23
  238. ;>>>>             AR = ARsqr - AIsqr + ConstR;
  239.    SUBF   RA6,RB6,RB1     ; ARsqr - AIsqr --> RB1
  240.    ADDF   RA7,RB1,RA8     ; ConstR + RB1 --> AR (RA8)
  241.  
  242.    .line  25
  243. ;>>>>             if ( ((ARsqr = AR*AR)+ 
  244.    MOVF   RA8,RB1         ; AR --> RB1
  245.    MPYF   RA8,RB1,RA6     ; Compute new ARsqr
  246.    MOVF   RB8,RA0         ; AI --> RA0
  247.    MPYF   RA0,RB8,RB6     ; Compute new AR_imag
  248.    ADDF   RA6,RB6,RA0     ; Sum of squares --> RA0
  249.    MOVI   FS3,A7          ; FS3 is a pointer to a float constant, 4.0
  250.    MOVF   *A7+,RB1        ; 4.0 --> RB1    
  251.    CMPF   RA0,RB1         ; if square of magnitude > 4.0, break
  252.    GETCST
  253.    JRGT   L6
  254.  
  255.    .line  26
  256. ;>>>>                   (AIsqr = AI*AI))  > 4.0F ) break;
  257.    .line  20
  258.    SUBK   1,A11           ; Otherwise, decrement color and see
  259.    JRGT   L5              ;     if loop ended.
  260.  
  261. L6:
  262.    .line  29
  263. ;>>>>         put_pixel(color,col,row); 
  264.    MOVE   STK,-*SP,1        ; Call display_board dependent routine
  265.    MOVE   A9,*STK+,1        ;      to place a pixel on the screen.
  266.    MOVE   A10,*STK+,1
  267.    MOVE   A11,*STK+,1
  268.    CALLA  _put_pixel
  269.  
  270.    .line  30
  271. ;>>>>         ConstR += DeltaR;
  272.    MOVE   FP,A8
  273.    MOVF   *A8+,RB0
  274.    ADDF   RA7,RB0,RA7
  275.  
  276.  
  277.    .line  16
  278.    ADDK   1,A10             ; col++
  279.    MOVE   @_screenx,A7,1
  280.    CMP    A7,A10            ; If col >= screenx, end middle loop
  281.    JRLT   L3                ; Otherwise, jump back
  282.  
  283. L4:
  284.    .line  32
  285. ;>>>>     ConstI += DeltaI;
  286.    ADDF   RA5,RB7,RB7
  287.  
  288.    .line  13
  289.    ADDK   1,A9              ; row++
  290.    MOVE   @_screeny,A7,1
  291.    CMP    A7,A9             ; If row >= screeny, end outer loop
  292.    JRLT   L1                ; Otherwise, jump back
  293.  
  294. L2:
  295. EPI0_1:
  296.    .line  34
  297.    MOVE   *SP(640),STK,1    ; C cleanup
  298.    MOVD   *SP+,RA5,4
  299.    MOVD   *SP+,RB6,3
  300.    MMFM   SP,A7,A9,A10,A11,FP
  301.    RETS   2
  302.  
  303.    .endfunc    83,00000ee80H,32
  304.  
  305.    .sym   _main,_main,36,2,0
  306.    .globl _main
  307.  
  308.    .func  103
  309. ;>>>> main()
  310. ;>>>> float origin_R,origin_I,size_R,size_I;
  311. ******************************************************
  312. * FUNCTION DEF : _main
  313. ******************************************************
  314. _main:
  315.    MOVE   FP,-*SP,1
  316.    MOVE   STK,FP
  317.    ADDI   128,STK
  318.    MOVE   SP,*STK+,1    ;; DEBUGGER TRACEBACK AID
  319.    .sym   _origin_R,0,6,1,32
  320.    .sym   _origin_I,32,6,1,32
  321.    .sym   _size_R,64,6,1,32
  322.    .sym   _size_I,96,6,1,32
  323.  
  324.  
  325.    .line  12
  326. ;>>>> if (initialize()) return(1);
  327.    CALLA  _initialize
  328.    MOVE   A8,A8
  329.    JRZ    L8
  330.    MOVK   1,A8
  331.    JR     EPI0_2
  332.  
  333.  
  334. L8:
  335.    .line  14
  336. ;>>>> origin_R = -4.0;     
  337.    MOVE   @FS4,A8,1
  338.    MOVE   A8,*FP,1
  339.  
  340.    .line  15
  341. ;>>>> origin_I = -3.0;     
  342.    MOVE   @FS5,A8,1
  343.    MOVE   A8,*FP(32),1
  344.  
  345.    .line  16
  346. ;>>>> size_R = 8.0;        
  347.    MOVE   @FS6,A8,1
  348.    MOVE   A8,*FP(64),1
  349.  
  350.    .line  17
  351. ;>>>> size_I = 6.0;        
  352.    MOVE   @FS7,A8,1
  353.    MOVE   A8,*FP(96),1
  354.  
  355.    .line  19
  356. ;>>>> compute_fractal(origin_R,origin_I,size_R,size_I);
  357.    MOVE   STK,-*SP,1
  358.    MOVE   *FP(96),*STK+,1
  359.    MOVE   *FP(64),*STK+,1
  360.    MOVE   *FP(32),*STK+,1
  361.    MOVE   *FP(0),*STK+,1
  362.    CALLA  _compute_fractal
  363.  
  364. EPI0_2:
  365.    .line  20
  366.    SUBI   160,STK
  367.    MOVE   *SP+,FP,1
  368.    RETS   0
  369.  
  370.    .endfunc    140,00000a000H,128
  371.  
  372.    .sym   _screenx,_screenx,4,2,32
  373.    .globl _screenx
  374.    .bss   _screenx,32,32
  375.  
  376.    .sym   _screeny,_screeny,4,2,32
  377.    .globl _screeny
  378.    .bss   _screeny,32,32
  379. *************************************************
  380. * DEFINE FLOATING POINT CONSTANTS               *
  381. *************************************************
  382.    .text
  383.    .even 32
  384. FS1:.float0.0
  385. FS3:.float4.0
  386. FS4:.float-4.0
  387. FS5:.float-3.0
  388.  
  389. FS6:.float8.0
  390. FS7:.float6.0
  391. *****************************************************
  392. * UNDEFINED REFERENCES                              *
  393. *****************************************************
  394.    .ref   _put_pixel
  395.    .ref   _initialize
  396.    .end
  397.  
  398. .po 0
  399.  
  400. [LISTING THREE]
  401.  
  402. * Hand-tweaked assembler code using Listing 2 as a basis. *
  403.    .version   20
  404.    .ieeefl
  405.    .globl   _screenx
  406.    .globl   _screeny
  407.  
  408. *   Register Nicknames are used for program clarity
  409. *       34020 Registers...
  410. FP    .set   A13                      ; C function Frame Pointer
  411. STK   .set   A14                      ; C function Stack
  412.  
  413. DPTCH    .set   B3                    ; Destination Pitch of Screen
  414. OFFSET   .set   B4                    ; Offset of Screen
  415.  
  416. *       34082 Registers...
  417. RA0_2           .set     RA0          ; 2.0 constant
  418. RA1_4           .set     RA1          ; 4.0 constant
  419. RA2_TMP         .set     RA2          ; temporary storage
  420. RA5_DI          .set     RA5          ; DeltaI
  421. RA6_AR2         .set     RA6          ; AR squared
  422. RA7_CR          .set     RA7          ; ConstR
  423. RA8_AR          .set     RA8          ; AR
  424.  
  425. RB1_DR          .set     RB1          ; DeltaR
  426. RB2_TMP         .set     RB2          ; temporary storage
  427. RB4_BI          .set     RB4          ; BaseI
  428. RB5_BR          .set     RB5          ; BaseR
  429. RB6_AI2         .set     RB6          ; AI squared
  430. RB7_CI          .set     RB7          ; ConstI
  431. RB8_AI          .set     RB8          ; AI
  432.  
  433. TubeOffset      .set    2000H         ; These definitions apply for the 
  434. TubePitch       .set    (1024 * 8)    ; SDB20 board which we used.
  435.  
  436.    .globl   _compute_fractal
  437.  
  438.  
  439. ******************************************************
  440. * FUNCTION DEF : _compute_fractal
  441. ******************************************************
  442. _compute_fractal:
  443.    MMTM   SP,A0,A1,A2,A3,A4,A11,FP
  444.  
  445. *   Since we are creating a highly efficient tweaked program, we have the
  446. *   main program place the 4 parameters used in compute_fractal directly 
  447. *   into 34082 registers. Specifically, BaseI has been placed in RB4,
  448. *   BaseR has been placed in RB5, SpanI has been placed in RA0, SpanR has 
  449. *   been placed in RA1
  450.  
  451. ;>>>>    DeltaR = SpanR / (float)screenx;
  452.    MOVE   @_screenx,A3,1           ; screenx --> A3 (stays there)
  453.    MOVE   A3,RA2_TMP
  454.    CVIF   RA2_TMP,RB0              ; (float)screenx --> RB0
  455.    DIVF   RA1,RB0,RB1_DR           ; SpanR / screenx = DeltaR --> RB1
  456.                                    ;                    (stays there)
  457. ;>>>>    DeltaI = SpanI / (float)screeny;
  458.    MOVE   @_screeny,A4,1           ; screeny --> A4 (stays there)
  459.    MOVE   A4,RA2_TMP 
  460.    CVIF   RA2_TMP,RB0              ; (float)screeny --> RB1
  461.    DIVF   RA0,RB0,RA5_DI           ; SpanI / screeny = DeltaI --> RA5
  462.                                    ;                    (stays there)
  463. *   Set up initializations outside any loops
  464.    TWOF   RA0_2                    ; constant 2.0 in RA0
  465.    SQRF   RA0_2,RA1_4              ; constant 4.0 in RA1
  466.  
  467. ;>>>> for (ConstI = BaseI, row=0; row < screeny; row++,ConstI += DeltaI)
  468.    MOVF   RB4_BI,RB7_CI            ; BaseI --> ConstI  (RB7)
  469.    CLRS   A0                       ; 0 --> row (A0)
  470.  
  471. L1:
  472. ;>>>>   for (ConstR = BaseR, col=0; col < screenx; col++,ConstR += DeltaR)
  473.    MOVF   RB5_BR,RA7_CR            ; BaseR --> ConstR  (RA7)
  474.    CLRS   A1                       ; 0 --> col (A1)
  475.  
  476. L3:
  477. ;>>>>         AR = AI = ARsqr = AIsqr = 0.0F;
  478.    CLRF   RB8_AI                   ; 0.0 --> AI (RB8)
  479.    MOVF   RB8_AI,RB6_AI2           ; 0.0 --> AI squared (RB6)
  480.    CLRF   RA8_AR                   ; 0.0 --> AR (RA8)
  481.    MOVF   RA8_AR,RA6_AR2           ; 0.0 --> AR squared (RA6)
  482.  
  483. ;>>>>            for (color = 256; --color > 0;)
  484.    MOVI   255,A2                   ; 255 --> color (A2)
  485.  
  486. L5:
  487.  
  488. ;>>>>                AI = ( AR * AI * 2.0F ) + ConstI;
  489.    MPYF   RA8_AR,RB8_AI,RB2_TMP    ; AR * AI --> tmp (RB2)
  490.    MPYF   RB2_TMP,RA0_2,RA2_TMP    ; tmp * 2.0 --> tmp (RA2)
  491.    ADDF   RA2_TMP,RB7_CI,RB8_AI    ; tmp + ConstI --> AI
  492.  
  493. ;>>>>             AR = ARsqr - AIsqr + ConstR;
  494.    SUBF   RA6_AR2,RB6_AI2,RB2_TMP  ; AR**2 - AI**2 --> tmp (RB2)
  495.    ADDF   RB2_TMP,RA7_CR,RA8_AR    ; tmp + ConstR --> AR
  496.  
  497. ;>>>>             if ( ((ARsqr = AR*AR)+ 
  498. ;>>>>                   (AIsqr = AI*AI))  > 4.0F ) break;
  499.    SQRF   RA8_AR,RA6_AR2           ; Compute new ARsqr
  500.    MOVF   RB8_AI,RA2_TMP           ; SQRF must be performed on an A reg.
  501.    SQRF   RA2_TMP,RB6_AI2          ; Compute new AIsqr
  502.    ADDF   RA6_AR2,RB6_AI2,RB2_TMP  ; sum of squares in RB2
  503.    CMPF   RA1_4,RB2_TMP            ; if sum of squares > 4.0, break
  504.    GETCST
  505.    JRLE   L6
  506.  
  507.    DSJ    A2,L5                    ; dec color and loop back if not 0
  508.  
  509. L6:
  510. ;>>>>            put_pixel(color,col,row); 
  511.    MOVE   A0,A8                    ; row becomes Y
  512.    SLL    16,A8                    ; shift Y into upper 16 bits
  513.    MOVA   A1,A8                    ; col becomes A,  Y:X now in A8
  514.    PIXT   A2,*A8.XY                ; write the pixel
  515.  
  516. ;               bottom of 'col' loop
  517.    ADDF   RB1_DR,RA7_CR,RA7_CR     ; ConstR += DeltaR
  518.    INC    A1                       ; col++
  519.    CMP    A3,A1                    ; if col < screenx, jump back
  520.    JRLT   L3                      
  521.  
  522. ;              bottom of 'row' loop
  523. L4:
  524.    ADDF   RA5_DI,RB7_CI,RB7_CI     ; ConstI += DeltaI
  525.    INC    A0                       ; row++
  526.    CMP    A4,A0                    ; if row < screeny, jump back
  527.    JRLT   L1                     
  528.  
  529. L2:
  530. EPI0_1:
  531.    MMFM   SP,A0,A1,A2,A3,A4,A11,FP
  532.    RETS   
  533.  
  534.    .globl   _main
  535.  
  536. ******************************************************
  537. * FUNCTION DEF : _main
  538. ******************************************************
  539. _main:
  540.    MOVE   FP,-*SP,1
  541.    MOVE   STK,FP
  542.    ADDI   128,STK
  543.  
  544.    MOVE   SP,*STK+,1    ;; DEBUGGER TRACEBACK AID
  545.    CALLA  _initialize
  546.    MOVE   A8,A8
  547.    JRZ    L8
  548.    MOVK   1,A8
  549.    JR     EPI0_2
  550. L8:
  551.    MOVE    @ORG_I,A8,1            ; We can place the initial parameters
  552.    MOVF    A8,RB4_BI              ; directly into the 34082 registers
  553.    MOVE    @ORG_R,A8,1            ; where they will be used by the
  554.    MOVF    A8,RB5_BR              ; compute_fractal routine.
  555.    MOVE    @SIZE_I,A8,1
  556.    MOVF    A8,RA0
  557.    MOVE    @SIZE_R,A8,1
  558.    MOVF    A8,RA1
  559.    CALLA   _compute_fractal
  560. EPI0_2:
  561.    MOVE   *SP+,FP,1
  562.    RETS   0
  563.  
  564.    .globl   _screenx
  565.    .bss   _screenx,32,32
  566.  
  567.    .globl   _screeny
  568.    .bss   _screeny,32,32
  569.  
  570. *************************************************
  571. * DEFINE FLOATING POINT CONSTANTS               *
  572. *************************************************
  573.    .text
  574.    .even 32
  575. ORG_R:    .float   -4.0
  576. ORG_I:    .float   -3.0
  577. SIZE_R:   .float    8.0
  578. SIZE_I:   .float    6.0
  579.  
  580.    .ref   _initialize
  581.    .end
  582.  
  583.  
  584.  
  585.