/src/capstonenext/arch/Sparc/SparcMapping.c
Line  | Count  | Source  | 
1  |  | /* Capstone Disassembly Engine */  | 
2  |  | /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */  | 
3  |  |  | 
4  |  | #ifdef CAPSTONE_HAS_SPARC  | 
5  |  |  | 
6  |  | #include <stdio.h> // debug  | 
7  |  | #include <string.h>  | 
8  |  |  | 
9  |  | #include "../../Mapping.h"  | 
10  |  | #include "../../utils.h"  | 
11  |  | #include "../../cs_simple_types.h"  | 
12  |  |  | 
13  |  | #include "SparcMapping.h"  | 
14  |  |  | 
15  |  | void Sparc_init_cs_detail(MCInst *MI)  | 
16  | 44.2k  | { | 
17  | 44.2k  |   if (!detail_is_set(MI)) { | 
18  | 0  |     return;  | 
19  | 0  |   }  | 
20  | 44.2k  |   memset(get_detail(MI), 0,  | 
21  | 44.2k  |          offsetof(cs_detail, sparc) + sizeof(cs_sparc));  | 
22  | 44.2k  |   Sparc_get_detail(MI)->cc = SPARC_CC_UNDEF;  | 
23  | 44.2k  |   Sparc_get_detail(MI)->cc_field = SPARC_CC_FIELD_NONE;  | 
24  | 44.2k  | }  | 
25  |  |  | 
26  |  | const insn_map sparc_insns[] = { | 
27  |  | #include "SparcGenCSMappingInsn.inc"  | 
28  |  | };  | 
29  |  |  | 
30  |  | void Sparc_set_instr_map_data(MCInst *MI)  | 
31  | 44.2k  | { | 
32  | 44.2k  |   map_cs_id(MI, sparc_insns, ARR_SIZE(sparc_insns));  | 
33  | 44.2k  |   map_implicit_reads(MI, sparc_insns);  | 
34  | 44.2k  |   map_implicit_writes(MI, sparc_insns);  | 
35  | 44.2k  |   map_groups(MI, sparc_insns);  | 
36  | 44.2k  |   const sparc_suppl_info *suppl_info =  | 
37  | 44.2k  |     map_get_suppl_info(MI, sparc_insns);  | 
38  | 44.2k  |   if (suppl_info) { | 
39  | 44.2k  |     Sparc_get_detail(MI)->format = suppl_info->form;  | 
40  | 44.2k  |   }  | 
41  | 44.2k  | }  | 
42  |  |  | 
43  |  | /// Adds details which are not defined consistently as LLVM operands like  | 
44  |  | /// condition codes for alias instructions or branch hint bits.  | 
45  |  | static void Sparc_add_bit_details(MCInst *MI, const uint8_t *Bytes,  | 
46  |  |           size_t BytesLen)  | 
47  | 44.2k  | { | 
48  | 44.2k  |   if (!Bytes || BytesLen < 4 || !detail_is_set(MI)) { | 
49  | 471  |     return;  | 
50  | 471  |   }  | 
51  | 43.8k  |   uint32_t insn = readBytes32(MI, Bytes);  | 
52  |  |  | 
53  |  |   // CC field  | 
54  | 43.8k  |   cs_sparc *detail = Sparc_get_detail(MI);  | 
55  | 43.8k  |   switch (detail->format) { | 
56  | 33.5k  |   default:  | 
57  | 33.5k  |     break;  | 
58  | 33.5k  |   case SPARC_INSN_FORM_F2_2: { | 
59  |  |     // This format is used either by B or FB instructions.  | 
60  |  |     // The op2 == 6 for the FB and 2 for B.  | 
61  |  |     // This is the only indicator we have here to determine which CC field is used  | 
62  |  |     // if we don't want big switch cases.  | 
63  |  |     //  | 
64  |  |     // See: Opcode Maps - Table 39 - Sparc V9 ISA  | 
65  | 3.50k  |     size_t op2 = get_insn_field_r(insn, 22, 24);  | 
66  | 3.50k  |     detail->cc_field = op2 == 6 ? SPARC_CC_FIELD_FCC0 :  | 
67  | 3.50k  |                 SPARC_CC_FIELD_ICC;  | 
68  | 3.50k  |     break;  | 
69  | 0  |   }  | 
70  | 3.23k  |   case SPARC_INSN_FORM_F2_3:  | 
71  | 3.23k  |     detail->cc_field = get_insn_field_r(insn, 20, 21);  | 
72  | 3.23k  |     if (get_insn_field_r(insn, 22, 24) == 1) { | 
73  |  |       // BPcc and FBPcc encode their fields in two bits.  | 
74  |  |       // BPcc needs the upper bit set to match our CC field enum.  | 
75  | 1.71k  |       detail->cc_field |= 0x4;  | 
76  | 1.71k  |     }  | 
77  | 3.23k  |     break;  | 
78  | 317  |   case SPARC_INSN_FORM_TRAPSP:  | 
79  | 317  |     detail->cc_field = 0x4 | get_insn_field_r(insn, 11, 12);  | 
80  | 317  |     break;  | 
81  | 1.04k  |   case SPARC_INSN_FORM_F4_1:  | 
82  | 1.83k  |   case SPARC_INSN_FORM_F4_2:  | 
83  | 1.83k  |     detail->cc_field = get_insn_field_r(insn, 11, 12);  | 
84  | 1.83k  |     detail->cc_field |= get_insn_field_r(insn, 18, 18) << 2;  | 
85  | 1.83k  |     break;  | 
86  | 1.37k  |   case SPARC_INSN_FORM_F4_3:  | 
87  | 1.37k  |     detail->cc_field = get_insn_field_r(insn, 11, 13);  | 
88  | 1.37k  |     break;  | 
89  | 43.8k  |   }  | 
90  |  |  | 
91  |  |   // Condition codes  | 
92  | 43.8k  |   switch (detail->format) { | 
93  | 28.4k  |   default:  | 
94  | 28.4k  |     break;  | 
95  | 28.4k  |   case SPARC_INSN_FORM_F2_1:  | 
96  | 7.14k  |   case SPARC_INSN_FORM_F2_2:  | 
97  | 10.3k  |   case SPARC_INSN_FORM_F2_3:  | 
98  | 10.6k  |   case SPARC_INSN_FORM_TRAPSP: { | 
99  |  |     // cond  | 
100  |  |     // Alias instructions don't define the conditions as operands.  | 
101  |  |     // We need to add them here to the details again.  | 
102  | 10.6k  |     sparc_cc cc = get_insn_field_r(insn, 25, 28);  | 
103  | 10.6k  |     if (MCInst_getOpcode(MI) == Sparc_CBCOND ||  | 
104  | 9.82k  |         MCInst_getOpcode(MI) == Sparc_CBCONDA) { | 
105  | 1.19k  |       cc += SPARC_CC_CPCC_BEGIN;  | 
106  | 1.19k  |     }  | 
107  | 10.6k  |     detail->cc = cc;  | 
108  | 10.6k  |     break;  | 
109  | 10.3k  |   }  | 
110  | 1.04k  |   case SPARC_INSN_FORM_F4_1:  | 
111  | 1.83k  |   case SPARC_INSN_FORM_F4_2:  | 
112  | 3.20k  |   case SPARC_INSN_FORM_F4_3: { | 
113  | 3.20k  |     sparc_cc cc = get_insn_field_r(insn, 14, 17);  | 
114  | 3.20k  |     detail->cc = cc;  | 
115  | 3.20k  |     break;  | 
116  | 1.83k  |   }  | 
117  | 1.11k  |   case SPARC_INSN_FORM_F2_4: { | 
118  |  |     // cond  | 
119  |  |     // Alias instructions don't define the conditions as operands.  | 
120  |  |     // We need to add them here to the details again.  | 
121  | 1.11k  |     sparc_cc rcc = get_insn_field_r(insn, 25, 27);  | 
122  | 1.11k  |     detail->cc = rcc + SPARC_CC_REG_BEGIN;  | 
123  | 1.11k  |     break;  | 
124  | 1.83k  |   }  | 
125  | 242  |   case SPARC_INSN_FORM_F4_4R:  | 
126  | 332  |   case SPARC_INSN_FORM_F4_4I: { | 
127  | 332  |     sparc_cc rcc = get_insn_field_r(insn, 10, 12);  | 
128  | 332  |     detail->cc = rcc + SPARC_CC_REG_BEGIN;  | 
129  | 332  |     break;  | 
130  | 242  |   }  | 
131  | 43.8k  |   }  | 
132  | 43.8k  |   switch (detail->cc_field) { | 
133  | 33.5k  |   default:  | 
134  | 37.0k  |   case SPARC_CC_FIELD_ICC:  | 
135  | 38.4k  |   case SPARC_CC_FIELD_XCC:  | 
136  | 38.4k  |     break;  | 
137  | 3.56k  |   case SPARC_CC_FIELD_FCC0:  | 
138  | 4.54k  |   case SPARC_CC_FIELD_FCC1:  | 
139  | 4.94k  |   case SPARC_CC_FIELD_FCC2:  | 
140  | 5.39k  |   case SPARC_CC_FIELD_FCC3:  | 
141  | 5.39k  |     detail->cc += SPARC_CC_FCC_BEGIN;  | 
142  | 5.39k  |     break;  | 
143  | 43.8k  |   }  | 
144  |  |  | 
145  |  |   // Hints  | 
146  | 43.8k  |   switch (detail->format) { | 
147  | 35.9k  |   default:  | 
148  | 35.9k  |     break;  | 
149  | 35.9k  |   case SPARC_INSN_FORM_F2_2:  | 
150  | 3.50k  |     detail->hint = get_insn_field_r(insn, 29, 29);  | 
151  | 3.50k  |     break;  | 
152  | 3.23k  |   case SPARC_INSN_FORM_F2_3:  | 
153  | 4.35k  |   case SPARC_INSN_FORM_F2_4:  | 
154  | 4.35k  |     detail->hint = get_insn_field_r(insn, 29, 29);  | 
155  | 4.35k  |     detail->hint |= get_insn_field_r(insn, 19, 19) == 0 ?  | 
156  | 1.17k  |           SPARC_HINT_PN :  | 
157  | 4.35k  |           SPARC_HINT_PT;  | 
158  | 4.35k  |     break;  | 
159  | 43.8k  |   }  | 
160  | 43.8k  | }  | 
161  |  |  | 
162  |  | bool Sparc_getInstruction(csh handle, const uint8_t *code, size_t code_len,  | 
163  |  |         MCInst *instr, uint16_t *size, uint64_t address,  | 
164  |  |         void *info)  | 
165  | 44.2k  | { | 
166  | 44.2k  |   Sparc_init_cs_detail(instr);  | 
167  | 44.2k  |   bool Result = Sparc_LLVM_getInstruction(handle, code, code_len, instr,  | 
168  | 44.2k  |             size, address,  | 
169  | 44.2k  |             info) != MCDisassembler_Fail;  | 
170  | 44.2k  |   Sparc_set_instr_map_data(instr);  | 
171  |  |  | 
172  | 44.2k  |   Sparc_add_bit_details(instr, code, code_len);  | 
173  | 44.2k  |   return Result;  | 
174  | 44.2k  | }  | 
175  |  |  | 
176  |  | void Sparc_init_mri(MCRegisterInfo *MRI)  | 
177  | 1.48k  | { | 
178  | 1.48k  |   MCRegisterInfo_InitMCRegisterInfo(  | 
179  | 1.48k  |     MRI, SparcRegDesc, sizeof(SparcRegDesc), 0, 0,  | 
180  | 1.48k  |     SparcMCRegisterClasses, ARR_SIZE(SparcMCRegisterClasses), 0, 0,  | 
181  | 1.48k  |     SparcRegDiffLists, 0, SparcSubRegIdxLists,  | 
182  | 1.48k  |     ARR_SIZE(SparcSubRegIdxLists), 0);  | 
183  | 1.48k  | }  | 
184  |  |  | 
185  |  | const char *Sparc_reg_name(csh handle, unsigned int reg)  | 
186  | 19.5k  | { | 
187  | 19.5k  |   int syntax_opt = ((cs_struct *)(uintptr_t)handle)->syntax;  | 
188  |  |  | 
189  | 19.5k  |   if (syntax_opt & CS_OPT_SYNTAX_NOREGNAME) { | 
190  | 0  |     return Sparc_LLVM_getRegisterName(reg, Sparc_NoRegAltName);  | 
191  | 0  |   }  | 
192  | 19.5k  |   return Sparc_LLVM_getRegisterName(reg, Sparc_RegNamesStateReg);  | 
193  | 19.5k  | }  | 
194  |  |  | 
195  |  | void Sparc_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)  | 
196  | 43.5k  | { | 
197  |  |   // Not used by Sparc. Information is set after disassembly.  | 
198  | 43.5k  | }  | 
199  |  |  | 
200  |  | static const char *const insn_name_maps[] = { | 
201  |  | #include "SparcGenCSMappingInsnName.inc"  | 
202  |  | };  | 
203  |  |  | 
204  |  | #ifndef CAPSTONE_DIET  | 
205  |  | static const name_map insn_alias_mnem_map[] = { | 
206  |  | #include "SparcGenCSAliasMnemMap.inc"  | 
207  |  |   { SPARC_INS_ALIAS_CALL, "call" }, | 
208  |  |   { SPARC_INS_ALIAS_END, NULL }, | 
209  |  | };  | 
210  |  | #endif  | 
211  |  |  | 
212  |  | static void insert_op(MCInst *MI, unsigned index, cs_sparc_op op)  | 
213  | 1.61k  | { | 
214  | 1.61k  |   if (!detail_is_set(MI)) { | 
215  | 0  |     return;  | 
216  | 0  |   }  | 
217  | 1.61k  |   Sparc_check_safe_inc(MI);  | 
218  |  |  | 
219  | 1.61k  |   cs_sparc_op *ops = Sparc_get_detail(MI)->operands;  | 
220  | 1.61k  |   int i = Sparc_get_detail(MI)->op_count;  | 
221  | 1.61k  |   if (index == -1) { | 
222  | 1.40k  |     ops[i] = op;  | 
223  | 1.40k  |     Sparc_inc_op_count(MI);  | 
224  | 1.40k  |     return;  | 
225  | 1.40k  |   }  | 
226  | 430  |   for (; i > 0 && i > index; --i) { | 
227  | 215  |     ops[i] = ops[i - 1];  | 
228  | 215  |   }  | 
229  | 215  |   ops[index] = op;  | 
230  | 215  |   Sparc_inc_op_count(MI);  | 
231  | 215  | }  | 
232  |  |  | 
233  |  | /// Inserts a register to the detail operands at @index.  | 
234  |  | /// Already present operands are moved.  | 
235  |  | /// If @index is -1 the operand is appended.  | 
236  |  | static void Sparc_insert_detail_op_reg_at(MCInst *MI, unsigned index,  | 
237  |  |             sparc_reg Reg, cs_ac_type access)  | 
238  | 1.61k  | { | 
239  | 1.61k  |   if (!detail_is_set(MI))  | 
240  | 0  |     return;  | 
241  |  |  | 
242  | 1.61k  |   cs_sparc_op op = { 0 }; | 
243  | 1.61k  |   op.type = SPARC_OP_REG;  | 
244  | 1.61k  |   op.reg = Reg;  | 
245  | 1.61k  |   op.access = access;  | 
246  | 1.61k  |   insert_op(MI, index, op);  | 
247  | 1.61k  | }  | 
248  |  |  | 
249  |  | static void Sparc_correct_details(MCInst *MI)  | 
250  | 43.5k  | { | 
251  | 43.5k  |   if (!detail_is_set(MI)) { | 
252  | 0  |     return;  | 
253  | 0  |   }  | 
254  | 43.5k  |   switch (MCInst_getOpcode(MI)) { | 
255  | 41.2k  |   default:  | 
256  | 41.2k  |     return;  | 
257  | 41.2k  |   case Sparc_LDSTUBri:  | 
258  | 271  |   case Sparc_LDSTUBrr:  | 
259  | 479  |   case Sparc_LDSTUBAri:  | 
260  | 689  |   case Sparc_LDSTUBArr:  | 
261  |  |     // The memory gets written back with ones  | 
262  |  |     // but there is not write back memory operand defined  | 
263  |  |     // (if even possible).  | 
264  | 689  |     Sparc_get_detail(MI)->operands[0].access = CS_AC_READ_WRITE;  | 
265  | 689  |     break;  | 
266  | 75  |   case Sparc_RDPSR:  | 
267  | 75  |     Sparc_insert_detail_op_reg_at(MI, 0, SPARC_REG_PSR, CS_AC_READ);  | 
268  | 75  |     break;  | 
269  | 76  |   case Sparc_PWRPSRri:  | 
270  | 148  |   case Sparc_PWRPSRrr:  | 
271  | 265  |   case Sparc_WRPSRri:  | 
272  | 650  |   case Sparc_WRPSRrr:  | 
273  | 650  |     Sparc_insert_detail_op_reg_at(MI, -1, SPARC_REG_PSR,  | 
274  | 650  |                 CS_AC_WRITE);  | 
275  | 650  |     break;  | 
276  | 74  |   case Sparc_RDWIM:  | 
277  | 74  |     Sparc_insert_detail_op_reg_at(MI, 0, SPARC_REG_WIM, CS_AC_READ);  | 
278  | 74  |     break;  | 
279  | 69  |   case Sparc_WRWIMri:  | 
280  | 337  |   case Sparc_WRWIMrr:  | 
281  | 337  |     Sparc_insert_detail_op_reg_at(MI, -1, SPARC_REG_WIM,  | 
282  | 337  |                 CS_AC_WRITE);  | 
283  | 337  |     break;  | 
284  | 66  |   case Sparc_RDTBR:  | 
285  | 66  |     Sparc_insert_detail_op_reg_at(MI, 0, SPARC_REG_TBR, CS_AC_READ);  | 
286  | 66  |     break;  | 
287  | 200  |   case Sparc_WRTBRri:  | 
288  | 417  |   case Sparc_WRTBRrr:  | 
289  | 417  |     Sparc_insert_detail_op_reg_at(MI, -1, SPARC_REG_TBR,  | 
290  | 417  |                 CS_AC_WRITE);  | 
291  | 417  |     break;  | 
292  | 43.5k  |   }  | 
293  | 43.5k  | }  | 
294  |  |  | 
295  |  | void Sparc_printer(MCInst *MI, SStream *O, void * /* MCRegisterInfo* */ info)  | 
296  | 43.5k  | { | 
297  | 43.5k  |   MCRegisterInfo *MRI = (MCRegisterInfo *)info;  | 
298  | 43.5k  |   MI->MRI = MRI;  | 
299  | 43.5k  |   MI->flat_insn->usesAliasDetails = map_use_alias_details(MI);  | 
300  | 43.5k  |   Sparc_LLVM_printInst(MI, MI->address, "", O);  | 
301  |  |  | 
302  | 43.5k  | #ifndef CAPSTONE_DIET  | 
303  | 43.5k  |   map_set_alias_id(MI, O, insn_alias_mnem_map,  | 
304  | 43.5k  |        ARR_SIZE(insn_alias_mnem_map));  | 
305  | 43.5k  |   Sparc_correct_details(MI);  | 
306  | 43.5k  | #endif  | 
307  | 43.5k  | }  | 
308  |  |  | 
309  |  | const char *Sparc_insn_name(csh handle, unsigned int id)  | 
310  | 43.5k  | { | 
311  | 43.5k  | #ifndef CAPSTONE_DIET  | 
312  | 43.5k  |   if (id < SPARC_INS_ALIAS_END && id > SPARC_INS_ALIAS_BEGIN) { | 
313  | 0  |     if (id - SPARC_INS_ALIAS_BEGIN >= ARR_SIZE(insn_alias_mnem_map))  | 
314  | 0  |       return NULL;  | 
315  |  |  | 
316  | 0  |     return insn_alias_mnem_map[id - SPARC_INS_ALIAS_BEGIN - 1].name;  | 
317  | 0  |   }  | 
318  | 43.5k  |   if (id >= SPARC_INS_ENDING)  | 
319  | 0  |     return NULL;  | 
320  |  |  | 
321  | 43.5k  |   if (id < ARR_SIZE(insn_name_maps))  | 
322  | 43.5k  |     return insn_name_maps[id];  | 
323  |  |   // not found  | 
324  | 0  |   return NULL;  | 
325  |  | #else  | 
326  |  |   return NULL;  | 
327  |  | #endif  | 
328  | 43.5k  | }  | 
329  |  |  | 
330  |  | #ifndef CAPSTONE_DIET  | 
331  |  | static const name_map group_name_maps[] = { | 
332  |  |   { SPARC_GRP_INVALID, NULL }, | 
333  |  |  | 
334  |  |   { SPARC_GRP_JUMP, "jump" }, | 
335  |  |   { SPARC_GRP_CALL, "call" }, | 
336  |  |   { SPARC_GRP_RET, "return" }, | 
337  |  |   { SPARC_GRP_INT, "int" }, | 
338  |  |   { SPARC_GRP_IRET, "iret" }, | 
339  |  |   { SPARC_GRP_PRIVILEGE, "privilege" }, | 
340  |  |   { SPARC_GRP_BRANCH_RELATIVE, "branch_relative" }, | 
341  |  |  | 
342  |  | // architecture-specific groups  | 
343  |  | #include "SparcGenCSFeatureName.inc"  | 
344  |  | };  | 
345  |  | #endif  | 
346  |  |  | 
347  |  | const char *Sparc_group_name(csh handle, unsigned int id)  | 
348  | 112k  | { | 
349  | 112k  | #ifndef CAPSTONE_DIET  | 
350  | 112k  |   return id2name(group_name_maps, ARR_SIZE(group_name_maps), id);  | 
351  |  | #else  | 
352  |  |   return NULL;  | 
353  |  | #endif  | 
354  | 112k  | }  | 
355  |  |  | 
356  |  | static const map_insn_ops insn_operands[] = { | 
357  |  | #include "SparcGenCSMappingInsnOp.inc"  | 
358  |  | };  | 
359  |  |  | 
360  |  | void Sparc_set_detail_op_imm(MCInst *MI, unsigned OpNum, sparc_op_type ImmType,  | 
361  |  |            int64_t Imm)  | 
362  | 19.6k  | { | 
363  | 19.6k  |   if (!detail_is_set(MI))  | 
364  | 0  |     return;  | 
365  | 19.6k  |   CS_ASSERT_RET((map_get_op_type(MI, OpNum) & ~CS_OP_MEM) == CS_OP_IMM);  | 
366  | 19.6k  |   CS_ASSERT_RET(ImmType == SPARC_OP_IMM);  | 
367  |  |  | 
368  | 19.6k  |   Sparc_get_detail_op(MI, 0)->type = ImmType;  | 
369  | 19.6k  |   Sparc_get_detail_op(MI, 0)->imm = Imm;  | 
370  | 19.6k  |   Sparc_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);  | 
371  | 19.6k  |   Sparc_inc_op_count(MI);  | 
372  | 19.6k  | }  | 
373  |  |  | 
374  |  | void Sparc_set_detail_op_reg(MCInst *MI, unsigned OpNum, sparc_reg Reg)  | 
375  | 43.0k  | { | 
376  | 43.0k  |   if (!detail_is_set(MI))  | 
377  | 0  |     return;  | 
378  | 43.0k  |   CS_ASSERT_RET((map_get_op_type(MI, OpNum) & ~CS_OP_MEM) == CS_OP_REG);  | 
379  |  |  | 
380  | 43.0k  |   switch (Reg) { | 
381  | 40.4k  |   default:  | 
382  | 40.4k  |     Sparc_get_detail_op(MI, 0)->type = SPARC_OP_REG;  | 
383  | 40.4k  |     Sparc_get_detail_op(MI, 0)->reg = Reg;  | 
384  | 40.4k  |     Sparc_get_detail_op(MI, 0)->access =  | 
385  | 40.4k  |       map_get_op_access(MI, OpNum);  | 
386  | 40.4k  |     Sparc_inc_op_count(MI);  | 
387  | 40.4k  |     return;  | 
388  |  |   // The LLVM definition is inconsistent with the cc fields.  | 
389  |  |   // Sometimes they are encoded as register, sometimes not at all.  | 
390  |  |   // For Capstone they are always saved in the cc_field field for now.  | 
391  | 0  |   case SPARC_REG_ICC:  | 
392  | 0  |     Sparc_get_detail(MI)->cc_field = SPARC_CC_FIELD_ICC;  | 
393  | 0  |     break;  | 
394  | 209  |   case SPARC_REG_FCC0:  | 
395  | 209  |     Sparc_get_detail(MI)->cc_field = SPARC_CC_FIELD_FCC0;  | 
396  | 209  |     break;  | 
397  | 978  |   case SPARC_REG_FCC1:  | 
398  | 978  |     Sparc_get_detail(MI)->cc_field = SPARC_CC_FIELD_FCC1;  | 
399  | 978  |     break;  | 
400  | 932  |   case SPARC_REG_FCC2:  | 
401  | 932  |     Sparc_get_detail(MI)->cc_field = SPARC_CC_FIELD_FCC2;  | 
402  | 932  |     break;  | 
403  | 450  |   case SPARC_REG_FCC3:  | 
404  | 450  |     Sparc_get_detail(MI)->cc_field = SPARC_CC_FIELD_FCC3;  | 
405  | 450  |     break;  | 
406  | 43.0k  |   }  | 
407  | 43.0k  | }  | 
408  |  |  | 
409  |  | static inline bool is_single_reg_mem_case(MCInst *MI, unsigned OpNo)  | 
410  | 23.8k  | { | 
411  | 23.8k  |   if (map_get_op_type(MI, OpNo) != CS_OP_MEM_REG) { | 
412  | 6.84k  |     return false;  | 
413  | 6.84k  |   }  | 
414  | 17.0k  |   cs_sparc_op *prev_op = Sparc_get_detail_op(MI, -1);  | 
415  | 17.0k  |   if (prev_op && prev_op->type == SPARC_OP_MEM) { | 
416  | 15.6k  |     return false;  | 
417  | 15.6k  |   }  | 
418  | 1.35k  |   if (MI->size == 1) { | 
419  | 0  |     return true;  | 
420  | 1.35k  |   } else if (MI->size > OpNo + 1 &&  | 
421  | 1.04k  |        Sparc_get_detail(MI)->operands[0].type != SPARC_OP_MEM) { | 
422  |  |     // Next operand is not a memory operand (disponent or index reg).  | 
423  | 1.04k  |     return !(map_get_op_type(MI, OpNo + 1) & SPARC_OP_MEM);  | 
424  | 1.04k  |   }  | 
425  | 311  |   return false;  | 
426  | 1.35k  | }  | 
427  |  |  | 
428  |  | void Sparc_add_cs_detail_0(MCInst *MI, sparc_op_group op_group, unsigned OpNo)  | 
429  | 112k  | { | 
430  | 112k  |   if (!detail_is_set(MI) || !map_fill_detail_ops(MI))  | 
431  | 0  |     return;  | 
432  |  |  | 
433  | 112k  |   cs_op_type op_type = map_get_op_type(MI, OpNo);  | 
434  |  |  | 
435  | 112k  |   switch (op_group) { | 
436  | 0  |   default:  | 
437  | 0  |   case Sparc_OP_GROUP_GetPCX:  | 
438  | 0  |     printf("Operand group %d not handled!\n", op_group); | 
439  | 0  |     return;  | 
440  | 86.5k  |   case Sparc_OP_GROUP_Operand:  | 
441  | 86.5k  |     if (op_type & CS_OP_MEM) { | 
442  | 23.8k  |       if (is_single_reg_mem_case(MI, OpNo)) { | 
443  | 1.04k  |         Sparc_get_detail_op(MI, 0)->type = SPARC_OP_MEM;  | 
444  | 1.04k  |         Sparc_get_detail_op(MI, 0)->mem.base =  | 
445  | 1.04k  |           MCInst_getOpVal(MI, OpNo);  | 
446  | 1.04k  |         Sparc_get_detail_op(MI, 0)->access =  | 
447  | 1.04k  |           map_get_op_access(MI, OpNo);  | 
448  | 1.04k  |         Sparc_inc_op_count(MI);  | 
449  | 1.04k  |       }  | 
450  | 23.8k  |       break;  | 
451  | 23.8k  |     }  | 
452  | 62.6k  |     if (op_type == CS_OP_IMM) { | 
453  | 19.6k  |       Sparc_set_detail_op_imm(MI, OpNo, SPARC_OP_IMM,  | 
454  | 19.6k  |             MCInst_getOpVal(MI, OpNo));  | 
455  | 43.0k  |     } else if (op_type == CS_OP_REG) { | 
456  | 43.0k  |       Sparc_set_detail_op_reg(MI, OpNo,  | 
457  | 43.0k  |             MCInst_getOpVal(MI, OpNo));  | 
458  | 43.0k  |     } else { | 
459  | 0  |       CS_ASSERT_RET(0 && "Op type not handled.");  | 
460  | 0  |     }  | 
461  | 62.6k  |     Sparc_get_detail_op(MI, 0)->access =  | 
462  | 62.6k  |       map_get_op_access(MI, OpNo);  | 
463  | 62.6k  |     break;  | 
464  | 8.11k  |   case Sparc_OP_GROUP_CCOperand: { | 
465  |  |     // Handled in Sparc_add_bit_details().  | 
466  | 8.11k  |     break;  | 
467  | 62.6k  |   }  | 
468  | 12.9k  |   case Sparc_OP_GROUP_MemOperand: { | 
469  | 12.9k  |     cs_sparc_op *prev_op = Sparc_get_detail_op(MI, -1);  | 
470  | 12.9k  |     if (prev_op && prev_op->type == SPARC_OP_MEM) { | 
471  |  |       // Already added.  | 
472  | 0  |       break;  | 
473  | 0  |     }  | 
474  | 12.9k  |     MCOperand *Op1 = MCInst_getOperand(MI, (OpNo));  | 
475  | 12.9k  |     MCOperand *Op2 = MCInst_getOperand(MI, (OpNo + 1));  | 
476  | 12.9k  |     if (!MCOperand_isReg(Op1) ||  | 
477  | 12.9k  |         MCOperand_getReg(Op1) == Sparc_G0) { | 
478  |  |       // Ignored  | 
479  | 891  |       return;  | 
480  | 891  |     }  | 
481  | 12.0k  |     Sparc_get_detail_op(MI, 0)->type = SPARC_OP_MEM;  | 
482  | 12.0k  |     Sparc_get_detail_op(MI, 0)->access =  | 
483  | 12.0k  |       map_get_op_access(MI, OpNo);  | 
484  | 12.0k  |     Sparc_get_detail_op(MI, 0)->mem.base = MCOperand_getReg(Op1);  | 
485  |  |  | 
486  | 12.0k  |     if (MCOperand_isReg(Op2) && MCOperand_getReg(Op2) != Sparc_G0) { | 
487  | 3.63k  |       Sparc_get_detail_op(MI, 0)->mem.index =  | 
488  | 3.63k  |         MCOperand_getReg(Op2);  | 
489  | 8.41k  |     } else if (MCOperand_isImm(Op2) && MCOperand_getImm(Op2) != 0) { | 
490  | 6.78k  |       Sparc_get_detail_op(MI, 0)->mem.disp =  | 
491  | 6.78k  |         MCOperand_getImm(Op2);  | 
492  | 6.78k  |     }  | 
493  | 12.0k  |     Sparc_inc_op_count(MI);  | 
494  | 12.0k  |     break;  | 
495  | 12.9k  |   }  | 
496  | 4.30k  |   case Sparc_OP_GROUP_ASITag:  | 
497  | 4.30k  |     Sparc_get_detail_op(MI, 0)->type = SPARC_OP_ASI;  | 
498  | 4.30k  |     Sparc_get_detail_op(MI, 0)->access =  | 
499  | 4.30k  |       map_get_op_access(MI, OpNo);  | 
500  | 4.30k  |     Sparc_get_detail_op(MI, 0)->asi =  | 
501  | 4.30k  |       MCOperand_getImm(MCInst_getOperand(MI, OpNo));  | 
502  | 4.30k  |     Sparc_inc_op_count(MI);  | 
503  | 4.30k  |     break;  | 
504  | 633  |   case Sparc_OP_GROUP_MembarTag:  | 
505  | 633  |     Sparc_get_detail_op(MI, 0)->type = SPARC_OP_MEMBAR_TAG;  | 
506  | 633  |     Sparc_get_detail_op(MI, 0)->access =  | 
507  | 633  |       map_get_op_access(MI, OpNo);  | 
508  | 633  |     Sparc_get_detail_op(MI, 0)->membar_tag =  | 
509  | 633  |       MCOperand_getImm(MCInst_getOperand(MI, OpNo));  | 
510  | 633  |     Sparc_inc_op_count(MI);  | 
511  | 633  |     break;  | 
512  | 112k  |   }  | 
513  | 112k  | }  | 
514  |  |  | 
515  |  | #endif  |