OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [newlib/] [libgloss/] [mips/] [vr4300.S] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 39 lampret
/*
2
 * vr4300.S -- CPU specific support routines
3
 *
4
 * Copyright (c) 1995,1996 Cygnus Support
5
 *
6
 * The authors hereby grant permission to use, copy, modify, distribute,
7
 * and license this software and its documentation for any purpose, provided
8
 * that existing copyright notices are retained in all copies and that this
9
 * notice is included verbatim in any distributions. No written agreement,
10
 * license, or royalty fee is required for any of the authorized uses.
11
 * Modifications to this software may be copyrighted by their authors
12
 * and need not follow the licensing terms described here, provided that
13
 * the new terms are clearly indicated on the first page of each file where
14
 * they apply.
15
 */
16
 
17 56 joel
#ifndef __mips64
18
        .set mips3
19
#endif
20 39 lampret
#ifdef __mips16
21
/* This file contains 32 bit assembly code.  */
22
        .set nomips16
23
#endif
24
 
25
#include "regs.S"
26
 
27
        .text
28
        .align  2
29
 
30
        # Taken from "R4300 Preliminary RISC Processor Specification
31
        # Revision 2.0 January 1995" page 39: "The Count
32
        # register... increments at a constant rate... at one-half the
33
        # PClock speed."
34
        # We can use this fact to provide small polled delays.
35
        .globl  __cpu_timer_poll
36
        .ent    __cpu_timer_poll
37
__cpu_timer_poll:
38
        .set    noreorder
39
        # in:   a0 = (unsigned int) number of PClock ticks to wait for
40
        # out:  void
41
 
42
        # The Vr4300 counter updates at half PClock, so divide by 2 to
43
        # get counter delta:
44
        bnezl   a0, 1f          # continue if delta non-zero
45
        srl     a0, a0, 1       # divide ticks by 2             {DELAY SLOT}
46
        # perform a quick return to the caller:
47
        j       ra
48
        nop                     #                               {DELAY SLOT}
49
1:
50
        mfc0    v0, $9          # C0_COUNT:  get current counter value
51
        nop
52
        nop
53
        # We cannot just do the simple test, of adding our delta onto
54
        # the current value (ignoring overflow) and then checking for
55
        # equality. The counter is incrementing every two PClocks,
56
        # which means the counter value can change between
57
        # instructions, making it hard to sample at the exact value
58
        # desired.
59
 
60
        # However, we do know that our entry delta value is less than
61
        # half the number space (since we divide by 2 on entry). This
62
        # means we can use a difference in signs to indicate timer
63
        # overflow.
64
        addu    a0, v0, a0      # unsigned add (ignore overflow)
65
        # We know have our end value (which will have been
66
        # sign-extended to fill the 64bit register value).
67
2:
68
        # get current counter value:
69
        mfc0    v0, $9  # C0_COUNT
70
        nop
71
        nop
72
        # This is an unsigned 32bit subtraction:
73
        subu    v0, a0, v0      # delta = (end - now)           {DELAY SLOT}
74
        bgtzl   v0, 2b          # looping back is most likely
75
        nop
76
        # We have now been delayed (in the foreground) for AT LEAST
77
        # the required number of counter ticks.
78
        j       ra              # return to caller
79
        nop                     #                               {DELAY SLOT}
80
        .set    reorder
81
        .end    __cpu_timer_poll
82
 
83
        # Flush the processor caches to memory:
84
 
85
        .globl  __cpu_flush
86
        .ent    __cpu_flush
87
__cpu_flush:
88
        .set    noreorder
89
        # NOTE: The Vr4300 *CANNOT* have any secondary cache (bit 17
90
        # of the CONFIG registered is hard-wired to 1). We just
91
        # provide code to flush the Data and Instruction caches.
92
 
93
        # Even though the Vr4300 has hard-wired cache and cache line
94
        # sizes, we still interpret the relevant Config register
95
        # bits. This allows this code to be used for other conforming
96
        # MIPS architectures if desired.
97
 
98
        # Get the config register
99
        mfc0    a0, C0_CONFIG
100
        nop
