| OLD | NEW |
| (Empty) |
| 1 #include <stdlib.h> | |
| 2 #include "libdis.h" | |
| 3 | |
| 4 | |
| 5 static void x86_oplist_append( x86_insn_t *insn, x86_oplist_t *op ) { | |
| 6 x86_oplist_t *list; | |
| 7 | |
| 8 if (! insn ) { | |
| 9 return; | |
| 10 } | |
| 11 | |
| 12 list = insn->operands; | |
| 13 if (! list ) { | |
| 14 insn->operand_count = 1; | |
| 15 /* Note that we have no way of knowing if this is an | |
| 16 * exlicit operand or not, since the caller fills | |
| 17 * the x86_op_t after we return. We increase the | |
| 18 * explicit count automatically, and ia32_insn_implicit_ops | |
| 19 * decrements it */ | |
| 20 insn->explicit_count = 1; | |
| 21 insn->operands = op; | |
| 22 return; | |
| 23 } | |
| 24 | |
| 25 /* get to end of list */ | |
| 26 for ( ; list->next; list = list->next ) | |
| 27 ; | |
| 28 | |
| 29 insn->operand_count = insn->operand_count + 1; | |
| 30 insn->explicit_count = insn->explicit_count + 1; | |
| 31 list->next = op; | |
| 32 | |
| 33 return; | |
| 34 } | |
| 35 | |
| 36 x86_op_t * x86_operand_new( x86_insn_t *insn ) { | |
| 37 x86_oplist_t *op; | |
| 38 | |
| 39 if (! insn ) { | |
| 40 return(NULL); | |
| 41 } | |
| 42 op = calloc( sizeof(x86_oplist_t), 1 ); | |
| 43 op->op.insn = insn; | |
| 44 x86_oplist_append( insn, op ); | |
| 45 return( &(op->op) ); | |
| 46 } | |
| 47 | |
| 48 void x86_oplist_free( x86_insn_t *insn ) { | |
| 49 x86_oplist_t *op, *list; | |
| 50 | |
| 51 if (! insn ) { | |
| 52 return; | |
| 53 } | |
| 54 | |
| 55 for ( list = insn->operands; list; ) { | |
| 56 op = list; | |
| 57 list = list->next; | |
| 58 free(op); | |
| 59 } | |
| 60 | |
| 61 insn->operands = NULL; | |
| 62 insn->operand_count = 0; | |
| 63 insn->explicit_count = 0; | |
| 64 | |
| 65 return; | |
| 66 } | |
| 67 | |
| 68 /* ================================================== LIBDISASM API */ | |
| 69 /* these could probably just be #defines, but that means exposing the | |
| 70 enum... yet one more confusing thing in the API */ | |
| 71 int x86_operand_foreach( x86_insn_t *insn, x86_operand_fn func, void *arg, | |
| 72 enum x86_op_foreach_type type ){ | |
| 73 x86_oplist_t *list; | |
| 74 char explicit = 1, implicit = 1; | |
| 75 | |
| 76 if (! insn || ! func ) { | |
| 77 return 0; | |
| 78 } | |
| 79 | |
| 80 /* note: explicit and implicit can be ORed together to | |
| 81 * allow an "all" limited by access type, even though the | |
| 82 * user is stupid to do this since it is default behavior :) */ | |
| 83 if ( (type & op_explicit) && ! (type & op_implicit) ) { | |
| 84 implicit = 0; | |
| 85 } | |
| 86 if ( (type & op_implicit) && ! (type & op_explicit) ) { | |
| 87 explicit = 0; | |
| 88 } | |
| 89 | |
| 90 type = type & 0x0F; /* mask out explicit/implicit operands */ | |
| 91 | |
| 92 for ( list = insn->operands; list; list = list->next ) { | |
| 93 if (! implicit && (list->op.flags & op_implied) ) { | |
| 94 /* operand is implicit */ | |
| 95 continue; | |
| 96 } | |
| 97 | |
| 98 if (! explicit && ! (list->op.flags & op_implied) ) { | |
| 99 /* operand is not implicit */ | |
| 100 continue; | |
| 101 } | |
| 102 | |
| 103 switch ( type ) { | |
| 104 case op_any: | |
| 105 break; | |
| 106 case op_dest: | |
| 107 if (! (list->op.access & op_write) ) { | |
| 108 continue; | |
| 109 } | |
| 110 break; | |
| 111 case op_src: | |
| 112 if (! (list->op.access & op_read) ) { | |
| 113 continue; | |
| 114 } | |
| 115 break; | |
| 116 case op_ro: | |
| 117 if (! (list->op.access & op_read) || | |
| 118 (list->op.access & op_write ) ) { | |
| 119 continue; | |
| 120 } | |
| 121 break; | |
| 122 case op_wo: | |
| 123 if (! (list->op.access & op_write) || | |
| 124 (list->op.access & op_read ) ) { | |
| 125 continue; | |
| 126 } | |
| 127 break; | |
| 128 case op_xo: | |
| 129 if (! (list->op.access & op_execute) ) { | |
| 130 continue; | |
| 131 } | |
| 132 break; | |
| 133 case op_rw: | |
| 134 if (! (list->op.access & op_write) || | |
| 135 ! (list->op.access & op_read ) ) { | |
| 136 continue; | |
| 137 } | |
| 138 break; | |
| 139 case op_implicit: case op_explicit: /* make gcc happy */ | |
| 140 break; | |
| 141 } | |
| 142 /* any non-continue ends up here: invoke the callback */ | |
| 143 (*func)( &list->op, insn, arg ); | |
| 144 } | |
| 145 | |
| 146 return 1; | |
| 147 } | |
| 148 | |
| 149 static void count_operand( x86_op_t *op, x86_insn_t *insn, void *arg ) { | |
| 150 size_t * count = (size_t *) arg; | |
| 151 *count = *count + 1; | |
| 152 } | |
| 153 | |
| 154 size_t x86_operand_count( x86_insn_t *insn, enum x86_op_foreach_type type ) { | |
| 155 size_t count = 0; | |
| 156 | |
| 157 /* save us a list traversal for common counts... */ | |
| 158 if ( type == op_any ) { | |
| 159 return insn->operand_count; | |
| 160 } else if ( type == op_explicit ) { | |
| 161 return insn->explicit_count; | |
| 162 } | |
| 163 | |
| 164 x86_operand_foreach( insn, count_operand, &count, type ); | |
| 165 return count; | |
| 166 } | |
| 167 | |
| 168 /* accessor functions */ | |
| 169 x86_op_t * x86_operand_1st( x86_insn_t *insn ) { | |
| 170 if (! insn->explicit_count ) { | |
| 171 return NULL; | |
| 172 } | |
| 173 | |
| 174 return &(insn->operands->op); | |
| 175 } | |
| 176 | |
| 177 x86_op_t * x86_operand_2nd( x86_insn_t *insn ) { | |
| 178 if ( insn->explicit_count < 2 ) { | |
| 179 return NULL; | |
| 180 } | |
| 181 | |
| 182 return &(insn->operands->next->op); | |
| 183 } | |
| 184 | |
| 185 x86_op_t * x86_operand_3rd( x86_insn_t *insn ) { | |
| 186 if ( insn->explicit_count < 3 ) { | |
| 187 return NULL; | |
| 188 } | |
| 189 | |
| 190 return &(insn->operands->next->next->op); | |
| 191 } | |
| OLD | NEW |