Re: Bankswitching!
- From: Stefan Reuther <stefan.news@xxxxxxxx>
- Date: Wed, 28 Dec 2005 22:02:54 +0100
Hallo,
Andreas Koch wrote:
> Stefan Reuther wrote:
>> Beim Umladen der Overlays (ent-
>> spricht dem Bankswitching) werden u.A. Stackframes entsprechend konver-
>> tiert, so dass ein Return im Overlay-Manager und nicht in der ausgeblen-
>> deten Routine landet.
>
> Was musste man bei der Benutzung dieser Overlays alles beachten?
> Manuell ent/laden? Zugriffe von einem Overlay auf das andere?
Das macht alles der Compiler. Es gibt einen Compilerschalter "mach
overlayfähigen Code" ($O+), das war's.
Es wird für jede exportierte Adresse ein Stub im allgemein sichtbaren
Speicher erzeugt. Wenn ein Modul geladen wird, wird der Stub durch einen
Sprung in die aktuelle Instanz des Moduls ersetzt. Wird es entladen,
wird wieder der Sprung in den Overlay-Manager eingetragen. Außerdem geht
der Overlaymanager beim Umladen den Stack durch und ersetzt Rücksprung-
Adressen, die in ein entferntes Modul zeigen, auf eine geeignete Routine
des Overlaymanagers.
Der Compilerschalter sorgt dann noch dafür, dass wirklich niemals
Adressen aus einem Modul in ein anderes gelangen. Beispielsweise wird
normalerweise mit
procedure foo(s : string);
ein Aufruf
foo('egal');
so übersetzt, dass der Aufrufer nur die Adresse der Konstanten übergibt
und 'foo' diese sich kopiert. Die Konstante liegt im Codesegment. Mit
Overlay-Unterstützung kopiert der Compiler den Parameter vorher
automatisch in eine lokale Variable und übergibt diese.
Ach so, und dann kann man zwecks Optimierung normalerweise seinen Code
mit Near-Calls übersetzen (Routinen im gleichen Modul rufen sich über
einen relativen Sprung, nicht über eine direkte Adresse auf), das geht
mit Overlays nicht, weil dann der Overlay-Manager den Stack nicht mehr
interpretieren kann. Aber auch das ist nur ein Compilerschalter.
>> Ansonsten ist das auch kein wirkliches Problem. Man macht halt 'fette'
>> Pointer, und speichert zu jedem Zeiger neben der Adresse auch noch die
>> Banknummer. Ist auch nichts anderes als Arithmetik mit 'huge'-Pointern.
>
> Schon. Das dumme ist nur, wenn man das z.B. in C machen will, müsste
> man da sehr sehr sehr oft Banken prüfen bzw. umschalten, denke ich;
Natürlich. Aber ein C-Compiler mit Huge-Pointern macht genau das. Ein
Huge-Pointer besteht aus Segment und Offset. Bei jeder Operation prüft
der Compiler, ob der Offset überläuft und in ein neues Segment
gewechselt werden muss.
Huge-Pointer unter MS-DOS haben nun noch die Eigenschaft, dass die
Segmente überlappen (also 0x200:0x1050 ist das gleiche wie
0x205:0x1000). Das kann man zur Optimierung ausnutzen. Muss man aber nicht.
> Es sei denn man schränkt stark ein, vonwegen maximal eine Bank für
> globale Variablen und je eine Bank pro Modul für lokale.
Das wären dann nur langweilige Large-Pointer :)
>> Wenn ich mich richtig erinnere, gibt für die PIC-µC C-Compiler, die
>> Bankswitching mittels fetter Pointer machen, weil diverse Modelle davon
>> nicht allen Speicher linear adressieren können.
>
> Kennst du da zufällig Details welche Limits das beim C-Code bewirkt?
Keine. Standardmäßig erzeugt der wohl Code, der wie wahnsinnig hin und
her switcht.
http://ww1.microchip.com/downloads/en/DeviceDoc/MPLAB_C18_Users_Guide_51288j.pdf
Seite 52:
| Banking optimization removes MOVLB instruction in instances where it
| can be determined that the Bank Select register already contains the
| correct value. For example, given the following C source code
| fragment:
| unsigned char a, b;
| a = 5;
| b = 5;
| If compiled with banking optimization disabled (-On-), MPLAB C18 will
| load the Bank Select register prior to each assignment:
| 0x000000 MOVLB a
| 0x000002 MOVLW 0x5
| 0x000004 MOVWF a,0x1
| 0x000006 MOVLB b
| 0x000008 MOVWF b,0x1
| When this same code is compiled with banking optimization enabled
| (-On+), MPLAB C18 may be able to eliminate the second MOVLB
| instruction by determining that the value of the Bank Select register
| will not change:
| 0x000000 MOVLB a
| 0x000002 MOVLW 0x5
| 0x000004 MOVWF a,0x1
| 0x000006 MOVWF b,0x1
> Um es etwas übertrieben darzustellen - Ich überlege ob/wie es möglich
> wäre, einen C-Compiler so zu bauen, daß er beliebige, (sehr) große
> C-Sourcen, die sagen wir mal 2 MB Code in einer einzigen Source-Datei
> haben und 500K große Records bearbeitet, also schlecht aufgeteilt
> werden kann, ohne Anpassungen für einem Z80 mit 64 KB Addressraum und 8
> MB bankswitched RAM compilieren kann.
> Und zwar ohne darauf eine virtuelle 32-Bit-CPU zu emulieren sondern
> halbwegs effizient ;-)
Möglich ist das. Aber es wird wirklich darauf hinauslaufen, "eine
32-bit-CPU zu emulieren". Mögliche Optimierungen sind nur sowas wie oben
(aufeinanderfolgende Zugriffe auf die gleiche Bank erkennen und
wegoptimieren). Ansonsten muss eben ein Pointer aus z.B. 24 Bit bestehen
und vor jedem Speicherzugriff ein Bankregister umgeladen werden.
Stefan
.
- References:
- Bankswitching!
- From: Andreas Koch
- Re: Bankswitching!
- From: Stefan Reuther
- Re: Bankswitching!
- From: Andreas Koch
- Bankswitching!
- Prev by Date: Re: Bankswitching!
- Next by Date: Re: Schleifenkonstrukt
- Previous by thread: Re: Bankswitching!
- Next by thread: Re: Bankswitching!
- Index(es):
Relevant Pages
|