diff --git a/asm/mathlib.s b/asm/mathlib.s index da29660..ea03cff 100644 --- a/asm/mathlib.s +++ b/asm/mathlib.s @@ -8,13 +8,14 @@ lda STACKBASE+6,x eor STACKBASE+2,x bpl samesign - lda STACKBASE+0,x - cmp STACKBASE+4,x - lda STACKBASE+2,x - sbc STACKBASE+6,x - bvc :+ + lda STACKBASE+4,x + cmp STACKBASE+0,x + lda STACKBASE+6,x + sbc STACKBASE+2,x + bvs :+ eor #$8000 -: rol +: sec ; make sure we don't set Z + rol ; move comparison into carry rts samesign: lda STACKBASE+6,x cmp STACKBASE+2,x diff --git a/platforms/GoSXB/run-tests.rb b/platforms/GoSXB/run-tests.rb new file mode 100755 index 0000000..8238cc1 --- /dev/null +++ b/platforms/GoSXB/run-tests.rb @@ -0,0 +1,108 @@ +#!/usr/bin/ruby + +require 'open3' +require 'yaml' +require 'stringio' +require 'timeout' + +TEST_DIR = '../../test' + +@verbose = $DEBUG +@total_errors = 0 + +def run_suite(suite) + puts "Executing suite: #{suite['name']}" + errors = 0 + suite_text = [] + outbuf = StringIO.new + errbuf = StringIO.new + suite['load'].each do |file| + suite_text += File.readlines("#{TEST_DIR}/#{file}") + end + suite_text << "\nbye\n" + Open3.popen3('./gosxb-of816.sh') do |stdin, stdout, stderr, wait_thr| + until [stdout, stderr].find {|f| !f.eof}.nil? + readable, writable, errored = IO.select([stdout,stderr],[stdin],[],0) + if writable.include?(stdin) + if line = suite_text.shift + puts ">> #{line}" if @verbose + stdin.write(line) + else + puts "Lines complete." + stdin.flush + begin + Timeout.timeout(10) do + outbuf.write(stdout.read) + end + rescue Timeout::Error + begin + outbuf.write(stdout.read_nonblock(1024)) + rescue IO::EAGAINWaitReadable + # nothing + end + puts outbuf.string unless @verbose + STDERR.puts "Emulator did not exit on its own." + errors += 1 + end + stdin.close + puts outbuf.string if @verbose + break + end + end + if readable.include?(stdout) + text = stdout.readline + puts "<< #{text}" if @verbose + outbuf.write(text) + end + if readable.include?(stderr) + stdin.flush + errbuf.write(stderr.read) + puts "Unexpected output on stderr:" + puts outbuf.string + puts errbuf.string + stdout.close + stderr.close + exit 2 + end + break unless wait_thr.alive? + end + prevline = "" + outbuf.string.lines.each do |line| + case line + when /Exception/, /not found/ + STDERR.puts prevline, line + errors += 1 + when /WRONG/, /INCORRECT/ + unless prevline =~ /\[OK\]/ + STDERR.puts line + errors += 1 + end + when /TESTING/i + puts line unless line.start_with?(':') + end + prevline = line + end + puts "Errors = #{errors}" + end + puts "Suite complete." + return errors +end + + +manifest = YAML.load(File.read("#{TEST_DIR}/test-manifest.yaml")) + +#puts manifest.inspect + +manifest.each do |suite| + @total_errors += run_suite(suite) +end + +puts "Tests complete, total errors: #{@total_errors}" + +if @total_errors > 0 + STDERR.puts "Tests complete, total errors: #{@total_errors}" + exit 1 +end + +STDOUT.puts "Tests complete, no errors." +exit 0 diff --git a/test/7.3.1.fs b/test/7.3.1.fs new file mode 100644 index 0000000..592d0ce --- /dev/null +++ b/test/7.3.1.fs @@ -0,0 +1,35 @@ +testing 7.3.1.1 Stack duplication +t{ 1 dup -> 1 1 }t +t{ 1 2 2dup -> 1 2 1 2 }t +t{ 1 2 3 3dup -> 1 2 3 1 2 3 }t +t{ 0 ?dup -> 0 }t +t{ 1 ?dup -> 1 1 }t +t{ 1 2 over -> 1 2 1 }t +t{ 1 2 3 4 2over -> 1 2 3 4 1 2 }t +t{ 1 2 3 1 pick -> 1 2 3 2 }t +t{ 1 2 tuck -> 2 1 2 }t + +testing 7.3.1.2 Stack removal +t{ 1 2 3 clear -> }t +t{ 1 drop -> }t +t{ 1 2 2drop -> }t +t{ 1 2 3 3drop -> }t +t{ 1 2 nip -> 2 }t + +testing 7.3.1.3 Stack rearrangement +T{ : RO5 100 200 300 400 500 ; -> }T +T{ RO5 3 ROLL -> 100 300 400 500 200 }T +T{ RO5 2 ROLL -> RO5 ROT }T +T{ RO5 1 ROLL -> RO5 SWAP }T +T{ RO5 0 ROLL -> RO5 }T +t{ 1 2 3 rot -> 2 3 1 }t +t{ 1 2 3 -rot -> 3 1 2 }t +t{ 1 2 swap -> 2 1 }t +t{ 1 2 3 4 2swap -> 3 4 1 2 }t + +testing 7.3.1.4 Return stack +t{ 1 2 >r drop >r -> 2 }t \ both >r and r> +t{ 1 >r r@ r> -> 1 1 }t + +testing 7.3.1.5 Stack depth +t{ 1 2 3 depth -> 1 2 3 3 }t diff --git a/test/7.3.2.1.fs b/test/7.3.2.1.fs new file mode 100644 index 0000000..5965b17 --- /dev/null +++ b/test/7.3.2.1.fs @@ -0,0 +1,215 @@ +testing 7.3.2.1 Single-precision integer arithmetic +T{ 0 5 + -> 5 }T +T{ 5 0 + -> 5 }T +T{ 0 -5 + -> -5 }T +T{ -5 0 + -> -5 }T +T{ 1 2 + -> 3 }T +T{ 1 -2 + -> -1 }T +T{ -1 2 + -> 1 }T +T{ -1 -2 + -> -3 }T +T{ -1 1 + -> 0 }T +T{ MID-UINT 1 + -> MID-UINT+1 }T + +T{ 0 5 - -> -5 }T +T{ 5 0 - -> 5 }T +T{ 0 -5 - -> 5 }T +T{ -5 0 - -> -5 }T +T{ 1 2 - -> -1 }T +T{ 1 -2 - -> 3 }T +T{ -1 2 - -> -3 }T +T{ -1 -2 - -> 1 }T +T{ 0 1 - -> -1 }T + +T{ MID-UINT+1 1 - -> MID-UINT }T +T{ 0 0 * -> 0 }T \ TEST IDENTITIES +T{ 0 1 * -> 0 }T +T{ 1 0 * -> 0 }T +T{ 1 2 * -> 2 }T +T{ 2 1 * -> 2 }T +T{ 3 3 * -> 9 }T +T{ -3 3 * -> -9 }T +T{ 3 -3 * -> -9 }T +T{ -3 -3 * -> 9 }T +T{ MID-UINT+1 1 RSHIFT 2 * -> MID-UINT+1 }T +T{ MID-UINT+1 2 RSHIFT 4 * -> MID-UINT+1 }T +T{ MID-UINT+1 1 RSHIFT MID-UINT+1 OR 2 * -> MID-UINT+1 }T + +\ todo: u* + +T{ 0 1 / -> 0 1 T/ }T +T{ 1 1 / -> 1 1 T/ }T +T{ 2 1 / -> 2 1 T/ }T +T{ -1 1 / -> -1 1 T/ }T +T{ -2 1 / -> -2 1 T/ }T +T{ 0 -1 / -> 0 -1 T/ }T +T{ 1 -1 / -> 1 -1 T/ }T +T{ 2 -1 / -> 2 -1 T/ }T +T{ -1 -1 / -> -1 -1 T/ }T +T{ -2 -1 / -> -2 -1 T/ }T +T{ 2 2 / -> 2 2 T/ }T +T{ -1 -1 / -> -1 -1 T/ }T +T{ -2 -2 / -> -2 -2 T/ }T +T{ 7 3 / -> 7 3 T/ }T +T{ 7 -3 / -> 7 -3 T/ }T +T{ -7 3 / -> -7 3 T/ }T +T{ -7 -3 / -> -7 -3 T/ }T +T{ MAX-INT 1 / -> MAX-INT 1 T/ }T +T{ MIN-INT 1 / -> MIN-INT 1 T/ }T +T{ MAX-INT MAX-INT / -> MAX-INT MAX-INT T/ }T +T{ MIN-INT MIN-INT / -> MIN-INT MIN-INT T/ }T + +T{ 0 2 1 */ -> 0 2 1 T*/ }T +T{ 1 2 1 */ -> 1 2 1 T*/ }T +T{ 2 2 1 */ -> 2 2 1 T*/ }T +T{ -1 2 1 */ -> -1 2 1 T*/ }T +T{ -2 2 1 */ -> -2 2 1 T*/ }T +T{ 0 2 -1 */ -> 0 2 -1 T*/ }T +T{ 1 2 -1 */ -> 1 2 -1 T*/ }T +T{ 2 2 -1 */ -> 2 2 -1 T*/ }T +T{ -1 2 -1 */ -> -1 2 -1 T*/ }T +T{ -2 2 -1 */ -> -2 2 -1 T*/ }T +T{ 2 2 2 */ -> 2 2 2 T*/ }T +T{ -1 2 -1 */ -> -1 2 -1 T*/ }T +T{ -2 2 -2 */ -> -2 2 -2 T*/ }T +T{ 7 2 3 */ -> 7 2 3 T*/ }T +T{ 7 2 -3 */ -> 7 2 -3 T*/ }T +T{ -7 2 3 */ -> -7 2 3 T*/ }T +T{ -7 2 -3 */ -> -7 2 -3 T*/ }T +T{ MAX-INT 2 MAX-INT */ -> MAX-INT 2 MAX-INT T*/ }T +T{ MIN-INT 2 MIN-INT */ -> MIN-INT 2 MIN-INT T*/ }T + +T{ 0 1 MOD -> 0 1 TMOD }T +T{ 1 1 MOD -> 1 1 TMOD }T +T{ 2 1 MOD -> 2 1 TMOD }T +T{ -1 1 MOD -> -1 1 TMOD }T +T{ -2 1 MOD -> -2 1 TMOD }T +T{ 0 -1 MOD -> 0 -1 TMOD }T +T{ 1 -1 MOD -> 1 -1 TMOD }T +T{ 2 -1 MOD -> 2 -1 TMOD }T +T{ -1 -1 MOD -> -1 -1 TMOD }T +T{ -2 -1 MOD -> -2 -1 TMOD }T +T{ 2 2 MOD -> 2 2 TMOD }T +T{ -1 -1 MOD -> -1 -1 TMOD }T +T{ -2 -2 MOD -> -2 -2 TMOD }T +T{ 7 3 MOD -> 7 3 TMOD }T +T{ 7 -3 MOD -> 7 -3 TMOD }T +T{ -7 3 MOD -> -7 3 TMOD }T +T{ -7 -3 MOD -> -7 -3 TMOD }T +T{ MAX-INT 1 MOD -> MAX-INT 1 TMOD }T +T{ MIN-INT 1 MOD -> MIN-INT 1 TMOD }T +T{ MAX-INT MAX-INT MOD -> MAX-INT MAX-INT TMOD }T +T{ MIN-INT MIN-INT MOD -> MIN-INT MIN-INT TMOD }T + +T{ 0 1 /MOD -> 0 1 T/MOD }T +T{ 1 1 /MOD -> 1 1 T/MOD }T +T{ 2 1 /MOD -> 2 1 T/MOD }T +T{ -1 1 /MOD -> -1 1 T/MOD }T +T{ -2 1 /MOD -> -2 1 T/MOD }T +T{ 0 -1 /MOD -> 0 -1 T/MOD }T +T{ 1 -1 /MOD -> 1 -1 T/MOD }T +T{ 2 -1 /MOD -> 2 -1 T/MOD }T +T{ -1 -1 /MOD -> -1 -1 T/MOD }T +T{ -2 -1 /MOD -> -2 -1 T/MOD }T +T{ 2 2 /MOD -> 2 2 T/MOD }T +T{ -1 -1 /MOD -> -1 -1 T/MOD }T +T{ -2 -2 /MOD -> -2 -2 T/MOD }T +T{ 7 3 /MOD -> 7 3 T/MOD }T +T{ 7 -3 /MOD -> 7 -3 T/MOD }T +T{ -7 3 /MOD -> -7 3 T/MOD }T +T{ -7 -3 /MOD -> -7 -3 T/MOD }T +T{ MAX-INT 1 /MOD -> MAX-INT 1 T/MOD }T +T{ MIN-INT 1 /MOD -> MIN-INT 1 T/MOD }T +T{ MAX-INT MAX-INT /MOD -> MAX-INT MAX-INT T/MOD }T +T{ MIN-INT MIN-INT /MOD -> MIN-INT MIN-INT T/MOD }T + +T{ 0 2 1 */MOD -> 0 2 1 T*/MOD }T +T{ 1 2 1 */MOD -> 1 2 1 T*/MOD }T +T{ 2 2 1 */MOD -> 2 2 1 T*/MOD }T +T{ -1 2 1 */MOD -> -1 2 1 T*/MOD }T +T{ -2 2 1 */MOD -> -2 2 1 T*/MOD }T +T{ 0 2 -1 */MOD -> 0 2 -1 T*/MOD }T +T{ 1 2 -1 */MOD -> 1 2 -1 T*/MOD }T +T{ 2 2 -1 */MOD -> 2 2 -1 T*/MOD }T +T{ -1 2 -1 */MOD -> -1 2 -1 T*/MOD }T +T{ -2 2 -1 */MOD -> -2 2 -1 T*/MOD }T +T{ 2 2 2 */MOD -> 2 2 2 T*/MOD }T +T{ -1 2 -1 */MOD -> -1 2 -1 T*/MOD }T +T{ -2 2 -2 */MOD -> -2 2 -2 T*/MOD }T +T{ 7 2 3 */MOD -> 7 2 3 T*/MOD }T +T{ 7 2 -3 */MOD -> 7 2 -3 T*/MOD }T +T{ -7 2 3 */MOD -> -7 2 3 T*/MOD }T +T{ -7 2 -3 */MOD -> -7 2 -3 T*/MOD }T +T{ MAX-INT 2 MAX-INT */MOD -> MAX-INT 2 MAX-INT T*/MOD }T +T{ MIN-INT 2 MIN-INT */MOD -> MIN-INT 2 MIN-INT T*/MOD }T + +\ todo: u/mod + +T{ 0 1+ -> 1 }T +T{ -1 1+ -> 0 }T +T{ 1 1+ -> 2 }T +T{ MID-UINT 1+ -> MID-UINT+1 }T + +T{ 2 1- -> 1 }T +T{ 1 1- -> 0 }T +T{ 0 1- -> -1 }T +T{ MID-UINT+1 1- -> MID-UINT }T + +t{ 1 2+ -> 3 }t +t{ -2 2+ -> 0 }t + +t{ 2 2- -> 0 }t +t{ 0 2- -> -2 }t + +T{ 0 ABS -> 0 }T +T{ 1 ABS -> 1 }T +T{ -1 ABS -> 1 }T +T{ MIN-INT ABS -> MID-UINT+1 }T + +T{ 0 NEGATE -> 0 }T +T{ 1 NEGATE -> -1 }T +T{ -1 NEGATE -> 1 }T +T{ 2 NEGATE -> -2 }T +T{ -2 NEGATE -> 2 }T + +T{ 0 1 MAX -> 1 }T +T{ 1 2 MAX -> 2 }T +T{ -1 0 MAX -> 0 }T +T{ -1 1 MAX -> 1 }T +T{ MIN-INT 0 MAX -> 0 }T +T{ MIN-INT MAX-INT MAX -> MAX-INT }T +T{ 0 MAX-INT MAX -> MAX-INT }T +T{ 0 0 MAX -> 0 }T +T{ 1 1 MAX -> 1 }T +T{ 1 0 MAX -> 1 }T +T{ 2 1 MAX -> 2 }T +T{ 0 -1 MAX -> 0 }T +T{ 1 -1 MAX -> 1 }T +T{ 0 MIN-INT MAX -> 0 }T +T{ MAX-INT MIN-INT MAX -> MAX-INT }T +T{ MAX-INT 0 MAX -> MAX-INT }T + +T{ 0 1 MIN -> 0 }T +T{ 1 2 MIN -> 1 }T +T{ -1 0 MIN -> -1 }T +T{ -1 1 MIN -> -1 }T +T{ MIN-INT 0 MIN -> MIN-INT }T +T{ MIN-INT MAX-INT MIN -> MIN-INT }T +T{ 0 MAX-INT MIN -> 0 }T +T{ 0 0 MIN -> 0 }T +T{ 1 1 MIN -> 1 }T +T{ 1 0 MIN -> 0 }T +T{ 2 1 MIN -> 1 }T +T{ 0 -1 MIN -> -1 }T +T{ 1 -1 MIN -> -1 }T +T{ 0 MIN-INT MIN -> MIN-INT }T +T{ MAX-INT MIN-INT MIN -> MIN-INT }T +T{ MAX-INT 0 MIN -> 0 }T + +t{ 0 5 bounds -> 5 0 }t +t{ 5 10 bounds -> 15 5 }t + +t{ 1 even -> 2 }t +t{ 2 even -> 2 }t +t{ -1 even -> 0 }t +t{ 0 even -> 0 }t + diff --git a/test/7.3.2.2.fs b/test/7.3.2.2.fs new file mode 100644 index 0000000..7498792 --- /dev/null +++ b/test/7.3.2.2.fs @@ -0,0 +1,66 @@ +testing 7.3.2.2 Bitwise logical operators + +( WE TRUST 1S, INVERT, AND BITSSET?; WE WILL CONFIRM RSHIFT LATER ) +1S 1 RSHIFT INVERT CONSTANT MSB +T{ MSB BITSSET? -> 0 0 }T + +T{ 1 0 LSHIFT -> 1 }T +T{ 1 1 LSHIFT -> 2 }T +T{ 1 2 LSHIFT -> 4 }T +T{ 1 F LSHIFT -> 8000 }T \ BIGGEST GUARANTEED SHIFT +T{ 1S 1 LSHIFT 1 XOR -> 1S }T +T{ MSB 1 LSHIFT -> 0 }T + +T{ 1 0 RSHIFT -> 1 }T +T{ 1 1 RSHIFT -> 0 }T +T{ 2 1 RSHIFT -> 1 }T +T{ 4 2 RSHIFT -> 1 }T +T{ 8000 F RSHIFT -> 1 }T \ BIGGEST +T{ MSB 1 RSHIFT MSB AND -> 0 }T \ RSHIFT ZERO FILLS MSBS +T{ MSB 1 RSHIFT 2* -> MSB }T + +\ todo: >>a << >> + +T{ 0S 2* -> 0S }T +T{ 1 2* -> 2 }T +T{ 4000 2* -> 8000 }T +T{ 1S 2* 1 XOR -> 1S }T +T{ MSB 2* -> 0S }T + +\ todo: u2/ + +T{ 0S 2/ -> 0S }T +T{ 1 2/ -> 0 }T +T{ 4000 2/ -> 2000 }T +T{ 1S 2/ -> 1S }T \ MSB PROPOGATED +T{ 1S 1 XOR 2/ -> 1S }T +T{ MSB 2/ MSB AND -> MSB }T + +T{ 0 0 AND -> 0 }T +T{ 0 1 AND -> 0 }T +T{ 1 0 AND -> 0 }T +T{ 1 1 AND -> 1 }T + +T{ 0 INVERT 1 AND -> 1 }T +T{ 1 INVERT 1 AND -> 0 }T + +T{ 0S 0S AND -> 0S }T +T{ 0S 1S AND -> 0S }T +T{ 1S 0S AND -> 0S }T +T{ 1S 1S AND -> 1S }T + +T{ 0S 0S OR -> 0S }T +T{ 0S 1S OR -> 1S }T +T{ 1S 0S OR -> 1S }T +T{ 1S 1S OR -> 1S }T + +T{ 0S 0S XOR -> 0S }T +T{ 0S 1S XOR -> 1S }T +T{ 1S 0S XOR -> 1S }T +T{ 1S 1S XOR -> 0S }T + +T{ 0S INVERT -> 1S }T +T{ 1S INVERT -> 0S }T + +t{ 0S not -> 1S }t +t{ 1S not -> 0S }t diff --git a/test/7.3.2.3.fs b/test/7.3.2.3.fs new file mode 100644 index 0000000..60804bb --- /dev/null +++ b/test/7.3.2.3.fs @@ -0,0 +1,187 @@ +DECIMAL +0 INVERT CONSTANT 1SD +1SD 1 RSHIFT CONSTANT MAX-INTD \ 01...1 +MAX-INTD INVERT CONSTANT MIN-INTD \ 10...0 +MAX-INTD 2/ CONSTANT HI-INT \ 001...1 +MIN-INTD 2/ CONSTANT LO-INT \ 110...1 + +1SD MAX-INTD 2CONSTANT MAX-2INT \ 01...1 +0 MIN-INTD 2CONSTANT MIN-2INT \ 10...0 +MAX-2INT 2/ 2CONSTANT HI-2INT \ 001...1 +MIN-2INT 2/ 2CONSTANT LO-2INT \ 110...0 + +testing 7.3.2.3 Double number arithmetic + +T{ 0 S>D -> 0 0 }T +T{ 1 S>D -> 1 0 }T +T{ 2 S>D -> 2 0 }T +T{ -1 S>D -> -1 -1 }T +T{ -2 S>D -> -2 -1 }T +T{ MIN-INT S>D -> MIN-INT -1 }T +T{ MAX-INT S>D -> MAX-INT 0 }T + +TESTING D+ with small integers +t{ 0 s>d 5 s>d D+ -> 5 s>d }t +t{ -5 s>d 0 s>d D+ -> -5 s>d }t +t{ 1 s>d 2 s>d D+ -> 3 s>d }t +t{ 1 s>d -2 s>d D+ -> -1 s>d }t +t{ -1 s>d 2 s>d D+ -> 1 s>d }t +t{ -1 s>d -2 s>d D+ -> -3 s>d }t +t{ -1 s>d 1 s>d D+ -> 0 s>d }t +TESTING D+ with mid range integers +T{ 0 0 0 5 D+ -> 0 5 }T +T{ -1 5 0 0 D+ -> -1 5 }T +T{ 0 0 0 -5 D+ -> 0 -5 }T +T{ 0 -5 -1 0 D+ -> -1 -5 }T +T{ 0 1 0 2 D+ -> 0 3 }T +T{ -1 1 0 -2 D+ -> -1 -1 }T +T{ 0 -1 0 2 D+ -> 0 1 }T +T{ 0 -1 -1 -2 D+ -> -1 -3 }T +T{ -1 -1 0 1 D+ -> -1 0 }T +T{ MIN-INTD 0 2DUP D+ -> 0 1 }T +T{ MIN-INTD S>D MIN-INTD 0 D+ -> 0 0 }T +TESTING D+ with large double integers +t{ HI-2INT 1 s>d D+ -> 0 HI-INT 1+ }t +T{ HI-2INT 2DUP D+ -> 1SD 1- MAX-INTD }T +t{ MAX-2INT MIN-2INT D+ -> -1 s>d }t +T{ MAX-2INT LO-2INT D+ -> HI-2INT }T +t{ HI-2INT MIN-2INT D+ s>d D+ -> LO-2INT }t +T{ LO-2INT 2DUP D+ -> MIN-2INT }T + +TESTING D- with small integers +t{ 0 s>d 5 s>d D- -> -5 s>d }t +t{ 5 s>d 0 s>d D- -> 5 s>d }t +t{ 0 s>d -5 s>d D- -> 5 s>d }t +t{ 1 s>d 2 s>d D- -> -1 s>d }t +t{ 1 s>d -2 s>d D- -> 3 s>d }t +t{ -1 s>d 2 s>d D- -> -3 s>d }t +t{ -1 s>d -2 s>d D- -> 1 s>d }t +t{ -1 s>d -1 s>d D- -> 0 s>d }t +TESTING D- with mid-range integers +T{ 0 0 0 5 D- -> 0 -5 }T +T{ -1 5 0 0 D- -> -1 5 }T +T{ 0 0 -1 -5 D- -> 1 4 }T +T{ 0 -5 0 0 D- -> 0 -5 }T +T{ -1 1 0 2 D- -> -1 -1 }T +T{ 0 1 -1 -2 D- -> 1 2 }T +T{ 0 -1 0 2 D- -> 0 -3 }T +T{ 0 -1 0 -2 D- -> 0 1 }T +T{ 0 0 0 1 D- -> 0 -1 }T +t{ MIN-INTD 0 2DUP D- -> 0 s>d }t +T{ MIN-INTD S>D MAX-INTD 0 D- -> 1 1SD }T +TESTING D- with large integers +t{ MAX-2INT MAX-2INT D- -> 0 s>d }t +t{ MIN-2INT MIN-2INT D- -> 0 s>d }t +T{ MAX-2INT HI-2INT D- -> LO-2INT DNEGATE }T +T{ HI-2INT LO-2INT D- -> MAX-2INT }T +t{ LO-2INT HI-2INT D- -> MIN-2INT 1 s>d D+ }t +t{ MIN-2INT MIN-2INT D- -> 0 s>d }t +T{ MIN-2INT LO-2INT D- -> LO-2INT }T + +T{ 0 0 UM* -> 0 0 }T +T{ 0 1 UM* -> 0 0 }T +T{ 1 0 UM* -> 0 0 }T +T{ 1 2 UM* -> 2 0 }T +T{ 2 1 UM* -> 2 0 }T +T{ 3 3 UM* -> 9 0 }T + +T{ 0 0 M* -> 0 S>D }T +T{ 0 1 M* -> 0 S>D }T +T{ 1 0 M* -> 0 S>D }T +T{ 1 2 M* -> 2 S>D }T +T{ 2 1 M* -> 2 S>D }T +T{ 3 3 M* -> 9 S>D }T +T{ -3 3 M* -> -9 S>D }T +T{ 3 -3 M* -> -9 S>D }T +T{ -3 -3 M* -> 9 S>D }T +T{ 0 MIN-INT M* -> 0 S>D }T +T{ 1 MIN-INT M* -> MIN-INT S>D }T +T{ 2 MIN-INT M* -> 0 1S }T +T{ 0 MAX-INT M* -> 0 S>D }T +T{ 1 MAX-INT M* -> MAX-INT S>D }T +T{ 2 MAX-INT M* -> MAX-INT 1 LSHIFT 0 }T +T{ MIN-INT MIN-INT M* -> 0 MSB 1 RSHIFT }T +T{ MAX-INT MIN-INT M* -> MSB MSB 2/ }T +T{ MAX-INT MAX-INT M* -> 1 MSB 2/ INVERT }T + +T{ MID-UINT+1 1 RSHIFT 2 UM* -> MID-UINT+1 0 }T +T{ MID-UINT+1 2 UM* -> 0 1 }T +T{ MID-UINT+1 4 UM* -> 0 2 }T +T{ 1S 2 UM* -> 1S 1 LSHIFT 1 }T +T{ MAX-UINT MAX-UINT UM* -> 1 1 INVERT }T + +T{ 0 0 1 UM/MOD -> 0 0 }T +T{ 1 0 1 UM/MOD -> 0 1 }T +T{ 1 0 2 UM/MOD -> 1 0 }T +T{ 3 0 2 UM/MOD -> 1 1 }T +T{ MAX-UINT 2 UM* 2 UM/MOD -> 0 MAX-UINT }T +T{ MAX-UINT 2 UM* MAX-UINT UM/MOD -> 0 2 }T +T{ MAX-UINT MAX-UINT UM* MAX-UINT UM/MOD -> 0 MAX-UINT }T + +T{ 0 S>D 1 FM/MOD -> 0 0 }T +T{ 1 S>D 1 FM/MOD -> 0 1 }T +T{ 2 S>D 1 FM/MOD -> 0 2 }T +T{ -1 S>D 1 FM/MOD -> 0 -1 }T +T{ -2 S>D 1 FM/MOD -> 0 -2 }T +T{ 0 S>D -1 FM/MOD -> 0 0 }T +T{ 1 S>D -1 FM/MOD -> 0 -1 }T +T{ 2 S>D -1 FM/MOD -> 0 -2 }T +T{ -1 S>D -1 FM/MOD -> 0 1 }T +T{ -2 S>D -1 FM/MOD -> 0 2 }T +T{ 2 S>D 2 FM/MOD -> 0 1 }T +T{ -1 S>D -1 FM/MOD -> 0 1 }T +T{ -2 S>D -2 FM/MOD -> 0 1 }T +T{ 7 S>D 3 FM/MOD -> 1 2 }T +T{ 7 S>D -3 FM/MOD -> -2 -3 }T +T{ -7 S>D 3 FM/MOD -> 2 -3 }T +T{ -7 S>D -3 FM/MOD -> -1 2 }T +T{ MAX-INT S>D 1 FM/MOD -> 0 MAX-INT }T +T{ MIN-INT S>D 1 FM/MOD -> 0 MIN-INT }T +T{ MAX-INT S>D MAX-INT FM/MOD -> 0 1 }T +T{ MIN-INT S>D MIN-INT FM/MOD -> 0 1 }T +T{ 1S 1 4 FM/MOD -> 3 MAX-INT }T +T{ 1 MIN-INT M* 1 FM/MOD -> 0 MIN-INT }T +T{ 1 MIN-INT M* MIN-INT FM/MOD -> 0 1 }T +T{ 2 MIN-INT M* 2 FM/MOD -> 0 MIN-INT }T +T{ 2 MIN-INT M* MIN-INT FM/MOD -> 0 2 }T +T{ 1 MAX-INT M* 1 FM/MOD -> 0 MAX-INT }T +T{ 1 MAX-INT M* MAX-INT FM/MOD -> 0 1 }T +T{ 2 MAX-INT M* 2 FM/MOD -> 0 MAX-INT }T +T{ 2 MAX-INT M* MAX-INT FM/MOD -> 0 2 }T +T{ MIN-INT MIN-INT M* MIN-INT FM/MOD -> 0 MIN-INT }T +T{ MIN-INT MAX-INT M* MIN-INT FM/MOD -> 0 MAX-INT }T +T{ MIN-INT MAX-INT M* MAX-INT FM/MOD -> 0 MIN-INT }T +T{ MAX-INT MAX-INT M* MAX-INT FM/MOD -> 0 MAX-INT }T + +T{ 0 S>D 1 SM/REM -> 0 0 }T +T{ 1 S>D 1 SM/REM -> 0 1 }T +T{ 2 S>D 1 SM/REM -> 0 2 }T +T{ -1 S>D 1 SM/REM -> 0 -1 }T +T{ -2 S>D 1 SM/REM -> 0 -2 }T +T{ 0 S>D -1 SM/REM -> 0 0 }T +T{ 1 S>D -1 SM/REM -> 0 -1 }T +T{ 2 S>D -1 SM/REM -> 0 -2 }T +T{ -1 S>D -1 SM/REM -> 0 1 }T +T{ -2 S>D -1 SM/REM -> 0 2 }T +T{ 2 S>D 2 SM/REM -> 0 1 }T +T{ -1 S>D -1 SM/REM -> 0 1 }T +T{ -2 S>D -2 SM/REM -> 0 1 }T +T{ 7 S>D 3 SM/REM -> 1 2 }T +T{ 7 S>D -3 SM/REM -> 1 -2 }T +T{ -7 S>D 3 SM/REM -> -1 -2 }T +T{ -7 S>D -3 SM/REM -> -1 2 }T +T{ MAX-INT S>D 1 SM/REM -> 0 MAX-INT }T +T{ MIN-INT S>D 1 SM/REM -> 0 MIN-INT }T +T{ MAX-INT S>D MAX-INT SM/REM -> 0 1 }T +T{ MIN-INT S>D MIN-INT SM/REM -> 0 1 }T +T{ 1S 1 4 SM/REM -> 3 MAX-INT }T +T{ 2 MIN-INT M* 2 SM/REM -> 0 MIN-INT }T +T{ 2 MIN-INT M* MIN-INT SM/REM -> 0 2 }T +T{ 2 MAX-INT M* 2 SM/REM -> 0 MAX-INT }T +T{ 2 MAX-INT M* MAX-INT SM/REM -> 0 2 }T +T{ MIN-INT MIN-INT M* MIN-INT SM/REM -> 0 MIN-INT }T +T{ MIN-INT MAX-INT M* MIN-INT SM/REM -> 0 MAX-INT }T +T{ MIN-INT MAX-INT M* MAX-INT SM/REM -> 0 MIN-INT }T +T{ MAX-INT MAX-INT M* MAX-INT SM/REM -> 0 MAX-INT }T + + diff --git a/test/7.3.2.4.fs b/test/7.3.2.4.fs new file mode 100644 index 0000000..ae22d5f --- /dev/null +++ b/test/7.3.2.4.fs @@ -0,0 +1,11 @@ +testing 7.3.2.4 Data type conversion + +t{ 01020304 lbsplit -> 04 03 02 01 }t +t{ 01020304 lwsplit -> 0304 0102 }t +t{ 0102 wbsplit -> 02 01 }t +t{ 04 03 02 01 bljoin -> 01020304 }t +t{ 02 01 bwjoin -> 0102 }t +t{ 0304 0102 wljoin -> 01020304 }t +t{ 0102 wbflip -> 0201 }t +t{ 01020304 lbflip -> 04030201 }t +t{ 01020304 lwflip -> 03040102 }t diff --git a/test/7.3.2.5.fs b/test/7.3.2.5.fs new file mode 100644 index 0000000..9951d34 --- /dev/null +++ b/test/7.3.2.5.fs @@ -0,0 +1,33 @@ +testing 7.3.2.5 Address arithmetic + +t{ /c -> 1 }t +t{ /w -> 2 }t +t{ /l -> 4 }t +t{ /n -> 4 }t \ OF816 is hardcoded to this + +t{ 0 2 ca+ -> 2 /c * }t +t{ 0 2 wa+ -> 2 /w * }t +t{ 0 2 la+ -> 2 /l * }t +t{ 0 2 na+ -> 2 /n * }t + +t{ 0 ca1+ -> /c }t +t{ 0 wa1+ -> /w }t +t{ 0 la1+ -> /l }t +t{ 0 na1+ -> /n }t + +t{ 2 /c* -> 2 /c * }t +t{ 2 /w* -> 2 /w * }t +t{ 2 /l* -> 2 /l * }t +t{ 2 /n* -> 2 /n * }t + +\ no alignment restrictions on the 816 +t{ 0 aligned -> 0 }t +t{ 1 aligned -> 1 }t +t{ 2 aligned -> 2 }t +t{ 3 aligned -> 3 }t + +t{ 0 char+ -> /c }t +t{ 0 cell+ -> /n }t + +t{ 2 chars -> 2 /c * }t +t{ 2 cells -> 2 /n * }t diff --git a/test/7.3.6.fs b/test/7.3.6.fs new file mode 100644 index 0000000..dc68a51 --- /dev/null +++ b/test/7.3.6.fs @@ -0,0 +1,90 @@ +0 CONSTANT 0S +0 INVERT CONSTANT 1S + +0 INVERT CONSTANT MAX-UINT +0 INVERT 1 RSHIFT CONSTANT MAX-INT +0 INVERT 1 RSHIFT INVERT CONSTANT MIN-INT +0 INVERT 1 RSHIFT CONSTANT MID-UINT +0 INVERT 1 RSHIFT INVERT CONSTANT MID-UINT+1 + +0S CONSTANT +1S CONSTANT + +testing 7.3.6 Comparison operators + +T{ 0 1 < -> }T +T{ 1 2 < -> }T +T{ -1 0 < -> }T +T{ -1 1 < -> }T +T{ MIN-INT 0 < -> }T +T{ MIN-INT MAX-INT < -> }T +T{ 0 MAX-INT < -> }T +T{ 0 0 < -> }T +T{ 1 1 < -> }T +T{ 1 0 < -> }T +T{ 2 1 < -> }T +T{ 0 -1 < -> }T +T{ 1 -1 < -> }T +T{ 0 MIN-INT < -> }T +T{ MAX-INT MIN-INT < -> }T +T{ MAX-INT 0 < -> }T + +T{ 0 0 = -> }T +T{ 1 1 = -> }T +T{ -1 -1 = -> }T +T{ 1 0 = -> }T +T{ -1 0 = -> }T +T{ 0 1 = -> }T +T{ 0 -1 = -> }T + +T{ 0 1 > -> }T +T{ 1 2 > -> }T +T{ -1 0 > -> }T +T{ -1 1 > -> }T +T{ MIN-INT 0 > -> }T +T{ MIN-INT MAX-INT > -> }T +T{ 0 MAX-INT > -> }T +T{ 0 0 > -> }T +T{ 1 1 > -> }T +T{ 1 0 > -> }T +T{ 2 1 > -> }T +T{ 0 -1 > -> }T +T{ 1 -1 > -> }T +T{ 0 MIN-INT > -> }T +T{ MAX-INT MIN-INT > -> }T +T{ MAX-INT 0 > -> }T + +\ todo: >= between within + +T{ 0 0< -> }T +T{ -1 0< -> }T +T{ MIN-INT 0< -> }T +T{ 1 0< -> }T +T{ MAX-INT 0< -> }T + +\ todo: 0<= 0<> + +T{ 0 0= -> }T +T{ 1 0= -> }T +T{ 2 0= -> }T +T{ -1 0= -> }T +T{ MAX-UINT 0= -> }T +T{ MIN-INT 0= -> }T +T{ MAX-INT 0= -> }T + +\ todo: 0> 0>= + +T{ 0 1 U< -> }T +T{ 1 2 U< -> }T +T{ 0 MID-UINT U< -> }T +T{ 0 MAX-UINT U< -> }T +T{ MID-UINT MAX-UINT U< -> }T +T{ 0 0 U< -> }T +T{ 1 1 U< -> }T +T{ 1 0 U< -> }T +T{ 2 1 U< -> }T +T{ MID-UINT 0 U< -> }T +T{ MAX-UINT 0 U< -> }T +T{ MAX-UINT MID-UINT U< -> }T + +\ todo: u<= u> u>= diff --git a/test/test-manifest.yaml b/test/test-manifest.yaml new file mode 100644 index 0000000..1799663 --- /dev/null +++ b/test/test-manifest.yaml @@ -0,0 +1,32 @@ +- name: 7.3.1 Stack functions + load: + - tester.fs + - 7.3.1.fs +- name: 7.3.2.1 Arithmetic + load: + - tester.fs + - test-utils.fs + - 7.3.2.1.fs +- name: 7.3.2.2 Arithmetic + load: + - tester.fs + - test-utils.fs + - 7.3.2.2.fs +- name: 7.3.2.3 Arithmetic + load: + - tester.fs + - test-utils.fs + - 7.3.2.3.fs +- name: 7.3.2.4 Arithmetic + load: + - tester.fs + - 7.3.2.4.fs +- name: 7.3.2.5 Arithmetic + load: + - tester.fs + - 7.3.2.5.fs +- name: 7.3.6 Comparison operators + load: + - tester.fs + - test-utils.fs + - 7.3.6.fs \ No newline at end of file diff --git a/test/test-utils.fs b/test/test-utils.fs new file mode 100644 index 0000000..a583964 --- /dev/null +++ b/test/test-utils.fs @@ -0,0 +1,39 @@ +0 INVERT CONSTANT MAX-UINT +0 INVERT 1 RSHIFT CONSTANT MAX-INT +0 INVERT 1 RSHIFT INVERT CONSTANT MIN-INT +0 INVERT 1 RSHIFT CONSTANT MID-UINT +0 INVERT 1 RSHIFT INVERT CONSTANT MID-UINT+1 + +: IFFLOORED + [ -3 2 / -2 = INVERT ] LITERAL IF POSTPONE \ THEN ; + +: IFSYM + [ -3 2 / -1 = INVERT ] LITERAL IF POSTPONE \ THEN ; + +\ THE SYSTEM MIGHT DO EITHER FLOORED OR SYMMETRIC DIVISION. +\ SINCE WE HAVE ALREADY TESTED M*, FM/MOD, AND SM/REM WE CAN USE THEM IN TEST. + +IFFLOORED : T/MOD >R S>D R> FM/MOD ; +IFFLOORED : T/ T/MOD SWAP DROP ; +IFFLOORED : TMOD T/MOD DROP ; +IFFLOORED : T*/MOD >R M* R> FM/MOD ; +IFFLOORED : T*/ T*/MOD SWAP DROP ; +IFSYM : T/MOD >R S>D R> SM/REM ; +IFSYM : T/ T/MOD SWAP DROP ; +IFSYM : TMOD T/MOD DROP ; +IFSYM : T*/MOD >R M* R> SM/REM ; +IFSYM : T*/ T*/MOD SWAP DROP ; + +0 CONSTANT 0S +0 INVERT CONSTANT 1S + +T{ -> }T \ START WITH CLEAN SLATE +( TEST IF ANY BITS ARE SET; ANSWER IN BASE 1 ) +T{ : BITSSET? IF 0 0 ELSE 0 THEN ; -> }T +T{ 0 BITSSET? -> 0 }T ( ZERO IS ALL BITS CLEAR ) +T{ 1 BITSSET? -> 0 0 }T ( OTHER NUMBER HAVE AT LEAST ONE BIT ) +T{ -1 BITSSET? -> 0 0 }T + +( WE TRUST 1S, INVERT, AND BITSSET?; WE WILL CONFIRM RSHIFT LATER ) +1S 1 RSHIFT INVERT CONSTANT MSB +T{ MSB BITSSET? -> 0 0 }T diff --git a/test/tester.fs b/test/tester.fs new file mode 100644 index 0000000..93be209 --- /dev/null +++ b/test/tester.fs @@ -0,0 +1,69 @@ +\ Adapted from: https://raw.githubusercontent.com/gerryjackson/forth2012-test-suite/master/src/tester.fr + +\ From: John Hayes S1I +\ Subject: tester.fr +\ Date: Mon, 27 Nov 95 13:10:09 PST + +\ (C) 1995 JOHNS HOPKINS UNIVERSITY / APPLIED PHYSICS LABORATORY +\ MAY BE DISTRIBUTED FREELY AS LONG AS THIS COPYRIGHT NOTICE REMAINS. +\ VERSION 1.2 + +\ 24/11/2015 Replaced Core Ext word <> with = 0= +\ 31/3/2015 Variable #ERRORS added and incremented for each error reported. +\ 22/1/09 The words { and } have been changed to T{ and }T respectively to +\ agree with the Forth 200X file ttester.fs. This avoids clashes with +\ locals using { ... } and the FSL use of } + +HEX + +\ SET THE FOLLOWING FLAG TO TRUE FOR MORE VERBOSE OUTPUT; THIS MAY +\ ALLOW YOU TO TELL WHICH TEST CAUSED YOUR SYSTEM TO HANG. +VARIABLE VERBOSE + FALSE VERBOSE ! +\ TRUE VERBOSE ! + +\ : EMPTY-STACK \ ( ... -- ) EMPTY STACK: HANDLES UNDERFLOWED STACK TOO. +\ DEPTH ?DUP IF DUP 0< IF NEGATE 0 DO 0 LOOP ELSE 0 DO DROP LOOP THEN THEN ; +\ THE IEEE-1275 CLEAR word works the same +ALIAS EMPTY-STACK CLEAR + +VARIABLE #ERRORS 0 #ERRORS ! + +: ERROR \ ( C-ADDR U -- ) DISPLAY AN ERROR MESSAGE FOLLOWED BY + \ THE LINE THAT HAD THE ERROR. + CR TYPE SOURCE TYPE \ DISPLAY LINE CORRESPONDING TO ERROR + EMPTY-STACK \ THROW AWAY EVERY THING ELSE + #ERRORS @ 1 + #ERRORS ! +\ QUIT \ *** Uncomment this line to QUIT on an error +; + +VARIABLE ACTUAL-DEPTH \ STACK RECORD +CREATE ACTUAL-RESULTS 20 CELLS ALLOT + +: T{ \ ( -- ) SYNTACTIC SUGAR. + ; + +: -> \ ( ... -- ) RECORD DEPTH AND CONTENT OF STACK. + DEPTH DUP ACTUAL-DEPTH ! \ RECORD DEPTH + ?DUP IF \ IF THERE IS SOMETHING ON STACK + 0 DO ACTUAL-RESULTS I CELLS + ! LOOP \ SAVE THEM + THEN ; + +: }T \ ( ... -- ) COMPARE STACK (EXPECTED) CONTENTS WITH SAVED + \ (ACTUAL) CONTENTS. + DEPTH ACTUAL-DEPTH @ = IF \ IF DEPTHS MATCH + DEPTH ?DUP IF \ IF THERE IS SOMETHING ON THE STACK + 0 DO \ FOR EACH STACK ITEM + ACTUAL-RESULTS I CELLS + @ \ COMPARE ACTUAL WITH EXPECTED + = 0= IF S" INCORRECT RESULT: " ERROR LEAVE THEN + LOOP + THEN + ELSE \ DEPTH MISMATCH + S" WRONG NUMBER OF RESULTS: " ERROR + THEN ; + +: TESTING \ ( -- ) TALKING COMMENT. + SOURCE VERBOSE @ + IF DUP >R TYPE CR R> >IN ! + ELSE >IN ! DROP [CHAR] * EMIT + THEN ;