mem.isa revision 7305:6ed0e7460ed5
1// -*- mode:c++ -*- 2 3// Copyright (c) 2010 ARM Limited 4// All rights reserved 5// 6// The license below extends only to copyright in the software and shall 7// not be construed as granting a license to any other intellectual 8// property including but not limited to intellectual property relating 9// to a hardware implementation of the functionality of the software 10// licensed hereunder. You may use the software subject to the license 11// terms below provided that you ensure that this notice is replicated 12// unmodified and in its entirety in all distributions of the software, 13// modified or unmodified, in source code or in binary form. 14// 15// Copyright (c) 2007-2008 The Florida State University 16// All rights reserved. 17// 18// Redistribution and use in source and binary forms, with or without 19// modification, are permitted provided that the following conditions are 20// met: redistributions of source code must retain the above copyright 21// notice, this list of conditions and the following disclaimer; 22// redistributions in binary form must reproduce the above copyright 23// notice, this list of conditions and the following disclaimer in the 24// documentation and/or other materials provided with the distribution; 25// neither the name of the copyright holders nor the names of its 26// contributors may be used to endorse or promote products derived from 27// this software without specific prior written permission. 28// 29// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40// 41// Authors: Gabe Black 42 43def format AddrMode2(imm) {{ 44 if eval(imm): 45 imm = True 46 else: 47 imm = False 48 49 def buildPUBWLCase(p, u, b, w, l): 50 return (p << 4) + (u << 3) + (b << 2) + (w << 1) + (l << 0) 51 52 header_output = decoder_output = exec_output = "" 53 decode_block = "switch(PUBWL) {\n" 54 55 # Loop over all the values of p, u, b, w and l and build instructions and 56 # a decode block for them. 57 for p in (0, 1): 58 for u in (0, 1): 59 for b in (0, 1): 60 for w in (0, 1): 61 post = (p == 0) 62 user = (p == 0 and w == 1) 63 writeback = (p == 0 or w == 1) 64 add = (u == 1) 65 if b == 0: 66 size = 4 67 else: 68 size = 1 69 if add: 70 addStr = "true" 71 else: 72 addStr = "false" 73 if imm: 74 newDecode = "return new %s(machInst, RD, RN," + \ 75 "%s, machInst.immed11_0);" 76 loadClass = loadImmClassName(post, add, writeback, 77 size, False, user) 78 storeClass = storeImmClassName(post, add, writeback, 79 size, False, user) 80 loadDecode = newDecode % (loadClass, addStr) 81 storeDecode = newDecode % (storeClass, addStr) 82 else: 83 newDecode = "return new %s(machInst, RD, RN, %s," + \ 84 "machInst.shiftSize," + \ 85 "machInst.shift, RM);" 86 loadClass = loadRegClassName(post, add, writeback, 87 size, False, user) 88 storeClass = storeRegClassName(post, add, writeback, 89 size, False, user) 90 loadDecode = newDecode % (loadClass, addStr) 91 storeDecode = newDecode % (storeClass, addStr) 92 decode = ''' 93 case %#x: 94 {%s} 95 break; 96 ''' 97 decode_block += decode % \ 98 (buildPUBWLCase(p,u,b,w,1), loadDecode) 99 decode_block += decode % \ 100 (buildPUBWLCase(p,u,b,w,0), storeDecode) 101 decode_block += ''' 102 default: 103 return new Unknown(machInst); 104 break; 105 }''' 106}}; 107 108def format AddrMode3() {{ 109 decode = ''' 110 { 111 const uint32_t op1 = bits(machInst, 24, 20); 112 const uint32_t op2 = bits(machInst, 6, 5); 113 const uint32_t puiw = bits(machInst, 24, 21); 114 const uint32_t imm = IMMED_HI_11_8 << 4 | IMMED_LO_3_0; 115 switch (op2) { 116 case 0x1: 117 if (op1 & 0x1) { 118 %(ldrh)s 119 } else { 120 %(strh)s 121 } 122 case 0x2: 123 if (op1 & 0x1) { 124 %(ldrsb)s 125 } else { 126 %(ldrd)s 127 } 128 case 0x3: 129 if (op1 & 0x1) { 130 %(ldrsh)s 131 } else { 132 %(strd)s 133 } 134 default: 135 return new Unknown(machInst); 136 } 137 } 138 ''' 139 140 def decodePuiwCase(load, d, p, u, i, w, size=4, sign=False): 141 post = (p == 0) 142 user = (p == 0 and w == 1) 143 writeback = (p == 0 or w == 1) 144 add = (u == 1) 145 caseVal = (p << 3) + (u << 2) + (i << 1) + (w << 0) 146 decode = ''' 147 case %#x: 148 return new '''% caseVal 149 if add: 150 addStr = "true" 151 else: 152 addStr = "false" 153 if d: 154 dests = "RT & ~1, RT | 1" 155 else: 156 dests = "RT" 157 if i: 158 if load: 159 if d: 160 className = loadDoubleImmClassName(post, add, writeback) 161 else: 162 className = loadImmClassName(post, add, writeback, \ 163 size=size, sign=sign, \ 164 user=user) 165 else: 166 if d: 167 className = storeDoubleImmClassName(post, add, writeback) 168 else: 169 className = storeImmClassName(post, add, writeback, \ 170 size=size, sign=sign, \ 171 user=user) 172 decode += ("%s(machInst, %s, RN, %s, imm);\n" % \ 173 (className, dests, addStr)) 174 else: 175 if load: 176 if d: 177 className = loadDoubleRegClassName(post, add, writeback) 178 else: 179 className = loadRegClassName(post, add, writeback, \ 180 size=size, sign=sign, \ 181 user=user) 182 else: 183 if d: 184 className = storeDoubleRegClassName(post, add, writeback) 185 else: 186 className = storeRegClassName(post, add, writeback, \ 187 size=size, sign=sign, \ 188 user=user) 189 decode += ("%s(machInst, %s, RN, %s, 0, LSL, RM);\n" % \ 190 (className, dests, addStr)) 191 return decode 192 193 def decodePuiw(load, d, size=4, sign=False): 194 global decodePuiwCase 195 decode = "switch (puiw) {\n" 196 for p in (0, 1): 197 for u in (0, 1): 198 for i in (0, 1): 199 for w in (0, 1): 200 decode += decodePuiwCase(load, d, p, u, i, w, 201 size, sign) 202 decode += ''' 203 default: 204 return new Unknown(machInst); 205 } 206 ''' 207 return decode 208 209 subs = { 210 "ldrh" : decodePuiw(True, False, size=2), 211 "strh" : decodePuiw(False, False, size=2), 212 "ldrsb" : decodePuiw(True, False, size=1, sign=True), 213 "ldrd" : decodePuiw(True, True), 214 "ldrsh" : decodePuiw(True, False, size=2, sign=True), 215 "strd" : decodePuiw(False, True) 216 } 217 decode_block = decode % subs 218}}; 219 220def format ArmSyncMem() {{ 221 decode_block = ''' 222 { 223 const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); 224 const IntRegIndex rt = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); 225 const IntRegIndex rt2 = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); 226 switch (PUBWL) { 227 case 0x10: 228 return new Swp(machInst, rt, rt2, rn); 229 case 0x14: 230 return new Swpb(machInst, rt, rt2, rn); 231 case 0x18: 232 return new %(strex)s(machInst, rt, rt2, rn, true, 0); 233 case 0x19: 234 return new %(ldrex)s(machInst, rt, rn, true, 0); 235 case 0x1a: 236 return new %(strexd)s(machInst, rt, rt2, rt2 + 1, rn, true, 0); 237 case 0x1b: 238 return new %(ldrexd)s(machInst, rt, rt + 1, rn, true, 0); 239 case 0x1c: 240 return new %(strexb)s(machInst, rt, rt2, rn, true, 0); 241 case 0x1d: 242 return new %(ldrexb)s(machInst, rt, rn, true, 0); 243 case 0x1e: 244 return new %(strexh)s(machInst, rt, rt2, rn, true, 0); 245 case 0x1f: 246 return new %(ldrexh)s(machInst, rt, rn, true, 0); 247 default: 248 return new Unknown(machInst); 249 } 250 } 251 ''' % { 252 "ldrex" : "LDREX_" + loadImmClassName(False, True, False, size=4), 253 "ldrexb" : "LDREXB_" + loadImmClassName(False, True, False, size=1), 254 "ldrexh" : "LDREXH_" + loadImmClassName(False, True, False, size=2), 255 "ldrexd" : "LDREXD_" + loadDoubleImmClassName(False, True, False), 256 "strex" : "STREX_" + storeImmClassName(False, True, False, size=4), 257 "strexb" : "STREXB_" + storeImmClassName(False, True, False, size=1), 258 "strexh" : "STREXH_" + storeImmClassName(False, True, False, size=2), 259 "strexd" : "STREXD_" + storeDoubleImmClassName(False, True, False) 260 } 261}}; 262 263def format Thumb32SrsRfe() {{ 264 decode_block = ''' 265 { 266 if (bits(machInst, 20) == 1) { 267 const bool add = (bits(machInst, 24, 23) == 0x3); 268 // post == add 269 const bool wb = (bits(machInst, 21) == 1); 270 const IntRegIndex rn = 271 (IntRegIndex)(uint32_t)bits(machInst, 19, 16); 272 if (!add && !wb) { 273 return new %(rfe)s(machInst, rn, RfeOp::DecrementBefore, wb); 274 } else if (add && !wb) { 275 return new %(rfe_u)s(machInst, rn, RfeOp::IncrementAfter, wb); 276 } else if (!add && wb) { 277 return new %(rfe_w)s(machInst, rn, RfeOp::DecrementBefore, wb); 278 } else { 279 return new %(rfe_uw)s(machInst, rn, RfeOp::IncrementAfter, wb); 280 } 281 } else { 282 return new WarnUnimplemented("srs", machInst); 283 } 284 } 285 ''' % { 286 "rfe" : "RFE_" + loadImmClassName(False, False, False, 8), 287 "rfe_u" : "RFE_" + loadImmClassName(True, True, False, 8), 288 "rfe_w" : "RFE_" + loadImmClassName(False, False, True, 8), 289 "rfe_uw" : "RFE_" + loadImmClassName(True, True, True, 8) 290 } 291}}; 292 293def format Thumb32LdrStrDExTbh() {{ 294 decode_block = ''' 295 { 296 const uint32_t op1 = bits(machInst, 24, 23); 297 const uint32_t op2 = bits(machInst, 21, 20); 298 const uint32_t op3 = bits(machInst, 7, 4); 299 const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); 300 const IntRegIndex rt = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); 301 const IntRegIndex rt2 = (IntRegIndex)(uint32_t)bits(machInst, 11, 8); 302 const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); 303 const uint32_t imm8 = bits(machInst, 7, 0); 304 if (bits(op1, 1) == 0 && bits(op2, 1) == 0) { 305 if (op1 == 0) { 306 const uint32_t imm = bits(machInst, 7, 0) << 2; 307 if (op2 == 0) { 308 return new %(strex)s(machInst, rt2, rt, rn, true, imm); 309 } else { 310 return new %(ldrex)s(machInst, rt, rn, true, imm); 311 } 312 } else { 313 if (op2 == 0) { 314 switch (op3) { 315 case 0x4: 316 return new %(strexb)s(machInst, rd, rt, rn, true, 0); 317 case 0x5: 318 return new %(strexh)s(machInst, rd, rt, rn, true, 0); 319 case 0x7: 320 return new %(strexd)s(machInst, rd, rt, 321 rt2, rn, true, 0); 322 default: 323 return new Unknown(machInst); 324 } 325 } else { 326 switch (op3) { 327 case 0x0: 328 return new WarnUnimplemented("tbb", machInst); 329 case 0x1: 330 return new WarnUnimplemented("tbh", machInst); 331 case 0x4: 332 return new %(ldrexb)s(machInst, rt, rn, true, 0); 333 case 0x5: 334 return new %(ldrexh)s(machInst, rt, rn, true, 0); 335 case 0x7: 336 return new %(ldrexd)s(machInst, rt, rt2, rn, true, 0); 337 default: 338 return new Unknown(machInst); 339 } 340 } 341 } 342 } else { 343 const uint32_t puw = (bits(machInst, 24, 23) << 1) | 344 bits(machInst, 21); 345 const uint32_t dimm = imm8 << 2; 346 if (bits(op2, 0) == 0) { 347 switch (puw) { 348 case 0x1: 349 return new %(strd_w)s(machInst, rt, rt2, rn, false, dimm); 350 case 0x3: 351 return new %(strd_uw)s(machInst, rt, rt2, rn, true, dimm); 352 case 0x4: 353 return new %(strd_p)s(machInst, rt, rt2, rn, false, dimm); 354 case 0x5: 355 return new %(strd_pw)s(machInst, rt, rt2, rn, false, dimm); 356 case 0x6: 357 return new %(strd_pu)s(machInst, rt, rt2, rn, true, dimm); 358 case 0x7: 359 return new %(strd_puw)s(machInst, rt, rt2, rn, true, dimm); 360 default: 361 return new Unknown(machInst); 362 } 363 } else { 364 switch (puw) { 365 case 0x1: 366 return new %(ldrd_w)s(machInst, rt, rt2, rn, false, dimm); 367 case 0x3: 368 return new %(ldrd_uw)s(machInst, rt, rt2, rn, true, dimm); 369 case 0x4: 370 return new %(ldrd_p)s(machInst, rt, rt2, rn, false, dimm); 371 case 0x5: 372 return new %(ldrd_pw)s(machInst, rt, rt2, rn, false, dimm); 373 case 0x6: 374 return new %(ldrd_pu)s(machInst, rt, rt2, rn, true, dimm); 375 case 0x7: 376 return new %(ldrd_puw)s(machInst, rt, rt2, rn, true, dimm); 377 default: 378 return new Unknown(machInst); 379 } 380 } 381 } 382 } 383 ''' % { 384 "ldrex" : "LDREX_" + loadImmClassName(False, True, False, size=4), 385 "ldrexb" : "LDREXB_" + loadImmClassName(False, True, False, size=1), 386 "ldrexh" : "LDREXH_" + loadImmClassName(False, True, False, size=2), 387 "ldrexd" : "LDREXD_" + loadDoubleImmClassName(False, True, False), 388 "strex" : "STREX_" + storeImmClassName(False, True, False, size=4), 389 "strexb" : "STREXB_" + storeImmClassName(False, True, False, size=1), 390 "strexh" : "STREXH_" + storeImmClassName(False, True, False, size=2), 391 "strexd" : "STREXD_" + storeDoubleImmClassName(False, True, False), 392 "ldrd_w" : loadDoubleImmClassName(True, False, True), 393 "ldrd_uw" : loadDoubleImmClassName(True, True, True), 394 "ldrd_p" : loadDoubleImmClassName(False, False, False), 395 "ldrd_pw" : loadDoubleImmClassName(False, False, True), 396 "ldrd_pu" : loadDoubleImmClassName(False, True, False), 397 "ldrd_puw" : loadDoubleImmClassName(False, True, True), 398 "strd_w" : storeDoubleImmClassName(True, False, True), 399 "strd_uw" : storeDoubleImmClassName(True, True, True), 400 "strd_p" : storeDoubleImmClassName(False, False, False), 401 "strd_pw" : storeDoubleImmClassName(False, False, True), 402 "strd_pu" : storeDoubleImmClassName(False, True, False), 403 "strd_puw" : storeDoubleImmClassName(False, True, True) 404 } 405}}; 406 407def format Thumb32LoadWord() {{ 408 decode = ''' 409 { 410 uint32_t op1 = bits(machInst, 24, 23); 411 if (bits(op1, 1) == 0) { 412 uint32_t op2 = bits(machInst, 11, 6); 413 if (HTRN == 0xF) { 414 if (UP) { 415 return new %(literal_u)s(machInst, RT, INTREG_PC, 416 true, IMMED_11_0); 417 } else { 418 return new %(literal)s(machInst, RT, INTREG_PC, 419 false, IMMED_11_0); 420 } 421 } else if (op1 == 0x1) { 422 return new %(imm_pu)s(machInst, RT, RN, true, IMMED_11_0); 423 } else if (op2 == 0) { 424 return new %(register)s(machInst, RT, RN, UP, 425 bits(machInst, 5, 4), LSL, RM); 426 } else if ((op2 & 0x3c) == 0x38) { 427 return new %(ldrt)s(machInst, RT, RN, true, IMMED_7_0); 428 } else if ((op2 & 0x3c) == 0x30 || //P 429 (op2 & 0x24) == 0x24) { //W 430 uint32_t puw = bits(machInst, 10, 8); 431 uint32_t imm = IMMED_7_0; 432 switch (puw) { 433 case 0: 434 case 2: 435 // If we're here, either P or W must have been set. 436 panic("Neither P or W set, but that " 437 "shouldn't be possible.\\n"); 438 case 1: 439 return new %(imm_w)s(machInst, RT, RN, false, imm); 440 case 3: 441 return new %(imm_uw)s(machInst, RT, RN, true, imm); 442 case 4: 443 return new %(imm_p)s(machInst, RT, RN, false, imm); 444 case 5: 445 return new %(imm_pw)s(machInst, RT, RN, false, imm); 446 case 6: 447 return new %(imm_pu)s(machInst, RT, RN, true, imm); 448 case 7: 449 return new %(imm_puw)s(machInst, RT, RN, true, imm); 450 } 451 } 452 } else { 453 return new Unknown(machInst); 454 } 455 } 456 ''' 457 classNames = { 458 "literal_u" : loadImmClassName(False, True, False), 459 "literal" : loadImmClassName(False, False, False), 460 "register" : loadRegClassName(False, True, False), 461 "ldrt" : loadImmClassName(False, True, False, user=True), 462 "imm_w" : loadImmClassName(True, False, True), 463 "imm_uw" : loadImmClassName(True, True, True), 464 "imm_p" : loadImmClassName(False, False, False), 465 "imm_pw" : loadImmClassName(False, False, True), 466 "imm_pu" : loadImmClassName(False, True, False), 467 "imm_puw" : loadImmClassName(False, True, True) 468 } 469 decode_block = decode % classNames 470}}; 471 472def format Thumb32StoreSingle() {{ 473 def buildPuwDecode(size): 474 puwDecode = ''' 475 { 476 uint32_t puw = bits(machInst, 10, 8); 477 uint32_t imm = IMMED_7_0; 478 switch (puw) { 479 case 0: 480 case 2: 481 // If we're here, either P or W must have been set. 482 panic("Neither P or W set, but that " 483 "shouldn't be possible.\\n"); 484 case 1: 485 return new %(imm_w)s(machInst, RT, RN, false, imm); 486 case 3: 487 return new %(imm_uw)s(machInst, RT, RN, true, imm); 488 case 4: 489 return new %(imm_p)s(machInst, RT, RN, false, imm); 490 case 5: 491 return new %(imm_pw)s(machInst, RT, RN, false, imm); 492 case 6: 493 return new %(imm_pu)s(machInst, RT, RN, true, imm); 494 case 7: 495 return new %(imm_puw)s(machInst, RT, RN, true, imm); 496 } 497 } 498 ''' 499 return puwDecode % { 500 "imm_w" : storeImmClassName(True, False, True, size=size), 501 "imm_uw" : storeImmClassName(True, True, True, size=size), 502 "imm_p" : storeImmClassName(False, False, False, size=size), 503 "imm_pw" : storeImmClassName(False, False, True, size=size), 504 "imm_pu" : storeImmClassName(False, True, False, size=size), 505 "imm_puw" : storeImmClassName(False, True, True, size=size) 506 } 507 decode = ''' 508 { 509 uint32_t op1 = bits(machInst, 23, 21); 510 uint32_t op2 = bits(machInst, 11, 6); 511 bool op2Puw = ((op2 & 0x24) == 0x24 || 512 (op2 & 0x3c) == 0x30); 513 if (RN == 0xf) { 514 return new Unknown(machInst); 515 } 516 if (op1 == 4) { 517 return new %(strb_imm)s(machInst, RT, RN, true, IMMED_11_0); 518 } else if (op1 == 0 && op2Puw) { 519 %(strb_puw)s; 520 } else if (op1 == 0 && ((op2 & 0x3c) == 0x38)) { 521 return new %(strbt)s(machInst, RT, RN, true, IMMED_7_0); 522 } else if (op1 == 0 && op2 == 0) { 523 return new %(strb_reg)s(machInst, RT, RN, true, 524 bits(machInst, 5, 4), LSL, RM); 525 } else if (op1 == 5) { 526 return new %(strh_imm)s(machInst, RT, RN, true, IMMED_11_0); 527 } else if (op1 == 1 && op2Puw) { 528 %(strh_puw)s; 529 } else if (op1 == 1 && ((op2 & 0x3c) == 0x38)) { 530 return new %(strht)s(machInst, RT, RN, true, IMMED_7_0); 531 } else if (op1 == 1 && op2 == 0) { 532 return new %(strh_reg)s(machInst, RT, RN, true, 533 bits(machInst, 5, 4), LSL, RM); 534 } else if (op1 == 6) { 535 return new %(str_imm)s(machInst, RT, RN, true, IMMED_11_0); 536 } else if (op1 == 2 && op2Puw) { 537 %(str_puw)s; 538 } else if (op1 == 2 && ((op2 & 0x3c) == 0x38)) { 539 return new %(strt)s(machInst, RT, RN, true, IMMED_7_0); 540 } else if (op1 == 2 && op2 == 0) { 541 return new %(str_reg)s(machInst, RT, RN, true, 542 bits(machInst, 5, 4), LSL, RM); 543 } else { 544 return new Unknown(machInst); 545 } 546 } 547 ''' 548 classNames = { 549 "strb_imm" : storeImmClassName(False, True, False, size=1), 550 "strb_puw" : buildPuwDecode(1), 551 "strbt" : storeImmClassName(False, True, False, user=True, size=1), 552 "strb_reg" : storeRegClassName(False, True, False, size=1), 553 "strh_imm" : storeImmClassName(False, True, False, size=2), 554 "strh_puw" : buildPuwDecode(2), 555 "strht" : storeImmClassName(False, True, False, user=True, size=2), 556 "strh_reg" : storeRegClassName(False, True, False, size=2), 557 "str_imm" : storeImmClassName(False, True, False), 558 "str_puw" : buildPuwDecode(4), 559 "strt" : storeImmClassName(False, True, False, user=True), 560 "str_reg" : storeRegClassName(False, True, False) 561 } 562 decode_block = decode % classNames 563}}; 564 565def format LoadByteMemoryHints() {{ 566 decode = ''' 567 { 568 const uint32_t op1 = bits(machInst, 24, 23); 569 const uint32_t op2 = bits(machInst, 11, 6); 570 const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); 571 const IntRegIndex rt = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); 572 const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); 573 const uint32_t imm12 = bits(machInst, 11, 0); 574 const uint32_t imm8 = bits(machInst, 7, 0); 575 bool pldw = bits(machInst, 21); 576 const uint32_t imm2 = bits(machInst, 5, 4); 577 if (rn == 0xf) { 578 if (rt == 0xf) { 579 const bool add = bits(machInst, 23); 580 if (bits(op1, 1) == 1) { 581 if (add) { 582 return new %(pli_iulit)s(machInst, INTREG_ZERO, 583 INTREG_PC, true, imm12); 584 } else { 585 return new %(pli_ilit)s(machInst, INTREG_ZERO, 586 INTREG_PC, false, imm12); 587 } 588 } else { 589 if (add) { 590 return new %(pld_iulit)s(machInst, INTREG_ZERO, 591 INTREG_PC, true, imm12); 592 } else { 593 return new %(pld_ilit)s(machInst, INTREG_ZERO, 594 INTREG_PC, false, imm12); 595 } 596 } 597 } else { 598 if (bits(op1, 1) == 1) { 599 if (bits(machInst, 23)) { 600 return new %(ldrsb_lit_u)s(machInst, rt, INTREG_PC, 601 true, imm12); 602 } else { 603 return new %(ldrsb_lit)s(machInst, rt, INTREG_PC, 604 false, imm12); 605 } 606 } else { 607 if (bits(machInst, 23)) { 608 return new %(ldrb_lit_u)s(machInst, rt, INTREG_PC, 609 true, imm12); 610 } else { 611 return new %(ldrb_lit)s(machInst, rt, INTREG_PC, 612 false, imm12); 613 } 614 } 615 } 616 } else if (rt == 0xf) { 617 switch (op1) { 618 case 0x0: 619 if (op2 == 0x0) { 620 if (pldw) { 621 return new %(pldw_radd)s(machInst, INTREG_ZERO, 622 rn, true, imm2, LSL, rm); 623 } else { 624 return new %(pld_radd)s(machInst, INTREG_ZERO, 625 rn, true, imm2, LSL, rm); 626 } 627 } else if (bits(op2, 5, 2) == 0xc) { 628 if (pldw) { 629 return new %(pldw_isub)s(machInst, INTREG_ZERO, 630 rn, false, imm8); 631 } else { 632 return new %(pld_isub)s(machInst, INTREG_ZERO, 633 rn, false, imm8); 634 } 635 } 636 break; 637 case 0x1: 638 if (pldw) { 639 return new %(pldw_iadd)s(machInst, INTREG_ZERO, 640 rn, true, imm12); 641 } else { 642 return new %(pld_iadd)s(machInst, INTREG_ZERO, 643 rn, true, imm12); 644 } 645 case 0x2: 646 if (op2 == 0x0) { 647 return new %(pli_radd)s(machInst, INTREG_ZERO, rn, 648 true, imm2, LSL, rm); 649 } else if (bits(op2, 5, 2) == 0xc) { 650 return new %(pli_ilit)s(machInst, INTREG_ZERO, 651 INTREG_PC, false, imm8); 652 } 653 break; 654 case 0x3: 655 return new %(pli_iulit)s(machInst, INTREG_ZERO, 656 INTREG_PC, true, imm12); 657 } 658 return new Unknown(machInst); 659 } else { 660 switch (op1) { 661 case 0x0: 662 if (op2 == 0) { 663 return new %(ldrb_radd)s(machInst, rt, rn, true, 664 imm2, LSL, rm); 665 } else if (bits(op2, 5, 2) == 0xe) { 666 return new %(ldrbt)s(machInst, rt, rn, true, imm8); 667 } else if ((op2 & 0x24) == 0x24 || bits(op2, 5, 2) == 0xc) { 668 const uint32_t puw = bits(machInst, 10, 8); 669 switch (puw) { 670 case 0x1: 671 return new %(ldrb_iw)s(machInst, rt, 672 rn, false, imm8); 673 case 0x3: 674 return new %(ldrb_iuw)s(machInst, rt, 675 rn, true, imm8); 676 case 0x4: 677 return new %(ldrb_ip)s(machInst, rt, 678 rn, false, imm8); 679 case 0x5: 680 return new %(ldrb_ipw)s(machInst, rt, 681 rn, false, imm8); 682 case 0x7: 683 return new %(ldrb_ipuw)s(machInst, rt, 684 rn, true, imm8); 685 } 686 } 687 break; 688 case 0x1: 689 return new %(ldrb_iadd)s(machInst, rt, rn, true, imm12); 690 case 0x2: 691 if (op2 == 0) { 692 return new %(ldrsb_radd)s(machInst, rt, rn, true, 693 imm2, LSL, rm); 694 } else if (bits(op2, 5, 2) == 0xe) { 695 return new %(ldrsbt)s(machInst, rt, rn, true, imm8); 696 } else if ((op2 & 0x24) == 0x24 || bits(op2, 5, 2) == 0xc) { 697 const uint32_t puw = bits(machInst, 10, 8); 698 switch (puw) { 699 case 0x1: 700 return new %(ldrsb_iw)s(machInst, rt, 701 rn, false, imm8); 702 case 0x3: 703 return new %(ldrsb_iuw)s(machInst, rt, 704 rn, true, imm8); 705 case 0x4: 706 return new %(ldrsb_ip)s(machInst, rt, 707 rn, false, imm8); 708 case 0x5: 709 return new %(ldrsb_ipw)s(machInst, rt, 710 rn, false, imm8); 711 case 0x7: 712 return new %(ldrsb_ipuw)s(machInst, rt, 713 rn, true, imm8); 714 } 715 } 716 break; 717 case 0x3: 718 return new %(ldrsb_iadd)s(machInst, rt, rn, true, imm12); 719 } 720 return new Unknown(machInst); 721 } 722 } 723 ''' 724 substDict = { 725 "ldrsb_lit_u" : loadImmClassName(False, True, False, 1, True), 726 "ldrsb_lit" : loadImmClassName(False, False, False, 1, True), 727 "ldrb_lit_u" : loadImmClassName(False, True, False, 1), 728 "ldrb_lit" : loadImmClassName(False, False, False, 1), 729 "ldrsb_radd" : loadRegClassName(False, True, False, 1, True), 730 "ldrb_radd" : loadRegClassName(False, True, False, 1), 731 "ldrsb_iw" : loadImmClassName(True, False, True, 1, True), 732 "ldrsb_iuw" : loadImmClassName(True, True, True, 1, True), 733 "ldrsb_ip" : loadImmClassName(False, False, False, 1, True), 734 "ldrsb_ipw" : loadImmClassName(False, False, True, 1, True), 735 "ldrsb_ipuw" : loadImmClassName(False, True, True, 1, True), 736 "ldrsb_iadd" : loadImmClassName(False, True, False, 1, True), 737 "ldrb_iw" : loadImmClassName(True, False, True, 1), 738 "ldrb_iuw" : loadImmClassName(True, True, True, 1), 739 "ldrb_ip" : loadImmClassName(False, False, False, 1), 740 "ldrb_ipw" : loadImmClassName(False, False, True, 1), 741 "ldrb_ipuw" : loadImmClassName(False, True, True, 1), 742 "ldrb_iadd" : loadImmClassName(False, True, False, 1), 743 "ldrbt" : loadImmClassName(False, True, False, 1, user=True), 744 "ldrsbt" : loadImmClassName(False, True, False, 1, True, user=True), 745 "pldw_radd" : "PLDW_" + loadRegClassName(False, True, False, 1), 746 "pld_radd" : "PLD_" + loadRegClassName(False, True, False, 1), 747 "pldw_isub" : "PLDW_" + loadImmClassName(False, False, False, 1), 748 "pld_isub" : "PLD_" + loadImmClassName(False, False, False, 1), 749 "pldw_iadd" : "PLDW_" + loadImmClassName(False, True, False, 1), 750 "pld_iadd" : "PLD_" + loadImmClassName(False, True, False, 1), 751 "pld_iulit" : "PLD_" + loadImmClassName(False, True, False, 1), 752 "pld_ilit" : "PLD_" + loadImmClassName(False, False, False, 1), 753 "pli_iulit" : "PLI_" + loadImmClassName(False, True, False, 1), 754 "pli_ilit" : "PLI_" + loadImmClassName(False, False, False, 1), 755 "pli_radd" : "PLI_" + loadRegClassName(False, True, False, 1), 756 "pli_iulit" : "PLI_" + loadImmClassName(False, True, False, 1), 757 "pli_ilit" : "PLI_" + loadImmClassName(False, False, False, 1) 758 } 759 decode_block = decode % substDict 760}}; 761 762def format LoadHalfwordMemoryHints() {{ 763 decode = ''' 764 { 765 const uint32_t op1 = bits(machInst, 24, 23); 766 const uint32_t op2 = bits(machInst, 11, 6); 767 const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); 768 const IntRegIndex rt = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); 769 const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); 770 const uint32_t imm12 = bits(machInst, 11, 0); 771 const uint32_t imm8 = bits(machInst, 7, 0); 772 bool pldw = bits(machInst, 21); 773 const uint32_t imm2 = bits(machInst, 5, 4); 774 if (rn == 0xf) { 775 if (rt == 0xf) { 776 if (bits(op1, 1) == 1) { 777 // Unallocated memory hint 778 return new NopInst(machInst); 779 } else { 780 return new Unknown(machInst); 781 } 782 } else { 783 if (bits(op1, 1) == 1) { 784 if (bits(machInst, 23)) { 785 return new %(ldrsh_lit_u)s(machInst, rt, INTREG_PC, 786 true, imm12); 787 } else { 788 return new %(ldrsh_lit)s(machInst, rt, INTREG_PC, 789 false, imm12); 790 } 791 } else { 792 if (bits(machInst, 23)) { 793 return new %(ldrh_lit_u)s(machInst, rt, INTREG_PC, 794 true, imm12); 795 } else { 796 return new %(ldrh_lit)s(machInst, rt, INTREG_PC, 797 false, imm12); 798 } 799 } 800 } 801 } else if (rt == 0xf) { 802 switch (op1) { 803 case 0x0: 804 if (op2 == 0x0) { 805 if (pldw) { 806 return new %(pldw_radd)s(machInst, INTREG_ZERO, 807 rn, true, imm2, LSL, rm); 808 } else { 809 return new %(pld_radd)s(machInst, INTREG_ZERO, 810 rn, true, imm2, LSL, rm); 811 } 812 } else if (bits(op2, 5, 2) == 0xc) { 813 if (pldw) { 814 return new %(pldw_isub)s(machInst, INTREG_ZERO, 815 rn, false, imm8); 816 } else { 817 return new %(pld_isub)s(machInst, INTREG_ZERO, 818 rn, false, imm8); 819 } 820 } 821 break; 822 case 0x1: 823 if (pldw) { 824 return new %(pldw_iadd)s(machInst, INTREG_ZERO, 825 rn, true, imm12); 826 } else { 827 return new %(pld_iadd)s(machInst, INTREG_ZERO, 828 rn, true, imm12); 829 } 830 case 0x2: 831 if (op2 == 0x0 || bits(op2, 5, 2) == 0xc) { 832 // Unallocated memory hint 833 return new NopInst(machInst); 834 } 835 break; 836 case 0x3: 837 return new NopInst(machInst); 838 } 839 return new Unknown(machInst); 840 } else { 841 switch (op1) { 842 case 0x0: 843 if (op2 == 0) { 844 return new %(ldrh_radd)s(machInst, rt, rn, true, 845 imm2, LSL, rm); 846 } else if (bits(op2, 5, 2) == 0xe) { 847 return new %(ldrht)s(machInst, rt, rn, true, imm8); 848 } else if ((op2 & 0x24) == 0x24 || bits(op2, 5, 2) == 0xc) { 849 const uint32_t puw = bits(machInst, 10, 8); 850 switch (puw) { 851 case 0x1: 852 return new %(ldrh_iw)s(machInst, rt, 853 rn, false, imm8); 854 case 0x3: 855 return new %(ldrh_iuw)s(machInst, rt, 856 rn, true, imm8); 857 case 0x4: 858 return new %(ldrh_ip)s(machInst, rt, 859 rn, false, imm8); 860 case 0x5: 861 return new %(ldrh_ipw)s(machInst, rt, 862 rn, false, imm8); 863 case 0x7: 864 return new %(ldrh_ipuw)s(machInst, rt, 865 rn, true, imm8); 866 } 867 } 868 break; 869 case 0x1: 870 return new %(ldrh_iadd)s(machInst, rt, rn, true, imm12); 871 case 0x2: 872 if (op2 == 0) { 873 return new %(ldrsh_radd)s(machInst, rt, rn, true, 874 imm2, LSL, rm); 875 } else if (bits(op2, 5, 2) == 0xe) { 876 return new %(ldrsht)s(machInst, rt, rn, true, imm8); 877 } else if ((op2 & 0x24) == 0x24 || bits(op2, 5, 2) == 0xc) { 878 const uint32_t puw = bits(machInst, 10, 8); 879 switch (puw) { 880 case 0x1: 881 return new %(ldrsh_iw)s(machInst, rt, 882 rn, false, imm8); 883 case 0x3: 884 return new %(ldrsh_iuw)s(machInst, rt, 885 rn, true, imm8); 886 case 0x4: 887 return new %(ldrsh_ip)s(machInst, rt, 888 rn, false, imm8); 889 case 0x5: 890 return new %(ldrsh_ipw)s(machInst, rt, 891 rn, false, imm8); 892 case 0x7: 893 return new %(ldrsh_ipuw)s(machInst, rt, 894 rn, true, imm8); 895 } 896 } 897 break; 898 case 0x3: 899 return new %(ldrsh_iadd)s(machInst, rt, rn, true, imm12); 900 } 901 return new Unknown(machInst); 902 } 903 } 904 ''' 905 substDict = { 906 "ldrsh_lit_u" : loadImmClassName(False, True, False, 2, True), 907 "ldrsh_lit" : loadImmClassName(False, False, False, 2, True), 908 "ldrh_lit_u" : loadImmClassName(False, True, False, 2), 909 "ldrh_lit" : loadImmClassName(False, False, False, 2), 910 "ldrsh_radd" : loadRegClassName(False, True, False, 2, True), 911 "ldrh_radd" : loadRegClassName(False, True, False, 2), 912 "ldrsh_iw" : loadImmClassName(True, False, True, 2, True), 913 "ldrsh_iuw" : loadImmClassName(True, True, True, 2, True), 914 "ldrsh_ip" : loadImmClassName(False, False, False, 2, True), 915 "ldrsh_ipw" : loadImmClassName(False, False, True, 2, True), 916 "ldrsh_ipuw" : loadImmClassName(False, True, True, 2, True), 917 "ldrsh_iadd" : loadImmClassName(False, True, False, 2, True), 918 "ldrh_iw" : loadImmClassName(True, False, True, 2), 919 "ldrh_iuw" : loadImmClassName(True, True, True, 2), 920 "ldrh_ip" : loadImmClassName(False, False, False, 2), 921 "ldrh_ipw" : loadImmClassName(False, False, True, 2), 922 "ldrh_ipuw" : loadImmClassName(False, True, True, 2), 923 "ldrh_iadd" : loadImmClassName(False, True, False, 2), 924 "ldrht" : loadImmClassName(False, True, False, 2, user=True), 925 "ldrsht" : loadImmClassName(False, True, False, 2, True, user=True), 926 "pldw_radd" : "PLDW_" + loadRegClassName(False, True, False, 1), 927 "pld_radd" : "PLD_" + loadRegClassName(False, True, False, 1), 928 "pldw_isub" : "PLDW_" + loadImmClassName(False, False, False, 1), 929 "pld_isub" : "PLD_" + loadImmClassName(False, False, False, 1), 930 "pldw_iadd" : "PLDW_" + loadImmClassName(False, True, False, 1), 931 "pld_iadd" : "PLD_" + loadImmClassName(False, True, False, 1) 932 } 933 decode_block = decode % substDict 934}}; 935 936def format Thumb16MemReg() {{ 937 decode = ''' 938 { 939 const uint32_t opb = bits(machInst, 11, 9); 940 const uint32_t rt = bits(machInst, 2, 0); 941 const uint32_t rn = bits(machInst, 5, 3); 942 const uint32_t rm = bits(machInst, 8, 6); 943 switch (opb) { 944 case 0x0: 945 return new %(str)s(machInst, rt, rn, true, 0, LSL, rm); 946 case 0x1: 947 return new %(strh)s(machInst, rt, rn, true, 0, LSL, rm); 948 case 0x2: 949 return new %(strb)s(machInst, rt, rn, true, 0, LSL, rm); 950 case 0x3: 951 return new %(ldrsb)s(machInst, rt, rn, true, 0, LSL, rm); 952 case 0x4: 953 return new %(ldr)s(machInst, rt, rn, true, 0, LSL, rm); 954 case 0x5: 955 return new %(ldrh)s(machInst, rt, rn, true, 0, LSL, rm); 956 case 0x6: 957 return new %(ldrb)s(machInst, rt, rn, true, 0, LSL, rm); 958 case 0x7: 959 return new %(ldrsh)s(machInst, rt, rn, true, 0, LSL, rm); 960 } 961 } 962 ''' 963 classNames = { 964 "str" : storeRegClassName(False, True, False), 965 "strh" : storeRegClassName(False, True, False, size=2), 966 "strb" : storeRegClassName(False, True, False, size=1), 967 "ldrsb" : loadRegClassName(False, True, False, sign=True, size=1), 968 "ldr" : loadRegClassName(False, True, False), 969 "ldrh" : loadRegClassName(False, True, False, size=2), 970 "ldrb" : loadRegClassName(False, True, False, size=1), 971 "ldrsh" : loadRegClassName(False, True, False, sign=True, size=2), 972 } 973 decode_block = decode % classNames 974}}; 975 976def format Thumb16MemImm() {{ 977 decode = ''' 978 { 979 const uint32_t opa = bits(machInst, 15, 12); 980 const uint32_t opb = bits(machInst, 11, 9); 981 const uint32_t lrt = bits(machInst, 2, 0); 982 const uint32_t lrn = bits(machInst, 5, 3); 983 const uint32_t hrt = bits(machInst, 10, 8); 984 const uint32_t imm5 = bits(machInst, 10, 6); 985 const uint32_t imm8 = bits(machInst, 7, 0); 986 const bool load = bits(opb, 2); 987 switch (opa) { 988 case 0x6: 989 if (load) { 990 return new %(ldr)s(machInst, lrt, lrn, true, imm5 << 2); 991 } else { 992 return new %(str)s(machInst, lrt, lrn, true, imm5 << 2); 993 } 994 case 0x7: 995 if (load) { 996 return new %(ldrb)s(machInst, lrt, lrn, true, imm5); 997 } else { 998 return new %(strb)s(machInst, lrt, lrn, true, imm5); 999 } 1000 case 0x8: 1001 if (load) { 1002 return new %(ldrh)s(machInst, lrt, lrn, true, imm5 << 1); 1003 } else { 1004 return new %(strh)s(machInst, lrt, lrn, true, imm5 << 1); 1005 } 1006 case 0x9: 1007 if (load) { 1008 return new %(ldr)s(machInst, hrt, INTREG_SP, true, imm8 << 2); 1009 } else { 1010 return new %(str)s(machInst, hrt, INTREG_SP, true, imm8 << 2); 1011 } 1012 default: 1013 return new Unknown(machInst); 1014 } 1015 } 1016 ''' 1017 classNames = { 1018 "ldr" : loadImmClassName(False, True, False), 1019 "str" : storeImmClassName(False, True, False), 1020 "ldrh" : loadImmClassName(False, True, False, size=2), 1021 "strh" : storeImmClassName(False, True, False, size=2), 1022 "ldrb" : loadImmClassName(False, True, False, size=1), 1023 "strb" : storeImmClassName(False, True, False, size=1), 1024 } 1025 decode_block = decode % classNames 1026}}; 1027 1028def format Thumb16MemLit() {{ 1029 decode_block = ''' 1030 { 1031 const uint32_t rt = bits(machInst, 10, 8); 1032 const uint32_t imm8 = bits(machInst, 7, 0); 1033 return new %s(machInst, rt, INTREG_PC, true, imm8 << 2); 1034 } 1035 ''' % loadImmClassName(False, True, False) 1036}}; 1037 1038