186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/*
286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner * Optimizations for Tiny Code Generator for QEMU
386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner *
486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner * Copyright (c) 2010 Samsung Electronics.
586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner * Contributed by Kirill Batuzov <batuzovk@ispras.ru>
686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner *
786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner * Permission is hereby granted, free of charge, to any person obtaining a copy
886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner * of this software and associated documentation files (the "Software"), to deal
986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner * in the Software without restriction, including without limitation the rights
1086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner * copies of the Software, and to permit persons to whom the Software is
1286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner * furnished to do so, subject to the following conditions:
1386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner *
1486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner * The above copyright notice and this permission notice shall be included in
1586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner * all copies or substantial portions of the Software.
1686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner *
1786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
2086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner * THE SOFTWARE.
2486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner */
2586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
2686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#include "config.h"
2786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
2886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#include <stdlib.h>
2986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#include <stdio.h>
3086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
3186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#include "qemu-common.h"
3286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#include "cpu.h"
3386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#include "exec/exec-all.h"
3486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#include "tcg-op.h"
3586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
3686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner#define CASE_OP_32_64(x)                        \
3786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        glue(glue(case INDEX_op_, x), _i32):    \
3886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        glue(glue(case INDEX_op_, x), _i64)
3986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
4086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnertypedef enum {
4186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCG_TEMP_UNDEF = 0,
4286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCG_TEMP_CONST,
4386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCG_TEMP_COPY,
4486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner} tcg_temp_state;
4586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
4686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstruct tcg_temp_info {
4786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_temp_state state;
4886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uint16_t prev_copy;
4986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uint16_t next_copy;
5086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_target_ulong val;
5186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_target_ulong mask;
5286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner};
5386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
5486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic struct tcg_temp_info temps[TCG_MAX_TEMPS];
5586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
5686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* Reset TEMP's state to TCG_TEMP_UNDEF.  If TEMP only had one copy, remove
5786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner   the copy flag from the left temp.  */
5886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void reset_temp(TCGArg temp)
5986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
6086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (temps[temp].state == TCG_TEMP_COPY) {
6186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (temps[temp].prev_copy == temps[temp].next_copy) {
6286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            temps[temps[temp].next_copy].state = TCG_TEMP_UNDEF;
6386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        } else {
6486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            temps[temps[temp].next_copy].prev_copy = temps[temp].prev_copy;
6586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy;
6686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
6786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
6886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    temps[temp].state = TCG_TEMP_UNDEF;
6986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    temps[temp].mask = -1;
7086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
7186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
7286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* Reset all temporaries, given that there are NB_TEMPS of them.  */
7386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void reset_all_temps(int nb_temps)
7486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
7586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    int i;
7686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    for (i = 0; i < nb_temps; i++) {
7786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        temps[i].state = TCG_TEMP_UNDEF;
7886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        temps[i].mask = -1;
7986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
8086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
8186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
8286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic int op_bits(TCGOpcode op)
8386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
8486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    const TCGOpDef *def = &tcg_op_defs[op];
8586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    return def->flags & TCG_OPF_64BIT ? 64 : 32;
8686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
8786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
8886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic TCGOpcode op_to_movi(TCGOpcode op)
8986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
9086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    switch (op_bits(op)) {
9186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case 32:
9286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return INDEX_op_movi_i32;
9386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case 64:
9486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return INDEX_op_movi_i64;
9586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    default:
9686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        fprintf(stderr, "op_to_movi: unexpected return value of "
9786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                "function op_bits.\n");
9886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_abort();
9986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
10086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
10186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
10286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic TCGArg find_better_copy(TCGContext *s, TCGArg temp)
10386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
10486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGArg i;
10586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
10686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* If this is already a global, we can't do better. */
10786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (temp < s->nb_globals) {
10886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return temp;
10986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
11086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
11186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* Search for a global first. */
11286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    for (i = temps[temp].next_copy ; i != temp ; i = temps[i].next_copy) {
11386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (i < s->nb_globals) {
11486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            return i;
11586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
11686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
11786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
11886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* If it is a temp, search for a temp local. */
11986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (!s->temps[temp].temp_local) {
12086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        for (i = temps[temp].next_copy ; i != temp ; i = temps[i].next_copy) {
12186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (s->temps[i].temp_local) {
12286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                return i;
12386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
12486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
12586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
12686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
12786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* Failure to find a better representation, return the same temp. */
12886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    return temp;
12986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
13086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
13186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic bool temps_are_copies(TCGArg arg1, TCGArg arg2)
13286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
13386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGArg i;
13486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
13586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (arg1 == arg2) {
13686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return true;
13786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
13886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
13986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (temps[arg1].state != TCG_TEMP_COPY
14086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        || temps[arg2].state != TCG_TEMP_COPY) {
14186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return false;
14286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
14386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
14486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    for (i = temps[arg1].next_copy ; i != arg1 ; i = temps[i].next_copy) {
14586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (i == arg2) {
14686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            return true;
14786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
14886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
14986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
15086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    return false;
15186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
15286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
15386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void tcg_opt_gen_mov(TCGContext *s, TCGArg *gen_args,
15486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                            TCGArg dst, TCGArg src)
15586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
15686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    reset_temp(dst);
15786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    temps[dst].mask = temps[src].mask;
15886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    assert(temps[src].state != TCG_TEMP_CONST);
15986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
16086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (s->temps[src].type == s->temps[dst].type) {
16186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (temps[src].state != TCG_TEMP_COPY) {
16286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            temps[src].state = TCG_TEMP_COPY;
16386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            temps[src].next_copy = src;
16486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            temps[src].prev_copy = src;
16586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
16686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        temps[dst].state = TCG_TEMP_COPY;
16786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        temps[dst].next_copy = temps[src].next_copy;
16886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        temps[dst].prev_copy = src;
16986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        temps[temps[dst].next_copy].prev_copy = dst;
17086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        temps[src].next_copy = dst;
17186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
17286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
17386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    gen_args[0] = dst;
17486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    gen_args[1] = src;
17586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
17686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
17786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic void tcg_opt_gen_movi(TCGArg *gen_args, TCGArg dst, TCGArg val)
17886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
17986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    reset_temp(dst);
18086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    temps[dst].state = TCG_TEMP_CONST;
18186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    temps[dst].val = val;
18286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    temps[dst].mask = val;
18386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    gen_args[0] = dst;
18486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    gen_args[1] = val;
18586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
18686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
18786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic TCGOpcode op_to_mov(TCGOpcode op)
18886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
18986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    switch (op_bits(op)) {
19086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case 32:
19186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return INDEX_op_mov_i32;
19286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case 64:
19386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return INDEX_op_mov_i64;
19486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    default:
19586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        fprintf(stderr, "op_to_mov: unexpected return value of "
19686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                "function op_bits.\n");
19786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_abort();
19886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
19986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
20086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
20186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y)
20286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
20386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    uint64_t l64, h64;
20486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
20586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    switch (op) {
20686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    CASE_OP_32_64(add):
20786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return x + y;
20886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
20986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    CASE_OP_32_64(sub):
21086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return x - y;
21186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
21286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    CASE_OP_32_64(mul):
21386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return x * y;
21486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
21586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    CASE_OP_32_64(and):
21686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return x & y;
21786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
21886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    CASE_OP_32_64(or):
21986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return x | y;
22086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
22186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    CASE_OP_32_64(xor):
22286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return x ^ y;
22386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
22486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_shl_i32:
22586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (uint32_t)x << (uint32_t)y;
22686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
22786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_shl_i64:
22886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (uint64_t)x << (uint64_t)y;
22986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
23086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_shr_i32:
23186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (uint32_t)x >> (uint32_t)y;
23286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
23386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_shr_i64:
23486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (uint64_t)x >> (uint64_t)y;
23586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
23686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_sar_i32:
23786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (int32_t)x >> (int32_t)y;
23886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
23986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_sar_i64:
24086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (int64_t)x >> (int64_t)y;
24186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
24286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_rotr_i32:
24386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return ror32(x, y);
24486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
24586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_rotr_i64:
24686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return ror64(x, y);
24786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
24886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_rotl_i32:
24986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return rol32(x, y);
25086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
25186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_rotl_i64:
25286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return rol64(x, y);
25386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
25486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    CASE_OP_32_64(not):
25586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return ~x;
25686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
25786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    CASE_OP_32_64(neg):
25886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return -x;
25986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
26086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    CASE_OP_32_64(andc):
26186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return x & ~y;
26286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
26386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    CASE_OP_32_64(orc):
26486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return x | ~y;
26586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
26686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    CASE_OP_32_64(eqv):
26786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return ~(x ^ y);
26886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
26986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    CASE_OP_32_64(nand):
27086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return ~(x & y);
27186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
27286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    CASE_OP_32_64(nor):
27386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return ~(x | y);
27486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
27586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    CASE_OP_32_64(ext8s):
27686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (int8_t)x;
27786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
27886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    CASE_OP_32_64(ext16s):
27986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (int16_t)x;
28086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
28186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    CASE_OP_32_64(ext8u):
28286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (uint8_t)x;
28386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
28486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    CASE_OP_32_64(ext16u):
28586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (uint16_t)x;
28686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
28786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_ext32s_i64:
28886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (int32_t)x;
28986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
29086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_ext32u_i64:
29186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (uint32_t)x;
29286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
29386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_muluh_i32:
29486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return ((uint64_t)(uint32_t)x * (uint32_t)y) >> 32;
29586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_mulsh_i32:
29686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return ((int64_t)(int32_t)x * (int32_t)y) >> 32;
29786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
29886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_muluh_i64:
29986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        mulu64(&l64, &h64, x, y);
30086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return h64;
30186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_mulsh_i64:
30286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        muls64(&l64, &h64, x, y);
30386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return h64;
30486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
30586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_div_i32:
30686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        /* Avoid crashing on divide by zero, otherwise undefined.  */
30786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (int32_t)x / ((int32_t)y ? : 1);
30886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_divu_i32:
30986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (uint32_t)x / ((uint32_t)y ? : 1);
31086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_div_i64:
31186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (int64_t)x / ((int64_t)y ? : 1);
31286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_divu_i64:
31386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (uint64_t)x / ((uint64_t)y ? : 1);
31486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
31586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_rem_i32:
31686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (int32_t)x % ((int32_t)y ? : 1);
31786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_remu_i32:
31886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (uint32_t)x % ((uint32_t)y ? : 1);
31986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_rem_i64:
32086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (int64_t)x % ((int64_t)y ? : 1);
32186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case INDEX_op_remu_i64:
32286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (uint64_t)x % ((uint64_t)y ? : 1);
32386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
32486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    default:
32586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        fprintf(stderr,
32686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                "Unrecognized operation %d in do_constant_folding.\n", op);
32786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_abort();
32886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
32986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
33086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
33186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic TCGArg do_constant_folding(TCGOpcode op, TCGArg x, TCGArg y)
33286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
33386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGArg res = do_constant_folding_2(op, x, y);
33486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (op_bits(op) == 32) {
33586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        res &= 0xffffffff;
33686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
33786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    return res;
33886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
33986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
34086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic bool do_constant_folding_cond_32(uint32_t x, uint32_t y, TCGCond c)
34186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
34286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    switch (c) {
34386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_EQ:
34486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return x == y;
34586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_NE:
34686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return x != y;
34786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_LT:
34886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (int32_t)x < (int32_t)y;
34986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_GE:
35086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (int32_t)x >= (int32_t)y;
35186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_LE:
35286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (int32_t)x <= (int32_t)y;
35386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_GT:
35486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (int32_t)x > (int32_t)y;
35586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_LTU:
35686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return x < y;
35786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_GEU:
35886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return x >= y;
35986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_LEU:
36086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return x <= y;
36186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_GTU:
36286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return x > y;
36386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    default:
36486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_abort();
36586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
36686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
36786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
36886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic bool do_constant_folding_cond_64(uint64_t x, uint64_t y, TCGCond c)
36986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
37086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    switch (c) {
37186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_EQ:
37286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return x == y;
37386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_NE:
37486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return x != y;
37586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_LT:
37686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (int64_t)x < (int64_t)y;
37786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_GE:
37886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (int64_t)x >= (int64_t)y;
37986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_LE:
38086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (int64_t)x <= (int64_t)y;
38186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_GT:
38286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return (int64_t)x > (int64_t)y;
38386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_LTU:
38486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return x < y;
38586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_GEU:
38686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return x >= y;
38786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_LEU:
38886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return x <= y;
38986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_GTU:
39086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return x > y;
39186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    default:
39286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_abort();
39386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
39486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
39586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
39686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic bool do_constant_folding_cond_eq(TCGCond c)
39786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
39886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    switch (c) {
39986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_GT:
40086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_LTU:
40186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_LT:
40286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_GTU:
40386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_NE:
40486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return 0;
40586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_GE:
40686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_GEU:
40786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_LE:
40886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_LEU:
40986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    case TCG_COND_EQ:
41086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return 1;
41186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    default:
41286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        tcg_abort();
41386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
41486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
41586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
41686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* Return 2 if the condition can't be simplified, and the result
41786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner   of the condition (0 or 1) if it can */
41886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x,
41986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                       TCGArg y, TCGCond c)
42086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
42186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (temps[x].state == TCG_TEMP_CONST && temps[y].state == TCG_TEMP_CONST) {
42286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        switch (op_bits(op)) {
42386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        case 32:
42486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            return do_constant_folding_cond_32(temps[x].val, temps[y].val, c);
42586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        case 64:
42686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            return do_constant_folding_cond_64(temps[x].val, temps[y].val, c);
42786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        default:
42886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_abort();
42986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
43086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    } else if (temps_are_copies(x, y)) {
43186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return do_constant_folding_cond_eq(c);
43286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    } else if (temps[y].state == TCG_TEMP_CONST && temps[y].val == 0) {
43386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        switch (c) {
43486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        case TCG_COND_LTU:
43586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            return 0;
43686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        case TCG_COND_GEU:
43786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            return 1;
43886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        default:
43986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            return 2;
44086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
44186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    } else {
44286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return 2;
44386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
44486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
44586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
44686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* Return 2 if the condition can't be simplified, and the result
44786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner   of the condition (0 or 1) if it can */
44886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic TCGArg do_constant_folding_cond2(TCGArg *p1, TCGArg *p2, TCGCond c)
44986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
45086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGArg al = p1[0], ah = p1[1];
45186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGArg bl = p2[0], bh = p2[1];
45286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
45386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (temps[bl].state == TCG_TEMP_CONST
45486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        && temps[bh].state == TCG_TEMP_CONST) {
45586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        uint64_t b = ((uint64_t)temps[bh].val << 32) | (uint32_t)temps[bl].val;
45686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
45786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (temps[al].state == TCG_TEMP_CONST
45886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            && temps[ah].state == TCG_TEMP_CONST) {
45986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            uint64_t a;
46086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            a = ((uint64_t)temps[ah].val << 32) | (uint32_t)temps[al].val;
46186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            return do_constant_folding_cond_64(a, b, c);
46286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
46386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (b == 0) {
46486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            switch (c) {
46586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            case TCG_COND_LTU:
46686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                return 0;
46786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            case TCG_COND_GEU:
46886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                return 1;
46986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            default:
47086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                break;
47186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
47286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
47386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
47486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (temps_are_copies(al, bl) && temps_are_copies(ah, bh)) {
47586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return do_constant_folding_cond_eq(c);
47686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
47786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    return 2;
47886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
47986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
48086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic bool swap_commutative(TCGArg dest, TCGArg *p1, TCGArg *p2)
48186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
48286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGArg a1 = *p1, a2 = *p2;
48386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    int sum = 0;
48486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    sum += temps[a1].state == TCG_TEMP_CONST;
48586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    sum -= temps[a2].state == TCG_TEMP_CONST;
48686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
48786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* Prefer the constant in second argument, and then the form
48886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner       op a, a, b, which is better handled on non-RISC hosts. */
48986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (sum > 0 || (sum == 0 && dest == a2)) {
49086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        *p1 = a2;
49186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        *p2 = a1;
49286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return true;
49386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
49486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    return false;
49586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
49686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
49786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic bool swap_commutative2(TCGArg *p1, TCGArg *p2)
49886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
49986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    int sum = 0;
50086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    sum += temps[p1[0]].state == TCG_TEMP_CONST;
50186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    sum += temps[p1[1]].state == TCG_TEMP_CONST;
50286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    sum -= temps[p2[0]].state == TCG_TEMP_CONST;
50386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    sum -= temps[p2[1]].state == TCG_TEMP_CONST;
50486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    if (sum > 0) {
50586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        TCGArg t;
50686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        t = p1[0], p1[0] = p2[0], p2[0] = t;
50786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        t = p1[1], p1[1] = p2[1], p2[1] = t;
50886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        return true;
50986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
51086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    return false;
51186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
51286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
51386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner/* Propagate constants and copies, fold constant expressions. */
51486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
51586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                    TCGArg *args, TCGOpDef *tcg_op_defs)
51686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
51786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    int i, nb_ops, op_index, nb_temps, nb_globals, nb_call_args;
51886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    tcg_target_ulong mask, affected;
51986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGOpcode op;
52086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    const TCGOpDef *def;
52186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGArg *gen_args;
52286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGArg tmp;
52386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
52486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    /* Array VALS has an element for each temp.
52586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner       If this temp holds a constant then its value is kept in VALS' element.
52686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner       If this temp is a copy of other ones then the other copies are
52786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner       available through the doubly linked circular list. */
52886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
52986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    nb_temps = s->nb_temps;
53086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    nb_globals = s->nb_globals;
53186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    reset_all_temps(nb_temps);
53286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
53386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    nb_ops = tcg_opc_ptr - s->gen_opc_buf;
53486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    gen_args = args;
53586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    for (op_index = 0; op_index < nb_ops; op_index++) {
53686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        op = s->gen_opc_buf[op_index];
53786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        def = &tcg_op_defs[op];
53886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        /* Do copy propagation */
53986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (op == INDEX_op_call) {
54086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            int nb_oargs = args[0] >> 16;
54186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            int nb_iargs = args[0] & 0xffff;
54286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            for (i = nb_oargs + 1; i < nb_oargs + nb_iargs + 1; i++) {
54386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                if (temps[args[i]].state == TCG_TEMP_COPY) {
54486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    args[i] = find_better_copy(s, args[i]);
54586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                }
54686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
54786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        } else {
54886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            for (i = def->nb_oargs; i < def->nb_oargs + def->nb_iargs; i++) {
54986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                if (temps[args[i]].state == TCG_TEMP_COPY) {
55086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    args[i] = find_better_copy(s, args[i]);
55186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                }
55286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
55386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
55486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
55586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        /* For commutative operations make constant second argument */
55686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        switch (op) {
55786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(add):
55886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(mul):
55986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(and):
56086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(or):
56186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(xor):
56286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(eqv):
56386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(nand):
56486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(nor):
56586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(muluh):
56686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(mulsh):
56786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            swap_commutative(args[0], &args[1], &args[2]);
56886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
56986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(brcond):
57086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (swap_commutative(-1, &args[0], &args[1])) {
57186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args[2] = tcg_swap_cond(args[2]);
57286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
57386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
57486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(setcond):
57586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (swap_commutative(args[0], &args[1], &args[2])) {
57686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args[3] = tcg_swap_cond(args[3]);
57786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
57886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
57986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(movcond):
58086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (swap_commutative(-1, &args[1], &args[2])) {
58186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args[5] = tcg_swap_cond(args[5]);
58286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
58386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            /* For movcond, we canonicalize the "false" input reg to match
58486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner               the destination reg so that the tcg backend can implement
58586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner               a "move if true" operation.  */
58686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (swap_commutative(args[0], &args[4], &args[3])) {
58786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args[5] = tcg_invert_cond(args[5]);
58886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
58986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
59086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(add2):
59186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            swap_commutative(args[0], &args[2], &args[4]);
59286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            swap_commutative(args[1], &args[3], &args[5]);
59386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
59486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(mulu2):
59586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(muls2):
59686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            swap_commutative(args[0], &args[2], &args[3]);
59786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
59886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        case INDEX_op_brcond2_i32:
59986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (swap_commutative2(&args[0], &args[2])) {
60086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args[4] = tcg_swap_cond(args[4]);
60186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
60286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
60386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        case INDEX_op_setcond2_i32:
60486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (swap_commutative2(&args[1], &args[3])) {
60586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args[5] = tcg_swap_cond(args[5]);
60686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
60786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
60886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        default:
60986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
61086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
61186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
61286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        /* Simplify expressions for "shift/rot r, 0, a => movi r, 0",
61386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner           and "sub r, 0, a => neg r, a" case.  */
61486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        switch (op) {
61586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(shl):
61686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(shr):
61786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(sar):
61886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(rotl):
61986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(rotr):
62086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (temps[args[1]].state == TCG_TEMP_CONST
62186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                && temps[args[1]].val == 0) {
62286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->gen_opc_buf[op_index] = op_to_movi(op);
62386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tcg_opt_gen_movi(gen_args, args[0], 0);
62486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args += 3;
62586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                gen_args += 2;
62686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                continue;
62786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
62886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
62986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(sub):
63086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            {
63186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                TCGOpcode neg_op;
63286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                bool have_neg;
63386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
63486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                if (temps[args[2]].state == TCG_TEMP_CONST) {
63586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    /* Proceed with possible constant folding. */
63686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    break;
63786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                }
63886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                if (op == INDEX_op_sub_i32) {
63986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    neg_op = INDEX_op_neg_i32;
64086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    have_neg = TCG_TARGET_HAS_neg_i32;
64186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                } else {
64286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    neg_op = INDEX_op_neg_i64;
64386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    have_neg = TCG_TARGET_HAS_neg_i64;
64486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                }
64586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                if (!have_neg) {
64686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    break;
64786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                }
64886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                if (temps[args[1]].state == TCG_TEMP_CONST
64986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    && temps[args[1]].val == 0) {
65086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    s->gen_opc_buf[op_index] = neg_op;
65186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    reset_temp(args[0]);
65286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    gen_args[0] = args[0];
65386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    gen_args[1] = args[2];
65486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    args += 3;
65586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    gen_args += 2;
65686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    continue;
65786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                }
65886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
65986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
66086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        default:
66186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
66286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
66386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
66486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        /* Simplify expression for "op r, a, 0 => mov r, a" cases */
66586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        switch (op) {
66686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(add):
66786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(sub):
66886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(shl):
66986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(shr):
67086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(sar):
67186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(rotl):
67286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(rotr):
67386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(or):
67486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(xor):
67586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (temps[args[1]].state == TCG_TEMP_CONST) {
67686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                /* Proceed with possible constant folding. */
67786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                break;
67886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
67986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (temps[args[2]].state == TCG_TEMP_CONST
68086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                && temps[args[2]].val == 0) {
68186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                if (temps_are_copies(args[0], args[1])) {
68286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    s->gen_opc_buf[op_index] = INDEX_op_nop;
68386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                } else {
68486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    s->gen_opc_buf[op_index] = op_to_mov(op);
68586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    tcg_opt_gen_mov(s, gen_args, args[0], args[1]);
68686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    gen_args += 2;
68786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                }
68886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args += 3;
68986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                continue;
69086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
69186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
69286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        default:
69386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
69486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
69586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
69686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        /* Simplify using known-zero bits */
69786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        mask = -1;
69886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        affected = -1;
69986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        switch (op) {
70086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(ext8s):
70186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if ((temps[args[1]].mask & 0x80) != 0) {
70286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                break;
70386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
70486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(ext8u):
70586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            mask = 0xff;
70686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            goto and_const;
70786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(ext16s):
70886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if ((temps[args[1]].mask & 0x8000) != 0) {
70986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                break;
71086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
71186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(ext16u):
71286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            mask = 0xffff;
71386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            goto and_const;
71486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        case INDEX_op_ext32s_i64:
71586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if ((temps[args[1]].mask & 0x80000000) != 0) {
71686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                break;
71786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
71886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        case INDEX_op_ext32u_i64:
71986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            mask = 0xffffffffU;
72086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            goto and_const;
72186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
72286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(and):
72386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            mask = temps[args[2]].mask;
72486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (temps[args[2]].state == TCG_TEMP_CONST) {
72586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        and_const:
72686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                affected = temps[args[1]].mask & ~mask;
72786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
72886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            mask = temps[args[1]].mask & mask;
72986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
73086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
73186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(sar):
73286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (temps[args[2]].state == TCG_TEMP_CONST) {
73386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                mask = ((tcg_target_long)temps[args[1]].mask
73486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                        >> temps[args[2]].val);
73586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
73686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
73786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
73886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(shr):
73986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (temps[args[2]].state == TCG_TEMP_CONST) {
74086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                mask = temps[args[1]].mask >> temps[args[2]].val;
74186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
74286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
74386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
74486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(shl):
74586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (temps[args[2]].state == TCG_TEMP_CONST) {
74686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                mask = temps[args[1]].mask << temps[args[2]].val;
74786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
74886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
74986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
75086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(neg):
75186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            /* Set to 1 all bits to the left of the rightmost.  */
75286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            mask = -(temps[args[1]].mask & -temps[args[1]].mask);
75386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
75486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
75586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(deposit):
75686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tmp = ((1ull << args[4]) - 1);
75786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            mask = ((temps[args[1]].mask & ~(tmp << args[3]))
75886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    | ((temps[args[2]].mask & tmp) << args[3]));
75986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
76086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
76186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(or):
76286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(xor):
76386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            mask = temps[args[1]].mask | temps[args[2]].mask;
76486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
76586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
76686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(setcond):
76786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            mask = 1;
76886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
76986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
77086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(movcond):
77186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            mask = temps[args[3]].mask | temps[args[4]].mask;
77286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
77386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
77486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        default:
77586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
77686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
77786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
77886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (mask == 0) {
77986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            assert(def->nb_oargs == 1);
78086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            s->gen_opc_buf[op_index] = op_to_movi(op);
78186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_opt_gen_movi(gen_args, args[0], 0);
78286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            args += def->nb_oargs + def->nb_iargs + def->nb_cargs;
78386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            gen_args += 2;
78486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            continue;
78586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
78686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        if (affected == 0) {
78786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            assert(def->nb_oargs == 1);
78886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (temps_are_copies(args[0], args[1])) {
78986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->gen_opc_buf[op_index] = INDEX_op_nop;
79086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            } else if (temps[args[1]].state != TCG_TEMP_CONST) {
79186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->gen_opc_buf[op_index] = op_to_mov(op);
79286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tcg_opt_gen_mov(s, gen_args, args[0], args[1]);
79386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                gen_args += 2;
79486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            } else {
79586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->gen_opc_buf[op_index] = op_to_movi(op);
79686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tcg_opt_gen_movi(gen_args, args[0], temps[args[1]].val);
79786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                gen_args += 2;
79886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
79986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            args += def->nb_iargs + 1;
80086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            continue;
80186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
80286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
80386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        /* Simplify expression for "op r, a, 0 => movi r, 0" cases */
80486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        switch (op) {
80586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(and):
80686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(mul):
80786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(muluh):
80886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(mulsh):
80986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if ((temps[args[2]].state == TCG_TEMP_CONST
81086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                && temps[args[2]].val == 0)) {
81186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->gen_opc_buf[op_index] = op_to_movi(op);
81286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tcg_opt_gen_movi(gen_args, args[0], 0);
81386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args += 3;
81486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                gen_args += 2;
81586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                continue;
81686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
81786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
81886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        default:
81986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
82086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
82186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
82286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        /* Simplify expression for "op r, a, a => mov r, a" cases */
82386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        switch (op) {
82486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(or):
82586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(and):
82686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (temps_are_copies(args[1], args[2])) {
82786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                if (temps_are_copies(args[0], args[1])) {
82886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    s->gen_opc_buf[op_index] = INDEX_op_nop;
82986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                } else {
83086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    s->gen_opc_buf[op_index] = op_to_mov(op);
83186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    tcg_opt_gen_mov(s, gen_args, args[0], args[1]);
83286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    gen_args += 2;
83386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                }
83486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args += 3;
83586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                continue;
83686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
83786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
83886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        default:
83986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
84086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
84186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
84286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        /* Simplify expression for "op r, a, a => movi r, 0" cases */
84386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        switch (op) {
84486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(sub):
84586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(xor):
84686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (temps_are_copies(args[1], args[2])) {
84786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->gen_opc_buf[op_index] = op_to_movi(op);
84886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tcg_opt_gen_movi(gen_args, args[0], 0);
84986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                gen_args += 2;
85086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args += 3;
85186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                continue;
85286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
85386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
85486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        default:
85586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
85686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
85786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
85886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        /* Propagate constants through copy operations and do constant
85986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner           folding.  Constants will be substituted to arguments by register
86086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner           allocator where needed and possible.  Also detect copies. */
86186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        switch (op) {
86286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(mov):
86386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (temps_are_copies(args[0], args[1])) {
86486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args += 2;
86586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->gen_opc_buf[op_index] = INDEX_op_nop;
86686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                break;
86786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
86886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (temps[args[1]].state != TCG_TEMP_CONST) {
86986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tcg_opt_gen_mov(s, gen_args, args[0], args[1]);
87086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                gen_args += 2;
87186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args += 2;
87286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                break;
87386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
87486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            /* Source argument is constant.  Rewrite the operation and
87586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner               let movi case handle it. */
87686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            op = op_to_movi(op);
87786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            s->gen_opc_buf[op_index] = op;
87886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            args[1] = temps[args[1]].val;
87986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            /* fallthrough */
88086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(movi):
88186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tcg_opt_gen_movi(gen_args, args[0], args[1]);
88286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            gen_args += 2;
88386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            args += 2;
88486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
88586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
88686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(not):
88786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(neg):
88886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(ext8s):
88986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(ext8u):
89086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(ext16s):
89186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(ext16u):
89286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        case INDEX_op_ext32s_i64:
89386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        case INDEX_op_ext32u_i64:
89486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (temps[args[1]].state == TCG_TEMP_CONST) {
89586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->gen_opc_buf[op_index] = op_to_movi(op);
89686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tmp = do_constant_folding(op, temps[args[1]].val, 0);
89786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tcg_opt_gen_movi(gen_args, args[0], tmp);
89886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                gen_args += 2;
89986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args += 2;
90086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                break;
90186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
90286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            goto do_default;
90386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
90486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(add):
90586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(sub):
90686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(mul):
90786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(or):
90886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(and):
90986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(xor):
91086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(shl):
91186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(shr):
91286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(sar):
91386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(rotl):
91486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(rotr):
91586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(andc):
91686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(orc):
91786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(eqv):
91886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(nand):
91986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(nor):
92086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(muluh):
92186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(mulsh):
92286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(div):
92386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(divu):
92486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(rem):
92586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(remu):
92686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (temps[args[1]].state == TCG_TEMP_CONST
92786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                && temps[args[2]].state == TCG_TEMP_CONST) {
92886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->gen_opc_buf[op_index] = op_to_movi(op);
92986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tmp = do_constant_folding(op, temps[args[1]].val,
93086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                          temps[args[2]].val);
93186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tcg_opt_gen_movi(gen_args, args[0], tmp);
93286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                gen_args += 2;
93386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args += 3;
93486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                break;
93586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
93686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            goto do_default;
93786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
93886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(deposit):
93986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (temps[args[1]].state == TCG_TEMP_CONST
94086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                && temps[args[2]].state == TCG_TEMP_CONST) {
94186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->gen_opc_buf[op_index] = op_to_movi(op);
94286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tmp = ((1ull << args[4]) - 1);
94386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tmp = (temps[args[1]].val & ~(tmp << args[3]))
94486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                      | ((temps[args[2]].val & tmp) << args[3]);
94586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tcg_opt_gen_movi(gen_args, args[0], tmp);
94686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                gen_args += 2;
94786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args += 5;
94886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                break;
94986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
95086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            goto do_default;
95186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
95286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(setcond):
95386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tmp = do_constant_folding_cond(op, args[1], args[2], args[3]);
95486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (tmp != 2) {
95586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->gen_opc_buf[op_index] = op_to_movi(op);
95686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tcg_opt_gen_movi(gen_args, args[0], tmp);
95786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                gen_args += 2;
95886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args += 4;
95986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                break;
96086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
96186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            goto do_default;
96286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
96386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(brcond):
96486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tmp = do_constant_folding_cond(op, args[0], args[1], args[2]);
96586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (tmp != 2) {
96686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                if (tmp) {
96786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    reset_all_temps(nb_temps);
96886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    s->gen_opc_buf[op_index] = INDEX_op_br;
96986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    gen_args[0] = args[3];
97086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    gen_args += 1;
97186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                } else {
97286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    s->gen_opc_buf[op_index] = INDEX_op_nop;
97386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                }
97486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args += 4;
97586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                break;
97686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
97786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            goto do_default;
97886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
97986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        CASE_OP_32_64(movcond):
98086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tmp = do_constant_folding_cond(op, args[1], args[2], args[5]);
98186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (tmp != 2) {
98286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                if (temps_are_copies(args[0], args[4-tmp])) {
98386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    s->gen_opc_buf[op_index] = INDEX_op_nop;
98486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                } else if (temps[args[4-tmp]].state == TCG_TEMP_CONST) {
98586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    s->gen_opc_buf[op_index] = op_to_movi(op);
98686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    tcg_opt_gen_movi(gen_args, args[0], temps[args[4-tmp]].val);
98786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    gen_args += 2;
98886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                } else {
98986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    s->gen_opc_buf[op_index] = op_to_mov(op);
99086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    tcg_opt_gen_mov(s, gen_args, args[0], args[4-tmp]);
99186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    gen_args += 2;
99286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                }
99386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args += 6;
99486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                break;
99586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
99686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            goto do_default;
99786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
99886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        case INDEX_op_add2_i32:
99986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        case INDEX_op_sub2_i32:
100086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (temps[args[2]].state == TCG_TEMP_CONST
100186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                && temps[args[3]].state == TCG_TEMP_CONST
100286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                && temps[args[4]].state == TCG_TEMP_CONST
100386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                && temps[args[5]].state == TCG_TEMP_CONST) {
100486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                uint32_t al = temps[args[2]].val;
100586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                uint32_t ah = temps[args[3]].val;
100686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                uint32_t bl = temps[args[4]].val;
100786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                uint32_t bh = temps[args[5]].val;
100886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                uint64_t a = ((uint64_t)ah << 32) | al;
100986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                uint64_t b = ((uint64_t)bh << 32) | bl;
101086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                TCGArg rl, rh;
101186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
101286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                if (op == INDEX_op_add2_i32) {
101386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    a += b;
101486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                } else {
101586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    a -= b;
101686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                }
101786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
101886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                /* We emit the extra nop when we emit the add2/sub2.  */
101986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                assert(s->gen_opc_buf[op_index + 1] == INDEX_op_nop);
102086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
102186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                rl = args[0];
102286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                rh = args[1];
102386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->gen_opc_buf[op_index] = INDEX_op_movi_i32;
102486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->gen_opc_buf[++op_index] = INDEX_op_movi_i32;
102586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tcg_opt_gen_movi(&gen_args[0], rl, (uint32_t)a);
102686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tcg_opt_gen_movi(&gen_args[2], rh, (uint32_t)(a >> 32));
102786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                gen_args += 4;
102886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args += 6;
102986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                break;
103086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
103186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            goto do_default;
103286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
103386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        case INDEX_op_mulu2_i32:
103486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (temps[args[2]].state == TCG_TEMP_CONST
103586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                && temps[args[3]].state == TCG_TEMP_CONST) {
103686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                uint32_t a = temps[args[2]].val;
103786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                uint32_t b = temps[args[3]].val;
103886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                uint64_t r = (uint64_t)a * b;
103986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                TCGArg rl, rh;
104086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
104186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                /* We emit the extra nop when we emit the mulu2.  */
104286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                assert(s->gen_opc_buf[op_index + 1] == INDEX_op_nop);
104386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
104486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                rl = args[0];
104586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                rh = args[1];
104686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->gen_opc_buf[op_index] = INDEX_op_movi_i32;
104786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->gen_opc_buf[++op_index] = INDEX_op_movi_i32;
104886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tcg_opt_gen_movi(&gen_args[0], rl, (uint32_t)r);
104986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tcg_opt_gen_movi(&gen_args[2], rh, (uint32_t)(r >> 32));
105086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                gen_args += 4;
105186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args += 4;
105286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                break;
105386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
105486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            goto do_default;
105586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
105686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        case INDEX_op_brcond2_i32:
105786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tmp = do_constant_folding_cond2(&args[0], &args[2], args[4]);
105886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (tmp != 2) {
105986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                if (tmp) {
106086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    reset_all_temps(nb_temps);
106186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    s->gen_opc_buf[op_index] = INDEX_op_br;
106286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    gen_args[0] = args[5];
106386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    gen_args += 1;
106486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                } else {
106586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    s->gen_opc_buf[op_index] = INDEX_op_nop;
106686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                }
106786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            } else if ((args[4] == TCG_COND_LT || args[4] == TCG_COND_GE)
106886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                       && temps[args[2]].state == TCG_TEMP_CONST
106986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                       && temps[args[3]].state == TCG_TEMP_CONST
107086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                       && temps[args[2]].val == 0
107186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                       && temps[args[3]].val == 0) {
107286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                /* Simplify LT/GE comparisons vs zero to a single compare
107386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                   vs the high word of the input.  */
107486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                reset_all_temps(nb_temps);
107586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->gen_opc_buf[op_index] = INDEX_op_brcond_i32;
107686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                gen_args[0] = args[1];
107786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                gen_args[1] = args[3];
107886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                gen_args[2] = args[4];
107986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                gen_args[3] = args[5];
108086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                gen_args += 4;
108186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            } else {
108286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                goto do_default;
108386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
108486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            args += 6;
108586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
108686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
108786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        case INDEX_op_setcond2_i32:
108886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            tmp = do_constant_folding_cond2(&args[1], &args[3], args[5]);
108986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (tmp != 2) {
109086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->gen_opc_buf[op_index] = INDEX_op_movi_i32;
109186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                tcg_opt_gen_movi(gen_args, args[0], tmp);
109286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                gen_args += 2;
109386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            } else if ((args[5] == TCG_COND_LT || args[5] == TCG_COND_GE)
109486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                       && temps[args[3]].state == TCG_TEMP_CONST
109586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                       && temps[args[4]].state == TCG_TEMP_CONST
109686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                       && temps[args[3]].val == 0
109786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                       && temps[args[4]].val == 0) {
109886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                /* Simplify LT/GE comparisons vs zero to a single compare
109986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                   vs the high word of the input.  */
110086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                s->gen_opc_buf[op_index] = INDEX_op_setcond_i32;
110186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                reset_temp(args[0]);
110286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                gen_args[0] = args[0];
110386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                gen_args[1] = args[2];
110486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                gen_args[2] = args[4];
110586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                gen_args[3] = args[5];
110686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                gen_args += 4;
110786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            } else {
110886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                goto do_default;
110986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
111086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            args += 6;
111186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
111286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
111386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        case INDEX_op_call:
111486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            nb_call_args = (args[0] >> 16) + (args[0] & 0xffff);
111586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (!(args[nb_call_args + 1] & (TCG_CALL_NO_READ_GLOBALS |
111686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                                            TCG_CALL_NO_WRITE_GLOBALS))) {
111786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                for (i = 0; i < nb_globals; i++) {
111886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    reset_temp(i);
111986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                }
112086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
112186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            for (i = 0; i < (args[0] >> 16); i++) {
112286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                reset_temp(args[i + 1]);
112386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
112486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            i = nb_call_args + 3;
112586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            while (i) {
112686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                *gen_args = *args;
112786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                args++;
112886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                gen_args++;
112986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                i--;
113086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
113186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
113286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
113386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        default:
113486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        do_default:
113586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            /* Default case: we know nothing about operation (or were unable
113686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner               to compute the operation result) so no propagation is done.
113786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner               We trash everything if the operation is the end of a basic
113886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner               block, otherwise we only trash the output args.  "mask" is
113986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner               the non-zero bits mask for the first output arg.  */
114086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            if (def->flags & TCG_OPF_BB_END) {
114186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                reset_all_temps(nb_temps);
114286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            } else {
114386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                for (i = 0; i < def->nb_oargs; i++) {
114486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                    reset_temp(args[i]);
114586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                }
114686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
114786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            for (i = 0; i < def->nb_args; i++) {
114886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner                gen_args[i] = args[i];
114986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            }
115086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            args += def->nb_args;
115186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            gen_args += def->nb_args;
115286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner            break;
115386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        }
115486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    }
115586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
115686b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    return gen_args;
115786b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
115886b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner
115986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' TurnerTCGArg *tcg_optimize(TCGContext *s, uint16_t *tcg_opc_ptr,
116086b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner        TCGArg *args, TCGOpDef *tcg_op_defs)
116186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner{
116286b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    TCGArg *res;
116386b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    res = tcg_constant_folding(s, tcg_opc_ptr, args, tcg_op_defs);
116486b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    return res;
116586b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner}
1166