diff options
| author | Michael Matz <matz@suse.de> | 2016-08-08 20:18:11 +0200 |
|---|---|---|
| committer | Michael Matz <matz@suse.de> | 2016-12-15 17:47:10 +0100 |
| commit | ca8c1cd643b12cd652bb73804e1645b75292357a (patch) | |
| tree | bced1ff0cf59d5eb5baa92000239959efd9bf53f /x86_64-gen.c | |
| parent | 9ae10cad1fecc2be27691de0a37a1ed25abc9639 (diff) | |
| download | tinycc-ca8c1cd643b12cd652bb73804e1645b75292357a.tar.gz tinycc-ca8c1cd643b12cd652bb73804e1645b75292357a.tar.bz2 | |
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).
Diffstat (limited to 'x86_64-gen.c')
| -rw-r--r-- | x86_64-gen.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/x86_64-gen.c b/x86_64-gen.c index 8a2d03a..ea06708 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -382,6 +382,22 @@ void load(int r, SValue *sv) load(fr, &v1); } 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) { b = 0x6e0f66; r = REG_VALUE(r); /* movd */ |
