1 //===-- SystemZInstPrinter.cpp - Convert SystemZ MCInst to assembly syntax --------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This class prints an SystemZ MCInst to a .s file. 11 // 12 //===----------------------------------------------------------------------===// 13 14 /* Capstone Disassembly Engine */ 15 /* By Nguyen Anh Quynh <aquynh (at) gmail.com>, 2013-2014 */ 16 17 #ifdef CAPSTONE_HAS_SYSZ 18 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <string.h> 22 #include <platform.h> 23 24 #include "SystemZInstPrinter.h" 25 #include "../../MCInst.h" 26 #include "../../utils.h" 27 #include "../../SStream.h" 28 #include "../../MCRegisterInfo.h" 29 #include "../../MathExtras.h" 30 #include "SystemZMapping.h" 31 32 static const char *getRegisterName(unsigned RegNo); 33 34 void SystemZ_post_printer(csh ud, cs_insn *insn, char *insn_asm, MCInst *mci) 35 { 36 /* 37 if (((cs_struct *)ud)->detail != CS_OPT_ON) 38 return; 39 */ 40 } 41 42 static void printAddress(MCInst *MI, unsigned Base, int64_t Disp, unsigned Index, SStream *O) 43 { 44 if (Disp >= 0) { 45 if (Disp > HEX_THRESHOLD) 46 SStream_concat(O, "0x%"PRIx64, Disp); 47 else 48 SStream_concat(O, "%"PRIu64, Disp); 49 } else { 50 if (Disp < -HEX_THRESHOLD) 51 SStream_concat(O, "-0x%"PRIx64, -Disp); 52 else 53 SStream_concat(O, "-%"PRIu64, -Disp); 54 } 55 56 if (Base) { 57 SStream_concat0(O, "("); 58 if (Index) 59 SStream_concat(O, "%%%s, ", getRegisterName(Index)); 60 SStream_concat(O, "%%%s)", getRegisterName(Base)); 61 62 if (MI->csh->detail) { 63 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_MEM; 64 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].mem.base = (uint8_t)SystemZ_map_register(Base); 65 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].mem.index = (uint8_t)SystemZ_map_register(Index); 66 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].mem.disp = Disp; 67 MI->flat_insn->detail->sysz.op_count++; 68 } 69 } else if (!Index) { 70 if (MI->csh->detail) { 71 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM; 72 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = Disp; 73 MI->flat_insn->detail->sysz.op_count++; 74 } 75 } 76 } 77 78 static void _printOperand(MCInst *MI, MCOperand *MO, SStream *O) 79 { 80 if (MCOperand_isReg(MO)) { 81 unsigned reg; 82 83 reg = MCOperand_getReg(MO); 84 SStream_concat(O, "%%%s", getRegisterName(reg)); 85 reg = SystemZ_map_register(reg); 86 87 if (MI->csh->detail) { 88 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_REG; 89 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].reg = reg; 90 MI->flat_insn->detail->sysz.op_count++; 91 } 92 } else if (MCOperand_isImm(MO)) { 93 int64_t Imm = MCOperand_getImm(MO); 94 95 if (Imm >= 0) { 96 if (Imm > HEX_THRESHOLD) 97 SStream_concat(O, "0x%"PRIx64, Imm); 98 else 99 SStream_concat(O, "%"PRIu64, Imm); 100 } else { 101 if (Imm < -HEX_THRESHOLD) 102 SStream_concat(O, "-0x%"PRIx64, -Imm); 103 else 104 SStream_concat(O, "-%"PRIu64, -Imm); 105 } 106 107 if (MI->csh->detail) { 108 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM; 109 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = Imm; 110 MI->flat_insn->detail->sysz.op_count++; 111 } 112 } 113 } 114 115 static void printU4ImmOperand(MCInst *MI, int OpNum, SStream *O) 116 { 117 int64_t Value = MCOperand_getImm(MCInst_getOperand(MI, OpNum)); 118 // assert(isUInt<4>(Value) && "Invalid u4imm argument"); 119 if (Value >= 0) { 120 if (Value > HEX_THRESHOLD) 121 SStream_concat(O, "0x%"PRIx64, Value); 122 else 123 SStream_concat(O, "%"PRIu64, Value); 124 } else { 125 if (Value < -HEX_THRESHOLD) 126 SStream_concat(O, "-0x%"PRIx64, -Value); 127 else 128 SStream_concat(O, "-%"PRIu64, -Value); 129 } 130 131 if (MI->csh->detail) { 132 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM; 133 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = Value; 134 MI->flat_insn->detail->sysz.op_count++; 135 } 136 } 137 138 static void printU6ImmOperand(MCInst *MI, int OpNum, SStream *O) 139 { 140 uint32_t Value = (uint32_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum)); 141 // assert(isUInt<6>(Value) && "Invalid u6imm argument"); 142 143 if (Value > HEX_THRESHOLD) 144 SStream_concat(O, "0x%x", Value); 145 else 146 SStream_concat(O, "%u", Value); 147 148 if (MI->csh->detail) { 149 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM; 150 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = (int64_t)Value; 151 MI->flat_insn->detail->sysz.op_count++; 152 } 153 } 154 155 static void printS8ImmOperand(MCInst *MI, int OpNum, SStream *O) 156 { 157 int8_t Value = (int8_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum)); 158 // assert(isInt<8>(Value) && "Invalid s8imm argument"); 159 160 if (Value >= 0) { 161 if (Value > HEX_THRESHOLD) 162 SStream_concat(O, "0x%x", Value); 163 else 164 SStream_concat(O, "%u", Value); 165 } else { 166 if (Value < -HEX_THRESHOLD) 167 SStream_concat(O, "-0x%x", -Value); 168 else 169 SStream_concat(O, "-%u", -Value); 170 } 171 172 if (MI->csh->detail) { 173 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM; 174 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = (int64_t)Value; 175 MI->flat_insn->detail->sysz.op_count++; 176 } 177 } 178 179 static void printU8ImmOperand(MCInst *MI, int OpNum, SStream *O) 180 { 181 uint8_t Value = (uint8_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum)); 182 // assert(isUInt<8>(Value) && "Invalid u8imm argument"); 183 184 if (Value > HEX_THRESHOLD) 185 SStream_concat(O, "0x%x", Value); 186 else 187 SStream_concat(O, "%u", Value); 188 189 if (MI->csh->detail) { 190 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM; 191 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = (int64_t)Value; 192 MI->flat_insn->detail->sysz.op_count++; 193 } 194 } 195 196 static void printS16ImmOperand(MCInst *MI, int OpNum, SStream *O) 197 { 198 int16_t Value = (int16_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum)); 199 // assert(isInt<16>(Value) && "Invalid s16imm argument"); 200 201 if (Value >= 0) { 202 if (Value > HEX_THRESHOLD) 203 SStream_concat(O, "0x%x", Value); 204 else 205 SStream_concat(O, "%u", Value); 206 } else { 207 if (Value < -HEX_THRESHOLD) 208 SStream_concat(O, "-0x%x", -Value); 209 else 210 SStream_concat(O, "-%u", -Value); 211 } 212 213 if (MI->csh->detail) { 214 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM; 215 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = (int64_t)Value; 216 MI->flat_insn->detail->sysz.op_count++; 217 } 218 } 219 220 static void printU16ImmOperand(MCInst *MI, int OpNum, SStream *O) 221 { 222 uint16_t Value = (uint16_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum)); 223 // assert(isUInt<16>(Value) && "Invalid u16imm argument"); 224 225 if (Value > HEX_THRESHOLD) 226 SStream_concat(O, "0x%x", Value); 227 else 228 SStream_concat(O, "%u", Value); 229 230 if (MI->csh->detail) { 231 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM; 232 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = (int64_t)Value; 233 MI->flat_insn->detail->sysz.op_count++; 234 } 235 } 236 237 static void printS32ImmOperand(MCInst *MI, int OpNum, SStream *O) 238 { 239 int32_t Value = (int32_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum)); 240 // assert(isInt<32>(Value) && "Invalid s32imm argument"); 241 242 if (Value >= 0) { 243 if (Value > HEX_THRESHOLD) 244 SStream_concat(O, "0x%x", Value); 245 else 246 SStream_concat(O, "%u", Value); 247 } else { 248 if (Value < -HEX_THRESHOLD) 249 SStream_concat(O, "-0x%x", -Value); 250 else 251 SStream_concat(O, "-%u", -Value); 252 } 253 254 if (MI->csh->detail) { 255 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM; 256 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = (int64_t)Value; 257 MI->flat_insn->detail->sysz.op_count++; 258 } 259 } 260 261 static void printU32ImmOperand(MCInst *MI, int OpNum, SStream *O) 262 { 263 uint32_t Value = (uint32_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum)); 264 // assert(isUInt<32>(Value) && "Invalid u32imm argument"); 265 266 if (Value > HEX_THRESHOLD) 267 SStream_concat(O, "0x%x", Value); 268 else 269 SStream_concat(O, "%u", Value); 270 271 if (MI->csh->detail) { 272 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM; 273 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = (int64_t)Value; 274 MI->flat_insn->detail->sysz.op_count++; 275 } 276 } 277 278 static void printAccessRegOperand(MCInst *MI, int OpNum, SStream *O) 279 { 280 int64_t Value = MCOperand_getImm(MCInst_getOperand(MI, OpNum)); 281 // assert(Value < 16 && "Invalid access register number"); 282 SStream_concat(O, "%%a%u", (unsigned int)Value); 283 284 if (MI->csh->detail) { 285 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_ACREG; 286 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].reg = (unsigned int)Value; 287 MI->flat_insn->detail->sysz.op_count++; 288 } 289 } 290 291 static void printPCRelOperand(MCInst *MI, int OpNum, SStream *O) 292 { 293 MCOperand *MO = MCInst_getOperand(MI, OpNum); 294 int32_t imm; 295 296 if (MCOperand_isImm(MO)) { 297 imm = (int32_t)MCOperand_getImm(MO); 298 if (imm >= 0) { 299 if (imm > HEX_THRESHOLD) 300 SStream_concat(O, "0x%x", imm); 301 else 302 SStream_concat(O, "%u", imm); 303 } else { 304 if (imm < -HEX_THRESHOLD) 305 SStream_concat(O, "-0x%x", -imm); 306 else 307 SStream_concat(O, "-%u", -imm); 308 } 309 310 if (MI->csh->detail) { 311 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM; 312 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = (int64_t)imm; 313 MI->flat_insn->detail->sysz.op_count++; 314 } 315 } 316 } 317 318 static void printOperand(MCInst *MI, int OpNum, SStream *O) 319 { 320 _printOperand(MI, MCInst_getOperand(MI, OpNum), O); 321 } 322 323 static void printBDAddrOperand(MCInst *MI, int OpNum, SStream *O) 324 { 325 printAddress(MI, MCOperand_getReg(MCInst_getOperand(MI, OpNum)), 326 MCOperand_getImm(MCInst_getOperand(MI, OpNum + 1)), 0, O); 327 } 328 329 static void printBDXAddrOperand(MCInst *MI, int OpNum, SStream *O) 330 { 331 printAddress(MI, MCOperand_getReg(MCInst_getOperand(MI, OpNum)), 332 MCOperand_getImm(MCInst_getOperand(MI, OpNum + 1)), 333 MCOperand_getReg(MCInst_getOperand(MI, OpNum + 2)), O); 334 } 335 336 static void printBDLAddrOperand(MCInst *MI, int OpNum, SStream *O) 337 { 338 unsigned Base = MCOperand_getReg(MCInst_getOperand(MI, OpNum)); 339 uint64_t Disp = (uint64_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum + 1)); 340 uint64_t Length = (uint64_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum + 2)); 341 342 if (Disp > HEX_THRESHOLD) 343 SStream_concat(O, "0x%"PRIx64, Disp); 344 else 345 SStream_concat(O, "%"PRIu64, Disp); 346 347 if (Length > HEX_THRESHOLD) 348 SStream_concat(O, "(0x%"PRIx64, Length); 349 else 350 SStream_concat(O, "(%"PRIu64, Length); 351 352 if (Base) 353 SStream_concat(O, ", %%%s", getRegisterName(Base)); 354 SStream_concat0(O, ")"); 355 356 if (MI->csh->detail) { 357 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_MEM; 358 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].mem.base = (uint8_t)SystemZ_map_register(Base); 359 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].mem.length = Length; 360 MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].mem.disp = (int64_t)Disp; 361 MI->flat_insn->detail->sysz.op_count++; 362 } 363 } 364 365 static void printCond4Operand(MCInst *MI, int OpNum, SStream *O) 366 { 367 static char *const CondNames[] = { 368 "o", "h", "nle", "l", "nhe", "lh", "ne", 369 "e", "nlh", "he", "nl", "le", "nh", "no" 370 }; 371 372 uint64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, OpNum)); 373 // assert(Imm > 0 && Imm < 15 && "Invalid condition"); 374 SStream_concat0(O, CondNames[Imm - 1]); 375 376 if (MI->csh->detail) 377 MI->flat_insn->detail->sysz.cc = (sysz_cc)Imm; 378 } 379 380 #define PRINT_ALIAS_INSTR 381 #include "SystemZGenAsmWriter.inc" 382 383 void SystemZ_printInst(MCInst *MI, SStream *O, void *Info) 384 { 385 printInstruction(MI, O, Info); 386 } 387 388 #endif 389