Home | History | Annotate | Download | only in XCore
      1 //===-- XCoreInstPrinter.cpp - Convert XCore 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 XCore 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_XCORE
     18 
     19 #if defined (WIN32) || defined (WIN64) || defined (_WIN32) || defined (_WIN64)
     20 #pragma warning(disable : 4996)			// disable MSVC's warning on strcpy()
     21 #pragma warning(disable : 28719)		// disable MSVC's warning on strcpy()
     22 #endif
     23 
     24 #include <stdio.h>
     25 #include <stdlib.h>
     26 #include <string.h>
     27 #include <platform.h>
     28 
     29 #include "XCoreInstPrinter.h"
     30 #include "../../MCInst.h"
     31 #include "../../utils.h"
     32 #include "../../SStream.h"
     33 #include "../../MCRegisterInfo.h"
     34 #include "../../MathExtras.h"
     35 #include "XCoreMapping.h"
     36 
     37 static char *getRegisterName(unsigned RegNo);
     38 
     39 void XCore_post_printer(csh ud, cs_insn *insn, char *insn_asm, MCInst *mci)
     40 {
     41 	/*
     42 	   if (((cs_struct *)ud)->detail != CS_OPT_ON)
     43 	   return;
     44 	 */
     45 }
     46 
     47 // stw sed, sp[3]
     48 void XCore_insn_extract(MCInst *MI, const char *code)
     49 {
     50 	int id;
     51 	char *p, *p2;
     52 	char tmp[128];
     53 
     54 	strcpy(tmp, code); // safe because code is way shorter than 128 bytes
     55 
     56 	// find the first space
     57 	p = strchr(tmp, ' ');
     58 	if (p) {
     59 		p++;
     60 		// find the next ','
     61 		p2 = strchr(p, ',');
     62 		if (p2) {
     63 			*p2 = '\0';
     64 			id = XCore_reg_id(p);
     65 			if (id) {
     66 				// register
     67 				if (MI->csh->detail) {
     68 					MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_REG;
     69 					MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].reg = id;
     70 					MI->flat_insn->detail->xcore.op_count++;
     71 				}
     72 			}
     73 			// next should be register, or memory?
     74 			// skip space
     75 			p2++;
     76 			while(*p2 && *p2 == ' ')
     77 				p2++;
     78 			if (*p2) {
     79 				// find '['
     80 				p = p2;
     81 				while(*p && *p != '[')
     82 					p++;
     83 				if (*p) {
     84 					// this is '['
     85 					*p = '\0';
     86 					id = XCore_reg_id(p2);
     87 					if (id) {
     88 						// base register
     89 						if (MI->csh->detail) {
     90 							MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_MEM;
     91 							MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = (uint8_t)id;
     92 							MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = XCORE_REG_INVALID;
     93 							MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = 0;
     94 							MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.direct = 1;
     95 						}
     96 
     97 						p++;
     98 						p2 = p;
     99 						// until ']'
    100 						while(*p && *p != ']')
    101 							p++;
    102 						if (*p) {
    103 							*p = '\0';
    104 							// p2 is either index, or disp
    105 							id = XCore_reg_id(p2);
    106 							if (id) {
    107 								// index register
    108 								if (MI->csh->detail) {
    109 									MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = (uint8_t)id;
    110 								}
    111 							} else {
    112 								// a number means disp
    113 								if (MI->csh->detail) {
    114 									MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = atoi(p2);
    115 								}
    116 							}
    117 						}
    118 
    119 						if (MI->csh->detail) {
    120 							MI->flat_insn->detail->xcore.op_count++;
    121 						}
    122 					}
    123 				} else {
    124 					// a register?
    125 					id = XCore_reg_id(p2);
    126 					if (id) {
    127 						// register
    128 						if (MI->csh->detail) {
    129 							MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_REG;
    130 							MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].reg = id;
    131 							MI->flat_insn->detail->xcore.op_count++;
    132 						}
    133 					}
    134 				}
    135 			}
    136 		} else {
    137 			id = XCore_reg_id(p);
    138 			if (id) {
    139 				// register
    140 				if (MI->csh->detail) {
    141 					MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_REG;
    142 					MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].reg = id;
    143 					MI->flat_insn->detail->xcore.op_count++;
    144 				}
    145 			}
    146 		}
    147 	}
    148 }
    149 
    150 static void set_mem_access(MCInst *MI, bool status, int reg)
    151 {
    152 	if (MI->csh->detail != CS_OPT_ON)
    153 		return;
    154 
    155 	MI->csh->doing_mem = status;
    156 	if (status) {
    157 		if (reg != 0xffff && reg != -0xffff) {
    158 			MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_MEM;
    159 			if (reg) {
    160 				MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = (uint8_t)reg;
    161 			} else {
    162 				MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = XCORE_REG_INVALID;
    163 			}
    164 			MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = XCORE_REG_INVALID;
    165 			MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = 0;
    166 			MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.direct = 1;
    167 		} else {
    168 			// the last op should be the memory base
    169 			MI->flat_insn->detail->xcore.op_count--;
    170 			MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_MEM;
    171 			MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = (uint8_t)MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].reg;
    172 			MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = XCORE_REG_INVALID;
    173 			MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = 0;
    174 			if (reg > 0)
    175 				MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.direct = 1;
    176 			else
    177 				MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.direct = -1;
    178 		}
    179 	} else {
    180 		if (reg) {
    181 			MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = (uint8_t)reg;
    182 			// done, create the next operand slot
    183 			MI->flat_insn->detail->xcore.op_count++;
    184 		}
    185 	}
    186 }
    187 
    188 static void _printOperand(MCInst *MI, MCOperand *MO, SStream *O)
    189 {
    190 	if (MCOperand_isReg(MO)) {
    191 		unsigned reg;
    192 
    193 		reg = MCOperand_getReg(MO);
    194 		SStream_concat0(O, getRegisterName(reg));
    195 
    196 		if (MI->csh->detail) {
    197 			if (MI->csh->doing_mem) {
    198 				if (MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base == ARM_REG_INVALID)
    199 					MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = (uint8_t)reg;
    200 				else
    201 					MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = (uint8_t)reg;
    202 			} else {
    203 				MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_REG;
    204 				MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].reg = reg;
    205 				MI->flat_insn->detail->xcore.op_count++;
    206 			}
    207 		}
    208 	} else if (MCOperand_isImm(MO)) {
    209 		int32_t Imm = (int32_t)MCOperand_getImm(MO);
    210 
    211 		if (Imm >= 0) {
    212 			if (Imm > HEX_THRESHOLD)
    213 				SStream_concat(O, "0x%x", Imm);
    214 			else
    215 				SStream_concat(O, "%u", Imm);
    216 		} else {
    217 			if (Imm < -HEX_THRESHOLD)
    218 				SStream_concat(O, "-0x%x", -Imm);
    219 			else
    220 				SStream_concat(O, "-%u", -Imm);
    221 		}
    222 
    223 		if (MI->csh->detail) {
    224 			if (MI->csh->doing_mem) {
    225 				MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = Imm;
    226 			} else {
    227 				MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_IMM;
    228 				MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].imm = Imm;
    229 				MI->flat_insn->detail->xcore.op_count++;
    230 			}
    231 		}
    232 	}
    233 }
    234 
    235 static void printOperand(MCInst *MI, int OpNum, SStream *O)
    236 {
    237 	if (OpNum >= MI->size)
    238 		return;
    239 
    240 	_printOperand(MI, MCInst_getOperand(MI, OpNum), O);
    241 }
    242 
    243 static void printInlineJT(MCInst *MI, int OpNum, SStream *O)
    244 {
    245 }
    246 
    247 static void printInlineJT32(MCInst *MI, int OpNum, SStream *O)
    248 {
    249 }
    250 
    251 #define PRINT_ALIAS_INSTR
    252 #include "XCoreGenAsmWriter.inc"
    253 
    254 void XCore_printInst(MCInst *MI, SStream *O, void *Info)
    255 {
    256 	printInstruction(MI, O, Info);
    257 	set_mem_access(MI, false, 0);
    258 }
    259 
    260 #endif
    261