|
|
nono 0.0.1
//
// nono
// Copyright (C) 2017 [email protected]
//
#include "header.h"
#include "m68030.h"
#include "disasm.h"
#include "bus.h"
#include "mystring.h"
// コンストラクタ
Disasm::Disasm()
{
init();
}
// デストラクタ
Disasm::~Disasm()
{
}
// 逆アセンブル
std::string
Disasm::Disassemble(uint32 laddr, uint32 paddr)
{
init();
pc = laddr;
pc0 = pc;
phys_pc = paddr;
switch (fetch16() >> 6) {
#include "m68030switch.h"
default:
__unreachable();
}
std::string s = name + size_str[size];
if (!src.empty() || !dst.empty()) {
// オペランドが片方でもあればインデントする
int sl = s.length();
if (sl < 8) {
s += std::string(8 - sl, ' ');
} else {
s += ' ';
}
// src があれば src を追加
if (!src.empty()) {
s += src;
}
// 両方あればカンマで区切る
if (!src.empty() && !dst.empty()) {
s += ",";
}
// dst があれば dst を追加
if (!dst.empty()) {
s += dst;
}
}
return s;
}
// 逆アセンブル + ダンプ
std::string
Disasm::DisassembleWithDump(uint32 laddr, uint32 paddr)
{
// 逆アセンブル
std::string s = Disassemble(laddr, paddr);
// ダンプ
std::string dump;
for (const auto & i : ir) {
dump += string_format("%04x ", i);
}
if (ir.size() < 5) {
dump += std::string(25 - ir.size() * 5, ' ');
}
return dump + s;
}
// 1行逆アセンブル前の初期化
void
Disasm::init()
{
ir.clear();
name.clear();
size = Size::None;
src.clear();
dst.clear();
}
// ワードピーク (PCを進めずワードを取得する)
uint32
Disasm::peek16()
{
// 物理空間から読み込む
uint16 data;
data = m68030_phys_peek_8(phys_pc) << 8;
data |= m68030_phys_peek_8(phys_pc + 1);
return data;
}
// ワードフェッチ
uint32
Disasm::fetch16()
{
uint16 data = peek16();
// IR に入れて PC を進める
ir.push_back(data);
pc += 2;
phys_pc += 2;
return data;
}
// ロングワードフェッチ
uint32
Disasm::fetch32()
{
uint32 data;
data = fetch16() << 16;
data |= fetch16();
return data;
}
// 符号なし8ビット16進数を文字列にして返す
std::string
Disasm::hex8(uint32 val)
{
return string_format("$%02x", val);
}
// 符号なし16ビット16進数を文字列にして返す
std::string
Disasm::hex16(uint32 val)
{
return string_format("$%04x", val);
}
// 符号なし32ビット16進数を文字列にして返す
std::string
Disasm::hex32(uint32 val)
{
return string_format("$%08x", val);
}
// 符号つき8ビット16進数を文字列にして返す
// 負数はマイナスを前置して表す。
std::string
Disasm::shex8(uint32 val)
{
if ((int8)val < 0) {
return string_format("-$%02x", -(int8)val);
} else {
return string_format("$%02x", val);
}
}
// 符号つき16ビット16進数を文字列にして返す
// 負数はマイナスを前置して表す。
std::string
Disasm::shex16(uint32 val)
{
if ((int16)val < 0) {
return string_format("-$%04x", -(int16)val);
} else {
return string_format("$%04x", val);
}
}
// 符号つき32ビット16進数を文字列にして返す
// 負数はマイナスを前置して表す。
std::string
Disasm::shex32(uint32 val)
{
if ((int32)val < 0) {
return string_format("-$%08x", (uint32)(-(int64)(int32)val));
} else {
return string_format("$%08x", val);
}
}
// EA を示す文字列を返す。ir[0] の mmmrrr の部分固定。
std::string
Disasm::make_ea()
{
return make_ea(ir[0]);
}
// mmrr に対して EA を示す文字列を返す。
std::string
Disasm::make_ea(uint mmrr)
{
std::string s;
uint rr;
mmrr &= 0x3f;
rr = mmrr & 7;
switch (mmrr) {
case 0x00 ... 0x07: // 0
s = make_dn(rr);
break;
case 0x08 ... 0x0f: // 1
s = make_an(rr);
break;
case 0x10 ... 0x17: // 2
s = make_anin(rr);
break;
case 0x18 ... 0x1f: // 3
s = make_anpi(rr);
break;
case 0x20 ... 0x27: // 4
s = make_anpd(rr);
break;
case 0x28 ... 0x2f: // 5
s = disp16() + make_anin(rr);
break;
case 0x30 ... 0x37: // 6
s = make_eaix(make_an(rr));
break;
case 0x38: // Abs.W
s = addr16();
break;
case 0x39: // Abs.L
s = addr32();
break;
case 0x3a: // d16(pc)
s = addr32(pc + (int32)(int16)fetch16()) +
"(" + make_reg(Reg::PC) + ")";
break;
case 0x3b: // d8(pc,IX)
s = make_eaix(make_reg(Reg::PC));
break;
case 0x3c: // imm
switch (size) {
case Size::B:
s = imm8();
break;
case Size::W:
s = imm16();
break;
case Size::L:
case Size::S:
s = imm32();
break;
case Size::D:
s = imm32();
s += string_format("_%08x", fetch32());
break;
case Size::X:
case Size::P:
s = imm32();
s += string_format("_%08x", fetch32());
s += string_format("_%08x", fetch32());
break;
default:
s = "(invalid ea size?)";
break;
}
break;
default:
s = "(invalid ea?)";
break;
}
return s;
}
std::string
Disasm::make_eaix(std::string basereg)
{
static const char * const scalestr[] = {
"", "*2", "*4", "*8",
};
uint16 ext = fetch16();
bool full = (ext & 0x0100);
uint rn = (ext >> 12);
bool wl = (ext & 0x0800);
uint scale = (ext >> 9) & 3;
std::string idx;
std::string s;
// インデックスレジスタ
Size sz = wl ? Size::L : Size::W;
idx = ",";
idx += make_rn(rn); // Rn
idx += size_str[sz]; // .[WL]
idx += scalestr[scale]; // *{2/4/8}
if (full == false) {
// 短縮フォーマット
uint8 disp = ext & 0xff;
if (disp == 0) {
// $00 は省略する
} else {
s = shex8(disp);
}
s += '(';
s += basereg;
s += idx;
s += ')';
} else {
// フルフォーマット
bool bs = (ext & 0x0080);
bool is = (ext & 0x0040);
uint bdsize = (ext >> 4) & 3;
uint iis = (ext & 7);
std::string bd;
std::string od;
// ベースレジスタ・サプレス
if (bs) {
basereg = "z" + basereg;
}
// ベース・ディスプレースメント
switch (bdsize) {
case 0: // 予約
return "<invalid EA(bdsize 0)>";
case 1: // ベースはヌル
break;
case 2: // ベース.W
bd = disp16();
bd += ",";
break;
case 3: // ベース.L
bd = disp32();
bd += ",";
break;
}
// アウター・ディスプレースメント
switch (iis & 3) {
case 0: // 不要?
case 1: // アウターはヌル
break;
case 2: // アウター.W
od = ",";
od += disp16();
break;
case 3: // アウター.L
od = ",";
od += disp32();
break;
}
if (is == 0) {
switch (iis) {
case 0: // no memory indirection
// (bd,base,idx)
s = "(";
s += bd;
s += basereg;
s += idx;
s += ")";
break;
case 1: // indirect pre-index with null outer
// ([bd,base,idx])
case 2: // indirect pre-index with word outer
case 3: // indirect pre-index with long outer
// ([bd,base,idx],od)
s = "([";
s += bd;
s += basereg;
s += idx;
s += "]";
s += od;
s += ")";
break;
case 4:
return "<invalid EA(iis=4)>";
case 5: // indirect post-index with null outer
// ([bd,base],idx)
case 6: // indirect post-index with word outer
case 7: // indirect post-index with long outer
// ([bd,base],idx,od)
s = "([";
s += bd;
s += basereg;
s += "]";
s += idx;
s += od;
s += ")";
break;
default:
__unreachable();
}
} else {
switch (iis) {
case 0: // no memory indirection
// (bd,base)
s = "(";
s += bd;
s += basereg;
s += ")";
break;
case 1: // memory indirect with null outer
// ([bd,base])
case 2: // memory indirect with word outer
case 3: // memory indirect with long outer
// ([bd,base],od)
s += "([";
s += bd;
s += basereg;
s += "]";
s += od;
s += ")";
break;
default:
return string_format("<invalid EA(is=1,iis=%d)>", iis);
}
}
}
return s;
}
// addr をワードアドレスとした時の文字列を返す
std::string
Disasm::addr16(uint32 addr)
{
return hex16(addr & 0xffff);
}
// addr をロングワードアドレスとした時の文字列を返す
std::string
Disasm::addr32(uint32 addr)
{
return hex32(addr);
}
// フェッチした値をワードアドレスとして文字列を返す
std::string
Disasm::addr16()
{
return addr16(fetch16());
}
// フェッチした値をロングワードアドレスとして文字列を返す
std::string
Disasm::addr32()
{
return addr32(fetch32());
}
// フェッチした値をワードディスプレースメントとして文字列を返す
std::string
Disasm::disp16()
{
return shex16(fetch16());
}
// フェッチした値をロングワードディスプレースメントとして文字列を返す
std::string
Disasm::disp32()
{
return shex32(fetch32());
}
// バイト即値 imm を文字列にして返す
std::string
Disasm::imm8()
{
return "#" + hex8(fetch16() & 0xff);
}
// ワード即値 imm を文字列にして返す
std::string
Disasm::imm16()
{
return "#" + hex16(fetch16());
}
// ロングワード即値 imm を文字列にして返す
std::string
Disasm::imm32()
{
return "#" + hex32(fetch32());
}
// Dn を文字列にして返す。n の上位ビットは無視する。
std::string
Disasm::make_dn(uint n)
{
n = (n & 7) + '0';
std::string s;
s = 'd';
s += n;
return s;
}
// An を文字列にして返す。n の上位ビットは無視する。
std::string
Disasm::make_an(uint n)
{
n = (n & 7) + '0';
std::string s;
s = 'a';
s += n;
return s;
}
// Rn (Dn/An) を文字列にして返す。n の上位ビットは無視する。
std::string
Disasm::make_rn(uint n)
{
n &= 0x0f;
if (n < 8) {
return make_dn(n);
} else {
return make_an(n - 8);
}
}
// (An) を文字列にして返す。n の上位ビットは無視する。
std::string
Disasm::make_anin(uint n)
{
std::string s;
s = '(';
s += make_an(n);
s += ')';
return s;
}
// (An)+ を文字列にして返す。n の上位ビットは無視する。
std::string
Disasm::make_anpi(uint n)
{
std::string s;
s = make_anin(n);
s += '+';
return s;
}
// -(An) を文字列にして返す。n の上位ビットは無視する。
std::string
Disasm::make_anpd(uint n)
{
std::string s;
s = '-';
s += make_anin(n);
return s;
}
// #qqq を文字列にして返す。ir[0] のいつものところにあると仮定する。
std::string
Disasm::make_q8()
{
uint q = (ir[0] >> 9) & 7;
if (q == 0) {
q = 8;
}
return string_format("#%d", q);
}
// regno で示されるレジスタ名を返す
std::string
Disasm::make_reg(Reg reg)
{
return reg_names[reg];
}
// MOVEM のレジスタリスト文字列を返す。
// 第2ワードのフェッチは呼び出し側で行っておくこと。
// プリデクリメントかどうかの判断はこちらで行う。
std::string
Disasm::make_reglist()
{
uint16 mask = ir[1];
uint mm = (ir[0] >> 3) & 7;
std::string s;
// 制御モード・ポストインクリメントモードなら、ビット順を入れ替える。
if (mm != 4) {
//mask = bitrev16(mask);
mask = ((mask & 0x5555) << 1) | ((mask >> 1) & 0x5555);
mask = ((mask & 0x3333) << 2) | ((mask >> 2) & 0x3333);
mask = ((mask & 0x0f0f) << 4) | ((mask >> 4) & 0x0f0f);
mask = (mask >> 8) | (mask << 8);
}
// これでどちらのモードでも 16ビット内に上から順に並んでいる。
// Bit: 15 14 ... 1 0
// Reg: D0 D1 ... A6 A7
make_reglist_half(s, "d", mask & 0xff00);
make_reglist_half(s, "a", mask << 8);
if (s.empty()) {
s = "noregs";
}
return s;
}
// データレジスタもしくはアドレスレジスタの8ビット分だけを処理する。
// FPn からも使うようになったので名前がいまいちか。
// mask は以下のように上位8ビットに上から下に向かって並ぶように渡すこと。
// ビット7 は番兵のため %0 にすること。
//
// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
// R0 R1 R2 R3 R4 R5 R6 R7 <-------- %0 --------->
//
void
Disasm::make_reglist_half(std::string& s, const char *reg, uint16 mask)
{
int top = -1;
// 番兵を含めてループするため1つ多く回る
for (int i = 0; i < 9; i++, mask <<= 1) {
if ((int16)mask < 0) {
// このビットは表示するレジスタ
if (top < 0) {
// 非表示中ならこのレジスタを出力する。
// 初回以外は区切りを先に出力する。
if (s.length() != 0) {
s += '/';
}
s += reg;
s += '0' + i;
top = i;
}
} else {
// このビットは表示しない
if (top >= 0) {
// 表示中ならこの一つ前のレジスタで終端
int last = i - 1;
if (top != last) {
// 表示が複数にまたがっていた
s += '-';
s += reg;
s += '0' + last;
}
top = -1;
}
}
}
}
// ビットフィールド欄を文字列にして返す。
// 第2ワードのフェッチは呼び出し側で行っておくこと。
std::string
Disasm::make_bf()
{
uint16 ext = ir[1];
uint od = (ext & 0x0800);
uint offset = (ext >> 6) & 0x1f;
uint wd = (ext & 0x0020);
uint width = ext & 0x1f;
std::string s = "{";
// offset
if (od) {
if (offset < 8) {
s += make_dn(offset);
} else {
s += string_format("<invalid regno %d>", offset);
}
} else {
// オフセットは 0..31
s += string_format("#%d", offset);
}
s += ":";
// width
if (wd) {
if (width < 8) {
s += make_dn(width);
} else {
s += string_format("<invalid regno %d>", width);
}
} else {
// 幅は 0 なら 32 を意味する
if (width == 0) {
width = 32;
}
s += string_format("#%d", width);
}
s += "}";
return s;
}
// ファンクションコードフィールドを文字列にして返す。
// MMU の拡張ワードは呼び出し側で取得済みのはず。
std::string
Disasm::make_fc()
{
uint fc = ir[1] & 0x1f;
switch (fc) {
case 0:
return make_reg(Reg::SFC);
case 1:
return make_reg(Reg::DFC);
case 0x08 ... 0x0f:
return make_dn(fc);
case 0x10 ... 0x17:
return string_format("#%d", fc & 7);
default:
return string_format("<invalid fc %d>", fc);
}
}
// MOVEC の制御レジスタを返す。
std::string
Disasm::make_movec()
{
uint n = ir[1] & 0x0fff;
Reg reg;
switch (n) {
case 0x000: reg = Reg::SFC; break;
case 0x001: reg = Reg::DFC; break;
case 0x002: reg = Reg::CACR; break;
case 0x800: reg = Reg::USP; break;
case 0x801: reg = Reg::VBR; break;
case 0x802: reg = Reg::CAAR; break;
case 0x803: reg = Reg::MSP; break;
case 0x804: reg = Reg::ISP; break;
// 040
// TC, MMUSR, SRP は名前が同じだが 030 MMU のではない
case 0x003: reg = Reg::TC; break;
case 0x004: reg = Reg::ITT0; break; // EC040 なら IACR0
case 0x005: reg = Reg::ITT1; break; // EC040 なら IACR1
case 0x006: reg = Reg::DTT0; break; // EC040 なら DACR0
case 0x007: reg = Reg::DTT1; break; // EC040 なら DACR1
case 0x805: reg = Reg::MMUSR; break;
case 0x806: reg = Reg::URP; break;
case 0x807: reg = Reg::SRP; break;
default:
return string_format("<invalid ctrl reg %03x>", n);
}
return make_reg(reg);
}
// FPgen 関数名を返す
// mode が適切でなければ "" を返す。
std::string
Disasm::make_fpgen()
{
uint mode = ir[1] & 0x7f;
if (mode < countof(fpgen_names)) {
return fpgen_names[mode];
}
return "";
}
// FPn を文字列にして返す。n の上位ビットは無視する。
std::string
Disasm::make_fpn(uint n)
{
n = (n & 7) + '0';
std::string s;
s = "fp";
s += n;
return s;
}
// FPU の condition 文字列を返す。
// word には condition が入ったワードを指定すること。
// 不要な上位ビットはこちらでマスクする。
std::string
Disasm::make_fpcc(uint16 word)
{
uint cc = word & 0x3f;
if (cc > 0x1f) {
return string_format("<invalid fpcc $%x>", cc);
}
return fpconditions[cc];
}
// FMOVEM 用の FPctls を文字列にして s に返す。
// 戻り値は指定された制御レジスタの個数。
uint
Disasm::make_fpctls(std::string& s)
{
uint n = 0;
uint list = ir[1] >> 10;
s.clear();
if ((list & 4)) {
s += make_reg(Reg::FPCR);
n++;
}
if ((list & 2)) {
if (!s.empty()) {
s += "/";
}
s += make_reg(Reg::FPSR);
n++;
}
if ((list & 1)) {
if (!s.empty()) {
s += "/";
}
s += make_reg(Reg::FPIAR);
n++;
}
if (n == 0)
s = "nofpc";
return n;
}
// FMOVEM のレジスタリスト文字列を返す。
// 第2ワードのフェッチはすでに行ってあるはず。
// プリデクリメントかどうかの判断はこちらで行う。
std::string
Disasm::make_fpnlist()
{
uint16 mask = ir[1] & 0x00ff;
std::string s;
// プリデクリメントモードなら、ビット順を入れ替える。
// An/Dn の時とは逆なので注意。てかなんでだよ。
// <ea> のモードと食い違ってたらその時は知らん…。
if ((ir[1] & 0x0800)) {
//mask = bitrev8(mask);
mask = ((mask & 0x55) << 1) | ((mask >> 1) & 0x55);
mask = ((mask & 0x33) << 2) | ((mask >> 2) & 0x33);
mask = ((mask & 0x0f) << 4) | ((mask >> 4) & 0x0f);
}
// これで、レジスタは常に上から順に並んでいる。
// 7 6 5 .. 1 0
// FP0 FP1 FP2 .. FP6 FP7
make_reglist_half(s, "fp", mask << 8);
if (s.empty()) {
s = "nofpn";
}
return s;
}
/*static*/ const char * const Disasm::reg_names[] = {
"ccr",
"sr",
"pc",
"usp",
"msp",
"isp",
"vbr",
"sfc",
"dfc",
"cacr",
"caar",
"tc",
"mmusr",
"srp",
"crp",
"tt0",
"tt1",
"fpcr",
"fpsr",
"fpiar",
};
/*static*/ const char * const Disasm::size_str[] = {
".l",
".s",
".x",
".p",
".w",
".d",
".b",
".p", // dynamic k-factor
".q",
"", // None
};
/*static*/ const char * const Disasm::conditions[] = {
"t", "f", "hi", "ls", "cc", "cs", "ne", "eq",
"vc", "vs", "pl", "mi", "ge", "lt", "gt", "le",
};
/*static*/ const char * const Disasm::fpconditions[] = {
"f", // 000000
"eq", // 000001
"ogt", // 000010
"oge", // 000011
"olt", // 000100
"ole", // 000101
"ogl", // 000110
"or", // 000111
"un", // 001000
"ueq", // 001001
"ugt", // 001010
"uge", // 001011
"ult", // 001100
"ule", // 001101
"ne", // 001110
"?", // 001111
"sf", // 010000
"seq", // 010001
"ge", // 010010
"ge", // 010011
"lt", // 010100
"le", // 010101
"gl", // 010110
"gle", // 010111
"ngle", // 011000
"ngl", // 011001
"nle", // 011010
"nlt", // 011011
"nge", // 011100
"ngt", // 011101
"sne", // 011110
"st", // 011111
};
/*static*/ const char * const Disasm::btst_names[] = {
"btst",
"bchg",
"bclr",
"bset",
};
/*static*/ const char * const Disasm::fpgen_names[] = {
"fmove", // $00
"fint", // $01
"fsinh", // $02
"fintrz", // $03
"fsqrt", // $04
"", // $05
"flognp1", // $06
"", // $07
"fetoxm1", // $08
"ftanh", // $09
"fatan", // $0a
"", // $0b
"fasin", // $0c
"fatanh", // $0d
"fsin", // $0e
"ftan", // $0f
"fetox", // $10
"ftwotox", // $11
"ftentox", // $12
"", // $13
"flogn", // $14
"flog10", // $15
"flog2", // $16
"", // $17
"fabs", // $18
"fcosh", // $19
"fneg", // $1a
"", // $1b
"facos", // $1c
"fcos", // $1d
"fgetexp", // $1e
"fgetman", // $1f
"fdiv", // $20
"fmod", // $21
"fadd", // $22
"fmul", // $23
"fsgldiv", // $24
"frem", // $25
"fscale", // $26
"fsglmul", // $27
"fsub", // $28
"", // $29
"", // $2a
"", // $2b
"", // $2c
"", // $2d
"", // $2e
"", // $2f
"", // $30 (fsincos)
"", // $31 (fsincos)
"", // $32 (fsincos)
"", // $33 (fsincos)
"", // $34 (fsincos)
"", // $35 (fsincos)
"", // $36 (fsincos)
"", // $37 (fsincos)
"fcmp", // $38
"", // $39
"ftst", // $3a
};
/*static*/ const char * const Disasm::fmovecr_text[] = {
"<log10(2)>", // [0] $0b
"<e>", // [1] $0c
"<log2(e)>", // [2] $0d
"<log10(e)>", // [3] $0e
"<0>", // [4] $0f
"<ln(2)>", // $30
"<ln(10)>", // $31
"<1>", // $32
"<10>", // $33
"<1e2>", // $34
"<1e4>", // $35
"<1e8>", // $36
"<1e16>", // $37
"<1e32>", // $38
"<1e64>", // $39
"<1e128>", // $3a
"<1e256>", // $3b
"<1e512>", // $3c
"<1e1024>", // $3d
"<1e2048>", // $3e
"<1e4096>", // $3f
};
/*static*/ const char *const Disasm::x68k_doscall[256] = {
"_EXIT", // ff00
"_GETCHAR", // ff01
"_PUTCHAR", // ff02
"_COMINP", // ff03
"_COMOUT", // ff04
"_PRNOUT", // ff05
"_INPOUT", // ff06
"_INKEY", // ff07
"_GETC", // ff08
"_PRINT", // ff09
"_GETS", // ff0a
"_KEYSNS", // ff0b
"_KFLUSH", // ff0c
"_FFLUSH", // ff0d
"_CHGDRV", // ff0e
"_DRVCTRL", // ff0f
"_CONSNS", // ff10
"_PRNSNS", // ff11
"_CINSNS", // ff12
"_COUTSNS", // ff13
NULL, // ff14
NULL, // ff15
NULL, // ff16
"_FATCHK", // ff17
"_HENDSP", // ff18
"_CURDRV", // ff19
"_GETSS", // ff1a
"_FGETC", // ff1b
"_FGETS", // ff1c
"_FPUTC", // ff1d
"_FPUTS", // ff1e
"_ALLCLOSE", // ff1f
"_SUPER", // ff20
"_FNCKEY", // ff21
"_KNJCTRL", // ff22
"_CONCTRL", // ff23
"_KEYCTRL", // ff24
"_INTVCS", // ff25
"_PSPSET", // ff26
"_GETTIM2", // ff27
"_SETTIM2", // ff28
"_NAMESTS", // ff29
"_GETDATE", // ff2a
"_SETDATE", // ff2b
"_GETTIME", // ff2c
"_SETTIME", // ff2d
"_VERIFY", // ff2e
"_DUP0", // ff2f
"_VERNUM", // ff30
"_KEEPPR", // ff31
"_GETDPB", // ff32
"_BREAKCK", // ff33
"_DRVXCHG", // ff34
"_INTVCG", // ff35
"_DSKFRE", // ff36
"_NAMECK", // ff37
NULL, // ff38
"_MKDIR", // ff39
"_RMDIR", // ff3a
"_CHDIR", // ff3b
"_CREATE", // ff3c
"_OPEN", // ff3d
"_CLOSE", // ff3e
"_READ", // ff3f
"_WRITE", // ff40
"_DELETE", // ff41
"_SEEK", // ff42
"_CHMOD", // ff43
"_IOCTRL", // ff44
"_DUP", // ff45
"_DUP2", // ff46
"_CURDIR", // ff47
"_MALLOC", // ff48
"_MFREE", // ff49
"_SETBLOCK", // ff4a
"_EXEC", // ff4b
"_EXIT2", // ff4c
"_WAIT", // ff4d
"_FILES", // ff4e
"_NFILES", // ff4f
"_SETPDB", // ff50 (Human68k ver.2)
"_GETPDB", // ff51 (Human68k ver.2)
"_SETENV", // ff52 (Human68k ver.2)
"_GETENV", // ff53 (Human68k ver.2)
"_VERIFYG", // ff54 (Human68k ver.2)
"_COMMON", // ff55 (Human68k ver.2)
"_RENAME", // ff56 (Human68k ver.2)
"_FILEDATE", // ff57 (Human68k ver.2)
"_MALLOC2", // ff58 (Human68k ver.2)
NULL, // ff59
"_MAKETMP", // ff5a (Human68k ver.2)
"_NEWFILE", // ff5b (Human68k ver.2)
"_LOCK", // ff5c (Human68k ver.2)
NULL, // ff5d
NULL, // ff5e
"_ASSIGN", // ff5f (Human68k ver.2)
NULL, // ff60
NULL, // ff61
NULL, // ff62
NULL, // ff63
NULL, // ff64
NULL, // ff65
NULL, // ff66
NULL, // ff67
NULL, // ff68
NULL, // ff69
NULL, // ff6a
NULL, // ff6b
NULL, // ff6c
NULL, // ff6d
NULL, // ff6e
NULL, // ff6f
NULL, // ff70
NULL, // ff71
NULL, // ff72
NULL, // ff73
NULL, // ff74
NULL, // ff75
NULL, // ff76
NULL, // ff77
NULL, // ff78
NULL, // ff79
"_FFLUSH_SET", // ff7a (Human68k ver.2)
"_OS_PATCH", // ff7b (Human68k ver.2)
"_GETFCB", // ff7c (Human68k ver.2)
"_S_MALLOC", // ff7d (Human68k ver.2)
"_S_MFREE", // ff7e (Human68k ver.2)
"_S_PROCESS", // ff7f (Human68k ver.2)
"_SETPDB", // ff80
"_GETPDB", // ff81
"_SETENV", // ff82
"_GETENV", // ff83
"_VERIFYG", // ff84
"_COMMON", // ff85
"_RENAME", // ff86
"_FILEDATE", // ff87
"_MALLOC2", // ff88
NULL, // ff89
"_MAKETMP", // ff8a
"_NEWFILE", // ff8b
"_LOCK", // ff8c
NULL, // ff8d
NULL, // ff8e
"_ASSIGN", // ff8f
NULL, // ff90
NULL, // ff91
NULL, // ff92
NULL, // ff93
NULL, // ff94
NULL, // ff95
NULL, // ff96
NULL, // ff97
NULL, // ff98
NULL, // ff99
NULL, // ff9a
NULL, // ff9b
NULL, // ff9c
NULL, // ff9d
NULL, // ff9e
NULL, // ff9f
NULL, // ffa0
NULL, // ffa1
NULL, // ffa2
NULL, // ffa3
NULL, // ffa4
NULL, // ffa5
NULL, // ffa6
NULL, // ffa7
NULL, // ffa8
NULL, // ffa9
"_FFLUSH_SET", // ffaa
"_OS_PATCH", // ffab
"_GETFCB", // ffac
"_S_MALLOC", // ffad
"_S_MFREE", // ffae
"_S_PROCESS", // ffaf
NULL, // ffb0
NULL, // ffb1
NULL, // ffb2
NULL, // ffb3
NULL, // ffb4
NULL, // ffb5
NULL, // ffb6
NULL, // ffb7
NULL, // ffb8
NULL, // ffb9
NULL, // ffba
NULL, // ffbb
NULL, // ffbc
NULL, // ffbd
NULL, // ffbe
NULL, // ffbf
NULL, // ffc0
NULL, // ffc1
NULL, // ffc2
NULL, // ffc3
NULL, // ffc4
NULL, // ffc5
NULL, // ffc6
NULL, // ffc7
NULL, // ffc8
NULL, // ffc9
NULL, // ffca
NULL, // ffcb
NULL, // ffcc
NULL, // ffcd
NULL, // ffce
NULL, // ffcf
NULL, // ffd0
NULL, // ffd1
NULL, // ffd2
NULL, // ffd3
NULL, // ffd4
NULL, // ffd5
NULL, // ffd6
NULL, // ffd7
NULL, // ffd8
NULL, // ffd9
NULL, // ffda
NULL, // ffdb
NULL, // ffdc
NULL, // ffdd
NULL, // ffde
NULL, // ffdf
NULL, // ffe0
NULL, // ffe1
NULL, // ffe2
NULL, // ffe3
NULL, // ffe4
NULL, // ffe5
NULL, // ffe6
NULL, // ffe7
NULL, // ffe8
NULL, // ffe9
NULL, // ffea
NULL, // ffeb
NULL, // ffec
NULL, // ffed
NULL, // ffee
NULL, // ffef
"_EXITVC", // fff0
"_CTRLVC", // fff1
"_ERRJVC", // fff2
"_DISKRED", // fff3
"_DISKWRT", // fff4
"_INDOSFLG", // fff5
"_SUPER_JSR", // fff6
"_BUS_ERR", // fff7
"_OPEN_PR", // fff8
"_KILL_PR", // fff9
"_GET_PR", // fffa
"_SUSPEND_PR", // fffb
"_SLEEP_PR", // fffc
"_SEND_PR", // fffd
"_TIME_PR", // fffe
"_CHANGE_PR", // ffff
};
/*static*/ const char * const Disasm::x68k_fpcall[256] = {
"__LMUL", // fe00
"__LDIV", // fe01
"__LMOD", // fe02
NULL, // fe03
"__UMUL", // fe04
"__UDIV", // fe05
"__UMOD", // fe06
NULL, // fe07
"__IMUL", // fe08
"__IDIV", // fe09
NULL, // fe0a
NULL, // fe0b
"__RANDOMIZE", // fe0c
"__SRAND", // fe0d
"__RAND", // fe0e
NULL, // fe0f
"__STOL", // fe10
"__LTOS", // fe11
"__STOH", // fe12
"__HTOS", // fe13
"__STOO", // fe14
"__OTOS", // fe15
"__STOB", // fe16
"__BTOS", // fe17
"__IUSING", // fe18
NULL, // fe19
"__LTOD", // fe1a
"__DTOL", // fe1b
"__LTOF", // fe1c
"__FTOL", // fe1d
"__FTOD", // fe1e
"__DTOF", // fe1f
"__VAL", // fe20
"__USING", // fe21
"__STOD", // fe22
"__DTOS", // fe23
"__ECVT", // fe24
"__FCVT", // fe25
"__GCVT", // fe26
NULL, // fe27
"__DTST", // fe28
"__DCMP", // fe29
"__DNEG", // fe2a
"__DADD", // fe2b
"__DSUB", // fe2c
"__DMUL", // fe2d
"__DDIV", // fe2e
"__DMOD", // fe2f
"__DABS", // fe30
"__DCEIL", // fe31
"__DFIX", // fe32
"__DFLOOR", // fe33
"__DFRAC", // fe34
"__DSGN", // fe35
"__SIN", // fe36
"__COS", // fe37
"__TAN", // fe38
"__ATAN", // fe39
"__LOG", // fe3a
"__EXP", // fe3b
"__SQR", // fe3c
"__PI", // fe3d
"__NPI", // fe3e
"__POWER", // fe3f
"__RND", // fe40
"__SINH", // fe41
"__COSH", // fe42
"__TANH", // fe43
"__ATANH", // fe44
"__ASIN", // fe45
"__ACOS", // fe46
"__LOG10", // fe47
"__LOG2", // fe48
"__DFREXP", // fe49
"__DLDEXP", // fe4a
"__DADDONE", // fe4b
"__DSUBONE", // fe4c
"__DDIVTWO", // fe4d
"__DIEECNV", // fe4e
"__IEEDCNV", // fe4f
"__FVAL", // fe50
"__FUSING", // fe51
"__STOF", // fe52
"__FTOS", // fe53
"__FECVT", // fe54
"__FFCVT", // fe55
"__FGCVT", // fe56
NULL, // fe57
"__FTST", // fe58
"__FCMP", // fe59
"__FNEG", // fe5a
"__FADD", // fe5b
"__FSUB", // fe5c
"__FMUL", // fe5d
"__FDIV", // fe5e
"__FMOD", // fe5f
"__FABS", // fe60
"__FCEIL", // fe61
"__FFIX", // fe62
"__FFLOOR", // fe63
"__FFRAC", // fe64
"__FSGN", // fe65
"__FSIN", // fe66
"__FCOS", // fe67
"__FTAN", // fe68
"__FATAN", // fe69
"__FLOG", // fe6a
"__FEXP", // fe6b
"__FSQR", // fe6c
"__FPI", // fe6d
"__FNPI", // fe6e
"__FPOWER", // fe6f
"__FRND", // fe70
"__FSINH", // fe71
"__FCOSH", // fe72
"__FTANH", // fe73
"__FATANH", // fe74
"__FASIN", // fe75
"__FACOS", // fe76
"__FLOG10", // fe77
"__FLOG2", // fe78
"__FFREXP", // fe79
"__FLDEXP", // fe7a
"__FADDONE", // fe7b
"__FSUBONE", // fe7c
"__FDIVTWO", // fe7d
"__FIEECNV", // fe7e
"__IEEFCNV", // fe7f
NULL, // fe80
NULL, // fe81
NULL, // fe82
NULL, // fe83
NULL, // fe84
NULL, // fe85
NULL, // fe86
NULL, // fe87
NULL, // fe88
NULL, // fe89
NULL, // fe8a
NULL, // fe8b
NULL, // fe8c
NULL, // fe8d
NULL, // fe8e
NULL, // fe8f
NULL, // fe90
NULL, // fe91
NULL, // fe92
NULL, // fe93
NULL, // fe94
NULL, // fe95
NULL, // fe96
NULL, // fe97
NULL, // fe98
NULL, // fe99
NULL, // fe9a
NULL, // fe9b
NULL, // fe9c
NULL, // fe9d
NULL, // fe9e
NULL, // fe9f
NULL, // fea0
NULL, // fea1
NULL, // fea2
NULL, // fea3
NULL, // fea4
NULL, // fea5
NULL, // fea6
NULL, // fea7
NULL, // fea8
NULL, // fea9
NULL, // feaa
NULL, // feab
NULL, // feac
NULL, // fead
NULL, // feae
NULL, // feaf
NULL, // feb0
NULL, // feb1
NULL, // feb2
NULL, // feb3
NULL, // feb4
NULL, // feb5
NULL, // feb6
NULL, // feb7
NULL, // feb8
NULL, // feb9
NULL, // feba
NULL, // febb
NULL, // febc
NULL, // febd
NULL, // febe
NULL, // febf
NULL, // fec0
NULL, // fec1
NULL, // fec2
NULL, // fec3
NULL, // fec4
NULL, // fec5
NULL, // fec6
NULL, // fec7
NULL, // fec8
NULL, // fec9
NULL, // feca
NULL, // fecb
NULL, // fecc
NULL, // fecd
NULL, // fece
NULL, // fecf
NULL, // fed0
NULL, // fed1
NULL, // fed2
NULL, // fed3
NULL, // fed4
NULL, // fed5
NULL, // fed6
NULL, // fed7
NULL, // fed8
NULL, // fed9
NULL, // feda
NULL, // fedb
NULL, // fedc
NULL, // fedd
NULL, // fede
NULL, // fedf
"__CLMUL", // fee0
"__CLDIV", // fee1
"__CLMOD", // fee2
"__CUMUL", // fee3
"__CUDIV", // fee4
"__CUMOD", // fee5
"__CLTOD", // fee6
"__CDTOL", // fee7
"__CLTOF", // fee8
"__CFTOL", // fee9
"__CFTOD", // feea
"__CDTOF", // feeb
"__CDCMP", // feec
"__CDADD", // feed
"__CDSUB", // feee
"__CDMUL", // feef
"__CDDIV", // fef0
"__CDMOD", // fef1
"__CFCMP", // fef2
"__CFADD", // fef3
"__CFSUB", // fef4
"__CFMUL", // fef5
"__CFDIV", // fef6
"__CFMOD", // fef7
"__CDTST", // fef8
"__CFTST", // fef9
"__CDINC", // fefa
"__CFINC", // fefb
"__CDDEC", // fefc
"__CFDEC", // fefd
"__FEVARG", // fefe
"__FEVECS", // feff
};
/*static*/ const char * const Disasm::x68k_iocscall[256] = {
"_B_KEYINP", // 7000
"_B_KEYSNS", // 7001
"_B_SFTSNS", // 7002
"_KEY_INIT", // 7003
"_BITSNS", // 7004
"_SKEYSET", // 7005
"_LEDCTRL", // 7006
"_LEDSET", // 7007
"_KEYDLY", // 7008
"_KEYREP", // 7009
NULL, // 700a
NULL, // 700b
"_TVCTRL", // 700c
"_LEDMOD", // 700d
"_TGUSEMD", // 700e
"_DEFCHR", // 700f
"_CRTMOD", // 7010
"_CONTRAST", // 7011
"_HSVTORGB", // 7012
"_TPALET", // 7013
"_TPALET2", // 7014
"_TCOLOR", // 7015
"_FNTADR", // 7016
"_VRAMGET", // 7017
"_VRAMPUT", // 7018
"_FNTGET", // 7019
"_TEXTGET", // 701a
"_TEXTPUT", // 701b
"_CLIPPUT", // 701c
"_SCROLL", // 701d
"_B_CURON", // 701e
"_B_CUROFF", // 701f
"_B_PUTC", // 7020
"_B_PRINT", // 7021
"_B_COLOR", // 7022
"_B_LOCATE", // 7023
"_B_DOWN_S", // 7024
"_B_UP_S", // 7025
"_B_UP", // 7026
"_B_DOWN", // 7027
"_B_RIGHT", // 7028
"_B_LEFT", // 7029
"_B_CLR_ST", // 702a
"_B_ERA_ST", // 702b
"_B_INS", // 702c
"_B_DEL", // 702d
"_B_CONSOL", // 702e
"_B_PUTMES", // 702f
"_SET232C", // 7030
"_LOF232C", // 7031
"_INP232C", // 7032
"_ISNS232C", // 7033
"_OSNS232C", // 7034
"_OUT232C", // 7035
NULL, // 7036
NULL, // 7037
"_SETFNTADR", // 7038
NULL, // 7039
NULL, // 703a
"_JOYGET", // 703b
"_INIT_PRN", // 703c
"_SNSPRN", // 703d
"_OUTLPT", // 703e
"_OUTPRN", // 703f
"_B_SEEK", // 7040
"_B_VERIFY", // 7041
"_B_READDI", // 7042
"_B_DSKINI", // 7043
"_B_DRVSNS", // 7044
"_B_WRITE", // 7045
"_B_READ", // 7046
"_B_RECALI", // 7047
"_B_ASSIGN", // 7048
"_B_WRITED", // 7049
"_B_READID", // 704a
"_B_BADFMT", // 704b
"_B_READDL", // 704c
"_B_FORMAT", // 704d
"_B_DRVCHK", // 704e
"_B_EJECT", // 704f
"_DATEBCD", // 7050
"_DATESET", // 7051
"_TIMEBCD", // 7052
"_TIMESET", // 7053
"_DATEGET", // 7054
"_DATEBIN", // 7055
"_TIMEGET", // 7056
"_TIMEBIN", // 7057
"_DATECNV", // 7058
"_TIMECNV", // 7059
"_DATEASC", // 705a
"_TIMEASC", // 705b
"_DAYASC", // 705c
"_ALARMMOD", // 705d
"_ALARMSET", // 705e
"_ALARMGET", // 705f
"_ADPCMOUT", // 7060
"_ADPCMINP", // 7061
"_ADPCMAOT", // 7062
"_ADPCMAIN", // 7063
"_ADPCMLOT", // 7064
"_ADPCMLIN", // 7065
"_ADPCMSNS", // 7066
"_ADPCMMOD", // 7067
"_OPMSET", // 7068
"_OPMSNS", // 7069
"_OPMINTST", // 706a
"_TIMERDST", // 706b
"_VDISPST", // 706c
"_CRTCRAS", // 706d
"_HSYNCST", // 706e
"_PRNINTST", // 706f
"_MS_INIT", // 7070
"_MS_CURON", // 7071
"_MS_CUROF", // 7072
"_MS_STAT", // 7073
"_MS_GETDT", // 7074
"_MS_CURGT", // 7075
"_MS_CURST", // 7076
"_MS_LIMIT", // 7077
"_MS_OFFTM", // 7078
"_MS_ONTM", // 7079
"_MS_PATST", // 707a
"_MS_SEL", // 707b
"_MS_SEL2", // 707c
"_SKEY_MOD", // 707d
"_DENSNS", // 707e
"_ONTIME", // 707f
"_B_INTVCS", // 7080
"_B_SUPER", // 7081
"_B_BPEEK", // 7082
"_B_WPEEK", // 7083
"_B_LPEEK", // 7084
"_B_MEMSTR", // 7085
"_B_BPOKE", // 7086
"_B_WPOKE", // 7087
"_B_LPOKE", // 7088
"_B_MEMSET", // 7089
"_DMAMOVE", // 708a
"_DMAMOV_A", // 708b
"_DMAMOV_L", // 708c
"_DMAMODE", // 708d
"_BOOTINF", // 708e
"_ROMVER", // 708f
"_G_CLR_ON", // 7090
NULL, // 7091
NULL, // 7092
NULL, // 7093
"_GPALET", // 7094
NULL, // 7095
NULL, // 7096
NULL, // 7097
NULL, // 7098
NULL, // 7099
NULL, // 709a
NULL, // 709b
NULL, // 709c
NULL, // 709d
NULL, // 709e
NULL, // 709f
"_SFTJIS", // 70a0
"_JISSFT", // 70a1
"_AKCONV", // 70a2
"_RMACNV", // 70a3
"_DAKJOB", // 70a4
"_HANJOB", // 70a5
NULL, // 70a6
NULL, // 70a7
NULL, // 70a8
NULL, // 70a9
NULL, // 70aa
NULL, // 70ab
"_SYS_STAT", // 70ac
"_B_CONMOD", // 70ad
"_OS_CURON", // 70ae
"_OS_CUROF", // 70af
"_DRAWMODE", // 70b0
"_APAGE", // 70b1
"_VPAGE", // 70b2
"_HOME", // 70b3
"_WINDOW", // 70b4
"_WIPE", // 70b5
"_PSET", // 70b6
"_POINT", // 70b7
"_LINE", // 70b8
"_BOX", // 70b9
"_FILL", // 70ba
"_CIRCLE", // 70bb
"_PAINT", // 70bc
"_SYMBOL", // 70bd
"_GETGRM", // 70be
"_PUTGRM", // 70bf
"_SP_INIT", // 70c0
"_SP_ON", // 70c1
"_SP_OFF", // 70c2
"_SP_CGCLR", // 70c3
"_SP_DEFCG", // 70c4
"_SP_GTPCG", // 70c5
"_SP_REGST", // 70c6
"_SP_REGGT", // 70c7
"_BGSCRLST", // 70c8
"_BGSCRLGT", // 70c9
"_BGCTRLST", // 70ca
"_BGCTRLGT", // 70cb
"_BGTEXTCL", // 70cc
"_BGTEXTST", // 70cd
"_BGTEXTGT", // 70ce
"_SPALET", // 70cf
NULL, // 70d0
NULL, // 70d1
NULL, // 70d2
"_TXXLINE", // 70d3
"_TXYLINE", // 70d4
"_TXLINE", // 70d5
"_TXBOX", // 70d6
"_TXFILL", // 70d7
"_TXREV", // 70d8
NULL, // 70d9
NULL, // 70da
NULL, // 70db
NULL, // 70dc
NULL, // 70dd
NULL, // 70de
"_TXRASCPY", // 70df
NULL, // 70e0
NULL, // 70e1
NULL, // 70e2
NULL, // 70e3
NULL, // 70e4
NULL, // 70e5
NULL, // 70e6
NULL, // 70e7
NULL, // 70e8
NULL, // 70e9
NULL, // 70ea
NULL, // 70eb
NULL, // 70ec
NULL, // 70ed
NULL, // 70ee
NULL, // 70ef
"_OPMDRV", // 70f0
"_RSDRV", // 70f1
"_A_JOYGET", // 70f2
"_MUSICDRV", // 70f3
NULL, // 70f4
"_SCSIDRV", // 70f5
NULL, // 70f6
NULL, // 70f7
NULL, // 70f8
NULL, // 70f9
NULL, // 70fa
NULL, // 70fb
NULL, // 70fc
"_ABORTRST", // 70fd
"_IPLERR", // 70fe
"_ABORTJOB", // 70ff
};
// ここから命令
// %0000_000000_mmmrrr ORI.B #<imm>,<ea>
// %0000_000000_111100 ORI.B #<imm>,CCR
OP_DEF(ori_b)
{
name = "ori";
size = Size::B;
src = imm8();
if ((ir[0] & 0x3f) == 0x3c) {
dst = make_reg(Reg::CCR);
} else {
dst = make_ea();
}
}
// %0000_000001_mmmrrr ORI.W #<imm>,<ea>
// %0000_000001_111100 ORI.W #<imm>,SR
OP_DEF(ori_w)
{
name = "ori";
size = Size::W;
src = imm16();
if ((ir[0] & 0x3f) == 0x3c) {
dst = make_reg(Reg::SR);
} else {
dst = make_ea();
}
}
// %0000_000010_mmmrrr ORI.L #<imm>,<ea>
OP_DEF(ori_l)
{
name = "ori";
size = Size::L;
src = imm32();
dst = make_ea();
}
void
Disasm::ops_cmp2chk2(Disasm::Size sz)
{
fetch16();
if ((ir[1] & 0x0800) == 0) {
// CMP2.[BWL] <ea>,Rn
name = "cmp2";
} else {
// CHK2.[BWL] <ea>,Rn
name = "chk2";
}
size = sz;
src = make_ea();
dst = make_rn(ir[1] >> 12);
}
// %0000_000011_mmmrrr CMP2/CHK2.B <ea>,Rn
OP_DEF(cmp2chk2_b)
{
ops_cmp2chk2(Size::B);
}
// B{TST,CHG,CLR,SET} と MOVEP のメイン部分
void
Disasm::ops_btst_movep()
{
uint mr = (ir[0] >> 3) & 7;
uint op = (ir[0] >> 6) & 3;
if (mr == 0) {
// B***.L Dx,Dy
name = btst_names[op];
size = Size::L;
src = make_dn(ir[0] >> 9);
dst = make_dn(ir[0]);
} else if (mr == 1) {
// MOVEP
ops_movep();
} else {
// B***.B Dx,<ea>
name = btst_names[op];
size = Size::B;
src = make_dn(ir[0] >> 9);
dst = make_ea();
}
}
// MOVEP
void
Disasm::ops_movep()
{
name = "movep";
uint mode = (ir[0] >> 6) & 3;
__assume(mode <= 3);
switch (mode) {
case 0: // MOVEP.W (d,Ay),Dx
size = Size::W;
src = "(" + addr16() + "," + make_an(ir[0]) + ")";
dst = make_dn(ir[0] >> 9);
break;
case 1: // MOVEP.L (d,Ay),Dx
size = Size::L;
src = "(" + addr16() + "," + make_an(ir[0]) + ")";
dst = make_dn(ir[0] >> 9);
break;
case 2: // MOVEP.W Dx,(d,Ay)
size = Size::W;
src = make_dn(ir[0] >> 9);
dst = "(" + addr16() + "," + make_an(ir[0]) + ")";
break;
case 3: // MOVEP.L Dx,(d,Ay)
size = Size::L;
src = make_dn(ir[0] >> 9);
dst = "(" + addr16() + "," + make_an(ir[0]) + ")";
break;
}
}
// %0000_xxx100_000yyy BTST.L Dx,Dy
// %0000_xxx100_001yyy MOVEP.W (d,Ay),Dx
// %0000_xxx100_mmmrrr BTST.B Dx,<ea>
OP_DEF(btst_dn_ea)
{
ops_btst_movep();
}
// %0000_xxx101_000yyy BCHG.L Dx,Dy
// %0000_xxx101_001yyy MOVEP.L (d,Ay),Dx
// %0000_xxx101_mmmrrr BCHG.B Dx,<ea>
OP_DEF(bchg_dn_ea)
{
ops_btst_movep();
}
// %0000_xxx110_000yyy BCLR.L Dx,Dy
// %0000_xxx110_001yyy MOVEP.W Dx,(d,Ay)
// %0000_xxx110_mmmrrr BCLR.B Dx,<ea>
OP_DEF(bclr_dn_ea)
{
ops_btst_movep();
}
// %0000_xxx111_000yyy BSET.L Dx,Dy
// %0000_xxx111_001yyy MOVEP.L Dx,(d,Ay)
// %0000_xxx111_mmmrrr BSET.B Dx,<ea>
OP_DEF(bset_dn_ea)
{
ops_btst_movep();
}
// %0000_001000_mmmrrr ANDI.B #<imm>,<ea>
// %0000_001000_111100 ANDI.B #<imm>,CCR
OP_DEF(andi_b)
{
name = "andi";
size = Size::B;
src = imm8();
if ((ir[0] & 0x3f) == 0x3c) {
dst = make_reg(Reg::CCR);
} else {
dst = make_ea();
}
}
// %0000_001001_mmmrrr ANDI.W #<imm>,<ea>
// %0000_001001_111100 ANDI.W #<imm>,SR
OP_DEF(andi_w)
{
name = "andi";
size = Size::W;
src = imm16();
if ((ir[0] & 0x3f) == 0x3c) {
dst = make_reg(Reg::SR);
} else {
dst = make_ea();
}
}
// %0000_001010_mmmrrr ANDI.L #<imm>,<ea>
OP_DEF(andi_l)
{
name = "andi";
size = Size::L;
src = imm32();
dst = make_ea();
}
// %0000_001011_mmmrrr CMP2/CHK2.W <ea>,Rn
OP_DEF(cmp2chk2_w)
{
ops_cmp2chk2(Size::W);
}
// %0000_010000_mmmrrr SUBI.B #<imm>,<ea>
OP_DEF(subi_b)
{
name = "subi";
size = Size::B;
src = imm8();
dst = make_ea();
}
// %0000_010001_mmmrrr SUBI.W #<imm>,<ea>
OP_DEF(subi_w)
{
name = "subi";
size = Size::W;
src = imm16();
dst = make_ea();
}
// %0000_010010_mmmrrr SUBI.L #<imm>,<ea>
OP_DEF(subi_l)
{
name = "subi";
size = Size::L;
src = imm32();
dst = make_ea();
}
// %0000_010011_mmmrrr CMP2/CHK2.L <ea>,Rn
OP_DEF(cmp2chk2_l)
{
ops_cmp2chk2(Size::L);
}
// %0000_011000_mmmrrr ADDI.B #<imm>,<ea>
OP_DEF(addi_b)
{
name = "addi";
size = Size::B;
src = imm8();
dst = make_ea();
}
// %0000_011001_mmmrrr ADDI.W #<imm>,<ea>
OP_DEF(addi_w)
{
name = "addi";
size = Size::W;
src = imm16();
dst = make_ea();
}
// %0000_011010_mmmrrr ADDI.L #<imm>,<ea>
OP_DEF(addi_l)
{
name = "addi";
size = Size::L;
src = imm32();
dst = make_ea();
}
// BTST,BCHG,BCLR,BSET #<imm>,<ea> の共通部分。
void
Disasm::ops_btst_imm_ea()
{
uint n = ir[0] & 0x3f;
uint op = (ir[0] >> 6) & 3;
fetch16();
name = btst_names[op];
if (n < 8) {
size = Size::L;
src = string_format("#%d", ir[1] & 31);
dst = make_dn(n);
} else {
size = Size::B;
src = string_format("#%d", ir[1] & 7);
dst = make_ea();
}
}
// %0000_100000_000yyy BTST.L #<imm>,Dy
// %0000_100000_mmmrrr BTST.B #<imm>,<ea>
OP_DEF(btst_imm_ea)
{
ops_btst_imm_ea();
}
// %0000_100001_000yyy BCHG.L #<imm>,Dy
// %0000_100001_mmmrrr BCHG.B #<imm>,<ea>
OP_DEF(bchg_imm_ea)
{
ops_btst_imm_ea();
}
// %0000_100010_000yyy BCLR.L #<imm>,Dy
// %0000_100010_mmmrrr BCLR.B #<imm>,<ea>
OP_DEF(bclr_imm_ea)
{
ops_btst_imm_ea();
}
// %0000_100011_000yyy BSET.L #<imm>,Dy
// %0000_100011_mmmrrr BSET.B #<imm>,<ea>
OP_DEF(bset_imm_ea)
{
ops_btst_imm_ea();
}
// %0000_101000_mmmrrr EORI.B #<imm>,<ea>
// %0000_101000_111100 EORI.B #<imm>,CCR
OP_DEF(eori_b)
{
name = "eori";
size = Size::B;
src = imm8();
if ((ir[0] & 0x3f) == 0x3c) {
dst = make_reg(Reg::CCR);
} else {
dst = make_ea();
}
}
// %0000_101001_mmmrrr EORI.W #<imm>,<ea>
// %0000_101001_111100 EORI.W #<imm>,SR
OP_DEF(eori_w)
{
name = "eori";
size = Size::W;
src = imm16();
if ((ir[0] & 0x3f) == 0x3c) {
dst = make_reg(Reg::SR);
} else {
dst = make_ea();
}
}
// %0000_101010_mmmrrr EORI.L #<imm>,<ea>
OP_DEF(eori_l)
{
name = "eori";
size = Size::L;
src = imm32();
dst = make_ea();
}
// CAS の共通部分
void
Disasm::ops_cas(Disasm::Size sz)
{
fetch16();
name = "cas";
size = sz;
uint dc = ir[1];
uint du = ir[1] >> 6;
src = make_dn(dc) + "," + make_dn(du);
dst = make_ea();
}
// CAS2 の共通部分
void
Disasm::ops_cas2(Disasm::Size sz)
{
name = "cas2";
size = sz;
fetch16();
uint dc1 = ir[1] & 7;
uint du1 = ir[1] >> 6;
uint rn1 = ir[1] >> 12;
fetch16();
uint dc2 = ir[2] & 7;
uint du2 = ir[2] >> 6;
uint rn2 = ir[2] >> 12;
src = make_dn(dc1) + ":" + make_dn(dc2) + ","
+ make_dn(du1) + ":" + make_dn(du2);
dst = "(" + make_rn(rn1) + "):(" + make_rn(rn2) + ")";
}
// %0000_101011_mmmrrr CAS.B Dc,Du,<ea>
OP_DEF(cas_b)
{
ops_cas(Size::B);
}
// %0000_110000_mmmrrr CMPI.B #<imm>,<ea>
OP_DEF(cmpi_b)
{
name = "cmpi";
size = Size::B;
src = imm8();
dst = make_ea();
}
// %0000_110001_mmmrrr CMPI.W #<imm>,<ea>
OP_DEF(cmpi_w)
{
name = "cmpi";
size = Size::W;
src = imm16();
dst = make_ea();
}
// %0000_110010_mmmrrr CMPI.L #<imm>,<ea>
OP_DEF(cmpi_l)
{
name = "cmpi";
size = Size::L;
src = imm32();
dst = make_ea();
}
// %0000_110011_mmmrrr CAS.W Dc,Du,<ea>
// %0000_110011_111100 CAS2.W Dc1:Dc2,Du1:Du2,(Rn1):(Rn2)
OP_DEF(cas_w)
{
uint n = ir[0] & 0x3f;
if (n == 0x3c) {
// CAS2.W Dc1:Dc2,Du1:Du2,(Rn1):(Rn2)
ops_cas2(Size::W);
} else {
// CAS.W Dc,Du,<ea>
ops_cas(Size::W);
}
}
// MOVES の共通部分
void
Disasm::ops_moves(Disasm::Size sz)
{
fetch16();
name = "moves";
size = sz;
if ((ir[1] & 0x0800) == 0) {
// MOVES <ea>,Rn
src = make_ea();
dst = make_rn(ir[1] >> 12);
} else {
// MOVES Rn,<ea>
src = make_rn(ir[1] >> 12);
dst = make_ea();
}
}
// %0000_111000_mmmrrr MOVES.B <ea>,Rn
OP_DEF(moves_b)
{
ops_moves(Size::B);
}
// %0000_111001_mmmrrr MOVES.W <ea>,Rn
OP_DEF(moves_w)
{
ops_moves(Size::W);
}
// %0000_111010_mmmrrr MOVES.L <ea>,Rn
OP_DEF(moves_l)
{
ops_moves(Size::L);
}
// %0000_111011_mmmrrr CAS.L Dc,Du,<ea>
// %0000_111011_111100 CAS2.L Dc1:Dc2,Du1:Du2,(Rn1):(Rn2)
OP_DEF(cas_l)
{
uint n = ir[0] & 0x3f;
if (n == 0x3c) {
// CAS2.L Dc1:Dc2,Du1:Du2,(Rn1):(Rn2)
ops_cas2(Size::L);
} else {
// CAS.L Dc,Du,<ea>
ops_cas(Size::L);
}
}
// MOVE.{BWL} <src>,<dst> の共通部分
void
Disasm::ops_move(Disasm::Size sz)
{
name = "move";
size = sz;
src = make_ea();
uint dstea = ((ir[0] >> 9) & 7) | ((ir[0] >> 3) & 0x38);
dst = make_ea(dstea);
}
// %0001_xxx000_mmmrrr MOVE.B <ea>,Dx
OP_DEF(move_b_ea_dn)
{
ops_move(Size::B);
}
// %0001_xxx010_mmmrrr MOVE.B <ea>,(Ax)
OP_DEF(move_b_ea_anin)
{
ops_move(Size::B);
}
// %0001_xxx011_mmmrrr MOVE.B <ea>,(Ax)+
OP_DEF(move_b_ea_anpi)
{
ops_move(Size::B);
}
// %0001_xxx100_mmmrrr MOVE.B <ea>,-(Ax)
OP_DEF(move_b_ea_anpd)
{
ops_move(Size::B);
}
// %0001_xxx101_mmmrrr MOVE.B <ea>,d16(Ax)
OP_DEF(move_b_ea_andi)
{
ops_move(Size::B);
}
// %0001_xxx110_mmmrrr MOVE.B <ea>,(Ax,IX)
OP_DEF(move_b_ea_anix)
{
ops_move(Size::B);
}
// %0001_000111_mmmrrr MOVE.B <ea>,Abs.W
OP_DEF(move_b_ea_absw)
{
ops_move(Size::B);
}
// %0001_001111_mmmrrr MOVE.B <ea>,Abs.L
OP_DEF(move_b_ea_absl)
{
ops_move(Size::B);
}
// %0010_xxx000_mmmrrr MOVE.L <ea>,Dx
OP_DEF(move_l_ea_dn)
{
ops_move(Size::L);
}
// %0010_xxx001_mmmrrr MOVEA.L <ea>,Ax
OP_DEF(movea_l)
{
name = "movea";
size = Size::L;
src = make_ea();
dst = make_an(ir[0] >> 9);
}
// %0010_xxx010_mmmrrr MOVE.L <ea>,(Ax)
OP_DEF(move_l_ea_anin)
{
ops_move(Size::L);
}
// %0010_xxx011_mmmrrr MOVE.L <ea>,(Ax)+
OP_DEF(move_l_ea_anpi)
{
ops_move(Size::L);
}
// %0010_xxx100_mmmrrr MOVE.L <ea>,-(Ax)
OP_DEF(move_l_ea_anpd)
{
ops_move(Size::L);
}
// %0010_xxx101_mmmrrr MOVE.L <ea>,d16(Ax)
OP_DEF(move_l_ea_andi)
{
ops_move(Size::L);
}
// %0010_xxx110_mmmrrr MOVE.L <ea>,(Ax,IX)
OP_DEF(move_l_ea_anix)
{
ops_move(Size::L);
}
// %0010_000111_mmmrrr MOVE.L <ea>,Abs.W
OP_DEF(move_l_ea_absw)
{
ops_move(Size::L);
}
// %0010_001111_mmmrrr MOVE.L <ea>,Abs.L
OP_DEF(move_l_ea_absl)
{
ops_move(Size::L);
}
// %0011_xxx000_mmmrrr MOVE.W <ea>,Dx
OP_DEF(move_w_ea_dn)
{
ops_move(Size::W);
}
// %0011_xxx001_mmmrrr MOVEA.W <ea>,Ax
OP_DEF(movea_w)
{
name = "movea";
size = Size::W;
src = make_ea();
dst = make_an(ir[0] >> 9);
}
// %0011_xxx010_mmmrrr MOVE.W <ea>,(Ax)
OP_DEF(move_w_ea_anin)
{
ops_move(Size::W);
}
// %0011_xxx011_mmmrrr MOVE.W <ea>,(Ax)+
OP_DEF(move_w_ea_anpi)
{
ops_move(Size::W);
}
// %0011_xxx100_mmmrrr MOVE.W <ea>,-(Ax)
OP_DEF(move_w_ea_anpd)
{
ops_move(Size::W);
}
// %0011_xxx101_mmmrrr MOVE.W <ea>,d16(Ax)
OP_DEF(move_w_ea_andi)
{
ops_move(Size::W);
}
// %0011_xxx110_mmmrrr MOVE.W <ea>,(Ax,IX)
OP_DEF(move_w_ea_anix)
{
ops_move(Size::W);
}
// %0011_000111_mmmrrr MOVE.W <ea>,Abs.W
OP_DEF(move_w_ea_absw)
{
ops_move(Size::W);
}
// %0011_001111_mmmrrr MOVE.W <ea>,Abs.L
OP_DEF(move_w_ea_absl)
{
ops_move(Size::W);
}
// %0100_000000_mmmrrr NEGX.B <ea>
OP_DEF(negx_b)
{
name = "negx";
size = Size::B;
src = make_ea();
}
// %0100_000001_mmmrrr NEGX.W <ea>
OP_DEF(negx_w)
{
name = "negx";
size = Size::W;
src = make_ea();
}
// %0100_000010_mmmrrr NEGX.L <ea>
OP_DEF(negx_l)
{
name = "negx";
size = Size::L;
src = make_ea();
}
// %0100_000011_mmmrrr MOVE.W SR,<ea>
OP_DEF(move_sr_ea)
{
name = "move";
size = Size::W;
src = make_reg(Reg::SR);
dst = make_ea();
}
// %0100_xxx100_mmmrrr CHK.L <ea>,Dx
OP_DEF(chk_l)
{
name = "chk";
size = Size::L;
src = make_ea();
dst = make_dn(ir[0] >> 9);
}
// %0100_xxx110_mmmrrr CHK.W <ea>,Dx
OP_DEF(chk_w)
{
name = "chk";
size = Size::W;
src = make_ea();
dst = make_dn(ir[0] >> 9);
}
// %0100_xxx111_mmmrrr LEA.L <ea>,Ax
// %0100_100111_000yyy EXTB.L Dy
OP_DEF(lea)
{
uint n = ir[0] & 0x3f;
uint x = (ir[0] >> 9) & 7;
if (n < 8) {
if (x == 4) {
// EXTB.L Dy
name = "extb";
size = Size::L;
src = make_dn(ir[0]);
} else {
OP_FUNC(illegal);
}
} else {
// LEA.L <ea>,Ax
name = "lea";
size = Size::L;
src = make_ea();
dst = make_an(x);
}
}
// %0100_001000_mmmrrr CLR.B <ea>
OP_DEF(clr_b)
{
name = "clr";
size = Size::B;
src = make_ea();
}
// %0100_001001_mmmrrr CLR.W <ea>
OP_DEF(clr_w)
{
name = "clr";
size = Size::W;
src = make_ea();
}
// %0100_001010_mmmrrr CLR.L <ea>
OP_DEF(clr_l)
{
name = "clr";
size = Size::L;
src = make_ea();
}
// %0100_001011_mmmrrr MOVE.W CCR,<ea>
OP_DEF(move_ccr_ea)
{
// MOVE to/from CCR のサイズは .W
name = "move";
size = Size::W;
src = make_reg(Reg::CCR);
dst = make_ea();
}
// %0100_010000_mmmrrr NEG.B <ea>
OP_DEF(neg_b)
{
name = "neg";
size = Size::B;
src = make_ea();
}
// %0100_010001_mmmrrr NEG.W <ea>
OP_DEF(neg_w)
{
name = "neg";
size = Size::W;
src = make_ea();
}
// %0100_010010_mmmrrr NEG.L <ea>
OP_DEF(neg_l)
{
name = "neg";
size = Size::L;
src = make_ea();
}
// %0100_010011_mmmrrr MOVE.W <ea>,CCR
OP_DEF(move_ea_ccr)
{
// MOVE to/from CCR のサイズは .W
name = "move";
size = Size::W;
src = make_ea();
dst = make_reg(Reg::CCR);
}
// %0100_011000_mmmrrr NOT.B <ea>
OP_DEF(not_b)
{
name = "not";
size = Size::B;
src = make_ea();
}
// %0100_011001_mmmrrr NOT.W <ea>
OP_DEF(not_w)
{
name = "not";
size = Size::W;
src = make_ea();
}
// %0100_011010_mmmrrr NOT.L <ea>
OP_DEF(not_l)
{
name = "not";
size = Size::L;
src = make_ea();
}
// %0100_011011_mmmrrr MOVE.W <ea>,SR
OP_DEF(move_ea_sr)
{
name = "move";
size = Size::W;
src = make_ea();
dst = make_reg(Reg::SR);
}
// %0100_100000_mmmrrr NBCD.B <ea>
// %0100_100000_001yyy LINK.L Ay,#<imm>
OP_DEF(nbcd)
{
uint mm = (ir[0] >> 3) & 7;
if (mm == 1) {
// LINK.L Ay,#<imm>
name = "link";
size = Size::L;
src = make_an(ir[0]);
dst = "#" + disp32();
} else {
// NBCD.B <ea>
name = "nbcd";
size = Size::B;
src = make_ea();
}
}
// %0100_100001_000yyy SWAP.W Dy
// %0100_100001_001nnn BKPT #<imm>
// %0100_100001_mmmrrr PEA.L <ea>
OP_DEF(pea)
{
uint n = ir[0] & 0x3f;
if (n < 8) {
// SWAP.W Dy
name = "swap";
size = Size::W;
src = make_dn(n);
} else if (n < 16) {
// BKPT #<imm>
name = "bkpt";
src = string_format("#%d", ir[0] & 7);
} else {
// PEA.L <ea>
name = "pea";
size = Size::L;
src = make_ea();
}
}
// MOVEM/EXT の共通部分
void
Disasm::ops_movem_ext(Disasm::Size sz)
{
uint n = ir[0] & 0x3f;
size = sz;
if (n < 8) {
// EXT.W Dy
name = "ext";
src = make_dn(ir[0]);
} else {
// MOVEM.W <list>,<ea>
fetch16();
name = "movem";
src = make_reglist();
dst = make_ea();
}
}
// %0100_100010_000yyy EXT.W Dy
// %0100_100010_mmmrrr MOVEM.W <list>,<ea>
OP_DEF(movem_w_mem)
{
ops_movem_ext(Size::W);
}
// %0100_100011_000yyy EXT.L Dy
// %0100_100011_mmmrrr MOVEM.L <list>,<ea>
OP_DEF(movem_l_mem)
{
ops_movem_ext(Size::L);
}
// %0100_101000_mmmrrr TST.B <ea>
OP_DEF(tst_b)
{
name = "tst";
size = Size::B;
src = make_ea();
}
// %0100_101001_mmmrrr TST.W <ea>
OP_DEF(tst_w)
{
name = "tst";
size = Size::W;
src = make_ea();
}
// %0100_101010_mmmrrr TST.L <ea>
OP_DEF(tst_l)
{
name = "tst";
size = Size::L;
src = make_ea();
}
// %0100_101011_mmmrrr TAS.B <ea>
// %0100_101011_111100 ILLEGAL
OP_DEF(tas)
{
uint n = ir[0] & 0x3f;
if (n == 0x3c) {
// ILLEGAL
name = "illegal";
} else {
// TAS.B <ea>
name = "tas";
size = Size::B;
src = make_ea();
}
}
// %0100_110000_mmmrrr MUL{U,S}.L <ea>,Dl
OP_DEF(mul)
{
fetch16();
if ((ir[1] & 0x0800) == 0) {
name = "mulu";
} else {
name = "muls";
}
size = Size::L;
src = make_ea();
if ((ir[1] & 0x0400) == 0) {
dst = make_dn(ir[1] >> 12);
} else {
dst = make_dn(ir[1]) + ":" + make_dn(ir[1] >> 12);
}
}
// %0100_110001_mmmrrr DIV{U,UL,S,SL}.L <ea>,Dq
OP_DEF(div)
{
fetch16();
if ((ir[1] & 0x0800) == 0) {
name = "divu";
} else {
name = "divs";
}
size = Size::L;
src = make_ea();
uint dr = ir[1] & 7;
uint dq = (ir[1] >> 12) & 7;
if ((ir[1] & 0x0400) == 0) {
if (dr == dq) {
dst = make_dn(dr);
} else {
dst = make_dn(dr) + ":" + make_dn(dq);
}
} else {
name += "l";
dst = make_dn(dr) + ":" + make_dn(dq);
}
}
// %0100_110010_mmmrrr MOVEM.W <ea>,<list>
OP_DEF(movem_w)
{
fetch16();
name = "movem";
size = Size::W;
src = make_ea();
dst = make_reglist();
}
// %0100_110011_mmmrrr MOVEM.L <ea>,<list>
OP_DEF(movem_l)
{
fetch16();
name = "movem";
size = Size::L;
src = make_ea();
dst = make_reglist();
}
// %0100_111001_00nnnn TRAP #<vector>
// %0100_111001_010yyy LINK.W Ay,#<imm>
// %0100_111001_011yyy UNLK Ay
// %0100_111001_100yyy MOVE.L Ay,USP
// %0100_111001_101yyy MOVE.L USP,Ay
// %0100_111001_110000 RESET
// %0100_111001_110001 NOP
// %0100_111001_110010 STOP #<imm>
// %0100_111001_110011 RTE
// %0100_111001_110100 RTD #<imm>
// %0100_111001_110101 RTS
// %0100_111001_110110 TRAPV
// %0100_111001_110111 RTR
// %0100_111001_111010 MOVEC.L Rc,Rn
// %0100_111001_111011 MOVEC.L Rn,Rc
OP_DEF(trap)
{
uint n = ir[0] & 0x3f;
switch (n) {
case 0x00 ... 0x0f: // TRAP #<vector>
name = "trap";
src = string_format("#%d", n);
break;
case 0x10 ... 0x17: // LINK.W Ay,#<imm>
name = "link";
size = Size::W;
src = make_an(ir[0]);
dst = "#" + disp16();
break;
case 0x18 ... 0x1f: // UNLK Ay
name = "unlk";
src = make_an(ir[0]);
break;
case 0x20 ... 0x27: // MOVE.L Ay,USP
name = "move";
size = Size::L;
src = make_an(ir[0]);
dst = make_reg(Reg::USP);
break;
case 0x28 ... 0x2f: // MOVE.L USP,Ay
name = "move";
size = Size::L;
src = make_reg(Reg::USP);
dst = make_an(ir[0]);
break;
case 0x30: // RESET
name = "reset";
break;
case 0x31: // NOP
name = "nop";
break;
case 0x32: // STOP #<imm>
name = "stop";
src = imm16();
break;
case 0x33: // RTE
name = "rte";
break;
case 0x34: // RTD #<imm>
name = "rtd";
src = imm16();
break;
case 0x35: // RTS
name = "rts";
break;
case 0x36: // TRAPV
name = "trapv";
break;
case 0x37: // RTR
name = "rtr";
break;
case 0x3a: // MOVEC.L Rc,Rn
fetch16();
name = "movec";
size = Size::L;
src = make_movec();
dst = make_rn(ir[1] >> 12);
break;
case 0x3b: // MOVEC.L Rn,Rc
fetch16();
name = "movec";
size = Size::L;
src = make_rn(ir[1] >> 12);
dst = make_movec();
break;
default:
OP_FUNC(illegal);
break;
}
}
// %0100_111010_mmmrrr JSR <ea>
OP_DEF(jsr)
{
name = "jsr";
src = make_ea();
}
// %0100_111011_mmmrrr JMP <ea>
OP_DEF(jmp)
{
name = "jmp";
src = make_ea();
}
// %0101_qqq000_mmmrrr ADDQ.B #qqq,<ea>
OP_DEF(addq_b)
{
name = "addq";
size = Size::B;
src = make_q8();
dst = make_ea();
}
// %0101_qqq001_mmmrrr ADDQ.W #qqq,<ea>
// %0101_qqq001_001yyy ADDQ.W #qqq,Ay (.Lと等価)
OP_DEF(addq_w)
{
// ニーモニック上は ADDQ.W #q,Ay を分ける必要はない
name = "addq";
size = Size::W;
src = make_q8();
dst = make_ea();
}
// %0101_qqq010_mmmrrr ADDQ.L #qqq,<ea>
// %0101_qqq010_001yyy ADDQ.L #qqq,Ay
OP_DEF(addq_l)
{
// ニーモニック上は ADDQ.L #q,Ay を分ける必要はない
name = "addq";
size = Size::L;
src = make_q8();
dst = make_ea();
}
// Scc/SF のメイン部分。
void
Disasm::ops_scc()
{
uint n = ir[0] & 0x3f;
uint cc = (ir[0] >> 8) & 15;
switch (n) {
case 0x00 ... 0x07: // Scc.B Dn
case 0x10 ... 0x39: // Scc.B <ea>
name = "s";
name += conditions[cc];
size = Size::B;
src = make_ea();
break;
case 0x08 ... 0x0f: // DBcc.W Dy,<label>
if (cc == 1) {
name = "dbra";
} else {
name = "db";
name += conditions[cc];
}
size = Size::W;
src = make_dn(ir[0]);
dst = addr32(pc0 + 2 + (int32)(int16)fetch16());
break;
case 0x3a: // TRAPcc.W #<imm>
name = "trap";
name += conditions[cc];
size = Size::W;
src = imm16();
break;
case 0x3b: // TRAPcc.L #<imm>
name = "trap";
name += conditions[cc];
size = Size::L;
src = imm32();
break;
case 0x3c: // TRAPcc
name = "trap";
name += conditions[cc];
break;
default:
OP_FUNC(illegal);
break;
}
}
// %0101_000011_mmmrrr ST.B <ea>
// %0101_000011_001yyy DBT.W Dy,<label>
// %0101_000011_111010 TRAPT.W #<imm>
// %0101_000011_111011 TRAPT.L #<imm>
// %0101_000011_111100 TRAPT
OP_DEF(st)
{
ops_scc();
}
// %0101_qqq100_mmmrrr SUBQ.B #qqq,<ea>
OP_DEF(subq_b)
{
name = "subq";
size = Size::B;
src = make_q8();
dst = make_ea();
}
// %0101_qqq101_mmmrrr SUBQ.W #qqq,<ea>
// %0101_qqq101_001yyy SUBQ.W #qqq,Ay (.Lと等価)
OP_DEF(subq_w)
{
// ニーモニック上は SUBQ.W #q,Ay を分ける必要はない
name = "subq";
size = Size::W;
src = make_q8();
dst = make_ea();
}
// %0101_qqq110_mmmrrr SUBQ.L #qqq,<ea>
// %0101_qqq110_001yyy SUBQ.L #qqq,Ay
OP_DEF(subq_l)
{
// ニーモニック上は SUBQ.L #q,Ay を分ける必要はない
name = "subq";
size = Size::L;
src = make_q8();
dst = make_ea();
}
// %0101_000111_mmmrrr SF.B <ea>
// %0101_000111_001yyy DBRA.W Dy,<label>
// %0101_000111_111010 TRAPF.W #<imm>
// %0101_000111_111011 TRAPF.L #<imm>
// %0101_000111_111100 TRAPF
OP_DEF(sf)
{
ops_scc();
}
// %0101_001011_mmmrrr SHI.B <ea>
// %0101_001011_001yyy DBHI.W Dy,<label>
// %0101_001011_111010 TRAPHI.W #<imm>
// %0101_001011_111011 TRAPHI.L #<imm>
// %0101_001011_111100 TRAPHI
OP_DEF(shi)
{
ops_scc();
}
// %0101_001111_mmmrrr SLS.B <ea>
// %0101_001111_001yyy DBLS.W Dy,<label>
// %0101_001111_111010 TRAPLS.W #<imm>
// %0101_001111_111011 TRAPLS.L #<imm>
// %0101_001111_111100 TRAPLS
OP_DEF(sls)
{
ops_scc();
}
// %0101_010011_mmmrrr SCC.B <ea>
// %0101_010011_001yyy DBCC.W Dy,<label>
// %0101_010011_111010 TRAPCC.W #<imm>
// %0101_010011_111011 TRAPCC.L #<imm>
// %0101_010011_111100 TRAPCC
OP_DEF(scc)
{
ops_scc();
}
// %0101_010111_mmmrrr SCS.B <ea>
// %0101_010111_001yyy DBCS.W Dy,<label>
// %0101_010111_111010 TRAPCS.W #<imm>
// %0101_010111_111011 TRAPCS.L #<imm>
// %0101_010111_111100 TRAPCS
OP_DEF(scs)
{
ops_scc();
}
// %0101_011011_mmmrrr SNE.B <ea>
// %0101_011011_001yyy DBNE.W Dy,<label>
// %0101_011011_111010 TRAPNE.W #<imm>
// %0101_011011_111011 TRAPNE.L #<imm>
// %0101_011011_111100 TRAPNE
OP_DEF(sne)
{
ops_scc();
}
// %0101_011111_mmmrrr SEQ.B <ea>
// %0101_011111_001yyy DBEQ.W Dy,<label>
// %0101_011111_111010 TRAPEQ.W #<imm>
// %0101_011111_111011 TRAPEQ.L #<imm>
// %0101_011111_111100 TRAPEQ
OP_DEF(seq)
{
ops_scc();
}
// %0101_100011_mmmrrr SVC.B <ea>
// %0101_100011_001yyy DBVC.W Dy,<label>
// %0101_100011_111010 TRAPVC.W #<imm>
// %0101_100011_111011 TRAPVC.L #<imm>
// %0101_100011_111100 TRAPVC
OP_DEF(svc)
{
ops_scc();
}
// %0101_100111_mmmrrr SVS.B <ea>
// %0101_100111_001yyy DBVS.W Dy,<label>
// %0101_100111_111010 TRAPVS.W #<imm>
// %0101_100111_111011 TRAPVS.L #<imm>
// %0101_100111_111100 TRAPVS
OP_DEF(svs)
{
ops_scc();
}
// %0101_101011_mmmrrr SPL.B <ea>
// %0101_101011_001yyy DBPL.W Dy,<label>
// %0101_101011_111010 TRAPPL.W #<imm>
// %0101_101011_111011 TRAPPL.L #<imm>
// %0101_101011_111100 TRAPPL
OP_DEF(spl)
{
ops_scc();
}
// %0101_101111_mmmrrr SMI.B <ea>
// %0101_101111_001yyy DBMI.W Dy,<label>
// %0101_101111_111010 TRAPMI.W #<imm>
// %0101_101111_111011 TRAPMI.L #<imm>
// %0101_101111_111100 TRAPMI
OP_DEF(smi)
{
ops_scc();
}
// %0101_110011_mmmrrr SGE.B <ea>
// %0101_110011_001yyy DBGE.W Dy,<label>
// %0101_110011_111010 TRAPGE.W #<imm>
// %0101_110011_111011 TRAPGE.L #<imm>
// %0101_110011_111100 TRAPGE
OP_DEF(sge)
{
ops_scc();
}
// %0101_110111_mmmrrr SLT.B <ea>
// %0101_110111_001yyy DBLT.W Dy,<label>
// %0101_110111_111010 TRAPLT.W #<imm>
// %0101_110111_111011 TRAPLT.L #<imm>
// %0101_110111_111100 TRAPLT
OP_DEF(slt)
{
ops_scc();
}
// %0101_111011_mmmrrr SGT.B <ea>
// %0101_111011_001yyy DBGT.W Dy,<label>
// %0101_111011_111010 TRAPGT.W #<imm>
// %0101_111011_111011 TRAPGT.L #<imm>
// %0101_111011_111100 TRAPGT
OP_DEF(sgt)
{
ops_scc();
}
// %0101_111111_mmmrrr SLE.B <ea>
// %0101_111111_001yyy DBLE.W Dy,<label>
// %0101_111111_111010 TRAPLE.W #<imm>
// %0101_111111_111011 TRAPLE.L #<imm>
// %0101_111111_111100 TRAPLE
OP_DEF(sle)
{
ops_scc();
}
// BRA/BSR/Bcc の共通部分。
void
Disasm::ops_bcc()
{
uint cond = (ir[0] >> 8) & 0x0f;
uint32 disp = ir[0] & 0xff;
switch (cond) {
case 0: name = "bra"; break;
case 1: name = "bsr"; break;
default:
name = "b";
name += conditions[cond];
break;
}
if (disp == 0) {
// Bxx.W <label>
size = Size::W;
disp = (int32)(int16)fetch16();
} else if (disp == 0xff) {
// Bxx.L <label>
size = Size::L;
disp = (int32)fetch32();
} else {
// Bxx.B <label>
size = Size::B;
disp = (int32)(int8)disp;
}
src = addr32(pc0 + 2 + disp);
}
// %0110_000000_000000 BRA.W <label>
// %0110_0000nn_nnnnnn BRA.B <label>
// %0110_000011_111111 BRA.L <label>
OP_DEF(bra)
{
ops_bcc();
}
// %0110_000100_000000 BSR.W <label>
// %0110_0001nn_nnnnnn BSR.B <label>
// %0110_000111_111111 BSR.L <label>
OP_DEF(bsr)
{
ops_bcc();
}
// %0110_001000_000000 BHI.W <label>
// %0110_0010nn_nnnnnn BHI.B <label>
// %0110_001011_111111 BHI.L <label>
OP_DEF(bhi)
{
ops_bcc();
}
// %0110_001100_000000 BLS.W <label>
// %0110_0011nn_nnnnnn BLS.B <label>
// %0110_001111_111111 BLS.L <label>
OP_DEF(bls)
{
ops_bcc();
}
// %0110_010000_000000 BCC.W <label>
// %0110_0100nn_nnnnnn BCC.B <label>
// %0110_010011_111111 BCC.L <label>
OP_DEF(bcc)
{
ops_bcc();
}
// %0110_010100_000000 BCS.W <label>
// %0110_0101nn_nnnnnn BCS.B <label>
// %0110_010111_111111 BCS.L <label>
OP_DEF(bcs)
{
ops_bcc();
}
// %0110_011000_000000 BNE.W <label>
// %0110_0110nn_nnnnnn BNE.B <label>
// %0110_011011_111111 BNE.L <label>
OP_DEF(bne)
{
ops_bcc();
}
// %0110_011100_000000 BEQ.W <label>
// %0110_0111nn_nnnnnn BEQ.B <label>
// %0110_011111_111111 BEQ.L <label>
OP_DEF(beq)
{
ops_bcc();
}
// %0110_100000_000000 BVC.W <label>
// %0110_1000nn_nnnnnn BVC.B <label>
// %0110_100011_111111 BVC.L <label>
OP_DEF(bvc)
{
ops_bcc();
}
// %0110_100100_000000 BVS.W <label>
// %0110_1001nn_nnnnnn BVS.B <label>
// %0110_100111_111111 BVS.L <label>
OP_DEF(bvs)
{
ops_bcc();
}
// %0110_101000_000000 BPL.W <label>
// %0110_1010nn_nnnnnn BPL.B <label>
// %0110_101011_111111 BPL.L <label>
OP_DEF(bpl)
{
ops_bcc();
}
// %0110_101100_000000 BMI.W <label>
// %0110_1011nn_nnnnnn BMI.B <label>
// %0110_101111_111111 BMI.L <label>
OP_DEF(bmi)
{
ops_bcc();
}
// %0110_110000_000000 BGE.W <label>
// %0110_1100nn_nnnnnn BGE.B <label>
// %0110_110011_111111 BGE.L <label>
OP_DEF(bge)
{
ops_bcc();
}
// %0110_110100_000000 BLT.W <label>
// %0110_1101nn_nnnnnn BLT.B <label>
// %0110_110111_111111 BLT.L <label>
OP_DEF(blt)
{
ops_bcc();
}
// %0110_111000_000000 BGT.W <label>
// %0110_1110nn_nnnnnn BGT.B <label>
// %0110_111011_111111 BGT.L <label>
OP_DEF(bgt)
{
ops_bcc();
}
// %0110_111100_000000 BLE.W <label>
// %0110_1111nn_nnnnnn BLE.B <label>
// %0110_111111_111111 BLE.L <label>
OP_DEF(ble)
{
ops_bcc();
}
// %0111_xxx0nn_nnnnnn MOVEQ.L #<imm>,Dx
OP_DEF(moveq)
{
uint8 val = ir[0] & 0xff;
// IOCS コールを表示する。XXX 機種判定はまだしてない
// IOCS コールは大抵
// 70NN moveq.l #nn,d0
// 4e4f trap #15
// という命令列になっているので、これを検出する。
uint16 next = peek16();
if (next == 0x4e4f) {
// IOCS コールと確定したら TRAP のワードも取り出しておく
fetch16();
name = "IOCS";
src = x68k_iocscall[(uint)val] ?: "<undefined>";
return;
}
name = "moveq";
size = Size::L;
// 負数なら 32bit で書いてみるか
if ((val & 0x80)) {
src = "#" + hex32((int32)(int8)val);
} else {
src = "#" + hex8(val);
}
dst = make_dn(ir[0] >> 9);
}
// %1000_xxx000_mmmrrr OR.B <ea>,Dx
OP_DEF(or_b_ea_dn)
{
name = "or";
size = Size::B;
src = make_ea();
dst = make_dn(ir[0] >> 9);
}
// %1000_xxx001_mmmrrr OR.W <ea>,Dx
OP_DEF(or_w_ea_dn)
{
name = "or";
size = Size::W;
src = make_ea();
dst = make_dn(ir[0] >> 9);
}
// %1000_xxx010_mmmrrr OR.L <ea>,Dx
OP_DEF(or_l_ea_dn)
{
name = "or";
size = Size::L;
src = make_ea();
dst = make_dn(ir[0] >> 9);
}
// %1000_xxx011_mmmrrr DIVU.W <ea>,Dx
OP_DEF(divu_w)
{
name = "divu";
size = Size::W;
src = make_ea();
dst = make_dn(ir[0] >> 9);
}
// %1000_xxx100_000yyy SBCD.B Dy,Dx
// %1000_xxx100_001yyy SBCD.B -(Ay),-(Ax)
// %1000_xxx100_mmmrrr OR.B Dx,<ea>
OP_DEF(or_b_dn_ea)
{
uint n = ir[0] & 0x3f;
uint x = ir[0] >> 9;
if (n < 8) {
// SBCD.B Dy,Dx
name = "sbcd";
size = Size::B;
src = make_dn(n);
dst = make_dn(x);
} else if (n < 16) {
// SBCD.B -(Ay),-(An)
name = "sbcd";
size = Size::B;
src = make_anpd(n);
dst = make_anpd(x);
} else {
// OR.B Dx,<ea>
name = "or";
size = Size::B;
src = make_dn(x);
dst = make_ea();
}
}
// %1000_xxx101_000yyy PACK Dy,Dx,#<imm>
// %1000_xxx101_001yyy PACK -(Ay),-(Ax),#<imm>
// %1000_xxx101_mmmrrr OR.W Dx,<ea>
OP_DEF(or_w_dn_ea)
{
uint n = ir[0] & 0x3f;
uint x = ir[0] >> 9;
if (n < 8) {
name = "pack";
src = make_dn(n) + "," + make_dn(x);
dst = imm16();
} else if (n < 16) {
name = "pack";
src = make_anpd(n) + "," + make_anpd(x);
dst = imm16();
} else {
// OR.W Dx,<ea>
name = "or";
size = Size::W;
src = make_dn(x);
dst = make_ea();
}
}
// %1000_xxx110_000yyy UNPK Dy,Dx,#<imm>
// %1000_xxx110_001yyy UNPK -(Ay),-(Ax),#<imm>
// %1000_xxx110_mmmrrr OR.L Dx,<ea>
OP_DEF(or_l_dn_ea)
{
uint n = ir[0] & 0x3f;
uint x = ir[0] >> 9;
if (n < 8) {
name = "unpk";
src = make_dn(n) + "," + make_dn(x);
dst = imm16();
} else if (n < 16) {
name = "unpk";
src = make_anpd(n) + "," + make_anpd(x);
dst = imm16();
} else {
// OR.L Dx,<ea>
name = "or";
size = Size::L;
src = make_dn(x);
dst = make_ea();
}
}
// %1000_xxx111_mmmrrr DIVS.W <ea>,Dx
OP_DEF(divs_w)
{
name = "divs";
size = Size::W;
src = make_ea();
dst = make_dn(ir[0] >> 9);
}
// %1001_xxx000_mmmrrr SUB.B <ea>,Dx
OP_DEF(sub_b_ea_dn)
{
name = "sub";
size = Size::B;
src = make_ea();
dst = make_dn(ir[0] >> 9);
}
// %1001_xxx001_mmmrrr SUB.W <ea>,Dx
OP_DEF(sub_w_ea_dn)
{
name = "sub";
size = Size::W;
src = make_ea();
dst = make_dn(ir[0] >> 9);
}
// %1001_xxx010_mmmrrr SUB.L <ea>,Dx
OP_DEF(sub_l_ea_dn)
{
name = "sub";
size = Size::L;
src = make_ea();
dst = make_dn(ir[0] >> 9);
}
// %1001_xxx011_mmmrrr SUBA.W <ea>,Ax
OP_DEF(suba_w)
{
name = "suba";
size = Size::W;
src = make_ea();
dst = make_an(ir[0] >> 9);
}
// SUB の共通部分
void
Disasm::ops_sub(Disasm::Size sz)
{
uint n = ir[0] & 0x3f;
uint x = ir[0] >> 9;
size = sz;
if (n < 8) {
// SUBX.B Dy,Dx
name = "subx";
src = make_dn(n);
dst = make_dn(x);
} else if (n < 16) {
// SUBX.B -(Ay),-(Ax)
name = "subx";
src = make_anpd(n);
dst = make_anpd(x);
} else {
// SUB.B Dx,<ea>
name = "sub";
src = make_dn(x);
dst = make_ea();
}
}
// %1001_xxx100_000yyy SUBX.B Dy,Dx
// %1001_xxx100_001yyy SUBX.B -(Ay),-(Ax)
// %1001_xxx100_mmmrrr SUB.B Dx,<ea>
OP_DEF(sub_b_dn_ea)
{
ops_sub(Size::B);
}
// %1001_xxx101_000yyy SUBX.W Dy,Dx
// %1001_xxx101_001yyy SUBX.W -(Ay),-(Ax)
// %1001_xxx101_mmmrrr SUB.W Dx,<ea>
OP_DEF(sub_w_dn_ea)
{
ops_sub(Size::W);
}
// %1001_xxx110_000yyy SUBX.L Dy,Dx
// %1001_xxx110_001yyy SUBX.L -(Ay),-(Ax)
// %1001_xxx110_mmmrrr SUB.L Dx,<ea>
OP_DEF(sub_l_dn_ea)
{
ops_sub(Size::L);
}
// %1001_xxx111_mmmrrr SUBA.L <ea>,Ax
OP_DEF(suba_l)
{
name = "suba";
size = Size::L;
src = make_ea();
dst = make_an(ir[0] >> 9);
}
// %1010_nnnnnn_nnnnnn A-Line
OP_DEF(aline)
{
name = "<unknown A-Line trap>";
}
// %1011_xxx000_mmmrrr CMP.B <ea>,Dx
OP_DEF(cmp_b)
{
name = "cmp";
size = Size::B;
src = make_ea();
dst = make_dn(ir[0] >> 9);
}
// %1011_xxx001_mmmrrr CMP.W <ea>,Dx
OP_DEF(cmp_w)
{
name = "cmp";
size = Size::W;
src = make_ea();
dst = make_dn(ir[0] >> 9);
}
// %1011_xxx010_mmmrrr CMP.L <ea>,Dx
OP_DEF(cmp_l)
{
name = "cmp";
size = Size::L;
src = make_ea();
dst = make_dn(ir[0] >> 9);
}
// %1011_xxx011_mmmrrr CMPA.W <ea>,Ax
OP_DEF(cmpa_w)
{
name = "cmpa";
size = Size::W;
src = make_ea();
dst = make_an(ir[0] >> 9);
}
void
Disasm::ops_eor_cmpm(Disasm::Size sz)
{
size = sz;
uint mm = (ir[0] >> 3) & 7;
if (mm == 1) {
// CMPM.x (Ay)+,(Ax)+
name = "cmpm";
src = make_anpi(ir[0]);
dst = make_anpi(ir[0] >> 9);
} else {
// EOR.x Dx,<ea>
name = "eor";
src = make_dn(ir[0] >> 9);
dst = make_ea();
}
}
// %1011_xxx100_mmmrrr EOR.B Dx,<ea>
// %1011_xxx100_001yyy CMPM.B (Ay)+,(Ax)+
OP_DEF(eor_b)
{
ops_eor_cmpm(Size::B);
}
// %1011_xxx101_mmmrrr EOR.W Dx,<ea>
// %1011_xxx101_001yyy CMPM.W (Ay)+,(Ax)+
OP_DEF(eor_w)
{
ops_eor_cmpm(Size::W);
}
// %1011_xxx110_mmmrrr EOR.L Dx,<ea>
// %1011_xxx110_001yyy CMPM.L (Ay)+,(Ax)+
OP_DEF(eor_l)
{
ops_eor_cmpm(Size::L);
}
// %1011_xxx111_mmmrrr CMPA.L <ea>,Ax
OP_DEF(cmpa_l)
{
name = "cmpa";
size = Size::L;
src = make_ea();
dst = make_an(ir[0] >> 9);
}
// %1100_xxx000_mmmrrr AND.B <ea>,Dx
OP_DEF(and_b_ea_dn)
{
name = "and";
size = Size::B;
src = make_ea();
dst = make_dn(ir[0] >> 9);
}
// %1100_xxx001_mmmrrr AND.W <ea>,Dx
OP_DEF(and_w_ea_dn)
{
name = "and";
size = Size::W;
src = make_ea();
dst = make_dn(ir[0] >> 9);
}
// %1100_xxx010_mmmrrr AND.L <ea>,Dx
OP_DEF(and_l_ea_dn)
{
name = "and";
size = Size::L;
src = make_ea();
dst = make_dn(ir[0] >> 9);
}
// %1100_xxx011_mmmrrr MULU.W <ea>,Dx
OP_DEF(mulu_w)
{
name = "mulu";
size = Size::W;
src = make_ea();
dst = make_dn(ir[0] >> 9);
}
// %1100_xxx100_000yyy ABCD.B Dy,Dx
// %1100_xxx100_001yyy ABCD.B -(Ay),-(Ax)
// %1100_xxx100_mmmrrr AND.B Dx,<ea>
OP_DEF(and_b_dn_ea)
{
uint n = ir[0] & 0x3f;
uint x = ir[0] >> 9;
if (n < 8) {
// ABCD.B Dy,Dx
name = "abcd";
size = Size::B;
src = make_dn(n);
dst = make_dn(x);
} else if (n < 16) {
// ABCD.B -(Ay),-(Ax)
name = "abcd";
size = Size::B;
src = make_anpd(n);
dst = make_anpd(x);
} else {
// AND.B Dx,<ea>
name = "and";
size = Size::B;
src = make_dn(x);
dst = make_ea();
}
}
// %1100_xxx101_000yyy EXG.L Dx,Dy
// %1100_xxx101_001yyy EXG.L Ax,Ay
// %1100_xxx101_mmmrrr AND.W Dx,<ea>
OP_DEF(and_w_dn_ea)
{
uint n = ir[0] & 0x3f;
uint x = ir[0] >> 9;
if (n < 8) {
// EXG.L Dx,Dy
name = "exg";
size = Size::L;
src = make_dn(x);
dst = make_dn(n);
} else if (n < 16) {
// EXG.L Ax,Ay
name = "exg";
size = Size::L;
src = make_an(x);
dst = make_an(n);
} else {
// AND.W Dx,<ea>
name = "and";
size = Size::W;
src = make_dn(x);
dst = make_ea();
}
}
// %1100_xxx110_001yyy EXG.L Dx,Ay
// %1100_xxx110_mmmrrr AND.L Dx,<ea>
OP_DEF(and_l_dn_ea)
{
uint mm = (ir[0] >> 3) & 7;
if (mm == 1) {
// EXG.L Dx,Ay
name = "exg";
size = Size::L;
src = make_dn(ir[0] >> 9);
dst = make_an(ir[0]);
} else {
// AND.L Dx,<ea>
name = "and";
size = Size::L;
src = make_dn(ir[0] >> 9);
dst = make_ea();
}
}
// %1100_xxx111_mmmrrr MULS.W <ea>,Dx
OP_DEF(muls_w)
{
name = "muls";
size = Size::W;
src = make_ea();
dst = make_dn(ir[0] >> 9);
}
// %1101_xxx000_mmmrrr ADD.B <ea>,Dx
OP_DEF(add_b_ea_dn)
{
name = "add";
size = Size::B;
src = make_ea();
dst = make_dn(ir[0] >> 9);
}
// %1101_xxx001_mmmrrr ADD.W <ea>,Dx
OP_DEF(add_w_ea_dn)
{
name = "add";
size = Size::W;
src = make_ea();
dst = make_dn(ir[0] >> 9);
}
// %1101_xxx010_mmmrrr ADD.L <ea>,Dx
OP_DEF(add_l_ea_dn)
{
name = "add";
size = Size::L;
src = make_ea();
dst = make_dn(ir[0] >> 9);
}
// %1101_xxx011_mmmrrr ADDA.W <ea>,Ax
OP_DEF(adda_w)
{
name = "adda";
size = Size::W;
src = make_ea();
dst = make_an(ir[0] >> 9);
}
// ADD の共通部分
void
Disasm::ops_add(Disasm::Size sz)
{
uint n = ir[0] & 0x3f;
uint x = ir[0] >> 9;
size = sz;
if (n < 8) {
// ADDX.B Dy,Dx
name = "addx";
src = make_dn(n);
dst = make_dn(x);
} else if (n < 16) {
// ADDX.B -(Ay),-(Ax)
name = "addx";
src = make_anpd(n);
dst = make_anpd(x);
} else {
// ADD.B Dx,<ea>
name = "add";
src = make_dn(x);
dst = make_ea();
}
}
// %1101_xxx100_000yyy ADDX.B Dy,Dx
// %1101_xxx100_001yyy ADDX.B -(Ay),-(Ax)
// %1101_xxx100_mmmrrr ADD.B Dx,<ea>
OP_DEF(add_b_dn_ea)
{
ops_add(Size::B);
}
// %1101_xxx101_000yyy ADDX.W Dy,Dx
// %1101_xxx101_001yyy ADDX.W -(Ay),-(Ax)
// %1101_xxx101_mmmrrr ADD.W Dx,<ea>
OP_DEF(add_w_dn_ea)
{
ops_add(Size::W);
}
// %1101_xxx110_000yyy ADDX.L Dy,Dx
// %1101_xxx110_001yyy ADDX.L -(Ay),-(Ax)
// %1101_xxx110_mmmrrr ADD.L Dx,<ea>
OP_DEF(add_l_dn_ea)
{
ops_add(Size::L);
}
// %1101_xxx111_mmmrrr ADDA.L <ea>,Ax
OP_DEF(adda_l)
{
name = "adda";
size = Size::L;
src = make_ea();
dst = make_an(ir[0] >> 9);
}
// シフト・ローテート系の共通部分
void
Disasm::ops_rotate(std::string dir, Disasm::Size sz)
{
uint xx = ir[0] >> 9;
uint mm = (ir[0] >> 3) & 7;
size = sz;
dst = make_dn(ir[0]);
switch (mm) {
case 0: // AS* #qqq,Dy
name = "as" + dir;
src = make_q8();
break;
case 1: // LS* #qqq,Dy
name = "ls" + dir;
src = make_q8();
break;
case 2: // ROX* #qqq,Dy
name = "rox" + dir;
src = make_q8();
break;
case 3: // RO* #qqq,Dy
name = "ro" + dir;
src = make_q8();
break;
case 4: // AS* Dx,Dy
name = "as" + dir;
src = make_dn(xx);
break;
case 5: // LS* Dx,Dy
name = "ls" + dir;
src = make_dn(xx);
break;
case 6: // ROX* Dx,Dy
name = "rox" + dir;
src = make_dn(xx);
break;
case 7: // RO* Dx,Dy
name = "ro" + dir;
src = make_dn(xx);
break;
default:
__unreachable();
}
}
// %1110_qqq000_000yyy ASR.B #qqq,Dy
// %1110_qqq000_001yyy LSR.B #qqq,Dy
// %1110_qqq000_010yyy ROXR.B #qqq,Dy
// %1110_qqq000_011yyy ROR.B #qqq,Dy
// %1110_xxx000_100yyy ASR.B Dx,Dy
// %1110_xxx000_101yyy LSR.B Dx,Dy
// %1110_xxx000_110yyy ROXR.B Dx,Dy
// %1110_xxx000_111yyy ROR.B Dx,Dy
OP_DEF(asr_b_imm)
{
ops_rotate("r", Size::B);
}
// %1110_qqq001_000yyy ASR.W #qqq,Dy
// %1110_qqq001_001yyy LSR.W #qqq,Dy
// %1110_qqq001_010yyy ROXR.W #qqq,Dy
// %1110_qqq001_011yyy ROR.W #qqq,Dy
// %1110_xxx001_100yyy ASR.W Dx,Dy
// %1110_xxx001_101yyy LSR.W Dx,Dy
// %1110_xxx001_110yyy ROXR.W Dx,Dy
// %1110_xxx001_111yyy ROR.W Dx,Dy
OP_DEF(asr_w_imm)
{
ops_rotate("r", Size::W);
}
// %1110_qqq010_000yyy ASR.L #qqq,Dy
// %1110_qqq010_001yyy LSR.L #qqq,Dy
// %1110_qqq010_010yyy ROXR.L #qqq,Dy
// %1110_qqq010_011yyy ROR.L #qqq,Dy
// %1110_xxx010_100yyy ASR.L Dx,Dy
// %1110_xxx010_101yyy LSR.L Dx,Dy
// %1110_xxx010_110yyy ROXR.L Dx,Dy
// %1110_xxx010_111yyy ROR.L Dx,Dy
OP_DEF(asr_l_imm)
{
ops_rotate("r", Size::L);
}
// %1110_000011_mmmrrr ASR.W <ea>
OP_DEF(asr_w)
{
name = "asr";
size = Size::W;
src = make_ea();
}
// %1110_qqq100_000yyy ASL.B #qqq,Dy
// %1110_qqq100_001yyy LSL.B #qqq,Dy
// %1110_qqq100_010yyy ROXL.B #qqq,Dy
// %1110_qqq100_011yyy ROL.B #qqq,Dy
// %1110_xxx100_100yyy ASL.B Dx,Dy
// %1110_xxx100_101yyy LSL.B Dx,Dy
// %1110_xxx100_110yyy ROXL.B Dx,Dy
// %1110_xxx100_111yyy ROL.B Dx,Dy
OP_DEF(asl_b_imm)
{
ops_rotate("l", Size::B);
}
// %1110_qqq101_000yyy ASL.W #qqq,Dy
// %1110_qqq101_001yyy LSL.W #qqq,Dy
// %1110_qqq101_010yyy ROXL.W #qqq,Dy
// %1110_qqq101_011yyy ROL.W #qqq,Dy
// %1110_xxx101_100yyy ASL.W Dx,Dy
// %1110_xxx101_101yyy LSL.W Dx,Dy
// %1110_xxx101_110yyy ROXL.W Dx,Dy
// %1110_xxx101_111yyy ROL.W Dx,Dy
OP_DEF(asl_w_imm)
{
ops_rotate("l", Size::W);
}
// %1110_qqq110_000yyy ASL.L #qqq,Dy
// %1110_qqq110_001yyy LSL.L #qqq,Dy
// %1110_qqq110_010yyy ROXL.L #qqq,Dy
// %1110_qqq110_011yyy ROL.L #qqq,Dy
// %1110_xxx110_100yyy ASL.L Dx,Dy
// %1110_xxx110_101yyy LSL.L Dx,Dy
// %1110_xxx110_110yyy ROXL.L Dx,Dy
// %1110_xxx110_111yyy ROL.L Dx,Dy
OP_DEF(asl_l_imm)
{
ops_rotate("l", Size::L);
}
// %1110_000111_mmmrrr ASL.W <ea>
OP_DEF(asl_w)
{
name = "asl";
size = Size::W;
src = make_ea();
}
// %1110_001011_mmmrrr LSR.W <ea>
OP_DEF(lsr_w)
{
name = "lsr";
size = Size::W;
src = make_ea();
}
// %1110_001111_mmmrrr LSL.W <ea>
OP_DEF(lsl_w)
{
name = "lsl";
size = Size::W;
src = make_ea();
}
// %1110_010011_mmmrrr ROXR.W <ea>
OP_DEF(roxr_w)
{
name = "roxr";
size = Size::W;
src = make_ea();
}
// %1110_010111_mmmrrr ROXL.W <ea>
OP_DEF(roxl_w)
{
name = "roxl";
size = Size::W;
src = make_ea();
}
// %1110_011011_mmmrrr ROR.W <ea>
OP_DEF(ror_w)
{
name = "ror";
size = Size::W;
src = make_ea();
}
// %1110_011111_mmmrrr ROL.W <ea>
OP_DEF(rol_w)
{
name = "rol";
size = Size::W;
src = make_ea();
}
// %1110_100011_mmmrrr BFTST <ea>{#o:#w}
OP_DEF(bftst)
{
fetch16();
name = "bftst";
src = make_ea() + make_bf();
}
// %1110_100111_mmmrrr BFEXTU <ea>{#o:#w},Dn
OP_DEF(bfextu)
{
fetch16();
name = "bfextu";
src = make_ea() + make_bf();
dst = make_dn(ir[1] >> 12);
}
// %1110_101011_mmmrrr BFCHG <ea>{#o:#w}
OP_DEF(bfchg)
{
fetch16();
name = "bfchg";
src = make_ea() + make_bf();
}
// %1110_101111_mmmrrr BFEXTS <ea>{#o:#w},Dn
OP_DEF(bfexts)
{
fetch16();
name = "bfexts";
src = make_ea() + make_bf();
dst = make_dn(ir[1] >> 12);
}
// %1110_110011_mmmrrr BFCLR <ea>{#o:#w}
OP_DEF(bfclr)
{
fetch16();
name = "bfclr";
src = make_ea() + make_bf();
}
// %1110_110111_mmmrrr BFFFO <ea>{#o:#w},Dn
OP_DEF(bfffo)
{
fetch16();
name = "bfffo";
src = make_ea() + make_bf();
dst = make_dn(ir[1] >> 12);
}
// %1110_111011_mmmrrr BFSET <ea>{#o:#w}
OP_DEF(bfset)
{
fetch16();
name = "bfset";
src = make_ea() + make_bf();
}
// %1110_111111_mmmrrr BFINS Dn,<ea>{#o:#w}
OP_DEF(bfins)
{
fetch16();
name = "bfins";
dst = make_ea() + make_bf();
src = make_dn(ir[1] >> 12);
}
// PMOVE* の共通部分
void
Disasm::ops_pmove(Reg reg, Disasm::Size sz)
{
if ((ir[1] & 0x0100) == 0) {
name = "pmove";
} else {
name = "pmovefd";
}
size = sz;
if ((ir[1] & 0x0200) == 0) {
src = make_ea();
dst = make_reg(reg);
} else {
src = make_reg(reg);
dst = make_ea();
}
}
// %1111_000nnn_nnnnnn MMU_OP
OP_DEF(mmuop)
{
uint16 ext = fetch16();
switch (ext >> 8) {
case 0x08: // PMOVE.L <ea>,TT0
case 0x09: // PMOVEFD.L <ea>,TT0
case 0x0a: // PMOVE.L TT0,<ea>
ops_pmove(Reg::TT0, Size::L);
break;
case 0x0c: // PMOVE.L <ea>,TT1
case 0x0d: // PMOVEFD.L <ea>,TT1
case 0x0e: // PMOVE.L TT1,<ea>
ops_pmove(Reg::TT1, Size::L);
break;
case 0x40: // PMOVE.L <ea>,TC
case 0x41: // PMOVEFD.L <ea>,TC
case 0x42: // PMOVE.L TC,<ea>
ops_pmove(Reg::TC, Size::L);
break;
case 0x48: // PMOVE.Q <ea>,SRP
case 0x49: // PMOVEFD.Q <ea>,SRP
case 0x4a: // PMOVE.Q SRP,<ea>
ops_pmove(Reg::SRP, Size::Q);
break;
case 0x4c: // PMOVE.Q <ea>,CRP
case 0x4d: // PMOVEFD.Q <ea>,CRP
case 0x4e: // PMOVE.Q CRP,<ea>
ops_pmove(Reg::CRP, Size::Q);
break;
case 0x60: // PMOVE.W <ea>,MMUSR
case 0x61: // PMOVEFD.W <ea>,MMUSR
case 0x62: // PMOVE.W MMUSR,<ea>
ops_pmove(Reg::MMUSR, Size::W);
break;
case 0x20: // PLOADW <fc>,<ea>
case 0x22: // PLOADR <fc>,<ea>
if ((ext & 0x0200) == 0) {
name = "ploadw";
} else {
name = "ploadr";
}
src = make_fc();
dst = make_ea();
break;
case 0x24: // PFLUSHA
name = "pflusha";
break;
case 0x38: // PFLUSH <fc>,#<mask>,<ea>
dst = make_ea();
FALLTHROUGH;
case 0x30: // PFLUSH <fc>,#<mask>
name = "pflush";
src = make_fc() + string_format(",#%d", (ir[1] >> 5) & 7);
break;
case 0x81: // PTESTW <fc>,<ea>,#0,An
case 0x85: // PTESTW <fc>,<ea>,#1,An
case 0x89: // PTESTW <fc>,<ea>,#2,An
case 0x8d: // PTESTW <fc>,<ea>,#3,An
case 0x91: // PTESTW <fc>,<ea>,#4,An
case 0x95: // PTESTW <fc>,<ea>,#5,An
case 0x99: // PTESTW <fc>,<ea>,#6,An
case 0x9d: // PTESTW <fc>,<ea>,#7,An
case 0x83: // PTESTR <fc>,<ea>,#0,An
case 0x87: // PTESTR <fc>,<ea>,#1,An
case 0x8b: // PTESTR <fc>,<ea>,#2,An
case 0x8f: // PTESTR <fc>,<ea>,#3,An
case 0x93: // PTESTR <fc>,<ea>,#4,An
case 0x97: // PTESTR <fc>,<ea>,#5,An
case 0x9b: // PTESTR <fc>,<ea>,#6,An
case 0x9f: // PTESTR <fc>,<ea>,#7,An
dst = make_an(ir[1] >> 5);
FALLTHROUGH;
case 0x80: // PTESTW <fc>,<ea>,#0
case 0x84: // PTESTW <fc>,<ea>,#1
case 0x88: // PTESTW <fc>,<ea>,#2
case 0x8c: // PTESTW <fc>,<ea>,#3
case 0x90: // PTESTW <fc>,<ea>,#4
case 0x94: // PTESTW <fc>,<ea>,#5
case 0x98: // PTESTW <fc>,<ea>,#6
case 0x9c: // PTESTW <fc>,<ea>,#7
case 0x82: // PTESTR <fc>,<ea>,#0
case 0x86: // PTESTR <fc>,<ea>,#1
case 0x8a: // PTESTR <fc>,<ea>,#2
case 0x8e: // PTESTR <fc>,<ea>,#3
case 0x92: // PTESTR <fc>,<ea>,#4
case 0x96: // PTESTR <fc>,<ea>,#5
case 0x9a: // PTESTR <fc>,<ea>,#6
case 0x9e: // PTESTR <fc>,<ea>,#7
if ((ext & 0x0200) == 0) {
name = "ptestw";
} else {
name = "ptestr";
}
src = make_fc() + "," + make_ea()
+ string_format(",#%d", (ext >> 10) & 7);
break;
default:
OP_FUNC(illegal);
break;
}
}
// %1111_001000_nnnnnn FPGEN
OP_DEF(fpgen)
{
uint16 ext = fetch16();
switch (ext >> 13) {
case 0:
ops_fpgen_fpn_fpn();
break;
case 2:
ops_fpgen_ea_fpn();
break;
case 3:
ops_fmove_fpn_ea();
break;
case 4:
ops_fmovem_ea_ctl();
break;
case 5:
ops_fmovem_ctl_ea();
break;
case 6:
ops_fmovem_ea_fpn();
break;
case 7:
ops_fmovem_fpn_ea();
break;
}
}
// FPgen <fpn>,<fpn>
void
Disasm::ops_fpgen_fpn_fpn()
{
uint sn = (ir[1] >> 10) & 7;
uint dn = (ir[1] >> 7) & 7;
uint mode = ir[1] & 0x7f;
// FSINCOS だけ形式が違うので先に処理
if (0x30 <= mode && mode < 0x38) {
name = "fsincos";
size = Size::X;
src = make_fpn(sn);
dst = make_fpn(ir[1]) + ":" + make_fpn(dn);
return;
}
// FSINCOS 以外は全部同じ書式
name = fpgen_names[mode];
if (name.empty()) {
OP_FUNC(illegal);
return;
}
size = Size::X;
src = make_fpn(sn);
// FSIN FPm,FPm のように src, dst が同じ場合は FSIN FPm と書くが、
// FMOVE FPm,FPm は src, dst が同じであっても FMOVE FPm,FPm と表記する。
if (mode == 0x00/*FMOVE*/ || sn != dn) {
dst = make_fpn(dn);
}
}
// FPgen <ea>,<reg>
void
Disasm::ops_fpgen_ea_fpn()
{
uint sz = (ir[1] >> 10) & 7;
uint dn = (ir[1] >> 7) & 7;
uint mode = ir[1] & 0x7f;
if (sz == 7) {
// ここに FMOVECR
ops_fmovecr();
return;
}
name = fpgen_names[mode];
if (name.empty()) {
OP_FUNC(illegal);
return;
}
size = (Size)sz;
src = make_ea();
dst = make_fpn(dn);
}
// FMOVECR
void
Disasm::ops_fmovecr()
{
uint dn = (ir[1] >> 7) & 7;
uint offset = ir[1] & 0x7f;
std::string text;
name = "fmovecr";
size = Size::X;
src = "#" + hex8(offset);
// 定数だけじゃ分かりづらいので内容も表示も表示してみるのはどうか。
switch (offset) {
case 0:
src += "<pi>";
break;
case 0x0b ... 0x0f:
src += fmovecr_text[offset - 0x0b];
break;
case 0x30 ... 0x3f:
src += fmovecr_text[offset - 0x30 + 5];
break;
default:
break;
}
dst = make_fpn(dn);
}
// FMOVE <fpn>,<ea>
void
Disasm::ops_fmove_fpn_ea()
{
uint sz = (ir[1] >> 10) & 7;
uint sn = (ir[1] >> 7) & 7;
uint mode = ir[1] & 0x7f;
name = "fmove";
size = (Size)sz;
src = make_fpn(sn);
dst = make_ea();
if (sz == Size::P) {
// static k-factor
int k;
// 7bit (符号なし)数を符号付き数に変える
if ((mode & 0x40)) {
k = (int8)(mode | 0x80);
} else {
k = mode;
}
dst += string_format("{#%d}", k);
} else if (sz == Size::Pk) {
// dynamic k-factor
dst += "{" + make_dn(mode >> 4) + "}";
}
}
void
Disasm::ops_fmovem_ea_ctl()
{
uint n;
n = make_fpctls(dst);
if (n == 1) {
name = "fmove";
} else {
name = "fmovem";
}
size = Size::L;
src = make_ea();
// #imm が複数ある場合
if ((ir[0] & 0x3f) == 0x3c && n > 1) {
for (int i = 1; i < n; i++) {
src += "/";
src += imm32();
}
}
}
void
Disasm::ops_fmovem_ctl_ea()
{
uint n;
n = make_fpctls(src);
if (n == 1) {
name = "fmove";
} else {
name = "fmovem";
}
size = Size::L;
dst = make_ea();
}
void
Disasm::ops_fmovem_ea_fpn()
{
name = "fmovem";
size = Size::X;
src = make_ea();
if ((ir[1] & 0x1800) == 0x1800) {
// dynamic list
dst = make_dn(ir[1] >> 4);
} else {
dst = make_fpnlist();
}
}
void
Disasm::ops_fmovem_fpn_ea()
{
name = "fmovem";
size = Size::X;
if ((ir[1] & 0x1800) == 0x1800) {
// dynamic list
src = make_dn(ir[1] >> 4);
} else {
src = make_fpnlist();
}
dst = make_ea();
}
// %1111_001001_nnnnnn FScc.B <ea>
// %1111_001001_001yyy FDBcc Dy,<label>
// %1111_001001_111010 FTRAPcc.W #<imm>
// %1111_001001_111011 FTRAPcc.L #<imm>
// %1111_001001_111100 FTRAPcc
OP_DEF(fxcc)
{
uint n = ir[0] & 0x3f;
fetch16();
switch (n) {
case 0x00 ... 0x07: // FScc
case 0x10 ... 0x39:
name = "fs" + make_fpcc(ir[1]);
size = Size::B;
src = make_ea();
break;
case 0x08 ... 0x0f: // FDBcc
name = "fdb" + make_fpcc(ir[1]);
src = make_dn(ir[0]);
dst = addr32(pc0 + 2 + (int32)(int16)fetch16());
break;
case 0x3a: // FTRAPcc.W #<imm>
name = "ftrap" + make_fpcc(ir[1]);
size = Size::W;
src = imm16();
break;
case 0x3b: // FTRAPcc.L #<imm>
name = "ftrap" + make_fpcc(ir[1]);
size = Size::L;
src = imm32();
break;
case 0x3c: // FTRAPcc
name = "ftrap" + make_fpcc(ir[1]);
break;
default:
OP_FUNC(illegal);
break;
}
}
// %1111_001010_nnnnnn FBcc.W <label>
OP_DEF(fbcc_w)
{
int32 disp = (int32)(int16)fetch16();
if ((ir[0] & 0x3f) == 0 && disp == 0) {
// FBF.W +$0000 のみ FNOP
name = "fnop";
return;
}
name = "fb" + make_fpcc(ir[0]);
size = Size::W;
src = addr32(pc0 + 2 + disp);
}
// %1111_001011_nnnnnn FBcc.L <label>
OP_DEF(fbcc_l)
{
name = "fb" + make_fpcc(ir[0]);
size = Size::L;
src = addr32(pc0 + 2 + (int32)fetch32());
}
// %1111_001100_nnnnnn FSAVE <ea>
OP_DEF(fsave)
{
name = "fsave";
src = make_ea();
}
// %1111_001101_nnnnnn FRESTORE <ea>
OP_DEF(frestore)
{
name = "frestore";
src = make_ea();
}
// %1111_nnnnnn_nnnnnn F-Line
OP_DEF(fline)
{
// XXX x68k/Human68k 判定するか
if ((ir[0] & 0xff00) == 0xff00) {
uint dosno = ir[0] & 0xff;
name = "DOS";
src = x68k_doscall[dosno] ?: "<undefined>";
} else if ((ir[0] & 0xff00) == 0xfe00) {
uint n = ir[0] & 0xff;
name = "FPACK";
src = x68k_fpcall[n] ?: "<undefined>";
} else {
name = "<unknown F-Line trap>";
}
}
// illegal instructions
OP_DEF(illegal)
{
name = "<illegal instruction>";
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.