switch (GET_CODE (XEXP (operands[1], 0)))
{
case REG:
- output_asm_insn ("ldm%(ia%)\t%m1, %M0", operands);
+ if (TARGET_LDRD)
+ output_asm_insn ("ldr%(d%)\t%0, [%m1]", operands);
+ else
+ output_asm_insn ("ldm%(ia%)\t%m1, %M0", operands);
break;
case PRE_INC:
break;
case POST_INC:
- output_asm_insn ("ldm%(ia%)\t%m1!, %M0", operands);
+ if (TARGET_LDRD)
+ output_asm_insn ("ldr%(d%)\t%0, [%m1], #8", operands);
+ else
+ output_asm_insn ("ldm%(ia%)\t%m1!, %M0", operands);
break;
case POST_DEC:
case LABEL_REF:
case CONST:
+ /* We might be able to use ldrd %0, %1 here. However the range is
+ different to ldr/adr, and it is broken on some ARMv7-M
+ implementations. */
output_asm_insn ("adr%?\t%0, %1", operands);
- output_asm_insn ("ldm%(ia%)\t%0, %M0", operands);
+ if (TARGET_LDRD)
+ output_asm_insn ("ldr%(d%)\t%0, [%0]", operands);
+ else
+ output_asm_insn ("ldm%(ia%)\t%0, %M0", operands);
break;
/* ??? This needs checking for thumb2. */
if (GET_CODE (XEXP (operands[1], 0)) == PLUS)
{
- if (GET_CODE (otherops[2]) == CONST_INT)
+ if (GET_CODE (otherops[2]) == CONST_INT && !TARGET_LDRD)
{
switch ((int) INTVAL (otherops[2]))
{
else
output_asm_insn ("sub%?\t%0, %1, %2", otherops);
+ if (TARGET_LDRD)
+ return "ldr%(d%)\t%0, [%0]";
+
return "ldm%(ia%)\t%0, %M0";
}
else
switch (GET_CODE (XEXP (operands[0], 0)))
{
case REG:
- output_asm_insn ("stm%(ia%)\t%m0, %M1", operands);
+ if (TARGET_LDRD)
+ output_asm_insn ("str%(d%)\t%1, [%m0]", operands);
+ else
+ output_asm_insn ("stm%(ia%)\t%m0, %M1", operands);
break;
case PRE_INC:
break;
case POST_INC:
- output_asm_insn ("stm%(ia%)\t%m0!, %M1", operands);
+ if (TARGET_LDRD)
+ output_asm_insn ("str%(d%)\t%1, [%m0], #8", operands);
+ else
+ output_asm_insn ("stm%(ia%)\t%m0!, %M1", operands);
break;
case POST_DEC:
case PLUS:
otherops[2] = XEXP (XEXP (operands[0], 0), 1);
- if (GET_CODE (otherops[2]) == CONST_INT)
+ if (GET_CODE (otherops[2]) == CONST_INT && !TARGET_LDRD)
{
switch ((int) INTVAL (XEXP (XEXP (operands[0], 0), 1)))
{