Atypical Language Reference

Introduction

Atypical is an experimental assembly language for the PICmicro family of microcontrollers (14-bit core only: 16f84, 16f628, 16f877, etc). It uses a vaguely pseudo-C-like syntax instead of opcode mnemonics, so rather than writing, for example,

	MOVF a, 0
	ANDWF b, W
	XORLW 0xf0
	MOVWF c

you can write

	w = a
	w = w & b
	w ^= 0xf0
	c = w

or even

	w += a, & b, ^ 0xf0, => c

The most important thing to remember about Atypical is that it is an assembly language, not a high-level language. There is a one-to-one correspondence between Atypical statements and PICmicro instructions. For example, this Atypical assignment,

	w = 42
is exactly equivalent to
	movlw 42
This next assignment, however,
	PORTA = 42
is not allowed because there is no "move immediate to file register" instruction. In regular assembly language, you would have to use two instructions:
	movlw 42
	movwf PORTA
In Atypical, you would use the same two instructions, just notated a little differently:
	w = 42, => PORTA

Familiarity with the PICmicro instruction set is a requirement for using Atypical.

Atypical is case-sensitive. Whitespace between symbols is generally unimportant, but line-breaks are significant. Comments start with // and continue to the end of the line.

    w=  PORTA  ;call     Process	// weird spacing doesn't matter.
  call   process // Process and process are different subroutines.

Instruction set in Atypical notation

The following tables list the PIC instructions and their Atypical equivalents. In the tables, k refers to a constant expression, f refers to a variable, and b is a bit number (a constant expression in the range 0 to 7 inclusive).

The columns labeled Focus and Implicit form contain information needed when comma-splicing multiple instructions on one line.

Literal and control instructions

PICmicro instruction Atypical equivalent Focus Implicit form

addlw k

w += k

w = w + k

w = k + w

w

+ k

k +=> w

k

+=> w

w -= k1

w = w - k

w

- k

andlw k

w &= k

w = w & k

w = k & w

w

& k

k &=> w

k

&=> w

call label

call label

   

clrwdt

clrwdt

   

goto label

goto label

goto { label1, label2, .. labeln }2

   

iorlw k

w |= k

w = w | k

w = k | w

w

| k

k |=> w

k

|=> w

movlw k

w = k

w

 

k => w

k

=> w

retfie

retfie

   

retlw k

retlw k

retlw { k1, k2, .. kn }2

   

return

return

   

sleep

sleep

   

sublw k

w = k - w

w

 

k -=> w

k

-=> w

xorlw k

w ^= k

w = w ^ k

w = k ^ w

w

^ k

k ^=> w

k

^=> w

1 These "subtraction" instructions actually add the 2's complement of k, so
	w -= 1
is really
	addlw 255

Byte-oriented instructions

PICmicro instruction Atypical equivalent Focus Implicit form

addwf f,0

w += f

w = w + f

w = f + w

w

+ f

f +=> w

f

+=> w

addwf f,1

f += w

f = f + w

f = w + f

f

+ w

w +=> f

w

+=> f

andwf f,0

w &= f

w = w & f

w = f & w

w

& f

f &=> w

f

&=> w

andwf f,1

f &= w

f = f & w

f = w & f

f

& w

w &=> f

w

&=> f

clrf f

clr f

f

clr

clrw w

clr w

w

clr

comf f,0

w = ~ f

w

 

comf f,1

f = ~ f

~ f

f

~

decf f,0

w = --f

w

 

decf f,1

f = --f

--f

f

--

decfsz f,0

if w = --f == 0 then skip

if !w = --f then skip

   

decfsz f,1

if --f == 0 then skip

if !--f then skip

   

incf f,0

w = ++f

w

 

incf f,1

f = ++f

++f

f

++

incfsz f,0

if w = ++f == 0 then skip

if !w = ++f then skip

   

incfsz f,1

if ++f == 0 then skip

