Forum: Compiler & IDEs Zugriff auf long long mit asm volatile


von Schawwi (Gast)


Lesenswert?

Hallo!

Ich möchte die Differenz zweier unsigned-short-Variablen möglichst 
schnell zu einer signed-long-long-Variable addieren. Da das Ergebnis der 
Differenz (lastadcvalue - zero) im Bereich von +/- 65536 liegt, reichen 
ja 3 Byte (lastadcvalue, tempA) für den Inhalt des Wertes aus. Ein 
weiteres Byte (tempB) nimmt dann die eventuellen Einsen des 
Zweierkomplements für vorstehende Bytes auf.

Mein dazu gehörender C-Code sieht so aus:
1
unsigned short us_temp;
2
asm volatile ( // rec_adcsum[rec_samplescounter] += (signed long long)rec_lastadcvalue - zero;
3
  "clr     %A[temp]                           \n\t"
4
  "clr     %B[temp]                           \n\t"
5
  "sub     %A[lastadcvalue], %A[zero]         \n\t"
6
  "sbc     %B[lastadcvalue], %B[zero]         \n\t"
7
  "sbc     %A[temp],         __zero_reg__     \n\t"
8
  "sbc     %B[temp],         __zero_reg__     \n\t"
9
  "add     %A[adcsum],       %A[lastadcvalue] \n\t"
10
  "adc     %B[adcsum],       %B[lastadcvalue] \n\t"
11
  "adc     %C[adcsum],       %A[temp]         \n\t"
12
  "adc     %D[adcsum],       %B[temp]         \n\t"
13
  "adc     %E[adcsum],       %B[temp]         \n\t"
14
  "adc     %F[adcsum],       %B[temp]         \n\t"
15
  "adc     %G[adcsum],       %B[temp]         \n\t"
16
  "adc     %H[adcsum],       %B[temp]             "
17
    : [adcsum] "+r" (rec_adcsum[rec_samplescounter]), [temp] "=&r" (us_temp)
18
    : [lastadcvalue] "r" (rec_lastadcvalue), [zero] "r" (zero)
19
);

Leider kommt der folgende Assembler-Code raus:
1
LDS     R30,0x05CA
2
CLR     R31       
3
LDI     R18,0x03  
4
LSL     R30       
5
ROL     R31       
6
DEC     R18       
7
BRNE    PC-0x03   
8
SUBI    R30,0x17  
9
SBCI    R31,0xFA  
10
LDS     R16,0x05E7
11
LDS     R17,0x05E8
12
LDS     R26,0x0104
13
LDS     R27,0x0105
14
LDD     R18,Z+0   
15
LDD     R19,Z+1   
16
LDD     R20,Z+2   
17
LDD     R21,Z+3   
18
LDD     R22,Z+4   
19
LDD     R23,Z+5   
20
LDD     R24,Z+6   
21
LDD     R25,Z+7   
22
MOVW    R28,R26   
23
CLR     R26       
24
CLR     R27       
25
SUB     R16,R28   
26
SBC     R17,R29   
27
SBC     R26,R1    
28
SBC     R27,R1    
29
ADD     R18,R16   
30
ADC     R19,R17   
31
ADC     R20,R26   
32
ADC     R21,R27   
33
ADC     R18,R27   
34
ADC     R18,R27   
35
ADC     R18,R27   
36
ADC     R18,R27   
37
STD     Z+0,R18   
38
STD     Z+1,R19   
39
STD     Z+2,R20   
40
STD     Z+3,R21   
41
STD     Z+4,R22   
42
STD     Z+5,R23   
43
STD     Z+6,R24   
44
STD     Z+7,R25

Wie man sieht, funktioniert die Registerzuordnung der oberen 4 Byte der 
long-long-Variable mit den Buchstaben E bis H nicht, weil sie alle auf 
den A-Wert mit Register 18 zeigen. Kann man etwa keine 
long-long-Variablen in Inline-Assembler verwenden?

Danke für Antworten!

Christian

von Falk B. (falk)


Lesenswert?

@ Schawwi (Gast)

>Ich möchte die Differenz zweier unsigned-short-Variablen möglichst
>schnell zu einer signed-long-long-Variable addieren.

Warum glaubst du das mit Inline Assembler machen zu müssen? SOOOO 
schlecht ist dein Compiler nicht.
Lass den Käse und schreibs einfach hin.
1
unsigned short a,b, tmp;
2
signed long long c;
3
4
tmp = (a-b);
5
c = c + tmp;

