Compiler Insights

This section provides some insights into what the compiler does.

How does the compiler cope with read-only registers in the Chip Family 12 range?

Within this chip range, the Option register is a write-only register. Reading the register is not permitted.

GCBASIC needs to update this when the user wants to change the configuration - the Sleep process is an example of a user change.

The compiler handles this by creating the Option_reg byte variable. This byte is created by the compiler to manage the required write process.

The Option_reg variable is a cache that the compiler will create if any bits of option_reg have been set manually.

If the user changes any of the bits in a program, then the compiler will find any uses of the option instruction and insert a movwf OPTION_REG immediately before the option instruction to cache the value in the buffer.

If Option_reg bits are not set individually anywhere, then option_reg does not get created, and nothing special is done with the option instruction.

Essentially the compiler maintains a special variable and manages the whole process without the user being aware of it.

How does the compiler cope with the TRIS register in the 10F products?

The compiler ensures that a TRIS cache matches the actual TRIS register. The TRIS cache is a byte variable called TRISIO. The TRISIO cache is required, as TRIS is a write-only register.

All ports default to input (where all TRIS bits are 1) on reset. Therefore, this is assumed to be the value 255.

TRISIO is updated when required by the user code, and then used when writing to the correct register.

The example user code and the associated assembly below show the TRISIO cache in use. This method complies with the datasheet.

User Code

    'set as input
    dir gpio.0 in          ' <<< the Dir instruction that triggers the TRISIO cache update
    gpio0State = gpio.0
    'set as output this will require TRIS GPIO to be set using the TRISIO cache.
    dir gpio.0 out
    gpio.0 = 1

Key line: dir gpio.0 in — since GPIO on the 10F range has no readable TRIS register, this Dir statement is compiled by updating the cached TRISIO variable and writing that cache out to the real TRIS register with tris GPIO, rather than reading-modifying-writing TRIS directly.

ASM

    ;dir gpio.0 in
      bsf TRISIO,0
      movf  TRISIO,W
      tris  GPIO
    ;gpio0State = gpio.0
      clrf  GPIO0STATE
      btfsc GPIO,0
      incf  GPIO0STATE,F
    ;dir gpio.0 out
      bcf TRISIO,0
      movf  TRISIO,W
      tris  GPIO
    ;gpio.0 = 1
      bsf GPIO,0

Anywhere that an individual TRIS bit is set or cleared by changing the port direction, the bit in the cache is changed and then that value gets written to the TRIS register.

Forcing the ASM to contain comments

It may be useful to force comments into the ASM file. The verbose mode of creating the ASM will include all of the source program as comments, but it may be useful to have specific comments in the ASM to aid the understanding of code or to support debugging.

To force an assembly comment, use the following:

    asm showdebug  `comment`

Where comment will be placed into the ASM file.

Example.

The source file contains the following, where the comment text is OSCCON type is 100:

    asm showdebug OSCCON type is 100
    OSCCON1 = 0x60

The generated assembly will be as follows - this assumes verbose mode is not selected.

    INITSYS
    ;osccon type is 100
      movlw 96
      banksel OSCCON1

Constants, variables, subs, functions, and labels

GCBASIC uses a single namespace. A namespace is the set of names used to identify and refer to objects of various kinds. In GCBASIC these can be constants, variables, methods, and labels, where a label is a true label like the start of a sub, function, or macro. A namespace ensures that all of a given set of objects have unique names, so that they can be identified. This organises constants, variables, methods, labels, etc. into a single list - the single namespace.

The namespace includes all libraries and source GCBASIC source files. If using MPASM, this expands to the chip-specific INF file. If using PIC-AS, then all of the PIC-AS toolchain, including non-chip-specific files. There are changes already in place to resolve an issue with PIC-AS, since HEX and LINE are reserved with the PIC-AS toolchain and these conflict with GCBASIC methods. These are automatically resolved by the GCBASIC compiler.

So, given that constants, variables, methods, and labels, etc. are all names, the compiler does not know whether a given name refers to a constant, a variable, a method, or a call to a label. Some use cases follow, using a constant called NORMAL. NORMAL is defined as a constant with the value 0.

#1. Code segment

  #DEFINE NORMAL 0
  CALL Normal

The compiler will issue no error. The compiler will assume the following and will do as instructed. Call normal - this calls normal, which has a value of 0.

Resulting ASM

  ;CALL Normal
  call 0

#2. Code segment

  #DEFINE NORMAL 0
  CALL Normal()

The compiler will issue no error. The compiler will assume the following and will do as instructed. Call normal() - this calls normal, which has a value of 0.

Resulting ASM

    ;CALL Normal()
    call 0

#3. Code segment

  #DEFINE NORMAL 0
  Normal

The compiler will issue an error message. The compiler will try to resolve the constant normal to a sub, but it cannot, as it has a value of 0.

Resulting ASM

    ;Normal
    0 ;?F1L8S0I8?

#4. Code segment

  #DEFINE NORMAL 0
  Normal()

The compiler will issue an error message. The compiler will try to resolve the constant normal to a sub, but it cannot, as it has a value of 0.

Resulting ASM

    ;Normal()
    0() ;?F1L8S0I8?

#5. Code segment

  #DEFINE NORMAL 0
  Normal = 1

The compiler will issue an error message. This tries to assign a value to the object.

Resulting ASM

  ;Normal = 1
  0 = 1

#6. Code segment

  #DEFINE NORMAL 0
  Goto normal

The compiler will not issue an error message. The compiler will goto (the same applies to jmp) to the value of the object.

Resulting ASM

    ;goto Normal
    goto 0

See Also:

  • Compiler Control — redirecting the startup/initialisation routines discussed above
  • #DEFINE — the directive used throughout these examples
  • Dir — setting a pin’s direction, as used in the TRISIO example