aboutsummaryrefslogtreecommitdiff
path: root/i386-asm.c
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2016-06-29 15:57:32 +0200
committerMichael Matz <matz@suse.de>2016-12-15 17:47:07 +0100
commit8e4da42384164d6eb862665d907b3b1138da2f94 (patch)
treefe7ac034c9839d95f9c2580f6e6d2b54b4743cdd /i386-asm.c
parentc82e52d55bd31eea943c616ad780f27e5ab9dc7a (diff)
downloadtinycc-8e4da42384164d6eb862665d907b3b1138da2f94.tar.gz
tinycc-8e4da42384164d6eb862665d907b3b1138da2f94.tar.bz2
Accept more asm expressions
In particular subtracting a defined symbol from current section makes the value PC relative, and .org accepts symbolic expressions as well, if the symbol is from the current section.
Diffstat (limited to 'i386-asm.c')
-rw-r--r--i386-asm.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/i386-asm.c b/i386-asm.c
index e7449bf..064b8aa 100644
--- a/i386-asm.c
+++ b/i386-asm.c
@@ -356,8 +356,7 @@ static void parse_operand(TCCState *s1, Operand *op)
next();
asm_expr(s1, &e);
op->type = OP_IM32;
- op->e.v = e.v;
- op->e.sym = e.sym;
+ op->e = e;
if (!op->e.sym) {
if (op->e.v == (uint8_t)op->e.v)
op->type |= OP_IM8;
@@ -378,8 +377,7 @@ static void parse_operand(TCCState *s1, Operand *op)
op->shift = 0;
if (tok != '(') {
asm_expr(s1, &e);
- op->e.v = e.v;
- op->e.sym = e.sym;
+ op->e = e;
} else {
next();
if (tok == '%') {
@@ -395,6 +393,7 @@ static void parse_operand(TCCState *s1, Operand *op)
op->e.v = e.v;
op->e.sym = e.sym;
}
+ op->e.pcrel = 0;
}
if (tok == '(') {
int type = 0;
@@ -425,7 +424,12 @@ static void parse_operand(TCCState *s1, Operand *op)
/* XXX: unify with C code output ? */
ST_FUNC void gen_expr32(ExprValue *pe)
{
- gen_addr32(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
+ if (pe->pcrel)
+ /* If PC-relative, always set VT_SYM, even without symbol,
+ so as to force a relocation to be emitted. */
+ gen_addrpc32(VT_SYM, pe->sym, pe->v);
+ else
+ gen_addr32(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
}
#ifdef TCC_TARGET_X86_64