Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:57

0001 /*  align_h.s   1.1 - 95/12/04
0002  *
0003  *  This file contains the assembly code for the PowerPC 403
0004  *  alignment exception handler for RTEMS.
0005  *
0006  *  Based upon IBM provided code with the following release:
0007  *
0008  *  This source code has been made available to you by IBM on an AS-IS
0009  *  basis.  Anyone receiving this source is licensed under IBM
0010  *  copyrights to use it in any way he or she deems fit, including
0011  *  copying it, modifying it, compiling it, and redistributing it either
0012  *  with or without modifications.  No license under IBM patents or
0013  *  patent applications is to be implied by the copyright license.
0014  *
0015  *  Any user of this software should understand that IBM cannot provide
0016  *  technical support for this software and will not be responsible for
0017  *  any consequences resulting from the use of this software.
0018  *
0019  *  Any person who transfers this source code or any derivative work
0020  *  must include the IBM copyright notice, this paragraph, and the
0021  *  preceding two paragraphs in the transferred software.
0022  *
0023  *      COPYRIGHT   I B M   CORPORATION 1995
0024  *      LICENSED MATERIAL  -  PROGRAM PROPERTY OF I B M
0025  *
0026  * Modifications:
0027  *
0028  *  Author: Andrew Bray <andy@i-cubed.co.uk>
0029  *
0030  *  COPYRIGHT (c) 1995 by i-cubed ltd.
0031  *
0032  *  To anyone who acknowledges that this file is provided "AS IS"
0033  *  without any express or implied warranty:
0034  *      permission to use, copy, modify, and distribute this file
0035  *      for any purpose is hereby granted without fee, provided that
0036  *      the above copyright notice and this notice appears in all
0037  *      copies, and that the name of i-cubed limited not be used in
0038  *      advertising or publicity pertaining to distribution of the
0039  *      software without specific, written prior permission.
0040  *      i-cubed limited makes no representations about the suitability
0041  *      of this software for any purpose.
0042  */
0043 
0044 #include <rtems/asm.h>
0045 #include <bsp.h>
0046 
0047 .set    CACHE_SIZE,16           # cache line size of 32 bytes
0048 .set    CACHE_SIZE_L2,4         # cache line size, log 2
0049 
0050 .set    Open_gpr0,0
0051 .set    Open_gpr1,4
0052 .set    Open_gpr2,8
0053 .set    Open_gpr3,12
0054 .set    Open_gpr4,16
0055 .set    Open_gpr5,20
0056 .set    Open_gpr6,24
0057 .set    Open_gpr7,28
0058 .set    Open_gpr8,32
0059 .set    Open_gpr9,36
0060 .set    Open_gpr10,40
0061 .set    Open_gpr11,44
0062 .set    Open_gpr12,48
0063 .set    Open_gpr13,52
0064 .set    Open_gpr14,56
0065 .set    Open_gpr15,60
0066 .set    Open_gpr16,64
0067 .set    Open_gpr17,68
0068 .set    Open_gpr18,72
0069 .set    Open_gpr19,76
0070 .set    Open_gpr20,80
0071 .set    Open_gpr21,84
0072 .set    Open_gpr22,88
0073 .set    Open_gpr23,92
0074 .set    Open_gpr24,96
0075 .set    Open_gpr25,100
0076 .set    Open_gpr26,104
0077 .set    Open_gpr27,108
0078 .set    Open_gpr28,112
0079 .set    Open_gpr29,116
0080 .set    Open_gpr30,120
0081 .set    Open_gpr31,124
0082 .set    Open_xer,128
0083 .set    Open_lr,132
0084 .set    Open_ctr,136
0085 .set    Open_cr,140
0086 .set    Open_srr2,144
0087 .set    Open_srr3,148
0088 .set    Open_srr0,152
0089 .set    Open_srr1,156
0090 
0091 /*
0092  *  This code makes several assumptions for processing efficiency
0093  *  *  General purpose registers are continuous in the image, beginning with
0094  *     Open_gpr0
0095  *  *  Hash table is highly dependent on opcodes - opcode changes *will*
0096  *     require rework of the instruction decode mechanism.
0097  */
0098 
0099         .text
0100         .globl  align_h
0101 
0102     .align  CACHE_SIZE_L2
0103 align_h:
0104         /*-----------------------------------------------------------------------
0105          * Store GPRs in Open Reg save area
0106          * Set up r2 as base reg, r1 pointing to Open Reg save area
0107          *----------------------------------------------------------------------*/
0108         stmw    r0,ALIGN_REGS(r0)
0109     li  r1,ALIGN_REGS
0110         /*-----------------------------------------------------------------------
0111          * Store special purpose registers in reg save area
0112          *----------------------------------------------------------------------*/
0113         mfxer   r7
0114         mflr    r8
0115         mfcr    r9
0116         mfctr   r10
0117         stw     r7,Open_xer(r1)
0118         stw     r8,Open_lr(r1)
0119         stw     r9,Open_cr(r1)
0120         stw     r10,Open_ctr(r1)
0121 #if defined(ppc403) || defined(ppc405)
0122         mfspr   r7, srr2        /* SRR 2 */
0123         mfspr   r8, srr3        /* SRR 3 */
0124 #endif
0125         mfspr   r9, srr0        /* SRR 0 */
0126         mfspr   r10, srr1       /* SRR 1 */
0127 #if defined(ppc403) || defined(ppc405)
0128         stw     r7,Open_srr2(r1)
0129         stw     r8,Open_srr3(r1)
0130 #endif
0131         stw     r9,Open_srr0(r1)
0132         stw     r10,Open_srr1(r1)
0133 
0134 /*      Set up common registers */
0135 #if defined(ppc403) || defined(ppc405)
0136         mfspr   r5, dear        /* DEAR: R5 is data exception address */
0137 #endif
0138         lwz     r9,Open_srr0(r1)        /* get faulting instruction */
0139         addi    r7,r9,4                 /* bump instruction */
0140         stw     r7,Open_srr0(r1)        /* restore to image */
0141         lwz     r9, 0(r9)               /* retrieve actual instruction */
0142         rlwinm  r6,r9,18,25,29          /* r6 is RA * 4 field from instruction */
0143         rlwinm  r7,r9,6,26,31           /* r7 is primary opcode */
0144         bl      ref_point               /* establish addressibility */
0145 ref_point:
0146         mflr    r11                     /* r11 is the anchor point for ref_point */
0147         addi    r10, r7, -31            /* r10 = r7 - 31 */
0148         rlwinm  r10,r10,2,2,31          /* r10 *= 4 */
0149         add     r10, r10, r11           /* r10 += anchor point */
0150         lwz     r10, primary_jt-ref_point(r10)
0151         mtlr    r10
0152         rlwinm  r8,r9,13,25,29          /* r8 is RD * 4 */
0153         la      r7,Open_gpr0(r1)        /* r7 is address of GPR 0 in list */
0154         blr
0155 primary_jt:
0156         .long   xform
0157         .long   lwz
0158         .long   lwzu
0159         .long   0
0160         .long   0
0161         .long   stw
0162         .long   stwu
0163         .long   0
0164         .long   0
0165         .long   lhz
0166         .long   lhzu
0167         .long   lha
0168         .long   lhau
0169         .long   sth
0170         .long   sthu
0171         .long   lmw
0172         .long   stmw
0173 /*
0174  *   handlers
0175  */
0176 /*
0177  * xform instructions require an additional decode.  Fortunately, a relatively
0178  * simple hash step breaks the instructions out with no collisions
0179  */
0180 xform:
0181         rlwinm  r7,r9,31,22,31          /* r7 is secondary opcode */
0182         rlwinm  r10,r7,27,5,31          /* r10 = r7 >> 5 */
0183         add     r10,r7,r10              /* r10 = r7 + r10 */
0184         rlwinm  r10,r10,2,25,29         /* r10 = (r10 & 0x1F) * 4 */
0185         add     r10,r10,r11             /* r10 += anchor point */
0186         lwz     r10, secondary_ht-ref_point(r10)
0187         mtlr    r10
0188         la      r7,Open_gpr0(r1)        /* r7 is address of GPR 0 in list */
0189         rlwinm  r8,r9,13,25,29          /* r8 is RD * 4 */
0190         blrl
0191 
0192 secondary_ht:
0193         .long   lhzux                   /* b 0  0x137 */
0194         .long   lhax                    /* b 1  0x157 */
0195         .long   lhaux                   /* b 2  0x177 */
0196         .long   sthx                    /* b 3  0x197 */
0197         .long   sthux                   /* b 4  0x1b7 */
0198         .long   0                       /* b 5 */
0199         .long   lwbrx                   /* b 6  0x216 */
0200         .long   0                       /* b 7 */
0201         .long   0                       /* b 8 */
0202         .long   0                       /* b 9 */
0203         .long   stwbrx                  /* b A  0x296 */
0204         .long   0                       /* b B */
0205         .long   0                       /* b C */
0206         .long   0                       /* b D */
0207         .long   lhbrx                   /* b E   0x316 */
0208         .long   0                       /* b F */
0209         .long   0                       /* b 10 */
0210         .long   0                       /* b 11 */
0211         .long   sthbrx                  /* b 12  0x396 */
0212         .long   0                       /* b 13 */
0213         .long   lwarx                   /* b 14  0x014 */
0214         .long   dcbz                    /* b 15  0x3f6 */
0215         .long   0                       /* b 16 */
0216         .long   lwzx                    /* b 17  0x017 */
0217         .long   lwzux                   /* b 18  0x037 */
0218         .long   0                       /* b 19 */
0219         .long   stwcx                   /* b 1A  0x096 */
0220         .long   stwx                    /* b 1B  0x097 */
0221         .long   stwux                   /* b 1C  0x0B7 */
0222         .long   0                       /* b 1D */
0223         .long   0                       /* b 1E */
0224         .long   lhzx                    /* b 1F 0x117 */
0225 
0226 /*
0227  * for all handlers
0228  *       r4 - Addressability to interrupt context
0229  *       r5 - DEAR address (faulting data address)
0230  *       r6 - RA field * 4
0231  *       r7 - Address of GPR 0 in image
0232  *       r8 - RD field * 4
0233  *       r9 - Failing instruction
0234  */
0235 
0236 /*       Load halfword algebraic with update */
0237 lhau:
0238 /*       Load halfword algebraic with update indexed */
0239 lhaux:
0240         stwx    r5,r7,r6                /* update RA with effective addr */
0241 
0242 /*       Load halfword algebraic */
0243 lha:
0244 /*       Load halfword algebraic indexed */
0245 lhax:
0246         lswi    r10,r5,2                /* load two bytes into r10 */
0247         srawi   r10,r10,16              /* shift right 2 bytes, extending sign */
0248         stwx    r10,r7,r8               /* update reg image */
0249         b       align_complete          /* return */
0250 
0251 /*       Load Half Word Byte-Reversed Indexed */
0252 lhbrx:
0253         lswi    r10,r5,2                /* load two bytes from DEAR into r10 */
0254         rlwinm  r10,r10,0,0,15          /* mask off lower 2 bytes */
0255         stwbrx  r10,r7,r8               /* store reversed in reg image */
0256         b       align_complete          /* return */
0257 
0258 /*       Load Half Word and Zero with Update */
0259 lhzu:
0260 /*       Load Half Word and Zero with Update Indexed */
0261 lhzux:
0262         stwx    r5,r7,r6                /* update RA with effective addr */
0263 
0264 /*       Load Half Word and Zero */
0265 lhz:
0266 /*       Load Half Word and Zero Indexed */
0267 lhzx:
0268         lswi    r10,r5,2                /* load two bytes from DEAR into r10 */
0269         rlwinm  r10,r10,16,16,31        /* shift right 2 bytes, with zero fill */
0270         stwx    r10,r7,r8               /* update reg image */
0271         b       align_complete          /* return */
0272 
0273 /*
0274  *       Load Multiple Word
0275  */
0276 lmw:
0277         lwzx    r9,r6,r7                /* R9 contains saved value of RA */
0278         addi    r10,r7,32*4             /* r10 points to r31 in image  + 4 */
0279         rlwinm  r8,r8,30,2,31           /* r8 >>= 2  (recovers RT) */
0280         subfic  r8,r8,32                /* r8 is reg count to load */
0281         mtctr   r8                      /* load counter */
0282         addi    r8,r8,-1                /* r8-- */
0283         rlwinm  r8,r8,2,2,31            /* r8 *= 4 */
0284         add     r5,r5,r8                /* update DEAR to point to last reg */
0285 lwmloop:
0286         lswi    r11,r5,4                /* load r11 with 4 bytes from DEAR */
0287         stwu    r11,-4(r10)             /* load image and decrement pointer */
0288         addi    r5,r5,-4                /* decrement effective address */
0289         bdnz    lwmloop
0290         stwx    r9,r6,r7                /* restore RA (in case it was trashed) */
0291         b       align_complete          /* return */
0292 
0293 /*
0294  *       Load Word and Reserve Indexed
0295  */
0296 lwarx:
0297         lswi    r10,r5,4                /* load four bytes from DEAR into r10 */
0298         stwx    r10,r7,r8               /* update reg image */
0299         rlwinm  r5,r5,0,0,29            /* Word align address */
0300         lwarx   r10,0,r5                /* Set reservation */
0301         b       align_complete          /* return */
0302 
0303 /*
0304  *       Load Word Byte-Reversed Indexed
0305  */
0306 lwbrx:
0307         lswi    r10,r5,4                /* load four bytes from DEAR into r10 */
0308         stwbrx  r10,r7,r8               /* store reversed in reg image */
0309         b       align_complete          /* return */
0310 
0311 /*       Load Word and Zero with Update */
0312 lwzu:
0313 /*       Load Word and Zero with Update Indexed */
0314 lwzux:
0315         stwx    r5,r7,r6                /* update RA with effective addr */
0316 
0317 /*       Load Word and Zero */
0318 lwz:
0319 /*       Load Word and Zero Indexed */
0320 lwzx:
0321         lswi    r10,r5,4                /* load four bytes from DEAR into r10 */
0322         stwx    r10,r7,r8               /* update reg image */
0323         b       align_complete          /* return */
0324 
0325 /*    Store instructions */
0326 
0327 /* */
0328 /*       Store Half Word and Update */
0329 sthu:
0330 /*       Store Half Word and Update Indexed */
0331 sthux:
0332         stwx    r5,r7,r6                /* Update RA with effective address */
0333 
0334 /*       Store Half Word */
0335 sth:
0336 /*       Store Half Word Indexed */
0337 sthx:
0338         lwzx    r10,r8,r7               /* retrieve source register value */
0339         rlwinm  r10,r10,16,0,15         /* move two bytes to high end of reg */
0340         stswi   r10,r5,2                /* store bytes to DEAR address */
0341         b       align_complete          /* return */
0342 
0343 /* */
0344 /*       Store Half Word Byte-Reversed Indexed */
0345 sthbrx:
0346         lwbrx   r10,r8,r7               /* retrieve src reg value byte reversed */
0347         stswi   r10,r5,2                /* move two bytes to DEAR address */
0348         b       align_complete          /* return */
0349 
0350 /* */
0351 /*       Store Multiple Word */
0352 stmw:
0353         addi    r10,r7,32*4             /* r10 points to r31 in image  + 4 */
0354         rlwinm  r8,r8,30,2,31           /* r8 >>= 2  (recovers RT) */
0355         subfic  r8,r8,32                /* r8 is reg count to load */
0356         mtctr   r8                      /* load counter */
0357         addi    r8,r8,-1                /* r8-- */
0358         rlwinm  r8,r8,2,2,31            /* r8 *= 4 */
0359         add     r5,r5,r8                /* update DEAR to point to last reg */
0360 stmloop:
0361         lwzu    r11,-4(r10)             /* get register value */
0362         stswi   r11,r5,4                /* output to DEAR address */
0363         addi    r5,r5,-4                /* decrement effective address */
0364         bdnz    stmloop
0365         b       align_complete          /* return */
0366 
0367 /* */
0368 /*       Store Word and Update */
0369 stwu:
0370 /*       Store Word and Update Indexed */
0371 stwux:
0372         stwx    r5,r7,r6                /* Update RA with effective address */
0373 
0374 /*       Store Word */
0375 stw:
0376 /*       Store Word Indexed */
0377 stwx:
0378         lwzx    r10,r8,r7               /* retrieve source register value */
0379         stswi   r10,r5,4                /* store bytes to DEAR address */
0380         b       align_complete          /* return */
0381 
0382 /* */
0383 /*       Store Word Byte-Reversed Indexed */
0384 stwbrx:
0385         lwbrx   r10,r8,r7               /* retrieve src reg value byte reversed */
0386         stswi   r10,r5,4                /* move two bytes to DEAR address */
0387         b       align_complete          /* return */
0388 
0389 /* */
0390 /*       Store Word Conditional Indexed */
0391 stwcx:
0392         rlwinm  r10,r5,0,0,29           /* r10 = word aligned DEAR */
0393         lwz     r11,0(r10)              /* save original value of store */
0394         stwcx.  r11,r0,r10              /* attempt store to address */
0395         bne     stwcx_moveon            /* store failed, move on */
0396         stw     r11,0(r10)              /* repair damage */
0397         lwzx    r9,r7,r8                /* get register value */
0398         stswi   r10,r5,4                /* store bytes to DEAR address */
0399 stwcx_moveon:
0400         mfcr    r11                     /* get condition reg */
0401         lwz     r9,Open_cr(r1)          /* get condition reg image */
0402         rlwimi  r9,r11,0,0,2            /* insert 3 CR bits into cr image */
0403         lwz     r11,Open_xer(r1)        /* get XER reg */
0404         rlwimi  r9,r11,29,2,2           /* insert XER SO bit into cr image */
0405         stw     r9,Open_cr(r1)          /* store cr image */
0406         b       align_complete          /* return */
0407 
0408 /* */
0409 /*       Data Cache Block Zero */
0410 dcbz:
0411         rlwinm  r5,r5,0,0,31-CACHE_SIZE_L2
0412                                         /* get address to nearest Cache line */
0413         addi    r5,r5,-4                /* adjust by a word */
0414         addi    r10,r0,CACHE_SIZE/4     /* set counter value */
0415         mtctr   r10
0416         addi    r11,r0,0                /* r11 = 0 */
0417 dcbz_loop:
0418         stwu    r11,4(r5)               /* store a word and update EA */
0419         bdnz    dcbz_loop
0420         b       align_complete          /* return */
0421 
0422 align_complete:
0423         /*-----------------------------------------------------------------------
0424          * Restore regs and return from the interrupt
0425          *----------------------------------------------------------------------*/
0426         lmw     r24,Open_xer+ALIGN_REGS(r0)
0427         mtxer   r24
0428         mtlr    r25
0429         mtctr   r26
0430         mtcrf   0xFF, r27
0431 #if defined(ppc403) || defined(ppc405)
0432         mtspr   srr2, r28       /* SRR 2 */
0433         mtspr   srr3, r29       /* SRR 3 */
0434 #endif
0435         mtspr   srr0, r30       /* SRR 0 */
0436         mtspr   srr1, r31       /* SRR 1 */
0437         lmw     r1,Open_gpr1+ALIGN_REGS(r0)
0438         lwz     r0,Open_gpr0+ALIGN_REGS(r0)
0439         rfi