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