Forum: Compiler & IDEs ARM7: Kann keine Konstante in Register schreiben?


von Kaspar Schleiser (Gast)


Lesenswert?

Hallo,

Beim lpc2387 konnte ich mit folgendem Code den VIC anspringen:
1
...
2
    mov    r0, #0xffffff00    /* lpc23xx */
3
4
/*    mov    r0, #0xfffffF030     /* lpc214x */
5
6
    ldr    r0, [r0]
7
    add    lr,pc,#4
8
    mov     pc, r0
9
...

Beim lpc2148 ist die VIC-Adresse nicht 0xffffff00, sondern 0xffffff030. 
Diese Konstante mag aber der Assembler nicht:

[...]
common.s: Assembler messages:
common.s:140: Error: invalid constant (fffff030) after fixup
[...]

Hat jemand eine Idee? Sollte ich nicht jeden Wert in das Register 
schreiben können?

Ich benutze gcc version 4.3.1 mit GNU assembler version 2.18.

Danke im Vorraus,
Kaspar

von Skua (Gast)


Lesenswert?

Zähl mal die Stellen deiner Konstanten.
Naaa.

von (prx) A. K. (prx)


Lesenswert?

Bei ALU Befehlen ist nur eine rotierte 8bit Konstante möglich. 
0xfffff030 past nicht in dieses Schema.

Bei LDR allerdings sind +/-12bit Offset möglich, und daher lässt sich 
diese Adresse innerhalb der ersten zig Bytes vom Flash per LDR direkt 
PC-relativ adressieren:
    ldr r0,[pc,#-...]
Oder eben so von überall her:
    mov r0,#0
    ldr r0,[r0,#0xfffff030]

von Skua (Gast)


Lesenswert?

@ A.K.
Deine Lösung hat aber weniger Fs als der OP.

von (prx) A. K. (prx)


Lesenswert?

Das ändert aber nichts am Problem. Auch mit einem F weniger passt die 
Konstante nicht ins ALU-I Schema. Das überschüssige F hat der Assembler 
sowieso ignoriert (siehe Fehlermeldung oben).

von Skua (Gast)


Lesenswert?

Jetzt hab ichs kapiert.

von Kaspar Schleiser (Gast)


Lesenswert?

Danke für die schnellen Antworten!

Die Fehlermeldung kam natürlich auch mit der richtigen Anzahl F's.

Ich hab das Problem jetz mit rumrechnen gelöst, allerdings würde ich 
natürlich gerne die Instruktion in der Interruptroutine sparen...

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

Kaspar Schleiser wrote:
> Ich hab das Problem jetz mit rumrechnen gelöst, allerdings würde ich
> natürlich gerne die Instruktion in der Interruptroutine sparen...

Am einfachsten ist es, die Pseudo Instruktion "LDR rn, =<const>" zu 
verwenden. Dann nimmt Dir der Assembler das Rechnen ab.
1
.equ VicVectAddr, 0xFFFFF030
2
3
ldr r0, =VicVectAddr
4
add lr,pc,#4
5
mov pc, r0

Gruß
Marcus

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

Marcus Harnisch wrote:
>
1
> .equ VicVectAddr, 0xFFFFF030
2
> 
3
> ldr r0, =VicVectAddr
4
> add lr,pc,#4
5
> mov pc, r0
6
>

Da fehlte natürlich noch ein "ldr r0, [r0]", aber das war ja nicht die 
eigentliche Frage...

Gruß
Marcus

von Kaspar S. (kaspar)


Lesenswert?

Marcus Harnisch wrote:
> Am einfachsten ist es, die Pseudo Instruktion "LDR rn, =<const>" zu
> verwenden. Dann nimmt Dir der Assembler das Rechnen ab.
>
>
1
> .equ VicVectAddr, 0xFFFFF030
2
> 
3
> ldr r0, =VicVectAddr
4
>
Daraus macht der Assembler:
1
ac:   e59f0048        ldr     r0, [pc, #72]   ; fc <switch_context_int+0xc>

Sonst habe ich ein MVN und ein SUB. ldr sieht schöner aus, braucht aber 
3 Takte, mvn und sub jeweils nur einen, oder nicht?

Gruß
Kaspar

von (prx) A. K. (prx)


Lesenswert?

Warum willst du eigentlich unbedingt die Adresse fertig ins Register 
laden, wenn man sie genausogut in den LDR Befehl mit reinschreiben kann? 
Also den LDR der den Vektor läd, nicht den mit dem "=" Operanden.

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.