aboutsummaryrefslogtreecommitdiff
path: root/i386-asm.c
diff options
context:
space:
mode:
Diffstat (limited to 'i386-asm.c')
-rw-r--r--i386-asm.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/i386-asm.c b/i386-asm.c
index 16b2e91..a62a4cf 100644
--- a/i386-asm.c
+++ b/i386-asm.c
@@ -1185,6 +1185,28 @@ static const char *skip_constraint_modifiers(const char *p)
return p;
}
+/* If T (a token) is of the form "%reg" returns the register
+ number and type, otherwise return -1. */
+ST_FUNC int asm_parse_regvar (int t)
+{
+ const char *s;
+ Operand op;
+ if (t < TOK_IDENT)
+ return -1;
+ s = table_ident[t - TOK_IDENT]->str;
+ if (s[0] != '%')
+ return -1;
+ t = tok_alloc(s+1, strlen(s)-1)->tok;
+ unget_tok(t);
+ unget_tok('%');
+ parse_operand(tcc_state, &op);
+ /* Accept only integer regs for now. */
+ if (op.type & OP_REG)
+ return op.reg;
+ else
+ return -1;
+}
+
#define REG_OUT_MASK 0x01
#define REG_IN_MASK 0x02
@@ -1227,6 +1249,11 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
tcc_error("cannot reference twice the same operand");
operands[k].input_index = i;
op->priority = 5;
+ } else if ((op->vt->r & VT_VALMASK) == VT_LOCAL
+ && op->vt->sym
+ && (reg = op->vt->sym->r & VT_VALMASK) < VT_CONST) {
+ op->priority = 1;
+ op->reg = reg;
} else {
op->priority = constraint_priority(str);
}
@@ -1274,6 +1301,12 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
} else {
reg_mask = REG_IN_MASK;
}
+ if (op->reg >= 0) {
+ if (is_reg_allocated(op->reg))
+ tcc_error("asm regvar requests register that's taken already");
+ reg = op->reg;
+ goto reg_found;
+ }
try_next:
c = *str++;
switch(c) {