xref: /qemu/target/tricore/op_helper.c (revision 2692802a37a53a832c76d9beec88c65972bc2a91)
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