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).
Unified · Split
| @@ -2677,6 +2677,7 @@ void asm_test(void) · 2676 unmodified lines | |||
| 2677 | asm block gets the outer one. */ | 2677 | asm block gets the outer one. */ |
| 2678 | int base_func = 42; | 2678 | int base_func = 42; |
| 2679 | void override_func3 (void); | 2679 | void override_func3 (void); |
| 2680 | unsigned long asmret; | ||
| 2680 | 2681 | ||
| 2681 | printf("inline asm:\n"); | 2682 | printf("inline asm:\n"); |
| 2682 | 2683 | ||
| @@ -2720,6 +2721,11 @@ void asm_test(void) · 37 unmodified lines | |||
| 2720 | the global one, not the local decl from this function. */ | 2721 | the global one, not the local decl from this function. */ |
| 2721 | asm volatile(".weak override_func3\n.set override_func3, base_func"); | 2722 | asm volatile(".weak override_func3\n.set override_func3, base_func"); |
| 2722 | override_func3(); | 2723 | override_func3(); |
| 2724 | /* Check that we can also load structs of appropriate layout | ||
| 2725 | into registers. */ | ||
| 2726 | asm volatile("" : "=r" (asmret) : "0"(s2)); | ||
| 2727 | if (asmret != s2.addr) | ||
| 2728 | printf("asmstr: failed\n"); | ||
| 2723 | return; | 2729 | return; |
| 2724 | label1: | 2730 | label1: |
| 2725 | goto label2; | 2731 | goto label2; |
| @@ -382,6 +382,22 @@ void load(int r, SValue *sv) · 381 unmodified lines | |||
| 382 | load(fr, &v1); | 382 | load(fr, &v1); |
| 383 | } | 383 | } |
| 384 | ll = 0; | 384 | ll = 0; |
| 385 | /* Like GCC we can load from small enough properly sized | ||
| 386 | structs and unions as well. | ||
| 387 | XXX maybe move to generic operand handling, but should | ||
| 388 | occur only with asm, so tccasm.c might also be a better place */ | ||
| 389 | if ((ft & VT_BTYPE) == VT_STRUCT) { | ||
| 390 | int align; | ||
| 391 | switch (type_size(&sv->type, &align)) { | ||
| 392 | case 1: ft = VT_BYTE; break; | ||
| 393 | case 2: ft = VT_SHORT; break; | ||
| 394 | case 4: ft = VT_INT; break; | ||
| 395 | case 8: ft = VT_LLONG; break; | ||
| 396 | default: | ||
| 397 | tcc_error("invalid aggregate type for register load"); | ||
| 398 | break; | ||
| 399 | } | ||
| 400 | } | ||
| 385 | if ((ft & VT_BTYPE) == VT_FLOAT) { | 401 | if ((ft & VT_BTYPE) == VT_FLOAT) { |
| 386 | b = 0x6e0f66; | 402 | b = 0x6e0f66; |
| 387 | r = REG_VALUE(r); /* movd */ | 403 | r = REG_VALUE(r); /* movd */ |