Revision 4acb54ba

b/target-microblaze/cpu.h
1
/*
2
 *  MicroBlaze virtual CPU header
3
 *
4
 *  Copyright (c) 2009 Edgar E. Iglesias
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
19
 */
20
#ifndef CPU_MICROBLAZE_H
21
#define CPU_MICROBLAZE_H
22

  
23
#define TARGET_LONG_BITS 32
24

  
25
#define CPUState struct CPUMBState
26

  
27
#include "cpu-defs.h"
28
struct CPUMBState;
29
#if !defined(CONFIG_USER_ONLY)
30
#include "mmu.h"
31
#endif
32

  
33
#define TARGET_HAS_ICE 1
34

  
35
#define ELF_MACHINE	EM_XILINX_MICROBLAZE
36

  
37
#define EXCP_NMI        1
38
#define EXCP_MMU        2
39
#define EXCP_IRQ        3
40
#define EXCP_BREAK      4
41
#define EXCP_HW_BREAK   5
42

  
43
/* Register aliases. R0 - R15 */
44
#define R_SP     1
45
#define SR_PC    0
46
#define SR_MSR   1
47
#define SR_EAR   3
48
#define SR_ESR   5
49
#define SR_FSR   7
50
#define SR_BTR   0xb
51
#define SR_EDR   0xd
52

  
53
/* MSR flags.  */
54
#define MSR_BE  (1<<0) /* 0x001 */
55
#define MSR_IE  (1<<1) /* 0x002 */
56
#define MSR_C   (1<<2) /* 0x004 */
57
#define MSR_BIP (1<<3) /* 0x008 */
58
#define MSR_FSL (1<<4) /* 0x010 */
59
#define MSR_ICE (1<<5) /* 0x020 */
60
#define MSR_DZ  (1<<6) /* 0x040 */
61
#define MSR_DCE (1<<7) /* 0x080 */
62
#define MSR_EE  (1<<8) /* 0x100 */
63
#define MSR_EIP (1<<9) /* 0x200 */
64
#define MSR_CC  (1<<31)
65

  
66
/* Machine State Register (MSR) Fields */
67
#define MSR_UM (1<<11) /* User Mode */
68
#define MSR_UMS        (1<<12) /* User Mode Save */
69
#define MSR_VM (1<<13) /* Virtual Mode */
70
#define MSR_VMS        (1<<14) /* Virtual Mode Save */
71

  
72
#define MSR_KERNEL      MSR_EE|MSR_VM
73
//#define MSR_USER     MSR_KERNEL|MSR_UM|MSR_IE
74
#define MSR_KERNEL_VMS  MSR_EE|MSR_VMS
75
//#define MSR_USER_VMS MSR_KERNEL_VMS|MSR_UMS|MSR_IE
76

  
77
/* Exception State Register (ESR) Fields */
78
#define          ESR_DIZ       (1<<11) /* Zone Protection */
79
#define          ESR_S         (1<<10) /* Store instruction */
80

  
81

  
82

  
83
/* Version reg.  */
84
/* Basic PVR mask */
85
#define PVR0_PVR_FULL_MASK              0x80000000
86
#define PVR0_USE_BARREL_MASK            0x40000000
87
#define PVR0_USE_DIV_MASK               0x20000000
88
#define PVR0_USE_HW_MUL_MASK            0x10000000
89
#define PVR0_USE_FPU_MASK               0x08000000
90
#define PVR0_USE_EXC_MASK               0x04000000
91
#define PVR0_USE_ICACHE_MASK            0x02000000
92
#define PVR0_USE_DCACHE_MASK            0x01000000
93
#define PVR0_USE_MMU                    0x00800000      /* new */
94
#define PVR0_VERSION_MASK               0x0000FF00
95
#define PVR0_USER1_MASK                 0x000000FF
96

  
97
/* User 2 PVR mask */
98
#define PVR1_USER2_MASK                 0xFFFFFFFF
99

  
100
/* Configuration PVR masks */
101
#define PVR2_D_OPB_MASK                 0x80000000
102
#define PVR2_D_LMB_MASK                 0x40000000
103
#define PVR2_I_OPB_MASK                 0x20000000
104
#define PVR2_I_LMB_MASK                 0x10000000
105
#define PVR2_INTERRUPT_IS_EDGE_MASK     0x08000000
106
#define PVR2_EDGE_IS_POSITIVE_MASK      0x04000000
107
#define PVR2_D_PLB_MASK                 0x02000000      /* new */
108
#define PVR2_I_PLB_MASK                 0x01000000      /* new */
109
#define PVR2_INTERCONNECT               0x00800000      /* new */
110
#define PVR2_USE_EXTEND_FSL             0x00080000      /* new */
111
#define PVR2_USE_FSL_EXC                0x00040000      /* new */
112
#define PVR2_USE_MSR_INSTR              0x00020000
113
#define PVR2_USE_PCMP_INSTR             0x00010000
114
#define PVR2_AREA_OPTIMISED             0x00008000
115
#define PVR2_USE_BARREL_MASK            0x00004000
116
#define PVR2_USE_DIV_MASK               0x00002000
117
#define PVR2_USE_HW_MUL_MASK            0x00001000
118
#define PVR2_USE_FPU_MASK               0x00000800
119
#define PVR2_USE_MUL64_MASK             0x00000400
120
#define PVR2_USE_FPU2_MASK              0x00000200      /* new */
121
#define PVR2_USE_IPLBEXC                0x00000100
122
#define PVR2_USE_DPLBEXC                0x00000080
123
#define PVR2_OPCODE_0x0_ILL_MASK        0x00000040
124
#define PVR2_UNALIGNED_EXC_MASK         0x00000020
125
#define PVR2_ILL_OPCODE_EXC_MASK        0x00000010
126
#define PVR2_IOPB_BUS_EXC_MASK          0x00000008
127
#define PVR2_DOPB_BUS_EXC_MASK          0x00000004
128
#define PVR2_DIV_ZERO_EXC_MASK          0x00000002
129
#define PVR2_FPU_EXC_MASK               0x00000001
130

  
131
/* Debug and exception PVR masks */
132
#define PVR3_DEBUG_ENABLED_MASK         0x80000000
133
#define PVR3_NUMBER_OF_PC_BRK_MASK      0x1E000000
134
#define PVR3_NUMBER_OF_RD_ADDR_BRK_MASK 0x00380000
135
#define PVR3_NUMBER_OF_WR_ADDR_BRK_MASK 0x0000E000
136
#define PVR3_FSL_LINKS_MASK             0x00000380
137

  
138
/* ICache config PVR masks */
139
#define PVR4_USE_ICACHE_MASK            0x80000000
140
#define PVR4_ICACHE_ADDR_TAG_BITS_MASK  0x7C000000
141
#define PVR4_ICACHE_USE_FSL_MASK        0x02000000
142
#define PVR4_ICACHE_ALLOW_WR_MASK       0x01000000
143
#define PVR4_ICACHE_LINE_LEN_MASK       0x00E00000
144
#define PVR4_ICACHE_BYTE_SIZE_MASK      0x001F0000
145

  
146
/* DCache config PVR masks */
147
#define PVR5_USE_DCACHE_MASK            0x80000000
148
#define PVR5_DCACHE_ADDR_TAG_BITS_MASK  0x7C000000
149
#define PVR5_DCACHE_USE_FSL_MASK        0x02000000
150
#define PVR5_DCACHE_ALLOW_WR_MASK       0x01000000
151
#define PVR5_DCACHE_LINE_LEN_MASK       0x00E00000
152
#define PVR5_DCACHE_BYTE_SIZE_MASK      0x001F0000
153

  
154
/* ICache base address PVR mask */
155
#define PVR6_ICACHE_BASEADDR_MASK       0xFFFFFFFF
156

  
157
/* ICache high address PVR mask */
158
#define PVR7_ICACHE_HIGHADDR_MASK       0xFFFFFFFF
159

  
160
/* DCache base address PVR mask */
161
#define PVR8_DCACHE_BASEADDR_MASK       0xFFFFFFFF
162

  
163
/* DCache high address PVR mask */
164
#define PVR9_DCACHE_HIGHADDR_MASK       0xFFFFFFFF
165

  
166
/* Target family PVR mask */
167
#define PVR10_TARGET_FAMILY_MASK        0xFF000000
168

  
169
/* MMU descrtiption */
170
#define PVR11_USE_MMU                   0xC0000000
171
#define PVR11_MMU_ITLB_SIZE             0x38000000
172
#define PVR11_MMU_DTLB_SIZE             0x07000000
173
#define PVR11_MMU_TLB_ACCESS            0x00C00000
174
#define PVR11_MMU_ZONES                 0x003C0000
175
/* MSR Reset value PVR mask */
176
#define PVR11_MSR_RESET_VALUE_MASK      0x000007FF
177

  
178

  
179

  
180
/* CPU flags.  */
181

  
182
/* Condition codes.  */
183
#define CC_GE  5
184
#define CC_GT  4
185
#define CC_LE  3
186
#define CC_LT  2
187
#define CC_NE  1
188
#define CC_EQ  0
189

  
190
#define NB_MMU_MODES    3
191
typedef struct CPUMBState {
192
    uint32_t debug;
193
    uint32_t btaken;
194
    uint32_t btarget;
195
    uint32_t bimm;
196

  
197
    uint32_t imm;
198
    uint32_t regs[33];
199
    uint32_t sregs[24];
200

  
201
    /* Internal flags.  */
202
#define IMM_FLAG	4	
203
#define DRTI_FLAG	(1 << 16)
204
#define DRTE_FLAG	(1 << 17)
205
#define DRTB_FLAG	(1 << 18)
206
#define D_FLAG		(1 << 19)  /* Bit in ESR.  */
207
/* TB dependant CPUState.  */
208
#define IFLAGS_TB_MASK	(D_FLAG | IMM_FLAG | DRTI_FLAG | DRTE_FLAG | DRTB_FLAG)
209
    uint32_t iflags;
210

  
211
    struct {
212
        uint32_t regs[16];
213
    } pvr;
214

  
215
#if !defined(CONFIG_USER_ONLY)
216
    /* Unified MMU.  */
217
    struct microblaze_mmu mmu;
218
#endif
219

  
220
    CPU_COMMON
221
} CPUMBState;
222

  
223
CPUState *cpu_mb_init(const char *cpu_model);
224
int cpu_mb_exec(CPUState *s);
225
void cpu_mb_close(CPUState *s);
226
void do_interrupt(CPUState *env);
227
/* you can call this signal handler from your SIGBUS and SIGSEGV
228
   signal handlers to inform the virtual CPU of exceptions. non zero
229
   is returned if the signal was handled by the virtual CPU.  */
