mirror of
https://github.com/mirror/tinycc.git
synced 2025-02-04 06:30:10 +08:00
Fix Extended Asm ignored constraints
This commit fixes the case where the register of for the Extended Asm
input or output is known. Before this commit, the following case:
register long __a0 asm ("a0") = one;
asm volatile (
"ecall\n\t"
: "+r" (__a0) // NOTE the +r here
);
Didn't treat `a0` as an input+output register (+ contraint) as the code
skipped the constraint processing when the register was already chosen
(instead of allocated later).
This issue comes from f081acbfba
, that was
taken as a reference in every other Extended Assembler implementation.
This commit is contained in:
parent
4944f509c3
commit
0703df1a6a
@ -3075,7 +3075,6 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
||||
tcc_error
|
||||
("asm regvar requests register that's taken already");
|
||||
reg = op->reg;
|
||||
goto reg_found;
|
||||
}
|
||||
try_next:
|
||||
c = *str++;
|
||||
@ -3095,7 +3094,9 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
||||
case 'r': // general-purpose register
|
||||
case 'p': // loadable/storable address
|
||||
/* any general register */
|
||||
for (reg = 0; reg <= 8; reg++) {
|
||||
if ((reg = op->reg) >= 0)
|
||||
goto reg_found;
|
||||
else for (reg = 0; reg <= 8; reg++) {
|
||||
if (!is_reg_allocated(reg))
|
||||
goto reg_found;
|
||||
}
|
||||
|
12
i386-asm.c
12
i386-asm.c
@ -1342,7 +1342,6 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
||||
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++;
|
||||
@ -1385,12 +1384,17 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
||||
case 'D':
|
||||
reg = 7;
|
||||
alloc_reg:
|
||||
if (op->reg >= 0 && reg != op->reg)
|
||||
goto try_next;
|
||||
if (is_reg_allocated(reg))
|
||||
goto try_next;
|
||||
goto reg_found;
|
||||
case 'q':
|
||||
/* eax, ebx, ecx or edx */
|
||||
for(reg = 0; reg < 4; reg++) {
|
||||
if (op->reg >= 0) {
|
||||
if ((reg = op->reg) < 4)
|
||||
goto reg_found;
|
||||
} else for(reg = 0; reg < 4; reg++) {
|
||||
if (!is_reg_allocated(reg))
|
||||
goto reg_found;
|
||||
}
|
||||
@ -1399,7 +1403,9 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
||||
case 'R':
|
||||
case 'p': /* A general address, for x86(64) any register is acceptable*/
|
||||
/* any general register */
|
||||
for(reg = 0; reg < 8; reg++) {
|
||||
if ((reg = op->reg) >= 0)
|
||||
goto reg_found;
|
||||
else for(reg = 0; reg < 8; reg++) {
|
||||
if (!is_reg_allocated(reg))
|
||||
goto reg_found;
|
||||
}
|
||||
|
@ -1720,7 +1720,6 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
||||
tcc_error
|
||||
("asm regvar requests register that's taken already");
|
||||
reg = op->reg;
|
||||
goto reg_found;
|
||||
}
|
||||
try_next:
|
||||
c = *str++;
|
||||
@ -1739,7 +1738,9 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
||||
case 'p': // loadable/storable address
|
||||
/* any general register */
|
||||
/* From a0 to a7 */
|
||||
for (reg = 10; reg <= 18; reg++) {
|
||||
if ((reg = op->reg) >= 0)
|
||||
goto reg_found;
|
||||
else for (reg = 10; reg <= 18; reg++) {
|
||||
if (!is_reg_allocated(reg))
|
||||
goto reg_found;
|
||||
}
|
||||
@ -1753,7 +1754,9 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands,
|
||||
case 'f': // floating pont register
|
||||
/* floating point register */
|
||||
/* From fa0 to fa7 */
|
||||
for (reg = 42; reg <= 50; reg++) {
|
||||
if ((reg = op->reg) >= 0)
|
||||
goto reg_found;
|
||||
else for (reg = 42; reg <= 50; reg++) {
|
||||
if (!is_reg_allocated(reg))
|
||||
goto reg_found;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user