2 * Altera Nios II helper routines.
4 * Copyright (C) 2012 Chris Wulff <crwulff@gmail.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see
18 * <http://www.gnu.org/licenses/lgpl-2.1.html>
21 #include "qemu/osdep.h"
23 #include "exec/helper-proto.h"
24 #include "exec/exec-all.h"
26 void helper_raise_exception(CPUNios2State
*env
, uint32_t index
)
28 CPUState
*cs
= env_cpu(env
);
29 cs
->exception_index
= index
;
33 void nios2_cpu_loop_exit_advance(CPUNios2State
*env
, uintptr_t retaddr
)
35 CPUState
*cs
= env_cpu(env
);
38 * Note that PC is advanced for all hardware exceptions.
39 * Do this here, rather than in restore_state_to_opc(),
40 * lest we affect QEMU internal exceptions, like EXCP_DEBUG.
42 cpu_restore_state(cs
, retaddr
);
47 static void maybe_raise_div(CPUNios2State
*env
, uintptr_t ra
)
49 Nios2CPU
*cpu
= env_archcpu(env
);
50 CPUState
*cs
= env_cpu(env
);
52 if (cpu
->diverr_present
) {
53 cs
->exception_index
= EXCP_DIV
;
54 nios2_cpu_loop_exit_advance(env
, ra
);
58 int32_t helper_divs(CPUNios2State
*env
, int32_t num
, int32_t den
)
60 if (unlikely(den
== 0) || unlikely(den
== -1 && num
== INT32_MIN
)) {
61 maybe_raise_div(env
, GETPC());
62 return num
; /* undefined */
67 uint32_t helper_divu(CPUNios2State
*env
, uint32_t num
, uint32_t den
)
69 if (unlikely(den
== 0)) {
70 maybe_raise_div(env
, GETPC());
71 return num
; /* undefined */
76 #ifndef CONFIG_USER_ONLY
77 void helper_eret(CPUNios2State
*env
, uint32_t new_status
, uint32_t new_pc
)
79 Nios2CPU
*cpu
= env_archcpu(env
);
80 CPUState
*cs
= env_cpu(env
);
82 if (unlikely(new_pc
& 3)) {
83 env
->ctrl
[CR_BADADDR
] = new_pc
;
84 cs
->exception_index
= EXCP_UNALIGND
;
85 nios2_cpu_loop_exit_advance(env
, GETPC());
89 * None of estatus, bstatus, or sstatus have constraints on write;
90 * do not allow reserved fields in status to be set.
91 * When shadow registers are enabled, eret *does* restore CRS.
92 * Rather than testing eic_present to decide, mask CRS out of
93 * the set of readonly fields.
95 new_status
&= cpu
->cr_state
[CR_STATUS
].writable
|
96 (cpu
->cr_state
[CR_STATUS
].readonly
& R_CR_STATUS_CRS_MASK
);
98 env
->ctrl
[CR_STATUS
] = new_status
;
100 nios2_update_crs(env
);
105 * RDPRS and WRPRS are implemented out of line so that if PRS == CRS,
106 * all of the tcg global temporaries are synced back to ENV.
108 uint32_t helper_rdprs(CPUNios2State
*env
, uint32_t regno
)
110 unsigned prs
= FIELD_EX32(env
->ctrl
[CR_STATUS
], CR_STATUS
, PRS
);
111 return env
->shadow_regs
[prs
][regno
];
114 void helper_wrprs(CPUNios2State
*env
, uint32_t regno
, uint32_t val
)
116 unsigned prs
= FIELD_EX32(env
->ctrl
[CR_STATUS
], CR_STATUS
, PRS
);
117 env
->shadow_regs
[prs
][regno
] = val
;
119 #endif /* !CONFIG_USER_ONLY */