230
int cpu_mb_signal_handler(int host_signum, void *pinfo,
231
                          void *puc);
232

  
233
enum {
234
    CC_OP_DYNAMIC, /* Use env->cc_op  */
235
    CC_OP_FLAGS,
236
    CC_OP_CMP,
237
};
238

  
239
/* FIXME: MB uses variable pages down to 1K but linux only uses 4k.  */
240
#define TARGET_PAGE_BITS 12
241
#define MMAP_SHIFT TARGET_PAGE_BITS
242

  
243
#define cpu_init cpu_mb_init
244
#define cpu_exec cpu_mb_exec
245
#define cpu_gen_code cpu_mb_gen_code
246
#define cpu_signal_handler cpu_mb_signal_handler
247

  
248
#define CPU_SAVE_VERSION 1
249

  
250
/* MMU modes definitions */
251
#define MMU_MODE0_SUFFIX _nommu
252
#define MMU_MODE1_SUFFIX _kernel
253
#define MMU_MODE2_SUFFIX _user
254
#define MMU_NOMMU_IDX   0
255
#define MMU_KERNEL_IDX  1
256
#define MMU_USER_IDX    2
257
/* See NB_MMU_MODES further up the file.  */
258

  
259
static inline int cpu_mmu_index (CPUState *env)
260
{
261
        /* Are we in nommu mode?.  */
262
        if (!(env->sregs[SR_MSR] & MSR_VM))
263
            return MMU_NOMMU_IDX;
264

  
265
	if (env->sregs[SR_MSR] & MSR_UM)
266
            return MMU_USER_IDX;
267
        return MMU_KERNEL_IDX;
268
}
269

  
270
int cpu_mb_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
271
                            int mmu_idx, int is_softmmu);
272

  
273
#if defined(CONFIG_USER_ONLY)
274
static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
275
{
276
    if (newsp)
277
        env->regs[R_SP] = newsp;
278
    env->regs[3] = 0;
279
}
280
#endif
281

  
282
static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
283
{
284
}
285

  
286
static inline int cpu_interrupts_enabled(CPUState *env)
287
{
288
    return env->sregs[SR_MSR] & MSR_IE;
289
}
290

  
291
#include "cpu-all.h"
292
#include "exec-all.h"
293

  
294
static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
295
{
296
    env->sregs[SR_PC] = tb->pc;
297
}
298

  
299
static inline target_ulong cpu_get_pc(CPUState *env)
300
{
301
    return env->sregs[SR_PC];
302
}
303

  
304
static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
305
                                        target_ulong *cs_base, int *flags)
306
{
307
    *pc = env->sregs[SR_PC];
308
    *cs_base = 0;
309
    *flags = env->iflags & IFLAGS_TB_MASK;
310
}
311
#endif
b/target-microblaze/exec.h
1
/*
2
 *  Microblaze execution defines
3
 *
4
 *  Copyright (c) 2009 Edgar E. Iglesias
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
19
 */
20
#include "dyngen-exec.h"
21

  
22
register struct CPUMBState *env asm(AREG0);
23

  
24
#include "cpu.h"
25
#include "exec-all.h"
26

  
27
static inline void env_to_regs(void)
28
{
29
}
30

  
31
static inline void regs_to_env(void)
32
{
33
}
34

  
35
#if !defined(CONFIG_USER_ONLY)
36
#include "softmmu_exec.h"
37
#endif
38

  
39
void cpu_mb_flush_flags(CPUMBState *env, int cc_op);
40

  
41
static inline int cpu_has_work(CPUState *env)
42
{
43
    return (env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI));
44
}
45

  
46
static inline int cpu_halted(CPUState *env) {
47
	if (!env->halted)
48
		return 0;
49

  
50
	/* IRQ, NMI and GURU execeptions wakes us up.  */
51
	if (env->interrupt_request
52
	    & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI)) {
53
		env->halted = 0;
54
		return 0;
55
	}
56
	return EXCP_HALTED;
57
}
b/target-microblaze/helper.c
1
/*
2
 *  MicroBlaze helper routines.
3
 *
4
 *  Copyright (c) 2009 Edgar E. Iglesias <edgar.iglesias@gmail.com>
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
19
 */
20

  
21
#include <stdio.h>
22
#include <string.h>
23
#include <assert.h>
24

  
25
#include "config.h"
26
#include "cpu.h"
27
#include "exec-all.h"
28
#include "host-utils.h"
29

  
30
#define D(x)
31
#define DMMU(x)
32

  
33
#if defined(CONFIG_USER_ONLY)
34

  
35
void do_interrupt (CPUState *env)
36
{
37
    env->exception_index = -1;
38
    env->regs[14] = env->sregs[SR_PC];
39
}
40

  
41
int cpu_mb_handle_mmu_fault(CPUState * env, target_ulong address, int rw,
42
                             int mmu_idx, int is_softmmu)
43
{
44
    env->exception_index = 0xaa;
45
    cpu_dump_state(env, stderr, fprintf, 0);
46
    return 1;
47
}
48

  
49
target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr)
50
{
51
    return addr;
52
}
53

  
54
#else /* !CONFIG_USER_ONLY */
55

  
56
int cpu_mb_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
57
                               int mmu_idx, int is_softmmu)
58
{
59
    unsigned int hit;
60
    unsigned int mmu_available;
61
    int r = 1;
62
    int prot;
63

  
64
    mmu_available = 0;
65
    if (env->pvr.regs[0] & PVR0_USE_MMU) {
66
        mmu_available = 1;
67
        if ((env->pvr.regs[0] & PVR0_PVR_FULL_MASK)
68
            && (env->pvr.regs[11] & PVR11_USE_MMU) != PVR11_USE_MMU) {
69
            mmu_available = 0;
70
        }
71
    }
72

  
73
    /* Translate if the MMU is available and enabled.  */
74
    if (mmu_available && (env->sregs[SR_MSR] & MSR_VM)) {
75
        target_ulong vaddr, paddr;
76
        struct microblaze_mmu_lookup lu;
77

  
78
        hit = mmu_translate(&env->mmu, &lu, address, rw, mmu_idx);
79
        if (hit) {
80
            vaddr = address & TARGET_PAGE_MASK;
81
            paddr = lu.paddr + vaddr - lu.vaddr;
82

  
83
            DMMU(qemu_log("MMU map mmu=%d v=%x p=%x prot=%x\n",
84
                     mmu_idx, vaddr, paddr, lu.prot));
85
            r = tlb_set_page(env, vaddr,
86
                             paddr, lu.prot, mmu_idx, is_softmmu);
87
        } else {
88
            env->sregs[SR_EAR] = address;
89
            DMMU(qemu_log("mmu=%d miss addr=%x\n", mmu_idx, vaddr));
90

  
91
            switch (lu.err) {
92
                case ERR_PROT:
93
                    env->sregs[SR_ESR] = rw == 2 ? 17 : 16;
94
                    env->sregs[SR_ESR] |= (rw == 1) << 10;
95
                    break;
96
                case ERR_MISS:
97
                    env->sregs[SR_ESR] = rw == 2 ? 19 : 18;
98
                    env->sregs[SR_ESR] |= (rw == 1) << 10;
99
                    break;
100
                default:
101
                    abort();
102
                    break;
103
            }
104

  
105
            if (env->exception_index == EXCP_MMU) {
106
                cpu_abort(env, "recursive faults\n");
107
            }
108

  
109
            /* TLB miss.  */
110
            env->exception_index = EXCP_MMU;
111
        }
112
    } else {
113
        /* MMU disabled or not available.  */
114
        address &= TARGET_PAGE_MASK;
115
        prot = PAGE_BITS;
116
        r = tlb_set_page(env, address, address, prot, mmu_idx, is_softmmu);
117
    }
118
    return r;
119
}
120

  
121
void do_interrupt(CPUState *env)
122
{
123
    uint32_t t;
124

  
125
    /* IMM flag cannot propagate accross a branch and into the dslot.  */
126
    assert(!((env->iflags & D_FLAG) && (env->iflags & IMM_FLAG)));
127
    assert(!(env->iflags & (DRTI_FLAG | DRTE_FLAG | DRTB_FLAG)));
128
/*    assert(env->sregs[SR_MSR] & (MSR_EE)); Only for HW exceptions.  */
129
    switch (env->exception_index) {
130
        case EXCP_MMU:
131
            env->regs[17] = env->sregs[SR_PC];
132

  
133
            /* Exception breaks branch + dslot sequence?  */
134
            if (env->iflags & D_FLAG) {
135
                D(qemu_log("D_FLAG set at exception bimm=%d\n", env->bimm));
136
                env->sregs[SR_ESR] |= 1 << 12 ;
137
                env->sregs[SR_BTR] = env->btarget;
138

  
139
                /* Reexecute the branch.  */
140
                env->regs[17] -= 4;
141
                /* was the branch immprefixed?.  */
142
                if (env->bimm) {
143
                    qemu_log_mask(CPU_LOG_INT,
144
                                  "bimm exception at pc=%x iflags=%x\n",
145
                                  env->sregs[SR_PC], env->iflags);
146
                    env->regs[17] -= 4;
147
                    log_cpu_state_mask(CPU_LOG_INT, env, 0);
148
                }
149
            } else if (env->iflags & IMM_FLAG) {
150
                D(qemu_log("IMM_FLAG set at exception\n"));
151
                env->regs[17] -= 4;
152
            }
153

  
154
            /* Disable the MMU.  */
155
            t = (env->sregs[SR_MSR] & (MSR_VM | MSR_UM)) << 1;
156
            env->sregs[SR_MSR] &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM);
157
            env->sregs[SR_MSR] |= t;
158
            /* Exception in progress.  */
159
            env->sregs[SR_MSR] |= MSR_EIP;
160

  
161
            qemu_log_mask(CPU_LOG_INT,
162
                          "exception at pc=%x ear=%x iflags=%x\n",
163
                          env->sregs[SR_PC], env->sregs[SR_EAR], env->iflags);
164
            log_cpu_state_mask(CPU_LOG_INT, env, 0);
165
            env->iflags &= ~(IMM_FLAG | D_FLAG);
166
            env->sregs[SR_PC] = 0x20;
167
            break;
168

  
169
        case EXCP_IRQ:
170
            assert(!(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP)));
