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 39

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

powered by: WebSVN 2.1.0

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