Home | History | Annotate | Download | only in SystemZ
      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