Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / rst / rstzip3 / rstzip_v3 / rz3iu.C
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: rz3iu.C
4// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
6//
7// The above named program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public
9// License version 2 as published by the Free Software Foundation.
10//
11// The above named program is distributed in the hope that it will be
12// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// General Public License for more details.
15//
16// You should have received a copy of the GNU General Public
17// License along with this work; if not, write to the Free Software
18// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19//
20// ========== Copyright Header End ============================================
21/* rz3iu.C
22 */
23
24#include <sys/types.h>
25
26#include "rz3iu.h"
27
28#include "rz_insttypes.h"
29
30// #include "spix_sparc.h"
31
32// union dcti_info_u gen_dcti_info(uint32_t instr, spix_sparc_iop_t iop)
33
34// fixed in v3.18 - better classification of branch_never insts
35union dcti_info_u gen_dcti_info(uint32_t instr)
36{
37 union dcti_info_u dinfo;
38 dinfo.u32 = 0x0;
39
40 // if (spix_sparc_iop_isdcti(iop)) {
41 if (rz_is_dcti(instr)) {
42 dinfo.flags.isdcti = true;
43 // if (spix_sparc_iop_isbranch(iop)) {
44 if (rz_is_branch(instr)) {
45 dinfo.flags.isbranch = true;
46 // if (spix_sparc_iop_iscbranch(iop)) {
47 if (rz_is_cbranch(instr)) {
48 dinfo.flags.iscbranch = true;
49 } else /* not cbranch */ {
50 dinfo.flags.isubranch = true;
51 // uint32_t b = (instr & UBRANCH_OPCODE_MASK);
52 // if ((b == FBN_OPCODE_BITS) || (b == BN_OPCODE_BITS)) {
53 if (rz_is_ubranch_never(instr)) {
54 dinfo.flags.isubranch_nottaken = true;
55 }
56 } /* cbranch? */
57
58 dinfo.flags.annul_flag = (instr >> 29) & 1;
59
60 // specific branch type and disp
61 // if ((instr & BPcc_OPCODE_MASK) == BPcc_OPCODE_BITS) {
62 if (rz_is_bpcc(instr)) {
63 dinfo.flags.isBPcc = 1;
64 // } else if ((instr & BPR_OPCODE_MASK) == BPR_OPCODE_BITS) {
65 } else if (rz_is_bpr(instr)) {
66 dinfo.flags.isBPR = 1;
67 // } else if ((instr & FBfcc_OPCODE_MASK) == FBfcc_OPCODE_BITS) {
68 } else if (rz_is_fbfcc(instr)) {
69 dinfo.flags.isFBfcc = 1;
70 // } else if ((instr & FBPfcc_OPCODE_MASK) == FBPfcc_OPCODE_BITS) {
71 } else if (rz_is_fbpfcc(instr)) {
72 dinfo.flags.isFBPfcc = 1;
73 // } else if ((instr & Bicc_OPCODE_MASK) == Bicc_OPCODE_BITS) {
74 } else if (rz_is_bicc(instr)) {
75 dinfo.flags.isBicc = 1;
76 } else {
77 /* other branch instr? */
78 fprintf(stderr, "ERROR: rz3iu: gen_dcti_info: invalid branch instr %08x\n", instr);
79 dinfo.u32 = 0;
80 return dinfo;
81 }
82
83 } else /* not branch */ {
84 // if ((instr & CALL_OPCODE_MASK) == CALL_OPCODE_BITS) {
85 if (rz_is_call(instr)) {
86 dinfo.flags.iscall = 1;
87 } else {
88 dinfo.flags.isindirect = 1;
89 // is ret if rd=0, rs1=31, imm=8
90 // is retl if rd=0, rs1=15, imm=8
91 // is "call indirect" otherwise if rd is 15
92 int rs1 = (instr >> 14) & 0x1f;
93 int rd = (instr >> 25) & 0x1f;
94 uint32_t simm13 = instr & 0x1fff;
95 if ((rd == 0) && (simm13 == 0x8)){
96 if (rs1 == 15) {
97 dinfo.flags.is_retl = 1;
98 } else if (rs1 == 31) {
99 dinfo.flags.is_ret = 1;
100 } else {
101 // do nothing
102 }
103 } // else - do nothing
104 }
105 } // branch?
106 // } else if ((iop == SPIX_SPARC_IOP_DONE)||(iop == SPIX_SPARC_IOP_RETRY)) {
107 } else if (rz_is_done(instr) || rz_is_retry(instr)) {
108 dinfo.flags.is_done_retry = 1;
109 } else {
110 // do nothing
111 } // instr type?
112
113 return dinfo;
114} // gen_dcti_info
115
116
117// BUG: in versions 3.17 and older, branch_never insts were counted
118// as conditional branches and iscbranch was set, because of the
119// way spix classifies these insts. this leads to an incorrect value
120// of iscbranch/isubranch/isubranch_nottaken for branch_never insts.
121// This causes the compressor to use the branch predictor for these
122// branches, which affects the compression efficiency.
123union dcti_info_u gen_dcti_info_v317(uint32_t instr)
124{
125 union dcti_info_u dinfo;
126 dinfo.u32 = 0x0;
127
128 // if (spix_sparc_iop_isdcti(iop)) {
129 if (rz_is_dcti(instr)) {
130 dinfo.flags.isdcti = true;
131 // if (spix_sparc_iop_isbranch(iop)) {
132 if (rz_is_branch(instr)) {
133 dinfo.flags.isbranch = true;
134 // if (spix_sparc_iop_iscbranch(iop)) {
135 if (rz_is_cbranch(instr) || rz_is_ubranch_never(instr)) {
136 dinfo.flags.iscbranch = true;
137 } else /* not cbranch */ {
138 dinfo.flags.isubranch = true;
139 uint32_t b = (instr & UBRANCH_OPCODE_MASK);
140 if ((b == FBN_OPCODE_BITS) || (b == BN_OPCODE_BITS)) {
141 dinfo.flags.isubranch_nottaken = true;
142 }
143 } /* cbranch? */
144
145 dinfo.flags.annul_flag = (instr >> 29) & 1;
146
147 // specific branch type and disp
148 // if ((instr & BPcc_OPCODE_MASK) == BPcc_OPCODE_BITS) {
149 if (rz_is_bpcc(instr)) {
150 dinfo.flags.isBPcc = 1;
151 // } else if ((instr & BPR_OPCODE_MASK) == BPR_OPCODE_BITS) {
152 } else if (rz_is_bpr(instr)) {
153 dinfo.flags.isBPR = 1;
154 // } else if ((instr & FBfcc_OPCODE_MASK) == FBfcc_OPCODE_BITS) {
155 } else if (rz_is_fbfcc(instr)) {
156 dinfo.flags.isFBfcc = 1;
157 // } else if ((instr & FBPfcc_OPCODE_MASK) == FBPfcc_OPCODE_BITS) {
158 } else if (rz_is_fbpfcc(instr)) {
159 dinfo.flags.isFBPfcc = 1;
160 // } else if ((instr & Bicc_OPCODE_MASK) == Bicc_OPCODE_BITS) {
161 } else if (rz_is_bicc(instr)) {
162 dinfo.flags.isBicc = 1;
163 } else {
164 /* other branch instr? */
165 fprintf(stderr, "ERROR: rz3iu: gen_dcti_info: invalid branch instr %08x\n", instr);
166 dinfo.u32 = 0;
167 return dinfo;
168 }
169
170 } else /* not branch */ {
171 // if ((instr & CALL_OPCODE_MASK) == CALL_OPCODE_BITS) {
172 if (rz_is_call(instr)) {
173 dinfo.flags.iscall = 1;
174 } else {
175 dinfo.flags.isindirect = 1;
176 // is ret if rd=0, rs1=31, imm=8
177 // is retl if rd=0, rs1=15, imm=8
178 // is "call indirect" otherwise if rd is 15
179 int rs1 = (instr >> 14) & 0x1f;
180 int rd = (instr >> 25) & 0x1f;
181 uint32_t simm13 = instr & 0x1fff;
182 if ((rd == 0) && (simm13 == 0x8)){
183 if (rs1 == 15) {
184 dinfo.flags.is_retl = 1;
185 } else if (rs1 == 31) {
186 dinfo.flags.is_ret = 1;
187 } else {
188 // do nothing
189 }
190 } // else - do nothing
191 }
192 } // branch?
193 // } else if ((iop == SPIX_SPARC_IOP_DONE)||(iop == SPIX_SPARC_IOP_RETRY)) {
194 } else if (rz_is_done(instr) || rz_is_retry(instr)) {
195 dinfo.flags.is_done_retry = 1;
196 } else {
197 // do nothing
198 } // instr type?
199
200 return dinfo;
201} // gen_dcti_info
202
203
204void rz3iu_icache_data::gen_target(uint64_t pc)
205{
206 if (dinfo.flags.isbranch) {
207 if (dinfo.flags.isBPcc) {
208 target = pc + BPcc_DISP(instr);
209 } else if (dinfo.flags.isBPR) {
210 target = pc + BPR_DISP(instr);
211 } else if (dinfo.flags.isFBfcc) {
212 target = pc + FBfcc_DISP(instr);
213 } else if (dinfo.flags.isFBPfcc) {
214 target = pc + FBPfcc_DISP(instr);
215 } else if (dinfo.flags.isBicc) {
216 target = pc + Bicc_DISP(instr);
217 } else {
218 assert(0);
219 }
220 } else if (dinfo.flags.iscall) {
221 target = pc + CALL_DISP(instr);
222 }
223} // gen_target()
224
225