Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * OpenSPARC T2 Processor File: SS_Instr.h | |
5 | * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
6 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES. | |
7 | * | |
8 | * The above named program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public | |
10 | * License version 2 as published by the Free Software Foundation. | |
11 | * | |
12 | * The above named program is distributed in the hope that it will be | |
13 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public | |
18 | * License along with this work; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. | |
20 | * | |
21 | * ========== Copyright Header End ============================================ | |
22 | */ | |
23 | #ifndef __SS_Instr_h__ | |
24 | #define __SS_Instr_h__ | |
25 | ||
26 | #include "SS_Types.h" | |
27 | #include "SS_Opcode.h" | |
28 | #include "SS_Tte.h" | |
29 | #include "SS_Chain.h" | |
30 | ||
31 | class SS_Strand; | |
32 | class SS_BreakPoint; | |
33 | ||
34 | #undef REG_ASI | |
35 | ||
36 | // The SS_Instr class captures the decoding of an intruction. The | |
37 | // decode cache, after decoding, contains SS_Instr objects. | |
38 | ||
39 | // Danger, danger, danger!! | |
40 | // | |
41 | // NB: The SS_Instr objects are interwoven in the decode cache and | |
42 | // overlap each other. An SS_Instr object's data layout is: | |
43 | // | |
44 | // Size Content | |
45 | // ---- ------ | |
46 | // 16 bytes Data block 0 | |
47 | // 15*16 bytes Unused hole | |
48 | // 16 bytes Data block 1 | |
49 | // 15*16 bytes Unused hole | |
50 | // 16 bytes Data block 2 | |
51 | // 15*16 bytes Unused hole | |
52 | // 16 bytes Data block 3 | |
53 | // 15*16 bytes Unused hole | |
54 | // | |
55 | // For a total size of 1024 bytes, only 1/16 of which hold meaningful | |
56 | // data. | |
57 | // | |
58 | // In the decode cache, 16 SS_Instr objects are overlapped at | |
59 | // intervals of 16 bytes. The key advantage is to share a D-cache | |
60 | // line among the "data block 0" areas of two SS_Instr objects. Since | |
61 | // D-cache lines are typically 32 bytes, this packing eliminates | |
62 | // almost D-cache misses for the second "data block 0" of the two | |
63 | // SS_Instr object sharing the cache line, at least in the case of | |
64 | // sequential execution. | |
65 | // | |
66 | // Do not modify this class without considering these packing | |
67 | // constraints. As a wise girl once said, "You *can* touch this -- | |
68 | // with your eyes." | |
69 | ||
70 | ||
71 | class SS_Instr | |
72 | { | |
73 | public: | |
74 | enum | |
75 | { | |
76 | BITS = 6, | |
77 | SIZE = (1 << BITS), | |
78 | ||
79 | SKEW = 2, | |
80 | ||
81 | LINE_BITS = 4, | |
82 | LINE_SIZE = 1 << LINE_BITS, | |
83 | LINE_MASK = LINE_SIZE - 1, | |
84 | ||
85 | HOLE = (LINE_SIZE - 1) * (1 << (BITS - SKEW)) / sizeof(uint64_t) | |
86 | }; | |
87 | ||
88 | SS_Instr* line_index( uint_t n ) | |
89 | { | |
90 | return (SS_Instr*)((char*)this + (n << (BITS - SKEW))); | |
91 | } | |
92 | ||
93 | SS_Instr() { assert(HOLE == 30); } | |
94 | ||
95 | union | |
96 | { | |
97 | SS_Execute exe; // The decode or execute routine ... | |
98 | uint64_t align0; // 64bit alignment in v8plus mode | |
99 | }; | |
100 | ||
101 | // Todo: AsiFlag and LsuFlag use 8 bits all together. | |
102 | // The asi flags don;t serve real meaning anymore as | |
103 | // each have thier own execute (so REG_ASI is known | |
104 | // without looking at this flag. I think we should use | |
105 | // | |
106 | // 000 NON_LSU | |
107 | // 001 READ | |
108 | // 010 WRITE | |
109 | // 011 ATOMIC | |
110 | // 101 FETCH | |
111 | // 110 FLUSH | |
112 | // 110 - | |
113 | // 111 - | |
114 | ||
115 | enum AsiFlag | |
116 | { | |
117 | NON_LSU = 0x00, // All non LSU instructions | |
118 | DFT_ASI = 0x01, | |
119 | REG_ASI = 0x02, | |
120 | IMM_ASI = 0x04 | |
121 | }; | |
122 | ||
123 | enum LsuFlag | |
124 | { | |
125 | READ = 0x10, | |
126 | WRITE = 0x20, | |
127 | FETCH = 0x40, | |
128 | FLUSH = 0x80 | |
129 | }; | |
130 | ||
131 | int is_lsu() { return flg != NON_LSU; } | |
132 | int is_dft_asi() { return flg & DFT_ASI; } | |
133 | int is_reg_asi() { return flg & REG_ASI; } | |
134 | int is_imm_asi() { return flg & IMM_ASI; } | |
135 | ||
136 | int is_read() { return flg & READ; } | |
137 | int is_write() { return flg & WRITE; } | |
138 | int is_atomic() { return (flg & (READ|WRITE)) == (READ|WRITE); } | |
139 | ||
140 | int is_fetch() { return flg & FETCH; } | |
141 | int is_flush() { return flg & FLUSH; } | |
142 | int is_cohere() { return flg & (FETCH|FLUSH); } | |
143 | ||
144 | // All register values below (rd, rs1, rd2, rs3) are not the | |
145 | // register number mapping directly to %g3, %l5, etc. Instead, | |
146 | // they are the ***byte offset*** into the Strand's integer | |
147 | // register file. So instruction referencing %g2 as its rd would | |
148 | // store 16 in "rd" below because registers are 8 bytes in size. | |
149 | ||
150 | int16_t rd; | |
151 | int16_t rs1; | |
152 | int16_t rs2; // Index to rs2 or signed immediate value | |
153 | union | |
154 | { | |
155 | int16_t rs3; // Index to rs3 | |
156 | uint16_t asi; // The asi used by LSU instructions (dft/reg/imm) @@ha144505 Todo -> uint8! | |
157 | }; | |
158 | ||
159 | uint64_t stride0[HOLE]; // For overlapping 16 SS_Instr in the decode cache | |
160 | ||
161 | SS_Opcode opc; | |
162 | uint8_t flg; // Flags specifing memory operation type | |
163 | uint8_t len; // The size of the memory operation | |
164 | uint16_t spare0; | |
165 | ||
166 | union | |
167 | { | |
168 | SS_Tte* tte; // Data TTE for LSU instructions. Bit0 is endianess, Bit1 is MEM(0)/IO(1) | |
169 | SS_BreakPoint* bp; // Pointer to breakpoint set on this instruction | |
170 | }; | |
171 | ||
172 | uint64_t stride1[HOLE]; // For overlapping 16 SS_Instr in the decode cache | |
173 | ||
174 | SS_Chain lnk; // Link same TTE together | |
175 | ||
176 | //uint64_t stride2[HOLE]; // For overlapping 16 SS_Instr in the decode cache | |
177 | SS_Chain stride2[LINE_SIZE-1]; | |
178 | ||
179 | uint16_t exe_tbl_idx; // Index into exe_table for this instruction | |
180 | ||
181 | uint16_t spare1; // Reserved space | |
182 | uint32_t spare2; | |
183 | uint64_t spare3; | |
184 | ||
185 | uint64_t stride3[HOLE]; // For overlapping 16 SS_Instr in the decode cache | |
186 | ||
187 | SS_Tte* get_tte() { return (SS_Tte*)(long(tte) &~ long(3)); } | |
188 | int tte_le() { return long(tte) & 1; } | |
189 | int tte_io() { return long(tte) & 2; } | |
190 | int tte_le_io() { return long(tte) & 3; } | |
191 | ||
192 | SS_Tte* set_tte( uint_t le, uint_t io, SS_Tte* t ) | |
193 | { | |
194 | assert((le == 0) || (le == 1)); | |
195 | assert((io == 0) || (io == 2)); | |
196 | tte = (SS_Tte*)(long(t) + long(le) + long(io)); | |
197 | return tte; | |
198 | } | |
199 | ||
200 | ||
201 | }; | |
202 | ||
203 | #endif | |
204 |