Closed cocoacrumbs closed 2 years ago
Regarding the "optimized out" part, have you tried __attribute__((optnone))
?
Hi,
To avoid confusion I tried your suggestion like so:
__attribute__((__interrupt__))
__attribute__((optnone))
void interrupt_code_generation_test(void)
{
int a;
int b;
int c;
a = 1;
b = 2;
c = a + b;
} /* end interrupt_code_generation_test */
void non_interrupt_code_generation_test(void)
{
int a;
int b;
int c;
a = 1;
b = 2;
c = a + b;
} /* end non_interrupt_code_generation_test */
int main(void)
{
int a;
int b;
int c;
a = 1;
b = 2;
c = a + b;
return c;
} /* end main */
And this is the resulting assembly:
section .text,"ax",@progbits
assume adl = 1
section .text,"ax",@progbits
public _interrupt_code_generation_test
_interrupt_code_generation_test:
exx
ld iy, 0
add iy, sp
ld hl, -9
add hl, sp
ld sp, hl
ld hl, 1
ld de, 2
ld (iy - 9), hl
ld (iy - 12), de
ld hl, (iy - 9)
ld de, (iy - 12)
add hl, de
ld (iy - 15), hl
ld hl, 9
add hl, sp
ld sp, hl
exx
ret
section .text,"ax",@progbits
section .text,"ax",@progbits
public _non_interrupt_code_generation_test
_non_interrupt_code_generation_test:
ret
section .text,"ax",@progbits
section .text,"ax",@progbits
public _main
_main:
ld hl, 3
ret
section .text,"ax",@progbits
ident "clang version 14.0.0 (https://github.com/jacobly0/llvm-project.git b1303ec02a1932c74c306658339d3386d7f46b47)"
extern __Unwind_SjLj_Register
extern __Unwind_SjLj_Unregister
So, it seems that __attribute__((optnone))
works :-)
Best regards,
Koen
User interrupt handling was removed before I ever got around to implement it, if you could provide the asm you want it to generate I can work on it.
Also, it's normal for a function that does nothing to be optimized to a function that does nothing, but you still need a ret
to return from the routine of course.
Hi,
Looking at the output of the Zilog compiler when the #pragma interrupt
is used, then I see that this code sequence is generated:
exx
ex af, af'
; interrupt handling code
exx
ex af, af'
ei
reti
Attached a zip file with various files that might help to understand what code needs to be generated based on a real, working interrupt handling code for uart0
(basically a copy of the one present in the Zilog ZDS II toolchain).
In the asm
sub folder you'll find:
isruart0.c
: the original source codeisruart0-no-interrupt.asm
: the assembly code that the C compiler generatedisruart0-with-interrupt.asm
: the same as isruart0-no-interrupt.asm
but I manually added the needed instructions so that it properly can handle an interrupt. I tested these manual changes and it works.The other files in the root directory might give more insight maybe how the C compiler currently generates assembly code:
isruart0-no-attribute-interrupt.*
: C source code without __attribute__((__interrupt__))
and the generated assembly code.isruart0-attribute-interrupt.*
: C source code with __attribute__((__interrupt__))
and the generated assembly code.isruart0-attribute-interrupt-and-patch.c.lst
: Generated assembly code when my patch is applied to generate the missing instructions with __attribute__((__interrupt__))
.But, with this patch applied, the code is still not working. When I compare isruart0-no-attribute-interrupt.c.lst
and isruart0-attribute-interrupt-and-patch.c.lst
I still see a few differences in the interrupt handling code itself:
lea hl, ix - 5 lea hl, ix - 5 <== wrong offset?
...
ld (ix - 5), l ld (ix - 20), l
...
.LBB0_8:
ld l, (ix - 5) ld l, (ix - 20)
...
.LBB0_25:
ld l, (ix - 5) ld l, (ix - 20)
As my manually modified assembly code in the asm
directory illustrated, the code works without different offsets.
Something else I bumped into when I tried comparing the output with x86-64 assembly. I got this error message:
$ clang main.c -S
main.c:3:1: error: x86-64 'interrupt' attribute only applies to functions that have only a pointer parameter optionally followed by an integer parameter
__attribute__((__interrupt__))
I don't know if this only applies to x86-64 code or for all cpu's. I tried changing the code to void isr_uart0(void *framePtr);
but that made no difference for me.
I hope this can help a bit to get to working interrupt handling code? The patch I mentioned is attached to my initial comment when I opened this issue.
I still have no clue what the expected output is so closing unless there are still issues.
Hi,
I tried using
__attribute__((__interrupt__))
so that a C routine is called when an interrupt happens but I discovered the following:ex af, af'
instruction at the beginning and end of the interrupt routine. Theexx
instruction is generated.ret
instruction while this should be areti
instruction.ei
instruction at the end of the interrupt routine.ld (ix - nn), rr
instructions are wrong.Consider the following C code:
I get the following assembly code back when using this command line
./ez80-none-elf-clang -S -target ez80-none-elf main.c
:In the assembly code we can see that the offsets in
_interrupt_code_generation_test
are different than those (correctly) generated for_non_interrupt_code_generation_test
.We also see that for
_interrupt_code_generation_test
, theex af, af'
,reti
andei
instructions are missing.I was able to work around this with a small wrapper assembly code like this to implement the
isr_uart0()
routine:with
_isr_uart0
being a normal C function with this prototypevoid isr_uart0(void)
and without the__attribute__((__interrupt__))
of course. Implemented like this I got a workinguart0
interrupt routine .This is also the way how the ZDS II C compiler generates code for C functions preceded by the
#pragma interrupt
. I.e. starting with anex af, af'
andexx
and ending withex af, af'
,exx
,ei
andreti
.Attached you can find a patch which generates the assembly code as described above but it might need improvements (I'm a total newbie regarding debugging compilers).
I did not find what causes the wrong offsets when
__attribute__((__interrupt__))
is used (that will take a lot more time to study for me).A minor problem arises when optimization is used. E.g. using this command line:
./ez80-none-elf-clang -S -target ez80-none-elf main.c -O1
:The problems I have here are:
_interrupt_code_generation_test
and_non_interrupt_code_generation_test
there is still aret
instruction left that probably shouldn't be there?Best regards,
Koen
0004-Fix-EI-RETI_partial-fix.patch.zip