// ========== Copyright Header Begin ========================================== // // OpenSPARC T2 Processor File: rstexample.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 ============================================ #include #include #include #include #include "rstf/rstf.h" #include "Rstzip.H" #define SET_ONES( bits ) ((1ULL << (bits))-1) #define GET_BITS( lw, hi, lo ) ((lw >> lo) & SET_ONES(hi - lo + 1)) #define SET_BITS( lw, hi, lo, v ) (lw=((lw & ~(SET_ONES(hi - lo + 1) << lo))|(((v&SET_ONES(hi - lo + 1)) << lo)))) typedef enum { Ty_0 = 0, /* branches and SETHI */ Ty_1 = 1, /* CALL */ Ty_2 = 2, /* arithmetic & Misc */ Ty_3 = 3 /* Loads/Stores */ } ty_code_t; typedef enum { T0o3_Illtrap = 0, T0o3_BPcc, T0o3_Bicc, T0o3_BPr, T0o3_SetHi, T0o3_FBPfcc, T0o3_FBfcc, T0o3_unknown_0x7 } T0o3_code_t; typedef enum { /* Col 0 (0x00 - 0x0f) */ T2o3_add, T2o3_and, T2o3_or, T2o3_xor, T2o3_sub, T2o3_andn, T2o3_orn, T2o3_xnor, T2o3_addc, T2o3_mulx, T2o3_umul, T2o3_smul, T2o3_subc, T2o3_udivx, T2o3_udiv, T2o3_sdiv, /* Col 1 (0x10 - 0x1f) */ T2o3_addcc, T2o3_andcc, T2o3_orcc, T2o3_xorcc, T2o3_subcc, T2o3_andncc, T2o3_orncc, T2o3_xnorcc, T2o3_addccc, T2o3_unknown_0x19, T2o3_umulcc, T2o3_smulcc, T2o3_subccc, T2o3_unknown_0x1d, T2o3_udivcc, T2o3_sdivcc, /* Col 2 (0x20 - 0x2f) */ T2o3_taddcc, T2o3_tsubcc, T2o3_taddcctv, T2o3_tsubcctv, T2o3_mulscc, T2o3_sll, T2o3_srl, T2o3_sra, T2o3_rdasr, T2o3_unknown_0x29, T2o3_rdpr, T2o3_flushw, T2o3_movcc, T2o3_sdivx, T2o3_popc, T2o3_movr, /* Col 3 (0x30 - 0x3f) */ T2o3_wrasr, T2o3_saved, T2o3_wrpr, T2o3_unknown_0x33, T2o3_fpop_0x34, T2o3_fpop_0x35, T2o3_gop, T2o3_fpop_0x37, T2o3_jmpl, T2o3_return, T2o3_tcc, T2o3_flush, T2o3_save, T2o3_restore, T2o3_retry, T2o3_fpop_0x3f } T2o3_code_t; typedef enum { /* Col 0 (0x00 - 0x0f) */ T3o3_lduw, T3o3_ldub, T3o3_lduh, T3o3_ldd, T3o3_stw, T3o3_stb, T3o3_sth, T3o3_std, T3o3_ldsw, T3o3_ldsb, T3o3_ldsh, T3o3_ldx, T3o3_unknown_0x0c, T3o3_ldstub1, T3o3_stx, T3o3_swapd, /* Col 1 (0x10 - 0x1f) */ T3o3_lduwa, T3o3_lduba, T3o3_lduha, T3o3_ldda, T3o3_stwa, T3o3_stba, T3o3_stha, T3o3_stda, T3o3_ldswa, T3o3_ldsba, T3o3_ldsha, T3o3_ldxa, T3o3_unknown_0x1c, T3o3_ldstuba, T3o3_stxa, T3o3_swapa, /* Col 2 (0x20 - 0x2f) */ T3o3_ldf, T3o3_ldfsr, T3o3_ldqf, T3o3_lddf, T3o3_stf, T3o3_stfsr, T3o3_stqf, T3o3_stdf, T3o3_unknown_0x28, T3o3_unknown_0x29, T3o3_unknown_0x2a, T3o3_unknown_0x2b, T3o3_unknown_0x2c, T3o3_prefetch, T3o3_unknown_0x2e, T3o3_unknown_0x2f, /* Col 3 (0x30 - 0x3f) */ T3o3_ldfa, T3o3_unknown_0x31, T3o3_ldqfa, T3o3_lddfa, T3o3_stfa, T3o3_unknown_0x35, T3o3_stqfa, T3o3_stdfa, T3o3_unknown_0x38, T3o3_unknown_0x39, T3o3_unknown_0x3a, T3o3_unknown_0x3b, T3o3_casa, T3o3_prefetcha, T3o3_casxa, T3o3_unknown_0x3f } T3o3_code_t; enum { BA = 0x8, BN = 0x0, BPN = 0x0, BPA = 0x8, FBA = 0x8, FBN = 0x0, FBPA = 0x8, FBPN = 0x0 }ops; typedef enum { UBICC, BICC, BPCC, BPR, SETHI, FINSTR, FBFCC, UFBCC, FBPFCC, ADD, AND, ANDN, OR, ORN, XOR, XNOR, SUB, SUBCC, SLL, SRL, ANDCC, JMPL, SAVED, SMUL, UMUL, ORCC, RETRY, RESTORE, ASI, LOAD, STORE, ATOMIC, LDUW, LDUB, LDUH, LDD, LDX, LDF, LDDF, STF, STDF, LDFA, LDDFA, STFA, STDFA, STW, STB, STH, STX, STD, LDSW, LDSB, LDSH, LDUWA, LDUBA, LDUHA, LDSWA, LDXA, LDSBA, LDSHA, STWA, STBA, STHA, STXA, LDSTUB, CASXA, BRANCH }instructions; const char usage[] = "parsetrace "; uint32_t rd_ofs = 32, rs1_ofs = 32, rs2_ofs = 32, rs3_ofs = 32; uint32_t op(uint64_t iw_) { return (iw_ >> 30); } // [31:30] uint32_t op2(uint64_t iw_) { return ((iw_ >> 22) & 0x7); } // [24:22] uint32_t op3(uint64_t iw_) { return ((iw_ >> 19) & 0x3f); } // [24:19] uint32_t opf(uint64_t iw_) { return ((iw_ >> 5) & 0x1ff); } // [13:5] uint32_t rd(uint64_t iw_) { return ((iw_ >> 25) & 0x1f) + rd_ofs; } // [29:25] uint32_t rs1(uint64_t iw_) { return ((iw_ >> 14) & 0x1f) + rs1_ofs; } // [18:14] uint32_t rs2(uint64_t iw_) { return ( iw_ & 0x1f) + rs2_ofs; } // [4:0] uint32_t rs3(uint64_t iw_) { return ((iw_ >> 9) & 0x1f) + rs3_ofs; } // [13:9] uint32_t i(uint64_t iw_) { return ((iw_ >> 13) & 0x1); } // [13:13] uint32_t immAsi(uint64_t iw_) { return ((iw_ >> 5) & 0xff); } // [12:5] uint32_t disp30(uint64_t iw_) { return (iw_ & 0x3fffffff); } // [29:0] uint32_t disp22(uint64_t iw_) { return (iw_ & 0x3fffff); } // [21:0] uint32_t imm22(uint64_t iw_) { return (iw_ & 0x3fffff); } // [21:0] uint32_t opf_cc(uint64_t iw_) { return ((iw_ >> 11) & 0x7); } // [13:11] uint32_t cc0(uint64_t iw_) { if ( op(iw_) == 0 ) { return GET_BITS( iw_, 20, 20 ); } else if ( op(iw_) == 2 ) { if ((op3(iw_) == 0x35) || (op3(iw_) == 0x36)) { return GET_BITS( iw_, 25, 25 ); } else { return GET_BITS( iw_, 11, 11 ); } } } uint32_t cc1(uint64_t iw_) { if ( op(iw_) == 0 ) { return GET_BITS( iw_, 21, 21 ); } else if ( op(iw_) == 2 ) { if ((op3(iw_) == 0x35) || (op3(iw_) == 0x36)) { return GET_BITS( iw_, 26, 26 ); } else { return GET_BITS( iw_, 12, 12 ); } } } uint32_t cc2(uint64_t iw_){ return ((iw_ >> 18) & 0x1); } // [18:18] uint32_t fmt2CC(uint64_t iw_) { return ((iw_ >> 20) & 0x3); } // [21:20] uint32_t rcond(uint64_t iw_) { if (op(iw_) == 0x0) return (iw_ >> 25) & 0x7; // [27:25] else return (iw_ >> 10) & 0x7; // [12:10] } uint32_t cond(uint64_t iw_) { if ((op(iw_) == 0x0) || ((op(iw_) == 0x2) && (op3(iw_) == 0x3A))) return (iw_ >> 25) & 0xf; // [28:25] else return (iw_ >> 14) & 0xf; // [17:14] } uint32_t get( uint8_t, uint8_t ); uint32_t x(uint64_t iw_) { return ((iw_ >> 12) & 0x1); } // [12:12] uint32_t p(uint64_t iw_) { return ((iw_ >> 19) & 0x1); } // [19:19] uint32_t a(uint64_t iw_) { return ((iw_ >> 29) & 0x1); } // [29:29] uint32_t disp19(uint64_t iw_) { return (iw_ & 0x7ffff); } // [18:0] uint32_t disp16(uint64_t iw_) { return ((((iw_ >> 20) & 0x3) << 14) | (iw_ & 0x3fff)); } // ([21:20] << 14) | [13:0] uint32_t shcnt32(uint64_t iw_) { return (iw_ & 0x1f); } // [4:0] uint32_t shcnt64(uint64_t iw_) { return (iw_ & 0x3f); } // [5:0] uint32_t cmask(uint64_t iw_) { return ((iw_ >> 4) & 0x7); } // [6:4] uint32_t fcn(uint64_t iw_) { return ((iw_ >> 25) & 0x1f); } // [29:25] uint32_t mode(uint64_t iw_) { return (iw_ & 0x7); } // [2:0] int64_t simm10(uint64_t iw_) { int64_t tmp = iw_ & 0x3ff; return ((tmp << 54) >> 54); } // [9:0] int64_t simm11(uint64_t iw_) { int64_t tmp = iw_ & 0x7ff; return ((tmp << 53) >> 53); } // [10:0] int64_t simm13(uint64_t iw_) { int64_t tmp = iw_ & 0x1fff; return ((tmp << 51) >> 51); } // [12:0] uint8_t movCC(uint64_t iw_) { return ((((iw_ >> 18) & 0x1) << 2) | ((iw_ >> 11) & 0x3)); } // ([18:18] << 2) | [12:11] uint8_t trapCC(uint64_t iw_) { return ((iw_ >> 11) & 0x3); } // [12:11] uint8_t swTrapNr(uint64_t iw_) { return (iw_ & 0x7f); } // [6:0] // Main int main(int argc, char **argv) { // argv[1] must be input file const char * ifname = NULL; uint64_t INSTR_TABLE[80]; int i=1; while(iopen(ifname, "r", "verbose=0"); if (rv != RSTZIP_OK) { fprintf(stderr, "ERROR: rstexample: Rstzip error opening input file %s\n", ifname); exit(1); } const int max_ncpu=1<<10; // RST supports 10-bit cpuids int64_t icounts[max_ncpu]; memset(icounts, 0, max_ncpu*sizeof(int64_t)); int64_t total_icount = 0; int nrecs, total_recs = 0; rstf_unionT buf[rstzip_opt_buffersize]; while((nrecs = rz->decompress(buf, rstzip_opt_buffersize)) != 0) { int i; uint32_t iw; for (i=0; iproto.rtype) { case INSTR_T: { total_icount++; int cpuid = rstf_instrT_get_cpuid(&(rp->instr)); icounts[cpuid]++; iw = rp->instr.instr; switch((ty_code_t) op(iw)) { case Ty_0: // Branches and SETHI { switch (op2(iw)) { case T0o3_Bicc: INSTR_TABLE[BRANCH]++; INSTR_TABLE[BICC]++; if ( cond(iw) == BA || cond(iw) == BN ) INSTR_TABLE[UBICC]++; break; case T0o3_BPcc: INSTR_TABLE[BRANCH]++; INSTR_TABLE[BPCC]++; break; case T0o3_BPr: INSTR_TABLE[BRANCH]++; INSTR_TABLE[BPR]++; break; case T0o3_SetHi: INSTR_TABLE[SETHI]++; break; case T0o3_FBfcc: INSTR_TABLE[BRANCH]++; INSTR_TABLE[FINSTR]++; INSTR_TABLE[FBFCC]++; if ( cond(iw) == FBN || cond(iw) == FBA ) INSTR_TABLE[UFBCC]++; break; case T0o3_FBPfcc: INSTR_TABLE[BRANCH]++; INSTR_TABLE[FINSTR]++; INSTR_TABLE[FBPFCC]++; if ( cond(iw) == FBPN || cond(iw) == FBPA ) INSTR_TABLE[UFBCC]++; break; // case T0o3_Illtrap: // case T0o3_unknown_0x7: // RIESLING_TRAP( Sf_Trap::illegal_instruction ); // return true; default: break; } } case Ty_1: // CALL -- always taken { INSTR_TABLE[BRANCH]++; } case Ty_2: // Arithmetic and misc. { switch (op3(iw)) { case T2o3_add : INSTR_TABLE[ADD]++; break; case T2o3_and : INSTR_TABLE[AND]; break; case T2o3_andn : INSTR_TABLE[ANDN]++; break; case T2o3_or : INSTR_TABLE[OR]++; break; case T2o3_orn : INSTR_TABLE[ORN]++; break; case T2o3_xor : INSTR_TABLE[XOR]++; break; case T2o3_xnor : INSTR_TABLE[XNOR]++; break; case T2o3_sub : INSTR_TABLE[SUB]++; break; case T2o3_fpop_0x34 : INSTR_TABLE[FINSTR]++; break; case T2o3_fpop_0x35 : INSTR_TABLE[FINSTR]++; break; case T2o3_gop : //INSTR_TABLE[XOR]++; break; case T2o3_subcc : INSTR_TABLE[SUBCC]++; break; case T2o3_sll : INSTR_TABLE[SLL]++; break; case T2o3_srl : INSTR_TABLE[SRL]++; break; case T2o3_andcc : INSTR_TABLE[ANDCC]++; break; case T2o3_jmpl : INSTR_TABLE[JMPL]++; break; case T2o3_saved :/* FIXME - are these valid */ INSTR_TABLE[SAVED]++; break; case T2o3_smul : INSTR_TABLE[SMUL]++; break; case T2o3_umul : INSTR_TABLE[UMUL]++; break; case T2o3_orcc : INSTR_TABLE[ORCC]++; break; case T2o3_retry : INSTR_TABLE[RETRY]++; break; case T2o3_restore : INSTR_TABLE[RESTORE]++; break; default: break; } } case Ty_3: // Loads/Stores { switch ( op3(iw) ) { case T3o3_lduw: INSTR_TABLE[LOAD]++; INSTR_TABLE[LDUW]++; break; case T3o3_ldub: INSTR_TABLE[LOAD]++; INSTR_TABLE[LDUB]++; break; case T3o3_lduh: INSTR_TABLE[LOAD]++; INSTR_TABLE[LDUH]++; break; case T3o3_ldd: INSTR_TABLE[LOAD]++; INSTR_TABLE[LDD]++; break; case T3o3_ldx: INSTR_TABLE[LOAD]++; INSTR_TABLE[LDX]++; break; case T3o3_ldf: INSTR_TABLE[LOAD]++; INSTR_TABLE[FINSTR]++; INSTR_TABLE[LDF]++; break; case T3o3_lddf: INSTR_TABLE[LOAD]++; INSTR_TABLE[FINSTR]++; INSTR_TABLE[LDDF]++; break; case T3o3_stf: INSTR_TABLE[FINSTR]++; INSTR_TABLE[STORE]++; INSTR_TABLE[STF]++; break; case T3o3_stdf: INSTR_TABLE[FINSTR]++; INSTR_TABLE[STORE]++; INSTR_TABLE[STDF]++; break; case T3o3_ldfa: INSTR_TABLE[LOAD]++; INSTR_TABLE[FINSTR]++; INSTR_TABLE[ASI]++; INSTR_TABLE[LDFA]++; break; case T3o3_lddfa: INSTR_TABLE[LOAD]++; INSTR_TABLE[FINSTR]++; INSTR_TABLE[ASI]++; INSTR_TABLE[LDDFA]++; break; case T3o3_stfa: INSTR_TABLE[FINSTR]++; INSTR_TABLE[STORE]++; INSTR_TABLE[ASI]++; INSTR_TABLE[STFA]++; break; case T3o3_stdfa: INSTR_TABLE[FINSTR]++; INSTR_TABLE[STORE]++; INSTR_TABLE[ASI]++; INSTR_TABLE[STDFA]++; break; case T3o3_stw: INSTR_TABLE[STORE]++; INSTR_TABLE[STW]++; break; case T3o3_stb: INSTR_TABLE[STORE]++; INSTR_TABLE[STB]++; break; case T3o3_sth: INSTR_TABLE[STORE]++; INSTR_TABLE[STH]++; break; case T3o3_stx: INSTR_TABLE[STORE]++; INSTR_TABLE[STX]++; break; case T3o3_std: INSTR_TABLE[STORE]++; INSTR_TABLE[STD]++; break; case T3o3_ldsw: INSTR_TABLE[LOAD]++; INSTR_TABLE[LDSW]++; break; case T3o3_ldsb: INSTR_TABLE[LOAD]++; INSTR_TABLE[LDSB]++; break; case T3o3_ldsh: INSTR_TABLE[LOAD]++; INSTR_TABLE[LDSH]++; break; case T3o3_lduwa: INSTR_TABLE[LOAD]++; INSTR_TABLE[ASI]++; INSTR_TABLE[LDUWA]++; break; case T3o3_lduba: INSTR_TABLE[LOAD]++; INSTR_TABLE[ASI]++; INSTR_TABLE[LDUBA]++; break; case T3o3_lduha: INSTR_TABLE[LOAD]++; INSTR_TABLE[ASI]++; INSTR_TABLE[LDUHA]++; break; case T3o3_ldswa: INSTR_TABLE[LOAD]++; INSTR_TABLE[ASI]++; INSTR_TABLE[LDSWA]++; break; case T3o3_ldxa: INSTR_TABLE[LOAD]++; INSTR_TABLE[ASI]++; INSTR_TABLE[LDXA]++; break; case T3o3_ldsba: INSTR_TABLE[LOAD]++; INSTR_TABLE[ASI]++; INSTR_TABLE[LDSBA]++; break; case T3o3_ldsha: INSTR_TABLE[LOAD]++; INSTR_TABLE[ASI]++; INSTR_TABLE[LDSHA]++; break; case T3o3_stwa: INSTR_TABLE[STORE]++; INSTR_TABLE[ASI]++; INSTR_TABLE[STWA]++; break; case T3o3_stba: INSTR_TABLE[STORE]++; INSTR_TABLE[ASI]++; INSTR_TABLE[STBA]++; break; case T3o3_stha: INSTR_TABLE[STORE]++; INSTR_TABLE[ASI]++; INSTR_TABLE[STHA]++; break; case T3o3_stxa: INSTR_TABLE[STORE]++; INSTR_TABLE[ASI]++; INSTR_TABLE[STXA]++; break; case T3o3_ldstub1: INSTR_TABLE[ATOMIC]++; INSTR_TABLE[LDSTUB]++; break; case T3o3_ldstuba: INSTR_TABLE[ATOMIC]++; INSTR_TABLE[ASI]++; INSTR_TABLE[LDSTUB]++; break; case T3o3_casxa: INSTR_TABLE[ATOMIC]++; INSTR_TABLE[ASI]++; INSTR_TABLE[CASXA]++; break; default: break; } } } } } } total_recs += nrecs; } rz->close(); delete rz; rz=NULL; printf("Total icount=%lld\n", total_icount); printf("Total load instr =%lld\n", INSTR_TABLE[LOAD]); printf("Total store instr =%lld\n", INSTR_TABLE[LOAD]); printf("Total branch instr =%lld\n", INSTR_TABLE[BRANCH]); printf("Load = %f\tStore = %f\tBranch = %f\n", ((float)INSTR_TABLE[LOAD]/(float)total_icount), ((float)INSTR_TABLE[STORE]/(float)total_icount), ((float)INSTR_TABLE[BRANCH]/(float)total_icount) ); for (i=0; i 0) { printf("cpu%d: icount=%lld\n", i, icounts[i]); } } } // main()