File: CALCMAND.S - Tab length: 1 2 4 8 - Lines: on off - No wrap: on off

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; The X numbers are shifted right by 13 before use
; These numbers are in units of 1/8192

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; The upper commented out numbers do this SciAm cover (almost)
;   XSTART      equ $fffffa86
;   XINC        equ 1

;   XSTART      equ ((-1)<<13)
;   XINC        equ (1<<9)

;   XSTART      equ 0
;   XINC        equ (1<<7)

;   XSTART      equ ((-2)<<13)
;   XINC        equ ((10<<11)/WIDTH)


; The Y numbers are shifted right by 13 before use
; These numbers are in units of 1/8192

; The upper commented out numbers do this SciAm cover
;   YSTART      equ $ffffde9a  
;   YINC        equ 1

;   YSTART      equ ((-1)<<13)
;   YINC        equ (1<<9)

;   YSTART      equ ((-2)<<13)
;   YINC        equ (1<<7)

;   YSTART      equ ((-19)<<9)
;   YINC        equ ((6<<12)/WIDTH)


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; The most important thing in a Mandlebrot program is the inner loop
; The most important thing in a GPU program is to keep as much as possible
; in registers and as much of the rest in internal RAM
; First the inner loop:
; In order to handle both the Mandlebrot and Julia sets we make no assumptions
; about initial conditions.
; The basic loop is: (given xi, yi, cx, cy)
; temp=xi*yi
; sx=xi*xi
; sy=yi*yi
; yi=temp+temp+cy
; xi=sx-sy+cx
; count+=1
; interate until count>maxcount or sx+sy>4

; Note that the nubers used here are 3.13 fixed point
; For a Mandlebrot xi=yi=0 at the start always

; Assume that the following registers are already set up
;       movei   #MAXCNT,maxcnt
;       movei   #FOUR,four

    INBUF       equ $00f03810
;   SEMAPHORE   equ $0000bff0

    WIDTH       equ 640
    HEIGHT      equ 480
   
    XSTART      equ ((-2)<<13)
    XINC        equ ((10<<11)/WIDTH)
   
    YSTART      equ ((-19)<<9)
    YINC        equ ((6<<12)/WIDTH)

    .gpu

    xi              .equr          R1
    yi              .equr          R2
    cx              .equr          R3
    cy              .equr          R4
    sx              .equr          R5
    sy              .equr          R6
    temp            .equr          R7
    count           .equr          R8
    maxcnt          .equr          R9
    four            .equr          R10
    inloop          .equr          R11
    semaphore       .equr          R12
    inbuf           .equr          R13
   
; A1 = R14
; d2 = R18
; A0 = R19
; d0 = R20
; d1 = R21

    jx              .equr          R15
    jy              .equr          R16
    ypos            .equr          R17
    xpos            .equr          R23
    rinner          .equr          R24
    router          .equr          R25

mandGPU::
    .org     $f03000
; ancien code 68000
; Mandle:
start_mandGPU::
    moveq   #0,jx
    moveq   #0,jy

    movei   #$20000,R14

    movei   #YSTART,ypos    ; Initialize y position

    movei   #HEIGHT-1,R18

    movei   #INBUF+8,R19
   
    movei   #inner,rinner
    movei   #outer,router

    move    jx,R20
    store   R20,(R19)
    addq    #4,R19

    move    jy,R20
    store   R20,(R19)

outer:
    movei   #INBUF+4,R19

    move    ypos,R20
    store   R20,(R19)

    movei   #WIDTH-1,R21
    movei   #XSTART,xpos    ; Initialize x position

inner:
    movei   #INBUF,R19

    move    xpos,R20
    store   R20,(R19)
; fin 68000

; start_mandGPU::
    movei   #loop,inloop

    movei   #(4<<13),four
    movei   #254,maxcnt

;   movei   #$0000bff0,semaphore
    movei   #$00f03810,inbuf

    xor     count,count

    load    (inbuf),cx
    addq    #4,inbuf

    load    (inbuf),cy
    addq    #4,inbuf

    load    (inbuf),xi
    addq    #4,inbuf

    load    (inbuf),yi
    addq    #4,inbuf

loop:
    move    xi,temp
    imult   yi,temp         ; temp=xi*yi

    imult   xi,xi           ; xi=xi*xi

    imult   yi,yi           ; yi=yi*yi

    sharq   #13,xi          ; normalize all mult results
    sharq   #13,temp
    sharq   #13,yi

; The folowing code has been interleaved

    add     temp,temp       ; temp=temp+temp

    move    yi,sy           ; sy=yi*yi

    add     cy,temp         ; temp=temp+temp+cy

    move    xi,sx           ; sx=xi*xi

    move    temp,yi         ; yi=temp+temp+cy

    sub     sy,xi           ; xi=sx-sy

    add     cx,xi           ; xi=sx-sy+cx


    addq    #1,count
    cmp     count,maxcnt

    jr      MI,noloop       ; MI is branch count<maxcnt
;   nop                     ; optimisation, no need to "nop" here

    add     sx,sy
    cmp     sy,four

    jr      EQ,noloop
    nop
    jump    CC,(inloop)
    nop

noloop:
;   store   count,(semaphore)
; re 68000
    storeb  count,(R14)
    addq    #1,R14


;   addq    #XINC,xpos
    movei   #XINC,R26
    add     R26,xpos
   
    subq    #1,R21
    jump    PL,(rinner)
    nop

;   addq    #YINC/2,ypos
;   addq    #YINC/2,ypos
    movei   #YINC,R26
    add     R26,ypos
   
    subq    #1,R18
    jump    PL,(router)
    nop
    nop
    ; re fin 68000  
;BRAK !

;       NOTE: This halts the GPU
    movei   #0,R30
    movei   #$00f02114,R31
    store   R30,(R31)

    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
end_mandGPU::