macromem.isa revision 6019
13760SN/A// -*- mode:c++ -*- 23760SN/A 33760SN/A// Copyright (c) 2007-2008 The Florida State University 43760SN/A// All rights reserved. 53760SN/A// 63760SN/A// Redistribution and use in source and binary forms, with or without 73760SN/A// modification, are permitted provided that the following conditions are 83760SN/A// met: redistributions of source code must retain the above copyright 93760SN/A// notice, this list of conditions and the following disclaimer; 103760SN/A// redistributions in binary form must reproduce the above copyright 113760SN/A// notice, this list of conditions and the following disclaimer in the 123760SN/A// documentation and/or other materials provided with the distribution; 133760SN/A// neither the name of the copyright holders nor the names of its 143760SN/A// contributors may be used to endorse or promote products derived from 153760SN/A// this software without specific prior written permission. 163760SN/A// 173760SN/A// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 183760SN/A// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 193760SN/A// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 203760SN/A// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 213760SN/A// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 223760SN/A// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 233760SN/A// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 243760SN/A// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 253760SN/A// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 263760SN/A// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 273760SN/A// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 285597SN/A// 293760SN/A// Authors: Stephen Hines 303760SN/A 3111793Sbrandon.potter@amd.com//////////////////////////////////////////////////////////////////// 3211793Sbrandon.potter@amd.com// 333760SN/A// Macro Memory-format instructions 343760SN/A// 354762SN/A 363760SN/Aoutput header {{ 374762SN/A 384762SN/A /** 393760SN/A * Arm Macro Memory operations like LDM/STM 408793SN/A */ 418793SN/A class ArmMacroMemoryOp : public PredMacroOp 428793SN/A { 438793SN/A protected: 448793SN/A /// Memory request flags. See mem_req_base.hh. 458793SN/A unsigned memAccessFlags; 468793SN/A /// Pointer to EAComp object. 478793SN/A const StaticInstPtr eaCompPtr; 488793SN/A /// Pointer to MemAcc object. 498793SN/A const StaticInstPtr memAccPtr; 508793SN/A 518793SN/A uint32_t reglist; 528793SN/A uint32_t ones; 538793SN/A uint32_t puswl, 548793SN/A prepost, 558793SN/A up, 566387SN/A psruser, 573760SN/A writeback, 585529SN/A loadop; 593760SN/A 6013559Snikos.nikoleris@arm.com ArmMacroMemoryOp(const char *mnem, MachInst _machInst, OpClass __opClass, 6113559Snikos.nikoleris@arm.com StaticInstPtr _eaCompPtr = nullStaticInstPtr, 623760SN/A StaticInstPtr _memAccPtr = nullStaticInstPtr) 635529SN/A : PredMacroOp(mnem, _machInst, __opClass), 643760SN/A 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