Shift mit Carry

#4360507
Lesenswert?

Nicht schöner, nicht kürzer, nicht optimal, nicht portabel, aber 
schneller:
1
static uint8_t rol32(uint8_t *p, uint8_t c) //inlined
2
{
3
    uint8_t r = p[3] & 0x80;
4
    *(uint32_t *)p <<= 1;
5
    if (c) p[0] |= 1;
6
    return r;
7
}
8

9
void g(uint8_t *data)
10
{
11
    uint8_t c = 0;
12
    for (uint8_t i = 0; i < 32; i += 4)
13
        c = rol32(data+i, c);
14
}

Deutlich länger, aber nochmal etwas schneller:
1
void g(uint8_t *data)
2
{
3
    uint8_t c;
4
    c = rol32(data+0, 0);
5
    c = rol32(data+4, c);
6
    c = rol32(data+8, c);
7
    c = rol32(data+12, c);
8
    c = rol32(data+16, c);
9
    c = rol32(data+20, c);
10
    c = rol32(data+24, c);
11
    c = rol32(data+28, c);
12
}
#4360788
Lesenswert?

Gustav schrieb:
> Geht das "schöner" (kürzer/schneller)? Plattform avr-gcc ATmega.
>
>
1
static void shift_left(uint8_t data[]) {
2
>   uint8_t i;
3
>   for (i = 31; i > 0; i--) data[i] = (data[i] << 1) | (data[i-1] >> 7);
4
>   data[0] <<= 1;
5
> }

Ich glaube da ist noch ein Bug drinne:
1
data[i] = (data[i] << 1) | (data[i-1] >> 7);
2

3

