• R/O
  • HTTP
  • SSH
  • HTTPS

fig-forth-68000: Commit

Source code for fig-forth-68000


Commit MetaInfo

Revision25e35ce9cb7c6157bf074f21ccde438836fd4bfb (tree)
Time2023-08-13 01:58:56
AuthorJoel Matthew Rees <joel.rees@gmai...>
CommiterJoel Matthew Rees

Log Message

buggy but improving U/ , fixed doc for M/MOD

Change Summary

Incremental Difference

--- a/FIG68K.S
+++ b/FIG68K.S
@@ -4218,8 +4218,8 @@ SSLASH DC.L DOCOL,SSMOD,SWAP,DROP
42184218 * ======>> 165 <<
42194219 * ( ud1 u1 --- u2 ud2 )
42204220 * U/ with an (unsigned) double quotient.
4221-* Guaranteed not to lose significant bits in 32 bit / 16 bit bit integer math,
4222-* if you are prepared to deal with the extra 16 bits of result.
4221+* Guaranteed not to lose significant bits in 64 bit / 32 bit bit integer math,
4222+* if you are prepared to deal with the extra 32 bits of result.
42234223 EVEN
42244224 DC.B $85
42254225 DC.B 'M/MO' ; 'M/MOD'
--- a/FIG68KFL.S
+++ b/FIG68KFL.S
@@ -1193,6 +1193,68 @@ USTAR DC.L *+NATWID
11931193 *
11941194 * ######>> screen 24 <<
11951195 * ======>> 19 <<
1196+* ( ud_dividend u_divisor --- ud_remainder ud_quotient )
1197+* 64 bit dividend, 16 bit divisor (in 32 bits) for optimizations.
1198+* Guaranteed not to lose significant bits in 64 bit / 16 bit bit integer math,
1199+* if you are prepared to deal with the extra 32 bits of result.
1200+* Avoids divide-by-zero exception,
1201+** returning the full 64 bit dividend as the remainder
1202+** and saturated quotient (-1 in 64 bits) as quotient.
1203+* For non-zero divisor, only the low 32 bits of remainder are valid.
1204+ DC.B $87
1205+ DC.B 'M/MOD1' ; 'M/MOD16'
1206+ DC.B '6'|$80
1207+ DC.L USTAR-3-NATWID
1208+MSLM16 DC.L *+NATWID
1209+ MOVE.L (PSP)+,D3 ; get divisor
1210+MSLMWT TST.L D3 ; divisor 0?
1211+ BNE.S MSLMW ; dodge divide-by-zero exception
1212+ MOVE.L #-1,-(PSP) ; saturated quotient:
1213+ MOVE.L #-1,-(PSP) ; 64 bits of -1
1214+ RTS ; low word of dividend is remainder, mimicking bit divide.
1215+MSLMW:
1216+* CMP.L #$10000,D3 ; 16-bit divisor? (dividend on stack, divisor in D3)
1217+* BLO.S MSLAMW ; yes
1218+* MOVE.L D3,-(PSP) ; no, bail to bit divide
1219+* BRA.S BSLASH+NATWID
1220+MSLAMW AND.L #$FFFF,D3 ; just to be safe
1221+ CLR.L D0 ; Clear working register
1222+ CLR.L D1 ; Clear result registers
1223+ CLR.L D2
1224+ TST.W (PSP) ; short-circuit high zeroes
1225+ BNE.S MSLMWA
1226+ TST.W NATWID/2(PSP)
1227+ BNE.S MSLMWB
1228+ TST.W NATWID(PSP)
1229+ BNE.S MSLMWC
1230+ TST.W NATWID*3/2(PSP)
1231+ BNE.S MSLMWD
1232+ CLR.L -(PSP) ; remainder is already clear, 0 quotient
1233+ CLR.L -(PSP)
1234+ RTS
1235+MSLMWA MOVE.W (PSP),D0 ; highest 16-bit word
1236+ DIVU.W D3,D0 ;
1237+ MOVE.W D0,D1 ; quotient part
1238+ SWAP.W D1 ; Shift it up.
1239+MSLMWB MOVE.W NATWID/2(PSP),D0 ; 2nd highest
1240+ DIVU.W D3,D0 ; remainder from previous in high 16-bits
1241+ MOVE.W D0,D1 ; move column in
1242+MSLMWC MOVE.W NATWID(PSP),D0 ; 3rd highest 16-bit
1243+ DIVU.W D3,D0 ; remainder from previous in high 16-bits
1244+ MOVE.W D0,D2
1245+ SWAP D2 ; Shift it up
1246+MSLMWD MOVE.W NATWID*3/2(PSP),D0 ; lowest 16-bit
1247+ DIVU.W D3,D0 ; remainder from previous in high 16-bits
1248+ MOVE.w D0,D2 ; result in place
1249+ CLR.W D0 ; prepare remainder
1250+ SWAP D0 ; final remainder is 16-bit
1251+ MOVE.L D0,NATWID*2(PSP)
1252+ MOVE.L D2,-(PSP) ; low word first
1253+ MOVE.L D1,-(PSP) ; high word
1254+ RTS
1255+*
1256+
1257+*
11961258 * ( ud u --- uremainder uquotient )
11971259 * Divides the top unsigned integer
11981260 * into the second and third words on the stack
@@ -1238,82 +1300,91 @@ USTAR DC.L *+NATWID
12381300 *
12391301 * For now, for the fig model --
12401302
1241-
1242-* ( uddividend udivisor --- uremainder udquotient )
1243-* ( uddividend udivisor --- udremainder udquotient ) so it can return full dividend on divide-by-zero?
1303+* ( ud_dividend u_divisor --- u_remainder u_quotient ) so it can return full dividend on divide-by-zero?
12441304 * Need to work out what bit divide is able to return.
12451305 * Divides the top unsigned integer
12461306 * into the second and third words on the stack
12471307 * as a single unsigned double integer,
12481308 * leaving the remainder and double quotient (quotient on top).
1249-
1309+*
12501310 * popped divisor is messing things up
12511311
12521312 EVEN
12531313 DC.B 0
1254- DC.B $84
1255- DC.B 'U32' ; 'U32/'
1314+ DC.B $82
1315+ DC.B 'U' ; 'U/'
12561316 DC.B '/'|$80
1257- DC.L USTAR-3-NATWID
1258-U32SL:
1317+ DC.L MSLM16-8-NATWID
1318+USLASH:
12591319 DC.L *+NATWID
1260- MOVE.L (PSP),D4 ; get divisor
1261- LEA -NATWID(PSP),PSP ; room for two doubles
1262- TST.L D4 ; divisor 0?
1263- BNE.S U64SLB ; dodge divide-by-zero exception
1264- MOVE.L #-1,NATWID(PSP) ; saturated quotient low word
1265- MOVE.L #-1,(PSP) ; saturated quotient high word
1266- RTS ; full dividend is remainder
1267-*
1268-U32SLB CMP.L #$10000,D4 ; 16-bit divisor?
1269- BLO.S U64SLW ; no
1270- MOVE.L D4,-(PSP) ; bail for now
1271- BRA.S BSLASH
1272-U32SLW CLR.L D0 ; working registers
1273- CLR.L D1
1274- CLR.L D2
1275- TST.W (PSP) ; short-circuit high zeroes
1276- BNE.S U64W64
1277- TST.W NATWID/2(PSP)
1278- BNE.S U64W48
1279- TST.W NATWID(PSP)
1280- BNE.S U64W32
1281- TST.W NATWID*3/2(PSP)
1282- BNE.S U64W16
1283- CLR.L (PSP) ; 0 quotient,
1284- CLR.L NATWID(PSP) ; 0 remainder
1285- RET
1286-U64W64 MOVE.W (PSP),D0 ; highest 16-bit word
1287- DIVU.W D4,D0 ;
1288- MOVE.W D0,D1 ; quotient part
1289- SWAP.W D1
1290-U64W48 MOVE.W NATWID/2(PSP),D0 ; 2nd highest
1291- DIVU.W D4,D0 ; remainder from previous in high 16-bits
1292- MOVE.W D0,D1 ; move column in
1293-U64W32 MOVE.W NATWID(PSP),D0 ; 3rd highest 16-bit
1294- DIVU.W D4,D0 ; remainder from previous in high 16-bits
1295- MOVE.W D0,D2
1296- SWAP D2
1297-U64W16 MOVE.S NATWID*3/2(PSP),D0 ; lowest 16-bit
1298- DIVU.W D4,D0 ; remainder from precious in high 16-bits
1299- MOVE.w D0,D2
1300- CLR.W D0
1301- SWAP D0 ; final remainder
1302- MOVE.L D0,NATWID*2(PSP)
1303- MOVE.L D1,(PSP)
1304- MOVE.L D2,NATWID(PSP)
1320+ MOVE.L (PSP)+,D3 ; get divisor
1321+* TST.L D3 ; divisor 0?
1322+* BNE.S USLA16 ; dodge divide-by-zero exception
1323+* MOVE.L #-1,(PSP) ; saturated quotient
1324+* RTS ; low word of dividend is remainder, mimicking bit divide.
1325+*
1326+USLA16 CMP.L #$10000,D3 ; 16-bit divisor?
1327+ BLO.S USLAW ; yes
1328+ MOVE.L D3,-(PSP) ; no, put divisor back and bail to bit divide
1329+ BRA.S BSLASH+NATWID
1330+USLAW:
1331+ BSR.W MSLMWT
1332+ MOVEM.L (PSP)+,D0/D1/D2 ; drop extra/high word of both remainder and quotient
1333+ MOVE.L D1,-(PSP)
13051334 RTS
1306-
1335+*
1336+
1337+* CLR.L D0 ; working register
1338+* MOVE.W (PSP),D0 ; Start from high word
1339+* CMP.L D3,D0 ; Anything to divide?
1340+* BLO.S USLAW3
1341+* DIVU.W D3,D0
1342+*
1343+*USLAW3 SWAP D0 ; Shift the column
1344+* MOVE.W NATWID/2(PSP),D0 ; get the next column
1345+* CMP.L D3,D0 ; Anything to divide?
1346+* BLO.S USLAW2
1347+* DIVU.W D3,D0
1348+*
1349+*USLAW2 SWAP D0 ; Shift the column
1350+* MOVE.W NATWID(PSP),D0 ; get the next column
1351+* CMP.L D3,D0 ; Anything to divide?
1352+* BLO.S USLAW1
1353+* DIVU.W D3,D0
1354+*
1355+*USLAW1 SWAP D0 ; Shift the column
1356+* MOVE.W NATWID*3/2(PSP),D0 ; get the next column
1357+* CMP.L D3,D0 ; Anything to divide?
1358+* BLO.S USLAW0
1359+* DIVU.W D3,D0
1360+
13071361
13081362 *
1363+* ( ud_dividend u_divisor --- u_remainder u_quotient )
1364+* Divides the top unsigned integer
1365+* into the second and third words on the stack
1366+* as a single unsigned double integer,
1367+* leaving the remainder and quotient (quotient on top)
1368+* as unsigned integers.
1369+*
1370+* The reason for this apparent oddity is that U/ is essentially the inverse of U* :
1371+* in other words,
1372+* U/ can only divide without overflow if the dividend is the result of
1373+* the divisor multiplied by the quotient using U* ,
1374+* with an added constant less than the divisor (the remainder portion).
1375+*
1376+* Keep in mind that, with arbitrary double-word dividends,
1377+* small divisors are likely to leave high-order bits chopped off the top.
1378+*
1379+* Division by zero leaves a saturated quotient,
1380+* with the dividend returned as the remainder (except for chopping off the high word).
13091381 EVEN
13101382 DC.B 0
13111383 DC.B $82
13121384 DC.B 'B' ; 'B/'
13131385 DC.B '/'|$80
1314- DC.L U64SL-5-NATWID
1386+ DC.L USLASH-3-NATWID
13151387 * Using the bit divide to reduce testing burden, working in registers.
1316-USLASH:
13171388 BSLASH:
13181389 DC.L *+NATWID
13191390 MOVEM.L (PSP),D0/D1/D2 ; D1:D2 by D0 (40~ ignore attempts to count cycles)
@@ -1339,7 +1410,7 @@ BSLMOR
13391410 ROXL.L #1,D1 ; remainder (8~)
13401411 BCC.S BSLDIV (8/10~)
13411412 BRA.S BSLSUB (10~) (~90*32=~2880+entry+exit, about 800 μS at 4 MHz)
1342-
1413+*
13431414 * The following is not yet functional, only here to help me remember:
13441415 * cUSLASH DC.L *+NATWID
13451416 * MOVE.W (PSP)+,D0
@@ -1405,7 +1476,6 @@ BSLMOR
14051476 DC.B $83
14061477 DC.B 'AN' ; 'AND'
14071478 DC.B "D"|$80
1408-* DC.L I-2-NATWID ; ***** debug link *****
14091479 DC.L BSLASH-3-NATWID ; correct link
14101480 AND DC.L *+NATWID
14111481 MOVE.L (PSP)+,D0
@@ -4458,10 +4528,11 @@ SSLASH DC.L DOCOL,SSMOD,SWAP,DROP
44584528 DC.L SEMIS
44594529 *
44604530 * ======>> 165 <<
4531+*
44614532 * ( ud1 u1 --- u2 ud2 )
44624533 * U/ with an (unsigned) double quotient.
4463-* Guaranteed not to lose significant bits in 32 bit / 16 bit bit integer math,
4464-* if you are prepared to deal with the extra 16 bits of result.
4534+* Guaranteed not to lose significant bits in 64 bit / 32 bit bit integer math,
4535+* if you are prepared to deal with the extra 32 bits of result.
44654536 EVEN
44664537 DC.B $85
44674538 DC.B 'M/MO' ; 'M/MOD'
@@ -4471,6 +4542,45 @@ MSMOD DC.L DOCOL,TOR,ZERO,R,USLASH
44714542 DC.L FROMR,SWAP,TOR,USLASH,FROMR
44724543 DC.L SEMIS
44734544 *
4545+* Not sure what to do with this
4546+** ( ud_dividend u_divisor --- u_remainder ud_quotient )
4547+** U/ with an (unsigned) double quotient.
4548+** Guaranteed not to lose significant bits in 64 bit / 32 bit bit integer math,
4549+** if you are prepared to deal with the extra 32 bits of result.
4550+** Uses bit division.
4551+* EVEN
4552+* DC.B 0
4553+* DC.B $82
4554+* DC.B 'B' ; 'B/'
4555+* DC.B '/'|$80
4556+* DC.L USLASH-3-NATWID
4557+** Using the bit divide to reduce testing burden, working in registers.
4558+*BSLASH:
4559+* DC.L *+NATWID
4560+* MOVEM.L (PSP),D0/D1/D2 ; D1:D2 by D0 (40~ ignore attempts to count cycles)
4561+*BSLENT:
4562+* MOVE.W #32,D3 ; bit ct for DBcc (8~)
4563+*BSLDIV:
4564+* CMP.L D0,D1 ; divisor (6~)
4565+* BHS.S BSLSUB (8/10~)
4566+* AND #~F_EXT,CCR ; X-carry clear (20~)
4567+* BRA.S BSLBIT (10~)
4568+*BSLSUB:
4569+* SUB.L D0,D1 (6~)
4570+* OR #F_EXT,CCR ; quotient, (X-carry set) (20~)
4571+*BSLBIT:
4572+* ROXL.L #1,D2 ; save it (8~)
4573+* DBF D3,BSLMOR ; more bits? Don't mess with CCR ((12/14)/10~)
4574+*BSLR:
4575+* LEA NATWID(PSP),PSP (8~)
4576+* MOVE.L D1,NATWID(PSP) (16~)
4577+* MOVE.L D2,(PSP) (12~)
4578+* RTS
4579+*BSLMOR
4580+* ROXL.L #1,D1 ; remainder (8~)
4581+* BCC.S BSLDIV (8/10~)
4582+* BRA.S BSLSUB (10~) (~90*32=~2880+entry+exit, about 800 μS at 4 MHz)
4583+*
44744584 * ======>> 166 <<
44754585 * ( n>=0 --- n )
44764586 * ( n<0 --- -n )
--- a/FIG68KRT.S
+++ b/FIG68KRT.S
@@ -4243,8 +4243,8 @@ SSLASH DC.L DOCOL,SSMOD,SWAP,DROP
42434243 * ======>> 165 <<
42444244 * ( ud1 u1 --- u2 ud2 )
42454245 * U/ with an (unsigned) double quotient.
4246-* Guaranteed not to lose significant bits in 32 bit / 16 bit bit integer math,
4247-* if you are prepared to deal with the extra 16 bits of result.
4246+* Guaranteed not to lose significant bits in 64 bit / 32 bit bit integer math,
4247+* if you are prepared to deal with the extra 32 bits of result.
42484248 EVEN
42494249 DC.B $85
42504250 DC.B 'M/MO' ; 'M/MOD'
Show on old repository browser