[libcpu] [422] x86: Decoding for opcode 0xe8 ("call")

92 views
Skip to first unread message

lib...@gh11.de

unread,
Apr 25, 2010, 8:54:20 AM4/25/10
to lib...@googlegroups.com
Revision
422
Author
penberg
Date
2010-04-25 05:54:16 -0700 (Sun, 25 Apr 2010)

Log Message

x86: Decoding for opcode 0xe8 ("call")

Signed-off-by: Pekka Enberg <pen...@cs.helsinki.fi>

Modified Paths

Diff

Modified: trunk/arch/x86/x86_decode.cpp (421 => 422)


--- trunk/arch/x86/x86_decode.cpp	2010-04-25 12:20:07 UTC (rev 421)
+++ trunk/arch/x86/x86_decode.cpp	2010-04-25 12:54:16 UTC (rev 422)
@@ -246,7 +246,7 @@
 	/*[0xE5]*/	0,
 	/*[0xE6]*/	0,
 	/*[0xE7]*/	0,
-	/*[0xE8]*/	0,
+	/*[0xE8]*/	INSTR_CALL | ADDMODE_REL | WIDTH_FULL,
 	/*[0xE9]*/	0,
 	/*[0xEA]*/	0,
 	/*[0xEB]*/	0,
@@ -346,6 +346,10 @@
 	switch (instr->flags & SRC_MASK) {
 	case SRC_NONE:
 		break;
+	case SRC_REL:
+		operand->type	= OP_REL;
+		operand->rel	= instr->rel_data;
+		break;
 	case SRC_IMM:
 	case SRC_IMM8:
 		operand->type	= OP_IMM;
@@ -372,6 +376,20 @@
 }
 
 static void
+decode_rel(struct x86_instr *instr, uint8_t* RAM, addr_t *pc)
+{
+	addr_t new_pc = *pc;
+
+	uint8_t imm_lo = RAM[new_pc++];
+	uint8_t imm_hi = RAM[new_pc++];
+
+	instr->imm_data	= (int16_t)((imm_hi << 8) | imm_lo);
+	instr->nr_bytes	+= 2;
+
+	*pc = new_pc;
+}
+
+static void
 decode_imm_full(struct x86_instr *instr, uint8_t* RAM, addr_t *pc)
 {
 	addr_t new_pc = *pc;
@@ -415,6 +433,15 @@
 }
 
 static void
