Forum: Mikrocontroller und Digitale Elektronik ATmega asm - schon mal CPSE benutzt?


von Alexander V. (avogra)


Lesenswert?

Hey,

ich bin grad schon wieder zum X-ten mal über den Befehl CPSE gestolpert. 
Ich hab mich riesig gefreut, was der alles auf einmal macht - um dann 
festzustellen, dass er für mich genau falsch rum ist.

CPSE vergleicht zwei Register und überspringt den nächsten Befehl, wenn 
beide Register gleich sind.

ich hätt schon oft ein CPSN oder noch besser: CPISN gebraucht. Also dass 
der nächste Befehl übersprungen wird, wenn die beiden Register NICHT 
gleich sind bzw. wenn ein Register und eine Konstante ungleich sind. 
Auch ein TSTSN würd ich oft hernehmen, also Befehl überspringen, wenn 
ein Register nicht 0 ist.

Tragisch ist es natürlich nicht, dann muss ich eben 2 Befehle benutzen.

Aber irgendwie wundert mich, dass Atmel genau den Befehl implementiert 
hat, der zumindest meiner Meinung nach der nutzloseste der genannten 
Varianten ist.

Nimmt den von euch wer her und ich bin einfach noch nicht drauf 
gekommen, wie ich ihn richtig einsetz?

Grüße, Alex

von (prx) A. K. (prx)


Lesenswert?

Der ist möglicherweise speziell für Funktionen wie strncpy/memchr... 
vorgesehen, die sowohl einen Zähler als auch einen Wert als 
Abbruchbedingung haben. Läuft dann raus auf sowas wie:

l1: ld   r1,x+
    dec  r2
    cpse r1,r0
    brne l1

von Michael U. (amiga)


Lesenswert?

Hallo,

Alexander v. Grafenstein schrieb:
> Hey,
>
> ich bin grad schon wieder zum X-ten mal über den Befehl CPSE gestolpert.
> Ich hab mich riesig gefreut, was der alles auf einmal macht - um dann
> festzustellen, dass er für mich genau falsch rum ist.
>
> CPSE vergleicht zwei Register und überspringt den nächsten Befehl, wenn
> beide Register gleich sind.

komisch, geht mir genauso, ich ignoriere ihn seitdem eigentlich meist... 
;-)

In bestimmten Schleifen macht er Sinn, wenn der übersprungene Befehl 
dann der rjmp zum Schleifenanfang ist.

ldi r16, 0x55 ; als Vergleichswert
loop:

in r17,PORTB
cpse r16,r17
rjmp loop

...

loop:
in r17,PORTB
cpi r17,0x55
brne loop

macht hier letztlich das Gleiche und spart ein Register.
Man müßte also wohl gezihlt nach Anwendungen suchen???

Gruß aus Berlin
Michael

von Alexander V. (avogra)


Lesenswert?

ah ok, dass könnte gut sein. Ich ärger mich einfach nur jedes mal, wenn 
ich ihn seh :) Danke für die Hinweise !

/edit: ui, geht das hier schnell

von Michael U. (amiga)


Lesenswert?

Hallo,

A. K. schrieb:
> Der ist möglicherweise speziell für Funktionen wie strncpy/memchr...
> vorgesehen, die sowohl einen Zähler als auch einen Wert als
> Abbruchbedingung haben. Läuft dann raus auf sowas wie:
>
> l1: ld   r1,x+
>     dec  r2
>     cpse r1,r0
>     brne l1

Hmmm...

 l1: ld   r1,x+
     dec  r2
     cp   r1,r0
     brne l1

macht das Gleiche, mir iat aber gerade der entscheidende Unterschied 
aufgefallen: CPSE verändert die Flags nicht!

da muß ich mal auf eine Anwendung achten...

Gruß aus Berlin
Michael

von Alexander V. (avogra)


Lesenswert?

Stimmt. Jetzt hab ich auch das Beispiel von A.K. richtig verstanden. Da 
wird das voll ausgenutzt. Hatte gedacht, da fehlt doch noch was, wenn 
auf zwei Abbruch-Kriterien überprüft werden soll. D'oh :)

Sowas kann man dann wirklich seehr elegant machen.

von Hagen (Gast)


Lesenswert?

>> l1: ld   r1,x+
>>     dec  r2
>>     cpse r1,r0
>>     brne l1

>Hmmm...

> l1: ld   r1,x+
>     dec  r2
>     cp   r1,r0
>     brne l1

>macht das Gleiche,

Nein macht es nicht. Das BRNE oben bezieht sich auf die Flags die beim 
DEC R2 verändert wurden. In deinem Beispiel bezieht sich BRNE auf den 
Vergleich CP r1,r0 wodurch dann auch das DEC R2 nicht ausgewertet wird 
und somit sinnfällig wäre.

Gruß Hagen

von Michael U. (amiga)


Lesenswert?

Hallo,

Hagen schrieb:
>>> l1: ld   r1,x+
>>>     dec  r2
>>>     cpse r1,r0
>>>     brne l1
>
>>Hmmm...
>
>> l1: ld   r1,x+
>>     dec  r2
>>     cp   r1,r0
>>     brne l1
>
>>macht das Gleiche,
>
> Nein macht es nicht. Das BRNE oben bezieht sich auf die Flags die beim
> DEC R2 verändert wurden. In deinem Beispiel bezieht sich BRNE auf den
> Vergleich CP r1,r0 wodurch dann auch das DEC R2 nicht ausgewertet wird
> und somit sinnfällig wäre.
>
> Gruß Hagen

ja, war mir inzwischen aufgefallen, man muß sich eben die Befehle auch 
nach Jahren asm noch genau anschauen... :-)

