Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_fixcpp/sys/src/libmach/8db.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <bio.h>
4
#include <mach.h>
5
 
6
/*
7
 * i386-specific debugger interface
8
 * also amd64 extensions
9
 */
10
 
11
static	char	*i386excep(Map*, Rgetter);
12
 
13
static	int	i386trace(Map*, uvlong, uvlong, uvlong, Tracer);
14
static	uvlong	i386frame(Map*, uvlong, uvlong, uvlong, uvlong);
15
static	int	i386foll(Map*, uvlong, Rgetter, uvlong*);
16
static	int	i386inst(Map*, uvlong, char, char*, int);
17
static	int	i386das(Map*, uvlong, char*, int);
18
static	int	i386instlen(Map*, uvlong);
19
 
20
static	char	STARTSYM[] =	"_main";
21
static	char	PROFSYM[] =	"_mainp";
22
static	char	FRAMENAME[] =	".frame";
23
static char *excname[] =
24
{
25
[0]	"divide error",
26
[1]	"debug exception",
27
[4]	"overflow",
28
[5]	"bounds check",
29
[6]	"invalid opcode",
30
[7]	"math coprocessor emulation",
31
[8]	"double fault",
32
[9]	"math coprocessor overrun",
33
[10]	"invalid TSS",
34
[11]	"segment not present",
35
[12]	"stack exception",
36
[13]	"general protection violation",
37
[14]	"page fault",
38
[16]	"math coprocessor error",
39
[17]	"alignment check",
40
[18]	"machine check",
41
[19]	"floating-point exception",
42
[24]	"clock",
43
[25]	"keyboard",
44
[27]	"modem status",
45
[28]	"serial line status",
46
[30]	"floppy disk",
47
[36]	"mouse",
48
[37]	"math coprocessor",
49
[38]	"hard disk",
50
[64]	"system call",
51
};
52
 
53
Machdata i386mach =
54
{
55
	{0xCC, 0, 0, 0},	/* break point: INT 3 */
56
	1,			/* break point size */
57
 
58
	leswab,			/* convert short to local byte order */
59
	leswal,			/* convert long to local byte order */
60
	leswav,			/* convert vlong to local byte order */
61
	i386trace,		/* C traceback */
62
	i386frame,		/* frame finder */
63
	i386excep,		/* print exception */
64
	0,			/* breakpoint fixup */
65
	leieeesftos,		/* single precision float printer */
66
	leieeedftos,		/* double precision float printer */
67
	i386foll,		/* following addresses */
68
	i386inst,		/* print instruction */
69
	i386das,		/* dissembler */
70
	i386instlen,		/* instruction size calculation */
71
};
72
 
73
static char*
74
i386excep(Map *map, Rgetter rget)
75
{
76
	ulong c;
77
	uvlong pc;
78
	static char buf[16];
79
 
80
	c = (*rget)(map, "TRAP");
81
	if(c > 64 || excname[c] == 0) {
82
		if (c == 3) {
83
			pc = (*rget)(map, "PC");
84
			if (get1(map, pc, (uchar*)buf, machdata->bpsize) > 0)
85
			if (memcmp(buf, machdata->bpinst, machdata->bpsize) == 0)
86
				return "breakpoint";
87
		}
88
		snprint(buf, sizeof(buf), "exception %ld", c);
89
		return buf;
90
	} else
91
		return excname[c];
92
}
93
 
94
static int
95
i386trace(Map *map, uvlong pc, uvlong sp, uvlong link, Tracer trace)
96
{
97
	int i;
98
	uvlong osp;
99
	Symbol s, f;
100
 
101
	USED(link);
102
	i = 0;
103
	osp = 0;
104
	while(findsym(pc, CTEXT, &s)) {
105
		if (osp == sp)
106
			break;
107
		osp = sp;
108
 
109
		if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0)
110
			break;
111
 
112
		if(pc != s.value) {	/* not at first instruction */
113
			if(findlocal(&s, FRAMENAME, &f) == 0)
114
				break;
115
			sp += f.value-mach->szaddr;
116
		}
117
 
118
		if (geta(map, sp, &pc) < 0)
119
			break;
120
 
121
		if(pc == 0)
122
			break;
123
 
124
		(*trace)(map, pc, sp, &s);
125
		sp += mach->szaddr;
126
 
127
		if(++i > 1000)
128
			break;
129
	}
130
	return i;
131
}
132
 
133
static uvlong
134
i386frame(Map *map, uvlong addr, uvlong pc, uvlong sp, uvlong link)
135
{
136
	Symbol s, f;
137
 
138
	USED(link);
139
	while (findsym(pc, CTEXT, &s)) {
140
		if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0)
141
			break;
142
 
143
		if(pc != s.value) {	/* not first instruction */
144
			if(findlocal(&s, FRAMENAME, &f) == 0)
145
				break;
146
			sp += f.value-mach->szaddr;
147
		}
148
 
149
		if (s.value == addr)
150
			return sp;
151
 
152
		if (geta(map, sp, &pc) < 0)
153
			break;
154
		sp += mach->szaddr;
155
	}
156
	return 0;
157
}
158
 
159
	/* I386/486 - Disassembler and related functions */
160
 
161
/*
162
 *  an instruction
163
 */
164
typedef struct Instr Instr;
165
struct	Instr
166
{
167
	uchar	mem[1+1+1+1+2+1+1+4+4];		/* raw instruction */
168
	uvlong	addr;		/* address of start of instruction */
169
	int	n;		/* number of bytes in instruction */
170
	char	*prefix;	/* instr prefix */
171
	char	*segment;	/* segment override */
172
	uchar	jumptype;	/* set to the operand type for jump/ret/call */
173
	uchar	amd64;
174
	uchar	rex;		/* REX prefix (or zero) */
175
	char	osize;		/* 'W' or 'L' (or 'Q' on amd64) */
176
	char	asize;		/* address size 'W' or 'L' (or 'Q' or amd64) */
177
	uchar	mod;		/* bits 6-7 of mod r/m field */
178
	uchar	reg;		/* bits 3-5 of mod r/m field */
179
	char	ss;		/* bits 6-7 of SIB */
180
	char	index;		/* bits 3-5 of SIB */
181
	char	base;		/* bits 0-2 of SIB */
182
	char	rip;		/* RIP-relative in amd64 mode */
183
	uchar	opre;		/* f2/f3 could introduce media */
184
	short	seg;		/* segment of far address */
185
	ulong	disp;		/* displacement */
186
	ulong 	imm;		/* immediate */
187
	ulong 	imm2;		/* second immediate operand */
188
	uvlong	imm64;		/* big immediate */
189
	char	*curr;		/* fill level in output buffer */
190
	char	*end;		/* end of output buffer */
191
	char	*err;		/* error message */
192
};
193
 
194
	/* 386 register (ha!) set */
195
enum{
196
	AX=0,
197
	CX,
198
	DX,
199
	BX,
200
	SP,
201
	BP,
202
	SI,
203
	DI,
204
 
205
	/* amd64 */
206
	R8,
207
	R9,
208
	R10,
209
	R11,
210
	R12,
211
	R13,
212
	R14,
213
	R15
214
};
215
 
216
	/* amd64 rex extension byte */
217
enum{
218
	REXW		= 1<<3,	/* =1, 64-bit operand size */
219
	REXR		= 1<<2,	/* extend modrm reg */
220
	REXX		= 1<<1,	/* extend sib index */
221
	REXB		= 1<<0	/* extend modrm r/m, sib base, or opcode reg */
222
};
223
 
224
	/* Operand Format codes */
225
/*
226
%A	-	address size register modifier (!asize -> 'E')
227
%C	-	Control register CR0/CR1/CR2
228
%D	-	Debug register DR0/DR1/DR2/DR3/DR6/DR7
229
%I	-	second immediate operand
230
%O	-	Operand size register modifier (!osize -> 'E')
231
%T	-	Test register TR6/TR7
232
%S	-	size code ('W' or 'L')
233
%W	-	Weird opcode: OSIZE == 'W' => "CBW"; else => "CWDE"
234
%d	-	displacement 16-32 bits
235
%e	-	effective address - Mod R/M value
236
%f	-	floating point register F0-F7 - from Mod R/M register
237
%g	-	segment register
238
%i	-	immediate operand 8-32 bits
239
%p	-	PC-relative - signed displacement in immediate field
240
%r	-	Reg from Mod R/M
241
%w	-	Weird opcode: OSIZE == 'W' => "CWD"; else => "CDQ"
242
*/
243
 
244
typedef struct Optable Optable;
245
struct Optable
246
{
247
	char	operand[2];
248
	void	*proto;		/* actually either (char*) or (Optable*) */
249
};
250
	/* Operand decoding codes */
251
enum {
252
	Ib = 1,			/* 8-bit immediate - (no sign extension)*/
253
	Ibs,			/* 8-bit immediate (sign extended) */
254
	Jbs,			/* 8-bit sign-extended immediate in jump or call */
255
	Iw,			/* 16-bit immediate -> imm */
256
	Iw2,			/* 16-bit immediate -> imm2 */
257
	Iwd,			/* Operand-sized immediate (no sign extension)*/
258
	Iwdq,			/* Operand-sized immediate, possibly 64 bits */
259
	Awd,			/* Address offset */
260
	Iwds,			/* Operand-sized immediate (sign extended) */
261
	RM,			/* Word or long R/M field with register (/r) */
262
	RMB,			/* Byte R/M field with register (/r) */
263
	RMOP,			/* Word or long R/M field with op code (/digit) */
264
	RMOPB,			/* Byte R/M field with op code (/digit) */
265
	RMR,			/* R/M register only (mod = 11) */
266
	RMM,			/* R/M memory only (mod = 0/1/2) */
267
	R0,			/* Base reg of Mod R/M is literal 0x00 */
268
	R1,			/* Base reg of Mod R/M is literal 0x01 */
269
	FRMOP,			/* Floating point R/M field with opcode */
270
	FRMEX,			/* Extended floating point R/M field with opcode */
271
	JUMP,			/* Jump or Call flag - no operand */
272
	RET,			/* Return flag - no operand */
273
	OA,			/* literal 0x0a byte */
274
	PTR,			/* Seg:Displacement addr (ptr16:16 or ptr16:32) */
275
	AUX,			/* Multi-byte op code - Auxiliary table */
276
	AUXMM,			/* multi-byte op code - auxiliary table chosen by prefix */
277
	PRE,			/* Instr Prefix */
278
	OPRE,			/* Instr Prefix or media op extension */
279
	SEG,			/* Segment Prefix */
280
	OPOVER,			/* Operand size override */
281
	ADDOVER,		/* Address size override */
282
};
283
 
284
static Optable optab0F00[8]=
285
{
286
[0x00]	0,0,		"MOVW	LDT,%e",
287
[0x01]	0,0,		"MOVW	TR,%e",
288
[0x02]	0,0,		"MOVW	%e,LDT",
289
[0x03]	0,0,		"MOVW	%e,TR",
290
[0x04]	0,0,		"VERR	%e",
291
[0x05]	0,0,		"VERW	%e",
292
};
293
 
294
static Optable optab0F01[8]=
295
{
296
[0x00]	0,0,		"MOVL	GDTR,%e",
297
[0x01]	0,0,		"MOVL	IDTR,%e",
298
[0x02]	0,0,		"MOVL	%e,GDTR",
299
[0x03]	0,0,		"MOVL	%e,IDTR",
300
[0x04]	0,0,		"MOVW	MSW,%e",	/* word */
301
[0x06]	0,0,		"MOVW	%e,MSW",	/* word */
302
[0x07]	0,0,		"INVLPG	%e",		/* or SWAPGS */
303
};
304
 
305
static Optable optab0F01F8[1]=
306
{
307
[0x00]	0,0,		"SWAPGS",
308
};
309
 
310
/* 0F71 */
311
/* 0F72 */
312
/* 0F73 */
313
 
314
static Optable optab0FAE[8]=
315
{
316
[0x00]	0,0,		"FXSAVE	%e",
317
[0x01]	0,0,		"FXRSTOR	%e",
318
[0x02]	0,0,		"LDMXCSR	%e",
319
[0x03]	0,0,		"STMXCSR	%e",
320
[0x05]	0,0,		"LFENCE",
321
[0x06]	0,0,		"MFENCE",
322
[0x07]	0,0,		"SFENCE",
323
};
324
 
325
/* 0F18 */
326
/* 0F0D */
327
 
328
static Optable optab0FBA[8]=
329
{
330
[0x04]	Ib,0,		"BT%S	%i,%e",
331
[0x05]	Ib,0,		"BTS%S	%i,%e",
332
[0x06]	Ib,0,		"BTR%S	%i,%e",
333
[0x07]	Ib,0,		"BTC%S	%i,%e",
334
};
335
 
