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
Well, I don't think there is a way to know which register holds which variable unless you look at the compiled code. You cannot even be sure that a 'register' variable is actually stored in a register (imagine that you've declared more 'register' variables than there are registers). In this particular case you could try to use the system stack:
void function(void) { int jumplock; /* ... */ _push_(jumplock); #pragma asm RET #pragma endasm }
( (void (*)(void)) jumplock )(); return;
Hello, sounds well. > Chances are that the compiler will generate > 'JMPI' instead of 'CALLI/RET'. May this depend on some optimizing level? So far, the problem remains to put the address of a label in a variable. Your examples brought me to an idea like the following:
#pragma asm PUSH REG MOV REG, #?function_name?label_name MOV ?function_name?variable_name, REG POP REG #pragma endasm
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