Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

x86: Decoding for opcode 0xc1 ("shift group 2")

Opcode 0xc1 is the full width version of opcode 0xc0.

Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
  • Loading branch information...
commit 4242395b35a7e661de802081f339bec299f5c436 1 parent 8974b61
@penberg penberg authored
View
50 arch/x86/x86_decode.cpp
@@ -206,8 +206,8 @@ static const uint32_t decode_table[256] = {
/*[0xBD]*/ INSTR_MOV | ADDMODE_IMM_REG | WIDTH_FULL,
/*[0xBE]*/ INSTR_MOV | ADDMODE_IMM_REG | WIDTH_FULL,
/*[0xBF]*/ INSTR_MOV | ADDMODE_IMM_REG | WIDTH_FULL,
- /*[0xC0]*/ INSTR_SHIFT_GRP2 | ADDMODE_IMM_RM | WIDTH_BYTE,
- /*[0xC1]*/ 0,
+ /*[0xC0]*/ INSTR_SHIFT_GRP2 | ADDMODE_IMM8_RM | WIDTH_BYTE,
+ /*[0xC0]*/ INSTR_SHIFT_GRP2 | ADDMODE_IMM8_RM | WIDTH_FULL,
/*[0xC2]*/ 0,
/*[0xC3]*/ INSTR_RET | ADDMODE_IMPLIED,
/*[0xC4]*/ 0,
@@ -347,6 +347,7 @@ decode_src_operand(struct x86_instr *instr)
case SRC_NONE:
break;
case SRC_IMM:
+ case SRC_IMM8:
operand->type = OP_IMM;
operand->imm = instr->imm_data;
break;
@@ -371,25 +372,46 @@ decode_src_operand(struct x86_instr *instr)
}
static void
-decode_imm(struct x86_instr *instr, uint8_t* RAM, addr_t *pc)
+decode_imm_full(struct x86_instr *instr, uint8_t* RAM, addr_t *pc)
{
addr_t new_pc = *pc;
- switch (instr->flags & WIDTH_MASK) {
- case WIDTH_FULL: {
- uint8_t imm_lo = RAM[new_pc++];
- uint8_t imm_hi = RAM[new_pc++];
+ uint8_t imm_lo = RAM[new_pc++];
+ uint8_t imm_hi = RAM[new_pc++];
- instr->imm_data = (uint16_t)((imm_hi << 8) | imm_lo);
- instr->nr_bytes += 2;
- break;
+ instr->imm_data = (uint16_t)((imm_hi << 8) | imm_lo);
+ instr->nr_bytes += 2;
+
+ *pc = new_pc;
+}
+
+static void
+decode_imm_byte(struct x86_instr *instr, uint8_t* RAM, addr_t *pc)
+{
+ addr_t new_pc = *pc;
+
+ instr->imm_data = (uint8_t)RAM[new_pc++];
+ instr->nr_bytes += 1;
+
+ *pc = new_pc;
+}
+
+static void
+decode_imm(struct x86_instr *instr, uint8_t* RAM, addr_t *pc)
+{
+ if (instr->flags & SRC_IMM8) {
+ decode_imm_byte(instr, RAM, pc);
+ return;
}
+
+ switch (instr->flags & WIDTH_MASK) {
+ case WIDTH_FULL:
+ decode_imm_full(instr, RAM, pc);
+ break;
case WIDTH_BYTE:
- instr->imm_data = (uint8_t)RAM[new_pc++];
- instr->nr_bytes += 1;
+ decode_imm_byte(instr, RAM, pc);
break;
}
- *pc = new_pc;
}
static void
@@ -509,7 +531,7 @@ arch_8086_decode_instr(struct x86_instr *instr, uint8_t* RAM, addr_t pc)
if (instr->flags & MEM_DISP_MASK)
decode_disp(instr, RAM, &pc);
- if (instr->flags & SRC_IMM)
+ if (instr->flags & IMM_MASK)
decode_imm(instr, RAM, &pc);
decode_src_operand(instr);
View
30 arch/x86/x86_decode.h
@@ -50,21 +50,25 @@ enum x86_instr_flags {
/* Source operand */
SRC_NONE = (1U << 12),
+
SRC_IMM = (1U << 13),
- SRC_REG = (1U << 14),
- SRC_ACC = (1U << 15),
- SRC_MEM = (1U << 16),
- SRC_MEM_DISP_BYTE = (1U << 17),
- SRC_MEM_DISP_FULL = (1U << 18),
- SRC_MASK = SRC_NONE|SRC_IMM|SRC_REG|SRC_ACC|SRC_MEM|SRC_MEM_DISP_BYTE|SRC_MEM_DISP_FULL,
+ 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,
/* Destination operand */
- DST_NONE = (1U << 19),
- DST_REG = (1U << 20),
- DST_ACC = (1U << 21), /* AL/AX */
- DST_MEM = (1U << 22),
- DST_MEM_DISP_BYTE = (1U << 23), /* 8 bits */
- DST_MEM_DISP_FULL = (1U << 24), /* 16 bits or 32 bits */
+ 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_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,
@@ -79,7 +83,7 @@ enum x86_addmode {
ADDMODE_IMM = SRC_IMM|DST_NONE, /* immediate operand */
ADDMODE_IMM_ACC = SRC_IMM|DST_ACC, /* immediate -> AL/AX */
ADDMODE_IMM_REG = SRC_IMM|DST_REG, /* immediate -> register */
- ADDMODE_IMM_RM = SRC_IMM|MOD_RM|DIR_REVERSED, /* immediate -> register/memory */
+ 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 */
View
25 test/bin/x86/i8086/i8086.S
@@ -364,7 +364,7 @@ _start:
xchgw %si, %ax
xchgw %di, %ax
- # 0xc0
+ # 0xc0 /digit ("shift group 2")
rolb $0x00, %al
rolb $0xff, %bh
@@ -387,5 +387,28 @@ _start:
shrb $0x00, %al
shrb $0xff, %bh
+ # 0xc1 /digit ("shift group 2")
+ rolw $0x00, %ax
+ rolw $0xff, %bx
+
+ rorw $0x00, %ax
+ rorw $0xff, %bx
+
+ rclw $0x00, %ax
+ rclw $0xff, %bx
+
+ rcrw $0x00, %ax
+ rcrw $0xff, %bx
+
+ sarw $0x00, %ax
+ sarw $0xff, %bx
+
+ # The sal and shl instructions perform the same operation.
+ shlw $0x00, %ax
+ shlw $0xff, %bx
+
+ shrw $0x00, %ax
+ shrw $0xff, %bx
+
# 0xd7
xlat
View
BIN  test/bin/x86/i8086/i8086.bin
Binary file not shown
Please sign in to comment.
Something went wrong with that request. Please try again.