PIC Microcontoller Bit Math Method


Rotate a byte a variable number of positions

by Isaac Marino Bavaresco


I was needing a (very) efficient way to rotate a byte a variable number
of positions when the following popped on my mind(code in PIC18 assembly, see more code lower in the page):


btfsc TABLAT, 2, ACCESS swapf PRODL, F, ACCESS btfsc TABLAT, 1, ACCESS rrncf PRODL, F, ACCESS btfsc TABLAT, 1, ACCESS rrncf PRODL, F, ACCESS btfsc TABLAT, 0, ACCESS rrncf PRODL, F, ACCESS

The number of positions to rotate is in TABLAT and the value to be
rotated is in PRODL.
The routine can rotate from zero to 7 positions, takes only 8
instructions and as a bonus it is isochronous.
Any other registers can be used. If banked registers are used then the bank selection must be cared of properly.




Macros for the PIC18 architecture:


;===============================================================================
; Macro to rotate a register a variable number of positions to the right.
; The number of positions to rotate must be in another register.
;
; Input:
;	value:		Register with the value to be rotated.
;	vacc:		Access method (ACCESS or BANKED) for the value.
;	positions:	Register with the number of positions to rotate.
;	pacc:		Access method (ACCESS or BANKED) for the positions.
;
; Output:
;	"value" register with the result.
;
; Changes:
;	"value" register.
;
; Side effects:
;	Flags Z and N may be affected.
;
; Notes:
;	- If both registers use access method BANKED, both must reside in the
;	  same bank.
;	- The code is isochronous (runs always in the same number of cycles).

rrvar		macro	value,vacc,positions,pacc

		btfsc	positions, 2, pacc
		swapf	value, F, vacc
		btfsc	positions, 1, pacc
		rrncf	value, F, vacc
		btfsc	positions, 1, pacc
		rrncf	value, F, vacc
		btfsc	positions, 0, pacc
		rrncf	value, F, vacc

		endm
;===============================================================================
; Macro to rotate a register a variable number of positions to the left.
; The number of positions to rotate must be in another register.
;
; Input:
;	value:		Register with the value to be rotated.
;	vacc:		Access method (ACCESS or BANKED) for the value.
;	positions:	Register with the number of positions to rotate.
;	pacc:		Access method (ACCESS or BANKED) for the positions.
;
; Output:
;	"value" register with the result.
;
; Changes:
;	"value" register.
;
; Side effects:
;	Flags Z and N may be affected.
;
; Notes:
;	- If both registers use access method BANKED, both must reside in the
;	  same bank.
;	- The code is isochronous (runs always in the same number of cycles).

rlvar		macro	value,vacc,positions,pacc

		btfsc	positions, 2, pacc
		swapf	value, F, vacc
		btfsc	positions, 1, pacc
		rlncf	value, F, vacc
		btfsc	positions, 1, pacc
		rlncf	value, F, vacc
		btfsc	positions, 0, pacc
		rlncf	value, F, vacc

		endm
;===============================================================================
; Macro to rotate a register a fixed number of positions to the right.
; The number of positions to rotate must be a numeric constant.
;
; Input:
;	value:		Register with the value to be rotated.
;	vacc:		Access method (ACCESS or BANKED) for the value.
;	positions:	Constant with the number of positions to rotate.
;
; Output:
;	"value" register with the result.
;
; Changes:
;	"value" register.
;
; Side effects:
;	Flags Z and N may be affected.
;
; Notes:
;	- The code generated may range from one to four instructions.

rrcon		macro	value,vacc,positions

	if positions & b'00000100'
		swapf	value, F, vacc
	endif
	if positions & b'00000010'
		rrncf	value, F, vacc
		rrncf	value, F, vacc
	endif
	if positions & b'00000001'
		rrncf	value, F, vacc
	endif

		endm
