// PIC Port Peep rules
//
//
// INTRODUCTION:
//
// The peep hole optimizer searchs the
// the SDCC generated code for small snippets
// that can be optimized. As a user, you have
// control over this optimization process without
// having to learn the SDCC source code. (However
// you'll still need access to the source since
// these rules are compiled into the source.)
//
// The way it works is you specify the target
// snippet that you want replaced with a more 
// efficient snippet that you write. Wild card
// variables allow the rules to be parameterized.
// 
// In all of the SDCC ports, labels and operands
// can be wild cards. However, in the PIC even the
// instructions can be wild cards.
//
// EXAMPLE:
//
// Consider Peep Rule 1 as an example. This rule
// replaces some code like:
//
//   skpz           ;i.e. btfss status,Z
//    goto    lab1
//   clrw
//lab1:
//
// with:
//
//   skpnz     ;i.e. btfsc status,Z
//    clrw
//lab1
//
// However, the Rule has four wild cards.
// The first allows the btfss instruction operator
// be anything, not just the Z bit in status register.
// The second wild card applies to a label.
// The third wild card is for an instruction - any
// single instruction can be substituted.
// The fourth wild card is also an instruction. It's
// just an instruction place holder associated with
// a label (think of it as the PIC Port author's laziness
// imposed upon the user).
//
//
// CONDITIONS
//
// There are certain instances where a peep rule may not
// be applicable. Consider this subtle example:
//
//     movwf    R0
//     movf     R0,W
//
// It would seem that the second move is unnecessary. But
// be careful! The movf instruction affects the 'Z' bit.
// So if this sequence is followed by a btfsc status,Z, you
// will have to leave the second move in.
//
// To get around this proble, the peep rule can be followed
// by a conditon:  "if NZ". Which is to say, apply the rule
// if Z bit is not needed in the code that follows. The optimizer
// is smart enough to look more than one instruction past the
// target block...
//
// Special commands
//
//
//   _NOTBITSKIP_   %1   - Creates a wild card instruction that
//                         will match all instructions except for
//                         bit skip instructions (btfsc or btfss)
//   _BITSKIP_  %1 - Creates a wild card instruction that only
//                   will match a bit skip instruction (btfsc
//                   or btfss)
//   _INVERTBITSKIP_ %1  - For the wild card instruction %1, invert
//                         the state of the bit skip. If %1 is not
//                         a bit skip instruction, then there's an
//                         error in the peep rule.
//
// 
//


// Peep 1 
//   Converts 
//
//    btfss   reg1,bit
//     goto   label
//    incf    reg2,f
//label
//
// Into:
//
//    btfsc   reg1,bit
//     incf   reg2,f
//label
//
// Notice that wild cards will allow any instruction
// besides incf to be used in the above.
//
// Also, notice that this snippet is not valid if
// it follows another skip


replace restart {
        _NOTBITSKIP_	%1
	_BITSKIP_	%2
        goto	%3
	%4
%3:	%5
} by {
	;     peep 1 - test/jump to test/skip
        %1
	_INVERTBITSKIP_	%2
	%4
%3:	%5
} 

replace restart {
        _NOTBITSKIP_	%1
	_BITSKIP_	%2
        goto	%3
%4:	%5
%3:	%6
} by {
	;     peep 1b - test/jump to test/skip
        %1
	_INVERTBITSKIP_	%2
%4:	%5
%3:	%6
} 


//bogus test for pcode
//replace restart {
//	movf	%1,w	;comment at end
//%4:	movf	%1,w
//	RETURN
//	clrf	INDF0
//	movlw	0xa5
//	movf	fsr0,w
//	incf	indf0,f
//	%2
//} by {
//	; peep test remove redundant move
//%4:	movf	%1,w	;another comment
//	%2
//} if AYBABTU %3


// peep 2
replace restart {
	movwf	%1
	movf	%1,w
} by {
	;     peep 2 - Removed redundant move
	movwf	%1
} if NZ

// peep 3
//replace restart {
/	decf	%1,f
///	movf	%1,w
//	btfss	_STATUS,z
//	goto	%2
//} by {
//	;     peep 3 - decf/mov/skpz to decfsz
//	decfsz	%1,f
//	 goto	%2
//}


replace restart {
	movf	%1,w
	movf	%1,w
} by {
	;     peep 4 - Removed redundant move
	movf	%1,w
}


replace restart {
	movlw	%1
	movwf	%2
	movlw	%1
} by {
	;     peep 5 - Removed redundant move
	movlw	%1
	movwf	%2
}

replace restart {
	movwf	%1
	movwf	%1
} by {
	;     peep 6 - Removed redundant move
	movwf	%1
}

replace restart {
	movlw	0
	iorwf	%1,w
} by {
	;     peep 7 - Removed redundant move
	movf	%1,w
}

replace restart {
	movf	%1,w
	movwf	%2
	decf	%2,f
} by {
	;     peep 8 - Removed redundant move
	decf	%1,w
	movwf	%2
}

replace restart {
	movwf	%1
	movf	%2,w
	xorwf	%1,w
} by {
	;     peep 9a - Removed redundant move
	movwf	%1
	xorwf	%2,w
}

replace restart {
	movwf	%1
	movf	%2,w
	iorwf	%1,w
} by {
	;     peep 9b - Removed redundant move
	movwf	%1
	iorwf	%2,w
}

replace restart {
	movf	%1,w
	movwf	%2
	movf	%2,w
} by {
	;     peep 9c - Removed redundant move
	movf	%1,w
	movwf	%2
}

replace restart {
	movwf	%1
	movf	%1,w
	movwf	%2
} by {
	;     peep 9d - Removed redundant move
	movwf	%1
	movwf	%2
} if NZ

// From: Frieder Ferlemann

replace restart {
        iorlw   0
} by {
        ;     peep 10a - Removed unnecessary iorlw
} if NZ

// From: Frieder Ferlemann

replace restart {
        xorlw   0
} by {
        ;     peep 10b - Removed unnecessary xorlw
} if NZ

// From: Frieder Ferlemann

replace restart {
        movf    %1,w
        movwf   %1
} by {
        ;     peep 11 - Removed redundant move
        movf    %1,w
}

replace restart {
        movf    %1,w
        movf    %2,w
} by {
        ;     peep 12 - Removed redundant move
        movf    %2,w
}

replace restart {
	movf	%1,w
	xorlw	%2
	bz	%3
	bra	%4
%3:	%5
} by {
	;	peep 101 - test for equality
	movlw	%2
	cpfseq	%1
	bra	%4
%3:	%5
}
