; Internal library routines - always included by the compiler
; Generic machine independent 6502 code.


orig_stackpointer	.byte  0	; stores the Stack pointer register at program start

read_byte_from_address_on_stack	.proc
	; -- read the byte from the memory address on the top of the stack, return in A (stack remains unchanged)
		lda  P8ESTACK_LO+1,x
		ldy  P8ESTACK_HI+1,x
		sta  P8ZP_SCRATCH_W2
		sty  P8ZP_SCRATCH_W2+1
		ldy  #0
		lda  (P8ZP_SCRATCH_W2),y
		rts
		.pend


write_byte_to_address_on_stack	.proc
	; -- write the byte in A to the memory address on the top of the stack (stack remains unchanged)
		ldy  P8ESTACK_LO+1,x
		sty  P8ZP_SCRATCH_W2
		ldy  P8ESTACK_HI+1,x
		sty  P8ZP_SCRATCH_W2+1
		ldy  #0
		sta  (P8ZP_SCRATCH_W2),y
		rts
		.pend



neg_b		.proc
		lda  #0
		sec
		sbc  P8ESTACK_LO+1,x
		sta  P8ESTACK_LO+1,x
		rts
		.pend

neg_w		.proc
		sec
		lda  #0
		sbc  P8ESTACK_LO+1,x
		sta  P8ESTACK_LO+1,x
		lda  #0
		sbc  P8ESTACK_HI+1,x
		sta  P8ESTACK_HI+1,x
		rts
		.pend

inv_word	.proc
		lda  P8ESTACK_LO+1,x
		eor  #255
		sta  P8ESTACK_LO+1,x
		lda  P8ESTACK_HI+1,x
		eor  #255
		sta  P8ESTACK_HI+1,x
		rts
		.pend

bitand_b	.proc
		; -- bitwise and (of 2 bytes)
		lda  P8ESTACK_LO+2,x
		and  P8ESTACK_LO+1,x
		inx
		sta  P8ESTACK_LO+1,x
		rts
		.pend

bitor_b		.proc
		; -- bitwise or (of 2 bytes)
		lda  P8ESTACK_LO+2,x
		ora  P8ESTACK_LO+1,x
		inx
		sta  P8ESTACK_LO+1,x
		rts
		.pend

bitxor_b	.proc
		; -- bitwise xor (of 2 bytes)
		lda  P8ESTACK_LO+2,x
		eor  P8ESTACK_LO+1,x
		inx
		sta  P8ESTACK_LO+1,x
		rts
		.pend

bitand_w	.proc
		; -- bitwise and (of 2 words)
		lda  P8ESTACK_LO+2,x
		and  P8ESTACK_LO+1,x
		sta  P8ESTACK_LO+2,x
		lda  P8ESTACK_HI+2,x
		and  P8ESTACK_HI+1,x
		sta  P8ESTACK_HI+2,x
		inx
		rts
		.pend

bitor_w		.proc
		; -- bitwise or (of 2 words)
		lda  P8ESTACK_LO+2,x
		ora  P8ESTACK_LO+1,x
		sta  P8ESTACK_LO+2,x
		lda  P8ESTACK_HI+2,x
		ora  P8ESTACK_HI+1,x
		sta  P8ESTACK_HI+2,x
		inx
		rts
		.pend

bitxor_w	.proc
		; -- bitwise xor (of 2 bytes)
		lda  P8ESTACK_LO+2,x
		eor  P8ESTACK_LO+1,x
		sta  P8ESTACK_LO+2,x
		lda  P8ESTACK_HI+2,x
		eor  P8ESTACK_HI+1,x
		sta  P8ESTACK_HI+2,x
		inx
		rts
		.pend


add_w		.proc
	; -- push word+word / uword+uword
		inx
		clc
		lda  P8ESTACK_LO,x
		adc  P8ESTACK_LO+1,x
		sta  P8ESTACK_LO+1,x
		lda  P8ESTACK_HI,x
		adc  P8ESTACK_HI+1,x
		sta  P8ESTACK_HI+1,x
		rts
		.pend

