linux-mips
[Top] [All Lists]

Re: function call on MIPS (newbie question)

To: Harald Krapfenbauer <krapfenbauer@ict.tuwien.ac.at>
Subject: Re: function call on MIPS (newbie question)
From: Chris Dearman <chris@mips.com>
Date: Tue, 24 Jun 2008 10:48:17 -0700
Cc: "linux-mips@linux-mips.org" <linux-mips@linux-mips.org>
In-reply-to: <4860C9FD.60103@ict.tuwien.ac.at>
Original-recipient: rfc822;linux-mips@linux-mips.org
References: <4860C9FD.60103@ict.tuwien.ac.at>
Sender: linux-mips-bounce@linux-mips.org
User-agent: Icedove 1.5.0.14eol (X11/20080509)
Harald Krapfenbauer wrote:
Hi!

I'm a newbie to the MIPS architecture and I want to port some program to
MIPS.
I must call a function within the .text segment with 2 simple
parameters. So I figured out the following code which
*) loads arg1 into register $4
*) loads arg2 into register $5
*) loads the address into $15
*) executes a jalr
*) breaks afterwards


        *((guint32 *)(code)) = ((method_argument1 >> 16) & 0xffff) |
0x3c040000;    /* arg 1 upper half word */
        *((guint32 *)(code+4)) = (method_argument1 & 0xffff) | 0x24040000;
     /* arg 1 lower half word */
        *((guint32 *)(code+8)) = ((method_argument2 >> 16) & 0xffff) |
0x3c050000;  /* arg 2 upper half word */
        *((guint32 *)(code+12)) = (method_argument2 & 0xffff) | 0x24050000;
     /* arg 2 lower half word */
        *((guint32 *)(code+16)) = ((method_address >> 16) & 0xffff) |
0x3c0f0000;   /* address upper half word */
        *((guint32 *)(code+20)) = (method_address & 0xffff) | 0x240f0000;
     /* address lower half word */
        *((guint32 *)(code+24)) = 0x01e0f809;
     /* jalr */
        *((guint32 *)(code+28)) = 0x0;
     /* branch delay slot */
        edit *((guint32 *)(code+32)) = 0x0d;
     /* breakpoint */



The code is written to the stack, the SP and the PC are then set to the
beginning of the code on the stack.

Something must be going wrong because after the program stops again, the
PC is 0xffffcb38 (The method address is 0x53cb38) and my program
receives signal 10.

Did I miss something or is my code wrong?
Any help appreciated!

The code you generate for the function address is
3C0F0053  lui         t7,0x53
240FCB38  addiu       t7,zero,-13512

There are 2 problems here... the second instruction should be "addiu t7,t7,-13512" and addiu sign-extends the immediate value so you have to deal with this by adjusting the lui if bit 15 of the address is set. It's simpler to use ori which does not sign-extend the immediate value:

3C0F0053  lui         t7,0x53
35EFEB37  ori         t7,t7,0xeb37

You will need to modify the instructions that load a0 and a1 in the same way.

The next issue will be cache maintenance which you have to do explicitly. Most MIPS CPUs use writeback caches, so you need to flush this data from the dcache into memory and then invalidate the icache to make sure the CPU does not execute stale data. MIPS32 processors support synci to accomplish this. If the processor you're using doesn't have synci, there is a cachectl syscall which does the required cache writeback/invalidation

One final point is calling conventions. If you are calling other JIT code you will know what assumptions it makes about register/stack usage, but if you are calling normal code (eg a library function) then you have to use the normal calling conventions. The caller is required to allocate 4 words at $sp where the callee can store $a0..$a3. PIC code requires that the call is made using "jalr $t9" etc.

If you're new to the MIPS world I'd strongly recommend "See MIPS Run Linux" by Dominic Sweetman which covers a lot of this stuff and is very readable.

Chris

--
Chris Dearman                 Desk:+1 650 567 5092  Cell:+1 650 224 8603
MIPS Technologies Inc         1225 Charleston Rd, Mountain View CA 94043

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