;; -*- Mode: mpasm -*-
;; ****************************************************************************
;;   macro library for PIC12/16 Pseudo Operating System
;; ****************************************************************************

; *** configure ***
	IFNDEF	SP
	EXTERN	SP
	ENDIF
	IFNDEF	RA
	EXTERN	RA
	ENDIF
	IFNDEF	TOPSTACK
	EXTERN	TOPSTACK
	ENDIF

; *****************************************************************************
; *** Low level macro ***
;;; Exchange value (XOR Swap)
;;  _______        _______        _______        _______
;; |_F_|_W_|      |_F_|_W_|      |_F_|_W_|      |_F_|_W_|
;; |_0_|_0_| XOR  |_0_|_0_| XOR  |_0_|_0_| XOR  |_0_|_0_|
;; |_0_|_1_|=====>|_0_|_1_|=====>|_1_|_1_|=====>|_1_|_0_|
;; |_1_|_0_|  W   |_1_|_1_|  F   |_0_|_1_|  W   |_0_|_1_|
;; |_1_|_1_|      |_1_|_0_|      |_1_|_0_|      |_1_|_1_|
;;   start           1st            2nd            3rd
XCHG	MACRO	_REGISTER
	XORWF	_REGISTER,W
	XORWF	_REGISTER,F
	XORWF	_REGISTER,W
	ENDM
;; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;;; Change endian (X-1)Byte length data
;;   RAM address   _____________            _____________
;;            00h |_____________|          |_____________|
;;                |     ....    |          |     ....    |
;;                |_____________|          |_____________|
;;      _REGISTER |__MSBs_Byte__|          |__LSBs_Byte__|
;;                |     ....    |  ENDIAN  |     ....    |
;;                |_____________| <======> |_____________|
;; _REGISTER + _X |__LSBs_Byte__|          |__MSBs_Byte__|
;;                |     ....    |          |     ....    |
;;                |_____________|          |_____________|
;;           0FFh |_____________|          |_____________|
;;                  big endian              little endian
;;
ENDIAN	MACRO	_REGISTER,_X
	VARIABLE	INCREMENT=D'0'
	WHILE	_X>INCREMENT*D'2'
	MOVF	_REGISTER+INCREMENT,W
	XCHG	_REGISTER+_X-INCREMENT
	MOVWF	_REGISTER+INCREMENT
	INCREMENT=INCREMENT+D'1'
	ENDW
	ENDM
; *****************************************************************************
; *** Stack control macro library ***
;;; Push stack macro
;;                       _________
;;            _REGISTER |__H'0B'__|----------,
;;                                           |
;;                                           V
;;                                      |_________|
;;        |_________|                   |__H'0B'__| <-- SP
;; SP --> |__H'0A'__| ================> |__H'0A'__|
;;        |   ...   |  PUSH _REGISTER   |   ...   |
;;        |_________|     SP=SP-D'1'    |_________|
;;        |_________|                   |_________|
;;      __|_________|__               __|_________|__
;;           STACK                         STACK
PUSH	MACRO	_REGISTER
	BANKISEL(TOPSTACK)			;1cycle
	DECF	SP,W
	MOVWF	SP
	MOVWF	FSR
	MOVF	_REGISTER,W
	MOVWF	INDF
	ENDM
;; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;;; Pop stack macro
;;                            _________
;;               ,----> WREG |__H'0B'__|
;;              /
;;        |_________|
;; SP --> |__H'0B'__|                   |_________|
;;        |__H'0A'__| ================> |__H'0A'__| <-- SP
;;        |   ...   |  POP SP=SP+D'1'   |   ...   |
;;        |_________|                   |_________|
;;        |_________|                   |_________|
;;      __|_________|__               __|_________|__
;;           STACK                         STACK
POP	MACRO
	BANKISEL(TOPSTACK)
	MOVF	SP,W
	MOVWF	FSR
	MOVF	INDF,W
	INCF	SP,F
	ENDM
;; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;;; Duplicate top stack macro
;;                            _________
;;                ,---> WREG |__H'0A'__|-----,
;;               /                           |
;;              /                            V
;;             /                        |_________|
;;        |_________|                   |__H'0A'__| <-- SP
;; SP --> |__H'0A'__| ================> |__H'0A'__|
;;        |   ...   |  DUP SP=SP-D'1'   |   ...   |
;;        |_________|                   |_________|
;;        |_________|                   |_________|
;;      __|_________|__               __|_________|__
;;           STACK                         STACK
DUP	MACRO
	BANKISEL(TOPSTACK)
	MOVF	SP,W
	MOVWF	FSR
	MOVF	INDF,W
	DECF	SP,F
	DECF	FSR,F
	MOVWF	INDF
	ENDM
;; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;;; Peek stack macro
;;                             _________
;;                ,----> WREG |__H'0A'__|
;;               /
;;        |_________|                   |_________|
;;  SP--> |__H'0A'__| ================> |__H'0A'__| <-- SP
;;        |   ...   |  PEEK             |   ...   |
;;        |_________|                   |_________|
;;        |_________|                   |_________|
;;      __|_________|__               __|_________|__
;;           STACK                         STACK
PEEK	MACRO
	BANKISEL(TOPSTACK)
	MOVF	SP,W
	MOVWF	FSR
	MOVF	INDF,W
	ENDM
;; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;;; Swap stack macro
;;                ,----------------------------------------.
;;               /                                          :
;;        |_________|                   |_________|         |
;; SP --> |__H'0B'__|         ,-------> |__H'0A'__| <-- SP  |
;;        |__H'0A'__| _______/          |__H'0B'__| <-------'
;;        |   ...   |                   |   ...   |
;;        |_________| ================> |_________|
;;        |_________|  SWAP             |_________|
;;      __|_________|__               __|_________|__
;;           STACK                         STACK
SWAP	MACRO
	BANKISEL(TOPSTACK)
	MOVF	SP,W
	MOVWF	FSR
	MOVF	INDF,W
	INCF	FSR,F
	XCHG	INDF
	DECF	FSR,F
	XCHG	INDF
	ENDM
;; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;;; Right rotate stack macro
;;                ,----------------------------------------.
;;               /                                          :
;;        |_________|                   |_________|         |
;; SP --> |__H'0A'__|         ,-------> |__H'0B'__| <-- SP  |
;;        |__H'0B'__| _______/,-------> |__H'0C'__|         |
;;        |__H'0C'__| _______/...-----> |_________|         |
;;        |   ...   |         ...       |   ...   |         |
;;        |_________|         ...       |_________|         |
;;        |__H'0E'__| _______/,-------> |__H'0F'__|         |
;;        |__H'0F'__| _______/          |__H'0A'__| <-------'
;;        |   ...   |                   |   ...   |
;;        |_________| ================> |_________|
;;        |_________|  RROTETA          |_________|
;;      __|_________|__               __|_________|__
;;           STACK                         STACK
RROTATE	MACRO	_NUMBER
	BANKISEL(TOPSTACK)
	MOVF	SP,W
	MOVWF	FSR
	VARIABLE	INCREMENT=D'0'
	WHILE	_NUMBER>INCREMENT
	MOVF	INDF,W
	INCF	FSR,F
	XCHG	INDF
	DECF	FSR,F
	XCHG	INDF
	INCF	FSR,F
	INCREMENT=INCREMENT+D'1'
	ENDW
	ENDM
;; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;;; Light rotate stack macro
;;      ,------------------------------------.
;;     /                                      :
;;    ,                                       |
;;    |                                       V
;;    |   |_________|                   |_________|
;; SP +-> |__H'0A'__| _______           |__H'0F'__| <-- SP
;;    |   |__H'0B'__| _______`--------> |__H'0A'__|
;;    |   |__H'0C'__| _______`--------> |_________|
;;    |   |   ...   |        `...       |   ...   |
;;    |   |_________|         ...       |_________|
;;    |   |__H'0E'__| _______    -----> |_________|
;;    t__ |__H'0F'__|        `--------> |__H'0E'__|
;;        |   ...   |                   |   ...   |
;;        |_________| ================> |_________|
;;        |_________|  LROTETA          |_________|
;;      __|_________|__               __|_________|__
;;           STACK                         STACK
LROTATE	MACRO	_NUMBER
	BANKISEL(TOPSTACK)
	MOVF	SP,W
	ADDLW	_NUMBER-D'1'
	MOVWF	FSR
	VARIABLE	INCREMENT=D'0'
	WHILE	_NUMBER>INCREMENT
	MOVF	INDF,W
	DECF	FSR,F
	XCHG	INDF
	INCF	FSR,F
	XCHG	INDF
	DECF	FSR,F
	INCREMENT=INCREMENT+D'1'
	ENDW
	ENDM
; *****************************************************************************
; *** Subroutine call macro library ***
;;; Subroutine call macro
JUMP	MACRO	_LABEL
	PAGESEL(_LABEL)
	PUSH	RA
	PUSH	RA+D'1'
	MOVLW	HIGH($+D'5')
	MOVWF	RA
	MOVLW	LOW($+D'3')
	MOVWF	RA+D'1'
	GOTO	_LABEL
	POP
	MOVWF	RA+D'1'
	POP
	MOVWF	RA
	ENDM
;; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;;; Return from subroutine macro
BACK	MACRO
	MOVF	RA,W
	MOVWF	PCLATH
	MOVF	RA+D'1',W
	MOVWF	PCL
	ENDM
;;; Software delay
DELAY1	MACRO	_TMP,_CYCLE
	LOCAL	LOOP
	VARIABLE	WAIT0=(_CYCLE-D'1')/D'3'
	IF	WAIT0>D'256'
WAIT0=D'256'
	ENDIF
	VARIABLE	REST=(_CYCLE-D'1')-D'3'*WAIT0
	IF	REST>D'2'
	ERROR	"Out of range."
	ENDIF
	MOVLW	LOW(WAIT0)
	MOVWF	_TMP
	FILL	(NOP),REST
LOOP
	DECFSZ	_TMP,F
	GOTO	LOOP
	ENDM

DELAY2	MACRO	_TMP,_CYCLE
	LOCAL	LOOP
	VARIABLE	WAIT1=(_CYCLE+D'765')/D'770'
	IF	WAIT1>D'256'
WAIT1=D'256'
	ENDIF
	VARIABLE	WAIT0=((_CYCLE+D'765')-D'770'*WAIT1)/D'3'
	IF	WAIT0>D'256'
WAIT0=D'256'
	ENDIF
	VARIABLE	REST=((_CYCLE+D'765')-D'770'*WAIT1)-D'3'*WAIT0
	IF	REST>D'2'
	ERROR	"Out of range."
	ENDIF
	MOVLW	LOW(WAIT0)
	MOVWF	_TMP
	MOVLW	LOW(WAIT1)
	MOVWF	_TMP+D'1'
	FILL	(NOP),REST
LOOP
	DECFSZ	_TMP,F
	GOTO	LOOP
	DECFSZ	_TMP+D'1',F
	GOTO	LOOP
	ENDM

DELAY3	MACRO	_TMP,_CYCLE
	LOCAL	LOOP
	VARIABLE	WAIT2=(_CYCLE+D'197883')/D'197122'
	IF	WAIT2>D'256'
WAIT2=D'256'
	ENDIF
	VARIABLE	WAIT1=((_CYCLE+D'197883')-D'197122'*WAIT2)/D'770'
	IF	WAIT1>D'256'
