123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- /*
- * (C) Copyright 2001
- * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
- #include <config.h>
- #if defined(CONFIG_4xx) && defined(CONFIG_CMD_SETGETDCR)
- #include <asm/ppc4xx.h>
- #include <ppc_asm.tmpl>
- #include <ppc_defs.h>
- #include <asm/cache.h>
- #include <asm/mmu.h>
- #define _ASMLANGUAGE
- /*****************************************************************************
- *
- * XXX - DANGER
- * These routines make use of self modifying code. DO NOT CALL THEM
- * UNTIL THEY ARE RELOCATED TO RAM. Additionally, I do not
- * recommend them for use in anything other than an interactive
- * debugging environment. This is mainly due to performance reasons.
- *
- ****************************************************************************/
- /*
- * static void _create_MFDCR(unsigned short dcrn)
- *
- * Builds a 'mfdcr' instruction for get_dcr
- * function.
- */
- .section ".text"
- .align 2
- .type _create_MFDCR,@function
- _create_MFDCR:
- /*
- * Build up a 'mfdcr' instruction formatted as follows:
- *
- * OPCD | RT | DCRF | XO | CR |
- * ---------------|--------------|--------------|----|
- * 0 5 | 6 10 | 11 20 | 21 30 | 31 |
- * | | DCRN | | |
- * 31 | %r3 | (5..9|0..4) | 323 | 0 |
- *
- * Where:
- * OPCD = opcode - 31
- * RT = destination register - %r3 return register
- * DCRF = DCRN # with upper and lower halves swapped
- * XO = extended opcode - 323
- * CR = CR[CR0] NOT undefined - 0
- */
- rlwinm r0, r3, 27, 27, 31 /* OPCD = 31 */
- rlwinm r3, r3, 5, 22, 26
- or r3, r3, r0
- slwi r3, r3, 10
- oris r3, r3, 0x3e30 /* RT = %r3 */
- ori r3, r3, 323 /* XO = 323 */
- slwi r3, r3, 1 /* CR = 0 */
- mflr r4
- stw r3, 0(r4) /* Store instr in get_dcr() */
- dcbst r0, r4 /* Make sure val is written out */
- sync /* Wait for write to complete */
- icbi r0, r4 /* Make sure old instr is dumped */
- isync /* Wait for icbi to complete */
- blr
- .Lfe1: .size _create_MFDCR,.Lfe1-_create_MFDCR
- /* end _create_MFDCR() */
- /*
- * static void _create_MTDCR(unsigned short dcrn, unsigned long value)
- *
- * Builds a 'mtdcr' instruction for set_dcr
- * function.
- */
- .section ".text"
- .align 2
- .type _create_MTDCR,@function
- _create_MTDCR:
- /*
- * Build up a 'mtdcr' instruction formatted as follows:
- *
- * OPCD | RS | DCRF | XO | CR |
- * ---------------|--------------|--------------|----|
- * 0 5 | 6 10 | 11 20 | 21 30 | 31 |
- * | | DCRN | | |
- * 31 | %r3 | (5..9|0..4) | 451 | 0 |
- *
- * Where:
- * OPCD = opcode - 31
- * RS = source register - %r4
- * DCRF = dest. DCRN # with upper and lower halves swapped
- * XO = extended opcode - 451
- * CR = CR[CR0] NOT undefined - 0
- */
- rlwinm r0, r3, 27, 27, 31 /* OPCD = 31 */
- rlwinm r3, r3, 5, 22, 26
- or r3, r3, r0
- slwi r3, r3, 10
- oris r3, r3, 0x3e40 /* RS = %r4 */
- ori r3, r3, 451 /* XO = 451 */
- slwi r3, r3, 1 /* CR = 0 */
- mflr r5
- stw r3, 0(r5) /* Store instr in set_dcr() */
- dcbst r0, r5 /* Make sure val is written out */
- sync /* Wait for write to complete */
- icbi r0, r5 /* Make sure old instr is dumped */
- isync /* Wait for icbi to complete */
- blr
- .Lfe2: .size _create_MTDCR,.Lfe2-_create_MTDCR
- /* end _create_MTDCR() */
- /*
- * unsigned long get_dcr(unsigned short dcrn)
- *
- * Return a given DCR's value.
- */
- /* */
- /* XXX - This is self modifying code, hence */
- /* it is in the data section. */
- /* */
- .section ".data"
- .align 2
- .globl get_dcr
- .type get_dcr,@function
- get_dcr:
- mflr r0 /* Get link register */
- stwu r1, -32(r1) /* Save back chain and move SP */
- stw r0, +36(r1) /* Save link register */
- bl _create_MFDCR /* Build following instruction */
- /* XXX - we build this instuction up on the fly. */
- .long 0 /* Get DCR's value */
- lwz r0, +36(r1) /* Get saved link register */
- mtlr r0 /* Restore link register */
- addi r1, r1, +32 /* Remove frame from stack */
- blr /* Return to calling function */
- .Lfe3: .size get_dcr,.Lfe3-get_dcr
- /* end get_dcr() */
- /*
- * unsigned void set_dcr(unsigned short dcrn, unsigned long value)
- *
- * Return a given DCR's value.
- */
- /*
- * XXX - This is self modifying code, hence
- * it is in the data section.
- */
- .section ".data"
- .align 2
- .globl set_dcr
- .type set_dcr,@function
- set_dcr:
- mflr r0 /* Get link register */
- stwu r1, -32(r1) /* Save back chain and move SP */
- stw r0, +36(r1) /* Save link register */
- bl _create_MTDCR /* Build following instruction */
- /* XXX - we build this instuction up on the fly. */
- .long 0 /* Set DCR's value */
- lwz r0, +36(r1) /* Get saved link register */
- mtlr r0 /* Restore link register */
- addi r1, r1, +32 /* Remove frame from stack */
- blr /* Return to calling function */
- .Lfe4: .size set_dcr,.Lfe4-set_dcr
- /* end set_dcr() */
- #endif
|