101
        nop
102
        li      a1, 1           # a useful constant
103
        #
104
        srl     a2, a0, 9       # bits 11..9 for instruction cache size
105
        andi    a2, a2, 0x7     # 3bits of information
106
        add     a2, a2, 12      # get full power-of-2 value
107
        sllv    a2, a1, a2      # instruction cache size
108
        #
109
        srl     a3, a0, 6       # bits 8..6 for data cache size
110
        andi    a3, a3, 0x7     # 3bits of information
111
        add     a3, a3, 12      # get full power-of-2 value
112
        sllv    a3, a1, a3      # data cache size
113
        #
114
        li      a1, (1 << 5)    # check IB (instruction cache line size)
115
        and     a1, a0, a1      # mask against the CONFIG register value
116
        beqz    a1, 1f          # branch on result of delay slot operation
117
        nop
118
        li      a1, 32          # non-zero, then 32bytes
119
        j       2f              # continue
120
        nop
121
1:
122
        li      a1, 16          # 16bytes
123
2:
124
        #
125
        li      t0, (1 << 4)    # check DB (data cache line size)
126
        and     a0, a0, t0      # mask against the CONFIG register value
127
        beqz    a0, 3f          # branch on result of delay slot operation
128
        nop
129
        li      a0, 32          # non-zero, then 32bytes
130
        j       4f              # continue
131
        nop
132
3:
133
        li      a0, 16          # 16bytes
134
4:
135
        #
136
        # a0 = data cache line size
137
        # a1 = instruction cache line size
138
        # a2 = instruction cache size
139
        # a3 = data cache size
140
        #
141
        lui     t0, ((K0BASE >> 16) & 0xFFFF)
142
        ori     t0, t0, (K0BASE & 0xFFFF)
143
        addu    t1, t0, a2      # end cache address
144
        subu    t2, a1, 1       # line size mask
145
        not     t2              # invert the mask
146
        and     t3, t0, t2      # get start address
147
        addu    t1, -1
148
        and     t1, t2          # get end address
149
5:
150
        cache   INDEX_INVALIDATE_I,0(t3)
151
        bne     t3, t1, 5b
152
        addu    t3, a1
153
        #
154
        addu    t1, t0, a3      # end cache address
155
        subu    t2, a0, 1       # line size mask
156
        not     t2              # invert the mask
157
        and     t3, t0, t2      # get start address
158
        addu    t1, -1
159
        and     t1, t2          # get end address
160
6:
161
        cache   INDEX_WRITEBACK_INVALIDATE_D,0(t3)
162
        bne     t3, t1, 6b
163
        addu    t3, a0
164
        #
165
        j       ra      # return to the caller
166
        nop
167
        .set    reorder
168
        .end    __cpu_flush
169
 
170
        # NOTE: This variable should *NOT* be addressed relative to
171
        # the $gp register since this code is executed before $gp is
172
        # initialised... hence we leave it in the text area. This will
173
        # cause problems if this routine is ever ROMmed:
174
 
175
        .globl  __buserr_cnt
176
__buserr_cnt:
177
        .word   0
178
        .align  3
179
__k1_save:
180
        .word   0
181
        .word   0
182
        .align  2
183
 
184
        .ent __buserr
185
        .globl __buserr
186
__buserr:
187
        .set noat
188
        .set noreorder
189
        # k0 and k1 available for use:
190
        mfc0    k0,C0_CAUSE
191
        nop
192
        nop
193
        andi    k0,k0,0x7c
194
        sub     k0,k0,7 << 2
195
        beq     k0,$0,__buserr_do
196
        nop
197
        # call the previous handler
198
        la      k0,__previous
199
        jr      k0
200
        nop
201
        #
202
__buserr_do:
203
        # TODO: check that the cause is indeed a bus error
204
        # - if not then just jump to the previous handler
205
        la      k0,__k1_save
206
        sd      k1,0(k0)
207
        #
208
        la      k1,__buserr_cnt
209
        lw      k0,0(k1)        # increment counter
210
        addu    k0,1
211
        sw      k0,0(k1)
212
        #
213
        la      k0,__k1_save
