forked from Mirrors/tinycc
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.master
parent
c82e52d55b
commit
8e4da42384
14
i386-asm.c
14
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
|
||||
|
|
1
tcc.h
1
tcc.h
|
@ -555,6 +555,7 @@ typedef struct CachedInclude {
|
|||
typedef struct ExprValue {
|
||||
uint64_t v;
|
||||
Sym *sym;
|
||||
int pcrel;
|
||||
} ExprValue;
|
||||
|
||||
#define MAX_ASM_OPERANDS 30
|
||||
|
|
55
tccasm.c
55
tccasm.c
|
@ -67,11 +67,13 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
|
|||
sym->type.t = VT_STATIC | VT_VOID;
|
||||
}
|
||||
}
|
||||
pe->v = 0;
|
||||
pe->sym = sym;
|
||||
pe->v = 0;
|
||||
pe->sym = sym;
|
||||
pe->pcrel = 0;
|
||||
} else if (*p == '\0') {
|
||||
pe->v = n;
|
||||
pe->sym = NULL;
|
||||
pe->pcrel = 0;
|
||||
} else {
|
||||
tcc_error("invalid number syntax");
|
||||
}
|
||||
|
@ -97,6 +99,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
|
|||
case TOK_LCHAR:
|
||||
pe->v = tokc.i;
|
||||
pe->sym = NULL;
|
||||
pe->pcrel = 0;
|
||||
next();
|
||||
break;
|
||||
case '(':
|
||||
|
@ -107,6 +110,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
|
|||
case '.':
|
||||
pe->v = 0;
|
||||
pe->sym = &sym_dot;
|
||||
pe->pcrel = 0;
|
||||
sym_dot.type.t = VT_VOID | VT_STATIC;
|
||||
sym_dot.r = cur_text_section->sh_num;
|
||||
sym_dot.jnext = ind;
|
||||
|
@ -125,9 +129,11 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
|
|||
/* if absolute symbol, no need to put a symbol value */
|
||||
pe->v = sym->jnext;
|
||||
pe->sym = NULL;
|
||||
pe->pcrel = 0;
|
||||
} else {
|
||||
pe->v = 0;
|
||||
pe->sym = sym;
|
||||
pe->pcrel = 0;
|
||||
}
|
||||
next();
|
||||
} else {
|
||||
|
@ -230,20 +236,21 @@ static inline void asm_expr_sum(TCCState *s1, ExprValue *pe)
|
|||
pe->v -= e2.v;
|
||||
/* NOTE: we are less powerful than gas in that case
|
||||
because we store only one symbol in the expression */
|
||||
if (!pe->sym && !e2.sym) {
|
||||
/* OK */
|
||||
} else if (pe->sym && !e2.sym) {
|
||||
/* OK */
|
||||
} else if (pe->sym && e2.sym) {
|
||||
if (pe->sym == e2.sym) {
|
||||
/* OK */
|
||||
} else if (pe->sym->r == e2.sym->r && pe->sym->r != 0) {
|
||||
/* we also accept defined symbols in the same section */
|
||||
pe->v += pe->sym->jnext - e2.sym->jnext;
|
||||
} else {
|
||||
goto cannot_relocate;
|
||||
}
|
||||
pe->sym = NULL; /* same symbols can be subtracted to NULL */
|
||||
if (!e2.sym) {
|
||||
/* OK */
|
||||
} else if (pe->sym == e2.sym) {
|
||||
/* OK */
|
||||
pe->sym = NULL; /* same symbols can be subtracted to NULL */
|
||||
} else if (pe->sym && pe->sym->r == e2.sym->r && pe->sym->r != 0) {
|
||||
/* we also accept defined symbols in the same section */
|
||||
pe->v += pe->sym->jnext - e2.sym->jnext;
|
||||
pe->sym = NULL;
|
||||
} else if (e2.sym->r == cur_text_section->sh_num) {
|
||||
/* When subtracting a defined symbol in current section
|
||||
this actually makes the value PC-relative. */
|
||||
pe->v -= e2.sym->jnext - ind - 4;
|
||||
pe->pcrel = 1;
|
||||
e2.sym = NULL;
|
||||
} else {
|
||||
cannot_relocate:
|
||||
tcc_error("invalid operation with label");
|
||||
|
@ -531,9 +538,15 @@ static void asm_parse_directive(TCCState *s1)
|
|||
case TOK_ASMDIR_org:
|
||||
{
|
||||
unsigned long n;
|
||||
ExprValue e;
|
||||
next();
|
||||
/* XXX: handle section symbols too */
|
||||
n = asm_int_expr(s1);
|
||||
asm_expr(s1, &e);
|
||||
n = e.v;
|
||||
if (e.sym) {
|
||||
if (e.sym->r != cur_text_section->sh_num)
|
||||
expect("constant or same-section symbol");
|
||||
n += e.sym->jnext;
|
||||
}
|
||||
if (n < ind)
|
||||
tcc_error("attempt to .org backwards");
|
||||
v = 0;
|
||||
|
@ -703,6 +716,7 @@ static void asm_parse_directive(TCCState *s1)
|
|||
case TOK_ASMDIR_section:
|
||||
{
|
||||
char sname[256];
|
||||
int old_nb_section = s1->nb_sections;
|
||||
|
||||
tok1 = tok;
|
||||
/* XXX: support more options */
|
||||
|
@ -733,6 +747,11 @@ static void asm_parse_directive(TCCState *s1)
|
|||
use_section(s1, sname);
|
||||
else
|
||||
push_section(s1, sname);
|
||||
/* If we just allocated a new section reset its alignment to
|
||||
1. new_section normally acts for GCC compatibility and
|
||||
sets alignment to PTR_SIZE. The assembler behaves different. */
|
||||
if (old_nb_section != s1->nb_sections)
|
||||
cur_text_section->sh_addralign = 1;
|
||||
}
|
||||
break;
|
||||
case TOK_ASMDIR_previous:
|
||||
|
|
|
@ -727,6 +727,19 @@ nop
|
|||
.popsection
|
||||
.popsection
|
||||
|
||||
1: ud2
|
||||
.pushsection __bug_table,"a"
|
||||
.align 8
|
||||
2: .long 1b - 2b
|
||||
.long 0x600000 - 2b
|
||||
.long 1b + 42
|
||||
.long 43 + 1b
|
||||
.long 2b + 144
|
||||
.long 145 + 2b
|
||||
.word 164, 0
|
||||
.org 2b+32
|
||||
.popsection
|
||||
|
||||
movd %esi, %mm1
|
||||
movd %edi, %xmm2
|
||||
movd (%ebx), %mm3
|
||||
|
|
Loading…
Reference in New Issue