1//===-- M68kInstrControl.td - Control Flow Instructions ----*- tablegen -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8/// 9/// \file 10/// This file describes the M68k jump, return, call, and related instructions. 11/// Here is the current status of the file: 12/// 13/// Machine: 14/// 15/// BRA [x] BSR [~] Bcc [~] DBcc [ ] FBcc [ ] 16/// FDBcc [ ] FNOP [ ] FPn [ ] FScc [ ] FTST [ ] 17/// JMP [~] JSR [x] NOP [x] RTD [!] RTR [ ] 18/// RTS [x] Scc [~] TST [ ] 19/// 20/// Pseudo: 21/// 22/// RET [x] 23/// TCRETURNj [x] TCRETURNq [x] 24/// TAILJMPj [x] TAILJMPq [x] 25/// 26/// Map: 27/// 28/// [ ] - was not touched at all 29/// [!] - requires extarnal stuff implemented 30/// [~] - in progress but usable 31/// [x] - done 32/// 33/// 34/// NOTE 35/// Though branch and jump instructions are using memory operands they 36/// DO NOT read the jump address from memory, they just calculate EA 37/// and jump there. 38/// 39//===----------------------------------------------------------------------===// 40 41//===----------------------------------------------------------------------===// 42// NOP 43//===----------------------------------------------------------------------===// 44 45let hasSideEffects = 0 in { 46 def NOP : MxInst<(outs), (ins), "nop", []> { 47 let Inst = (descend 0b0100, 0b1110, 0b0111, 0b0001); 48 } 49} 50 51 52//===----------------------------------------------------------------------===// 53// Conditions 54//===----------------------------------------------------------------------===// 55 56/// CC—Carry clear GE—Greater than or equal 57/// LS—Lower or same PL—Plus 58/// CS—Carry set GT—Greater than 59/// LT—Less than T—Always true* 60/// EQ—Equal HI—Higher 61/// MI—Minus VC—Overflow clear 62/// F—Never true* LE—Less than or equal 63/// NE—Not equal VS—Overflow set 64/// 65/// *Not applicable to the Bcc instructions. 66class MxEncCondOp<bits<4> cond> { 67 dag Value = (descend cond); 68} 69 70def MxCCt : MxEncCondOp<0b0000>; 71def MxCCf : MxEncCondOp<0b0001>; 72def MxCChi : MxEncCondOp<0b0010>; 73def MxCCls : MxEncCondOp<0b0011>; 74def MxCCcc : MxEncCondOp<0b0100>; 75def MxCCcs : MxEncCondOp<0b0101>; 76def MxCCne : MxEncCondOp<0b0110>; 77def MxCCeq : MxEncCondOp<0b0111>; 78def MxCCvc : MxEncCondOp<0b1000>; 79def MxCCvs : MxEncCondOp<0b1001>; 80def MxCCpl : MxEncCondOp<0b1010>; 81def MxCCmi : MxEncCondOp<0b1011>; 82def MxCCge : MxEncCondOp<0b1100>; 83def MxCClt : MxEncCondOp<0b1101>; 84def MxCCgt : MxEncCondOp<0b1110>; 85def MxCCle : MxEncCondOp<0b1111>; 86 87 88 89/// --------------------------------+---------+--------- 90/// F E D C | B A 9 8 | 7 6 | 5 4 3 | 2 1 0 91/// --------------------------------+---------+--------- 92/// 0 1 0 1 | CONDITION | 1 1 | MODE | REG 93/// ---------------------------------------------------- 94 95let Uses = [CCR] in { 96class MxSccR<string CC> 97 : MxInst<(outs MxDRD8:$dst), (ins), "s"#CC#"\t$dst", 98 [(set i8:$dst, (MxSetCC !cast<PatLeaf>("MxCOND"#CC), CCR))]> { 99 let Inst = (descend 0b0101, !cast<MxEncCondOp>("MxCC"#CC).Value, 0b11, 100 /*MODE without last bit*/0b00, 101 /*REGISTER prefixed with D/A bit*/(operand "$dst", 4)); 102} 103 104class MxSccM<string CC, MxOperand MEMOpd, ComplexPattern MEMPat, MxEncMemOp DST_ENC> 105 : MxInst<(outs), (ins MEMOpd:$dst), "s"#CC#"\t$dst", 106 [(store (MxSetCC !cast<PatLeaf>("MxCOND"#CC), CCR), MEMPat:$dst)]> { 107 let Inst = 108 (ascend 109 (descend 0b0101, !cast<MxEncCondOp>("MxCC"#CC).Value, 0b11, DST_ENC.EA), 110 DST_ENC.Supplement 111 ); 112} 113} 114 115foreach cc = [ "cc", "ls", "lt", "eq", "mi", "f", "ne", "ge", 116 "cs", "pl", "gt", "t", "hi", "vc", "le", "vs"] in { 117def SET#"d8"#cc : MxSccR<cc>; 118def SET#"j8"#cc : MxSccM<cc, MxType8.JOp, MxType8.JPat, MxEncAddrMode_j<"dst">>; 119def SET#"p8"#cc : MxSccM<cc, MxType8.POp, MxType8.PPat, MxEncAddrMode_p<"dst">>; 120} 121 122//===----------------------------------------------------------------------===// 123// Jumps 124//===----------------------------------------------------------------------===// 125 126///------------------------------+---------+--------- 127/// F E D C B A 9 8 7 6 | 5 4 3 | 2 1 0 128///------------------------------+---------+--------- 129/// 0 1 0 0 1 1 1 0 1 1 | MODE | REG 130///------------------------------+---------+--------- 131let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in 132class MxJMP<MxOperand LOCOp, MxEncMemOp DST_ENC> 133 : MxInst<(outs), (ins LOCOp:$dst), "jmp\t$dst", [(brind iPTR:$dst)]> { 134 let Inst = 135 (ascend 136 (descend 0b0100, 0b1110, 0b11, DST_ENC.EA), 137 DST_ENC.Supplement 138 ); 139} 140 141def JMP32j : MxJMP<MxARI32, MxEncAddrMode_j<"dst">>; 142 143 144// FIXME Support 16 bit indirect jump. 145// Currently M68k does not allow 16 bit indirect jumps use sext operands 146// def JMP16r : MxInst<(outs), (ins M68k_ARI16:$dst), 147// "jmp\t$dst", 148// [(brind AR16:$dst)]>; 149 150//===----------------------------------------------------------------------===// 151// Branches 152//===----------------------------------------------------------------------===// 153 154/// -------------------------------------------------- 155/// F E D C | B A 9 8 | 7 6 5 4 3 2 1 0 156/// -------------------------------------------------- 157/// 0 1 1 0 | CONDITION | 8-BIT DISPLACEMENT 158/// -------------------------------------------------- 159/// 16-BIT DISPLACEMENT IF 8-BIT DISPLACEMENT = $00 160/// -------------------------------------------------- 161/// 32-BIT DISPLACEMENT IF 8-BIT DISPLACEMENT = $FF 162/// -------------------------------------------------- 163let isBranch = 1, isTerminator = 1, Uses = [CCR] in 164class MxBcc<string cc, Operand TARGET, dag disp_8, dag disp_16_32> 165 : MxInst<(outs), (ins TARGET:$dst), "b"#cc#"\t$dst", []> { 166 // FIXME: If we want to avoid supplying disp_16_32 with empty 167 // (ascend) for 16/32 bits variants, we can use conditional 168 // bang operator like this: 169 // ``` 170 // class MxBcc<string cc, Operand TARGET, int SIZE> 171 // ... 172 // let Inst = !cond( 173 // !eq(SIZE, 8): /* encoding for Bcc8 */ 174 // !eq(SIZE, 16): /* encoding for Bcc16 */ 175 // !eq(SIZE, 32): /* encoding for Bcc32 */ 176 // ); 177 let Inst = 178 (ascend 179 (descend 0b0110, !cast<MxEncCondOp>("MxCC"#cc).Value, disp_8), 180 disp_16_32 181 ); 182 183 let Predicates = !if(!eq(TARGET, MxBrTarget32), [AtLeastM68020], []); 184} 185 186foreach cc = [ "cc", "ls", "lt", "eq", "mi", "ne", "ge", 187 "cs", "pl", "gt", "hi", "vc", "le", "vs"] in { 188 def B#cc#"8" 189 : MxBcc<cc, MxBrTarget8, 190 (operand "$dst", 8, (encoder "encodePCRelImm<8>")), (ascend)>; 191 192 def B#cc#"16" 193 : MxBcc<cc, MxBrTarget16, (descend 0b0000, 0b0000), 194 (operand "$dst", 16, (encoder "encodePCRelImm<16>"))>; 195 196 def B#cc#"32" 197 : MxBcc<cc, MxBrTarget32, (descend 0b1111, 0b1111), 198 (operand "$dst", 32, (encoder "encodePCRelImm<32>"))>; 199} 200 201foreach cc = [ "cc", "ls", "lt", "eq", "mi", "ne", "ge", 202 "cs", "pl", "gt", "hi", "vc", "le", "vs"] in { 203def : Pat<(MxBrCond bb:$target, !cast<PatLeaf>("MxCOND"#cc), CCR), 204 (!cast<Instruction>("B"#cc#"8") MxBrTarget8:$target)>; 205} 206 207/// ------------------------------------------------- 208/// F E D C B A 9 8 | 7 6 5 4 3 2 1 0 209/// ------------------------------------------------- 210/// 0 1 1 0 0 0 0 0 | 8-BIT DISPLACEMENT 211/// ------------------------------------------------- 212/// 16-BIT DISPLACEMENT IF 8-BIT DISPLACEMENT = $00 213/// ------------------------------------------------- 214/// 32-BIT DISPLACEMENT IF 8-BIT DISPLACEMENT = $FF 215/// ------------------------------------------------- 216let isBranch = 1, isTerminator = 1, isBarrier = 1 in 217class MxBra<Operand TARGET, dag disp_8, dag disp_16_32> 218 : MxInst<(outs), (ins TARGET:$dst), "bra\t$dst", []> { 219 let Inst = 220 (ascend 221 (descend 0b0110, 0b0000, disp_8), 222 disp_16_32 223 ); 224 225 let Predicates = !if(!eq(TARGET, MxBrTarget32), [AtLeastM68020], []); 226} 227 228def BRA8 : MxBra<MxBrTarget8, 229 (operand "$dst", 8, (encoder "encodePCRelImm<8>")), (ascend)>; 230 231def BRA16 : MxBra<MxBrTarget16, (descend 0b0000, 0b0000), 232 (operand "$dst", 16, (encoder "encodePCRelImm<16>"))>; 233 234def BRA32 : MxBra<MxBrTarget32, (descend 0b1111, 0b1111), 235 (operand "$dst", 32, (encoder "encodePCRelImm<32>"), 236 (decoder "DecodeImm32"))>; 237 238def : Pat<(br bb:$target), (BRA8 MxBrTarget8:$target)>; 239 240/// ------------------------------------------------- 241/// F E D C B A 9 8 | 7 6 5 4 3 2 1 0 242/// ------------------------------------------------- 243/// 0 1 1 0 0 0 0 1 | 8-BIT DISPLACEMENT 244/// ------------------------------------------------- 245/// 16-BIT DISPLACEMENT IF 8-BIT DISPLACEMENT = $00 246/// ------------------------------------------------- 247/// 32-BIT DISPLACEMENT IF 8-BIT DISPLACEMENT = $FF 248/// ------------------------------------------------- 249 250let isBranch = 1, isTerminator = 1 in 251class MxBsr<Operand TARGET, MxType TYPE, dag disp_8, dag disp_16_32> 252 : MxInst<(outs), (ins TARGET:$dst), "bsr."#TYPE.Prefix#"\t$dst"> { 253 let Inst = (ascend 254 (descend 0b0110, 0b0001, disp_8), 255 disp_16_32 256 ); 257 let Predicates = !if(!eq(TARGET, MxBrTarget32), [AtLeastM68020], []); 258} 259 260def BSR8 : MxBsr<MxBrTarget8, MxType8, 261 (operand "$dst", 8, (encoder "encodePCRelImm<8>")), (ascend)>; 262 263def BSR16 : MxBsr<MxBrTarget16, MxType16, (descend 0b0000, 0b0000), 264 (operand "$dst", 16, (encoder "encodePCRelImm<16>"))>; 265 266def BSR32 : MxBsr<MxBrTarget32, MxType32, (descend 0b1111, 0b1111), 267 (operand "$dst", 32, (encoder "encodePCRelImm<32>"), 268 (decoder "DecodeImm32"))>; 269 270//===----------------------------------------------------------------------===// 271// Call 272//===----------------------------------------------------------------------===// 273 274// All calls clobber the non-callee saved registers. %SP is marked as 275// a use to prevent stack-pointer assignments that appear immediately 276// before calls from potentially appearing dead. Uses for argument 277// registers are added manually. 278let Uses = [SP] in 279let isCall = 1 in 280///------------------------------+---------+--------- 281/// F E D C B A 9 8 7 6 | 5 4 3 | 2 1 0 282///------------------------------+---------+--------- 283/// 0 1 0 0 1 1 1 0 1 0 | MODE | REG 284///------------------------------+---------+--------- 285class MxCall<MxOperand LOCOp, MxEncMemOp DST_ENC> 286 : MxInst<(outs), (ins LOCOp:$dst), "jsr\t$dst", []> { 287 let Inst = 288 (ascend 289 (descend 0b0100, 0b1110, 0b10, DST_ENC.EA), 290 DST_ENC.Supplement 291 ); 292} 293 294def CALLk : MxCall<MxPCI32, MxEncAddrMode_k<"dst">>; 295def CALLq : MxCall<MxPCD32, MxEncAddrMode_q<"dst">>; 296def CALLb : MxCall<MxAL32, MxEncAddrMode_abs<"dst", true>>; 297def CALLj : MxCall<MxARI32, MxEncAddrMode_j<"dst">>; 298 299multiclass CallPat<MxCall callOp, Predicate pred> { 300 let Predicates = [pred] in { 301 def : Pat<(MxCall (i32 tglobaladdr:$dst)), (callOp tglobaladdr:$dst)>; 302 def : Pat<(MxCall (i32 texternalsym:$dst)), (callOp texternalsym:$dst)>; 303 def : Pat<(MxCall (i32 imm:$dst)), (callOp imm:$dst)>; 304 } 305} 306 307defm : CallPat<CALLq, IsPIC>; 308defm : CallPat<CALLb, IsNotPIC>; 309 310def : Pat<(MxCall iPTR:$dst), (CALLj MxARI32:$dst)>; 311 312//===----------------------------------------------------------------------===// 313// Tail Call 314//===----------------------------------------------------------------------===// 315 316let isCodeGenOnly = 1 in { 317let Uses = [SP] in { 318let isCall = 1, isTerminator = 1, isBarrier = 1 in { 319 320let isReturn = 1 in 321def TCRETURNq : MxPseudo<(outs), (ins MxPCD32:$dst, i32imm:$adj)>; 322def TAILJMPq : MxPseudo<(outs), (ins MxPCD32:$dst)>; 323 324// NOTE j does not mean load and jump M68k jmp just calculates EA and jumps 325// and it is using Mem form like (An) thus j letter. 326let isReturn = 1 in 327def TCRETURNj : MxPseudo<(outs), (ins MxARI32_TC:$dst, i32imm:$adj)>; 328def TAILJMPj : MxPseudo<(outs), (ins MxARI32_TC:$dst)>; 329} // isCall = 1, isTerminator = 1, isBarrier = 1 330} // Uses = [SP] 331} // isCodeGenOnly = 1 332 333//===----------------------------------------------------------------------===// 334// Return 335//===----------------------------------------------------------------------===// 336 337let isTerminator = 1, isReturn = 1, isBarrier = 1, hasCtrlDep = 1 in { 338 339def RTS : MxInst<(outs), (ins), "rts", []> { 340 let Inst = (descend 0b0100, 0b1110, 0b0111, 0b0101); 341} 342 343def RTE: MxInst<(outs), (ins), "rte", []> { 344 let Inst = (descend 0b0100, 0b1110, 0b0111, 0b0011); 345} 346 347let isCodeGenOnly = 1 in 348def RET : MxPseudo<(outs), (ins i32imm:$adj, variable_ops), 349 [(MxRet timm:$adj)]>; 350} // isTerminator = 1, isReturn = 1, isBarrier = 1, hasCtrlDep = 1 351 352//===----------------------------------------------------------------------===// 353// SETCC_C Patterns 354//===----------------------------------------------------------------------===// 355 356// Use subx to materialize carry bit. 357let Uses = [CCR], Defs = [CCR], isPseudo = 1 in { 358// FIXME These are pseudo ops that should be replaced with Pat<> patterns. 359// However, Pat<> can't replicate the destination reg into the inputs of the 360// result. 361def SETCS_C8d : MxPseudo<(outs MxDRD8:$dst), (ins), 362 [(set MxDRD8:$dst, (MxSetCC_C MxCONDcs, CCR))]>; 363def SETCS_C16d : MxPseudo<(outs MxDRD16:$dst), (ins), 364 [(set MxDRD16:$dst, (MxSetCC_C MxCONDcs, CCR))]>; 365def SETCS_C32d : MxPseudo<(outs MxXRD32:$dst), (ins), 366 [(set MxXRD32:$dst, (MxSetCC_C MxCONDcs, CCR))]>; 367} // Uses = [CCR], Defs = [CCR], isPseudo = 1 368 369 370def : Pat<(i16 (anyext (i8 (MxSetCC_C MxCONDcs, CCR)))), (SETCS_C16d)>; 371def : Pat<(i32 (anyext (i8 (MxSetCC_C MxCONDcs, CCR)))), (SETCS_C32d)>; 372 373def : Pat<(i16 (sext (i8 (MxSetCC_C MxCONDcs, CCR)))), (SETCS_C16d)>; 374def : Pat<(i32 (sext (i8 (MxSetCC_C MxCONDcs, CCR)))), (SETCS_C32d)>; 375 376// We canonicalize 'scs' to "(and (subx reg,reg), 1)" on the hope that the and 377// will be eliminated and that the subx can be extended up to a wider type. When 378// this happens, it is great. However, if we are left with an 8-bit subx and an 379// and, we might as well just match it as a setb. 380def : Pat<(and (i8 (MxSetCC_C MxCONDcs, CCR)), 1), (SETd8cs)>; 381 382// (add OP, SETB) -> (addx OP, (move 0)) 383def : Pat<(add (and (i8 (MxSetCC_C MxCONDcs, CCR)), 1), MxDRD8:$op), 384 (ADDX8dd MxDRD8:$op, (MOV8di 0))>; 385def : Pat<(add (and (i32 (MxSetCC_C MxCONDcs, CCR)), 1), MxXRD32:$op), 386 (ADDX32dd MxDRD32:$op, (MOV32ri 0))>; 387 388// (sub OP, SETB) -> (subx OP, (move 0)) 389def : Pat<(sub MxDRD8:$op, (and (i8 (MxSetCC_C MxCONDcs, CCR)), 1)), 390 (SUBX8dd MxDRD8:$op, (MOV8di 0))>; 391def : Pat<(sub MxXRD32:$op, (and (i32 (MxSetCC_C MxCONDcs, CCR)), 1)), 392 (SUBX32dd MxDRD32:$op, (MOV32ri 0))>; 393 394// (sub OP, SETCC_CARRY) -> (addx OP, (move 0)) 395def : Pat<(sub MxDRD8:$op, (i8 (MxSetCC_C MxCONDcs, CCR))), 396 (ADDX8dd MxDRD8:$op, (MOV8di 0))>; 397def : Pat<(sub MxXRD32:$op, (i32 (MxSetCC_C MxCONDcs, CCR))), 398 (ADDX32dd MxDRD32:$op, (MOV32ri 0))>; 399 400//===------------===// 401// Trap / Breakpoint 402//===------------===// 403 404let RenderMethod = "addImmOperands", ParserMethod = "parseImm" in { 405 def MxTrapImm : AsmOperandClass { 406 let Name = "MxTrapImm"; 407 let PredicateMethod = "isTrapImm"; 408 } 409 410 def MxBkptImm : AsmOperandClass { 411 let Name = "MxBkptImm"; 412 let PredicateMethod = "isBkptImm"; 413 } 414} 415 416let ParserMatchClass = MxTrapImm in 417def MxTrapimm : MxOp<i8, MxSize8, "i">; 418 419let ParserMatchClass = MxBkptImm in 420def MxBkptimm : MxOp<i8, MxSize8, "i">; 421 422def TRAP : MxInst<(outs), (ins MxTrapimm:$vect), "trap\t$vect", []> { 423 let Inst = (descend 0b0100, 0b1110, 0b0100, (operand "$vect", 4)); 424} 425 426def TRAPV : MxInst<(outs), (ins), "trapv", []> { 427 let Inst = (descend 0b0100, 0b1110, 0b0111, 0b0110); 428} 429 430def BKPT : MxInst<(outs), (ins MxBkptimm:$vect), "bkpt\t$vect", []> { 431 let Inst = (descend 0b0100, 0b1000, 0b0100, 0b1 , (operand "$vect", 3)); 432} 433 434def ILLEGAL : MxInst<(outs), (ins), "illegal", []> { 435 let Inst = (descend 0b0100, 0b1010, 0b1111, 0b1100); 436} 437