macromem.isa revision 6019
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 {{ 37 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; 50 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, MachInst _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 79 { 80 protected: 81 uint32_t puswl, 82 prepost, 83 up, 84 psruser, 85 writeback, 86 loadop; 87 int32_t disp8; 88 89 ArmMacroFPAOp(const char *mnem, MachInst _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 }; 99 100 /** 101 * Arm Macro FM operations to fix lfm and sfm 102 */ 103 class ArmMacroFMOp : public PredMacroOp 104 { 105 protected: 106 uint32_t punwl, 107 prepost, 108 up, 109 n1bit, 110 writeback, 111 loadop, 112 n0bit, 113 count; 114 int32_t disp8; 115 116 ArmMacroFMOp(const char *mnem, MachInst _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 }; 130 131 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 143 { 144 public: 145 // Constructor 146 %(class_name)s(MachInst machInst); 147 %(BasicExecDeclare)s 148 }; 149}}; 150 151def template MacroStoreConstructor {{ 152 inline %(class_name)s::%(class_name)s(MachInst machInst) 153 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) 154 { 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) 162 { 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; 202 } 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++) 211 { 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; 223 } 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(); 255 } 256 257}}; 258 259def template MacroStoreExecute {{ 260 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const 261 { 262 Fault fault = NoFault; 263 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; 274 } 275}}; 276 277def template MacroFPAConstructor {{ 278 inline %(class_name)s::%(class_name)s(MachInst machInst) 279 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) 280 { 281 %(constructor)s; 282 283 uint32_t start_addr = 0; 284 285 if (prepost) 286 start_addr = disp8; 287 else 288 start_addr = 0; 289 290 emit_ldfstf_uops(microOps, 0, machInst, loadop, up, start_addr); 291 292 if (writeback) 293 { 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 } 312 } 313 microOps[numMicroops-1]->setLastMicroop(); 314 } 315 316}}; 317 318 319def template MacroFMConstructor {{ 320 inline %(class_name)s::%(class_name)s(MachInst machInst) 321 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) 322 { 323 %(constructor)s; 324 325 uint32_t start_addr = 0; 326 327 if (prepost) 328 start_addr = disp8; 329 else 330 start_addr = 0; 331 332 for (int i = 0; i < count; i++) 333 { 334 emit_ldfstf_uops(microOps, 3*i, machInst, loadop, up, start_addr); 335 } 336 337 if (writeback) 338 { 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 } 357 } 358 microOps[numMicroops-1]->setLastMicroop(); 359 } 360 361}}; 362 363 364def format ArmMacroStore(code, mem_flags = [], inst_flag = [], *opt_flags) {{ 365 iop = InstObjParams(name, Name, 'ArmMacroMemoryOp', code, opt_flags) 366 header_output = MacroStoreDeclare.subst(iop) 367 decoder_output = MacroStoreConstructor.subst(iop) 368 decode_block = BasicDecode.subst(iop) 369 exec_output = MacroStoreExecute.subst(iop) 370}}; 371 372def format ArmMacroFPAOp(code, mem_flags = [], inst_flag = [], *opt_flags) {{ 373 iop = InstObjParams(name, Name, 'ArmMacroFPAOp', code, opt_flags) 374 header_output = BasicDeclare.subst(iop) 375 decoder_output = MacroFPAConstructor.subst(iop) 376 decode_block = BasicDecode.subst(iop) 377 exec_output = PredOpExecute.subst(iop) 378}}; 379 380def format ArmMacroFMOp(code, mem_flags = [], inst_flag = [], *opt_flags) {{ 381 iop = InstObjParams(name, Name, 'ArmMacroFMOp', code, opt_flags) 382 header_output = BasicDeclare.subst(iop) 383 decoder_output = MacroFMConstructor.subst(iop) 384 decode_block = BasicDecode.subst(iop) 385 exec_output = PredOpExecute.subst(iop) 386}}; 387 388 389 390