Allow gencode.c to generate input to the igen generator.

This commit is contained in:
Andrew Cagney
1997-09-25 04:23:24 +00:00
parent eb2e3c85ca
commit e63bc706fe
2 changed files with 489 additions and 201 deletions

View File

@ -1,3 +1,16 @@
Thu Sep 25 11:15:22 1997 Andrew Cagney <cagney@b1.cygnus.com>
* Makefile.in (tmp.igen): Add target. Generate igen input from
gencode file.
* gencode.c (FEATURE_IGEN): Define.
(main): Add --igen option. Generate output in igen format.
(process_instructions): Format output according to igen option.
(print_igen_insn_format): New function.
(print_igen_insn_models): New function.
(process_instructions): Only issue warnings and ignore
instructions when no FEATURE_IGEN.
Wed Sep 24 17:38:57 1997 Andrew Cagney <cagney@b1.cygnus.com> Wed Sep 24 17:38:57 1997 Andrew Cagney <cagney@b1.cygnus.com>
* interp.c (COP_SD, COP_LD): Add UNUSED to pacify GCC for some * interp.c (COP_SD, COP_LD): Add UNUSED to pacify GCC for some

View File

@ -116,6 +116,7 @@
#define FEATURE_WARN_MEM (1 << 27) /* 0 = nothing; 1 = generate warnings when memory problems are noticed */ #define FEATURE_WARN_MEM (1 << 27) /* 0 = nothing; 1 = generate warnings when memory problems are noticed */
#define FEATURE_WARN_R31 (1 << 28) /* 0 = nothing; 1 = generate warnings if r31 used dangerously */ #define FEATURE_WARN_R31 (1 << 28) /* 0 = nothing; 1 = generate warnings if r31 used dangerously */
#define FEATURE_WARN_RESULT (1 << 29) /* 0 = nothing; 1 = generate warnings when undefined results may occur */ #define FEATURE_WARN_RESULT (1 << 29) /* 0 = nothing; 1 = generate warnings when undefined results may occur */
#define FEATURE_IGEN (1 << 20) /* 0 = nothing; 1 = generate igen formatted output file */
/* We used to enable FEATURE_WARN_ZERO, but it is perfectly legitimate to /* We used to enable FEATURE_WARN_ZERO, but it is perfectly legitimate to
have the zero register as a destination -- the zero register just doesn't have the zero register as a destination -- the zero register just doesn't
@ -375,7 +376,9 @@ typedef enum {
#define DOUBLEWORD (3) /* 64bit */ #define DOUBLEWORD (3) /* 64bit */
#define SINGLE (4) /* single precision FP */ #define SINGLE (4) /* single precision FP */
#define DOUBLE (5) /* double precision FP */ #define DOUBLE (5) /* double precision FP */
/* start-sanitize-r5900 */
#define QUADWORD (6) /* 128bit */ #define QUADWORD (6) /* 128bit */
/* end-sanitize-r5900 */
/* Shorthand to get the size field from the flags value: */ /* Shorthand to get the size field from the flags value: */
#define GETDATASIZEINSN(i) (((i)->flags >> SIM_SH_SIZE) & SIM_MASK_SIZE) #define GETDATASIZEINSN(i) (((i)->flags >> SIM_SH_SIZE) & SIM_MASK_SIZE)
@ -965,6 +968,168 @@ static const struct instruction MIPS16_DECODE[] = {
{"XOR", 1, "11101wwwyyy01110", RR, XOR, NONE } {"XOR", 1, "11101wwwyyy01110", RR, XOR, NONE }
}; };
/*---------------------------------------------------------------------------*/
static void print_igen_insn_format PARAMS ((const char *bitmap,
inst_type mark,
int data_size,
const char *options,
const char *name));
static void
print_igen_insn_format (bitmap, mark, data_size, options, name)
const char *bitmap;
inst_type mark;
int data_size;
const char *options;
const char *name;
{
const char *chp;
char lch = *bitmap;
for (chp = bitmap; *chp != '\0'; chp++)
{
if ((isdigit (lch) && !isdigit (*chp))
|| (!isdigit (lch) && isdigit (*chp))
|| (!isdigit (lch) && !isdigit (*chp) && lch != *chp))
{
lch = *chp;
printf (",");
}
switch (*chp)
{
case '?':
printf ("*");
break;
case '<':
printf ("s"); /* good guess */
break;
default:
printf ("%c", *chp);
break;
}
}
printf (":");
switch (mark)
{
case NORMAL:
printf ("NORMAL");
break;
case SPECIAL:
printf ("SPECIAL");
break;
case REGIMM:
printf ("REGIMM");
break;
case COP1:
printf ("COP1");
break;
case COP1X:
printf ("COP1X");
break;
case COP1S: /* These instructions live in the reserved FP format values: 0..15,18-19,22-31 */
printf ("COP1S");
break;
case MMINORM:
printf ("MMINORM");
break;
case MMI0:
printf ("MMI0");
break;
case MMI1:
printf ("MMI1");
break;
case MMI2:
printf ("MMI2");
break;
case MMI3:
printf ("MMI3");
break;
/* mips16 encoding types. */
case I:
printf ("I");
break;
case RI:
printf ("RI");
break;
case RR:
printf ("RR");
break;
case RRI:
printf ("RRI");
break;
case RRR:
printf ("RRR");
break;
case RRI_A:
printf ("RRI_A");
break;
case ISHIFT:
printf ("ISHIFT");
break;
case I8:
printf ("I8");
break;
case I8_MOVR32:
printf ("I8_MOVR32");
break;
case I8_MOV32R:
printf ("I8_MOV32R");
break;
case I64:
printf ("I64");
break;
case RI64:
printf ("RI64");
break;
}
printf (":");
switch (data_size)
{
case DOUBLEWORD:
printf ("64");
break;
/* start-sanitize-r5900 */
case QUADWORD:
printf ("128");
break;
/* end-sanitize-r5900 */
default:
printf ("32");
}
printf (":%s:%s\n", options, name);
}
static void print_igen_insn_models PARAMS ((unsigned int isa));
static void
print_igen_insn_models (isa)
unsigned int isa;
{
/* common mips ISAs */
switch ((isa & MASK_ISA))
{
case 1:
printf ("*mipsI:\n");
case 2:
printf ("*mipsII:\n");
case 3:
printf ("*mipsIII:\n");
}
/* processor specific ISAs */
if ((isa & ARCH_VR4100))
printf ("*vr4100:\n");
/* start-sanitize-r5900 */
if ((isa & ARCH_R5900))
printf ("*r5900:\n");
/* end-sanitize-r5900 */
if ((isa & ARCH_R3900))
printf ("*r3900:\n");
}
/*---------------------------------------------------------------------------*/
static int bitmap_val PARAMS ((const char *, int, int)); static int bitmap_val PARAMS ((const char *, int, int));
static void build_mips16_operands PARAMS ((const char *)); static void build_mips16_operands PARAMS ((const char *));
static void build_instruction static void build_instruction
@ -988,9 +1153,11 @@ name_for_data_len( insn )
else if (GETDATASIZEINSN(insn) == DOUBLEWORD) else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
return "DOUBLEWORD"; return "DOUBLEWORD";
/* start-sanitize-r5900 */
else if (GETDATASIZEINSN(insn) == QUADWORD) else if (GETDATASIZEINSN(insn) == QUADWORD)
return "QUADWORD"; return "QUADWORD";
/* end-sanitize-r5900 */
else else
return 0; return 0;
} }
@ -1011,9 +1178,11 @@ letter_for_data_len( insn )
else if (GETDATASIZEINSN(insn) == DOUBLEWORD) else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
return "D"; return "D";
/* start-sanitize-r5900 */
else if (GETDATASIZEINSN(insn) == QUADWORD) else if (GETDATASIZEINSN(insn) == QUADWORD)
return "Q"; return "Q";
/* end-sanitize-r5900 */
else else
return 0; return 0;
} }
@ -1035,9 +1204,11 @@ type_for_data_len( insn , is_signed )
else if (GETDATASIZEINSN(insn) == DOUBLEWORD) else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
return 0; return 0;
/* start-sanitize-r5900 */
else if (GETDATASIZEINSN(insn) == QUADWORD) else if (GETDATASIZEINSN(insn) == QUADWORD)
return 0; return 0;
/* end-sanitize-r5900 */
else else
return 0; return 0;
} }
@ -1058,9 +1229,11 @@ max_for_data_len( insn )
else if (GETDATASIZEINSN(insn) == DOUBLEWORD) else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
return 0; return 0;
/* start-sanitize-r5900 */
else if (GETDATASIZEINSN(insn) == QUADWORD) else if (GETDATASIZEINSN(insn) == QUADWORD)
return 0; return 0;
/* end-sanitize-r5900 */
else else
return 0; return 0;
} }
@ -1081,9 +1254,11 @@ min_for_data_len( insn )
else if (GETDATASIZEINSN(insn) == DOUBLEWORD) else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
return 0; return 0;
/* start-sanitize-r5900 */
else if (GETDATASIZEINSN(insn) == QUADWORD) else if (GETDATASIZEINSN(insn) == QUADWORD)
return 0; return 0;
/* end-sanitize-r5900 */
else else
return 0; return 0;
} }
@ -1104,9 +1279,11 @@ umax_for_data_len( insn )
else if (GETDATASIZEINSN(insn) == DOUBLEWORD) else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
return 0; return 0;
/* start-sanitize-r5900 */
else if (GETDATASIZEINSN(insn) == QUADWORD) else if (GETDATASIZEINSN(insn) == QUADWORD)
return 0; return 0;
/* end-sanitize-r5900 */
else else
return 0; return 0;
} }
@ -1127,9 +1304,11 @@ bits_for_data_len( insn )
else if (GETDATASIZEINSN(insn) == DOUBLEWORD) else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
return "64"; return "64";
/* start-sanitize-r5900 */
else if (GETDATASIZEINSN(insn) == QUADWORD) else if (GETDATASIZEINSN(insn) == QUADWORD)
return "128"; return "128";
/* end-sanitize-r5900 */
else else
return 0; return 0;
} }
@ -1756,125 +1935,128 @@ process_instructions(doarch,features)
if (doisa == 0) if (doisa == 0)
doisa = maxisa; doisa = maxisa;
printf("#if defined(SIM_MANIFESTS)\n"); if (!(features & FEATURE_IGEN))
printf("#define MIPSISA (%d)\n",doisa); {
if (proc64) printf("#if defined(SIM_MANIFESTS)\n");
printf("#define PROCESSOR_64BIT (1 == 1)\n"); printf("#define MIPSISA (%d)\n",doisa);
else if (proc64)
printf("#define PROCESSOR_64BIT (1 == 0)\n"); printf("#define PROCESSOR_64BIT (1 == 1)\n");
else
printf("#define PROCESSOR_64BIT (1 == 0)\n");
#if 1 /* cheat: We only have a 64bit LoadMemory and StoreMemory routines at the moment */ #if 1 /* cheat: We only have a 64bit LoadMemory and StoreMemory routines at the moment */
printf("#define LOADDRMASK (0x%08X)\n",0x7); printf("#define LOADDRMASK (0x%08X)\n",0x7);
#else #else
printf("#define LOADDRMASK (0x%08X)\n",(proc64 ? 0x7 : 0x3)); printf("#define LOADDRMASK (0x%08X)\n",(proc64 ? 0x7 : 0x3));
#endif #endif
/* The FP registers are the same width as the CPU registers: */ /* The FP registers are the same width as the CPU registers: */
printf("#define GPRLEN (%d)\n",gprlen); printf("#define GPRLEN (%d)\n",gprlen);
printf("typedef %s t_reg;\n",((gprlen == 64) ? "word64" : "int")); printf("typedef %s t_reg;\n",((gprlen == 64) ? "word64" : "int"));
printf("typedef %s ut_reg;\n",((gprlen == 64) ? "uword64" : "unsigned int")); printf("typedef %s ut_reg;\n",((gprlen == 64) ? "uword64" : "unsigned int"));
printf("typedef %s t_fpreg;\n",((gprlen == 64) ? "word64" : "int")); printf("typedef %s t_fpreg;\n",((gprlen == 64) ? "word64" : "int"));
if (dofp) if (dofp)
printf("#define HASFPU (1 == 1)\n"); printf("#define HASFPU (1 == 1)\n");
if (features & FEATURE_FAST) if (features & FEATURE_FAST)
printf("#define FASTSIM (1 == 1)\n"); printf("#define FASTSIM (1 == 1)\n");
if (features & FEATURE_WARN_STALL) if (features & FEATURE_WARN_STALL)
printf("#define WARN_STALL (1 == 1)\n"); printf("#define WARN_STALL (1 == 1)\n");
if (features & FEATURE_WARN_LOHI) if (features & FEATURE_WARN_LOHI)
printf("#define WARN_LOHI (1 == 1)\n"); printf("#define WARN_LOHI (1 == 1)\n");
if (features & FEATURE_WARN_ZERO) if (features & FEATURE_WARN_ZERO)
printf("#define WARN_ZERO (1 == 1)\n"); printf("#define WARN_ZERO (1 == 1)\n");
if (features & FEATURE_WARN_MEM) if (features & FEATURE_WARN_MEM)
printf("#define WARN_MEM (1 == 1)\n"); printf("#define WARN_MEM (1 == 1)\n");
if (features & FEATURE_WARN_R31) if (features & FEATURE_WARN_R31)
printf("#define WARN_R31 (1 == 1)\n"); printf("#define WARN_R31 (1 == 1)\n");
if (features & FEATURE_WARN_RESULT) if (features & FEATURE_WARN_RESULT)
printf("#define WARN_RESULT (1 == 1)\n"); printf("#define WARN_RESULT (1 == 1)\n");
printf("#else /* simulator engine */\n"); printf("#else /* simulator engine */\n");
printf("/* Engine generated by \"%s\" at %s */\n","<SHOW PROGRAM ARGS>","<SHOW CURRENT DATE AND TIME>"); printf("/* Engine generated by \"%s\" at %s */\n","<SHOW PROGRAM ARGS>","<SHOW CURRENT DATE AND TIME>");
printf("/* Main instruction decode for %d-bit MIPS ISA %d (Table entry limit = %d) */\n",(proc64 ? 64 : 32),doisa,limit); printf("/* Main instruction decode for %d-bit MIPS ISA %d (Table entry limit = %d) */\n",(proc64 ? 64 : 32),doisa,limit);
if (dofp) if (dofp)
printf("/* %sFP instructions included */\n",(fpsingle ? "Single precision " : "")); printf("/* %sFP instructions included */\n",(fpsingle ? "Single precision " : ""));
printf("/* NOTE: \"DSPC\" is the delay slot PC address */\n"); printf("/* NOTE: \"DSPC\" is the delay slot PC address */\n");
if (proc64) { if (proc64) {
printf("#if !defined(PROCESSOR_64BIT)\n"); printf("#if !defined(PROCESSOR_64BIT)\n");
printf("#error \"Automatically constructed decoder has been built for a 64bit processor\"\n"); printf("#error \"Automatically constructed decoder has been built for a 64bit processor\"\n");
printf("#endif\n"); printf("#endif\n");
} }
printf("/* Actual instruction decoding block */\n"); printf("/* Actual instruction decoding block */\n");
printf("if ((vaddr & 1) == 0){\n"); printf("if ((vaddr & 1) == 0){\n");
{ {
int limit; int limit;
printf("int num = ((instruction >> %d) & 0x%08X);\n",OP_SH_OP,OP_MASK_OP); printf("int num = ((instruction >> %d) & 0x%08X);\n",OP_SH_OP,OP_MASK_OP);
limit = (OP_MASK_OP + 1); limit = (OP_MASK_OP + 1);
printf("#ifdef DEBUG\n"); printf("#ifdef DEBUG\n");
printf("printf(\"DBG: instruction = 0x%%08X\\n\",instruction);\n"); printf("printf(\"DBG: instruction = 0x%%08X\\n\",instruction);\n");
printf("#endif\n"); printf("#endif\n");
printf("if (num == 0x00) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC); printf("if (num == 0x00) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC);
limit += (OP_MASK_SPEC + 1); limit += (OP_MASK_SPEC + 1);
printf("else if (num == 0x01) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_RT,OP_MASK_RT); printf("else if (num == 0x01) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_RT,OP_MASK_RT);
limit += (OP_MASK_RT + 1); limit += (OP_MASK_RT + 1);
printf("else if (num == 0x11) {\n"); printf("else if (num == 0x11) {\n");
printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1NORM,OP_SH_COP1NORM,(OP_MASK_COP1NORM << OP_SH_COP1NORM)); printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1NORM,OP_SH_COP1NORM,(OP_MASK_COP1NORM << OP_SH_COP1NORM));
printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1CMP,OP_SH_COP1CMP,(OP_MASK_COP1CMP << OP_SH_COP1CMP)); printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1CMP,OP_SH_COP1CMP,(OP_MASK_COP1CMP << OP_SH_COP1CMP));
printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,(OP_MASK_SPEC & (OP_MASK_COP1CMP << OP_SH_COP1CMP))); printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,(OP_MASK_SPEC & (OP_MASK_COP1CMP << OP_SH_COP1CMP)));
printf(" else\n"); printf(" else\n");
printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC); printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC);
limit += (OP_MASK_SPEC + 1); limit += (OP_MASK_SPEC + 1);
printf(" else\n"); printf(" else\n");
/* To keep this code quick, we just clear out the "to" bit /* To keep this code quick, we just clear out the "to" bit
here. The proper (though slower) code would be to have another here. The proper (though slower) code would be to have another
conditional, checking whether this instruction is a branch or conditional, checking whether this instruction is a branch or
not, before limiting the range to the bottom two bits of the not, before limiting the range to the bottom two bits of the
move operation. */ move operation. */
printf(" num = (%d + (((instruction >> %d) & 0x%08X) & ~0x%08X));\n",limit,OP_SH_COP1SPEC,OP_MASK_COP1SPEC,OP_MASK_COP1SCLR); printf(" num = (%d + (((instruction >> %d) & 0x%08X) & ~0x%08X));\n",limit,OP_SH_COP1SPEC,OP_MASK_COP1SPEC,OP_MASK_COP1SCLR);
limit += (OP_MASK_COP1SPEC + 1); limit += (OP_MASK_COP1SPEC + 1);
printf("} else if (num == 0x13) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC); printf("} else if (num == 0x13) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC);
limit += (OP_MASK_SPEC + 1); limit += (OP_MASK_SPEC + 1);
printf("else if (num == 0x1C) {\n"); printf("else if (num == 0x1C) {\n");
printf(" int mmi_func = ((instruction >> %d) & 0x%08X);\n",OP_SH_MMI,OP_MASK_MMI); printf(" int mmi_func = ((instruction >> %d) & 0x%08X);\n",OP_SH_MMI,OP_MASK_MMI);
printf(" if (mmi_func == 0x08) \n"); printf(" if (mmi_func == 0x08) \n");
printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB); printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB);
limit += (OP_MASK_MMISUB + 1); limit += (OP_MASK_MMISUB + 1);
printf(" else if (mmi_func == 0x28) \n"); printf(" else if (mmi_func == 0x28) \n");
printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB); printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB);
limit += (OP_MASK_MMISUB + 1); limit += (OP_MASK_MMISUB + 1);
printf(" else if (mmi_func == 0x09) \n"); printf(" else if (mmi_func == 0x09) \n");
printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB); printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB);
limit += (OP_MASK_MMISUB + 1); limit += (OP_MASK_MMISUB + 1);
printf(" else if (mmi_func == 0x29) \n"); printf(" else if (mmi_func == 0x29) \n");
printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB); printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB);
limit += (OP_MASK_MMISUB + 1); limit += (OP_MASK_MMISUB + 1);
printf(" else \n"); printf(" else \n");
printf(" num = (%d + mmi_func);\n",limit); printf(" num = (%d + mmi_func);\n",limit);
limit += (OP_MASK_MMI + 1); limit += (OP_MASK_MMI + 1);
printf("}\n"); printf("}\n");
printf("/* Total possible switch entries: %d */\n",limit) ; printf("/* Total possible switch entries: %d */\n",limit) ;
} }
printf("#ifdef DEBUG\n"); printf("#ifdef DEBUG\n");
printf("printf(\"DBG: num = %%d\\n\",num);\n"); printf("printf(\"DBG: num = %%d\\n\",num);\n");
printf("#endif\n"); printf("#endif\n");
printf("switch (num)\n") ; printf("switch (num)\n") ;
printf("{\n"); printf("{\n");
}
for (loop = 0; (loop < limit); loop++) { for (loop = 0; (loop < limit); loop++) {
/* First check if the insn is in a requested isa# independent set, /* First check if the insn is in a requested isa# independent set,
then check that the ISA number we are constructing for is then check that the ISA number we are constructing for is
@ -1885,7 +2067,8 @@ process_instructions(doarch,features)
if (((isa & doarch & MASK_ISA_INDEP) if (((isa & doarch & MASK_ISA_INDEP)
|| (((isa & MASK_ISA) <= doisa) || (((isa & MASK_ISA) <= doisa)
&& (((isa & MASK_ISA_DEP) == 0) || ((isa & MASK_ISA_DEP) & doarch) != 0))) && (((isa & MASK_ISA_DEP) == 0) || ((isa & MASK_ISA_DEP) & doarch) != 0)))
&& (!(MIPS_DECODE[loop].flags & FP) || ((MIPS_DECODE[loop].flags & FP) && dofp))) { && (!(MIPS_DECODE[loop].flags & FP) || ((MIPS_DECODE[loop].flags & FP) && dofp))
|| (features & FEATURE_IGEN)) {
unsigned int onemask; unsigned int onemask;
unsigned int zeromask; unsigned int zeromask;
unsigned int dontmask; unsigned int dontmask;
@ -1895,7 +2078,8 @@ process_instructions(doarch,features)
convert_bitmap(MIPS_DECODE[loop].bitmap,&onemask,&zeromask,&dontmask); convert_bitmap(MIPS_DECODE[loop].bitmap,&onemask,&zeromask,&dontmask);
if (!(MIPS_DECODE[loop].flags & COPROC) if (!(MIPS_DECODE[loop].flags & COPROC)
&& ((GETDATASIZEINSN(&MIPS_DECODE[loop]) == DOUBLEWORD) && !proc64)) { && ((GETDATASIZEINSN(&MIPS_DECODE[loop]) == DOUBLEWORD) && !proc64)
&& !(features & FEATURE_IGEN)) {
fprintf(stderr,"DOUBLEWORD width specified for non 64-bit processor for instruction \"%s\"\n",MIPS_DECODE[loop].name); fprintf(stderr,"DOUBLEWORD width specified for non 64-bit processor for instruction \"%s\"\n",MIPS_DECODE[loop].name);
exit(4); exit(4);
} }
@ -1985,25 +2169,45 @@ process_instructions(doarch,features)
fprintf(stderr,"Unrecognised opcode mark %d in table slot %d \"%s\"\n",MIPS_DECODE[loop].mark,loop,MIPS_DECODE[loop].name) ; fprintf(stderr,"Unrecognised opcode mark %d in table slot %d \"%s\"\n",MIPS_DECODE[loop].mark,loop,MIPS_DECODE[loop].name) ;
exit(5) ; exit(5) ;
} }
printf("case %d : /* \"%s\" %s */\n",number,MIPS_DECODE[loop].name,MIPS_DECODE[loop].bitmap) ; if (!(features & FEATURE_IGEN))
{
printf("case %d : /* \"%s\" %s */\n",number,MIPS_DECODE[loop].name,MIPS_DECODE[loop].bitmap) ;
#if defined(DEBUG) #if defined(DEBUG)
printf("/* DEBUG: mask 0x%08X */\n",mask) ; printf("/* DEBUG: mask 0x%08X */\n",mask) ;
printf(" printf(\"\\\"%s\\\"\\n\");\n",MIPS_DECODE[loop].name); printf(" printf(\"\\\"%s\\\"\\n\");\n",MIPS_DECODE[loop].name);
#endif #endif
/* Check if there are any other explicit bits in the instruction: */ /* Check if there are any other explicit bits in the instruction: */
if ((~mask & (onemask | zeromask)) != 0x00000000) { if ((~mask & (onemask | zeromask)) != 0x00000000) {
printf(" if ((instruction & 0x%08X) != 0x%08X)\n",(onemask | zeromask),onemask) ; printf(" if ((instruction & 0x%08X) != 0x%08X)\n",(onemask | zeromask),onemask) ;
printf(" {\n") ; printf(" {\n") ;
printf(" SignalException(ReservedInstruction,instruction);\n") ; printf(" SignalException(ReservedInstruction,instruction);\n") ;
printf(" }\n") ; printf(" }\n") ;
printf(" else\n") ; printf(" else\n") ;
} }
printf(" {\n") ; printf(" {\n") ;
}
else
{
/* start-sanitize-cygnus-never */
/* If any sanitization occures, this line should be printed */
if ((MIPS_DECODE[loop].isa & ARCH_R5900))
printf ("// %s-%s-%s\n", "start", "sanitize", "r5900");
/* end-sanitize-cygnus-never */
printf ("\n");
print_igen_insn_format (MIPS_DECODE[loop].bitmap,
MIPS_DECODE[loop].mark, /* format-name */
GETDATASIZEINSN (&MIPS_DECODE[loop]), /* filter-flags */
"", /* options */
MIPS_DECODE[loop].name);
print_igen_insn_models (MIPS_DECODE[loop].isa);
printf ("{\n") ;
printf (" unsigned32 instruction = instruction_0;\n");
}
/* Get hold of the operands */ /* Get hold of the operands */
/* NOTE: If we wanted to make the simulator code smaller, we /* NOTE: If we wanted to make the simulator code smaller, we
* could pull these into a common sequence before we perform * could pull these into a common sequence before we perform
@ -2016,24 +2220,42 @@ process_instructions(doarch,features)
* compilation of the produced code. * compilation of the produced code.
*/ */
build_operands(doisa, features, &MIPS_DECODE[loop]); build_operands(doisa, features, &MIPS_DECODE[loop]);
printf(" {\n") ; printf(" {\n") ;
build_instruction (doisa, features, 0, &MIPS_DECODE[loop]); build_instruction (doisa, features, 0, &MIPS_DECODE[loop]);
printf(" }\n") ; printf(" }\n") ;
printf(" }\n") ; if (!(features & FEATURE_IGEN))
printf(" break ;\n") ; {
printf(" }\n") ;
printf(" break ;\n") ;
}
else
{
printf ("}\n");
printf ("\n");
/* start-sanitize-cygnus-never */
/* When sanitized, this output should never be produced */
if ((MIPS_DECODE[loop].isa & ARCH_R5900))
printf ("// %s-%s-%s\n", "end", "sanitize", "r5900");
/* end-sanitize-cygnus-never */
}
} }
} }
printf("default : /* Unrecognised instruction */\n") ;
printf(" SignalException(ReservedInstruction,instruction);\n") ;
printf(" break ;\n") ;
printf("}\n}\n") ;
if (!(features & FEATURE_IGEN))
{
printf("default : /* Unrecognised instruction */\n") ;
printf(" SignalException(ReservedInstruction,instruction);\n") ;
printf(" break ;\n") ;
printf("}\n}\n") ;
}
/* Handle mips16 instructions. The switch table looks like this: /* Handle mips16 instructions. The switch table looks like this:
0 - 31: I, RI, and RRI instructions by major. 0 - 31: I, RI, and RRI instructions by major.
32 - 35: ISHIFT instructions by function + 32 32 - 35: ISHIFT instructions by function + 32
36 - 37: RRI_A instructions by function + 36 36 - 37: RRI_A instructions by function + 36
38 - 45: I8, I8_MOV32R, and I8_MOVR32 instructions by function + 38 38 - 45: I8, I8_MOV32R, and I8_MOVR32 instructions by function + 38
@ -2042,31 +2264,34 @@ process_instructions(doarch,features)
82 - 89: I64 and RI64 instructions by funct + 82 82 - 89: I64 and RI64 instructions by funct + 82
90 - 97: jalr (RR minor 0) by y + 90 90 - 97: jalr (RR minor 0) by y + 90
*/ */
printf ("else {\n"); if (!(features & FEATURE_IGEN))
printf ("static int extendval;\n"); {
printf ("static int have_extendval;\n"); printf ("else {\n");
printf ("int num = ((instruction >> %d) & 0x%08X);\n", printf ("static int extendval;\n");
MIPS16OP_SH_OP, MIPS16OP_MASK_OP); printf ("static int have_extendval;\n");
printf ("switch (num)\n{\n"); printf ("int num = ((instruction >> %d) & 0x%08X);\n",
printf ("case 0x6: num = 32 + (instruction & 3); break;\n"); MIPS16OP_SH_OP, MIPS16OP_MASK_OP);
printf ("case 0x8: num = 36 + ((instruction & 0x10) >> 4); break;\n"); printf ("switch (num)\n{\n");
printf ("case 0xc: num = 38 + ((instruction & 0x700) >> 8); break;\n"); printf ("case 0x6: num = 32 + (instruction & 3); break;\n");
printf ("case 0x1c: num = 46 + (instruction & 3); break;\n"); printf ("case 0x8: num = 36 + ((instruction & 0x10) >> 4); break;\n");
printf ("case 0x1d: num = 50 + (instruction & 0x1f);\n"); printf ("case 0xc: num = 38 + ((instruction & 0x700) >> 8); break;\n");
printf (" if (num == 50) num = 90 + ((instruction & 0xe0) >> 5);\n"); printf ("case 0x1c: num = 46 + (instruction & 3); break;\n");
printf (" break;\n"); printf ("case 0x1d: num = 50 + (instruction & 0x1f);\n");
printf ("case 0x1f: num = 82 + ((instruction & 0x700) >> 8); break;\n"); printf (" if (num == 50) num = 90 + ((instruction & 0xe0) >> 5);\n");
printf ("default: break;\n}\n"); printf (" break;\n");
printf ("switch (num)\n{\n"); printf ("case 0x1f: num = 82 + ((instruction & 0x700) >> 8); break;\n");
printf ("default: break;\n}\n");
printf ("switch (num)\n{\n");
}
for (loop = 0; loop < sizeof MIPS16_DECODE / sizeof MIPS16_DECODE[0]; loop++) for (loop = 0; loop < sizeof MIPS16_DECODE / sizeof MIPS16_DECODE[0]; loop++)
{ {
const char *bitmap; const char *bitmap;
int num; int num;
if (! proc64 && GETDATASIZEINSN (&MIPS16_DECODE[loop]) == DOUBLEWORD) if (! proc64 && GETDATASIZEINSN (&MIPS16_DECODE[loop]) == DOUBLEWORD)
continue; continue;
bitmap = MIPS16_DECODE[loop].bitmap; bitmap = MIPS16_DECODE[loop].bitmap;
switch (MIPS16_DECODE[loop].mark) switch (MIPS16_DECODE[loop].mark)
{ {
@ -2092,7 +2317,7 @@ process_instructions(doarch,features)
case RR: case RR:
{ {
int minor; int minor;
minor = bitmap_val (bitmap, 0, 5); minor = bitmap_val (bitmap, 0, 5);
if (minor != 0) if (minor != 0)
num = 50 + minor; num = 50 + minor;
@ -2108,10 +2333,25 @@ process_instructions(doarch,features)
abort (); abort ();
} }
printf ("case %d: /* \"%s\" %s */\n", num, MIPS16_DECODE[loop].name,
bitmap);
printf (" {\n"); if (!(features & FEATURE_IGEN))
{
printf ("case %d: /* \"%s\" %s */\n", num, MIPS16_DECODE[loop].name,
bitmap);
printf (" {\n");
}
else
{
printf ("\n");
print_igen_insn_format (bitmap,
MIPS16_DECODE[loop].mark, /* format-name */
GETDATASIZEINSN (&MIPS16_DECODE[loop]), /* filter-flags */
"", /* options */
MIPS16_DECODE[loop].name);
printf ("*mips16:\n");
printf ("{\n");
printf (" unsigned32 instruction = instruction_0;\n");
}
build_mips16_operands (bitmap); build_mips16_operands (bitmap);
@ -2127,17 +2367,28 @@ process_instructions(doarch,features)
} }
printf (" }\n"); printf (" }\n");
printf (" }\n") ; if (!(features & FEATURE_IGEN))
printf (" break ;\n") ; {
printf (" }\n") ;
printf (" break ;\n") ;
}
else
{
printf ("}\n");
printf ("\n");
}
} }
printf ("default : /* Unrecognised instruction */\n") ; if (!(features & FEATURE_IGEN))
printf (" SignalException(ReservedInstruction,instruction);\n") ; {
printf (" break ;\n") ; printf ("default : /* Unrecognised instruction */\n") ;
printf ("}\n}\n") ; printf (" SignalException(ReservedInstruction,instruction);\n") ;
printf (" break ;\n") ;
printf("#endif /* simulator engine */\n"); printf ("}\n}\n") ;
printf("#endif /* simulator engine */\n");
}
return ; return ;
} }
@ -2643,11 +2894,13 @@ build_instruction (doisa, features, mips16, insn)
datalen = 8; datalen = 8;
accesslength = "AccessLength_DOUBLEWORD"; accesslength = "AccessLength_DOUBLEWORD";
break ; break ;
/* start-sanitize-r5900 */
case QUADWORD : case QUADWORD :
datalen = 16; datalen = 16;
accesslength = "AccessLength_QUADWORD"; accesslength = "AccessLength_QUADWORD";
break ; break ;
/* end-sanitize-r5900 */
} }
if (insn->flags & REG) if (insn->flags & REG)
@ -2687,11 +2940,14 @@ build_instruction (doisa, features, mips16, insn)
switch (datalen) { switch (datalen) {
case 8: case 8:
if (!proc64) { if (!(features & FEATURE_IGEN))
fprintf(stderr,"DOUBLEWORD shifted memory transfers only valid for 64-bit processors \"%s\"\n",insn->name); {
exit(4); if (!proc64) {
} fprintf(stderr,"DOUBLEWORD shifted memory transfers only valid for 64-bit processors \"%s\"\n",insn->name);
/* fall through to... */ exit(4);
}
}
/* fall through to... */
case 4: case 4:
{ {
printf(" uword64 mask = %d;\n",((datalen == 8) ? 0x7 : 0x3)); printf(" uword64 mask = %d;\n",((datalen == 8) ? 0x7 : 0x3));
@ -2786,16 +3042,19 @@ build_instruction (doisa, features, mips16, insn)
exit(6); exit(6);
} }
} else { /* normal memory transfer */ } else { /* normal memory transfer */
if (!(insn->flags & COPROC) && ((datalen == 8) || ((datalen == 4) & (insn->flags & UNSIGNED))) && !proc64) { if (!(features & FEATURE_IGEN))
fprintf(stderr,"Operation not available with 32bit wide memory access \"%s\"\n",insn->name); {
exit(4); if (!(insn->flags & COPROC) && ((datalen == 8) || ((datalen == 4) & (insn->flags & UNSIGNED))) && !proc64) {
/* TODO: The R4000 documentation states that a LWU fprintf(stderr,"Operation not available with 32bit wide memory access \"%s\"\n",insn->name);
instruction executed when in a 32bit processor mode exit(4);
should cause a ReservedInstruction exception. This /* TODO: The R4000 documentation states that a LWU
will mean adding a run-time check into the code instruction executed when in a 32bit processor mode
sequence. */ should cause a ReservedInstruction exception. This
} will mean adding a run-time check into the code
sequence. */
}
}
if (isload) { if (isload) {
#if 1 /* see the comments attached to LOADDRMASK above */ #if 1 /* see the comments attached to LOADDRMASK above */
printf(" uword64 mask = 0x7;\n"); printf(" uword64 mask = 0x7;\n");
@ -2808,14 +3067,22 @@ build_instruction (doisa, features, mips16, insn)
printf(" unsigned int byte UNUSED;\n"); printf(" unsigned int byte UNUSED;\n");
/* TODO: This should really also check for 32bit world performing 32bit access */ /* TODO: This should really also check for 32bit world performing 32bit access */
if (datalen < 8) /* not for DOUBLEWORD or QUADWORD*/ if (datalen < 8)
printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n"); /* not for DOUBLEWORD */
/* start-sanitize-r5900 */
/* not for QUADWORD */
/* end-sanitize-r5900 */
printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
printf(" LoadMemory(&memval,&memval1,uncached,%s,paddr,vaddr,isDATA,isREAL);\n",accesslength); printf(" LoadMemory(&memval,&memval1,uncached,%s,paddr,vaddr,isDATA,isREAL);\n",accesslength);
/* The following will only make sense if the /* The following will only make sense if the
"LoadMemory" above returns a DOUBLEWORD entity */ "LoadMemory" above returns a DOUBLEWORD entity */
if (datalen < 8) { /* not for DOUBLEWORD or QUADWORD*/ if (datalen < 8) {
/* not for DOUBLEWORD */
/* start-sanitize-r5900 */
/* not for QUADWORD */
/* end-sanitize-r5900 */
int valmask; int valmask;
switch (datalen) { switch (datalen) {
case 1: case 1:
@ -2905,10 +3172,13 @@ build_instruction (doisa, features, mips16, insn)
else else
printf(" memval = ((uword64) op2 << (8 * byte));\n"); printf(" memval = ((uword64) op2 << (8 * byte));\n");
} else if (datalen <= 8) { /* SD and SCD */ } else if (datalen <= 8) { /* SD and SCD */
if (!(insn->flags & COPROC) && ((datalen == 8) || ((datalen == 4) & (insn->flags & UNSIGNED))) && !proc64) { if (! (features & FEATURE_IGEN))
fprintf(stderr,"Operation not available with 32bit wide memory access \"%s\"\n",insn->name); {
exit(4); if (!(insn->flags & COPROC) && ((datalen == 8) || ((datalen == 4) & (insn->flags & UNSIGNED))) && !proc64) {
} fprintf(stderr,"Operation not available with 32bit wide memory access \"%s\"\n",insn->name);
exit(4);
}
}
if (insn->flags & COPROC) if (insn->flags & COPROC)
printf(" memval = (uword64)COP_SD(%s,%s);\n", printf(" memval = (uword64)COP_SD(%s,%s);\n",
((insn->flags & REG) ((insn->flags & REG)
@ -4226,6 +4496,7 @@ main(argc,argv)
{"fast", 0,0,'f'}, {"fast", 0,0,'f'},
{"help", 0,0,'h'}, {"help", 0,0,'h'},
{"warnings",0,0,'w'}, {"warnings",0,0,'w'},
{"igen", 0,0,'i'},
{0, 0,0,0} {0, 0,0,0}
}; };
@ -4242,6 +4513,10 @@ main(argc,argv)
features |= FEATURE_FAST; features |= FEATURE_FAST;
break; break;
case 'i' : /* igen formatted output */
features |= FEATURE_IGEN;
break;
case 'w' : /* warnings */ case 'w' : /* warnings */
features |= FEATURE_WARNINGS; features |= FEATURE_WARNINGS;
/* TODO: Future extension: Allow better control over the warnings generated: /* TODO: Future extension: Allow better control over the warnings generated: