Forum: Mikrocontroller und Digitale Elektronik 6502 ROR auf ARM7 Emulieren / freie Bits im Statusregister?


von Peter P. (uncle-sam7)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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:
1
mov  r6, r6, rrx         // the rotate operation
2
movs temp, r6, lsr #24   // bit 23 to C
3
and  r6, r6, #0xFF << 24 // clear bits 0-23
4
tst  r6, r6              // get NZV state, C unaffected

von Peter P. (uncle-sam7)


Lesenswert?

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

von Peter P. (uncle-sam7)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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.

von Peter P. (uncle-sam7)


Lesenswert?

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 :-)

von (prx) A. K. (prx)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

Sorry wenns den Thread etwas zersemmelt hat, aber da war bei meinen 
Beiträgen auch mancher Schnellschuss dabei, der dem Löschknopf zu Opfer 
fiel.

von (prx) A. K. (prx)


Lesenswert?

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

von Torsten K. (ago)


Lesenswert?

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?

von (prx) A. K. (prx)


Lesenswert?

Nö, du irrst nicht. Ob er 1<<31 oder 3<<31 schreibt ist daher egal. 
Jedenfalls wenn der Assembler nicht meckert.

von (prx) A. K. (prx)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von Peter P. (uncle-sam7)


Lesenswert?

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...

von (prx) A. K. (prx)


Lesenswert?

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.

von Peter P. (uncle-sam7)


Lesenswert?

...jetzt wo du´s sagst, ich glaube da fehlt beim Laden und Speichern 
noch der Shift der Daten auf bits0-7. Danke :-)

von (prx) A. K. (prx)


Lesenswert?

Kann der IAR Assembler den Registern eigene Namen geben? Wäre hier 
sicherlich nützlich.

von Peter P. (uncle-sam7)


Lesenswert?

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?

von (prx) A. K. (prx)


Lesenswert?

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.

von Peter P. (uncle-sam7)


Lesenswert?

Ok, habs mir nochmal angesehen:
1
opc_DEC macro 
2
  mov r6, r6, lsl #24    // shift value to last 8 bits
3
  subs r6, r6, #1 << 24  // {adress} = {adress} - 1
4
  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

von (prx) A. K. (prx)


Lesenswert?

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 ;-).

von Peter P. (uncle-sam7)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von Peter Pippinger (Gast)


Lesenswert?

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?

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.