//gcc a.c ../../../VEX/priv/tilegx_disasm.c -I ../../../ -I ../../../VEX/priv/ -I ../../../VEX/pub/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "tilegx_disasm.h"
#undef DGB
static unsigned char op_abnorm[TILEGX_OPC_NONE] = {
/* Black list */
[ TILEGX_OPC_BPT ] = 1,
[ TILEGX_OPC_INFO ] = 1,
[ TILEGX_OPC_INFOL ] = 1,
[ TILEGX_OPC_DRAIN ] = 1,
[ TILEGX_OPC_IRET ] = 1,
[ TILEGX_OPC_SWINT0 ] = 1,
[ TILEGX_OPC_SWINT1 ] = 1,
[ TILEGX_OPC_SWINT2 ] = 1,
[ TILEGX_OPC_SWINT3 ] = 1,
[ TILEGX_OPC_LD4S_TLS ] = 1,
[ TILEGX_OPC_LD_TLS ] = 1,
[ TILEGX_OPC_MFSPR ] = 1,
[ TILEGX_OPC_MTSPR ] = 1,
[ TILEGX_OPC_ILL ] = 1,
[ TILEGX_OPC_NAP ] = 1,
/* mem load */
[ TILEGX_OPC_LD ] = 2,
[ TILEGX_OPC_LD_ADD ] = 2,
[ TILEGX_OPC_LD1S ] = 2,
[ TILEGX_OPC_LD1S_ADD ] = 2,
[ TILEGX_OPC_LD1U ] = 2,
[ TILEGX_OPC_LD1U_ADD ] = 2,
[ TILEGX_OPC_LD2S ] = 2,
[ TILEGX_OPC_LD2S_ADD ] = 2,
[ TILEGX_OPC_LD2U ] = 2,
[ TILEGX_OPC_LD2U_ADD ] = 2,
[ TILEGX_OPC_LD4S ] = 2,
[ TILEGX_OPC_LD4S_ADD ] = 2,
[ TILEGX_OPC_LD4U ] = 2,
[ TILEGX_OPC_LD4U_ADD ] = 2,
[ TILEGX_OPC_LDNA ] = 2,
[ TILEGX_OPC_LDNA_ADD ] = 2,
[ TILEGX_OPC_LDNT ] = 2,
[ TILEGX_OPC_LDNT1S ] = 2,
[ TILEGX_OPC_LDNT1S_ADD ] = 2,
[ TILEGX_OPC_LDNT1U ] = 2,
[ TILEGX_OPC_LDNT1U_ADD ] = 2,
[ TILEGX_OPC_LDNT2S ] = 2,
[ TILEGX_OPC_LDNT2S_ADD ] = 2,
[ TILEGX_OPC_LDNT2U ] = 2,
[ TILEGX_OPC_LDNT2U_ADD ] = 2,
[ TILEGX_OPC_LDNT4S ] = 2,
[ TILEGX_OPC_LDNT4S_ADD ] = 2,
[ TILEGX_OPC_LDNT4U ] = 2,
[ TILEGX_OPC_LDNT4U_ADD ] = 2,
[ TILEGX_OPC_LDNT_ADD ] = 2,
/* mem store */
[ TILEGX_OPC_ST ] = 4,
[ TILEGX_OPC_ST1 ] = 4,
[ TILEGX_OPC_ST1_ADD ] = 4,
[ TILEGX_OPC_ST2 ] = 4,
[ TILEGX_OPC_ST2_ADD ] = 4,
[ TILEGX_OPC_ST4 ] = 4,
[ TILEGX_OPC_ST4_ADD ] = 4,
[ TILEGX_OPC_ST_ADD ] = 4,
[ TILEGX_OPC_STNT ] = 4,
[ TILEGX_OPC_STNT1 ] = 4,
[ TILEGX_OPC_STNT1_ADD ] = 4,
[ TILEGX_OPC_STNT2 ] = 4,
[ TILEGX_OPC_STNT2_ADD ] = 4,
[ TILEGX_OPC_STNT4 ] = 4,
[ TILEGX_OPC_STNT4_ADD ] = 4,
[ TILEGX_OPC_STNT_ADD ] = 4,
/* conditional branch */
[ TILEGX_OPC_BEQZ ] = 8,
[ TILEGX_OPC_BEQZT ] = 8,
[ TILEGX_OPC_BGEZ ] = 8,
[ TILEGX_OPC_BGEZT ] = 8,
[ TILEGX_OPC_BGTZ ] = 8,
[ TILEGX_OPC_BGTZT ] = 8,
[ TILEGX_OPC_BLBC ] = 8,
[ TILEGX_OPC_BLBCT ] = 8,
[ TILEGX_OPC_BLBS ] = 8,
[ TILEGX_OPC_BLBST ] = 8,
[ TILEGX_OPC_BLEZ ] = 8,
[ TILEGX_OPC_BLEZT ] = 8,
[ TILEGX_OPC_BLTZ ] = 8,
[ TILEGX_OPC_BLTZT ] = 8,
[ TILEGX_OPC_BNEZ ] = 8,
[ TILEGX_OPC_BNEZT ] = 8,
};
static tilegx_bundle_bits
encode_insn_tilegx_X (int p, struct tilegx_decoded_instruction decoded);
static tilegx_bundle_bits
encode_insn_tilegx_Y (int p, struct tilegx_decoded_instruction decoded);
static int decode( tilegx_bundle_bits *p, int count, ULong pc );
static uint64_t
RAND(int round) {
static volatile uint64_t rand_seed = 0;
while (round-- > 0)
rand_seed = (rand_seed >> 8) * 201520052007 + 1971;
#ifdef DBG
printf("RAND: %d\n", (int)rand_seed);
#endif
return rand_seed;
}
int main(int argc, char* argv[])
{
int i, start, end, pipe;
struct tilegx_decoded_instruction decoded;
if (argc == 1) {
pipe = 0x1F;
start = 0;
end = TILEGX_OPC_NONE;
} else if (argc == 3) {
start = atoi(argv[1]);
if (start >= TILEGX_OPC_NONE)
return -1;
end = start + 1;
/* pipes: X: bit 0,1; Y: bit 2-4 */
pipe = atoi(argv[2]);
} else {
return -1;
}
for (i = start; i < end; i++) {
memset(&decoded, 0, sizeof(decoded));
const struct tilegx_opcode *opcode = &tilegx_opcodes[i];
decoded.opcode = opcode;
#ifdef DBG
const char *op_name = decoded.opcode->name;
printf("\n\n%d) %s\n", i, op_name);
#endif
if (op_abnorm[i] & 1)
continue;
/* X0 pipeline */
if (tilegx_opcodes[i].pipes & 1 & pipe)
encode_insn_tilegx_X(0, decoded);
/* X1 pipeline */
if (tilegx_opcodes[i].pipes & 2 & pipe)
encode_insn_tilegx_X(1, decoded);
/* Y0 pipleline */
if (tilegx_opcodes[i].pipes & 4 & pipe)
encode_insn_tilegx_Y(0, decoded);
/* Y1 pipleline */
if (tilegx_opcodes[i].pipes & 8 & pipe)
encode_insn_tilegx_Y(1, decoded);
/* Y2 pipleline */
if (tilegx_opcodes[i].pipes & 16 & pipe)
encode_insn_tilegx_Y(2, decoded);
}
return 0;
}
static tilegx_bundle_bits
encode_insn_tilegx_X(int p, struct tilegx_decoded_instruction decoded)
{
const struct tilegx_opcode *opc =
decoded.opcode;
int op_idx = decoded.opcode->mnemonic;
tilegx_bundle_bits insn = 0;
//int pipeX01 = (opc->pipes & 0x01) ? 0 : 1;
int op_num = opc->num_operands;
/* Assume either X0 or X1. */
if ((opc->pipes & 3) == 0)
return -1;
/* Insert fnop in other pipe. */
insn = tilegx_opcodes[TILEGX_OPC_FNOP].
fixed_bit_values[p ? 0 : 1];
#ifdef DBG
printf(" X%d, ", p);
#endif
insn |= opc->fixed_bit_values[p];
printf("//file: _insn_test_%s_X%d.c\n", decoded.opcode->name, p);
printf("//op=%d\n", op_idx);
printf("#include <stdio.h>\n");
printf("#include <stdlib.h>\n");
printf("\n"
"void func_exit(void) {\n"
" printf(\"%cs\\n\", __func__);\n"
" exit(0);\n"
"}\n"
"\n"
"void func_call(void) {\n"
" printf(\"%cs\\n\", __func__);\n"
" exit(0);\n"
"}\n"
"\n"
"unsigned long mem[2] = { 0x%lx, 0x%lx };\n"
"\n", '%', '%', RAND(op_idx), RAND(op_idx));
printf("int main(void) {\n");
printf(" unsigned long a[4] = { 0, 0 };\n");
printf(" asm __volatile__ (\n");
int i, n = 0;
if (op_abnorm[op_idx] & 6)
{
/* loop for each operand. */
for (i = 0 ; i < op_num; i++)
{
const struct tilegx_operand *opd =
&tilegx_operands[opc->operands[p][i]];
if (opd->type == TILEGX_OP_TYPE_REGISTER) {
/* A register operand, pick register 0-50 randomly. */
decoded.operand_values[i] = RAND(op_idx) % 51;
int r = decoded.operand_values[i];
int64_t d = RAND(op_idx);
#ifdef DBG
printf(" %d) r%-2d %016lx\n", i, (int)r, (unsigned long)d);
#endif
int k = 0;
for (k = 3; k >= 0 ; k--) {
if (d >> (16 * k) || k == 0) {
printf(" \"moveli r%d, %d\\n\"\n", r, (int)(d >> (16 * k)));
for (k--; k >= 0; k--)
printf(" \"shl16insli r%d, r%d, %d\\n\"\n", r, r, (int)(int16_t)(d >> (16 * k)));
break;
}
}
} else {
/* An immediate operand, pick a random value. */
decoded.operand_values[i] = RAND(op_idx);
#ifdef DBG
printf(" %d) %016lx\n", (int)i, (unsigned long)decoded.operand_values[i]);
#endif
}
Long op = decoded.operand_values[i];
decoded.operands[i] = opd;
ULong x = opd->insert(op);
insn |= x;
}
printf(" \"");
if (op_abnorm[op_idx] & 2)
printf("move r%d, %c2\\n\"\n", (int)decoded.operand_values[1], '%');
else
printf("move r%d, %c2\\n\"\n", (int)decoded.operand_values[0], '%');
printf(" \"");
decode(&insn, 2, 0);
printf("\\n\"\n");
/* loop for each operand. */
n = 0;
for (i = 0 ; i < op_num; i++)
{
const struct tilegx_operand *opd =
&tilegx_operands[opc->operands[p][i]];
if (opd->type == TILEGX_OP_TYPE_REGISTER) {
/* A register operand */
printf(" \"move %c%d, r%d\\n\"\n", '%', n, (int)decoded.operand_values[i]);
n++;
}
}
printf(" ");
if (n)
printf(":");
for (i = 0; i < n; i++)
{
printf("\"=r\"(a[%d])", i);
if (i != n - 1)
printf(",");
}
printf(" : \"r\"(mem)");
printf(");\n");
printf(" printf(\"%c016lx %c016lx\\n\", mem[0], mem[1]);\n", '%', '%');
}
else if (op_idx == TILEGX_OPC_J)
{
printf(" \"%s %c0\\n\"\n", decoded.opcode->name, '%');
printf(" :: \"i\"(func_exit));\n");
}
else if (op_idx == TILEGX_OPC_JAL)
{
printf(" \"%s %c0\\n\"\n", decoded.opcode->name, '%');
printf(" :: \"i\"(func_call));\n");
}
else if (op_idx == TILEGX_OPC_JR || op_idx == TILEGX_OPC_JRP)
{
printf(" \"%s %c0\\n\"\n", decoded.opcode->name, '%');
printf(" :: \"r\"(func_exit));\n");
}
else if (op_idx == TILEGX_OPC_JALR || op_idx == TILEGX_OPC_JALRP )
{
printf(" \"%s %c0\\n\"\n", decoded.opcode->name, '%');
printf(" :: \"r\"(func_call));\n");
}
else if (op_abnorm[op_idx] & 8)
{
// OPC_BXXX conditional branch
int r = RAND(op_idx) % 51;
int d = RAND(op_idx) & 1;
printf(" \"movei r%d, %d\\n\"\n", r, d);
printf(" \"%s r%d, %c0\\n\"\n", decoded.opcode->name, r, '%');
printf(" \"jal %c1\\n\"\n", '%');
printf(" :: \"i\"(func_exit), \"i\"(func_call));\n");
}
else
{
/* loop for each operand. */
for (i = 0 ; i < op_num; i++)
{
const struct tilegx_operand *opd =
&tilegx_operands[opc->operands[p][i]];
if (opd->type == TILEGX_OP_TYPE_REGISTER) {
/* A register operand, pick register 0-50 randomly. */
decoded.operand_values[i] = RAND(op_idx) % 51;
int r = decoded.operand_values[i];
int64_t d = RAND(op_idx);
#ifdef DBG
printf(" %d) r%-2d %016lx\n", i, (int)r, (unsigned long)d);
#endif
int k = 0;
for (k = 3; k >= 0 ; k--) {
if (d >> (16 * k) || k == 0) {
printf(" \"moveli r%d, %d\\n\"\n", r, (int)(d >> (16 * k)));
for (k--; k >= 0; k--)
printf(" \"shl16insli r%d, r%d, %d\\n\"\n", r, r, (int)(int16_t)(d >> (16 * k)));
break;
}
}
} else {
/* An immediate operand, pick a random value. */
decoded.operand_values[i] = RAND(op_idx);
#ifdef DBG
printf(" %d) %016lx\n", (int)i, (unsigned long)decoded.operand_values[i]);
#endif
}
Long op = decoded.operand_values[i];
decoded.operands[i] = opd;
ULong x = opd->insert(op);
insn |= x;
}
printf(" \"");
decode(&insn, 2, 0);
printf("\\n\"\n");
/* loop for each operand. */
n = 0;
for (i = 0 ; i < op_num; i++)
{
const struct tilegx_operand *opd =
&tilegx_operands[opc->operands[p][i]];
if (opd->type == TILEGX_OP_TYPE_REGISTER) {
/* A register operand */
printf(" \"move %c%d, r%d\\n\"\n", '%', n, (int)decoded.operand_values[i]);
n++;
}
}
printf(" ");
if (n)
printf(":");
for (i = 0; i < n; i++)
{
printf("\"=r\"(a[%d])", i);
if (i != n - 1)
printf(",");
}
printf(");\n");
}
for (i = 0; i < n; i++)
{
printf(" printf(\"%c016lx\\n\", a[%d]);\n", '%', i);
}
printf(" return 0;\n");
printf("}\n");
return insn;
}
static tilegx_bundle_bits
encode_insn_tilegx_Y (int p, struct tilegx_decoded_instruction decoded )
{
int i;
const struct tilegx_opcode *opc =
decoded.opcode;
int op_idx = decoded.opcode->mnemonic;
const struct tilegx_operand *opd;
tilegx_bundle_bits insn = 0;
Int op_num = opc->num_operands;
/* Insert fnop in Y0 and Y1 pipeline. */
if (p != 0)
insn |= tilegx_opcodes[TILEGX_OPC_FNOP].
fixed_bit_values[2];
if (p != 1)
insn |= tilegx_opcodes[TILEGX_OPC_FNOP].
fixed_bit_values[3];
/* Fill-in Y2 as dumy load "ld zero, sp" */
if (p != 2) {
insn |= tilegx_opcodes[TILEGX_OPC_LD].
fixed_bit_values[4];
opd = &tilegx_operands[tilegx_opcodes[TILEGX_OPC_LD].operands[4][0]];
insn |= opd->insert(63);
opd = &tilegx_operands[tilegx_opcodes[TILEGX_OPC_LD].operands[4][1]];
insn |= opd->insert(54);
}
#ifdef DBG
printf(" Y%d, ", p);
#endif
insn |= opc->fixed_bit_values[2 + p];
printf("//file: _insn_test_%s_Y%d.c\n", decoded.opcode->name, p);
printf("//op=%d\n", op_idx);
printf("#include <stdio.h>\n");
printf("#include <stdlib.h>\n");
printf("\n"
"void func_exit(void) {\n"
" printf(\"%cs\\n\", __func__);\n"
" exit(0);\n"
"}\n"
"\n"
"void func_call(void) {\n"
" printf(\"%cs\\n\", __func__);\n"
" exit(0);\n"
"}\n"
"\n"
"unsigned long mem[2] = { 0x%lx, 0x%lx };\n"
"\n", '%', '%', RAND(op_idx), RAND(op_idx));
printf("int main(void) {\n");
printf(" unsigned long a[4] = { 0, 0 };\n");
printf(" asm __volatile__ (\n");
int n = 0;
if (op_abnorm[op_idx] & 6)
{
/* loop for each operand. */
for (i = 0 ; i < op_num; i++)
{
opd = &tilegx_operands[opc->operands[2 + p][i]];
if (opd->type == TILEGX_OP_TYPE_REGISTER) {
/* A register operand, pick register 0-53 randomly. */
decoded.operand_values[i] = RAND(op_idx) % 53;
int r = decoded.operand_values[i];
int64_t d = RAND(op_idx);
#ifdef DBG
printf(" %d) r%-2d %016lx\n", i, (int)r, (unsigned long)d);
#endif
int k = 0;
for (k = 3; k >= 0 ; k--) {
if (d >> (16 * k) || k == 0) {
printf(" \"moveli r%d, %d\\n\"\n", r, (int)(d >> (16 * k)));
for (k--; k >= 0; k--)
printf(" \"shl16insli r%d, r%d, %d\\n\"\n", r, r, (int)(int16_t)(d >> (16 * k)));
break;
}
}
} else {
/* An immediate operand, pick a random value. */
decoded.operand_values[i] = RAND(op_idx);
#ifdef DBG
printf(" %d) %016lx\n", (int)i, (unsigned long)decoded.operand_values[i]);
#endif
}
Long op = decoded.operand_values[i];
decoded.operands[i] = opd;
ULong x = opd->insert(op);
insn |= x;
}
printf(" \"");
if (op_abnorm[op_idx] & 2)
printf("move r%d, %c2\\n\"\n", (int)decoded.operand_values[1], '%');
else
printf("move r%d, %c2\\n\"\n", (int)decoded.operand_values[0], '%');
printf(" \"");
decode(&insn, 3, 0);
printf("\\n\"\n");
/* loop for each operand. */
n = 0;
for (i = 0 ; i < op_num; i++)
{
opd = &tilegx_operands[opc->operands[2 + p][i]];
if (opd->type == TILEGX_OP_TYPE_REGISTER) {
/* A register operand */
printf(" \"move %c%d, r%d\\n\"\n", '%', n, (int)decoded.operand_values[i]);
n++;
}
}
printf(" ");
if (n)
printf(":");
for (i = 0; i < n; i++)
{
printf("\"=r\"(a[%d])", i);
if (i != n - 1)
printf(",");
}
printf(" : \"r\"(mem)");
printf(");\n");
printf(" printf(\"%c016lx %c016lx\\n\", mem[0], mem[1]);\n", '%', '%');
}
else if (op_idx == TILEGX_OPC_J)
{
printf(" \"%s %c0\\n\"\n", decoded.opcode->name, '%');
printf(" :: \"i\"(func_exit));\n");
}
else if (op_idx == TILEGX_OPC_JAL)
{
printf(" \"%s %c0\\n\"\n", decoded.opcode->name, '%');
printf(" :: \"i\"(func_call));\n");
}
else if (op_idx == TILEGX_OPC_JR || op_idx == TILEGX_OPC_JRP)
{
printf(" \"%s %c0\\n\"\n", decoded.opcode->name, '%');
printf(" :: \"r\"(func_exit));\n");
}
else if (op_idx == TILEGX_OPC_JALR || op_idx == TILEGX_OPC_JALRP )
{
printf(" \"%s %c0\\n\"\n", decoded.opcode->name, '%');
printf(" :: \"r\"(func_call));\n");
}
else if (op_abnorm[op_idx] & 8)
{
// OPC_BXXX conditional branch
int r = RAND(op_idx) % 51;
int d = RAND(op_idx) & 1;
printf(" \"movei r%d, %d\\n\"\n", r, d);
printf(" \"%s r%d, %c0\\n\"\n", decoded.opcode->name, r, '%');
printf(" \"jal %c1\\n\"\n", '%');
printf(" :: \"i\"(func_exit), \"i\"(func_call));\n");
}
else
{
/* loop for each operand. */
for (i = 0 ; i < op_num; i++)
{
opd = &tilegx_operands[opc->operands[2 + p][i]];
if (opd->type == TILEGX_OP_TYPE_REGISTER) {
/* A register operand, pick register 0-50 randomly. */
decoded.operand_values[i] = RAND(op_idx) % 51;
int r = decoded.operand_values[i];
int64_t d = RAND(op_idx);
#ifdef DBG
printf(" %d) r%-2d %016lx\n", i, (int)r, (unsigned long)d);
#endif
int k = 0;
for (k = 3; k >= 0 ; k--) {
if (d >> (16 * k) || k == 0) {
printf(" \"moveli r%d, %d\\n\"\n", r, (int)(d >> (16 * k)));
for (k--; k >= 0; k--)
printf(" \"shl16insli r%d, r%d, %d\\n\"\n", r, r, (int)(int16_t)(d >> (16 * k)));
break;
}
}
} else {
/* An immediate operand, pick a random value. */
decoded.operand_values[i] = RAND(op_idx);
#ifdef DBG
printf(" %d) %016lx\n", (int)i, (unsigned long)decoded.operand_values[i]);
#endif
}
Long op = decoded.operand_values[i];
decoded.operands[i] = opd;
ULong x = opd->insert(op);
insn |= x;
}
printf(" \"");
decode(&insn, 3, 0);
printf("\\n\"\n");
/* loop for each operand. */
n = 0;
for (i = 0 ; i < op_num; i++)
{
opd = &tilegx_operands[opc->operands[2 + p][i]];
if (opd->type == TILEGX_OP_TYPE_REGISTER) {
/* A register operand */
printf(" \"move %c%d, r%d\\n\"\n", '%', n, (int)decoded.operand_values[i]);
n++;
}
}
printf(" ");
if (n)
printf(":");
for (i = 0; i < n; i++)
{
printf("\"=r\"(a[%d])", i);
if (i != n - 1)
printf(",");
}
printf(");\n");
}
for (i = 0; i < n; i++)
{
printf(" printf(\"%c016lx\\n\", a[%d]);\n", '%', i);
}
printf(" return 0;\n");
printf("}\n");
return insn;
}
static int display_insn ( struct tilegx_decoded_instruction
decoded[1] )
{
int i;
for (i = 0;
decoded[i].opcode && (i < 1);
i++) {
int n;
printf("%s ", decoded[i].opcode->name);
for (n = 0; n < decoded[i].opcode->num_operands; n++) {
const struct tilegx_operand *op = decoded[i].operands[n];
if (op->type == TILEGX_OP_TYPE_REGISTER)
printf("r%d", (int) decoded[i].operand_values[n]);
else
printf("%ld", (unsigned long)decoded[i].operand_values[n]);
if (n != (decoded[i].opcode->num_operands - 1))
printf(", ");
}
printf(" ");
}
return i;
}
int decode( tilegx_bundle_bits *p, int count, ULong pc )
{
struct tilegx_decoded_instruction
decode[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE];
if (pc) {
printf("%012llx %016llx ", pc, (ULong)p[0]);
pc += 8;
}
parse_insn_tilegx(p[0], 0, decode);
int k;
printf("{ ");
for(k = 0; decode[k].opcode && (k <TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE);
k++) {
display_insn(&decode[k]);
if (--count > 0)
printf("; ");
}
printf(" }");
return count;
}