
; Routinen für Mathematik










;****************************************************************************
; 16-Bit-Arithmetik.  Alle Werte werden als 32-Bit-Werte gestackt.

      IFD   MulDiv16

      XDEF  _IDivS,_IDivU,_IMulS,_IMulU,_sdiv,_smuls,_umuls



; IDivS (arg1, arg2)
; Teile arg1 (32 Bit) durch arg2 (16 Bit) vorzeichenbehaftet.
; Rückgabe: 32-Bit-Ergebnis vorzeichenbehaftet.

_sdiv
_IDivS
      move.l   4(SP),d0
      divs     8+2(SP),d0
      ext.l    d0
      rts



; IDivU (arg1, arg2)
; Teile arg1 (32 Bit) durch arg2 (16 Bit) vorzeichenlos.
; Rückgabe: 32-Bit-Ergebnis vorzeichenlos.

_IDivU
      move.l   4(SP),d0
      divu     8+2(SP),d0
      swap     d0
      clr.w    d0
      swap     d0
      rts



; IMulS (arg1, arg2)
; Multipliziere arg1 (16 Bit) mit arg2 (16 Bit) vorzeichenbehaftet.
; Rückgabe: 32-Bit-Ergebnis vorzeichenbehaftet.

_smuls
_IMulS
      move     4+2(SP),d0
      muls     8+2(SP),d0
      rts



; IMulU (arg1, arg2)
; Multipliziere arg1 (16 Bit) mit arg2 (16 Bit) vorzeichenlos.
; Rückgabe: 32-Bit-Ergebnis vorzeichenlos.

_umuls
_IMulU
      move     4+2(SP),d0
      mulu     8+2(SP),d0
      rts

      ENDC










;****************************************************************************
; 32-Bit-Arithmetik für Assembler-Anwendung.  Das erste Argument wird in D0
; übergeben, das zweite in D1.  Rückgabe in D0.

      IFD   MulDiv32

      XDEF  lmult,ulmult
      XDEF  ldivt,uldivt
      XDEF  lmodt,ulmodt





lmult
ulmult
      ; D0 = D0 * D1  vorzeichenlos oder vorzeichenbehaftet.
      movem.l  d1-d3,-(SP)
      move.l   d0,d2
      swap     d2
      move.l   d1,d3
      swap     d3
      mulu     d1,d2                ; Kreuzprodukt 1
      mulu     d0,d3                ; Kreuzprodukt 2
      mulu     d1,d0                ; unteres Langwort
      add.l    d3,d2                ; addiere Kreuzprodukte
      swap     d2                   ; verwende nur unteres Wort
      clr.w    d2                   
      add.l    d2,d0                ; unteres Langwort + Kreuzprodukt-Summe
      movem.l  (SP)+,d1-d3
      rts





ldivt
      ; D0 = D0 / D1  vorzeichenbehaftet.
      ; Ergebnis negativ, wenn ENTWEDER Dividend ODER Divisor negativ.
      movem.l  d1-d4,-(SP)
      move.l   d0,d4
      bpl.s    1$
      neg.l    d0
1$    eor.l    d1,d4                ; ergibt Vorzeichenbit in Bit 31
      tst.l    d1
      bpl.s    2$
      neg.l    d1
2$    bsr.s    Divide
      tst.l    d4                   ; Ergebnis negativ ?
      bpl.s    3$
      neg.l    d0                   ; ja
3$    movem.l  (SP)+,d1-d4
      rts





lmodt
      ; D0 = D0 mod D1  vorzeichenbehaftet.
      ; Ergebnis negativ, wenn Dividend negativ.
      movem.l  d1-d4,-(SP)
      move.l   d0,d4
      bpl.s    1$
      neg.l    d0
1$    tst.l    d1
      bpl.s    2$
      neg.l    d1
2$    bsr.s    Divide
      move.l   d1,d0
      tst.l    d4                   ; Ergebnis negativ ?
      bpl.s    3$
      neg.l    d0                   ; ja
3$    movem.l  (SP)+,d1-d4
      rts





uldivt
      ; D0 = D0 / D1  vorzeichenlos.  Zusätzlich: Modulo in D1.
      movem.l  d2-d3,-(SP)
      bsr.s    Divide
      movem.l  (SP)+,d2-d3
      rts





ulmodt
      ; D0 = D0 mod D1  vorzeichenlos.  Zusätzlich: Quotient in D1.
      movem.l  d2-d3,-(SP)
      bsr.s    Divide
      exg      d1,d0                ; Modulo
      movem.l  (SP)+,d2-d3
      rts





Divide
      ; Hilfsroutine.  D0 = D0 / D1  vorzeichenlos.  D1 enthält den Modulo.
      move.l   d1,d2                ; Divisor nach D2
      swap     d1
      tst.w    d1
      bne.s    1$                   ; wenn Divisor größer $FFFF
      move.l   d0,d3
      clr.w    d0
      swap     d0
      divu     d2,d0
      move.l   d0,d1
      swap     d0                   ; oberer Quotient nach oben
      move.w   d3,d1
      divu     d2,d1
      move.w   d1,d0                ; ergibt 32-Bit-Quotient
      clr.w    d1
      swap     d1                   ; Modulo
      rts

      ; Divisor > $FFFF.  Die Division ergibt einen 16-Bit-Wert.
1$    move.l   d0,d1
      swap     d0                   ; beginne schon mit 16-Bit-Verschiebung !
      clr.w    d0
      clr.w    d1
      swap     d1
      moveq    #16-1,d3             ; schiebe nur noch 16 mal für den Rest
3$    add.l    d0,d0                ; ADD ist schneller als LSL #1 !
      addx.l   d1,d1                ; Übertrag berücksichtigen
      cmp.l    d1,d2                ; kann schon eine Eins ins Ergebnis ?
      bhi.s    2$
      addq     #1,d0                ; ja, setze die Eins
      sub.l    d2,d1                ; und kürze den Modulo
2$    dbra     d3,3$
      rts





      ENDC










      END

