3
votes

I am a master student and currently doing my summer final project, which is about design a MIPS processor with a FPU and implement in a FPGA.

The instructions that I'm going to implement are depended on the cross-compiler I'm using. So, from a hardware designer point of view, I started the project by first looking the instructions can be generated from the compiler.

For integer design(the main core design), I wrote some C codes, here for example, a simple one:

int main ()
{
int a,b,c;
a=1;
b=2;
c=a+2;
}

A simple addition, the compiler gives assembly codes: (I just posted the assembly codes in main, because I did not plan to run a operating system on my MIPS)

00400168 <main>:
  400168:       27bdffe8        addiu   sp,sp,-24
  40016c:       afbe0010        sw      s8,16(sp)
  400170:       03a0f021        move    s8,sp
  400174:       24020001        li      v0,1
  400178:       afc20008        sw      v0,8(s8)
  40017c:       24020002        li      v0,2
  400180:       afc20004        sw      v0,4(s8)
  400184:       8fc20008        lw      v0,8(s8)
  400188:       00000000        nop
  40018c:       20420002        addi    v0,v0,2
  400190:       afc20000        sw      v0,0(s8)
  400194:       03c0e821        move    sp,s8
  400198:       8fbe0010        lw      s8,16(sp)
  40019c:       27bd0018        addiu   sp,sp,24
  4001a0:       03e00008        jr      ra

I like to understand the assembly code, that can helps me more understand MIPS architecture, and based on the instructions order I can design a hazard detection unit based on the compiler.

We can see from those 4 instruction:

  400174:       24020001        li      v0,1
  400178:       afc20008        sw      v0,8(s8)
  40017c:       24020002        li      v0,2
  400180:       afc20004        sw      v0,4(s8)

The compiler loads 1, 2 into variable a, b. For the integer assembly code, I can understand no problems.

Ok, lets go to the floating point unit, as the same, I wrote a very similar C :

Floating point testing C code

void main ()
{
float a,b,c;
a=1;
b=2;
c=a+b;
}

Now the assembly codes are much different:

00400168 <main>:
  400168:       27bdffe8        addiu   sp,sp,-24
  40016c:       afbe0010        sw      s8,16(sp)
  400170:       03a0f021        move    s8,sp
  400174:       c7808004        lwc1    $f0,-32764(gp)
  400178:       00000000        nop
  40017c:       e7c00008        swc1    $f0,8(s8)
  400180:       c7808008        lwc1    $f0,-32760(gp)
  400184:       00000000        nop
  400188:       e7c00004        swc1    $f0,4(s8)
  40018c:       c7c20008        lwc1    $f2,8(s8)
  400190:       c7c00004        lwc1    $f0,4(s8)
  400194:       00000000        nop
  400198:       46001000        add.s   $f0,$f2,$f0
  40019c:       e7c00000        swc1    $f0,0(s8)
  4001a0:       03c0e821        move    sp,s8
  4001a4:       8fbe0010        lw      s8,16(sp)
  4001a8:       27bd0018        addiu   sp,sp,24
  4001ac:       03e00008        jr      ra
  4001b0:       00000000        nop

Doesn't like pervious code, those 6 instructions looks like the program load the variable's value from data memory instead using instruction li:

  400174:       c7808004        lwc1    $f0,-32764(gp)
  400178:       00000000        nop
  40017c:       e7c00008        swc1    $f0,8(s8)
  400180:       c7808008        lwc1    $f0,-32760(gp)
  400184:       00000000        nop
  400188:       e7c00004        swc1    $f0,4(s8)

Here comes the problem, I just can not figure out what is value stored in -32764(gp) and f0,-32760(gp), because there are not any SW instructions that try to store data into those address.

Here is the fully assembly code generated by compiler:

floatadd:     file format elf32-bigmips


Disassembly of section .init:

00400018 <_init>:
  400018:       27bdffe0        addiu   sp,sp,-32
  40001c:       afbf0014        sw      ra,20(sp)
  400020:       0c10003a        jal     4000e8 <frame_dummy>
  400024:       00000000        nop
  400028:       0c10006d        jal     4001b4 <__do_global_ctors_aux>
  40002c:       00000000        nop
  400030:       8fbf0014        lw      ra,20(sp)
  400034:       27bd0020        addiu   sp,sp,32
  400038:       03e00008        jr      ra
  40003c:       00000000        nop

Disassembly of section .text:

