Skip to content

Instantly share code, notes, and snippets.

@non
Last active October 20, 2022 03:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save non/00e0a45297a7f67a0fbfe149aba29abf to your computer and use it in GitHub Desktop.
Save non/00e0a45297a7f67a0fbfe149aba29abf to your computer and use it in GitHub Desktop.
tested implementation of signed division for 16-bit numbers in uxntal
( main method for testing )
|0100
#1234 #0001 ;testcases JSR2
#0000 #0431 ;testcases JSR2
#0039 #0003 ;testcases JSR2
#9321 #ffff ;testcases JSR2
#ffff #9321 ;testcases JSR2
#ffff #ffff ;testcases JSR2
#7654 #8000 ;testcases JSR2
#8000 #0001 ;testcases JSR2
#8000 #0012 ;testcases JSR2
#8000 #8000 ;testcase JSR2 #0a #18 DEO
BRK
( run tests for all of: x/y, -x/y, x/-y, -x/-y )
@testcases ( x* y* -> )
OVR2 OVR2 ;testcase JSR2
OVR2 #ffff MUL2 OVR2 ;testcase JSR2
OVR2 OVR2 #ffff MUL2 ;testcase JSR2
#ffff MUL2 SWP2 #ffff MUL2 SWP2 ;testcase JSR2
#0a #18 DEO JMP2r
( test x/y )
( print out the result and the absolute value of the result )
@testcase ( x* y* -> )
OVR2 ;print/short JSR2
#20 #18 DEO LIT "/ #18 DEO #20 #18 DEO
DUP2 ;print/short JSR2
#20 #18 DEO LIT "= #18 DEO #20 #18 DEO
;s16-div JSR2
DUP2 ;print/short JSR2
#20 #18 DEO LIT "( #18 DEO
;abs JSR2 ;print/short JSR2
LIT ") #18 DEO #0a #18 DEO JMP2r
( absolute value function )
@abs ( x* -> |x|* )
DUP2 ;xsign JSR2 MUL2 JMP2r
( modified sign function )
( )
( returns: )
( #0001 for non-negative )
( #1111 for negative )
( )
( this is not quite "signum" since we return #0001 for zero. )
( but for our purposes this is fine. )
@xsign ( x* -> sign* )
#0f SFT2 ( neg-x? )
#ffff MUL2 ( ffff or 0000 )
#0001 ORA2 ( ffff or 0001 )
JMP2r
( signed division )
( )
( the MIN value (-32768) needs special consideration. )
( since +32768 is not representable, -1 * MIN = MIN. )
( )
( rules (in precedence order): )
( )
( 1. x/0 = error )
( 2a. x/1 = x )
( 2b. MIN/MIN = 1 )
( 2c. x/MIN = 0 )
( 2d. MIN/-1 = MIN, because -1*MIN -> MIN )
( 3. x/y = |x|/|y| * xsign(x) * xsign(y) )
( )
( we must ensure these rules are handled in our code. )
( )
( as long as we run DIV2 we can be sure (1) is handled. )
( )
( similarly, we can be sure that (2a) is handled by )
( |x|/1 * xsign(x) * xsign(1), since xsign(1) = 1 )
( and this simplifies to |x| * xsign(x) = x. )
( )
( we handle (2b) because abs breaks down in the same way )
( for the numerator and denominator, and DIV2 preserves )
( this property ensuring MIN/MIN=1. )
( )
( since for any x we know |x| < 32768, we can be sure )
( that (2c) holds when using DIV2. )
( )
( finally, (2d) works because -1*MIN = MIN. )
( )
( therefore we don't have to special case MIN despite )
( the strangeness 16-bit signed numbers. )
@s16-div ( x* y* -> x/y* )
DUP2 ;xsign JSR2 ( x y sy )
STH2k MUL2 ( x |y| {sy} )
SWP2 ( |y| x {sy} )
DUP2 ;xsign JSR2 ( |y| x sx {sy} )
STH2k MUL2 MUL2r ( |y| |x| {sx*sy} )
SWP2 DIV2 ( |x|/|y| {sx*sy} )
STH2r MUL2 ( (|x|/|y|)*(sx*sy) )
JMP2r
( print unsigned 16-bit numbers )
@print ( short* -> )
&short ( short* -> ) SWP ,&byte JSR
&byte ( byte^ -> ) DUP #04 SFT ,&char JSR
&char ( char -> ) #0f AND DUP #09 GTH #27 MUL ADD #30 ADD #18 DEO
JMP2r
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment