aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbellard <bellard>2005-09-03 22:03:39 +0000
committerbellard <bellard>2005-09-03 22:03:39 +0000
commit3ba1190eb4b7ec2f1ec6be6aa1e983f051313796 (patch)
tree9cf8e324d38000e2ed560dd28b529e6cd54e2b56
parent6f8b8887b14546f2e838dc90ad92677275663019 (diff)
downloadtinycc-3ba1190eb4b7ec2f1ec6be6aa1e983f051313796.tar.gz
tinycc-3ba1190eb4b7ec2f1ec6be6aa1e983f051313796.tar.bz2
segment override prefix support (Filip Navara)
-rw-r--r--i386-asm.c28
1 files changed, 26 insertions, 2 deletions
diff --git a/i386-asm.c b/i386-asm.c
index 5c7c1de..80184a7 100644
--- a/i386-asm.c
+++ b/i386-asm.c
@@ -151,6 +151,15 @@ static const uint8_t test_bits[NB_TEST_OPCODES] = {
0x0f, /* g */
};
+static const uint8_t segment_prefixes[] = {
+ 0x26, /* es */
+ 0x2e, /* cs */
+ 0x36, /* ss */
+ 0x3e, /* ds */
+ 0x64, /* fs */
+ 0x65 /* gs */
+};
+
static const ASMInstr asm_instrs[] = {
#define ALT(x) x
#define DEF_ASM_OP0(name, opcode)
@@ -410,14 +419,15 @@ static inline void asm_modrm(int reg, Operand *op)
static void asm_opcode(TCCState *s1, int opcode)
{
const ASMInstr *pa;
- int i, modrm_index, reg, v, op1, is_short_jmp;
+ int i, modrm_index, reg, v, op1, is_short_jmp, has_seg_prefix;
int nb_ops, s, ss;
- Operand ops[MAX_OPERANDS], *pop;
+ Operand ops[MAX_OPERANDS], *pop, seg_prefix;
int op_type[3]; /* decoded op type */
/* get operands */
pop = ops;
nb_ops = 0;
+ has_seg_prefix = 0;
for(;;) {
if (tok == ';' || tok == TOK_LINEFEED)
break;
@@ -425,6 +435,18 @@ static void asm_opcode(TCCState *s1, int opcode)
error("incorrect number of operands");
}
parse_operand(s1, pop);
+ if (tok == ':') {
+ if (pop->type != OP_SEG || has_seg_prefix) {
+ error("incorrect prefix");
+ }
+ seg_prefix = *pop;
+ has_seg_prefix = 1;
+ next();
+ parse_operand(s1, pop);
+ if (!(pop->type & OP_EA)) {
+ error("segment prefix must be followed by memory reference");
+ }
+ }
pop++;
nb_ops++;
if (tok != ',')
@@ -538,6 +560,8 @@ static void asm_opcode(TCCState *s1, int opcode)
/* now generates the operation */
if (pa->instr_type & OPC_FWAIT)
g(0x9b);
+ if (has_seg_prefix)
+ g(segment_prefixes[seg_prefix.reg]);
v = pa->opcode;
if (v == 0x69 || v == 0x69) {