I want to write code that has a public C interface, but is otherwise implemented entirely in MIPS, mainly as a learning exercise. However, I'm stuck fighting GAS because it seems to assume it knows better than I do.
To illustrate, let's say I want to implement the following in MIPS:
int bar(void)
{
return (4 / 2);
}
As I mentioned above, I want to be able to call ASM routines from C, so we'll need a C code file, bar.c, as well as the MIPS assembly in bar.S.
bar.c:
extern int bar(void);
void _start()
{
int foo = bar();
}
bar.S:
.global bar .text
bar:
addi $2, $0, 4
addi $3, $0, 2
div $2, $3
mflo $2
jr $31
addu $3, $0, $0
mipsel-none-elf-gcc bar.c bar.S -o bar.elf -ffreestanding -nostdinc -nostdlib
successfully compiles this, but mipsel-none-elf-objdump -d bar.elf
shows that GAS is messing with my bar() code:
00400050 <bar>:
400050: 20020004 addi v0,zero,4
400054: 20030002 addi v1,zero,2
400058: 14600002 bnez v1,400064 <bar+0x14>
40005c: 0043001a div zero,v0,v1
400060: 0007000d break 0x7
400064: 2401ffff li at,-1
400068: 14610004 bne v1,at,40007c <bar+0x2c>
40006c: 3c018000 lui at,0x8000
400070: 14410002 bne v0,at,40007c <bar+0x2c>
400074: 00000000 nop
400078: 0006000d break 0x6
40007c: 00001012 mflo v0
400080: 00001012 mflo v0
400084: 03e00008 jr ra
400088: 00000000 nop
40008c: 00001821 move v1,zero
I don't want the division checks, or delay slot fixups, or the assembler being "helpful" in any way here: I'm perfectly capable of handling those things myself if necessary. How do I tell GAS to just be a dumb assembler?
This one was solved in the comments. GAS accepts a 3-operand version of div
where division checks are disabled if the first operand is $0
. As for the delay slot, a .set noreorder
directive prevents reordering of instructions (duh). Changing the assembly to:
.set noreorder
.global bar .text
bar:
addi $2, $0, 4
addi $3, $0, 2
div $0, $2, $3
mflo $2
jr $31
addu $3, $0, $0
produces the correct output:
00400050 <bar>:
400050: 20020004 addi v0,zero,4
400054: 20030002 addi v1,zero,2
400058: 0043001a div zero,v0,v1
40005c: 00001012 mflo v0
400060: 03e00008 jr ra
400064: 00001821 move v1,zero