WAIT1=D'256'
	ENDIF
	VARIABLE	WAIT0=(((_CYCLE+D'197883')-D'197122'*WAIT2)-(D'770'*WAIT1))/D'3'
	IF	WAIT0>D'256'
WAIT0=D'256'
	ENDIF
	VARIABLE	REST=(((_CYCLE+D'197883')-D'197122'*WAIT2)-(D'770'*WAIT1))-(D'3'*WAIT0)
	IF	REST>D'2'
	ERROR	"Out of range."
	ENDIF
	MOVLW	LOW(WAIT0)
	MOVWF	_TMP
	MOVLW	LOW(WAIT1)
	MOVWF	_TMP+D'1'
	MOVLW	LOW(WAIT2)
	MOVWF	_TMP+D'2'
	FILL	(NOP),REST
LOOP
	DECFSZ	_TMP,F
	GOTO	LOOP
	DECFSZ	_TMP+D'1',F
	GOTO	LOOP
	DECFSZ	_TMP+D'2',F
	GOTO	LOOP
	ENDM

DELAY	MACRO	_TMP,_CYCLE
	IF	_CYCLE<=D'4'
	FILL	(NOP),_CYCLE
	ENDIF
	IF	(D'4'<_CYCLE)&&(_CYCLE<=D'771')
	DELAY1	_TMP,_CYCLE
	ENDIF
	IF	(D'771'<_CYCLE)&&(_CYCLE<=D'197125')
	DELAY2	_TMP,_CYCLE
	ENDIF
	IF	D'197125'<_CYCLE
	DELAY3	_TMP,_CYCLE
	ENDIF
	ENDM

WAIT_S	MACRO	_TMP,_S
	VARIABLE	_CYCLE=(_S*FOSC/D'4')
	IF	_CYCLE<=D'4'
	FILL	(NOP),_CYCLE
	ENDIF
	IF	(D'4'<_CYCLE)&&(_CYCLE<=D'771')
	PUSH	_TMP
	DELAY1	_TMP,_CYCLE
	POP	_TMP
	ENDIF
	IF	(D'771'<_CYCLE)&&(_CYCLE<=D'197125')
	PUSH	_TMP
	PUSH	_TMP+D'1'
	DELAY2	_TMP,_CYCLE
	POP	_TMP+D'1'
	POP	_TMP
	ENDIF
	IF	D'197125'<_CYCLE
	PUSH	_TMP
	PUSH	_TMP+D'1'
	PUSH	_TMP+D'2'
	DELAY3	_TMP,_CYCLE
	POP	_TMP+D'2'
	POP	_TMP+D'1'
	POP	_TMP
	ENDIF
	ENDM

WAIT_MS	MACRO	_TMP,_MS
	VARIABLE	_CYCLE=(_MS*FOSC/D'4000')
	IF	_CYCLE<=D'4'
	FILL	(NOP),_CYCLE
	ENDIF
	IF	(D'4'<_CYCLE)&&(_CYCLE<=D'771')
	PUSH	_TMP
	DELAY1	_TMP,_CYCLE
	POP	_TMP
	ENDIF
	IF	(D'771'<_CYCLE)&&(_CYCLE<=D'197125')
	PUSH	_TMP
	PUSH	_TMP+D'1'
	DELAY2	_TMP,_CYCLE
	POP	_TMP+D'1'
	POP	_TMP
	ENDIF
	IF	D'197125'<_CYCLE
	PUSH	_TMP
	PUSH	_TMP+D'1'
	PUSH	_TMP+D'2'
	DELAY3	_TMP,_CYCLE
	POP	_TMP+D'2'
	POP	_TMP+D'1'
	POP	_TMP
	ENDIF
	ENDM

