prof: properly save and restore RARG for amd64

amd64 passes first argument in RARG (BP) register
which has the be preserved duing _profin() and
_profout() calls. to handle this we introduce
_saveret() and _savearg(). _saveret() returns
AX, _savearg() returns RARG (BP). for archs other
and amd64, _saveret() and _savearg() are the
same function, doing nothing.

restoing works with dummy function:

uintptr
_restore(uintptr, uintptr ret)
{
	return ret;
}

...

ret = _saveret();
arg = _savearg();
...
return _restore(arg, ret);

as we pass arg as the first argument, RARG (BP) is
restored.
This commit is contained in:
cinap_lenrek 2014-02-17 13:25:24 +01:00
parent 87fcb107ef
commit 2c5c784255
18 changed files with 56 additions and 24 deletions

View file

@ -40,6 +40,7 @@ loop:
MOVL $0, AX MOVL $0, AX
JMP loop JMP loop
TEXT _saveret(SB), 1, $0
TEXT _savearg(SB), 1, $0 TEXT _savearg(SB), 1, $0
RET RET

View file

@ -43,6 +43,7 @@ loop:
MOVQ $_profin(SB), R31 /* force loading of profile */ MOVQ $_profin(SB), R31 /* force loading of profile */
JMP loop JMP loop
TEXT _saveret(SB), 1, $0
TEXT _savearg(SB), 1, $0 TEXT _savearg(SB), 1, $0
RET RET

View file

@ -37,7 +37,11 @@ loop:
MOVL $0, AX MOVL $0, AX
JMP loop JMP loop
TEXT _saveret(SB), 1, $0
RET
TEXT _savearg(SB), 1, $0 TEXT _savearg(SB), 1, $0
MOVQ RARG, AX
RET RET
TEXT _callpc(SB), 1, $0 TEXT _callpc(SB), 1, $0

View file

@ -47,6 +47,7 @@ loop:
MOVW $_profin(SB), R(arg) /* force loading of profile */ MOVW $_profin(SB), R(arg) /* force loading of profile */
B loop B loop
TEXT _saveret(SB), 1, $0
TEXT _savearg(SB), 1, $0 TEXT _savearg(SB), 1, $0
RET RET

View file

@ -49,6 +49,7 @@ loop:
MOVW $_profin(SB), R0 /* force loading of profile */ MOVW $_profin(SB), R0 /* force loading of profile */
JMP loop JMP loop
TEXT _saveret(SB), 1, $0
TEXT _savearg(SB), 1, $0 TEXT _savearg(SB), 1, $0
RET RET

View file

@ -23,7 +23,8 @@ typedef unsigned long long uvlong;
extern void* sbrk(ulong); extern void* sbrk(ulong);
extern long _callpc(void**); extern long _callpc(void**);
extern long _savearg(void); extern void* _savearg(void);
extern void* _saveret(void);
extern void _cycles(uvlong*); /* 64-bit value of the cycle counter if there is one, 0 if there isn't */ extern void _cycles(uvlong*); /* 64-bit value of the cycle counter if there is one, 0 if there isn't */
static ulong khz; static ulong khz;
@ -43,20 +44,27 @@ struct Plink
#pragma profile off #pragma profile off
ulong static void*
_restore(void*, void *ret)
{
return ret;
}
void*
_profin(void) _profin(void)
{ {
void *dummy; void *dummy;
long pc; long pc;
Plink *pp, *p; Plink *pp, *p;
ulong arg; void *ret, *arg;
vlong t; vlong t;
ret = _saveret();
arg = _savearg(); arg = _savearg();
pc = _callpc(&dummy); pc = _callpc(&dummy);
pp = _tos->prof.pp; pp = _tos->prof.pp;
if(pp == 0 || (_tos->prof.pid && _tos->pid != _tos->prof.pid)) if(pp == 0 || (_tos->prof.pid && _tos->pid != _tos->prof.pid))
return arg; return _restore(arg, ret);
for(p=pp->down; p; p=p->link) for(p=pp->down; p; p=p->link)
if(p->pc == pc) if(p->pc == pc)
@ -65,7 +73,7 @@ _profin(void)
if(p >= _tos->prof.last){ if(p >= _tos->prof.last){
_tos->prof.pp = 0; _tos->prof.pp = 0;
perr++; perr++;
return arg; return _restore(arg, ret);
} }
_tos->prof.next = p; _tos->prof.next = p;
p->link = pp->down; p->link = pp->down;
@ -96,16 +104,17 @@ out:
p->time = p->time - _tos->clock; p->time = p->time - _tos->clock;
break; break;
} }
return arg; /* disgusting linkage */ return _restore(arg, ret);
} }
ulong void*
_profout(void) _profout(void)
{ {
Plink *p; Plink *p;
ulong arg; void *ret, *arg;
vlong t; vlong t;
ret = _saveret();
arg = _savearg(); arg = _savearg();
p = _tos->prof.pp; p = _tos->prof.pp;
if (p == NULL || (_tos->prof.pid != 0 && _tos->pid != _tos->prof.pid)) if (p == NULL || (_tos->prof.pid != 0 && _tos->pid != _tos->prof.pid))
@ -127,7 +136,7 @@ _profout(void)
break; break;
} }
_tos->prof.pp = p->old; _tos->prof.pp = p->old;
return arg; return _restore(arg, ret);
} }
/* stdio may not be ready for us yet */ /* stdio may not be ready for us yet */

