;opt_gc_quick = 1
timecheck = 0

;               shell/quick
;6656 words for 13.167/8.3 secs
;4096 words for 7.5/4.933 secs
;2048 words for 3.333/2.217 secs
;1024 words for 1.567/1.067 secs

gc        lda #>strdmax       ;uses $14-15
          cmp strdcurre+1
          ;bcc gc0   ;impossible branch
          bne exit3

          ;lda #<strdmax    ;strdmax=$fc00???
          ;cmp strdcurre
          ;bcs exit3

gc0
.if timecheck
          sei
          lda $a5
          sta $d5
          lda $a4
          sta $d4
          lda $a3
          sta $d3
          cli
     inc $d0
     bne *+4
     inc $d1
.endif

          lda r5l
          sta strestatic-2
          lda r5h
          sta strestatic-1   ;r5 is free now

.if opt_gc_quick
          tsx
          stx qs_csp+1
          jsr quicksort
.endif
.ifeq opt_gc_quick
          jsr shellsort
.endif
          ;jsr checksort
          lda #>strsdyn
          sta r3h
          lda #<strsdyn
          sta r3l

          lda #>strsgc
          sta r1h
          lda #<strsgc
          sta r1l
gc_ll3    ;lda r1l
          cmp #<strsstatic
          bne gc_no8

          lda #>strsstatic
          cmp r1h
          beq gc_ll2

gc_no8    ldy #0
          lda (r1l),y
          sta r0l
          iny
          lda (r1l),y
          sta r0h
          lda (r0l),y
          sta r4h
          dey
          lda (r0l),y
          sta r4l
          ldx r3l
          cpx r4l
          lda r3h
          sbc r4h
          bcs gc_ll10

          lda (r4l),y
          bne gc_ll3x

          lda #<lib_end
          sta (r0l),y
          lda #>lib_end
          iny
          sta (r0l),y
          bne gc_ll7x  ;=jmp

gc_ll3x   sta gc_m+1
          sta (r3l),y
          tax
          lda r3l
          sta (r0l),y
          iny
          lda r3h
          sta (r0l),y
gc_ll6    lda (r4l),y
          sta (r3l),y
          iny
          dex
          bne gc_ll6

          sec
gc_m      lda #0
          adc r3l
          sta r3l
          bcc gc_ll7x

          inc r3h
gc_ll10   bne gc_ll7x   ;=jmp after inc

          cpx r4l
          bne gc_ll7x

          txa
          adc (r3l),y   ;CY=1
          sta r3l
          bcc gc_ll7x

          inc r3h
gc_ll7x   clc
          lda #2
          adc r1l
          sta r1l
          bcc gc_ll3

          inc r1h
          bne gc_ll3    ;=jmp

gc_ll2    lda r3l
          sta strdcurre
          lda r3h
          sta strdcurre+1
          ldx strestatic-2
          stx r5l
          ldx strestatic-1
          stx r5h
          ;lda strdcurre+1
          cmp #>strdmax
          beq gc_err
.if timecheck
   jmp time0
.endif
.ifeq timecheck
exit10     rts
.endif
gc_err lda #16  ;out of memory
     jmp traphandle2

.if timecheck
time0
   sei
   sec
   lda $a5
   sbc $d5
   pha
   lda $a4
   sbc $d4
   tay
   lda $a3
   sbc $d3
   tax
   cli
   clc
   pla
   adc $d8
   sta $d8
   tya
   adc $d9
   sta $d9
   txa
   adc $da
   sta $da
exit10   rts
.endif

.ifeq opt_gc_quick
j2lo   = r3l
j2hi   = r3h
l2lo   = r4l
l2hi   = r4h

shellsort ldx #gc_start_k2
lss1      stx lssm+1        ;=k2
          beq exit10

          ldy #>strsgc
          sty j2hi
          ldy #<strsgc
          sty j2lo
          lda gap2table-2,x
          sta gap2lo+1
          clc
          adc l2lo
          sta l2lo
          lda gap2table-1,x
          sta gap2hi+1
          adc l2hi
          sta l2hi
lss3      ;lda l2hi
          cmp #>strsgc+gc_sz2
          ;bcc lss2
          ;bne lssm
          bne lss2

          ldx l2lo
          cpx #<strsgc+gc_sz2
          bne lss2

lssm      ldx #0
          dex
          dex
          bpl lss1   ;=jmp

lss2      lda j2hi
          pha
          lda j2lo
          pha
lss8      ldy #0
          lda (l2lo),y
          sta r0l
          iny
          lda (l2lo),y
          sta r0h

          lda (j2lo),y
          sta r5h
          dey
          lda (j2lo),y
          sta r5l
          lda (r0l),y
          cmp (r5l),y
          iny
          lda (r0l),y
          sbc (r5l),y
          bcs lss5

lss6      lda (l2lo),y
          tax
          lda (j2lo),y
          sta (l2lo),y
          txa
          sta (j2lo),y
          dey
          bpl lss6

          sec
          lda j2lo
          sta l2lo
gap2lo    sbc #0
          sta j2lo
          lda j2hi
          sta l2hi
gap2hi    sbc #0
          bcc lss5

          sta j2hi
          lda j2lo
          cmp #<strsgc
          lda j2hi
          sbc #>strsgc
          bcs lss8

