PageRenderTime 41ms CodeModel.GetById 1ms app.highlight 35ms RepoModel.GetById 1ms app.codeStats 0ms

/thirdparty/breakpad/third_party/libdisasm/x86_operand_list.c

http://github.com/tomahawk-player/tomahawk
C | 191 lines | 142 code | 32 blank | 17 comment | 32 complexity | e5a666b890b4ddf91464e51e3edeea10 MD5 | raw file
  1#include <stdlib.h>
  2#include "libdis.h"
  3
  4
  5static 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	
 36x86_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
 48void 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 */
 71int 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
149static 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
154size_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 */
169x86_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
177x86_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
185x86_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}