You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

249 lines
6.0 KiB

/*
* Copyright 2002-2019 Intel Corporation.
*
* This software is provided to you as Sample Source Code as defined in the accompanying
* End User License Agreement for the Intel(R) Software Development Products ("Agreement")
* section 1.L.
*
* This software and the related documents are provided as is, with no express or implied
* warranties, other than those that are expressly stated in the License.
*/
/*
* A test which includes a large number of different push instructions.
*
* The idea is that we validate their behaviour here, so that we can check
* that they're still working correctly when we rewrite their addressing
* with Pin.
*
* Code assumes Gcc inline asm, so won't run on Windows.
* This shouldn't matter, since none of the rewriting is OS dependent.
*/
#include <stdio.h>
extern void * pushIW_(void *stack);
typedef long int addrint;
/* Macros for building test routines. */
#define switchStack(newSP) \
__asm__ ("mov %0,%%esp": :"r"(newSP): "%esp")
#define readStack(SP) \
__asm__ ("mov %%esp,%0": "=r"(SP) :: "%esp")
static void * pushI(void *stack)
{
// Don't use anything on the stack, since we're about to switch esp.
// (Since they're normally addressed relative to ebp locals should be OK,
// but this is safest)
register void * sp asm("%edx");
register void * osp asm("%ecx");
readStack(sp);
switchStack (stack);
__asm__ ("pushl $99");
readStack(osp);
switchStack(sp);
return osp;
}
static void * pushIW(void *stack)
{
// Don't use anything on the stack, since we're about to switch esp.
// (Since they're normally addressed relative to ebp locals should be OK,
// but this is safest)
register void * sp asm("%edx");
register void * osp asm("%ecx");
readStack(sp);
switchStack (stack);
__asm__ ("pushw $-5");
readStack(osp);
switchStack(sp);
return osp;
}
static void * pushSP(void *stack)
{
register void * sp asm("%edx");
register void * osp asm("%ecx");
readStack(sp);
switchStack (stack);
__asm__ ("pushl %esp");
readStack(osp);
switchStack(sp);
return osp;
}
static void * pushSPIndirect(void *stack)
{
register void * sp asm("%edx");
register void * osp asm("%ecx");
readStack(sp);
switchStack (stack);
__asm__ ("pushl (%esp)");
readStack(osp);
switchStack(sp);
return osp;
}
/* Can't easily check the results for this one, but at least we can
* see that the correct number of things were pushed.
*/
static void * pushA(void *stack)
{
register void * sp asm("%edx");
register void * osp asm("%ecx");
readStack(sp);
switchStack (stack);
__asm__ ("pusha");
readStack(osp);
switchStack(sp);
return osp;
}
/* Can't easily check the results for this one, but at least we can
* see that the correct number of things were pushed.
*/
static void * pushF(void *stack)
{
register void * sp asm("%edx");
register void * osp asm("%ecx");
readStack(sp);
switchStack (stack);
__asm__ ("pushf");
readStack(osp);
switchStack(sp);
return osp;
}
static unsigned char xlat(unsigned char * base, unsigned char index)
{
// ebx is the PIC register, but its use is fixed in xlat. Preserve original value.
register unsigned char result asm ("%al") = index;
__asm__ (
"movl %%ebx, %%edx;"
"movl %2, %%ebx;"
"xlat;"
"movl %%edx, %%ebx;"
: "=a"(result)
: "0"(result), "m"(base)
: "%edx");
return result;
}
static int xlatTest()
{
unsigned char notV[256];
unsigned char xlated[256];
int i;
int failures = 0;
for (i=0;i<256; i++)
{
notV[i] = (unsigned char)~i;
}
for (i=0;i<256;i++)
{
xlated[i] = xlat(notV, (unsigned char)i);
}
for (i=0; i<256; i++)
{
if (xlated[i] != notV[i])
{
printf("XLAT failed : got %02x expected %02x\n", xlated[i], notV[i]);
failures++;
}
}
printf ("XLAT test %s\n", failures ? "FAILED" : "Passed");
return failures;
}
struct result
{
void * before;
void * after;
addrint expected;
addrint seen;
};
int printResult (const char * test, struct result *r)
{
printf ("%-8s %p %p %4ld %010p %010p %7ld\n",
test, r->before, r->after,
(int)(((char *)r->after) - (char *)r->before),
(void *) r->expected, (void *)r->seen, r->seen - r->expected);
return (r->expected != r->seen);
}
int main (int argc, char ** argv)
{
struct result r;
addrint stack[32];
addrint * stackp = &stack[32];
int failures = xlatTest();
printf (" Stack Pointer Value\n");
printf ("Test Before After Delta Expect See Delta\n");
r.before = stackp;
r.after = pushI(stackp);
r.expected = 99;
r.seen = stack[31];
failures += printResult ("I",&r);
r.before = stackp;
r.after = pushIW_(stackp); // Since ICC 11 is not supporting pushw in it's inline asm, the pushIW changed to an asm version pushIW_
r.expected = -5;
r.seen = *(short *)(((char *)stackp)-2);
failures += printResult ("IW",&r);
r.before = stackp;
r.after = pushSP(stackp);
r.expected = (addrint)stackp; /* push esp is an interesting case. See esp before decrement. */
r.seen = stack[31];
failures += printResult ("%esp",&r);
stack[31] = 101;
r.before = stackp-1;
r.after = pushSPIndirect(r.before);
r.expected = 101;
r.seen = stack[30];
failures += printResult("(%esp)", &r);
r.before = stackp;
r.after = pushA(stackp);
r.expected = 0;
r.seen = 0;
failures += printResult ("pusha",&r);
printf ("Flags result varies, not counted as a failure\n");
r.before = stackp;
r.after = pushF(stackp);
r.expected = 0x286;
r.seen = stack[31];
printResult ("pushf",&r);
printf ("Done\n");
return failures;
}