shithub: rgbds

Download patch

ref: 7ce5cf1595f2fb3a508e920d8e4929381e298e59
parent: 7e3fc1db038c1707e00fc130dc1e4a0bfd2e7ff0
author: Rangi <remy.oukaour+rangi42@gmail.com>
date: Mon Jan 4 05:49:30 EST 2021

Convert floating to fixed point by rounding, not truncation

Fixes #678

--- a/src/asm/lexer.c
+++ b/src/asm/lexer.c
@@ -13,6 +13,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
+#include <math.h>
 #include <limits.h>
 #include <stdbool.h>
 #include <stdint.h>
@@ -1130,7 +1131,7 @@
 	/* Cast to unsigned avoids UB if shifting discards bits */
 	yylval.nConstValue = (uint32_t)yylval.nConstValue << 16;
 	/* Cast to unsigned avoids undefined overflow behavior */
-	uint16_t fractional = value * 65536 / divisor;
+	uint16_t fractional = (uint16_t)round(value * 65536.0 / divisor);
 
 	yylval.nConstValue |= fractional * (yylval.nConstValue >= 0 ? 1 : -1);
 }
--- a/src/asm/math.c
+++ b/src/asm/math.c
@@ -20,7 +20,7 @@
 #include "asm/warning.h"
 
 #define fx2double(i)	((double)((i) / 65536.0))
-#define double2fx(d)	((int32_t)((d) * 65536.0))
+#define double2fx(d)	((int32_t)round((d) * 65536.0))
 
 #ifndef M_PI
 #define M_PI 3.14159265358979323846
--- /dev/null
+++ b/test/asm/fixed-point-precision.asm
@@ -1,0 +1,11 @@
+f1 = 3.1
+f2 = 5.2
+pm = MUL(f1, f2)
+pr = 16.12
+	println "`3.1`:   {9.6f:f1} -> ${08x:f1}"
+	println "`5.2`:   {9.6f:f2} -> ${08x:f2}"
+	println "`MUL`:   {9.6f:pm} -> ${08x:pm}"
+	println "`16.12`: {9.6f:pr} -> ${08x:pr}"
+
+fl = 6.283185
+	println "`6.283185`: {.6f:fl} -> ${08x:fl}"
--- /dev/null
+++ b/test/asm/fixed-point-precision.out
@@ -1,0 +1,5 @@
+`3.1`:    3.100007 -> $0003199a
+`5.2`:    5.199997 -> $00053333
+`MUL`:   16.120026 -> $00101eba
+`16.12`: 16.119996 -> $00101eb8
+`6.283185`: 6.283188 -> $0006487f
binary files a/test/asm/underscore-in-numeric-literal.out.bin b/test/asm/underscore-in-numeric-literal.out.bin differ