Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / legion / src / support / sparcccgen.c
/*
* ========== Copyright Header Begin ==========================================
*
* OpenSPARC T2 Processor File: sparcccgen.c
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
*
* The above named program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License version 2 as published by the Free Software Foundation.
*
* The above named program is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ========== Copyright Header End ============================================
*/
/*
* Sparc condition code operations are nasty ...
* Ideally we want a fast mechanism to determine if a conditional
* operation is true or not based on the condition codes.
* Except that the condition expressions dont well match
* the condition code flags.
*
* Now we have a 4 bit condition expression and a 4 bit condition
* code register, so we could combine to form an index for a 256
* bit array of true and false ... except that the cond expression
* is always encoded in the instruction ...
*
* For now we use the cond expression, as an index into a table of
* 16bit words. The cond code register selects a bit from this
* the result of which is true or false ...
*
* This code mechanically builds those 16bit words to be indexed
* by the condition code register value.
*/
#include <ctype.h> /* for islower / toupper */
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* for strchr */
#include <sys/param.h> /* for MAXPATHLEN */
#include <sys/types.h>
#include <unistd.h>
#include "hostcpu.h"
void fatal(char* fmt, ...);
void strcasecpy(char * top, char * fromp);
typedef enum {
cond_a = 0x8,
cond_n = 0x0,
cond_ne = 0x9,
cond_e = 0x1,
cond_g = 0xA,
cond_le = 0x2,
cond_ge = 0xB,
cond_l = 0x3,
cond_gu = 0xC,
cond_leu = 0x4,
cond_cc = 0xD,
cond_cs = 0x5,
cond_pos = 0xE,
cond_neg = 0x6,
cond_vc = 0xF,
cond_vs = 0x7
} cond_type_t;
typedef enum {
cc_bit_c = 0x1,
cc_bit_v = 0x2,
cc_bit_z = 0x4,
cc_bit_n = 0x8
} cc_bit_t;
void
gencodes(FILE * fp)
{
int cond, ccr;
for (cond=0; cond<16; cond++) {
uint16_t mask;
mask = 0;
for (ccr=0; ccr<16; ccr++) {
switch (cond) {
case cond_a:
goto set_bit;
case cond_n:
goto clear_bit;
case cond_ne:
if (!(ccr & cc_bit_z)) goto set_bit;
goto clear_bit;
case cond_e:
if (ccr & cc_bit_z) goto set_bit;
goto clear_bit;
case cond_g:
if ( !( (ccr&cc_bit_z) || (((ccr>>2)^ccr)&cc_bit_v) ) ) goto set_bit;
goto clear_bit;
case cond_le:
if ( (ccr&cc_bit_z) || (((ccr>>2)^ccr)&cc_bit_v) ) goto set_bit;
goto clear_bit;
case cond_ge:
if (!( ((ccr>>2)^ccr)&cc_bit_v )) goto set_bit;
goto clear_bit;
case cond_l:
if ( ((ccr>>2)^ccr)&cc_bit_v ) goto set_bit;
goto clear_bit;
case cond_gu:
if (!((ccr & cc_bit_c) || (ccr & cc_bit_z))) goto set_bit;
goto clear_bit;
case cond_leu:
if ((ccr & cc_bit_c) || (ccr & cc_bit_z)) goto set_bit;
goto clear_bit;
case cond_cc:
if (!(ccr & cc_bit_c)) goto set_bit;
goto clear_bit;
case cond_cs:
if (ccr & cc_bit_c) goto set_bit;
goto clear_bit;
case cond_pos:
if (!(ccr & cc_bit_n)) goto set_bit;
goto clear_bit;
case cond_neg:
if (ccr & cc_bit_n) goto set_bit;
goto clear_bit;
case cond_vc:
if (!(ccr & cc_bit_v)) goto set_bit;
goto clear_bit;
case cond_vs:
if (ccr & cc_bit_v) goto set_bit;
goto clear_bit;
default:
abort();
}
set_bit:;
mask |= 1<<ccr;
clear_bit:;
}
fprintf(fp, "\t0x%04lx%s\n", (uint32_t)mask, cond!=15 ? "," : "");
}
}
int main(int argc, char ** argv)
{
#define MAXBUF 1024
char bufp[MAXPATHLEN];
char caps[MAXPATHLEN];
char * bnamep;
FILE * dotc, * doth;
char * basenamep;
char * structnamep;
char * specfilep;
if (argc != 3) fatal("usage: %s <basefilename> <basestructname>\n",
argv[0]);
basenamep = argv[1];
structnamep = argv[2];
if (strlen(structnamep)>MAXBUF-100) fatal("basestructname is too long!");
/* Initialise the .h and .c files */
sprintf(bufp, "%s.c", basenamep);
dotc = fopen(bufp, "w");
if (dotc == NULL) fatal("creating %s", bufp);
sprintf(bufp, "%s.h", basenamep);
doth = fopen(bufp, "w");
if (doth == NULL) fatal("creating %s", bufp);
/* remove any earlier path ... */
bnamep = strrchr(basenamep, '/');
if (bnamep == (char*)0)
bnamep = basenamep;
else
bnamep ++;
strcasecpy(caps, bnamep);
fprintf(dotc,"\
/* Autogenerated file - DO NOT EDIT */\n\
#include \"basics.h\"\n\
#include \"%s.h\"\n\
\n\
uint16_t %s[16]={\n", bnamep, structnamep);
gencodes(dotc);
fprintf(dotc,"\
};\n\
\n\
\n", bnamep, structnamep);
fclose(dotc);
fprintf(doth,"\
#ifndef _%s_H_\n\
#define _%s_H_\n\
\n\
extern uint16_t %s[];\n\
\n\
#endif\n", caps, caps, structnamep);
fclose(doth);
exit(0);
return 0; /* compiler joy */
}
void fatal(char* fmt, ...)
{
va_list args;
if (errno!=0) perror("FATAL: "); else fprintf(stderr,"FATAL: ");
if (fmt) {
va_start(args, fmt);
(void)vfprintf(stderr, fmt, args);
va_end(args);
}
fprintf(stderr,"\n");
fflush(stderr);
fflush(stdout);
exit(1);
}
void strcasecpy(char * top, char * fromp)
{
do {
*top++ = islower((unsigned)*fromp) ? toupper((unsigned)*fromp) : *fromp;
} while (*fromp++ != '\0');
}