|
|
nono 1.7.0
//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//
#include "mpu680x0.h"
#define M680X0_CYCLE_TABLE
#include "m680x0cycle.h"
class MPU680x0Test : public MPU680x0Device
{
public:
MPU680x0Test() {
cycle_table = cycle_table_030cc;
}
~MPU680x0Test() override { }
void test_ea_ix();
void test_ea_ix2();
uint32 fetch_2() override;
uint32 fetch_4() override;
uint32 read_data(busaddr addr) override;
void write_data(busaddr addr, uint32 data) override;
busaddr TranslatePeek(busaddr) override { return busaddr(0); }
void CalcStat() override { }
bool ops_movec_rc_rn_cpu(uint, uint) override { return true; }
bool ops_movec_rn_rc_cpu(uint, uint) override { return true; }
void ops_mmu30() override { }
void ops_mmu40_pflush() override { }
void ResetMMU() override { }
void ResetCache() override { }
void SetCACR(uint32) override { }
};
static uint16 g_fetch[5];
static int g_fetch_ptr;
// ダミーのフェッチルーチン
// グローバル変数 g_fetch[] で指定された値を順に返す
uint32
MPU680x0Test::fetch_2()
{
uint16 data;
if (g_fetch_ptr >= countof(g_fetch)) {
abort();
}
data = g_fetch[g_fetch_ptr++];
return data;
}
uint32
MPU680x0Test::fetch_4()
{
uint32 data;
data = fetch_2() << 16;
data |= fetch_2();
return data;
}
// ダミーリード
// アドレスを2倍にして返す。
// メモリ間接の post index、pre index を演算だけで判別するため。
uint32
MPU680x0Test::read_data(busaddr laddr)
{
if (laddr.GetSize() == 4) {
return laddr.Addr() << 1;
}
return 0;
}
void
MPU680x0Test::write_data(busaddr laddr, uint32 data)
{
}
// リンクを通すためのダミー。
Object::Object(uint) { }
Object::~Object() { }
Device::Device(uint) : inherited(0) { }
Device::~Device() { }
MPUDevice::MPUDevice(uint) : inherited(0) { }
MPUDevice::~MPUDevice() { }
MainMPUDevice::MainMPUDevice() : inherited(0) { }
MainMPUDevice::~MainMPUDevice() { }
MPU680x0Device::MPU680x0Device() { }
MPU680x0Device::~MPU680x0Device() { }
BranchHistory::BranchHistory(uint) : inherited(0) { }
BranchHistory::~BranchHistory() { }
BranchHistory_m680x0::BranchHistory_m680x0(uint) : inherited(0) { }
BranchHistory_m680x0::~BranchHistory_m680x0() { }
void Object::SetLogLevel(int) { }
void Object::putlogn(const char *, ...) const { }
void Device::putlogn(const char *, ...) const { }
bool Device::Create() { return true; }
bool Device::Create2() { return true; }
bool Device::Init() { return true; }
void Device::ResetHard(bool) { }
void Device::PowerOff() { }
bool MPUDevice::Init() { return true; }
void MPUDevice::ResetHard(bool) { }
void MPUDevice::PowerOff() { }
bool MainMPUDevice::Init() { return true; }
bool MPU680x0Device::Init() { return true; }
void MPU680x0Device::ResetHard(bool) { }
void MPU680x0Device::Interrupt(int) { }
void MPU680x0Device::SetTrace(bool) { }
std::string BranchHistory::FormatHeader() const { return ""; }
std::string BranchHistory::FormatEntry(const BranchEntry&) { return ""; }
std::string BranchHistory_m680x0::FormatEntry(const BranchEntry&) { return ""; }
void
panic_func(const char *func, const char *fmt, ...)
{
va_list ap;
printf("panic: %s:", func);
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
abort();
}
static MPU680x0Test *cpu;
static int tested;
static int failed;
// 拡張 EA の全組み合わせを試す網羅テスト
void
MPU680x0Test::test_ea_ix()
{
uint32 ea;
struct {
uint16 ext; // 拡張ワード
int exp_pc; // 何ワード読まれるべきかの期待値1(extを含む)
uint32 exp_ea; // 期待値
const char *name;
} table[] = {
#if 1
#include "testea.h"
#endif
};
uint32 An = 0x00010000;
cpu->reg.D[1] = 0x00100010;
for (int i = 0; i < countof(table); i++) {
g_fetch_ptr = 0;
g_fetch[g_fetch_ptr++] = table[i].ext;
// bd
switch ((table[i].ext >> 4) & 3) {
case 0:
case 1:
break;
case 2:
g_fetch[g_fetch_ptr++] = 0x0100;
break;
case 3:
g_fetch[g_fetch_ptr++] = 0x0100;
g_fetch[g_fetch_ptr++] = 0x0200;
break;
}
// od
switch (table[i].ext & 3) {
case 0:
case 1:
break;
case 2:
g_fetch[g_fetch_ptr++] = 0x1000;
break;
case 3:
g_fetch[g_fetch_ptr++] = 0x1000;
g_fetch[g_fetch_ptr++] = 0x2000;
break;
}
g_fetch_ptr = 0;
tested++;
printf("test_ea_ix[0x%04x] %-20s ", table[i].ext, table[i].name);
ea = internal_ea_ix(An);
if (table[i].exp_pc != g_fetch_ptr) {
printf("FAILED! pc expects %d but %d\n",
table[i].exp_pc, g_fetch_ptr);
failed++;
continue;
}
if (table[i].exp_ea != ea) {
printf("FAILED! ea expects %x but %x\n",
table[i].exp_ea, ea);
printf(" 0x%04x .. WL=%d SC=%d BS=%d IS=%d BDSZ=%d IIS=%d\n",
table[i].ext,
(table[i].ext >> 11) & 1,
(table[i].ext >> 9) & 3,
(table[i].ext >> 7) & 1,
(table[i].ext >> 6) & 1,
(table[i].ext >> 4) & 3,
(table[i].ext ) & 7);
failed++;
continue;
}
printf("ok\n");
}
}
static const char *scalestr[] = {
"", "*2", "*4", "*8"
};
// 拡張 EA Full format の指定パターンのテストを生成する。
static void
make_ea_ix_full(int wl, int scale, int bs, int is, int bdsz, int iis)
{
uint32 data;
uint32 an = 0x00010000;
uint32 xn = 0;
uint32 bd = 0;
uint32 od = 0;
int cnt = 1;
if (bs) {
an = 0;
}
if (!is) {
xn = 0x00100010;
if (wl == 0) xn &= 0xffff;
xn <<= scale;
}
if (bdsz == 2) {
bd = 0x00000100; cnt+=1;
} else if (bdsz == 3) {
bd = 0x01000200; cnt+=2;
}
switch (iis & 3) {
case 2:
od = 0x00001000; cnt += 1; break;
case 3:
od = 0x10002000; cnt += 2; break;
}
data = 0;
if (is == 0) {
switch (iis) {
case 0: data = an + bd + xn; break;
case 1:
case 2:
case 3:
data = ((an + bd + xn) << 1) + od; break;
case 4:
return;
case 5:
case 6:
case 7:
data = ((an + bd) << 1) + xn + od; break;
}
} else {
switch (iis) {
case 0: data = an + bd; break;
case 1:
case 2:
case 3:
data = ((an + bd) << 1) + od; break;
default:
return;
}
}
printf("\t\t{ 0x%04x, %d, 0x%08x, \"(",
(0x1100 + (wl<<11) + (scale<<9) + (bs<<7) + (is << 6) + (bdsz<<4)+ iis),
cnt,
data);
char anbuf[16];
char xnbuf[16];
char bdbuf[16];
char odbuf[16];
anbuf[0] = '\0';
xnbuf[0] = '\0';
bdbuf[0] = '\0';
odbuf[0] = '\0';
if (bdsz == 2)
snprintf(bdbuf, sizeof(bdbuf), "bd.W");
else if (bdsz == 3)
snprintf(bdbuf, sizeof(bdbuf), "bd.L");
if (bs == 0)
snprintf(anbuf, sizeof(anbuf), "An");
if (is == 0) {
snprintf(xnbuf, sizeof(xnbuf),
"Xn.%c%s", (wl?'L':'W'), scalestr[scale]);
}
if ((iis & 3) == 2)
snprintf(odbuf, sizeof(odbuf), "od.W");
else if ((iis & 3) == 3)
snprintf(odbuf, sizeof(odbuf), "od.L");
if (is == 0) {
switch (iis) {
case 0: printf("%s,%s,%s", anbuf, bdbuf, xnbuf); break;
case 1: printf("[%s,%s,%s]", anbuf, bdbuf, xnbuf); break;
case 2: printf("[%s,%s,%s],od.W", anbuf, bdbuf, xnbuf); break;
case 3: printf("[%s,%s,%s],od.L", anbuf, bdbuf, xnbuf); break;
case 4: printf("reserved"); break;
case 5: printf("[%s,%s],%s", anbuf, bdbuf, xnbuf); break;
case 6: printf("[%s,%s],%s,od.W", anbuf, bdbuf, xnbuf); break;
case 7: printf("[%s,%s],%s,od.L", anbuf, bdbuf, xnbuf); break;
}
} else {
switch (iis) {
case 0: printf("%s,%s", anbuf, bdbuf); break;
case 1: printf("[%s,%s]", anbuf, bdbuf); break;
case 2: printf("[%s,%s],od.W", anbuf, bdbuf); break;
case 3: printf("[%s,%s],od.L", anbuf, bdbuf); break;
default: printf("reserved"); break;
}
}
printf(")\" },\n");
}
// 拡張 EA 全パターンのテストを生成する。
static void
make_ea_ix()
{
// Brief format
for (int wl = 0; wl <= 1; wl++) {
for (int scale=0; scale <= 3; scale++) {
uint32 an = 0x00010000;
uint32 d8 = 1;
uint32 data;
uint32 xn;
xn = 0x00100010;
if (wl == 0) xn &= 0xffff;
xn <<= scale;
data = an + xn + d8;
printf("\t\t{ 0x%04x, 1, 0x%08x, \"d8(An,D1.%c%s)\" },\n",
0x1000 + (wl << 11) + (scale << 9) + d8,
data,
wl ? 'L' : 'W',
scalestr[scale]);
}
}
// Full format
for (int wl=0; wl<= 1; wl++) {
for (int scale=0; scale<=3; scale++) {
for (int bs = 0; bs <= 1; bs++) {
for (int is = 0; is <= 1; is++) {
for (int bdsz = 1; bdsz <= 3; bdsz++) {
for (int iis = 0; iis < 8; iis++) {
make_ea_ix_full(wl, scale, bs, is, bdsz, iis);
}
}
}
}
}
}
}
// 符号拡張のテスト。
// 符号拡張が起きるのは xn.W, bd.W, od.W の3か所。
void
MPU680x0Test::test_ea_ix2()
{
struct {
uint16 ext; // 拡張ワード
uint32 exp_ea; // 期待値
const char *name;
} table[] = {
{ 0x1122, 0x00020000, "([An,bd.W,Xn.W],od.W)" },
{ 0x1126, 0x00020010, "([An,bd.W],Xn.W,od.W)" },
{ 0x1162, 0x00020020, "([An,bd.W],od.W)" },
};
uint32 An = 0x00011110;
cpu->reg.D[1] = 0x0000fff0; // -0x0010.W
for (int i = 0; i < countof(table); i++) {
g_fetch[0] = table[i].ext;
g_fetch[1] = 0xff00; // -0x0100.W
g_fetch[2] = 0xe000; // -0x2000.W
g_fetch_ptr = 0;
tested++;
printf("test_ea_ix2[0x%04x] %-20s ", table[i].ext, table[i].name);
uint32 ea = internal_ea_ix(An);
if (table[i].exp_ea != ea) {
printf("FAILED! ea expects %08x but %08x\n",
table[i].exp_ea, ea);
printf(" 0x%04x .. WL=%d SC=%d BS=%d IS=%d BDSZ=%d IIS=%d\n",
table[i].ext,
(table[i].ext >> 11) & 1,
(table[i].ext >> 9) & 3,
(table[i].ext >> 7) & 1,
(table[i].ext >> 6) & 1,
(table[i].ext >> 4) & 3,
(table[i].ext ) & 7);
failed++;
continue;
}
printf("ok\n");
}
}
int
main(int ac, char *av[])
{
cpu = new MPU680x0Test();
// 引数が何かあればテストパターン生成、なければテスト。
// XXX そのうち整備する。
if (ac > 1) {
make_ea_ix();
} else {
tested = 0;
failed = 0;
cpu->test_ea_ix();
cpu->test_ea_ix2();
printf("RESULT: %d tested, %d success", tested, tested - failed);
if (failed > 0)
printf(", %d failed", failed);
printf("\n");
}
return 0;
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.