if !++f then skip

   

iorwf f,0

w |= f

w = w | f

w = f | w

w

| f

f |=> w

f

|=> w

iorwf f,1

f |= w

f = f | w

f = w | f

f

| w

w |=> f

w

|=> f

movf f,0

w = f

w

 

f => w

f

=> w

movf f,1

f = f

f => f

f

=> f

movwf f

f = w

f

= w

w => f

w

=> f

nop

nop

   

rlf f,0

w = rol f

w

 

rlf f,1

f = rol f

rol f

f

rol

rrf f,0

w = ror f

w

 

rrf f,1

f = ror f

ror f

f

ror

subwf f,0

w = f - w

w

 

f -=> w

f

-=> w

subwf f,1

f = f - w

f -= w

f

- w

swapf f,0

w = swap f

w

 

swapf f,1

f = swap f

swap f

f

swap

xorwf f,0

w ^= f

w = w ^ f

w = f ^ w

w

^ f

f ^=> w

f

^=> w

xorwf f,1

f ^= w

f = f ^ w

f = w ^ f

f

^ w

w ^=> f

w

^=> f

Bit-oriented instructions

PICmicro instruction Atypical equivalent Focus Implicit form

bcf f,b

f<b> = 0

f

<b> = 0

bsf f,b

f<b> = 0

f

<b> = 1

btfsc f,b

if f<b> == 0 then skip

if f<b> != 1 then skip

if !f<b> then skip

   

btfss f,b

if f<b> == 1 then skip

if f<b> != 0 then skip

if f<b> then skip

   

Combining instructions

When a series of Atypical instructions share a common operand (called the focus for lack of a better term), they can be "comma-spliced" together on one line. The focus is typically the left-hand side of assignment-operator instructions. Example:
	w = var1	// focus is w
	w += 3		// focus is w
	w = w & 0x0f	// focus is w
All three instructions have w as their focus, so they can be written
	w = var1, + 3, & 0x0f

Note that instructions after the comma are written in implicit form, as listed in the instruction set tables.

Sometimes you have to reverse left- and right-hand sides before comma-splicing:
	w = var1	// focus is w
	w = w & 0x0f	// focus is w
	PORTA |= w	// focus is PORTA
becomes
	w = var1
	w = w & 0x0f
	w |=> PORTA   // same as previous code, but now the focus is w
which can be rewritten like this:
	w = var1, & 0x0f, |=> PORTA
Some instructions are notated as unary operators in Atypical; their focus is their operand:
	--var1		// focus is var1
	com var1	// focus is var1
	clr var1	// focus is var1

	--var1, com, clr // the preceding instructions comma-spliced
The focus of the bit set and clear instructions is the file register:
	PORTA<0> = 1	// focus is PORTA
	PORTA<7> = 0	// focus is PORTA

	PORTA<0> = 1, <7> = 0 // comma-spliced equivalent
Some instructions have no operand to be the focus; those instructions can be combined on one line with semicolons in between:
	nop; nop; nop;
You can mix and match:
	w = var1, com; call DoSomething; w &= 0x7f, => var2

Variables

Variables in Atypical correspond to file registers. They are defined with the byte keyword and are allocated consecutively starting with the register specified in the varorg pseudo-op.
	varorg 0x20
	byte x          // x is file register 0x20
	byte a, b, c	// a is 0x21, b 0x22, c 0x23
You can also specify file registers explicitly:
	varorg 0x20
	byte PORTA  : 0x05  // PORTA is file register 0x05
	byte PORTB  : 0x06  // guess what
	byte x              // x is 0x20
You can define arrays:
	varorg 0x20
	byte a[3]  // a[0] is 0x20, a[1] is 0x21, a[2] is 0x22
	byte b     // b is 0x23
Indirect addressing is done either the traditional way, through INDF,
	w = INDF   // movf 0, w
or with the special notation @FSR, which assembles to exactly the same thing:
	w = @fsr   // movf 0, w

