123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366 |
- /*
- * Copyright 2014, Michael Ellerman, IBM Corp.
- * Licensed under GPLv2.
- */
- #include <ppc-asm.h>
- #include "reg.h"
- /* ppc-asm.h defines most of the reg aliases, but not r1/r2. */
- #define r1 1
- #define r2 2
- #define RFEBB .long 0x4c000924
- /* Stack layout:
- *
- * ^
- * User stack |
- * Back chain ------+ <- r1 <-------+
- * ... |
- * Red zone / ABI Gap |
- * ... |
- * vr63 <+ |
- * vr0 | |
- * VSCR | |
- * FSCR | |
- * r31 | Save area |
- * r0 | |
- * XER | |
- * CTR | |
- * LR | |
- * CCR <+ |
- * ... <+ |
- * LR | Caller frame |
- * CCR | |
- * Back chain <+ <- updated r1 --------+
- *
- */
- #if defined(_CALL_ELF) && _CALL_ELF == 2
- #define ABIGAP 512
- #else
- #define ABIGAP 288
- #endif
- #define NR_GPR 32
- #define NR_SPR 6
- #define NR_VSR 64
- #define SAVE_AREA ((NR_GPR + NR_SPR) * 8 + (NR_VSR * 16))
- #define CALLER_FRAME 112
- #define STACK_FRAME (ABIGAP + SAVE_AREA + CALLER_FRAME)
- #define CCR_SAVE (CALLER_FRAME)
- #define LR_SAVE (CCR_SAVE + 8)
- #define CTR_SAVE (LR_SAVE + 8)
- #define XER_SAVE (CTR_SAVE + 8)
- #define GPR_SAVE(n) (XER_SAVE + 8 + (8 * n))
- #define FSCR_SAVE (GPR_SAVE(31) + 8)
- #define VSCR_SAVE (FSCR_SAVE + 8)
- #define VSR_SAVE(n) (VSCR_SAVE + 8 + (16 * n))
- #define SAVE_GPR(n) std n,GPR_SAVE(n)(r1)
- #define REST_GPR(n) ld n,GPR_SAVE(n)(r1)
- #define TRASH_GPR(n) lis n,0xaaaa
- #define SAVE_VSR(n, b) li b, VSR_SAVE(n); stxvd2x n,b,r1
- #define LOAD_VSR(n, b) li b, VSR_SAVE(n); lxvd2x n,b,r1
- #define LOAD_REG_IMMEDIATE(reg,expr) \
- lis reg,(expr)@highest; \
- ori reg,reg,(expr)@higher; \
- rldicr reg,reg,32,31; \
- oris reg,reg,(expr)@h; \
- ori reg,reg,(expr)@l;
- #if defined(_CALL_ELF) && _CALL_ELF == 2
- #define ENTRY_POINT(name) \
- .type FUNC_NAME(name),@function; \
- .globl FUNC_NAME(name); \
- FUNC_NAME(name):
- #define RESTORE_TOC(name) \
- /* Restore our TOC pointer using our entry point */ \
- LOAD_REG_IMMEDIATE(r12, name) \
- 0: addis r2,r12,(.TOC.-0b)@ha; \
- addi r2,r2,(.TOC.-0b)@l;
- #else
- #define ENTRY_POINT(name) FUNC_START(name)
- #define RESTORE_TOC(name) \
- /* Restore our TOC pointer via our opd entry */ \
- LOAD_REG_IMMEDIATE(r2, name) \
- ld r2,8(r2);
- #endif
- .text
- ENTRY_POINT(ebb_handler)
- stdu r1,-STACK_FRAME(r1)
- SAVE_GPR(0)
- mflr r0
- std r0,LR_SAVE(r1)
- mfcr r0
- std r0,CCR_SAVE(r1)
- mfctr r0
- std r0,CTR_SAVE(r1)
- mfxer r0
- std r0,XER_SAVE(r1)
- SAVE_GPR(2)
- SAVE_GPR(3)
- SAVE_GPR(4)
- SAVE_GPR(5)
- SAVE_GPR(6)
- SAVE_GPR(7)
- SAVE_GPR(8)
- SAVE_GPR(9)
- SAVE_GPR(10)
- SAVE_GPR(11)
- SAVE_GPR(12)
- SAVE_GPR(13)
- SAVE_GPR(14)
- SAVE_GPR(15)
- SAVE_GPR(16)
- SAVE_GPR(17)
- SAVE_GPR(18)
- SAVE_GPR(19)
- SAVE_GPR(20)
- SAVE_GPR(21)
- SAVE_GPR(22)
- SAVE_GPR(23)
- SAVE_GPR(24)
- SAVE_GPR(25)
- SAVE_GPR(26)
- SAVE_GPR(27)
- SAVE_GPR(28)
- SAVE_GPR(29)
- SAVE_GPR(30)
- SAVE_GPR(31)
- SAVE_VSR(0, r3)
- mffs f0
- stfd f0, FSCR_SAVE(r1)
- mfvscr f0
- stfd f0, VSCR_SAVE(r1)
- SAVE_VSR(1, r3)
- SAVE_VSR(2, r3)
- SAVE_VSR(3, r3)
- SAVE_VSR(4, r3)
- SAVE_VSR(5, r3)
- SAVE_VSR(6, r3)
- SAVE_VSR(7, r3)
- SAVE_VSR(8, r3)
- SAVE_VSR(9, r3)
- SAVE_VSR(10, r3)
- SAVE_VSR(11, r3)
- SAVE_VSR(12, r3)
- SAVE_VSR(13, r3)
- SAVE_VSR(14, r3)
- SAVE_VSR(15, r3)
- SAVE_VSR(16, r3)
- SAVE_VSR(17, r3)
- SAVE_VSR(18, r3)
- SAVE_VSR(19, r3)
- SAVE_VSR(20, r3)
- SAVE_VSR(21, r3)
- SAVE_VSR(22, r3)
- SAVE_VSR(23, r3)
- SAVE_VSR(24, r3)
- SAVE_VSR(25, r3)
- SAVE_VSR(26, r3)
- SAVE_VSR(27, r3)
- SAVE_VSR(28, r3)
- SAVE_VSR(29, r3)
- SAVE_VSR(30, r3)
- SAVE_VSR(31, r3)
- SAVE_VSR(32, r3)
- SAVE_VSR(33, r3)
- SAVE_VSR(34, r3)
- SAVE_VSR(35, r3)
- SAVE_VSR(36, r3)
- SAVE_VSR(37, r3)
- SAVE_VSR(38, r3)
- SAVE_VSR(39, r3)
- SAVE_VSR(40, r3)
- SAVE_VSR(41, r3)
- SAVE_VSR(42, r3)
- SAVE_VSR(43, r3)
- SAVE_VSR(44, r3)
- SAVE_VSR(45, r3)
- SAVE_VSR(46, r3)
- SAVE_VSR(47, r3)
- SAVE_VSR(48, r3)
- SAVE_VSR(49, r3)
- SAVE_VSR(50, r3)
- SAVE_VSR(51, r3)
- SAVE_VSR(52, r3)
- SAVE_VSR(53, r3)
- SAVE_VSR(54, r3)
- SAVE_VSR(55, r3)
- SAVE_VSR(56, r3)
- SAVE_VSR(57, r3)
- SAVE_VSR(58, r3)
- SAVE_VSR(59, r3)
- SAVE_VSR(60, r3)
- SAVE_VSR(61, r3)
- SAVE_VSR(62, r3)
- SAVE_VSR(63, r3)
- TRASH_GPR(2)
- TRASH_GPR(3)
- TRASH_GPR(4)
- TRASH_GPR(5)
- TRASH_GPR(6)
- TRASH_GPR(7)
- TRASH_GPR(8)
- TRASH_GPR(9)
- TRASH_GPR(10)
- TRASH_GPR(11)
- TRASH_GPR(12)
- TRASH_GPR(14)
- TRASH_GPR(15)
- TRASH_GPR(16)
- TRASH_GPR(17)
- TRASH_GPR(18)
- TRASH_GPR(19)
- TRASH_GPR(20)
- TRASH_GPR(21)
- TRASH_GPR(22)
- TRASH_GPR(23)
- TRASH_GPR(24)
- TRASH_GPR(25)
- TRASH_GPR(26)
- TRASH_GPR(27)
- TRASH_GPR(28)
- TRASH_GPR(29)
- TRASH_GPR(30)
- TRASH_GPR(31)
- RESTORE_TOC(ebb_handler)
- /*
- * r13 is our TLS pointer. We leave whatever value was in there when the
- * EBB fired. That seems to be OK because once set the TLS pointer is not
- * changed - but presumably that could change in future.
- */
- bl ebb_hook
- nop
- /* r2 may be changed here but we don't care */
- lfd f0, FSCR_SAVE(r1)
- mtfsf 0xff,f0
- lfd f0, VSCR_SAVE(r1)
- mtvscr f0
- LOAD_VSR(0, r3)
- LOAD_VSR(1, r3)
- LOAD_VSR(2, r3)
- LOAD_VSR(3, r3)
- LOAD_VSR(4, r3)
- LOAD_VSR(5, r3)
- LOAD_VSR(6, r3)
- LOAD_VSR(7, r3)
- LOAD_VSR(8, r3)
- LOAD_VSR(9, r3)
- LOAD_VSR(10, r3)
- LOAD_VSR(11, r3)
- LOAD_VSR(12, r3)
- LOAD_VSR(13, r3)
- LOAD_VSR(14, r3)
- LOAD_VSR(15, r3)
- LOAD_VSR(16, r3)
- LOAD_VSR(17, r3)
- LOAD_VSR(18, r3)
- LOAD_VSR(19, r3)
- LOAD_VSR(20, r3)
- LOAD_VSR(21, r3)
- LOAD_VSR(22, r3)
- LOAD_VSR(23, r3)
- LOAD_VSR(24, r3)
- LOAD_VSR(25, r3)
- LOAD_VSR(26, r3)
- LOAD_VSR(27, r3)
- LOAD_VSR(28, r3)
- LOAD_VSR(29, r3)
- LOAD_VSR(30, r3)
- LOAD_VSR(31, r3)
- LOAD_VSR(32, r3)
- LOAD_VSR(33, r3)
- LOAD_VSR(34, r3)
- LOAD_VSR(35, r3)
- LOAD_VSR(36, r3)
- LOAD_VSR(37, r3)
- LOAD_VSR(38, r3)
- LOAD_VSR(39, r3)
- LOAD_VSR(40, r3)
- LOAD_VSR(41, r3)
- LOAD_VSR(42, r3)
- LOAD_VSR(43, r3)
- LOAD_VSR(44, r3)
- LOAD_VSR(45, r3)
- LOAD_VSR(46, r3)
- LOAD_VSR(47, r3)
- LOAD_VSR(48, r3)
- LOAD_VSR(49, r3)
- LOAD_VSR(50, r3)
- LOAD_VSR(51, r3)
- LOAD_VSR(52, r3)
- LOAD_VSR(53, r3)
- LOAD_VSR(54, r3)
- LOAD_VSR(55, r3)
- LOAD_VSR(56, r3)
- LOAD_VSR(57, r3)
- LOAD_VSR(58, r3)
- LOAD_VSR(59, r3)
- LOAD_VSR(60, r3)
- LOAD_VSR(61, r3)
- LOAD_VSR(62, r3)
- LOAD_VSR(63, r3)
- ld r0,XER_SAVE(r1)
- mtxer r0
- ld r0,CTR_SAVE(r1)
- mtctr r0
- ld r0,LR_SAVE(r1)
- mtlr r0
- ld r0,CCR_SAVE(r1)
- mtcr r0
- REST_GPR(0)
- REST_GPR(2)
- REST_GPR(3)
- REST_GPR(4)
- REST_GPR(5)
- REST_GPR(6)
- REST_GPR(7)
- REST_GPR(8)
- REST_GPR(9)
- REST_GPR(10)
- REST_GPR(11)
- REST_GPR(12)
- REST_GPR(13)
- REST_GPR(14)
- REST_GPR(15)
- REST_GPR(16)
- REST_GPR(17)
- REST_GPR(18)
- REST_GPR(19)
- REST_GPR(20)
- REST_GPR(21)
- REST_GPR(22)
- REST_GPR(23)
- REST_GPR(24)
- REST_GPR(25)
- REST_GPR(26)
- REST_GPR(27)
- REST_GPR(28)
- REST_GPR(29)
- REST_GPR(30)
- REST_GPR(31)
- addi r1,r1,STACK_FRAME
- RFEBB
- FUNC_END(ebb_handler)
|