a GCC question

Takashi Oe toe at unlserve.unl.edu
Sun Aug 6 12:15:28 EST 2000


Hi,

I have modified the code in arch/ppc/kernel/prom.c to add support for
various depths and it looks like this:

static void
draw_byte(unsigned char c, long locX, long locY)
{
	unsigned long offset	= reloc_offset();
	boot_infos_t* bi	= PTRRELOC(RELOC(disp_bi));
	unsigned char *base	= calc_base(bi, locX << 3, locY << 4);
	unsigned char *font	= &RELOC(vga_font)[((unsigned long)c) *
16];
	int rb			= bi->dispDeviceRowBytes;

	switch (bi->dispDeviceDepth) {
	case 32:
		draw_byte_32(font, (unsigned long *)base, rb);
		break;
	case 16:
		draw_byte_16(font, (unsigned long *)base, rb);
		break;
	case 8:
		draw_byte_8(font, (unsigned long *)base, rb);
		break;
	case 4:
		draw_byte_4(font, (unsigned long *)base, rb);
		break;
	case 2:
		draw_byte_2(font, (unsigned short *)base, rb);
		break;
	case 1:
		draw_byte_1(font, (unsigned char *)base, rb);
		break;
	}
}

At the early boot time when this function is called inside kernel, it is
not at its linked location.  When I have only top three cases (32, 16, 8),
it works just fine.  However, when there are more cases, it doesn't work.
Here is the objdump of the function:

000004e0 <draw_byte>:
     4e0:       94 21 ff d0     stwu    r1,-48(r1)
     4e4:       7c 08 02 a6     mflr    r0
     4e8:       bf 21 00 14     stmw    r25,20(r1)
     4ec:       90 01 00 34     stw     r0,52(r1)
     4f0:       7c 7c 1b 78     mr      r28,r3
     4f4:       7c 9a 23 78     mr      r26,r4
     4f8:       7c b9 2b 78     mr      r25,r5
     4fc:       48 00 00 01     bl      4fc <draw_byte+0x1c>
                        4fc: R_PPC_REL24        reloc_offset
     500:       3d 20 00 00     lis     r9,0
                        502: R_PPC_ADDR16_HA    disp_bi
     504:       7c 7b 1b 78     mr      r27,r3
     508:       39 29 00 00     addi    r9,r9,0
                        50a: R_PPC_ADDR16_LO    disp_bi
     50c:       7f bb 48 2e     lwzx    r29,r27,r9
     510:       57 44 18 38     rlwinm  r4,r26,3,0,28
     514:       7f bd da 14     add     r29,r29,r27
     518:       57 25 20 36     rlwinm  r5,r25,4,0,27
     51c:       7f a3 eb 78     mr      r3,r29
     520:       4b ff fa e1     bl      0 <calc_base>
     524:       81 7d 00 2c     lwz     r11,44(r29)
     528:       3d 20 00 00     lis     r9,0
                        52a: R_PPC_ADDR16_HA    vga_font
     52c:       38 0b ff ff     addi    r0,r11,-1
     530:       57 9c 20 36     rlwinm  r28,r28,4,0,27
     534:       39 29 00 00     addi    r9,r9,0
                        536: R_PPC_ADDR16_LO    vga_font
     538:       28 00 00 1f     cmplwi  r0,31
     53c:       7c 64 1b 78     mr      r4,r3
     540:       7f 9c 4a 14     add     r28,r28,r9
     544:       80 bd 00 34     lwz     r5,52(r29)
     548:       7c 7b e2 14     add     r3,r27,r28
     54c:       41 81 00 54     bgt     5a0 <draw_byte+0xc0>
     550:       3d 60 00 00     lis     r11,0
                        552: R_PPC_ADDR16_HA    .rodata+0x770
     554:       39 6b 07 70     addi    r11,r11,1904
                        556: R_PPC_ADDR16_LO    .rodata+0x770
     558:       54 00 10 3a     rlwinm  r0,r0,2,0,29
     55c:       7d 4b 00 2e     lwzx    r10,r11,r0
     560:       3d 20 00 00     lis     r9,0
                        562: R_PPC_ADDR16_HA    .rodata+0x770
     564:       39 29 07 70     addi    r9,r9,1904
                        566: R_PPC_ADDR16_LO    .rodata+0x770
     568:       7d 4a 4a 14     add     r10,r10,r9
     56c:       7d 49 03 a6     mtctr   r10
     570:       4e 80 04 20     bctr
     574:       48 00 00 91     bl      604 <draw_byte_32>
     578:       48 00 00 28     b       5a0 <draw_byte+0xc0>
     57c:       48 00 01 6d     bl      6e8 <draw_byte_16>
     580:       48 00 00 20     b       5a0 <draw_byte+0xc0>
     584:       48 00 02 31     bl      7b4 <draw_byte_8>
     588:       48 00 00 18     b       5a0 <draw_byte+0xc0>
     58c:       48 00 03 25     bl      8b0 <draw_byte_4>
     590:       48 00 00 10     b       5a0 <draw_byte+0xc0>
     594:       48 00 03 ad     bl      940 <draw_byte_2>
     598:       48 00 00 08     b       5a0 <draw_byte+0xc0>
     59c:       48 00 04 39     bl      9d4 <draw_byte_1>
     5a0:       80 01 00 34     lwz     r0,52(r1)
     5a4:       7c 08 03 a6     mtlr    r0
     5a8:       bb 21 00 14     lmw     r25,20(r1)
     5ac:       38 21 00 30     addi    r1,r1,48
     5b0:       4e 80 00 20     blr

As you can see, the switch statement is causing offsets fetch from
.rodata, and, since .rodata section is also not at its linked location,
the value fetched is total garbage or, in the case of my machine, it
causes a machine check.

Is there a gcc flag which will prevent generation of codes like this?  Or
any suggestion for better C codes?


Takashi Oe


** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/





More information about the Linuxppc-dev mailing list