@ RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -o - \ @ RUN: | llvm-readobj -s -sd | FileCheck %s @ Check the .save directive @ The .save directive records the GPR registers which are pushed to the @ stack. There are 4 different unwind opcodes: @ @ 0xB100: pop r[3:0] @ 0xA0: pop r[(4+x):4] @ r[4+x]-r[4] must be consecutive. @ 0xA8: pop r14, r[(4+x):4] @ r[4+x]-r[4] must be consecutive. @ 0x8000: pop r[15:4] @ @ If register list specifed by .save directive is possible to be encoded @ by 0xA0 or 0xA8, then the assembler should prefer them over 0x8000. .syntax unified @------------------------------------------------------------------------------- @ TEST1 @------------------------------------------------------------------------------- .section .TEST1 .globl func1a .align 2 .type func1a,%function .fnstart func1a: .save {r0} push {r0} pop {r0} bx lr .personality __gxx_personality_v0 .handlerdata .fnend .globl func1b .align 2 .type func1b,%function .fnstart func1b: .save {r0, r1} push {r0, r1} pop {r0, r1} bx lr .personality __gxx_personality_v0 .handlerdata .fnend .globl func1c .align 2 .type func1c,%function .fnstart func1c: .save {r0, r2} push {r0, r2} pop {r0, r2} bx lr .personality __gxx_personality_v0 .handlerdata .fnend .globl func1d .align 2 .type func1d,%function .fnstart func1d: .save {r1, r2} push {r1, r2} pop {r1, r2} bx lr .personality __gxx_personality_v0 .handlerdata .fnend .globl func1e .align 2 .type func1e,%function .fnstart func1e: .save {r0, r1, r2, r3} push {r0, r1, r2, r3} pop {r0, r1, r2, r3} bx lr .personality __gxx_personality_v0 .handlerdata .fnend @------------------------------------------------------------------------------- @ The assembler should emit 0xB000 unwind opcode. @------------------------------------------------------------------------------- @ CHECK: Section { @ CHECK: Name: .ARM.extab.TEST1 @ CHECK: SectionData ( @ CHECK: 0000: 00000000 B001B100 00000000 B003B100 |................| @ CHECK: 0010: 00000000 B005B100 00000000 B006B100 |................| @ CHECK: 0020: 00000000 B00FB100 |........| @ CHECK: ) @ CHECK: } @------------------------------------------------------------------------------- @ TEST2 @------------------------------------------------------------------------------- .section .TEST2 .globl func2a .align 2 .type func2a,%function .fnstart func2a: .save {r4} push {r4} pop {r4} bx lr .personality __gxx_personality_v0 .handlerdata .fnend .globl func2b .align 2 .type func2b,%function .fnstart func2b: .save {r4, r5} push {r4, r5} pop {r4, r5} bx lr .personality __gxx_personality_v0 .handlerdata .fnend .globl func2c .align 2 .type func2c,%function .fnstart func2c: .save {r4, r5, r6, r7, r8, r9, r10, r11} push {r4, r5, r6, r7, r8, r9, r10, r11} pop {r4, r5, r6, r7, r8, r9, r10, r11} bx lr .personality __gxx_personality_v0 .handlerdata .fnend @------------------------------------------------------------------------------- @ The assembler should emit 0xA0 unwind opcode. @------------------------------------------------------------------------------- @ CHECK: Section { @ CHECK: Name: .ARM.extab.TEST2 @ CHECK: SectionData ( @ CHECK: 0000: 00000000 B0B0A000 00000000 B0B0A100 |................| @ CHECK: 0010: 00000000 B0B0A700 |........| @ CHECK: ) @ CHECK: } @------------------------------------------------------------------------------- @ TEST3 @------------------------------------------------------------------------------- .section .TEST3 .globl func3a .align 2 .type func3a,%function .fnstart func3a: .save {r4, r14} push {r4, r14} pop {r4, r14} bx lr .personality __gxx_personality_v0 .handlerdata .fnend .globl func3b .align 2 .type func3b,%function .fnstart func3b: .save {r4, r5, r14} push {r4, r5, r14} pop {r4, r5, r14} bx lr .personality __gxx_personality_v0 .handlerdata .fnend .globl func3c .align 2 .type func3c,%function .fnstart func3c: .save {r4, r5, r6, r7, r8, r9, r10, r11, r14} push {r4, r5, r6, r7, r8, r9, r10, r11, r14} pop {r4, r5, r6, r7, r8, r9, r10, r11, r14} bx lr .personality __gxx_personality_v0 .handlerdata .fnend @------------------------------------------------------------------------------- @ The assembler should emit 0xA8 unwind opcode. @------------------------------------------------------------------------------- @ CHECK: Section { @ CHECK: Name: .ARM.extab.TEST3 @ CHECK: SectionData ( @ CHECK: 0000: 00000000 B0B0A800 00000000 B0B0A900 |................| @ CHECK: 0010: 00000000 B0B0AF00 |........| @ CHECK: ) @ CHECK: } @------------------------------------------------------------------------------- @ TEST4 @------------------------------------------------------------------------------- .section .TEST4 .globl func4a .align 2 .type func4a,%function .fnstart func4a: .save {r4, r5, r6, r7, r8, r9, r10, r11, r12, r14} push {r4, r5, r6, r7, r8, r9, r10, r11, r12, r14} pop {r4, r5, r6, r7, r8, r9, r10, r11, r12, r14} bx lr .personality __gxx_personality_v0 .handlerdata .fnend .globl func4b .align 2 .type func4b,%function .fnstart func4b: @ Note: r7 is missing intentionally. .save {r4, r5, r6, r8, r9, r10, r11} push {r4, r5, r6, r8, r9, r10, r11} pop {r4, r5, r6, r8, r9, r10, r11} bx lr .personality __gxx_personality_v0 .handlerdata .fnend .globl func4c .align 2 .type func4c,%function .fnstart func4c: @ Note: r7 is missing intentionally. .save {r4, r5, r6, r8, r9, r10, r11, r14} push {r4, r5, r6, r8, r9, r10, r11, r14} pop {r4, r5, r6, r8, r9, r10, r11, r14} bx lr .personality __gxx_personality_v0 .handlerdata .fnend .globl func4d .align 2 .type func4d,%function .fnstart func4d: @ Note: The register list is not start with r4. .save {r5, r6, r7} push {r5, r6, r7} pop {r5, r6, r7} bx lr .personality __gxx_personality_v0 .handlerdata .fnend .globl func4e .align 2 .type func4e,%function .fnstart func4e: @ Note: The register list is not start with r4. .save {r5, r6, r7, r14} push {r5, r6, r7, r14} pop {r5, r6, r7, r14} bx lr .personality __gxx_personality_v0 .handlerdata .fnend @------------------------------------------------------------------------------- @ The assembler should emit 0x8000 unwind opcode. @------------------------------------------------------------------------------- @ CHECK: Section { @ CHECK: Name: .ARM.extab.TEST4 @ CHECK: SectionData ( @ CHECK: 0000: 00000000 B0FF8500 00000000 B0F78000 |................| @ CHECK: 0010: 00000000 B0F78400 00000000 B00E8000 |................| @ CHECK: 0020: 00000000 B00E8400 |........| @ CHECK: ) @ CHECK: } @------------------------------------------------------------------------------- @ TEST5 @------------------------------------------------------------------------------- .section .TEST5 .globl func5a .align 2 .type func5a,%function .fnstart func5a: .save {r0, r1, r2, r3, r4, r5, r6} push {r0, r1, r2, r3, r4, r5, r6} pop {r0, r1, r2, r3, r4, r5, r6} bx lr .personality __gxx_personality_v0 .handlerdata .fnend .globl func5b .align 2 .type func5b,%function .fnstart func5b: .save {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r14} push {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r14} pop {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r14} bx lr .personality __gxx_personality_v0 .handlerdata .fnend @------------------------------------------------------------------------------- @ Check the order of unwind opcode to pop registers. @ 0xB10F "pop {r0-r3}" should be emitted before 0xA2 "pop {r4-r6}". @ 0xB10F "pop {r0-r3}" should be emitted before 0x85FF "pop {r4-r12, r14}". @------------------------------------------------------------------------------- @ CHECK: Section { @ CHECK: Name: .ARM.extab.TEST5 @ CHECK: SectionData ( @ CHECK: 0000: 00000000 A20FB100 00000000 850FB101 |................| @ CHECK: 0010: B0B0B0FF |....| @ CHECK: ) @ CHECK: }