|
|
|
|
*** Selbstoptimierender Assemblercode ? Klar, kein Problem ! *** Als ich mit Piranha (grüße !) ein paar Mails schrieb und mich mit Splines beschäftigte (Die Propellerteile die in "Static Chaos" rumfliegen), ärgerte ich mich darüber wieviel Zyklen nur allein für die eigentlich unnötigen Befehle (Iterationscounter, Verzweigungen etc) draufgehen, und ich dachte mir eine möglichkeit aus dieses Ballast abzuwerfen, durch selbstoptimierenden Code. *** Download ***
;
;$VER: SelfOptimize.asm 1.05 am 27.4.92 (c) Holger.Hippenstiel.org - lynxx@uni.de
;
;Erdacht und verwendet für "The Silents - Static Chaos" Trackmo, relase 7/92.
;
;Dies ist eine Routine, die per Trace-Exception Programme optimieren kann,
;so eine Art "Just in Time" Compiler. Wäre Beispielsweise diese Programm gegeben:
;
; lea Count(pc),a3
;Loop: bsr.b Unter
; subq #1,(a3)
; bcc.b Loop
; rts
;Unter: addq #1,(a0)+
; rts
;Count: dc.w 2
;Und würde diesen Optimierer durchlaufen, würde nur
;
; addq #1,(a0)+
; addq #1,(a0)+
; rts
;
;übrigbleiben.
:
;Die übernommenen Befehle können je nach Anforderung im "TraceWatcher" angepasst werden.
;
;Assembler-Kompabilität:
;+AsmOne, AsmPro, DevPac [Default Type = word], MasterSeka & Profimat
;+Mindest 68010-Assemblier-Modi erforderlich.
;-Ungetestet: A68k
;
_LVOSuperVisor = -30 ;SuperVisor modus aktivieren
AttnFlags = 296 ;Prozessor-Flags in der ExecBase
SelfOptimizer:
move.l 4.w,a6 ;ExecBase holen
lea Optimize(pc),a5 ;Routine für SuperVisor-Modus
jsr _LVOSuperVisor(a6) ;Sprung in SuperVisor-Routine
move.l a2,d0 ;Ende Gelände, das Erzeugte Programm steht
rts ;jetzt bei A-E, bzw d0 gibt das genaue Ende an.
Optimize:
sub.l a5,a5 ;Default für VBR ist 0
moveq #1+2+4+8+128,d7 ;68010+68020+68030+68040+68060
and AttnFlags(a6),d7 ;Mit vorhandenen Prozessor-Flags maskieren
beq.b .NoTurbo ;Nur 68000
movec VBR,a5 ;Vector Base Register holen
.NoTurbo:
move.l $24(a5),-(a7) ;Trace-Vector sichern
move.l a5,-(a7) ;VBR sichern
lea TraceWatcher(pc),a0 ;Trace-Überwachungs-Routine
move.l a0,$24(a5) ;In Trace-Vector eintragen
lea SplinePrg(pc),a2 ;Hier soll das erzeugte Programm abgelegt werden
lea -400(a7),a7 ;Work-Space für die Spline-Routine
lea 300(a7),a0 ;Workspace absteigend
lea 320(a7),a3 ;Counter für Iterations-tiefe,
;wird nur für die normale/Trace-Version benötigt
move #3,(a3) ;Anfangs-Rekursions
;(Rekursions-Tiefe (Max 14=>1+2^(14+1)=32769 Pixel))
move #$a700,SR ;Alle Interrupts aus, aber TRACE an !
bsr.s FbRec ;Ab hier schlägt nach jedem Befehl die
;Trace-Exception zu, siehe -> TraceWatcher
move #$2700,SR ;Alle Interrupts aus, und kein TRACE mehr.
subq #2,a2 ;Den obigen Befehl "move #$2700,SR" wieder wegnehmen.
move #$4e75,-2(a2) ;Erzeugte Routine mit rts abschliessen.
lea 400(a7),a7 ;Stack korrigieren
move.l (a7)+,a5 ;VBR restaurieren
move.l (a7)+,$24(a5) ;Alten Trace-Vector setzen.
rte ;Ende des SuperVisor-Modus
;Diese Routine wird bei jedem ausgeführtem Befehl aufgerufen
;"Befehl überspringen" bedeutet nicht, das der Befehl nicht ausgeführt wird,
;er wird nur nicht in der erzeugten Routine übernommen.
TraceWatcher:
move.l 2(a7),a1 ;Gerade auszuführenden Befehl holen
move (a1),d7 ;Momentaner Befehl
cmp #$5353,d7 ;subq #1,(a3) == Iterationstiefe kleiner ?
beq.b .SkipCommand ;Befehl überspringen
cmp #$5253,d7 ;addq #1,(a3) == Iterationstiefe größer ?
beq.b .SkipCommand ;Befehl überspringen
cmp #$4e75,d7 ;rts ?
beq.b .SkipCommand ;Befehl überspringen
clr.b d7 ;Untereres Byte löschen
cmp #$6400,d7 ;bcc.b xxx
beq.b .SkipCommand ;Befehl überspringen
cmp #$6100,d7 ;bsr.s xxx
beq.b .SkipCommand ;Befehl überspringen
cmp #$4c00,d7 ;movem (ax)+
beq.b .TakeLong ;Langwort übernehmen
cmp #$4800,d7 ;movem -(ax)
beq.b .TakeLong ;Langwort übernehmen
move (a1),(a2)+ ;Wort übernehmen
.SkipCommand:
rte ;Zurück und Befehl ausführen !
.TakeLong:
move.l (a1),(a2)+ ;Langwort übernehmen
rte ;Zurück und Befehl ausführen !
;Long-Align etc unnötig, da diese Routine nur 1 mal ausgeführt wird.
FbRec: ;Dies ist die "normale" Spline-Routine, die optimiert werden soll.
.IterM: move d5,d2
.IterL: add d1,d2
roxr #1,d2
addx d0,d1
roxr #1,d1
addx d6,d5
roxr #1,d5
move d5,d4
add d2,d4
roxr #1,d4
addx d1,d2
roxr #1,d2
move d4,d3
add d2,d3
roxr #1,d3
subq #1,(a3)
bcc.b .ReIter
sub a2,d3
sub a2,d6
movem d3/d6,-(a0)
addq #1,(a3)
rts
.ReIter:movem d3/d4/d5/d6,-(a7)
move d2,d5
move d3,d6
bsr.b .IterL
movem (a7)+,d0/d1/d5/d6
bsr.b .IterM
addq #1,(a3)
rts
;Der normale init-Code für die Spline-Routine
A: movem -6(a0),d0/d1/d5/d6
add a2,d0
add a2,d1
add a2,d5
add a2,d6
;An dieser Stelle wird die optimierte Routine abgelegt.
SplinePrg: ds.l 147
E:
|