171
            assert(env->sregs[SR_MSR] & MSR_IE);
172
            assert(!(env->iflags & D_FLAG));
173

  
174
            t = (env->sregs[SR_MSR] & (MSR_VM | MSR_UM)) << 1;
175

  
176
#if 0
177
#include "disas.h"
178

  
179
/* Useful instrumentation when debugging interrupt issues in either
180
   the models or in sw.  */
181
            {
182
                const char *sym;
183

  
184
                sym = lookup_symbol(env->sregs[SR_PC]);
185
                if (sym
186
                    && (!strcmp("netif_rx", sym)
187
                        || !strcmp("process_backlog", sym))) {
188

  
189
                    qemu_log(
190
                         "interrupt at pc=%x msr=%x %x iflags=%x sym=%s\n",
191
                         env->sregs[SR_PC], env->sregs[SR_MSR], t, env->iflags,
192
                         sym);
193

  
194
                    log_cpu_state(env, 0);
195
                }
196
            }
197
#endif
198
            qemu_log_mask(CPU_LOG_INT,
199
                         "interrupt at pc=%x msr=%x %x iflags=%x\n",
200
                         env->sregs[SR_PC], env->sregs[SR_MSR], t, env->iflags);
201

  
202
            env->sregs[SR_MSR] &= ~(MSR_VMS | MSR_UMS | MSR_VM \
203
                                    | MSR_UM | MSR_IE);
204
            env->sregs[SR_MSR] |= t;
205

  
206
            env->regs[14] = env->sregs[SR_PC];
207
            env->sregs[SR_PC] = 0x10;
208
            //log_cpu_state_mask(CPU_LOG_INT, env, 0);
209
            break;
210

  
211
        case EXCP_BREAK:
212
        case EXCP_HW_BREAK:
213
            assert(!(env->iflags & IMM_FLAG));
214
            assert(!(env->iflags & D_FLAG));
215
            t = (env->sregs[SR_MSR] & (MSR_VM | MSR_UM)) << 1;
216
            qemu_log_mask(CPU_LOG_INT,
217
                        "break at pc=%x msr=%x %x iflags=%x\n",
218
                        env->sregs[SR_PC], env->sregs[SR_MSR], t, env->iflags);
219
            log_cpu_state_mask(CPU_LOG_INT, env, 0);
220
            env->sregs[SR_MSR] &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM);
221
            env->sregs[SR_MSR] |= t;
222
            env->sregs[SR_MSR] |= MSR_BIP;
223
            if (env->exception_index == EXCP_HW_BREAK) {
224
                env->regs[16] = env->sregs[SR_PC];
225
                env->sregs[SR_MSR] |= MSR_BIP;
226
                env->sregs[SR_PC] = 0x18;
227
            } else
228
                env->sregs[SR_PC] = env->btarget;
229
            break;
230
        default:
231
            cpu_abort(env, "unhandled exception type=%d\n",
232
                      env->exception_index);
233
            break;
234
    }
235
}
236

  
237
target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr)
238
{
239
    target_ulong vaddr, paddr = 0;
240
    struct microblaze_mmu_lookup lu;
241
    unsigned int hit;
242

  
243
    if (env->sregs[SR_MSR] & MSR_VM) {
244
        hit = mmu_translate(&env->mmu, &lu, addr, 0, 0);
245
        if (hit) {
246
            vaddr = addr & TARGET_PAGE_MASK;
247
            paddr = lu.paddr + vaddr - lu.vaddr;
248
        } else
249
            paddr = 0; /* ???.  */
250
    } else
251
        paddr = addr & TARGET_PAGE_MASK;
252

  
253
    return paddr;
254
}
255
#endif
b/target-microblaze/helper.h
1
#include "def-helper.h"
2

  
3
DEF_HELPER_1(raise_exception, void, i32)
4
DEF_HELPER_0(debug, void)
5
DEF_HELPER_4(addkc, i32, i32, i32, i32, i32)
6
DEF_HELPER_4(subkc, i32, i32, i32, i32, i32)
7
DEF_HELPER_2(cmp, i32, i32, i32)
8
DEF_HELPER_2(cmpu, i32, i32, i32)
9

  
10
DEF_HELPER_2(divs, i32, i32, i32)
11
DEF_HELPER_2(divu, i32, i32, i32)
12

  
13
DEF_HELPER_FLAGS_2(pcmpbf, TCG_CALL_PURE | TCG_CALL_CONST, i32, i32, i32)
14
#if !defined(CONFIG_USER_ONLY)
15
DEF_HELPER_1(mmu_read, i32, i32)
16
DEF_HELPER_2(mmu_write, void, i32, i32)
17
#endif
18

  
19
#include "def-helper.h"
b/target-microblaze/microblaze-decode.h
1
/*
2
 *  MicroBlaze insn decoding macros.
3
 *
4
 *  Copyright (c) 2009 Edgar E. Iglesias <edgar.iglesias@gmail.com>
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
19
 */
20

  
21
/* Convenient binary macros.  */
22
#define HEX__(n) 0x##n##LU
23
#define B8__(x) ((x&0x0000000FLU)?1:0) \
24
                 + ((x&0x000000F0LU)?2:0) \
25
                 + ((x&0x00000F00LU)?4:0) \
26
                 + ((x&0x0000F000LU)?8:0) \
27
                 + ((x&0x000F0000LU)?16:0) \
28
                 + ((x&0x00F00000LU)?32:0) \
29
                 + ((x&0x0F000000LU)?64:0) \
30
                 + ((x&0xF0000000LU)?128:0)
