please dont rip this site
;PIC Microcontoller Basic Math Method
;Mainly Maths Macros for PIC18F458 (16bit & some 32bit)
;By Roger Froud

;Overview...
;This approach to handling 16bit maths is borrowed from Microchips
;Embedded Control Handbook where it is flirted with but not generalised
;or published in any useful form.
;The aim is to provide the user with 16bit pseudo registers in RAM
;that behave very much like an extended native 16bit instuction set.
;You can create your own 16 bit variables by reserving 2 consecutive bytes
;and then freely mix them with the 16bit macros.
;This allows you to have as many 16bit files as you need while allowing
;easy manipulation of their values using the macros.

;The only downside of this approach is that it exposes a nasty bug in MPLAB
;that has been made worse post V7.11. Up to V7.11 the assembler often shows
;errors listed against the wrong line numbers. It does single step correctly
;through the macros though. By V7.31, the assembler not only gives the wrong
;line numbers but MPLAB no longer shows the correct lines while stepping
;through the macros. The code still works fine but you don't see the
;lines that are being executed. Microchip have acknowledged this problem
;so perhaps they will at last get both these problems sorted out.

;These macros have been tested and published here in good faith but
;no liability can be accepted for any inaccuracies.
;Please feel free to correct, improve or add to these for the greater good.

;Caution:-

;Do not assume that the W register or status registers are preserved
;unless specifically mentioned.

;Don't forget that these routines use memory pairs which can be
;corrupted if you use these macros in interrupt routines as well
;as in the main body of the code. You are responsible for storing
;their contents. Beware High & Low level interrupts that may need to
;store their own copies. The code routines are shown below are complete
;to show what resources would be used if you used all of the macros.
;Typically you will only have definitions for ACCaLO & ACCaHI
;If you forget to allocate memory for them, the assembler will complain
;so you could just use the macros and let the assembler tell you
;what definitions you need to include.

;The pseudo registers are normally stored in Access RAM so that they
;are readily available without Bank switching.
;Beware changing macro names as some are used in other macros

;16 Bit Pseudo register definitions. LS & MS explicitly defined
;so they can be accessed by macros
;ACCaLO		RES 1	;LS of accumulator 'a'
;ACCaHI		RES 1	;MS
;ACCbLO		RES 1	;LS of accumulator 'b'
;ACCbHI		RES 1	;MS
;ACCcLO		RES 1	;LS of accumulator 'c'
;ACCcHI		RES 1	;MS
;ACCdLO		RES 1	;LS of accumulator 'd'
;ACCdHI		RES 1	;MS
;M_TEMP		RES 1	;Temp counter for 16bit/16bit maths routines

;The following are only required for 16bit x 16bit multiplication
;RES0		RES 1	;LS Destination for multiply result
;RES1		RES 1
;RES2		RES 1
;RES3		RES 1	;MS


;Beware! 2 sets of temp stores required as low priority interrupt can be interrupted by a high priority one!
;These can be defined in other banks as their data is stored using movff instructions that include the full address
;W_TEMP_L	RES 1	; variable used for context saving durng interrupts
;W_TEMP_H	RES 1	; variable used for context saving durng interrupts
;NB:- STATUS_TEMP etc in another bank to save acces bank space

;M_TEMP_L	RES 1	;Counter for some maths routines (check if you are using it by leaving it out)

;M_TEMP_H	RES 1	;Counter for some maths routines (check if you are using it by leaving it out)

;ACCaLO_TEMP_L	RES 1	; for context saving LS of accumulator 'A'
;ACCaHI_TEMP_L	RES 1	; for context saving MS
;ACCbLO_TEMP_L	RES 1	; for context saving LS of accumulator 'b'
;ACCbHI_TEMP_L	RES 1	; for context saving MS
;ACCcLO_TEMP_L	RES 1	; for context saving LS of accumulator 'c'
;ACCcHI_TEMP_L	RES 1	; for context saving MS
;ACCdLO_TEMP_L	RES 1	; for context saving LS of accumulator 'd'
;ACCdHI_TEMP_L	RES 1	; for context saving MS
;The following are only required for 16bit x 16bit multiplication
;RES0_L		RES 1	;LS Destination for multiply result
;RES1_L		RES 1
;RES2_L		RES 1
;RES3_L		RES 1	;MS

;ACCaLO_TEMP_H	RES 1	; for context saving LS of accumulator 'A'
;ACCaHI_TEMP_H	RES 1	; for context saving MS
;ACCbLO_TEMP_H	RES 1	; for context saving LS of accumulator 'b'
;ACCbHI_TEMP_H	RES 1	; for context saving MS
;ACCcLO_TEMP_H	RES 1	; for context saving LS of accumulator 'b'
;ACCcHI_TEMP_H	RES 1	; for context saving MS
;ACCdLO_TEMP_H	RES 1	; for context saving LS of accumulator 'b'
;ACCdHI_TEMP_H	RES 1	; for context saving MS
;The following are only required for 16bit x 16bit multiplication
;RES0_H		RES 1	;LS Destination for multiply result
;RES1_H		RES 1
;RES2_H		RES 1
;RES3_H		RES 1	;MS

;Use same style definition for High priority interrupt but change the _L to _H for variables


;LOWINT		MOVWF W_TEMP_L			;Copy W register else it will be corrupted
;		MOVFF STATUS,STATUS_TEMP_L 	;save status
;		MOVFF BSR,BSR_TEMP_L		;Save BSR register
;						;Leave out any or all of the following if macros
;						;are not used in the interrupt routine. Just check the
;						;macros to see what they use.
;		MOVFF ACCaLO,ACCaLO_TEMP_L	;Save my pseudo registers for 16 bit macros
;		MOVFF ACCaHI,ACCaHI_TEMP_L	;Save my pseudo registers for 16 bit macros
;		MOVFF ACCbLO,ACCbLO_TEMP_L	;Save my pseudo registers for 16 bit macros
;		MOVFF ACCbHI,ACCbHI_TEMP_L	;Save my pseudo registers for 16 bit macros
;		MOVFF ACCcLO,ACCaLO_TEMP_L	;Save my pseudo registers for 16 bit macros
;		MOVFF ACCcHI,ACCaHI_TEMP_L	;Save my pseudo registers for 16 bit macros
;		MOVFF ACCdLO,ACCbLO_TEMP_L	;Save my pseudo registers for 16 bit macros
;		MOVFF ACCdHI,ACCbHI_TEMP_L	;Save my pseudo registers for 16 bit macros
;		MOVFF M_TEMP,M_TEMP_L		;Save counter
;		MOVFF RES0,RES0_L		;Save 32bit result of 16 x 16 bit multiply
;		MOVFF RES1,RES1_L
;		MOVFF RES2,RES2_L
;		MOVFF RES3,RES3_L
;
;		body of low priority interrupt
;
;		MOVFF RES3_L,RES3
;		MOVFF RES2_L,RES2
;		MOVFF RES1_L,RES1
;		MOVFF RES0_L,RES0
;		MOVFF M_TEMP_L,M_TEMP		;Restore counter
;		MOVFF ACCdHI_TEMP_L,ACCbHI	;Restore my pseudo registers for 16 bit macros
;		MOVFF ACCdLO_TEMP_L,ACCbLO
;		MOVFF ACCcHI_TEMP_L,ACCbHI	;Restore my pseudo registers for 16 bit macros
;		MOVFF ACCcLO_TEMP_L,ACCbLO
;		MOVFF ACCbHI_TEMP_L,ACCbHI	;Restore my pseudo registers for 16 bit macros
;		MOVFF ACCbLO_TEMP_L,ACCbLO
;		MOVFF ACCaHI_TEMP_L,ACCaHI	;Restore my pseudo registers for 16 bit macros
;		MOVFF ACCaLO_TEMP_L,ACCaLO
;		MOVFF BSR_TEMP_L,BSR	;Restore BSR register
;		MOVF W_TEMP_L,W	;Restore W reg.
;		MOVFF STATUS_TEMP_L,STATUS ;Restore status reg.
;		RETFIE			;back to interrupted program