;===============================================================================
; Macro to rotate a register a fixed number of positions to the left.
; The number of positions to rotate must be a numeric constant.
;
; Input:
;	value:		Register with the value to be rotated.
;	vacc:		Access method (ACCESS or BANKED) for the value.
;	positions:	Constant with the number of positions to rotate.
;
; Output:
;	"value" register with the result.
;
; Changes:
;	"value" register.
;
; Side effects:
;	Flags Z and N may be affected.
;
; Notes:
;	- The code generated may range from one to four instructions.

rlcon		macro	value,vacc,positions

	if positions & b'00000100'
		swapf	value, F, vacc
	endif
	if positions & b'00000010'
		rlncf	value, F, vacc
		rlncf	value, F, vacc
	endif
	if positions & b'00000001'
		rlncf	value, F, vacc
	endif

		endm
;===============================================================================



Macros for the baseline/midrange architecture:


;===============================================================================
; Macro to rotate a register a variable number of positions to the right.
; The number of positions to rotate must be in another register.
;
; Input:
;	value:		Register with the value to be rotated.
;	positions:	Register with the number of positions to rotate.
;
; Output:
;	"value" register with the result.
;
; Changes:
;	"value" register, WREG.
;
; Side effects:
;	Flag C is affected.
;
; Notes:
;	- Both registers must reside in the same bank.
;	- The code is isochronous (runs always in the same number of cycles).

rrvar		macro	value,positions

		btfsc	positions, 2
		swapf	value, F
		rrf	value, W
		btfsc	positions, 1
		rrf	value, F
		btfsc	positions, 1
		rrf	value, F
		btfsc	positions, 0
		rrf	value, F

		endm
;===============================================================================
; Macro to rotate a register a variable number of positions to the left.
; The number of positions to rotate must be in another register.
;
; Input:
;	value:		Register with the value to be rotated.
;	positions:	Register with the number of positions to rotate.
;
; Output:
;	"value" register with the result.
;
; Changes:
;	"value" register, WREG.
;
; Side effects:
;	Flag C is affected.
;
; Notes:
;	- Both registers must reside in the same bank.
;	- The code is isochronous (runs always in the same number of cycles).

rlvar		macro	value,positions

		btfsc	positions, 2
		swapf	value, F
		rlf	value, W
		btfsc	positions, 1
		rlf	value, F
		btfsc	positions, 1
		rlf	value, F
		btfsc	positions, 0
		rlf	value, F

		endm
;===============================================================================
; Macro to rotate a register a fixed number of positions to the right.
; The number of positions to rotate must be a numeric constant.
;
; Input:
;	value:		Register with the value to be rotated.
;	positions:	Constant with the number of positions to rotate.
;
; Output:
;	"value" register with the result.
;
; Changes:
;	"value" register, "WREG".
;
; Side effects:
;	Flag C is affected.
;
; Notes:
;	- The code generated may range from one to five instructions.

rrcon		macro	value,positions

	if positions & b'00000100'
		swapf	value, F
	endif
	if positions & b'00000011' != 0
		rrf	value, W
	endif
	if positions & b'00000010'
		rrf	value, F
		rrf	value, F
	endif
	if positions & b'00000001'
		rrf	value, F
	endif

		endm
;===============================================================================
; Macro to rotate a register a fixed number of positions to the left.
; The number of positions to rotate must be a numeric constant.
;
; Input:
;	value:		Register with the value to be rotated.
;	positions:	Constant with the number of positions to rotate.
;
; Output:
;	"value" register with the result.
;
; Changes:
;	"value" register, WREG.
;
; Side effects:
;	Flag C is affected.
;
; Notes:
;	- The code generated may range from one to five instructions.

rlcon		macro	value,positions

	if positions & b'00000100'
		swapf	value, F
	endif
	if positions & b'00000011' != 0
		rlf	value, W
	endif
	if positions & b'00000010'
		rlf	value, F
		rlf	value, F
	endif
	if positions & b'00000001'
		rlf	value, F
	endif

		endm
;===============================================================================