MfG
Falk

von Schawwi (Gast)


Lesenswert?

Hallo Falk!

Ich finde schon, dass er das schlecht macht.
Die Sache ist, dass die Differenz größer sein kann als signed short. 
Demnach müsste ich hierfür signed long nehmen.

Also lautet mein C-Code:
1
signed long sl_temp;
2
sl_temp = rec_lastadcvalue - zero;
3
rec_adcsum[rec_samplescounter] = rec_adcsum[rec_samplescounter] + sl_temp;

Und der Assembler-Code wird deutlich länger als das, was bei meiner 
Variante nötig wäre.
1
LDS     R18,0x05E7
2
LDS     R19,0x05E8
3
LDS     R22,0x0104
4
LDS     R23,0x0105
5
LDS     R24,0x05CA
6
MOV     R6,R24    
7
CLR     R7        
8
LDS     R30,0x05CA
9
MOV     R26,R30   
10
CLR     R27       
11
LDI     R31,0x03  
12
LSL     R26       
13
ROL     R27       
14
DEC     R31       
15
BRNE    PC-0x03   
16
SUBI    R26,0x17  
17
SBCI    R27,0xFA  
18
LD      R24,X     
19
STD     Y+1,R24   
20
MOVW    R30,R26   
21
LDD     R31,Z+1   
22
STD     Y+2,R31   
23
MOVW    R30,R26   
24
LDD     R31,Z+2   
25
STD     Y+3,R31   
26
MOVW    R30,R26   
27
LDD     R31,Z+3   
28
STD     Y+4,R31   
29
MOVW    R30,R26   
30
LDD     R31,Z+4   
31
STD     Y+5,R31   
32
MOVW    R30,R26   
33
LDD     R31,Z+5   
34
STD     Y+6,R31   
35
MOVW    R30,R26   
36
LDD     R31,Z+6   
37
STD     Y+7,R31   
38
MOVW    R30,R26   
39
LDD     R26,Z+7   
40
STD     Y+8,R26   
41
SUB     R18,R22   
42
SBC     R19,R23   
43
CLR     R20       
44
CLR     R21       
45
MOVW    R26,R20   
46
MOVW    R24,R18   
47
LSL     R27       
48
SBC     R24,R24   
49
MOV     R25,R24   
50
MOVW    R26,R24   
51
STD     Y+9,R18   
52
STD     Y+10,R19  
53
STD     Y+11,R20  
54
STD     Y+12,R21  
55
STD     Y+13,R24  
56
STD     Y+14,R24  
57
STD     Y+15,R24  
58
STD     Y+16,R24  
59
LDD     R8,Y+1    
60
LDD     R31,Y+9   
61
ADD     R8,R31    
62
LDI     R24,0x01  
63
LDD     R25,Y+1   
64
CP      R8,R25    
65
BRCS    PC+0x02   
66
LDI     R24,0x00  
67
LDD     R9,Y+2    
68
LDD     R30,Y+10  
69
ADD     R9,R30    
70
LDI     R18,0x01  
71
LDD     R31,Y+2   
72
CP      R9,R31    
73
BRCS    PC+0x02   
74
LDI     R18,0x00  
75
ADD     R24,R9    
76
LDI     R25,0x01  
77
CP      R24,R9    
78
BRCS    PC+0x02   
79
LDI     R25,0x00  
80
OR      R18,R25   
81
MOV     R9,R24    
82
LDD     R10,Y+3   
83
LDD     R24,Y+11  
84
ADD     R10,R24   
85
LDI     R19,0x01  
86
LDD     R25,Y+3   
87
CP      R10,R25   
88
BRCS    PC+0x02   
89
LDI     R19,0x00  
90
MOV     R24,R18   
91
ADD     R24,R10   
92
LDI     R25,0x01  
93
CP      R24,R10   
94
BRCS    PC+0x02   
95
LDI     R25,0x00  
96
OR      R19,R25   
97
MOV     R10,R24   
98
LDD     R11,Y+4   
99
LDD     R30,Y+12  
100
ADD     R11,R30   
101
LDI     R18,0x01  
102
LDD     R31,Y+4   
103
CP      R11,R31   
104
BRCS    PC+0x02   
105
LDI     R18,0x00  
106
MOV     R24,R19   
107
ADD     R24,R11   
108
LDI     R25,0x01  
109
CP      R24,R11   
110
BRCS    PC+0x02   
111
LDI     R25,0x00  
112
OR      R18,R25   
113
MOV     R11,R24   
114
LDD     R12,Y+5   
115
LDD     R24,Y+13  
116
ADD     R12,R24   
117
LDI     R19,0x01  
118
LDD     R25,Y+5   
119
CP      R12,R25   
120
BRCS    PC+0x02   
121
LDI     R19,0x00  
122
MOV     R24,R18   
123
ADD     R24,R12   
124
LDI     R25,0x01  
125
CP      R24,R12   
126
BRCS    PC+0x02   
127
LDI     R25,0x00  
128
OR      R19,R25   
129
MOV     R12,R24   
130
LDD     R13,Y+6   
131
LDD     R30,Y+14  
132
ADD     R13,R30   
133
LDI     R18,0x01  
134
LDD     R31,Y+6   
135
CP      R13,R31   
136
BRCS    PC+0x02   
137
LDI     R18,0x00  
138
MOV     R24,R19   
139
ADD     R24,R13   
140
LDI     R25,0x01  
141
CP      R24,R13   
142
BRCS    PC+0x02   
143
LDI     R25,0x00  
144
OR      R18,R25   
145
MOV     R13,R24   
146
LDD     R14,Y+7   
147
LDD     R24,Y+15  
148
ADD     R14,R24   
149
LDI     R19,0x01  
150
LDD     R25,Y+7   
151
CP      R14,R25   
152
BRCS    PC+0x02   
153
LDI     R19,0x00  
154
MOV     R25,R18   
155
ADD     R25,R14   
156
LDI     R24,0x01  
157
CP      R25,R14   
158
BRCS    PC+0x02   
159
LDI     R24,0x00  
160
OR      R24,R19   
161
LDD     R15,Y+8   
162
LDD     R30,Y+16  
163
ADD     R15,R30   
164
ADD     R24,R15   
165
MOVW    R30,R6    
166
LDI     R23,0x03  
167
LSL     R30       
168
ROL     R31       
169
DEC     R23       
170
BRNE    PC-0x03   
171
SUBI    R30,0x17  
172
SBCI    R31,0xFA  
173
STD     Z+0,R8    
174
STD     Z+1,R9    
175
STD     Z+2,R10   
176
STD     Z+3,R11   
177
STD     Z+4,R12   
178
STD     Z+5,R13   
179
STD     Z+6,R25   
180
STD     Z+7,R24

Grüße,

Christian

von Falk B. (falk)


Lesenswert?

@ Schawwi (Gast)


>Ich finde schon, dass er das schlecht macht.
>Die Sache ist, dass die Differenz größer sein kann als signed short.
>Demnach müsste ich hierfür signed long nehmen.

Ja. Musst du aber auch in ASM (naja, man kann mit 24 Bit rechen, bringt 
aber nicht viel wenn es um die Summe mit long long geht, CARRY!).

>Also lautet mein C-Code:

>Und der Assembler-Code wird deutlich länger als das, was bei meiner
>Variante nötig wäre.

MOMENT! Das sind Indizierungen drin. Die werden dadurch nicht kürzer. 
Optimierung eingeschaltet? Denn ohne ist das reichlich sinnlos.

MFg
Falk

von Schawwi (Gast)


Lesenswert?

Hallo Falk!

Doch, Optimierung ist an. Habe auch alle Stufen durchprobiert und von 
der Länge ändert sich auf einen groben Blick nichts.

Hast Du andere Ideen?

Grüße,

Christian

von Falk B. (falk)


Lesenswert?

@ Schawwi (Gast)

>Doch, Optimierung ist an. Habe auch alle Stufen durchprobiert und von
>der Länge ändert sich auf einen groben Blick nichts.
>Hast Du andere Ideen?

Leider nein. So richtig sehe ich da nicht durch. Aber wie es scheint 
kann/will der GCC die Operanden nicht in den Registern halten (hat ja 
nur 32 Stück . . .) und läd immer über ldd nach. Wobei eine 8 + 8 Byte 
Addition nun wirklich nicht die Welt ist. :-(
Da musst du dich wohl oder übel mehr mit Inline Assembler rumschlagen. 
Aber vielleicht ist es besser, die Berechnug in eine Funktion 
auszulagern und richtig in Assembler zu programmieren. Das soll 
einfacher sein.

MFg
Falk

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.