;16 bit pseudo-register macro definitions

;Test accumulator and set Z flag if zero & c flag if MS bit set
;Corrupts W reg.
TSTA	MACRO
	TSTF16 ACCaLO
	ENDM

;Test accumulator and set Z flag if zero & c flag if MS bit set
;Corrupts W reg.
TSTB	MACRO
	TSTF16 ACCbLO
	ENDM

;Test 16 bit file and set Z flag if zero
;Corrupts W reg.
TSTF16	MACRO ADDRESS
	BCF STATUS,C
	BTFSC ADDRESS+1,7	;Set carry if MS bit=1
	BSF STATUS,C		;None of the following changes Carry
	MOVF ADDRESS,W	;get LS
	IORWF ADDRESS+1,W	;Z flag set if both zero
	ENDM

TSTW	MACRO
	IORLW 0
	ENDM

;Make accumulator +ve if -ve (assuming signed numbers of course)
ABSA	MACRO
	 ABSF16 ACCaLO
	ENDM

;Make 16bit file +ve if -ve (assuming signed numbers of course)
ABSF16	MACRO ADDRESS
	LOCAL PLUSNOW
	BTFSS ADDRESS+1,7	;MS byte
	GOTO PLUSNOW
	NEGF16 ADDRESS
PLUSNOW
	ENDM

;Moves 16bit file in LS/MS format to Accumulator A
MOVFA	MACRO   ADDRESS
	MOVF16 ADDRESS,ACCaLO
	ENDM

;Moves Accumulator A to Accumulator B
MOVAB	MACRO
	MOVF16 ACCaLO,ACCbLO
	ENDM

;Moves 16bit file in LS/MS format from Accumulator A
MOVAF	MACRO   ADDRESS
	MOVF16 ACCaLO,ADDRESS
	ENDM

;moves 16bit file in LS/MS format to Accumulator B
MOVFB	MACRO   ADDRESS
	MOVF16 ADDRESS,ACCbLO	;Move LS
	ENDM

;moves 16bit file in LS/MS format from Accumulator B
MOVBF	MACRO   ADDRESS
	MOVF16 ACCbLO,ADDRESS
	ENDM

;moves 16bit file in LS/MS format to Accumulator C
MOVFC	MACRO   ADDRESS
	MOVF16 ADDRESS,ACCcLO
	ENDM

;moves 16bit file in LS/MS format from Accumulator C
MOVCF	MACRO   ADDRESS
	MOVF16 ACCcLO,ADDRESS
	ENDM

;moves 16bit file in LS/MS format to Accumulator D
MOVFD	MACRO   ADDRESS
	MOVF16 ADDRESS,ACCdLO
	ENDM

;moves 16bit file in LS/MS format from Accumulator D
MOVDF	MACRO   ADDRESS
	MOVF16 ACCdLO,ADDRESS
	ENDM

;Moves 16 bit literal to accumulator A
MOVLAA	MACRO	VALUE
	MOVLW LOW VALUE
	MOVWF ACCaLO
	MOVLW HIGH VALUE
	MOVWF ACCaHI
	ENDM

;Moves 16 bit literal to accumulator B

MOVLAB	MACRO	VALUE
	MOVLW LOW VALUE
	MOVWF ACCbLO
	MOVLW HIGH VALUE
	MOVWF ACCbHI
	ENDM

;Moves 16 bit literal to accumulator C
MOVLAC	MACRO	VALUE
	MOVLW LOW VALUE
	MOVWF ACCcLO
	MOVLW HIGH VALUE
	MOVWF ACCcHI
	ENDM

;Moves 16 bit literal to accumulator D
MOVLAD	MACRO	VALUE
	MOVLW LOW VALUE
	MOVWF ACCdLO
	MOVLW HIGH VALUE
	MOVWF ACCdHI
	ENDM

;Moves 8 bit literal to file (corrupts W)
MOVLF	MACRO VALUE,ADDRESS
	MOVLW VALUE
	MOVWF ADDRESS
	ENDM

;Make file absolute
ABSF	MACRO ADDRESS
	BTFSC ADDRESS,7	;-ve?
	NEGF ADDRESS		;Make -ve into +ve
	ENDM

;Moves 16 bit literal to file
;NB:-Done MS first to writes to 16bit timers work correctly.
;You can't use this for reading 16 bit timers, you must reverse the order!
MOVLF16	MACRO VALUE,ADDRESS
	MOVLW HIGH VALUE
	MOVWF ADDRESS+1	;MS
	MOVLW LOW VALUE
	MOVWF ADDRESS	;LS
	ENDM

;Moves 16 bit file to file. Uses MOVFF so it is page independant
;NB:-Done MS first to writes to 16bit timers work correctly.
;You can't use this for reading 16 bit timers, you must reverse the order!
MOVF16	MACRO ADDRESS,ADDRESS1
	MOVFF ADDRESS+1,ADDRESS1+1 ;MS
	MOVFF ADDRESS,ADDRESS1	;LS
	ENDM

;Add 16 bit file to accumulator A
ADDFA	MACRO	ADDRESS  ;a+f->a
	MOVF ADDRESS,W
	ADDWF ACCaLO,F
	MOVF ADDRESS+1,W
	ADDWFC ACCaHI,F
	ENDM

;Add accumulator A to 16 bit file
ADDAF	MACRO	ADDRESS  ;f+a->f
	MOVF ACCaLO,W	
	ADDWF ADDRESS,F		;Save LS back to file
	MOVF ACCaHI,W
	ADDWFC ADDRESS+1,F
	ENDM

