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@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 32static const char *getRegisterName(unsigned RegNo); 33 34void 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 42static 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 78static 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 115static 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 138static 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 155static 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 179static 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 196static 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 220static 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 237static 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 261static 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 278static 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 291static 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 318static void printOperand(MCInst *MI, int OpNum, SStream *O) 319{ 320 _printOperand(MI, MCInst_getOperand(MI, OpNum), O); 321} 322 323static 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 329static 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 336static 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 365static 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 383void SystemZ_printInst(MCInst *MI, SStream *O, void *Info) 384{ 385 printInstruction(MI, O, Info); 386} 387 388#endif 389