;*******************************************************************
;
;	Embedded Pascal AVR Runtime library
;
;	For release with version Embedded Pascal version 2.0
;
;	The routines in this library are reentrant and can be
;	used from within interrupt routines provided used
;	registers are saved accordingly
;
;	It is not recommended that you add routines to this
;	library. Do so in another module. This will prevent
;	unnecessary re-work on your side should you receive an
;	update to this library.
;
;	Note on string formats while on stack:
;	strings are stored with the length byte at the lowest
;	address. The string content follows but is in byte-
;	reversed order, i.e. the first character in the string
;	occupies the highest address. This format aids string
;	concatenation
;
;	Notes on registers R28,R29 (Y)
;	if these registers need to be used, they must be
;	saved and restored as Y is used as frame pointer
;	for dynamic parameters and variables
;
;*******************************************************************

 Global	__Mult16,__SMult16,__Div16,__SDiv16,__Mod16
 Global __Add32,__Sub32,__And32,__Or32,__Xor32
 Global __SMult32,__Mod32,__SDiv32,__Div8,__Mult8
 Global __LintODD,__IntABS,__LintABS,__Move,__CMove
 Global __NotBool,__NotInt,__NotLint,__MakeBool,_ADRCache_
 Global __bequ,__bnotequ,__bless,__blessorequ,__bgreater,__bgreaterorequ
 Global __equ,__notequ,__less,__lessorequ,__greater,__greaterorequ
 Global __sequ,__snotequ,__sless,__slessorequ,__sgreater,__sgreaterorequ
 Global __iless,__ilessorequ,__igreater,__igreaterorequ
 Global __lequ,__lnotequ,__lless,__llessorequ,__lgreater,__lgreaterorequ
 Global __succ8,__pred8,__succ16,__pred16,__succ16w,__pred16w
 Global __succ32,__pred32,__inc16,__dec16,__inc32,__dec32
 Global __inc16Z,__dec16Z,__inc32Z,__dec32Z,__inc24Z,__dec24Z
 Global __PushString,__PushCString,__PopString,__DumpString
 Global __CharToString,__TwoCharsToString,__UpCase
 Global __Shr8,__Shl8,__Shr16,__Shl16,__Shr32,__Shl32
 Global __Rr8,__Rl8,__Rr16,__Rl16,__Rr32,__Rl32
 Global __LoopTestUp,__LoopTestDown,__SwitchByte,__JpTable,__ConstSet
 Global __GetHeapPtr,__SetHeapPtr,__Malloc,HeapPtr
 Global __FillChar,__AddStrings,__AddCharToString,__AddStrToCharOnStack
 Global __AddStringToChar,__PopStringWA
 Global __ByteToHexStr,__WordToHexStr,__LintToHexStr
 Global __ByteToStr,__WordToStr,__IntToStr,__LintToStr,__PosN
 Global __StrToInt,__CopyString,__CopyCString,__Insert,__Delete
 Global __SimpleProcEntry,__ProcEntry,__ProcExit,__SubStack
 Global __FrameRel,__FrameRelPtr,__StrFixup
 Global __ExtendSint,__ExtendInt,__ExtendSintToLint
 Global __STTLA,__LDTLA,__LDTLB,__LDTCLA,__LDTCLB
 Global __LDLLA,__LDLLB,__LDLCLA,__LDLCLB,__STLLA,__MoveStringCtoD
 Global __BitIsSet,__BitIsReset,__ToggleBit,__MOVLBLA,__AddStringToString
 Global __BitMask
 Global _LintPrep,_LintPost

	const 	;_Dectab needs to be located in the first 64K
		;code block so we can use it with LPM

	ifref _DecTab

_DecTab:
	DL 1000000000,100000000,10000000,1000000
	DL 100000,10000,1000,100,10

	endif

	ifref __BitIsSet,__BitIsReset

_mask:  DB 1,2,4,8,16,32,64,128	

	endif

	code	;remainder of code located in special code segment