sub_w		.proc
	; -- push word-word
		inx
		sec
		lda  P8ESTACK_LO+1,x
		sbc  P8ESTACK_LO,x
		sta  P8ESTACK_LO+1,x
		lda  P8ESTACK_HI+1,x
		sbc  P8ESTACK_HI,x
		sta  P8ESTACK_HI+1,x
		rts
		.pend

mul_byte	.proc
	; -- b*b->b (signed and unsigned)
		inx
		lda  P8ESTACK_LO,x
		ldy  P8ESTACK_LO+1,x
		jsr  math.multiply_bytes
		sta  P8ESTACK_LO+1,x
		rts
		.pend

mul_word	.proc
		inx
		lda  P8ESTACK_LO,x
		sta  P8ZP_SCRATCH_W1
		lda  P8ESTACK_HI,x
		sta  P8ZP_SCRATCH_W1+1
		lda  P8ESTACK_LO+1,x
		ldy  P8ESTACK_HI+1,x
		jsr  math.multiply_words
		lda  math.multiply_words.result
		sta  P8ESTACK_LO+1,x
		lda  math.multiply_words.result+1
		sta  P8ESTACK_HI+1,x
		rts
		.pend

idiv_b		.proc
	; signed division: use unsigned division and fix sign of result afterwards
		inx
		lda  P8ESTACK_LO,x
		eor  P8ESTACK_LO+1,x
		php			; save sign of result
		lda  P8ESTACK_LO,x
		bpl  +
		eor  #$ff
		sec
		adc  #0			; make num1 positive
+		tay
		inx
		lda  P8ESTACK_LO,x
		bpl  +
		eor  #$ff
		sec
		adc  #0			; make num2 positive
+		jsr  math.divmod_ub_asm
		sta  _remainder
		tya
		plp			; get sign of result
		bpl  +
		eor  #$ff
		sec
		adc  #0			; negate result
+		sta  P8ESTACK_LO,x
		dex
		rts
_remainder	.byte  0
		.pend

idiv_ub		.proc
		inx
		ldy  P8ESTACK_LO,x
		lda  P8ESTACK_LO+1,x
		jsr  math.divmod_ub_asm
		tya
		sta  P8ESTACK_LO+1,x
		rts
		.pend

idiv_w		.proc
	; signed division: use unsigned division and fix sign of result afterwards
		lda  P8ESTACK_HI+2,x
		eor  P8ESTACK_HI+1,x
		php				; save sign of result
		lda  P8ESTACK_HI+1,x
		bpl  +
		jsr  neg_w			; make value positive
+		inx
		lda  P8ESTACK_HI+1,x
		bpl  +
		jsr  neg_w			; make value positive
+		lda  P8ESTACK_LO+1,x
		sta  P8ZP_SCRATCH_W1
		lda  P8ESTACK_HI+1,x
		sta  P8ZP_SCRATCH_W1+1
		lda  P8ESTACK_LO,x
		ldy  P8ESTACK_HI,x
		jsr  math.divmod_uw_asm
		sta  P8ESTACK_LO+1,x
		tya
		sta  P8ESTACK_HI+1,x
		plp
		bpl  +
		jmp  neg_w		; negate result
+		rts
		.pend

idiv_uw		.proc
		inx
		lda  P8ESTACK_LO+1,x
		sta  P8ZP_SCRATCH_W1
		lda  P8ESTACK_HI+1,x
		sta  P8ZP_SCRATCH_W1+1
		lda  P8ESTACK_LO,x
		ldy  P8ESTACK_HI,x
		jsr  math.divmod_uw_asm
		sta  P8ESTACK_LO+1,x
		tya
		sta  P8ESTACK_HI+1,x
		rts
		.pend

remainder_ub	.proc
		inx
		ldy  P8ESTACK_LO,x	; right operand
		lda  P8ESTACK_LO+1,x  ; left operand
		jsr  math.divmod_ub_asm
		sta  P8ESTACK_LO+1,x
		rts
		.pend

remainder_uw	.proc
		inx
		lda  P8ESTACK_LO+1,x
		sta  P8ZP_SCRATCH_W1
		lda  P8ESTACK_HI+1,x
		sta  P8ZP_SCRATCH_W1+1
		lda  P8ESTACK_LO,x
		ldy  P8ESTACK_HI,x
		jsr  math.divmod_uw_asm
		lda  P8ZP_SCRATCH_W2
		sta  P8ESTACK_LO+1,x
		lda  P8ZP_SCRATCH_W2+1
		sta  P8ESTACK_HI+1,x
		rts
		.pend

equal_w		.proc
	; -- are the two words on the stack identical?
		lda  P8ESTACK_LO+1,x
		cmp  P8ESTACK_LO+2,x
		bne  equal_b._equal_b_false
		lda  P8ESTACK_HI+1,x
		cmp  P8ESTACK_HI+2,x
		bne  equal_b._equal_b_false
		beq  equal_b._equal_b_true
		.pend

notequal_b	.proc
	; -- are the two bytes on the stack different?
		lda  P8ESTACK_LO+1,x
		cmp  P8ESTACK_LO+2,x
		beq  equal_b._equal_b_false
		bne  equal_b._equal_b_true
		.pend

notequal_w	.proc
	; -- are the two words on the stack different?
		lda  P8ESTACK_HI+1,x
		cmp  P8ESTACK_HI+2,x
		beq  notequal_b
		bne  equal_b._equal_b_true
		.pend

less_ub		.proc
		lda  P8ESTACK_LO+2,x
		cmp  P8ESTACK_LO+1,x
		bcc  equal_b._equal_b_true
		bcs  equal_b._equal_b_false
		.pend

less_b		.proc
	; see http://www.6502.org/tutorials/compare_beyond.html
		lda  P8ESTACK_LO+2,x
		sec
		sbc  P8ESTACK_LO+1,x
		bvc  +
		eor  #$80
+		bmi  equal_b._equal_b_true
		bpl  equal_b._equal_b_false
		.pend

reg_less_uw	.proc
		;  AY < P8ZP_SCRATCH_W2?
		cpy  P8ZP_SCRATCH_W2+1
		bcc  _true
		bne  _false
		cmp  P8ZP_SCRATCH_W2
		bcc  _true
_false		lda  #0
		rts
_true		lda  #1
		rts
		.pend

less_uw		.proc
		lda  P8ESTACK_HI+2,x
		cmp  P8ESTACK_HI+1,x
		bcc  equal_b._equal_b_true
		bne  equal_b._equal_b_false
		lda  P8ESTACK_LO+2,x
		cmp  P8ESTACK_LO+1,x
		bcc  equal_b._equal_b_true
		bcs  equal_b._equal_b_false
		.pend

reg_less_w	.proc
		; -- AY < P8ZP_SCRATCH_W2?
		cmp  P8ZP_SCRATCH_W2
		tya
		sbc  P8ZP_SCRATCH_W2+1
		bvc  +
		eor  #$80
+		bmi  _true
		lda  #0
		rts
_true		lda  #1
		rts
		.pend

less_w		.proc
		lda  P8ESTACK_LO+2,x
		cmp  P8ESTACK_LO+1,x
		lda  P8ESTACK_HI+2,x
		sbc  P8ESTACK_HI+1,x
		bvc  +
		eor  #$80
+		bmi  equal_b._equal_b_true
		bpl  equal_b._equal_b_false
		.pend

equal_b		.proc
	; -- are the two bytes on the stack identical?
		lda  P8ESTACK_LO+2,x
		cmp  P8ESTACK_LO+1,x
		bne  _equal_b_false
_equal_b_true	lda  #1
_equal_b_store	inx
		sta  P8ESTACK_LO+1,x
		rts
_equal_b_false	lda  #0
		beq  _equal_b_store
		.pend

lesseq_ub	.proc
		lda  P8ESTACK_LO+1,x
		cmp  P8ESTACK_LO+2,x
		bcs  equal_b._equal_b_true
		bcc  equal_b._equal_b_false
		.pend

lesseq_b	.proc
	; see http://www.6502.org/tutorials/compare_beyond.html
		lda  P8ESTACK_LO+2,x
		clc
		sbc  P8ESTACK_LO+1,x
		bvc  +
		eor  #$80
+		bmi  equal_b._equal_b_true
		bpl  equal_b._equal_b_false
		.pend

reg_lesseq_uw	.proc
		; AY <= P8ZP_SCRATCH_W2?
		cpy  P8ZP_SCRATCH_W2+1
		beq  +
		bcc  _true
		lda  #0
		rts
