randinst.c 5.98 KB

/**************************************************************************
 *                                                                        *
 *               Copyright (C) 1994, Silicon Graphics, Inc.               *
 *                                                                        *
 *  These coded instructions, statements, and computer programs  contain  *
 *  unpublished  proprietary  information of Silicon Graphics, Inc., and  *
 *  are protected by Federal copyright  law.  They  may not be disclosed  *
 *  to  third  parties  or copied or duplicated in any form, in whole or  *
 *  in part, without the prior written consent of Silicon Graphics, Inc.  *
 *                                                                        *
 *************************************************************************/

/*
 * File:	randinst.c
 * Creator:	rww@sgi.com
 * Create Date:	Wed Sep 28 13:52:37 PDT 1994
 *
 * This file has some functions to generate random instructions.
 *
 */

#include <stdio.h>
#include <string.h>

typedef unsigned long int	u32;

void rsp_DisasmInst( u32, char *, int );
u32 R32(void);
void init_random(void);
u32 rand_inst( char *buf, int pc );

#define NUM_INSTS	(1024)

#define LOADS	"lw", "lh", "lb"
#define STORES	"sw", "sh", "sb"
#define MULTS	"mult", "div"
#define BRNCHES	"b", "j"
#define COPROCS	"mt", "mf", "ctc", "cfc", "bc0"
#define VLOADS	"lpv", "lrv", "lqv", "ltv", "luv", "lsv", "lav", "llv", "ldv", "lfv"
#define VSAVES	"spv", "srv", "sqv", "stv", "suv", "ssv", "sav", "slv", "sdv", "sfv"
#define VECTOPS	"v"

char *special_list[100] = { NULL };
int  special_and[100];
int  special_or[100];

char *skip_list[100] = { NULL };

void skip_list_read( char * );

char *branch_list[10] = {    BRNCHES };
char *vect_list[10]   = {    VECTOPS };

int count;

main( int argc, char **argv )
{
    int i, c;
    u32 inst;
    char buf[80];
    FILE *insts;
    int first_branch;
    int branch;

    if( argc <= 1 ) {
	fprintf(stderr,"Usage: %s bad_insts_file\n", argv[0] );
	exit(1);
    };

    skip_list_read( argv[1] );

    insts = fopen("insts","w");

    init_random();

    /* Remember if first inst is a branch */

    i = 0;
    inst = rand_inst( buf, i );
    first_branch = inst_check( buf, branch_list );

    printf("pc%03x:\t%-30s\t# 0x%08x (%d)\n", 4*i, buf, inst, count );
    fwrite( & inst, sizeof( inst ), 1, insts );

    for(i=1; i<NUM_INSTS-1; i++) {

	inst = rand_inst( buf, i*4 );

	printf("pc%03x:\t%-30s\t# 0x%08x (%d)\n", 4*i, buf, inst, count );
	fwrite( & inst, sizeof( inst ), 1, insts );
    };

    /* Make sure first and last aren't BOTH branches */

    /* Doesn't handle case of :

	0000: b
	.
	.
	.
	1022: b
	1023: v

	or

	0000: v
	0001: b
	.
	.
	.
	1023: b
    */

    do {

	inst = rand_inst( buf, i );
	branch = inst_check( buf, branch_list );

    } while( branch && first_branch );

    printf("pc%03x:\t%-30s\t# 0x%08x (%d)\n", 4*i, buf, inst, count );
    fwrite( & inst, sizeof( inst ), 1, insts );

    fclose( insts );
}

#define SPECIAL_MASK	(~(0x3f<<26))
#define VECTOR_MASK	(0x12<<26)
#define VLOAD_MASK	(0x32<<26)
#define VSTOR_MASK	(0x3a<<26)


u32
rand_inst( char *buf, int pc )
{
    u32 inst;
    int branch;
    int vect;
    int indx;
    static int prev_branch = 0;
    static int prev_vect = 0;

    count = 0;
    do {
	inst = R32();
	if( random() & 1 )
	    inst = VECTOR_MASK | (inst & SPECIAL_MASK);
	else if( random() & 1 ) {
	    if( random() & 1 )
		inst = VLOAD_MASK | (inst & SPECIAL_MASK);
	    else
		inst = VSTOR_MASK | (inst & SPECIAL_MASK);
	} else if( random() & 0x3 )
	    inst &= SPECIAL_MASK;

	rsp_DisasmInst( inst, buf, pc );

	branch = inst_check( buf, branch_list );
	count++;
    } while( inst_check( buf, skip_list ) ||
	     (branch && prev_branch) );

    if( indx = inst_check( buf, special_list ) ) {

#ifdef SPECIAL_TRACE
	fprintf(stderr,"Special_inst(%d) <%s> & 0x%08x | 0x%08x => ", indx-1,
			buf, special_and[indx-1], special_or[indx-1] );
#endif

	inst = (inst & special_and[indx-1]) | special_or[indx-1];

	rsp_DisasmInst( inst, buf, pc );

#ifdef SPECIAL_TRACE
	fprintf(stderr,"<%s>\n", buf );
#endif
    };

    vect = inst_check( buf, vect_list );
    if( prev_branch && vect && !prev_vect )	/* b+v => b */
	prev_branch = 1;
    else
	prev_branch = branch;

    prev_vect = vect;

    return( inst );
}

int
inst_check( char *buf, char *skips[] )
{
    int i, len;

    for(i=0; skips[i] != NULL; i++) {
	len = strlen( skips[i] );
	if( len == 0 )
	    break;
	
	if( strncmp( buf, skips[i], len ) == 0 )
	    return( i+1 );
    };

    return( 0 );
}

void
init_random( void )
{
    int rseed;

    rseed = time( 0 );
    srandom(rseed);
}

u32
R32( void )
{
    return( (random()<<1) | (random() & 1) );
}

#include <ctype.h>

#define BUFLEN	(1024)

void
skip_list_read( char *fname )
{
    FILE *skipfile;
    char buf[BUFLEN];
    char *b, *word;
    int sknum;
    int spnum;
    int special;

    skipfile = fopen( fname, "r" );
    if( skipfile == NULL ) {
	fprintf(stderr,"Couldn't open <%s>", fname);
	perror(":");
	exit(2);
    };

    for( sknum=0; skip_list[sknum] != NULL; sknum++ )
	;

    for( spnum=0; special_list[spnum] != NULL; spnum++ )
	;

    while( fgets( buf, BUFLEN, skipfile ) != NULL ) {

	if( buf[0] == '#' )	/* Skip comment lines */
	    continue;

	b=buf;

	special = 0;

/*
	Format for Special lines:

	$ Inst_name And_mask Or_mask

	Ex.

	$ lpv 0xfffff87f 0x00000400
*/

	if( buf[0] == '$' ) {	/* Special  */
	    b++;
	    special = 1;
	};

	while( *b ) {
	    while( *b && isspace( *b ) )	/* Skip Spaces */
		b++;
	    
	    if( *b == 0 )
		continue;

	    word = b;
	    while( *b && !isspace( *b ) )	/* Skip non-Spaces */
		b++;
	    
	    if( *b ) {			/* Terminate word */
		*b = '\0';
		b++;			/* Skip to next char if not End Of String */
	    };

	    if( special == 0 ) {
		skip_list[sknum++] = strdup( word );
	    } else {
		sscanf( b, "%i %i", &special_and[spnum], &special_or[spnum] );
		special_list[spnum++] = strdup( word );
		*b = '\0';
	    };
	};
    };

    skip_list[sknum] = NULL;
    special_list[spnum] = NULL;

}