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"
25 #include "qemu/main-loop.h"
27 void helper_raise_exception(CPUNios2State
*env
, uint32_t index
)
29 CPUState
*cs
= env_cpu(env
);
30 cs
->exception_index
= index
;
34 void nios2_cpu_loop_exit_advance(CPUNios2State
*env
, uintptr_t retaddr
)
36 CPUState
*cs
= env_cpu(env
);
39 * Note that PC is advanced for all hardware exceptions.
40 * Do this here, rather than in restore_state_to_opc(),
41 * lest we affect QEMU internal exceptions, like EXCP_DEBUG.
43 cpu_restore_state(cs
, retaddr
);
48 static void maybe_raise_div(CPUNios2State
*env
, uintptr_t ra
)
50 Nios2CPU
*cpu
= env_archcpu(env
);
51 CPUState
*cs
= env_cpu(env
);
53 if (cpu
->diverr_present
) {
54 cs
->exception_index
= EXCP_DIV
;
55 nios2_cpu_loop_exit_advance(env
, ra
);
59 int32_t helper_divs(CPUNios2State
*env
, int32_t num
, int32_t den
)
61 if (unlikely(den
== 0) || unlikely(den
== -1 && num
== INT32_MIN
)) {
62 maybe_raise_div(env
, GETPC());
63 return num
; /* undefined */
68 uint32_t helper_divu(CPUNios2State
*env
, uint32_t num
, uint32_t den
)
70 if (unlikely(den
== 0)) {
71 maybe_raise_div(env
, GETPC());
72 return num
; /* undefined */
77 #ifndef CONFIG_USER_ONLY
78 void helper_eret(CPUNios2State
*env
, uint32_t new_status
, uint32_t new_pc
)
80 Nios2CPU
*cpu
= env_archcpu(env
);
81 CPUState
*cs
= env_cpu(env
);
83 if (unlikely(new_pc
& 3)) {
84 env
->ctrl
[CR_BADADDR
] = new_pc
;
85 cs
->exception_index
= EXCP_UNALIGND
;
86 nios2_cpu_loop_exit_advance(env
, GETPC());
90 * None of estatus, bstatus, or sstatus have constraints on write;
91 * do not allow reserved fields in status to be set.
92 * When shadow registers are enabled, eret *does* restore CRS.
93 * Rather than testing eic_present to decide, mask CRS out of
94 * the set of readonly fields.
96 new_status
&= cpu
->cr_state
[CR_STATUS
].writable
|
97 (cpu
->cr_state
[CR_STATUS
].readonly
& R_CR_STATUS_CRS_MASK
);
99 env
->ctrl
[CR_STATUS
] = new_status
;
101 nios2_update_crs(env
);
106 * RDPRS and WRPRS are implemented out of line so that if PRS == CRS,
107 * all of the tcg global temporaries are synced back to ENV.
109 uint32_t helper_rdprs(CPUNios2State
*env
, uint32_t regno
)
111 unsigned prs
= FIELD_EX32(env
->ctrl
[CR_STATUS
], CR_STATUS
, PRS
);
112 return env
->shadow_regs
[prs
][regno
];
115 void helper_wrprs(CPUNios2State
*env
, uint32_t regno
, uint32_t val
)
117 unsigned prs
= FIELD_EX32(env
->ctrl
[CR_STATUS
], CR_STATUS
, PRS
);
118 env
->shadow_regs
[prs
][regno
] = val
;
120 #endif /* !CONFIG_USER_ONLY */