|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2017 [email protected]
4: //
5:
6: #pragma once
7:
8: #include "m68030.h"
9: #include "m68030excep.h"
10: #include "mpu.h"
11:
12: // XXX ?
13: #define CCR (cpu->reg.ccr)
14:
15: #define RegIsS (cpu->reg.s)
16:
17: extern void m68030_restore_reg_pi(m68kcpu *);
18: extern void m68030_restore_reg_pd(m68kcpu *);
19: extern void m68030_set_sr(m68kcpu *, uint16);
20: extern void m68030_exception(m68kcpu *, int);
21: extern void m68030_exception_reset(m68kcpu *);
22: extern void m68030_exception_interrupt(m68kcpu *, int, int);
23: extern void m68030_rte(m68kcpu *);
24: extern const char *m68030_get_exception_name(int);
25:
26: static inline void cpulog(int lv, const char *fmt, ...) __printflike(2, 3);
27: static inline void
28: cpulog(int lv, const char *fmt, ...)
29: {
30: if (__predict_false(gMPU->loglevel >= lv)) {
31: va_list ap;
32: va_start(ap, fmt);
33: gMPU->vputlog(fmt, ap);
34: va_end(ap);
35: }
36: }
37:
38: // ops 用のマクロとか
39:
40: static inline void
41: m68k_add_cycle(m68kcpu *cpu, int cc)
42: {
43: cpu->cycle_cache += cc;
44: }
45:
46: static inline void
47: m68k_add_cycle_nc(m68kcpu *cpu, int cc, int ncc)
48: {
49: cpu->cycle_cache += cc;
50: cpu->cycle_nocache += ncc - cc;
51: }
52:
53: // サイクルを加算する。
54: // キャッシュケース、ノーキャッシュケースで同じ場合用。
55: #define CYCLE(cc) m68k_add_cycle(cpu, (cc))
56:
57: // サイクルを加算する。
58: // cc はキャッシュケース、ncc はノーキャッシュケースのサイクル。
59: // ncc は cc からの差分ではなく、ノーキャッシュケースの時のサイクル数
60: // そのものを指定する。(内部で差分をとっている)
61: #define CYCLE2(cc, ncc) m68k_add_cycle_nc(cpu, (cc), (ncc));
62:
63: // PC を addr に変更する。
64: // addr がメモリからの入力の場合アドレスエラーのチェックが必要なため。
65: static inline void
66: m68030_jump(m68kcpu *cpu, uint32 addr)
67: {
68: // アドレスエラーチェック
69: if (__predict_false((addr & 1) != 0)) {
70: m68030_exception(cpu, M68K_EXCEP_ADDRERR);
71: return;
72: }
73:
74: RegPC = addr;
75:
76: // ブランチ履歴
77: m68kbrhist *h = &cpu->brhist[cpu->brhist_top];
78: //printf("jump PPC=%x addr=%x h.from=%x to=%x", RegPPC, addr, h->from, h->to);
79: if (h->from == RegPPC && h->to == addr) {
80: // 前回と同じなら通過回数++
81: h->count++;
82: //printf(" ++\n");
83: } else {
84: // そうでなければ、新規エントリ
85: cpu->brhist_top++;
86: //printf(" [%d]\n", cpu->brhist_top);
87: h = &cpu->brhist[cpu->brhist_top];
88: h->from = RegPPC;
89: h->to = addr;
90: h->count = 1;
91: }
92: }
93:
94: // -(An) 実行前にレジスタを保存する。
95: // バスエラーからの復帰用。
96: static inline void
97: m68030_save_reg_pd(m68kcpu *cpu, int n)
98: {
99: // 該当ビットのフラグを立てる
100: cpu->flag_pd |= (1 << n);
101:
102: // 保存
103: cpu->save_pd[n] = RegA(n);
104: }
105:
106: // (An)+ 実行前にレジスタを保存する。
107: // バスエラーからの復帰用。
108: static inline void
109: m68030_save_reg_pi(m68kcpu *cpu, int n)
110: {
111: // 該当ビットのフラグを立てる
112: cpu->flag_pi |= (1 << n);
113:
114: // 保存
115: cpu->save_pi[n] = RegA(n);
116: }
117:
118: // cond で示される条件が成立すれば true を返す。
119: static inline bool
120: cond_func(m68kcpu *cpu, int cond)
121: {
122: switch (cond) {
123: case 0: // T
124: return RegCondT;
125: case 1: // F
126: return RegCondF;
127: case 2:
128: return RegCondHI;
129: case 3:
130: return RegCondLS;
131: case 4:
132: return RegCondCC;
133: case 5:
134: return RegCondCS;
135: case 6:
136: return RegCondNE;
137: case 7:
138: return RegCondEQ;
139: case 8:
140: return RegCondVC;
141: case 9:
142: return RegCondVS;
143: case 10:
144: return RegCondPL;
145: case 11:
146: return RegCondMI;
147: case 12:
148: return RegCondGE;
149: case 13:
150: return RegCondLT;
151: case 14:
152: return RegCondGT;
153: case 15:
154: return RegCondLE;
155: }
156: __unreachable();
157: }
158:
159:
160: // 副作用のあるマクロ
161: // 特権違反例外のスタックに積む PC は違反を起こした命令先頭。
162: #define SUPERVISOR_OP \
163: if (!RegIsS) { \
164: CYCLE2(18, 20); \
165: m68030_exception(cpu, M68K_EXCEP_PRIV); \
166: return; \
167: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.