pacito LMM Assembler
--------------------

(c) 2007-2008 Pacito.Sys - distributed under the terms of the GNU Public licence v 2.0

-------------

Section 1 - Using the assembler
---------


This section explains how to use the assembler.

A suitable source file (extension lmmpasm) contains a full source of HUB memory
in assembler. Spin is not yet supported, but do not despair, because you chose
LMM for some reason.

The source file is divided in several sections, these sections are useful to 
tell the assembler how to process the symbols. As the propeller is a multi-
processor arquitechture and Spin is not possible in the source file, a bit of
magic is needed. 
The sections are LMM, HUB and COG. 
LMM is a section that has a flat address space with no limits in size. Only
symbols defined in this section can be used. It is useful for LMM programs that
run in a VM or LMM kernel. These programs can be mixed wih the rest of the 
sections but beaware that the HUB has only 32 kbytes.

HUB is the section that contains the whole source
and implies that all symbols defined within its boundaries are HUB addresses, 
and global. COG is a section with COG addresses, all symbols within are COG
addresses. A duplicate symbol in HUB address space is generated with the .global
directive.
Be aware that the name space is shared.

example.lmmpasm

.section HUB hub

' we instruct the compiler to emit the spin bytecode to load cog 0 with starting
' address cog0addr, Spin interpreter overwritten with program at addr cog0addr

        slaunch0 cog0addr

' here are valid HUB addresses




' now we start a new section, all symbols now belog to the section "cog0"
' global symbols should be made global explicitly

.section COG cog0

.global cog0addr    

        mov     _a,#500
        shl     _a,#16      ' PAR
        mov     _b,cog1addr
        shl     _b,#3
        or      _a,_b
        or      _a,#4
        coginit _a,#0       ' we start a new cog at address cog1addr with PAR = 500
        
localsym        
        nop
        jmp     localsym        ' this symbol is local to cog0 section (addr $003)

cog1a   long    cog1addr        ' reference to symbol in HUB section
_a      long    0
_b      long    0

' now we ca change the section
.section HUB hub


...

.section COG cog1
.global cog1addr

...


****


As we see in the example these are a bit complicated, but not bad.

Addresses:

In a HUB section all addresses are at byte
In a COG section all addresses are to longs, global addresses are to bytes, though.

Section 2 - Special fatures that make this assembler different from Parallax's
---------

Directives they instruct the compiler to perform a certain action

.align <power_of_two> 

Useful to align the next usable address to a specific boundary. As COG memory 
is long aligned, it must start at a long boundary, padding should be explicitly 
added.

.global <symbol>

Declares symbol as global, useful in a COG section, global symbols are byte 
aligned.

.section <COG|HUB|LMM> <name>

Instructs the compiler to change the behaviour of symbol creation: COG sections
have long aligned symbols and every address is to a long. Special HUB 
instructions can use global addresses declared with constants of with global
symbols.

.include <path_to_file>

Includes a file to be compiled. All normal rules apply

.macro <name> [args]/.endm

Starts/terminates a macro definition. The name must be unique because shares the
namespace of other symbols treated as macros, not as normal symbols. Arguments
are optional and are passed directly to the first pass.

Arithmetic expressions

Normal arithmetic expressions like (3*4)<<2, are evaluated and can be placed at
any point expectic a number or symbol (not as destination of call though, use 
jmpret instead). Please do not use any Parallax specifics like |<2 or similar,
they are not implemented.

Bootstrap

The Propeller expects that in HUB RAM, after loading the EEPROM to internal RAM
a valid bootstrap be present. Taken from Mike Green's post at the parallax forums
website.

        Minimal Spin bootstrap code for assembly language launch
        --------------------------------------------------------
        $0000: HZ HZ HZ HZ CR CS 10 00 LL LL 18 00 18 00 10 00
        $0010: FF FF F9 FF FF FF F9 FF 35 37 04 35 2C -- -- --
        $0020: your assembly code starts here - loaded into COG #0

        elaboration:
        $0000: HZ HZ HZ HZ - internal clock frequency in Hz (long)
        $0004: CR          - value to be written to clock register (byte)
        $0005: CS          - checksum so that all RAM bytes will sum to 0 (modulus 256)
        $0006: 10 00       - 'pbase' (word) must be $0010
        $0008: LL LL       - 'vbase' (word) number of longs loaded times 4
        $000A: 18 00       - 'dbase' (word) above where $FFF9FFFF's get placed
        $000C: 18 00       - 'pcurr' (word) points to Spin code
        $000E: 10 00       - 'dcurr' (word) points to local stack
        $0010: FF FF F9 FF - below local stack, must be $FFF9FFFF
        $0014: FF FF F9 FF - below local stack, must be $FFF9FFFF
        $0018: 35          - push #0   (long written to $0010)
        $0019: 37 04       - push #$20 (long written to $0014)
        $001B: 35          - push #0   (long written to $0018)
        $001C: 2C          - COGINIT(0, $20, 0) - load asm code from $20+ into same COG #0
        $001D: -- -- --    - filler
        $0020: XX XX XX XX - 1st long of asm program to be loaded into COG #0
        $0024: XX XX XX XX - 2nd long of asm program to be loaded into COG #0
        $0028:             - rest of data

        Note: 'vbase' is the total number of bytes loaded.  If valid, the IDE
        will load the binary file and transfer it to a Propellor.
     

The address pushed at $0019 is used to launch COG 0 (the one running the SPIN
interpreter) with an ASM program. This preamble must be at address 0 to precede
any other instruction. 


Section 3 - LMM
---------

To sucessfully implement LMM a series of caveats have to be taken in account:

- All asm instructions expect numbers between 0 and 511. 
- Jumps and calls are macros with traps to a kernel.
- Loading of data is performed using macros.
- Conditionals are supported.
- Aligment of instructions should be observed.

The file pacitolmm.lmmpasm has a series of macros and a LMM kernel suitable to
use the whole HUB memory as program memory.

This first implementation is a subset of my original Design notes.

To start using the LMM the file pacitolmm.lmmpasm should be included at the top
of your file, but after the required bootstrap code. Modify the bootstrap to 
launch the lmm kernel using the symbol plmmkernetstart. Your program has to 
declare the starting point with lmmstart.
The kernel supports the following new instructions:
All these instructions support conditionals


    li    <reg>,<32bit constant>

loads a register (0 to 15) with a 32 bit long (2 to 3 longs long)

    push  <reg>

pushes reg into the stack (2 longs)

    pop   <reg>

pops reg from the stack (2 longs)
    
    lcall <addr>

Calls a subroutine, pushes next PC onto the stack (2 longs)

    ljmp  <addr>

Jumps to addr (2 longs)

Registers are called kr0 to kr15. kr14 has the stack pointer and kr15 has the pc.
Flags are handled automatically. Control transfer instructions jmp, call, ret,
jmpret, tjz, tjnz, djnz are not to be used. The code is half interpreted so no
reliable operation can be expected from those instructions. 




Multiline comments
------------------

Comments that are enclosed in curly braces {}. They can be in the same line or span
multiple lines. When thy span multiple lines... lines are concatenated!!

So
    mov {comment} a,b
Produces the same result as
    mov {comment
in two lines}a,b