31
#define B8(d) ((unsigned char)B8__(HEX__(d)))
32

  
33
/* Decode logic, mask and value.  */
34
#define DEC_ADD     {B8(00000000), B8(00110001)}
35
#define DEC_SUB     {B8(00000001), B8(00110001)}
36
#define DEC_AND     {B8(00100001), B8(00110101)}
37
#define DEC_XOR     {B8(00100010), B8(00110111)}
38
#define DEC_OR      {B8(00100000), B8(00110111)}
39
#define DEC_BIT     {B8(00100100), B8(00111111)}
40
#define DEC_MSR     {B8(00100101), B8(00111111)}
41

  
42
#define DEC_BARREL  {B8(00010001), B8(00110111)}
43
#define DEC_MUL     {B8(00010000), B8(00110111)}
44
#define DEC_DIV     {B8(00010010), B8(00110111)}
45

  
46
#define DEC_LD      {B8(00110000), B8(00110100)}
47
#define DEC_ST      {B8(00110100), B8(00110100)}
48
#define DEC_IMM     {B8(00101100), B8(00111111)}
49

  
50
#define DEC_BR      {B8(00100110), B8(00110111)}
51
#define DEC_BCC     {B8(00100111), B8(00110111)}
52
#define DEC_RTS     {B8(00101101), B8(00111111)}
b/target-microblaze/op_helper.c
1
/*
2
 *  Microblaze helper routines.
3
 *
4
 *  Copyright (c) 2009 Edgar E. Iglesias <edgar.iglesias@gmail.com>.
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
19
 */
20

  
21
#include <assert.h>
22
#include "exec.h"
23
#include "helper.h"
24
#include "host-utils.h"
25

  
26
#define D(x)
27

  
28
#if !defined(CONFIG_USER_ONLY)
29
#define MMUSUFFIX _mmu
30
#define SHIFT 0
31
#include "softmmu_template.h"
32
#define SHIFT 1
33
#include "softmmu_template.h"
34
#define SHIFT 2
35
#include "softmmu_template.h"
36
#define SHIFT 3
37
#include "softmmu_template.h"
38

  
39
/* Try to fill the TLB and return an exception if error. If retaddr is
40
   NULL, it means that the function was called in C code (i.e. not
41
   from generated code or from helper.c) */
42
/* XXX: fix it to restore all registers */
43
void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
44
{
45
    TranslationBlock *tb;
46
    CPUState *saved_env;
47
    unsigned long pc;
48
    int ret;
49

  
50
    /* XXX: hack to restore env in all cases, even if not called from
51
       generated code */
52
    saved_env = env;
53
    env = cpu_single_env;
54

  
55
    ret = cpu_mb_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
56
    if (unlikely(ret)) {
57
        if (retaddr) {
58
            /* now we have a real cpu fault */
59
            pc = (unsigned long)retaddr;
60
            tb = tb_find_pc(pc);
61
            if (tb) {
62
                /* the PC is inside the translated code. It means that we have
63
                   a virtual CPU fault */
64
                cpu_restore_state(tb, env, pc, NULL);
65
            }
66
        }
67
        cpu_loop_exit();
68
    }
69
    env = saved_env;
70
}
71
#endif
72

  
73
void helper_raise_exception(uint32_t index)
74
{
75
    env->exception_index = index;
76
    cpu_loop_exit();
77
}
78

  
79
void helper_debug(void)
80
{
81
    int i;
82

  
83
    qemu_log("PC=%8.8x\n", env->sregs[SR_PC]);
84
    for (i = 0; i < 32; i++) {
85
        qemu_log("r%2.2d=%8.8x ", i, env->regs[i]);
86
        if ((i + 1) % 4 == 0)
87
            qemu_log("\n");
88
    }
89
    qemu_log("\n\n");
90
}
91

  
92
static inline uint32_t compute_carry(uint32_t a, uint32_t b, uint32_t cin)
93
{
94
    uint32_t cout = 0;
95

  
96
    if ((b == ~0) && cin)
97
        cout = 1;
98
    else if ((~0 - a) < (b + cin))
99
        cout = 1;
100
    return cout;
101
}
102

  
103
uint32_t helper_cmp(uint32_t a, uint32_t b)
104
{
105
    uint32_t t;
106

  
107
    t = b + ~a + 1;
108
    if ((b & 0x80000000) ^ (a & 0x80000000))
109
        t = (t & 0x7fffffff) | (b & 0x80000000);
110
    return t;
111
}
112

  
113
uint32_t helper_cmpu(uint32_t a, uint32_t b)
114
{
115
    uint32_t t;
116

  
117
    t = b + ~a + 1;
118
    if ((b & 0x80000000) ^ (a & 0x80000000))
119
        t = (t & 0x7fffffff) | (a & 0x80000000);
120
    return t;
121
}
122

  
123
uint32_t helper_addkc(uint32_t a, uint32_t b, uint32_t k, uint32_t c)
124
{
125
    uint32_t d, cf = 0, ncf;
126

  
127
    if (c)
128
        cf = env->sregs[SR_MSR] >> 31;
129
    assert(cf == 0 || cf == 1);
130
    d = a + b + cf;
131

  
132
    if (!k) {
133
        ncf = compute_carry(a, b, cf);
134
        assert(ncf == 0 || ncf == 1);
135
        if (ncf)
136
            env->sregs[SR_MSR] |= MSR_C | MSR_CC;
137
        else
138
            env->sregs[SR_MSR] &= ~(MSR_C | MSR_CC);
139
    }
140
    D(qemu_log("%x = %x + %x cf=%d ncf=%d k=%d c=%d\n",
141
               d, a, b, cf, ncf, k, c));
142
    return d;
143
}
144

  
145
uint32_t helper_subkc(uint32_t a, uint32_t b, uint32_t k, uint32_t c)
146
{
147
    uint32_t d, cf = 1, ncf;
148

  
149
    if (c)
150
        cf = env->sregs[SR_MSR] >> 31; 
151
    assert(cf == 0 || cf == 1);
152
    d = b + ~a + cf;
153

  
154
    if (!k) {
155
        ncf = compute_carry(b, ~a, cf);
156
        assert(ncf == 0 || ncf == 1);
157
        if (ncf)
158
            env->sregs[SR_MSR] |= MSR_C | MSR_CC;
159
        else
160
            env->sregs[SR_MSR] &= ~(MSR_C | MSR_CC);
161
    }
162
    D(qemu_log("%x = %x + %x cf=%d ncf=%d k=%d c=%d\n",
163
               d, a, b, cf, ncf, k, c));
164
    return d;
165
}
166

  
167
static inline int div_prepare(uint32_t a, uint32_t b)
168
{
169
    if (b == 0) {
170
        env->sregs[SR_MSR] |= MSR_DZ;
171
        /* FIXME: Raise the div by zero exception.  */
172
        return 0;
173
    }
174
    env->sregs[SR_MSR] &= ~MSR_DZ;
175
    return 1;
176
}
177

  
178
uint32_t helper_divs(uint32_t a, uint32_t b)
179
{
180
    if (!div_prepare(a, b))
181
        return 0;
182
    return (int32_t)a / (int32_t)b;
183
}
184

  
185
uint32_t helper_divu(uint32_t a, uint32_t b)
186
{
187
    if (!div_prepare(a, b))
188
        return 0;
189
    return a / b;
190
}
191

  
192
uint32_t helper_pcmpbf(uint32_t a, uint32_t b)
193
{
194
    unsigned int i;
195
    uint32_t mask = 0xff000000;
196

  
197
    for (i = 0; i < 4; i++) {
198
        if ((a & mask) == (b & mask))
199
            return i + 1;
200
        mask >>= 8;
201
    }
202
    return 0;
203
}
204

  
205
#if !defined(CONFIG_USER_ONLY)
206
/* Writes/reads to the MMU's special regs end up here.  */
207
uint32_t helper_mmu_read(uint32_t rn)
208
{
209
    return mmu_read(env, rn);
210
}
211

  
212
void helper_mmu_write(uint32_t rn, uint32_t v)
213
{
214
    mmu_write(env, rn, v);
215
}
216
#endif
b/target-microblaze/translate.c
1
/*
2
 *  Xilinx MicroBlaze emulation for qemu: main translation routines.
3
 *
4
 *  Copyright (c) 2009 Edgar E. Iglesias.
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
19
 */
