        .width    132
        .title    'draw circle'

*----------------------------------------------------------------------
*                                    TIGA
*          Copyright (C) 1987-1990  Texas Instruments Incorporated.
*                            All Rights Reserved
*----------------------------------------------------------------------
* draw_circle function
*
*   Draw outline of circle.  Radius of circle is specified by argument
*   r.	Center point is specified by arguments x and y.
*
*   This function is designed to be called from a GSP-C program.
*----------------------------------------------------------------------
* Usage:  draw_circle(r, x, y);
*
* Description of stack arguments:
*   int r;     /* radius */
*   int x, y;  /* center coordinates */
*
* Returned in register A8:  void (undefined)
*
* Registers altered:  A8
*----------------------------------------------------------------------
* Revision history:
*   01/09/87...Original version written..................Jerry Van Aken
*----------------------------------------------------------------------
;
;
;     DECLARE GLOBAL FUNCTION NAME
;
        .globl    _draw_circle
;
;
;     DECLARE EXTERNAL VARIABLES
;
        .globl    _xyorigin
;
;
;     ENTRY POINT
;
_draw_circle:

        MMTM      SP,A0,A1,A2,A3,A4,A5,A6,A10,A11,A12,A13,A14
        MMTM      SP,B0,B1,B2,B7,B10,B11,B12,B13,B14
        MOVE      *-A14,A8,1          ;get argument 'r'
        MOVE      *-A14,A0,1          ;get argument 'x'
        MOVE      *-A14,A1,1          ;get argument 'y'
* Form XY address of circle's center point.
        SLL       16,A1               ;concatenate x and y
        MOVY      A1,A0               ;
        MOVE      @_xyorigin,A1,1     ;
        ADDXY     A1,A0               ;
* Get starting XY addresses for arcs in 8 octants.
        MOVE      A8,A1               ;copy r
        JRZ       C3                  ;jump if r = 0
        SLL       16,A1               ;XY displacement +r::0 in A1
        MOVE      A1,A2               ;
        NEG       A2                  ;XY displacement -r::0 in A2
        MOVE      A2,A3               ;
        SRL       16,A3               ;XY displacement 0::-r in A3
        ADDXY     A0,A1               ;A1 = XY pointer in octant 2
        ADDXY     A0,A2               ;A2 = XY pointer in octant 5
        ADDXY     A0,A3               ;
        ADDXY     A8,A0               ;A0 = XY pointer in octant 0
        MOVE      A1,B0               ;B0 = XY pointer in octant 1
        MOVE      A3,B1               ;B1 = XY pointer in octant 3
        MOVE      A3,B2               ;B2 = XY pointer in octant 4
        MOVE      A2,B7               ;B7 = XY pointer in octant 6
        MOVE      A0,A3               ;A3 = XY pointer in octant 7
* Set up XY increments for horizontal, vertical and diagonal moves.
        MOVI      010000h,A10         ;deltay = +1, deltax = 0
        MOVI      01ffffh,A11         ;deltay = +1, deltax = -1
        MOVI      0ffffh,A12          ;deltay = 0, deltax = -1
        MOVI      -1,A13              ;deltay = -1, deltax = -1
        MOVI      0ffff0000h,A14      ;deltay = -1, deltax = 0
        MOVE      A10,B10             ;deltay = +1, deltax = 0
        MOVI      010001h,B11         ;deltay = +1, deltax = +1
        MOVK      01h,B12             ;deltay = 0, deltax = +1
        MOVI      0ffff0001h,B13      ;deltay = -1, deltax = +1
        MOVE      A14,B14             ;deltay = -1, deltax = 0
* Set up initial values for loop control variables.
        MOVE      A8,A4               ;initially d = 5 - 4*r
        SLL       2,A4                ;
        NEG       A4                  ;
        ADDK      5,A4                ;
        MOVK      4,A5                ;initially p = 4
        MOVE      A8,A6               ;initially q = 4 - 8*r
        SLL       3,A6                ;
        NEG       A6                  ;
        ADDK      4,A6                ;
* Draw 4 starting pixels at top, bottom and sides of circle.
        DRAV      A10,A0              ;draw & advance in octant 0
        ADDXY     B12,B0              ;------ advance in octant 1
        DRAV      A12,A1              ;draw & advance in octant 2
        DRAV      B10,B1              ;draw & advance in octant 3
        ADDXY     B14,B2              ;------ advance in octant 4
        DRAV      A12,A2              ;draw & advance in octant 5
        ADDXY     B12,B7              ;------ advance in octant 6
        ADDXY     A14,A3              ;------ advance in octant 7
        SUBK      1,A8                ;decrement loop count by 1
        JRLE      C5                  ;jump if r < 2 (all done)
        ADDK      8,A5                ;p += 8
        ADDK      8,A6                ;q += 8
        ADD       A5,A4               ;d += p
        JRNN      C2                  ;jump if d >= 0 (and r < 5)
*----------BEGIN INNER LOOP OF CIRCLE ALGORITHM-------------
* Move arc in horizontal or vertical direction in each of the 8 octants.
C1:
        DRAV      A10,A0              ;draw & advance in octant 0
        DRAV      B12,B0              ;draw & advance in octant 1
        DRAV      A12,A1              ;draw & advance in octant 2
        DRAV      B10,B1              ;draw & advance in octant 3
        DRAV      B14,B2              ;draw & advance in octant 4
        DRAV      A12,A2              ;draw & advance in octant 5
        DRAV      B12,B7              ;draw & advance in octant 6
        DRAV      A14,A3              ;draw & advance in octant 7
        SUBK      1,A8                ;decrement loop count by 1
        JRLE      C5                  ;jump if at end of octant
        ADDK      8,A5                ;p += 8
        ADDK      8,A6                ;q += 8
        ADD       A5,A4               ;d += p
        JRN       C1                  ;jump if d < 0
* Move arc in diagonal direction in each of the 8 octants.
C2:
        DRAV      A11,A0              ;draw & advance in octant 0
        DRAV      B13,B0              ;draw & advance in octant 1
        DRAV      A13,A1              ;draw & advance in octant 2
        DRAV      B11,B1              ;draw & advance in octant 3
        DRAV      B13,B2              ;draw & advance in octant 4
        DRAV      A11,A2              ;draw & advance in octant 5
        DRAV      B11,B7              ;draw & advance in octant 6
        DRAV      A13,A3              ;draw & advance in octant 7
        SUBK      2,A8                ;decrement loop count by 2
        JRLE      C4                  ;jump if at end of octant
        ADDK      8,A5                ;p += 8
        ADDK      16,A6               ;q += 16
        ADD       A6,A4               ;d += q
        JRN       C1                  ;jump if d < 0
        JRUC      C2                  ;jump if d >= 0
* In special case in which r = 0, draw a single point.
C3:
        DRAV      A0,A0               ;
        JRUC      C5                  ;
* Check whether 4 final pixels must be drawn so that arcs touch.
C4:
        JRNZ      C5                  ;jump if arcs already touch
        DRAV      A8,A0               ;draw pixel between oct's 0,1
        DRAV      A8,A1               ;draw pixel between oct's 2,3
        DRAV      A8,A2               ;draw pixel between oct's 4,5
        DRAV      A8,A3               ;draw pixel between oct's 6,7
* Restore registers and return.
C5:
        MMFM      SP,B0,B1,B2,B7,B10,B11,B12,B13,B14
        MMFM      SP,A0,A1,A2,A3,A4,A5,A6,A10,A11,A12,A13,A14
        MOVE      *SP(32),A14,1       ;restore default param stack ptr
        RETS      2                   ;
        .end

