Source file: /~heha/Mikrocontroller/LED-PWM.zip/MAKROS.I90

;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
Wrong umlauts? - Assume file is ANSI (CP1252) encoded