20

  
21
#include <stdarg.h>
22
#include <stdlib.h>
23
#include <stdio.h>
24
#include <string.h>
25
#include <inttypes.h>
26
#include <assert.h>
27

  
28
#include "cpu.h"
29
#include "exec-all.h"
30
#include "disas.h"
31
#include "tcg-op.h"
32
#include "helper.h"
33
#include "microblaze-decode.h"
34
#include "qemu-common.h"
35

  
36
#define GEN_HELPER 1
37
#include "helper.h"
38

  
39
#define SIM_COMPAT 0
40
#define DISAS_GNU 1
41
#define DISAS_MB 1
42
#if DISAS_MB && !SIM_COMPAT
43
#  define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
44
#else
45
#  define LOG_DIS(...) do { } while (0)
46
#endif
47

  
48
#define D(x)
49

  
50
#define EXTRACT_FIELD(src, start, end) \
51
            (((src) >> start) & ((1 << (end - start + 1)) - 1))
52

  
53
static TCGv env_debug;
54
static TCGv_ptr cpu_env;
55
static TCGv cpu_R[32];
56
static TCGv cpu_SR[18];
57
static TCGv env_imm;
58
static TCGv env_btaken;
59
static TCGv env_btarget;
60
static TCGv env_iflags;
61

  
62
#include "gen-icount.h"
63

  
64
/* This is the state at translation time.  */
65
typedef struct DisasContext {
66
    CPUState *env;
67
    target_ulong pc, ppc;
68
    target_ulong cache_pc;
69

  
70
    /* Decoder.  */
71
    int type_b;
72
    uint32_t ir;
73
    uint8_t opcode;
74
    uint8_t rd, ra, rb;
75
    uint16_t imm;
76

  
77
    unsigned int cpustate_changed;
78
    unsigned int delayed_branch;
79
    unsigned int tb_flags, synced_flags; /* tb dependent flags.  */
80
    unsigned int clear_imm;
81
    int is_jmp;
82

  
83
#define JMP_NOJMP    0
84
#define JMP_DIRECT   1
85
#define JMP_INDIRECT 2
86
    unsigned int jmp;
87
    uint32_t jmp_pc;
88

  
89
    int abort_at_next_insn;
90
    int nr_nops;
91
    struct TranslationBlock *tb;
92
    int singlestep_enabled;
93
} DisasContext;
94

  
95
const static char *regnames[] =
96
{
97
    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
98
    "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
99
    "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
100
    "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
101
};
102

  
103
const static char *special_regnames[] =
104
{
105
    "rpc", "rmsr", "sr2", "sr3", "sr4", "sr5", "sr6", "sr7",
106
    "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15",
107
    "sr16", "sr17", "sr18"
108
};
109

  
110
/* Sign extend at translation time.  */
111
static inline int sign_extend(unsigned int val, unsigned int width)
112
{
113
        int sval;
114

  
115
        /* LSL.  */
116
        val <<= 31 - width;
117
        sval = val;
118
        /* ASR.  */
119
        sval >>= 31 - width;
120
        return sval;
121
}
122

  
123
static inline void t_sync_flags(DisasContext *dc)
124
{
125
    /* Synch the tb dependant flags between translator and runtime.  */
126
    if (dc->tb_flags != dc->synced_flags) {
127
        tcg_gen_movi_tl(env_iflags, dc->tb_flags);
128
        dc->synced_flags = dc->tb_flags;
129
    }
130
}
131

  
132
static inline void t_gen_raise_exception(DisasContext *dc, uint32_t index)
133
{
134
    TCGv_i32 tmp = tcg_const_i32(index);
135

  
136
    t_sync_flags(dc);
137
    tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
138
    gen_helper_raise_exception(tmp);
139
    tcg_temp_free_i32(tmp);
140
    dc->is_jmp = DISAS_UPDATE;
141
}
142

  
143
static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
144
{
145
    TranslationBlock *tb;
146
    tb = dc->tb;
147
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
148
        tcg_gen_goto_tb(n);
149
        tcg_gen_movi_tl(cpu_SR[SR_PC], dest);
150
        tcg_gen_exit_tb((long)tb + n);
151
    } else {
152
        tcg_gen_movi_tl(cpu_SR[SR_PC], dest);
153
        tcg_gen_exit_tb(0);
154
    }
155
}
156

  
157
static inline TCGv *dec_alu_op_b(DisasContext *dc)
158
{
159
    if (dc->type_b) {
160
        if (dc->tb_flags & IMM_FLAG)
161
            tcg_gen_ori_tl(env_imm, env_imm, dc->imm);
162
        else
163
            tcg_gen_movi_tl(env_imm, (int32_t)((int16_t)dc->imm));
164
        return &env_imm;
165
    } else
166
        return &cpu_R[dc->rb];
167
}
168

  
169
static void dec_add(DisasContext *dc)
170
{
171
    unsigned int k, c;
172

  
173
    k = dc->opcode & 4;
174
    c = dc->opcode & 2;
175

  
176
    LOG_DIS("add%s%s%s r%d r%d r%d\n",
177
            dc->type_b ? "i" : "", k ? "k" : "", c ? "c" : "",
178
            dc->rd, dc->ra, dc->rb);
179

  
180
    if (k && !c && dc->rd)
181
        tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
182
    else if (dc->rd)
183
        gen_helper_addkc(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)),