4
byte   : |data[i-1]              |data[i]                |
5
vorher : |a7 a6 a5 a4 a3 a2 a1 a0|b7 b6 b5 b4 b3 b2 b1 b0|
6
           `-------------------------/--/--/--/--/--/--/.
7
                                    /  /  /  /  /  /  / v
8
nachher: |a7 a6 a5 a4 a3 a2 a1 a0|b6 b5 b4 b3 b2 b1 b0 a7|
9

10
Und b7 ist weg!
Gast #4360827
Lesenswert?

Habe mal beides disassembliert. Sicher, dass deine Variante (unten) auch 
schneller ist??
1
    22ca:  dc 01         movw  r26, r24
2
    22cc:  90 96         adiw  r26, 0x20  ; 32
3
    22ce:  fc 01         movw  r30, r24
4
    22d0:  7f 96         adiw  r30, 0x1f  ; 31
5
    22d2:  2e 91         ld  r18, -X
6
    22d4:  22 0f         add  r18, r18
7
    22d6:  32 91         ld  r19, -Z
8
    22d8:  33 1f         adc  r19, r19
9
    22da:  33 27         eor  r19, r19
10
    22dc:  33 1f         adc  r19, r19
11
    22de:  23 2b         or  r18, r19
12
    22e0:  2c 93         st  X, r18
13
    22e2:  e8 17         cp  r30, r24
14
    22e4:  f9 07         cpc  r31, r25
15
    22e6:  a9 f7         brne  .-22       ; 0x22d2 <shift_left+0x8>
16
    22e8:  80 81         ld  r24, Z
17
    22ea:  88 0f         add  r24, r24
18
    22ec:  80 83         st  Z, r24
19
    22ee:  08 95         ret
20

21
    323e:  fc 01         movw  r30, r24
22
    3240:  9c 01         movw  r18, r24
23
    3242:  20 5e         subi  r18, 0xE0  ; 224
24
    3244:  3f 4f         sbci  r19, 0xFF  ; 255
25
    3246:  80 e0         ldi  r24, 0x00  ; 0
26
    3248:  93 81         ldd  r25, Z+3  ; 0x03
27
    324a:  90 78         andi  r25, 0x80  ; 128
28
    324c:  40 81         ld  r20, Z
29
    324e:  51 81         ldd  r21, Z+1  ; 0x01
30
    3250:  62 81         ldd  r22, Z+2  ; 0x02
31
    3252:  73 81         ldd  r23, Z+3  ; 0x03
32
    3254:  44 0f         add  r20, r20
33
    3256:  55 1f         adc  r21, r21
34
    3258:  66 1f         adc  r22, r22
35
    325a:  77 1f         adc  r23, r23
36
    325c:  40 83         st  Z, r20
37
    325e:  51 83         std  Z+1, r21  ; 0x01
38
    3260:  62 83         std  Z+2, r22  ; 0x02
39
    3262:  73 83         std  Z+3, r23  ; 0x03
40
    3264:  88 23         and  r24, r24
41
    3266:  19 f0         breq  .+6        ; 0x326e <shift_left.lto_priv.21+0x30>
42
    3268:  80 81         ld  r24, Z
43
    326a:  81 60         ori  r24, 0x01  ; 1
44
    326c:  80 83         st  Z, r24
45
    326e:  34 96         adiw  r30, 0x04  ; 4
46
    3270:  89 2f         mov  r24, r25
47
    3272:  e2 17         cp  r30, r18
48
    3274:  f3 07         cpc  r31, r19
49
    3276:  41 f7         brne  .-48       ; 0x3248 <shift_left.lto_priv.21+0xa>
50
    3278:  08 95         ret
#4366534
Lesenswert?

Hallo,

mit ähnlichem habe ich vor Jahren mal experimentiert und Jörg Wunsch hat 
mir damals bei der inline-ASM Geschichte geholfen.
War für eine DCF77-Uhr, die alle Impulse in ein 64Bit Register schiebt 
und das neue Bit anhängt.

Schiebt zwar nach rechts und hängt ganz links an, das zum links schieben 
umzubauen und auf 32 statt 64 Bit zu kürzen sollte aber ja kein Problem 
sein.
1
                  dcf77_bit_cnt++;         // Bitcount erhöhen
2
                  asm volatile             // shift long long right und höchstwertiges Bit bleibt 0
3
                    (
4
                      "lds __tmp_reg__, %0 + 7" "\n\t"
5
                      "lsr __tmp_reg__" "\n\t"
6
                      "sts %0 + 7, __tmp_reg__" "\n\t"
7
                      "lds __tmp_reg__, %0 + 6" "\n\t"
8
                      "ror __tmp_reg__" "\n\t"
9
                      "sts %0 + 6, __tmp_reg__" "\n\t"
10
                      "lds __tmp_reg__, %0 + 5" "\n\t"
11
                      "ror __tmp_reg__" "\n\t"
12
                      "sts %0 + 5, __tmp_reg__" "\n\t"
13
                      "lds __tmp_reg__, %0 + 4" "\n\t"
14
                      "ror __tmp_reg__" "\n\t"
15
                      "sts %0 + 4, __tmp_reg__" "\n\t"
16
                      "lds __tmp_reg__, %0 + 3" "\n\t"
17
                      "ror __tmp_reg__" "\n\t"
18
                      "sts %0 + 3, __tmp_reg__" "\n\t"
19
                      "lds __tmp_reg__, %0 + 2" "\n\t"
20
                      "ror __tmp_reg__" "\n\t"
21
                      "sts %0 + 2, __tmp_reg__" "\n\t"
22
                      "lds __tmp_reg__, %0 + 1" "\n\t"
23
                      "ror __tmp_reg__" "\n\t"
24
                      "sts %0 + 1, __tmp_reg__" "\n\t"
25
                      "lds __tmp_reg__, %0" "\n\t"
26
                      "ror __tmp_reg__" "\n\t"
27
                      "sts %0, __tmp_reg__"
28
                    : "+m" (dcf77_daten)
29
                    );
30
                  if (dcf77_time_cnt < 87) // Bit war 1 
31
                    {
32
                      asm volatile        // höchstwertiges Bit des long long auf 1 setzen
33
                        (
34
                          "lds __tmp_reg__, %0 + 7" "\n\t"
35
                          "set" "\n\t"                      // T setzen
36
                          "bld __tmp_reg__, 7" "\n\t"       // und in Bit 7 kopieren
37
                          "sts %0 + 7, __tmp_reg__" "\n\t"
38
                        : "+m" (dcf77_daten)
39
                        );
40
                    }

Ist jetzt nur schnell rauskopiert...

Gruß aus Berlin
Michael

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren