home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / program / misc / line_f / lfed_5.s < prev    next >
Text File  |  1994-02-09  |  24KB  |  662 lines

  1. ;---------------------------------------------------------------------
  2. ;Programm-/Routinen-Name:    Line-F Emulation Driver / LFED
  3. ;                         Version 2.00
  4. ;Datum: 27.07.92
  5. ;
  6. ;Aufgabe/Kurzdoku: Line-F-Emulator für die Benutzung eines MC68881
  7. ;in einem Atari ST/STE mit MC68000 (also auch der SFP004-Karte).
  8. ;Mit LFED ist die Nutzung der FPU in vollem Umfang gewährleistet und
  9. ;kann von jedem Programm angesprochen werden, welches FPU-Unterstützung
  10. ;verlangt. MC68030 (TT) optimierte Programme sind hiervon natürlich
  11. ;ausgenommen, da der MC68000 dessen InstructionSet nicht versteht!
  12. ;
  13. ;Wird ein MC68882 als FPU genutzt, müssen einige kleinere Anpassungen
  14. ;vorgenommen werden, da dieser an verschiedenen Stellen Übertragungen
  15. ;des PC's erwartet.
  16.  
  17. ;Autor:  Roger Butenuth (c't 04/90 Seite 430 ff.)
  18. ;         Michael Hauschild (XBRA-Erweiterungen und alle folgenden
  19. ;         Versionen)  
  20.  
  21. ;    (c)    Smart Systems '92
  22. ;        Windhornstraße 2 / 3016 Seelze 1
  23. ;        Telefon (05137) 9 20 09
  24. ;---------------------------------------------------------------------
  25. ;Dokumentation: 
  26. ;---------------------------------------------------------------------
  27. ;Der Treiber installiert sich unter Beachtung des XBRA-Protokolls, 
  28. ;d.h. er erkennt sein Vorhandensein und gibt eine Meldung aus, falls
  29. ;versucht wird, ihn erneut zu installieren.
  30.  
  31. ;Nicht unterstützte FPU-Befehle:
  32.  
  33. ;    FTRAP, FSAVE, FRESTORE
  34.  
  35. ;Erkannte BUGS in Version 1.00:
  36.  
  37. ;    FMOVEM (An),FP0-FPn  ... dieser ist eigentlich kein BUG !
  38.  
  39. ;    Es tritt ein BUS-Error beim Terminieren von Programmen auf, die
  40. ;    die FPU nutzen und für das Terminieren die C-Funktion return() 
  41. ;    verwenden. Der Grund hierfür ist ein Restore der FPU-Register
  42. ;    mit FMOVEM (diese werden am Programmbegin gesichert). Man kann
  43. ;    dieses SAUBER umgehen, indem man aus FPU-nutzenden Funktionen
  44. ;    mit exit() zurückkehrt (sofern man kein Funktionsergebnis
  45. ;    erwartet!) - dann sollte auch kein Bus-Error mehr auftreten 
  46. ;    (siehe FPU_TST2.C oder auch BGIDEMO.C)
  47.  
  48. ;Letzte Änderung:
  49. ;    19.05.92    Freigabe der Version 1.00, da der BUG mit FMOVEM und
  50. ;                return(0) "gefixt" ist!
  51. ;    27.07.92    Version 2.00 für neuere TOS-Versionen (ab TOS-Version
  52. ;                1.06), in denen die    LineF nicht mehr "mißbraucht" wird.
  53. ;                In dieser Version wird keine Prüfung mehr gemacht, ob 
  54. ;                der Trap-Aufruf aus    dem ROM oder RAM kam. Es wird 
  55. ;                grundsätzlich davon ausgegangen, daß dieser von einer
  56. ;                Applikation gemacht wurde!
  57. ;   09.02.94    Diverse kleinere Änderungen die den Code optimieren
  58. ;                und kleiner machen. Zudem wird jetzt auch auf den
  59. ;                _FPU-Cookie getestet und bei diesem das untere Wort
  60. ;                auf 1 gesetzt. Wenn der _FPU-Cookie oder kein 68881
  61. ;                Prozessor vorhanden ist, dann installiert sich diese
  62. ;                Version auch _nicht_!
  63. ;                Es gibt unter PureC keine Probleme wenn man die
  64. ;                Compileroption '-S' setzt, anscheinend optimiert sich 
  65. ;                PureC selber raus! :-((
  66. ;                                    Jan Kriesten, Maus F
  67. ;                                                  2:244/4344@Fidonet
  68. ;                                                  90:400/1002@NeST
  69.  
  70. ;---------------------------------------------------------------------
  71. ;ACHTUNG: bei den Assembler-Options muß -S Flag gesetzt werden 
  72. ;(wegen ReTurn from Exception / RTE) ! 
  73.  
  74. ;-------------- macro - definitions ----------------------------------
  75.  
  76. .MACRO Supexec
  77.     move.w        #38,-(sp)        ;Supexec()
  78.     trap        #14                ;XBIOS
  79.     addq.l        #6,sp            ;Stack aufräumen
  80. .ENDM            
  81.         
  82. ;-------------- set FPU-register-addresses ---------------------------
  83.     
  84. _p_cookies    equ        $05a0.w
  85.  
  86. response     equ     $fffa40    ;in a6 (Coprozessor-Basisregister)
  87. control        equ        $02        ;Alle weiteren Register relativ zu
  88. save        equ        $04        ;response
  89. restore        equ        $06        
  90. command        equ        $0a        ;in a5
  91. condition    equ        $0e
  92. operand        equ        $10        ;in a4
  93. reg_selec    equ        $14
  94. ins_add        equ        $18
  95. lineF        equ        $2c        ;Line-F / TRAP #11
  96.  
  97. ;-------------- start of code ----------------------------------------
  98.  
  99.             .TEXT
  100.             pea.l        Install(pc)        ;Installations-Routine
  101.             Supexec                        ;SVC
  102.             cmp.l        #"LFED",d1        ;ist "LFED" ?
  103.             beq            Terminate_1        ;ja -> dann terminieren
  104.             
  105.             bsr            getcookie        ;ist _FPU-Cookie vorhanden?
  106.             tst.b        d0                ;
  107.             beq            Terminate_2        ; nicht -> dann terminieren
  108.  
  109.             move.w        4(a0), d0        ;Copro überhaupt vorhanden?
  110.             andi.w        #%111, d0        ;
  111.             beq            Terminate_3        ;
  112.             
  113.             move.w        #1, 6(a0)        ; LineF-Unterstützung eintragen
  114.             
  115. start:        pea.l        titel(pc)        ;Titel-Daten holen
  116.             move.w        #9,-(sp)        ;Cconws 
  117.             trap        #1                ;GEMDOS-Call
  118.             addq.l        #6,sp            ;Stack-Korrektur
  119.  
  120.             pea            mytrap(pc)        ;Diesen Vektor setzen
  121.             move.l        #$0005000B,-(sp);Setexc (BIOS 5),LineF (Exception 11) setzen
  122.             trap        #13
  123.             addq.l        #8, sp
  124.             move.l        d0, oldtrap        ;Alten Wert retten
  125.                         
  126.             movea.l        4(sp),a0        ;Basepageadresse holen
  127.             move.l        #$100,d1        ;Basepagelänge
  128.             add.l        $0c(a0),d1        ;+Textlänge
  129.             add.l        $14(a0),d1        ;+Datenlänge
  130.             add.l        $1c(a0),d1        ;+BSS-Länge
  131.             move.l        d1,-(sp)        ;Länge des belegten Speichers
  132.             move.w        #$31,-(sp)        ;an GEMDOS melden
  133.             trap        #1
  134.             
  135. getcookie:
  136.         move.l        d3, -(sp)            ; Register retten
  137.         move.l        #"_FPU", d3            ;
  138.  
  139.         ; Cookie Jar Adresse holen:        
  140.         pea            .cookies(pc)        ; Adresse der Funktion auf den Stack
  141.         Supexec
  142.  
  143.         tst.l        d0                    ; ist überhaupt ein Cookie Jar vorhanden?
  144.         beq.b        .end_search            ; wenn nicht, dann zurück
  145.  
  146.         movea.l        d0, a0                ; Adresse speichern
  147.         moveq        #0, d0                ; erstmal auf FALSE setzen
  148.  
  149. .loop:
  150.         tst.l        (a0)                ; Ende des Cookie Jars erreicht?
  151.         beq.b        .end_search            ; wenn, dann zurück
  152.         
  153.         cmp.l        (a0), d3            ; Cookie gefunden?
  154.         bne.b        .not_found            ; wenn nicht, dann weitersuchen
  155.  
  156.         moveq        #1, d0                ; Cookie gefunden;
  157.         bra            .end_search            ; und zurück
  158.         
  159. .not_found:
  160.         addq.l        #8, a0                ; nächster Cookie
  161.         bra.b        .loop                ; Schleife
  162.         
  163. .end_search:
  164.         move.l        (sp)+, d3            ;    Register restaurieren
  165.         rts
  166.         
  167. .cookies:
  168.         move.l        (_p_cookies), d0    ; Zeiger auf den Cookie Jar
  169.         rts                                ;
  170.  
  171. ;-------------- XBRA-structure ---------------------------------------
  172.             
  173. xb_magic:    .dc.b        "XBRA"            ;XBRA-Struktur vor neuem Trap
  174. xb_id:        .dc.b        "LFED"            ;XBRA-Kennung
  175.  
  176. oldtrap:    .dc.l        0                ;Platz für alten Line-F-Vektor
  177.  
  178. ;-------------- lineF-handler -----------------------------------------
  179.  
  180. mytrap:        movem.l        d0-a6,dregs        ;Register retten
  181.             move.l        usp,a0            ;USP retten
  182.             move.l        a0,rusp            ;über Umweg
  183.             lea            response,a6        ;#response nach A6
  184.             lea            command(a6),a5    ;#command  nach A5
  185.             lea            operand(a6),a4    ;#operand  nach A4
  186.             lea            dregs(pc),a3    ;#dregs    nach A3
  187.             movea.l        2(sp),a0        ;PC nach A0
  188.             move.w        (a0),d1            ;Kommando nach D1
  189. again:                ;-------- Einsprung für weitere FPU-Befehle
  190.             andi.w        #%111000000,d1    ;Spezialteil ausmaskieren
  191.             bne            spezial            ;Ein Bit gesetzt->Spezialbefehl
  192.             move.w        2(a0),d1        ;zweiten Befehlsteil in D1 merken
  193.             move.w        d1,(a5)            ;Befehl in FPU schreiben (A3==#command)
  194. do_ca:                ;-------- Einsprung für weiter Nachfragen an FPU
  195.             move.w        (a6),d0            ;Response lesen
  196.             btst        #12,d0            ;erstes Modusbit testen
  197.             bne            rw_1x            ;==1 -> springen
  198.             btst        #11,d0            ;zweites Modusbit testen
  199.             beq.s        rw_00            ;==0 -> springen
  200.             ;-------- %xxx01, Null-Primitive/Transfer Single CPU-Register
  201.             btst        #10,d0            ;Register übertragen?
  202.             bne.s        rw_sngl            ;JA -> Transfer Single CPU-Register
  203.             btst        #15,d0            ;CA (Come Again) gesetzt?
  204.             bne.s        do_ca            ;JA -> weiter fragen, sonst fertig
  205.             addq.l        #4,a0            ;A0 um reine Befehlslänge weiter
  206.                     ;(Alles andere wurde in calc_add erledigt)
  207.             move.w        (a0),d1            ;erstes Befehlswort holen
  208.             move.w        d1,d0            ;und nach D0
  209.             andi.w        #$f000,d0        ;wieder COP-Befehl?
  210.             eori.w        #$f000,d0        ;
  211.             beq.s        again            ;JA -> direkt weiter machen
  212.             move.l        a0,2(sp)        ;neuen PC eintragen
  213.             movea.l        rusp(pc),a0        ;USP wieder restaurieren
  214.             move.l        a0,usp            ;wieder über Umweg
  215.             movem.l        (a3),d0-a6        ;Register restaurieren
  216.             rte                            ;Trap beenden
  217.  
  218. rw_sngl:    andi.w        #%1110000,d1    ;Registernummer ausmaskieren (nur Dn)
  219.             lsr.w        #2,d1            ;D1=Nummer*4
  220.             move.l        (a3,d1.w),(a4)    ;Register übertragen (a4==#operand,a3==#dregs)
  221.             bra.s        do_ca            ;danach kommt immer noch etwas
  222.             
  223. rw_00:        ;-------- %xxx00, Transfer multiple coprocessor registers
  224.             bsr         calc_add        ;Operandenadresse nach A1 holen
  225.             move.w        reg_selec(a6),d4    ;Registerliste nach D4 holen
  226.             btst        #13,d0            ;Dr-Bit testen
  227.             beq.s        w_00            ;==0 -> Daten in FPU schreiben
  228.                         
  229.             btst        #12,d0            ;Predekrementmodus?
  230.             beq.s        r_pred            ;==0 -> ja, springen
  231.             
  232.             moveq        #7,d0            ;Schleifenzähler für 8 Bits
  233.             
  234. .l_1:        add.w        d4,d4            ;ein Bit ins Carry
  235.             bcc.s        .l_2             ;nur bei Bit==1 etwas machen
  236.             move.l        (a4),(a1)+        ;1 (A4==#operand)
  237.             move.l        (a4),(a1)+        ;2
  238.             move.l        (a4),(a1)+        ;3 Langworte für jedes Register
  239. .l_2:        dbra        d0,.l_1            ;für alle 8 Bits
  240.  
  241.             bra            do_ca            ;nochmal FPU befragen
  242.             
  243. r_pred:        moveq        #7,d0            ;Schleifenzähler für 8 Bits
  244.  
  245. .l_1:        add.w        d4,d4            ;ein Bit ins Carry
  246.             bcc.s        .l_2            ;nur bei Bit==1 etwas machen
  247.             move.l        (a4),(a1)+        ;1 (A4==#operand)
  248.             move.l        (a4),(a1)+        ;2
  249.             move.l        (a4),(a1)+        ;3 Langworte für jedes Register
  250.             suba.w        #24,a1            ;Dekrement durchführen
  251. .l_2:        dbra        d0,.l_1            ;für alle 8 Bits
  252.  
  253.             adda.w        #12,a1            ;A1 wieder auf letztes Register
  254.             move.l        a1,(a2)            ;A1 als Registerinhalt abspeichern
  255.  
  256.             bra            do_ca            ;Nochmal FPU fragen
  257.             
  258. w_00:        move.w        (a0),d0            ;erstes Befehlswort holen
  259.             andi.b        #%111000,d0        ;Adressierungsart maskieren
  260.             cmpi.b        #%011000,d0        ;Gleich (An)+ ?
  261.             beq.s        w_post            ;JA -> Postinkrementmodus
  262.  
  263.             moveq        #7,d0            ;Schleifenzähler für 8 Bits
  264.  
  265. .l_1:        add.w        d4,d4            ;ein Bit ins Carry
  266.             bcc.s        .l_2            ;nur bei Bit==1 etwas machen
  267.             move.l        (a1)+,(a4)        ;1 (A4==#operand)
  268.             move.l        (a1)+,(a4)        ;2
  269.             move.l        (a1)+,(a4)        ;3 Langworte für jedes Register
  270. .l_2:        dbra        d0,.l_1            ;für alle 8 Bits
  271.  
  272.             bra            do_ca            ;Nochmal FPU fragen
  273.             
  274. w_post:        suba.w        #12,a1            ;Inkrement von calc_add aufheben
  275.  
  276.             moveq        #7,d0            ;Schleifenzähler für 8 Bits
  277.  
  278. .l_1:        add.w        d4,d4            ;ein Bit ins Carry
  279.             bcc.s        .l_2            ;nur bei Bit==1 etwas machen
  280.             move.l        (a1)+,(a4)        ;1 (A4==#operand)
  281.             move.l        (a1)+,(a4)        ;2
  282.             move.l        (a1)+,(a4)        ;3 Langworte für jedes Register
  283. .l_2:        dbra        d0,.l_1            ;für alle 8 Bits
  284.             move.l        a1,(a2)            ;A1 als Registerinhalt abspeichern
  285.             
  286.             bra            do_ca            ;Nochmal FPU fragen
  287.             
  288. rw_1x:        btst        #11,d0            ;zweites Modusbit testen
  289.             bne.s        rw_11            ;==1 -> springen (Trap, Error)
  290.             btst        #13,d0            ;DR-Bit testen
  291.             beq.s        w_10            ;==0 -> Daten an FPU schreiben
  292.             ;--------  %xx110, evaluate effective address and transfer data
  293.             bsr            calc_add        ;Operandenadresse berechnen
  294.                                         ;A1=Operandenadresse, d1.l=Operandenlänge
  295.             cmpi.w        #2,d1            ;Länge-2
  296.             ble.s        r_bw            ;<=2 -> Wort- oder Byteoperand
  297.             
  298. r_11:        move.l        (a4),(a1)+        ;ein Langwort lesen (a4==#operand)
  299.             subq.l        #4,d1            ;und runterzählen
  300.             bgt.s        r_11            ;>0 -> weiter übertragen
  301.             bra            do_ca            ;Nochmal FPU befragen
  302.             
  303. r_bw:        subq.b        #1,d1            ;Byte?
  304.             beq.s        r_byte            ;JA!
  305.             move.w        (a4),(a1)        ;Word-Operand lesen (A4==#operand)
  306.             bra            do_ca            ;Nochmal FPU befragen
  307.             
  308. r_byte:        move.b        (a4),(a1)        ;Byteoperand lesen (A4==#operand)
  309.             bra            do_ca            ;Nochmal FPU befragen
  310.             
  311. w_10:        ;--------  %xx010, evaluate effective address and transfer data
  312.             bsr            calc_add        ;Operandenadresse berechnen
  313.                                         ;A1=Operandenadresse, d1.l=Operandenlänge
  314.             cmpi.w        #2,d1            ;Länge-2
  315.             ble.s        w_bw            ;<=2 -> Wort- oder Byteoperan
  316.             
  317. w_11:        move.l        (a1)+,(a4)        ;Langwort schreiben (a4==#operand)
  318.             subq.l        #4,d1            ;und runterzählen
  319.             bgt.s        w_11            ;>0 -> weiter übertragen
  320.             bra            do_ca            ;Nochmal FPU befragen
  321.             
  322. w_bw:        subq.b        #1,d1            ;Byte?
  323.             beq.s        w_byte            ;JA!
  324.             move.w        (a1),(a4)        ;Word schreiben (A4==#operand)
  325.             bra            do_ca            ;Nochmal FPU befragen
  326.  
  327. w_byte:        move.b        (a1),(a4)        ;Byte schreiben (A4==#operand)
  328.             bra            do_ca            ;Nochmal FPU befragen
  329.             
  330. rw_11:        ;-------- %xxx11, take pre-instruction exception
  331.             bra         cop_error        ;Error-Handler anspringen
  332.             ;(hier sollte man eine genauere Fehleranalyse machen)!
  333.             
  334. spezial:                ;Sprungbefehle etc.
  335.             cmpi.w        #%001000000,d1    ;FScc, FDBcc oder FTRAPcc
  336.             beq.s        s_trap
  337.             cmpi.w        #%010000000,d1    ;Branch mit 16Bit-Offset
  338.             beq            s_br16
  339.             eori.w        #%011000000,d1    ;Branch mit 32Bit-Offset
  340.             beq            s_br32
  341.             bra            cop_error        ;FSAVE/FRESTORE nicht unterstützt
  342.             
  343. s_trap:        move.w        (a0),d0            ;erstes Befehlswort nach D0
  344.             move.w        d0,d1            ;und nach D1 retten
  345.             andi.w        #%111000,d0        ;wichtige Bits ausmaskieren
  346.             cmpi.w        #%001000,d0        ;FDBcc?
  347.             beq.s        s_fdbcc            ;JA -> springen
  348.             cmpi.w        #%111000,d0        ;FTRAP?
  349.             beq            cop_error        ;JA -> Fehler (s.o.)
  350.                                         ;sonst FScc
  351.             move.w        2(a0),condition(a6)    ;Bedingung an FPU schicken
  352.             moveq        #1,d0            ;Operandenlänge=1 (für calc_add)
  353.             bsr            calc_add        ;Operandenlänge berechnen
  354.             
  355. .l_1:        move.w        (a6),d0            ;Response lesen
  356.             btst        #8,d0            ;IA-Bit testen
  357.             beq.s        .l_2            ;==0 -> fertig
  358.             andi.w        #%1100000000000,d0    ;Bit 11 und 12 ausmaskieren
  359.             eori.w        #%1100000000000,d0    ;Beide gesetzt?
  360.             bne.s        .l_1            ;nicht Beide ==1 -> warten
  361.             bra            cop_error        ;sonst Exception aufgetreten
  362.             
  363. .l_2:        btst        #0,d0            ;Antwortbit testen
  364.             sne            (a1)            ;je nach Bit setzen/löschen
  365.             bra            do_ca            ;nochmal FPU befragen
  366.             
  367. s_fdbcc:    move.w        2(a0),condition(a6)    ;Bedingung an FPU schicken
  368.             andi.w        #%111,d1        ;Registernummer maskieren (D1=(A0))
  369.             add.w        d1,d1            ;D1=Nummer*4
  370.             add.w        d1,d1            ;
  371.             lea            (a3,d1.w),a1    ;A1 enthält Adresse des Datenregisters
  372.             move.l        (a1),d1            ;Dn holen
  373.             subq.w        #1,d1            ;Dn=Dn-1
  374.             move.l        d1,(a1)            ;Dn zurückschreiben
  375.             movea.l        a0,a2            ;alten PC nach A2 holen
  376.             addq.l        #2,a0            ;PC 2 weiter (für "nicht springen")
  377.                         
  378. .l_1:        move.w        (a6),d0            ;Response lesen
  379.             btst        #8,d0            ;IA-Bit testen
  380.             beq.s        .l_2            ;==0 -> fertig
  381.             andi.w        #%1100000000000,d0    ;Bit 11 und 12 ausmaskieren
  382.             eori.w        #%1100000000000,d0    ;Beide gesetzt?
  383.             bne.s        .l_1            ;nicht Beide ==1 -> warten
  384.             bra            cop_error        ;sonst Exception aufgetreten
  385.             
  386. .l_2:        btst        #0,d0            ;Antwortbit testen
  387.             bne            do_ca            ;TRUE -> das war's schon
  388.             adda.w        4(a2),a2        ;16Bit Sprungdist. add. (A2=PC)
  389.             addq.w        #1,d1            ;Dn==1 ?
  390.             beq            do_ca            ;JA -> kein Sprung (Schleifenende)
  391.             movea.l        a2,a0            ;sonst "Sprung" (neuen PC laden)
  392.             bra            do_ca            ;nochmal FPU befragen
  393.             
  394. s_br16:        move.w        (a0),condition(a6)    ;Bedingung an FPU schicken
  395.  
  396. .l_1:        move.w        (a6),d0            ;Response lesen
  397.             btst        #8,d0            ;IA-Bit testen
  398.             beq.s        .l_2            ;==0 -> fertig
  399.             andi.w        #%1100000000000,d0    ;Bit 11 und 12 ausmaskieren
  400.             eori.w        #%1100000000000,d0    ;Beide gesetzt?
  401.             bne.s        .l_1            ;nicht Beide ==1 -> warten
  402.             bra            cop_error        ;sonst Exception aufgetreten
  403.             
  404. .l_2:        btst        #0,d0            ;Antwortbit testen
  405.             beq            do_ca            ;FALSE -> das war's schon
  406.             adda.w        2(a0),a0        ;16Bit Sprungdistanz addieren
  407.             subq.l        #2,a0            ;ein Wort zurück (weil später
  408.             ;noch addiert wird und nur 2 addiert werden müßte)
  409.             bra            do_ca            ;nochmal FPU befragen
  410.             
  411. s_br32:        move.w        (a0),condition(a6)    ;Bedingung an FPU schicken
  412.  
  413. .l_1:        move.w        (a6),d0            ;Response lesen
  414.             btst        #8,d0            ;IA-Bit testen
  415.             beq.s        .l_2            ;==0 -> fertig
  416.             andi.w        #%1100000000000,d0    ;Bit 11 und 12 ausmaskieren
  417.             eori.w        #%1100000000000,d0    ;Beide gesetzt?
  418.             bne.s        .l_1            ;nicht Beide ==1 -> warten
  419.             bra            cop_error        ;sonst Exception aufgetreten
  420.             addq.l        #2,a0            ;Befehl ist 3 Worte lang
  421.                                         ;(nun: (A0)=Distanz)            
  422. .l_2:        btst        #0,d0            ;Antwortbit testen
  423.             beq            do_ca            ;TRUE -> das war's schon
  424.             adda.l        (a0),a0            ;32Bit Sprungdistanz addieren
  425.             subq.l        #4,a0            ;ein Wort zurück (weil später
  426.             ;noch addiert wird und nur 2 addiert werden müßte)
  427.             bra            do_ca            ;nochmal FPU befragen
  428.             
  429. cop_error:        ;Error_Handler für einen TRAP der FPU (sehr einfach gehalten).
  430.                 ;Es wird ein Reset der FPU durchgeführt und das aktuelle
  431.                 ;Programm terminiert. Return-Code = 881.
  432.             move.w        #0,control(a6)    ;FPU-Reset (kein clr.w verwenden!)
  433.             move.w        #881,-(sp)        ;Return-Code
  434.             move.w        #$4c,-(sp)        ;Funktion Pterm(881)
  435.             trap        #1                ;des GEMDOS aufrufen
  436.             
  437. calc_add:
  438.     ;Operandenadresse berechnen. A0 muß die Adresse des Line-F-Befehls 
  439.     ;enthalten, D0 im unteren Byte die Operandenlänge. Die zu berechnende
  440.     ;Adresse wird in A1 abgelegt. A0 wird um die Länge der zusätzlichen
  441.     ;Daten erhöht. Zusätzlichen wird in D1 die Länge des Operanden zurück-
  442.     ;gegeben (in Bytes, als Langwort). D2, D3, A2 werden zerstört. Bei den
  443.     ;Adressierungsarten -(An), (An)+ steht in A2 ein Zeiger auf die Stelle,
  444.     ;in der der Inhalt des Adressregisters An steht (wird für FMOVEM 
  445.     ;gebraucht).
  446.     
  447.             clr.l        d1                ;Länge als Langwort löschen
  448.             move.b        d0,d1            ;und Byte einkopieren
  449.             move.w        (a0),d2            ;Erstes Befehlswort nach D2
  450.             move.w        d2,d3            ;und nach D3 retten
  451.             andi.w        #%111000,d3        ;Adressierungsart ausmaskieren
  452.             lsr.w        #1,d3            ;D3=Adressierungsart*4 (Langworte!)
  453.             lea            cs_tab(pc),a1    ;Sprungtabellenadresse nach A1
  454.             move.l        (a1,d3.w),a1    ;Adresse der Routine nach A1
  455.             jmp            (a1)            ;und Routine anspringen
  456.             
  457. c_drd:        ;%000    Data Register Direct:        Dn
  458. c_ard:        ;%001    Address Register Direct:    An
  459.             lea            (a3),a1            ;A1 auf Registerfeld
  460.             andi.w        #%1111,d2        ;Registernummer ausmaskieren
  461.             ;(und ein Bit vom Modus, 0 für Daten-, 1 für Adressregister)
  462.             add.w        d2,d2            ;D2="Registernummer"*4 (+Modusbit!)
  463.             add.w        d2,d2            ;
  464.             addq.w        #4,d2            ;+4 (für Operandenlänge)
  465.             sub.w        d1,d2            ;wahre Länge abziehen
  466.             adda.w        d2,a1            ;Offset auf Registerfeldanfang add.
  467.             rts
  468.             
  469. c_ari:        ;%010    Address Register Indirect:    (An)
  470.             andi.w        #%111,d2        ;Registernummer ausmaskieren
  471.             add.w        d2,d2            ;D2="Registernummer"*4 
  472.             add.w        d2,d2            ;
  473.             move.l        32(a3,d2.w),a1    ;Adresse nach A1
  474.             rts
  475.             
  476. c_arpo:        ;%011    ARI with Postincrement:        (An)+
  477.             andi.w        #%111,d2        ;Registernummer ausmaskieren
  478.             add.w        d2,d2            ;D2="Registernummer"*4 
  479.             add.w        d2,d2            ;
  480.             lea         32(a3,d2.w),a2    ;Adresse Adressregister nach A2
  481.             movea.l        (a2),a1            ;Adresse (Inhalt A.-Reg.) nach A1
  482.             btst        #0,d1            ;D1 ungerade? (Byteoperand)
  483.             bne.s        .l_2            ;JA -> Spezialbehandlung
  484.             
  485. .l_1:        add.l        d1,(a2)            ;Inkrement durchführen
  486.             rts
  487.             
  488. .l_2:        cmpi.w        #4*7,d2            ;ist A7 gemeint?
  489.             bne.s        .l_1            ;NEIN -> normal vorgehen
  490.             addq.l        #2,(a2)            ;sonst (bei Byte) 2 addieren,
  491.             rts                            ;damit Stack gerade bleibt!
  492.             
  493. c_arpr:        ;%100    ARI with Predecrement:        -(An)
  494.             andi.w        #%111,d2        ;Registernummer ausmaskieren
  495.             add.w        d2,d2            ;D2="Registernummer"*4 
  496.             add.w        d2,d2            ;
  497.             lea         32(a3,d2.w),a2    ;Adresse Adressregister nach A2
  498.             btst        #0,d1            ;D1 ungerade? (Byteoperand)
  499.             bne.s        .l_2            ;JA -> Spezialbehandlung
  500.             
  501. .l_1:        sub.l        d1,(a2)            ;Inkrement durchführen
  502.             movea.l        (a2),a1            ;Adresse (Inhalt des A.-Reg.) nach A1
  503.             rts
  504.             
  505. .l_2:        cmpi.w        #4*7,d2            ;ist A7 gemeint?
  506.             bne.s        .l_1            ;NEIN -> normal vorgehen
  507.             subq.l        #2,(a2)            ;sonst (bei Byte) 2 subtrahieren,
  508.                                            ;damit Stack gerade bleibt!
  509.             movea.l        (a2),a1            ;Adresse (Inhalt A.-Reg.) nach A1
  510.             rts
  511.             
  512. c_ar16:        ;%101    ARI with Displacement:        d16(An)
  513.             andi.w        #%111,d2        ;Registernummer ausmaskieren
  514.             add.w        d2,d2            ;D2="Registernummer"*4 
  515.             add.w        d2,d2
  516.             movea.l        32(a3,d2.w),a1    ;Adresse nach A1
  517.             move.w        4(a0),d2        ;3. Befehlswort nach D2 (Offset)
  518.             adda.w        d2,a1            ;Offset auf Adresse addieren
  519.             addq.l        #2,a0            ;A0 ein Wort (d16) weiter
  520.             rts
  521.             
  522. c_ar08:        ;%110    ARI with Index:                d8(An,Xn)
  523.             andi.w        #%111,d2        ;Registernummer ausmaskieren
  524.             add.w        d2,d2            ;D2="Registernummer"*4 
  525.             add.w        d2,d2            ;
  526.             movea.l        32(a3,d2.w),a1    ;Adresse nach A1
  527.             move.w        4(a0),d2        ;3. Befehlswort nach D2 (Offset)
  528.             move.w        d2,d3            ;und nach D3
  529.             andi.w        #$ff,d3            ;Byte ausmaskieren (Byte-Offset)
  530.             adda.w        d3,a1            ;Offset auf Adresse addieren
  531.             btst        #11,d2            ;1=long, 0=word
  532.             bne.s        c_ar81
  533.  
  534.             rol.w        #6, d2            ;Nummer von Dn und Modusbit maskieren
  535.             andi.w        #%111100,d2        ;d2=Registernummer*4 (+Modusbit)
  536.             adda.w        2(a3,d2.w),a1    ;16Bit-Index auf A1 addieren
  537.             addq.l        #2,a0            ;A0 ein Wort (Kram & d8) weiter
  538.             rts
  539.             
  540. c_ar81:
  541.             rol.w        #6, d2            ;Nummer von Dn und Modusbit maskieren
  542.             andi.w        #%111100,d2        ;d2=Registernummer*4 (+Modusbit)
  543.             adda.l        (a3,d2.w),a1    ;32Bit-Index auf A1 addieren
  544.             addq.l        #2,a0            ;A0 ein Wort (Kram & d8) weiter
  545.             rts
  546.             
  547. c_pc:        ;%111    absolut short/long, PC-Relativ (ohne/mit Index)
  548.             ;oder direkt
  549.             btst        #2,d2            ;Immidiate?
  550.             bne.s        immi            ;!=0 -> JA
  551.             btst        #1,d2            ;PC-Relativ?
  552.             bne.s        pc_rel            ;!=0 -> JA
  553.             btst        #0,d2            ;Long?
  554.             bne.s        c_long            ;!=0 -> JA
  555.                                         ;sonst Short
  556.             move.w        4(a0),d2        ;Wortadresse holen,
  557.             ext.l        d2                ;Auf Langwort erweitern
  558.             movea.l        d2,a1            ;und als Operandenadresse merken
  559.             addq.l        #2,a0            ;A0 ein Wort (Short-Addr.) weiter
  560.             rts
  561.  
  562. c_long:        movea.l        4(a0),a1        ;Langwortadresse holen
  563.             addq.l        #4,a0            ;A0 zwei Worte (Long-Addr.) weiter
  564.             rts
  565.             
  566. immi:        movea.l        a0,a1           ;Langwortadresse holen
  567.             addq.l        #4,a1            ;Beide Befehlsworte überspringen
  568.             adda.l        d1,a0            ;A0 über Operand hinwegsetzen
  569.             rts
  570.             
  571. pc_rel:        btst        #0,d2            ;mit Index?
  572.             bne.s        pc_idx            ;!=0 -> JA
  573.             movea.l        a0,a1            ;PC nach A1
  574.             adda.w        4(a0),a1        ;Offset addieren
  575.             addq.l        #4,a1            ;+4 für Länge des FPU-Befehls
  576.             addq.l        #2,a0            ;A0 zwei (16Bit-Offset) weiter
  577.             rts
  578.             
  579. pc_idx:        move.l        a0,a1            ;PC nach A1
  580.             clr.w        d2                ;oberes Byte löschen
  581.             move.b        5(a0),d2        ;Offset nach D2
  582.             adda.w        d2,a1            ;und addieren
  583.             addq.l        #4,a1            ;+4 für Länge des FPU-Befehls
  584.             move.b        4(a0),d2            ;D2=Registernummer*16 und Modusbit
  585.                                         ;(high-byte ist noch 0)
  586.             btst        #3,d2            ;Long-Bit testen
  587.             bne.s        pc_i_l            ;!=0 -> Long-Index
  588.             andi.w        #%111110000,d2    ;Restinformation ausblenden
  589.             lsr.w        #2,d2            ;D2=Registernummer*4 und Modusbit
  590.             adda.w        2(a3,d2.w),a1    ;Word-Index addieren
  591.             addq.l        #2,a0            ;A0 zwei (16Bit-Offset) weiter
  592.             rts
  593.             
  594. pc_i_l:        andi.w        #%111110000,d2    ;Restinformation ausblenden
  595.             lsr.w        #2,d2            ;D2=Registernummer*4 und Modusbit
  596.             adda.l        (a3,d2.w),a1    ;Long-Index addieren
  597.             addq.l        #2,a0            ;A0 zwei (16Bit-Offset) weiter
  598.             rts            ;ENDE von calc_add ***
  599.  
  600. ;-------------- installation-handler ---------------------------------
  601.  
  602. Install:    movea.l        lineF.w,a0         ;Vektor nach A0
  603.             move.l        (-12.b,a0),d0    ;falls "XBRA" -> jetzt in D0
  604.             move.l        (-8.b,a0),d1    ;falls "LFED" -> jetzt in D1
  605.             rts 
  606.             
  607. Terminate_1:
  608.             pea            failure_1(pc)    ;Fehlermeldung
  609.             bra            Ende
  610.  
  611. Terminate_2:
  612.             pea            failure_2(pc)    ;Fehlermeldung
  613.             bra            Ende
  614.  
  615. Terminate_3:
  616.             pea            failure_3(pc)    ;Fehlermeldung
  617.  
  618. Ende:
  619.             move.w        #9,-(sp)        ;Cconws
  620.             trap        #1                ;GEMDOS
  621.             move.w        #0,-(sp)        ;richtig terminieren
  622.             trap        #1                ;mit Pterm(0)/GEMDOS
  623.                         
  624. ;-------------- data-segment -----------------------------------------
  625.             
  626.             .DATA
  627.             .EVEN
  628.             
  629. cs_tab:        .dc.l    c_drd,c_ard,c_ari,c_arpo    ;Sprungtabelle für
  630.             .dc.l    c_arpr,c_ar16,c_ar08,c_pc    ;Adressierungsarten
  631.  
  632. titel:      .dc.b     10, 13, 27, 112    ;CR/invers on
  633.             .ASCII    "  Line-F-Emulation-Driver LFED  ", 10, 13 
  634.             .ASCII    "         Version 2.00           ", 10, 13
  635.             .dc.b    27, 113         ;invers off
  636.             .ASCII  "    (c) by Smart Systems '92   ", 10, 13
  637.             .ASCII  "   Michael Hauschild / Seelze  ", 10, 13
  638.             .ASCII  "     Phone: 05137 / 9 20 09    ", 10, 13, 0
  639.  
  640. failure_1:    .dc.b    10, 13    ;CR
  641.             .ASCIIZ    " LFED already installed! "
  642.             .dc.b    10, 13    ;CR
  643.  
  644. failure_2:    .dc.b    10, 13    ;CR
  645.             .ASCIIZ    " No _FPU cookie installed! "
  646.             .dc.b    10, 13    ;CR
  647.  
  648. failure_3:    .dc.b    10, 13    ;CR
  649.             .ASCIIZ    " No coprocessor available! "
  650.             .dc.b    10, 13    ;CR
  651.  
  652. ;-------------- blockstorage-segment ---------------------------------
  653.             
  654.             .BSS
  655.             .EVEN
  656.  
  657. dregs:        .ds.l    (8+7)    ;Platz für Register (D0-D7/A0-A6)
  658. rusp:        .ds.l    1        ;Platz für USP (A7)
  659.  
  660. ;-------------- end of code ------------------------------------------
  661.             .END
  662.