Hello NG, I've got the following problem: I want to store the current position in a interrupt routine and leave it. By entering the routine after the next interrupt, I want to jump to this stored position. My first idea was the following: void irq (void) interrupt 0x14 using irq_level_2 { static int flag = 0; static void (*cont_here) (); if (flag!=0) goto *cont_here; ... if (something) { flag = 1; cont_here = &here1; goto end_irq; } here1: ... if (something_else) { flag = 1; cont_here = &here2; goto end_irq; } here2: ... end_irq: } But it doesn't work, 'cause labels and variables aren't the same and goto *bla doesn't work. Is there a solution besides the using of setjmp and longjump (which got too much, in this case, senseless overhead)? Thanks for any ideas - Peter
If you need to jump to one of a few points in a function, maybe you should use 'switch/case' as Jon Young proposed because that is exactly what 'switch' does ('case X' labels work just like ordinary labels, although you cannot 'goto case X'). If you are determined to use C/asm mixing (which in my view is only justified when 'C approach' has proved too slow) then you will have to deal with low-level stuff like C166 instruction set, interfacing between C and assembler, naming conventions, memory models and so on. To find out how it works I compiled C code and looked through generated *.SRC files (that's how I knew about ?function_name?label_name). As for storing address of a label in a variable and using it as a target for a jump (which does not look like an elegant solution at all), this is one of the ways to go:
void (*fptr)(void) = 0; void isr(void) interrupt INT_NO using RB { if ( fptr ) { fptr(); return; // or _push_((int)fptr); #pragma asm RET #pragma endasm } if ( /* some condition */ ) { #pragma asm SCXT R1, #?isr?label1 MOV fptr, R1 POP R1 #pragma endasm } else { #pragma asm SCXT R1, #?isr?label2 MOV fptr, R1 POP R1 #pragma endasm } label1: _nop_(); label2: _nop_(); }
Thanks, Mike! I will continue to find a solution at monday. So have a nice Weekend - Peter