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.  */
 | 
			
		||||
    int base_func = 42;
 | 
			
		||||
    void override_func3 (void);
 | 
			
		||||
    unsigned long asmret;
 | 
			
		||||
 | 
			
		||||
    printf("inline asm:\n");
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2720,6 +2721,11 @@ void asm_test(void)
 | 
			
		|||
       the global one, not the local decl from this function.  */
 | 
			
		||||
    asm volatile(".weak override_func3\n.set override_func3, base_func");
 | 
			
		||||
    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;
 | 
			
		||||
 label1:
 | 
			
		||||
    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);
 | 
			
		||||
        }
 | 
			
		||||
        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 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue