mirror of
https://github.com/kichikuou/xsystem35-sdl2.git
synced 2026-10-12 00:58:27 +03:00
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:
+17
-11
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
+5
-5
@@ -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":
|
||||
|
||||
Reference in New Issue
Block a user