Hallo NG,
ich bin ja gerade dabe, den 6502 Emulator zu schreiben.
Nachdem ich ja nur das oberste Byte nehme, um gleich die Status-Flags
des ARMs ausnützen zu können, gilt dem ROR-Befehl besondere
Aufmerksamkeit:
1
opc_ROR macro
2
lsrs r6, r6, #1 // lsr value
3
tst r6, #1 << 23 // check if bit is "outshifted"
4
bicne r6, r6, #1 << 23 // clear "outshifted" bit
5
orrnes r6, r6, #3 << 31 // also set carry
6
strb r6, [r5] // store value
7
mrs r9, cpsr
8
endm
r6 ist der 8-Bit-Wert (Bit 24-31)
r5 ist der PC des 6502
r9 ist das Statusregister
Kann man da noch was besser machen (weniger Befehle)?
Und dann wollte ich noch Fragen, ob es beim ARM7 in cpsr noch "freie
Bits" gibt. Ich würde die gerne verwenden, um das Dezimal-Flag und das
Interrupt-Flag vom 6502 mit rein zu nehmen.
Gute Nacht,
Peter
Nein, es gibt keine "freien" Bits im Statusregister.
ROR hat Carry rein, dein Code nicht.
Bist du sicher, dass dein C-Status danach stimmt?
C dürfte bei dir identisch mit N sein.
Besser:
hallo AK,
>mov r6, r6, rrx // the rotate operation
ist rrx ein shift-befehl?
habs ausprobiert:
orrnes r6, r6, #3 << 31 // also set carry
hab extra die 3 genommen (Bit0+1). Bit1 "rutscht" automatisch ins Carry.
Bin eigentlich ziemlich begeistert von diesem nächtlichen Gedankenblitz
:-)
Dann darf man wohl eher nicht ins Statusregister schreiben?
Werden alle Bits immer gesetzt bei den Flag-relevanten Befehlen?
Kann man einzelne Flags auch wieder löschen?
Also mit Kann meine ich mehr oder weniger immer: darf.
Gruß
Peter
A. K. schrieb im Beitrag #2038439:
> Peter Pippinger schrieb:>>> hab extra die 3 genommen (Bit0+1). Bit1 "rutscht" automatisch ins Carry.> Die Doku drückt sich da etwas anders aus. Derzufolge entstammt das Carry> bei Data-Immediate und Rotatecount != 0 dem Bit 31 der fertig rotierten> Konstanten. Ohnehin ist 3<<31 der Wert 0x1_8000_0000 und auf 32 Bits> beschränkt identisch mit 0x8000_0000 also 1<<31.
Hmm, da hab ich mich wohl auf die Workbench verlassen. Ich habs im
SW-Debugger getestet und da wird das Carry gesetzt. Muss ich mir nochmal
anschauen.
>> Werden alle Bits immer gesetzt bei den Flag-relevanten Befehlen?>> Deine Konsequenz bei der Vermeidung jedweder zielführender Lektüre ist> auf Dauer irgendwie beeindruckend, insbesondere wenn man bedenkt dass du> schon seit mehreren Jahren an ARMs sitzt und Code schreibst, bei dem es> auf jedes Detail ankommt.
Naja, der Zeitraum stimmt. Allerdings mit extremen zeitlichen Lücken
dazwischen. So war das erste Mal, als ich mich mit der Thematik
auseinander gesetzt habe vor einer Renovierung eines alten Häuschens.
Danach hättest Du mich nur noch zum Thema Brecheisen etc. befragen
können :-) Ich bin so einer, der relativ schnell Dinge vergisst, die er
nicht ständig anwendet. Ist halt so. Und ehrlich gesagt, glaube ich,
dass es da anderen auch nicht unbedingt besser geht. Ich denke, wenn ich
mit dem Zeug mein Geld verdienen würde, dann würde der Code auch anders
aussehen. Ich hab jetzt eigentlich nur noch die Brach-Befehle zu machen.
Wenn das dann alles fertig ist, werde ich mal so einen 6502
Emulator-Testcode laufen lassen und schauen, was passiert.
Und noch zum Thema Lernresistenz: Bin gerade dabei mir das Buch "Der
leichte Einstieg in die Elektronik" durchzulesen. Das passiert bei mir
immer auf dem Weg zur Arbeit. Also unterm Strich. Es ist einfach ein
sehr weites Thema alles zusammen. Und ich habe nicht den Anspruch, alles
auf Anhieb perfekt zu machen. Deswegen wende ich mich auch oft hier ins
Forum. Zugegeben, dass es manchmal so aussieht wie "lass die mal
machen". Mich interessieren halt oft auch die Meinungen von den Profis.
Viele Grüße,
Peter
Peter Pippinger schrieb:> > Und noch zum Thema Lernresistenz: Bin gerade dabei mir das Buch "Der> > leichte Einstieg in die Elektronik" durchzulesen.
Das hilft dir allerdings nicht wirklich bei der Frage weiter, wann
welcher ARM-Befehl welche Flags beeinflusst. Dafür brauchts auch keinen
Profi (der ich übrigens nicht bin), sondern das passende Handbuch. Das
ARM Architecture Reference Manual. Das du dafür auch nicht von vorne bis
hinten durchblättern musst, das hat nämlich ein Inhaltsverzechnis.
ahh, ok, wenn das so ist, dann habe ich da was falsch gemacht. Ich
dachte, dass das rausgerutschte Bit ins Carry wandert, und danach gleich
an Bit7 des eigentlichen Wertes "wandert". Das schaue ich mir mal im
6502-Assembler an.
Ich habs frei nach
{adr}:={adr}/+C*128
aufgebaut.
Das habe ich dann wohl falsch interpretiert bzw. nicht richtig
verstanden.
Danke für den Hinweis.
So wie es aussieht, wird der Testcode eh noch so manches ans Licht
führen :-)
Peter Pippinger schrieb:
> > orrnes r6, r6, #3 << 31 // also set carry
Jau, stimmt, dass Carry wird hier gesetzt. Dummerweise aber auch Bit 31,
was meiner Erinnerung nach nicht ganz zum ROR Befehl der 6502 passt, der
ja nicht 8 sondern 9 Bits rotiert. Der LSR #1 davor passt dazu auch
nicht, das sollte wohl eher RRX sein.
Mir scheint es wird ein Schuh draus, wenn dein ORRNES sein Ergebnis in
die Wüste schickt. C wird gesetzt, NZ ebenfalls, und R6 ist dank RRX
bereits vorher schon korrekt.
Peter Pippinger schrieb:> ahh, ok, wenn das so ist, dann habe ich da was falsch gemacht. Ich> dachte, dass das rausgerutschte Bit ins Carry wandert, und danach gleich> an Bit7 des eigentlichen Wertes "wandert". Das schaue ich mir mal im> 6502-Assembler an.
Oder gleich in der offiziellen Referenz:
http://archive.6502.org/datasheets/synertek_programming_manual.pdf
Peter Pippinger schrieb:> habs ausprobiert:> orrnes r6, r6, #3 << 31 // also set carry>> hab extra die 3 genommen (Bit0+1). Bit1 "rutscht" automatisch ins Carry.
Meine ARM-Zeiten liegen schon etwas zurück, aber das kann nicht stimmen.
#3<<31 ist einfach eine Konstante, die auch so nicht (als ein Befehl)
kodiert werden kann.
Für den "immediate"-Teil gibt es nur 12 Bit, 8 Bit für den Wert und 4
Bit für die Shift-Position (*2) des 8-Bit-Wertes.
#3<<31 wäre binär also (als Konstante im Assembler)
1 10000000 00000000 00000000 00000000
und wenn der Assembler da keinen Fehler meldet, dann sollte er das
rausgefallene Bit einfach abschneiden (und 1<<31 als Konstante
verwenden).
Oder irre ich mich da?
A. K. schrieb:> Mir scheint es wird ein Schuh draus, wenn dein ORRNES sein Ergebnis in> die Wüste schickt.
Nö, weil N trotzdem falsch. Es wäre eine Operation nötig, die NZ
entsprechend R6 setzt und gleichzeitig C auf 1 setzt, ohne was an den
Daten zu verändern.
In meine Variante oben ist der Kommentar falsch, besser:
tst r6, r6 // get NZ state, CV unaffected
Peter Pippinger schrieb:>>mov r6, r6, rrx // the rotate operation> ist rrx ein shift-befehl?
Jein, es ist eine 33-Bit Rotate-Operation in der gleichen Weise wie die
9-Bit Rotate-Operation des ROR Befehls vom 6502, d.h. durch das Carry
Bit hindurch. ROR vom ARM hingegen ist eine 32-Bit Rotate-Operation.
Peter Pippinger schrieb:> strb r6, [r5] // store value
Was soll das eigentlich werden? Wenn R5 der 6502-PC ist, dann
überschreibst du den 6502-Code. Zudem mit 0, denn das sind die Bits 0-7
von R6 ja wohl.
A. K. schrieb:> Peter Pippinger schrieb:>>> strb r6, [r5] // store value>> Was soll das eigentlich werden?
Das wird mit allen Befehlen gemacht, die nicht implizit waren, also den
Speicher verändern. Damit wird der Wert (r6={pc}), den meine
entsprechende Adressierungsart an die Adresse (r5=pc) zurückgeschrieben,
wo der Wert herkam...
Also z.B.:
1
...
2
ROR__zp:
3
mov r4, #5 // at least 5 clock-cycles
4
mem_zp
5
opc_ROR
6
b drive_cpu
7
...
8
mem_zp macro
9
ldrb r5, [r8], #1 // get address for $xx
10
ldrb r6, [r5] // get value from $xx into r6
11
endm
12
...
PS.: die Extracyclecounts bei boundary-crossed / Branchtaken sind noch
nicht berücksichtigt, werden aber auch noch kommen...
Darin ist R5 der Zeiger auf den Operanden und eben nicht der PC. Der
sitzt offenbar in R8.
Du müsstest dich mal entscheiden, ob du nun die Bits 0-7 oder 24-31 von
R6 als relevant betrachtest.
hmm, weiß nicht. Werde ich mal anschauen...
Aber nochmal wegen strb: es würde mich sehr wundern, wenn das bei meinen
Tests nicht aufgefallen wäre, da ich die Adressierungsarten eigentlich
auch schon getestet habe (bin mir zumindest sicher, dass ich DEC und INC
mit allen Adressierungsarten angesehen habe). Kann es sein, dass es
funktioniert, wenn die Bytereihenfolge (Byteorder, oder wie man das
nennt?) entspechend richtig eingestellt ist?
Peter Pippinger schrieb:> Kann es sein, dass es> funktioniert, wenn die Bytereihenfolge (Byteorder, oder wie man das> nennt?) entspechend richtig eingestellt ist?
Die kannst du übicherweise nicht verändern. Und wie auch immer die
eingestellt ist, STRB speichert immer die Bits 0-7 des Registers, die
Frage wäre höchstens wohin.
mov r6, r6, lsr #24 // shift value to first 8 bits
5
strb r6, [r5]
6
mrs r9, cpsr
7
endm
Da ist wohl wirklich noch nicht die gewünschte Konsistenz erreicht :-)
Werd ich noch anpassen... Macht wahrscheinlich Sinn, das gleich beim
Laden des Wertes zu machen bzw. beim Speichern (evtl. zusätzliches
Makro)...
Aber Danke nochmal für den Hinweis!
Gruß
Peter
Peter Pippinger schrieb:> Da ist wohl wirklich noch nicht die gewünschte Konsistenz erreicht :-)
Wohl wahr. DEC lässt nämlich die CV Flags in Frieden. Es könnte sich
lohnen, die Funktion der Befehle der 6502 nicht zu erraten, sondern
nachzuschlagen. Aber da klinge ich wohl wie eine Endlosschleife ;-).
hmm, auch hier hast Du Recht. ( Wobei ich schon zu meiner Verteidigung
sagen muss, dass ich durchaus nach einer Vorlage arbeite:
http://www.oxyron.de/html/opcodes02.html ). Evtl. ist der
Produktivitätsfaktor in der Nacht nicht so hoch :-)
Würdest Du dann sagen, dass es überhaupt Sinn macht, die Status-Flags
vom ARM zu nehmen? Hmm vielleicht ist das wirklich zu viel der
Optimierung zu Beginn. Ich denke mal, ich werde die Flag-Geschichten
auch über Makros abbilden, dass ich das dann zentral ändern kann...
Wie hättest Du denn den DEC-Befehl umgesetzt?
würdest Du dann den SUB(S) ohne (S) machen und entsprechend Bit7 testen
und N-Flag setzen, und dann noch nach Zero testen und entsprechend das
Z-Flag setzen?
Was hältst Du davon, nur die betroffenen Bits von cpsr nach r9 zu
"kopieren". Dann könnte ich doch weiterhin mit dem SUBS arbeiten.
Peter Pippinger schrieb:> Würdest Du dann sagen, dass es überhaupt Sinn macht, die Status-Flags> vom ARM zu nehmen?
Kann man durchaus so machen wie du. Aber natürlich nur bei NVZC und bei
6502-Befehlen mit passender Arbeitsweise. Bei BIT passt das weniger gut.
> Wie hättest Du denn den DEC-Befehl umgesetzt?
Trivial: NZ lässt sich aus dem Ergebnis testen ohne CV zu stören, wie
ich es oben in meiner Version verwendete. Gibt halt einen Befehl mehr.
A. K. schrieb:> Kann der IAR Assembler den Registern eigene Namen geben? Wäre hier> sicherlich nützlich.
Hallo, nachdem jetzt endlich der Jungelkönig feststeht, habe ich mal
Zeit gefunden in der IAR-Anleitung nachzulesen (man lese und staune!).
Da konnte ich auf Anhieb nichts finden. Google hingegen hat mir dann ein
Ergebnis gebracht, welches ich hier der Vollständigkeit halber aufzeigen
möchte:
// register A
#define REG_A r10
ldr REG_A, =0x01 << 31;
Läd dann in r10 den gewünschten Wert.
@A.K. ist ein prima Tip gewesen, den ich gleich mit in den Code
reinbauen werde.
Um nochmal auf das Threadthema zu kommen. Ich habe eben gelesen, dass
die Bits 8-27 im CPSR "unused" wären. Kann ich die dann auch setzen?