184
                         tcg_const_tl(k), tcg_const_tl(c));
185
    else {
186
        TCGv d = tcg_temp_new();
187
        gen_helper_addkc(d, cpu_R[dc->ra], *(dec_alu_op_b(dc)),
188
                         tcg_const_tl(k), tcg_const_tl(c));
189
        tcg_temp_free(d);
190
    }
191
}
192

  
193
static void dec_sub(DisasContext *dc)
194
{
195
    unsigned int u, cmp, k, c;
196

  
197
    u = dc->imm & 2;
198
    k = dc->opcode & 4;
199
    c = dc->opcode & 2;
200
    cmp = (dc->imm & 1) && (!dc->type_b) && k;
201

  
202
    if (cmp) {
203
        LOG_DIS("cmp%s r%d, r%d ir=%x\n", u ? "u" : "", dc->rd, dc->ra, dc->ir);
204
        if (dc->rd) {
205
            if (u)
206
                gen_helper_cmpu(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
207
            else
208
                gen_helper_cmp(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
209
        }
210
    } else {
211
        LOG_DIS("sub%s%s r%d, r%d r%d\n",
212
                 k ? "k" : "",  c ? "c" : "", dc->rd, dc->ra, dc->rb);
213

  
214
        if (!k || c) {
215
            TCGv t;
216
            t = tcg_temp_new();
217
            if (dc->rd)
218
                gen_helper_subkc(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)),
219
                                 tcg_const_tl(k), tcg_const_tl(c));
220
            else
221
                gen_helper_subkc(t, cpu_R[dc->ra], *(dec_alu_op_b(dc)),
222
                                 tcg_const_tl(k), tcg_const_tl(c));
223
            tcg_temp_free(t);
224
        }
225
        else if (dc->rd)
226
            tcg_gen_sub_tl(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
227
    }
228
}
229

  
230
static void dec_pattern(DisasContext *dc)
231
{
232
    unsigned int mode;
233
    int l1;
234

  
235
    mode = dc->opcode & 3;
236
    switch (mode) {
237
        case 0:
238
            /* pcmpbf.  */
239
            LOG_DIS("pcmpbf r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
240
            if (dc->rd)
241
                gen_helper_pcmpbf(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
242
            break;
243
        case 2:
244
            LOG_DIS("pcmpeq r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
245
            if (dc->rd) {
246
                TCGv t0 = tcg_temp_local_new();
247
                l1 = gen_new_label();
248
                tcg_gen_movi_tl(t0, 1);
249
                tcg_gen_brcond_tl(TCG_COND_EQ,
250
                                  cpu_R[dc->ra], cpu_R[dc->rb], l1);
251
                tcg_gen_movi_tl(t0, 0);
252
                gen_set_label(l1);
253
                tcg_gen_mov_tl(cpu_R[dc->rd], t0);
254
                tcg_temp_free(t0);
255
            }
256
            break;
257
        case 3:
258
            LOG_DIS("pcmpne r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
259
            l1 = gen_new_label();
260
            if (dc->rd) {
261
                TCGv t0 = tcg_temp_local_new();
262
                tcg_gen_movi_tl(t0, 1);
263
                tcg_gen_brcond_tl(TCG_COND_NE,
264
                                  cpu_R[dc->ra], cpu_R[dc->rb], l1);
265
                tcg_gen_movi_tl(t0, 0);
266
                gen_set_label(l1);
267
                tcg_gen_mov_tl(cpu_R[dc->rd], t0);
268
                tcg_temp_free(t0);
269
            }
270
            break;
271
        default:
272
            cpu_abort(dc->env,
273
                      "unsupported pattern insn opcode=%x\n", dc->opcode);
274
            break;
275
    }
276
}
277

  
278
static void dec_and(DisasContext *dc)
279
{
280
    unsigned int not;
281

  
282
    if (!dc->type_b && (dc->imm & (1 << 10))) {
283
        dec_pattern(dc);
284
        return;
285
    }
286

  
287
    not = dc->opcode & (1 << 1);
288
    LOG_DIS("and%s\n", not ? "n" : "");
289

  
290
    if (!dc->rd)
291
        return;
292

  
293
    if (not) {
294
        TCGv t = tcg_temp_new();
295
        tcg_gen_not_tl(t, *(dec_alu_op_b(dc)));
296
        tcg_gen_and_tl(cpu_R[dc->rd], cpu_R[dc->ra], t);
297
        tcg_temp_free(t);
298
    } else
299
        tcg_gen_and_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
300
}
301

  
302
static void dec_or(DisasContext *dc)
303
{
304
    if (!dc->type_b && (dc->imm & (1 << 10))) {
305
        dec_pattern(dc);
306
        return;
307
    }
308

  
309
    LOG_DIS("or r%d r%d r%d imm=%x\n", dc->rd, dc->ra, dc->rb, dc->imm);
310
    if (dc->rd)
311
        tcg_gen_or_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
312
}
313

  
314
static void dec_xor(DisasContext *dc)
315
{
316
    if (!dc->type_b && (dc->imm & (1 << 10))) {
317
        dec_pattern(dc);
318
        return;
319
    }
320

  
321
    LOG_DIS("xor r%d\n", dc->rd);
322
    if (dc->rd)
323
        tcg_gen_xor_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
324
}
325

  
326
static void read_carry(DisasContext *dc, TCGv d)
327
{
328
    tcg_gen_shri_tl(d, cpu_SR[SR_MSR], 31);
329
}
330

  
331
static void write_carry(DisasContext *dc, TCGv v)
332
{
333
    TCGv t0 = tcg_temp_new();
334
    tcg_gen_shli_tl(t0, v, 31);
335
    tcg_gen_sari_tl(t0, t0, 31);
336
    tcg_gen_mov_tl(env_debug, t0);
337
    tcg_gen_andi_tl(t0, t0, (MSR_C | MSR_CC));
338
    tcg_gen_andi_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR],
339
                    ~(MSR_C | MSR_CC));
340
    tcg_gen_or_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], t0);
341
    tcg_temp_free(t0);
342
}
343

  
344

  
345
static inline void msr_read(DisasContext *dc, TCGv d)
346
{
347
    tcg_gen_mov_tl(d, cpu_SR[SR_MSR]);
348
}
349

  
350
static inline void msr_write(DisasContext *dc, TCGv v)
351
{
352
    dc->cpustate_changed = 1;
353
    tcg_gen_mov_tl(cpu_SR[SR_MSR], v);
354
    /* PVR, we have a processor version register.  */
355
    tcg_gen_ori_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], (1 << 10));