336
static Optable optab0F0F[256]=
337
{
338
[0x0c]	0,0,		"PI2FW	%m,%M",
339
[0x0d]	0,0,		"PI2L	%m,%M",
340
[0x1c]	0,0,		"PF2IW	%m,%M",
341
[0x1d]	0,0,		"PF2IL	%m,%M",
342
[0x8a]	0,0,		"PFNACC	%m,%M",
343
[0x8e]	0,0,		"PFPNACC	%m,%M",
344
[0x90]	0,0,		"PFCMPGE	%m,%M",
345
[0x94]	0,0,		"PFMIN	%m,%M",
346
[0x96]	0,0,		"PFRCP	%m,%M",
347
[0x97]	0,0,		"PFRSQRT	%m,%M",
348
[0x9a]	0,0,		"PFSUB	%m,%M",
349
[0x9e]	0,0,		"PFADD	%m,%M",
350
[0xa0]	0,0,		"PFCMPGT	%m,%M",
351
[0xa4]	0,0,		"PFMAX	%m,%M",
352
[0xa6]	0,0,		"PFRCPIT1	%m,%M",
353
[0xa7]	0,0,		"PFRSQIT1	%m,%M",
354
[0xaa]	0,0,		"PFSUBR	%m,%M",
355
[0xae]	0,0,		"PFACC	%m,%M",
356
[0xb0]	0,0,		"PFCMPEQ	%m,%M",
357
[0xb4]	0,0,		"PFMUL	%m,%M",
358
[0xb6]	0,0,		"PFRCPI2T	%m,%M",
359
[0xb7]	0,0,		"PMULHRW	%m,%M",
360
[0xbb]	0,0,		"PSWAPL	%m,%M",
361
};
362
 
363
static Optable optab0FC7[8]=
364
{
365
[0x01]	0,0,		"CMPXCHG8B	%e",
366
};
367
 
368
static Optable optab660F71[8]=
369
{
370
[0x02]	Ib,0,		"PSRLW	%i,%X",
371
[0x04]	Ib,0,		"PSRAW	%i,%X",
372
[0x06]	Ib,0,		"PSLLW	%i,%X",
373
};
374
 
375
static Optable optab660F72[8]=
376
{
377
[0x02]	Ib,0,		"PSRLL	%i,%X",
378
[0x04]	Ib,0,		"PSRAL	%i,%X",
379
[0x06]	Ib,0,		"PSLLL	%i,%X",
380
};
381
 
382
static Optable optab660F73[8]=
383
{
384
[0x02]	Ib,0,		"PSRLQ	%i,%X",
385
[0x03]	Ib,0,		"PSRLO	%i,%X",
386
[0x06]	Ib,0,		"PSLLQ	%i,%X",
387
[0x07]	Ib,0,		"PSLLO	%i,%X",
388
};
389
 
390
static Optable optab660F[256]=
391
{
392
[0x2B]	RM,0,		"MOVNTPD	%x,%e",
393
[0x2E]	RM,0,		"UCOMISD	%x,%X",
394
[0x2F]	RM,0,		"COMISD	%x,%X",
395
[0x5A]	RM,0,		"CVTPD2PS	%x,%X",
396
[0x5B]	RM,0,		"CVTPS2PL	%x,%X",
397
[0x6A]	RM,0,		"PUNPCKHLQ %x,%X",
398
[0x6B]	RM,0,		"PACKSSLW %x,%X",
399
[0x6C]	RM,0,		"PUNPCKLQDQ %x,%X",
400
[0x6D]	RM,0,		"PUNPCKHQDQ %x,%X",
401
[0x6E]	RM,0,		"MOV%S	%e,%X",
402
[0x6F]	RM,0,		"MOVO	%x,%X",		/* MOVDQA */
403
[0x70]	RM,Ib,		"PSHUFL	%i,%x,%X",
404
[0x71]	RMOP,0,		optab660F71,
405
[0x72]	RMOP,0,		optab660F72,
406
[0x73]	RMOP,0,		optab660F73,
407
[0x7E]	RM,0,		"MOV%S	%X,%e",
408
[0x7F]	RM,0,		"MOVO	%X,%x",
409
[0xC4]	RM,Ib,		"PINSRW	%i,%e,%X",
410
[0xC5]	RMR,Ib,		"PEXTRW	%i,%X,%e",
411
[0xD4]	RM,0,		"PADDQ	%x,%X",
412
[0xD5]	RM,0,		"PMULLW	%x,%X",
413
[0xD6]	RM,0,		"MOVQ	%X,%x",
414
[0xE6]	RM,0,		"CVTTPD2PL	%x,%X",
415
[0xE7]	RM,0,		"MOVNTO	%X,%e",
416
[0xF7]	RM,0,		"MASKMOVOU	%x,%X",
417
};
418
 
419
static Optable optabF20F[256]=
420
{
421
[0x10]	RM,0,		"MOVSD	%x,%X",
422
[0x11]	RM,0,		"MOVSD	%X,%x",
423
[0x2A]	RM,0,		"CVTS%S2SD	%e,%X",
424
[0x2C]	RM,0,		"CVTTSD2S%S	%x,%r",
425
[0x2D]	RM,0,		"CVTSD2S%S	%x,%r",
426
[0x5A]	RM,0,		"CVTSD2SS	%x,%X",
427
[0x6F]	RM,0,		"MOVOU	%x,%X",
428
[0x70]	RM,Ib,		"PSHUFLW	%i,%x,%X",
429
[0x7F]	RM,0,		"MOVOU	%X,%x",
430
[0xD6]	RM,0,		"MOVQOZX	%M,%X",
431
[0xE6]	RM,0,		"CVTPD2PL	%x,%X",
432
};
433
 
434
static Optable optabF30F[256]=
435
{
436
[0x10]	RM,0,		"MOVSS	%x,%X",
437
[0x11]	RM,0,		"MOVSS	%X,%x",
438
[0x2A]	RM,0,		"CVTS%S2SS	%e,%X",
439
[0x2C]	RM,0,		"CVTTSS2S%S	%x,%r",
440
[0x2D]	RM,0,		"CVTSS2S%S	%x,%r",
441
[0x5A]	RM,0,		"CVTSS2SD	%x,%X",
442
[0x5B]	RM,0,		"CVTTPS2PL	%x,%X",
443
[0x6F]	RM,0,		"MOVOU	%x,%X",
444
[0x70]	RM,Ib,		"PSHUFHW	%i,%x,%X",
445
[0x7E]	RM,0,		"MOVQOZX	%x,%X",
446
[0x7F]	RM,0,		"MOVOU	%X,%x",
447
[0xD6]	RM,0,		"MOVQOZX	%m*,%X",
448
[0xE6]	RM,0,		"CVTPL2PD	%x,%X",
449
};
450
 