The @ is supposed to be reminiscent of C's * dereferencing operator, and thus is supposed to indicate indirection through the FSR file register. @ can only be followed by "fsr" (case-insensitive).

Note: Forward references to variables and constants are not allowed.

Constants

Constants are either literals,
	w = 15     // decimal
	w = 0x0f   // hex
	w = 0b1111 // binary
	w = 'A'    // ASCII
or named constants defined with the const keyword:
	const max_len = 100
You can form constant expressions with +, -, *, /, &, |, ^, <<, and >>. These all have equal precedence, so use parentheses to change the order of evaluation.
	const recsize = 3, numrecs = 10
	const buffsize = 1 + (recsize * numrecs)
Note that if you use a constant expression in an instruction, you must enclose the expression in parentheses:
	w = w + recsize		// plain constant doesn't need parentheses
	w = w + (recsize * 2)	// constant expression needs parentheses
You can use the # operator to make a constant equal to the address of a label or variable:
	varorg 0x20
	byte a
	w = (#a), => fsr	// put address of a into FSR (note parentheses around constant expression)
	w = a, => fsr		// put contents of a into FSR
The symbol $ is the address in program memory where the next assembled instruction will go. It's not really a constant, but it can be used as one.

Control flow

Labels

A label can be the target of a goto or call instruction. A label may be placed on any line that isn't a pseudo-op. The label can start in any column but it must be the first non-blank sequence on the line (in other words, any instructions on that line must come after the label).

infinite_loop:		// here's a label (infinite_loop)
	call do_something
	goto infinite_loop

    do_something: w = PORTA	// another label (do_something)
	// etc etc

Local labels are labels that begin with the . (dot) character. Local labels need be unique only within their scope; local labels may be redefined in other scopes. A non-local (global) label starts a new scope. Within its scope, a local label can be referred to as itself; outside its scope, a local label can be referred to by prepending the global label to the local label.

Blah:	goto Foo.0	// forward reference to local label in Foo

Foo:			// global label Foo starts new scope
	...
.0:	...		// local label (Foo.0)
	goto .0

Bar:	...		// start new scope (Bar)
.0:	...		// this .0 doesn't conflict with previous one
	goto .0
.zzz:	...		// local labels can be alphanumeric

Variables and constants may also be local to a scope. Note that global variables and constants do not start new scopes.

Foo:	byte .i		// local variable Foo.i
	byte Total	// global variable doesn't start new scope
	const .max=10	// local variable Foo.max
	byte .0		// ERROR: only local labels may be numeric

Basic control flow

The basic Atypical notation for the conditional instructions is of this general form:

	if condition then skip
where condition is a bit test or a decrement (or increment) and test against zero (see the instruction set tables).

However, the basic form is rarely used; far more common is the one-liner if, in which the condition is negated and the instruction that would have followed the if is instead incorporated into the same line. For example,

	if STATUS then skip
	goto nonzero
is more clearly expressed as this one-liner:
	if !STATUS then goto nonzero  // exactly the same machine code as above
or
	if STATUS==0 then goto nonzero
The one-liner if is not restricted to goto instructions:
	if !STATUS then ++Count
Any single instruction can follow the then.

Structured control flow

One can use the basic Atypical conditionals (or the one-liner if) along with the goto instruction and explicit labels to emulate the unstructured control flow typical of assembly language programming; however, Atypical also provides structured if/then/else and looping constructs. These reduce spaghetti code and make program flow more understandable, but their translation into machine code is less transparent than the standard PICmicro instructions.
Atypical Assembly language
if condition then
    ...
endif
	btfsc/btfss/decfsz/incfsz (condition)
	goto  .endif_label
	...
.endif_label:
if condition then
    ...
else
    ...
endif
	btfsc/btfss/decfsz/incfsz (condition)
	goto  .else_label
	...
	goto  .endif_label
.else_label:
	...
.endif_label:
if condition1 then
    ...
elseif condition2 then
    ...
// there can be multiple elseif clauses
else
    ...
endif
	btfsc/btfss/decfsz/incfsz (condition1)
	goto  .elseif_label
	...
	goto  .endif_label
.elseif_label:
	btfsc/btfss/decfsz/incfsz (condition2)
	goto  .else_label
	...
	goto  .endif_label
.else_label:
	...
.endif_label:
// infinite loop
do
    ...
loop
.do_label:
	...
	goto do_label
// loop (test at top)
while condition do
    ...
loop
	goto .test
.do_label:
	...
.test:	btfsc/btfss/decfsz/incfsz (!condition)
	goto .do_label
// loop (test at bottom)
do
    ...
loop while condition
.do_label:
	...
.test:	btfsc/btfss/decfsz/incfsz (!condition)
	goto .do_label

You can also use break to exit a loop, and continue to jump directly to the next iteration of a loop.

Control-flow structures can, of course, be nested.

Atypical does not perform any optimizations; the various program-flow constructs always generate the code described above.

Note that, because decfsz and incfsz do not have "skip on non-zero" counterparts, you must choose your conditions carefully when decrementing or incrementing. Some constructs require that you test for equality to 0; others for inequality.

Atypical construct Examples of suitable conditions

explicit skip form; if/then (not one-liner if)

--f == 0 (test for 0)

!w = ++f

one-liner if; while loops

++f != 0 (test for non-0)

w = --f

Jump tables and lookup tables

Jump tables are formed by following a goto with a list of labels surrounded by braces:
	goto  { .0, .1, ErrorHandler }
	// equivalent to goto .0; goto.1; goto ErrorHandler
Similarly, lookup tables are formed by following a retlw with a list of constants surrounded by braces:
	retlw { 10, 0xff, 'y' }
	// equivalent to retlw 10; retlw 0xff; retlw 'y'
Lookup tables can also contain string constants:
	retlw { "Hello, world!", CR, LF, 0 }
The assembler does not check for page boundary crossings. You can implement such a check with the assert pseudo-op:
.table:	retlw { "0123456789abcdef" }
	assert ($-1>>8) == (#.table>>8)

Pseudo-ops

Pseudo-op Description

assert const_expr

Generates a warning if const_expr is false (zero). Example:

	assert ($-1>>8) == (#.table2>>8)

bank const_expr

Specifies the bank that the program is supposed to be accessing. Example:

	byte TRISA  : 0x85 // TRISA is in bank 1
	...
	STATUS = 1    // ready to access bank 1
	bank 1		   // let Atypical assembler know
			   // (otherwise we'll get a warning)
	TRISA = 0

byte var_list

Defines variables. Example:

	byte a, TRISA:0x85, buff[10]

config const_expr

Specifies the configuration byte. Example:

	config _WDT_OFF & _INTRC_OSC_CLKOUT

const const_list

Defines named constants. Example:

	const height=50, width=20

include "filename"

Includes the named file. Typically used for processor-specific header files. Example:

	include "p16f877.aty"

list

Enables output to the listing file.

nolist

Disables output to the listing file.

org const_expr

Specifies the location in program memory where the next instruction will be assembled. Example:

	org 0x0100

varorg const_expr

Specifies the starting file register for variables. Example:

	varorg 0x20

Reserved words

The following words are reserved and cannot be used for variables, constants, or labels.

Atypical else retlw
assert elseif return
bank endif rol
break goto ror
byte if skip
call include sleep
clr list swap
clrwdt loop then
config nolist varorg
const nop w
continue org W
do retfie while

-------------------------------------------------- Paid Advertisement Links Below --------------------------------------------------
Checks By Phone | Verify a Check | Reorder Checks | Routing Number | Check Verification
| BIN Database |
| Recycle Food Waste Boston | Check By Phone Software Reviews | Short Term Furnished Allston | SWIFT Code Database |