356
}
357

  
358
static void dec_msr(DisasContext *dc)
359
{
360
    TCGv t0, t1;
361
    unsigned int sr, to, rn;
362

  
363
    sr = dc->imm & ((1 << 14) - 1);
364
    to = dc->imm & (1 << 14);
365
    dc->type_b = 1;
366
    if (to)
367
        dc->cpustate_changed = 1;
368

  
369
    /* msrclr and msrset.  */
370
    if (!(dc->imm & (1 << 15))) {
371
        unsigned int clr = dc->ir & (1 << 16);
372

  
373
        LOG_DIS("msr%s r%d imm=%x\n", clr ? "clr" : "set",
374
                dc->rd, dc->imm);
375
        if (dc->rd)
376
            msr_read(dc, cpu_R[dc->rd]);
377

  
378
        t0 = tcg_temp_new();
379
        t1 = tcg_temp_new();
380
        msr_read(dc, t0);
381
        tcg_gen_mov_tl(t1, *(dec_alu_op_b(dc)));
382

  
383
        if (clr) {
384
            tcg_gen_not_tl(t1, t1);
385
            tcg_gen_and_tl(t0, t0, t1);
386
        } else
387
            tcg_gen_or_tl(t0, t0, t1);
388
        msr_write(dc, t0);
389
        tcg_temp_free(t0);
390
        tcg_temp_free(t1);
391
	tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc + 4);
392
        dc->is_jmp = DISAS_UPDATE;
393
        return;
394
    }
395

  
396
#if !defined(CONFIG_USER_ONLY)
397
    /* Catch read/writes to the mmu block.  */
398
    if ((sr & ~0xff) == 0x1000) {
399
        sr &= 7;
400
        LOG_DIS("m%ss sr%d r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm);
401
        if (to)
402
            gen_helper_mmu_write(tcg_const_tl(sr), cpu_R[dc->ra]);
403
        else
404
            gen_helper_mmu_read(cpu_R[dc->rd], tcg_const_tl(sr));
405
        return;
406
    }
407
#endif
408

  
409
    if (to) {
410
        LOG_DIS("m%ss sr%x r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm);
411
        switch (sr) {
412
            case 0:
413
                break;
414
            case 1:
415
                msr_write(dc, cpu_R[dc->ra]);
416
                break;
417
            case 0x3:
418
                tcg_gen_mov_tl(cpu_SR[SR_EAR], cpu_R[dc->ra]);
419
                break;
420
            case 0x5:
421
                tcg_gen_mov_tl(cpu_SR[SR_ESR], cpu_R[dc->ra]);
422
                break;
423
            case 0x7:
424
                /* Ignored at the moment.  */
425
                break;
426
            default:
427
                cpu_abort(dc->env, "unknown mts reg %x\n", sr);
428
                break;
429
        }
430
    } else {
431
        LOG_DIS("m%ss r%d sr%x imm=%x\n", to ? "t" : "f", dc->rd, sr, dc->imm);
432

  
433
        switch (sr) {
434
            case 0:
435
                tcg_gen_movi_tl(cpu_R[dc->rd], dc->pc);
436
                break;
437
            case 1:
438
                msr_read(dc, cpu_R[dc->rd]);
439
                break;
440
            case 0x3:
441
                tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_EAR]);
442
                break;
443
            case 0x5:
444
                tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_ESR]);
445
                break;
446
             case 0x7:
447
                tcg_gen_movi_tl(cpu_R[dc->rd], 0);
448
                break;
449
            case 0xb:
450
                tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_BTR]);
451
                break;
452
            case 0x2000:
453
            case 0x2001:
454
            case 0x2002:
455
            case 0x2003:
456
            case 0x2004:
457
            case 0x2005:
458
            case 0x2006:
459
            case 0x2007:
460
            case 0x2008:
461
            case 0x2009:
462
            case 0x200a:
463
            case 0x200b:
464
            case 0x200c:
465
                rn = sr & 0xf;
466
                tcg_gen_ld_tl(cpu_R[dc->rd],
467
                              cpu_env, offsetof(CPUState, pvr.regs[rn]));
468
                break;
469
            default:
470
                cpu_abort(dc->env, "unknown mfs reg %x\n", sr);
471
                break;
472
        }
473
    }
474
}
475

  
476
/* 64-bit signed mul, lower result in d and upper in d2.  */
477
static void t_gen_muls(TCGv d, TCGv d2, TCGv a, TCGv b)
478
{
479
    TCGv_i64 t0, t1;
480

  
481
    t0 = tcg_temp_new_i64();
482
    t1 = tcg_temp_new_i64();
483

  
484
    tcg_gen_ext_i32_i64(t0, a);
485
    tcg_gen_ext_i32_i64(t1, b);
486
    tcg_gen_mul_i64(t0, t0, t1);
487

  
488
    tcg_gen_trunc_i64_i32(d, t0);
489
    tcg_gen_shri_i64(t0, t0, 32);
490
    tcg_gen_trunc_i64_i32(d2, t0);
491

  
492
    tcg_temp_free_i64(t0);
493
    tcg_temp_free_i64(t1);
494
}
495

  
496
/* 64-bit unsigned muls, lower result in d and upper in d2.  */
497
static void t_gen_mulu(TCGv d, TCGv d2, TCGv a, TCGv b)
498
{
499
    TCGv_i64 t0, t1;
500

  
501
    t0 = tcg_temp_new_i64();
502
    t1 = tcg_temp_new_i64();
503

  
504
    tcg_gen_extu_i32_i64(t0, a);
505
    tcg_gen_extu_i32_i64(t1, b);
506
    tcg_gen_mul_i64(t0, t0, t1);
507

  
508
    tcg_gen_trunc_i64_i32(d, t0);
509
    tcg_gen_shri_i64(t0, t0, 32);
510
    tcg_gen_trunc_i64_i32(d2, t0);
511

  
512
    tcg_temp_free_i64(t0);
513
    tcg_temp_free_i64(t1);
514
}
515

  
516
/* Multiplier unit.  */
517
static void dec_mul(DisasContext *dc)
518
{
519
    TCGv d[2];
520
    unsigned int subcode;
521

  
522
    subcode = dc->imm & 3;
523
    d[0] = tcg_temp_new();
524
    d[1] = tcg_temp_new();
525

  
526
    if (dc->type_b) {
527
        LOG_DIS("muli r%d r%d %x\n", dc->rd, dc->ra, dc->imm);
528
        t_gen_mulu(cpu_R[dc->rd], d[1], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
529
        goto done;
530
    }
531

  
532
    switch (subcode) {
533
        case 0:
534
            LOG_DIS("mul r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
535
            t_gen_mulu(cpu_R[dc->rd], d[1], cpu_R[dc->ra], cpu_R[dc->rb]);
536
            break;
537
        case 1:
538
            LOG_DIS("mulh r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
539
            t_gen_muls(d[0], cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
540
            break;
541
        case 2:
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff