Skip to content

Commit

Permalink
Parse segment register on x64
Browse files Browse the repository at this point in the history
`mov %fs:0,%rax`
  • Loading branch information
tyfkda committed Mar 28, 2024
1 parent c99f3df commit e7e5cee
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 0 deletions.
19 changes: 19 additions & 0 deletions src/as/asm_x86.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
13 changes: 13 additions & 0 deletions src/as/inst.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,14 @@ enum RegType {
R15,

RIP,

// Segment register
CS,
DS,
ES,
FS,
GS,
SS,
};

enum RegXmmType {
Expand Down Expand Up @@ -237,6 +245,7 @@ enum OperandType {
DEREF_INDIRECT, // *ofs(%rax)
DEREF_INDIRECT_WITH_INDEX, // *(%rax, %rcx, 4)
REG_XMM,
SEGMENT_OFFSET,
};

enum ExprKind {
Expand Down Expand Up @@ -292,6 +301,10 @@ typedef struct {
Reg index_reg;
} indirect_with_index;
enum RegXmmType regxmm;
struct {
enum RegType reg;
Expr *offset;
} segment;
};
} Operand;

Expand Down
23 changes: 23 additions & 0 deletions src/as/parse_asm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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] = {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)) {
Expand Down

0 comments on commit e7e5cee

Please sign in to comment.