00400040 <_ftext>:
  400040:       27bdffe0        addiu   sp,sp,-32
  400044:       afb10014        sw      s1,20(sp)
  400048:       3c110040        lui     s1,0x40
  40004c:       9222126c        lbu     v0,4716(s1)
  400050:       afbf0018        sw      ra,24(sp)
  400054:       14400019        bnez    v0,4000bc <_ftext+0x7c>
  400058:       afb00010        sw      s0,16(sp)
  40005c:       3c100040        lui     s0,0x40
  400060:       8e021260        lw      v0,4704(s0)
  400064:       00000000        nop
  400068:       8c430000        lw      v1,0(v0)
  40006c:       00000000        nop
  400070:       10600009        beqz    v1,400098 <_ftext+0x58>
  400074:       24420004        addiu   v0,v0,4
  400078:       0060f809        jalr    v1
  40007c:       ae021260        sw      v0,4704(s0)
  400080:       8e021260        lw      v0,4704(s0)
  400084:       00000000        nop
  400088:       8c430000        lw      v1,0(v0)
  40008c:       00000000        nop
  400090:       1460fff9        bnez    v1,400078 <_ftext+0x38>
  400094:       24420004        addiu   v0,v0,4
  400098:       3c020000        lui     v0,0x0
  40009c:       24420000        addiu   v0,v0,0
  4000a0:       10400005        beqz    v0,4000b8 <_ftext+0x78>
  4000a4:       24020001        li      v0,1
  4000a8:       3c040040        lui     a0,0x40
  4000ac:       0c000000        jal     0 <_init-0x400018>
  4000b0:       24840244        addiu   a0,a0,580
  4000b4:       24020001        li      v0,1
  4000b8:       a222126c        sb      v0,4716(s1)
  4000bc:       8fbf0018        lw      ra,24(sp)
  4000c0:       8fb10014        lw      s1,20(sp)
  4000c4:       8fb00010        lw      s0,16(sp)
  4000c8:       03e00008        jr      ra
  4000cc:       27bd0020        addiu   sp,sp,32

004000d0 <call___do_global_dtors_aux>:
  4000d0:       27bdffe8        addiu   sp,sp,-24
  4000d4:       afbf0010        sw      ra,16(sp)
  4000d8:       8fbf0010        lw      ra,16(sp)
  4000dc:       00000000        nop
  4000e0:       03e00008        jr      ra
  4000e4:       27bd0018        addiu   sp,sp,24

004000e8 <frame_dummy>:
  4000e8:       3c020000        lui     v0,0x0
  4000ec:       27bdffe8        addiu   sp,sp,-24
  4000f0:       3c040040        lui     a0,0x40
  4000f4:       3c050040        lui     a1,0x40
  4000f8:       24420000        addiu   v0,v0,0
  4000fc:       afbf0010        sw      ra,16(sp)
  400100:       24840244        addiu   a0,a0,580
  400104:       10400003        beqz    v0,400114 <frame_dummy+0x2c>
  400108:       24a51270        addiu   a1,a1,4720
  40010c:       0c000000        jal     0 <_init-0x400018>
  400110:       00000000        nop
  400114:       3c040040        lui     a0,0x40
  400118:       8c831258        lw      v1,4696(a0)
  40011c:       3c020000        lui     v0,0x0
  400120:       10600007        beqz    v1,400140 <frame_dummy+0x58>
  400124:       24590000        addiu   t9,v0,0
  400128:       24841258        addiu   a0,a0,4696
  40012c:       13200004        beqz    t9,400140 <frame_dummy+0x58>
  400130:       00000000        nop
  400134:       8fbf0010        lw      ra,16(sp)
  400138:       03200008        jr      t9
  40013c:       27bd0018        addiu   sp,sp,24
  400140:       8fbf0010        lw      ra,16(sp)
  400144:       00000000        nop
  400148:       03e00008        jr      ra
  40014c:       27bd0018        addiu   sp,sp,24

00400150 <call_frame_dummy>:
  400150:       27bdffe8        addiu   sp,sp,-24
  400154:       afbf0010        sw      ra,16(sp)
  400158:       8fbf0010        lw      ra,16(sp)
  40015c:       00000000        nop
  400160:       03e00008        jr      ra
  400164:       27bd0018        addiu   sp,sp,24

00400168 <main>:
  400168:       27bdffe8        addiu   sp,sp,-24
  40016c:       afbe0010        sw      s8,16(sp)
  400170:       03a0f021        move    s8,sp
  400174:       c7808004        lwc1    $f0,-32764(gp)
  400178:       00000000        nop
  40017c:       e7c00008        swc1    $f0,8(s8)
  400180:       c7808008        lwc1    $f0,-32760(gp)
  400184:       00000000        nop
  400188:       e7c00004        swc1    $f0,4(s8)
  40018c:       c7c20008        lwc1    $f2,8(s8)
  400190:       c7c00004        lwc1    $f0,4(s8)
  400194:       00000000        nop
  400198:       46001000        add.s   $f0,$f2,$f0
  40019c:       e7c00000        swc1    $f0,0(s8)
  4001a0:       03c0e821        move    sp,s8
  4001a4:       8fbe0010        lw      s8,16(sp)
  4001a8:       27bd0018        addiu   sp,sp,24
  4001ac:       03e00008        jr      ra
  4001b0:       00000000        nop

004001b4 <__do_global_ctors_aux>:
  4001b4:       3c020040        lui     v0,0x40
  4001b8:       2442124c        addiu   v0,v0,4684
  4001bc:       8c44fffc        lw      a0,-4(v0)
  4001c0:       27bdffe0        addiu   sp,sp,-32
  4001c4:       2403ffff        li      v1,-1
  4001c8:       afb00010        sw      s0,16(sp)
  4001cc:       afbf0018        sw      ra,24(sp)
  4001d0:       afb10014        sw      s1,20(sp)
  4001d4:       10830008        beq     a0,v1,4001f8 <__do_global_ctors_aux+0x44>
  4001d8:       2450fffc        addiu   s0,v0,-4
  4001dc:       2411ffff        li      s1,-1
  4001e0:       0080f809        jalr    a0
  4001e4:       2610fffc        addiu   s0,s0,-4
  4001e8:       8e040000        lw      a0,0(s0)
  4001ec:       00000000        nop
  4001f0:       1491fffb        bne     a0,s1,4001e0 <__do_global_ctors_aux+0x2c>
  4001f4:       00000000        nop
  4001f8:       8fbf0018        lw      ra,24(sp)
  4001fc:       8fb10014        lw      s1,20(sp)
  400200:       8fb00010        lw      s0,16(sp)
  400204:       03e00008        jr      ra
  400208:       27bd0020        addiu   sp,sp,32

0040020c <call___do_global_ctors_aux>:
  40020c:       27bdffe8        addiu   sp,sp,-24
  400210:       afbf0010        sw      ra,16(sp)
  400214:       8fbf0010        lw      ra,16(sp)
  400218:       00000000        nop
  40021c:       03e00008        jr      ra
  400220:       27bd0018        addiu   sp,sp,24

Disassembly of section .fini:

00400224 <_fini>:
  400224:       27bdffe0        addiu   sp,sp,-32
  400228:       afbf0014        sw      ra,20(sp)
  40022c:       0c100010        jal     400040 <_ftext>
  400230:       00000000        nop
  400234:       8fbf0014        lw      ra,20(sp)
  400238:       27bd0020        addiu   sp,sp,32
  40023c:       03e00008        jr      ra
  400240:       00000000        nop

I am not good at MIPS assembly, can someone explain where are the floating point variable' value 1 and 2?

1
Could you include a dump of the .data section? That's probably where $gp is pointing to.Michael
I don't know exactly what target you built for, but when I built with -mhard-float -mips32 I found the floats in the .sdata section: Disassembly of section .sdata: 00000000 <.sdata>: 0: 3f800000 0x3f800000 4: 40000000 mfc0 zero,c0_index. 0x3f800000 is 1.0f, and 0x40000000 is 2.0f.Michael
I do not know what is the .data section.... The codes I posted are all I have got from compiler.Shuaiyu Jiang
If you use the -D switch with objdump you should get all sections instead of just the ones containing code.Michael
$gp points to the middle of the 64k static data section, so -32764($gp) is the first or second word of that section. Presumably $gp is expected to be set up by the loader.Jester

1 Answers

4
votes

About your question

ELF executables can have one or more sections filled with the static data (string, floating point numbers, numbers, whatever) used by the program.
This sections are loaded into memory by the loader with the rest of the program, thereby avoiding intermixing code and data and reducing the code size.

For the ELF on MIPS systems you should refer to this where there is this nice picture:

MIPS ELF Sections

As you can see $gp is used to address the section .sdata and .sbss, where the initial s stands for small.

All these efforts are taken to minimize code size as by using $gp the compiler can generate 16 bit offsets (versus the 32 bit ones normally used).
Since the offset is signed, $gp is placed in the middle of a (at most) 64 KiB region formed by .sdata + .sbss.

Your floating points value are not coded directly in the instructions because FP instruction does not takes immediates, instead they are saved into a readonly section and loaded from there.

About your purpose

Why in the end do you care about this?
If your goal is to design an implementation of the MIPS ISA, just pick the specific ISA (MIPS32 I? MIPS32 IV? MIPS 64?), get the documents, get the whole picture and implement a microarchitecture for it.

If an instruction is a valid instruction according to your chosen ISA then your implementation must be able to execute it, don't worry about what the compilers are doing, they are grown up, they can take care of them selves and in the end if the code you are executing is broken, who cares? As long it is valid.

These will help you:

MIPS32™ Architecture For Programmers Volume I: Introduction to the MIPS32™ Architecture MIPS32™ Architecture For Programmers Volume II: The MIPS32™ Instruction Set