; MINITOS.S - miniTOS-Emulator fr EPAC68008 ; Daten im RAM organisieren ; Vektoren: $0-$3FF, Supervisor Stack: $400-$7FF ; Chip-I/O (Buffer): $800-$BFF, miniTOS: $C00-$FFF ; User: $1000-$FFFF SSTACK EQU $800 ; Anfang, dekrementiert zu $7FF-$400 GMALLOCTABLE EQU $C00 ; 32 Eintr„ge zu je 8 Bytes USERRAMBEGIN EQU $1000 ; Anfang des UserRAMs USERRAMEND EQU $10000 ; Ende des UserRAMs (+1) ; Startup-Code SUPER ; Supervisor Befehlssatz zul„ssig DC.L SSTACK ; Supervisorstack setzen DC.L SINIT ; Programm-Anfangsadresse SINIT: ; Modul 'Startup' ORI #$700,SR ; Interupts ausschalten RESET ; Port-Chips reseten LEA 8,A0 ; erster Exeptionvektor im RAM MOVE.L #254,D0 ; 2 Vektoren sind schon gesetzt BRA SINITWHILE SINITNEXT: MOVE.L #SINTR,(A0)+ ; Vektor setzen SINITWHILE: DBRA D0,SINITNEXT BRA BINIT SINTR: RTE ; Dummy-Interrupthandler, tut nichts ; BIOS, TRAP #13 BINIT: ; Modul 'BIOS' initialisieren MOVE.L #BINTR,$B4 ; Trap #13 setzen JSR BCHIPINIT ; Port-Chips initialisieren BRA XINIT BCHIPINIT: ; hierhin kommen die Routinen von Louis ; Initialisieren und Interruptservice ORG $1D4 BCONINS: ; Zeichen in Buffer A? ORG $1F4 BCONIN: ; Zeichen aus Buffer A holen ORG $232 BCONOUTS: ; Sender A bereit? ORG $258 BCONOUT: ; Zeichen mit A senden ORG $260 BAUXINS: ; Zeichen in Buffer B? ORG $280 BAUXIN: ; Zeichen aus Buffer B holen ORG $2BE BAUXOUTS: ; Sender B bereit? ORG $2E4 BAUXOUT: ; Zeichen mit B senden ORG $2EC BPRTINS: RTS BPRTIN: RTS BPRTOUTS: RTS BPRTOUT: RTS BINTR: MOVEM.L D0-D1/A0-A1,-(A7) MOVE.W 16(A7),D0 ; gesicherter SR AND.W #$2000,D0 ; Supervisor-Bit BNE BSUPER ; gesetzt MOVE USP,A0 ; A0 zeigt auf Parameter BRA BNOTSUPER BSUPER: LEA 22(A7),A0 ; A0 zeigt auf Parameter BNOTSUPER: MOVE.W (A0)+,D0 ; Funktion holen CMPI.W #12,D0 BCC BINTREND ; Funktion 12 oder gr”sser -> nicht definiert LSL.W #2,D0 ; mal 4 LEA BFUNCTABLE,A1 MOVEA.L (A1,D0.W),A1 ; Anfangsadresse der Routine JMP (A1) BINTREND0: MOVEQ #0,D0 ; Ergebnis = 0 BINTRENDD0: MOVE.L D0,(A7) ; Ergebnis in D0 BINTREND: MOVEM.L (A7)+,D0-D1/A0-A1 RTE BFUNCTABLE: ; Funktionen 0-11 DC.L BNOTEMU,B01,B02,B03,BNOTEMU DC.L B05,B06,BNOTEMU,B08,BNOTEMU DC.L B10,B11 BNOTEMU: ; nicht emulierte Funktion aufgerufen LEA 28(A7),A7 ; gepushte Register berspringen LSR.W #2,D0 ; durch 4 MOVE.W D0,-(A7) ; Funktionsnummer MOVE.W #0,-(A7) ; Fehler in BIOS aufgetreten TRAP #15 ; 'Nicht emulierte Funktion'-Meldung, Abbruch ; ->kehrt nicht mehr zurck B01: MOVE.W (A0),D0 ; Bconstat, Ger„t holen CMPI.W #3,D0 BCC BINTREND0 ; Ger„t 3 oder gr”sser -> kein Zeichen bereit LSL.W #2,D0 ; mal 4 LEA BCONSTABLE,A1 MOVEA.L (A1,D0.W),A1 JSR (A1) ; Status testen BRA BINTRENDD0 BCONSTABLE: DC.L BPRTINS,BAUXINS,BCONINS B02: MOVE.W (A0),D1 ; Bconin, Ger„t holen CMPI.W #3,D1 BCC BINTREND0 ; Ger„t 3 oder gr”sser -> Null-Zeichen LSL.W #2,D1 ; mal 4 LEA BCONSTABLE,A1 MOVEA.L (A1,D1.W),A1 BCONINREPEAT: JSR (A1) ; bereit? TST.W D0 BEQ BCONINREPEAT ; noch nicht, warten LEA BCONINTABLE,A1 MOVEA.L (A1,D1.W),A1 JSR (A1) ; Zeichen holen oder ausgeben BRA BINTRENDD0 BCONINTABLE: DC.L BPRTIN,BAUXIN,BCONIN B03: MOVE.W (A0)+,D1 ; Bconout, Ger„t holen CMPI.W #3,D1 BCC BINTREND ; Ger„t 3 oder gr”sser -> nichts tun LSL.W #2,D1 ; mal 4 LEA BCOSTABLE,A1 MOVEA.L (A1,D1.W),A1 BCONOUTREPEAT: JSR (A1) ; bereit? TST.W D0 BEQ BCONOUTREPEAT ; noch nicht, warten LEA BCONOUTTABLE,A1 MOVEA.L (A1,D1.W),A1 MOVE.W (A0),D0 JSR (A1) ; Zeichen holen oder ausgeben CMPI #0,D1 ; Drucker? BEQ BCONOUTPRT BRA BINTREND BCONOUTPRT: MOVEQ #-1,D0 ; ja, OK zurckgeben BRA BINTRENDD0 BCONOUTTABLE: DC.L BPRTOUT,BAUXOUT,BCONOUT B05: MOVE.W (A0)+,D0 ; Setexc, Vektornummer LSL.W #2,D0 LEA 0,A1 MOVE.L (A0),D1 ; -1 oder Vektorinhalt BMI BSETEXCGET MOVE.L D1,(A1,D0.W) ; falls erwnscht setzen BSETEXCGET: MOVE.L (A1,D0.W),D0 ; lesen BRA BINTRENDD0 B06: MOVEQ #5,D0 ; Tickcal, 200Hz BRA BINTRENDD0 B08: MOVE.W (A0),D0 ; Bcostat, Ger„t holen CMPI.W #3,D0 BCC BINTREND0 ; Ger„t 3 oder gr”sser -> wartet nicht LSL.W #2,D0 ; mal 4 LEA BCOSTABLE,A1 MOVEA.L (A1,D0.W),A1 JSR (A1) ; Status testen BRA BINTRENDD0 BCOSTABLE: DC.L BPRTOUTS,BAUXOUTS,BCONOUTS B10: BRA BINTREND0 ; Drvmap, keine Laufwerke B11: BRA BINTREND0 ; Kbshift, keine Tasten geschiftet ; XBIOS, TRAP #14 XINIT: ; Modul 'XBIOS' initialisieren MOVE.L #XINTR,$B8 ; TRAP #14 setzen BRA GINIT XINTR: MOVEM.L D0-D1/A0-A1,-(A7) MOVE.W 16(A7),D0 ; gesicherter SR AND.W #$2000,D0 ; Supervisor-Bit BNE XSUPER ; gesetzt MOVE USP,A0 ; A0 zeigt auf Parameter BRA XNOTSUPER XSUPER: LEA 22(A7),A0 ; A0 zeigt auf Parameter XNOTSUPER: MOVE.W (A0)+,D0 ; Funktion holen CMPI.W #65,D0 BCC XINTREND ; Funktion 65 oder gr”sser -> nicht definiert LSL.W #2,D0 ; mal 4 LEA XFUNCTABLE,A1 MOVEA.L (A1,D0.W),A1 ; Anfangsadresse der Routine JMP (A1) XINTREND0: MOVEQ #0,D0 ; Ergebnis = 0 XINTRENDD0: MOVE.L D0,(A7) ; Ergebnis in D0 XINTREND: MOVEM.L (A7)+,D0-D1/A0-A1 RTE XFUNCTABLE: ; Funktionen 0-64 DC.L XNOTEMU,XNOTEMU,XNOTEMU,XNOTEMU,XNOTEMU DC.L XNOTEMU,XNOTEMU,XNOTEMU,XNOTEMU,XNOTEMU DC.L XNOTEMU,XNOTEMU,XNOTEMU,XNOTEMU,XNOTEMU DC.L XNOTEMU,XNOTEMU,XNOTEMU,XNOTEMU,XNOTEMU DC.L XNOTEMU,X21,XNOTEMU,XNOTEMU,XNOTEMU DC.L XNOTEMU,XNOTEMU,XNOTEMU,XNOTEMU,XNOTEMU DC.L XNOTEMU,XNOTEMU,XNOTEMU,XNOTEMU,XNOTEMU DC.L XNOTEMU,XNOTEMU,XNOTEMU,X38,XNOTEMU DC.L XINTREND,XINTREND,XINTREND,XINTREND,XINTREND DC.L XINTREND,XINTREND,XINTREND,XINTREND,XINTREND DC.L XINTREND,XINTREND,XINTREND,XINTREND,XINTREND DC.L XINTREND,XINTREND,XINTREND,XINTREND,XINTREND DC.L XINTREND,XINTREND,XINTREND,XINTREND,XNOTEMU XNOTEMU: ; nicht emulierte Funktion aufgerufen LEA 12(A7),A7 ; gepushte Register berspringen LSR.W #2,D0 ; durch 4 MOVE.W D0,-(A7) ; Funktionsnummer MOVE.W #1,-(A7) ; Fehler in XBIOS aufgetreten TRAP #15 ; 'Nicht emulierte Funktion'-Meldung, Abbruch ; ->kehrt nicht mehr zurck X21: MOVE.W (A0),D0 ; Cursorconf: Was mit Cursor machen CMPI.W #2,D0 BCC XINTREND ; Funktion 2 und gr”sser -> nichs machen MOVE.W #$1B,-(A7) ; auf Stack MOVE.W #2,-(A7) ; CON MOVE.W #3,-(A7) ; Bconout TRAP #13 ; BIOS ADDQ.L #6,A7 MOVE.W #$66,D1 ; SUB.W D0,D1 ; f fr Funktion 0, e fr 1 MOVE.W D1,-(A7) ; auf Stack MOVE.W #2,-(A7) ; CON MOVE.W #3,-(A7) ; Bconout TRAP #13 ADDQ.L #6,A7 BRA XINTREND X38: MOVEA.L (A0),A0 ; Unterprogramm in Supervisormodus ausfhren JSR (A0) BRA XINTREND ; GEMDOS, TRAP #1 GINIT: ; Modul 'GEMDOS' initialisieren MOVE.L #GINTR,$84 ; TRAP #1 setzen MOVE.L #0,GMALLOCTABLE ; Speicher nicht belegt BRA NINIT GINTR: MOVEM.L D0-D3/A0-A2,-(A7) MOVE.W 28(A7),D0 ; gesicherter SR AND.W #$2000,D0 ; Supervisor-Bit BNE GSUPER ; gesetzt MOVE USP,A0 ; A0 zeigt auf Parameter BRA GNOTSUPER GSUPER: LEA 34(A7),A0 ; A0 zeigt auf Parameter GNOTSUPER: MOVE.W (A0)+,D0 ; Funktion holen CMPI.W #88,D0 BCC GNOTDEF ; Funktion 88 oder gr”sser -> nicht definiert LSL.W #2,D0 ; mal 4 LEA GFUNCTABLE,A1 MOVEA.L (A1,D0.W),A1 ; Anfangsadresse der Routine JMP (A1) GNOTDEF: ; nicht definierte Funktion MOVE.W #-32,D0 BRA GINTRENDD0 GINTREND0: MOVEQ #0,D0 ; Ergebnis = 0 GINTRENDD0: MOVE.L D0,(A7) ; Ergebnis in D0 GINTREND: MOVEM.L (A7)+,D0-D3/A0-A2 RTE GFUNCTABLE: ; Funktionen 0-87 DC.L G00,G01,G02,G03,G04,G05,G06,G07,G08,G09 DC.L G10,G11,GNOTDEF,GNOTDEF,GNOTEMU DC.L GNOTDEF,G16,G17,G18,G19 DC.L GNOTDEF,GNOTDEF,GNOTDEF,GNOTDEF,GNOTDEF DC.L GNOTEMU,GNOTEMU,GNOTDEF,GNOTDEF,GNOTDEF DC.L GNOTDEF,GNOTDEF,GNOTEMU,GNOTDEF,GNOTDEF DC.L GNOTDEF,GNOTDEF,GNOTDEF,GNOTDEF,GNOTDEF DC.L GNOTDEF,GNOTDEF,GNOTEMU,GNOTEMU,GNOTEMU DC.L GNOTEMU,GNOTDEF,GNOTEMU,G48,GNOTEMU DC.L GNOTDEF,GNOTDEF,GNOTDEF,GNOTDEF,GNOTEMU DC.L GNOTDEF,GNOTDEF,GNOTEMU,GNOTEMU,GNOTEMU DC.L GNOTEMU,GNOTEMU,GNOTEMU,G63,G64 DC.L GNOTEMU,GNOTEMU,GNOTEMU,GNOTDEF,GNOTEMU DC.L GNOTEMU,GNOTEMU,G72,G73,G74 DC.L G75,G76,GNOTDEF,GNOTEMU,GNOTEMU DC.L GNOTDEF,GNOTDEF,GNOTDEF,GNOTDEF,GNOTDEF DC.L GNOTDEF,GNOTEMU,GNOTEMU GNOTEMU: ; nicht emulierte Funktion aufgerufen LEA 28(A7),A7 ; gepushte Register berspringen LSR.W #2,D0 ; durch 4 MOVE.W D0,-(A7) ; Funktionsnummer MOVE.W #2,-(A7) ; Fehler in GEMDOS aufgetreten TRAP #15 ; 'Nicht emulierte Funktion'-Meldung, Abbruch ; ->kehrt nicht mehr zurck G00: MOVE.W #0,-(A0) ; Pterm0, 0 auf Stack berschreibt Funktiosnnr. BRA G76 ; Pterm G01: MOVE.W #2,-(A7) ; Cconin, CON MOVE.W #2,-(A7) ; Bconin TRAP #13 ; BIOS ADDQ.L #4,A7 MOVE.W D0,-(A7) ; Zeichen auf Stack MOVE.W #2,-(A7) ; CON, Echo MOVE.W #3,-(A7) ; Bconout TRAP #13 ; BIOS ADDQ.L #6,A7 BRA GINTRENDD0 ; Zeichen zurckgeben G02: MOVE.W (A0),-(A7) ; Cconout MOVE.W #2,-(A7) ; CON MOVE.W #3,-(A7) ; Bconout TRAP #13 ; BIOS ADDQ.L #6,A7 BRA GINTREND G03: MOVE.W #1,-(A7) ; Cauxin, AUX MOVE.W #2,-(A7) ; Bconin TRAP #13 ; BIOS ADDQ.L #4,A7 BRA GINTRENDD0 G04: MOVE.W (A0),-(A7) ; Cauxout MOVE.W #1,-(A7) ; AUX MOVE.W #3,-(A7) ; Bconout TRAP #13 ; BIOS ADDQ.L #6,A7 BRA GINTREND G05: MOVE.W (A0),-(A7) ; Cprnout MOVE.W #0,-(A7) ; PRN MOVE.W #3,-(A7) ; Bconout TRAP #13 ; BIOS ADDQ.L #6,A7 BRA GINTRENDD0 ; Status vom BIOS zurckgeben G06: MOVE.W (A0),D0 ; Crawio CMPI.B #-1,D0 BNE G02 ; <> -1 Zeichen einlesen, Cconin MOVE.W #2,-(A7) ; CON MOVE.W #1,-(A7) ; Bconstat TRAP #13 ; BIOS ADDQ.L #4,A7 TST.W D0 BEQ GINTREND0 ; kein Zeichen bereit, Null zurck sonst: G07: ; Crawcin G08: MOVE.W #2,-(A7) ; Cnecin, CON MOVE.W #2,-(A7) ; Bconin TRAP #13 ; BIOS ADDQ.L #4,A7 BRA GINTRENDD0 G09: MOVE.L (A0),A0 ; Cconws MOVEQ #0,D1 ; geholte Zeichen GCCONWSNEXT: MOVEQ #0,D0 MOVE.B (A0)+,D0 BEQ GCCONWSEND ; Null = Ende des Strings MOVE.W D0,-(A7) ; Zeichen auf Stack MOVE.W #2,-(A7) ; CON MOVE.W #3,-(A7) ; Bconout TRAP #13 ; BIOS ADDQ.L #6,A7 BRA GCCONWSNEXT ; n„chstes Zeichen GCCONWSEND: MOVE.W #13,-(A7) ; Return MOVE.W #2,-(A7) ; CON MOVE.W #3,-(A7) ; Bconout TRAP #13 ; BIOS ADDQ.L #6,A7 MOVE.W #10,-(A7) ; Linefeed MOVE.W #2,-(A7) ; CON MOVE.W #3,-(A7) ; Bconout TRAP #13 ; BIOS ADDQ.L #6,A7 MOVE.L D1,D0 ; Anzahl Zeichen zurckgeben BRA GINTRENDD0 G10: MOVEA.L (A0),A0 ; Cconrs MOVE.B (A0)+,D1 ; A0 zeigt auf Platz fr Rckgabewert LEA 1(A0),A1 ; Buffer fr erstes Zeichen MOVEQ #0,D2 ; geholte Zeichen BRA GCCONRSWHILE GCCONRSNEXT: MOVE.W #2,-(A7) ; Zeichen holen, CON MOVE.W #2,-(A7) ; Bconin TRAP #13 ; BIOS ADDQ.L #4,A7 MOVE.W D0,-(A7) ; Echo, Zeichen auf Stack MOVE.W #2,-(A7) ; CON MOVE.W #3,-(A7) ; Bconout TRAP #13 ; BIOS ADDQ.L #6,A7 CMPI.B #10,D0 ; Linefeed? BEQ GCCONRSDONE ; Terminal Atari, abbrechen CMPI.B #13,D0 ; Return? BNE GCCONRSDELTEST MOVE.W #10,-(A7) ; Terminal VT, Linefeed senden und abbrechen MOVE.W #2,-(A7) ; CON MOVE.W #3,-(A7) ; Bconout TRAP #13 ; BIOS ADDQ.L #6,A7 BRA GCCONRSDONE GCCONRSDELTEST: CMPI.B #8,D0 ; Backspace? (Atari) BEQ GCCONRSDELETE CMPI.B #$7F,D0 ; Delete? (VT) BNE GCCONRSSAVE GCCONRSDELETE: TST D3 ; keine Zeichen gespeichert? BEQ GCCONRSWHILE ; nichts l”schen LEA -1(A0),A0 ; letztes Zeichen vergessen SUBQ.W #1,D2 ; 1 Zeichen weniger BRA GCCONRSWHILE GCCONRSSAVE: MOVE.B D0,(A0)+ ; Zeichen speichern ADDQ.W #1,D2 ; ein Zeichen mehr GCCONRSWHILE: DBRA D1,GFREADNEXT GCCONRSDONE: MOVE.B D2,(A0) ; Rckgabewert speichern MOVE.W D2,D0 ; Anzahl Zeichen zurckgeben BRA GINTRENDD0 G11: MOVE.W #2,-(A7) ; Cconis, CON MOVE.W #1,-(A7) ; Bconstat TRAP #13 ; BIOS ADDQ.L #4,A7 BRA GINTRENDD0 ; in D0 zurck G16: MOVE.W #2,-(A7) ; Cconos, CON MOVE.W #8,-(A7) ; Bcostat TRAP #13 ; BIOS ADDQ.L #4,A7 BRA GINTRENDD0 ; in D0 zurck G17: MOVE.W #0,-(A7) ; Cprnos, PRN MOVE.W #8,-(A7) ; Bcostat TRAP #13 ; BIOS ADDQ.L #4,A7 BRA GINTRENDD0 ; in D0 zurck G18: MOVE.W #1,-(A7) ; Cauxis, AUX MOVE.W #1,-(A7) ; Bconstat TRAP #13 ; BIOS ADDQ.L #4,A7 BRA GINTRENDD0 ; in D0 zurck G19: MOVE.W #1,-(A7) ; Cauxos, AUX MOVE.W #8,-(A7) ; Bcostat TRAP #13 ; BIOS ADDQ.L #4,A7 BRA GINTRENDD0 ; in D0 zurck G48: MOVE.W #$1300,D0 ; Sversion BRA GINTRENDD0 G63: MOVE.W (A0)+,D0 ; Fread CMPI.W #4,D0 BCS GFREADVALID MOVE.W #-37,D0 ; Handle 4 und gr”sser -> ungltig GFREADVALID: LEA GHANDLES,A1 MOVEQ #0,D1 MOVE.B (A1,D0.W),D1 ; Ger„tenummer holen MOVE.L (A0)+,D2 ; max. Anzahl Zeichen, long MOVEQ #0,D3 ; geholte Zeichen MOVEA.L (A0),A0 ; Buffer fr die Zeichen BRA GFREADWHILE GFREADNEXT: MOVE.W D1,-(A7) ; Zeichen holen, von Ger„t D1 MOVE.W #2,-(A7) ; Bconin TRAP #13 ; BIOS ADDQ.L #4,A7 MOVE.W D0,-(A7) ; Echo, Zeichen auf Stack MOVE.W D1,-(A7) ; zum Ger„t D1 MOVE.W #3,-(A7) ; Bconout TRAP #13 ; BIOS ADDQ.L #6,A7 CMPI.B #10,D0 ; Linefeed? BEQ GFREADDONE ; Terminal Atari, abbrechen CMPI.B #13,D0 ; Return? BNE GFREADDELTEST MOVE.W #10,-(A7) ; Terminal VT, Linefeed senden und abbrechen MOVE.W #2,-(A7) ; CON MOVE.W #3,-(A7) ; Bconout TRAP #13 ; BIOS ADDQ.L #6,A7 BRA GFREADDONE GFREADDELTEST: CMPI.B #8,D0 ; Backspace? (Atari) BEQ GFREADDELETE CMPI.B #$7F,D0 ; Delete? (VT) BNE GFREADSAVE GFREADDELETE: TST D3 ; keine Zeichen gespeichert? BEQ GFREADWHILE ; nichts l”schen LEA -1(A0),A0 ; letztes Zeichen vergessen SUBQ.W #1,D3 ; 1 Zeichen weniger BRA GFREADWHILE GFREADSAVE: MOVE.B D0,(A0)+ ; Zeichen speichern ADDQ.W #1,D3 ; ein Zeichen mehr GFREADWHILE: DBRA D2,GFREADNEXT ; l„uft nur bis max. 65535 Zeichen! GFREADDONE: MOVE.L D3,D0 ; Anzahl Zeichen zurckgeben (long) BRA GINTRENDD0 G64: MOVE.W (A0)+,D0 ; Fwrite CMPI.W #4,D0 BCS GFWRITEVALID MOVE.W #-37,D0 ; Handle 4 ung#d gr”sser -> ungltig BRA GINTRENDD0 GFWRITEVALID: LEA GHANDLES,A1 MOVEQ #0,D1 MOVE.B (A1,D0.W),D1 ; Ger„tenummer holen MOVE.L (A0)+,D2 ; max. Anzahl Zeichen MOVE.L D2,D3 ; werden alle ausgegeben (Rckgabe long) MOVE.L (A0),A0 BRA GFWRITEWHILE GFWRITENEXT: MOVEQ #0,D0 MOVE.B (A0)+,D0 ; Zeichen auf Stack MOVE.W D0,-(A7) MOVE.W D1,-(A7) ; zum Ger„t D1 MOVE.W #3,-(A7) ; Bconout TRAP #13 ; BIOS ADDQ.L #6,A7 GFWRITEWHILE: DBRA D2,GFWRITENEXT ; l„uft nur bis max. 65535 Zeichen! MOVE.W #13,-(A7) ; Return MOVE.W D1,-(A7) ; zum Ger„t D1 MOVE.W #3,-(A7) ; Bconout TRAP #13 ; BIOS ADDQ.L #6,A7 MOVE.W #10,-(A7) ; Linefeed MOVE.W D1,-(A7) ; zum Ger„t D1 MOVE.W #3,-(A7) ; Bconout TRAP #13 ; BIOS ADDQ.L #6,A7 MOVE.L D3,D0 ; Anzahl Zeichen zurckgeben BRA GINTRENDD0 GHANDLES: DC.B 2,2,1,0 G72: MOVE.L (A0),D0 ; Malloc CMPI.L #-1,D0 BEQ GMALLOCSIZE MOVE.W D0,D1 ANDI.W #1,D1 ; ungerade Anzahl Bytes? BEQ GMALLOCEVEN ADDQ.L #1,D0 ; gerade machen GMALLOCEVEN: LEA GMALLOCTABLE,A0 ; erster Block GMALLOCREPEAT: MOVE.L (A0),D1 ; Blockanfang BEQ GINTREND0 ; Tabelle zu Ende, NULL zurckgeben BMI GMALLOCNEXT ; Bit 31 = besetzt, n„chster Block MOVE.L 4(A0),D1 ; L„nge dieses Blockes CMP.L D1,D0 ; geforderter Block gr”sser? BPL GMALLOCNEXT ; falls ja, n„chster Block BNE GMALLOCSHRINK ; dieser Block zu gross, aufteilen in Mshrink MOVE.L (A0),D0 ; genau richtig, Anfang des Blockes zurckgeben ORI.L #$80000000,(A0) ; als belegt bezeichnen BRA GINTRENDD0 GMALLOCNEXT: ADDQ.L #8,A0 ; n„chster Block BRA GMALLOCREPEAT GMALLOCSIZE: MOVEQ #0,D0 ; bisher kein Block gefunden LEA GMALLOCTABLE,A0 ; erster Block GMSIZEREPEAT: MOVE.L (A0),D1 ; Blockanfang BEQ GINTRENDD0 ; Tabelle zu Ende BMI GMSIZENEXT ; Bit 31 = besetzt, n„chster Block MOVE.L 4(A0),D1 ; L„nge dieses Blockes CMP.L D1,D0 ; gr”sser als bisheriger Block? BPL GMSIZENEXT MOVE.L D1,D0 ; als gr”ssten bisherigen Block merken GMSIZENEXT: ADDQ.L #8,A0 ; n„chster Block BRA GMSIZEREPEAT G73: MOVE.L (A0),D1 ; Mfree ORI.L #$80000000,D1 ; Block ist als belegt bezeichnet LEA GMALLOCTABLE,A0 ; erster Block GMFREEREPEAT: CMP.L (A0),D1 ; Blockanfang, unser Block? BNE GMFREENEXT ANDI.L #$7FFFFFFF,(A0) ; Block frei bezeichnen LEA 8(A0),A1 ; fr Verschiebung: Quelle = n„chster TST.L 8(A0) ; n„chster Block auch frei? BMI GMFREEPREVTEST ; nein, belegt BEQ GMFREEPREVTEST ; nein, Tabellenende MOVE.L 12(A0),D0 ADD.L D0,4(A0) ; seine L„nge zu eigener L„nge hinzuz„hlen LEA 16(A0),A1 ; Quelle = bern„chster (nachster entf„llt) GMFREEPREVTEST: LEA 8(A0),A2 ; fr Verschiebung: Ziel = n„chster CMPA.L #GMALLOCTABLE,A0 ; Erster Eintrag der Tabelle? BEQ GMFREECHECK ; falls ja, kein Vorheriger TST.L -8(A0) ; vorheriger Block auch frei? BMI GMFREECHECK ; nein MOVE.L 4(A0),D0 ADD.L D0,-4(A0) ; eigene L„nge zu seiner LEA (A0),A2 ; Ziel = selbst (selbst entf„llt) GMFREECHECK: CMPA A1,A2 ; Ziel und Quelle gleich? BEQ GINTREND0 GMFREECOPY: MOVE.L (A1)+,(A2)+ ; wenn nicht, nach vorne kopieren MOVE.L (A1)+,(A2)+ CMPA.L #GMALLOCTABLE+256,A1 ; ganzer Tabellenschwanz kopiert? BNE GMFREECOPY BRA GINTREND0 GMFREENEXT: ADDQ.L #8,A0 ; n„chster Block TST.L (A0) BNE GMFREEREPEAT MOVE.L #-40,D0 ; ungltiger Block BRA GINTRENDD0 G74: LEA 2(A0),A0 ; Mshrink, (A0) = 0 MOVE.L (A0)+,D1 ; Adresse MOVE.L (A0),D0 ; neue L„nge MOVE.W D0,D2 ANDI.W #1,D2 ; ungerade Anzahl Bytes? BEQ GMSHRINKEVEN ADDQ.L #1,D0 ; gerade machen GMSHRINKEVEN: ORI.L #$80000000,D1 ; Block ist als belegt bezeichnet LEA GMALLOCTABLE,A0 ; erster Block GMSHRINKREPEAT: CMP.L (A0),D1 ; Blockanfang, unser Block? BNE GMSHRINKNEXT MOVE.L 4(A0),D1 ; bisherige L„nge unseres Blockes CMP.L D1,D0 ; neu gr”sser? BPL GMSHRINKTOBIG ; falls ja, Fehler BEQ GINTREND0 ; gleich gross, nichts „ndern GMALLOCSHRINK: ; von Malloc her MOVE.L D0,4(A0) ; neue L„nge merken ORI.L #$80000000,(A0) ; als belegt bezeichnen fr von Malloc her TST.L 8(A0) ; n„chstes Element belegt, leer oder Ende? BEQ GMSHRINKNEW ; Ende, Liste erweitern BPL GMSHRINKMERGE ; leer, Rest zu n„chstem Element dazuz„hlen GMSHRINKNEW: ; belegt oder Ende, neues Element erstellen LEA GMALLOCTABLE+240,A1 ; zweitletzter Tabellenplatz -> letzter CMPA A1,A0 BCC GMSHRINKTOBIG ; Tabelle voll, Rest geht verloren GMSHRINKCOPY: MOVE.L -8(A1),(A1) ; um ein Platz nach hinten kopieren MOVE.L -4(A1),4(A1) LEA -8(A1),A1 CMPA.L A1,A0 ; ganzer Tabellenschwanz kopiert? BNE GMSHRINKCOPY MOVE.L #0,12(A0) ; L„nge des neuen Elementes = 0 GMSHRINKMERGE: ; Rest zu Element hinzu SUB.L D0,D1 ; L„nge des Restes ADD.L (A0),D0 ; Anfangsadresse des Restes AND.L #$7FFFFFFF,D0 ; nicht belegt MOVE.L D0,8(A0) ; setzen ADD.L D1,12(A0) ; L„nge setzen BRA GINTREND0 ; erfolgreich erledigt GMSHRINKNEXT: ADDQ.L #8,A0 ; n„chster Block TST.L (A0) BNE GMSHRINKREPEAT MOVE.L #-40,D0 ; ungltiger Block BRA GINTRENDD0 GMSHRINKTOBIG: MOVE.L #-67,D0 ; vergr”ssern nicht erlaubt BRA GINTRENDD0 G75: MOVE.W (A0)+,D0 ; Pexec CMPI.W #4,D0 ; Progrann starten? BNE GINTREND0 ; Nein, Null zurck MOVE USP,A1 ; Userstack wird von neuem Programm ver„ndert, MOVE.L A1,-(A7) ; fr Pterm auf Systemstack merken MOVE.L (A0),A0 ; Anfangsadresse ebenfalls MOVE.L A0,-(A7) ; fr Mfree in Pterm auf Systemstack merken ANDI #$DFFF,SR ; in User-Modus schalten JMP $100(A0) ; Programm ausfhren, Basepage berspringen ; nach Userprogramm hier weiter G76: MOVEQ #0,D0 ; Pterm MOVE.W (A0),D0 ; Exitcode, Rckgabe von Pexec ist long LEA 34(A7),A7 ; kehrt nicht zurck, Aufruf beseitigen ; immer nur 6 Bytes, da Aufruf von User-Modus MOVE.W #73,-(A7) ; Mfree ; Blockanfang Userprog auf Stack (von Pexec) TRAP #1 ; GEMDOS ADDQ.L #6,A7 MOVE.L (A7)+,A0 ; Userstack wiederherstellen MOVE A0,USP BRA GINTRENDD0 ; mit Exitwert zu Elterprogramm zurck ; TRAP #15, fr nicht emulierte Funktionen des miniTOS ; Aufruf: MOVE.W Funktion,-(A7) MOVE.W Ort,-(A7) TRAP #15 ; Ort: BIOS=0, XBIOS=1, GEMDOS=2 NINIT: ; Modul 'Not emulated' initialisieren MOVE.L #NINTR,$BC ; TRAP #15 setzen BRA UINIT NINTR: MOVE.W 6(A7),D0 ; wo Fehler auftrat LSL.W #2,D0 ; mal 4 LEA NWHERETABLE,A0 MOVEA.L (A0,D0.W),A0 ; dieser Fehlerort BSR NSTROUT ; ausgeben LEA NFUNKTNR,A0 ; erster Teil des Textes BSR NSTROUT ; ausgeben MOVEQ #0,D0 MOVE.W 8(A7),D0 ; Nummer der nicht emulierten Funktion BSR NNROUT ; ausgeben LEA NNICHTEMU,A0 ; zweiter Teil des Textes BSR NSTROUT ; ausgeben MOVE.L 12(A7),D0 ; Adresse an der Fehler auftrat BSR NNROUT ; ausgeben MOVE.L #$200000,D0 NWAIT: DBRA D0,NWAIT ; ungef„r 5s warten LEA 0,A0 ; Userprogramm beenden -> Reset MOVEA.L (A0)+,A7 ; Supervisor-Stack setzen MOVEA.L (A0),A0 JMP (A0) ; an Reset springen NSTROUT: ; String ausgeben MOVE.B (A0)+,D0 ; n„chstes Zeichen zum Ausgeben BEQ NSTROUTEND ; 0 = Ende des Strings MOVEQ #0,D1 MOVE.B D0,D1 MOVE.W D1,-(A7) ; Zeichen auf den Stack MOVE.W #2,-(A7) ; CON MOVE.W #3,-(A7) ; Bconout TRAP #13 ; BIOS ADDQ.L #6,A7 BRA NSTROUT NSTROUTEND: RTS NNROUT: ; Zahl in D0 als Hexstring ausgeben ROL.L #4,D0 ; D0 mal 16, vorderste 4 Bits in untere 4 Bits MOVE.W D0,D1 ANDI.W #$F,D1 ; n„chste Ziffer isolieren BEQ NNROUT ; fhrende Nullen auslassen NNRNEXT: MOVE.W D0,D1 ANDI.W #$F,D1 ; n„chste Ziffer isolieren LEA NHEXTABLE,A1 MOVE.B (A1,D1.W),D1 MOVE.W D1,-(A7) ; Ziffer auf den Stack MOVE.W #2,-(A7) ; CON MOVE.W #3,-(A7) ; Bconout TRAP #13 ; BIOS ADDQ.L #6,A7 ANDI.L #$FFFFFFF0,D0 ; Ziffer erledigt ROL.L #4,D0 ; D0 mal 16, vorderste 4 Bits in untere 4 Bits BNE NNRNEXT ; noch nicht 0, n„chste Ziffer RTS ; Zahl erledigt NWHERETABLE: DC.L NBIOS,NXBIOS,NGEMDOS NBIOS: DC.B 10,"BIOS",0 NXBIOS: DC.B 10,"XBIOS",0 NGEMDOS: DC.B 10,"GEMDOS",0 NFUNKTNR: DC.B "-Funktionsnummer $",0 NNICHTEMU: DC.B " nicht emuliert",10,"Fehler aufgetreten an Adresse $",0 NHEXTABLE: DC.B "0123456789ABCDEF" ; Userprogramm-Einbindung UINIT: ; Modul 'Userprogramm' initialisieren LEA GMALLOCTABLE,A0 ; Malloc wie von Pexec, Funktion 0 simulieren MOVE.L #USERPROGBEGIN,D0 ORI.L #$80000000,D0 ; belegter Block MOVE.L D0,(A0)+ MOVE.L #USERRAMEND,D0 SUB.L #USERPROGBEGIN,D0 ; L„nge des Blockes MOVE.L D0,(A0)+ MOVE.L #0,(A0) ; Neues Ende markieren ANDI #$20FF,SR ; Interupts einsschalten PEA USERPROGBEGIN ; Userprogramm MOVE.W #4,-(A7) ; starten MOVE.W #75,-(A7) ; Pexec TRAP #1 ; GEMDOS ADDQ.L #8,A7 BRA UINIT ; Userprogramm beendet -> wiederholen USERPROGBEGIN: ; hier f„ngt Userprogramm an ; z.B. dieses Testprogramm DS.B $100 ; Basepage USTART: LEA USTART-$100,A0 ; Anfang Code MOVE.L #$2000,A7 ; Stack setzen, Ende Speicher MOVE.L A7,D0 SUB.L A0,D0 ; L„nge Speicher MOVE.L D0,-(A7) MOVE.L A0,-(A7) MOVE.W #0,-(A7) MOVE.W #74,-(A7) ; Mshrink TRAP #1 LEA 12(A7),A7 PEA UHELLO ; Hello World! MOVE.L #12,-(A7) MOVE.W #1,-(A7) ; stdout MOVE.W #64,-(A7) ; Fwrite TRAP #1 LEA 12(A7),A7 PEA $1000 ; Buffer MOVE.L #100,-(A7) MOVE.W #0,-(A7) ; stdin MOVE.W #63,-(A7) ; Fread TRAP #1 LEA 12(A7),A7 PEA $1000 ; Buffer MOVE.L D0,-(A7) ; Length MOVE.W #1,-(A7) ; stdout MOVE.W #64,-(A7) ; Fwrite TRAP #1 LEA 12(A7),A7 MOVE.L #-1,-(A7) ; longest? MOVE.W #72,-(A7) ; Malloc TRAP #1 ADDQ.L #6,A7 MOVE.L #100,-(A7) ; Length MOVE.W #72,-(A7) ; Malloc TRAP #1 ADDQ.L #6,A7 MOVE.L D0,-(A7) ; Blockanfang MOVE.W #73,-(A7) ; Mfree TRAP #1 ADDQ.L #6,A7 MOVE.W #0,-(A7) ; Pterm0 TRAP #1 UHELLO: DC.B "Hello World!" END