@@ -3520,18 +3520,22 @@ msp430_expand_shift (enum rtx_code code, machine_mode mode, rtx *operands)
3520
3520
For 430X it is inneficient to do so for any modes except SI and DI, since we
3521
3521
can make use of R*M insns or RPT with 430X insns, so this function is only
3522
3522
used for SImode in that case. */
3523
- const char *
3523
+ int
3524
3524
msp430_output_asm_shift_insns (enum rtx_code code , machine_mode mode ,
3525
- rtx * operands )
3525
+ rtx * operands , bool return_length )
3526
3526
{
3527
3527
int i ;
3528
3528
int amt ;
3529
3529
int max_shift = GET_MODE_BITSIZE (mode ) - 1 ;
3530
+ int length = 0 ;
3531
+
3530
3532
gcc_assert (CONST_INT_P (operands [2 ]));
3531
3533
amt = INTVAL (operands [2 ]);
3532
3534
3533
3535
if (amt == 0 || amt > max_shift )
3534
3536
{
3537
+ if (return_length )
3538
+ return 0 ;
3535
3539
switch (code )
3536
3540
{
3537
3541
case ASHIFT :
@@ -3549,51 +3553,90 @@ msp430_output_asm_shift_insns (enum rtx_code code, machine_mode mode,
3549
3553
default :
3550
3554
gcc_unreachable ();
3551
3555
}
3552
- return "" ;
3556
+ return 0 ;
3553
3557
}
3554
3558
3555
3559
if (code == ASHIFT )
3556
3560
{
3557
3561
if (!msp430x && mode == HImode )
3558
- for (i = 0 ; i < amt ; i ++ )
3559
- output_asm_insn ("RLA.W\t%0" , operands );
3562
+ {
3563
+ if (return_length )
3564
+ length = 2 + (MEM_P (operands [0 ]) ? 2 : 0 );
3565
+ else
3566
+ for (i = 0 ; i < amt ; i ++ )
3567
+ output_asm_insn ("RLA.W\t%0" , operands );
3568
+ }
3560
3569
else if (mode == SImode )
3561
- for (i = 0 ; i < amt ; i ++ )
3562
- output_asm_insn ("RLA%X0.W\t%L0 { RLC%X0.W\t%H0" , operands );
3570
+ {
3571
+ if (return_length )
3572
+ length = 4 + (MEM_P (operands [0 ]) ? 4 : 0 )
3573
+ + (4 * msp430x_insn_required (operands [0 ]));
3574
+ else
3575
+ for (i = 0 ; i < amt ; i ++ )
3576
+ output_asm_insn ("RLA%X0.W\t%L0 { RLC%X0.W\t%H0" , operands );
3577
+ }
3563
3578
else
3564
3579
/* Catch unhandled cases. */
3565
3580
gcc_unreachable ();
3566
3581
}
3567
3582
else if (code == ASHIFTRT )
3568
3583
{
3569
3584
if (!msp430x && mode == HImode )
3570
- for (i = 0 ; i < amt ; i ++ )
3571
- output_asm_insn ("RRA.W\t%0" , operands );
3585
+ {
3586
+ if (return_length )
3587
+ length = 2 + (MEM_P (operands [0 ]) ? 2 : 0 );
3588
+ else
3589
+ for (i = 0 ; i < amt ; i ++ )
3590
+ output_asm_insn ("RRA.W\t%0" , operands );
3591
+ }
3572
3592
else if (mode == SImode )
3573
- for (i = 0 ; i < amt ; i ++ )
3574
- output_asm_insn ("RRA%X0.W\t%H0 { RRC%X0.W\t%L0" , operands );
3593
+ {
3594
+ if (return_length )
3595
+ length = 4 + (MEM_P (operands [0 ]) ? 4 : 0 )
3596
+ + (4 * msp430x_insn_required (operands [0 ]));
3597
+ else
3598
+ for (i = 0 ; i < amt ; i ++ )
3599
+ output_asm_insn ("RRA%X0.W\t%H0 { RRC%X0.W\t%L0" , operands );
3600
+ }
3575
3601
else
3576
3602
gcc_unreachable ();
3577
3603
}
3578
3604
else if (code == LSHIFTRT )
3579
3605
{
3580
3606
if (!msp430x && mode == HImode )
3581
- for (i = 0 ; i < amt ; i ++ )
3582
- output_asm_insn ("CLRC { RRC.W\t%0" , operands );
3607
+ {
3608
+ if (return_length )
3609
+ length = 4 + (MEM_P (operands [0 ]) ? 2 : 0 );
3610
+ else
3611
+ for (i = 0 ; i < amt ; i ++ )
3612
+ output_asm_insn ("CLRC { RRC.W\t%0" , operands );
3613
+ }
3583
3614
else if (mode == SImode )
3584
- for (i = 0 ; i < amt ; i ++ )
3585
- output_asm_insn ("CLRC { RRC%X0.W\t%H0 { RRC%X0.W\t%L0" , operands );
3615
+ {
3616
+ if (return_length )
3617
+ length = 6 + (MEM_P (operands [0 ]) ? 4 : 0 )
3618
+ + (4 * msp430x_insn_required (operands [0 ]));
3619
+ else
3620
+ for (i = 0 ; i < amt ; i ++ )
3621
+ output_asm_insn ("CLRC { RRC%X0.W\t%H0 { RRC%X0.W\t%L0" ,
3622
+ operands );
3623
+ }
3586
3624
/* FIXME: Why doesn't "RRUX.W\t%H0 { RRC%X0.W\t%L0" work for msp430x?
3587
3625
It causes execution timeouts e.g. pr41963.c. */
3588
3626
#if 0
3589
3627
else if (msp430x && mode == SImode )
3590
- for (i = 0 ; i < amt ; i ++ )
3591
- output_asm_insn ("RRUX.W\t%H0 { RRC%X0.W\t%L0" , operands );
3628
+ {
3629
+ if (return_length )
3630
+ length = 2 ;
3631
+ else
3632
+ for (i = 0 ; i < amt ; i ++ )
3633
+ output_asm_insn ("RRUX.W\t%H0 { RRC%X0.W\t%L0" , operands );
3634
+ }
3592
3635
#endif
3593
3636
else
3594
3637
gcc_unreachable ();
3595
3638
}
3596
- return "" ;
3639
+ return length * amt ;
3597
3640
}
3598
3641
3599
3642
/* Called by cbranch<mode>4 to coerce operands into usable forms. */
@@ -4115,6 +4158,20 @@ msp430_op_not_in_high_mem (rtx op)
4115
4158
return false;
4116
4159
}
4117
4160
4161
+ /* Based on the operand OP, is a 430X insn required to handle it?
4162
+ There are only 3 conditions for which a 430X insn is required:
4163
+ - PSImode operand
4164
+ - memory reference to a symbol which could be in upper memory
4165
+ (so its address is > 0xFFFF)
4166
+ - absolute address which has VOIDmode, i.e. (mem:HI (const_int))
4167
+ Use a 430 insn if none of these conditions are true. */
4168
+ bool
4169
+ msp430x_insn_required (rtx op )
4170
+ {
4171
+ return (GET_MODE (op ) == PSImode
4172
+ || !msp430_op_not_in_high_mem (op ));
4173
+ }
4174
+
4118
4175
#undef TARGET_PRINT_OPERAND
4119
4176
#define TARGET_PRINT_OPERAND msp430_print_operand
4120
4177
@@ -4455,35 +4512,52 @@ msp430_register_pre_includes (const char *sysroot ATTRIBUTE_UNUSED,
4455
4512
4456
4513
/* Generate a sequence of instructions to sign-extend an HI
4457
4514
value into an SI value. Handles the tricky case where
4458
- we are overwriting the destination. */
4459
-
4460
- const char *
4461
- msp430x_extendhisi (rtx * operands )
4515
+ we are overwriting the destination.
4516
+ Return the number of bytes used by the emitted instructions.
4517
+ If RETURN_LENGTH is true then do not emit the assembly instruction
4518
+ sequence. */
4519
+ int
4520
+ msp430x_extendhisi (rtx * operands , bool return_length )
4462
4521
{
4463
4522
if (REGNO (operands [0 ]) == REGNO (operands [1 ]))
4464
- /* Low word of dest == source word. 8-byte sequence. */
4465
- return "BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0" ;
4466
-
4467
- if (! msp430x )
4468
- /* Note: This sequence is approximately the same length as invoking a helper
4469
- function to perform the sign-extension, as in:
4470
-
4471
- MOV.W %1, %L0
4472
- MOV.W %1, r12
4473
- CALL __mspabi_srai_15
4474
- MOV.W r12, %H0
4475
-
4476
- but this version does not involve any function calls or using argument
4477
- registers, so it reduces register pressure. 10-byte sequence. */
4478
- return "MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 "
4479
- "{ INV.W\t%H0, %H0" ;
4480
-
4481
- if (REGNO (operands [0 ]) + 1 == REGNO (operands [1 ]))
4482
- /* High word of dest == source word. 6-byte sequence. */
4483
- return "MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0" ;
4523
+ {
4524
+ /* Low word of dest == source word. */
4525
+ if (!return_length )
4526
+ output_asm_insn ("BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0" ,
4527
+ operands );
4528
+ return 8 ;
4529
+ }
4530
+ else if (! msp430x )
4531
+ {
4532
+ /* Note: This sequence is approximately the same length as invoking a
4533
+ helper function to perform the sign-extension, as in:
4534
+
4535
+ MOV.W %1, %L0
4536
+ MOV.W %1, r12
4537
+ CALL __mspabi_srai_15
4538
+ MOV.W r12, %H0
4539
+
4540
+ but this version does not involve any function calls or using argument
4541
+ registers, so it reduces register pressure. */
4542
+ if (!return_length )
4543
+ output_asm_insn ("MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0" ,
4544
+ operands );
4545
+ return 10 ;
4546
+ }
4547
+ else if (REGNO (operands [0 ]) + 1 == REGNO (operands [1 ]))
4548
+ {
4549
+ /* High word of dest == source word. */
4550
+ if (!return_length )
4551
+ output_asm_insn ("MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0" ,
4552
+ operands );
4553
+ return 6 ;
4554
+ }
4484
4555
4485
- /* No overlap between dest and source. 8-byte sequence. */
4486
- return "MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0" ;
4556
+ /* No overlap between dest and source. */
4557
+ if (!return_length )
4558
+ output_asm_insn ("MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0" ,
4559
+ operands );
4560
+ return 8 ;
4487
4561
}
4488
4562
4489
4563
/* Stop GCC from thinking that it can eliminate (SUBREG:PSI (SI)). */
0 commit comments