;; -*- 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. ;; ;; ****************************************************************************