+decode_imm_rel(struct x86_instr *instr, uint8_t* RAM, addr_t *pc)
+{
+	if (instr->flags & IMM_MASK)
+		decode_imm(instr, RAM, pc);
+	else
+		decode_rel(instr, RAM, pc);
+}
+
+static void
 decode_disp(struct x86_instr *instr, uint8_t* RAM, addr_t *pc)
 {
 	addr_t new_pc = *pc;
@@ -531,8 +558,8 @@
 	if (instr->flags & MEM_DISP_MASK)
 		decode_disp(instr, RAM, &pc);
 
-	if (instr->flags & IMM_MASK)
-		decode_imm(instr, RAM, &pc);
+	if (instr->flags & (IMM_MASK|REL_MASK))
+		decode_imm_rel(instr, RAM, &pc);
 
 	decode_src_operand(instr);
 

Modified: trunk/arch/x86/x86_decode.h (421 => 422)


--- trunk/arch/x86/x86_decode.h	2010-04-25 12:20:07 UTC (rev 421)
+++ trunk/arch/x86/x86_decode.h	2010-04-25 12:54:16 UTC (rev 422)
@@ -12,10 +12,11 @@
 #include <stdint.h>
 
 enum x86_operand_type {
-	OP_REG,
 	OP_IMM,
 	OP_MEM,
 	OP_MEM_DISP,
+	OP_REG,
+	OP_REL,
 };
 
 enum x86_seg_override {
@@ -36,7 +37,10 @@
 	enum x86_operand_type	type;
 	uint8_t			reg;
 	int32_t			disp;		/* address displacement can be negative */
-	uint32_t		imm;
+	union {
+		uint32_t		imm;
+		int32_t			rel;
+	};
 };
 
 enum x86_instr_flags {
@@ -55,20 +59,23 @@
 	SRC_IMM8		= (1U << 14),
 	IMM_MASK		= SRC_IMM|SRC_IMM8,
 
-	SRC_REG			= (1U << 15),
-	SRC_ACC			= (1U << 16),
-	SRC_MEM			= (1U << 17),
-	SRC_MEM_DISP_BYTE	= (1U << 18),
-	SRC_MEM_DISP_FULL	= (1U << 19),
-	SRC_MASK		= SRC_NONE|SRC_IMM|SRC_IMM8|SRC_REG|SRC_ACC|SRC_MEM|SRC_MEM_DISP_BYTE|SRC_MEM_DISP_FULL,
+	SRC_REL			= (1U << 15),
+	REL_MASK		= SRC_REL,
 
+	SRC_REG			= (1U << 16),
+	SRC_ACC			= (1U << 17),
+	SRC_MEM			= (1U << 18),
+	SRC_MEM_DISP_BYTE	= (1U << 19),
+	SRC_MEM_DISP_FULL	= (1U << 20),
+	SRC_MASK		= SRC_NONE|IMM_MASK|REL_MASK|SRC_REG|SRC_ACC|SRC_MEM|SRC_MEM_DISP_BYTE|SRC_MEM_DISP_FULL,
+
 	/* Destination operand */
-	DST_NONE		= (1U << 20),
-	DST_REG			= (1U << 21),
-	DST_ACC			= (1U << 22),	/* AL/AX */
-	DST_MEM			= (1U << 23),
-	DST_MEM_DISP_BYTE	= (1U << 24),	/* 8 bits */
-	DST_MEM_DISP_FULL	= (1U << 25),	/* 16 bits or 32 bits */
+	DST_NONE		= (1U << 21),
+	DST_REG			= (1U << 22),
+	DST_ACC			= (1U << 23),	/* AL/AX */
+	DST_MEM			= (1U << 24),
+	DST_MEM_DISP_BYTE	= (1U << 25),	/* 8 bits */
+	DST_MEM_DISP_FULL	= (1U << 26),	/* 16 bits or 32 bits */
 	DST_MASK		= DST_NONE|DST_REG|DST_ACC|DST_MEM|DST_MEM_DISP_BYTE|DST_MEM_DISP_FULL,
 
 	MEM_DISP_MASK		= SRC_MEM_DISP_BYTE|SRC_MEM_DISP_FULL|DST_MEM_DISP_BYTE|DST_MEM_DISP_FULL,
@@ -81,13 +88,14 @@
 	ADDMODE_ACC_MEM		= SRC_ACC|DST_MEM|DIR_REVERSED,	/* AL/AX -> memory */
 	ADDMODE_ACC_REG		= SRC_ACC|DST_REG,		/* AL/AX -> reg */
 	ADDMODE_IMM		= SRC_IMM|DST_NONE,		/* immediate operand */
+	ADDMODE_IMM8_RM		= SRC_IMM8|MOD_RM|DIR_REVERSED,	/* immediate -> register/memory */
 	ADDMODE_IMM_ACC		= SRC_IMM|DST_ACC,		/* immediate -> AL/AX */
 	ADDMODE_IMM_REG		= SRC_IMM|DST_REG,		/* immediate -> register */
-	ADDMODE_IMM8_RM		= SRC_IMM8|MOD_RM|DIR_REVERSED,	/* immediate -> register/memory */
 	ADDMODE_IMPLIED		= SRC_NONE|DST_NONE,		/* no operands */
 	ADDMODE_MEM_ACC		= SRC_ACC|DST_MEM,		/* memory -> AL/AX */
 	ADDMODE_REG		= SRC_REG|DST_NONE,		/* register */
 	ADDMODE_REG_RM		= SRC_REG|MOD_RM|DIR_REVERSED,	/* register -> register/memory */
+	ADDMODE_REL		= SRC_REL|DST_NONE,		/* relative */
 	ADDMODE_RM_REG		= DST_REG|MOD_RM,		/* register/memory -> register */
 };
 
@@ -100,7 +108,10 @@
 	uint8_t			rm;		/* R/M */
 	uint8_t			reg_opc;	/* Reg/Opcode */
 	uint32_t		disp;		/* Address displacement */
-	uint32_t		imm_data;	/* Immediate data */
+	union {
+		uint32_t		imm_data;	/* Immediate data */
+		int32_t			rel_data;	/* Relative address data */
+	};
 
 	unsigned long		type;		/* See enum x86_instr_types */
 	unsigned long		flags;		/* See enum x86_instr_flags */

Modified: trunk/arch/x86/x86_disasm.cpp (421 => 422)


--- trunk/arch/x86/x86_disasm.cpp	2010-04-25 12:20:07 UTC (rev 421)
+++ trunk/arch/x86/x86_disasm.cpp	2010-04-25 12:54:16 UTC (rev 422)
@@ -200,7 +200,7 @@
 }
 
 static int