451
static Optable optab0F[256]=
452
{
453
[0x00]	RMOP,0,		optab0F00,
454
[0x01]	RMOP,0,		optab0F01,
455
[0x02]	RM,0,		"LAR	%e,%r",
456
[0x03]	RM,0,		"LSL	%e,%r",
457
[0x05]	0,0,		"SYSCALL",
458
[0x06]	0,0,		"CLTS",
459
[0x07]	0,0,		"SYSRET",
460
[0x08]	0,0,		"INVD",
461
[0x09]	0,0,		"WBINVD",
462
[0x0B]	0,0,		"UD2",
463
[0x0F]	RM,AUX,		optab0F0F,		/* 3DNow! */
464
[0x10]	RM,0,		"MOVU%s	%x,%X",
465
[0x11]	RM,0,		"MOVU%s	%X,%x",
466
[0x12]	RM,0,		"MOV[H]L%s	%x,%X",	/* TO DO: H if source is XMM */
467
[0x13]	RM,0,		"MOVL%s	%X,%e",
468
[0x14]	RM,0,		"UNPCKL%s	%x,%X",
469
[0x15]	RM,0,		"UNPCKH%s	%x,%X",
470
[0x16]	RM,0,		"MOV[L]H%s	%x,%X",	/* TO DO: L if source is XMM */
471
[0x17]	RM,0,		"MOVH%s	%X,%x",
472
[0x20]	RMR,0,		"MOVL	%C,%e",
473
[0x21]	RMR,0,		"MOVL	%D,%e",
474
[0x22]	RMR,0,		"MOVL	%e,%C",
475
[0x23]	RMR,0,		"MOVL	%e,%D",
476
[0x24]	RMR,0,		"MOVL	%T,%e",
477
[0x26]	RMR,0,		"MOVL	%e,%T",
478
[0x28]	RM,0,		"MOVA%s	%x,%X",
479
[0x29]	RM,0,		"MOVA%s	%X,%x",
480
[0x2A]	RM,0,		"CVTPL2%s	%m*,%X",
481
[0x2B]	RM,0,		"MOVNT%s	%X,%e",
482
[0x2C]	RM,0,		"CVTT%s2PL	%x,%M",
483
[0x2D]	RM,0,		"CVT%s2PL	%x,%M",
484
[0x2E]	RM,0,		"UCOMISS	%x,%X",
485
[0x2F]	RM,0,		"COMISS	%x,%X",
486
[0x30]	0,0,		"WRMSR",
487
[0x31]	0,0,		"RDTSC",
488
[0x32]	0,0,		"RDMSR",
489
[0x33]	0,0,		"RDPMC",
490
[0x42]	RM,0,		"CMOVC	%e,%r",		/* CF */
491
[0x43]	RM,0,		"CMOVNC	%e,%r",		/* ¬ CF */
492
[0x44]	RM,0,		"CMOVZ	%e,%r",		/* ZF */
493
[0x45]	RM,0,		"CMOVNZ	%e,%r",		/* ¬ ZF */
494
[0x46]	RM,0,		"CMOVBE	%e,%r",		/* CF ∨ ZF */
495
[0x47]	RM,0,		"CMOVA	%e,%r",		/* ¬CF ∧ ¬ZF */
496
[0x48]	RM,0,		"CMOVS	%e,%r",		/* SF */
497
[0x49]	RM,0,		"CMOVNS	%e,%r",		/* ¬ SF */
498
[0x4A]	RM,0,		"CMOVP	%e,%r",		/* PF */
499
[0x4B]	RM,0,		"CMOVNP	%e,%r",		/* ¬ PF */
500
[0x4C]	RM,0,		"CMOVLT	%e,%r",		/* LT ≡ OF ≠ SF */
501
[0x4D]	RM,0,		"CMOVGE	%e,%r",		/* GE ≡ ZF ∨ SF */
502
[0x4E]	RM,0,		"CMOVLE	%e,%r",		/* LE ≡ ZF ∨ LT */
503
[0x4F]	RM,0,		"CMOVGT	%e,%r",		/* GT ≡ ¬ZF ∧ GE */
504
[0x50]	RM,0,		"MOVMSK%s	%X,%r",	/* TO DO: check */
505
[0x51]	RM,0,		"SQRT%s	%x,%X",
506
[0x52]	RM,0,		"RSQRT%s	%x,%X",
507
[0x53]	RM,0,		"RCP%s	%x,%X",
508
[0x54]	RM,0,		"AND%s	%x,%X",
509
[0x55]	RM,0,		"ANDN%s	%x,%X",
510
[0x56]	RM,0,		"OR%s	%x,%X",		/* TO DO: S/D */
511
[0x57]	RM,0,		"XOR%s	%x,%X",		/* S/D */
512
[0x58]	RM,0,		"ADD%s	%x,%X",		/* S/P S/D */
513
[0x59]	RM,0,		"MUL%s	%x,%X",
514
[0x5A]	RM,0,		"CVTPS2PD	%x,%X",
515
[0x5B]	RM,0,		"CVTPL2PS	%x,%X",
516
[0x5C]	RM,0,		"SUB%s	%x,%X",
517
[0x5D]	RM,0,		"MIN%s	%x,%X",
518
[0x5E]	RM,0,		"DIV%s	%x,%X",		/* TO DO: S/P S/D */
519
[0x5F]	RM,0,		"MAX%s	%x,%X",
520
[0x60]	RM,0,		"PUNPCKLBW %m,%M",
521
[0x61]	RM,0,		"PUNPCKLWL %m,%M",
522
[0x62]	RM,0,		"PUNPCKLLQ %m,%M",
523
[0x63]	RM,0,		"PACKSSWB %m,%M",
524
[0x64]	RM,0,		"PCMPGTB %m,%M",
525
[0x65]	RM,0,		"PCMPGTW %m,%M",
526
[0x66]	RM,0,		"PCMPGTL %m,%M",
527
[0x67]	RM,0,		"PACKUSWB %m,%M",
528
[0x68]	RM,0,		"PUNPCKHBW %m,%M",
529
[0x69]	RM,0,		"PUNPCKHWL %m,%M",
530
[0x6A]	RM,0,		"PUNPCKHLQ %m,%M",
531
[0x6B]	RM,0,		"PACKSSLW %m,%M",
532
[0x6E]	RM,0,		"MOV%S %e,%M",
533
[0x6F]	RM,0,		"MOVQ %m,%M",
534
[0x70]	RM,Ib,		"PSHUFW	%i,%m,%M",
535
[0x74]	RM,0,		"PCMPEQB %m,%M",
536
[0x75]	RM,0,		"PCMPEQW %m,%M",
537
[0x76]	RM,0,		"PCMPEQL %m,%M",
538
[0x7E]	RM,0,		"MOV%S %M,%e",
539
[0x7F]	RM,0,		"MOVQ %M,%m",
540
[0xAE]	RMOP,0,		optab0FAE,
541
[0xAA]	0,0,		"RSM",
542
[0xB0]	RM,0,		"CMPXCHGB	%r,%e",
543
[0xB1]	RM,0,		"CMPXCHG%S	%r,%e",
544
[0xC0]	RMB,0,		"XADDB	%r,%e",
545
[0xC1]	RM,0,		"XADD%S	%r,%e",
546
[0xC2]	RM,Ib,		"CMP%s	%i,%x,%X",
547
[0xC3]	RM,0,		"MOVNTI%S	%r,%e",
548
[0xC6]	RM,Ib,		"SHUF%s	%i,%x,%X",
549
[0xC8]	0,0,		"BSWAP	AX",
550
[0xC9]	0,0,		"BSWAP	CX",
551
[0xCA]	0,0,		"BSWAP	DX",
552
[0xCB]	0,0,		"BSWAP	BX",
553
[0xCC]	0,0,		"BSWAP	SP",
554
[0xCD]	0,0,		"BSWAP	BP",
555
[0xCE]	0,0,		"BSWAP	SI",
556
[0xCF]	0,0,		"BSWAP	DI",
557
[0xD1]	RM,0,		"PSRLW %m,%M",
558
[0xD2]	RM,0,		"PSRLL %m,%M",
559
[0xD3]	RM,0,		"PSRLQ %m,%M",
560
[0xD5]	RM,0,		"PMULLW %m,%M",
561
[0xD6]	RM,0,		"MOVQOZX	%m*,%X",
562
[0xD7]	RM,0,		"PMOVMSKB %m,%r",
563
[0xD8]	RM,0,		"PSUBUSB %m,%M",
564
[0xD9]	RM,0,		"PSUBUSW %m,%M",
565
[0xDA]	RM,0,		"PMINUB %m,%M",
566
[0xDB]	RM,0,		"PAND %m,%M",
567
[0xDC]	RM,0,		"PADDUSB %m,%M",
568
[0xDD]	RM,0,		"PADDUSW %m,%M",
569
[0xDE]	RM,0,		"PMAXUB %m,%M",
570
[0xDF]	RM,0,		"PANDN %m,%M",
571
[0xE0]	RM,0,		"PAVGB %m,%M",
572
[0xE1]	RM,0,		"PSRAW %m,%M",
573
[0xE2]	RM,0,		"PSRAL %m,%M",
574
[0xE3]	RM,0,		"PAVGW %m,%M",
575
[0xE4]	RM,0,		"PMULHUW %m,%M",
576
[0xE5]	RM,0,		"PMULHW %m,%M",
577
[0xE7]	RM,0,		"MOVNTQ	%M,%e",
578
[0xE8]	RM,0,		"PSUBSB %m,%M",
579
[0xE9]	RM,0,		"PSUBSW %m,%M",
580
[0xEA]	RM,0,		"PMINSW %m,%M",
581
[0xEB]	RM,0,		"POR %m,%M",
582
[0xEC]	RM,0,		"PADDSB %m,%M",
583
[0xED]	RM,0,		"PADDSW %m,%M",
584
[0xEE]	RM,0,		"PMAXSW %m,%M",
585
[0xEF]	RM,0,		"PXOR %m,%M",
586
[0xF1]	RM,0,		"PSLLW %m,%M",
587
[0xF2]	RM,0,		"PSLLL %m,%M",
588
[0xF3]	RM,0,		"PSLLQ %m,%M",
589
[0xF4]	RM,0,		"PMULULQ	%m,%M",
590
[0xF5]	RM,0,		"PMADDWL %m,%M",
591
[0xF6]	RM,0,		"PSADBW %m,%M",
592
[0xF7]	RMR,0,		"MASKMOVQ	%m,%M",
593
[0xF8]	RM,0,		"PSUBB %m,%M",
594
[0xF9]	RM,0,		"PSUBW %m,%M",
595
[0xFA]	RM,0,		"PSUBL %m,%M",
596
[0xFC]	RM,0,		"PADDB %m,%M",
597
[0xFD]	RM,0,		"PADDW %m,%M",
598
[0xFE]	RM,0,		"PADDL %m,%M",
599
 
600
[0x80]	Iwds,0,		"JOS	%p",
601
[0x81]	Iwds,0,		"JOC	%p",
602
[0x82]	Iwds,0,		"JCS	%p",
603
[0x83]	Iwds,0,		"JCC	%p",
604
[0x84]	Iwds,0,		"JEQ	%p",
605
[0x85]	Iwds,0,		"JNE	%p",
606
[0x86]	Iwds,0,		"JLS	%p",
607
[0x87]	Iwds,0,		"JHI	%p",
608
[0x88]	Iwds,0,		"JMI	%p",
609
[0x89]	Iwds,0,		"JPL	%p",
610
[0x8a]	Iwds,0,		"JPS	%p",
611
[0x8b]	Iwds,0,		"JPC	%p",
612
[0x8c]	Iwds,0,		"JLT	%p",
613
[0x8d]	Iwds,0,		"JGE	%p",
614
[0x8e]	Iwds,0,		"JLE	%p",
615
[0x8f]	Iwds,0,		"JGT	%p",
616
[0x90]	RMB,0,		"SETOS	%e",
617
[0x91]	RMB,0,		"SETOC	%e",
618
[0x92]	RMB,0,		"SETCS	%e",
619
[0x93]	RMB,0,		"SETCC	%e",
620
[0x94]	RMB,0,		"SETEQ	%e",
621
[0x95]	RMB,0,		"SETNE	%e",
622
[0x96]	RMB,0,		"SETLS	%e",
623
[0x97]	RMB,0,		"SETHI	%e",
624
[0x98]	RMB,0,		"SETMI	%e",
625
[0x99]	RMB,0,		"SETPL	%e",
626
[0x9a]	RMB,0,		"SETPS	%e",
627
[0x9b]	RMB,0,		"SETPC	%e",
628
[0x9c]	RMB,0,		"SETLT	%e",
629
[0x9d]	RMB,0,		"SETGE	%e",
630
[0x9e]	RMB,0,		"SETLE	%e",
631
[0x9f]	RMB,0,		"SETGT	%e",
632
[0xa0]	0,0,		"PUSHL	FS",
633
[0xa1]	0,0,		"POPL	FS",
634
[0xa2]	0,0,		"CPUID",
635
[0xa3]	RM,0,		"BT%S	%r,%e",
636
[0xa4]	RM,Ib,		"SHLD%S	%r,%i,%e",
637
[0xa5]	RM,0,		"SHLD%S	%r,CL,%e",
638
[0xa8]	0,0,		"PUSHL	GS",
639
[0xa9]	0,0,		"POPL	GS",
640
[0xab]	RM,0,		"BTS%S	%r,%e",
641
[0xac]	RM,Ib,		"SHRD%S	%r,%i,%e",
642
[0xad]	RM,0,		"SHRD%S	%r,CL,%e",
643
[0xaf]	RM,0,		"IMUL%S	%e,%r",
644
[0xb2]	RMM,0,		"LSS	%e,%r",
645
[0xb3]	RM,0,		"BTR%S	%r,%e",
646
[0xb4]	RMM,0,		"LFS	%e,%r",
647
[0xb5]	RMM,0,		"LGS	%e,%r",
648
[0xb6]	RMB,0,		"MOVBZX	%e,%R",
649
[0xb7]	RM,0,		"MOVWZX	%e,%R",
650
[0xba]	RMOP,0,		optab0FBA,
651
[0xbb]	RM,0,		"BTC%S	%e,%r",
652
[0xbc]	RM,0,		"BSF%S	%e,%r",
653
[0xbd]	RM,0,		"BSR%S	%e,%r",
654
[0xbe]	RMB,0,		"MOVBSX	%e,%R",
655
[0xbf]	RM,0,		"MOVWSX	%e,%R",
656
[0xc7]	RMOP,0,		optab0FC7,
657
};
658
 
659
static Optable optab80[8]=
660
{
661
[0x00]	Ib,0,		"ADDB	%i,%e",
662
[0x01]	Ib,0,		"ORB	%i,%e",
663
[0x02]	Ib,0,		"ADCB	%i,%e",
664
[0x03]	Ib,0,		"SBBB	%i,%e",
665
[0x04]	Ib,0,		"ANDB	%i,%e",
666
[0x05]	Ib,0,		"SUBB	%i,%e",
667
[0x06]	Ib,0,		"XORB	%i,%e",
668
[0x07]	Ib,0,		"CMPB	%e,%i",
669
};
670
 
671
static Optable optab81[8]=
672
{
673
[0x00]	Iwd,0,		"ADD%S	%i,%e",
674
[0x01]	Iwd,0,		"OR%S	%i,%e",
675
[0x02]	Iwd,0,		"ADC%S	%i,%e",
676
[0x03]	Iwd,0,		"SBB%S	%i,%e",
677
[0x04]	Iwd,0,		"AND%S	%i,%e",
678
[0x05]	Iwd,0,		"SUB%S	%i,%e",
679
[0x06]	Iwd,0,		"XOR%S	%i,%e",
680
[0x07]	Iwd,0,		"CMP%S	%e,%i",
681
};
682
 
683
static Optable optab83[8]=
684
{
685
[0x00]	Ibs,0,		"ADD%S	%i,%e",
686
[0x01]	Ibs,0,		"OR%S	%i,%e",
687
[0x02]	Ibs,0,		"ADC%S	%i,%e",
688
[0x03]	Ibs,0,		"SBB%S	%i,%e",
689
[0x04]	Ibs,0,		"AND%S	%i,%e",
690
[0x05]	Ibs,0,		"SUB%S	%i,%e",
691
[0x06]	Ibs,0,		"XOR%S	%i,%e",
692
[0x07]	Ibs,0,		"CMP%S	%e,%i",
693
};
694
 
695
static Optable optabC0[8] =
696
{
697
[0x00]	Ib,0,		"ROLB	%i,%e",
698
[0x01]	Ib,0,		"RORB	%i,%e",
699
[0x02]	Ib,0,		"RCLB	%i,%e",
700
[0x03]	Ib,0,		"RCRB	%i,%e",
701
[0x04]	Ib,0,		"SHLB	%i,%e",
702
[0x05]	Ib,0,		"SHRB	%i,%e",
703
[0x07]	Ib,0,		"SARB	%i,%e",
704
};
705
 
706
static Optable optabC1[8] =
707
{
708
[0x00]	Ib,0,		"ROL%S	%i,%e",
709
[0x01]	Ib,0,		"ROR%S	%i,%e",
710
[0x02]	Ib,0,		"RCL%S	%i,%e",
711
[0x03]	Ib,0,		"RCR%S	%i,%e",
712
[0x04]	Ib,0,		"SHL%S	%i,%e",
713
[0x05]	Ib,0,		"SHR%S	%i,%e",
714
[0x07]	Ib,0,		"SAR%S	%i,%e",
715
};
716
 
717
static Optable optabD0[8] =
718
{
719
[0x00]	0,0,		"ROLB	%e",
720
[0x01]	0,0,		"RORB	%e",
721
[0x02]	0,0,		"RCLB	%e",
722
[0x03]	0,0,		"RCRB	%e",
723
[0x04]	0,0,		"SHLB	%e",
724
[0x05]	0,0,		"SHRB	%e",
725
[0x07]	0,0,		"SARB	%e",
726
};
727
 
728
static Optable optabD1[8] =
729
{
730
[0x00]	0,0,		"ROL%S	%e",
731
[0x01]	0,0,		"ROR%S	%e",
732
[0x02]	0,0,		"RCL%S	%e",
733
[0x03]	0,0,		"RCR%S	%e",
734
[0x04]	0,0,		"SHL%S	%e",
735
[0x05]	0,0,		"SHR%S	%e",
736
[0x07]	0,0,		"SAR%S	%e",
737
};
738
 
