How about something like Sparc, where you can pass up to 8 arguments (if I
remember correctly) in registers. I'm not sure how Sparc handles varargs
functions, though.
Indeed, but you've probably already lost that by using va_start().
Well, they'll be the context of panic() in your implementation.
Yes. The easiest way might be to write the saver in assembly and call it from
within an inline asm statement.
Indeed, but the more things panic() does, the more likely it is to clobber
registers anyway.
Note, also: panic() is __attribute__((noreturn)), which means that the
compiler calling it is not required to save the return address or registers
before jumping to panic() or even in panic() itself.
As I mentioned above, you can use asm for this. For instance, you can write
an inline asm statement that saves onto the stack the registers that need to
be clobbered to make a jump, then make the jump, and then have the saver
routine retrieve the register values from the stack and place them in the
storage area.
In fact, you could insert a prologue wrapper on panic() with a bit of asm to
save the registers, for example on FRV:
panic:
subi sp,#-8,sp
stdi.p gr4,@(sp,#0) # save GR4/GR5 on stack
addi sp,#8,gr5
sethi.p %hi(__panic_reg_save),gr4 # get the save space addr
setlo %lo(__panic_reg_save),gr4
sti gr5,@(gr4,#REG_SP)) # save orig stack pointer
stdi gr2,@(gr4,#REG_GR(2)) # save GR2/GR3
ldi @(sp,#0),gr5
sti gr5,@(gr4,#REG_GR(4)) # save orig GR4
ldi @(sp,#4),gr5
sti gr5,@(gr4,#REG_GR(5)) # save orig GR5
stdi gr6,@(gr4,#REG_GR(6)) # save GR6/GR7
stdi gr8,@(gr4,#REG_GR(8)) # save GR8/GR9
...
lddi.p @(sp,#0),gr4 # restore GR4/GR5 from stack
addi sp,#8,sp
bra real_panic # chain
Then real_panic() would be the original C panic function.
Most load/store instructions come in two types, and you need to modify the
opcode according to the addressing mode and indicate that you're interpolating
a memory dereference argument rather than an address:
asm("ldd%I1 %M1,%0"
: "=e"(counter)
: "m"(v->counter));
You're also trying to load data into GR0 which won't achieve anything. GR0 is
hardwired to 0. It's used as the target of instructions where you don't care
about the calculated result (eg: compare is implemented as subtract to GR0),
and as a source of 0.
David
--