Hallo NG, ich habe hier ein Problem, von dem ich nicht weiß, warum es da ist. Für meinen Programmcounter des 6502 Emulators habe ich das Register R8 vorgesehen, was auch super funktioniert. Jetzt habe angefangen, die restlichen Opcodes "einzubauen". Der Assembler (IAR) fängt nun plötzlich zum Meckern an, dass ein Label out of range wäre. Das Komische daran: Wenn ich die Adresse des Labels "hart" übergebe funktioniert es. Dabei verliere ich allerdings den Komfort, dass sich diese Adresse nach einer Programmveräderung ändern kann. Vielen Dank für jeden Hinweis und viele Grüße Peter ---------------------- Im Quelltext: ---------------------- // program counter (pc) ldr r8, =0xc80 // FUNKTIONIERT // ldr r8, =memory // expression out of range ---------------------- Nach dem Assemblieren: ---------------------- ... __iar_program_start: 0x80: 0xe3a08ec8 MOV r8, #3200 ; 0xc80 ... memory: 0xc80: 0x0a0a0a0a DC32 168430090 ; '....' 0xc84: 0x0a0a0a0a DC32 168430090 ; '....'
ich denke mal der IAR versucht beim... ldr r8, =memory nen 32bit wert in den Opcode einzubauen. wenn ich es aber richtig verstehe kann das der Arm nicht. Schau mal hier rein (letzten 2 Seiten)... http://www.informatik.uni-ulm.de/ni/Lehre/WS01/TI2/folien/ciscC.PDF ----EDIT: hab nochmal geschaut ... versuch das doch mal mit dem GNU AS zu assemblieren ... in meinem startupcode mach ich das auch recht oft genau so und es funzelt wunderbar ... evtl macht der IAR da iwas anders ne gute toolchain die gut funzelt ist die sog. YAGARTO http://www.yagarto.de/
Ich kenne den ARM-Befehlssatz nicht so gut, aber hier: http://simplemachines.it/doc/arm_inst.pdf steht auf Seite 35, daß LDR alles laden kann. Wenn's nicht passt, dann wird es per Literal geladen. Zumindest sollte der Compiler es so umsetzen. Aber warum schreibst du den C64-Emulator überhaupt in Assembler? Ich habe letztens mal einen IIR-Filter in C implementiert und der war mit -O2 und GCC compiliert problemlos noch halb so schnell, wie die handoptimierte Referenzimplementation aus einem ARM Handbuch, die mehrere Seiten brauchte und interessante Tricks mit zwei Werte in einem Register speichern usw. angewendet hat. Meine C-Implementierung war 5 Zeilen oder so lang, denn die IIR-Implementierung ist trivial, wenn man erstmal die Koeffizienten hat.
Frank Buss schrieb: > http://simplemachines.it/doc/arm_inst.pdf > steht auf Seite 35, daß LDR alles laden kann. Wenn's nicht passt, dann > wird es per Literal geladen. Zumindest sollte der Compiler es so > umsetzen. Wie gesagt, er machte es z.Zt. nur noch, wenn ich die Adresse "fest" reinschreibe. > Aber warum schreibst du den C64-Emulator überhaupt in Assembler? naja, das mit C hat ja bei mir schon mal ein SID-File abgespielt. Der negative Beigeschmack war allerdings, dass der Compiler für sich auch Dinge im SRAM des AT91SAM7 reserviert (Stack, Variablen etc.). In der Assembler Version passiert in der Emulationsschicht überhaupt nichts im SRAM ausser Zugriffe auf den "64er"-Speicher. Mir gefällt der Weg so viel besser, da ich mir da um viele andere Dinge keine Gedanken machen muss... @Lennart S.: hab http://www.yagarto.de/ bei mir installiert. Ein C-Projekt jabe ich damit schon mal gemacht. Wie muss denn ein Assemblerprojekt damit aussehen? Hast Du da ein Beispiel oder einen Link? Viele Grüße, Peter
Die Operation LDR rx, =symbol legt üblicherweise das gewünschte Adresswort in den Speicher und erzeugt einen LDR-Befehl, der dieses Wort PC-relativ läd. Solche Konstanten werden in einem Konstanten-Pool gesammelt, der irgenwann raus muss. Rechtzeitig raus muss, bevor die PC-relative Distanz dazu grösser als 4KB wird. Man muss also dem Assembler gelegentlich zu verstehen geben, dass nun im Code Platz dafür ist, denn von sich aus darf der das ja nicht irgendwo zwischen zwei Befehlen reinschieben.
A. K. schrieb: > Man muss also dem Assembler gelegentlich zu verstehen geben, > dass nun im Code Platz dafür ist, denn von sich aus darf der das ja > nicht irgendwo zwischen zwei Befehlen reinschieben. hmm, das verstehe ich nicht ganz, die 4K-Grenze könnte wirklich sein, aber wieso funktioniert das dann, wenn ich nicht den Labelnamen verwende, sondern die Adresse, die das Label nach dem Assemblieren haben wird? ldr r8, =0xc80 // FUNKTIONIERT ldr r8, =memory // funktioniert NICHT: expression out of range Hast Du vielleich ein Schlagwort, wonach ich diesbezgl. in den Einstllungen sichen könnte? Viele Grüße, Peter
Peter schrieb: > hmm, das verstehe ich nicht ganz, die 4K-Grenze könnte wirklich sein, > aber wieso funktioniert das dann, wenn ich nicht den Labelnamen > verwende, sondern die Adresse, die das Label nach dem Assemblieren haben > wird? Das liegt daran, dass "memory" für den Assembler eine verschiebliche Adresse ist, deren exakten Wert erst der Linker kennt, während 0xC80 ein bereits dem Assembler bekannter Wert ist. Für bekannte passende Konstanten erzeugt er MOV/MVN, andernfalls LDR PC-rel. Nur letzteres benötigt den literal pool. Zum literal pool siehe Assembler-Statement LTORG. Darauf wird übrigens auch in der (m.E. hier ziemlich miesen) IAR Assembler Doku verwiesen.
Hallo nochmal, also ich hab nichts mehr rausfinden können, wie man dem Assembler beibringt, nicht so kleinlich zu sein :-( Naja, jetzt habe ich es - um weitermachen zu können - einfach über einen "Zeigerumweg" gelöst (siehe unten). Gefällt mir nicht, aber es geht. Was mir noch aufgefallen ist: für "memory" benötige ich ja sowas eh nicht, da die Adresse dann ja sowieso innerhalb 0x200000 (SRAM) liegt. "Memory" war für mich nur ne Krücke, um die Opcodes testen zu können. Und den Opcodes-Pointer kann ich ja zu Beginn 1x setzen. Während des Betriebs wird dieses Register dann eh nicht mehr geändert. @A.K.: wäre schön, wenn Du mir noch sagen könntest, ob es da nicht doch ne Lösung innerhalb der IAR gibt, damit die 4k keine Rolle spielen. Wäre rein Interessehalber... PS.: Die Opcodes die mit "_" beginnen und noch keine Adressierungsart am Ende haben, muss ich noch umsetzen. Die anderen funktionieren schon. PPS.: Hab übrigens noch richtig gute Testsuites für 6502-Emulator-Bauern gefunden: http://visual6502.org/wiki/index.php?title=6502TestPrograms (nur für die, die es interessiert). PPPS.: Die Adressierungsarten / Clockcyclecount etc. habe ich nicht in eine getrennte Sprungtabelle gepackt. Somit spare ich mir auch wieder ein paar Takte...
1 | ... |
2 | |
3 | pointer_memory: |
4 | DC32 memory |
5 | |
6 | pointer_opcodes: |
7 | DC32 opcodes |
8 | |
9 | // ------------------------------------------------------------------- |
10 | // include headers |
11 | // ------------------------------------------------------------------- |
12 | #include <at91sam7s256.h> |
13 | |
14 | // ------------------------------------------------------------------- |
15 | // main entry point |
16 | // ------------------------------------------------------------------- |
17 | __iar_program_start: |
18 | |
19 | // ------------------------------------------------------------------- |
20 | // definitions for 6502 cpu |
21 | // ------------------------------------------------------------------- |
22 | // stack pointer (sp) |
23 | ldr r7, =0xff |
24 | |
25 | // program counter (pc) |
26 | ldr r8, pointer_memory |
27 | |
28 | ... |
29 | |
30 | // ------------------------------------------------------------------- |
31 | // 6502 main loop |
32 | // ------------------------------------------------------------------- |
33 | drive_cpu: |
34 | ldrb r4, [r8], #1 |
35 | ldr r3, pointer_opcodes |
36 | ldr pc, [r3, r4, lsl #2] |
37 | |
38 | ... |
39 | |
40 | // ------------------------------------------------------------------- |
41 | // c64 memory / this is where the sidfiles remaining |
42 | // ------------------------------------------------------------------- |
43 | ALIGNRAM 4 |
44 | memory: |
45 | DC8 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a |
46 | |
47 | // ------------------------------------------------------------------- |
48 | // c64 opcodes |
49 | // ------------------------------------------------------------------- |
50 | // _imm = #$xx |
51 | // __zp = $xx |
52 | // _zpx = $xx,X |
53 | // _zpy = $xx,Y |
54 | // _izx = ($xx,X) |
55 | // _izy = ($xx),Y |
56 | // _abs = $xxxx |
57 | // _abx = $xxxx,X |
58 | // _aby = $xxxx,Y |
59 | // _ind = ($xxxx) |
60 | // _rel = $xxxx (pc-relative) |
61 | // ------------------------------------------------------------------- |
62 | ALIGNRAM 4 |
63 | |
64 | // ------------------------------------------------------------------- |
65 | opcodes: /* 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F */ |
66 | // ------------------------------------------------------------------- |
67 | DC32 /*00*/ _BRK , ORA_izx, _xxx , _xxx , _xxx , ORA__zp, ASL__zp, _xxx , _PHP , ORA_imm, ASL_imp, _xxx , _xxx , ORA_abs, ASL_abs, _xxx |
68 | // ------------------------------------------------------------------- |
69 | DC32 /*01*/ _BPL , ORA_izy, _xxx , _xxx , _xxx , ORA_zpx, ASL_zpx, _xxx , _CLC , ORA_aby, _xxx , _xxx , _xxx , ORA_abx, ASL_abx, _xxx |
70 | // ------------------------------------------------------------------- |
71 | DC32 /*02*/ _JSR , AND_izx, _xxx , _xxx , _BIT , AND__zp, _ROL , _xxx , _PLP , AND_imm, _ROL , _xxx , _BIT , AND_abs, _ROL , _xxx |
72 | // ------------------------------------------------------------------- |
73 | DC32 /*03*/ _BMI , AND_izy, _xxx , _xxx , _xxx , AND_zpx, _ROL , _xxx , _SEC , AND_aby, _xxx , _xxx , _xxx , AND_abx, _ROL , _xxx |
74 | // ------------------------------------------------------------------- |
75 | DC32 /*04*/ _RTI , EOR_izx, _xxx , _xxx , _xxx , EOR__zp, _LSR , _xxx , _PHA , EOR_imm, _LSR , _xxx , JMP_abs, EOR_abs, _LSR , _xxx |
76 | // ------------------------------------------------------------------- |
77 | DC32 /*05*/ _BVC , EOR_izy, _xxx , _xxx , _xxx , EOR_zpx, _LSR , _xxx , _CLI , EOR_aby, _xxx , _xxx , _xxx , EOR_abx, _LSR , _xxx |
78 | // ------------------------------------------------------------------- |
79 | DC32 /*06*/ _RTS , _ADC , _xxx , _xxx , _xxx , _ADC , _ROR , _xxx , _PLA , _ADC , _ROR , _xxx , JMP_ind, _ADC , _ROR , _xxx |
80 | // ------------------------------------------------------------------- |
81 | DC32 /*07*/ _BVS , _ADC , _xxx , _xxx , _xxx , _ADC , _ROR , _xxx , _SEI , _ADC , _xxx , _xxx , _xxx , _ADC , _ROR , _xxx |
82 | // ------------------------------------------------------------------- |
83 | DC32 /*08*/ _xxx , STA_izx, _xxx , _xxx , STY__zp, STA__zp, STX__zp, _xxx , DEY_imp, _xxx , TXA_imp, _xxx , STY_abs, STA_abs, STX_abs, _xxx |
84 | // ------------------------------------------------------------------- |
85 | DC32 /*09*/ _BCC , STA_izy, _xxx , _xxx , STY_zpx, STA_zpx, STX_zpy, _xxx , TYA_imp, STA_aby, TXS_imp, _xxx , _xxx , STA_abx, _xxx , _xxx |
86 | // ------------------------------------------------------------------- |
87 | DC32 /*0A*/ LDY_imm, LDA_izx, LDX_imm, _xxx , LDY__zp, LDA__zp, LDX__zp, _xxx , TAY_imp, LDA_imm, TAX_imp, _xxx , LDY_abs, LDA_abs, LDX_abs, _xxx |
88 | // ------------------------------------------------------------------- |
89 | DC32 /*0B*/ _BCS , LDA_izy, _xxx , _xxx , LDY_zpx, LDA_zpx, LDX_zpy, _xxx , _CLV , LDA_aby, TSX_imp, _xxx , LDY_abx, LDA_abx, LDX_aby, _xxx |
90 | // ------------------------------------------------------------------- |
91 | DC32 /*0C*/ CPY_imm, CMP_izx, _xxx , _xxx , CPY__zp, CMP__zp, DEC__zp, _xxx , INY_imp, CMP_imm, DEX_imp, _xxx , CPY_abs, CMP_abs, DEC_abs, _xxx |
92 | // ------------------------------------------------------------------- |
93 | DC32 /*0D*/ _BNE , CMP_izy, _xxx , _xxx , _xxx , CMP_zpx, DEC_zpx, _xxx , _CLD , CMP_aby, _xxx , _xxx , _xxx , CMP_abx, DEC_abx, _xxx |
94 | // ------------------------------------------------------------------- |
95 | DC32 /*0E*/ CPX_imm, _SBC , _xxx , _xxx , CPX__zp, _SBC , INC__zp, _xxx , INX_imp, _SBC , NOP_imp, _xxx , CPX_abs, _SBC , INC_abs, _xxx |
96 | // ------------------------------------------------------------------- |
97 | DC32 /*0F*/ _BEQ , _SBC , _xxx , _xxx , _xxx , _SBC , INC_zpx, _xxx , _SED , _SBC , _xxx , _xxx , _xxx , _SBC , INC_abx, _xxx |
98 | // ------------------------------------------------------------------- |
Peter Pippinger schrieb: > @A.K.: wäre schön, wenn Du mir noch sagen könntest, ob es da nicht doch > ne Lösung innerhalb der IAR gibt, damit die 4k keine Rolle spielen. Wäre > rein Interessehalber... Klar. Rechtzeitig mal ein LTORG einstreuen, damit der Assembler den literal pool los wird bevor die 4K rum sind. Wirst ja wohl irgendwo ein Plätzchen finden, bei dem die so erzeugten Daten dem Code nicht im Weg sind, beispielsweise hinter einem unbedingten Sprung oder Return.
Vielen Dank, A.K.! das funktioniert. Habe jetzt bei einem Opcode (ca. in der Mitte des Codes) folgendes gemacht:
1 | ... |
2 | |
3 | ORA_aby: |
4 | mov r4, #4 // at least 4 clock-cycles |
5 | mem_aby |
6 | opc_ORA |
7 | b drive_cpu |
8 | LTORG |
9 | |
10 | ... |
Jetzt funktioniert auch das Assemblieren wieder auf die "alte" Art :-) Danke nochmal und viele Grüße, Peter
Peter Pippinger schrieb: > naja, das mit C hat ja bei mir schon mal ein SID-File abgespielt. Der > negative Beigeschmack war allerdings, dass der Compiler für sich auch > Dinge im SRAM des AT91SAM7 reserviert (Stack, Variablen etc.). > > In der Assembler Version passiert in der Emulationsschicht überhaupt > nichts im SRAM ausser Zugriffe auf den "64er"-Speicher. Mir gefällt der > Weg so viel besser, da ich mir da um viele andere Dinge keine Gedanken > machen muss... Also streng genommen brauchst du mehr als 64k Speicher, um den C64 perfekt nachzubilden, siehe die Dekodierungstabelle des PLAs: http://www.c64-wiki.de/index.php/PLA_(C64-Chip) Also die 64 kB RAM, die man tatsächlich komplett einblenden kann in den adressierbaren Bereich (natürlich bis auf die Adressen 0 und 1) und zusätzlich die IO-Bereiche von SID, VIC usw., die sich zwar größtenteils wiederholen, aber man darf auch nicht das 1k Nibble RAM des Farbspeichers vergessen. Ich würde aber mal vermuten, daß es keine Musik gibt, die das alles ausnutzt. Habe gerade die HVSC durchsucht und gibt zwar einige SID-Dateien, die bis zu 62k groß sind, aber das sind meist nur langweilige Samples, kein richtiger Chip-Tune. Man könnte bestimmt mit 32k fast alle (interessanten) SID-Files abspielen. Wäre also kein Grund für Assembler. Ich verstehe aber, wenn du in Assembler programmieren willst, weil das cool ist oder so :-)
Frank Buss schrieb: > Wäre also kein Grund für Assembler. > Ich verstehe aber, wenn du in Assembler programmieren > willst, weil das cool ist oder so :-) Hallo Frank, "oder so" trifft es gut ;-) nee, im Ernst: Ich finde es tatsächlich cool, mal wieder was in Assembler zu machen. Das mit dem Speicher ist mir bekannt. Aber ich denke für die SIDs ist es nicht von Bedeutung. Bin ja auch schon am schauen, was ich dann als nächste Hardware verwenden kann, gerade weil mir das mit dem "knappen" Speicher nicht so gefällt. Was hältst Du von diesem Board hier: http://shop.embedded-projects.net/index.php?module=artikel&action=artikel&id=499 Viele Grüße, Peter
Sieht gut aus das Board. Müsste man mal probieren, ob das mit dem externen RAM nicht problematisch wird mit der Zugriffszeit, aber sollte gehen. Wenn du es kleiner haben willst, gibt es von Renesas noch nette Microcontroller, z.B. mit 1 MB integriertem RAM, ziemlich schnell und mit vielen anderen Features: http://www.renesas.com/products/mpumcu/superh/sh7260/sh7262/sh7262_root.jsp Damit könnte man vielleicht sogar Teile der Grafikausgabe für einen C64 simulieren. Natürlich keine VIC-Spezialeffekte, da braucht man dann einen FPGA für, wie beim C-One: http://de.wikipedia.org/wiki/C-One
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.