WAIT_MS	MACRO	_TMP,_US
	VARIABLE	_CYCLE=(_US*FOSC/D'4000000')
	IF	_CYCLE<=D'4'
	FILL	(NOP),_CYCLE
	ENDIF
	IF	(D'4'<_CYCLE)&&(_CYCLE<=D'771')
	PUSH	_TMP
	DELAY1	_TMP,_CYCLE
	POP	_TMP
	ENDIF
	IF	(D'771'<_CYCLE)&&(_CYCLE<=D'197125')
	PUSH	_TMP
	PUSH	_TMP+D'1'
	DELAY2	_TMP,_CYCLE
	POP	_TMP+D'1'
	POP	_TMP
	ENDIF
	IF	D'197125'<_CYCLE
	PUSH	_TMP
	PUSH	_TMP+D'1'
	PUSH	_TMP+D'2'
	DELAY3	_TMP,_CYCLE
	POP	_TMP+D'2'
	POP	_TMP+D'1'
	POP	_TMP
	ENDIF
	ENDM

; *****************************************************************************
; *** Mathmatic macro library ***
;;; Negate
;;;; Negate 8bit
NEG8	MACRO	_ARG
	COMF	_ARG,F
	INCF	_ARG,F
	ENDM
;;;; Negate 16bit
NEG16	MACRO	_ARG
	COMF	_ARG,F
	COMF	_ARG+D'1',F
	INCF	_ARG+D'1',F
	BTFSC	STATUS,Z
	INCF	_ARG,F
	ENDM
;;;; Negate 24bit
NEG24	MACRO	_ARG
	COMF	_ARG,F
	COMF	_ARG+D'1',F
	COMF	_ARG+D'2',F
	INCF	_ARG+D'2',F
	BTFSC	STATUS,Z
	INCF	_ARG+D'1',F
	BTFSC	STATUS,Z
	INCF	_ARG,F
	ENDM
;;;; Negate 32bit
NEG32	MACRO	_ARG
	COMF	_ARG,F
	COMF	_ARG+D'1',F
	COMF	_ARG+D'2',F
	COMF	_ARG+D'3',F
	INCF	_ARG+D'3',F
	BTFSC	STATUS,Z
	INCF	_ARG+D'2',F
	BTFSC	STATUS,Z
	INCF	_ARG+D'1',F
	BTFSC	STATUS,Z
	INCF	_ARG,F
	ENDM
;;; Absolute
;;;; Absolute 8bit
ABSLT8	MACRO	_ARG
	LOCAL	SKIP
	BTFSS	_ARG,D'7'
	GOTO	SKIP
	NEG8	_ARG
SKIP
	ENDM
;;;; Absolute 16bit
ABSLT16	MACRO	_ARG
	LOCAL	SKIP
	BTFSS	_ARG,D'7'
	GOTO	SKIP
	NEG16	_ARG
SKIP
	ENDM
;;;; Absolute 24bit
ABSLT24	MACRO	_ARG
	LOCAL	SKIP
	BTFSS	_ARG,D'7'
	GOTO	SKIP
	NEG24	_ARG
SKIP
	ENDM
;;;; Absolute 32bit
ABSLT32	MACRO	_ARG
	LOCAL	SKIP
	BTFSS	_ARG,D'7'
	GOTO	SKIP
	NEG32	_ARG
SKIP
	ENDM
;;; Multiplication
;;;; Multiplication 8bit unsigned
MUL8US	MACRO	_VAL,_ARG0,_ARG1,_TMP
	LOCAL	MUL8LOOP
	CLRF	_VAL				;Clear product high
	CLRF	_VAL+D'1'			;Clear product low
	MOVLW	B'11000000'
	ANDWF	_TMP,W
	IORLW	D'8'
	MOVWF	_TMP				;Set loop counter
MUL8LOOP
	MOVF	_ARG0,W
	RRF	_ARG1,F
	BTFSC	STATUS,C
	ADDWF	_VAL,F
	RRF	_VAL,F
	RRF	_VAL+D'1',F
	DECF	_TMP,F
	MOVLW	B'00111111'
	ANDWF	_TMP,W
	BTFSS	STATUS,Z
	GOTO	MUL8LOOP
	ENDM
;;;; Multiplication 8bit signed
MUL8S	MACRO	_VAL,_ARG0,_ARG1,_TMP
	LOCAL	SKIP
	MOVF	_ARG0,W
	XORWF	_ARG1,W
	MOVWF	_TMP
	ABSLT8	_ARG0				;Absolute multiplier
	ABSLT8	_ARG1				;Absolute multiplicand
	MUL8US	_VAL,_ARG0,_ARG1,_TMP		;Multiplication unsigned
	BTFSS	_TMP,D'7'
	GOTO	SKIP
	NEG16	_VAL
SKIP
	ENDM
;;;; Multiplication 16bit unsigned
MUL16US	MACRO	_VAL,_ARG0,_ARG1,_TMP
	LOCAL	MUL16LOOP
	CLRF	_VAL				;Clear product
	CLRF	_VAL+D'1'
	CLRF	_VAL+D'2'
	CLRF	_VAL+D'3'
	MOVLW	B'11000000'
	ANDWF	_TMP,W
	IORLW	D'16'
	MOVWF	_TMP				;Initialize loop counter
MUL16LOOP
	RRF	_ARG1,F
	RRF	_ARG1+D'1',F
	BTFSS	STATUS,C
	GOTO	$+D'7'
	MOVF	_ARG0+D'1',W
	ADDWF	_VAL+D'1',F
	BTFSC	STATUS,C
	INCF	_VAL,F
	MOVF	_ARG0,W
	ADDWF	_VAL,W
	RRF	_VAL,F
	RRF	_VAL+D'1',F
	RRF	_VAL+D'2',F
	RRF	_VAL+D'3',F
	DECF	_TMP,F
	MOVLW	B'00111111'
	ANDWF	_TMP,W
	BTFSS	STATUS,Z
	GOTO	MUL16LOOP
	ENDM
;;;; Multiplication 16bit signed
MUL16S	MACRO	_VAL,_ARG0,_ARG1,_TMP
	LOCAL	SKIP
	MOVF	_ARG0,W
	XORWF	_ARG1,W
	MOVWF	_TMP
	ABSLT16	_ARG0				;Absolute multiplier
	ABSLT16	_ARG1				;Absolute multiplicand
	MUL16US	_VAL,_ARG0,_ARG1,_TMP		;Multiplication unsigned
	BTFSS	_TMP,D'7'
	GOTO	SKIP
	NEG32	_VAL
SKIP
	ENDM
;;; Division
;;;; Division 8bit unsigned
DIV8US	MACRO	_VAL0,_VAL1,_ARG0,_ARG1,_TMP
	LOCAL	DIV8LOOP
	CLRF	_VAL1				;Clear remainder
	MOVLW	B'11000000'
	ANDWF	_TMP,W
	IORLW	D'8'
	MOVWF	_TMP				;Initialize loop counter
DIV8LOOP
	RLF	_ARG0,F				;Shift dividend
	RLF	_VAL1,F				;Shift remainder
	RLF	_VAL0,F				;Shift quotient
	MOVF	_ARG1,W
	SUBWF	_VAL1,W
	BTFSS	STATUS,C
	GOTO	$+D'3'
	MOVWF	_VAL1
	BSF	_VAL0,D'0'
	DECF	_TMP,F
	MOVLW	B'00111111'
	ANDWF	_TMP,W
	BTFSS	STATUS,Z
	GOTO	DIV8LOOP
	ENDM
;;;; Division 8bit singed
DIV8S	MACRO	_VAL0,_VAL1,_ARG0,_ARG1,_TMP
	LOCAL	SKIP0,SKIP1
	MOVF	_ARG1,W
	XORWF	_ARG0,W
	MOVWF	_TMP
	BCF	_TMP,D'6'
	BTFSC	_ARG0,D'7'
	BSF	_TMP,D'6'
	ABSLT8	_ARG0				;Absolute dividend
	ABSLT8	_ARG1				;Absolute divisor
	;Division 8bit unsigned
	DIV8US	_VAL0,_VAL1,_ARG0,_ARG1,_TMP
	BTFSS	_TMP,D'7'
	GOTO	SKIP0
	NEG8	_VAL0
SKIP0
	BTFSS	_TMP,D'6'
	GOTO	SKIP1
	NEG8	_VAL1
SKIP1
	ENDM
;;;; Division 16bit unsigned
DIV16US	MACRO	_VAL0,_VAL1,_ARG0,_ARG1,_TMP
	LOCAL	DIV16LOOP
	CLRF	_VAL1				;Clear remainder
	CLRF	_VAL1+D'1'
	MOVLW	B'11000000'
	ANDWF	_TMP,W
	IORLW	D'16'
	MOVWF	_TMP				;Initialize loop counter
DIV16LOOP
	RLF	_ARG0+D'1',F
	RLF	_ARG0,F
	RLF	_VAL1+D'1',F
	RLF	_VAL1,F
	RLF	_VAL0+D'1',F
	RLF	_VAL0,F
	MOVF	_ARG1+D'1',W
	SUBWF	_VAL1+D'1',W
	MOVWF	_TEMP+D'2'
	MOVF	_VAL1,W
	MOVWF	_TMP+D'1'
	BTFSC	STATUS,C
	GOTO	$+D'5'
	MOVLW	D'1'
	SUBWF	_TMP+D'1',F
	BTFSS	STATUS,C
	GOTO	$+D'9'
	MOVF	_ARG1,W
	SUBWF	_TMP+D'1',W
	BTFSS	STATUS,C
	GOTO	$+D'5'
	MOVWF	_VAL1
	MOVF	_TMP+D'2',W
	MOVWF	_VAL1+D'1'
	BSF	_VAL0+D'1',D'0'
	DECF	_TMP,F
	MOVLW	B'00111111'
	ANDWF	_TMP,W
	BTFSS	STATUS,Z
	GOTO	DIV16LOOP
	ENDM
;;;; Division 16bit signed
DIV16S	MACRO	_VAL0,_VAL1,_ARG0,_ARG1,_TMP
	LOCAL	SKIP0,SKIP1
	MOVF	_ARG1,W
	XORWF	_ARG0,W
	MOVWF	_TMP
	BCF	_TMP,D'6'
	BTFSC	_ARG0,D'7'
	BSF	_TMP,D'6'
	ABSLT16	_ARG0				;Absolute dividend
	ABSLT16	_ARG1				;Absolute divisor
	;Division 8bit unsigned
	DIV16US	_VAL0,_VAL1,_ARG0,_ARG1,_TMP
	BTFSS	_TMP,D'7'
	GOTO	SKIP0
	NEG16	_VAL0
SKIP0
	BTFSS	_TMP,D'0'
	GOTO	SKIP1
	NEG16	_VAL1
SKIP1
	ENDM
; *****************************************************************************

;; ****************************************************************************
;;
;;  Copyright (c) Hitoshi Gomi
;;  All rights reserved.
;;
;;  Redistribution and use in source and binary forms, with or without
;;  modification, are permitted provided that the following conditions are met:
;;
;;  1.Redistributions of source code must retain the above copyright notice,
;;    this list of conditions and the following disclaimer.
;;  2.Redistributions in binary form must reproduce the above copyright notice,
;;    this list of conditions and the following disclaimer in the documentation
;;    and/or other materials provided with the distribution.
;;  3.The names of the author may not be used to endorse or promote products
;;    derived from this software without specific prior written permission.
;;
;;  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
;;  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
;;  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
;;  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
;;  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
;;  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
;;  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
;;  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
;;  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
;;  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
;;  POSSIBILITY OF SUCH DAMAGE.
;;
;; ****************************************************************************