+		cmp  P8ZP_SCRATCH_W2
		bcc  _true
		beq  _true
		lda  #0
		rts
_true		lda  #1
		rts
		.pend

lesseq_uw	.proc
		lda  P8ESTACK_HI+1,x
		cmp  P8ESTACK_HI+2,x
		bcc  equal_b._equal_b_false
		bne  equal_b._equal_b_true
		lda  P8ESTACK_LO+1,x
		cmp  P8ESTACK_LO+2,x
		bcs  equal_b._equal_b_true
		bcc  equal_b._equal_b_false
		.pend

reg_lesseq_w	.proc
		; -- P8ZP_SCRATCH_W2 <= AY ?   (note: order different from other routines)
		cmp  P8ZP_SCRATCH_W2
		tya
		sbc  P8ZP_SCRATCH_W2+1
		bvc  +
		eor  #$80
+		bpl  +
		lda  #0
		rts
+		lda  #1
		rts
		.pend

lesseq_w	.proc
		lda  P8ESTACK_LO+1,x
		cmp  P8ESTACK_LO+2,x
		lda  P8ESTACK_HI+1,x
		sbc  P8ESTACK_HI+2,x
		bvc  +
		eor  #$80
+		bpl  equal_b._equal_b_true
		bmi  equal_b._equal_b_false
		.pend

greater_ub	.proc
		lda  P8ESTACK_LO+2,x
		cmp  P8ESTACK_LO+1,x
		beq  equal_b._equal_b_false
		bcs  equal_b._equal_b_true
		bcc  equal_b._equal_b_false
		.pend

greater_b	.proc
	; see http://www.6502.org/tutorials/compare_beyond.html
		lda  P8ESTACK_LO+2,x
		clc
		sbc  P8ESTACK_LO+1,x
		bvc  +
		eor  #$80
+		bpl  equal_b._equal_b_true
		bmi  equal_b._equal_b_false
		.pend

greater_uw	.proc
		lda  P8ESTACK_HI+1,x
		cmp  P8ESTACK_HI+2,x
		bcc  equal_b._equal_b_true
		bne  equal_b._equal_b_false
		lda  P8ESTACK_LO+1,x
		cmp  P8ESTACK_LO+2,x
		bcc  equal_b._equal_b_true
		bcs  equal_b._equal_b_false
		.pend

greater_w	.proc
		lda  P8ESTACK_LO+1,x
		cmp  P8ESTACK_LO+2,x
		lda  P8ESTACK_HI+1,x
		sbc  P8ESTACK_HI+2,x
		bvc  +
		eor  #$80
+		bmi  equal_b._equal_b_true
		bpl  equal_b._equal_b_false
		.pend

greatereq_ub	.proc
		lda  P8ESTACK_LO+2,x
		cmp  P8ESTACK_LO+1,x
		bcs  equal_b._equal_b_true
		bcc  equal_b._equal_b_false
		.pend

greatereq_b	.proc
	; see http://www.6502.org/tutorials/compare_beyond.html
		lda  P8ESTACK_LO+2,x
		sec
		sbc  P8ESTACK_LO+1,x
		bvc  +
		eor  #$80
+		bpl  equal_b._equal_b_true
		bmi  equal_b._equal_b_false
		.pend

greatereq_uw	.proc
		lda  P8ESTACK_HI+2,x
		cmp  P8ESTACK_HI+1,x
		bcc  equal_b._equal_b_false
		bne  equal_b._equal_b_true
		lda  P8ESTACK_LO+2,x
		cmp  P8ESTACK_LO+1,x
		bcs  equal_b._equal_b_true
		bcc  equal_b._equal_b_false
		.pend

greatereq_w	.proc
		lda  P8ESTACK_LO+2,x
		cmp  P8ESTACK_LO+1,x
		lda  P8ESTACK_HI+2,x
		sbc  P8ESTACK_HI+1,x
		bvc  +
		eor  #$80
+		bmi  equal_b._equal_b_false
		bpl  equal_b._equal_b_true
		.pend


shiftleft_b	.proc
		inx
		ldy  P8ESTACK_LO,x
		bne  +
		rts
