dcr.S 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*
  2. * (C) Copyright 2001
  3. * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. #include <config.h>
  8. #if defined(CONFIG_4xx) && defined(CONFIG_CMD_SETGETDCR)
  9. #include <asm/ppc4xx.h>
  10. #include <ppc_asm.tmpl>
  11. #include <ppc_defs.h>
  12. #include <asm/cache.h>
  13. #include <asm/mmu.h>
  14. #define _ASMLANGUAGE
  15. /*****************************************************************************
  16. *
  17. * XXX - DANGER
  18. * These routines make use of self modifying code. DO NOT CALL THEM
  19. * UNTIL THEY ARE RELOCATED TO RAM. Additionally, I do not
  20. * recommend them for use in anything other than an interactive
  21. * debugging environment. This is mainly due to performance reasons.
  22. *
  23. ****************************************************************************/
  24. /*
  25. * static void _create_MFDCR(unsigned short dcrn)
  26. *
  27. * Builds a 'mfdcr' instruction for get_dcr
  28. * function.
  29. */
  30. .section ".text"
  31. .align 2
  32. .type _create_MFDCR,@function
  33. _create_MFDCR:
  34. /*
  35. * Build up a 'mfdcr' instruction formatted as follows:
  36. *
  37. * OPCD | RT | DCRF | XO | CR |
  38. * ---------------|--------------|--------------|----|
  39. * 0 5 | 6 10 | 11 20 | 21 30 | 31 |
  40. * | | DCRN | | |
  41. * 31 | %r3 | (5..9|0..4) | 323 | 0 |
  42. *
  43. * Where:
  44. * OPCD = opcode - 31
  45. * RT = destination register - %r3 return register
  46. * DCRF = DCRN # with upper and lower halves swapped
  47. * XO = extended opcode - 323
  48. * CR = CR[CR0] NOT undefined - 0
  49. */
  50. rlwinm r0, r3, 27, 27, 31 /* OPCD = 31 */
  51. rlwinm r3, r3, 5, 22, 26
  52. or r3, r3, r0
  53. slwi r3, r3, 10
  54. oris r3, r3, 0x3e30 /* RT = %r3 */
  55. ori r3, r3, 323 /* XO = 323 */
  56. slwi r3, r3, 1 /* CR = 0 */
  57. mflr r4
  58. stw r3, 0(r4) /* Store instr in get_dcr() */
  59. dcbst r0, r4 /* Make sure val is written out */
  60. sync /* Wait for write to complete */
  61. icbi r0, r4 /* Make sure old instr is dumped */
  62. isync /* Wait for icbi to complete */
  63. blr
  64. .Lfe1: .size _create_MFDCR,.Lfe1-_create_MFDCR
  65. /* end _create_MFDCR() */
  66. /*
  67. * static void _create_MTDCR(unsigned short dcrn, unsigned long value)
  68. *
  69. * Builds a 'mtdcr' instruction for set_dcr
  70. * function.
  71. */
  72. .section ".text"
  73. .align 2
  74. .type _create_MTDCR,@function
  75. _create_MTDCR:
  76. /*
  77. * Build up a 'mtdcr' instruction formatted as follows:
  78. *
  79. * OPCD | RS | DCRF | XO | CR |
  80. * ---------------|--------------|--------------|----|
  81. * 0 5 | 6 10 | 11 20 | 21 30 | 31 |
  82. * | | DCRN | | |
  83. * 31 | %r3 | (5..9|0..4) | 451 | 0 |
  84. *
  85. * Where:
  86. * OPCD = opcode - 31
  87. * RS = source register - %r4
  88. * DCRF = dest. DCRN # with upper and lower halves swapped
  89. * XO = extended opcode - 451
  90. * CR = CR[CR0] NOT undefined - 0
  91. */
  92. rlwinm r0, r3, 27, 27, 31 /* OPCD = 31 */
  93. rlwinm r3, r3, 5, 22, 26
  94. or r3, r3, r0
  95. slwi r3, r3, 10
  96. oris r3, r3, 0x3e40 /* RS = %r4 */
  97. ori r3, r3, 451 /* XO = 451 */
  98. slwi r3, r3, 1 /* CR = 0 */
  99. mflr r5
  100. stw r3, 0(r5) /* Store instr in set_dcr() */
  101. dcbst r0, r5 /* Make sure val is written out */
  102. sync /* Wait for write to complete */
  103. icbi r0, r5 /* Make sure old instr is dumped */
  104. isync /* Wait for icbi to complete */
  105. blr
  106. .Lfe2: .size _create_MTDCR,.Lfe2-_create_MTDCR
  107. /* end _create_MTDCR() */
  108. /*
  109. * unsigned long get_dcr(unsigned short dcrn)
  110. *
  111. * Return a given DCR's value.
  112. */
  113. /* */
  114. /* XXX - This is self modifying code, hence */
  115. /* it is in the data section. */
  116. /* */
  117. .section ".data"
  118. .align 2
  119. .globl get_dcr
  120. .type get_dcr,@function
  121. get_dcr:
  122. mflr r0 /* Get link register */
  123. stwu r1, -32(r1) /* Save back chain and move SP */
  124. stw r0, +36(r1) /* Save link register */
  125. bl _create_MFDCR /* Build following instruction */
  126. /* XXX - we build this instuction up on the fly. */
  127. .long 0 /* Get DCR's value */
  128. lwz r0, +36(r1) /* Get saved link register */
  129. mtlr r0 /* Restore link register */
  130. addi r1, r1, +32 /* Remove frame from stack */
  131. blr /* Return to calling function */
  132. .Lfe3: .size get_dcr,.Lfe3-get_dcr
  133. /* end get_dcr() */
  134. /*
  135. * unsigned void set_dcr(unsigned short dcrn, unsigned long value)
  136. *
  137. * Return a given DCR's value.
  138. */
  139. /*
  140. * XXX - This is self modifying code, hence
  141. * it is in the data section.
  142. */
  143. .section ".data"
  144. .align 2
  145. .globl set_dcr
  146. .type set_dcr,@function
  147. set_dcr:
  148. mflr r0 /* Get link register */
  149. stwu r1, -32(r1) /* Save back chain and move SP */
  150. stw r0, +36(r1) /* Save link register */
  151. bl _create_MTDCR /* Build following instruction */
  152. /* XXX - we build this instuction up on the fly. */
  153. .long 0 /* Set DCR's value */
  154. lwz r0, +36(r1) /* Get saved link register */
  155. mtlr r0 /* Restore link register */
  156. addi r1, r1, +32 /* Remove frame from stack */
  157. blr /* Return to calling function */
  158. .Lfe4: .size set_dcr,.Lfe4-set_dcr
  159. /* end set_dcr() */
  160. #endif