739
static Optable optabD2[8] =
740
{
741
[0x00]	0,0,		"ROLB	CL,%e",
742
[0x01]	0,0,		"RORB	CL,%e",
743
[0x02]	0,0,		"RCLB	CL,%e",
744
[0x03]	0,0,		"RCRB	CL,%e",
745
[0x04]	0,0,		"SHLB	CL,%e",
746
[0x05]	0,0,		"SHRB	CL,%e",
747
[0x07]	0,0,		"SARB	CL,%e",
748
};
749
 
750
static Optable optabD3[8] =
751
{
752
[0x00]	0,0,		"ROL%S	CL,%e",
753
[0x01]	0,0,		"ROR%S	CL,%e",
754
[0x02]	0,0,		"RCL%S	CL,%e",
755
[0x03]	0,0,		"RCR%S	CL,%e",
756
[0x04]	0,0,		"SHL%S	CL,%e",
757
[0x05]	0,0,		"SHR%S	CL,%e",
758
[0x07]	0,0,		"SAR%S	CL,%e",
759
};
760
 
761
static Optable optabD8[8+8] =
762
{
763
[0x00]	0,0,		"FADDF	%e,F0",
764
[0x01]	0,0,		"FMULF	%e,F0",
765
[0x02]	0,0,		"FCOMF	%e,F0",
766
[0x03]	0,0,		"FCOMFP	%e,F0",
767
[0x04]	0,0,		"FSUBF	%e,F0",
768
[0x05]	0,0,		"FSUBRF	%e,F0",
769
[0x06]	0,0,		"FDIVF	%e,F0",
770
[0x07]	0,0,		"FDIVRF	%e,F0",
771
[0x08]	0,0,		"FADDD	%f,F0",
772
[0x09]	0,0,		"FMULD	%f,F0",
773
[0x0a]	0,0,		"FCOMD	%f,F0",
774
[0x0b]	0,0,		"FCOMPD	%f,F0",
775
[0x0c]	0,0,		"FSUBD	%f,F0",
776
[0x0d]	0,0,		"FSUBRD	%f,F0",
777
[0x0e]	0,0,		"FDIVD	%f,F0",
778
[0x0f]	0,0,		"FDIVRD	%f,F0",
779
};
780
/*
781
 *	optabD9 and optabDB use the following encoding: 
782
 *	if (0 <= modrm <= 2) instruction = optabDx[modrm&0x07];
783
 *	else instruction = optabDx[(modrm&0x3f)+8];
784
 *
785
 *	the instructions for MOD == 3, follow the 8 instructions
786
 *	for the other MOD values stored at the front of the table.
787
 */
788
static Optable optabD9[64+8] =
789
{
790
[0x00]	0,0,		"FMOVF	%e,F0",
791
[0x02]	0,0,		"FMOVF	F0,%e",
792
[0x03]	0,0,		"FMOVFP	F0,%e",
793
[0x04]	0,0,		"FLDENV%S %e",
794
[0x05]	0,0,		"FLDCW	%e",
795
[0x06]	0,0,		"FSTENV%S %e",
796
[0x07]	0,0,		"FSTCW	%e",
797
[0x08]	0,0,		"FMOVD	F0,F0",		/* Mod R/M = 11xx xxxx*/
798
[0x09]	0,0,		"FMOVD	F1,F0",
799
[0x0a]	0,0,		"FMOVD	F2,F0",
800
[0x0b]	0,0,		"FMOVD	F3,F0",
801
[0x0c]	0,0,		"FMOVD	F4,F0",
802
[0x0d]	0,0,		"FMOVD	F5,F0",
803
[0x0e]	0,0,		"FMOVD	F6,F0",
804
[0x0f]	0,0,		"FMOVD	F7,F0",
805
[0x10]	0,0,		"FXCHD	F0,F0",
806
[0x11]	0,0,		"FXCHD	F1,F0",
807
[0x12]	0,0,		"FXCHD	F2,F0",
808
[0x13]	0,0,		"FXCHD	F3,F0",
809
[0x14]	0,0,		"FXCHD	F4,F0",
810
[0x15]	0,0,		"FXCHD	F5,F0",
811
[0x16]	0,0,		"FXCHD	F6,F0",
812
[0x17]	0,0,		"FXCHD	F7,F0",
813
[0x18]	0,0,		"FNOP",
814
[0x28]	0,0,		"FCHS",
815
[0x29]	0,0,		"FABS",
816
[0x2c]	0,0,		"FTST",
817
[0x2d]	0,0,		"FXAM",
818
[0x30]	0,0,		"FLD1",
819
[0x31]	0,0,		"FLDL2T",
820
[0x32]	0,0,		"FLDL2E",
821
[0x33]	0,0,		"FLDPI",
822
[0x34]	0,0,		"FLDLG2",
823
[0x35]	0,0,		"FLDLN2",
824
[0x36]	0,0,		"FLDZ",
825
[0x38]	0,0,		"F2XM1",
826
[0x39]	0,0,		"FYL2X",
827
[0x3a]	0,0,		"FPTAN",
828
[0x3b]	0,0,		"FPATAN",
829
[0x3c]	0,0,		"FXTRACT",
830
[0x3d]	0,0,		"FPREM1",
831
[0x3e]	0,0,		"FDECSTP",
832
[0x3f]	0,0,		"FNCSTP",
833
[0x40]	0,0,		"FPREM",
834
[0x41]	0,0,		"FYL2XP1",
835
[0x42]	0,0,		"FSQRT",
836
[0x43]	0,0,		"FSINCOS",
837
[0x44]	0,0,		"FRNDINT",
838
[0x45]	0,0,		"FSCALE",
839
[0x46]	0,0,		"FSIN",
840
[0x47]	0,0,		"FCOS",
841
};
842
 
843
static Optable optabDA[8+8] =
844
{
845
[0x00]	0,0,		"FADDL	%e,F0",
846
[0x01]	0,0,		"FMULL	%e,F0",
847
[0x02]	0,0,		"FCOML	%e,F0",
848
[0x03]	0,0,		"FCOMLP	%e,F0",
849
[0x04]	0,0,		"FSUBL	%e,F0",
850
[0x05]	0,0,		"FSUBRL	%e,F0",
851
[0x06]	0,0,		"FDIVL	%e,F0",
852
[0x07]	0,0,		"FDIVRL	%e,F0",
853
[0x0d]	R1,0,		"FUCOMPP",
854
};
855
 
856
static Optable optabDB[8+64] =
857
{
858
[0x00]	0,0,		"FMOVL	%e,F0",
859
[0x02]	0,0,		"FMOVL	F0,%e",
860
[0x03]	0,0,		"FMOVLP	F0,%e",
861
[0x05]	0,0,		"FMOVX	%e,F0",
862
[0x07]	0,0,		"FMOVXP	F0,%e",
863
[0x2a]	0,0,		"FCLEX",
864
[0x2b]	0,0,		"FINIT",
865
};
866
 
867
static Optable optabDC[8+8] =
868
{
869
[0x00]	0,0,		"FADDD	%e,F0",
870
[0x01]	0,0,		"FMULD	%e,F0",
871
[0x02]	0,0,		"FCOMD	%e,F0",
872
[0x03]	0,0,		"FCOMDP	%e,F0",
873
[0x04]	0,0,		"FSUBD	%e,F0",
874
[0x05]	0,0,		"FSUBRD	%e,F0",
875
[0x06]	0,0,		"FDIVD	%e,F0",
876
[0x07]	0,0,		"FDIVRD	%e,F0",
877
[0x08]	0,0,		"FADDD	F0,%f",
878
[0x09]	0,0,		"FMULD	F0,%f",
879
[0x0c]	0,0,		"FSUBRD	F0,%f",
880
[0x0d]	0,0,		"FSUBD	F0,%f",
881
[0x0e]	0,0,		"FDIVRD	F0,%f",
882
[0x0f]	0,0,		"FDIVD	F0,%f",
883
};
884
 
885
static Optable optabDD[8+8] =
886
{
887
[0x00]	0,0,		"FMOVD	%e,F0",
888
[0x02]	0,0,		"FMOVD	F0,%e",
889
[0x03]	0,0,		"FMOVDP	F0,%e",
890
[0x04]	0,0,		"FRSTOR%S %e",
891
[0x06]	0,0,		"FSAVE%S %e",
892
[0x07]	0,0,		"FSTSW	%e",
893
[0x08]	0,0,		"FFREED	%f",
894
[0x0a]	0,0,		"FMOVD	%f,F0",
895
[0x0b]	0,0,		"FMOVDP	%f,F0",
896
[0x0c]	0,0,		"FUCOMD	%f,F0",
897
[0x0d]	0,0,		"FUCOMDP %f,F0",
898
};
899
 
900
static Optable optabDE[8+8] =
901
{
902
[0x00]	0,0,		"FADDW	%e,F0",
903
[0x01]	0,0,		"FMULW	%e,F0",
904
[0x02]	0,0,		"FCOMW	%e,F0",
905
[0x03]	0,0,		"FCOMWP	%e,F0",
906
[0x04]	0,0,		"FSUBW	%e,F0",
907
[0x05]	0,0,		"FSUBRW	%e,F0",
908
[0x06]	0,0,		"FDIVW	%e,F0",
909
[0x07]	0,0,		"FDIVRW	%e,F0",
910
[0x08]	0,0,		"FADDDP	F0,%f",
911
[0x09]	0,0,		"FMULDP	F0,%f",
912
[0x0b]	R1,0,		"FCOMPDP",
913
[0x0c]	0,0,		"FSUBRDP F0,%f",
914
[0x0d]	0,0,		"FSUBDP	F0,%f",
915
[0x0e]	0,0,		"FDIVRDP F0,%f",
916
[0x0f]	0,0,		"FDIVDP	F0,%f",
917
};
918
 
919
static Optable optabDF[8+8] =
920
{
921
[0x00]	0,0,		"FMOVW	%e,F0",
922
[0x02]	0,0,		"FMOVW	F0,%e",
923
[0x03]	0,0,		"FMOVWP	F0,%e",
924
[0x04]	0,0,		"FBLD	%e",
925
[0x05]	0,0,		"FMOVL	%e,F0",
926
[0x06]	0,0,		"FBSTP	%e",
927
[0x07]	0,0,		"FMOVLP	F0,%e",
928
[0x0c]	R0,0,		"FSTSW	%OAX",
929
};
930
 
931
static Optable optabF6[8] =
932
{
933
[0x00]	Ib,0,		"TESTB	%i,%e",
934
[0x02]	0,0,		"NOTB	%e",
935
[0x03]	0,0,		"NEGB	%e",
936
[0x04]	0,0,		"MULB	AL,%e",
937
[0x05]	0,0,		"IMULB	AL,%e",
938
[0x06]	0,0,		"DIVB	AL,%e",
939
[0x07]	0,0,		"IDIVB	AL,%e",
940
};
941
 
942
static Optable optabF7[8] =
943
{
944
[0x00]	Iwd,0,		"TEST%S	%i,%e",
945
[0x02]	0,0,		"NOT%S	%e",
946
[0x03]	0,0,		"NEG%S	%e",
947
[0x04]	0,0,		"MUL%S	%OAX,%e",
948
[0x05]	0,0,		"IMUL%S	%OAX,%e",
949
[0x06]	0,0,		"DIV%S	%OAX,%e",
950
[0x07]	0,0,		"IDIV%S	%OAX,%e",
951
};
952
 
953
static Optable optabFE[8] =
954
{
955
[0x00]	0,0,		"INCB	%e",
956
[0x01]	0,0,		"DECB	%e",
957
};
958
 
959
static Optable optabFF[8] =
960
{
961
[0x00]	0,0,		"INC%S	%e",
962
[0x01]	0,0,		"DEC%S	%e",
963
[0x02]	JUMP,0,		"CALL*	%e",
964
[0x03]	JUMP,0,		"CALLF*	%e",
965
[0x04]	JUMP,0,		"JMP*	%e",
966
[0x05]	JUMP,0,		"JMPF*	%e",
967
[0x06]	0,0,		"PUSHL	%e",
968
};
969
 
