From 333b605b2afd472b823aeda0adf0e8b1ea9843c0 Mon Sep 17 00:00:00 2001 From: fishsoupisgood Date: Mon, 27 May 2019 02:41:51 +0100 Subject: initial commit from asl-1.41r8.tar.gz --- tests/t_parsys/t_parsys.asm | 994 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 994 insertions(+) create mode 100644 tests/t_parsys/t_parsys.asm (limited to 'tests/t_parsys/t_parsys.asm') diff --git a/tests/t_parsys/t_parsys.asm b/tests/t_parsys/t_parsys.asm new file mode 100644 index 0000000..8afe6f3 --- /dev/null +++ b/tests/t_parsys/t_parsys.asm @@ -0,0 +1,994 @@ + include parsys.i68 + + page 60 + cpu 68000 + +;----------------------------------------------------------------------------- +; Die Exceptionvektoren: + + supmode on + + org $00000000 ; Die Vektoren + dc.l 0 ; Adresse vom Stack (Dummy) + dc.l Start ; erster Start + dc.l ex_vec2 ; Busfehler + dc.l ex_vec3 ; Adressfehler + dc.l ex_vec4 ; Illegaler Befehl + dc.l ex_vec5 ; Division durch Null + dc.l ex_vec6 ; Befehl CHK + dc.l ex_vec7 ; Befehl TRAPV + dc.l ex_vec8 ; Privilegverletzung + dc.l StepProc ; Ablaufverfolgung + dc.l ex_vec10 ; Line-A --> Gleitkomma + dc.l S_LineF ; Line-F --> 68881-Emulator + dc.l ex_vec12 ; Reserviert + dc.l ex_vec13 ; Koprozessor-Protokollfehler + dc.l ex_vec14 ; illegaler FRESTORE-Frame + dc.l ex_vec15 ; nicht initialisierter Unterbrechungsvektor + dc.l ex_vec16 ; Reserviert + dc.l ex_vec17 ; Reserviert + dc.l ex_vec18 ; Reserviert + dc.l ex_vec19 ; Reserviert + dc.l ex_vec20 ; Reserviert + dc.l ex_vec21 ; Reserviert + dc.l ex_vec22 ; Reserviert + dc.l ex_vec23 ; Reserviert + dc.l ex_vec24 ; Unechte Unterbrechung + dc.l ex_vec25 ; autovektoriell 1 + dc.l ex_vec26 ; autovektoriell 2 + dc.l ex_vec27 ; autovektoriell 3 + dc.l ex_vec28 ; autovektoriell 4 + dc.l ex_vec29 ; autovektoriell 5 + dc.l ex_vec30 ; autovektoriell 6 + dc.l ex_vec31 ; autovektoriell 7 + dc.l PcSysCall ; Trap #0 --> PC-Kommunikation + dc.l ex_vec33 ; Trap #1 + dc.l ex_vec34 ; Trap #2 + dc.l ex_vec35 ; Trap #3 + dc.l ex_vec36 ; Trap #4 + dc.l ex_vec37 ; Trap #5 + dc.l ex_vec38 ; Trap #6 + dc.l ex_vec39 ; Trap #7 + dc.l ex_vec40 ; Trap #8 + dc.l ex_vec41 ; Trap #9 + dc.l ex_vec42 ; Trap #10 + dc.l ex_vec43 ; Trap #11 + dc.l ex_vec44 ; Trap #12 + dc.l S_LibFun ; Trap #13 --> Libraryverwaltung + dc.l S_StepTgl ; Trap #14 --> Trace an/aus + dc.l S_ProgEnd ; Trap #15 --> Programmende + dc.l ex_vec48 ; BSUN in FPU gesetzt + dc.l ex_vec49 ; FPU inexaktes Ergebnis + dc.l ex_vec50 ; FPU Division durch 0 + dc.l ex_vec51 ; FPU Unterlauf + dc.l ex_vec52 ; FPU Operandenfehler + dc.l ex_vec53 ; FPU Ueberlauf + dc.l ex_vec54 ; FPU signaling NAN + dc.l ex_vec55 ; reserviert + dc.l ex_vec56 ; MMU Konfigurationsfehler + dc.l ex_vec57 ; MMU Illegale Operation + dc.l ex_vec58 ; MMU Zugriffsfehler + ; Vektoren 59..255 frei + +;---------------------------------------------------------------------------- +; Installationssequenz: + + org $800 +start: + clr.w S_Latch.w ; Port nullen + + and.b #$fc,S_MemEnd+3.w ; Speichergroesse auf Lang- + ; wortadresse ausrichten + move.l S_MemEnd.w,a7 ; SSP setzen + + lea -256(a7),a0 ; SSP-Anfang in A0 + move.l a0,S_SSPEnd.w ; sichern + + lea S_End.w,a1 ; Codelaenge berechnen + lea S_Start.w,a2 + sub.l a2,a1 ; A1=Laenge Systemcode + moveq #4,d0 ; auf mehrfaches von 4 aus- + sub.w a1,d0 ; richten + and.l #3,d0 + add.l d0,a1 + + sub.l a1,a0 ; Start des Systemcodes rechnen + move.l a0,S_SysStart.w ; sichern + move.l a0,$4.w ; =Programmstart + + move.l a1,d0 ; Systemcode umkopieren + lsr.l #2,d0 ; =Zahl Langworttransfers + subq.w #1,d0 ; wg. DBRA +S_SysCopy: move.l (a2)+,(a0)+ + dbra d0,S_SysCopy + + sub.l a2,a0 ; Verschiebedifferenz rechnen + move.l a0,d1 + + lea 8.w,a1 ; alle Vektoren relozieren + moveq #45,d0 +S_RelVec: add.l d1,(a1)+ + dbra d0,S_RelVec + + move.l S_SysStart.w,a1 ; obere Speichergrenze in USP... + move a1,usp + move.l a1,S_FreeMemEnd.w ; und Variable + + move.l #-1,S_LibStart.w; Librarykette leer + + lea S_floatlib.w,a0 ; passende FloatLib installieren + btst #0,S_Latch+1.w ; 68881 vorhanden ? + bne.s S_NoCo81 + lea S_float81lib.w,a0 ; ja-->andere Library +S_NoCo81: moveq #LibCtrlInstall,d0 ; einschreiben + trap #TrapLibCtrl + + moveq #LibCtrlGetAdr,d0 ; Adresse holen + lea S_LibName.w,a0 + trap #TrapLibCtrl + move.l d0,S_LibAdr.w + + move.l 4*4.w,a4 ; Exceptionvektoren 4 und 11 retten + move.l 11*4.w,a5 + move.l sp,a6 ; SP retten + move.l #S_NoCPU,4*4.w ; neue Exceptionhandler einschreiben + move.l #S_NoMMU,11*4.w + moveq #is68008,d1 ; Prozessorcode loeschen + + cpu 68030 ; fuer zus. Befehle + + ori #1,ccr ; 68008 ausfiltern + moveq #is68000,d1 + + movec vbr,d0 ; geht erst ab 68010 + moveq #is68010,d1 + + extb d0 ; geht erst ab 68020 + moveq #is68020,d1 + + cpu 68000 ; nicht mehr gebraucht + fpu on ; dafuer dies + +S_NoCPU: btst #0,S_Latch+1.w ; FPU vorhanden ? + bne.s S_NoFPU ; nein--> + or.w #has68881,d1 ; ja : 68881 annehmen + fnop ; FPU idle machen, damit im folgenden + fsave -(sp) ; ein idle frame gespeichert wird + cmp.b #$18,1(sp) ; Framelaenge=$18 fuer 68881, $38 fuer 882 + beq.s S_NoFPU + add.w #(has68882-has68881),d1 ; 68882 eintragen + + fpu off ; FPU nicht mehr gebraucht + pmmu on ; dafuer die MMU + +S_NoFPU: move.l a4,4*4.w ; Exception 4 zuruecksetzen + pflusha ; dies versteht auch die 68030-MMU + add.w #hasMMU,d1 ; gefunden: Flag dazu + move.l #S_SmallMMU,11*4.w ; testen ob Schmalspur-MMU + psave -(sp) + bra.s S_NoMMU ; Ergebnis 68020/68851 + +S_SmallMMU: move.b #is68030,d1 ; 68030 eintragen (nicht MOVEQ!!) + add.w #(intMMU-hasMMU),d1 ; Code interne MMU + +S_NoMMU: move.l a5,11*4.w ; Line-F-Vektor zuruecksetzen + move.l a6,sp ; SP restaurieren + move.w d1,S_CPUNo.w ; Ergebnis einschreiben + + trap #TrapProgEnd + +S_LibName: dc.b "FLOAT",0 + +;---------------------------------------------------------------------------- +; Gleitkommalibrary, ohne 68881: + + supmode off + + include float.i68 + +;---------------------------------------------------------------------------- +; Gleitkommalibrary, mit 68881: + + supmode off + + include float81.i68 + +;---------------------------------------------------------------------------- +; Die Startsequenz: + + supmode on + +S_Start: clr.w S_Latch.w ; Ports loeschen + clr.l _fadd_cnt.w ; Zielvariablen loeschen + clr.l _fmul_cnt.w + clr.l _fdiv_cnt.w + clr.l _fsqrt_cnt.w + + move.l S_MemEnd.w,d0 ; SSP an Speicherende legen + move.l d0,$0.w ; Neben Resetvekor vermerken + move.l d0,a7 ; SSP setzen + move.l S_FreeMemEnd.w,a0 ; USP liegt am Speicherende + move a0,usp + + andi #$dfff,sr ; In Usermodus schalten + jmp Start.w ; zum Programmstart + +;---------------------------------------------------------------------------- +; Die Ausnahmebehandlungsprozeduren: + +ex_vec2: + move.w #2,S_ExVec.w + bra.l ex_handle +ex_vec3: + move.w #3,S_ExVec.w + bra.l ex_handle +ex_vec4: + move.w #4,S_ExVec.w + bra.l ex_handle +ex_vec5: + move.w #5,S_ExVec.w + bra.l ex_handle +ex_vec6: + move.w #6,S_ExVec.w + bra.l ex_handle +ex_vec7: + move.w #7,S_ExVec.w + bra.l ex_handle +ex_vec8: + move.w #8,S_ExVec.w + bra.l ex_handle +ex_vec10: + move.w #10,S_ExVec.w + bra.l ex_handle +ex_vec11: + move.w #0,S_Control+S_Response.w ; FPU resetten + move.w #11,S_ExVec.w + bra.l ex_handle +ex_vec12: + move.w #12,S_ExVec.w + bra.l ex_handle +ex_vec13: + move.w #13,S_ExVec.w + bra.l ex_handle +ex_vec14: + move.w #14,S_ExVec.w + bra.l ex_handle +ex_vec15: + move.w #15,S_ExVec.w + bra.l ex_handle +ex_vec16: + move.w #16,S_ExVec.w + bra.l ex_handle +ex_vec17: + move.w #17,S_ExVec.w + bra.l ex_handle +ex_vec18: + move.w #18,S_ExVec.w + bra.l ex_handle +ex_vec19: + move.w #19,S_ExVec.w + bra.l ex_handle +ex_vec20: + move.w #20,S_ExVec.w + bra.l ex_handle +ex_vec21: + move.w #21,S_ExVec.w + bra.l ex_handle +ex_vec22: + move.w #22,S_ExVec.w + bra.l ex_handle +ex_vec23: + move.w #23,S_ExVec.w + bra.l ex_handle +ex_vec24: + move.w #24,S_ExVec.w + bra.l ex_handle +ex_vec25: + move.w #25,S_ExVec.w + bra.l ex_handle +ex_vec26: + move.w #26,S_ExVec.w + bra.l ex_handle +ex_vec27: + move.w #27,S_ExVec.w + bra.l ex_handle +ex_vec28: + move.w #28,S_ExVec.w + bra.l ex_handle +ex_vec29: + move.w #29,S_ExVec.w + bra.l ex_handle +ex_vec30: + move.w #30,S_ExVec.w + bra.l ex_handle +ex_vec31: + move.w #31,S_ExVec.w + bra.l ex_handle +ex_vec33: + move.w #33,S_ExVec.w + bra.l ex_handle +ex_vec34: + move.w #34,S_ExVec.w + bra.l ex_handle +ex_vec35: + move.w #35,S_ExVec.w + bra.l ex_handle +ex_vec36: + move.w #36,S_ExVec.w + bra.l ex_handle +ex_vec37: + move.w #37,S_ExVec.w + bra.l ex_handle +ex_vec38: + move.w #38,S_ExVec.w + bra.l ex_handle +ex_vec39: + move.w #39,S_ExVec.w + bra.l ex_handle +ex_vec40: + move.w #40,S_ExVec.w + bra.l ex_handle +ex_vec41: + move.w #41,S_ExVec.w + bra.l ex_handle +ex_vec42: + move.w #42,S_ExVec.w + bra.l ex_handle +ex_vec43: + move.w #43,S_ExVec.w + bra.l ex_handle +ex_vec44: + move.w #44,S_ExVec.w + bra.l ex_handle +ex_vec48: + move.w #48,S_ExVec.w + bra.l ex_handle +ex_vec49: + move.w #49,S_ExVec.w + bra.l ex_handle +ex_vec50: + move.w #50,S_ExVec.w + bra.l ex_handle +ex_vec51: + move.w #51,S_ExVec.w + bra.l ex_handle +ex_vec52: + move.w #52,S_ExVec.w + bra.l ex_handle +ex_vec53: + move.w #53,S_ExVec.w + bra.l ex_handle +ex_vec54: + move.w #54,S_ExVec.w + bra.l ex_handle +ex_vec55: + move.w #55,S_ExVec.w + bra.l ex_handle +ex_vec56: + move.w #56,S_ExVec.w + bra.l ex_handle +ex_vec57: + move.w #57,S_ExVec.w + bra.l ex_handle +ex_vec58: + move.w #58,S_ExVec.w + +ex_handle: + movem.l d0-d7/a0-a7,S_RegSave.w ; Wert der Register abspeichern + move usp,a0 + move.l a0,S_RegSave+64.w + lea S_Latch.w,a0 + move.w S_ExVec.w,d0 ; Vektornr. holen + move.b d0,1(a0) ; Fehlernr. ausgeben +ex_infinite: + move.b d0,d1 ; Die LED n-mal blinken lassen ; Die LED n-mal blinken lassen +ex_blink: + bset #0,(a0) ; LED an + bsr.s ex_wait + bclr #0,(a0) ; LED aus + bsr.s ex_wait + subq.b #1,d1 + bne.s ex_blink + move.b #$05,d1 ; eine Pause einlegen +ex_pause: + bsr.s ex_wait + subq.b #1,d1 + bne.s ex_pause + bra.s ex_handle ; und alles von vorne + +ex_wait: + move.l d0,-(a7) ; Register retten + move.l #$50000,d0 ; ungefaehr 1/2 Sekunde +ex_wloop: ; Register herunterzaehlen + subq.l #1,d0 + bne.s ex_wloop + move.l (a7)+,d0 ; D0 wieder zurueck + rts + +;---------------------------------------------------------------------------- +; Einzelschrittverfolgung: + +StepProc: + clr.b S_Latch+1.w + movem.l d0-d7/a0-a7,S_RegSave.w ; Register retten + move usp,a0 + move.l a0,S_RegSave+64.w + move.l $4.w,S_ResVecSave.w ; Resetvektor sichern + lea S_Restart(pc),a0 ; am Punkt S_StepBack wacht + move.l a0,$4.w ; der PcPar wieder auf + move.b #9,S_Latch+1.w ; ParMon-Aufruf ausgeben + stop #$2000 ; hier geht es nur mit einem + ; Reset weiter + +;---------------------------------------------------------------------------- +; Routinen zur Kommunikation mit dem PC (Trap 0) + +PcSysCall: + clr.b S_Latch+1.w + movem.l d0-d7/a0-a7,S_RegSave.w ; Register retten + move usp,a0 + move.l a0,S_RegSave+64.w + move.l $4.w,S_ResVecSave.w ; Resetvektor sichern + lea S_Restart(pc),a0 ; am Punkt S_Restart wacht + move.l a0,$4.w ; der PcPar wieder auf + move.b #$40,S_Latch+1.w ; PC-Aufruf ausgeben + stop #$2000 ; hier geht es nur mit einem + +S_Restart: + clr.b S_Latch+1.w ; Systemanfrage loeschen + move.l S_ResVecSave.w,$4.w ; Resetvektor zurueck + move.l S_RegSave+64.w,a0 + move a0,usp + movem.l S_RegSave.w,d0-d7/a0-a7 ; Register zurueckholen + rte ; das war's + +;---------------------------------------------------------------------------- +; Libraryverwaltung : Trap #13 +; +; Struktur einer Library : +; +; Adresse 0: Laenge in Bytes (1 <= Laenge <= 256k) +; Adresse 4: Dummyzeiger =-1 (vom System verwendet) \ +; Adresse 8: Libraryname als ASCIIZ-String | kopierter Block +; Adresse n: Sprungtabelle | +; Adresse m: Librarycode, private Daten / +; +; der gesamte Librarycode muss lageunabhaengig geschrieben sein ! +; +; definierte Unterfunktionen: +; +; D0.L=0 : Library installieren +; D0.L=1 : Libraryzeiger holen +; +;---------------------------------------------------------------------------- + +; Subfunktion 0: Library von Adresse 0 installieren: +; Eingabe: A0=Startadresse der Library +; Ausgabe: keine + +S_LibFun: movem.l d1-d2/a1-a2,-(a7) ; Register sichern + tst.l d0 ; ist es Funktion 0 ? + bne.s S_LibFun1 ; nein-->bei Funktion 1 weitertesten + + move.l (a0),d0 ; Laenge Library holen + addq.l #3,d0 ; auf Doppelworte aufrunden + and.b #$fc,d0 + moveq #1,d1 + cmp.l #$40000,d0 ; Maximalgroesse ueberschritten ? + bge.l S_LibErr ; ja-->Ende mit Fehler Nr.1 + + move usp,a1 ; Userstack holen + move.l S_FreeMemEnd.w,d2 ; mom. belegte Stackmenge berechnen + sub.l a1,d2 + move.l a1,a2 ; neue Untergrenze in A2 rechnen + sub.l d0,a2 + moveq #2,d1 + cmp.l #$800,a2 ; unter abs. Untergrenze gesunken ? + ble.l S_LibErr ; ja-->Ende mit Fehler Nr.2 + + move a2,usp ; neuen Userstack einschreiben + lsr.l #1,d2 ; Stackgroesse in Worten + bra.s S_LibStckEnd ; damit Ende, falls kein Stack belegt + +S_LibStckCpy: move.w (a1)+,(a2)+ ; Userstack umkopieren +S_LibStckEnd: dbra d2,S_LibStckCpy + + move.l S_FreeMemEnd.w,a1 ; Startadresse der Library rechnen + sub.l d0,a1 ; =altes Speicherende-Laenge + addq.l #4,a0 ; Quellzeiger weitersetzen + move.l S_LibStart.w,d1 ; bisheriges Ende der Kette holen + move.l d1,(a0) ; in neue Library eintragen + move.l a1,S_FreeMemEnd.w ; Speichergrenze heruntersetzen + move.l a1,S_LibStart.w ; neuen Kettenanfang eintragen + + lsr.l #2,d0 ; Laenge in Doppelworte umrechnen + subq.w #1,d0 ; wg. DBRA + +S_LibInstLoop: move.l (a0)+,(a1)+ ; Library umkopieren + dbra d0,S_LibInstLoop + + bra.l S_LibOK ; Ende ohne Fehler + +; Subfunktion 1: Library finden, deren Name ab (A0) als ASCIIZ steht: +; Eingabe: A0=Startadresse des ASCIIZ-Strings +; Ausgabe: D0=Startadresse der Sprungtabelle + +S_LibFun1: subq.l #1,d0 ; ist es Funktion 1 ? + bne.s S_LibFun2 ; nein-->bei Funktion 2 weitertesten + + move.l S_LibStart.w,a2 ; Wurzelzeiger der Kette holen + +S_LibGetLoop: moveq #3,d1 ; Kettenende erreicht ? + move.l a2,d0 + addq.l #1,d0 ; wird durch -1 angezeigt + beq.l S_LibErr ; ja-->Ende mit Fehler + + move.l a0,d0 ; Startadresse Vergleichsstring retten + lea 4(a2),a1 ; A1 zeigt auf zu testenden Namen +S_LibGetComp: cmpm.b (a0)+,(a1)+ ; ein Zeichen vergleichen + bne.s S_LibGetNext ; ungleich-->weiter in Kette + tst.b -1(a0) ; War das das Ende ? + beq.s S_LibGetFnd ; ja-->Heureka! + bra.s S_LibGetComp ; ansonsten naechstes Zeichen vergleichen + +S_LibGetNext: move.l (a2),a2 ; weiter auf Nachfolger in Kette + move.l d0,a0 ; A0 auf Referenzstringanfang + bra.s S_LibGetLoop + +S_LibGetFnd: move.l a1,d0 ; Libraryadresse gerade machen + addq.l #1,d0 + bclr #0,d0 + + bra.l S_LibOK ; Ende ohne Fehler + +S_LibFun2: moveq #127,d1 ; unbekannte Funktion: + bra.l S_LibErr + +S_LibErr: move.l d1,d0 ; Fehlercode in D0 holen + movem.l (a7)+,d1-d2/a1-a2 ; Register zurueck + or.b #1,1(a7) ; Carry setzen + rte + +S_LibOK: movem.l (a7)+,d1-d2/a1-a2 ; Register zurueck + and.b #$fe,1(a7) ; Carry loeschen + rte + +;---------------------------------------------------------------------------- +; Tracemode ein/aus: + +S_StepTgl: + andi #$7fff,sr ; bitte hier kein Trace! + bclr #7,(a7) ; altes T-Flag loeschen + btst #0,1(a7) + bne.s S_StepOn ; C=1-->Tracemodus an + rte ; C=0-->fertig +S_StepOn: + bset #7,(a7) ; T-Flag setzen + rte + +;---------------------------------------------------------------------------- +; Programmende (Trap 15) + +S_ProgEnd: lea S_Start(pc),a0 ; Startvektor zurueck + move.l a0,4.w + move.b #$ff,S_Latch+1.w ; "Ich bin fertig" + stop #$2000 ; und Ende + +;---------------------------------------------------------------------------- +; Line-F-Exception + +S_Response equ $fffffe00 ; In a6 (Coprozessor-Register) +S_Control equ $02 ; Alle weiteren Register relativ +S_Save equ $04 ; zu "Response" +S_Restore equ $06 +S_Command equ $0a ; in a5 +S_Condition equ $0e +S_Operand equ $10 ; in a4 +S_Reg_Selec equ $14 +S_Ins_Add equ $18 + + supmode on + +S_LineF: btst #0,S_Latch+1.w ; Ist ein Koprozessor vorhanden ? + bne ex_vec11 ; nein-->normaler Line-F + + movem.l d0-d7/a0-a6,S_RegSave.w ; Register retten + move.l usp,a0 ; USP retten + move.l a0,S_RegSave+60.w ; (geht nur ueber Umweg) + lea S_Response.w,a6 ; #response nach A6 + lea S_Command(a6),a5 ; #command nach A5 + lea S_Operand(a6),a6 ; #operand nach A4 + lea S_RegSave.w,a3 ; #dregs nach A3 + move.l 2(a7),a0 ; PC nach A0 + move.w (a0),d1 ; Kommando nach D1 +S_again: ; Einsprung fuer weitere FPU-Befehle + and.w #%0000000111000000,d1 ; Spezialteil ausmaskieren + bne S_spezial ; Ein Bit gesetzt-->Spezialbefehl + move.w 2(a0),d1 ; zweiten Befehlsteil in D1 merken + move.w d1,(a5) ; Befehl in FPU schr. (A5==#command) +S_do_ca: ; Einsprung fuer weitere Nachfragen an FPU + move.w (a6),d0 ; Response lesen + btst #12,d0 ; Erstes Modusbit testen + bne S_rw_1x ; ==1 --> springen + btst #11,d0 ; Zweites Modusbit testen + beq.s S_rw_00 ; ==0 --> springen +; ----- %xxx01, Null-Primitive/Transfer Single CPU Register + btst #10,d0 ; Register uebertragen ? + bne.s S_rw_sngl ; Ja--> Transfer Single CPU-Register + btst #15,d0 ; CA (Come Again) gesetzt ? + bne.s S_do_ca ; Ja--> weiter fragen, sonst fertig + addq.l #4,a0 ; A0 um reine Befehlslaenge weiter + ; ( alles andere wurde in calc_add erledigt ) + move.w (a0),d1 ; erstes Befehlswort holen + move.w d1,d0 ; und nach D0 + and.w #$f000,d0 ; Wieder COP-Befehl ? + eor.w #$f000,d0 + beq.s S_again ; Ja-->direkt weitermachen + move.l a0,2(a7) ; Neuen PC eintragen + move.l S_RegSave+60.w,a0 ; USP wiederherstellen + move.l a0,usp ; (geht nur ueber Umweg) + movem.l (a3),d0-a6 ; Register wiederherstellen + rte ; Trap beenden +S_rw_sngl: + and.w #%1110000,d1 ; Registernummer ausmaskieren ( nur Dn ) + lsr.w #2,d1 ; D1=Nummer*4 + move.l 0(a3,d1.w),(a4) ; Register uebertragen (a4==#operand, a3==#dregs) + bra.s S_do_ca ; danach kommt immer noch etwas +;-----%xxx00, Transfer multiple coprocessor Reg. +S_rw_00: + bsr S_calc_add ; Operandenadresse nach A1 holen + move.w S_Reg_Selec(a6),d4 ; Registerliste nach D4 holen + btst #13,d0 ; Dr-Bit testen + beq.s S_w_00 ; ==0--> Daten in FPU schreiben + btst #12,d0 ; Predekrementmodus ? + beq.s S_r_pred ; ==0--> Ja,springen + moveq #7,d0 ; Schleifenzaehler fuer 8 Bits +S_11: + lsl.w #1,d4 ; Ein Bit ins Carry + bcc.s S_21 ; nur bei Bit==1 etwas machen + move.l (a4),(a1)+ ; 1 (A4==#operand) + move.l (a4),(a1)+ ; 2 + move.l (a4),(a1)+ ; 3 Langworte fuer jedes Register +S_21: + dbra d0,S_11 ; Fuer alle 8 Bits + bra.s S_do_ca ; Nochmal FPU befragen +S_r_Pred: + moveq #7,d0 ; Schleifenzaehler fuer 8 Bits +S_12: + lsl.w #1,d4 ; Ein Bit ins Carry + bcc.s S_22 ; nur bei Bit=1 etwas machen + move.l (a4),(a1)+ ; 1 (A4==#operand) + move.l (a4),(a1)+ ; 2 + move.l (a4),(a1)+ ; 3 Langworte fuer jedes Register + suba.w #24,a1 ; Dekrement durchfuehren +S_22: + dbra d0,S_12 ; Fuer alle 8 Bits + adda.w #12,a1 ; A1 wieder auf letztes Register + move.l a1,(a2) ; A1 als Registerinhalt abspeichern + bra S_do_ca ; Nochmal FPU befragen +S_w_00: + move.w (a0),d0 ; erstes Befehlswort holen + and.b #%111000,d0 ; Adressierungsart maskieren + cmp.b #%011000,d0 ; Gleich (An)+ ? + beq.s S_w_Post ; Ja-->Postinkrementiermodus + moveq #7,d0 ; Schleifenzaehler fuer 8 Bits +S_13: + lsl.w #1,d4 ; Ein Bit ins Carry + bcc.s S_23 ; Nur bei Bit==1 etwas machen + move.l (a1)+,(a4) ; 1 (A4==#operand) + move.l (a1)+,(a4) ; 2 + move.l (a1)+,(a4) ; 3 Langworte fuer jedes Register +S_23: + dbra d0,S_13 ; Fuer alle 8 Bits + bra S_do_ca ; Nochmal FPU befragen +S_w_Post: + suba.w #12,a1 ; Inkrement von calc_add aufheben + moveq #7,d0 ; Schleifenzaehler fuer 8 Bits +S_14: + lsl.w #1,d4 ; Ein Bit ins Carry + bcc.s S_24 ; nur bei Bit==1 etwas machen + move.l (a1)+,(a4) ; 1 (A4==#operand) + move.l (a1)+,(a4) ; 2 + move.l (a1)+,(a4) ; 3 Langworte fuer jedes Register +S_24: + dbra d0,S_14 ; Fuer alle 8 Bits + move.l a1,(a2) ; A1 als Registerinhalt abspeichern + bra S_do_ca ; Nochmal FPU befragen + +S_rw_1x: + btst #11,d0 ; zweites Modusbit testen + bne.s S_rw_11 ; ==1 --> springen (Trap,Error) + btst #13,d0 ; DR-Bit testen + beq.s S_w_10 ; ==0 --> Daten an FPU schreiben +;----- %xx110, evaluate effective adress and transfer data + bsr S_calc_add ; Operandenadresse berechnen + ; A1=Operandenadresse, d1.l=Operandenl„nge + cmp.w #2,d1 ; Laenge-2 + ble.s S_r_bw ; <=2 --> Wort-oder-Byteoperand +S_r_11: + move.l (a4),(a1)+ ; ein Langwort lesen (A4==#operand) + subq.l #4,d1 ; und runterzaehlen + bgt.s S_r_11 ; >0 --> weiter uebertragen + bra S_do_ca ; Nochmal FPU befragen +S_r_bw: + btst #0,d1 ; Byte ? + bne.s S_r_byte ; Ja! + move.w (a4),(a1) ; Wort-Operand lesen (A4==#operand) + bra S_do_ca ; Nochmal FPU befragen +S_r_byte: + move.b (a4),(a1) ; Byte-Operand lesen (A4==#operand) + bra.l S_do_ca ; Nochmal FPU befragen + +;----- %xx101, evaluate effective adress and transfer data +S_w_10: + bsr S_calc_add ; Operandenadresse berechnen + ; A1=Operandenadresse, d1.l=Operandenl„nge + cmp.w #2,d1 ; Laenge-2 + ble.s S_w_bw ; <=2 --> Wort-oder-Byteoperand +S_w_11: + move.l (a1)+,(a4) ; ein Langwort lesen (A4==#operand) + subq.l #4,d1 ; und runterzaehlen + bgt.s S_w_11 ; >0 --> weiter uebertragen + bra S_do_ca ; Nochmal FPU befragen +S_w_bw: + btst #0,d1 ; Byte ? + bne.s S_w_byte ; Ja! + move.w (a1),(a4) ; Wort-Operand lesen (A4==#operand) + bra S_do_ca ; Nochmal FPU befragen +S_w_byte: + move.b (a1),(a4) ; Byte-Operand lesen (A4==#operand) + bra.l S_do_ca ; Nochmal FPU befragen + +;----- %xxx11, take pre-instruction exception +S_rw_11: + bra ex_vec11 ; Error-Handler anspringen +; ( hier koennte man eine genauere Fehleranalyse machen ) + +S_spezial: ; Sprungbefehle etc. + cmp.w #%001000000,d1 ; FScc,FDBcc oder FTRAPcc + beq.s S_s_trap + cmp.w #%010000000,d1 ; Branch mit 16-Bit-Offset + beq.l S_s_br16 + cmp.w #%011000000,d1 ; Branch mit 32-Bit-Offset + beq.l S_s_br32 + bra ex_vec11 ; FSAVE/FRESTORE nicht unterstuetzt +S_s_trap: + move.w (a0),d0 ; Erstes Befehlswort nach D0 + move.w d0,d1 ; und nach D1 retten + and.w #%111000,d0 ; Wichtige Bits ausmaskieren + cmp.w #%001000,d0 ; FDBcc ? + beq.s S_s_fdbcc ; Ja-->springen + cmp.w #%111000,d0 ; FTRAP ? + beq ex_vec11 ; Ja-->Fehler (nicht unterstuetzt) + ; sonst FScc + move.w 2(a0),S_condition(a6) ; Bedingung an FPU schicken + moveq #1,d0 ; Operandenlaenge=1 (fuer calc_add) + bsr S_calc_add ; Operandenadresse berechnen +S_15: + move.w (a6),d0 ; Response lesen + btst #8,d0 ; IA-Bit testen + beq.s S_25 ; ==0 --> fertig + and.w #%1100000000000,d0 ; Bits 11 und 12 ausmaskieren + eor.w #%1100000000000,d0 ; Beide gesetzt ? + bne.s S_15 ; Nicht beide==1 --> warten + bra ex_vec11 ; Sonst ist Exception aufgetreten +S_25: + btst #0,d0 ; Antwortbit testen + sne (a1) ; Je nach Bit setzen/loeschen + bra S_do_ca ; Nochmal FPU befragen +S_s_fdbcc: + move.w 2(a0),S_condition(a6) ; Bedingung an FPU schicken + and.w #%111,d1 ; Registernummer maskieren (D1=(A0)) + lsl.w #2,d1 ; D1=Nummer*4 + lea 0(a3,d1.w),a1 ; A1 enthaelt Adresse des Datenreg. + move.l (a1),d1 ; Dn holen + subq.w #1,d1 ; Dn=Dn-1 + move.l d1,(a1) ; Dn zurueckschreiben + move.l a0,a2 ; alten PC nach A2 holen + addq.l #2,a0 ; PC 2 weiter ( fuer "nicht springen") +S_16: + move.w (a6),d0 ; Response lesen + btst #8,d0 ; IA-Bit testen + beq.s S_26 ; ==0 --> fertig + and.w #%1100000000000,d0 ; Bits 11 und 12 ausmaskieren + eor.w #%1100000000000,d0 ; Beide gesetzt ? + bne.s S_16 ; Nicht beide==1 --> warten + bra ex_vec11 ; Sonst ist Exception aufgetreten +S_26: + btst #0,d0 ; Antwortbit testen + bne S_do_ca ; True-->das war's schon + adda.w 2(a2),a2 ; 16-Bit-Sprungdist. add. (A2=PC) + addq.w #1,d1 ; Dn=-1 ? + beq S_do_ca ; Ja-->kein Sprung (Schleifenende) + move.l a2,a0 ; Sonst "Sprung" (neuen PC laden) + bra S_do_ca ; nochmal FPU befragen +S_s_br16: + move.w (a0),S_Condition(a6) ; Bedingung an FPU schicken +S_17: + move.w (a6),d0 ; Response lesen + btst #8,d0 ; IA-Bit testen + beq.s S_27 ; ==0 --> fertig + and.w #%1100000000000,d0 ; Bits 11 und 12 ausmaskieren + eor.w #%1100000000000,d0 ; Beide gesetzt ? + bne.s S_17 ; Nicht beide==1 --> warten + bra ex_vec11 ; Sonst ist Exception aufgetreten +S_27: + btst #0,d0 ; Antwortbit testen + beq S_do_ca ; False--> das war's schon + adda.w 2(a0),a0 ; 16-Bit-Sprungdistanz addieren + subq.l #2,a0 ; Ein Wort zurueck ( weil spaeter + ; noch 4 addiert wird und und nur 2 addiert werden muesste ) + bra S_do_ca ; Nochmal FPU befragen +S_s_br32: + move.w (a0),S_Condition(a6) ; Bedingung an FPU schicken +S_18: + move.w (a6),d0 ; Response lesen + btst #8,d0 ; IA-Bit testen + beq.s S_28 ; ==0 --> fertig + and.w #%1100000000000,d0 ; Bits 11 und 12 ausmaskieren + eor.w #%1100000000000,d0 ; Beide gesetzt ? + bne.s S_18 ; Nicht beide==1 --> warten + bra ex_vec11 ; Sonst ist Exception aufgetreten +S_28: + addq.l #2,a0 ; Befehl ist 3 Worte lang + ; (jetzt : (A0)=Distanz) + btst #0,d0 ; Antwortbit testen + beq S_do_ca ; False--> das war's schon + adda.l (a0),a0 ; 32-Bit-Sprungdistanz addieren + subq.l #4,a0 ; Zwei Worte zurueck ( weil spaeter + ; noch 4 addiert wird, 2 wurden schon addiert ) + bra S_do_ca ; Nochmal FPU befragen +S_calc_add: + ; Operandenadresse berechnen. A0 muss die Adresse des Line-F- + ; Befehls enthalten, D0 im unteren Byte die Operandenlaenge. + ; die zu berechnende Adresse wird in A1 abgelegt. A0 wird + ; um die Laenge der zusaetzlichen Daten erhaelt. + ; Zusaetzlich wird in D1 die Laenge des Operanden zurueckge- + ; geben (in Bytes, als Langwort). D2,D3,A3 werden zerstoert. + ; Bei den Adressierungsarten -(An),(An)+ steht in A2 ein + ; Zeiger auf die Stelle, in der der Inhalt des Adressregisters + ; gisters An steht (wird fuer FMOVEM gebraucht). + + clr.l d1 ; Laenge als Langwort loeschen + move.b d0,d1 ; und Byte umkopieren + move.w (a0),d2 ; erstes Befehlswort nach D2 + move.w d2,d3 ; und D3 retten + and.w #%111000,d3 ; Adressierungsart ausmaskieren + lsr.w #1,d3 ; D3=Adressierungsart*4 (Langworte) + lea S_cs_tab(pc),a1 ; Sprungtabellenadresse nach A1 + move.l 0(a1,d3.w),a1 ; Adresse der Routine nach A1 + jmp (a1) ; und Routine anspringen +S_c_drd: ; %000 Data Register Direct: Dn +S_c_ard: ; %001 Address Register Direct: An + lea (a3),a1 ; A1 auf Registerfeld + and.w #%1111,d2 ; Registernummer ausmaskieren +; ( und ein Bit vom Modus, 0 fuer Daten-,1 fuer Adressregister ) + lsl.w #2,d2 ; D2="Registernummer"*4 (+Modusbit) + addq.w #4,d2 ; +4 (fuer Operandenlaenge) + sub.w d1,d2 ; Wahre Laenge abziehen + adda.w d2,a1 ; Offset auf Registerfeldanfang add. + rts +S_c_ari: ; %010 Address Register indirect: (An) + and.w #%111,d2 ; Registernummer ausmaskieren + lsl.w #2,d2 ; D2=Registernummer*4 + move.l 32(a3,d2.w),a1 ; Adresse nach A1 + rts +S_c_arpo: ; %011 Adressregister indirect with Postincrement: (An)+ + and.w #%111,d2 ; Registernummer ausmaskieren + lsl.w #2,d2 ; D2=Registernummer*4 + lea 32(a3,d2.w),a2 ; Adresse Adressregister nach A2 + move.l (a2),a1 ; Adresse (Inhalt A.-Reg.) nach A1 + btst #0,d1 ; D1 ungerade ? (Byteoperand) + bne.s S_29 ; Ja-->Spezialbehandlung +S_19: + add.l d1,(a2) ; Inkrement durchfuehren + rts +S_29: + cmp.w #4*7,d2 ; Ist A7 gemeint ? + bne.s S_19 ; nein-->normal vorgehen + addq.l #2,(a2) ; Sonst (bei Byte) 2 addieren, + rts ; damit Stack gerade bleibt! +S_c_arpr: ; %100 Adressregister Indirect with Predekrement: -(An) + and.w #%111,d2 ; Registernummer ausmaskieren + lsl.w #2,d2 ; D2=Registernummer*4 + lea 32(a3,d2.w),a2 ; Adresse des Adressreg. nach A2 + btst #0,d1 ; D1 ungerade? (Byteoperand) + bne.s S_210 ; Ja-->Spezialbehandlung +S_110: + sub.l d1,(a2) ; Dekrement durchfuehren + move.l (a2),a1 ; Adresse (Inhalt des A.-Reg) nach A1 + rts +S_210: + cmp.w #4*7,d2 ; Ist A7 gemeint? + bne.s S_110 ; nein-->normal vorgehen + subq.l #2,(a2) ; Sonst (bei Byte) 2 addieren, + ; damit Stack gerade bleibt ! + move.l (a2),a1 ; Adresse (Inhalt des A.-Reg) nach A1 + rts +S_c_ar16: ; %101 Addressregister Indirect with Displacement: d16(An) + and.w #%111,d2 ; Registernummer ausmaskieren + lsl.w #2,d2 ; D2=Registernummer*4 + move.l 32(a3,d2.w),a1 ; Adresse nach A1 + move.w 4(a0),d2 ; 3.Befehlswort nach D2 (Offset) + adda.w d2,a1 ; Offset auf Adresse addieren + addq.l #2,a0 ; A0 ein Wort (d16) weiter + rts +S_c_ar08: ; %110 Addressregister Indirect with Index : d8(An,Xn) + and.w #%111,d2 ; Registernummer ausmaskieren + lsl.w #2,d2 ; D2=Registernummer*4 + move.l 32(a3,d2.w),a1 ; Adresse nach A1 + move.w 4(a0),d2 ; 3.Befehlswort nach D2 (Byte-Offset) + move.w d2,d3 ; und nach D3 + and.w #$ff,d3 ; Byte ausmaskieren (Byte-Offset) + adda.w d3,a1 ; Offset auf Adresse addieren + btst #11,d2 ; 1=long; 0=word + bne.s S_c_ar81 + and.w #%1111000000000000,d2 ; Nummer von Dn und Modusbit + lsr.w #5,d2 ; maskieren + lsr.w #5,d2 ; D2=Registernummer*4 (und modusbit) + adda.w 2(a3,d2.w),a1 ; 16-Bit-Index auf A1 addieren + addq.l #2,a0 ; A0 ein Wort (Kram & d8) weiter + rts +S_c_ar81: + and.w #%1111000000000000,d2 ; Nummer von Dn und Modusbit + lsr.w #5,d2 ; maskieren + lsr.w #5,d2 ; D2=Registernummer*4 (und modusbit) + adda.w 0(a3,d2.w),a1 ; 32-Bit-Index auf A1 addieren + addq.l #2,a0 ; A0 ein Wort (Kram & d8) weiter + rts +S_c_pc: ; %111 absolut short/long, PC-relativ (ohne/mit Index) \ oder direkt + btst #2,d2 ; Immidiate ? + bne.s S_immi ; <>0 --> Ja! + btst #1,d2 ; PC-relativ ? + bne.s S_pc_rel ; <>0 --> Ja! + btst #0,d2 ; Long ? + bne.s S_c_long ; <>0 --> Ja! + ; sonst short + move.w 4(a0),d2 ; Wortadresse holen + ext.l d2 ; Auf Langwort erweitern + move.l d2,a1 ; und als Operandenadresse merken + addq.l #2,a0 ; A0 ein Wort (Short-A.) weiter + rts +S_c_long: + move.l 4(a0),a1 ; Langwortadresse holen + addq.l #4,a0 ; A0 zwei Worte (Long-A.) weiter + rts +S_immi: + move.l a0,a1 ; Befehlsadresse nach A1 + add.l d1,a0 ; A0 ueber Operand hinwegsetzen + rts +S_pc_rel: + btst #0,d2 ; mit Index ? + bne.s S_pc_idx ; <>0 --> Ja! + move.l a0,a1 ; PC nach A1 + adda.w 4(a0),a1 ; Offset addieren + addq.l #4,a1 ; +4 fuer Laenge des FPU-Befehls + addq.l #2,a0 ; A0 zwei (16-Bit-Offset) weiter + rts +S_pc_idx: + move.l a0,a1 ; PC nach A1 + clr.w d2 ; Oberes Byte loeschen + move.b 5(a0),d2 ; Offset nach D2 + adda.w d2,a1 ; und addieren + addq.l #4,a1 ; +4 fuer Laenge des FPU-Befehls + move.b 4(a0),d2 ; D2=Registernummer*16 und Modusbit + ; ( high-Byte ist noch 0 ) + btst #3,d2 ; Long-Bit testen + bne.s S_pc_i_l ; <>0 -->Long-Index + and.b #%11110000,d2 ; Registerinformation ausblenden + lsr.w #2,d2 ; D2=Registernummer*4 (und Modusbit) + adda.w 2(a3,d2.w),a1 ; Word-Index addieren + addq.l #2,a0 ; A0 zwei (8-Bit-Offset & Kram) weiter + rts +S_pc_i_l: + and.b #%11110000,d2 ; Restinformation ausblenden + lsr.w #2,d2 ; D2=Registernummer*4 (und Modusbit) + adda.l 0(a3,d2.w),a1 ; Long-Index addieren + addq.l #2,a0 ; A0 zwei (8-Bit-Offset & Kram) weiter + rts ; Ende von S_calc_add + +S_cs_tab: + dc.l S_c_drd,S_c_ard,S_c_ari,S_c_arpo ; Sprungtabelle fuer + dc.l S_c_arpr,S_c_ar16,S_c_ar08,S_c_pc ; Adressierungsarten +S_End: + -- cgit v1.2.3