;Add 16 bit file to accumulator B
ADDFB	MACRO	ADDRESS  ;b+f->b
	MOVF ADDRESS,W
	ADDWF ACCbLO,F
	MOVF ADDRESS+1,W
	ADDWFC ACCbHI,F
	ENDM

;Add literal to accumulator 'A'
ADDLA	MACRO VALUE  ;a+l->a
	MOVLW LOW VALUE
	ADDWF ACCaLO,F
	MOVLW HIGH VALUE
	ADDWFC ACCaHI,F
	ENDM

;Add literal to file'
ADDLF16	MACRO VALUE,ADDRESS  ;f+l->f
	MOVLW LOW VALUE
	ADDWF ADDRESS,F
	MOVLW HIGH VALUE
	ADDWFC ADDRESS+1,F
	ENDM

;Subtract 16 bit file from 'A' result in 'A'
SUBFA	MACRO ADDRESS	;See AN526
	MOVF ADDRESS,W
	SUBWF ACCaLO,F
	MOVF ADDRESS+1,W
	SUBWFB ACCaHI,F	
	ENDM

;Subtract 16 bit file ADDRESS from 16 bit file ADDRESS1. result in ADDRESS1
SUBF16	MACRO ADDRESS,ADDRESS1	;See AN526
	MOVF ADDRESS,W
	SUBWF ADDRESS1,F
	MOVF ADDRESS+1,W
	SUBWFB ADDRESS1+1,F	
	ENDM

;Subtract 16 bit literal from 'A' result in 'A'
SUBLA	MACRO VALUE	;a-l->a
	MOVLW LOW VALUE
	SUBWF ACCaLO,F
	MOVLW HIGH VALUE
	SUBWFB ACCaHI,F	
	ENDM

;Subtract 16 bit file from 'B' result in 'B'
SUBFB	MACRO ADDRESS	;See AN526
	MOVF ADDRESS,W
	SUBWF ACCbLO,F
	MOVF ADDRESS+1,W
	SUBWFB ACCbHI,F	
	ENDM

;Subtract 16 bit literal from 'B' result in 'B'
SUBLB	MACRO VALUE	;b-l->b
	MOVLW LOW VALUE
	SUBWF ACCbLO,F
	MOVLW HIGH VALUE
	SUBWFB ACCbHI,F	
	ENDM

;Subtract 16 bit literal from 'f' result in 'f'
SUBLF16	MACRO VALUE,ADDRESS	;f-l->f
	MOVLW LOW VALUE
	SUBWF ADDRESS,F
	MOVLW HIGH VALUE
	SUBWFB ADDRESS+1,F	
	ENDM

;Unsigned Compare of 16 bit file with 'A' (A-f)
;Set carry & zero flags to reflect unsigned 16bit result
;so we can use BLT macros etc the same as for signed compare
CMPFAU	MACRO ADDRESS	;See signed compare below
	LOCAL NOCHK
	LOCAL LSCHK
	MOVF ADDRESS+1,W ;ms
	SUBWF ACCaHI,W	;check if File > A
	BZ LSCHK	;continue if File=A
	GOTO NOCHK	;ms result tells all
LSCHK	MOVF ADDRESS,W	;ms same so LS tells all
	SUBWF ACCaLO,W	;carry set if A > File
NOCHK	
	ENDM

;Unsigned Compare of 16 bit file with Literal (L-f)
;Set carry & zero flags to reflect unsigned 16bit result
;so we can use BLT macros etc the same as for signed compare
CMPFLU	MACRO VALUE,ADDRESS	;See signed compare below
	LOCAL NOCHK
	LOCAL LSCHK
	MOVF ADDRESS+1,W ;ms
	SUBLW HIGH VALUE	;check if File > L
	BZ LSCHK	;continue if File=L
	GOTO NOCHK	;ms result tells all
LSCHK	MOVF ADDRESS,W	;ms same so LS tells all
	SUBLW LOW VALUE	;carry set if L > File
NOCHK	
	ENDM

;Compare signed 16 bit file with 'A' (A-f)
;Using biased (inverted sign) method to set carry & zero flags
;to reflect signed 16bit result

CMPFA	MACRO ADDRESS	;See AN526
	LOCAL NOCHK
	LOCAL LSCHK

;first invert sign bit of accumulator
	BTG ACCaHI,7	;inverts bit
;Now do unsigned compare on biased values
	MOVF ADDRESS+1,W ;ms
	XORLW H'80'	;invert sign of file
	SUBWF ACCaHI,W	;check if file > a (both numbers are biased)
	BZ LSCHK	;continue if file=a
	GOTO NOCHK	;ms result tells all
LSCHK	MOVF ADDRESS,W	;ms same so LS tells all
	SUBWF ACCaLO,W	;carry set if a > file
NOCHK	
;Z and C bits now set but we must repair accumulator sign without
;corrupting the Z flag
	BTG ACCaHI,7	;inverts bit
	ENDM

;Compare signed 16 bit accumulator with literal (A-L)
;Using biased (inverted sign) method to set carry & zero flags
;to reflect signed 16bit result

CMPLA	MACRO VALUE
	LOCAL NOCHK
	LOCAL LSCHK
;first invert sign bit of accumulator
	BTG ACCaHI,7	;inverts bit
;Now do unsigned compare on biased values
	MOVLW HIGH VALUE ;ms
	XORLW H'80'	;invert sign of value
	SUBWF ACCaHI,W	;check if value > a (both numbers are biased)
	BZ LSCHK	;continue if file=a
	GOTO NOCHK	;ms result tells all
LSCHK	MOVLW LOW VALUE	;ms same so LS tells all
	SUBWF ACCaLO,W	;carry set if a > value
NOCHK	
;Z and C bits now set but we must repair accumulator sign without corrupting the Z flag
	BTG ACCaHI,7	;inverts bit
	ENDM

;Compare unsigned 16 bit accumulator with literal (A-L)
;carry & zero flags reflect unsigned 16bit result
CMPLAU	MACRO VALUE
	LOCAL NOCHK
	LOCAL LSCHK
	MOVLW HIGH VALUE ;ms
	SUBWF ACCaHI,W	;check if value > a (both numbers are biased)
	BZ LSCHK	;continue if file=a
	GOTO NOCHK	;ms result tells all
LSCHK	MOVLW LOW VALUE	;ms same so LS tells all
	SUBWF ACCaLO,W	;carry set if a > value
NOCHK	
	ENDM

;Compare signed 16 bit file with 16 bit file (f2-f1)
;Using biased (inverted sign) method to set carry & zero flags
;to reflect signed 16bit result
CMPFF16	MACRO ADDRESS1,ADDRESS2	;See AN526
	LOCAL NOCHK
	LOCAL LSCHK
;first invert sign bit of accumulator
	BTG ADDRESS2+1,7	;inverts bit
