|
|
nono 0.3.0
//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//
#pragma once
#include "m68030.h"
#include "m68030excep.h"
#include "mpu.h"
// XXX ?
#define CCR (cpu->reg.ccr)
#define RegIsS (cpu->reg.s)
extern void m68030_restore_reg_pi(m68kcpu *);
extern void m68030_restore_reg_pd(m68kcpu *);
extern void m68030_set_sr(m68kcpu *, uint16);
extern void m68030_exception(m68kcpu *, int);
extern void m68030_exception_buserr(m68kcpu *, int);
extern void m68030_rte(m68kcpu *);
extern void m68030_stop(m68kcpu *);
// 文字列を作る前にレベルを評価するためマクロ
#define cpulog(lv, fmt...) do { \
if (__predict_false(gMPU->loglevel >= (lv))) { \
gMPU->putlogn(fmt); \
} \
} while (0)
#define cpulogf(lv, msgf) do { \
gMPU->putlogf(lv, msgf); \
} while (0)
// ops 用のマクロとか
static inline void
m68k_add_cycle(m68kcpu *cpu, int cc)
{
cpu->used_cycle += cc;
}
static inline void
m68k_add_cycle_nc(m68kcpu *cpu, int cc, int ncc)
{
cpu->used_cycle += cc;
cpu->cycle_nocache += ncc - cc;
}
// サイクルを加算する。
// キャッシュケース、ノーキャッシュケースで同じ場合用。
#define CYCLE(cc) m68k_add_cycle(cpu, (cc))
// サイクルを加算する。
// cc はキャッシュケース、ncc はノーキャッシュケースのサイクル。
// ncc は cc からの差分ではなく、ノーキャッシュケースの時のサイクル数
// そのものを指定する。(内部で差分をとっている)
#define CYCLE2(cc, ncc) m68k_add_cycle_nc(cpu, (cc), (ncc))
// アドレスエラーチェック
// (jump() と jump_vector() の2か所で必要なため)
#define CHECK_ADDRESS_ERROR(addr) do { \
if (__predict_false(((addr) & 1) != 0)) { \
m68030_exception(cpu, M68K_EXCEP_ADDRERR); \
return; \
} \
} while (0)
// PC を addr に変更する。
// addr がメモリからの入力の場合アドレスエラーのチェックが必要なため。
// ベクタへのジャンプはここではなく subr.cpp::m68030_jump_vector()。
static inline void
m68030_jump(m68kcpu *cpu, uint32 addr)
{
CHECK_ADDRESS_ERROR(addr);
RegPC = addr;
// ブランチ履歴
cpu->brhist.AddEntry(RegPPC | (cpu->reg.s ? 1 : 0), addr, cpu->ir << 16);
}
// -(An) 実行前にレジスタを保存する。
// バスエラーからの復帰用。
static inline void
m68030_save_reg_pd(m68kcpu *cpu, int n)
{
// 該当ビットのフラグを立てる
cpu->flag_pd |= (1 << n);
// 保存
cpu->save_pd[n] = RegA(n);
}
// (An)+ 実行前にレジスタを保存する。
// バスエラーからの復帰用。
static inline void
m68030_save_reg_pi(m68kcpu *cpu, int n)
{
// 該当ビットのフラグを立てる
cpu->flag_pi |= (1 << n);
// 保存
cpu->save_pi[n] = RegA(n);
}
// cond で示される条件が成立すれば true を返す。
static inline bool
cond_func(m68kcpu *cpu, int cond)
{
switch (cond) {
case 0: // T
return RegCondT;
case 1: // F
return RegCondF;
case 2:
return RegCondHI;
case 3:
return RegCondLS;
case 4:
return RegCondCC;
case 5:
return RegCondCS;
case 6:
return RegCondNE;
case 7:
return RegCondEQ;
case 8:
return RegCondVC;
case 9:
return RegCondVS;
case 10:
return RegCondPL;
case 11:
return RegCondMI;
case 12:
return RegCondGE;
case 13:
return RegCondLT;
case 14:
return RegCondGT;
case 15:
return RegCondLE;
}
__unreachable();
}
// 副作用のあるマクロ
// 特権違反例外のスタックに積む PC は違反を起こした命令先頭。
#define SUPERVISOR_OP do { \
if (!RegIsS) { \
CYCLE2(18, 20); \
m68030_exception(cpu, M68K_EXCEP_PRIV); \
return; \
} \
} while (0)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.