View file

@ -40,6 +40,7 @@ loop:
MOVW $_profin(SB), R4 /* force loading of profile */ MOVW $_profin(SB), R4 /* force loading of profile */
BR loop BR loop
TEXT _saveret(SB), 1, $0
TEXT _savearg(SB), 1, $0 TEXT _savearg(SB), 1, $0
RETURN RETURN

View file

@ -48,6 +48,7 @@ loop:
MOVW $_profin(SB), R0 /* force loading of profile */ MOVW $_profin(SB), R0 /* force loading of profile */
JMP loop JMP loop
TEXT _saveret(SB), 1, $0
TEXT _savearg(SB), 1, $0 TEXT _savearg(SB), 1, $0
RETURN RETURN

View file

@ -26,6 +26,7 @@ loop:
MOVL $_profin(SB), AX /* force loading of profile */ MOVL $_profin(SB), AX /* force loading of profile */
JMP loop JMP loop
TEXT _saveret(SB), 1, $0
TEXT _savearg(SB), 1, $0 TEXT _savearg(SB), 1, $0
RET RET

View file

@ -19,6 +19,7 @@ loop:
LEA _profin(SB), A0 /* force loading of profile */ LEA _profin(SB), A0 /* force loading of profile */
BRA loop BRA loop
TEXT _saveret(SB), 1, $0
TEXT _savearg(SB), 1, $0 TEXT _savearg(SB), 1, $0
RTS RTS

View file

@ -20,6 +20,7 @@ loop:
LEA _profin(SB), A0 /* force loading of profile */ LEA _profin(SB), A0 /* force loading of profile */
BRA loop BRA loop
TEXT _saveret(SB), 1, $0
TEXT _savearg(SB), 1, $0 TEXT _savearg(SB), 1, $0
RTS RTS

View file

@ -26,6 +26,7 @@ loop:
MOVQ $_profin(SB), R31 /* force loading of profile */ MOVQ $_profin(SB), R31 /* force loading of profile */
JMP loop JMP loop
TEXT _saveret(SB), 1, $0
TEXT _savearg(SB), 1, $0 TEXT _savearg(SB), 1, $0
RET RET

View file

@ -28,9 +28,6 @@ TEXT _savearg(SB), 1, $0
RET RET
TEXT _saveret(SB), 1, $0 TEXT _saveret(SB), 1, $0
RET
TEXT _restorearg(SB), 1, $0
RET /* we want RARG in RARG */ RET /* we want RARG in RARG */
TEXT _callpc(SB), 1, $0 TEXT _callpc(SB), 1, $0

View file

@ -31,6 +31,7 @@ loop:
MOVW $_profin(SB), R(arg) /* force loading of profile */ MOVW $_profin(SB), R(arg) /* force loading of profile */
B loop B loop
TEXT _saveret(SB), 1, $0
TEXT _savearg(SB), 1, $0 TEXT _savearg(SB), 1, $0
RET RET

