fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/cpu/ppc405/internal.h *
7 * Created: 2003-11-07 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2003-2018 Hampa Hug <hampa@hampa.ch> *
9 * Copyright: (C) 2003-2006 Lukas Ruf <ruf@lpr.ch> *
10 *****************************************************************************/
11
12/*****************************************************************************
13 * This program is free software. You can redistribute it and / or modify it *
14 * under the terms of the GNU General Public License version 2 as published *
15 * by the Free Software Foundation. *
16 * *
17 * This program is distributed in the hope that it will be useful, but *
18 * WITHOUT ANY WARRANTY, without even the implied warranty of *
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
20 * Public License for more details. *
21 *****************************************************************************/
22
23/*****************************************************************************
24 * This software was developed at the Computer Engineering and Networks *
25 * Laboratory (TIK), Swiss Federal Institute of Technology (ETH) Zurich. *
26 *****************************************************************************/
27
28
29#ifndef PPC405_INTERNAL_H
30#define PPC405_INTERNAL_H
31
32
33#include <stdlib.h>
34#include <stdio.h>
35
36
37/*****************************************************************************
38 * MMU
39 *****************************************************************************/
40
41void p405_tlb_init (p405_tlb_t *tlb);
42
43void p405_tbuf_clear (p405_t *c);
44
45void p405_set_tlb_entry_hi (p405_t *c, unsigned idx, uint32_t tlbhi, uint8_t pid);
46void p405_set_tlb_entry_lo (p405_t *c, unsigned idx, uint32_t tlblo);
47
48uint32_t p405_get_tlb_entry_hi (p405_t *c, unsigned idx);
49uint32_t p405_get_tlb_entry_lo (p405_t *c, unsigned idx);
50uint32_t p405_get_tlb_entry_tid (p405_t *c, unsigned idx);
51
52void p405_tlb_invalidate_all (p405_t *c);
53
54int p405_ifetch (p405_t *c, uint32_t addr, uint32_t *val);
55
56int p405_dload8 (p405_t *c, uint32_t addr, uint8_t *val);
57int p405_dload16 (p405_t *c, uint32_t addr, uint16_t *val);
58int p405_dload32 (p405_t *c, uint32_t addr, uint32_t *val);
59
60int p405_dstore8 (p405_t *c, uint32_t addr, uint8_t val);
61int p405_dstore16 (p405_t *c, uint32_t addr, uint16_t val);
62int p405_dstore32 (p405_t *c, uint32_t addr, uint32_t val);
63
64
65/*****************************************************************************
66 * PPC
67 *****************************************************************************/
68
69#define P405_PVR_405GP 0x40110000
70#define P405_PVR_405GP_A 0x40110000
71#define P405_PVR_405GP_B 0x40110040
72#define P405_PVR_405GP_C 0x40110082
73#define P405_PVR_405GP_D 0x401100c4
74#define P405_PVR_NPE405H 0x41410140UL
75#define P405_PVR_NPE405L 0x416100c0UL
76
77#define P405_CACHE_LINE_SIZE 32
78
79#define P405_IR_OE 0x0400
80#define P405_IR_RC 0x0001
81#define P405_IR_LK 0x0001
82#define P405_IR_AA 0x0002
83
84#define P405_INT_EXT 1
85#define P405_INT_PIT 2
86#define P405_INT_FIT 4
87
88#define P405_EXCPT_MSR (P405_MSR_AP | P405_MSR_APE | P405_MSR_WE | P405_MSR_EE |\
89 P405_MSR_PR | P405_MSR_FP | P405_MSR_FE0 | P405_MSR_DWE | P405_MSR_FE1 |\
90 P405_MSR_IR | P405_MSR_DR)
91
92#define p405_sext(x, n) ( \
93 ((x) & (1UL << ((n) - 1))) ? \
94 (((x) | ~((1UL << (n)) - 1)) & 0xffffffffUL) : \
95 ((x) & ((1UL << (n)) - 1)) \
96 )
97
98#define p405_uext(x, n) ((x) & ((1 << (n)) - 1))
99
100#define p405_bits(val, i, n) (((val) >> (32 - (i) - (n))) & ((1UL << (n)) - 1))
101
102#define p405_get_ir_rc(ir) (((ir) & P405_IR_RC) != 0)
103#define p405_get_ir_oe(ir) (((ir) & P405_IR_OE) != 0)
104#define p405_get_ir_lk(ir) (((ir) & P405_IR_LK) != 0)
105#define p405_get_ir_aa(ir) (((ir) & P405_IR_AA) != 0)
106
107#define p405_get_ir_ra(ir) (((ir) >> 16) & 0x1f)
108#define p405_get_ir_rb(ir) (((ir) >> 11) & 0x1f)
109#define p405_get_ir_rs(ir) (((ir) >> 21) & 0x1f)
110#define p405_get_ir_rt(ir) (((ir) >> 21) & 0x1f)
111
112#define p405_get_ra(c, ir) ((c)->gpr[p405_get_ir_ra (ir)])
113#define p405_get_rb(c, ir) ((c)->gpr[p405_get_ir_rb (ir)])
114#define p405_get_rs(c, ir) ((c)->gpr[p405_get_ir_rs (ir)])
115#define p405_get_rt(c, ir) ((c)->gpr[p405_get_ir_rt (ir)])
116#define p405_get_ra0(c, ir) (((ir) & 0x1f0000) ? p405_get_ra (c, ir) : 0)
117
118#define p405_set_ra(c, ir, val) do { (c)->gpr[p405_get_ir_ra (ir)] = (val); } while (0)
119#define p405_set_rb(c, ir, val) do { (c)->gpr[p405_get_ir_rb (ir)] = (val); } while (0)
120#define p405_set_rs(c, ir, val) do { (c)->gpr[p405_get_ir_rs (ir)] = (val); } while (0)
121#define p405_set_rt(c, ir, val) do { (c)->gpr[p405_get_ir_rt (ir)] = (val); } while (0)
122
123#define p405_get_simm16(ir) (((ir) & 0x8000) ? ((ir) | 0xffff0000) : ((ir) & 0xffff))
124#define p405_get_uimm16(ir) ((ir) & 0xffff)
125
126#define p405_set_clk(c, dpc, clk) do { (c)->pc += (dpc); (c)->delay += (clk); } while (0)
127
128
129typedef struct {
130 unsigned op;
131 p405_opcode_f fct;
132} p405_opcode_list_t;
133
134
135uint64_t p405_mul (uint32_t s1, uint32_t s2);
136uint16_t p405_br16 (uint16_t x);
137uint32_t p405_br32 (uint32_t x);
138
139void p405_op_branch (p405_t *c, uint32_t dst, unsigned bo, unsigned bi, int aa, int lk);
140void p405_op_crop (p405_t *c, unsigned bt, unsigned ba, unsigned bb, unsigned booltab);
141void p405_op_lsw (p405_t *c, unsigned rt, unsigned ra, unsigned rb, uint32_t ea, unsigned cnt);
142void p405_op_stsw (p405_t *c, unsigned rs, uint32_t ea, unsigned cnt);
143void p405_op_undefined (p405_t *c);
144
145void p405_exception_data_store (p405_t *c, uint32_t ea, int store, int zone);
146void p405_exception_instr_store (p405_t *c, int zone);
147void p405_exception_external (p405_t *c);
148void p405_exception_program (p405_t *c, uint32_t esr);
149void p405_exception_program_fpu (p405_t *c);
150void p405_exception_syscall (p405_t *c);
151void p405_exception_pit (p405_t *c);
152void p405_exception_fit (p405_t *c);
153void p405_exception_tlb_miss_data (p405_t *c, uint32_t ea, int store);
154void p405_exception_tlb_miss_instr (p405_t *c);
155
156void p405_set_opcode13 (p405_t *c);
157void p405_set_opcode1f (p405_t *c);
158void p405_set_opcodes (p405_t *c);
159
160
161static inline
162int p405_check_reserved (p405_t *c, uint32_t res)
163{
164 if (c->ir & res) {
165 p405_op_undefined (c);
166 return (1);
167 }
168
169 return (0);
170}
171
172static inline
173int p405_check_privilege (p405_t *c)
174{
175 if (p405_get_msr_pr (c)) {
176 p405_exception_program (c, P405_ESR_PPR);
177 return (1);
178 }
179
180 return (0);
181}
182
183static inline
184void p405_set_xer_oflow (p405_t *c, int of)
185{
186 if (of) {
187 c->xer |= (P405_XER_SO | P405_XER_OV);
188 }
189 else {
190 c->xer &= ~P405_XER_OV;
191 }
192}
193
194static inline
195void p405_set_cr0 (p405_t *c, uint32_t r)
196{
197 c->cr &= 0x0fffffff;
198
199 if (r & 0x80000000) {
200 c->cr |= P405_CR0_LT;
201 }
202 else if (r & 0x7fffffff) {
203 c->cr |= P405_CR0_GT;
204 }
205 else {
206 c->cr |= P405_CR0_EQ;
207 }
208
209 if (c->xer & P405_XER_SO) {
210 c->cr |= P405_CR0_SO;
211 }
212}
213
214static inline
215int p405_get_ea (p405_t *c, uint32_t *val, int idx, int upd)
216{
217 if (upd) {
218 if (p405_get_ir_ra (c->ir) == 0) {
219 p405_op_undefined (c);
220 return (1);
221 }
222 }
223
224 if (idx) {
225 *val = p405_get_ra0 (c, c->ir) + p405_get_rb (c, c->ir);
226 }
227 else {
228 *val = p405_get_ra0 (c, c->ir) + p405_get_simm16 (c->ir);
229 }
230
231 *val &= 0xffffffff;
232
233 return (0);
234}
235
236
237#endif