The NetBSD i386 kernel sets up the IDT using code that end up (after some
inlining done with -Os or -O3) looking like:
struct region_descriptor { int rd_base; int rd_limit; };
struct gate_descriptor { int x; } *idt;
static __inline void lidt(struct region_descriptor *p) {
__asm volatile("lidt (%0)" : : "r" (p));
}
void set_idt1(void) {
struct region_descriptor region;
region.rd_limit = (int)1024;
region.rd_base = (int)idt;
lidt(®ion);
}
gcc 4.1.2 optimises out the assignments to 'region', so the lidtl instruction
loads a garbage vector table.
Changing the lidt function to:
static __inline void lidt(void *vp) {
int *p = vp;
__asm volatile("lidt %0" : : "m" (*p));
}
seems to fix this case.
But I can't see how to enforce the assignments to:
- a variable size buffer
- a buffer which must be specified in a register in the assembler opcode.
both of which might happen trying to write the pattern for 'rep outsb'.
David
--
Summary: Assignment to data used in __asm() get optimised away.
Product: gcc
Version: 4.1.2
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: dsl at netbsd dot org
GCC host triplet: i386--netbsdelf
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=28729