+		lda  P8ESTACK_LO+1,x
-		asl  a
		dey
		bne  -
		sta  P8ESTACK_LO+1,x
		rts
		.pend

shiftright_b	.proc
		inx
		ldy  P8ESTACK_LO,x
		bne  +
		rts
+		lda  P8ESTACK_LO+1,x
-		lsr  a
		dey
		bne  -
		sta  P8ESTACK_LO+1,x
		rts
		.pend


equalzero_b	.proc
		lda  P8ESTACK_LO+1,x
		beq  _true
		bne  _false
_true		lda  #1
		sta  P8ESTACK_LO+1,x
		rts
_false		lda  #0
		sta  P8ESTACK_LO+1,x
		rts
		.pend

equalzero_w	.proc
		lda  P8ESTACK_LO+1,x
		ora  P8ESTACK_HI+1,x
		beq  equalzero_b._true
		bne  equalzero_b._false
		.pend

notequalzero_b	.proc
		lda  P8ESTACK_LO+1,x
		beq  equalzero_b._false
		bne  equalzero_b._true
		.pend

notequalzero_w	.proc
		lda  P8ESTACK_LO+1,x
		ora  P8ESTACK_HI+1,x
		beq  equalzero_b._false
		bne  equalzero_b._true
		.pend

lesszero_b	.proc
		lda  P8ESTACK_LO+1,x
		bmi  equalzero_b._true
		jmp  equalzero_b._false
		.pend

lesszero_w	.proc
		lda  P8ESTACK_HI+1,x
		bmi  equalzero_b._true
		jmp  equalzero_b._false
		.pend

greaterzero_ub	.proc
		lda  P8ESTACK_LO+1,x
		bne  equalzero_b._true
		beq  equalzero_b._false
		.pend

greaterzero_sb	.proc
		lda  P8ESTACK_LO+1,x
		beq  equalzero_b._false
		bpl  equalzero_b._true
		bmi  equalzero_b._false
		.pend

greaterzero_uw	.proc
		lda  P8ESTACK_LO+1,x
		ora  P8ESTACK_HI+1,x
		bne  equalzero_b._true
		beq  equalzero_b._false
		.pend

greaterzero_sw	.proc
		lda  P8ESTACK_HI+1,x
		bmi  equalzero_b._false
		ora  P8ESTACK_LO+1,x
		beq  equalzero_b._false
		bne  equalzero_b._true
		.pend

lessequalzero_sb	.proc
		lda  P8ESTACK_LO+1,x
		bmi  equalzero_b._true
		beq  equalzero_b._true
		bne  equalzero_b._false
		.pend

lessequalzero_sw	.proc
		lda  P8ESTACK_HI+1,x
		bmi  equalzero_b._true
		ora  P8ESTACK_LO+1,x
		beq  equalzero_b._true
		bne  equalzero_b._false
		.pend

greaterequalzero_sb	.proc
		lda  P8ESTACK_LO+1,x
	    	bpl  equalzero_b._true
	    	bmi  equalzero_b._false
		.pend

greaterequalzero_sw	.proc
		lda  P8ESTACK_HI+1,x
	    	bpl  equalzero_b._true
	    	bmi  equalzero_b._false
		.pend

memcopy16_up	.proc
	; -- copy memory UP from (P8ZP_SCRATCH_W1) to (P8ZP_SCRATCH_W2) of length X/Y (16-bit, X=lo, Y=hi)
	;    clobbers register A,X,Y
		source = P8ZP_SCRATCH_W1
		dest = P8ZP_SCRATCH_W2
		length = P8ZP_SCRATCH_B1   ; (and SCRATCH_ZPREG)

		stx  length
		sty  length+1

		ldx  length             ; move low byte of length into X
		bne  +                  ; jump to start if X > 0
		dec  length             ; subtract 1 from length
+		ldy  #0                 ; set Y to 0
-		lda  (source),y         ; set A to whatever (source) points to offset by Y
		sta  (dest),y           ; move A to location pointed to by (dest) offset by Y
		iny                     ; increment Y
		bne  +                  ; if Y<>0 then (rolled over) then still moving bytes
		inc  source+1           ; increment hi byte of source
		inc  dest+1             ; increment hi byte of dest
+		dex                     ; decrement X (lo byte counter)
		bne  -                  ; if X<>0 then move another byte
		dec  length             ; we've moved 255 bytes, dec length
		bpl  -                  ; if length is still positive go back and move more
		rts                     ; done
		.pend


memset          .proc
	; -- fill memory from (P8ZP_SCRATCH_W1), length XY, with value in A.
	;    clobbers X, Y
		stx  P8ZP_SCRATCH_B1
		sty  _save_reg
		ldy  #0
		ldx  _save_reg
		beq  _lastpage

_fullpage	sta  (P8ZP_SCRATCH_W1),y
		iny
		bne  _fullpage
		inc  P8ZP_SCRATCH_W1+1          ; next page
		dex
		bne  _fullpage

_lastpage	ldy  P8ZP_SCRATCH_B1
		beq  +
-         	dey
		sta  (P8ZP_SCRATCH_W1),y
		bne  -

+           	rts
_save_reg	.byte  0
		.pend


memsetw		.proc
	; -- fill memory from (P8ZP_SCRATCH_W1) number of words in P8ZP_SCRATCH_W2, with word value in AY.
	;    clobbers A, X, Y
		sta  _mod1+1                    ; self-modify
		sty  _mod1b+1                   ; self-modify
		sta  _mod2+1                    ; self-modify
		sty  _mod2b+1                   ; self-modify
		ldx  P8ZP_SCRATCH_W1
		stx  P8ZP_SCRATCH_B1
		ldx  P8ZP_SCRATCH_W1+1
		inx
		stx  P8ZP_SCRATCH_REG                ; second page

		ldy  #0
		ldx  P8ZP_SCRATCH_W2+1
		beq  _lastpage

_fullpage
_mod1           lda  #0                         ; self-modified
		sta  (P8ZP_SCRATCH_W1),y        ; first page
		sta  (P8ZP_SCRATCH_B1),y            ; second page
		iny
_mod1b		lda  #0                         ; self-modified
		sta  (P8ZP_SCRATCH_W1),y        ; first page
		sta  (P8ZP_SCRATCH_B1),y            ; second page
		iny
		bne  _fullpage
		inc  P8ZP_SCRATCH_W1+1          ; next page pair
		inc  P8ZP_SCRATCH_W1+1          ; next page pair
		inc  P8ZP_SCRATCH_B1+1              ; next page pair
		inc  P8ZP_SCRATCH_B1+1              ; next page pair
		dex
		bne  _fullpage

_lastpage	ldx  P8ZP_SCRATCH_W2
		beq  _done

		ldy  #0
-
_mod2           lda  #0                         ; self-modified
                sta  (P8ZP_SCRATCH_W1), y
		inc  P8ZP_SCRATCH_W1
		bne  _mod2b
		inc  P8ZP_SCRATCH_W1+1
_mod2b          lda  #0                         ; self-modified
		sta  (P8ZP_SCRATCH_W1), y
		inc  P8ZP_SCRATCH_W1
		bne  +
		inc  P8ZP_SCRATCH_W1+1
+               dex
		bne  -
_done		rts
		.pend



ror2_mem_ub	.proc
		; -- in-place 8-bit ror of byte at memory location in AY
		sta  P8ZP_SCRATCH_W1
		sty  P8ZP_SCRATCH_W1+1
		ldy  #0
		lda  (P8ZP_SCRATCH_W1),y
		lsr  a
		bcc  +
		ora  #$80
+		sta  (P8ZP_SCRATCH_W1),y
		rts
		.pend

rol2_mem_ub	.proc
		; -- in-place 8-bit rol of byte at memory location in AY
		sta  P8ZP_SCRATCH_W1
		sty  P8ZP_SCRATCH_W1+1
		ldy  #0
		lda  (P8ZP_SCRATCH_W1),y
		cmp  #$80
		rol  a
		sta  (P8ZP_SCRATCH_W1),y
		rts
		.pend

rol_array_ub	.proc
		; -- rol a ubyte in an array
		lda  _arg_target
		ldy  _arg_target+1
		sta  P8ZP_SCRATCH_W1
		sty  P8ZP_SCRATCH_W1+1
		ldy  _arg_index
		lda  (P8ZP_SCRATCH_W1),y
		rol  a
		sta  (P8ZP_SCRATCH_W1),y
		rts
_arg_target	.word	0
_arg_index	.byte   0
		.pend


ror_array_ub	.proc
		; -- ror a ubyte in an array
		lda  _arg_target
		ldy  _arg_target+1
		sta  P8ZP_SCRATCH_W1
		sty  P8ZP_SCRATCH_W1+1
		ldy  _arg_index
		lda  (P8ZP_SCRATCH_W1),y
		ror  a
		sta  (P8ZP_SCRATCH_W1),y
		rts
_arg_target	.word	0
_arg_index	.byte   0
		.pend

ror2_array_ub	.proc
		; -- ror2 (8-bit ror) a ubyte in an array
		lda  _arg_target
		ldy  _arg_target+1
		sta  P8ZP_SCRATCH_W1
		sty  P8ZP_SCRATCH_W1+1
		ldy  _arg_index
		lda  (P8ZP_SCRATCH_W1),y
		lsr  a
		bcc  +
		ora  #$80
+		sta  (P8ZP_SCRATCH_W1),y
		rts
_arg_target	.word	0
_arg_index	.byte   0
		.pend

rol2_array_ub	.proc
		; -- rol2 (8-bit rol) a ubyte in an array
		lda  _arg_target
		ldy  _arg_target+1
		sta  P8ZP_SCRATCH_W1
		sty  P8ZP_SCRATCH_W1+1
		ldy  _arg_index
		lda  (P8ZP_SCRATCH_W1),y
		cmp  #$80
		rol  a
		sta  (P8ZP_SCRATCH_W1),y
		rts
_arg_target	.word	0
_arg_index	.byte   0
		.pend

ror_array_uw	.proc
		; -- ror a uword in an array
		php
		lda  _arg_target
		ldy  _arg_target+1
		sta  P8ZP_SCRATCH_W1
		sty  P8ZP_SCRATCH_W1+1
		lda  _arg_index
		asl  a
		tay
		iny
		lda  (P8ZP_SCRATCH_W1),y
		plp
		ror  a
		sta  (P8ZP_SCRATCH_W1),y
		dey
		lda  (P8ZP_SCRATCH_W1),y
		ror  a
		sta  (P8ZP_SCRATCH_W1),y
		rts
_arg_target	.word  0
_arg_index	.byte  0
		.pend

rol_array_uw	.proc
		; -- rol a uword in an array
		php
		lda  _arg_target
		ldy  _arg_target+1
		sta  P8ZP_SCRATCH_W1
		sty  P8ZP_SCRATCH_W1+1
		lda  _arg_index
		asl  a
		tay
		lda  (P8ZP_SCRATCH_W1),y
		plp
		rol  a
		sta  (P8ZP_SCRATCH_W1),y
		iny
		lda  (P8ZP_SCRATCH_W1),y
		rol  a
		sta  (P8ZP_SCRATCH_W1),y
		rts
_arg_target	.word  0
_arg_index	.byte  0
		.pend

rol2_array_uw	.proc
		; -- rol2 (16-bit rol) a uword in an array
		lda  _arg_target
		ldy  _arg_target+1
		sta  P8ZP_SCRATCH_W1
		sty  P8ZP_SCRATCH_W1+1
		lda  _arg_index
		asl  a
		tay
		lda  (P8ZP_SCRATCH_W1),y
		asl  a
		sta  (P8ZP_SCRATCH_W1),y
		iny
		lda  (P8ZP_SCRATCH_W1),y
		rol  a
		sta  (P8ZP_SCRATCH_W1),y
		bcc  +
		dey
		lda  (P8ZP_SCRATCH_W1),y
		adc  #0
		sta  (P8ZP_SCRATCH_W1),y
+		rts
_arg_target	.word  0
_arg_index	.byte  0
		.pend

ror2_array_uw	.proc
		; -- ror2 (16-bit ror) a uword in an array
		lda  _arg_target
		ldy  _arg_target+1
		sta  P8ZP_SCRATCH_W1
		sty  P8ZP_SCRATCH_W1+1
		lda  _arg_index
		asl  a
		tay
		iny
		lda  (P8ZP_SCRATCH_W1),y
		lsr  a
		sta  (P8ZP_SCRATCH_W1),y
		dey
		lda  (P8ZP_SCRATCH_W1),y
		ror  a
		sta  (P8ZP_SCRATCH_W1),y
		bcc  +
		iny
		lda  (P8ZP_SCRATCH_W1),y
		ora  #$80
		sta  (P8ZP_SCRATCH_W1),y
+		rts
_arg_target	.word  0
_arg_index	.byte  0
		.pend


strcpy		.proc
		; copy a string (must be 0-terminated) from A/Y to (P8ZP_SCRATCH_W1)
		; it is assumed the target string is large enough.
		; returns the length of the string that was copied in Y.
		sta  P8ZP_SCRATCH_W2
		sty  P8ZP_SCRATCH_W2+1
		ldy  #$ff
-		iny
		lda  (P8ZP_SCRATCH_W2),y
		sta  (P8ZP_SCRATCH_W1),y
		bne  -
		rts
		.pend

strcmp_expression	.proc
		; -- compare strings, result in A
		lda  _arg_s2
		ldy  _arg_s2+1
		sta  P8ZP_SCRATCH_W2
		sty  P8ZP_SCRATCH_W2+1
		lda  _arg_s1
		ldy  _arg_s1+1
		jmp  strcmp_mem
_arg_s1		.word  0
_arg_s2		.word  0
		.pend


strcmp_mem	.proc
		; --   compares strings in s1 (AY) and s2 (P8ZP_SCRATCH_W2).
		;      Returns -1,0,1 in A, depeding on the ordering. Clobbers Y.
		sta  P8ZP_SCRATCH_W1
		sty  P8ZP_SCRATCH_W1+1
		ldy  #0
_loop		lda  (P8ZP_SCRATCH_W1),y
		bne  +
		lda  (P8ZP_SCRATCH_W2),y
		bne  _return_minusone
		beq  _return
+		cmp  (P8ZP_SCRATCH_W2),y
		bcc  _return_minusone
		bne  _return_one
		inc  P8ZP_SCRATCH_W1
		bne  +
		inc  P8ZP_SCRATCH_W1+1
+		inc  P8ZP_SCRATCH_W2
		bne  _loop
		inc  P8ZP_SCRATCH_W2+1
		bne  _loop
_return_one
		lda  #1
_return		rts
_return_minusone
		lda  #-1
		rts
		.pend


sign_extend_stack_byte	.proc
	; -- sign extend the (signed) byte on the stack to full 16 bits
		lda  P8ESTACK_LO+1,x
		ora  #$7f
		bmi  +
		lda  #0
+		sta  P8ESTACK_HI+1,x
		rts
		.pend

strlen          .proc
        ; -- returns the number of bytes in the string in AY, in Y.
		sta  P8ZP_SCRATCH_W1
		sty  P8ZP_SCRATCH_W1+1
		ldy  #0
-		lda  (P8ZP_SCRATCH_W1),y
		beq  +
		iny
		bne  -
+		rts
		.pend


containment_bytearray	.proc
	; -- check if a value exists in a byte array.
	;    parameters: P8ZP_SCRATCH_W1: address of the byte array, A = byte to check, Y = length of array (>=1).
	;    returns boolean 0/1 in A.
		dey
-		cmp  (P8ZP_SCRATCH_W1),y
		beq  +
		dey
		cpy  #255
		bne  -
		lda  #0
		rts
+		lda  #1
		rts
		.pend

containment_wordarray	.proc
	; -- check if a value exists in a word array.
	;    parameters: P8ZP_SCRATCH_W1: value to check, P8ZP_SCRATCH_W2: address of the word array, Y = length of array (>=1).
	;    returns boolean 0/1 in A.
		dey
		tya
		asl  a
		tay
-		lda  P8ZP_SCRATCH_W1
		cmp  (P8ZP_SCRATCH_W2),y
		bne  +
		lda  P8ZP_SCRATCH_W1+1
		iny
		cmp  (P8ZP_SCRATCH_W2),y
		beq  _found
		dey
+		dey
		dey
		cpy  #254
		bne  -
		lda  #0
		rts
_found		lda  #1
		rts
		.pend
