This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: %hi() operator on MIPS


Shinpei Kato <shinpei@rt.k2.keio.ac.jp> writes:
> If we assemble the following codes with -d option, we want to expect the following output. But the actual output is like below.
>
> [code]
> 	lui $8, %hi(0x87f0c000)
> 	ori $8, $8, %lo(0x87f0c000)
>
> [expected output]
> 	lui t0, 0x87f0
> 	ori t0, 0xc000
>
> [actual output]
> 	lui t0, 0x87f1
> 	ori t0, 0xc000
>
> Why 0x87f0 is changed to 0x87f1?

Because %lo() is a _signed_ 16-bit number, not an unsigned number,
and because (for a 32-bit X) %hi(X) = X - %lo(X).  You want to use
addiu instead of ori:

 	lui $8, %hi(0x87f0c000)
 	addiu $8, $8, %lo(0x87f0c000)

The idea behind %lo() being signed is that you can use it as an offset
in memory accesses.  E.g.:

 	lui $8, %hi(0x87f0c000)
 	lw $8, %lo(0x87f0c000)($8)

> If we use la instead of lui/ori/%hi/%lo, it's expanded as follows and works.
>
> [code]
> 	la $8, 0x87f0c000
>
> [output]
> 	lui t0, 0x87f0
> 	ori t0, t0, 0xc000

That's because gas isn't using %hi/%lo internally in this case.

Richard


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]