970
static Optable optable[256+1] =
971
{
972
[0x00]	RMB,0,		"ADDB	%r,%e",
973
[0x01]	RM,0,		"ADD%S	%r,%e",
974
[0x02]	RMB,0,		"ADDB	%e,%r",
975
[0x03]	RM,0,		"ADD%S	%e,%r",
976
[0x04]	Ib,0,		"ADDB	%i,AL",
977
[0x05]	Iwd,0,		"ADD%S	%i,%OAX",
978
[0x06]	0,0,		"PUSHL	ES",
979
[0x07]	0,0,		"POPL	ES",
980
[0x08]	RMB,0,		"ORB	%r,%e",
981
[0x09]	RM,0,		"OR%S	%r,%e",
982
[0x0a]	RMB,0,		"ORB	%e,%r",
983
[0x0b]	RM,0,		"OR%S	%e,%r",
984
[0x0c]	Ib,0,		"ORB	%i,AL",
985
[0x0d]	Iwd,0,		"OR%S	%i,%OAX",
986
[0x0e]	0,0,		"PUSHL	CS",
987
[0x0f]	AUXMM,0,	optab0F,
988
[0x10]	RMB,0,		"ADCB	%r,%e",
989
[0x11]	RM,0,		"ADC%S	%r,%e",
990
[0x12]	RMB,0,		"ADCB	%e,%r",
991
[0x13]	RM,0,		"ADC%S	%e,%r",
992
[0x14]	Ib,0,		"ADCB	%i,AL",
993
[0x15]	Iwd,0,		"ADC%S	%i,%OAX",
994
[0x16]	0,0,		"PUSHL	SS",
995
[0x17]	0,0,		"POPL	SS",
996
[0x18]	RMB,0,		"SBBB	%r,%e",
997
[0x19]	RM,0,		"SBB%S	%r,%e",
998
[0x1a]	RMB,0,		"SBBB	%e,%r",
999
[0x1b]	RM,0,		"SBB%S	%e,%r",
1000
[0x1c]	Ib,0,		"SBBB	%i,AL",
1001
[0x1d]	Iwd,0,		"SBB%S	%i,%OAX",
1002
[0x1e]	0,0,		"PUSHL	DS",
1003
[0x1f]	0,0,		"POPL	DS",
1004
[0x20]	RMB,0,		"ANDB	%r,%e",
1005
[0x21]	RM,0,		"AND%S	%r,%e",
1006
[0x22]	RMB,0,		"ANDB	%e,%r",
1007
[0x23]	RM,0,		"AND%S	%e,%r",
1008
[0x24]	Ib,0,		"ANDB	%i,AL",
1009
[0x25]	Iwd,0,		"AND%S	%i,%OAX",
1010
[0x26]	SEG,0,		"ES:",
1011
[0x27]	0,0,		"DAA",
1012
[0x28]	RMB,0,		"SUBB	%r,%e",
1013
[0x29]	RM,0,		"SUB%S	%r,%e",
1014
[0x2a]	RMB,0,		"SUBB	%e,%r",
1015
[0x2b]	RM,0,		"SUB%S	%e,%r",
1016
[0x2c]	Ib,0,		"SUBB	%i,AL",
1017
[0x2d]	Iwd,0,		"SUB%S	%i,%OAX",
1018
[0x2e]	SEG,0,		"CS:",
1019
[0x2f]	0,0,		"DAS",
1020
[0x30]	RMB,0,		"XORB	%r,%e",
1021
[0x31]	RM,0,		"XOR%S	%r,%e",
1022
[0x32]	RMB,0,		"XORB	%e,%r",
1023
[0x33]	RM,0,		"XOR%S	%e,%r",
1024
[0x34]	Ib,0,		"XORB	%i,AL",
1025
[0x35]	Iwd,0,		"XOR%S	%i,%OAX",
1026
[0x36]	SEG,0,		"SS:",
1027
[0x37]	0,0,		"AAA",
1028
[0x38]	RMB,0,		"CMPB	%r,%e",
1029
[0x39]	RM,0,		"CMP%S	%r,%e",
1030
[0x3a]	RMB,0,		"CMPB	%e,%r",
1031
[0x3b]	RM,0,		"CMP%S	%e,%r",
1032
[0x3c]	Ib,0,		"CMPB	%i,AL",
1033
[0x3d]	Iwd,0,		"CMP%S	%i,%OAX",
1034
[0x3e]	SEG,0,		"DS:",
1035
[0x3f]	0,0,		"AAS",
1036
[0x40]	0,0,		"INC%S	%OAX",
1037
[0x41]	0,0,		"INC%S	%OCX",
1038
[0x42]	0,0,		"INC%S	%ODX",
1039
[0x43]	0,0,		"INC%S	%OBX",
1040
[0x44]	0,0,		"INC%S	%OSP",
1041
[0x45]	0,0,		"INC%S	%OBP",
1042
[0x46]	0,0,		"INC%S	%OSI",
1043
[0x47]	0,0,		"INC%S	%ODI",
1044
[0x48]	0,0,		"DEC%S	%OAX",
1045
[0x49]	0,0,		"DEC%S	%OCX",
1046
[0x4a]	0,0,		"DEC%S	%ODX",
1047
[0x4b]	0,0,		"DEC%S	%OBX",
1048
[0x4c]	0,0,		"DEC%S	%OSP",
1049
[0x4d]	0,0,		"DEC%S	%OBP",
1050
[0x4e]	0,0,		"DEC%S	%OSI",
1051
[0x4f]	0,0,		"DEC%S	%ODI",
1052
[0x50]	0,0,		"PUSH%S	%OAX",
1053
[0x51]	0,0,		"PUSH%S	%OCX",
1054
[0x52]	0,0,		"PUSH%S	%ODX",
1055
[0x53]	0,0,		"PUSH%S	%OBX",
1056
[0x54]	0,0,		"PUSH%S	%OSP",
1057
[0x55]	0,0,		"PUSH%S	%OBP",
1058
[0x56]	0,0,		"PUSH%S	%OSI",
1059
[0x57]	0,0,		"PUSH%S	%ODI",
1060
[0x58]	0,0,		"POP%S	%OAX",
1061
[0x59]	0,0,		"POP%S	%OCX",
1062
[0x5a]	0,0,		"POP%S	%ODX",
1063
[0x5b]	0,0,		"POP%S	%OBX",
1064
[0x5c]	0,0,		"POP%S	%OSP",
1065
[0x5d]	0,0,		"POP%S	%OBP",
1066
[0x5e]	0,0,		"POP%S	%OSI",
1067
[0x5f]	0,0,		"POP%S	%ODI",
1068
[0x60]	0,0,		"PUSHA%S",
1069
[0x61]	0,0,		"POPA%S",
1070
[0x62]	RMM,0,		"BOUND	%e,%r",
1071
[0x63]	RM,0,		"ARPL	%r,%e",
1072
[0x64]	SEG,0,		"FS:",
1073
[0x65]	SEG,0,		"GS:",
1074
[0x66]	OPOVER,0,	"",
1075
[0x67]	ADDOVER,0,	"",
1076
[0x68]	Iwd,0,		"PUSH%S	%i",
1077
[0x69]	RM,Iwd,		"IMUL%S	%e,%i,%r",
1078
[0x6a]	Ib,0,		"PUSH%S	%i",
1079
[0x6b]	RM,Ibs,		"IMUL%S	%e,%i,%r",
1080
[0x6c]	0,0,		"INSB	DX,(%ODI)",
1081
[0x6d]	0,0,		"INS%S	DX,(%ODI)",
1082
[0x6e]	0,0,		"OUTSB	(%ASI),DX",
1083
[0x6f]	0,0,		"OUTS%S	(%ASI),DX",
1084
[0x70]	Jbs,0,		"JOS	%p",
1085
[0x71]	Jbs,0,		"JOC	%p",
1086
[0x72]	Jbs,0,		"JCS	%p",
1087
[0x73]	Jbs,0,		"JCC	%p",
1088
[0x74]	Jbs,0,		"JEQ	%p",
1089
[0x75]	Jbs,0,		"JNE	%p",
1090
[0x76]	Jbs,0,		"JLS	%p",
1091
[0x77]	Jbs,0,		"JHI	%p",
1092
[0x78]	Jbs,0,		"JMI	%p",
1093
[0x79]	Jbs,0,		"JPL	%p",
1094
[0x7a]	Jbs,0,		"JPS	%p",
1095
[0x7b]	Jbs,0,		"JPC	%p",
1096
[0x7c]	Jbs,0,		"JLT	%p",
1097
[0x7d]	Jbs,0,		"JGE	%p",
1098
[0x7e]	Jbs,0,		"JLE	%p",
1099
[0x7f]	Jbs,0,		"JGT	%p",
1100
[0x80]	RMOPB,0,	optab80,
1101
[0x81]	RMOP,0,		optab81,
1102
[0x83]	RMOP,0,		optab83,
1103
[0x84]	RMB,0,		"TESTB	%r,%e",
1104
[0x85]	RM,0,		"TEST%S	%r,%e",
1105
[0x86]	RMB,0,		"XCHGB	%r,%e",
1106
[0x87]	RM,0,		"XCHG%S	%r,%e",
1107
[0x88]	RMB,0,		"MOVB	%r,%e",
1108
[0x89]	RM,0,		"MOV%S	%r,%e",
1109
[0x8a]	RMB,0,		"MOVB	%e,%r",
1110
[0x8b]	RM,0,		"MOV%S	%e,%r",
1111
[0x8c]	RM,0,		"MOVW	%g,%e",
1112
[0x8d]	RM,0,		"LEA%S	%e,%r",
1113
[0x8e]	RM,0,		"MOVW	%e,%g",
1114
[0x8f]	RM,0,		"POP%S	%e",
1115
[0x90]	0,0,		"NOP",
1116
[0x91]	0,0,		"XCHG	%OCX,%OAX",
1117
[0x92]	0,0,		"XCHG	%ODX,%OAX",
1118
[0x93]	0,0,		"XCHG	%OBX,%OAX",
1119
[0x94]	0,0,		"XCHG	%OSP,%OAX",
1120
[0x95]	0,0,		"XCHG	%OBP,%OAX",
1121
[0x96]	0,0,		"XCHG	%OSI,%OAX",
1122
[0x97]	0,0,		"XCHG	%ODI,%OAX",
1123
[0x98]	0,0,		"%W",			/* miserable CBW or CWDE */
1124
[0x99]	0,0,		"%w",			/* idiotic CWD or CDQ */
1125
[0x9a]	PTR,0,		"CALL%S	%d",
1126
[0x9b]	0,0,		"WAIT",
1127
[0x9c]	0,0,		"PUSHF",
1128
[0x9d]	0,0,		"POPF",
1129
[0x9e]	0,0,		"SAHF",
1130
[0x9f]	0,0,		"LAHF",
1131
[0xa0]	Awd,0,		"MOVB	%i,AL",
1132
[0xa1]	Awd,0,		"MOV%S	%i,%OAX",
1133
[0xa2]	Awd,0,		"MOVB	AL,%i",
1134
[0xa3]	Awd,0,		"MOV%S	%OAX,%i",
1135
[0xa4]	0,0,		"MOVSB	(%ASI),(%ADI)",
1136
[0xa5]	0,0,		"MOVS%S	(%ASI),(%ADI)",
1137
[0xa6]	0,0,		"CMPSB	(%ASI),(%ADI)",
1138
[0xa7]	0,0,		"CMPS%S	(%ASI),(%ADI)",
1139
[0xa8]	Ib,0,		"TESTB	%i,AL",
1140
[0xa9]	Iwd,0,		"TEST%S	%i,%OAX",
1141
[0xaa]	0,0,		"STOSB	AL,(%ADI)",
1142
[0xab]	0,0,		"STOS%S	%OAX,(%ADI)",
1143
[0xac]	0,0,		"LODSB	(%ASI),AL",
1144
[0xad]	0,0,		"LODS%S	(%ASI),%OAX",
1145
[0xae]	0,0,		"SCASB	(%ADI),AL",
1146
[0xaf]	0,0,		"SCAS%S	(%ADI),%OAX",
1147
[0xb0]	Ib,0,		"MOVB	%i,AL",
1148
[0xb1]	Ib,0,		"MOVB	%i,CL",
1149
[0xb2]	Ib,0,		"MOVB	%i,DL",
1150
[0xb3]	Ib,0,		"MOVB	%i,BL",
1151
[0xb4]	Ib,0,		"MOVB	%i,AH",
1152
[0xb5]	Ib,0,		"MOVB	%i,CH",
1153
[0xb6]	Ib,0,		"MOVB	%i,DH",
1154
[0xb7]	Ib,0,		"MOVB	%i,BH",
1155
[0xb8]	Iwdq,0,		"MOV%S	%i,%OAX",
1156
[0xb9]	Iwdq,0,		"MOV%S	%i,%OCX",
1157
[0xba]	Iwdq,0,		"MOV%S	%i,%ODX",
1158
[0xbb]	Iwdq,0,		"MOV%S	%i,%OBX",
1159
[0xbc]	Iwdq,0,		"MOV%S	%i,%OSP",
1160
[0xbd]	Iwdq,0,		"MOV%S	%i,%OBP",
1161
[0xbe]	Iwdq,0,		"MOV%S	%i,%OSI",
1162
[0xbf]	Iwdq,0,		"MOV%S	%i,%ODI",
1163
[0xc0]	RMOPB,0,	optabC0,
1164
[0xc1]	RMOP,0,		optabC1,
1165
[0xc2]	Iw,0,		"RET	%i",
1166
[0xc3]	RET,0,		"RET",
1167
[0xc4]	RM,0,		"LES	%e,%r",
1168
[0xc5]	RM,0,		"LDS	%e,%r",
1169
[0xc6]	RMB,Ib,		"MOVB	%i,%e",
1170
[0xc7]	RM,Iwd,		"MOV%S	%i,%e",
1171
[0xc8]	Iw2,Ib,		"ENTER	%i,%I",		/* loony ENTER */
1172
[0xc9]	RET,0,		"LEAVE",		/* bizarre LEAVE */
1173
[0xca]	Iw,0,		"RETF	%i",
1174
[0xcb]	RET,0,		"RETF",
1175
[0xcc]	0,0,		"INT	3",
1176
[0xcd]	Ib,0,		"INTB	%i",
1177
[0xce]	0,0,		"INTO",
1178
[0xcf]	0,0,		"IRET",
1179
[0xd0]	RMOPB,0,	optabD0,
1180
[0xd1]	RMOP,0,		optabD1,
1181
[0xd2]	RMOPB,0,	optabD2,
1182
[0xd3]	RMOP,0,		optabD3,
1183
[0xd4]	OA,0,		"AAM",
1184
[0xd5]	OA,0,		"AAD",
1185
[0xd7]	0,0,		"XLAT",
1186
[0xd8]	FRMOP,0,	optabD8,
1187
[0xd9]	FRMEX,0,	optabD9,
1188
[0xda]	FRMOP,0,	optabDA,
1189
[0xdb]	FRMEX,0,	optabDB,
1190
[0xdc]	FRMOP,0,	optabDC,
1191
[0xdd]	FRMOP,0,	optabDD,
1192
[0xde]	FRMOP,0,	optabDE,
1193
[0xdf]	FRMOP,0,	optabDF,
1194
[0xe0]	Jbs,0,		"LOOPNE	%p",
1195
[0xe1]	Jbs,0,		"LOOPE	%p",
1196
[0xe2]	Jbs,0,		"LOOP	%p",
1197
[0xe3]	Jbs,0,		"JCXZ	%p",
1198
[0xe4]	Ib,0,		"INB	%i,AL",
1199
[0xe5]	Ib,0,		"IN%S	%i,%OAX",
1200
[0xe6]	Ib,0,		"OUTB	AL,%i",
1201
[0xe7]	Ib,0,		"OUT%S	%OAX,%i",
1202
[0xe8]	Iwds,0,		"CALL	%p",
1203
[0xe9]	Iwds,0,		"JMP	%p",
1204
[0xea]	PTR,0,		"JMP	%d",
1205
[0xeb]	Jbs,0,		"JMP	%p",
1206
[0xec]	0,0,		"INB	DX,AL",
1207
[0xed]	0,0,		"IN%S	DX,%OAX",
1208
[0xee]	0,0,		"OUTB	AL,DX",
1209
[0xef]	0,0,		"OUT%S	%OAX,DX",
1210
[0xf0]	PRE,0,		"LOCK",
1211
[0xf2]	OPRE,0,		"REPNE",
1212
[0xf3]	OPRE,0,		"REP",
1213
[0xf4]	0,0,		"HLT",
1214
[0xf5]	0,0,		"CMC",
1215
[0xf6]	RMOPB,0,	optabF6,
1216
[0xf7]	RMOP,0,		optabF7,
1217
[0xf8]	0,0,		"CLC",
1218
[0xf9]	0,0,		"STC",
1219
[0xfa]	0,0,		"CLI",
1220
[0xfb]	0,0,		"STI",
1221
[0xfc]	0,0,		"CLD",
1222
[0xfd]	0,0,		"STD",
1223
[0xfe]	RMOPB,0,	optabFE,
1224
[0xff]	RMOP,0,		optabFF,
1225
[0x100]	RM,0,		"MOVLQSX	%r,%e",
1226
};
1227
 
