Skip to content

Commit 5b554df

Browse files
committed
Add integer register preservation test
Test verifies that callee-saved integer registers are properly preserved across stack switches by: - Performing complex integer arithmetic with many intermediate values - Calling stackman_switch (should preserve register state) - Re-running same computation - Verifying bit-exact results match Uses multiple operations (multiply, add, shift, xor, or, and) to: - Create many live intermediate values - Pressure compiler to use callee-saved registers (s0-s11 on RISC-V, rbx/r12-r15 on x86_64, x19-x28 on ARM64) - Detect any register corruption from incorrect save/restore Complements test_07 (FP registers) to provide comprehensive register preservation validation.
1 parent adbed20 commit 5b554df

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed

tests/test.c

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,98 @@ void test_07(void)
376376
assert(sum2 == sum4);
377377
}
378378

379+
/* Test integer register preservation across stack switches.
380+
* This test verifies that callee-saved integer registers are properly
381+
* preserved across stack switches on all platforms.
382+
*
383+
* Uses complex integer arithmetic with many intermediate values to
384+
* pressure the compiler to use multiple registers.
385+
*/
386+
typedef struct int_test_context {
387+
void *saved_sp;
388+
int switch_done;
389+
} int_test_context;
390+
391+
void *test_08_cb(void* context, int opcode, void *sp)
392+
{
393+
int_test_context *c = (int_test_context*)context;
394+
395+
if (opcode == STACKMAN_OP_SAVE) {
396+
c->saved_sp = sp;
397+
return sp; /* No stack switch */
398+
} else {
399+
c->switch_done = 1;
400+
return sp;
401+
}
402+
}
403+
404+
/* Complex integer computation with many intermediate values
405+
* to encourage use of multiple callee-saved registers
406+
*/
407+
void test_08_compute(long *input, long *output, int count)
408+
{
409+
int i;
410+
/* Multiple operations creating intermediate values to stress register usage */
411+
for (i = 0; i < count; i++) {
412+
long a = input[i];
413+
long b = a * 123456789L;
414+
long c = b + 987654321L;
415+
long d = c ^ (a << 3);
416+
long e = d - (a * 7);
417+
long f = e | (b & 0xFF00FF00);
418+
long g = f + (c >> 2);
419+
long h = g ^ (d * 13);
420+
output[i] = h - (a + b + c);
421+
}
422+
}
423+
424+
void test_08(void)
425+
{
426+
int_test_context ctx;
427+
long input[16], output1[16], output2[16];
428+
int i;
429+
430+
/* Initialize input with varying values */
431+
for (i = 0; i < 16; i++) {
432+
input[i] = (long)(i + 1) * 314159L + i * 271828L;
433+
}
434+
435+
/* First computation - fills integer registers */
436+
test_08_compute(input, output1, 16);
437+
438+
/* Additional integer work to maximize register pressure */
439+
long sum1 = 0, sum2 = 0, xor1 = 0;
440+
for (i = 0; i < 16; i++) {
441+
sum1 += output1[i] * (i + 1);
442+
sum2 += input[i] << (i & 3);
443+
xor1 ^= (output1[i] + input[i]);
444+
}
445+
446+
/* Stack switch - all callee-saved integer registers must be preserved */
447+
memset(&ctx, 0, sizeof(ctx));
448+
stackman_switch(&test_08_cb, &ctx);
449+
assert(ctx.switch_done);
450+
451+
/* Second computation - should produce identical results */
452+
test_08_compute(input, output2, 16);
453+
454+
/* Verify outputs match exactly */
455+
for (i = 0; i < 16; i++) {
456+
assert(output1[i] == output2[i]);
457+
}
458+
459+
/* Verify accumulated values still work */
460+
long sum3 = 0, sum4 = 0, xor2 = 0;
461+
for (i = 0; i < 16; i++) {
462+
sum3 += output2[i] * (i + 1);
463+
sum4 += input[i] << (i & 3);
464+
xor2 ^= (output2[i] + input[i]);
465+
}
466+
assert(sum1 == sum3);
467+
assert(sum2 == sum4);
468+
assert(xor1 == xor2);
469+
}
470+
379471
int main(int argc, char*argv[])
380472
{
381473
int stack_marker = 0;
@@ -396,5 +488,7 @@ int main(int argc, char*argv[])
396488
printf("test_06 ok\n");
397489
test_07();
398490
printf("test_07 ok\n");
491+
test_08();
492+
printf("test_08 ok\n");
399493
return 0;
400494
}

0 commit comments

Comments
 (0)