[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [patch] Various (mostly) x86-64 related patches
From: |
Filip Navara |
Subject: |
Re: [Qemu-devel] [patch] Various (mostly) x86-64 related patches |
Date: |
Sat, 23 Jul 2005 16:34:04 +0200 |
User-agent: |
Mozilla Thunderbird 0.9 (Windows/20041103) |
Two more patches...
qemu-20050723-05-apic.diff
EXTINT delivery mode support for I/O APIC.
qemu-20050723-06-div.diff
Raise #DE exception on DIV/IDIV overflows.
--- hw/apic.c Sat Jul 23 16:23:17 2005
+++ hw/apic.c Fri Jul 22 20:49:53 2005
@@ -127,7 +127,7 @@ static void apic_bus_deliver(uint32_t de
return;
case APIC_DM_EXTINT:
- /* XXX: implement */
+ /* handled in I/O APIC code */
break;
default:
@@ -742,24 +742,34 @@ int apic_init(CPUState *env)
static void ioapic_service(IOAPICState *s)
{
+ uint8_t i;
+ uint8_t trig_mode;
uint8_t vector;
+ uint8_t delivery_mode;
uint32_t mask;
uint64_t entry;
uint8_t dest;
uint8_t dest_mode;
+ uint8_t polarity;
- for (vector = 0; vector < IOAPIC_NUM_PINS; vector++) {
- mask = 1 << vector;
+ for (i = 0; i < IOAPIC_NUM_PINS; i++) {
+ mask = 1 << i;
if (s->irr & mask) {
- entry = s->ioredtbl[vector];
+ entry = s->ioredtbl[i];
if (!(entry & APIC_LVT_MASKED)) {
- if (!((entry >> 15) & 1))
- s->irr &= ~mask;
+ trig_mode = ((entry >> 15) & 1);
dest = entry >> 56;
dest_mode = (entry >> 11) & 1;
+ delivery_mode = (entry >> 8) & 7;
+ polarity = (entry >> 13) & 1;
+ if (trig_mode == APIC_TRIGGER_EDGE)
+ s->irr &= ~mask;
+ if (delivery_mode == APIC_DM_EXTINT)
+ vector = pic_read_irq(isa_pic);
+ else
+ vector = entry & 0xff;
apic_bus_deliver(apic_get_delivery_bitmask(dest, dest_mode),
- (entry >> 8) & 7, entry & 0xff,
- (entry >> 13) & 1, (entry >> 15) & 1);
+ delivery_mode, vector, polarity, trig_mode);
}
}
}
--- target-i386/helper.c Sat Jul 23 16:23:17 2005
+++ target-i386/helper.c Sat Jul 23 15:13:34 2005
@@ -1209,13 +1209,13 @@ void raise_exception(int exception_index
#ifdef BUGGY_GCC_DIV64
/* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we
call it from another function */
-uint32_t div32(uint32_t *q_ptr, uint64_t num, uint32_t den)
+uint32_t div32(uint64_t *q_ptr, uint64_t num, uint32_t den)
{
*q_ptr = num / den;
return num % den;
}
-int32_t idiv32(int32_t *q_ptr, int64_t num, int32_t den)
+int32_t idiv32(int64_t *q_ptr, int64_t num, int32_t den)
{
*q_ptr = num / den;
return num % den;
@@ -1224,8 +1224,8 @@ int32_t idiv32(int32_t *q_ptr, int64_t n
void helper_divl_EAX_T0(void)
{
- unsigned int den, q, r;
- uint64_t num;
+ unsigned int den, r;
+ uint64_t num, q;
num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
den = T0;
@@ -1238,14 +1238,17 @@ void helper_divl_EAX_T0(void)
q = (num / den);
r = (num % den);
#endif
+ if (q > 0xffffffff) {
+ raise_exception(EXCP00_DIVZ);
+ }
EAX = (uint32_t)q;
EDX = (uint32_t)r;
}
void helper_idivl_EAX_T0(void)
{
- int den, q, r;
- int64_t num;
+ int den, r;
+ int64_t num, q;
num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
den = T0;
@@ -1258,6 +1262,9 @@ void helper_idivl_EAX_T0(void)
q = (num / den);
r = (num % den);
#endif
+ if (q > 0x7fffffff || q < -0x7fffffff) {
+ raise_exception(EXCP00_DIVZ);
+ }
EAX = (uint32_t)q;
EDX = (uint32_t)r;
}
--- target-i386/op.c Sat Jul 23 16:23:17 2005
+++ target-i386/op.c Sat Jul 23 13:55:13 2005
@@ -328,7 +328,6 @@ void OPPROTO op_imulq_T0_T1(void)
#endif
/* division, flags are undefined */
-/* XXX: add exceptions for overflow */
void OPPROTO op_divb_AL_T0(void)
{
@@ -341,6 +340,9 @@ void OPPROTO op_divb_AL_T0(void)
}
q = (num / den) & 0xff;
r = (num % den) & 0xff;
+ if (q > 0xff) {
+ raise_exception(EXCP00_DIVZ);
+ }
EAX = (EAX & ~0xffff) | (r << 8) | q;
}
@@ -355,6 +357,9 @@ void OPPROTO op_idivb_AL_T0(void)
}
q = (num / den) & 0xff;
r = (num % den) & 0xff;
+ if (q > 0x7f || q < -0x7f) {
+ raise_exception(EXCP00_DIVZ);
+ }
EAX = (EAX & ~0xffff) | (r << 8) | q;
}
@@ -369,6 +374,9 @@ void OPPROTO op_divw_AX_T0(void)
}
q = (num / den) & 0xffff;
r = (num % den) & 0xffff;
+ if (q > 0xffff) {
+ raise_exception(EXCP00_DIVZ);
+ }
EAX = (EAX & ~0xffff) | q;
EDX = (EDX & ~0xffff) | r;
}
@@ -384,6 +392,9 @@ void OPPROTO op_idivw_AX_T0(void)
}
q = (num / den) & 0xffff;
r = (num % den) & 0xffff;
+ if (q > 0x7fff || q < -0x7fff) {
+ raise_exception(EXCP00_DIVZ);
+ }
EAX = (EAX & ~0xffff) | q;
EDX = (EDX & ~0xffff) | r;
}