2er complement auf MMX register



  • Moin.
    Kennt einer von euch ne möglichkeit das 2er complement von nem mmx register zu bilden? Da ja es ja keine neg anweisung gib ist das einzige was mir eingefallen is das register nach eax zu laden und dort ein neg/and zum machen. Das scheint mir allerdings ziehmlich umständlich... gibts da nichst besseres?

    thx!



  • hm, mir fällt im Moment nur eine Methode ein, wie man diese perfomant gestaltet ist vom Problem abhängig, jedenfall ist sie imho besser als 4 mal in die normalregister und dann wieder zurückzuschieben:
    man nehme ein MMX-Register oder ein QWORD mit dem Inhalt 0FF FF FF FF FF FF FF FF
    jetzt mache man PXOR mit dem "Zielregister" und addiere eins dazu (z.B mit OR ).
    Jetzt hat man dasselbe wie NEG gemacht... fürs komplement muss man nur noch die Ursprungszahl dazu addieren...
    Wenn man also einen Register entbehren kann dann gehts imho schneller als das ganze auszulagern...

    PS: habs gerade mit den normalen registern getestet und es scheint vom Prinzip richtig zu sein... vielleicht kann man da auch was "optimieren" .


  • Mod

    beim letzten mal galt noch, dass

    -x = 0 - x
    

    das kann man auch benutzen 😉



  • camper schrieb:

    beim letzten mal galt noch, dass

    -x = 0 - x
    

    das kann man auch benutzen 😉

    leider nicht 😉 denn MMX hat keinen PSUBQ bzw nur PSUBD
    zu Deutsch: man kann damit höchsten 2 Doublewords (also nicht den ganzen Wert im Register sonder nur jeweils die "Hälften") gleichzeitig subtrahiren, aber wenn man von
    00000000 00000000
    FFFFFFFF FFFFFFFF
    abzieht, dann bleibt statt 1 eine 00000001 000000001 was gleich 4294967297 ist 😉



  • CDW schrieb:

    hm, mir fällt im Moment nur eine Methode ein, wie man diese perfomant gestaltet ist vom Problem abhängig, jedenfall ist sie imho besser als 4 mal in die normalregister und dann wieder zurückzuschieben:
    man nehme ein MMX-Register oder ein QWORD mit dem Inhalt 0FF FF FF FF FF FF FF FF
    jetzt mache man PXOR mit dem "Zielregister" und addiere eins dazu (z.B mit OR ).
    Jetzt hat man dasselbe wie NEG gemacht... fürs komplement muss man nur noch die Ursprungszahl dazu addieren...
    Wenn man also einen Register entbehren kann dann gehts imho schneller als das ganze auszulagern...

    PS: habs gerade mit den normalen registern getestet und es scheint vom Prinzip richtig zu sein... vielleicht kann man da auch was "optimieren" .

    kling ziehmlich brauchbar, werde ich gleich versuchen 🙂



  • Hat echt was gebracht. thx! Der alte algo lieft 438ms der mit der neg version von CDW braucht jetzt noch 265ms 🙂 🙂


  • Mod

    CDW schrieb:

    camper schrieb:

    beim letzten mal galt noch, dass

    -x = 0 - x
    

    das kann man auch benutzen 😉

    leider nicht 😉 denn MMX hat keinen PSUBQ bzw nur PSUBD
    zu Deutsch: man kann damit höchsten 2 Doublewords (also nicht den ganzen Wert im Register sonder nur jeweils die "Hälften") gleichzeitig subtrahiren, aber wenn man von
    00000000 00000000
    FFFFFFFF FFFFFFFF
    abzieht, dann bleibt statt 1 eine 00000001 000000001 was gleich 4294967297 ist 😉

    axo, 64bit integer also. hm, wenns 64bit ist muss man sich ja auch wenn man über eax geht etwas einfallen lassen. das trifft im übrigen auch auf deinen algorithmus zu, schliesslich musst du die eins auch irgendwie so addieren, dass ein evtl. übertrag berücksichtigt wird (wie geht das überhaupt mit OR 😕 ).
    nur so eine idee, ungetestet:

    pxor  mm1, mm1             ; wir wollen mm0 negieren
    pxor  mm2, mm2
    psubd mm1, mm0
    pcmpeqd mm2, mm0           ; ein übertrag entsteht immer, es sei denn, das low word war vorher schon 0
    pxor  mm2, mm3             ; dort stehe mal unsere 0xffffff.. konstante
    psllq mm2, 32
    paddd mm1, mm2             ; wenns ein übertrag war addieren wir -1 im high word, sonst 0; fertig
    

    ok, ist irgenwie nicht so der hit. mal sehen wie es mit direktem xor geht (mm0 quelle, mm2 = 0xffff..)

    pxor  mm0, mm2
    psubd mm0, mm2
    pxor  mm1, mm1
    pcmpeqd mm1, mm0           ; wenn das low word null ist, gabs einen übertrag
    pxor  mm1, mm2
    psllq mm1, 32
    paddd mm0, mm1             ; dann haben wir diesen bereits richtigerweise addiert, sonst müssen wir hier etwas rückgängig machen
    

    sieht etwas besser aus, und man braucht weniger register. reihenfolge ist sicher nicht optimal. geht es noch besser?



  • wie geht das überhaupt mit OR

    war mein Denkfehler, es geht nicht...
    hm, wenn man es von der anderen Seite betrachtet:
    um die Eins dazuzuaddieren kann man immer noch PADDD benutzen, denn:
    man addiert ja nur eine Eins dazu, das heißt dass wenn es einen übertrag gab,
    dann stehet im zweiten DWORD eine Null (denn es kann ja nur einen übertrag geben wenn es vorher FF FF FF FF stand)
    wenn da jetzt eine Null steht, sollte man auch zum oberem DWORD eine eins dazuaddieren, damit wäre das "übertragen".Ich hab jetzt ein wenig dran gesessen, aber mir fällt nichts dazu ein wie man es besser machen könnte als du es schon vorgeschlagen hast..(denn um vergleiche durchzuführen müsste man wieder auf die normalregister zugreifen). Vielleicht wäre die FPU hier angebrachter 🙄



  • btw. habs oben gelöst indem ich die requirements von MXX aus SSE2 hoch geschraub hab, was brautet ich habe ein paddq ... 🤡 😃


Anmelden zum Antworten