user_exceptions.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*
  2. * Copyright 2015 Dius Computing Pty Ltd. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * - Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * - Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the
  13. * distribution.
  14. * - Neither the name of the copyright holders nor the names of
  15. * its contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  21. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  22. * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  23. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  25. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  26. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  27. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  28. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  29. * OF THE POSSIBILITY OF SUCH DAMAGE.
  30. *
  31. * @author Johny Mattsson <jmattsson@dius.com.au>
  32. */
  33. #include "user_exceptions.h"
  34. static exception_handler_fn load_store_handler;
  35. void load_non_32_wide_handler (struct exception_frame *ef, uint32_t cause)
  36. {
  37. uint32_t val, insn;
  38. (void)cause; /* If this is not EXCCAUSE_LOAD_STORE_ERROR you're doing it wrong! */
  39. asm (
  40. /*
  41. * Move the aligned content of the exception addr to val
  42. */
  43. "rsr a6, EXCVADDR;" /* read out the faulting address */
  44. "movi a5, ~3;" /* prepare a mask for the EPC */
  45. "and a5, a5, a6;" /* apply mask for 32bit aligned base */
  46. "l32i a5, a5, 0;" /* load aligned value */
  47. "ssa8l a6;" /* set up shift register for value */
  48. "srl %[val], a5;" /* shift left to align value */
  49. /* we are done with a6 = EXCVADDR */
  50. /*
  51. * Move the aligned instruction to insn
  52. */
  53. "movi a5, ~3;" /* prepare a mask for the insn */
  54. "and a6, a5, %[epc];" /* apply mask for 32bit aligned base */
  55. "l32i a5, a6, 0;" /* load part 1 */
  56. "l32i a6, a6, 4;" /* load part 2 */
  57. "ssa8l %[epc];" /* set up shift register for src op */
  58. "src %[op], a6, a5;" /* right shift to get faulting instruction */
  59. :[val]"=r"(val), [op]"=r"(insn)
  60. :[epc]"r"(ef->epc)
  61. :"a5", "a6"
  62. );
  63. /* These instructions have the format 0xADSBII where AB = opcode and D = dest reg */
  64. uint32_t regno = (insn>>4)&0x0f; /* pick out nibble D*/
  65. uint32_t opcode = (uint8_t) (((insn>>12)<<4)|(insn&0xf)); /* and nibbles AB */
  66. #define L8UI 0x02u
  67. #define L16UI 0x12u
  68. #define L16SI 0x92u
  69. if (opcode == L8UI) { /* L8UI */
  70. val = (uint8_t) val;
  71. } else {
  72. val = (uint16_t) val; /* assume L16SI or L16UI */
  73. if (opcode == L16SI) {
  74. val = (unsigned)((int)((sint16_t)val)); /* force signed 16->32 bit */
  75. } else if (opcode != L16UI) {
  76. /*
  77. * Anything other than L8UI, L16SI or L16UI then chain to the next handler
  78. * if set (typically a remote GDB break). Otherwise execute the default action
  79. * which is to trigger a system break and hang if the break doesn't get handled
  80. */
  81. if (load_store_handler) {
  82. load_store_handler(NULL, 0 /* ef , cause */);
  83. return;
  84. } else {
  85. asm ("break 1, 1");
  86. while (1) {}
  87. }
  88. }
  89. }
  90. ef->a_reg[regno ? regno-1: regno] = val; /* carry out the load */
  91. ef->epc += 3; /* resume at following instruction */
  92. }
  93. /**
  94. * The SDK's user_main function installs a debugging handler regardless
  95. * of whether there's a proper handler installed for EXCCAUSE_LOAD_STORE_ERROR,
  96. * which of course breaks everything if we allow that to go through. As such,
  97. * we use the linker to wrap that call and stop the SDK from shooting itself in
  98. * its proverbial foot. We do save the EXCCAUSE_LOAD_STORE_ERROR handler so that
  99. * we can chain to it above.
  100. */
  101. exception_handler_fn TEXT_SECTION_ATTR
  102. __wrap__xtos_set_exception_handler (uint32_t cause, exception_handler_fn fn)
  103. {
  104. if (cause != EXCCAUSE_LOAD_STORE_ERROR)
  105. __real__xtos_set_exception_handler (cause, fn);
  106. else
  107. load_store_handler = fn;
  108. }