-
        

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 17

Thema: ASM clobber register?

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    04.09.2007
    Beiträge
    13

    ASM clobber register?

    Anzeige

    Hallo,

    ich hoffe Ihr könnt mir helfen. Ich beschäftige mich zur Zeit mit dem gcc, genauer gesagt mit der Zwischensprache des GCC also RTL(Register Transfer Language). In ihr kommt ein Befehl (clobber x) wobei x meist ein Register ist.
    Laut GCC internals bewirkt dies eine speicherung bzw eine mögliche speicherung von x hier mal ein beispiel
    Code:
    (insn 9 8 10 1 (parallel [
                (set (reg:SI 60)
                    (plus:SI (mem/c/i:SI (reg/f:SI 53 virtual-incoming-args) [0 a+0 S4 A32])
                        (reg:SI 61)))
                (clobber (reg:CC 17 flags))
            ]) -1 (nil)
        (nil))
    kann mir wer sagen was nun genau dabei gemacht wird, also was der befehl clobber mit dem reg17 macht-

    gruss matze

  2. #2
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    30.01.2005
    Ort
    Tokyo
    Alter
    59
    Beiträge
    242
    Dieses Register wird im Ram zwischengespeichert, damit darin später andere Werte gespeichert werden können. (z.B. via Inline Assembler Code).

    Gruß
    pctoaster

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801

    Re: ASM clobber register?

    Code:
    (clobber (reg:CC 17 flags))
    clobber sagt, daß REG 17 durch diese insn verändert wird; und zwar in einer Weise, die zu kompliziert ist, um sie hier genau zu beschreiben. Wichtig ist, daß REG 17 den Inhalt wechselt. REG 17 hat den Mode (enum machine_mode) CCmode (CC), enthält also den condition code der Maschine.

    das parallel[] (eine zeitgleiche(!) Ausführung mehrerer insns) enthält ein set. In C-Syntax:

    reg60 = (*(reg53)) + reg61

    wobei die Operation als 32-Bit ausgeführt wird (SImode=single integer). Sie lädt also einen 32-Bit-Wert, und diese Ladeoperation hat eine nicht weiter spezifizierte Änderung von reg17 zur Folge.

    Was weiter mit REG 17 geschieht, ist aus der insn nicht ersichtlich. Weiterverwendet werden kann REG 17 nicht -- was wollte man mit einem Register mit undefiniertem Inhalt auch anfangen?

    Wie REG 17 auf Funktionsebene gehandhabt wird, hängt davon ab, ob es sich um ein Hard-Reg handelt oder um ein Pseudo-Reg (siehst du im Header ./gcc/config/target/target.h). Zu vermuten ist, daß die Maschine 16 GPRs hat und REG 17 ebenfalls zu den Hard-Regs gehört.

    Dieser Beitrag passt übrigens nicht in dieses Forum, da es sich dabei nicht um Assembler-Programmierung handelt. (Die insn entstand ja nicht aus einem Inline-Assembler, und selbst wenn, ist es keine Frage von asm-Programmierung), sondern ist ein Pattern aus der Backend-Beschreibung der Maschine, die du findest in ./gcc/config/target/target.md

    Dieses Thema gehört zu "Compilerbau", also am ehesten nach "Software, Algorithmen und KI".
    Disclaimer: none. Sue me.

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    04.09.2007
    Beiträge
    13
    danke erst mal für die schnelle antwort. der hauptgrund, warum ich nun in diesem forum meine frage stellte ist der das ich nun nicht rausbekommen hatte, was der befehl clobber nun genau macht. das einzige was ich fand war
    der asm befehl. ich hoffte das es da einen zusammenhang gab zwischen beiden befehlen

    was der befehl nun genau mit dem register macht kann man wo nicht sagen?
    ich habe zwar das internal des GCC gelesen, kann aber immer noch nicht sagen was da nun geschied besonders in verbindung mit dem (scratch:m) befehl was nich immer für mich sinn macht

    Code:
    (clobber (scratch:SI))
    zum beispiel ?

  5. #5
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    Was hier passiert ist wesentlich komplexer als bei inline asm.

    Nehmen wir mal das Beispiel einer 16-Bit AND-Insn für AVR:
    Code:
    (define_insn "andhi3"
      [(set (match_operand:HI 0         "register_operand"  "=r,d,r")
            (and:HI (match_operand:HI 1 "register_operand"  "%0,0,0")
                    (match_operand:HI 2 "nonmemory_operand" " r,i,M")))
       (clobber (match_scratch:QI 3                         "=X,X,&d"))]
      ""
      {
        if (which_alternative==0)
            return (AS2 (and,%A0,%A2) CR_TAB
                    AS2 (and,%B0,%B2));
        else if (which_alternative==1)
        {
            if (GET_CODE (operands[2]) == CONST_INT)
            {
                int mask = INTVAL (operands[2]);
                if ((mask & 0xff) != 0xff)
                    output_asm_insn (AS2 (andi,%A0,lo8(%2)), operands);
                if ((mask & 0xff00) != 0xff00)
                    output_asm_insn (AS2 (andi,%B0,hi8(%2)), operands);
                return "";
            }
            return (AS2 (andi,%A0,lo8(%2)) CR_TAB
                    AS2 (andi,%B0,hi8(%2)));
        }
        return (AS2 (ldi,%3,lo8(%2)) CR_TAB
                AS2 (and,%A0,%3)     CR_TAB
                AS1 (clr,%B0));
      }
      [(set_attr "length" "2,2,3")
       (set_attr "cc" "set_n,clobber,set_n")])
    Diese Standard-Insn wird vom Middle-End emitiert, wenn ein 16-Bit
    bitweises And gemacht werden soll. %0 und %1 liegen vor Pass LREG
    höchstwahrscheinlich in Pseudo-Registern, %2 ist ein Immediate oder
    ein Reg und %3 ist ein evtl. benötigtes Clobber-Register.

    Vor Pass LREG hat das clobber nur eine Funktion was Matching der
    Insn-Pattern angeht. Wichtig wird es erst im Reload-Pass, also in
    GREG. GREG kümmert sich um die globale Register-Allokierung, d.h. es
    bildet die (potentiell) unendlich vielen Pseudo-Regs auf die endlich
    vielen Hard-Regs der Maschine ab, wobei noch Nebenbedingungen
    berücksichtigt werden müssen, weil nicht jede Instruktion auf jedem
    GPR erlaubt ist.

    GREG hat 3 Möglichkeiten der Allokierung, beschrieben in den Constraints:

    • #0 ist einfach: Ein- und Ausgabe liegen in Registern; das And wird mit
      2 AND-Instruktionen erledigt und die Constraint zu %1 sorgt dafür,
      daß %0 und %1 im gleichen Hard-Reg zu liegen kommen (dafür muss GREG
      evtl. eine movhi-Insn emittieren).
    • #1 ist auch einfach: Ausgabe ist ein REG aus Klasse "d" (LD_REGS) auf
      das eine Konstante drauf-geundet wird. Für diese Register gibt's die
      ANDI-Instruktion, und je nachdem, ob die Konstante schon zur
      Compilezeit bekannt ist oder nicht (Symbole sind zB Konstanten, die
      aber erst zur Locate-Zeit bekannt werden) werden eine oder zwei ANDI
      ausgegeben.
    • #2 %2 ist eine 16-Bit-Konstante und %0 gehört nicht zu LD_REGS
      (regclass NO_LD_REGS). In diesem Falls ist es
      nicht möglich, die ANDI-Instruktion zu verwenden. Falls %2 eine
      8-Bit-Konstante ist (Contraint "M"), dann bewirkt das "=&d" bei %3,
      daß GREG ein Register aus Klasse "d" zur Verfügung stellt, das wir
      temporär in dieser insn verwenden können.
      Globale Register-Allokierung ist einer der schwierigen und
      komplexesten Teile jedes optimierenden Compilers.
      Es ist zB denkbar, daß kein "d"-Reg mehr frei ist, und GCC muss erst
      eines frei machen und extra Code dafür ausgeben, indem irgendein
      "d"-Reg auf den Stack gesichert wird.
      #2 erledigt den Reload der Konstanden in das Register %3 von Hand und führt
      das AND auf dem unteren Byte von %0 aus. Das obere Byte ist 0, denn
      die Konstante ist nur 8 Bit breit.
    • Es verbleibt der Fall, daß %0 zu NO_LD_REGS gehört und die
      Konstante keine 8-Bit-Konstante ist. In diesem Fall kümmert sich GREG
      um den Reload, lädt also %2 in ein GPR und wird dann #0 anwenden
      können. Schwierig daran ist dann der Reload von %2, weil man keine
      Konstante nach NO_LD_REGS laden darf... Wie das gelöst wird, führt
      jetzt zu weit.


    In #0 und #1 sagt die Contraint "X" bei %3, daß kein Clobber-Reg
    gebraucht wird.

    Clobber macht also mehr, als zu sagen, daß der Registerinhalt
    verändert wird (um das Register zu verändern, müssen wir es erst
    *haben*!)
    Es hat Einfluß auf Insn-Matching und die
    Register-Allokierung. Beachte, daß das Ergebnis besser ist, als wenn
    man über ein extra Pseudo arbeiten würde um die Konstante dahin zu
    laden. Dann würde man einen Expander schreiben und dort die Konstante
    in ein Pseudo laden. Dann würde man allerdings nicht in dieser Form
    von der ANDI profitieren können.

    Um das Pattern für #2 erzeugen zu lassen, muss man schon was
    tricksen. Für avr-gcc 3.4.6 geht's mit folgender Quelle:

    Code:
    void foo (void);
    
    int B;
    
    void bar (void)
    {
        int b = B;
    
        foo ();
    
        asm volatile ("":::"16","17");
    
        B = b & 0xf;
    }
    Das asm volatile dient nur dazu, daß GREG b nicht nach 16/17 legt
    (würde zu #1 führen). Zum weiteren Verständnis wird's nicht gebraucht.
    Code:
    avr-gcc clobber.c -S -Os -da -dP -fverbose-asm
    Code:
     ; (insn 14 12 15 (parallel [(set (reg/v:HI 14 r14 [orig:41 b ] [41])
     ;                                (and:HI (reg/v:HI 14 r14 [orig:41 b ] [41])
     ;                                        (const_int 15 [0xf])))
     ;                           (clobber (reg:QI 24 r24))
     ;                ]) 45 {andhi3} (insn_list 8 (nil))
     ;     (expr_list:REG_UNUSED (reg:QI 24 r24)
     ;         (nil)))
        ldi r24,lo8(15)  ; ,     ;  14  andhi3/3    [length = 3]
        and r14,r24      ;  b,
        clr r15          ;  b
    Disclaimer: none. Sue me.

  6. #6
    Neuer Benutzer Öfters hier
    Registriert seit
    04.09.2007
    Beiträge
    13
    also ich bin mir nicht so sicher ob ich deine Antwort verstanden habe?

    [(set (match_operand:HI 0 "register_operand" "=r,d,r")
    (and:HI (match_operand:HI 1 "register_operand" "%0,0,0")
    (match_operand:HI 2 "nonmemory_operand" " r,i,M")))
    (clobber (match_scratch:QI 3 "=X,X,&d"))]
    also ich denke mal das die Constraints die in "" beschriebnen werte sind wie zB "=r,d,r" nur kann ich diese net so recht deuten! in der entsprechenden definition für den i386 sieht es wie folgt aus

    (define_expand "andhi3"
    [(set (match_operand:HI 0 "nonimmediate_operand" "")
    (and:HI (match_operand:HI 1 "nonimmediate_operand" "")
    (match_operand:HI 2 "general_operand" "")))
    (clobber (reg:CC FLAGS_REG))] "TARGET_HIMODE_MATH"
    "ix86_expand_binary_operator (AND, HImode, operands); DONE;")
    hier werden keine solche angaben gemacht?

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    04.09.2007
    Beiträge
    13
    PS: wo kann man den diese Sachen nachlesen?

  8. #8
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    In Expandern (define_expand) werden keine Constraints angegeben, man wird sogar angewarnt wenn man es tut. Ein Expander arbeitet ja auf Pseudo-Ebene. Constraints findest du zB bei Insns (define_insn, define_insn_and_split) und bei den Scratch-Regs für Peephole2 (define_peephole2).

    RTL anhand von i386 zu lernen ist übel, weil das eines der komplexesten Maschinenbeschreibungen überhaupt ist; es kann Code für 32-Bit oder 64-Bit Maschinen ausgegeben werden, es werden unterschiedliche Assembler-Dialekte unterstützt, und es gibt *viele* Hacks.

    reg 17 gehört zu den fixed Hard-Regs des i386, d.h. es wird nicht von GCC verwaltet. Von daher sind die Clobbers auf reg 17 nicht so spannend. Es heisst einfach, daß ein vorher in reg 17 vorhandener Wert nicht mehr verwendbar und futsch ist.

    Zitat Zitat von matzeed7
    PS: wo kann man den diese Sachen nachlesen?
    Gute Frage... Zum Einstieg ist das GCC Internals ganz ok. Teilweise Kommentare in den Quellen des Middle-End von gcc. Aber erschöpfende Auskunft und Spezifikation ist meiner Erfahrung nach Fehlanzeige. Zum Nachlesen ist das Genannte ganz ok, aber wenn man selber ein Backend implementiert stösst man fix an die Grenzen und man muss sich durchackern...
    Disclaimer: none. Sue me.

  9. #9
    Neuer Benutzer Öfters hier
    Registriert seit
    04.09.2007
    Beiträge
    13
    Ach du schande da habe ich mich natürlich mit meinem i386 ganz schon was eingebrockt!!!

    Ich schreibe zZ eine Art Semesterarbeit über die Möglichkeit, welche Aussagen man, über die Infos die man aus dem GCC mit -da und dann aus der *.c.00.expand datei erhält, treffen kann . Ziel ist also die Erstellung eines RTL parsers (den habe ich schon fast fertig) und dann halt noch die Umwandlung der einzelnen RTL Konstrukte (set, mem, plus....) in eine Art Pseudocode. Dafür brauch ich aber die Bedeutung der einzelnen Konstrukte!!!

    Danke erst mal !!!!!!!

    zZ hänge ich an der Fragestellung, wie ich den mem am besten darstellen kann, der er ja zum lesen und schreiben benutzt wird, zB

    (set(reg:SI 61)(mem ...))

    und dann halt noch

    (set (mem ...)(reg:SI 66))

  10. #10
    Neuer Benutzer Öfters hier
    Registriert seit
    04.09.2007
    Beiträge
    13
    PS: diese Arbeit soll dann mal als Grundlage für gewisse tests dienen.

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •