mirror of
				https://github.com/yuzu-emu/unicorn.git
				synced 2025-11-04 09:15:11 +00:00 
			
		
		
		
	tcg: Synchronize with qemu
This commit is contained in:
		
							parent
							
								
									006a13026a
								
							
						
					
					
						commit
						3996153514
					
				
							
								
								
									
										183
									
								
								qemu/tcg/tcg.c
									
									
									
									
									
								
							
							
						
						
									
										183
									
								
								qemu/tcg/tcg.c
									
									
									
									
									
								
							| 
						 | 
					@ -2159,104 +2159,109 @@ static void liveness_pass_1(TCGContext *s)
 | 
				
			||||||
                        goto do_not_remove;
 | 
					                        goto do_not_remove;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            do_remove:
 | 
					                goto do_remove;
 | 
				
			||||||
                tcg_op_remove(s, op);
 | 
					            }
 | 
				
			||||||
            } else {
 | 
					            goto do_not_remove;
 | 
				
			||||||
            do_not_remove:
 | 
					 | 
				
			||||||
                /* output args are dead */
 | 
					 | 
				
			||||||
                for (i = 0; i < nb_oargs; i++) {
 | 
					 | 
				
			||||||
                    ts = arg_temp(op->args[i]);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    /* Remember the preference of the uses that followed.  */
 | 
					        do_remove:
 | 
				
			||||||
                    op->output_pref[i] = *la_temp_pref(ts);
 | 
					            tcg_op_remove(s, op);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    /* Output args are dead.  */
 | 
					        do_not_remove:
 | 
				
			||||||
                    if (ts->state & TS_DEAD) {
 | 
					            for (i = 0; i < nb_oargs; i++) {
 | 
				
			||||||
                        arg_life |= DEAD_ARG << i;
 | 
					                ts = arg_temp(op->args[i]);
 | 
				
			||||||
                    }
 | 
					
 | 
				
			||||||
                    if (ts->state & TS_MEM) {
 | 
					                /* Remember the preference of the uses that followed.  */
 | 
				
			||||||
                        arg_life |= SYNC_ARG << i;
 | 
					                op->output_pref[i] = *la_temp_pref(ts);
 | 
				
			||||||
                    }
 | 
					
 | 
				
			||||||
                    ts->state = TS_DEAD;
 | 
					                /* Output args are dead.  */
 | 
				
			||||||
                    la_reset_pref(s, ts);
 | 
					                if (ts->state & TS_DEAD) {
 | 
				
			||||||
 | 
					                    arg_life |= DEAD_ARG << i;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					                if (ts->state & TS_MEM) {
 | 
				
			||||||
                /* If end of basic block, update.  */
 | 
					                    arg_life |= SYNC_ARG << i;
 | 
				
			||||||
                if (def->flags & TCG_OPF_BB_END) {
 | 
					 | 
				
			||||||
                    // Unicorn: do not optimize dead temps on brcond,
 | 
					 | 
				
			||||||
                    // this causes problem because check_exit_request() inserts
 | 
					 | 
				
			||||||
                    // brcond instruction in the middle of the TB,
 | 
					 | 
				
			||||||
                    // which incorrectly flags end-of-block
 | 
					 | 
				
			||||||
                    if (opc != INDEX_op_brcond_i32) {
 | 
					 | 
				
			||||||
                        la_bb_end(s, nb_globals, nb_temps);
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        // Unicorn: we do not touch dead temps for brcond,
 | 
					 | 
				
			||||||
                        // but we should refresh TCG globals In-Memory states,
 | 
					 | 
				
			||||||
                        // otherwise, important CPU states(especially conditional flags) might be forgotten,
 | 
					 | 
				
			||||||
                        // result in wrongly generated host code that run into wrong branch.
 | 
					 | 
				
			||||||
                        // Refer to https://github.com/unicorn-engine/unicorn/issues/287 for further information
 | 
					 | 
				
			||||||
                        tcg_la_br_end(s);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                } else if (def->flags & TCG_OPF_SIDE_EFFECTS) {
 | 
					 | 
				
			||||||
                    la_global_sync(s, nb_globals);
 | 
					 | 
				
			||||||
                    if (def->flags & TCG_OPF_CALL_CLOBBER) {
 | 
					 | 
				
			||||||
                        la_cross_call(s, nb_temps);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					                ts->state = TS_DEAD;
 | 
				
			||||||
 | 
					                la_reset_pref(s, ts);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                /* Record arguments that die in this opcode.  */
 | 
					            /* If end of basic block, update.  */
 | 
				
			||||||
 | 
					            if (def->flags & TCG_OPF_BB_EXIT) {
 | 
				
			||||||
 | 
					                la_func_end(s, nb_globals, nb_temps);
 | 
				
			||||||
 | 
					            } else if (def->flags & TCG_OPF_BB_END) {
 | 
				
			||||||
 | 
					                // Unicorn: do not optimize dead temps on brcond,
 | 
				
			||||||
 | 
					                // this causes problem because check_exit_request() inserts
 | 
				
			||||||
 | 
					                // brcond instruction in the middle of the TB,
 | 
				
			||||||
 | 
					                // which incorrectly flags end-of-block
 | 
				
			||||||
 | 
					                if (opc != INDEX_op_brcond_i32) {
 | 
				
			||||||
 | 
					                    la_bb_end(s, nb_globals, nb_temps);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    // Unicorn: we do not touch dead temps for brcond,
 | 
				
			||||||
 | 
					                    // but we should refresh TCG globals In-Memory states,
 | 
				
			||||||
 | 
					                    // otherwise, important CPU states(especially conditional flags) might be forgotten,
 | 
				
			||||||
 | 
					                    // result in wrongly generated host code that run into wrong branch.
 | 
				
			||||||
 | 
					                    // Refer to https://github.com/unicorn-engine/unicorn/issues/287 for further information
 | 
				
			||||||
 | 
					                    tcg_la_br_end(s);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else if (def->flags & TCG_OPF_SIDE_EFFECTS) {
 | 
				
			||||||
 | 
					                la_global_sync(s, nb_globals);
 | 
				
			||||||
 | 
					                if (def->flags & TCG_OPF_CALL_CLOBBER) {
 | 
				
			||||||
 | 
					                    la_cross_call(s, nb_temps);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* Record arguments that die in this opcode.  */
 | 
				
			||||||
 | 
					            for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
 | 
				
			||||||
 | 
					                ts = arg_temp(op->args[i]);
 | 
				
			||||||
 | 
					                if (ts->state & TS_DEAD) {
 | 
				
			||||||
 | 
					                    arg_life |= DEAD_ARG << i;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* Input arguments are live for preceding opcodes.  */
 | 
				
			||||||
 | 
					            for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
 | 
				
			||||||
 | 
					                ts = arg_temp(op->args[i]);
 | 
				
			||||||
 | 
					                if (ts->state & TS_DEAD) {
 | 
				
			||||||
 | 
					                    /* For operands that were dead, initially allow
 | 
				
			||||||
 | 
					                       all regs for the type.  */
 | 
				
			||||||
 | 
					                    *la_temp_pref(ts) = s->tcg_target_available_regs[ts->type];
 | 
				
			||||||
 | 
					                    ts->state &= ~TS_DEAD;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* Incorporate constraints for this operand.  */
 | 
				
			||||||
 | 
					            switch (opc) {
 | 
				
			||||||
 | 
					            case INDEX_op_mov_i32:
 | 
				
			||||||
 | 
					            case INDEX_op_mov_i64:
 | 
				
			||||||
 | 
					                /* Note that these are TCG_OPF_NOT_PRESENT and do not
 | 
				
			||||||
 | 
					                   have proper constraints.  That said, special case
 | 
				
			||||||
 | 
					                   moves to propagate preferences backward.  */
 | 
				
			||||||
 | 
					                if (IS_DEAD_ARG(1)) {
 | 
				
			||||||
 | 
					                    *la_temp_pref(arg_temp(op->args[0]))
 | 
				
			||||||
 | 
					                        = *la_temp_pref(arg_temp(op->args[1]));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
                for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
 | 
					                for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
 | 
				
			||||||
 | 
					                    const TCGArgConstraint *ct = &def->args_ct[i];
 | 
				
			||||||
 | 
					                    TCGRegSet set, *pset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    ts = arg_temp(op->args[i]);
 | 
					                    ts = arg_temp(op->args[i]);
 | 
				
			||||||
                    if (ts->state & TS_DEAD) {
 | 
					                    pset = la_temp_pref(ts);
 | 
				
			||||||
                        arg_life |= DEAD_ARG << i;
 | 
					                    set = *pset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    set &= ct->u.regs;
 | 
				
			||||||
 | 
					                    if (ct->ct & TCG_CT_IALIAS) {
 | 
				
			||||||
 | 
					                        set &= op->output_pref[ct->alias_index];
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					                    /* If the combination is not possible, restart.  */
 | 
				
			||||||
 | 
					                    if (set == 0) {
 | 
				
			||||||
 | 
					                        set = ct->u.regs;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    *pset = set;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                /* Input arguments are live for preceding opcodes.  */
 | 
					                break;
 | 
				
			||||||
                for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
 | 
					 | 
				
			||||||
                    ts = arg_temp(op->args[i]);
 | 
					 | 
				
			||||||
                    if (ts->state & TS_DEAD) {
 | 
					 | 
				
			||||||
                        /* For operands that were dead, initially allow
 | 
					 | 
				
			||||||
                           all regs for the type.  */
 | 
					 | 
				
			||||||
                        *la_temp_pref(ts) = s->tcg_target_available_regs[ts->type];
 | 
					 | 
				
			||||||
                        ts->state &= ~TS_DEAD;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                /* Incorporate constraints for this operand.  */
 | 
					 | 
				
			||||||
                switch (opc) {
 | 
					 | 
				
			||||||
                case INDEX_op_mov_i32:
 | 
					 | 
				
			||||||
                case INDEX_op_mov_i64:
 | 
					 | 
				
			||||||
                    /* Note that these are TCG_OPF_NOT_PRESENT and do not
 | 
					 | 
				
			||||||
                       have proper constraints.  That said, special case
 | 
					 | 
				
			||||||
                       moves to propagate preferences backward.  */
 | 
					 | 
				
			||||||
                    if (IS_DEAD_ARG(1)) {
 | 
					 | 
				
			||||||
                        *la_temp_pref(arg_temp(op->args[0]))
 | 
					 | 
				
			||||||
                            = *la_temp_pref(arg_temp(op->args[1]));
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                default:
 | 
					 | 
				
			||||||
                    for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
 | 
					 | 
				
			||||||
                        const TCGArgConstraint *ct = &def->args_ct[i];
 | 
					 | 
				
			||||||
                        TCGRegSet set, *pset;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        ts = arg_temp(op->args[i]);
 | 
					 | 
				
			||||||
                        pset = la_temp_pref(ts);
 | 
					 | 
				
			||||||
                        set = *pset;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        set &= ct->u.regs;
 | 
					 | 
				
			||||||
                        if (ct->ct & TCG_CT_IALIAS) {
 | 
					 | 
				
			||||||
                            set &= op->output_pref[ct->alias_index];
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        /* If the combination is not possible, restart.  */
 | 
					 | 
				
			||||||
                        if (set == 0) {
 | 
					 | 
				
			||||||
                            set = ct->u.regs;
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        *pset = set;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue