1// -*- mode:c++ -*- 2 3// Copyright (c) 2007-2008 The Florida State University 4// All rights reserved. 5// 6// Redistribution and use in source and binary forms, with or without 7// modification, are permitted provided that the following conditions are 8// met: redistributions of source code must retain the above copyright 9// notice, this list of conditions and the following disclaimer; 10// redistributions in binary form must reproduce the above copyright 11// notice, this list of conditions and the following disclaimer in the 12// documentation and/or other materials provided with the distribution; 13// neither the name of the copyright holders nor the names of its 14// contributors may be used to endorse or promote products derived from 15// this software without specific prior written permission. 16// 17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28// 29// Authors: Stephen Hines 30 31//////////////////////////////////////////////////////////////////// 32// 33// Macro Memory-format instructions 34// 35
|
36output header {{
|
36def template MacroStoreDeclare {{ 37/** 38 * Static instructions class for a store multiple instruction 39 */ 40class %(class_name)s : public %(base_class)s 41{ 42 public: 43 // Constructor 44 %(class_name)s(ExtMachInst machInst); 45 %(BasicExecDeclare)s 46}; 47}}; |
48
|
38 /**
39 * Arm Macro Memory operations like LDM/STM
40 */
41 class ArmMacroMemoryOp : public PredMacroOp
42 {
43 protected:
44 /// Memory request flags. See mem_req_base.hh.
45 unsigned memAccessFlags;
46 /// Pointer to EAComp object.
47 const StaticInstPtr eaCompPtr;
48 /// Pointer to MemAcc object.
49 const StaticInstPtr memAccPtr;
|
49def template MacroStoreConstructor {{ 50inline %(class_name)s::%(class_name)s(ExtMachInst machInst) 51 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) 52{ 53 %(constructor)s; 54 uint32_t regs_to_handle = reglist; 55 uint32_t j = 0, 56 start_addr = 0, 57 end_addr = 0; |
58
|
51 uint32_t reglist;
52 uint32_t ones;
53 uint32_t puswl,
54 prepost,
55 up,
56 psruser,
57 writeback,
58 loadop;
59
60 ArmMacroMemoryOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
61 StaticInstPtr _eaCompPtr = nullStaticInstPtr,
62 StaticInstPtr _memAccPtr = nullStaticInstPtr)
63 : PredMacroOp(mnem, _machInst, __opClass),
64 memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr),
65 reglist(REGLIST), ones(0), puswl(PUSWL), prepost(PREPOST), up(UP),
66 psruser(PSRUSER), writeback(WRITEBACK), loadop(LOADOP)
67 {
68 ones = number_of_ones(reglist);
69 numMicroops = ones + writeback + 1;
70 // Remember that writeback adds a uop
71 microOps = new StaticInstPtr[numMicroops];
72 }
73 };
74
75 /**
76 * Arm Macro FPA operations to fix ldfd and stfd instructions
77 */
78 class ArmMacroFPAOp : public PredMacroOp
|
59 switch (puswl) |
60 {
|
80 protected:
81 uint32_t puswl,
82 prepost,
83 up,
84 psruser,
85 writeback,
86 loadop;
87 int32_t disp8;
|
61 case 0x01: // L ldmda_l 62 start_addr = (ones << 2) - 4; 63 end_addr = 0; 64 break; 65 case 0x03: // WL ldmda_wl 66 start_addr = (ones << 2) - 4; 67 end_addr = 0; 68 break; 69 case 0x08: // U stmia_u 70 start_addr = 0; 71 end_addr = (ones << 2) - 4; 72 break; 73 case 0x09: // U L ldmia_ul 74 start_addr = 0; 75 end_addr = (ones << 2) - 4; 76 break; 77 case 0x0b: // U WL ldmia 78 start_addr = 0; 79 end_addr = (ones << 2) - 4; 80 break; 81 case 0x11: // P L ldmdb 82 start_addr = (ones << 2); // U-bit is already 0 for subtract 83 end_addr = 4; // negative 4 84 break; 85 case 0x12: // P W stmdb 86 start_addr = (ones << 2); // U-bit is already 0 for subtract 87 end_addr = 4; // negative 4 88 break; 89 case 0x18: // PU stmib 90 start_addr = 4; 91 end_addr = (ones << 2) + 4; 92 break; 93 case 0x19: // PU L ldmib 94 start_addr = 4; 95 end_addr = (ones << 2) + 4; 96 break; 97 default: 98 panic("Unhandled Load/Store Multiple Instruction"); 99 break; 100 } |
101
|
89 ArmMacroFPAOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
90 : PredMacroOp(mnem, _machInst, __opClass),
91 puswl(PUSWL), prepost(PREPOST), up(UP),
92 psruser(PSRUSER), writeback(WRITEBACK), loadop(LOADOP),
93 disp8(IMMED_7_0 << 2)
94 {
95 numMicroops = 3 + writeback;
96 microOps = new StaticInstPtr[numMicroops];
97 }
98 };
|
102 //TODO - Add addi_uop/subi_uop here to create starting addresses 103 //Just using addi with 0 offset makes a "copy" of Rn for our use 104 uint32_t newMachInst = 0; 105 newMachInst = machInst & 0xffff0000; 106 microOps[0] = new Addi_uop(newMachInst); |
107
|
100 /**
101 * Arm Macro FM operations to fix lfm and sfm
102 */
103 class ArmMacroFMOp : public PredMacroOp
|
108 for (int i = 1; i < ones+1; i++) |
109 {
|
105 protected:
106 uint32_t punwl,
107 prepost,
108 up,
109 n1bit,
110 writeback,
111 loadop,
112 n0bit,
113 count;
114 int32_t disp8;
|
110 // Get next available bit for transfer 111 while (! ( regs_to_handle & (1<<j))) 112 j++; 113 regs_to_handle &= ~(1<<j); |
114
|
116 ArmMacroFMOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
117 : PredMacroOp(mnem, _machInst, __opClass),
118 punwl(PUNWL), prepost(PREPOST), up(UP),
119 n1bit(OPCODE_22), writeback(WRITEBACK), loadop(LOADOP),
120 n0bit(OPCODE_15), disp8(IMMED_7_0 << 2)
121 {
122 // Transfer 1-4 registers based on n1 and n0 bits (with 00 repr. 4)
123 count = (n1bit << 1) | n0bit;
124 if (count == 0)
125 count = 4;
126 numMicroops = (3*count) + writeback;
127 microOps = new StaticInstPtr[numMicroops];
128 }
129 };
|
115 microOps[i] = gen_ldrstr_uop(machInst, loadop, j, start_addr); |
116
|
117 if (up) 118 start_addr += 4; 119 else 120 start_addr -= 4; 121 } |
122
|
132}};
133
134
135output decoder {{
136}};
137
138def template MacroStoreDeclare {{
139 /**
140 * Static instructions class for a store multiple instruction
141 */
142 class %(class_name)s : public %(base_class)s
|
123 /* TODO: Take a look at how these 2 values should meet together 124 if (start_addr != (end_addr - 4)) |
125 {
|
144 public:
145 // Constructor
146 %(class_name)s(ExtMachInst machInst);
147 %(BasicExecDeclare)s
148 };
149}};
|
126 fprintf(stderr, "start_addr: %d\n", start_addr); 127 fprintf(stderr, "end_addr: %d\n", end_addr); 128 panic("start_addr does not meet end_addr"); 129 } 130 */ |
131
|
151def template MacroStoreConstructor {{
152 inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
153 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
|
132 if (writeback) |
133 {
|
155 %(constructor)s;
156 uint32_t regs_to_handle = reglist;
157 uint32_t j = 0,
158 start_addr = 0,
159 end_addr = 0;
160
161 switch (puswl)
|
134 uint32_t newMachInst = machInst & 0xf0000000; 135 uint32_t rn = (machInst >> 16) & 0x0f; 136 // 3322 2222 2222 1111 1111 11 137 // 1098 7654 3210 9876 5432 1098 7654 3210 138 // COND 0010 0100 [RN] [RD] 0000 [ IMM ] 139 // sub rn, rn, imm 140 newMachInst |= 0x02400000; 141 newMachInst |= ((rn << 16) | (rn << 12)); 142 newMachInst |= (ones << 2); 143 if (up) |
144 {
|
163 case 0x01: // L ldmda_l
164 start_addr = (ones << 2) - 4;
165 end_addr = 0;
166 break;
167 case 0x03: // WL ldmda_wl
168 start_addr = (ones << 2) - 4;
169 end_addr = 0;
170 break;
171 case 0x08: // U stmia_u
172 start_addr = 0;
173 end_addr = (ones << 2) - 4;
174 break;
175 case 0x09: // U L ldmia_ul
176 start_addr = 0;
177 end_addr = (ones << 2) - 4;
178 break;
179 case 0x0b: // U WL ldmia
180 start_addr = 0;
181 end_addr = (ones << 2) - 4;
182 break;
183 case 0x11: // P L ldmdb
184 start_addr = (ones << 2); // U-bit is already 0 for subtract
185 end_addr = 4; // negative 4
186 break;
187 case 0x12: // P W stmdb
188 start_addr = (ones << 2); // U-bit is already 0 for subtract
189 end_addr = 4; // negative 4
190 break;
191 case 0x18: // PU stmib
192 start_addr = 4;
193 end_addr = (ones << 2) + 4;
194 break;
195 case 0x19: // PU L ldmib
196 start_addr = 4;
197 end_addr = (ones << 2) + 4;
198 break;
199 default:
200 panic("Unhandled Load/Store Multiple Instruction");
201 break;
|
145 microOps[numMicroops-1] = new Addi_rd_uop(newMachInst); |
146 }
|
203
204 //TODO - Add addi_uop/subi_uop here to create starting addresses
205 //Just using addi with 0 offset makes a "copy" of Rn for our use
206 uint32_t newMachInst = 0;
207 newMachInst = machInst & 0xffff0000;
208 microOps[0] = new Addi_uop(newMachInst);
209
210 for (int i = 1; i < ones+1; i++)
|
147 else |
148 {
|
212 // Get next available bit for transfer
213 while (! ( regs_to_handle & (1<<j)))
214 j++;
215 regs_to_handle &= ~(1<<j);
216
217 microOps[i] = gen_ldrstr_uop(machInst, loadop, j, start_addr);
218
219 if (up)
220 start_addr += 4;
221 else
222 start_addr -= 4;
|
149 microOps[numMicroops-1] = new Subi_rd_uop(newMachInst); |
150 }
|
224
225 /* TODO: Take a look at how these 2 values should meet together
226 if (start_addr != (end_addr - 4))
227 {
228 fprintf(stderr, "start_addr: %d\n", start_addr);
229 fprintf(stderr, "end_addr: %d\n", end_addr);
230 panic("start_addr does not meet end_addr");
231 }
232 */
233
234 if (writeback)
235 {
236 uint32_t newMachInst = machInst & 0xf0000000;
237 uint32_t rn = (machInst >> 16) & 0x0f;
238 // 3322 2222 2222 1111 1111 11
239 // 1098 7654 3210 9876 5432 1098 7654 3210
240 // COND 0010 0100 [RN] [RD] 0000 [ IMM ]
241 // sub rn, rn, imm
242 newMachInst |= 0x02400000;
243 newMachInst |= ((rn << 16) | (rn << 12));
244 newMachInst |= (ones << 2);
245 if (up)
246 {
247 microOps[numMicroops-1] = new Addi_rd_uop(newMachInst);
248 }
249 else
250 {
251 microOps[numMicroops-1] = new Subi_rd_uop(newMachInst);
252 }
253 }
254 microOps[numMicroops-1]->setLastMicroop();
|
151 }
|
152 microOps[numMicroops-1]->setLastMicroop(); 153} |
154 155}}; 156 157def template MacroStoreExecute {{
|
260 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
261 {
262 Fault fault = NoFault;
|
158Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const 159{ 160 Fault fault = NoFault; |
161
|
264 %(fp_enable_check)s;
265 %(op_decl)s;
266 %(op_rd)s;
267 %(code)s;
268 if (fault == NoFault)
269 {
270 %(op_wb)s;
271 }
272
273 return fault;
|
162 %(fp_enable_check)s; 163 %(op_decl)s; 164 %(op_rd)s; 165 %(code)s; 166 if (fault == NoFault) 167 { 168 %(op_wb)s; |
169 }
|
170 171 return fault; 172} |
173}}; 174 175def template MacroFPAConstructor {{
|
278 inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
279 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
280 {
281 %(constructor)s;
|
176inline %(class_name)s::%(class_name)s(ExtMachInst machInst) 177 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) 178{ 179 %(constructor)s; |
180
|
283 uint32_t start_addr = 0;
|
181 uint32_t start_addr = 0; |
182
|
285 if (prepost)
286 start_addr = disp8;
287 else
288 start_addr = 0;
|
183 if (prepost) 184 start_addr = disp8; 185 else 186 start_addr = 0; |
187
|
290 emit_ldfstf_uops(microOps, 0, machInst, loadop, up, start_addr);
|
188 emit_ldfstf_uops(microOps, 0, machInst, loadop, up, start_addr); |
189
|
292 if (writeback)
|
190 if (writeback) 191 { 192 uint32_t newMachInst = machInst & 0xf0000000; 193 uint32_t rn = (machInst >> 16) & 0x0f; 194 // 3322 2222 2222 1111 1111 11 195 // 1098 7654 3210 9876 5432 1098 7654 3210 196 // COND 0010 0100 [RN] [RD] 0000 [ IMM ] 197 // sub rn, rn, imm 198 newMachInst |= 0x02400000; 199 newMachInst |= ((rn << 16) | (rn << 12)); 200 if (up) |
201 {
|
294 uint32_t newMachInst = machInst & 0xf0000000;
295 uint32_t rn = (machInst >> 16) & 0x0f;
296 // 3322 2222 2222 1111 1111 11
297 // 1098 7654 3210 9876 5432 1098 7654 3210
298 // COND 0010 0100 [RN] [RD] 0000 [ IMM ]
299 // sub rn, rn, imm
300 newMachInst |= 0x02400000;
301 newMachInst |= ((rn << 16) | (rn << 12));
302 if (up)
303 {
304 newMachInst |= disp8;
305 microOps[numMicroops-1] = new Addi_rd_uop(newMachInst);
306 }
307 else
308 {
309 newMachInst |= disp8;
310 microOps[numMicroops-1] = new Subi_rd_uop(newMachInst);
311 }
|
202 newMachInst |= disp8; 203 microOps[numMicroops-1] = new Addi_rd_uop(newMachInst); |
204 }
|
313 microOps[numMicroops-1]->setLastMicroop();
|
205 else 206 { 207 newMachInst |= disp8; 208 microOps[numMicroops-1] = new Subi_rd_uop(newMachInst); 209 } |
210 }
|
211 microOps[numMicroops-1]->setLastMicroop(); 212} |
213 214}}; 215 216 217def template MacroFMConstructor {{
|
320 inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
321 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
322 {
323 %(constructor)s;
|
218inline %(class_name)s::%(class_name)s(ExtMachInst machInst) 219 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) 220{ 221 %(constructor)s; |
222
|
325 uint32_t start_addr = 0;
|
223 uint32_t start_addr = 0; |
224
|
327 if (prepost)
328 start_addr = disp8;
329 else
330 start_addr = 0;
|
225 if (prepost) 226 start_addr = disp8; 227 else 228 start_addr = 0; |
229
|
332 for (int i = 0; i < count; i++)
|
230 for (int i = 0; i < count; i++) 231 { 232 emit_ldfstf_uops(microOps, 3*i, machInst, loadop, up, start_addr); 233 } 234 235 if (writeback) 236 { 237 uint32_t newMachInst = machInst & 0xf0000000; 238 uint32_t rn = (machInst >> 16) & 0x0f; 239 // 3322 2222 2222 1111 1111 11 240 // 1098 7654 3210 9876 5432 1098 7654 3210 241 // COND 0010 0100 [RN] [RD] 0000 [ IMM ] 242 // sub rn, rn, imm 243 newMachInst |= 0x02400000; 244 newMachInst |= ((rn << 16) | (rn << 12)); 245 if (up) |
246 {
|
334 emit_ldfstf_uops(microOps, 3*i, machInst, loadop, up, start_addr);
|
247 newMachInst |= disp8; 248 microOps[numMicroops-1] = new Addi_rd_uop(newMachInst); |
249 }
|
336
337 if (writeback)
|
250 else |
251 {
|
339 uint32_t newMachInst = machInst & 0xf0000000;
340 uint32_t rn = (machInst >> 16) & 0x0f;
341 // 3322 2222 2222 1111 1111 11
342 // 1098 7654 3210 9876 5432 1098 7654 3210
343 // COND 0010 0100 [RN] [RD] 0000 [ IMM ]
344 // sub rn, rn, imm
345 newMachInst |= 0x02400000;
346 newMachInst |= ((rn << 16) | (rn << 12));
347 if (up)
348 {
349 newMachInst |= disp8;
350 microOps[numMicroops-1] = new Addi_rd_uop(newMachInst);
351 }
352 else
353 {
354 newMachInst |= disp8;
355 microOps[numMicroops-1] = new Subi_rd_uop(newMachInst);
356 }
|
252 newMachInst |= disp8; 253 microOps[numMicroops-1] = new Subi_rd_uop(newMachInst); |
254 }
|
358 microOps[numMicroops-1]->setLastMicroop();
|
255 }
|
360
|
256 microOps[numMicroops-1]->setLastMicroop(); 257} |
258}}; 259 260 261def format ArmMacroStore(code, mem_flags = [], inst_flag = [], *opt_flags) {{ 262 iop = InstObjParams(name, Name, 'ArmMacroMemoryOp', code, opt_flags) 263 header_output = MacroStoreDeclare.subst(iop) 264 decoder_output = MacroStoreConstructor.subst(iop) 265 decode_block = BasicDecode.subst(iop) 266 exec_output = MacroStoreExecute.subst(iop) 267}}; 268 269def format ArmMacroFPAOp(code, mem_flags = [], inst_flag = [], *opt_flags) {{ 270 iop = InstObjParams(name, Name, 'ArmMacroFPAOp', 271 {"code": code, 272 "predicate_test": predicateTest}, 273 opt_flags) 274 header_output = BasicDeclare.subst(iop) 275 decoder_output = MacroFPAConstructor.subst(iop) 276 decode_block = BasicDecode.subst(iop) 277 exec_output = PredOpExecute.subst(iop) 278}}; 279 280def format ArmMacroFMOp(code, mem_flags = [], inst_flag = [], *opt_flags) {{ 281 iop = InstObjParams(name, Name, 'ArmMacroFMOp', 282 {"code": code, 283 "predicate_test": predicateTest}, 284 opt_flags) 285 header_output = BasicDeclare.subst(iop) 286 decoder_output = MacroFMConstructor.subst(iop) 287 decode_block = BasicDecode.subst(iop) 288 exec_output = PredOpExecute.subst(iop) 289}};
|
393
394
395
|
|