214
        ld      k1,0(k0)
215
        #
216
        mfc0    k0,C0_EPC
217
        nop
218
        nop
219
        addu    k0,k0,4         # skip offending instruction
220
        mtc0    k0,C0_EPC       # update EPC
221
        nop
222
        nop
223
        eret
224
#        j       k0
225
#        rfe
226
        .set reorder
227
        .set at
228
        .end __buserr
229
 
230
__exception_code:
231
        .set noreorder
232
        lui     k0,%hi(__buserr)
233
        daddiu  k0,k0,%lo(__buserr)
234
        jr      k0
235
        nop
236
        .set reorder
237
__exception_code_end:
238
 
239
        .data
240
__previous:
241
        .space  (__exception_code_end - __exception_code)
242
        # This subtracting two addresses is working
243
        # but is not garenteed to continue working.
244
        # The assemble reserves the right to put these
245
        # two labels into different frags, and then
246
        # cant take their difference.
247
 
248
        .text
249
 
250
        .ent    __default_buserr_handler
251
        .globl  __default_buserr_handler
252
__default_buserr_handler:
253
        .set noreorder
254
        # attach our simple bus error handler:
255
        # in:  void
256
        # out: void
257
        mfc0    a0,C0_SR
258
        nop
259
        li      a1,SR_BEV
260
        and     a1,a1,a0
261
        beq     a1,$0,baseaddr
262
        lui     a0,0x8000       # delay slot
263
        lui     a0,0xbfc0
264
        daddiu  a0,a0,0x0200
265
baseaddr:
266
        daddiu  a0,a0,0x0180
267
        # a0 = base vector table address
268
        la      a1,__exception_code_end
269
        la      a2,__exception_code
270
        subu    a1,a1,a2
271
        la      a3,__previous
272
        # there must be a better way of doing this????
273
copyloop:
274
        lw      v0,0(a0)
275
        sw      v0,0(a3)
276
        lw      v0,0(a2)
277
        sw      v0,0(a0)
278
        daddiu  a0,a0,4
279
        daddiu  a2,a2,4
280
        daddiu  a3,a3,4
281
        subu    a1,a1,4
282
        bne     a1,$0,copyloop
283
        nop
284
        la      a0,__buserr_cnt
285
        sw      $0,0(a0)
286
        j       ra
287
        nop
288
        .set reorder
289
        .end    __default_buserr_handler
290
 
291
        .ent    __restore_buserr_handler
292
        .globl  __restore_buserr_handler
293
__restore_buserr_handler:
294
        .set noreorder
295
        # restore original (monitor) bus error handler
296
        # in:  void
297
        # out: void
298
        mfc0    a0,C0_SR
299
        nop
300
        li      a1,SR_BEV
301
        and     a1,a1,a0
302
        beq     a1,$0,res_baseaddr
303
        lui     a0,0x8000       # delay slot
304
        lui     a0,0xbfc0
305
        daddiu  a0,a0,0x0200
306
res_baseaddr:
307
        daddiu  a0,a0,0x0180
308
        # a0 = base vector table address
309
        la      a1,__exception_code_end
310
        la      a3,__exception_code
311
        subu    a1,a1,a3
312
        la      a3,__previous
313
        # there must be a better way of doing this????
314
res_copyloop:
315
        lw      v0,0(a3)
316
        sw      v0,0(a0)
317
        daddiu  a0,a0,4
318
        daddiu  a3,a3,4
319
        subu    a1,a1,4
320
        bne     a1,$0,res_copyloop
321
        nop
322
        j       ra
323
        nop
324
        .set reorder
325
        .end    __restore_buserr_handler
326
 
327
        .ent    __buserr_count
328
        .globl  __buserr_count
329
__buserr_count:
330
        .set noreorder
331
        # restore original (monitor) bus error handler
332
        # in:  void
333
        # out: unsigned int __buserr_cnt
334
        la      v0,__buserr_cnt
335
        lw      v0,0(v0)
336
        j       ra
337
        nop
338
        .set reorder
339
        .end    __buserr_count
340
 
341
/* EOF vr4300.S */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.