Mercurial > hg > Members > kono > os9 > sbc09
diff examples/uslash.asm @ 57:2088fd998865
sbc09 directry clean up
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 23 Jul 2018 16:07:12 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/uslash.asm Mon Jul 23 16:07:12 2018 +0900 @@ -0,0 +1,145 @@ + ; 6809 32/16 divison for a forth environment + ; 2012-06-20, 2014-07-01 J.E. Klasek j+forth@klasek.at + ; + ; There are two implementations: + ; TALBOT just for analysis, not really used here. + ; EFORTH advanced and optimized version for ef09 + ; + ; EFORTH version's special cases: + ; overflow: quotient = $FFFF, remainder = divisor + ; underflow: quotient = $0000, remainder = dividend low + ; division by zero: quotient = $FFFF, remainder = $0000 + + org $100 + lds #$100 + ldu #$8000 + +; Testvalues: +; +; DIVH DIVL DVSR QUOT REM comment +; +; 0100 0000 FFFF 0100 0100 maximum divisor +; 0000 0001 8000 0000 0001 underflow (REM = DIVL) +; 0000 5800 3000 0001 1800 normal divsion +; 5800 0000 3000 FFFF 3000 overflow +; 0000 0001 0000 FFFF 0000 overflow (division by zero) +; + +DIVH EQU $0000 +DIVL EQU $5800 +DVSR EQU $3000 + + bra EFORTH ; comment out to try TALBOT's version + + ; ------------------------------------ + ; Version from Talbot System FIG Forth + ; ------------------------------------ + +TALBOT: + + ; sample parameters on forth parameter stack (U) ... + ldd #DIVL ; dividend low word + pshu d + ldd #DIVH ; dividend high word + pshu d + ldd #DVSR ; divisor + pshu d + +USLASH: ldd 2,u ; dividend swap H/L word + ldx 4,u + stx 2,u + std 4,u + asl 3,u ; initial shift of L word + rol 2,u + ldx #$10 +USL1: rol 5,u ; shift H word + rol 4,u + ldd 4,u + subd ,u ; does divisor fit? + andcc #$fe ; clc - clear carry flag + bmi USL2 + std 4,u ; fits -> quotient = 1 + orcc #$01 ; sec - set carry flag +USL2: rol 3,u ; L word/quotient + rol 2,u + leax -1,x + bne USL1 + leau 2,u ; drop divisor from parameter stack + + ; into registers for simulator ... + + ldx ,u ; quotient on TOS + ldd 2,u ; remainder on 2nd + +realexit: + sync + + + + + ; ------------------------------------ + ; Version from J.E. Klasek, replacing + ; high-level variant in eFORTH. + ; ------------------------------------ + +EFORTH: + ; sample parameters on forth parameter stack (S) ... + ldd #DIVL ; dividend low word + pshs d + ldd #DIVH ; dividend high word + pshs d + ldd #DVSR ; divisor + pshs d + +; U/ ( udl udh un -- ur uq ) +; Unsigned divide of a double by a single. Return mod and quotient. +; +; Special cases: +; 1. overflow: quotient overflow if dividend is to great (remainder = divisor), +; remainder is set to $FFFF -> special handling. +; This is checked also right before the main loop. +; 2. underflow: divisor does not fit into dividend -> remainder +; get the value of the dividend -> automatically covered. + +USLASH2: + ldx #16 + ldd 2,s ; udh + cmpd ,s ; dividend to great? + bhs UMMODOV ; quotient overflow! + asl 5,s ; udl low + rol 4,s ; udl high + +UMMOD1: rolb ; got one bit from udl + rola + bcs UMMOD2 ; bit 16 means always greater as divisor + cmpd ,s ; divide by un + bhs UMMOD2 ; higher or same as divisor? + andcc #$fe ; clc - clear carry flag + bra UMMOD3 +UMMOD2: subd ,s + orcc #$01 ; sec - set carry flag +UMMOD3: rol 5,s ; udl, quotient shifted in + rol 4,s + leax -1,x + bne UMMOD1 + + ldx 4,s ; quotient + cmpd ,s ; remainder >= divisor -> overflow + blo UMMOD4 +UMMODOV: + ldd ,s ; remainder set to divisor + ldx #$FFFF ; quotient = FFFF (-1) marks overflow + ; (case 1) +UMMOD4: + leas 2,s ; un (divisor thrown away) + stx ,s ; quotient to TOS + std 2,s ; remainder 2nd + + bra realexit + + ; not reached + pulu pc ; eFORTH NEXT + +enddata + + end