diff --git a/src/as/asm_x86.c b/src/as/asm_x86.c index 6d6636e2f..7c39672cc 100644 --- a/src/as/asm_x86.c +++ b/src/as/asm_x86.c @@ -269,6 +269,24 @@ static unsigned char *asm_mov_rd(Inst *inst, Code *code) { return p; } +static unsigned char *asm_mov_sr(Inst *inst, Code *code) { + if (inst->src.segment.reg == FS && inst->dst.reg.size == REG64) { + Expr *offset = inst->src.segment.offset; + if (offset == NULL || offset->kind == EX_FIXNUM) { + uint64_t value = offset == NULL ? 0 : offset->fixnum; + short buf[] = { + 0x64, 0x48, 0x8b, 0x04, 0x25, + }; + unsigned char *p = code->buf; + p = put_code_filtered(p, buf, ARRAY_SIZE(buf)); + PUT_CODE(p, IM32(value)); + p += 4; + return p; + } + } + return NULL; +} + static unsigned char *asm_movbwlq_imi(Inst *inst, Code *code) { long offset = inst->dst.indirect.offset->fixnum; unsigned char sno = 0; @@ -1506,6 +1524,7 @@ static const AsmInstTable *table[] = { {asm_mov_iir, INDIRECT_WITH_INDEX, REG}, {asm_mov_dr, DIRECT, REG}, {asm_mov_rd, REG, DIRECT}, + {asm_mov_sr, SEGMENT_OFFSET, REG}, {NULL} }, [MOVB] = table_movbwlq, [MOVW] = table_movbwlq, [MOVL] = table_movbwlq, [MOVQ] = table_movbwlq, [MOVSX] = table_movszx, [MOVZX] = table_movszx, diff --git a/src/as/inst.h b/src/as/inst.h index 1d93d7c43..8694ee68f 100644 --- a/src/as/inst.h +++ b/src/as/inst.h @@ -205,6 +205,14 @@ enum RegType { R15, RIP, + + // Segment register + CS, + DS, + ES, + FS, + GS, + SS, }; enum RegXmmType { @@ -237,6 +245,7 @@ enum OperandType { DEREF_INDIRECT, // *ofs(%rax) DEREF_INDIRECT_WITH_INDEX, // *(%rax, %rcx, 4) REG_XMM, + SEGMENT_OFFSET, }; enum ExprKind { @@ -292,6 +301,10 @@ typedef struct { Reg index_reg; } indirect_with_index; enum RegXmmType regxmm; + struct { + enum RegType reg; + Expr *offset; + } segment; }; } Operand; diff --git a/src/as/parse_asm.c b/src/as/parse_asm.c index b6acef789..e4b887813 100644 --- a/src/as/parse_asm.c +++ b/src/as/parse_asm.c @@ -205,6 +205,13 @@ static const struct { {"r15", R15}, {"rip", RIP}, + + {"cs", CS}, + {"ds", DS}, + {"es", ES}, + {"fs", FS}, + {"gs", GS}, + {"ss", SS}, }; static const char kXmmRegisters[][6] = { @@ -258,6 +265,10 @@ inline bool is_reg64(enum RegType reg) { return reg >= RAX && reg <= R15; } +inline bool is_segment(enum RegType reg) { + return reg >= CS && reg <= SS; +} + static int find_match_index(const char **pp, const char **table, size_t count) { const char *p = *pp; const char *start = p; @@ -454,6 +465,18 @@ static enum RegType parse_direct_register(ParseInfo *info, Operand *operand) { } enum RegType reg = find_register(&info->p); + if (is_segment(reg)) { + Expr *offset = NULL; + if (*info->p == ':') { + ++info->p; + offset = parse_expr(info); + } + operand->type = SEGMENT_OFFSET; + operand->segment.reg = reg; + operand->segment.offset = offset; + return true; + } + enum RegSize size; int no; if (is_reg8(reg)) {