//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; }