Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiler bug in DC 9.30 and later generates incorrect opcode sequence #9

Open
tomlogic opened this issue Dec 1, 2022 · 1 comment

Comments

@tomlogic
Copy link
Contributor

tomlogic commented Dec 1, 2022

Digi has discovered a bug present in Dynamic C 9.30 (but not 9.25) related to code generation for assigning 8-bit values to 16-bit variables via a pointer. The bug has been in all releases of Dynamic C from 9.30 through 9.62A.

Some examples of affected C statements:

pt->int_val = char_val;          // impacts pointers to structures
*stack_int_ptr = char_val;       // impacts pointers on stack
int_array[7] = char_val;         // impacts arrays w/constant index
int_array[int_val] = char_val;   // impacts arrays w/variable index
int_ptr[7] = char_val;           // impacts array syntax with pointer
*(int_ptr + 7) = char_val;       // impacts dereferenced pointer
int_ptr[int_val] = char_val;     // impacts pointer w/variable index

The work around is quite simple. Users can either wrap char_val in parentheses, or explicitly cast it to int:

*int_ptr = char_val;            // affected
*int_ptr = (char_val);          // workaround
*int_ptr = (int)char_val;       // workaround

Dynamic C 9.25 generates the following 11-byte opcode sequence – upon entry, HL holds the address of the integer destination:

1de9 E5       push   hl                10
1dea 2A1BB8   ld     hl,(0xB81B)       11
1ded 2600     ld     h,0x00             4
1def FDE1     pop    iy                 9
1df1 FDF400   ld     (iy+0),hl         13

Note the protection of HL before loading the byte at 0xB81B, and the use of IY to write the 16-bit value to memory.

Starting with Dynamic C 9.30, the compiler generates this 9-byte sequence:

1a88 3A18BA   ld a, (0xBA18)                 9
1a8b 6F       ld l, a                        2
1a8c 2600     ld h, 0x00                     4
1a8e DDF400   ld (hl + 0), hl                13

Effectively overwriting the destination address with the value to write.

To assess impact, customers can search their binary files for the sequence 6F 26 00 DD F4 00, which should be unique and unlikely to appear outside of this specific opcode sequence. They can also search the assembly listing (.LST file) for the DDF400 sequence corresponding to ld (hl + 0), hl which is unlikely to occur outside of this bug.

Users can patch the sequence after the ld a, (0xBA18) with the following opcodes, making it possible to "fix" existing .bin files containing the 6F 26 00 DD F4 00 sequence in cases where it isn't possible to update and re-compile source code.

77       ld (hl), a
23       inc hl
AF       xor a
77       ld (hl), a
2B       dec hl         ; restore original HL value
00       nop            ; keep original byte count

We don’t necessarily have to restore the HL value after the write, but we have two bytes to spare and might as well do it instead of just adding another NOP.

We are adding this as a KNOWN ISSUE and have no plans to update the compiler to fix this bug. This is the first report of the problem since releasing Dynamic C 9.30 over 16 years ago.

tomlogic added a commit that referenced this issue Dec 1, 2022
Corresponds to GitHub issue #9.
@tomlogic
Copy link
Contributor Author

tomlogic commented Dec 1, 2022

Be sure to "subscribe" to notifications for this issue to be kept up to date on any updates regarding this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant