aboutsummaryrefslogtreecommitdiff
path: root/x86_64-gen.c
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2016-08-08 20:18:11 +0200
committerMichael Matz <matz@suse.de>2016-12-15 17:47:10 +0100
commitca8c1cd643b12cd652bb73804e1645b75292357a (patch)
treebced1ff0cf59d5eb5baa92000239959efd9bf53f /x86_64-gen.c
parent9ae10cad1fecc2be27691de0a37a1ed25abc9639 (diff)
downloadtinycc-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.c16
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 */