148e06fe0SBastian Koppelmann /* 248e06fe0SBastian Koppelmann * Copyright (c) 2012-2014 Bastian Koppelmann C-Lab/University Paderborn 348e06fe0SBastian Koppelmann * 448e06fe0SBastian Koppelmann * This library is free software; you can redistribute it and/or 548e06fe0SBastian Koppelmann * modify it under the terms of the GNU Lesser General Public 648e06fe0SBastian Koppelmann * License as published by the Free Software Foundation; either 748e06fe0SBastian Koppelmann * version 2 of the License, or (at your option) any later version. 848e06fe0SBastian Koppelmann * 948e06fe0SBastian Koppelmann * This library is distributed in the hope that it will be useful, 1048e06fe0SBastian Koppelmann * but WITHOUT ANY WARRANTY; without even the implied warranty of 1148e06fe0SBastian Koppelmann * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1248e06fe0SBastian Koppelmann * Lesser General Public License for more details. 1348e06fe0SBastian Koppelmann * 1448e06fe0SBastian Koppelmann * You should have received a copy of the GNU Lesser General Public 1548e06fe0SBastian Koppelmann * License along with this library; if not, see <http://www.gnu.org/licenses/>. 1648e06fe0SBastian Koppelmann */ 1748e06fe0SBastian Koppelmann #include <stdlib.h> 1848e06fe0SBastian Koppelmann #include "cpu.h" 1948e06fe0SBastian Koppelmann #include "qemu/host-utils.h" 2048e06fe0SBastian Koppelmann #include "exec/helper-proto.h" 2148e06fe0SBastian Koppelmann #include "exec/cpu_ldst.h" 2248e06fe0SBastian Koppelmann 232692802aSBastian Koppelmann #define SSOV(env, ret, arg, len) do { \ 242692802aSBastian Koppelmann int64_t max_pos = INT##len ##_MAX; \ 252692802aSBastian Koppelmann int64_t max_neg = INT##len ##_MIN; \ 262692802aSBastian Koppelmann if (arg > max_pos) { \ 272692802aSBastian Koppelmann env->PSW_USB_V = (1 << 31); \ 282692802aSBastian Koppelmann env->PSW_USB_SV = (1 << 31); \ 292692802aSBastian Koppelmann ret = (target_ulong)max_pos; \ 302692802aSBastian Koppelmann } else { \ 312692802aSBastian Koppelmann if (arg < max_neg) { \ 322692802aSBastian Koppelmann env->PSW_USB_V = (1 << 31); \ 332692802aSBastian Koppelmann env->PSW_USB_SV = (1 << 31); \ 342692802aSBastian Koppelmann ret = (target_ulong)max_neg; \ 352692802aSBastian Koppelmann } else { \ 362692802aSBastian Koppelmann env->PSW_USB_V = 0; \ 372692802aSBastian Koppelmann ret = (target_ulong)arg; \ 382692802aSBastian Koppelmann } \ 392692802aSBastian Koppelmann } \ 402692802aSBastian Koppelmann env->PSW_USB_AV = arg ^ arg * 2u; \ 412692802aSBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; \ 422692802aSBastian Koppelmann } while (0) 432692802aSBastian Koppelmann 442692802aSBastian Koppelmann target_ulong helper_add_ssov(CPUTriCoreState *env, target_ulong r1, 452692802aSBastian Koppelmann target_ulong r2) 462692802aSBastian Koppelmann { 472692802aSBastian Koppelmann target_ulong ret; 482692802aSBastian Koppelmann int64_t t1 = sextract64(r1, 0, 32); 492692802aSBastian Koppelmann int64_t t2 = sextract64(r2, 0, 32); 502692802aSBastian Koppelmann int64_t result = t1 + t2; 512692802aSBastian Koppelmann SSOV(env, ret, result, 32); 522692802aSBastian Koppelmann return ret; 532692802aSBastian Koppelmann } 542692802aSBastian Koppelmann 552692802aSBastian Koppelmann target_ulong helper_sub_ssov(CPUTriCoreState *env, target_ulong r1, 562692802aSBastian Koppelmann target_ulong r2) 572692802aSBastian Koppelmann { 582692802aSBastian Koppelmann target_ulong ret; 592692802aSBastian Koppelmann int64_t t1 = sextract64(r1, 0, 32); 602692802aSBastian Koppelmann int64_t t2 = sextract64(r2, 0, 32); 612692802aSBastian Koppelmann int64_t result = t1 - t2; 622692802aSBastian Koppelmann SSOV(env, ret, result, 32); 632692802aSBastian Koppelmann return ret; 642692802aSBastian Koppelmann } 652692802aSBastian Koppelmann 662d30267eSBastian Koppelmann static inline void QEMU_NORETURN do_raise_exception_err(CPUTriCoreState *env, 672d30267eSBastian Koppelmann uint32_t exception, 682d30267eSBastian Koppelmann int error_code, 692d30267eSBastian Koppelmann uintptr_t pc) 702d30267eSBastian Koppelmann { 712d30267eSBastian Koppelmann CPUState *cs = CPU(tricore_env_get_cpu(env)); 722d30267eSBastian Koppelmann cs->exception_index = exception; 732d30267eSBastian Koppelmann env->error_code = error_code; 742d30267eSBastian Koppelmann 752d30267eSBastian Koppelmann if (pc) { 762d30267eSBastian Koppelmann /* now we have a real cpu fault */ 772d30267eSBastian Koppelmann cpu_restore_state(cs, pc); 782d30267eSBastian Koppelmann } 792d30267eSBastian Koppelmann 802d30267eSBastian Koppelmann cpu_loop_exit(cs); 812d30267eSBastian Koppelmann } 822d30267eSBastian Koppelmann 832d30267eSBastian Koppelmann static inline void QEMU_NORETURN do_raise_exception(CPUTriCoreState *env, 842d30267eSBastian Koppelmann uint32_t exception, 852d30267eSBastian Koppelmann uintptr_t pc) 862d30267eSBastian Koppelmann { 872d30267eSBastian Koppelmann do_raise_exception_err(env, exception, 0, pc); 882d30267eSBastian Koppelmann } 892d30267eSBastian Koppelmann 9048e06fe0SBastian Koppelmann void tlb_fill(CPUState *cs, target_ulong addr, int is_write, int mmu_idx, 9148e06fe0SBastian Koppelmann uintptr_t retaddr) 9248e06fe0SBastian Koppelmann { 932d30267eSBastian Koppelmann int ret; 942d30267eSBastian Koppelmann ret = cpu_tricore_handle_mmu_fault(cs, addr, is_write, mmu_idx); 952d30267eSBastian Koppelmann if (ret) { 962d30267eSBastian Koppelmann TriCoreCPU *cpu = TRICORE_CPU(cs); 972d30267eSBastian Koppelmann CPUTriCoreState *env = &cpu->env; 982d30267eSBastian Koppelmann do_raise_exception_err(env, cs->exception_index, 992d30267eSBastian Koppelmann env->error_code, retaddr); 10048e06fe0SBastian Koppelmann } 1012d30267eSBastian Koppelmann } 102