With the new mnemonics for 18Fxx2 chips, a "few words" explaining the new should be necesary.




A.- ACCESSING MEMORY

   Many mnemonmics haves a new operand called "a" (please, see datasheets. Example "addwf f,d,a". This operand selects Access Bank for a=1 or BSR register to select the correct bank.

   F (a=1, Access)    True Address
   ======================================
   0x00..0x7F         0x000..0x07F (GPRs)
   0x80..0xFF         0xF80..0xFFF (SPRs)

   F (a=0, BSR)     BSR      True Address
   ===================================================
   0x00..0xFF       0x00     0x000..0x0FF (GPRs)
   0x00..0xFF       0x01     0x100..0x1FF (GPRs)
   0x00..0xFF       0x02     0x200..0x2FF (GPRs)
      ...           ...             ...
   0x00..0xFF       0x0E     0xE00..0xEFF (GPRs)
   0x00..0xFF       0x0F     0xF00..0xFFF (GPRs/SFRs)

   In JAL "f" and "a" are coded automatically based on the true address of the file (SFR or GPR), that is, if True_Address <=0x07F or >=0xF80 will be assembled with "a=1", and the rest of files (>=0x080 or <=0xF7F) will be coded with BSR (a=0). Examples:

   WE WRITE               JAL UNDERSTAND
   ===========================================
   addwf H'012',f    ->   addwf H'12',f,1
   addwf H'072',f    ->   addwf H'72',f,1
   addwf H'FE8',f    ->   addwf H'E8',f,1

   addwf H'084',f    ->   addwf H'84',f,0
   addwf H'123',f    ->   addwf H'23',f,0
   addwf H'F08',f    ->   addwf H'08',f,0

   To place the correct bank automatically in the assembler statements, place the token "bank" before the menmonic. Example:

   WE WRITE                    JAL UNDERSTAND
   ========================================================================
   bank addwf H'012',f    ->   addwf H'12',f,1  ; nothing done, access bank.

   bank addwf H'084',f    ->   movlb H'00'      ; Bank=0
                               addwf H'84',f,0  ; True_address=0x084

   bank addwf H'123',f    ->   movlb H'01'      ; Bank=1
                               addwf H'23',f,0  ; True_address=0x123

   bank addwf H'F08',f    ->   movlb H'0F'      ; Bank=F
                               addwf H'08',f,0  ; True_address=0xF08


   Outside the assembler statements, JAL also manages the hole RAM memory and selects the bank when necesary. Example:

<JAL>
include f452_20

var volatile byte myvar01 at 0x0123
var volatile byte myvar02 at 0x0047

myvar01 = 0x10
myvar02 = 0x10
</JAL>

<ASM>
;; 006 : var volatile byte myvar01 at 0x0123
; var H'123:000' myvar01

;; 007 : var volatile byte myvar02 at 0x0047
; var H'047:000' myvar02

;; 009 : myvar01 = 0x10
  movlw   H'10'
  movlb   H'01'   ; bank=1
  movwf   H'123'  ; true_address=0x123

;; 010 : myvar02 = 0x10
  movlw   H'10'
  movwf   H'047'  ; access_bank ; true_address=0x047
</ASM>


  Available RAM for current PIC_16 core supported chips:

     PIC18F242  0x000..0x2FF & 0xF80..0xFFF
     PIC18F252  0x000..0x5FF & 0xF80..0xFFF
     PIC18F442  0x000..0x2FF & 0xF80..0xFFF
     PIC18F452  0x000..0x5FF & 0xF80..0xFFF




B.- INDIRECT MEMORY ACCFESS

   In PIC_14 chips (PIC16F84, PIC16F877, etc.) we have 2 SFRs for indirect addressing: FSR that holds the address (I'm not to talk now about IRP bit, so I left this as is) and INDF that manages the data of the file pointed by the FSR register.

   In a simple description:

<JAL>
var byte myvar

   FSR = 0x67     -- We put here the address of the file.

   myvar = INDF   -- The file "myvar" haves now a copy of the
                  -- data stored in the address 0x67.
</JAL>


  With PIC_16 cores this is enhanced by 3 diferent FSRs (address holders) and 5 diferent INDF for each one of the FSRs.

  As the RAM memory  it's larger than a byte (0..255) the FSRs are splitted in 2 registers for High byte of the address and Low byte of the address.

     SFR name   Address   Description
     =========================================
     FSR0H      0xFEA     High byte of FSR0 (address holder #0)
     FSR0L      0xFE9     Low byte of FSR0 (address holder #0)
     -----------------------------------------
     FSR1H      0xFE2     High byte of FSR1 (address holder #1)
     FSR1L      0xFE1     Low byte of FSR1 (address holder #1)
     -----------------------------------------
     FSR2H      0xFDA     High byte of FSR2 (address holder #2)
     FSR2L      0xFD9     Low byte of FSR2 (address holder #2)


   With these registers we can select any address on the chip. Example:

<JAL>
FSR0H == 0x00
FSR0L == 0x23  -- FSR0 = 0x023

FSR1H == 0x02
FSR1L == 0x44  -- FSR1 = 0x244

FSR2H == 0x0F
FSR2L == 0xFC  -- FSR2 = 0xFFC
</JAL>

<JAL>
assembler
    LFSR 0,0x0023  ; FSR0 = 0x023
    LFSR 1,0x0244  ; FSR1 = 0x244
    LFSR 2,0x0FFC  ; FSR2 = 0xFFC
end assembler
</JAL>


   In order to manage the data pointed by FSRs we have the INDFs registers. They have the following meaning:


   SFR name   Address      Description
   ===========================================
   INDF0      0xFEF        Uses the content of FSR0 to address
                           data memory. FSR0 not changed.

   POSTINC0   0xFEE        Uses the content of FSR0 to address
                           data memory. FSR0 is post-incremented by 1.

   POSTDEC0   0xFED        Uses the content of FSR0 to address
                           data memory. FSR0 is post-decremented by 1.

   PREINC0    0xFEC        Uses the content of FSR0 to address
                           data memory. FSR0 is pre-incremented by 1.

   PLUSW0     0xFEB        Uses the content of FSR0 and W as offset to
                           address data memory. FSR0 not changed.
   ----------------------------------------------------------------------
   INDF1      0xFE7        Uses the content of FSR1 to address
                           data memory. FSR1 not changed.

   POSTINC1   0xFE6        Uses the content of FSR1 to address
                           data memory. FSR1 is post-incremented by 1.

   POSTDEC1   0xFE5        Uses the content of FSR1 to address
                           data memory. FSR1 is post-decremented by 1.

   PREINC1    0xFE4        Uses the content of FSR1 to address
                           data memory. FSR1 is pre-incremented by 1.

   PLUSW1     0xFE3        Uses the content of FSR1 and W as offset to
                           address data memory. FSR1 not changed.
   ----------------------------------------------------------------------
   INDF2      0xFDF        Uses the content of FSR2 to address
                           data memory. FSR2 not changed.

   POSTINC2   0xFDE        Uses the content of FSR2 to address
                           data memory. FSR2 is post-incremented by 1.

   POSTDEC2   0xFDD        Uses the content of FSR2 to address
                           data memory. FSR2 is post-decremented by 1.

   PREINC2    0xFDC        Uses the content of FSR2 to address
                           data memory. FSR2 is pre-incremented by 1.

   PLUSW2     0xFDB        Uses the content of FSR2 and W as offset to
                           address data memory. FSR2 not changed.
   ----------------------------------------------------------------------


   Some examples:

<JAL>
-- Initialize the FSRs
assembler
    LFSR 0,0x0100  ; FSR0 = 0x100
    LFSR 1,0x0200  ; FSR1 = 0x200
    LFSR 2,0x0300  ; FSR2 = 0x300
end assembler

-- Store some value into 0x100..0x123, 0x200..0x223, 0x200..0x223.
-- 105 bytes changed with this loop:
for 0x23 loop   -- assigment
  POSTINC0 = 0x00  -- [FSR0]<-0x00 and then FSR0=FSR0+1
  POSTINC1 = " "   -- [FSR1]<-0x20 and then FSR1=FSR1+1
  POSTINC2 = 0xFF  -- [FSR2]<-0xFF and then FSR2=FSR2+1
end loop

-- Store some value into 0x101..0x124, 0x201..0x224, 0x201..0x224.
for 0x23 loop   -- assigment
  PREINC0 = 0x00  -- FSR0=FSR0+1 and then [FSR0]<-0x00
  PREINC1 = " "   -- FSR1=FSR1+1 and then [FSR1]<-0x20
  PREINC2 = 0xFF  -- FSR2=FSR2+1 and then [FSR2]<-0xFF
end loop

-- Store some value into 0x100, 0x200, 0x200.
-- the same value are written 35 times in the same address.
for 0x23 loop   -- assigment
  INDF0 = 0x00  -- [FSR0]<-0x00; FSR0 = 0x100
  INDF1 = " "   -- [FSR1]<-0x20; FSR1 = 0x200
  INDF2 = 0xFF  -- [FSR2]<-0xFF; FSR2 = 0x300
end loop
</JAL>





B.- SIGNED JUMPS

   In PIC_14 chips we have 2 diferent jumps: to an absolute label, or just skip the next mnemonic.

   In PIC_16 we have also signed jumps. This kind of jumps (used in mnemonics like "bra", "bc", "rcall", etc), are signed jumps (in 2's complement format) relatives to the current Program Counter. A note: as PC (program counter) counts in bytes instead of words, the labels are relative to words. That is, these signed jumps are multiplied by 2 and then added to the PC internally by the chip.

   In JAL those conversions between signed jumps and absolute jumps (refered to a label) are done automatically by the compiler. Example:


<JAL>
assembler
   local label01 , label02
   bsf status_c
   bra label02    ; Jump to label02. Coded as: bra H'001' (+1)
label01:
   bcf status_c
label02:
   movlw 0x10
   movwf myvar01
   bc label01    ; If carry jumps to label01. Coded as: bc H'FC' (-4)
end assembler
</JAL>


   Sequence:
      1.-   bsf status_c   ; Set carry
      2.-   bra label02    ; Jump to label02. PC+2+2n, n=+1
      3.-   movlw 0x10     ; Wreg<=0x10
      4.-   movwf myvar01  ; myvar01<=Wreg
      5.-   bc label01     ; Carry. Jump to label01. PC+2+2n, n=-4
      6.-   bcf status_c   ; clear Carry
      7.-   movlw 0x10     ; Wreg<=0x10
      8.-   movwf myvar01  ; myvar01<=Wreg
      9.-   bc label01     ; Not Carry. Continues without jump.


   The folloging mnemonics uses signed jumps, but we will use them with labels:

   Name     Description
   ======================
   BC       Branch if carry
   BNC      Branch if not carry
   BN       Branch if negative
   BNC      Branch if not negative
   Bz       Branch if zero
   BNZ      Branch if not zero
   BOV      Branch if overflow
   BNOV     Branch if not overflow
   BRA      Branch unconditionally
   RCALL    Relative call





C.- NEW MNEMONICS

   Please, read datasheets to know each one. But take care that "MOVFF" it's not implemented yet.