Gruß aus Berlin
Michael

von Hauke S. (hauke)


Lesenswert?

Ich verwende CPSE sehr gerne.

Für den inversen Fall von CPSE verwende ich zwei CPSE hintereinander .
Weiterhin habe ich meist ein Register auf Null reserviert.
Schleifen werden dadurch einfacher.
1
.def leer =r2
2
.def work =r16
3
clr leer
4
...
5
cpse work,leer
6
  cpse leer,leer
7
    JMP xxx

Vorteile:
FLAG neutral
Interruptfest
unbegrenzte Sprungmöglichkeiten (im Gegensatz zu Branch)
Festgelegte und konstante Taktanzahl

Für mehrere Vergleiche kann man auch CPSE Kaskaden verwenden, jedoch 
wird dass schnell unübersichtlich und sollte vermieden werden.

cu
Hauke

von H.Joachim S. (crazyhorse)


Lesenswert?

der CodeVision-compiler liebt den cpse....
ATmega88 instruction use summary:
adc   :  12 add   :  13 adiw  :  10 and   :   1 andi  :   3 asr   :   0
bclr  :   0 bld   :   0 brbc  :   0 brbs  :   0 brcc  :   2 brcs  :   4
break :   0 breq  :  11 brge  :   0 brhc  :   0 brhs  :   0 brid  :   0
brie  :   0 brlo  :   8 brlt  :   0 brmi  :   0 brne  :  14 brpl  :   0
brsh  :   1 brtc  :   0 brts  :   0 brvc  :   0 brvs  :   0 bset  :   0
bst   :   0 cbi   :   5 cbr   :   1 clc   :   0 clh   :   0 cli   :   4
cln   :   0 clr   :  22 cls   :   0 clt   :   0 clv   :   0 clz   :   0
com   :   0 cp    :   2 cpc   :   5 cpi   :  21 cpse  :   0 dec   :   4
eor   :   0 fmul  :   0 fmuls :   0 fmulsu:   0 icall :   0 ijmp  :   0
in    :  10 inc   :   0 ld    :  28 ldd   :  14 ldi   : 156 lds   :  29
lpm   :   8 lsl   :   2 lsr   :   0 mov   :  19 movw  :  19 mul   :  12
muls  :   0 mulsu :   0 neg   :   0 nop   :   0 or    :   0 ori   :   3
out   :  41 pop   :   5 push  :   5 rcall :  50 ret   :  26 reti  :   6
rjmp  :  50 rol   :  10 ror   :   0 sbc   :   4 sbci  :   8 sbi   :  12
sbic  :   3 sbis  :   5 sbiw  :   8 sbr   :   2 sbrc  :   2 sbrs  :   0
sec   :   0 seh   :   0 sei   :   2 sen   :   0 ser   :   0 ses   :   0
set   :   0 sev   :   0 sez   :   0 sleep :   0 spm   :   0 st    :  27
std   :   8 sts   :  58 sub   :   2 subi  :  14 swap  :   0 tst   :   2

Man könnte mal suchen, wofür eingesetzt.

von Klaus (Gast)


Lesenswert?

> cpse  :   0

Wenn ich die Tabelle richtig lese, wird cpse genau 0 mal eingesetzt.

von H.Joachim S. (crazyhorse)


Lesenswert?

stop, Irrtum, die 21 sind für cpi.
cpse: 0.

von H.Joachim S. (crazyhorse)


Lesenswert?

Und aus einem andern Projekt, auch Fehlanzeige.
ATmega8 instruction use summary:
adc   :  23 add   :  19 adiw  :  37 and   :   2 andi  :   6 asr   :   0
bclr  :   0 bld   :  33 brbc  :   0 brbs  :   0 brcc  :   5 brcs  :   4
break :   0 breq  :  88 brge  :   3 brhc  :   0 brhs  :   0 brid  :   0
brie  :   0 brlo  :  34 brlt  :   2 brmi  :   9 brne  :  98 brpl  :   7
brsh  :  14 brtc  :   1 brts  :   1 brvc  :   4 brvs  :   4 bset  :   0
bst   :   3 cbi   :   5 cbr   :   0 clc   :   3 clh   :   0 cli   :   5
cln   :   0 clr   :  52 cls   :   0 clt   :  24 clv   :   0 clz   :   2
com   :   8 cp    :  19 cpc   :  13 cpi   : 137 cpse  :   0 dec   :  10
eor   :  12 fmul  :   0 fmuls :   0 fmulsu:   0 icall :   0 ijmp  :   0
in    :  10 inc   :   6 ld    :  67 ldd   :  96 ldi   : 373 lds   :  45
lpm   :  16 lsl   :  16 lsr   :   2 mov   : 106 movw  :  65 mul   :  15
muls  :   0 mulsu :   0 neg   :   4 nop   :   0 or    :   8 ori   :   7
out   :  50 pop   :  33 push  :  33 rcall : 635 ret   : 151 reti  :   4
rjmp  : 283 rol   :  31 ror   :  12 sbc   :   9 sbci  :  32 sbi   :   9
sbic  :   3 sbis  :   2 sbiw  :  31 sbr   :   1 sbrc  :  23 sbrs  :  46
sec   :   4 seh   :   0 sei   :   3 sen   :   0 ser   :   8 ses   :   0
set   :  20 sev   :   0 sez   :   1 sleep :   0 spm   :   0 st    : 136
std   :  31 sts   :  32 sub   :   6 subi  :  58 swap  :   0 tst   :  36
wdr   :   1
Instructions used: 78 out of 109 (71.6%)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.