]>
git.proxmox.com Git - mirror_qemu.git/blob - target-ppc/excp_helper.c
2 * PowerPC exception emulation helpers for QEMU.
4 * Copyright (c) 2003-2007 Jocelyn Mayer
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 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 <http://www.gnu.org/licenses/>.
22 #include "helper_regs.h"
25 //#define DEBUG_EXCEPTIONS
27 /*****************************************************************************/
28 /* Exceptions processing helpers */
30 void helper_raise_exception_err(CPUPPCState
*env
, uint32_t exception
,
34 printf("Raise exception %3x code : %d\n", exception
, error_code
);
36 env
->exception_index
= exception
;
37 env
->error_code
= error_code
;
41 void helper_raise_exception(CPUPPCState
*env
, uint32_t exception
)
43 helper_raise_exception_err(env
, exception
, 0);
46 #if !defined(CONFIG_USER_ONLY)
47 void helper_store_msr(CPUPPCState
*env
, target_ulong val
)
49 val
= hreg_store_msr(env
, val
, 0);
51 env
->interrupt_request
|= CPU_INTERRUPT_EXITTB
;
52 helper_raise_exception(env
, val
);
56 static inline void do_rfi(CPUPPCState
*env
, target_ulong nip
, target_ulong msr
,
57 target_ulong msrm
, int keep_msrh
)
59 #if defined(TARGET_PPC64)
60 if (msr
& (1ULL << MSR_SF
)) {
62 msr
&= (uint64_t)msrm
;
65 msr
= (uint32_t)(msr
& msrm
);
67 msr
|= env
->msr
& ~((uint64_t)0xFFFFFFFF);
72 msr
&= (uint32_t)msrm
;
74 /* XXX: beware: this is false if VLE is supported */
75 env
->nip
= nip
& ~((target_ulong
)0x00000003);
76 hreg_store_msr(env
, msr
, 1);
78 cpu_dump_rfi(env
->nip
, env
->msr
);
80 /* No need to raise an exception here,
81 * as rfi is always the last insn of a TB
83 env
->interrupt_request
|= CPU_INTERRUPT_EXITTB
;
86 void helper_rfi(CPUPPCState
*env
)
88 do_rfi(env
, env
->spr
[SPR_SRR0
], env
->spr
[SPR_SRR1
],
89 ~((target_ulong
)0x783F0000), 1);
92 #if defined(TARGET_PPC64)
93 void helper_rfid(CPUPPCState
*env
)
95 do_rfi(env
, env
->spr
[SPR_SRR0
], env
->spr
[SPR_SRR1
],
96 ~((target_ulong
)0x783F0000), 0);
99 void helper_hrfid(CPUPPCState
*env
)
101 do_rfi(env
, env
->spr
[SPR_HSRR0
], env
->spr
[SPR_HSRR1
],
102 ~((target_ulong
)0x783F0000), 0);
106 /*****************************************************************************/
107 /* Embedded PowerPC specific helpers */
108 void helper_40x_rfci(CPUPPCState
*env
)
110 do_rfi(env
, env
->spr
[SPR_40x_SRR2
], env
->spr
[SPR_40x_SRR3
],
111 ~((target_ulong
)0xFFFF0000), 0);
114 void helper_rfci(CPUPPCState
*env
)
116 do_rfi(env
, env
->spr
[SPR_BOOKE_CSRR0
], SPR_BOOKE_CSRR1
,
117 ~((target_ulong
)0x3FFF0000), 0);
120 void helper_rfdi(CPUPPCState
*env
)
122 do_rfi(env
, env
->spr
[SPR_BOOKE_DSRR0
], SPR_BOOKE_DSRR1
,
123 ~((target_ulong
)0x3FFF0000), 0);
126 void helper_rfmci(CPUPPCState
*env
)
128 do_rfi(env
, env
->spr
[SPR_BOOKE_MCSRR0
], SPR_BOOKE_MCSRR1
,
129 ~((target_ulong
)0x3FFF0000), 0);
133 void helper_tw(CPUPPCState
*env
, target_ulong arg1
, target_ulong arg2
,
136 if (!likely(!(((int32_t)arg1
< (int32_t)arg2
&& (flags
& 0x10)) ||
137 ((int32_t)arg1
> (int32_t)arg2
&& (flags
& 0x08)) ||
138 ((int32_t)arg1
== (int32_t)arg2
&& (flags
& 0x04)) ||
139 ((uint32_t)arg1
< (uint32_t)arg2
&& (flags
& 0x02)) ||
140 ((uint32_t)arg1
> (uint32_t)arg2
&& (flags
& 0x01))))) {
141 helper_raise_exception_err(env
, POWERPC_EXCP_PROGRAM
,
146 #if defined(TARGET_PPC64)
147 void helper_td(CPUPPCState
*env
, target_ulong arg1
, target_ulong arg2
,
150 if (!likely(!(((int64_t)arg1
< (int64_t)arg2
&& (flags
& 0x10)) ||
151 ((int64_t)arg1
> (int64_t)arg2
&& (flags
& 0x08)) ||
152 ((int64_t)arg1
== (int64_t)arg2
&& (flags
& 0x04)) ||
153 ((uint64_t)arg1
< (uint64_t)arg2
&& (flags
& 0x02)) ||
154 ((uint64_t)arg1
> (uint64_t)arg2
&& (flags
& 0x01))))) {
155 helper_raise_exception_err(env
, POWERPC_EXCP_PROGRAM
,
161 #if !defined(CONFIG_USER_ONLY)
162 /*****************************************************************************/
163 /* PowerPC 601 specific instructions (POWER bridge) */
165 void helper_rfsvc(CPUPPCState
*env
)
167 do_rfi(env
, env
->lr
, env
->ctr
, 0x0000FFFF, 0);
170 /* Embedded.Processor Control */
171 static int dbell2irq(target_ulong rb
)
173 int msg
= rb
& DBELL_TYPE_MASK
;
177 case DBELL_TYPE_DBELL
:
178 irq
= PPC_INTERRUPT_DOORBELL
;
180 case DBELL_TYPE_DBELL_CRIT
:
181 irq
= PPC_INTERRUPT_CDOORBELL
;
183 case DBELL_TYPE_G_DBELL
:
184 case DBELL_TYPE_G_DBELL_CRIT
:
185 case DBELL_TYPE_G_DBELL_MC
:
194 void helper_msgclr(CPUPPCState
*env
, target_ulong rb
)
196 int irq
= dbell2irq(rb
);
202 env
->pending_interrupts
&= ~(1 << irq
);
205 void helper_msgsnd(target_ulong rb
)
207 int irq
= dbell2irq(rb
);
208 int pir
= rb
& DBELL_PIRTAG_MASK
;
215 for (cenv
= first_cpu
; cenv
!= NULL
; cenv
= cenv
->next_cpu
) {
216 if ((rb
& DBELL_BRDCAST
) || (cenv
->spr
[SPR_BOOKE_PIR
] == pir
)) {
217 cenv
->pending_interrupts
|= 1 << irq
;
218 cpu_interrupt(cenv
, CPU_INTERRUPT_HARD
);