Revision 678dde13 target-i386/helper.c
b/target-i386/helper.c | ||
---|---|---|
1193 | 1193 |
} |
1194 | 1194 |
|
1195 | 1195 |
/* |
1196 |
* Check nested exceptions and change to double or triple fault if |
|
1197 |
* needed. It should only be called, if this is not an interrupt. |
|
1198 |
* Returns the new exception number. |
|
1199 |
*/ |
|
1200 |
int check_exception(int intno, int *error_code) |
|
1201 |
{ |
|
1202 |
char first_contributory = env->old_exception == 0 || |
|
1203 |
(env->old_exception >= 10 && |
|
1204 |
env->old_exception <= 13); |
|
1205 |
char second_contributory = intno == 0 || |
|
1206 |
(intno >= 10 && intno <= 13); |
|
1207 |
|
|
1208 |
if (loglevel & CPU_LOG_INT) |
|
1209 |
fprintf(logfile, "check_exception old: %x new %x\n", |
|
1210 |
env->old_exception, intno); |
|
1211 |
|
|
1212 |
if (env->old_exception == EXCP08_DBLE) |
|
1213 |
cpu_abort(env, "triple fault"); |
|
1214 |
|
|
1215 |
if ((first_contributory && second_contributory) |
|
1216 |
|| (env->old_exception == EXCP0E_PAGE && |
|
1217 |
(second_contributory || (intno == EXCP0E_PAGE)))) { |
|
1218 |
intno = EXCP08_DBLE; |
|
1219 |
*error_code = 0; |
|
1220 |
} |
|
1221 |
|
|
1222 |
if (second_contributory || (intno == EXCP0E_PAGE) || |
|
1223 |
(intno == EXCP08_DBLE)) |
|
1224 |
env->old_exception = intno; |
|
1225 |
|
|
1226 |
return intno; |
|
1227 |
} |
|
1228 |
|
|
1229 |
/* |
|
1196 | 1230 |
* Signal an interruption. It is executed in the main CPU loop. |
1197 | 1231 |
* is_int is TRUE if coming from the int instruction. next_eip is the |
1198 | 1232 |
* EIP value AFTER the interrupt instruction. It is only relevant if |
... | ... | |
1201 | 1235 |
void raise_interrupt(int intno, int is_int, int error_code, |
1202 | 1236 |
int next_eip_addend) |
1203 | 1237 |
{ |
1238 |
if (!is_int) |
|
1239 |
intno = check_exception(intno, &error_code); |
|
1240 |
|
|
1204 | 1241 |
env->exception_index = intno; |
1205 | 1242 |
env->error_code = error_code; |
1206 | 1243 |
env->exception_is_int = is_int; |
... | ... | |
1211 | 1248 |
/* same as raise_exception_err, but do not restore global registers */ |
1212 | 1249 |
static void raise_exception_err_norestore(int exception_index, int error_code) |
1213 | 1250 |
{ |
1251 |
exception_index = check_exception(exception_index, &error_code); |
|
1252 |
|
|
1214 | 1253 |
env->exception_index = exception_index; |
1215 | 1254 |
env->error_code = error_code; |
1216 | 1255 |
env->exception_is_int = 0; |
Also available in: Unified diff