COMP 4550 AVR-GCC Inline Assembler
Autonomous Agents Lab, University of Manitoba [email protected] http://www.cs.umanitoba.ca/~jacky http://aalab.cs.umanitoba.ca AVR-GCC Application Binary Interface (ABI)
● Data types: ○ char is 8 bits, ○ int is 16 bits, ○ long is 32 bits, ○ long long is 64 bits, ○ float and double are 32 bits (this is the only supported floating point format) ● include
● asm introduces inline asm("\n\ assembler mov %0, %1 \n\ ● Assembly code is single lsr %0\n\ string constant " : "=r" (result) ● Use line continuation to : "r" (value) format ● %0,%1 correspond to ); pseudo registers, which are mapped by the compiler ● Correspond to input, output, clobber registers ● List of output operands (e.g., result) ● List of input operands (e.g., value) General Form
● General form ○ asm(code : output operand list : input operand list : clobber list); ● Input ○ registers that provide values to your code ● Output ○ registers that specify result of your expression ● Clobber ○ registers that are changed because of your code, outputs are always clobbered Volatile
● asm volatile instructs the compiler not to do any optimizations ● Must have at least two colons ● clobber list may be left off ● Special registers ● __SREG__(PORTE) - Port ● __SP_H__,__SP_L__ - Stack pointer ● __tmp_reg__ - R0 tmp variable, no need to restore ● __zero_reg__ - R1 always 0
asm volatile("cli"::); Register Constraints
● a simple upper register R16 to R23 ● b base pointer pair, y,z ● d upper register R16 to R31 ● e pointer register pairs x,y,z ● G floating point constant ● I,J 6 bit positive/negative constant ● t – temporary register ● K/L/N/O/P integer constants 0/2/-1/8,16,24/1 ● w – special upper reg ● l lower register ● x/y/z – pointer x,y,z ● M 8 bit constant ● q Stack pointer register SPH:SPL ● r Any register AVR-GCC Inline Assembler
● Read/write register values ● Can specify a digit to refer to previous register ○ asm volatile("swap %0" : "=r" (value) : "0" (value)); ● Read only registers
asm volatile("in %0,%1\n\t" "out %1, %2\n\t" : "=&r" (input) : "I" (_SFR_IO_ADDR(port)), "r" (output)); Register Swap asm volatile("\t mov __tmp_reg__, %A0\n\" "\t mov %A0, %B0\n\" "\t mov %B0, __tmp_reg__\n\" ● 16 bit swap : "=r" (value) ○ %A0 upper 16 bit : "0" (value) ○ %B0 lower 16 bit ); ● 32 bit swap asm volatile("\t mov __tmp_reg__, %A0\n\" ○ %A0..%D0 "\t mov %A0, %D0\n\" ○ %A1..%D1 "\t mov %D0, __tmp_reg__\n\" "\t mov __tmp_reg__, %B0\n\" "\t mov %B0, %C0\n\" "\t mov %C0, __tmp_reg__\n\" : "=r" (value) : "0" (value) ); X,Y,Z Pointers
● Register pairs X,Y,Z are specified by the “e” constraint ● Z %A0=R30, %B0=R31 ● How to create the original register pair ○ ld r24,Z ○ ld r24, %a0 ; Note lower case “a” Clobber Registers
● Clobbers specify registers that are modified ● Atomic increment ● No input operand asm volatile( "\t cli\n\" ● Synchronization "\t ld r24, %a0\n\" ○ store value in memory "\t inc r24\n\" ● Better to use __tmp_reg__ "\t st %a0, r24\n\" ● Specify R24 as clobbered "\t sei\n" : ● Memory clobbers : "e" (ptr) ● *ptr is also changed : "r24" ● special clobber “memory” ); ○ will reload everything ● Better specify ptr as volatile Labels
● C Stub functions to hold temporary variables etc. ● L_dl1%= creates label void delay(uint8_t ms) { uint16_t cnt; ● cnt used as tmp reg asm volatile ( ● Can also unix label syntax "L_dl1%=:\n\" ● 1:/2: brne 2b "\t mov %A0, %A2\n\" "\t mov %B0, %B2\n\" "L_dl2%=:\n\" "\t sbiw %A0, 1\n\" "\t brne L_dl2%=\n\" "\t dec %1\n\" "\t brne L_dl1%=\n\" : "=&w" (cnt) : "r" (ms), "r" (delay_count) ); } Names
● Names used by the assembler can be defined by the C program ○ unsigned long value asm("clock") = 3686400; ● C uses value, assembler uses clock ● Specify register ○ register unsigned char counter asm("r3"); ● Functions ○ extern long Calc(void) asm ("CALCULATE");