Hallo Freunde, ich steh gerade total auf dem Schlauch. Und zwar möchte ich zwei 16-Bit-Signed-Zahlen zu einer 32-Bit-Signed-Zahl multiplizieren. In C sieht das so aus: sint16_t a_s16; sint16_t b_s16; sint32_t c_s32; c_s32 = a_s16 * b_s16; Der C30-Compiler macht nun folgendes daraus: mul.ss 0x0000, 0x0004, 0x0000 asr 0x0000, #15, 0x0002 Das heißt: Der "mul.ss" berechnet das Ergebnis genau so, wie ich es haben will, mit dem Low-Wort in Register 0x0000 und dem High-Wort in Register 0x0002 (das kann ich im Debugger so verifzieren). Dann kommt aber der "asr"-Befehl und überschreibt mein High-Wort (in 0x0002) mit dem Vorzeichenbit aus dem Low-Wort (in 0x0000). Damit ist dann mein Ergebnis falsch, wenn es größer als ein sint16_t ist. Okay, jetzt kann ich nachvollziehen, daß der Compiler das so macht, weil er zuerst die rechte Seite 16-Bit-breit berechnet und erst bei der Zuweisung auf 32-Bit erweitert. Aber kann ich ihm denn nicht irgendwie sagen, daß er die Erweiterung lassen soll? Die Variante c_s32 = (sint32)a_s16 * (sint32)b_s16; rechnet zwar korrekt, aber auch komplett 32-Bit-breit, d.h. ich hab im Assemblercode 4 mul-Befehle, was ich vermeiden will. Grüße, Dosmo
Sebastian F. schrieb: > In C sieht das so aus: Das entspricht aber nicht der C Sprachkonvention. Auch wenn Du dir das wünscht. In C hat das Ergebnis denselben Datentyp wie der größere der beiden Operanden. Gruß Anja
Wie steht's mit:
1 | c_s32 = (sint32)(a_s16 * b_s16); |
bzw.
1 | c_s32 = (sint32)a_s16 * b_s16; |
Kommt da auch das gleiche raus? Ralf
Probier ggf. mal sowas wie:
1 | static inline long mulss(int a, int b) |
2 | {
|
3 | long result; |
4 | asm ("mul.ss %1, %2, %0" : "=r"(result) : "r"(a), "r"(b) : "cc"); |
5 | return result: |
6 | }
|
Ungetestet.
Hallo, ich hab inzwischen noch was heraus gefunden: 1. Manche C-Compiler verstehen das Konstrukt c_s32 = (sint32)(sint16)a_s16 * (sint32)(sint16)b_s16; 2. Mein C30-Comiler hat eine spezielle Intrinsic-Funktion dafür: __builtin_mulss Anscheinend kann man das Problem in Standard-C nicht lösen. Grüße, Dosmo @Ralf: c_s32 = (sint32)(a_s16 * b_s16); c_s32 = (sint32)a_s16 * b_s16; -> ergeben beide volle 32Bit-Multiplikation mit 4 mul-Befehlen
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.