1228
/*
1229
 *  get a byte of the instruction
1230
 */
1231
static int
1232
igetc(Map *map, Instr *ip, uchar *c)
1233
{
1234
	if(ip->n+1 > sizeof(ip->mem)){
1235
		werrstr("instruction too long");
1236
		return -1;
1237
	}
1238
	if (get1(map, ip->addr+ip->n, c, 1) < 0) {
1239
		werrstr("can't read instruction: %r");
1240
		return -1;
1241
	}
1242
	ip->mem[ip->n++] = *c;
1243
	return 1;
1244
}
1245
 
1246
/*
1247
 *  get two bytes of the instruction
1248
 */
1249
static int
1250
igets(Map *map, Instr *ip, ushort *sp)
1251
{
1252
	uchar c;
1253
	ushort s;
1254
 
1255
	if (igetc(map, ip, &c) < 0)
1256
		return -1;
1257
	s = c;
1258
	if (igetc(map, ip, &c) < 0)
1259
		return -1;
1260
	s |= (c<<8);
1261
	*sp = s;
1262
	return 1;
1263
}
1264
 
1265
/*
1266
 *  get 4 bytes of the instruction
1267
 */
1268
static int
1269
igetl(Map *map, Instr *ip, ulong *lp)
1270
{
1271
	ushort s;
1272
	long	l;
1273
 
1274
	if (igets(map, ip, &s) < 0)
1275
		return -1;
1276
	l = s;
1277
	if (igets(map, ip, &s) < 0)
1278
		return -1;
1279
	l |= (s<<16);
1280
	*lp = l;
1281
	return 1;
1282
}
1283
 
1284
/*
1285
 *  get 8 bytes of the instruction
1286
 */
1287
static int
1288
igetq(Map *map, Instr *ip, vlong *qp)
1289
{
1290
	ulong	l;
1291
	uvlong q;
1292
 
1293
	if (igetl(map, ip, &l) < 0)
1294
		return -1;
1295
	q = l;
1296
	if (igetl(map, ip, &l) < 0)
1297
		return -1;
1298
	q |= ((uvlong)l<<32);
1299
	*qp = q;
1300
	return 1;
1301
}
1302
 
1303
static int
1304
getdisp(Map *map, Instr *ip, int mod, int rm, int code, int pcrel)
1305
{
1306
	uchar c;
1307
	ushort s;
1308
 
1309
	if (mod > 2)
1310
		return 1;
1311
	if (mod == 1) {
1312
		if (igetc(map, ip, &c) < 0)
1313
			return -1;
1314
		if (c&0x80)
1315
			ip->disp = c|0xffffff00;
1316
		else
1317
			ip->disp = c&0xff;
1318
	} else if (mod == 2 || rm == code) {
1319
		if (ip->asize == 'E') {
1320
			if (igetl(map, ip, &ip->disp) < 0)
1321
				return -1;
1322
			if (mod == 0)
1323
				ip->rip = pcrel;
1324
		} else {
1325
			if (igets(map, ip, &s) < 0)
1326
				return -1;
1327
			if (s&0x8000)
1328
				ip->disp = s|0xffff0000;
1329
			else
1330
				ip->disp = s;
1331
		}
1332
		if (mod == 0)
1333
			ip->base = -1;
1334
	}
1335
	return 1;
1336
}
1337
 
1338
static int
1339
modrm(Map *map, Instr *ip, uchar c)
1340
{
1341
	uchar rm, mod;
1342
 
1343
	mod = (c>>6)&3;
1344
	rm = c&7;
1345
	ip->mod = mod;
1346
	ip->base = rm;
1347
	ip->reg = (c>>3)&7;
1348
	ip->rip = 0;
1349
	if (mod == 3)			/* register */
1350
		return 1;
1351
	if (ip->asize == 0) {		/* 16-bit mode */
1352
		switch(rm) {
1353
		case 0:
1354
			ip->base = BX; ip->index = SI;
1355
			break;
1356
		case 1:
1357
			ip->base = BX; ip->index = DI;
1358
			break;
1359
		case 2:
1360
			ip->base = BP; ip->index = SI;
1361
			break;
1362
		case 3:
1363
			ip->base = BP; ip->index = DI;
1364
			break;
1365
		case 4:
1366
			ip->base = SI;
1367
			break;
1368
		case 5:
1369
			ip->base = DI;
1370
			break;
1371
		case 6:
1372
			ip->base = BP;
1373
			break;
1374
		case 7:
1375
			ip->base = BX;
1376
			break;
1377
		default:
1378
			break;
1379
		}
1380
		return getdisp(map, ip, mod, rm, 6, 0);
1381
	}
1382
	if (rm == 4) {	/* scummy sib byte */
1383
		if (igetc(map, ip, &c) < 0)
1384
			return -1;
1385
		ip->ss = (c>>6)&0x03;
1386
		ip->index = (c>>3)&0x07;
1387
		if (ip->index == 4)
1388
			ip->index = -1;
1389
		ip->base = c&0x07;
1390
		return getdisp(map, ip, mod, ip->base, 5, 0);
1391
	}
1392
	return getdisp(map, ip, mod, rm, 5, ip->amd64);
1393
}
1394
 
1395
static Optable *
1396
mkinstr(Map *map, Instr *ip, uvlong pc)
1397
{
1398
	int i, n, norex;
1399
	uchar c;
1400
	ushort s;
1401
	Optable *op, *obase;
1402
	char buf[128];
1403
 
1404
	memset(ip, 0, sizeof(*ip));
1405
	norex = 1;
1406
	ip->base = -1;
1407
	ip->index = -1;
1408
	if(asstype == AI8086)
1409
		ip->osize = 'W';
1410
	else {
1411
		ip->osize = 'L';
1412
		ip->asize = 'E';
1413
		ip->amd64 = asstype != AI386;
1414
		norex = 0;
1415
	}
1416
	ip->addr = pc;
1417
	if (igetc(map, ip, &c) < 0)
1418
		return 0;
1419
	obase = optable;
1420
newop:
1421
	if(ip->amd64 && !norex){
1422
		if(c >= 0x40 && c <= 0x4f) {
1423
			ip->rex = c;
1424
			if(igetc(map, ip, &c) < 0)
1425
				return 0;
1426
		}
1427
		if(c == 0x63){
1428
			op = &obase[0x100];	/* MOVLQSX */
1429
			goto hack;
1430
		}
1431
	}
1432
	op = &obase[c];
1433
hack:
1434
	if (op->proto == 0) {
1435
badop:
1436
		n = snprint(buf, sizeof(buf), "opcode: ??");
1437
		for (i = 0; i < ip->n && n < sizeof(buf)-3; i++, n+=2)
1438
			_hexify(buf+n, ip->mem[i], 1);
1439
		strcpy(buf+n, "??");
1440
		werrstr(buf);
1441
		return 0;
1442
	}
1443
	for(i = 0; i < 2 && op->operand[i]; i++) {
1444
		switch(op->operand[i]) {
1445
		case Ib:	/* 8-bit immediate - (no sign extension)*/
1446
			if (igetc(map, ip, &c) < 0)
1447
				return 0;
1448
			ip->imm = c&0xff;
1449
			ip->imm64 = ip->imm;
1450
			break;
1451
		case Jbs:	/* 8-bit jump immediate (sign extended) */
1452
			if (igetc(map, ip, &c) < 0)
1453
				return 0;
1454
			if (c&0x80)
1455
				ip->imm = c|0xffffff00;
1456
			else
1457
				ip->imm = c&0xff;
1458
			ip->imm64 = (long)ip->imm;
1459
			ip->jumptype = Jbs;
1460
			break;
1461
		case Ibs:	/* 8-bit immediate (sign extended) */
1462
			if (igetc(map, ip, &c) < 0)
1463
				return 0;
1464
			if (c&0x80)
1465
				if (ip->osize == 'L')
1466
					ip->imm = c|0xffffff00;
1467
				else
1468
					ip->imm = c|0xff00;
1469
			else
1470
				ip->imm = c&0xff;
1471
			ip->imm64 = (long)ip->imm;
1472
			break;
1473
		case Iw:	/* 16-bit immediate -> imm */
1474
			if (igets(map, ip, &s) < 0)
1475
				return 0;
1476
			ip->imm = s&0xffff;
1477
			ip->imm64 = ip->imm;
1478
			ip->jumptype = Iw;
1479
			break;
1480
		case Iw2:	/* 16-bit immediate -> in imm2*/
1481
			if (igets(map, ip, &s) < 0)
1482
				return 0;
1483
			ip->imm2 = s&0xffff;
1484
			break;
1485
		case Iwd:	/* Operand-sized immediate (no sign extension unless 64 bits)*/
1486
			if (ip->osize == 'L') {
1487
				if (igetl(map, ip, &ip->imm) < 0)
1488
					return 0;
1489
				ip->imm64 = ip->imm;
1490
				if(ip->rex&REXW && (ip->imm & (1<<31)) != 0)
1491
					ip->imm64 |= (vlong)~0 << 32;
1492
			} else {
1493
				if (igets(map, ip, &s)< 0)
1494
					return 0;
1495
				ip->imm = s&0xffff;
1496
				ip->imm64 = ip->imm;
1497
			}
1498
			break;
1499
		case Iwdq:	/* Operand-sized immediate, possibly big */
1500
			if (ip->osize == 'L') {
1501
				if (igetl(map, ip, &ip->imm) < 0)
1502
					return 0;
1503
				ip->imm64 = ip->imm;
1504
				if (ip->rex & REXW) {
1505
					ulong l;
1506
					if (igetl(map, ip, &l) < 0)
1507
						return 0;
1508
					ip->imm64 |= (uvlong)l << 32;
1509
				}
1510
			} else {
1511
				if (igets(map, ip, &s)< 0)
1512
					return 0;
1513
				ip->imm = s&0xffff;
1514
			}
1515
			break;
1516
		case Awd:	/* Address-sized immediate (no sign extension)*/
1517
			if (ip->asize == 'E') {
1518
				if (igetl(map, ip, &ip->imm) < 0)
1519
					return 0;
1520
				/* TO DO: REX */
1521
			} else {
1522
				if (igets(map, ip, &s)< 0)
1523
					return 0;
1524
				ip->imm = s&0xffff;
1525
			}
1526
			break;
1527
		case Iwds:	/* Operand-sized immediate (sign extended) */
1528
			if (ip->osize == 'L') {
1529
				if (igetl(map, ip, &ip->imm) < 0)
1530
					return 0;
1531
			} else {
1532
				if (igets(map, ip, &s)< 0)
1533
					return 0;
1534
				if (s&0x8000)
1535
					ip->imm = s|0xffff0000;
1536
				else
1537
					ip->imm = s&0xffff;
1538
			}
1539
			ip->jumptype = Iwds;
1540
			break;
1541
		case OA:	/* literal 0x0a byte */
1542
			if (igetc(map, ip, &c) < 0)
1543
				return 0;
1544
			if (c != 0x0a)
1545
				goto badop;
1546
			break;
1547
		case R0:	/* base register must be R0 */
1548
			if (ip->base != 0)
1549
				goto badop;
1550
			break;
1551
		case R1:	/* base register must be R1 */
1552
			if (ip->base != 1)
1553
				goto badop;
1554
			break;
1555
		case RMB:	/* R/M field with byte register (/r)*/
1556
			if (igetc(map, ip, &c) < 0)
1557
				return 0;
1558
			if (modrm(map, ip, c) < 0)
1559
				return 0;
1560
			ip->osize = 'B';
1561
			break;
1562
		case RM:	/* R/M field with register (/r) */
1563
			if (igetc(map, ip, &c) < 0)
1564
				return 0;
1565
			if (modrm(map, ip, c) < 0)
1566
				return 0;
1567
			break;
1568
		case RMOPB:	/* R/M field with op code (/digit) */
1569
			if (igetc(map, ip, &c) < 0)
1570
				return 0;
1571
			if (modrm(map, ip, c) < 0)
1572
				return 0;
1573
			c = ip->reg;		/* secondary op code */
1574
			obase = (Optable*)op->proto;
1575
			ip->osize = 'B';
1576
			goto newop;
1577
		case RMOP:	/* R/M field with op code (/digit) */
1578
			if (igetc(map, ip, &c) < 0)
1579
				return 0;
1580
			if (modrm(map, ip, c) < 0)
1581
				return 0;
1582
			obase = (Optable*)op->proto;
1583
			if(ip->amd64 && obase == optab0F01 && c == 0xF8)
1584
				return optab0F01F8;
1585
			c = ip->reg;
1586
			goto newop;
1587
		case FRMOP:	/* FP R/M field with op code (/digit) */
1588
			if (igetc(map, ip, &c) < 0)
1589
				return 0;
1590
			if (modrm(map, ip, c) < 0)
1591
				return 0;
1592
			if ((c&0xc0) == 0xc0)
1593
				c = ip->reg+8;		/* 16 entry table */
1594
			else
1595
				c = ip->reg;
1596
			obase = (Optable*)op->proto;
1597
			goto newop;
1598
		case FRMEX:	/* Extended FP R/M field with op code (/digit) */
1599
			if (igetc(map, ip, &c) < 0)
1600
				return 0;
1601
			if (modrm(map, ip, c) < 0)
1602
				return 0;
1603
			if ((c&0xc0) == 0xc0)
1604
				c = (c&0x3f)+8;		/* 64-entry table */
1605
			else
1606
				c = ip->reg;
1607
			obase = (Optable*)op->proto;
1608
			goto newop;
1609
		case RMR:	/* R/M register only (mod = 11) */
1610
			if (igetc(map, ip, &c) < 0)
1611
				return 0;
1612
			if ((c&0xc0) != 0xc0) {
1613
				werrstr("invalid R/M register: %x", c);
1614
				return 0;
1615
			}
1616
			if (modrm(map, ip, c) < 0)
1617
				return 0;
1618
			break;
1619
		case RMM:	/* R/M register only (mod = 11) */
1620
			if (igetc(map, ip, &c) < 0)
1621
				return 0;
1622
			if ((c&0xc0) == 0xc0) {
1623
				werrstr("invalid R/M memory mode: %x", c);
1624
				return 0;
1625
			}
1626
			if (modrm(map, ip, c) < 0)
1627
				return 0;
1628
			break;
1629
		case PTR:	/* Seg:Displacement addr (ptr16:16 or ptr16:32) */
1630
			if (ip->osize == 'L') {
1631
				if (igetl(map, ip, &ip->disp) < 0)
1632
					return 0;
1633
			} else {
1634
				if (igets(map, ip, &s)< 0)
1635
					return 0;
1636
				ip->disp = s&0xffff;
1637
			}
1638
			if (igets(map, ip, (ushort*)&ip->seg) < 0)
1639
				return 0;
1640
			ip->jumptype = PTR;
1641
			break;
1642
		case AUXMM:	/* Multi-byte op code; prefix determines table selection */
1643
			if (igetc(map, ip, &c) < 0)
1644
				return 0;
1645
			obase = (Optable*)op->proto;
1646
			switch (ip->opre) {
1647
			case 0x66:	op = optab660F; break;
1648
			case 0xF2:	op = optabF20F; break;
1649
			case 0xF3:	op = optabF30F; break;
1650
			default:	op = nil; break;
1651
			}
1652
			if(op != nil && op[c].proto != nil)
1653
				obase = op;
1654
			norex = 1;	/* no more rex prefixes */
1655
			/* otherwise the optab entry captures it */
1656
			goto newop;
1657
		case AUX:	/* Multi-byte op code - Auxiliary table */
1658
			obase = (Optable*)op->proto;
1659
			if (igetc(map, ip, &c) < 0)
1660
				return 0;
1661
			goto newop;
1662
		case OPRE:	/* Instr Prefix or media op */
1663
			ip->opre = c;
1664
			/* fall through */
1665
		case PRE:	/* Instr Prefix */
1666
			ip->prefix = (char*)op->proto;
1667
			if (igetc(map, ip, &c) < 0)
1668
				return 0;
1669
			if (ip->opre && c == 0x0F)
1670
				ip->prefix = 0;
1671
			goto newop;
1672
		case SEG:	/* Segment Prefix */
1673
			ip->segment = (char*)op->proto;
1674
			if (igetc(map, ip, &c) < 0)
1675
				return 0;
1676
			goto newop;
1677
		case OPOVER:	/* Operand size override */
1678
			ip->opre = c;
1679
			ip->osize = 'W';
1680
			if (igetc(map, ip, &c) < 0)
1681
				return 0;
1682
			if (c == 0x0F)
1683
				ip->osize = 'L';
1684
			else if (ip->amd64 && (c&0xF0) == 0x40)
1685
				ip->osize = 'Q';
1686
			goto newop;
1687
		case ADDOVER:	/* Address size override */
1688
			ip->asize = 0;
1689
			if (igetc(map, ip, &c) < 0)
1690
				return 0;
1691
			goto newop;
1692
		case JUMP:	/* mark instruction as JUMP or RET */
1693
		case RET:
1694
			ip->jumptype = op->operand[i];
1695
			break;
1696
		default:
1697
			werrstr("bad operand type %d", op->operand[i]);
1698
			return 0;
1699
		}
1700
	}
1701
	return op;
1702
}
1703
 
1704
#pragma	varargck	argpos	bprint		2
1705
 
1706
static void
1707
bprint(Instr *ip, char *fmt, ...)
1708
{
1709
	va_list arg;
1710
 
1711
	va_start(arg, fmt);
1712
	ip->curr = vseprint(ip->curr, ip->end, fmt, arg);
1713
	va_end(arg);
1714
}
1715
 
1716
/*
1717
 *  if we want to call 16 bit regs AX,BX,CX,...
1718
 *  and 32 bit regs EAX,EBX,ECX,... then
1719
 *  change the defs of ANAME and ONAME to:
1720
 *  #define	ANAME(ip)	((ip->asize == 'E' ? "E" : "")
1721
 *  #define	ONAME(ip)	((ip)->osize == 'L' ? "E" : "")
1722
 */
1723
#define	ANAME(ip)	""
1724
#define	ONAME(ip)	""
1725
 
1726
static char *reg[] =  {
1727
[AX]	"AX",
1728
[CX]	"CX",
1729
[DX]	"DX",
1730
[BX]	"BX",
1731
[SP]	"SP",
1732
[BP]	"BP",
1733
[SI]	"SI",
1734
[DI]	"DI",
1735
 
1736
	/* amd64 */
1737
[R8]	"R8",
1738
[R9]	"R9",
1739
[R10]	"R10",
1740
[R11]	"R11",
1741
[R12]	"R12",
1742
[R13]	"R13",
1743
[R14]	"R14",
1744
[R15]	"R15",
1745
};
1746
 
1747
static char *breg[] = { "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH" };
1748
static char *breg64[] = { "AL", "CL", "DL", "BL", "SPB", "BPB", "SIB", "DIB",
1749
	"R8B", "R9B", "R10B", "R11B", "R12B", "R13B", "R14B", "R15B" };
1750
static char *sreg[] = { "ES", "CS", "SS", "DS", "FS", "GS" };
1751
 
1752
static void
1753
plocal(Instr *ip)
1754
{
1755
	int ret;
1756
	long offset;
1757
	Symbol s;
1758
	char *reg;
1759
 
1760
	offset = ip->disp;
1761
	if (!findsym(ip->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s)) {
1762
		bprint(ip, "%lux(SP)", offset);
1763
		return;
1764
	}
1765
 
1766
	if (s.value > ip->disp) {
1767
		ret = getauto(&s, s.value-ip->disp-mach->szaddr, CAUTO, &s);
1768
		reg = "(SP)";
1769
	} else {
1770
		offset -= s.value;
1771
		ret = getauto(&s, offset, CPARAM, &s);
1772
		reg = "(FP)";
1773
	}
1774
	if (ret)
1775
		bprint(ip, "%s+", s.name);
1776
	else
1777
		offset = ip->disp;
1778
	bprint(ip, "%lux%s", offset, reg);
1779
}
1780
 
1781
static int
1782
isjmp(Instr *ip)
1783
{
1784
	switch(ip->jumptype){
1785
	case Iwds:
1786
	case Jbs:
1787
	case JUMP:
1788
		return 1;
1789
	default:
1790
		return 0;
1791
	}
1792
}
1793
 
1794
/*
1795
 * This is too smart for its own good, but it really is nice
1796
 * to have accurate translations when debugging, and it
1797
 * helps us identify which code is different in binaries that
1798
 * are changed on sources.
1799
 */
1800
static int
1801
issymref(Instr *ip, Symbol *s, long w, long val)
1802
{
1803
	Symbol next, tmp;
1804
	long isstring, size;
1805
 
1806
	if (isjmp(ip))
1807
		return 1;
1808
	if (s->class==CTEXT && w==0)
1809
		return 1;
1810
	if (s->class==CDATA) {
1811
		/* use first bss symbol (or "end") rather than edata */
1812
		if (s->name[0]=='e' && strcmp(s->name, "edata") == 0){
1813
			if((s ->index >= 0 && globalsym(&tmp, s->index+1) && tmp.value==s->value)
1814
			|| (s->index > 0 && globalsym(&tmp, s->index-1) && tmp.value==s->value))
1815
				*s = tmp;
1816
		}
1817
		if (w == 0)
1818
			return 1;
1819
		for (next=*s; next.value==s->value; next=tmp)
1820
			if (!globalsym(&tmp, next.index+1))
1821
				break;
1822
		size = next.value - s->value;
1823
		if (w >= size)
1824
			return 0;
1825
		if (w > size-w)
1826
			w = size-w;
1827
		/* huge distances are usually wrong except in .string */
1828
		isstring = (s->name[0]=='.' && strcmp(s->name, ".string") == 0);
1829
		if (w > 8192 && !isstring)
1830
			return 0;
1831
		/* medium distances are tricky - look for constants */
1832
		/* near powers of two */
1833
		if ((val&(val-1)) == 0 || (val&(val+1)) == 0)
1834
			return 0;
1835
		return 1;
1836
	}
1837
	return 0;
1838
}
1839
 