;Now do unsigned compare on biased values
	MOVF ADDRESS1+1,W ;ms
	XORLW H'80'		;invert sign of file
	SUBWF ADDRESS2+1,W	;check if file > file (both numbers are biased)
	BZ LSCHK		;continue if file=file
	GOTO NOCHK		;ms result tells all
LSCHK	MOVF ADDRESS1,W		;ms same so LS tells all
	SUBWF ADDRESS2,W	;carry set if a > file
NOCHK	
;Z and C bits now set but we must repair accumulator sign without
;corrupting the Z flag
	BTG ADDRESS2+1,7	;inverts bit
	ENDM

;Unsigned compare 16 bit file with 16 bit file (f2-f1)
;carry & zero flags reflect unsigned 16bit result
CMPFFU16	MACRO ADDRESS1,ADDRESS2	;See AN526
	LOCAL NOCHK
	LOCAL LSCHK
	MOVF ADDRESS1+1,W ;ms
	SUBWF ADDRESS2+1,W	;check if file > file
	BZ LSCHK		;continue if file=file
	GOTO NOCHK		;ms result tells all
LSCHK	MOVF ADDRESS1,W		;ms same so LS tells all
	SUBWF ADDRESS2,W	;carry set if a > file
NOCHK	
	ENDM

;Compare unsigned 16 bit file with literal (F-L)
;carry & zero flags reflect unsigned 16bit result
CMPLFU16	MACRO VALUE,ADDRESS
	LOCAL NOCHK
	LOCAL LSCHK
	MOVLW HIGH VALUE ;ms
	SUBWF ADDRESS+1,W	;check if file > l
	BZ LSCHK		;continue if file=l
	GOTO NOCHK		;ms result tells all
LSCHK	MOVLW LOW VALUE		;ms same so LS tells all
	SUBWF ADDRESS,W		;carry set if l > value
NOCHK	
	ENDM

;Compare signed 16 bit file with literal (F-L)
;Using biased (inverted sign) method to set carry & zero flags
;to reflect signed 16bit result
CMPLF16	MACRO VALUE,ADDRESS
	LOCAL NOCHK
	LOCAL LSCHK
;first invert sign bit of accumulator
	BTG ACCaHI,7	;inverts bit
;Now do unsigned compare on biased values
	MOVLW HIGH VALUE ;ms
	XORLW H'80'	;invert sign of file
	SUBWF ADDRESS+1,W	;check if file > a (both numbers are biased)
	BZ LSCHK	;continue if file=a
	GOTO NOCHK	;ms result tells all
LSCHK	MOVLW LOW VALUE	;ms same so LS tells all
	SUBWF ADDRESS,W	;carry set if a > value
NOCHK	
;Z and C bits now set but we must repair file sign without corrupting the Z flag
	BTG ADDRESS+1,7	;inverts bit
	ENDM

;Branch if >

BGT	MACRO ADDRESS
	LOCAL ONE
	BTFSC STATUS,Z
	GOTO ONE	;Equal so not >
	BTFSC STATUS,C	;Take branch if Carry clear
	GOTO ADDRESS
ONE
	ENDM

;Branch if <

BLT	MACRO ADDRESS
	LOCAL ONE
	BTFSC STATUS,Z
	GOTO ONE	;Equal so not <
	BTFSS STATUS,C	;Take branch if carry set
	GOTO ADDRESS
ONE
	ENDM

;Branch if >=

BGE	MACRO ADDRESS
	LOCAL ONE
	BTFSC STATUS,C	;Take branch if carry clear
	GOTO ONE
	BTFSC STATUS,Z	;Take branch if not zero
ONE	GOTO ADDRESS
	ENDM

;Branch if <=

BLE	MACRO ADDRESS
	LOCAL ONE
	BTFSS STATUS,C	;Take branch if carry set
	GOTO ONE
	BTFSC STATUS,Z	;Take branch if not zero
ONE	GOTO ADDRESS
	ENDM

;Negate accumulator A
NEGA	MACRO	;2's comp.
	NEGF16 ACCaLO
	ENDM

;Negate accumulator B
NEGB	MACRO	;2's comp.
	NEGF16 ACCbLO
	ENDM

;Negate 16 bit file
NEGF16	MACRO	ADDRESS	;See AN526 P5-14 2's comp.
	COMF ADDRESS,F	;LS
	INCF ADDRESS,F
	BTFSC STATUS,Z
	DECF ADDRESS+1,F ;MS
	COMF ADDRESS+1,F
	ENDM

;Clip 'A' to signed 15bits so that 2 of these added together
;can never exceed 16bits signed. The result can then be clipped itself

CLIPA15	MACRO
	LOCAL CLIPPLU
	LOCAL SATDAT
	BTFSS ACCaHI,7		;Test if -ve (ms bit set)
	GOTO CLIPPLU
;This way if -ve
	BTFSC ACCaHI,6
	GOTO SATDAT
	MOVLAA H'C000'
	GOTO SATDAT
;-----------------------
;This way to clip plus
CLIPPLU	BTFSS ACCaHI,6
	GOTO SATDAT
	MOVLAA H'3FFF'
SATDAT		
	ENDM

;Clip 'A' to signed 14bits to limit swings in control system
CLIPA14	MACRO
	LOCAL CLIPPLU
	LOCAL SATDAT
	LOCAL NEGCLIP
	LOCAL POSCLIP
	BTFSS ACCaHI,7		;Test if -ve (ms bit set)
	GOTO CLIPPLU
;This way if -ve
	BTFSS ACCaHI,6
	GOTO NEGCLIP
	BTFSC ACCaHI,5
	GOTO SATDAT
NEGCLIP	MOVLAA H'E000'
	GOTO SATDAT
;-----------------------
;This way to clip plus
CLIPPLU	BTFSC ACCaHI,6
	GOTO POSCLIP
	BTFSS ACCaHI,5
	GOTO SATDAT
POSCLIP	MOVLAA H'1FFF'
SATDAT		
	ENDM


;Clip A to the value in F ie if A>F then A=F
CLIPAF	MACRO ADDRESS
	LOCAL NOCLIP
	NOP
	CMPFA ADDRESS	;Is it > clip value?
	BLT NOCLIP
	NOP
	MOVFA ADDRESS	;Use clip value
NOCLIP
	ENDM

;Clip A to the Literal value ie if A>L then A=L
CLIPAL	MACRO VALUE
	LOCAL NOCLIP
	NOP
	CMPLA VALUE	;Is it > clip value?
	BLT NOCLIP
	NOP
	MOVLAA VALUE	;Use clip value
NOCLIP
	ENDM

;Clip F to A
CLIPFA MACRO ADDRESS
	LOCAL NOCLIP
	CMPFA ADDRESS	;Is it < clip value?
	BGE NOCLIP
	MOVAF ADDRESS	;Use clip value
NOCLIP
	ENDM

;Increment 16 bit file and test if zero
INCF16	MACRO	ADDRESS
	INCF ADDRESS,F
	BTFSC STATUS,Z
	INCF ADDRESS+1,F
	TSTF16 ADDRESS
	ENDM

;Increment accumulator 'A' and test if zero
INCA	MACRO
	INCF16 ACCaLO
	ENDM

;Increment accumulator 'B' and test if zero
INCB	MACRO
	INCF16 ACCbLO
	ENDM

;Decrement accumulator 'A' and test if zero
DECA	MACRO
	DECF16 ACCaLO
	ENDM

;Decrement accumulator 'B' and test if zero
DECB	MACRO
	DECF16 ACCbLO
	ENDM

;The following are Used for timers in interrupt routine which
;are then polled outside

;Decrement 16 bit file and test if zero
DECF16	MACRO	ADDRESS
	LOCAL NBORROW
	TSTFSZ ADDRESS	;LS
	GOTO NBORROW
	DECF ADDRESS+1,F ;MS
NBORROW	DECF ADDRESS,F	;LS
	TSTF16 ADDRESS
	ENDM

;Decrement A to zero if not already zero
DECATZ	MACRO
	DECFTZ16 ACCaLO
	ENDM

;Decrement B to zero if not already zero
DECBTZ	MACRO
	DECFTZ16 ACCbLO
	ENDM

;Decrement 8 bit file if not already zero
;Sets Z bit to suit
DECFTZ	MACRO ADDRESS
	TSTFSZ ADDRESS	;Aready zero
	DECF ADDRESS,F
	TSTF ADDRESS
	ENDM

;Decrement 16 bit file if not already zero
DECFTZ16 MACRO	ADDRESS
	LOCAL ZEXIT
	TSTF16 ADDRESS
	BTFSC STATUS,Z
	GOTO ZEXIT
;This way if not zero so decrement it
	DECF16 ADDRESS
ZEXIT
	ENDM

;XOR 16 bit file with accumulator 'A', result in 'A'
XORFA	MACRO	ADDRESS  
	MOVF ADDRESS,W
	XORWF ACCaLO,F
	MOVF ADDRESS+1,W
	XORWF ACCaHI,F
	TSTA		;use previous macro
	ENDM

;XOR literal with accumulator 'A', result in 'A'
XORLA	MACRO	VALUE
	MOVLW LOW VALUE
	XORWF ACCaLO,F
	MOVLW HIGH VALUE
	XORWF ACCaHI,F
	TSTA		;use previous macro
	ENDM

;clears the 16bit file in LS/MS format
CLRF16	MACRO   ADDRESS
	CLRF ADDRESS	;Clear LS
	CLRF ADDRESS+1	;MS
	ENDM

;clears the accumulator 'A'
CLRA	MACRO
	CLRF16 ACCaLO	;Clear LS/MS
	ENDM

;Sets the accumulator 'A'
SETA	MACRO
	SETF16 ACCaLO	;Clear LS/MS
	ENDM

;Set 16bit file
SETF16	MACRO	ADDRESS
	SETF ADDRESS
	SETF ADDRESS+1
	ENDM

;clears the accumulator 'B'
CLRB	MACRO
	CLRF16 ACCbLO	;Clear LS/MS
	ENDM

;Sets the accumulator 'B'
SETB	MACRO
	SETF16 ACCaLO	;Clear LS/MS
	ENDM

;clears the accumulator 'C'
CLRAC	MACRO
	CLRF16 ACCcLO	;Clear LS/MS
	ENDM

;clears the accumulator 'B'
CLRD	MACRO
	CLRF16 ACCdLO	;Clear LS/MS
	ENDM

;clears the 24bit file in LS/MS format
CLRF24	MACRO   ADDRESS
	CLRF ADDRESS	;Clear LS
	CLRF ADDRESS+1
	CLRF ADDRESS+2	;MS
	ENDM

;Shift 16 bit file left one bit
LSLF16	MACRO	ADDRESS
	CLRC			;so it won't corrupt LS bit
	RLCF ADDRESS,F		;LS setting carry as appropriate
	RLCF ADDRESS+1,F	;MS with any carry from LS byte
	ENDM

;Shift 16bit accumulator left 1 bit
LSLA	MACRO		;See LSLF16 for comments
	LSLF16 ACCaLO
	ENDM

;Shift 16bit accumulator left 1 bit
LSLB	MACRO		;See LSLF16 for comments
	LSLF16 ACCbLO
	ENDM

;Shift 16 bit file right one bit
LSRF16	MACRO	ADDRESS
	CLRC			;so it won't corrupt MS bit
	RRCF ADDRESS+1,F	;MS setting carry as appropriate
	RRCF ADDRESS,F		;LS with any carry from MS byte
	ENDM

;Logical Shift 16bit accumulator right 1 bit
LSRA	MACRO		;See LSLF16 for comments
	LSRF16 ACCaLO
	ENDM

;Logical Shift 16bit accumulator right 1 bit
LSRB	MACRO		;See LSLF16 for comments
	LSRF16 ACCbLO
	ENDM

;Logical Shift 32bits right where 'B' holds MS and 'A' holds LS part
LSRBA	MACRO
	RLCF ACCbHI,W	;Get Sign bit into carry without corrupting file
	RRCF ACCbHI,F
	RRCF ACCbLO,F
	RRCF ACCaHI,F
	RRCF ACCaLO,F
	ENDM

;Logical shift right 32bit number by 8 bits through 'B' and 'A'
;where 'B' holds MS and 'A' holds LS
LSRBA8	MACRO
	MOVFF ACCaHI,ACCaLO
	MOVFF ACCbLO,ACCaHI
	MOVFF ACCbHI,ACCbLO
	CLRF ACCbHI
	ENDM

;Arithmetic shift right 32bit number by 8 bits through 'B' and 'A'
;where 'B' holds MS and 'A' holds LS
ASRBA8	MACRO
	MOVFF ACCaHI,ACCaLO
	MOVFF ACCbLO,ACCaHI
	MOVFF ACCbHI,ACCbLO
	CLRF ACCbHI
	BTFSC ADDRESS+1,7 	;If original MS bit is set
	SETF ACCbHI		;Then new MS is all 1's
	ENDM

;Increment 32bits in 'B' MS and 'A' LS
INCBA	MACRO
	INCF ACCaLO,F
	BTFSC STATUS,Z
	INCF ACCaHI,F
	BTFSC STATUS,Z
	INCF ACCbLO,F
	BTFSC STATUS,Z
	INCF ACCbHI,F
	ENDM

;Arithmetic Shift 16 bit file right one bit
;Same as logical shift except MS bit is copied into new MS bit
ASRF16	MACRO	ADDRESS
	CLRC
	BTFSC ADDRESS+1,7 	;If MS bit is set
	SETC			;Then set carry ready for copying
	RRCF ADDRESS+1,F	;MS setting carry as appropriate
	RRCF ADDRESS,F		;LS with any carry from MS byte
	ENDM

