Seite 2 von 2

Re: bits in bytes und umgekehrt...

Verfasst: Donnerstag 24. Oktober 2013, 14:56
von jerch
@jens:
Ich denke auch, dass Du gerade die low level Sachen wie Registerabstraktion mit Flaghandling und die Adressierungsmodi über den ganzen möglichen Wertebereich testen solltest. Wenn Du mit intensiven Tests erst auf op-Codeebene einsteigst, könnte ein kleiner Fehler im low level-Bereich unerkannt bleiben bzw. nur noch schwer zurückverfolgbar sein. Wenn dieser Unterbau stimmt, sind die op-Codes mit Tests reine Fleissarbeit.

Ist der Chip eigentlich fehlerfrei gewesen? Evtl. funktioniert Dein Emulator am Ende besser als das Original und muss entsprechend "kaputt gepatcht" werden, damit Originalsoftware so wie damals läuft. ;)

Re: bits in bytes und umgekehrt...

Verfasst: Donnerstag 24. Oktober 2013, 15:12
von jens
Mir ist kein Bug bekannt. Beim Ursprünglichen ApplyPy Projekt war es allerdings wirklich so z.B.:
https://github.com/jtauber/applepy/blob ... py#L80-L84

Ein Test mit SUBA ist auch fertig und gleich einen Fehler im OP-Code behoben: https://github.com/jedie/DragonPy/commi ... b85763fb12

Unittests mache ich eigentlich gern nicht ganz Low-Level, obwohl es ja "unit" heißt. Auf der einen Seite schließt man mit einen Test der höher ansetzt mehr Code mit ein. Also man testet mehr. Auf der anderen Seite ist es schwieriger den eigentlichen Bug zu lokalisieren...
Aber ich teste lieber mehr auf einmal, als viele Code-Teile überhaupt nicht zu testen.

Re: bits in bytes und umgekehrt...

Verfasst: Sonntag 27. Oktober 2013, 10:35
von jens
Hab nochmal zwei Fragen zum konvertieren von C nach Python.

Einmal für SEX:

Code: Alles auswählen

WREG_A = (RREG_B & 0x80) ? 0xff : 0;
das hab ich daraus gemacht:

Code: Alles auswählen

        if b & 0x80 == 0:
            self.accu_a.set(0x00)

Und das andere ist für DAA und komplexer:

Code: Alles auswählen

				unsigned tmp = 0;
				if ((RREG_A&0x0f) >= 0x0a || REG_CC & CC_H) tmp |= 0x06;
				if (RREG_A >= 0x90 && (RREG_A&0x0f) >= 0x0a) tmp |= 0x60;
				if (RREG_A >= 0xa0 || REG_CC & CC_C) tmp |= 0x60;
				tmp += RREG_A;
				WREG_A = tmp;
				// CC.C NOT cleared, only set if appropriate
				CLR_NZV;
				SET_NZC8(tmp);
und das hab ich daraus gemacht:

Code: Alles auswählen

        tmp = 0
        a = self.accu_a.get()
        cc = self.cc.get()

        if (a & 0x0f) >= 0x0a or cc & self.cc.H:
            tmp |= 0x06

        if a >= 0x90 and (a & 0x0f) >= 0x0a:
            tmp |= 0x60

        if a >= 0xa0 or cc & self.cc.C:
            tmp |= 0x60

        new_value = tmp + a
        self.accu_a.set(new_value)
Als erstes ist mir erstmal wichtig das das selbe herraus kommt. Dann, wie man es einfacher in Python umsetzten kann.
Kann da jemand helfen?

Re: bits in bytes und umgekehrt...

Verfasst: Sonntag 27. Oktober 2013, 11:16
von Sirius3
@jens: das erste sieht für mich aus wie

Code: Alles auswählen

self.accu_a.set(b & 0x80 and 0xff)
Das zweite sieht richtig aus, würde ich aber so schreiben:

Code: Alles auswählen

a = self.accu_a.get()
cc = self.cc.get()

tmp = (cc & self.cc.H and 0x06) | (cc & self.cc.C and 0x60)
if a & 0x0f >= 0x0a:
    tmp |= 0x06 if a<0x90 else 0x66
elif a >= 0xa0:
    tmp |= 0x60
self.accu_a.set(a + tmp)

Re: bits in bytes und umgekehrt...

Verfasst: Donnerstag 26. Juni 2014, 12:34
von jens
Hab nochmal eine Ähnliche Frage:

Der Code aus XRoar (siehe: https://github.com/jedie/XRoar/blob/mas ... mon.c#L295 ) brauche ich in Python:

Code: Alles auswählen

#define N_EOR_V ((REG_CC & CC_N)^((REG_CC & CC_V)<<2))
case 0xe: cond = !(N_EOR_V || REG_CC & CC_Z); break; // BGT, LBGT
Zusammengefasst ist es doch:

Code: Alles auswählen

!(((REG_CC & CC_N)^((REG_CC & CC_V)<<2)) || REG_CC & CC_Z)
Vereinfacht also:

Code: Alles auswählen

!((N^V)<<2) || Z)
oder?

Code der eigentlich das selbe machen soll, aus 6809.js (siehe: https://github.com/maly/6809js/blob/master/6809.js#L781 ):

Code: Alles auswählen

(!((CC&F_NEGATIVE) ^ ((CC&F_OVERFLOW)<<2) || (CC&F_ZERO)))
ist vereinfacht das:

Code: Alles auswählen

!(N ^ (V<<2) || Z)
oder?
Ist da die Klammern falsch gesetzt?



In Python habe ich aktuell das:

Code: Alles auswählen

if not ((self.cc.N ^ self.cc.V) == 1 or self.cc.Z == 1):
    self.program_counter = ea

Der Text zu BGT lautet allerdings:
Causes a branch if the N (negative) bit and V (overflow) bit are either both set or both clear and the Z (zero) bit is clear.
Das heißt doch aber einfach nur das:

Code: Alles auswählen

if self.cc.N == self.cc.V and self.cc.Z == 0:
    self.program_counter = ea
Entspricht das dem C Code von XRoar?

EDIT: Merke gerade not ((self.cc.N ^ self.cc.V) == 1 or self.cc.Z == 1) ist das selbe wie self.cc.N == self.cc.V and self.cc.Z == 0 nur viel komplizierter ausgedrückt ;)

EDIT2: Und not ((self.cc.N ^ self.cc.V) | self.cc.Z) führt ebenfalls zum selben Ergebnis.

Re: bits in bytes und umgekehrt...

Verfasst: Donnerstag 26. Juni 2014, 16:26
von MagBen
Mit Numpy:

Code: Alles auswählen

import numpy as N

bits = 2**N.arange(7,-1,-1)

class Foo(object):
    def status_from_byte(self, status):
        self.flag_E, \
        self.flag_F, \
        self.flag_H, \
        self.flag_I, \
        self.flag_N, \
        self.flag_Z, \
        self.flag_V, \
        self.flag_C = N.bitwise_and(status, bits)!=0
        
    def status_as_byte(self):
        return self.flag_C | \
            self.flag_V << 1 | \
            self.flag_Z << 2 | \
            self.flag_N << 3 | \
            self.flag_I << 4 | \
            self.flag_H << 5 | \
            self.flag_F << 6 | \
            self.flag_E << 7
        
f = Foo()
 
for i in xrange(255):
    f.status_from_byte(i)
    i2 = f.status_as_byte()
    print i, i2
    assert i == i2

Re: bits in bytes und umgekehrt...

Verfasst: Donnerstag 26. Juni 2014, 16:44
von EyDu
jens hat geschrieben:Das heißt doch aber einfach nur das:

Code: Alles auswählen

if self.cc.N == self.cc.V and self.cc.Z == 0:
    self.program_counter = ea
Das hast du doch selber hergeleitet. Ausgehend von deinem ersten Stück Python-Code:

Code: Alles auswählen

not ((self.cc.N ^ self.cc.V) == 1 or self.cc.Z == 1
Da ``== 1`` in deime Fall ``== True`` entspricht:

Code: Alles auswählen

not ((self.cc.N ^ self.cc.V) or self.cc.Z
Da ein xor von zwei Bits nichts anderes ist als Ungleich:

Code: Alles auswählen

not ((self.cc.N != self.cc.V) or self.cc.Z
Und dann kannst du noch das not reinziehen:

Code: Alles auswählen

self.cc.N == self.cc.V and not self.cc.Z
Und schon hast du deinen Ausdurck.

Re: bits in bytes und umgekehrt...

Verfasst: Donnerstag 26. Juni 2014, 16:56
von jens
Danke euch. Numpy werde ich z.Z. aber nicht nutzten. Optimierungen kommen, wenn es denn mal einwandfrei laufen würde ;)
EyDu hat geschrieben:Und dann kannst du noch das not reinziehen:

Code: Alles auswählen

self.cc.N == self.cc.V and not self.cc.Z
Stimmt, aber IMHO ist if self.cc.N == self.cc.V and self.cc.Z == 0: direkter zu verstehen, oder nicht?

Re: bits in bytes und umgekehrt...

Verfasst: Donnerstag 26. Juni 2014, 17:52
von EyDu
Finde ich nicht. Ein == 0 würde ich bei Bool'schen Ausdrücken so nie verwenden und ist ist mir in der Form auch noch niemals begegnet.

Re: bits in bytes und umgekehrt...

Verfasst: Donnerstag 26. Juni 2014, 19:52
von jens
In meinem Falle sind es allerdings wirklich 1 und 0 und nicht True / False ;)

Vielleicht ändere ich das irgendwann mal oder nicht, mal sehen...

Re: bits in bytes und umgekehrt...

Verfasst: Donnerstag 26. Juni 2014, 23:07
von jerch
@jens:
Die zusätzliche == 0|1 ist für die Register unsinnig, da Du ja hoffentlich mit den Registern nur boolsche Operationen machst. Dann ist doch egal, was konkret in der Variable drinsteckt, solange das wahr/falsch korrekt abgebildet wird. (Ich hätt da wahrscheinlich von Anfang an mit True/False gearbeitet.)
Bei dem nach `and` umgestellten Ausdruck würde ich die Z-Prüfung noch nach links nehmen. Die Testung auf 0 ist idR schneller, kA ob das bei Python auch eine Rolle spielt, trotzdem dürfte die Prüfung schneller sein als das (N==V) wegen 1 vs. 2 Variablenlookups.