View file

@ -25,6 +25,7 @@ loop:
MOVW $_profin(SB), R0 /* force loading of profile */ MOVW $_profin(SB), R0 /* force loading of profile */
JMP loop JMP loop
TEXT _saveret(SB), 1, $0
TEXT _savearg(SB), 1, $0 TEXT _savearg(SB), 1, $0
RET RET

View file

@ -2,8 +2,9 @@
#include <libc.h> #include <libc.h>
#include <tos.h> #include <tos.h>
extern long _callpc(void**); extern uintptr _callpc(void**);
extern long _savearg(void); extern uintptr _saveret(void);
extern uintptr _savearg(void);
static ulong khz; static ulong khz;
static ulong perr; static ulong perr;
@ -22,21 +23,27 @@ struct Plink
#pragma profile off #pragma profile off
ulong static uintptr
_restore(uintptr, uintptr ret)
{
return ret;
}
uintptr
_profin(void) _profin(void)
{ {
void *dummy; void *dummy;
long pc; long pc;
Plink *pp, *p; Plink *pp, *p;
ulong arg; uintptr arg, ret;
vlong t; vlong t;
ret = _saveret();
arg = _savearg(); arg = _savearg();
pc = _callpc(&dummy); pc = _callpc(&dummy);
pp = _tos->prof.pp; pp = _tos->prof.pp;
if(pp == 0 || (_tos->prof.pid && _tos->pid != _tos->prof.pid)) if(pp == 0 || (_tos->prof.pid && _tos->pid != _tos->prof.pid))
return arg; return _restore(arg, ret);
for(p=pp->down; p; p=p->link) for(p=pp->down; p; p=p->link)
if(p->pc == pc) if(p->pc == pc)
goto out; goto out;
@ -44,7 +51,7 @@ _profin(void)
if(p >= _tos->prof.last) { if(p >= _tos->prof.last) {
_tos->prof.pp = 0; _tos->prof.pp = 0;
perr++; perr++;
return arg; return _restore(arg, ret);
} }
_tos->prof.next = p; _tos->prof.next = p;
p->link = pp->down; p->link = pp->down;
@ -75,20 +82,21 @@ out:
p->time = p->time - _tos->clock; p->time = p->time - _tos->clock;
break; break;
} }
return arg; /* disgusting linkage */ return _restore(arg, ret);
} }
ulong uintptr
_profout(void) _profout(void)
{ {
Plink *p; Plink *p;
ulong arg; uintptr ret, arg;
vlong t; vlong t;
ret = _saveret();
arg = _savearg(); arg = _savearg();
p = _tos->prof.pp; p = _tos->prof.pp;
if (p == nil || (_tos->prof.pid != 0 && _tos->pid != _tos->prof.pid)) if (p == nil || (_tos->prof.pid != 0 && _tos->pid != _tos->prof.pid))
return arg; /* Not our process */ return _restore(arg, ret); /* Not our process */
switch(_tos->prof.what){ switch(_tos->prof.what){
case Profkernel: /* Add proc cycles on proc entry */ case Profkernel: /* Add proc cycles on proc entry */
p->time = p->time + _tos->pcycles; p->time = p->time + _tos->pcycles;
@ -106,7 +114,7 @@ _profout(void)
break; break;
} }
_tos->prof.pp = p->old; _tos->prof.pp = p->old;
return arg; return _restore(arg, ret);
} }
void void

View file

@ -26,6 +26,7 @@ loop:
MOVW $_profin(SB), R3 /* force loading of profile */ MOVW $_profin(SB), R3 /* force loading of profile */
BR loop BR loop
TEXT _saveret(SB), 1, $0
TEXT _savearg(SB), 1, $0 TEXT _savearg(SB), 1, $0
RETURN RETURN

View file

@ -33,6 +33,7 @@ loop:
MOVW $_profin(SB), R9 /* force loading of profile */ MOVW $_profin(SB), R9 /* force loading of profile */
JMP loop JMP loop
TEXT _saveret(SB), 1, $0
TEXT _savearg(SB), 1, $0 TEXT _savearg(SB), 1, $0
RETURN RETURN