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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [mips64/] [kernel/] [branch.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * This file is subject to the terms and conditions of the GNU General Public
3
 * License.  See the file "COPYING" in the main directory of this archive
4
 * for more details.
5
 *
6
 * Branch and jump emulation.
7
 *
8
 * Copyright (C) 1996, 1997 by Ralf Baechle
9
 */
10
#include <linux/kernel.h>
11
#include <linux/sched.h>
12
#include <linux/signal.h>
13
#include <asm/branch.h>
14
#include <asm/cpu.h>
15
#include <asm/inst.h>
16
#include <asm/ptrace.h>
17
#include <asm/uaccess.h>
18
 
19
/*
20
 * Compute the return address and do emulate branch simulation, if required.
21
 */
22
int __compute_return_epc(struct pt_regs *regs)
23
{
24
        unsigned int *addr, bit, fcr31;
25
        long epc;
26
        union mips_instruction insn;
27
 
28
        epc = regs->cp0_epc;
29
        if (epc & 3) {
30
                printk("%s: unaligned epc - sending SIGBUS.\n", current->comm);
31
                force_sig(SIGBUS, current);
32
                return -EFAULT;
33
        }
34
 
35
        /*
36
         * Read the instruction
37
         */
38
        addr = (unsigned int *) epc;
39
        if (__get_user(insn.word, addr)) {
40
                force_sig(SIGSEGV, current);
41
                return -EFAULT;
42
        }
43
 
44
        regs->regs[0] = 0;
45
        switch (insn.i_format.opcode) {
46
        /*
47
         * jr and jalr are in r_format format.
48
         */
49
        case spec_op:
50
                switch (insn.r_format.func) {
51
                case jalr_op:
52
                        regs->regs[insn.r_format.rd] = epc + 8;
53
                        /* Fall through */
54
                case jr_op:
55
                        regs->cp0_epc = regs->regs[insn.r_format.rs];
56
                        break;
57
                }
58
                break;
59
 
60
        /*
61
         * This group contains:
62
         * bltz_op, bgez_op, bltzl_op, bgezl_op,
63
         * bltzal_op, bgezal_op, bltzall_op, bgezall_op.
64
         */
65
        case bcond_op:
66
                switch (insn.i_format.rt) {
67
                case bltz_op:
68
                case bltzl_op:
69
                        if ((long)regs->regs[insn.i_format.rs] < 0)
70
                                epc = epc + 4 + (insn.i_format.simmediate << 2);
71
                        else
72
                                epc += 8;
73
                        regs->cp0_epc = epc;
74
                        break;
75
 
76
                case bgez_op:
77
                case bgezl_op:
78
                        if ((long)regs->regs[insn.i_format.rs] >= 0)
79
                                epc = epc + 4 + (insn.i_format.simmediate << 2);
80
                        else
81
                                epc += 8;
82
                        regs->cp0_epc = epc;
83
                        break;
84
 
85
                case bltzal_op:
86
                case bltzall_op:
87
                        regs->regs[31] = epc + 8;
88
                        if ((long)regs->regs[insn.i_format.rs] < 0)
89
                                epc = epc + 4 + (insn.i_format.simmediate << 2);
90
                        else
91
                                epc += 8;
92
                        regs->cp0_epc = epc;
93
                        break;
94
 
95
                case bgezal_op:
96
                case bgezall_op:
97
                        regs->regs[31] = epc + 8;
98
                        if ((long)regs->regs[insn.i_format.rs] >= 0)
99
                                epc = epc + 4 + (insn.i_format.simmediate << 2);
100
                        else
101
                                epc += 8;
102
                        regs->cp0_epc = epc;
103
                        break;
104
                }
105
                break;
106
 
107
        /*
108
         * These are unconditional and in j_format.
109
         */
110
        case jal_op:
111
                regs->regs[31] = regs->cp0_epc + 8;
112
        case j_op:
113
                epc += 4;
114
                epc >>= 28;
115
                epc <<= 28;
116
                epc |= (insn.j_format.target << 2);
117
                regs->cp0_epc = epc;
118
                break;
119
 
120
        /*
121
         * These are conditional and in i_format.
122
         */
123
        case beq_op:
124
        case beql_op:
125
                if (regs->regs[insn.i_format.rs] ==
126
                    regs->regs[insn.i_format.rt])
127
                        epc = epc + 4 + (insn.i_format.simmediate << 2);
128
                else
129
                        epc += 8;
130
                regs->cp0_epc = epc;
131
                break;
132
 
133
        case bne_op:
134
        case bnel_op:
135
                if (regs->regs[insn.i_format.rs] !=
136
                    regs->regs[insn.i_format.rt])
137
                        epc = epc + 4 + (insn.i_format.simmediate << 2);
138
                else
139
                        epc += 8;
140
                regs->cp0_epc = epc;
141
                break;
142
 
143
        case blez_op: /* not really i_format */
144
        case blezl_op:
145
                /* rt field assumed to be zero */
146
                if ((long)regs->regs[insn.i_format.rs] <= 0)
147
                        epc = epc + 4 + (insn.i_format.simmediate << 2);
148
                else
149
                        epc += 8;
150
                regs->cp0_epc = epc;
151
                break;
152
 
153
        case bgtz_op:
154
        case bgtzl_op:
155
                /* rt field assumed to be zero */
156
                if ((long)regs->regs[insn.i_format.rs] > 0)
157
                        epc = epc + 4 + (insn.i_format.simmediate << 2);
158
                else
159
                        epc += 8;
160
                regs->cp0_epc = epc;
161
                break;
162
 
163
        /*
164
         * And now the FPA/cp1 branch instructions.
165
         */
166
        case cop1_op:
167
                if (!cpu_has_fpu)
168
                        fcr31 = current->thread.fpu.soft.sr;
169
                else
170
                        asm volatile("cfc1\t%0,$31" : "=r" (fcr31));
171
                bit = (insn.i_format.rt >> 2);
172
                bit += (bit != 0);
173
                bit += 23;
174
                switch (insn.i_format.rt) {
175
                case 0:  /* bc1f */
176
                case 2: /* bc1fl */
177
                        if (~fcr31 & (1 << bit))
178
                                epc = epc + 4 + (insn.i_format.simmediate << 2);
179
                        else
180
                                epc += 8;
181
                        regs->cp0_epc = epc;
182
                        break;
183
 
184
                case 1: /* bc1t */
185
                case 3: /* bc1tl */
186
                        if (fcr31 & (1 << bit))
187
                                epc = epc + 4 + (insn.i_format.simmediate << 2);
188
                        else
189
                                epc += 8;
190
                        regs->cp0_epc = epc;
191
                        break;
192
                }
193
                break;
194
        }
195
 
196
        return 0;
197
}

powered by: WebSVN 2.1.0

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