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