1*10465441SEvalZero/* 2*10465441SEvalZero * (C) Copyright 2001 3*10465441SEvalZero * Erik Theisen, Wave 7 Optics, [email protected] 4*10465441SEvalZero * 5*10465441SEvalZero * See file CREDITS for list of people who contributed to this 6*10465441SEvalZero * project. 7*10465441SEvalZero * 8*10465441SEvalZero * This program is free software; you can redistribute it and/or 9*10465441SEvalZero * modify it under the terms of the GNU General Public License as 10*10465441SEvalZero * published by the Free Software Foundation; either version 2 of 11*10465441SEvalZero * the License, or (at your option) any later version. 12*10465441SEvalZero * 13*10465441SEvalZero * This program is distributed in the hope that it will be useful, 14*10465441SEvalZero * but WITHOUT ANY WARRANTY; without even the implied warranty of 15*10465441SEvalZero * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*10465441SEvalZero * GNU General Public License for more details. 17*10465441SEvalZero * 18*10465441SEvalZero * You should have received a copy of the GNU General Public License 19*10465441SEvalZero * along with this program; if not, write to the Free Software 20*10465441SEvalZero * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21*10465441SEvalZero * MA 02111-1307 USA 22*10465441SEvalZero */ 23*10465441SEvalZero#include <asm/ppc4xx.h> 24*10465441SEvalZero 25*10465441SEvalZero/***************************************************************************** 26*10465441SEvalZero * 27*10465441SEvalZero * XXX - DANGER 28*10465441SEvalZero * These routines make use of self modifying code. DO NOT CALL THEM 29*10465441SEvalZero * UNTIL THEY ARE RELOCATED TO RAM. Additionally, I do not 30*10465441SEvalZero * recommend them for use in anything other than an interactive 31*10465441SEvalZero * debugging environment. This is mainly due to performance reasons. 32*10465441SEvalZero * 33*10465441SEvalZero ****************************************************************************/ 34*10465441SEvalZero 35*10465441SEvalZero/* 36*10465441SEvalZero * static void _create_MFDCR(unsigned short dcrn) 37*10465441SEvalZero * 38*10465441SEvalZero * Builds a 'mfdcr' instruction for get_dcr 39*10465441SEvalZero * function. 40*10465441SEvalZero */ 41*10465441SEvalZero .section ".text" 42*10465441SEvalZero .align 2 43*10465441SEvalZero .type _create_MFDCR,@function 44*10465441SEvalZero_create_MFDCR: 45*10465441SEvalZero /* 46*10465441SEvalZero * Build up a 'mfdcr' instruction formatted as follows: 47*10465441SEvalZero * 48*10465441SEvalZero * OPCD | RT | DCRF | XO | CR | 49*10465441SEvalZero * ---------------|--------------|--------------|----| 50*10465441SEvalZero * 0 5 | 6 10 | 11 20 | 21 30 | 31 | 51*10465441SEvalZero * | | DCRN | | | 52*10465441SEvalZero * 31 | %r3 | (5..9|0..4) | 323 | 0 | 53*10465441SEvalZero * 54*10465441SEvalZero * Where: 55*10465441SEvalZero * OPCD = opcode - 31 56*10465441SEvalZero * RT = destination register - %r3 return register 57*10465441SEvalZero * DCRF = DCRN # with upper and lower halves swapped 58*10465441SEvalZero * XO = extended opcode - 323 59*10465441SEvalZero * CR = CR[CR0] NOT undefined - 0 60*10465441SEvalZero */ 61*10465441SEvalZero rlwinm r0, r3, 27, 27, 31 /* OPCD = 31 */ 62*10465441SEvalZero rlwinm r3, r3, 5, 22, 26 63*10465441SEvalZero or r3, r3, r0 64*10465441SEvalZero slwi r3, r3, 10 65*10465441SEvalZero oris r3, r3, 0x3e30 /* RT = %r3 */ 66*10465441SEvalZero ori r3, r3, 323 /* XO = 323 */ 67*10465441SEvalZero slwi r3, r3, 1 /* CR = 0 */ 68*10465441SEvalZero 69*10465441SEvalZero mflr r4 70*10465441SEvalZero stw r3, 0(r4) /* Store instr in get_dcr() */ 71*10465441SEvalZero dcbst r0, r4 /* Make sure val is written out */ 72*10465441SEvalZero sync /* Wait for write to complete */ 73*10465441SEvalZero icbi r0, r4 /* Make sure old instr is dumped */ 74*10465441SEvalZero isync /* Wait for icbi to complete */ 75*10465441SEvalZero 76*10465441SEvalZero blr 77*10465441SEvalZero.Lfe1: .size _create_MFDCR,.Lfe1-_create_MFDCR 78*10465441SEvalZero/* end _create_MFDCR() */ 79*10465441SEvalZero 80*10465441SEvalZero/* 81*10465441SEvalZero * static void _create_MTDCR(unsigned short dcrn, unsigned long value) 82*10465441SEvalZero * 83*10465441SEvalZero * Builds a 'mtdcr' instruction for set_dcr 84*10465441SEvalZero * function. 85*10465441SEvalZero */ 86*10465441SEvalZero .section ".text" 87*10465441SEvalZero .align 2 88*10465441SEvalZero .type _create_MTDCR,@function 89*10465441SEvalZero_create_MTDCR: 90*10465441SEvalZero /* 91*10465441SEvalZero * Build up a 'mtdcr' instruction formatted as follows: 92*10465441SEvalZero * 93*10465441SEvalZero * OPCD | RS | DCRF | XO | CR | 94*10465441SEvalZero * ---------------|--------------|--------------|----| 95*10465441SEvalZero * 0 5 | 6 10 | 11 20 | 21 30 | 31 | 96*10465441SEvalZero * | | DCRN | | | 97*10465441SEvalZero * 31 | %r3 | (5..9|0..4) | 451 | 0 | 98*10465441SEvalZero * 99*10465441SEvalZero * Where: 100*10465441SEvalZero * OPCD = opcode - 31 101*10465441SEvalZero * RS = source register - %r4 102*10465441SEvalZero * DCRF = dest. DCRN # with upper and lower halves swapped 103*10465441SEvalZero * XO = extended opcode - 451 104*10465441SEvalZero * CR = CR[CR0] NOT undefined - 0 105*10465441SEvalZero */ 106*10465441SEvalZero rlwinm r0, r3, 27, 27, 31 /* OPCD = 31 */ 107*10465441SEvalZero rlwinm r3, r3, 5, 22, 26 108*10465441SEvalZero or r3, r3, r0 109*10465441SEvalZero slwi r3, r3, 10 110*10465441SEvalZero oris r3, r3, 0x3e40 /* RS = %r4 */ 111*10465441SEvalZero ori r3, r3, 451 /* XO = 451 */ 112*10465441SEvalZero slwi r3, r3, 1 /* CR = 0 */ 113*10465441SEvalZero 114*10465441SEvalZero mflr r5 115*10465441SEvalZero stw r3, 0(r5) /* Store instr in set_dcr() */ 116*10465441SEvalZero dcbst r0, r5 /* Make sure val is written out */ 117*10465441SEvalZero sync /* Wait for write to complete */ 118*10465441SEvalZero icbi r0, r5 /* Make sure old instr is dumped */ 119*10465441SEvalZero isync /* Wait for icbi to complete */ 120*10465441SEvalZero 121*10465441SEvalZero blr 122*10465441SEvalZero.Lfe2: .size _create_MTDCR,.Lfe2-_create_MTDCR 123*10465441SEvalZero/* end _create_MTDCR() */ 124*10465441SEvalZero 125*10465441SEvalZero 126*10465441SEvalZero/* 127*10465441SEvalZero * unsigned long get_dcr(unsigned short dcrn) 128*10465441SEvalZero * 129*10465441SEvalZero * Return a given DCR's value. 130*10465441SEvalZero */ 131*10465441SEvalZero /* */ 132*10465441SEvalZero /* XXX - This is self modifying code, hence */ 133*10465441SEvalZero /* it is in the data section. */ 134*10465441SEvalZero /* */ 135*10465441SEvalZero .section ".text" 136*10465441SEvalZero .align 2 137*10465441SEvalZero .globl get_dcr 138*10465441SEvalZero .type get_dcr,@function 139*10465441SEvalZeroget_dcr: 140*10465441SEvalZero mflr r0 /* Get link register */ 141*10465441SEvalZero stwu r1, -32(r1) /* Save back chain and move SP */ 142*10465441SEvalZero stw r0, +36(r1) /* Save link register */ 143*10465441SEvalZero 144*10465441SEvalZero bl _create_MFDCR /* Build following instruction */ 145*10465441SEvalZero /* XXX - we build this instuction up on the fly. */ 146*10465441SEvalZero .long 0 /* Get DCR's value */ 147*10465441SEvalZero 148*10465441SEvalZero lwz r0, +36(r1) /* Get saved link register */ 149*10465441SEvalZero mtlr r0 /* Restore link register */ 150*10465441SEvalZero addi r1, r1, +32 /* Remove frame from stack */ 151*10465441SEvalZero blr /* Return to calling function */ 152*10465441SEvalZero.Lfe3: .size get_dcr,.Lfe3-get_dcr 153*10465441SEvalZero/* end get_dcr() */ 154*10465441SEvalZero 155*10465441SEvalZero 156*10465441SEvalZero/* 157*10465441SEvalZero * unsigned void set_dcr(unsigned short dcrn, unsigned long value) 158*10465441SEvalZero * 159*10465441SEvalZero * Return a given DCR's value. 160*10465441SEvalZero */ 161*10465441SEvalZero /* 162*10465441SEvalZero * XXX - This is self modifying code, hence 163*10465441SEvalZero * it is in the data section. 164*10465441SEvalZero */ 165*10465441SEvalZero .section ".text" 166*10465441SEvalZero .align 2 167*10465441SEvalZero .globl set_dcr 168*10465441SEvalZero .type set_dcr,@function 169*10465441SEvalZeroset_dcr: 170*10465441SEvalZero mflr r0 /* Get link register */ 171*10465441SEvalZero stwu r1, -32(r1) /* Save back chain and move SP */ 172*10465441SEvalZero stw r0, +36(r1) /* Save link register */ 173*10465441SEvalZero 174*10465441SEvalZero bl _create_MTDCR /* Build following instruction */ 175*10465441SEvalZero /* XXX - we build this instuction up on the fly. */ 176*10465441SEvalZero .long 0 /* Set DCR's value */ 177*10465441SEvalZero 178*10465441SEvalZero lwz r0, +36(r1) /* Get saved link register */ 179*10465441SEvalZero mtlr r0 /* Restore link register */ 180*10465441SEvalZero addi r1, r1, +32 /* Remove frame from stack */ 181*10465441SEvalZero blr /* Return to calling function */ 182*10465441SEvalZero.Lfe4: .size set_dcr,.Lfe4-set_dcr 183*10465441SEvalZero/* end set_dcr() */ 184*10465441SEvalZero 185