;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 16:37, local time: 2024/8/31 19:05,
owner: RF-AMY-K22a,
|
| ©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? <A HREF="http://sxlist.com/techref/member/RF-AMY-K22a/mathsdefs_h.htm"> Roger Froud's 16 and 32 bit maths function macros for PIC18F458</A> |
Did you find what you needed?
|