1840
static void
1841
immediate(Instr *ip, vlong val)
1842
{
1843
	Symbol s;
1844
	long w;
1845
 
1846
	if (findsym(val, CANY, &s)) {		/* TO DO */
1847
		w = val - s.value;
1848
		if (w < 0)
1849
			w = -w;
1850
		if (issymref(ip, &s, w, val)) {
1851
			if (w)
1852
				bprint(ip, "%s+%lux(SB)", s.name, w);
1853
			else
1854
				bprint(ip, "%s(SB)", s.name);
1855
			return;
1856
		}
1857
/*
1858
		if (s.class==CDATA && globalsym(&s, s.index+1)) {
1859
			w = s.value - val;
1860
			if (w < 0)
1861
				w = -w;
1862
			if (w < 4096) {
1863
				bprint(ip, "%s-%lux(SB)", s.name, w);
1864
				return;
1865
			}
1866
		}
1867
*/
1868
	}
1869
	if((ip->rex & REXW) == 0)
1870
		bprint(ip, "%lux", (long)val);
1871
	else
1872
		bprint(ip, "%llux", val);
1873
}
1874
 
1875
static void
1876
pea(Instr *ip)
1877
{
1878
	if (ip->mod == 3) {
1879
		if (ip->osize == 'B')
1880
			bprint(ip, (ip->rex & REXB? breg64: breg)[ip->base]);
1881
		else if(ip->rex & REXB)
1882
			bprint(ip, "%s%s", ANAME(ip), reg[ip->base+8]);
1883
		else
1884
			bprint(ip, "%s%s", ANAME(ip), reg[ip->base]);
1885
		return;
1886
	}
1887
	if (ip->segment)
1888
		bprint(ip, ip->segment);
1889
	if (ip->asize == 'E' && ip->base == SP)
1890
		plocal(ip);
1891
	else {
1892
		if (ip->base < 0)
1893
			immediate(ip, ip->disp);
1894
		else {
1895
			bprint(ip, "%lux", ip->disp);
1896
			if(ip->rip)
1897
				bprint(ip, "(RIP)");
1898
			bprint(ip,"(%s%s)", ANAME(ip), reg[ip->rex&REXB? ip->base+8: ip->base]);
1899
		}
1900
	}
1901
	if (ip->index >= 0)
1902
		bprint(ip,"(%s%s*%d)", ANAME(ip), reg[ip->rex&REXX? ip->index+8: ip->index], 1<<ip->ss);
1903
}
1904
 
1905
static void
1906
prinstr(Instr *ip, char *fmt)
1907
{
1908
	vlong v;
1909
 
1910
	if (ip->prefix)
1911
		bprint(ip, "%s ", ip->prefix);
1912
	for (; *fmt && ip->curr < ip->end; fmt++) {
1913
		if (*fmt != '%'){
1914
			*ip->curr++ = *fmt;
1915
			continue;
1916
		}
1917
		switch(*++fmt){
1918
		case '%':
1919
			*ip->curr++ = '%';
1920
			break;
1921
		case 'A':
1922
			bprint(ip, "%s", ANAME(ip));
1923
			break;
1924
		case 'C':
1925
			bprint(ip, "CR%d", ip->reg);
1926
			break;
1927
		case 'D':
1928
			if (ip->reg < 4 || ip->reg == 6 || ip->reg == 7)
1929
				bprint(ip, "DR%d",ip->reg);
1930
			else
1931
				bprint(ip, "???");
1932
			break;
1933
		case 'I':
1934
			bprint(ip, "$");
1935
			immediate(ip, ip->imm2);
1936
			break;
1937
		case 'O':
1938
			bprint(ip,"%s", ONAME(ip));
1939
			break;
1940
		case 'i':
1941
			bprint(ip, "$");
1942
			v = ip->imm;
1943
			if(ip->rex & REXW)
1944
				v = ip->imm64;
1945
			immediate(ip, v);
1946
			break;
1947
		case 'R':
1948
			bprint(ip, "%s%s", ONAME(ip), reg[ip->rex&REXR? ip->reg+8: ip->reg]);
1949
			break;
1950
		case 'S':
1951
			if(ip->osize == 'Q' || ip->osize == 'L' && ip->rex & REXW)
1952
				bprint(ip, "Q");
1953
			else
1954
				bprint(ip, "%c", ip->osize);
1955
			break;
1956
		case 's':
1957
			if(ip->opre == 0 || ip->opre == 0x66)
1958
				bprint(ip, "P");
1959
			else
1960
				bprint(ip, "S");
1961
			if(ip->opre == 0xf2 || ip->opre == 0x66)
1962
				bprint(ip, "D");
1963
			else
1964
				bprint(ip, "S");
1965
			break;
1966
		case 'T':
1967
			if (ip->reg == 6 || ip->reg == 7)
1968
				bprint(ip, "TR%d",ip->reg);
1969
			else
1970
				bprint(ip, "???");
1971
			break;
1972
		case 'W':
1973
			if (ip->osize == 'Q' || ip->osize == 'L' && ip->rex & REXW)
1974
				bprint(ip, "CDQE");
1975
			else if (ip->osize == 'L')
1976
				bprint(ip,"CWDE");
1977
			else
1978
				bprint(ip, "CBW");
1979
			break;
1980
		case 'd':
1981
			bprint(ip,"%ux:%lux",ip->seg,ip->disp);
1982
			break;
1983
		case 'm':
1984
			if (ip->mod == 3 && ip->osize != 'B') {
1985
				if(fmt[1] != '*'){
1986
					if(ip->opre != 0) {
1987
						bprint(ip, "X%d", ip->rex&REXB? ip->base+8: ip->base);
1988
						break;
1989
					}
1990
				} else
1991
					fmt++;
1992
				bprint(ip, "M%d", ip->base);
1993
				break;
1994
			}
1995
			pea(ip);
1996
			break;
1997
		case 'e':
1998
			pea(ip);
1999
			break;
2000
		case 'f':
2001
			bprint(ip, "F%d", ip->base);
2002
			break;
2003
		case 'g':
2004
			if (ip->reg < 6)
2005
				bprint(ip,"%s",sreg[ip->reg]);
2006
			else
2007
				bprint(ip,"???");
2008
			break;
2009
		case 'p':
2010
			/*
2011
			 * signed immediate in the ulong ip->imm.
2012
			 */
2013
			v = (long)ip->imm;
2014
			immediate(ip, v+ip->addr+ip->n);
2015
			break;
2016
		case 'r':
2017
			if (ip->osize == 'B')
2018
				bprint(ip,"%s", (ip->rex? breg64: breg)[ip->rex&REXR? ip->reg+8: ip->reg]);
2019
			else
2020
				bprint(ip, reg[ip->rex&REXR? ip->reg+8: ip->reg]);
2021
			break;
2022
		case 'w':
2023
			if (ip->osize == 'Q' || ip->rex & REXW)
2024
				bprint(ip, "CQO");
2025
			else if (ip->osize == 'L')
2026
				bprint(ip,"CDQ");
2027
			else
2028
				bprint(ip, "CWD");
2029
			break;
2030
		case 'M':
2031
			if(ip->opre != 0)
2032
				bprint(ip, "X%d", ip->rex&REXR? ip->reg+8: ip->reg);
2033
			else
2034
				bprint(ip, "M%d", ip->reg);
2035
			break;
2036
		case 'x':
2037
			if (ip->mod == 3 && ip->osize != 'B') {
2038
				bprint(ip, "X%d", ip->rex&REXB? ip->base+8: ip->base);
2039
				break;
2040
			}
2041
			pea(ip);
2042
			break;
2043
		case 'X':
2044
			bprint(ip, "X%d", ip->rex&REXR? ip->reg+8: ip->reg);
2045
			break;
2046
		default:
2047
			bprint(ip, "%%%c", *fmt);
2048
			break;
2049
		}
2050
	}
2051
	*ip->curr = 0;		/* there's always room for 1 byte */
2052
}
2053
 
2054
static int
2055
i386inst(Map *map, uvlong pc, char modifier, char *buf, int n)
2056
{
2057
	Instr instr;
2058
	Optable *op;
2059
 
2060
	USED(modifier);
2061
	op = mkinstr(map, &instr, pc);
2062
	if (op == 0) {
2063
		errstr(buf, n);
2064
		return -1;
2065
	}
2066
	instr.curr = buf;
2067
	instr.end = buf+n-1;
2068
	prinstr(&instr, op->proto);
2069
	return instr.n;
2070
}
2071
 
2072
static int
2073
i386das(Map *map, uvlong pc, char *buf, int n)
2074
{
2075
	Instr instr;
2076
	int i;
2077
 
2078
	if (mkinstr(map, &instr, pc) == 0) {
2079
		errstr(buf, n);
2080
		return -1;
2081
	}
2082
	for(i = 0; i < instr.n && n > 2; i++) {
2083
		_hexify(buf, instr.mem[i], 1);
2084
		buf += 2;
2085
		n -= 2;
2086
	}
2087
	*buf = 0;
2088
	return instr.n;
2089
}
2090
 
2091
static int
2092
i386instlen(Map *map, uvlong pc)
2093
{
2094
	Instr i;
2095
 
2096
	if (mkinstr(map, &i, pc))
2097
		return i.n;
2098
	return -1;
2099
}
2100
 
2101
static int
2102
i386foll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
2103
{
2104
	Instr i;
2105
	Optable *op;
2106
	ushort s;
2107
	uvlong l, addr;
2108
	vlong v;
2109
	int n;
2110
 
2111
	op = mkinstr(map, &i, pc);
2112
	if (!op)
2113
		return -1;
2114
 
2115
	n = 0;
2116
 
2117
	switch(i.jumptype) {
2118
	case RET:		/* RETURN or LEAVE */
2119
	case Iw:		/* RETURN */
2120
		if (strcmp(op->proto, "LEAVE") == 0) {
2121
			if (geta(map, (*rget)(map, "BP"), &l) < 0)
2122
				return -1;
2123
		} else if (geta(map, (*rget)(map, mach->sp), &l) < 0)
2124
			return -1;
2125
		foll[0] = l;
2126
		return 1;
2127
	case Iwds:		/* pc relative JUMP or CALL*/
2128
	case Jbs:		/* pc relative JUMP or CALL */
2129
		v = (long)i.imm;
2130
		foll[0] = pc+v+i.n;
2131
		n = 1;
2132
		break;
2133
	case PTR:		/* seg:displacement JUMP or CALL */
2134
		foll[0] = (i.seg<<4)+i.disp;
2135
		return 1;
2136
	case JUMP:		/* JUMP or CALL EA */
2137
 
2138
		if(i.mod == 3) {
2139
			foll[0] = (*rget)(map, reg[i.rex&REXB? i.base+8: i.base]);
2140
			return 1;
2141
		}
2142
			/* calculate the effective address */
2143
		addr = i.disp;
2144
		if (i.base >= 0) {
2145
			if (geta(map, (*rget)(map, reg[i.rex&REXB? i.base+8: i.base]), &l) < 0)
2146
				return -1;
2147
			addr += l;
2148
		}
2149
		if (i.index >= 0) {
2150
			if (geta(map, (*rget)(map, reg[i.rex&REXX? i.index+8: i.index]), &l) < 0)
2151
				return -1;
2152
			addr += l*(1<<i.ss);
2153
		}
2154
			/* now retrieve a seg:disp value at that address */
2155
		if (get2(map, addr, &s) < 0)			/* seg */
2156
			return -1;
2157
		foll[0] = s<<4;
2158
		addr += 2;
2159
		if (i.asize == 'L') {
2160
			if (geta(map, addr, &l) < 0)		/* disp32 */
2161
				return -1;
2162
			foll[0] += l;
2163
		} else {					/* disp16 */
2164
			if (get2(map, addr, &s) < 0)
2165
				return -1;
2166
			foll[0] += s;
2167
		}
2168
		return 1;
2169
	default:
2170
		break;
2171
	}		
2172
	if (strncmp(op->proto,"JMP", 3) == 0 || strncmp(op->proto,"CALL", 4) == 0)
2173
		return 1;
2174
	foll[n++] = pc+i.n;
2175
	return n;
2176
}