x86-64: Allow loads from some structs/unions
GCC allows register loads for asms based on type mode, and correctly sized structs/union have an allowed mode (basically 1,2,4,8 sized aggregates).
This commit is contained in:
parent
9ae10cad1f
commit
ca8c1cd643
2 changed files with 22 additions and 0 deletions
|
|
@ -2677,6 +2677,7 @@ void asm_test(void)
|
||||||
asm block gets the outer one. */
|
asm block gets the outer one. */
|
||||||
int base_func = 42;
|
int base_func = 42;
|
||||||
void override_func3 (void);
|
void override_func3 (void);
|
||||||
|
unsigned long asmret;
|
||||||
|
|
||||||
printf("inline asm:\n");
|
printf("inline asm:\n");
|
||||||
|
|
||||||
|
|
@ -2720,6 +2721,11 @@ void asm_test(void)
|
||||||
the global one, not the local decl from this function. */
|
the global one, not the local decl from this function. */
|
||||||
asm volatile(".weak override_func3\n.set override_func3, base_func");
|
asm volatile(".weak override_func3\n.set override_func3, base_func");
|
||||||
override_func3();
|
override_func3();
|
||||||
|
/* Check that we can also load structs of appropriate layout
|
||||||
|
into registers. */
|
||||||
|
asm volatile("" : "=r" (asmret) : "0"(s2));
|
||||||
|
if (asmret != s2.addr)
|
||||||
|
printf("asmstr: failed\n");
|
||||||
return;
|
return;
|
||||||
label1:
|
label1:
|
||||||
goto label2;
|
goto label2;
|
||||||
|
|
|
||||||
16
x86_64-gen.c
16
x86_64-gen.c
|
|
@ -382,6 +382,22 @@ void load(int r, SValue *sv)
|
||||||
load(fr, &v1);
|
load(fr, &v1);
|
||||||
}
|
}
|
||||||
ll = 0;
|
ll = 0;
|
||||||
|
/* Like GCC we can load from small enough properly sized
|
||||||
|
structs and unions as well.
|
||||||
|
XXX maybe move to generic operand handling, but should
|
||||||
|
occur only with asm, so tccasm.c might also be a better place */
|
||||||
|
if ((ft & VT_BTYPE) == VT_STRUCT) {
|
||||||
|
int align;
|
||||||
|
switch (type_size(&sv->type, &align)) {
|
||||||
|
case 1: ft = VT_BYTE; break;
|
||||||
|
case 2: ft = VT_SHORT; break;
|
||||||
|
case 4: ft = VT_INT; break;
|
||||||
|
case 8: ft = VT_LLONG; break;
|
||||||
|
default:
|
||||||
|
tcc_error("invalid aggregate type for register load");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
if ((ft & VT_BTYPE) == VT_FLOAT) {
|
if ((ft & VT_BTYPE) == VT_FLOAT) {
|
||||||
b = 0x6e0f66;
|
b = 0x6e0f66;
|
||||||
r = REG_VALUE(r); /* movd */
|
r = REG_VALUE(r); /* movd */
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue