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