tcg: Allow an operand to be matching or a constant
This allows an output operand to match an input operand only when the input operand needs a register. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
		
							parent
							
								
									069ea736b5
								
							
						
					
					
						commit
						17280ff4a5
					
				
							
								
								
									
										13
									
								
								tcg/README
								
								
								
								
							
							
						
						
									
										13
									
								
								tcg/README
								
								
								
								
							| 
						 | 
				
			
			@ -539,24 +539,29 @@ version. Aliases are specified in the input operands as for GCC.
 | 
			
		|||
The same register may be used for both an input and an output, even when
 | 
			
		||||
they are not explicitly aliased.  If an op expands to multiple target
 | 
			
		||||
instructions then care must be taken to avoid clobbering input values.
 | 
			
		||||
GCC style "early clobber" outputs are not currently supported.
 | 
			
		||||
GCC style "early clobber" outputs are supported, with '&'.
 | 
			
		||||
 | 
			
		||||
A target can define specific register or constant constraints. If an
 | 
			
		||||
operation uses a constant input constraint which does not allow all
 | 
			
		||||
constants, it must also accept registers in order to have a fallback.
 | 
			
		||||
The constraint 'i' is defined generically to accept any constant.
 | 
			
		||||
The constraint 'r' is not defined generically, but is consistently
 | 
			
		||||
used by each backend to indicate all registers.
 | 
			
		||||
 | 
			
		||||
The movi_i32 and movi_i64 operations must accept any constants.
 | 
			
		||||
 | 
			
		||||
The mov_i32 and mov_i64 operations must accept any registers of the
 | 
			
		||||
same type.
 | 
			
		||||
 | 
			
		||||
The ld/st instructions must accept signed 32 bit constant offsets. It
 | 
			
		||||
can be implemented by reserving a specific register to compute the
 | 
			
		||||
address if the offset is too big.
 | 
			
		||||
The ld/st/sti instructions must accept signed 32 bit constant offsets.
 | 
			
		||||
This can be implemented by reserving a specific register in which to
 | 
			
		||||
compute the address if the offset is too big.
 | 
			
		||||
 | 
			
		||||
The ld/st instructions must accept any destination (ld) or source (st)
 | 
			
		||||
register.
 | 
			
		||||
 | 
			
		||||
The sti instruction may fail if it cannot store the given constant.
 | 
			
		||||
 | 
			
		||||
4.3) Function call assumptions
 | 
			
		||||
 | 
			
		||||
- The only supported types for parameters and return value are: 32 and
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										63
									
								
								tcg/tcg.c
								
								
								
								
							
							
						
						
									
										63
									
								
								tcg/tcg.c
								
								
								
								
							| 
						 | 
				
			
			@ -1256,37 +1256,37 @@ static void process_op_defs(TCGContext *s)
 | 
			
		|||
 | 
			
		||||
            tcg_regset_clear(def->args_ct[i].u.regs);
 | 
			
		||||
            def->args_ct[i].ct = 0;
 | 
			
		||||
            if (ct_str[0] >= '0' && ct_str[0] <= '9') {
 | 
			
		||||
                int oarg;
 | 
			
		||||
                oarg = ct_str[0] - '0';
 | 
			
		||||
                tcg_debug_assert(oarg < def->nb_oargs);
 | 
			
		||||
                tcg_debug_assert(def->args_ct[oarg].ct & TCG_CT_REG);
 | 
			
		||||
                /* TCG_CT_ALIAS is for the output arguments. The input
 | 
			
		||||
                   argument is tagged with TCG_CT_IALIAS. */
 | 
			
		||||
                def->args_ct[i] = def->args_ct[oarg];
 | 
			
		||||
                def->args_ct[oarg].ct = TCG_CT_ALIAS;
 | 
			
		||||
                def->args_ct[oarg].alias_index = i;
 | 
			
		||||
                def->args_ct[i].ct |= TCG_CT_IALIAS;
 | 
			
		||||
                def->args_ct[i].alias_index = oarg;
 | 
			
		||||
            } else {
 | 
			
		||||
                for(;;) {
 | 
			
		||||
                    if (*ct_str == '\0')
 | 
			
		||||
                        break;
 | 
			
		||||
                    switch(*ct_str) {
 | 
			
		||||
                    case '&':
 | 
			
		||||
                        def->args_ct[i].ct |= TCG_CT_NEWREG;
 | 
			
		||||
                        ct_str++;
 | 
			
		||||
                        break;
 | 
			
		||||
                    case 'i':
 | 
			
		||||
                        def->args_ct[i].ct |= TCG_CT_CONST;
 | 
			
		||||
                        ct_str++;
 | 
			
		||||
                        break;
 | 
			
		||||
                    default:
 | 
			
		||||
                        ct_str = target_parse_constraint(&def->args_ct[i],
 | 
			
		||||
                                                         ct_str, type);
 | 
			
		||||
                        /* Typo in TCGTargetOpDef constraint. */
 | 
			
		||||
                        tcg_debug_assert(ct_str != NULL);
 | 
			
		||||
            while (*ct_str != '\0') {
 | 
			
		||||
                switch(*ct_str) {
 | 
			
		||||
                case '0' ... '9':
 | 
			
		||||
                    {
 | 
			
		||||
                        int oarg = *ct_str - '0';
 | 
			
		||||
                        tcg_debug_assert(ct_str == tdefs->args_ct_str[i]);
 | 
			
		||||
                        tcg_debug_assert(oarg < def->nb_oargs);
 | 
			
		||||
                        tcg_debug_assert(def->args_ct[oarg].ct & TCG_CT_REG);
 | 
			
		||||
                        /* TCG_CT_ALIAS is for the output arguments.
 | 
			
		||||
                           The input is tagged with TCG_CT_IALIAS. */
 | 
			
		||||
                        def->args_ct[i] = def->args_ct[oarg];
 | 
			
		||||
                        def->args_ct[oarg].ct |= TCG_CT_ALIAS;
 | 
			
		||||
                        def->args_ct[oarg].alias_index = i;
 | 
			
		||||
                        def->args_ct[i].ct |= TCG_CT_IALIAS;
 | 
			
		||||
                        def->args_ct[i].alias_index = oarg;
 | 
			
		||||
                    }
 | 
			
		||||
                    ct_str++;
 | 
			
		||||
                    break;
 | 
			
		||||
                case '&':
 | 
			
		||||
                    def->args_ct[i].ct |= TCG_CT_NEWREG;
 | 
			
		||||
                    ct_str++;
 | 
			
		||||
                    break;
 | 
			
		||||
                case 'i':
 | 
			
		||||
                    def->args_ct[i].ct |= TCG_CT_CONST;
 | 
			
		||||
                    ct_str++;
 | 
			
		||||
                    break;
 | 
			
		||||
                default:
 | 
			
		||||
                    ct_str = target_parse_constraint(&def->args_ct[i],
 | 
			
		||||
                                                     ct_str, type);
 | 
			
		||||
                    /* Typo in TCGTargetOpDef constraint. */
 | 
			
		||||
                    tcg_debug_assert(ct_str != NULL);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -2296,7 +2296,8 @@ static void tcg_reg_alloc_op(TCGContext *s,
 | 
			
		|||
            arg = args[i];
 | 
			
		||||
            arg_ct = &def->args_ct[i];
 | 
			
		||||
            ts = &s->temps[arg];
 | 
			
		||||
            if (arg_ct->ct & TCG_CT_ALIAS) {
 | 
			
		||||
            if ((arg_ct->ct & TCG_CT_ALIAS)
 | 
			
		||||
                && !const_args[arg_ct->alias_index]) {
 | 
			
		||||
                reg = new_args[arg_ct->alias_index];
 | 
			
		||||
            } else if (arg_ct->ct & TCG_CT_NEWREG) {
 | 
			
		||||
                reg = tcg_reg_alloc(s, arg_ct->u.regs,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue