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(&region);
}

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

Reply via email to