MIPS汇编商抱怨PIC "Branch out of range"



我正在尝试为Android/MIPSEL32构建一个程序集源文件。这是一个奇怪的Pascal编译器问题的测试用例;但是这个错误可能是在汇编程序中。

MIPS汇编程序如何在PIC模式下实现j命令?我有一个j-to-label语句,其中标签距离当前指令184200字节;在PIC模式下组装时,组装程序出错:

 a.s:67: Error: Branch out of range

我可靠的MIPS手册说j采用绝对偏移,应用于256-MB块内。整个代码块的大小远小于256MB。我看不出这个j有什么问题。当不是为PIC编译时,它会按预期工作。为什么要谈论分支?分支和跳转在MIPS上是明显不同的。

在这种情况下,PC相对偏移量将是18比特长。忍不住注意到它刚刚超过b的限制。汇编程序会在PIC模式下悄悄地将j转换为b吗?汇编程序级命令被实现为与底层体系结构命令同名的宏,这并非闻所未闻。但是函数序言中有一个set .nomacro,不是吗?

请解释一下,也许可以提供一个变通办法。我不介意在构建路径上增加一个脚本程序集修复步骤。

这里,这里,这里也讨论了类似的问题。

为了重新编程步骤,装配源如下所示:

.section .text.n_main
.balign 4
.globl  PASCALMAIN
.type   PASCALMAIN,@function
PASCALMAIN:
.globl  main
.type   main,@function
main:
.ent main
.set    nomips16
.frame  $sp,112,$ra
.mask   0xC0010000,-40
.fmask  0x00000000,0
.set    noreorder
.cpload $t9
.set    nomacro
addiu   $sp,$sp,-112
sw  $ra,72($sp)
sw  $fp,68($sp)
addiu   $fp,$sp,112
.cprestore  104
sw  $s0,64($sp)
lw  $t9,%call16(FPC_INITIALIZEUNITS)($gp)
jalr    $t9
nop
lw  $gp,104($sp)
lw  $t9,%call16(fpc_get_input)($gp)
jalr    $t9
nop
lw  $gp,104($sp)
move    $s0,$v0
lw  $a1,%got(U_$P$A_$$_S)($gp)
addiu   $a1,$a1,%lo(U_$P$A_$$_S)
move    $a0,$s0
addiu   $a2,$zero,255
lw  $t9,%call16(fpc_read_text_shortstr)($gp)
jalr    $t9
nop
lw  $gp,104($sp)
lw  $t9,%call16(FPC_IOCHECK)($gp)
jalr    $t9
nop
lw  $gp,104($sp)
move    $a0,$s0
lw  $t9,%call16(fpc_readln_end)($gp)
jalr    $t9
nop
lw  $gp,104($sp)
lw  $t9,%call16(FPC_IOCHECK)($gp)
jalr    $t9
nop
lw  $gp,104($sp)
lw  $v0,%got(U_$P$A_$$_I)($gp)
sw  $zero,%lo(U_$P$A_$$_I)($v0)
lw  $v0,%got(U_$P$A_$$_S)($gp)
lbu $v0,%lo(U_$P$A_$$_S)($v0)
beq $v0,$zero,.Lj15
nop
# fixup_jmps, A_BA changed into A_J
j   .Lj16
nop
.Lj15:
##### Then there's the following fragment, repeated 9210 times:
lw  $v0,%got(U_$P$A_$$_I)($gp)
lw  $v1,%lo(U_$P$A_$$_I)($v0)
addiu   $v1,$v1,1
lw  $v0,%got(U_$P$A_$$_I)($gp)
sw  $v1,%lo(U_$P$A_$$_I)($v0)
##### End of repeating fragment
.Lj16:
lw  $t9,%call16(FPC_DO_EXIT)($gp)
jalr    $t9
nop
lw  $gp,104($sp)
lw  $s0,64($sp)
lw  $fp,68($sp)
lw  $ra,72($sp)
jr  $ra
addiu   $sp,$sp,112
.set    macro
.set    reorder
.end main

汇编程序调用命令为:

mipsel-linux-android-as.exe -mabi=32 -march=mips32 -W -EL -KPIC -o a.o a.s

编辑:自由Pascal的人已经解决了根本问题。现在不应该出现这种情况,至少在这种特殊情况下不会出现。

EDIT:Free Pascal团队已经解决了这个问题,我要感谢他们。对于这种特殊情况,下面的解决方法不再是必要的,但其他受影响的人可能会感兴趣。


Lame解决方法:我扫描组件,对于目标标签超过32000行的每个j,我用以下内容替换:

la $t9, TargetLabel
jr $t9

至少装配工不再抱怨了。关于CCD_ 10/CCD_。

EDIT:la实现为宏。在PIC模式下,汇编程序将其替换为以下内容:

lw $t9, CurrentFunctionsBase($gp)
addiu $t9, $t9, OffsetWithinFunction

如果偏移量很大,可能会更多。所以它对PIC很友好。

最新更新