lss5      pla
          clc
          adc #2
          sta j2lo
          pla
          adc #0
          sta j2hi

          lda j2lo
          adc gap2lo+1
          sta l2lo
          lda j2hi
          adc gap2hi+1
          sta l2hi
          jmp lss3

;gap2table .word 2,4,14,26,62,122,246,506,1022,2046,4082,4093*2,8191*2  ;this sequence
   ;must be the same as in code.cpp!
gap2table .word 2,8,20,46,114,264,602,1402,3500,4759*2,12923*2
.endif

.if opt_gc_quick
i2lo = r0l
i2hi = r0h
j2lo = r3l
j2hi = r3h
x_lo = r2l
x_hi = r2h
zp1lo = $14
zp1hi = $15
ublo = r1l
ubhi = r1h
lblo = r4l
lbhi = r4h
;ublo = qsstore+0
;ubhi = qsstore+1
;lblo = qsstore+2
;lbhi = qsstore+3
qsstore .byte 0,0,0,0
quicksort0
          tsx
          cpx #16  ;stack limit
          bcs qsok

qs_csp    ldx #0
          dex
          dex
          txs
quicksort lda #>strsgc+gc_sz2-2
          sta ubhi
          lda #<strsgc+gc_sz2-2
          sta ublo
          lda #>strsgc
          sta lbhi
          lda #<strsgc
          sta lblo
qsok      lda lblo
          sta i2lo
          lda lbhi
          sta i2hi
          ldy ubhi
          sty j2hi
          lda ublo
          sta j2lo
          clc        ;this code works only for the even align for strsgc
          adc i2lo
          and #$fc
          sta zp1lo
          tya
          adc i2hi
          ror
          sta zp1hi
          ror zp1lo

          ldy #0
          lda (zp1lo),y
          sta r5l
          iny
          lda (zp1lo),y
          sta r5h
          lda (r5l),y
          sta x_hi
          dey
          lda (r5l),y
          sta x_lo
qsloop1   ldy #1     ;compare array[i] and x
          lda (i2lo),y
          sta r5h
          dey
          lda (i2lo),y
          sta r5l
          lda (r5l),y
          cmp x_lo
          iny
          lda (r5l),y
          sbc x_hi
          bcs qs_l1

          lda #2
          adc i2lo
          sta i2lo
          bcc qsloop1

          inc i2hi
          bne qsloop1 ;=jmp

qs_l1     ;ldy #1    ;compare array[j] and x
          lda (j2lo),y
          sta r5h
          dey
          lda (j2lo),y
          sta r5l
          lda x_lo
          cmp (r5l),y
          iny
          lda x_hi
          sbc (r5l),y
          bcs qs_l3

          lda j2lo
          sbc #1
          sta j2lo
          bcs qs_l1

          dec j2hi
          bne qs_l1 ;=jmp

qs_l3     lda j2lo    ;compare i and j
          cmp i2lo
          lda j2hi
          sbc i2hi
          bcc qs_l8

qs_l6     lda (j2lo),y    ;exchange elements with i and j indices
          tax
          lda (i2lo),y
          sta (j2lo),y
          txa
          sta (i2lo),y
          dey
          bpl qs_l6

          ;sec
          lda #1        ;CY=1
          adc i2lo
          sta i2lo
          bcc *+4
          inc i2hi
          sec
          lda j2lo
          sbc #2
          sta j2lo
          bcs *+4
          dec j2hi
          ;lda j2lo
          cmp i2lo
          lda j2hi
          sbc i2hi
          ;bcc *+5
          ;jmp qsloop1
          bcs qsloop1

qs_l8     lda lblo
          cmp j2lo
          lda lbhi
          sbc j2hi
          bcs qs_l5

          lda i2hi
          pha
          lda i2lo
          pha
          lda ubhi
          pha
          lda ublo
          pha
          lda j2hi
          sta ubhi
          lda j2lo
          sta ublo
          jsr quicksort0
          pla
          sta ublo
          pla
          sta ubhi
          pla
          sta i2lo
          pla
          sta i2hi
qs_l5     lda i2lo
          cmp ublo
          lda i2hi
          sbc ubhi
          bcs qs_l7

          lda i2hi
          sta lbhi
          lda i2lo
          sta lblo
          jmp qsok
qs_l7     rts
.endif

.if 0
checksort lda #>1-gc_sz2/2
          sta r0h
          lda #<1-gc_sz2/2
          sta r0l
          lda #>strsgc
          sta r1h
          lda #<strsgc
          sta r1l
chkloop   ldy #0
          lda (r1l),y
          sta r2l
          iny
          lda (r1l),y
          sta r2h
          iny
          lda (r1l),y
          sta r3l
          iny
          lda (r1l),y
          sta r3h
          ldy #0
          lda (r3l),y
          cmp (r2l),y
          iny
          lda (r3l),y
          sbc (r2l),y
          bcc chkserr

          lda #1
          adc r1l
          sta r1l
          bcc *+4
          inc r1h
          inc r0l
          bne chkloop

          inc r0h
          bne chkloop
          rts

chkserr   sta $ff3e
          brk
.endif


