1 /* bug-2822.c
2    Overwritten register in call to __z88dk_fastcall function pointer in struct.
3  */
4 
5 #include <testfwk.h>
6 
7 #include <stdint.h>
8 
9 #if !defined(__SDCC_z80) && !defined(__SDCC_z180) && !defined(__SDCC_r2k) && !defined(__SDCC_r3ka) && !defined(__SDCC_tlcs90)
10 #define __z88dk_fastcall
11 #endif
12 
13 #ifndef __SDCC_pdk14 // Lack of memory
14 struct wibble
15 {
16     int (*wobble)(uint8_t *x) __z88dk_fastcall __reentrant;
17 } w;
18 
19 struct wibble *wubble = &w;
20 uint8_t xp[4];
21 
foo(uint8_t minor)22 void foo(uint8_t minor)
23 {
24     uint8_t x;
25     uint8_t err;
26     uint8_t *bar = xp + minor;
27 
28     for(x = 0; x < 4; x++) {
29         err = wubble->wobble(bar);
30         if (err)
31             wubble->wobble(bar);
32     }
33 }
34 
35 uint8_t called;
36 
f(uint8_t * x)37 int f(uint8_t *x) __z88dk_fastcall __reentrant
38 {
39     ASSERT(*x == 0x5a);
40     called++;
41     return(1);
42 }
43 
44 struct wibble2
45 {
46     int (*wobble2)(uint32_t) __z88dk_fastcall __reentrant;
47 } w2;
48 
49 struct wibble2 *wubble2 = &w2;
50 uint32_t xp2[4];
51 
foo2(uint8_t minor)52 void foo2(uint8_t minor)
53 {
54     uint8_t x;
55     uint8_t err;
56     uint32_t *bar = xp2 + minor;
57 
58     for(x = 0; x < 4; x++) {
59         err = wubble2->wobble2(*bar);
60         if (err)
61             wubble2->wobble2(*bar);
62     }
63 }
64 
65 uint8_t called2;
66 
f2(uint32_t x)67 int f2(uint32_t x) __z88dk_fastcall __reentrant
68 {
69     ASSERT(x == 0x1155aa88);
70     called2++;
71     return(1);
72 }
73 #endif
74 
testBug(void)75 void testBug(void)
76 {
77 #ifndef __SDCC_pdk14 // Lack of memory
78     wubble->wobble = &f;
79     xp[1] = 0x5a;
80     foo(1);
81     ASSERT(called == 8);
82 
83     wubble2->wobble2 = &f2;
84     xp2[1] = 0x1155aa88;
85     foo2(1);
86     ASSERT(called2 == 8);
87 #endif
88 }
89 
90