/*
 *  qemu user cpu loop
 *
 *  Copyright (c) 2003-2008 Fabrice Bellard
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
 */

#include "qemu/osdep.h"
#include "qemu.h"
#include "user-internals.h"
#include "user/cpu_loop.h"
#include "signal-common.h"


static int get_pgm_data_si_code(int dxc_code)
{
    switch (dxc_code) {
    /* Non-simulated IEEE exceptions */
    case 0x80:
        return TARGET_FPE_FLTINV;
    case 0x40:
        return TARGET_FPE_FLTDIV;
    case 0x20:
    case 0x28:
    case 0x2c:
        return TARGET_FPE_FLTOVF;
    case 0x10:
    case 0x18:
    case 0x1c:
        return TARGET_FPE_FLTUND;
    case 0x08:
    case 0x0c:
        return TARGET_FPE_FLTRES;
    }
    /*
     * Non-IEEE and simulated IEEE:
     * Includes compare-and-trap, quantum exception, etc.
     * Simulated IEEE are included here to match current
     * s390x linux kernel.
     */
    return 0;
}

void cpu_loop(CPUS390XState *env)
{
    CPUState *cs = env_cpu(env);
    int trapnr, n, sig;
    target_ulong addr;
    abi_long ret;

    while (1) {
        cpu_exec_start(cs);
        trapnr = cpu_exec(cs);
        cpu_exec_end(cs);
        process_queued_cpu_work(cs);

        switch (trapnr) {
        case EXCP_INTERRUPT:
            /* Just indicate that signals should be handled asap.  */
            break;

        case EXCP_SVC:
            n = env->int_svc_code;
            if (!n) {
                /* syscalls > 255 */
                n = env->regs[1];
            }
            env->psw.addr += env->int_svc_ilen;
            ret = do_syscall(env, n, env->regs[2], env->regs[3],
                             env->regs[4], env->regs[5],
                             env->regs[6], env->regs[7], 0, 0);
            if (ret == -QEMU_ERESTARTSYS) {
                env->psw.addr -= env->int_svc_ilen;
            } else if (ret != -QEMU_ESIGRETURN) {
                env->regs[2] = ret;
            }

            if (unlikely(cs->singlestep_enabled)) {
                /*
                 * cpu_tb_exec() did not raise EXCP_DEBUG, because it has seen
                 * that EXCP_SVC was already pending.
                 */
                cs->exception_index = EXCP_DEBUG;
            }

            break;

        case EXCP_DEBUG:
            sig = TARGET_SIGTRAP;
            n = TARGET_TRAP_BRKPT;
            /*
             * For SIGTRAP the PSW must point after the instruction, which it
             * already does thanks to s390x_tr_tb_stop(). si_addr doesn't need
             * to be filled.
             */
            addr = 0;
            goto do_signal;
        case EXCP_PGM:
            n = env->int_pgm_code;
            switch (n) {
            case PGM_OPERATION:
            case PGM_PRIVILEGED:
                sig = TARGET_SIGILL;
                n = TARGET_ILL_ILLOPC;
                goto do_signal_pc;
            case PGM_PROTECTION:
                force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_ACCERR,
                                env->__excp_addr);
                break;
            case PGM_ADDRESSING:
                force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR,
                                env->__excp_addr);
                break;
            case PGM_EXECUTE:
            case PGM_SPECIFICATION:
            case PGM_SPECIAL_OP:
            case PGM_OPERAND:
            do_sigill_opn:
                sig = TARGET_SIGILL;
                n = TARGET_ILL_ILLOPN;
                goto do_signal_pc;

            case PGM_FIXPT_OVERFLOW:
                sig = TARGET_SIGFPE;
                n = TARGET_FPE_INTOVF;
                goto do_signal_pc;
            case PGM_FIXPT_DIVIDE:
                sig = TARGET_SIGFPE;
                n = TARGET_FPE_INTDIV;
                goto do_signal_pc;

            case PGM_DATA:
                n = (env->fpc >> 8) & 0xff;
                if (n == 0) {
                    goto do_sigill_opn;
                }

                sig = TARGET_SIGFPE;
                n = get_pgm_data_si_code(n);
                goto do_signal_pc;

            default:
                fprintf(stderr, "Unhandled program exception: %#x\n", n);
                cpu_dump_state(cs, stderr, 0);
                exit(EXIT_FAILURE);
            }
            break;

        do_signal_pc:
            addr = env->psw.addr;
            /*
             * For SIGILL and SIGFPE the PSW must point after the instruction.
             */
            env->psw.addr += env->int_pgm_ilen;
        do_signal:
            force_sig_fault(sig, n, addr);
            break;

        case EXCP_ATOMIC:
            cpu_exec_step_atomic(cs);
            break;
        default:
            fprintf(stderr, "Unhandled trap: 0x%x\n", trapnr);
            cpu_dump_state(cs, stderr, 0);
            exit(EXIT_FAILURE);
        }
        process_pending_signals (env);
    }
}

void target_cpu_copy_regs(CPUArchState *env, target_pt_regs *regs)
{
    int i;
    for (i = 0; i < 16; i++) {
        env->regs[i] = regs->gprs[i];
    }
    env->psw.mask = regs->psw.mask;
    env->psw.addr = regs->psw.addr;
}