;Arithmetic Shift 16bit accumulator right 1 bit
;Same as logical shift except MS bit is copied into new MS bit
ASRA	MACRO
	ASRF16 ACCaLO
	ENDM

;Add source file to destination file (corrupts W reg)
ADDFF	MACRO ADDRSRC,ADDRDEST
	MOVF ADDRSRC,W
	ADDWF ADDRDEST,F
	ENDM

;Add source file to destination file with carry (corrupts W reg)
ADDFFC	MACRO ADDRSRC,ADDRDEST
	MOVF ADDRSRC,W
	ADDWFC ADDRDEST,F
	ENDM

;Add literal to designated file (corrupts W reg)
ADDLF	MACRO ADDRESS,VALUE
	MOVLW VALUE
	ADDWF ADDRESS,F
	ENDM

;Add literal with carry to designated file (corrupts W reg)
ADDLFC	MACRO ADDRESS,VALUE
	MOVLW VALUE
	ADDWFC ADDRESS,F
	ENDM

;Double precision unsigned 16x16 bit multiplication of accumulator x file
;with LS result in accumulator 'a'
;and MS result in accumulator 'b'
;NB:-Uses RES0:RES3 so don't use it in interrupt routine as well as
;in main loop without saving RES0:RES3 context

MULFA	MACRO	ADDRESS
	MULFA16 ADDRESS			;Unsigned multiply
	MOVF32 RES0,ACCaLO		;Get result in accumulator pair 'ab'
	ENDM

;Double precision Signed 16x16 bit multiplication of accumulator x file
;with LS result in accumulator 'a'
;and MS result in accumulator 'b'
;NB:-Uses RES0:RES3 so don't use it in interrupt routine as well as
;in main loop without saving RES0:RES3 context
MULFAS	MACRO	ADDRESS
	MULFA16S ADDRESS		;Signed multiply
	MOVF32 RES0,ACCaLO		;Get result in accumulator pair 'ab'
	ENDM

;Unsigned multiply accumulator 'a' by file, answer in RES0:RES3
;Copied from PIC18FXX8 manual P76
;NB:-Uses RES0:RES3 so don't use it in interrupt routine as well as
;in main loop without saving RES0:RES3 context
MULFA16	MACRO ADDRESS
		MOVF ACCaLO,W
		MULWF ADDRESS
		MOVFF PRODH,RES1
		MOVFF PRODL,RES0

		MOVF ACCaHI,W
		MULWF ADDRESS+1
		MOVFF PRODH,RES3
		MOVFF PRODL,RES2

		MOVF ACCaLO,W
		MULWF ADDRESS+1
		MOVF PRODL,W
		ADDWF RES1
		MOVF PRODH,W
		ADDWFC RES2
		CLRF WREG
		ADDWFC RES3

		MOVF ACCaHI,W
		MULWF ADDRESS
		MOVF PRODL,W
		ADDWF RES1
		MOVF PRODH,W
		ADDWFC RES2
		CLRF WREG
		ADDWFC RES3
		ENDM

;Signed multiply accumulator 'a' by file, answer in RES0:RES3
MULFA16S	MACRO ADDRESS
		LOCAL SIGN_ARG1
		LOCAL CONT_CODE
		MULFA16 ADDRESS		;Unsigned multiply
;Now handle signs
		BTFSS ADDRESS+1,7
		BRA SIGN_ARG1
		MOVF ACCaLO,W
		SUBWF RES2
		MOVF ACCaHI,W
		SUBWFB RES3
SIGN_ARG1
		BTFSS ACCaHI,7
		BRA CONT_CODE
		MOVF ADDRESS,W
		SUBWF RES2
		MOVF ADDRESS+1,W
		SUBWFB RES3
CONT_CODE
		ENDM

;Double Precision unsigned 16/16 division ACCb/ACCa->ACCb with remainder in ACCc
;Source modified from AN526 P5-36
;Beware, make sure that ACCb > ACCa
;Beware,don't use Div routine in interrupt routines as it uses M_TEMP unless you save it
;Uses register 'd'
DIVBA	MACRO
	LOCAL DLOOP
	LOCAL NOCHK
	LOCAL NOGO
;First move 16 bit register b to register d
;	INTERRUPTS_OFF		;Make sure it doesn't change between reading MS & LS halves!
	MOVFF ACCbHI,ACCdHI	;MS
	MOVFF ACCbLO,ACCdLO	;LS
;	INTERRUPTS_ON
;And clear register b
	CLRF ACCbHI
	CLRF ACCbLO
;Also clear register c
	CLRF ACCcHI
	CLRF ACCcLO
;And setup loop counter
	MOVLW .16
	MOVWF M_TEMP
DLOOP	BCF STATUS,C
	RLCF ACCdLO,F
	RLCF ACCdHI,F
	RLCF ACCcLO,F
	RLCF ACCcHI,F
	MOVF ACCaHI,W
	SUBWF ACCcHI,W	;Check if a>c
	BTFSS STATUS,Z	;carry set if c>a
	GOTO NOCHK
	MOVF ACCaLO,W
	SUBWF ACCcLO,W	;If msb equal then check lsb
NOCHK	BTFSS STATUS,C
	GOTO  NOGO
	MOVF ACCaLO,W	;C-A into C
	SUBWF ACCcLO,F
	BTFSS STATUS,C
	DECF ACCcHI,F
	MOVF ACCaHI,W
	SUBWF ACCcHI,F
	BSF STATUS,C	;Shift a 1 into b (result)
NOGO	RLCF ACCbLO,F
	RLCF ACCbHI,F
	DECFSZ M_TEMP,F	;Loop until all bits checked
	GOTO DLOOP

	ENDM

;32/16 bit division…
;(ACCa,ACCb)/ACCc-> (ACCa,ACCb) rem ACCd
;Move ab pair into ef pair & clear ab pair & d
;Setup loop counter to 32
;Shift d & ef left one bit (ef ms into d ls)
;Check if c>d
;If yes then d-c->d & shift a 1 into lsb of ab (result)
;Else shift a 0 into lsb of ab (result)
;Repeat for all bits

;Double Precision unsigned 32/16 division (ACCa,ACCb)/ACCc->(ACCa,ACCb) with remainder in (ACCe,ACCf)
;Source modified from above DIVBA
;Beware, make sure that ACCb > ACCa
;Beware,don't use Div routine in interrupt routines as it uses M_TEMP unless you save it

DIVABC	MACRO
	LOCAL DLOOP
	LOCAL NOCHK
	LOCAL NOGO
;First move 32 bit register ab to register gh
;	INTERRUPTS_OFF		;Make sure it doesn't change between reading each byte!
	MOVF16 ACCaLO,ACCgLO	;Done as 2 lots so explicit use of Acc h makes sure it exists!
	MOVF16 ACCbLO,ACChLO
;	INTERRUPTS_ON

	CLRAB		;Clear 32bit register pair ab that will hold the answer
	CLREF		;Also clear 32 bit register pair EF
;And setup loop counter
	MOVLW d'32'
	MOVWF M_TEMP
DLOOP
	LSLGH		;Logical shift left GH pair
	RLFEFC		;into EF with carry
	NOP
	NOP
;if EF > C
	CLRC		;Following MOVF does not affect C flag
	MOVF ACCfHI,W	;F register contains overflow from E register so will always be bigger than C if non zero
	BNZ SUBIT
	MOVF ACCfLO,W
	BNZ SUBIT
	MOVF ACCcHI,W
	SUBWF ACCeHI,W
	BTFSS STATUS,Z
	GOTO NOCHK
	MOVF ACCcLO,W
	SUBWF ACCeLO,W
NOCHK	BTFSS STATUS,C
	GOTO  NOGO	;Shift a 0 into b (result)
SUBIT
	MOVF ACCcLO,W	;EF-C into EF
	SUBWF ACCeLO,F
	MOVF ACCcHI,W
	SUBWFB ACCeHI,F
	CLRF WREG
	SUBWFB ACCfLO,F
	CLRF WREG
	SUBWFB ACCfHI,F
	BSF STATUS,C	;Shift a 1 into b (result)
NOGO
	RLCF ACCaLO,F	;Shift 1 or 0 into result
	RLCF ACCaHI,F
	RLCF ACCbLO,F
	RLCF ACCbHI,F
	DECFSZ M_TEMP,F	;Loop until all bits checked
	GOTO DLOOP

	ENDM

;Start of 32Bit maths definitions
;When using register pairs eg A & B then A is LS and B is MS

MOVF32		MACRO	ADDRESS,ADDRESS1
	MOVFF ADDRESS,ADDRESS1
	MOVFF ADDRESS+1,ADDRESS1+1
	MOVFF ADDRESS+2,ADDRESS1+2
	MOVFF ADDRESS+3,ADDRESS1+3
	ENDM

;Move 16bit file into 32bit file & sign extend
MOVF16E32	MACRO	ADDRESS,ADDRESS1
	LOCAL PLUS
	MOVFF ADDRESS,ADDRESS1
	MOVFF ADDRESS+1,ADDRESS1+1
	CLRF ADDRESS1+2
	CLRF ADDRESS1+3
	BTFSS ADDRESS+1,7	;Original sign
	GOTO PLUS
	SETF ADDRESS1+2
	SETF ADDRESS1+3
PLUS
	ENDM

;Move 32bit pair AB to File MOVABF
MOVABF	MACRO   ADDRESS
	MOVF32 ACCaLO,ADDRESS
	ENDM

;Move File to 32bit pair AB
MOVFAB	MACRO   ADDRESS
	MOVF32 ADDRESS,ACCaLO
	ENDM

;Move 16 bit File to 32bit pair AB & sign extend
MOVF16EAB	MACRO   ADDRESS
	MOVF16E32 ADDRESS,ACCaLO
	ENDM

;Move 16 bit File to 32bit pair CD & sign extend
MOVF16ECD	MACRO   ADDRESS
	MOVF16E32 ADDRESS,ACCcLO
	ENDM

;Move File to 32bit pair CD
MOVFCD	MACRO   ADDRESS
	MOVF32 ADDRESS,ACCcLO
	ENDM

;Move 32bit pair CD to File
MOVCDF	MACRO   ADDRESS
	MOVF32 ACCcLO,ADDRESS
	ENDM

;Move 32bit pair AB to CD
MOVABCD MACRO
	MOVF32 ACCaLO,ACCcLO
	ENDM

;Move 32bit pair CD to AB
MOVCDAB MACRO
	MOVF32 ACCcLO,ACCaLO
	ENDM

;clears the 32bit file in LS/MS format
CLRF32	MACRO   ADDRESS
	CLRF ADDRESS	;Clear LS
	CLRF ADDRESS+1
	CLRF ADDRESS+2
	CLRF ADDRESS+3	;MS
	ENDM

;Clear 32 bit register pair AB
CLRAB MACRO
	CLRF32 ACCaLO
	ENDM

;Clear 32 bit register pair CD
CLRCD MACRO
	CLRF32 ACCcLO
	ENDM

;Clear 32 bit register pair EF
CLREF MACRO
	CLRF32 ACCeLO
	ENDM

;Add CD to AB
ADDCDAB	MACRO	;ab+cd->ab
	ADDFAB ACCcLO
	ENDM

;Add 32 bit file to accumulator pair AB
ADDFAB	MACRO	ADDRESS  ;ab+f->ab
	MOVF ADDRESS,W
	ADDWF ACCaLO,F
	MOVF ADDRESS+1,W
	ADDWFC ACCaHI,F
	MOVF ADDRESS+2,W
	ADDWFC ACCbLO,F
	MOVF ADDRESS+3,W
	ADDWFC ACCbHI,F
	ENDM

;Add accumulator pair AB to 32 bit file
ADDABF	MACRO	ADDRESS  ;f+ab->f
	MOVF ACCaLO,W
	ADDWF ADDRESS,F
	MOVF ACCaHI,W
	ADDWFC ADDRESS+1,F
	MOVF ACCbLO,W
	ADDWFC ADDRESS+2,F
	MOVF ACCbHI,W
	ADDWFC ADDRESS+3,F
	ENDM

;Subtract 32 bit file from 'AB' result in 'AB'
SUBFAB		MACRO ADDRESS
	MOVF ADDRESS,W
	SUBWF ACCaLO,F
	MOVF ADDRESS+1,W
	SUBWFB ACCaHI,F	
	MOVF ADDRESS+2,W
	SUBWFB ACCbLO,F	
	MOVF ADDRESS+3,W
	SUBWFB ACCbHI,F	
	ENDM

;Subtract 'AB' from 32 bit file result in file
SUBABF		MACRO ADDRESS
	MOVF ACCaLO,W
	SUBWF ADDRESS,F
	MOVF ACCaHI,W
	SUBWFB ADDRESS+1,F
	MOVF ACCbLO,W
	SUBWFB ADDRESS+2,F	
	MOVF ACCbHI,W
	SUBWFB ADDRESS+3,F	
	ENDM

;Unsigned compare 32 bit file with 32 bit file (f2-f1)
;carry & zero flags reflect unsigned 32bit result
CMPFFU32	MACRO ADDRESS1,ADDRESS2	;See AN526
	LOCAL NOCHK
	LOCAL LSCHK
	MOVF ADDRESS1+3,W ;ms
	SUBWF ADDRESS2+3,W	;check if file > file
	BZ LSCHK1		;continue if file=file
	GOTO NOCHK		;ms result tells all
LSCHK1	MOVF ADDRESS1+2,W	;ms same so test next ms
	SUBWF ADDRESS2+2,W	;carry set if a > file
	BZ LSCHK2		;continue if file=file
	GOTO NOCHK		;next ms result tells all
LSCHK2	MOVF ADDRESS1+1,W	;ms same so test next ms
	SUBWF ADDRESS2+1,W	;carry set if a > file
	BZ LSCHK3		;continue if file=file
	GOTO NOCHK		;next ms result tells all
LSCHK3	MOVF ADDRESS1,W		;ms same so test next ms
	SUBWF ADDRESS2,W	;carry set if a > file
NOCHK	
	ENDM

;Negate 32 bit register pair AB
NEGAB	MACRO
	NEGF32 ACCaLO
	ENDM

;Negate 32 bit file
NEGF32	MACRO	ADDRESS	;Invert then add 1
	COMF ADDRESS,F	;LS
	COMF ADDRESS+1,F
	COMF ADDRESS+2,F
	COMF ADDRESS+3,F
	CLRF WREG
	SETC
	ADDWFC ADDRESS,F	;LS
	ADDWFC ADDRESS+1,F
	ADDWFC ADDRESS+2,F
	ADDWFC ADDRESS+3,F
	ENDM

;Shift 32 bit file left one bit
LSLF32	MACRO	ADDRESS
	CLRC		;so it won't corrupt LS bit
	RLCF ADDRESS,F		;LS setting carry as appropriate
	RLCF ADDRESS+1,F	;carry from LS byte
	RLCF ADDRESS+2,F
	RLCF ADDRESS+3,F
	ENDM

;Rotate 32 bit file left one bit through carry
RLF32C	MACRO	ADDRESS
	RLCF ADDRESS,F		;Using carry from caller
	RLCF ADDRESS+1,F	;carry from LS byte
	RLCF ADDRESS+2,F
	RLCF ADDRESS+3,F
	ENDM

;Rotate 32bit register pair EF left through carry
RLFEFC	MACRO
	RLF32C ACCeLO
	ENDM

;Logical Shift 32bit register pair AB one bit right.
LSRAB	MACRO
	LSRF32 ACCaLO
	ENDM

;Logical Shift 32 bit file right one bit
LSRF32	MACRO	ADDRESS
	CLRC		;so it won't corrupt MS bit
	RRCF ADDRESS+3,F	;MS setting carry as appropriate
	RRCF ADDRESS+2,F
	RRCF ADDRESS+1,F
	RRCF ADDRESS,F		;LS with any carry from MS byte
	ENDM

;Arithmetic Shift 32 bit file right one bit
ASRF32	MACRO	ADDRESS
	CLRC
	BTFSC ADDRESS+3,7	;If MS bit is set
	SETC		;Then set carry ready for copying
	RRCF ADDRESS+3,F	;MS setting carry as appropriate
	RRCF ADDRESS+2,F
	RRCF ADDRESS+1,F
	RRCF ADDRESS,F		;LS with any carry from MS byte
	ENDM

;Arithmetic Shift accumulator pair AB one bit right
ASRAB MACRO
	ASRF32 ACCbLO
	ENDM

;Logical Shift accumulator pair AB one bit left
LSLAB MACRO
	LSLF32 ACCaLO
	ENDM

;Logical Shift accumulator pair CD one bit left
LSLCD MACRO
	LSLF32 ACCcLO
	ENDM

;Logical Shift accumulator pair EF one bit left
LSLEF MACRO
	LSLF32 ACCeLO
	ENDM

;Logical Shift accumulator pair GH one bit left
LSLGH MACRO
	LSLF32 ACCgLO
	ENDM

;Save 8 bit file to Indirection pointer 2
POST2F8 MACRO ADDRESS
	MOVF ADDRESS,W
	MOVWF POSTINC2	;Save to Capture buffer & increment pointer
	ENDM

;Save 16 bit file to Indirection pointer 2
POST2F16 MACRO ADDRESS
	MOVF ADDRESS,W
	MOVWF POSTINC2	;Save to Capture buffer & increment pointer
	MOVF ADDRESS+1,W
	MOVWF POSTINC2	;Save to Capture buffer & increment pointer
	ENDM

;Save 32 bit file to Indirection pointer 2
POST2F32 MACRO ADDRESS
	MOVF ADDRESS,W
	MOVWF POSTINC2	;Save to Capture buffer & increment pointer
	MOVF ADDRESS+1,W
	MOVWF POSTINC2	;Save to Capture buffer & increment pointer
	MOVF ADDRESS+2,W
	MOVWF POSTINC2	;Save to Capture buffer & increment pointer
	MOVF ADDRESS+3,W
	MOVWF POSTINC2	;Save to Capture buffer & increment pointer
	ENDM

;Odds & ends for PIC18F458

;Select databank given
REGBANK	MACRO BANKNUMBER
	MOVLB BANKNUMBER	;BSR=0 for bank 0 etc
	ENDM

;Extend instruction set with more convenient op-codes

SAVEMAX8 MACRO ADDRESS
	CPFSGT ADDRESS
	MOVWF ADDRESS	;Save as its bigger
	ENDM

SAVEMIN8 MACRO ADDRESS
	CPFSLT ADDRESS
	MOVWF ADDRESS	;Save as its smaller
	ENDM

;Clear carry
CLRC	MACRO
	BCF STATUS,C
	ENDM

;Set Carry
SETC	MACRO
	BSF STATUS,C
	ENDM

;Logical shift left file
LSLF	MACRO ADDRESS
	CLRC		;So it won't corrupt LS bit
	RLCF ADDRESS,F
	ENDM

;Logical shift right file
LSRF	MACRO ADDRESS
	CLRC		;So it won't corrupt MS bit
	RRCF ADDRESS,F
	ENDM

;Sets Z and N flag but does not change file
TSTF	MACRO ADDRESS
	MOVF ADDRESS,F
	ENDM
+
file: /Techref/member/RF-AMY-K22a/mathsdefs_h.htm, 34KB, , updated: 2014/4/9 15:37, local time: 2024/12/1 10:14, owner: RF-AMY-K22a,
TOP NEW HELP FIND: 
18.97.9.169:LOG IN

 ©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions?
Please DO link to this page! Digg it! / MAKE!

<A HREF="http://massmind.org/Techref/member/RF-AMY-K22a/mathsdefs_h.htm"> Roger Froud's 16 and 32 bit maths function macros for PIC18F458</A>

After you find an appropriate page, you are invited to your to this massmind site! (posts will be visible only to you before review) Just type a nice message (short messages are blocked as spam) in the box and press the Post button. (HTML welcomed, but not the <A tag: Instead, use the link box to link to another page. A tutorial is available Members can login to post directly, become page editors, and be credited for their posts.


Link? Put it here: 
if you want a response, please enter your email address: 
Attn spammers: All posts are reviewed before being made visible to anyone other than the poster.
Did you find what you needed?