You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

70 lines
2.3KB

  1. /*
  2. * this is the internal transfer function.
  3. *
  4. * HISTORY
  5. * 07-Sep-16 Add clang support using x register naming. Fredrik Fornwall
  6. * 13-Apr-13 Add support for strange GCC caller-save decisions
  7. * 08-Apr-13 File creation. Michael Matz
  8. *
  9. * NOTES
  10. *
  11. * Simply save all callee saved registers
  12. *
  13. */
  14. #define STACK_REFPLUS 1
  15. #ifdef SLP_EVAL
  16. #define STACK_MAGIC 0
  17. #define REGS_TO_SAVE "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", \
  18. "x27", "x28", "x30" /* aka lr */, \
  19. "v8", "v9", "v10", "v11", \
  20. "v12", "v13", "v14", "v15"
  21. static int
  22. slp_switch(void)
  23. {
  24. int err;
  25. void *fp;
  26. register long *stackref, stsizediff;
  27. __asm__ volatile ("" : : : REGS_TO_SAVE);
  28. __asm__ volatile ("str x29, %0" : "=m"(fp) : : );
  29. __asm__ ("mov %0, sp" : "=r" (stackref));
  30. {
  31. SLP_SAVE_STATE(stackref, stsizediff);
  32. __asm__ volatile (
  33. "add sp,sp,%0\n"
  34. "add x29,x29,%0\n"
  35. :
  36. : "r" (stsizediff)
  37. );
  38. SLP_RESTORE_STATE();
  39. /* SLP_SAVE_STATE macro contains some return statements
  40. (of -1 and 1). It falls through only when
  41. the return value of slp_save_state() is zero, which
  42. is placed in x0.
  43. In that case we (slp_switch) also want to return zero
  44. (also in x0 of course).
  45. Now, some GCC versions (seen with 4.8) think it's a
  46. good idea to save/restore x0 around the call to
  47. slp_restore_state(), instead of simply zeroing it
  48. at the return below. But slp_restore_state
  49. writes random values to the stack slot used for this
  50. save/restore (from when it once was saved above in
  51. SLP_SAVE_STATE, when it was still uninitialized), so
  52. "restoring" that precious zero actually makes us
  53. return random values. There are some ways to make
  54. GCC not use that zero value in the normal return path
  55. (e.g. making err volatile, but that costs a little
  56. stack space), and the simplest is to call a function
  57. that returns an unknown value (which happens to be zero),
  58. so the saved/restored value is unused. */
  59. __asm__ volatile ("mov %0, #0" : "=r" (err));
  60. }
  61. __asm__ volatile ("ldr x29, %0" : : "m" (fp) :);
  62. __asm__ volatile ("" : : : REGS_TO_SAVE);
  63. return err;
  64. }
  65. #endif