;h#s Makrosammlung 01/06
;Diese Makros sollen das Schreiben von Assemblerprogrammen erleichtern
;und unterstützen insbesondere 16-bit-Operationen.
;Die Endung "I90" ("Include für AT90-Architektur") statt "ASM" ermöglicht
;plattformspezifische Dateiverknüpfung und Syntaxhervorhebung.
;#########################
;## Register-Festlegung ##
;#########################
;R16 wird immer als allgemeines Arbeitsregister verwendet.
;Für die Arbeit mit schnellen Interruptserviceroutinen sowie allgemeinen
;Aufgaben sollten folgende Registerbereiche freigehalten werden:
;R20-R26, zumindest R22-R23, für alles, wo Konstantenvergleich oder
; Bitsetzoperationen vorherrschen (Bit-Register, UART_InChar u.ä.)
;R8-R15, zumindest R12-R15, für alles andere
; (Zähler, Software-PWM-Werte u.ä.)
;YH Es wird empfohlen, YH zur Adressierung der meisten "kleinen"
; Variablen permanent auf Null zu halten, dann genügt das Laden
; von YL in Interruptserviceroutinen usw.
; Der Zugriff auf memory-mapped Register des ATmega128
; (mit LDD/STD) verkürzt sich wesentlich.
; Für einige meiner Makros und Routinen ist YH=0 Voraussetzung!
;Faustregel: Globale Register, die in ISRs verwendet werden, dürfen
; niemals gePUSHt werden! (YH braucht nie gePUSHt zu werden.)
;Die Register R0-R7 sind für umfangreichere Mathematik unabdingbar;
; in R16-R19 ist schlicht zu wenig Platz.
;Als allgemeines Zeigerregister wird vorrangig Z verwendet.
; Weil LPM nur mit Z funktioniert, YH=0 festgelegt ist
; und X kein LDD/STD unterstützt.
#ifndef MAKROS_I90
#define MAKROS_I90
;################
;## IN und OUT ##
;################
;8-bit-Konstante auf Ausgabeport, benutzt R16
.macro outi ;Ausgabeport, Konstante
ldi r16,@1
out @0,r16
.endm
;16-bit-Konstante auf zwei Ausgabeports, benutzt R16
.macro outiw ;High-I/O, Low-I/O, Konstante
outi @0,HIGH(@2)
outi @1,LOW(@2)
.endm
;16-bit-Konstante auf ein Doppel-Ausgabeport mit Endungen "H" und "L", via R16
.macro outihl ;I/O-Präfix, Konstante
outiw @0H,@0L,@1
.endm
;16-bit-Zahl (2 Register) auf Doppel-Ausgabeport
.macro outhl ;I/O-Präfix, RegH,RegL
out @0H,@1 ;Erst High
out @0L,@2 ;Dann Low
.endm
;16-bit-Zahl (2 Register) von Doppel-Eingabeport
.macro inhl ;RegH,RegL, I/O-Präfix
in @1,@2L ;Erst Low
in @0,@2H ;Dann High
.endm
;################
;## Konstanten ##
;################
;Konstanten-Operationen für "unzugängliche" Register (<R16)
.macro i_ ;Op(ohne "i"), Reg, Konstante
ldi r16,@2
@0 @1,r16
.endm
;8-bit-Konstante in "unzugängliches" Register (<R16) laden, benutzt R16
.macro ldi_ ;Reg, Konstante
i_ mov, @0,@1
.endm
;16-bit-Konstante in zwei Register laden, Reg >= R16
.macro ldiw ;RegH,RegL, Konstante
ldi @0,HIGH(@2)
ldi @1,LOW(@2)
.endm
;16-bit-Konstante in Doppelregister mit "H" und "L" laden, wie ZH, ZL u.ä.
.macro ldihl ;Reg-Präfix, Konstante
ldiw @0H,@0L, @1
.endm
;#####################
;## Speicherzugriff ##
;#####################
;8-bit-Konstante speichern (via STD, nur mit Y oder Z möglich), benutzt R16
.macro stdi ;Speicherziel, Konstante
ldi r16,@1
std @0,r16
.endm
;16-bit-Konstante speichern (via STD, nur mit Y oder Z möglich), benutzt R16
.macro stdiw ;Speicherziel, Konstante
stdi @0+1,HIGH(@1)
stdi @0+0,LOW(@1)
.endm
;16-bit-Zahl speichern (via STD, nur mit Y oder Z möglich)
.macro stdw ;Speicherziel, RegH,RegL
std @0+1,@1 ;falls I/O, erst High-Teil
std @0+0,@2
.endm
.macro stdhl ;Speicherziel, Reg-Präfix
stdhl @0, @1H,@1L
.endm
;16-bit-Zahl lesen (via LDD, nur mit Y oder Z möglich)
.macro lddw ;RegH,RegL, Speicherquelle
ldd @1,@2+0 ;erst Low-Teil
ldd @0,@2+1
.endm
.macro lddhl ;Reg-Präfix, Speicherquelle
lddw @0H,@0L, @1
.endm
;###############
;## Schleifen ##
;###############
;Dekrementieren und springen (wie 8051)
.macro djnz ;Register, Sprungziel
dec @0
brne @1
.endm
;Doppelregister dekrementieren und springen
;Es wird empfohlen, R25:R24 als WH:WL zu .DEF-inieren.
.macro djnzhl ;Doppelregister, Sprungziel
subiw @0H:@0L,1
brne @1
.endm
;##############
;## Bit-Test ##
;##############
;Springe wenn Bit im Register gesetzt
.macro jbrs ;Register, Bitnummer, Sprungziel
sbrc @0,@1
rjmp @2
.endm
;Springe wenn Bit im Register gelöscht
.macro jbrc ;Register, Bitnummer, Sprungziel
sbrs @0,@1
rjmp @2
.endm
;Springe wenn Bit im Eingabeport gesetzt
.macro jbis ;Port, Bitnummer, Sprungziel
sbic @0,@1
rjmp @2
.endm
;Springe wenn Bit im Eingabeport gelöscht
.macro jbic ;Port, Bitnummer, Sprungziel
sbis @0,@1
rjmp @2
.endm
;################
;## Mathematik ##
;################
;Negation mit eingehendem Übertrag, R16 wird zerstört
.macro negc ;Register
ldi r16,0
sbc r16,@0
mov @0,r16
.endm
;Addition einer Null mit Übertrag, YH=0 ist Voraussetzung!
.macro adc0 ;Register
#if 1
adc @0,YH
#else
adc @0,r16 ;Problem: C wird nicht korrekt durchgereicht!
sub @0,r16
#endif
.endm
;Addition einer Konstanten
.macro addi
subi @0,-(@1)
.endm
;Konvertiere "char" zu "short" (Byte zu Wort) vzb.
.macro cbw ;RegH,RegL
lsl @1 ;Vorzeichenbit ausschieben (C)
sbc @0,@0 ;0 oder FF draus machen, C unverändert
lsr @1 ;C zurück
.endm
;Konvertiere "short" zu "long" (Wort zu DWord) vzb.
.macro cwd ;Reg3,Reg2,RegH,RegL
lsl @2 ;das gleiche Strickmuster, RegL wird nicht verwendet
sbc @1,@1
sbc @0,@0
lsr @2
.endm
;Konvertiere "char" zu "long" (Byte zu DWord) vzb.
.macro cbd ;Reg3,Reg2,RegH,RegL
lsl @3
sbc @2,@2
sbc @1,@1
sbc @0,@0
lsr @3
.endm
;Vorzeichenlose Erweiterungen sind keine Makros wert!
;Einfach High-Bytes nullsetzen.
#endif
Detected encoding: ANSI (CP1252) | 4
|
|