[Top] [All Lists]

MIPS Assembler help

Subject: MIPS Assembler help
From: Warner Losh <>
Date: Thu, 07 Sep 1995 00:17:58 -0600
What follows is very detailed, but I hope that some of the
"old-timers" can take a look at it and let me know where I'm going

I'm having a crash in the floppy init code.  I'm starting to think
that gcc just might be generating bogus code, but I can't be sure
since I don't swim in MIPS R4x00 assembler just yet.

Before I start, my kernel is compiled -DPORT_BASE=0xB0000000 rather
than using the default address for that, since I don't have my maps
working quite right yet.

I guess I'm having trouble with delay slots.  R -> R operations take
place right away, right?

The 'C' code:
        for(i=0; i< N_FDC; i++){
                if(FDCS->address != -1){        
                        fdc = i;
                        fd_out(FDCS->dor, FD_DOR);      /* 
outb_p(fdc_state[fdc].dor, FD_DOR) */

The fd_out line expands to
        outb_p(fdc_state[fdc].dor, 2 + fdc_state[fdc].address);
and then to
((__builtin_constant_p((2 + fdc_state[fdc].address)) && (2 + 
fdc_state[fdc].address) < 32768) ?
        __outbc_p((fdc_state[fdc].dor),(2 + fdc_state[fdc].address)) :
        __outb_p((fdc_state[fdc].dor),(2 + fdc_state[fdc].address)));
which should optimize to
        __outb_p((fdc_state[fdc].dor),(2 + fdc_state[fdc].address));
since __buildin_constant_p is going to be false.

[[ Hmmm, I've just hacked this part of the code, so maybe that's the
   probelm :-( ]]

which translates to:
extern inline void __outb_p(unsigned int value, unsigned int port) {
__asm__ __volatile__ ("s" #b "\t%0,%1(%2)" : : "r" (value), "i" (0), "r" 
__asm__ __volatile__( "sb\t$0,0x80(%0)" : : "r" (PORT_BASE));
__asm__ __volatile__( "sb\t$0,0x80(%0)" : : "r" (PORT_BASE));
__asm__ __volatile__( "sb\t$0,0x80(%0)" : : "r" (PORT_BASE));
__asm__ __volatile__( "sb\t$0,0x80(%0)" : : "r" (PORT_BASE));

Which then gets expanded out to the following by gcc:
        li      $19,-1342177280                 # 0xb0000000
# $18 seems to be 0x80030b8 which is in the bss section at fdc_state
# fdc is at 0x800830d0, but that is likely not relevant
        lw      $3,fdc
        #nop                            # $3 = 0
        sll     $2,$3,1                 # $2 = 0
        addu    $2,$2,$3                # $2 = 0
        sll     $2,$2,3                 # $2 = 0 (which is fdc * 24, btw)
        lw      $3,fdc_state+16($2)     # Loads the contents of 0x800830e0 into 
                                        # Why n+16????
        addu    $2,$2,$18               # $2 = 80030b8
        lbu     $2,13($2)               # Load the DOR byte into $2
        addu    $3,$3,2                 # $3 should have the address in it now
        addu    $3,$3,$19               # Add 2 and also add the BASE_PORT to $3
        sb      $2,0($3)                # *** $3 = 0x600003f2
        li      $9,-1342177280                  # 0xb0000000
        sb      $0,0x80($9)
        sb      $0,0x80($9)
        sb      $0,0x80($9)
        sb      $0,0x80($9)

At the three stared point in the code, $3 is 0x600003f2.  It really
should be 0xB00003f2.  I'm just not seeing where things are going

address = 0xb000003f0
dor = 0x4.

FD_DOR = 0xb000003f2

FD_DOR is interesting, since it is BASE_PORT + FD_IOPORT + 2, but I
think it should really only be FD_IOPORT + 2 = 0x3f0.  That would make
the macro expand correctly, and 0xb0000000 + 0xb0000000 = 0x160000000
or 0x60000000, which is the virtual address in my crash.

So I'm confused.  Why is it defined like that?  I would guess that is
because that's the way it is on the ACER, MAGNUM and OLIVETTY boards
(fixed at location 0xe00030000), but on all others it is defined to be
PORT_BASE + 0x3f0.  Why not just 0x3f0?  On the Deskstation, that
seems to be the right thing to define it as, but I'm not keen on
breaking anybody else's ports.

Wo whats the right thing to do here?  When I change it to be just
0xf30 I get farther in my boot (it hangs afer printing FDC 0 is a
8272A, which is more progress).  Is this a valid change, or should I
be doing something different?


<Prev in Thread] Current Thread [Next in Thread>