#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "tests/malloc.h"

typedef  unsigned char           UChar;
typedef  unsigned int            UInt;
typedef  unsigned long int       UWord;
typedef  unsigned long long int  ULong;


typedef  struct { UChar cs[40]; }  Block;

void showBlock ( char* msg, Block* b )
{
   int i;
   printf("  %s ", msg);
   for (i = 0; i < 40; i++) 
      printf("%02x", (UInt)b->cs[i]);
   printf("\n");
}

UChar randUChar ( void )
{
   static UInt seed = 80021;
   seed = 1103515245 * seed + 12345;
   return (seed >> 17) & 0xFF;
}

void randBlock ( Block* b )
{
   int i;
   UChar* p = (UChar*)b;
   for (i = 0; i < sizeof(Block); i++)
      p[i] = randUChar();
}

/* Generate a function test_NAME, that tests the given insn.
   The insn may only mention (%eax) and esi. */

#define GEN_test_Monly(_name, _mem_form)   \
    \
    __attribute__ ((noinline)) static void test_##_name ( void )   \
    { \
       Block* b = memalign32(sizeof(Block)); \
       randBlock(b); \
       printf("%s\n", #_name); \
       showBlock("before", b); \
       __asm__ __volatile__( \
          "leal      16(%0),%%eax"  "\n\t" \
          "movl      24(%0),%%esi"   "\n\t" \
          _mem_form  "\n\t" \
          "movl      %%esi, 32(%0)"  "\n\t" \
          : /*OUT*/  \
          : /*IN*/"r"(b) \
          : /*TRASH*/"esi","eax","memory","cc" \
       ); \
       showBlock("after ", b); \
       printf("\n"); \
       free(b); \
    }

GEN_test_Monly( MOVBE_RtoM_32, "movbel %%esi,1(%%eax)")
GEN_test_Monly( MOVBE_RtoM_16, "movbew %%si,1(%%eax)")

GEN_test_Monly( MOVBE_MtoR_32, "movbel 1(%%eax), %%esi")
GEN_test_Monly( MOVBE_MtoR_16, "movbew 1(%%eax), %%si")

int main ( void )
{
   test_MOVBE_RtoM_32();
   test_MOVBE_RtoM_16();
   test_MOVBE_MtoR_32();
   test_MOVBE_MtoR_16();
   return 0;
}