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