;__ProcEntry: Used for procedures and functions declared with
;Dynamic variables and procedures active (#K+}
;Save Y, setup local variable space, prepare Y

	ifref __ProcEntry
	RegUse #__ProcEntry
__ProcEntry:
	pop R31	     ;return address
	pop R30
	pop R15	     ;Procedure return address
	pop R14
	in R16,spl   ;current stack pointer
	iftrue LargeStack
          in R17,sph
        endif
	sub R16,R20 ;sub size of local variables
	iftrue LargeStack
           sbc R17,R21
        endif
        iftrue LargeStack
          in R18,SREG
          cli
	  out spl,R16  ;it is required to disable them
	  out sph,R17  ;when updating the stack pointer
          out SREG,R18          
	endif
	iffalse LargeStack
	  out spl,R16
        endif
	push R14
	push R15
	push R28
	push R29     ;old Y
	mov R28,R16
	iftrue LargeStack
          mov R29,R17  ;New Y
        endif
        iffalse LargeStack
          clr R29
        endif  
	adiw R28,1   ;to compensate for stack -1
	ijmp
	endif
	RegEnd

;__Simple ProcEntry - Same as above but for routines without
;local variables

	ifref __SimpleProcEntry
	RegUse #__SimpleProcEntry
__SimpleProcEntry:
	pop R31
	pop R30
    	push R28
    	push R29
    	in R28,spl
    	iftrue LargeStack
          in R29,sph
	endif
	iffalse LargeStack
	  clr R29
	endif  
	adiw R28,5 ;set FramePointer=stackptr+5
	ijmp
	endif
	RegEnd

;Exit code for procedures compiled with {#K+}. Remove
;local variables and parameters from stack. Z contains
;return address for procedure / function
;Also used to subtract a value from the stackpointer
 
	ifref __SubStack
	RegUse #__SubStack
__SubStack:
	pop R31
	pop R30
	RegAdd #__SubStack,#__ProcExit
	endif
	RegEnd

	ifref __ProcExit,__SubStack,__StrFixup
	RegUse #__ProcExit
__ProcExit:
        in R16,spl
        iftrue LargeStack
          in R17,sph
        endif  
        sub R16,R20
        iftrue LargeStack
          sbc R17,R21
        endif  
_FromFx:
	iftrue LargeStack
	  in R18,SREG  ;interrupts must be disabled when manipulating the full stack pointer
	  cli
    	  out sph,R17
    	  out spl,R16
    	  out SREG,R18
        endif
	iffalse LargeStack
	  out spl,R16
	endif  
        ijmp
	endif
	RegEnd

;__FrameRel: Given the Frame pointer in Y and offset in Z, returns
;Z pointing to item on stack

	ifref __FrameRel
	RegUse #__FrameRel
__FrameRel:
	add R30,R28
	adc R31,R29
	ret
	endif
	RegEnd

;__FrameRelPtr: Given the Frame pointer in Y and offset in Z, 
;returns contents of pointer addressed on stack

	ifref __FrameRelPtr
	RegUse #__FrameRelPtr
__FrameRelPtr:
	add R30,R28
	adc R31,R29
	ld R0,Z+
	ld R31,Z
	mov R30,R0
	ret
	endif
	RegEnd

;__StrFixup: As for procexit but fixes up the return string for
;functions with string results. This routine is only called in
;those cases. On entry: WA=size of the local string function
;result. WB=number of bytes to remove from stack (local vars and
;parameters)

	ifref __StrFixup
	RegUse #__StrFixup
__StrFixup:
	mov R0,R30	;save Z
	mov R1,R31
        in R18,spl	;first remove local vars and parameters
        iftrue LargeStack
          in R19,sph
        endif
        sub R18,R20
        iftrue LargeStack
          sbc R19,R21
          in R21,SREG
          cli
    	  out sph,R19
    	  out spl,R18
    	  out SREG,R21
        endif
        iffalse LargeStack
          out spl,R18
        endif  
	mov R30,R18	;point to start of result string
	iftrue LargeStack
	  mov R31,R19
	endif
	iffalse LargeStack
	  clr R31
	endif     
	adiw R30,1
	mov R26,R30
	mov R27,R31	;keep that
	add R26,R16
	iftrue LargeStack
	  adc R27,R17	;point to last byte of final result+1
	endif
	iffalse LargeStack
	  clr R27
	endif
	.call __PushString ;string is now moved underneath
	RegAdd #__StrFixup,#__PushString
	in R30,spl
	iftrue LargeStack
	  in R31,sph	;find out where it is
	endif
	iffalse largeStack
	  clr R31
	endif  
	adiw R30,1
	ld R18,Z
	clr R19
	add R30,R18	;set to last byte of string+1
	adc R31,R19	
	adiw R30,1
	inc R18		;now number of bytes to move 0=256
_fu1:	ld R16,-Z
	st -X,R16
	dec R18
	brne _fu1
	sbiw R26,1
	mov R16,R26	;new stackpointer
	iftrue LargeStack
	  mov R17,R27
	endif  
	mov R30,R0	;return address for function
	mov R31,R1
	rjmp _FromFx	;rest as for procexit
	RegAdd #__StrFixup,#__ProcExit
	RegEnd
	endif

;Signed multiply 16 bit

	ifref __SMult16
	RegUse #__SMult16

__SMult16:
	RegAdd #__SMult16,_IntPrep
	.call _IntPrep
	push R0
	.call __Mult16
	RegAdd #__SMult16,#__Mult16
	pop R0
	RegAdd #__SMult16,_IntPost
	rjmp _IntPost

	endif
	RegEnd

;prepare for signed multiplication or division
;absolute value of all arguments needed, bit 0 of R0 will indicate
;if result is to be negated

	ifref _IntPrep
	RegUse _IntPrep
_IntPrep:
	clr R0
	sbrs R17,7
	rjmp _ip1
	.call __NotInt
	RegAdd _IntPrep,#__NotInt
	inc R0
_ip1:	sbrs R21,7
	rjmp _ip2
	ldi R18,0FFH
	eor R20,R18
	eor R21,R18
	ldi R18,1
	add R20,R18
	clr R18
	adc R21,R18
	inc R0
_ip2:	ret

	endif
	RegEnd

;_IntPost: negate result of multiplication or division if bit 0
;of R0 is set

	ifref _IntPost
	RegUse _IntPost
_IntPost:
	sbrs R0,0
	ret
	.jmp __NotInt
	RegAdd _IntPost,#__NotInt
	endif
	RegEnd

;Multiply two 8 bit values in R16 and R20. 16 bit Result in R16,17. 
;Note: uses R0,1

	ifref __Mult8
	RegUse #__Mult8
__Mult8:

	iftrue CPUHasMultiply

	mul R16,R20
	mov R16,R0
	mov R17,R1
	ret

	endif

	iffalse CPUHasMultiply

	clr R17
	clr R21
	RegAdd ##,#__Mult16

	endif

	endif
	RegEnd


;Multiply two 16 bit values in R16,17 and R20,21. Result in R16,17. 
;Uses 8 bit MUL for speed
;Note: uses R0,1,2,3

	ifref __Mult16,__Mult8
	RegUse #__Mult16
__Mult16:

	iftrue CPUHasMultiply

	mul R16,R20	;lsb*lsb
	mov R2,R0
	mov R3,R1
	mul R16,R21	;lsb*msb
	add R3,R0
	mul R17,R20	;msb*lsb
	add R3,R0
	mov R16,R2
	mov R17,R3
	ret

	endif

	iffalse CPUHasMultiply

	clr R0		;temp result
	clr R1
	ldi R24,16	;init loop counter
_m161:	lsr R21
	ror R20
	brcc _m162
	add R0,R16
	adc R1,R17
_m162:	lsl R16
	rol R17
	dec R24
	brne _m161
	mov R16,R0
	mov R17,R1
	ret

	endif

	endif
	RegEnd

;Signed multiply 32 bit

	ifref __SMult32
	RegUse #__SMult32
__SMult32:
	.call _LIntPrep
	RegAdd #__SMult32,_LintPrep
	push R0
	.call __Mult32
	RegAdd #__SMult32,#__Mult32
	pop R0
	.jmp _LIntPost
	RegAdd #__SMult32,_LintPost

	endif
	RegEnd

;prepare for signed longint multiplication or division
;absolute value of all arguments needed, bit 0 of R0 will indicate
;if result is to be negated

	ifref _LIntPrep
	RegUse _LIntPrep

_LIntPrep:
	clr R0
	sbrs R19,7
	rjmp _lip1
	.call __NotLInt
	RegAdd _LIntPrep,#__NotLInt
	inc R0
_lip1:	sbrs R23,7
	rjmp _lip2
	ldi R24,0FFH
	eor R20,R24
	eor R21,R24
	eor R22,R24
	eor R23,R24
	ldi R24,1
	add R20,R24
	clr R24
	adc R21,R24
	adc R22,R24
	adc R23,R24
	inc R0
_lip2:	ret

	endif
	RegEnd

;_LIntPost: negate result of longint 
;multiplication or division if bit 0
;of R0 is set

	ifref _LIntPost
	RegUse _LIntPost

_LIntPost:
	sbrs R0,0
	ret
	.jmp __NotLInt
	RegAdd _LIntPost,#__NotLint
	endif
	RegEnd

;__Mult32. Multiply LA*LB. Result in LA

	ifref __Mult32
	RegUse #__Mult32

__Mult32:
	clr R0		;temp result
	clr R1
	clr R2
	clr R3
	ldi R24,32	;init loop counter
_m321:	lsr R23
	ror R22
	ror R21
	ror R20
	brcc _m322
	add R0,R16
	adc R1,R17
	adc R2,R18
	adc R3,R19
_m322:	lsl R16
	rol R17
	rol R18
	rol R19
	dec R24
	brne _m321
	mov R16,R0
	mov R17,R1
	mov R18,R2
	mov R19,R3
	ret

	endif
	RegEnd

;Integer (16 bit) mod function. R16,17 mod R20,21. Result in R16,17

	ifref __Mod16
	RegUse #__Mod16

__Mod16:
	.call __Div16
	RegAdd #__Mod16,#__Div16
	mov R17,R1
	mov R16,R0
	ret

	endif
	RegEnd

;Integer (16 bit) divide R16,17 by R20,21. Result in R16,17. 
;Remainder in R2,3

	ifref __SDiv16
	RegUse #__SDiv16

__SDiv16:
	.call _IntPrep
	RegAdd #__SDiv16,_IntPrep
	push R0
	.call __Div16
	RegAdd #__SDiv16,#__Div16
	pop R0
	.jmp _IntPost
	RegAdd #__SDiv16,_IntPost

	endif
	RegEnd

;Divide R16,17 by R20,21. Result in R16,17. Remainder in R2,3

	ifref __Div16
	RegUse #__Div16

__Div16:
	ldi R18,16	;loop counter
	clr R0
	clr R1 		;will finaly hold remainder
_Div16b:	
	rol R16
	rol R17
	rol R0
	rol R1
	sub R0,R20
	sbc R1,R21
	brcc _Div16a
	add R0,R20
	adc R1,R21
_Div16a:
	brcc _Div16d
	clc
	rjmp _Div16c
_Div16d:
	sec
_Div16c:	
	dec R18
	brne _Div16b
	rol R16
	rol R17
	mov R4,R0	;preserve R0 (lsb of modulus)
	ret

	endif
	RegEnd

;Divide R16 by R20. Result in R16. Remainder in R0

	ifref __Div8
	RegUse #__Div8

__Div8:
	ldi R18,8	;loop counter
	clr R0 		;will finaly hold remainder
_Div8b:	
	rol R16
	rol R0
	sub R0,R20
	brcc _Div8a
	add R0,R20
_Div8a:
	brcc _Div8d
	clc
	rjmp _Div8c
_Div8d:
	sec
_Div8c:	
	dec R18
	brne _Div8b
	rol R16
	ret

	endif
	RegEnd

;Integer (32 bit) mod function. R16,17,18,19 mod R20,21,22,23. 
;Result in R16,17,18,19

	ifref __Mod32
	RegUse #__Mod32

__Mod32:
	.call __Div32
	RegAdd #__Mod32,#__Div32
	mov R19,R3
	mov R18,R2
	mov R17,R1
	mov R16,R0
	ret

	endif
	RegEnd

;Signed (32 bit) divide LA by LB. Result in LA. 
;Remainder in R2,3,4,5

	ifref __SDiv32
	RegUse #__SDiv32
__SDiv32:
	.call _LIntPrep
	RegAdd #__SDiv32,_LintPrep
	push R0
	.call __Div32
	RegAdd #__SDiv32,#__Div32
	pop R0
	.jmp _LIntPost
	RegAdd #__SDiv32,_LintPost

	endif

;Divide LA by LB Result in LA. Remainder in R0,1,2,3

	ifref __Div32
	RegUse #__Div32

__Div32:
        mov R0,R20
        or R0,R21
        or R0,R22
        or R0,R23
        breq _Div32Zero ;division by zero, return largest possible result
	ldi R24,32	;loop counter
	clr R0
	clr R1 		
	clr R2
	clr R3		;will finaly hold remainder
_Div32b:	
	rol R16
	rol R17
	rol R18
	rol R19
	rol R0
	rol R1
	rol R2
	rol R3
	sub R0,R20
	sbc R1,R21
	sbc R2,R22
	sbc R3,R23
	brcc _Div32a
	add R0,R20
	adc R1,R21
	adc R2,R22
	adc R3,R23
_Div32a:
	brcc _Div32d
	clc
	rjmp _Div32c
_Div32d:
	sec
_Div32c:	
	dec R24
	brne _Div32b
	rol R16
	rol R17
	rol R18
	rol R19
	mov R4,R0	;R0 will be destroyed in signed division (_SDIV32)
	ret		;preserve R0 in R4 for applications needing the modulus as well
_Div32Zero:
        ldi R16,$FF	;for division by zero, return largest possible positive result
        ldi R17,$FF	;negation, if required will be handled by calling routine
        ldi R18,$FF
        ldi R19,$7F
        ret	

	endif
	RegEnd

	ifref __Add32
	RegUse #__Add32

__Add32:
	add R16,R20
	adc R17,R21
	adc R18,R22
	adc R19,R23
	ret

	endif
	RegEnd

	ifref __Sub32
	RegUse #__Sub32

__Sub32:
	sub R16,R20
	sbc R17,R21
	sbc R18,R22
	sbc R19,R23
	ret

	endif
	RegEnd

	ifref __And32
	RegUse #__And32

__And32:
	and R16,R20
	and R17,R21
	and R18,R22
	and R19,R23
	ret

	endif
	RegEnd
	
	ifref __or32
	RegUse #__or32
__or32:
	or R16,R20
	or R17,R21
	or R18,R22
	or R19,R23
	ret

	endif
	RegEnd

	ifref __xor32
	RegUse #__xor32

__xor32:
	eor R16,R20
	eor R17,R21
	eor R18,R22
	eor R19,R23
	ret

	endif
	RegEnd

	ifref __IntABS,__NotInt

	RegUse #__IntAbs
__IntABS:
	sbrs R17,7
	ret
	RegAdd #__IntAbs,#__NotInt
	RegEnd
__NotInt:
	RegUse #__NotInt
	ldi R18,0FFH
	eor R16,R18
	eor R17,R18
	.jmp __Inc16
	RegAdd #__NotInt,#__Inc16

	endif
	RegEnd

	ifref __LIntABS,__NotLint
	RegUse #__LIntAbs

__LIntABS:
	sbrs R19,7
	ret
	RegAdd #__LIntAbs,#__NotLint
	RegEnd
__NotLint:
	RegUse #__NotLint
	ldi R24,0FFH
	eor R16,R24
	eor R17,R24
	eor R18,R24
	eor R19,R24
	.jmp __Inc32
	RegAdd #__NotLint,#__Inc32
	endif
	RegEnd

	ifref __LintODD
	RegUse #__LintOdd

__LintODD:
	sbrc R16,0
	rjmp _iodd
	clr R16
	ret
_iodd:	ldi R16,1
	ret

	endif
	RegEnd

	ifref __Move
	RegUse #__Move

__Move: or R16,R17
	brne _mv1
	ret
_mv1:	ld R18,Z+
	st X+,R18
	subi R16,1
	sbci R17,0
	rjmp __Move

	endif
	RegEnd

	ifref __CMove
	RegUse #__CMove

__CMove: or R16,R17
	brne _cmv1
	ret
_cmv1:	.lpm
	adiw R30,1
	st X+,R0
	subi R16,1
	sbci R17,0
	rjmp __CMove

	endif
	RegEnd

;__Notbool supports inversion of the boolean value in R16. Also used by the
;function __IOBitLow

	ifref __NotBool
	RegUse #__NotBool

__NotBool:
	tst R16
	breq _nb1
	clr R16
	ret
_nb1:	ldi R16,1
	tst R16
	ret

	endif
	RegEnd

;__Makebool supports the IOBitHigh function. Given a zero or non
;zero value in R16, will return a proper boolean result (0 or 1)

	ifref __MakeBool
	RegUse #__MakeBool

__MakeBool:
	tst R16
	breq _mb1
	ldi R16,1
        tst R16
	ret
_mb1:	clr R16
	ret

	endif
	RegEnd

	ifref _RetFalse,_RetTrue
	RegUse _RetFalse
_RetFalse:
	clr R16
	ret
	RegEnd
_RetTrue:
	RegUse _RetTrue
	ldi R16,1
	tst R16		;sets flags
	ret

	endif
	RegEnd

	ifref __bequ
	RegUse #__bequ
__bequ:
	cp R16,R20
	.jmpeq _RetTrue
	.jmp _RetFalse
	RegAdd #__bequ,_RetTrue
	RegAdd #__bequ,_RetFalse

	endif
	RegEnd

	ifref __bnotequ
	RegUse #__bnotequ

__bnotequ:
	cp R16,R20
	.jmpeq _RetFalse
	.jmp _RetTrue
	RegAdd #__bnotequ,_RetTrue
	RegAdd #__bnotequ,_RetFalse

	endif
	RegEnd

	ifref __bless
	RegUse #__bless

__bless:
	cp R16,R20
	.jmpcs _RetTrue
	.jmp _RetFalse
	RegAdd #__bless,_RetTrue
	RegAdd #__bless,_RetFalse

	endif
	RegEnd

	ifref __blessorequ
	RegUse #__blessorequ

__blessorequ:
	cp R20,R16
	.jmpcc _RetTrue
	.jmp _RetFalse
	RegAdd #__blessorequ,_RetTrue
	RegAdd #__blessorequ,_RetFalse

	endif
	RegEnd

	ifref __bgreater
	RegUse #__bgreater

__bgreater:
	cp R20,R16
	.jmpcs _RetTrue
	.jmp _RetFalse
	RegAdd #__bgreater,_RetTrue
	RegAdd #__bgreater,_RetFalse
	endif
	RegEnd

	ifref __bgreaterorequ
	RegUse #__bgreaterorequ

__bgreaterorequ:
	cp R16,R20
	.jmpcs _RetFalse
	.jmp _RetTrue
	RegAdd #__bgreaterorequ,_RetTrue
	RegAdd #__bgreaterorequ,_RetFalse
	endif
	RegEnd

	ifref __equ
	RegUse #__equ

__equ:
	cp R16,R20
	cpc R17,R21
	.jmpeq _RetTrue
	.jmp _RetFalse
	RegAdd #__equ,_RetTrue
	RegAdd #__equ,_RetFalse

	endif
	RegEnd

	ifref __notequ
	RegUse #__notequ

__notequ:
	cp R16,R20
	cpc R17,R21
	.jmpeq _RetFalse
	.jmp _RetTrue
	RegAdd #__notequ,_RetTrue
	RegAdd #__notequ,_RetFalse

	endif
	RegEnd

	ifref __less
	RegUse #__less
__less:
	cp R16,R20
	cpc R17,R21
	.jmpcs _RetTrue
	.jmp _RetFalse
	RegAdd #__less,_RetTrue
	RegAdd #__less,_RetFalse

	endif
	RegEnd
	ifref __lessorequ
	RegUse #__lessorequ
__lessorequ:
	cp R20,R16
	cpc R21,R17
	.jmpcc _RetTrue
	.jmp _RetFalse
	RegAdd #__lessorequ,_RetTrue
	RegAdd #__lessorequ,_RetFalse

	endif
	RegEnd
	ifref __greater
	RegUse #__greater
__greater:
	cp R20,R16
	cpc R21,R17
	.jmpcs _RetTrue
	.jmp _RetFalse
	RegAdd #__greater,_RetTrue
	RegAdd #__greater,_RetFalse

	endif
	RegEnd

	ifref __greaterorequ
	RegUse #__greaterorequ
__greaterorequ:
	cp R16,R20
	cpc R17,R21
	.jmpcs _RetFalse
	.jmp _RetTrue
	RegAdd #__greaterorequ,_RetTrue
	RegAdd #__greaterorequ,_RetFalse

	endif
	RegEnd

	ifref _IntCmpPrep
	RegUse _IntCmpPrep

_IntCmpPrep:
	clr R24
	sbrc R17,7 
	inc R24
	sbrc R21,7
	inc R24
	ret

	endif
	RegEnd

	ifref __iless
	RegUse #__iless
__iless:
	.call _IntCmpPrep
	RegAdd #__iless,_IntCmpPrep
	sbrs R24,0
	.jmp __less
	RegAdd #__iless,#__less
	andi R17,080H
	.jmpeq _RetFalse
	.jmp _RetTrue
	RegAdd #__iless,_RetTrue
	RegAdd #__iless,_RetFalse
	endif
	RegEnd

	ifref __ilessorequ
	RegUse #__ilessorequ
__ilessorequ:
	.call _IntCmpPrep
	RegAdd #__ilessorequ,_IntCmpPrep
	sbrs R24,0
	.jmp __LessOrequ
	RegAdd #__ilessorequ,#__LessOrequ
	andi R17,080H
	.jmpeq _RetFalse
	.jmp _RetTrue
	RegAdd #__ilessorequ,_RetTrue
	RegAdd #__ilessorequ,_RetFalse
	endif
	RegEnd

	ifref __igreater
	RegUse #__igreater
__igreater:
	.call _IntCmpPrep
	RegAdd #__igreater,_IntCmpPrep
	sbrs R24,0
	.jmp __greater
	RegAdd #__igreater,#__greater
	andi R17,080H
	.jmpeq _RetTrue
	.jmp _RetFalse
	RegAdd #__igreater,_RetTrue
	RegAdd #__igreater,_RetFalse
	endif
	RegEnd

	ifref __igreaterorequ
	RegUse #__igreaterorequ
__igreaterorequ:
	.call _IntCmpPrep
	RegAdd #__igreaterorequ,_IntCmpPrep
	sbrs R24,0
	.jmp __greaterorequ
	RegAdd #__igreaterorequ,#__greaterorequ
	andi R17,080H
	.jmpeq _RetTrue
	.jmp _RetFalse
	RegAdd #__igreaterorequ,_RetTrue
	RegAdd #__igreaterorequ,_RetFalse
	endif
	RegEnd

	ifref __lequ
	RegUse #__lequ
__lequ:
	cp R16,R20
	cpc R17,R21
	cpc R18,R22
	cpc R19,R23
	.jmpeq _RetTrue
	.jmp _RetFalse
	RegAdd #__lequ,_RetTrue
	RegAdd #__lequ,_RetFalse
	endif
	RegEnd

	ifref __lnotequ
	RegUse #__lnotequ
__lnotequ:
	cp R16,R20
	cpc R17,R21
	cpc R18,R22
	cpc R19,R23
	.jmpeq _RetFalse
	.jmp _RetTrue
	RegAdd #__lnotequ,_RetTrue
	RegAdd #__lnotequ,_RetFalse
	endif
	RegEnd

	ifref _LIntCmpPrep
	RegUse _LIntCmpPrep
_LIntCmpPrep:
	clr R24
	sbrc R19,7 
	inc R24
	sbrc R23,7
	inc R24
	ret
	endif
	RegEnd

	ifref __lless
	RegUse #__lless
__lless:
	.call _LIntCmpPrep
	RegAdd #__lless,_LIntCmpPrep
	sbrs R24,0
	rjmp _lless
	andi R19,080H
	.jmpeq _RetFalse
	.jmp _RetTrue
_lless:	
	cp R16,R20
	cpc R17,R21
	cpc R18,R22
	cpc R19,R23
	.jmpcc _RetFalse
	.jmp _RetTrue
	RegAdd #__lless,_RetTrue
	RegAdd #__lless,_RetFalse
	endif
	RegEnd

	ifref __llessorequ
	RegUse #__llessorequ
__llessorequ:
	.call _LIntCmpPrep
	RegAdd #__llessorequ,_LIntCmpPrep
	sbrs R24,0
	rjmp _LLessOrequ
	andi R19,080H
	.jmpeq _RetFalse
	.jmp _RetTrue
_LLessOrequ:
	cp R20,R16
	cpc R21,R17
	cpc R22,R18
	cpc R23,R19
	.jmpcc _RetTrue
	.jmp _RetFalse
	RegAdd #__llessorequ,_RetTrue
	RegAdd #__llessorequ,_RetFalse
	endif
	RegEnd

	ifref __lgreater
	RegUse #__lgreater
__lgreater:
	.call _LIntCmpPrep
	RegAdd #__lgreater,_LIntCmpPrep
	sbrs R24,0
	rjmp _lgreater
	andi R19,080H
	.jmpeq _RetTrue
	.jmp _RetFalse
_lgreater:
	cp R20,R16
	cpc R21,R17
	cpc R22,R18
	cpc R23,R19
	.jmpcs _RetTrue
	.jmp _RetFalse
	RegAdd #__lgreater,_RetTrue
	RegAdd #__lgreater,_RetFalse
	endif
	RegEnd

	ifref __lgreaterorequ
	RegUse #__lgreaterorequ
__lgreaterorequ:
	.call _LIntCmpPrep
	RegAdd #__lgreaterorequ,_LIntCmpPrep
	sbrs R24,0
	rjmp _lgreaterorequ
	andi R19,080H
	.jmpeq _RetTrue
	.jmp _RetFalse
_lgreaterorequ:
	cp R16,R20
	cpc R17,R21
	cpc R18,R22
	cpc R19,R23
	.jmpcs _RetFalse
	.jmp _RetTrue
	RegAdd #__lgreaterorequ,_RetTrue
	RegAdd #__lgreaterorequ,_RetFalse
	endif
	RegEnd

	ifref __pred8
	RegUse #__pred8
__pred8:
	tst R16
	brne _p8
	ret
_p8:	dec R16
	ret
	endif
	RegEnd

	ifref __succ8
	RegUse #__succ8
__succ8:
	cpi R16,0FFH
	brne _s8
	ret
_s8:	inc R16
	ret
	endif
	RegEnd

	ifref __pred16
	RegUse #__pred16
__pred16:
	tst R16
	brne _p16
	cpi R17,080H
	brne _p16
	ret
_p16:	.jmp __dec16
	RegAdd #__pred16,#__dec16
	endif
	RegEnd

	ifref __succ16
	RegUse #__succ16
__succ16:
	cpi R16,0FFH
	brne _s16
	cpi R17,7FH
	brne _s16
	ret
_s16:	.jmp __inc16
	RegAdd #__succ16,#__inc16
	endif
	RegEnd

	ifref __pred16w
	RegUse #__pred16w
__pred16w:
	or R16,R17
	brne _p16w
	ret
_p16w:	.jmp __dec16
	RegAdd #__pred16w,#__dec16
	endif
	RegEnd

	ifref __succ16
	RegUse #__succ16

__succ16w:
	cpi R16,0FFH
	brne _s16w
	cpi R17,0FFH
	brne _s16w
	ret
_s16w:	.jmp __inc16
	RegAdd #__succ16,#__inc16
	endif
	RegEnd

	ifref __pred32
	RegUse #__pred32
__pred32:
	or R16,R17
	brne _p32
	tst R18
	brne _p32
	cpi R19,080H
	brne _p32
	ret
_p32:	.jmp __dec32
	RegAdd #__pred32,#__dec32
	endif
	RegEnd

	ifref __succ32
	RegUse #__succ32
__succ32:
	cpi R16,0FFH
	brne _s32
	cpi R17,0FFH
	brne _s32
	cpi R18,0FFH
	brne _s32
	cpi R19,7FH
	brne _s32
	ret
_s32:	.jmp __inc32
	RegAdd #__succ32,#__inc32
	endif
	RegEnd

	ifref __Inc16
	RegUse #__Inc16
__Inc16:
	subi R16,0FFH
	sbci R17,0FFH
	ret
	endif
	RegEnd

	ifref __Dec16
	RegUse #__Dec16
__Dec16:
	subi R16,1
	sbci R17,0
	ret
	endif
	RegEnd

	ifref __Inc32
	RegUse #__Inc32
__Inc32:
	subi R16,0FFH
	sbci R17,0FFH
	sbci R18,0FFH
	sbci R19,0FFH
	ret
	endif
	RegEnd

	ifref __Dec32
	RegUse #__Dec32
__Dec32:
	subi R16,1
	sbci R17,0
	sbci R18,0
	sbci R19,0
	ret
	endif
	RegEnd

	ifref __Inc16Z
	RegUse #__Inc16Z
__Inc16Z:
	ld R16,Z+
	ld R17,Z+
	subi R16,0FFH
	sbci R17,0FFH
	st -Z,R17
	st -Z,R16
	ret
	endif
	RegEnd

	ifref __Dec16Z
	RegUse #__Dec16Z
__Dec16Z:
	ld R16,Z+
	ld R17,Z+
	subi R16,1
	sbci R17,0
	st -Z,R17
	st -Z,R16
	ret
	endif
	RegEnd

	ifref __Inc32Z
	RegUse #__Inc32Z
__Inc32Z:
	ld R16,Z+
	ld R17,Z+
	ld R18,Z+
	ld R19,Z+
	.call __Inc32
	st -Z,R19
	st -Z,R18
	st -Z,R17
	st -Z,R16
	ret
	endif
	RegEnd

	ifref __Dec32Z
	RegUse #__Dec32Z
__Dec32Z:
	ld R16,Z+
	ld R17,Z+
	ld R18,Z+
	ld R19,Z+
	.call __Dec32
	st -Z,R19
	st -Z,R18
	st -Z,R17
	st -Z,R16
	ret
	endif
	RegEnd

	ifref __Inc24Z
	RegUse #__Inc24Z
__Inc24Z:
	ld R16,Z+
	ld R17,Z+
	ld R18,Z
	clr R19
	.call __Inc32
	st Z,R18
	st -Z,R17
	st -Z,R16
	ret
	endif
	RegEnd

	ifref __Dec24Z
	RegUse #__Dec24Z
__Dec24Z:
	ld R16,Z+
	ld R17,Z+
	ld R18,Z
	clr R19
	.call __Dec32
	st Z,R18
	st -Z,R17
	st -Z,R16
	ret
	endif
	RegEnd

;Push a string referenced by Z
;Note: __Pushstring may not change R24,R25,R20,R21,R0,R1

	ifref __PushString
	RegUse #__PushString
__Pushstring:
	pop R14		;get return address
	pop R15
	ld R16,Z+	;length of the string
	mov R17,R16	;need length for later
	tst R16		;could be zero length string
	breq _pzl1	;>>yes it is
_pzl2:	ld R18,Z+	;get character
	push R18	;and store on stack
	dec R16
	brne _pzl2	;repeat for all chars
_pzl1:	push R17	;finally push the length byte
	.jmp _RetR14R15
	RegAdd #__PushString,_RetR14R15
	endif
	RegEnd

;Push a string in code memory referenced by Z
;(first 64K only)

	ifref __PushCString
	RegUse #__PushCString
__PushCString:
	pop R14		;get return address
	pop R15
	.lpm
	adiw R30,1
	mov R16,R0	;length of the string
	mov R17,R16	;need length for later
	tst R16		;could be zero length string
	breq _pczl1	;>>yes it is
_pczl2:	.lpm		;get character
	adiw R30,1
	push R0		;and store on stack
	dec R16
	brne _pczl2	;repeat for all chars
_pczl1:	push R17	;finally push the length byte
	.jmp _RetR14R15
	RegAdd #__PushCString,_RetR14R15
	endif
	RegEnd

;Pop a string on stack to address as second element on stack.
;R16 contains max length of target
;This routine uses __PopString. It is responsibility of caller
;to remove target address from stack

	ifref __PopStringWA
	RegUse #__PopStringWA
__PopstringWA:
	in R26,SPL	;current stack pointer
	iftrue LargeStack
	  in R27,SPH	;to X
	endif
	iffalse LargeStack
	  clr R27
	endif
	adiw R26,3	;point to length byte
	ld R17,X+	;get length of string on stack
	clr R18
	add R26,R17
	adc R27,R18
	ld R30,X+	;get to Z
	ld R31,X	;and fall into "popstring"
	RegAdd #__PopStringWA,#__PopString 	
	endif
	RegEnd

;Pop a string on stack to target at Z.
;R16 contains max length of target

	ifref __PopString,__PopStringWA
	RegUse #__PopString
__Popstring:
	pop R14		;get return address
	pop R15
	in R26,SPL	;current stack pointer
	iftrue LargeStack
	  in R27,SPH	;to X
	endif
	iffalse largeStack
	  clr R27
	endif
	adiw R26,1	;point to length byte
	ld R17,X+	;get length of string on stack
	cp R16,R17	;length of target will be either length
			;of string on stack or max length of target
	brsh _pcl3	;>>use actual string length
	st Z+,R16	;else use max length
	rjmp _pcl4
_pcl3:	st Z+,R17	;set length byte
_pcl4:	clr R18
	add R26,R17	;point one character past end of string on
	adc R27,R18	;stack so we can use -X
	sbiw R26,1
	mov R24,R26
	mov R25,R27	;keep that for new stack pointer
	adiw R26,1
	tst R17		;could be zero length string on stack
	breq _pcl1	;>>yes it is
	tst R16		;target could be zero length
	breq _pcl1	;>>yes is is...
_pcl2:	ld R19,-X	;get character
	st Z+,R19	;store at destination	
	dec R17
	breq _pcl1	;>>string transfered
	dec R16		;keep track of max string length
	brne _pcl2	;next
_pcl1:	.jmp _SPR14R15
	RegAdd #__PopString,_RetR14R15
	endif
	RegEnd

;Remove a string from stack
;May not change R16-R19

	ifref __DumpString,_DmpStr
	RegUse #__DumpString
__DumpString:
	pop R14		;get return address
	pop R15
_DmpStr:
	in R26,SPL	;current stack pointer
	iftrue LargeStack
	  in R27,SPH	;to X
	endif
	iffalse LargeStack
	  clr R27
	endif
	adiw R26,1	;point to length byte
	ld R20,X	;get length of string on stack
	clr R21
	add R26,R20	;point one character past end of string on
	adc R27,R21	;stack so.
	mov R24,R26
	mov R25,R27	;keep that for new stack pointer
	.jmp _SPR14R15
	RegAdd #__DumpString,_RetR14R15
	endif
	RegEnd

;Exit routines for library functions that manipulate the
;stack pointer.
;_RetR14R15 -> simple jump to address in R14R15
;_SPR14R15 -> Set stackpointer to value in R24/R25, disable 
;interrupts if they are enabled before changing the stackpointer.
;Exit using _RetR14R15
	
	ifref _SPR14R15True
	RegUse _SPR14R15True
_SPR14R15True:
	ldi R16,1
	tst R16
	rjmp _SPR14R15
	RegAdd _SPR14R15True,_SPR14R15
	endif
	RegEnd

	ifref _SPR14R15False
	RegUse _SPR14R15False
_SPR14R15False:
	clr R16
	RegAdd _SPR14R15False,_SPR14R15
	endif
	RegEnd

	ifref _SPR14R15,_SPR14R15False
	RegUse _SPR14R15 
_SPR14R15:
	iftrue LargeStack
	  in R20,SREG
          cli
	  out SPL,R24
	  out SPH,R25	;set new stackpointer
	  out SREG,R20
	  ;rjmp _RetR14R15
	endif
	iffalse LargeStack
	  out SPL,R24
	endif    
	RegAdd _SPR14R15,_RetR14R15
	endif
	RegEnd

	ifref _RetR14R15,_SPR14R15,_SPR14R15False,_SPR14R15True
	RegUse _RetR14R15
_RetR14R15:
	mov R31,R14	;branch to address in R14,R15
	mov R30,R15
	ijmp
	endif
	RegEnd

	ifref __TwoCharsToString
	RegUse #__TwoCharsToString
__TwoCharsToString:
	pop R14		;get return address
	pop R15
	push R16
	push R20
	ldi R16,2
	push R16
	.jmp _RetR14R15
	RegAdd #__TwoCharsToString,_RetR14R15
	endif
	RegEnd

	ifref __CharToString
	RegUse #__CharToString
__CharToString:
	pop R14		;get return address
	pop R15
	push R16
	ldi R16,1
	push R16
	.jmp _RetR14R15
	RegAdd #__CharToString,_RetR14R15
	endif
	RegEnd

	ifref __Shl8
	RegUse #__Shl8
__Shl8:
	tst R20
	brne _s8a
	ret
_s8a:	cpi R20,8
	brsh _s8b
_s8c:	lsl R16
	dec R20
	brne _s8c
	ret
_s8b:	clr R16
	ret
	endif
	RegEnd

	ifref __Shr8
	RegUse #__Shr8	
__Shr8:
	tst R20
	brne _sr8a
	ret
_sr8a:	cpi R20,8
	brsh _sr8b
_sr8c:	lsr R16
	dec R20
	brne _sr8c
	ret
_sr8b:	clr R16
	ret
	endif
	RegEnd

	ifref __Shl16
	RegUse #__Shl16
__Shl16:
	tst R20
	brne _s16a
	ret
_s16a:	cpi R20,16
	brsh _s16b
_s16c:	lsl R16
	rol R17
	dec R20
	brne _s16c
	ret
_s16b:	clr R16
	clr R17
	ret
	endif
	RegEnd

	ifref __Shr16
	RegUse #__Shr16
__Shr16:
	tst R20
	brne _sr16a
	ret
_sr16a:	cpi R20,16
	brsh _sr16b
_sr16c:	lsr R17
	ror R16
	dec R20
	brne _sr16c
	ret
_sr16b:	clr R16
	clr R17
	ret
	endif
	RegEnd

	ifref __Shl32
	RegUse #__Shl32
__Shl32:
	tst R20
	brne _s32a
	ret
_s32a:	cpi R20,32
	brsh _s32b
_s32c:	lsl R16
	rol R17
	rol R18
	rol R19
	dec R20
	brne _s32c
	ret
_s32b:	clr R16
	clr R17
	clr R18
	clr R19
	ret
	endif
	RegEnd

	ifref __Shr32
	RegUse #__Shr32
__Shr32:
	tst R20
	brne _sr32a
	ret
_sr32a:	cpi R20,32
	brsh _sr32b
_sr32c:	lsr R19
	ror R18
	ror R17
	ror R16
	dec R20
	brne _sr32c
	ret
_sr32b:	clr R16
	clr R17
	clr R18
	clr R19
	ret
	endif
	RegEnd

	ifref __Rl8
	RegUse #__Rl8
__Rl8:
	tst R20
	brne _rs8a
	ret
_rs8a:	ldi R21,7FH
_rs8c:	cp R21,R16
	rol R16
	dec R20
	brne _rs8c
	ret
	endif
	RegEnd

	ifref __Rr8
	RegUse #__Rr8	
__Rr8:
	tst R20
	brne _rsr8a
	ret
_rsr8a:	mov R21,R16
	lsr R21
	ror R16
	dec R20
	brne _rsr8a
	ret
	endif
	RegEnd

	ifref __Rl16
	RegUse #__Rl16
__Rl16:
	tst R20
	brne _rs16a
	ret
_rs16a:	ldi R21,7FH
_rs16c:	cp R21,R17
	rol R16
	rol R17
	dec R20
	brne _rs16c
	ret
	endif
	RegEnd

	ifref __Rr16
	RegUse #__Rr16
__Rr16:
	tst R20
	brne _rsr16a
	ret
_rsr16a:	
	mov R21,R16
	lsr R21
	ror R17
	ror R16
	dec R20
	brne _rsr16a
	ret
	endif
	RegEnd

	ifref __Rl32
	RegUse #__Rl32
__Rl32:
	tst R20
	brne _rs32a
	ret
_rs32a:	ldi R21,7FH
_rs32c:	cp R21,R19
	rol R16
	rol R17
	rol R18
	rol R19
	dec R20
	brne _rs32c
	ret
	endif
	RegEnd

	ifref __Rr32
	RegUse #__Rr32
__Rr32:
	tst R20
	brne _rsr32a
	ret
_rsr32a:	
	mov R21,R16
	lsr R21
	ror R19
	ror R18
	ror R17
	ror R16
	dec R20
	brne _rsr32a
	ret
	endif
	RegEnd

	ifref __Upcase
	RegUse #__UpCase
__Upcase:
	cpi R16,7BH
	brsh _upc1
	cpi R16,61H
	brlo _upc1
	subi R16,20H
_upc1:	ret
	endif
	RegEnd

	ifref __LoopTestUp
	RegUse #__LoopTestUp
__LoopTestUp:
	cp R26,R16	;cp limit,loopvar
	cpc R27,R17
	brlo _lpudone
	clz
	ret	
_lpudone:
	sez
	ret
	endif
	RegEnd

	ifref __LoopTestDown
	RegUse #__LoopTestDown
__LoopTestDown:
	cp R16,R26	;cp loopvar,limit
	cpc R17,R27
	brlo _lpddone
	clz
	ret	
_lpddone:
	sez
	ret
	endif
	RegEnd

	ifref __GetHeapPtr
	RegUse #__GetHeapPtr
__GetHeapPtr:
	lds R16,HeapPtr
	lds R17,HeapPtr+1
	ret
	endif
	RegEnd

	ifref __SetHeapPtr
	RegUse #__SetHeapPtr
__SetHeapPtr:
	sts HeapPtr,R16
	sts HeapPtr+1,R17
	ret
	endif
	RegEnd

;Malloc: Allocate WB bytes on heap, return pointer in WA

	ifref __Malloc
	RegUse #__Malloc
__Malloc:
	.ldwi Z,HeapPtr
	ld R18,Z+
	ld R19,Z
	mov R16,R18
	mov R17,R19
	add R18,R20
	add R19,R21
	st Z,R19
	st -Z,R18
	ret
	endif
	RegEnd

;Fill area in RAM (Z) with constant in R16. WB is count
 
	ifref __FillChar
	RegUse #__FillChar
__FillChar:
	mov R17,R20
	or R17,R21
	breq _filldone
_FillChar1:
	st Z+,R16
	dec R20
	brne _FillChar1
	subi R21,1
	brcc _FillChar1
_filldone:
	ret
	endif
	RegEnd

;__Switchbyte and __JpTable are the two routines used to evaluate
;case statements. __SwitchByte is used for complex, irregular 
;contitions while __Jptable is used if a linear table of 
;addresses can be used

	ifref __SwitchByte
	RegUse #__SwitchByte
__SwitchByte:
	.lpm
	mov R17,R0
	adiw R30,1	;number of case statements
	tst R0
_sw4:	breq _sw1	;>>no statements
	.lpm
	adiw R30,1
	mov R18,R0	;low
	.lpm
	adiw R30,1
	mov R19,R0	;high
	cp R16,R18
	brlo _sw2	;>no match
	cp R16,R19
	breq _sw3
	brsh _sw2	;>no match
_sw3:	.lpm
	adiw R30,1
	mov R18,R0	;execution address
	.lpm
	mov R31,R0
	mov R30,R18
	pop R18
	pop R18		;destroy return address
	ijmp
_sw2:	adiw R30,2	;try for next case statement
	dec R17
	rjmp _sw4
_sw1:	ret		;this will execute "else" statement if any
	endif
	RegEnd

	ifref __JpTable
	RegUse #__JpTable
__JpTable:
	.lpm
	mov R17,R0	;size of table
	adiw R30,1
	.lpm
	mov R18,R0	;offset of first value
	adiw R30,1
	sub R16,R18	;remove offset
	brcs _jt1
	cp R16,R17	;greater than number of entries ?
	brsh _jt1
	clr R17		;calc and get address
	add R16,R16	;of routine to execute
	add R30,R16
	adc R31,R17
	.lpm
	mov R18,R0
	adiw R30,1
	.lpm
	mov R30,R18
	mov R31,R0
	pop R18
	pop R18		;destroy return address
	ijmp
_jt1:	ret		;execute "else" if available
	endif
	RegEnd

;__Constset evaluates constant sets
;R16=item. Z=address of set table. Returns boolean in R16

	ifref __ConstSet
	RegUse #__ConstSet
__ConstSet:
	.lpm
	adiw R30,1
	mov R17,R0	;number of items
	tst R17
_cs4:	breq _cs1	;>>no items
	.lpm
	mov R18,R0	;low
	adiw R30,1
	.lpm
	mov R19,R0	;high
	adiw R30,1
	cp R16,R18
	brlo _cs2	;>no match
	cp R16,R19
	breq _cs3	;>match
	brsh _cs2	;>no match
_cs3:	ldi R16,1
	tst R16
	ret
_cs2:	dec R17		;next item
	rjmp _cs4
_cs1:	clr R16
	ret
	endif
	RegEnd

;Get2Str expects two strings on the stack.
;returns length and pointers to each string
;returns:
;X -> first char string 1 (+1)
;Z -> first char string 2 (+1)
;R17= length string 1
;R18= length string 2

	ifref _Get2Str
	RegUse _Get2Str
_Get2Str:
	in R30,SPL
	iftrue LargeStack
  	  in R31,SPH	;get stackpointer to Z
	endif
	iffalse LargeStack
	  clr R31
	endif  
	adiw R30,3	;point to length second string
	ld R18,Z	;get length second string
	clr R19
	add R30,R18
	adc R31,R19	;point Z to first character string 2
	adiw R30,1	;+1 so we can use -Z
	mov R26,R30	;X now points to length string 1
	mov R27,R31
	ld R17,Z	;length string 1
	add R26,R17
	adc R27,R19	;Point X to first char string 1
	mov R24,R26	;keep pointer to that in case
	mov R25,R27	;the strings are to be removed from stack
	adiw R26,1	;+1 so we can use -X
	ret
	endif
	RegEnd

;Add (concatenate) two strings on the stack. First string is first
;on the stack (higher address) followed by second string (lower
;address

	ifref __AddStrings
	RegUse #__AddStrings
__AddStrings:
	pop R14		;get return address
	pop R15
	.call _Get2Str	;get details on the two strings
	RegAdd #__AddStrings,_Get2Str
	mov R26,R30
	mov R27,R31	;Z points to length string 1
	adiw R26,1	;X points to last char string 1
_as2:	cpi R17,0FFH	;max string length reached ?
	breq _as1	;>>yes
	tst R18		;length string 2 (remaining)
	breq _as1
	ld R16,-Z
	st -X,R16
	inc R17		;size of new string
	dec R18		;characters moved from old string
	rjmp _as2
_as1:	st -X,R17	;set new length byte
	sbiw R26,1
	mov R24,R26	;new stackpointer
	mov R25,R27
	.jmp _SPR14R15
	RegAdd #__AddStrings,_SPR14R15
	endif
	RegEnd
	
;add a string on stack to a string in data memory. Z-> target, R16=maximum length of target.
;remove string on stack when done. Used with StrAdd procedure.
	
	ifref __AddStringToString
	RegUse #__AddStringToString
__AddStringToString:
	pop R14		;get return address
	pop R15
	in R26,SPL
	iftrue LargeStack
  	  in R27,SPH	;get stackpointer to Z
	endif
	iffalse LargeStack
	  clr R27
	endif  
	adiw R26,1	;point to length string on stack
	ld R18,X+	;get length
	cpi R18,0
	breq _ASS1	;>>source is empty, nothing to do
	clr R19
	add R26,R18
	adc R27,R19	;now X pointing to 1st char in source+1
	mov R21,R30
	mov R22,R31	;Need Z for later
	ld R17,Z+	;length of target string
	cp R17,R16
	brcc _ASS1	;>>target is at or above maximum length. Nothing to do.
	add R30,R17
	adc R31,R19	;point to end of string+1 in target
	
_ASS3:	ld R20,-X	;get char from source
	st Z+,R20	;and move to target
	inc R17		;inc length of target
	dec R18		;dec length of source
	breq _ASS2	;finished
	cp R17,R16	;max size of target reached ?
	brne _ASS3	;finished if yes
_ASS2:	
	mov R30,R21
	mov R31,R22	;point to length byte of target
	st Z,R17	;store new length of target
_ASS1:
	.jmp _DmpStr

	RegEnd
	endif

	ifref __AddCharToString
	RegUse #__AddCharToString
__AddCharToString:
	pop R14		;get return address
	pop R15
	in R30,SPL
	iftrue LargeStack
	  in R31,SPH	;get stackpointer to Z
	endif
	iffalse LargeStack
	  clr R31
	endif
	adiw R30,1	;point to length string
	ld R17,Z	;get length string
	cpi R17,0FFH
	breq _asc1	;>>string is full
	pop R18		;dump current length byte
	push R16	;added character onto stack
	inc R17		;inc length byte
	push R17	;length byte onto stack
_asc1:	.jmp _RetR14R15
	RegAdd #__AddCharToString,_RetR14R15
	endif
	RegEnd

;We have a character on the stack followed by a string
;The string is to be added to the character. This is simply
;done by incrementing the length of the string.
;However, if the string is allready full, the last character must
;be ditched.
 
	ifref __AddStrToCharOnStack
	RegUse #__AddStrToCharOnStack
__AddStrToCharOnStack:
	in R30,SPL
	iftrue LargeStack
	  in R31,SPH	;get stackpointer to Z
	endif
	iffalse LargeStack
	  clr R31
	endif
	adiw R30,3	;point to length string
	ld R17,Z	;get length string
	cpi R17,0FFH
	breq __scss1	;>string is full
	inc R17
	st Z,R17
	ret
__scss1:
	pop R14		;stack pointer footwork needed
	pop R15
	adiw R30,1
	st Z,R17	;store 0FFH at new length byte
	pop R18		;dump old lengthbyte
	.jmp _RetR14R15
	RegAdd #__AddStrToCharOnStack,_RetR14R15
	endif
	RegEnd

;AddStringToChar:
;We have a string on the stack. This needs to be added to a char
;in R16 in such a fashion that the new char is the first char in
;the string, ditching the last char if the string is full.

	ifref __AddStringToChar
	RegUse #__AddStringToChar
__AddStringToChar:
	pop R14		;stack pointer footwork needed
	pop R15
	in R30,SPL
	iftrue LargeStack
	  in R31,SPH	;get stackpointer to Z
	endif
	iffalse LargeStack
	  clr R31
	endif
	adiw R30,1	;point to length string
	ld R17,Z	;get length string
	mov R19,R17	;keep a counter
	clr R18
	add R30,R17
	adc R31,R18
	adiw R30,1	;point Z one char past first char of str
_assc1:	ld R18,-Z	;get char from string
	st Z,R16	;insert char
	mov R16,R18	;prepare for next char
	subi R19,1	;dec count
	brcc _assc1	;>finished
	cpi R17,0FFH	;full string ?
	breq _assc2	;>yes
	inc R17
	push R17	;new length byte
	.jmp _RetR14R15
_assc2:	st Z,R17	;restore length byte
	.jmp _RetR14R15
	RegAdd #__AddStringToChar,_RetR14R15
	endif
	RegEnd

	ifref __Sequ
	RegUse #__Sequ
__Sequ:	pop R14		;get return address
	pop R15
	.call _Get2Str
	.call _CpStr
	RegAdd #__Sequ,_Get2Str
	RegAdd #__Sequ,_CpStr
	.jmpeq _SPR14R15True
	.jmp _SPR14R15False
	RegAdd #__Sequ,_SPR14R15True
	RegAdd #__Sequ,_SPR14R15False
	endif
	RegEnd

	ifref __Snotequ
	RegUse #__Snotequ
__Snotequ:	
	pop R14		;get return address
	pop R15
	.call _Get2Str
	.call _CpStr
	RegAdd #__Snotequ,_Get2Str
	RegAdd #__Snotequ,_CpStr
	.jmpeq _SPR14R15False
	.jmp _SPR14R15True
	RegAdd #__Snotequ,_SPR14R15True
	RegAdd #__Snotequ,_SPR14R15False
	endif
	RegEnd

	ifref __Sless
	RegUse #__SLess
__Sless:	
	pop R14		;get return address
	pop R15
	.call _Get2Str
	.call _CpStr
	RegAdd #__Sless,_Get2Str
	RegAdd #__Sless,_CpStr
	.jmpcs _SPR14R15True
	.jmp _SPR14R15False
	RegAdd #__Sless,_SPR14R15True
	RegAdd #__Sless,_SPR14R15False
	endif
	RegEnd

	ifref __Sgreater
	RegUse #__SGreater
__Sgreater:	
	pop R14		;get return address
	pop R15
	.call _Get2Str
	.call _CpStr
	RegAdd #__Sgreater,_Get2Str
	RegAdd #__Sgreater,_CpStr
	.jmpcs _SPR14R15False
	.jmpeq _SPR14R15False
	.jmp _SPR14R15True
	RegAdd #__Sgreater,_SPR14R15True
	RegAdd #__Sgreater,_SPR14R15False
	endif
	RegEnd

	ifref __Slessorequ
	RegUse #__Slessorequ
__Slessorequ:	
	pop R14		;get return address
	pop R15
	.call _Get2Str
	.call _CpStr
	RegAdd #__Slessorequ,_Get2Str
	RegAdd #__Slessorequ,_CpStr
	.jmpcs _SPR14R15True
	.jmpeq _SPR14R15True
	.jmp _SPR14R15False
	RegAdd #__Slessorequ,_SPR14R15True
	RegAdd #__Slessorequ,_SPR14R15False
	endif
	RegEnd

	ifref __Sgreaterorequ
	RegUse #__Sgreaterorequ
__Sgreaterorequ:	
	pop R14		;get return address
	pop R15
	.call _Get2Str
	.call _CpStr
	RegAdd #__Sgreaterorequ,_Get2Str
	RegAdd #__Sgreaterorequ,_CpStr
	.jmpcs _SPR14R15False
	.jmp _SPR14R15True
	RegAdd #__Sgreaterorequ,_SPR14R15True
	RegAdd #__Sgreaterorequ,_SPR14R15False
	endif
	RegEnd

	ifref _CpStr
	RegUse _CPStr
_CpStr:	mov R24,R26	;keep for new stackpointer
	mov R25,R27
	sbiw R24,1
_scp3:	tst R17		;length string1
	breq _scp1	;string 1 done
	tst R18
	breq _scp5	;string 2 done, 1 not done. 1 is greater
	dec R17
	dec R18
	ld R19,-X	;get char string 1
	ld R20,-Z	;get char string 2
	cp R19,R20
	breq _scp3	;same so far, next char
	brlo _scp4	;>string 1 is less than string 2
_scp5:	clc		;string 1 > string 2
	clz
	ret
_scp4:	sec		;string 1<string 2
	ret
_scp1:	tst R18		;string 1 done
	brne _scp4	;string 2 not done. String 2 > string 1
	sez
	clc
	ret		;else strings are equal
	endif
	RegEnd

	ifref __LintToHexStr
	RegUse #__LintToHexStr
__LintToHexStr:
	pop R14
	pop R15
	ldi R20,8
	mov R21,R19
	swap R21
	rcall _MakeDigit
	RegAdd #__LintToHexStr,_MakeDigit
	push R21
	mov R21,R19
	rcall _MakeDigit
	push R21
	mov R21,R18
	swap R21
	rcall _MakeDigit
	push R21
	mov R21,R18
	rcall _MakeDigit
	push R21
	rjmp _Whs
	RegAdd #__LintToHexStr,#__WordToHexStr	
	endif
	RegEnd

	ifref __WordToHexStr,__LintToHexStr
	RegUse #__WordToHexStr
__WordToHexStr:
	pop R14
	pop R15
	ldi R20,4
_Whs:	mov R21,R17
	swap R21
	rcall _MakeDigit
	RegAdd #__WordToHexStr,_MakeDigit
	push R21
	mov R21,R17
	rcall _MakeDigit
	push R21
	rjmp _Bhs
	RegAdd #__WordToHexStr,#__ByteToHexStr
	endif
	RegEnd

	ifref __ByteToHexStr,__WordToHexStr,__LintToHexStr
	RegUse #__ByteToHexStr
__ByteToHexStr:
	pop R14
	pop R15
	ldi R20,2
_Bhs:	mov R21,R16
	swap R21
	rcall _MakeDigit
	RegAdd #__ByteToHexStr,_MakeDigit
	push R21
	mov R21,R16
	rcall _MakeDigit
	push R21
	push R20
	.jmp _RetR14R15
	RegAdd #__ByteToHexStr,_RetR14R15
	endif
	RegEnd

	ifref _MakeDigit
	RegUse _MakeDigit
_MakeDigit:
	andi R21,0FH
	subi R21,208
	cpi R21,$3A
	brsh _Pd1
	ret
_Pd1:	subi R21,249
	ret
	endif
	RegEnd

	ifref __ByteToStr
	RegUse #__ByteToStr
__ByteToStr:
	pop R14
	pop R15	
	clr R17
	clr R18
	clr R19	
	.jmp _ToStrMain
	RegAdd #__ByteToStr,_ToStrMain
	endif
	RegEnd

	ifref __IntToStr
	RegUse #__IntToStr
__IntToStr:
	pop R14
	pop R15	
	clr R18
	clr R19	
	sbrs R17,7
	rjmp _IntPos
	RegAdd #__IntToStr,#__NotInt
	.call __NotInt
	clr R18		;will be destroyed by __NotInt
	ldi R20,2dh
	push R20
	ldi R26,1
	rjmp _StM1 
_IntPos:	
	.jmp _ToStrMain
	RegAdd #__IntToStr,_ToStrMain
	endif
	RegEnd

	ifref __WordToStr
	RegUse #__WordToStr
__WordToStr:
	pop R14
	pop R15	
	clr R18
	clr R19	
	.jmp _ToStrMain
	RegAdd #__WordToStr,_ToStrMain
	endif
	RegEnd

	ifref __LintToStr
	RegUse #__LintToStr
__LintToStr:
	pop R14
	pop R15	
	sbrs R19,7
	rjmp _LintPos
	.call __NotLint
	RegAdd #__LintToStr,#__NotLint
	ldi R20,2dh
	push R20
	ldi R26,1
	rjmp _StM1 
_LintPos:	
	RegAdd #__LintToStr,_ToStrMain
	endif
	RegEnd

	ifref __ByteToStr,__WordToStr,__IntToStr,__LintToStr
	RegUse _ToStrMain
_ToStrMain:
	clr R26
_StM1:	.ldwi Z,_DecTab
	ldi R25,9
	clt
_str3:	clr R24
	.lpm
	mov R20,R0
	adiw R30,1
	.lpm
	mov R21,R0
	adiw R30,1
	.lpm
	mov R22,R0
	adiw R30,1
	.lpm
	mov R23,R0
	adiw R30,1
_str2:	.call __Sub32
	RegAdd _ToStrMain,#__Sub32
	brlo _str1
	inc R24
	rjmp _str2
_str1:	.call __Add32
	RegAdd _ToStrMain,#__Add32
	brts _str5
	tst R24
	breq _str4
_str5:	set
	subi R24,208
	push R24
	inc R26
_str4:	dec R25
	brne _str3
	subi R16,208
	push R16
	inc R26
	push R26
	.jmp _RetR14R15
	RegAdd _ToStrMain,_RetR14R15
	endif

;__StrToInt. Converts a string on the stack to a longint if
;possible. String may be prefixed with "-" or "+".
 
	ifref __StrToInt
	RegUse #__StrToInt
__StrToInt:
	pop R14
	pop R15
	clr R16
	clr R17
	clr R18
	clr R19
	in R26,SPL
	iftrue LargeStack
	  in R27,SPH	;get stackpointer to Z
	endif
	iffalse LargeStack
	  clr R27
	endif  
	adiw R26,1	;point to length string
	ld R30,X
	tst R30
	breq _sti4	;>empty string
	clr R25
	add R26,R30
	adc R27,R25
	clt
	ld R25,X
	cpi R25,2dh
	brne _sti1
	dec R30
	set
	rjmp _sti2
_sti1:	cpi R25,2bh
	brne _sti3
	dec R30
_sti2:	sbiw R26,1
_sti3:	ld R25,X
	subi R25,$30
	brcs _sti5	;>error
	cpi R25,10
	brsh _sti5	;>error
	ldi R20,10
	clr R21
	clr R22
	clr R23
	.call __mult32
	RegAdd #__StrToInt,#__Mult32
	add R16,R25
	clr R25
	adc R17,R25
	adc R18,R25
	adc R19,R25
	sbiw R26,1
	dec R30
	brne _sti3
	brtc _sti4
	.call __NotLint
	RegAdd #__StrToInt,#__NotLint
_sti4:	clt			;t clear = no error
	.jmp _DmpStr
	RegAdd #__StrToInt,#__DumpString
_sti5:	set			;t set = error
	.jmp _DmpStr
	endif
	RegEnd

;Copy() -> R20 pos, R16 count, Z-> string

	ifref __CopyString
	RegUse #__CopyString
__CopyString:
	pop R14
	pop R15
	clr R18		;transfer count
	ld R17,Z	;length source
	tst R20	
	breq _cst1	;invalid pos
	tst R16
	breq _cst1	;return zero length string
	add R30,R20
	adc R31,R18	;point to first char to transfer
_cst2:	cp R17,R20
	brlo _cst1
	ld R19,Z+
	push R19
	inc R20
	inc R18
	dec R16
	brne _cst2
_cst1:	push R18
	.jmp _RetR14R15
	RegAdd #__CopyString,_RetR14R15
	endif	
	RegEnd

;CopyCString -> R20 pos, R16 count, Z-> string in code memory

	ifref __CopyCString
	RegUse #__CopyCString
__CopyCString:
	pop R14
	pop R15
	clr R18		;transfer count
	.lpm
	mov R17,R0	;length source
	tst R20	
	breq _ccst1	;invalid pos
	tst R16
	breq _ccst1	;return zero length string
	add R30,R20
	adc R31,R18	;point to first char to transfer
_ccst2:	cp R17,R20
	brlo _ccst1
	.lpm
	push R0
	adiw R30,1
	inc R20
	inc R18
	dec R16
	brne _ccst2
_ccst1:	push R18
	.jmp _RetR14R15
	RegAdd #__CopyCString,_RetR14R15
	endif	
	RegEnd

;String delete procedure. Delete R16 bytes at index R20.
;String is pointed to by Z

	ifref __Delete
	RegUse #__Delete
__Delete:
	mov R24,R30	;keep a copy of Z
	mov R25,R31
	ld R17,Z	;get length of string
	breq _delx	;>>nothing to delete
	tst R16
	breq _delx	;>>same
	cp R17,R20
	brcs _delx	;Index is past end of string
	clr R21
	add R30,R20	;point Z to index position of string
	adc R31,R21	;=first character to delete
	mov R18,R20	;get index position
	add R18,R16	;plus number of bytes to delete
	brcs _dela	;no move required
	cp R17,R18
	brcs _dela	;string to short - no move
	mov R26,R30
	mov R27,R31	;prepare pointer to position after delete
	add R26,R16
	adc R27,R21	;point to first char to move
	mov R18,R17	;current length of string
	sub R18,R20	;minus insert position
	sub R18,R16	;minus chars to delete is number of chars to move 
	sub R17,R16	;new length
	inc R18
_delb:	ld R19,X+
	st Z+,R19	;move one char
	dec R18		;and chars to delete
	brne _delb
	mov R20,R17
	inc R20
_dela:	mov R30,R24
	mov R31,R25
	dec R20
	st Z,R20	;set new string length
_delx:	ret
	endif
	RegEnd

;Insert a string (located on the stack) into a string in data RAM
;at position R16. R20 is the maximum length of the target string.
;Z points to the target string

	ifref __Insert
	RegUse #__Insert
__Insert:
	pop R14		;get return address
	pop R15
	mov R24,R30	;keep a copy of Z
	mov R25,R31
	in R26,SPL	;current stack pointer +1
	iftrue LargeStack
	  in R27,SPH	;to X
	endif
	iffalse LargeStack
	  clr R27
	endif
	adiw R26,1
	tst R16
	breq _insx	;invalid insert position
	ld R22,X	;length of string on stack
	tst R22
	breq _insx	;>>nothing to insert
	ld R17,Z	;get current length of target string
	clr R21
	add R30,R16	;point Z to insert position
	adc R31,R21
	mov R2,R30
	mov R3,R31	;keep a pointer to the insertion point
	cp R17,R16	;insert or append ?
	brcc _insa	;>>insert
	;sbiw R26,1	;else is append
	mov R23,R17	;current length of string
	mov R16,R17
	inc R16		;insert position
	rjmp _ins4	;place string
_insa:	mov R0,R17	;length of target
	sub R0,R16	;sub insert position
	inc R0		;R0 is number of chars to push onto stack
	pop R23		;length of string on stack
_ins1:	ld R1,Z+
	push R1
	inc R23		;length of string on stack
	cpi R23,255
	breq _ins5	;string on stack is max length
	dec R0
	brne _ins1
_ins5:	in R26,SPL	;current stack pointer +1
	iftrue LargeStack
	  in R27,SPH	;to X
	endif
	iffalse LargeStack
	  clr R27
	endif
	push R23	;length byte for string on stack
_ins4:	mov R30,R2
	mov R31,R3	;restore insertion point
	add R26,R23	
	adc R27,R21
	adiw R26,1	;point X one char past end of string on stack
_ins2:	ld R0,-X
	st Z+,R0
	inc R16		;length of target string
	cp R20,R16	;max length reached ?
	brcs _ins3	;>>yes
	dec R23
	brne _ins2
_ins3:	mov R30,R24
	mov R31,R25
	dec R16
	st Z,R16	;set new length byte
_insx:	.jmp _DmpStr	;get rid of string on stack and exit
	RegAdd #__Insert,#__DumpString	
	endif
	RegEnd

;PosN. Find occurence of string on stack in string pointed to
;by Z. R16 contains start position in target string to search from
;T flag set means target string is in code memory else data mem.

	ifref __POSN
	RegUse #__Posn
__POSN:
	pop R14		;get return address
	pop R15
	tst R16
	breq _psnx	;>>invalid position
	brts _psnt1
	ld R17,Z	;length of target string
	rjmp _psnt2
_psnt1: .lpm
	mov R17,R0
_psnt2:	tst R17
	breq _psnx	;>>is zero, nothing to search
	cp R17,R16	
	brcs _psnx	;>>search past end of string
	clr R18
	add R30,R16	;prepare first search position
	adc R31,R18
	in R26,SPL	;current stack pointer +1
	iftrue LargeStack
	  in R27,SPH	;to X
	endif
	iffalse LargeStack
	  clr R27
	endif  
	adiw R26,1
	ld R19,X+	;length of search string
	tst R19
	breq _psnx	;search string is zero length
	add R26,R19
	adc R27,R18	;point to end of search string+1
	mov R24,R26
	mov R25,R27	;keep that pointer
	mov R22,R30	
	mov R23,R31	;and that one
	mov R20,R16	;search position
	mov R21,R19	;source length

_psn3:	mov R16,R20
	mov R19,R21
	mov R26,R24	;restore pointer to start of search string
	mov R27,R25	
	mov R30,R22
	mov R31,R23	;pointer to search current position

_psn2:	ld R1,-X	;get character from search string
	brts _psnt3
	ld R0,Z+	;and from target
	rjmp _psnt4
_psnt3: .lpm
	adiw R30,1
_psnt4:
	cp R0,R1	;same ?
	brne _psn1	;>>no
	cp R17,R16
	brcs _psnx	;end of target string. No find
	inc R16		
	dec R19		;prepare for next test
	brne _psn2

	sbiw R24,1	;correct for new stack pointer
	mov R16,R20	;search result
	.jmp _SPR14R15	;done
	RegAdd #__Posn,_SPR14R15

_psnx:	clr R16
	.jmp _DmpStr
	RegAdd #__Posn,#__DumpString

_psn1:	inc R20		;next search position
	ldi R18,1
	add R22,R18
	clr R18
	adc R23,R18	;bump pointer
	rjmp _psn3
 	endif
	RegEnd

	ifref __ExtendSint
	RegUse #__ExtendSint
__ExtendSint:
	ldi R17,0FFH
	sbrs R16,7
	ldi R17,0
	ret

	endif
	RegEnd

	ifref __ExtendSintToLint
	RegUse #__ExtendSintToLint
__ExtendSintToLint:
	ldi R17,0FFH
	sbrs R16,7
	ldi R17,0
	mov R18,R17
	mov R19,R17
	ret

	endif
	RegEnd

	ifref __Extendint
	RegUse #__Extendint
__Extendint:
	ldi R18,0FFH
	sbrs R17,7
	ldi R18,0
	mov R19,R18
	ret

	endif
	RegEnd

	ifref __LDTLA
	RegUse #__LDTLA

__LDTLA:
        ld R16,Z+
        ld R17,Z+
        ld R18,Z
        clr R19
	ret

	endif
	RegEnd

	ifref __LDTLB
	RegUse #__LDTLB

__LDTLB:
        ld R20,Z+
        ld R21,Z+
        ld R22,Z
        clr R23
	ret

	endif
	RegEnd

	ifref __LDLLA
	RegUse #__LDLLA

__LDLLA:
        ld R16,Z+
        ld R17,Z+
        ld R18,Z+
        ld R19,Z
	ret

	endif
	RegEnd

	ifref __STLLA
	RegUse #__STLLA

__STLLA:
        st Z+,R16
        st Z+,R17
        st Z+,R18
        st Z,R19
	ret

	endif
	RegEnd

	ifref __STTLA
	RegUse #__STTLA

__STTLA:
        st Z+,R16
        st Z+,R17
        st Z,R18
	ret

	endif
	RegEnd

	ifref __LDLLB
	RegUse #__LDLLB
	
__LDLLB:
        ld R20,Z+
        ld R21,Z+
        ld R22,Z+
        ld R23,Z
	ret

	endif
	RegEnd

	ifref __LDLCLA
	RegUse #__LDLCLA

__LDLCLA:
	.lpm
	mov R16,R0
	adiw R30,1
	.lpm
	mov R17,R0
	adiw R30,1
	.lpm
	mov R18,R0
	adiw R30,1
	.lpm
	mov R19,R0
	adiw R30,1
	ret

	endif
	RegEnd

	ifref __LDTCLA
	RegUse #__LDTCLA

__LDTCLA:
	.lpm
	mov R16,R0
	adiw R30,1
	.lpm
	mov R17,R0
	adiw R30,1
	.lpm
	mov R18,R0
	clr R19
	ret

	endif
	RegEnd

	ifref __LDLCLB
	RegUse #__LDLCLB

__LDLCLB:
	.lpm
	mov R20,R0
	adiw R30,1
	.lpm
	mov R21,R0
	adiw R30,1
	.lpm
	mov R22,R0
	adiw R30,1
	.lpm
	mov R23,R0
	adiw R30,1
	ret

	endif
	RegEnd

	ifref __LDTCLB
	RegUse #__LDTCLB

__LDTCLB:
	.lpm
	mov R20,R0
	adiw R30,1
	.lpm
	mov R21,R0
	adiw R30,1
	.lpm
	mov R22,R0
	clr R23
	ret

	endif
	RegEnd

	ifref __MOVLBLA
	RegUse #__MOVLBLA

__MOVLBLA:
	mov R20,R16
	mov R21,R17
	mov R22,R18
	mov R23,R19
	ret

	endif
	RegEnd

	ifref __MoveStringCtoD
	RegUse #__MoveStringCtoD

__MoveStringCtoD:
	tst R16
	breq _MSCD1
	.lpm
	mov R18,R0	;length of source
	adiw R30,1
	cp R18,R16	;length of source greater or equal to length of target ?
	brcs _MSCD4	
        st X+,R16	;target to maximum length
	rjmp _MSCD2
_MSCD4: st X+,R18
	mov R16,R18
_MSCD2:	.lpm
	st X+,R0
	adiw R30,1
	dec R16
	brne _MSCD2
_MSCD1:	ret

	endif
	RegEnd

	ifref _BitHelper
	RegUse _BitHelper
	
_BitHelper:
	ld R16,Z+
	cpi R20,8
	brcs _Bs1
	ld R16,Z+
	cpi R20,16
	brcs _Bs1
	ld R16,Z+
	cpi R20,24
	brcs _Bs1
	ld R16,Z+ 	;note must be Z+ for togglebit
_Bs1:	andi R20,7
	mov R26,R30
	mov R27,R31
	.ldwi Z,_mask
	add R30,R20
	ldi R20,0
	adc R31,R20
	.lpm
	ret
		
	endif
	RegEnd
	
	ifref __BitIsSet
	RegUse #__BitIsSet

__BitIsSet:
	.call _BitHelper
	and R16,R0
	RegAdd #__BitIsSet,_BitHelper
	.jmp __MakeBool
	
	endif
	RegEnd

	ifref __BitIsReset
	RegUse #__BitIsReset

__BitIsReset:
	.call _BitHelper
	and R16,R0
	RegAdd #__BitIsReset,_BitHelper
	.jmp __NotBool
		
	endif
	RegEnd

	ifref __ToggleBit
	RegUse #__ToggleBit

__ToggleBit:
        .call _BitHelper
        eor R16,R0
        st -X,R16
	RegAdd #__ToggleBit,_BitHelper
        ret

	endif
	RegEnd

;Bitmask returns a 32 bit mask. On entry R20=bit number to set. Result is in LB.

	ifref __BitMask
	RegUse #__BitMask

__BitMask:
	.ldwi Z,20
        .call _BitHelper
	ldi R20,0
	ldi R21,0
	ldi R22,0
	ldi R23,0
        st -X,R0
	RegAdd #__BitMask,_BitHelper
        ret

	endif
	RegEnd

	data

	ifref HeapPtr
HeapPtr: ds 2
	endif
	ifref _ADRCache_
_ADRCache_: 
        ds 2
	endif

	end


