Match variable bounds with System 3.9

System 3.9 saturates compound addition and multiplication at 65535,
while an overflowing ascending loop stores the wrapped 16-bit result
after testing the wide value.

Update the scenario expectations and regenerated fixture to cover both
cases. The suite passes with xsystem35 and the original System39.exe.
This commit is contained in:
kichikuou
2026-07-17 09:50:02 +09:00
parent a627a8ea3d
commit 30188c3a4f
3 changed files with 22 additions and 16 deletions
+17 -11
View File
@@ -50,6 +50,7 @@ static void commandsDEC() {
static void letVar(int type) {
vmvar_t *varno = getVariable();
int val = getCaliValue();
uint32_t result;
if (varno == NULL) {
WARNING("varno is NULL");
@@ -60,11 +61,15 @@ static void letVar(int type) {
case '!':
*varno = val; break;
case 0x10: /* += */
*varno = (uint16_t)(*varno + val); break;
result = (uint32_t)*varno + val;
*varno = result > UINT16_MAX ? UINT16_MAX : result;
break;
case 0x11: /* -= */
*varno = max(0, *varno - val); break;
case 0x12: /* *= */
*varno = (uint16_t)(*varno * val); break;
result = (uint32_t)*varno * val;
*varno = result > UINT16_MAX ? UINT16_MAX : result;
break;
case 0x13: /* /= */
if (val == 0) *varno = 0;
else *varno /= val;
@@ -101,7 +106,7 @@ static void getDataTableAdr() {
/* < ループ開始 */
static void loopStart() {
int p1 = sl_getc();
int exitadr, limit, direction, step;
int exitadr, limit, direction, step, value;
vmvar_t *var;
if (p1 == 0) {
@@ -116,32 +121,33 @@ static void loopStart() {
limit = getCaliValue();
direction = getCaliValue();
step = getCaliValue();
value = *var;
if (direction == 0) {
/* dec */
if (p1 == 1) {
*var -= step;
value -= step;
}
if (*var < limit) {
if (p1 == 0) *var-= step;
if (value < limit) {
if (p1 == 0) value -= step;
sl_jmpNear(exitadr);
if (*var < 0) { *var = 0; }
*var = max(0, value);
return;
}
} else if (direction == 1) {
/* inc */
if (p1 == 1) {
*var += step;
value += step;
}
if (*var > limit) {
// if (p1 == 0) *var+= step;
if (value > limit) {
sl_jmpNear(exitadr);
if (*var > 65535) { *var = 65535; }
*var = (uint16_t)value;
return;
}
} else {
undeferr();
}
*var = value;
return;
}
BIN
View File
Binary file not shown.
+5 -5
View File
@@ -24,16 +24,16 @@
dec value:
~AssertEquals value,0,__LINE__:
; Compound assignments preserve their documented wrap/saturate behavior.
; Compound arithmetic assignments saturate at the word bounds.
!value:65535!
!value+:1!
~AssertEquals value,0,__LINE__:
~AssertEquals value,65535,__LINE__:
!value:0!
!value-:1!
~AssertEquals value,0,__LINE__:
!value:32768!
!value*:2!
~AssertEquals value,0,__LINE__:
~AssertEquals value,65535,__LINE__:
!value:7!
!value/:2!
~AssertEquals value,3,__LINE__:
@@ -52,7 +52,7 @@
!value^:0x00ff!
~AssertEquals value,0x0f0f,__LINE__:
; FOR loops terminate after crossing either word boundary.
; FOR loops test the wide result, then store the terminal word value.
!count:0!
<value,1,0,0,2:
inc count:
@@ -64,7 +64,7 @@
inc count:
>
~AssertEquals count,1,__LINE__:
~AssertEquals value,65535,__LINE__:
~AssertEquals value,0,__LINE__:
; A module result above 65535 is observed through expressions as a word.
MS 10,"65536":