-print_operand(char *operands, size_t size, struct x86_instr *instr, struct x86_operand *operand)
+print_operand(addr_t pc, char *operands, size_t size, struct x86_instr *instr, struct x86_operand *operand)
 {
 	int ret = 0;
 
@@ -208,6 +208,9 @@
 	case OP_IMM:
 		ret = snprintf(operands, size, "$0x%x", operand->imm);
 		break;
+	case OP_REL:
+		ret = snprintf(operands, size, "%x", (unsigned int)((long)pc + instr->nr_bytes + operand->rel));
+		break;
 	case OP_REG:
 		ret = snprintf(operands, size, "%s", to_reg_name(instr, operand->reg));
 		break;
@@ -237,13 +240,13 @@
 
 	/* AT&T syntax operands */
 	if (!(instr.flags & SRC_NONE))
-		len += print_operand(operands+len, sizeof(operands)-len, &instr, &instr.src);
+		len += print_operand(pc, operands+len, sizeof(operands)-len, &instr, &instr.src);
 
 	if (!(instr.flags & SRC_NONE) && !(instr.flags & DST_NONE))
 		len += snprintf(operands+len, sizeof(operands)-len, ",");
 
 	if (!(instr.flags & DST_NONE))
-		len += print_operand(operands+len, sizeof(operands)-len, &instr, &instr.dst);
+		len += print_operand(pc, operands+len, sizeof(operands)-len, &instr, &instr.dst);
 
         snprintf(line, max_line, "%s%s\t%s", prefix_names[instr.rep_prefix], to_mnemonic(&instr), operands);
 

Modified: trunk/test/bin/x86/i8086/i8086.S (421 => 422)


--- trunk/test/bin/x86/i8086/i8086.S	2010-04-25 12:20:07 UTC (rev 421)
+++ trunk/test/bin/x86/i8086/i8086.S	2010-04-25 12:54:16 UTC (rev 422)
@@ -1,5 +1,13 @@
+# This test case is not runnable, it simply attempts to cover as much of the
+# x86 instruction set encoding as possible.
 	.code16gcc
 	.text
+
+	.globl function_0
+	.type  function_0, @function
+function_0:
+	retw
+
 	.globl  _start
 	.type   _start, @function
 _start:
@@ -412,3 +420,15 @@
 
 	# 0xd7
 	xlat
+
+	# 0xe8
+	callw function_0
+	callw function_1
+
+	nop
+	nop
+
+	.globl function_1
+	.type  function_1, @function
+function_1:
+	retw

Modified: trunk/test/bin/x86/i8086/i8086.bin


(Binary files differ)


 
--
Subscription settings: http://groups.google.com/group/libcpu/subscribe?hl=en
Reply all
Reply to author
Forward
0 new messages