The compactor uses the Machine Definition File (MDF) to translate the compiler output into microcode or instruction encodings specifically for your machine. The MDF contains:
You can reach us by email at info@archelon.com.
/* @(#) m68000.mdf 1.3 97/05/27 00:25:04 @(#)
*
* m68000.mdf
*
* Copyright © 1996-97 Archelon Inc. All Rights Reserved.
*/
.wordsize 16;
.noop "nop";
/*
* Field definitions
*/
.field
WORD [16] {
.constant;
}
.location WORD 0;
.mop
msw(a) {
.expansion "WORD# .bits(16, 31,", WORD, ")";
WORD = a;
}
.mop
lsw(a) {
.expansion "WORD# .bits(0, 15,", WORD, ")";
WORD = a;
}
/*
* Effective Address
*/
.field
ZREG [3] {
.mnemonics {
d0 = 0;
d1 = 1;
d2 = 2;
d3 = 3;
d4 = 4;
d5 = 5;
d6 = 6;
d7 = 7;
a0 = 0;
a1 = 1;
a2 = 2;
a3 = 3;
a4 = 4;
a5 = 5;
a6 = 6;
a7 = 7;
sp = 7;
zreg_word = 0;
zreg_long = 1;
zreg_disp = 2;
zreg_index = 3;
zreg_imm = 4;
zreg_sr = 4;
}
}
.location ZREG 0;
.field
ZMODE [3] {
.mnemonics {
/*
* put an underbar in front of a couple of mnemonics
* in order to avoid conflicts with variable names,
* due to mcpack becoming more careful in checking
* for name redeclaration. rpg 970525
*/
dreg = 0;
areg = 1;
ind = 2;
postinc = 3;
predec = 4;
disp = 5;
index = 6;
zreg = 7;
}
}
.location ZMODE 0;
.field
S_REG [3] {
.same_as ZREG;
}
.location S_REG 0;
.field
S_MODE [3] {
.same_as ZMODE;
}
.location S_MODE 3;
.field
D_MODE [3] {
.same_as D_MODE;
}
.location D_MODE 6;
.field
D_REG [3] {
.same_as ZREG;
}
.location D_REG 9;
.field
SIZE [2] {
.mnemonics {
byte = 0;
word = 1;
long = 2;
size_filler = 3;
}
.default word;
}
.location SIZE 6;
.field
COND [4] {
.mnemonics {
true = 0;
always = 1;
false = 1;
subroutine = 2;
high = 2;
low_same = 3;
carry_clear = 4;
carry_set = 5;
not_equal = 6;
equal = 7;
overflow_clear = 8;
overflow_set = 9;
plus = 10;
minus = 11;
greater_equal = 12;
less_than = 13;
greater_than = 14;
less_equal = 15;
}
}
.location COND 8;
/*
* Address Register Indirect with Index
*/
.field
INDEX [1, 3, 1] {
.mnemonics {
Xd0 = 0, 0, 0;
Xd1 = 0, 1, 0;
Xd2 = 0, 2, 0;
Xd3 = 0, 3, 0;
Xd4 = 0, 4, 0;
Xd5 = 0, 5, 0;
Xd6 = 0, 6, 0;
Xd7 = 0, 7, 0;
Xd0.w = 0, 0, 0;
Xd1.w = 0, 1, 0;
Xd2.w = 0, 2, 0;
Xd3.w = 0, 3, 0;
Xd4.w = 0, 4, 0;
Xd5.w = 0, 5, 0;
Xd6.w = 0, 6, 0;
Xd7.w = 0, 7, 0;
Xd0.l = 0, 0, 1;
Xd1.l = 0, 1, 1;
Xd2.l = 0, 2, 1;
Xd3.l = 0, 3, 1;
Xd4.l = 0, 4, 1;
Xd5.l = 0, 5, 1;
Xd6.l = 0, 6, 1;
Xd7.l = 0, 7, 1;
Xa0 = 1, 0, 0;
Xa1 = 1, 1, 0;
Xa2 = 1, 2, 0;
Xa3 = 1, 3, 0;
Xa4 = 1, 4, 0;
Xa5 = 1, 5, 0;
Xa6 = 1, 6, 0;
Xa7 = 1, 7, 0;
Xsp = 1, 7, 0;
Xa0.w = 1, 0, 0;
Xa1.w = 1, 1, 0;
Xa2.w = 1, 2, 0;
Xa3.w = 1, 3, 0;
Xa4.w = 1, 4, 0;
Xa5.w = 1, 5, 0;
Xa6.w = 1, 6, 0;
Xa7.w = 1, 7, 0;
Xsp.w = 1, 7, 0;
Xa0.l = 1, 0, 1;
Xa1.l = 1, 1, 1;
Xa2.l = 1, 2, 1;
Xa3.l = 1, 3, 1;
Xa4.l = 1, 4, 1;
Xa5.l = 1, 5, 1;
Xa6.l = 1, 6, 1;
Xa7.l = 1, 7, 1;
Xsp.l = 1, 7, 1;
}
}
.location INDEX 15, 12, 11;
.field
DISP [.signed 8] {
.constant;
}
.location DISP 0;
.mop
index(ea) {
.numvar start, finish;
.expansion INDEX, "DISP#", DISP;
start = .search(ea, ", *");
finish = .search(ea, "[)]") - 2;
INDEX = .concat("X", .substr(ea, start, finish));
DISP = .substr(ea, 0, .search(ea, "[(]") - 2);
}
.func
extension(ea, size, mode, reg) {
.select (mode) {
.case "index":
index(ea);
.break;
.case "disp":
lsw(.substr(ea, 0, .search(ea, "[(]") - 2));
.break;
.case "zreg":
.select (reg) {
.case zreg_index:
index(ea);
.break;
.case zreg_disp:
lsw(.substr(ea, 0, .search(ea, "[(]") - 2));
.break;
.case zreg_long:
msw(ea);
.case zreg_word:
lsw(ea);
.break;
.case zreg_imm:
.if (size :: "long")
msw(.substr(ea, 1));
lsw(.substr(ea, 1));
.break;
}
}
}
/*
* OPCODE12 D_REG D_MODE S_MODE S_REG
* OPCODE12 COND DISP
*/
.field
OPCODE12 [4] {
.mnemonics {
bit = 0;
movep = 0;
move_b = 1;
move_l = 2;
move_w = 3;
chk = 4;
lea = 4;
branch = 6;
set = 5;
dec_branch = 5;
}
}
.location OPCODE12 12;
/*
* MOP functions, describing low-level encodings.
*/
.mop
opcode12(code, d_reg, d_mode, s_mode, s_reg) {
.expansion OPCODE12, D_REG, D_MODE, S_MODE, S_REG;
OPCODE12 = code;
D_REG = d_reg;
D_MODE = d_mode;
S_MODE = s_mode;
S_REG = s_reg;
}
.mop
branch(cond, brdisp) {
.expansion OPCODE12, COND, "DISP#", DISP;
OPCODE12 = branch;
COND = cond;
DISP = brdisp;
}
.mop
set_dbra(code, cond, mode, reg) {
.expansion OPCODE12, COND, SIZE, S_MODE, S_REG;
OPCODE12 = code;
COND = cond;
SIZE = size_filler;
S_MODE = mode;
S_REG = reg;
}
/*
* OPCODE12A D_REG S_MODE S_REG
*/
.field
OPCODE12A [4, 3] {
.mnemonics {
btst_imm = 0, 0;
bchg_imm = 0, 1;
bclr_imm = 0, 2;
bset_imm = 0, 3;
btst_reg = 0, 4;
bchg_reg = 0, 5;
bclr_reg = 0, 6;
bset_reg = 0, 7;
movep_w_mem_reg = 0, 4;
movep_l_mem_reg = 0, 5;
movep_w_reg_mem = 0, 6;
movep_l_reg_mem = 0, 7;
divu = 8, 3;
divs = 8, 7;
suba_word = 9, 3;
suba_long = 9, 7;
cmpa_word = 11, 3;
cmpa_long = 11, 7;
mulu = 12, 3;
muls = 12, 7;
adda_word = 13, 3;
adda_long = 13, 7;
}
}
.location OPCODE12A 12, 6;
.mop
opcode12a(code, d_reg, s_mode, s_reg) {
.expansion OPCODE12A, D_REG, S_MODE, S_REG;
OPCODE12A = code;
D_REG = d_reg;
S_MODE = s_mode;
S_REG = s_reg;
}
/*
* OPCODE12B D_REG SIZE S_MODE S_REG
*/
.field
OPCODE12B [4, 1] {
.mnemonics {
addq = 5, 0;
subq = 5, 1;
moveq = 7, 1;
or_reg_ea = 8, 0;
or_ea_reg = 8, 1;
sub_reg_ea = 9, 0;
sub_ea_reg = 9, 1;
cmp_ea_reg = 11, 0;
eor_reg_ea = 11, 1;
and_reg_ea = 12, 0;
and_ea_reg = 12, 1;
add_reg_ea = 13, 0;
add_ea_reg = 13, 1;
}
}
.location OPCODE12B 12, 8;
.mop
opcode12b(code, data, size, s_mode, s_reg) {
.expansion OPCODE12B, D_REG, SIZE, S_MODE, S_REG;
OPCODE12B = code;
D_REG = data;
SIZE = size;
S_MODE = s_mode;
S_REG = s_reg;
}
.mop
op_moveq(data, reg) {
.expansion OPCODE12B, D_REG, "DISP#", DISP;
OPCODE12B = moveq;
D_REG = reg;
DISP = data;
}
/*
* OPCODE12C D_REG SIZE S_REG
*/
.field
OPCODE12C [4, 1, 3] {
.mnemonics {
subx_reg_reg = 9, 1, 0;
subx_mem_mem = 9, 1, 1;
cmpm = 11, 1, 1;
addx_reg_reg = 13, 1, 0;
addx_mem_mem = 13, 1, 1;
asr_imm = 14, 0, 0;
lsr_imm = 14, 0, 1;
roxr_imm = 14, 0, 2;
ror_imm = 14, 0, 3;
asr_reg = 14, 0, 4;
lsr_reg = 14, 0, 5;
roxr_reg = 14, 0, 6;
ror_reg = 14, 0, 7;
asl_imm = 14, 1, 0;
lsl_imm = 14, 1, 1;
roxl_imm = 14, 1, 2;
rol_imm = 14, 1, 3;
asl_reg = 14, 1, 4;
lsl_reg = 14, 1, 5;
roxl_reg = 14, 1, 6;
rol_reg = 14, 1, 7;
}
}
.location OPCODE12C 12, 8, 3;
.mop
opcode12c(code, d_reg, size, s_reg) {
.expansion OPCODE12C, D_REG, SIZE, S_REG;
OPCODE12C = code;
D_REG = d_reg;
SIZE = size;
S_REG = s_reg;
}
/*
* OPCODE12D D_REG S_REG
*/
.field
OPCODE12D [4, 6] {
.mnemonics {
sbcd_reg_reg = 8, 040;
sbcd_mem_mem = 8, 041;
abcd_reg_reg = 12, 040;
abcd_mem_mem = 12, 041;
ext_dreg_dreg = 12, 050;
ext_areg_areg = 12, 051;
ext_dreg_areg = 12, 061;
}
}
.location OPCODE12D 12, 3;
.mop
opcode12d(code, d_reg, s_reg) {
.expansion OPCODE12D, D_REG, S_REG;
OPCODE12D = code;
D_REG = d_reg;
S_REG = s_reg;
}
/*
* OPCODE8 SIZE S_EA;
*/
.field
OPCODE8 [8] {
.mnemonics {
ori = 0x00;
andi = 0x02;
subi = 0x04;
addi = 0x05;
eori = 0x0a;
cmpi = 0x0c;
negx = 0x40;
clr = 0x42;
neg = 0x44;
not = 0x46;
tst = 0x4a;
}
}
.location OPCODE8 8;
.mop
opcode8(code, size, mode, reg) {
.expansion OPCODE8, SIZE, S_MODE, S_REG;
OPCODE8 = code;
SIZE = size;
S_MODE = mode;
S_REG = reg;
}
.strvar sm_mode, sm_reg;
.func
set_mode_reg(ea) {
.numvar num;
.if (.search(ea, "[(](a[0-7]|sp)[)][+]") == 5) {
sm_reg = .substr(ea, 1, 2);
sm_mode = "postinc";
.done;
}
.if (.search(ea, "-[(](a[0-7]|sp)[)]") == 5) {
sm_reg = .substr(ea, 2, 3);
sm_mode = "predec";
.done;
}
.if (.search(ea, "[(](a[0-7]|sp)[)]") == 4) {
sm_reg = .substr(ea, 1, 2);
sm_mode = "ind";
.done;
}
.if (.search(ea, "(a[0-7]|sp)") == 2) {
sm_reg = ea;
sm_mode = "areg";
.done;
}
.if (.search(ea, "d[0-7]") == 2) {
sm_reg = ea;
sm_mode = "dreg";
.done;
}
.if (2 < .search(ea, "[(](a[0-7]|sp)[)]")) {
num = .search(ea, "a[0-7]|sp");
sm_reg = .substr(ea, num-2, num-1);
sm_mode = "disp";
.done;
}
.if (2 < .search(ea, "[(](a[0-7]|sp), *([ad][0-7]|sp)([.][wl])?[)]")) {
num = .search(ea, "a[0-7]|sp");
sm_reg = .substr(ea, num-2, num-1);
sm_mode = "index";
.done;
}
sm_mode = "zreg";
.if (2 < .search(ea, "[(]pc[)]$")) {
sm_reg = "zreg_disp";
.done;
}
.if (2 < .search(ea, "[(]pc, *([ad][0-7]|sp)([.][wl])?[)]")) {
sm_reg = "zreg_index";
.done;
}
.if (.substr(ea, 0, 0) :: "#") {
sm_reg = "zreg_imm";
.done;
}
.if (ea :: "ccr" || ea :: "sr") {
sm_reg = "zreg_sr";
.done;
}
.if (.numeric(ea)) {
num = .number(ea);
.if (-32768 <= num && num <= 32767) {
sm_reg = "zreg_word";
.done;
}
}
sm_reg = "zreg_long";
}
.func
chk_dst(mode, reg) {
.if (mode :: "areg")
.done 0;
.select (reg) {
.case "zreg_disp":
.case "zreg_index":
.case "zreg_imm":
.done 0;
}
.done 1;
}
.func
chk_ea(mode, reg) {
.select (mode) {
.case zreg:
.if (reg :: "zreg_imm" || reg :: "zreg_sr")
.case dreg:
.case areg:
.case postinc:
.case predec:
.done 0;
}
.done 1;
}
.func
chk_movem_reg_mem(mode, reg) {
.select (mode) {
.case zreg:
.if (reg :: "zreg_word" || reg :: "zreg_long")
.done 1;
.case dreg:
.case areg:
.case postinc:
.done 0;
}
.done 1;
}
.func
chk_movem_mem_reg(mode, reg) {
.done chk_ea(mode, reg) || mode :: "postinc";
}
/*
* OPCODE4 VECTOR
*/
.field
OPCODE4 [12] {
.mnemonics {
trap = 0x4e4;
}
}
.location OPCODE4 4;
.field
VECTOR [4] {
.constant;
}
.location VECTOR 0;
.mop
opcode4(code, vec) {
.expansion OPCODE4, "VECTOR#", VECTOR;
OPCODE4 = code;
VECTOR = vec;
}
.vop
trap(num) {
.numvar vec;
.if (.numeric(num))
vec = num;
.elif (.substr(num, 0, 0) :: "#" && .numeric(.substr(num, 1)))
vec = .substr(num, 1);
.else
.error("Invalid trap operand :", num);
.if (vec < 0 || 15 < vec)
.error("Value out of range (0-15) :", num);
opcode4(trap, vec);
}
/*
* OPCODE0
*/
.field
OPCODE0 [16] {
.mnemonics {
illegal = 0x4afc;
reset = 0x4e70;
nop = 0x4e71;
stop = 0x4e72;
rte = 0x4e73;
rtd = 0x4e74;
rts = 0x4e75;
trapv = 0x4e76;
rtr = 0x4e77;
}
.default nop;
}
.mop
opcode0(code) {
.expansion OPCODE0;
OPCODE0 = code;
}
.vop
illegal() {
opcode0(illegal);
}
.vop
reset() {
opcode0(reset);
}
.vop
nop() {
opcode0(nop);
}
.vop
stop() {
opcode0(stop);
}
.vop
rte() {
opcode0(rte);
}
.vop
rtd() {
opcode0(rtd);
}
.vop
rtr() {
opcode0(rtr);
}
.vop
rts() {
opcode0(rts);
}
.vop
trapv() {
opcode0(trapv);
}
.func
do_opcode8(code, size, src, dst) {
.strvar sz;
set_mode_reg(dst);
.if (! chk_dst(sm_mode, sm_reg))
.error("Invalid destination operand :", dst);
.select (dst) {
.case "ccr":
sz = byte;
.break;
.case "sr":
sz = word;
.break;
.default:
sz = size;
}
.bundle {
opcode8(code, sz, sm_mode, sm_reg);
.if (.substr(src, 0, 0) :: "#")
extension(src, sz, zreg, zreg_imm);
extension(dst, sz, sm_mode, sm_reg);
}
}
/*
* VOP functions, describing the high-level instruction set.
*/
.vop
ori(imm, dst) {
do_opcode8(ori, word, imm, dst);
}
.vop
ori.b(imm, dst) {
do_opcode8(ori, byte, imm, dst);
}
.vop
ori.w(imm, dst) {
do_opcode8(ori, word, imm, dst);
}
.vop
ori.l(imm, dst) {
do_opcode8(ori, long, imm, dst);
}
.vop
andi(imm, dst) {
do_opcode8(andi, word, imm, dst);
}
.vop
andi.b(imm, dst) {
do_opcode8(andi, byte, imm, dst);
}
.vop
andi.w(imm, dst) {
do_opcode8(andi, word, imm, dst);
}
.vop
andi.l(imm, dst) {
do_opcode8(andi, long, imm, dst);
}
.vop
eori(imm, dst) {
do_opcode8(eori, word, imm, dst);
}
.vop
eori.b(imm, dst) {
do_opcode8(eori, byte, imm, dst);
}
.vop
eori.w(imm, dst) {
do_opcode8(eori, word, imm, dst);
}
.vop
eori.l(imm, dst) {
do_opcode8(eori, long, imm, dst);
}
.vop
subi(imm, dst) {
do_opcode8(subi, word, imm, dst);
}
.vop
subi.b(imm, dst) {
do_opcode8(subi, byte, imm, dst);
}
.vop
subi.w(imm, dst) {
do_opcode8(subi, word, imm, dst);
}
.vop
subi.l(imm, dst) {
do_opcode8(subi, long, imm, dst);
}
.vop
addi(imm, dst) {
do_opcode8(addi, word, imm, dst);
}
.vop
addi.b(imm, dst) {
do_opcode8(addi, byte, imm, dst);
}
.vop
addi.w(imm, dst) {
do_opcode8(addi, word, imm, dst);
}
.vop
addi.l(imm, dst) {
do_opcode8(addi, long, imm, dst);
}
.func
do_bit(code, src, dst) {
set_mode_reg(dst);
.if (.search(src, "d[0-7]") == 2)
.bundle {
opcode12a(.concat(code, "_reg"), src, sm_mode, sm_reg);
extension(dst, "", sm_mode, sm_reg);
}
.elif (.substr(src, 0, 0) :: "#")
.bundle {
opcode12a(.concat(code, "_imm"), d4, sm_mode, sm_reg);
extension(src, word, zreg, zreg_imm);
}
.else
.error("Invalid source operand :", src);
}
.vop
btst(src, dst) {
do_bit("btst", src, dst);
}
.vop
bchg(src, dst) {
do_bit("bchg", src, dst);
}
.vop
bclr(src, dst) {
do_bit("bclr", src, dst);
}
.vop
bset(src, dst) {
do_bit("bset", src, dst);
}
.vop
cmpi(imm, dst) {
do_opcode8(cmpi, word, imm, dst);
}
.vop
cmpi.b(imm, dst) {
do_opcode8(cmpi, byte, imm, dst);
}
.vop
cmpi.w(imm, dst) {
do_opcode8(cmpi, word, imm, dst);
}
.vop
cmpi.l(imm, dst) {
do_opcode8(cmpi, long, imm, dst);
}
.vop
negx(dst) {
do_opcode8(negx, word, "", dst);
}
.vop
negx.b(dst) {
do_opcode8(negx, byte, "", dst);
}
.vop
negx.w(dst) {
do_opcode8(negx, word, "", dst);
}
.vop
negx.l(dst) {
do_opcode8(negx, long, "", dst);
}
.vop
clr(dst) {
do_opcode8(clr, word, "", dst);
}
.vop
clr.b(dst) {
do_opcode8(clr, byte, "", dst);
}
.vop
clr.w(dst) {
do_opcode8(clr, word, "", dst);
}
.vop
clr.l(dst) {
do_opcode8(clr, long, "", dst);
}
.vop
neg(dst) {
do_opcode8(neg, word, "", dst);
}
.vop
neg.b(dst) {
do_opcode8(neg, byte, "", dst);
}
.vop
neg.w(dst) {
do_opcode8(neg, word, "", dst);
}
.vop
neg.l(dst) {
do_opcode8(neg, long, "", dst);
}
.vop
not(dst) {
do_opcode8(not, word, "", dst);
}
.vop
not.b(dst) {
do_opcode8(not, byte, "", dst);
}
.vop
not.w(dst) {
do_opcode8(not, word, "", dst);
}
.vop
not.l(dst) {
do_opcode8(not, long, "", dst);
}
.vop
tst(dst) {
do_opcode8(tst, word, "", dst);
}
.vop
tst.b(dst) {
do_opcode8(tst, byte, "", dst);
}
.vop
tst.w(dst) {
do_opcode8(tst, word, "", dst);
}
.vop
tst.l(dst) {
do_opcode8(tst, long, "", dst);
}
/*
* OPCODE6 S_MODE S_REG
*/
.field
OPCODE6 [10] {
.mnemonics {
move_from_sr = 00403;
move_from_ccr = 00413;
move_to_ccr = 00423;
move_to_sr = 00433;
nbcd = 00440;
pea = 00441;
movem_w_reg_mem = 00442;
movem_l_reg_mem = 00443;
tas = 00453;
movem_w_mem_reg = 00462;
movem_l_mem_reg = 00463;
jsr = 00472;
jmp = 00473;
asr_mem = 01603;
asl_mem = 01607;
lsr_mem = 01613;
lsl_mem = 01617;
roxr_mem = 01623;
roxl_mem = 01627;
ror_mem = 01633;
rol_mem = 01637;
}
}
.location OPCODE6 6;
.mop
opcode6(code, mode, reg) {
.expansion OPCODE6, S_MODE, S_REG;
OPCODE6 = code;
S_MODE = mode;
S_REG = reg;
}
.func
do_opcode6(code, test, ea) {
set_mode_reg(ea);
.select (test) {
.case 0:
.if (! chk_dst(sm_mode, sm_reg))
.error("Invalid destination operand :", ea);
.break;
.case 1:
.if (sm_mode :: "areg")
.error("Invalid source operand :", ea);
.break;
.case 2:
.if (! chk_ea(sm_mode, sm_reg))
.error("Invalid operand :", ea);
.break;
.case 3:
.if (! chk_dst(sm_mode, sm_reg) || sm_mode :: "dreg")
.error("Invalid destination operand :", ea);
.break;
}
.bundle {
opcode6(code, sm_mode, sm_reg);
extension(ea, word, sm_mode, sm_reg);
}
}
.vop
nbcd(dst) {
do_opcode6(nbcd, 0, dst);
}
.vop
pea(ea) {
do_opcode6(pea, 2, ea);
}
.vop
tas(dst) {
do_opcode6(tas, 0, dst);
}
.vop
jsr(ea) {
do_opcode6(jsr, 2, ea);
}
.vop
jmp(ea) {
do_opcode6(jmp, 2, ea);
}
/*
* OPCODE3 S_REG
*/
.field
OPCODE3 [13] {
.mnemonics {
swap = 04410;
ext_w = 04420;
ext_l = 04430;
link = 04712;
unlk = 04713;
move_to_usp = 04714;
move_from_usp = 04715;
}
}
.location OPCODE3 3;
.mop
opcode3(code, reg) {
.expansion OPCODE3, S_REG;
OPCODE3 = code;
S_REG = reg;
}
.func
do_opcode3(code, op_areg, op_reg) {
set_mode_reg(op_reg);
.if ((op_areg && sm_mode !: "areg") || (!op_areg && sm_mode !: "dreg"))
.error("Invalid operand :", op_reg);
opcode3(code, op_reg);
}
.vop
swap(op_dreg) {
do_opcode3(swap, 0, op_dreg);
}
.vop
ext(op_dreg) {
do_opcode3(ext_w, 0, op_dreg);
}
.vop
ext.w(op_dreg) {
do_opcode3(ext_w, 0, op_dreg);
}
.vop
ext.l(op_dreg) {
do_opcode3(ext_l, 0, op_dreg);
}
.vop
unlk(op_areg) {
do_opcode3(unlk, 1, op_areg);
}
.vop
link(op_areg, op_disp) {
set_mode_reg(op_areg);
.if (sm_mode !: "areg")
.error("Invalid operand :", op_areg);
.bundle {
opcode3(link, sm_reg);
extension(op_disp, word, zreg, zreg_imm);
}
}
.func
do_move(code, size, src, dst) {
.strvar s_reg, s_mode;
set_mode_reg(src);
s_mode = sm_mode;
s_reg = sm_reg;
set_mode_reg(dst);
.if (! chk_dst(sm_mode, sm_reg) && sm_mode !: "areg")
.error("Invalid destination operand :", dst);
.bundle {
opcode12(code, sm_reg, sm_mode, s_mode, s_reg);
extension(src, size, s_mode, s_reg);
extension(dst, "", sm_mode, sm_reg);
}
}
.vop
move(src, dst) {
.select (src) {
.case "ccr":
do_opcode6(move_from_ccr, 0, dst);
.done;
.case "sr":
do_opcode6(move_from_sr, 0, dst);
.done;
.case "usp":
do_opcode3(move_from_usp, 1, dst);
.done;
}
.select (dst) {
.case "ccr":
do_opcode6(move_to_ccr, 1, src);
.done;
.case "sr":
do_opcode6(move_to_sr, 1, src);
.done;
.case "usp":
do_opcode3(move_to_usp, 1, src);
.done;
}
do_move(move_w, word, src, dst);
}
.vop
move.b(src, dst) {
do_move(move_b, byte, src, dst);
}
.vop
move.w(src, dst) {
do_move(move_w, word, src, dst);
}
.vop
move.l(src, dst) {
do_move(move_l, long, src, dst);
}
.vop
movea(src, dst) {
do_move(move_w, word, src, dst);
}
.vop
movea.w(src, dst) {
do_move(move_w, word, src, dst);
}
.vop
movea.l(src, dst) {
do_move(move_l, long, src, dst);
}
.vop
chk(src, dst) {
.strvar d_reg;
set_mode_reg(dst);
d_reg = sm_reg;
.if (sm_mode !: "dreg")
.error("Invalid destination operand :", dst);
set_mode_reg(src);
.if (sm_mode :: "areg")
.error("Invalid source operand :", src);
.bundle {
opcode12(chk, d_reg, index, sm_mode, sm_reg);
extension(src, word, sm_mode, sm_reg);
}
}
.vop
lea(src, dst) {
.strvar d_reg;
set_mode_reg(dst);
d_reg = sm_reg;
.if (sm_mode !: "areg")
.error("Invalid destination operand :", dst);
set_mode_reg(src);
.if (! chk_ea(sm_mode, sm_reg))
.error("Invalid source operand :", src);
.bundle {
opcode12(chk, d_reg, index, sm_mode, sm_reg);
extension(src, word, sm_mode, sm_reg);
}
}
.func
do_movep(code, src, dst) {
.strvar d_reg, d_mode;
set_mode_reg(dst);
d_mode = sm_mode;
d_reg = sm_reg;
set_mode_reg(src);
.if (d_mode !: sm_mode) {
.select (sm_mode) {
.case dreg:
.bundle {
opcode12a(.concat(code, "_reg_mem"), sm_reg, areg, d_reg);
extension(dst, "", disp, d_reg);
}
.done;
.case disp:
.bundle {
opcode12a(.concat(code, "_mem_reg"), d_reg, areg, sm_reg);
extension(src, "", disp, sm_reg);
}
.done;
}
}
.error("Invalid combination of operands :", src, ",", dst);
}
.vop
movep(src, dst) {
do_movep("movep_w", src, dst);
}
.vop
movep.w(src, dst) {
do_movep("movep_w", src, dst);
}
.vop
movep.l(src, dst) {
do_movep("movep_l", src, dst);
}
.func
reglist(regs, reverse) {
.strvar str;
.numvar count, shift, mask, len, scan;
mask = 0;
len = .search(regs, ".*");
.for (scan = 0; scan < len; ) {
str = .substr(regs, scan, scan+1);
shift = .value(str);
scan = scan + 2;
count = 1;
.if (.search(regs, "-[0-7]", scan) == scan+2) {
count = .number(.substr(regs, scan+1, scan+1)) - shift + 1;
scan = scan + 2;
}
.if (.substr(regs, scan, scan) :: "/")
scan = scan + 1;
.if (.substr(str, 0, 0) :: "a")
shift = shift + 8;
.for ( ; 0 < count; count = count - 1) {
mask = mask | (1 << shift);
shift = shift + 1;
}
}
.if (reverse) {
scan = 0;
.for (count = 0; count < 16; count = count + 1) {
scan = scan << 1;
.if (mask & 1)
scan = scan | 1;
mask = mask >> 1;
}
mask = scan;
}
.done .string(mask);
}
.func
do_movem(code, src, dst) {
.strvar s_reg, s_mode, list;
set_mode_reg(src);
s_mode = sm_mode;
s_reg = sm_reg;
set_mode_reg(dst);
.if (chk_movem_reg_mem(sm_mode, sm_reg)
&& (s_mode :: "dreg" || s_mode :: "areg" || s_reg :: "zreg_imm")) {
.if (s_reg :: "zreg_imm")
list = .substr(src, 1);
.else
list = reglist(src, sm_mode :: "predec");
.bundle {
opcode6(.concat(code, "_reg_mem"), sm_mode, sm_reg);
lsw(list);
extension(dst, "", sm_mode, sm_reg);
}
.done;
}
.if (chk_movem_mem_reg(s_mode, s_reg)
&& (sm_mode :: "dreg" || sm_mode :: "areg" || sm_reg :: "zreg_imm")) {
.if (sm_reg :: "zreg_imm")
list = .substr(dst, 1);
.else
list = reglist(dst, 0);
.bundle {
opcode6(.concat(code, "_mem_reg"), s_mode, s_reg);
lsw(list);
extension(src, "", s_mode, s_reg);
}
.done;
}
.error("Invalid combination of operands :", src, ",", dst);
}
.vop
movem(src, dst) {
do_movem("movem_w", src, dst);
}
.vop
movem.w(src, dst) {
do_movem("movem_w", src, dst);
}
.vop
movem.l(src, dst) {
do_movem("movem_l", src, dst);
}
.func
do_branch(cond, label) {
.numvar dx;
.if (.numeric(label)) {
/* Explicit displacement. */
dx = .number(label);
.if (-128 <= dx && dx <= 127)
branch(cond, dx);
.else
.bundle {
branch(cond, 0);
lsw(dx);
}
} .else {
/* Distance between label and program counter.
*
* The displacement is relative the start of the
* branch instruction plus two.
*/
.output(".ifa (", label, "- . - 2), -128, 127");
branch(cond, .concat("(", .concat(label, " - . - 2)")));
.output(".else");
.bundle {
branch(cond, 0);
lsw(.concat(label, " - ."));
}
.output(".endif");
}
}
.vop
bra(label) {
do_branch(always, label);
}
.vop
bsr(label) {
do_branch(subroutine, label);
}
.vop
bhi(label) {
do_branch(high, label);
}
.vop
bls(label) {
do_branch(low_same, label);
}
.vop
bcc(label) {
do_branch(carry_clear, label);
}
.vop
bhs(label) {
do_branch(carry_clear, label);
}
.vop
bcs(label) {
do_branch(carry_set, label);
}
.vop
blo(label) {
do_branch(carry_set, label);
}
.vop
bne(label) {
do_branch(not_equal, label);
}
.vop
beq(label) {
do_branch(equal, label);
}
.vop
bvc(label) {
do_branch(overflow_clear, label);
}
.vop
bvs(label) {
do_branch(overflow_set, label);
}
.vop
bpl(label) {
do_branch(plus, label);
}
.vop
bmi(label) {
do_branch(minus, label);
}
.vop
bge(label) {
do_branch(greater_equal, label);
}
.vop
blt(label) {
do_branch(less_than, label);
}
.vop
bgt(label) {
do_branch(greater_than, label);
}
.vop
ble(label) {
do_branch(less_equal, label);
}
.func
do_quick(code, size, src, dst) {
.numvar data;
.if (.substr(src, 0, 0) :: "#") {
data = .number(.substr(src, 1));
.if (data == 8)
data = 0;
.elif (data < 1 || 7 < data)
.error("Operand", src, "is out of range (1..8).");
} .else {
.error("Invalid source operand :", src);
}
set_mode_reg(dst);
.if (! chk_dst(sm_mode, sm_reg) && sm_mode !: "areg")
.error("Invalid destination operand :", dst);
.if (sm_mode :: "areg" && size :: "byte")
.error("Invalid size attribute for address register.");
.bundle {
opcode12b(code, data, size, sm_mode, sm_reg);
extension(dst, "", sm_mode, sm_reg);
}
}
.vop
addq(src, dst) {
do_quick(addq, word, src, dst);
}
.vop
addq.b(src, dst) {
do_quick(addq, byte, src, dst);
}
.vop
addq.w(src, dst) {
do_quick(addq, word, src, dst);
}
.vop
addq.l(src, dst) {
do_quick(addq, long, src, dst);
}
.vop
subq(src, dst) {
do_quick(subq, word, src, dst);
}
.vop
subq.b(src, dst) {
do_quick(subq, byte, src, dst);
}
.vop
subq.w(src, dst) {
do_quick(subq, word, src, dst);
}
.vop
subq.l(src, dst) {
do_quick(subq, long, src, dst);
}
.vop
moveq(src, dst) {
.numvar data;
.if (.substr(src, 0, 0) :: "#") {
data = .number(.substr(src, 1));
.if (data < -128 || 127 < data)
.error("Operand", src, "is out of range (-128..127).");
} .else {
.error("Invalid source operand :", src);
}
set_mode_reg(dst);
.if (sm_mode !: "dreg")
.error("Invalid destination operand :", dst);
op_moveq(data, sm_reg);
}
.func
do_set(cond, dst) {
set_mode_reg(dst);
.if (! chk_dst(sm_mode, sm_reg))
.error("Invalid destination operand :", dst);
.bundle {
set_dbra(set, cond, sm_mode, sm_reg);
extension(dst, "", sm_mode, sm_reg);
}
}
.vop
st(dst) {
do_set(true, dst);
}
.vop
sf(dst) {
do_set(false, dst);
}
.vop
shi(dst) {
do_set(high, dst);
}
.vop
sls(dst) {
do_set(low_same, dst);
}
.vop
scc(dst) {
do_set(carry_clear, dst);
}
.vop
shs(dst) {
do_set(carry_clear, dst);
}
.vop
scs(dst) {
do_set(carry_set, dst);
}
.vop
slo(dst) {
do_set(carry_set, dst);
}
.vop
sne(dst) {
do_set(not_equal, dst);
}
.vop
seq(dst) {
do_set(equal, dst);
}
.vop
svc(dst) {
do_set(overflow_clear, dst);
}
.vop
svs(dst) {
do_set(overflow_set, dst);
}
.vop
spl(dst) {
do_set(plus, dst);
}
.vop
smi(dst) {
do_set(minus, dst);
}
.vop
sge(dst) {
do_set(greater_equal, dst);
}
.vop
slt(dst) {
do_set(less_than, dst);
}
.vop
sgt(dst) {
do_set(greater_than, dst);
}
.vop
sle(dst) {
do_set(less_equal, dst);
}
.func
do_db(cond, src, label) {
.numvar dx;
set_mode_reg(src);
.if (sm_mode !: "dreg")
.error("Invalid destination operand :", src);
.if (.numeric(label)) {
/* Explicit displacement. */
dx = .number(label);
.bundle {
set_dbra(dec_branch, cond, areg, sm_reg);
lsw(dx);
}
} .else {
/* Distance between label and program counter.
*
* The displacement is relative the start of the
* branch instruction plus two.
*/
.bundle {
set_dbra(dec_branch, cond, areg, sm_reg);
lsw(.concat(label, " - ."));
}
}
}
.vop
dbra(src, label) {
do_db(always, src, label);
}
.vop
dbt(src, label) {
do_db(true, src, label);
}
.vop
dbf(src, label) {
do_db(false, src, label);
}
.vop
dbhi(src, label) {
do_db(high, src, label);
}
.vop
dbls(src, label) {
do_db(low_same, src, label);
}
.vop
dbcc(src, label) {
do_db(carry_clear, src, label);
}
.vop
dbhs(src, label) {
do_db(carry_clear, src, label);
}
.vop
dbcs(src, label) {
do_db(carry_set, src, label);
}
.vop
dblo(src, label) {
do_db(carry_set, src, label);
}
.vop
dbne(src, label) {
do_db(not_equal, src, label);
}
.vop
dbeq(src, label) {
do_db(equal, src, label);
}
.vop
dbvc(src, label) {
do_db(overflow_clear, src, label);
}
.vop
dbvs(src, label) {
do_db(overflow_set, src, label);
}
.vop
dbpl(src, label) {
do_db(plus, src, label);
}
.vop
dbmi(src, label) {
do_db(minus, src, label);
}
.vop
dbge(src, label) {
do_db(greater_equal, src, label);
}
.vop
dblt(src, label) {
do_db(less_than, src, label);
}
.vop
dbgt(src, label) {
do_db(greater_than, src, label);
}
.vop
dble(src, label) {
do_db(less_equal, src, label);
}
.func
do_alu(code, size, src, dst) {
.numvar data;
.strvar s_mode, s_reg, num;
set_mode_reg(src);
s_mode = sm_mode;
s_reg = sm_reg;
set_mode_reg(dst);
num = .substr(src, 1);
.if (sm_mode :: "dreg" && code !: "eor") {
/* Check for faster forms of immediate-to-register instructions. */
.if (s_reg :: "zreg_imm") {
.if ((code :: "add" || code :: "sub") && .numeric(num)) {
data = .number(num);
.if (1 <= data && data <= 8) {
do_quick(.concat(code, "q"), size, src, dst);
.done;
}
}
do_opcode8(.concat(code, "i"), size, src, dst);
} .else {
.bundle {
opcode12b(.concat(code, "_ea_reg"), sm_reg, size, s_mode, s_reg);
extension(src, size, s_mode, s_reg);
}
}
} .elif (sm_mode :: "areg") {
.if (size :: byte)
.error("Invalid operand size.");
.select (code) {
.case "add":
.case "sub":
.if (s_reg :: "zreg_imm" && .numeric(num)) {
data = .number(num);
.if (1 <= data && data <= 8) {
do_quick(.concat(code, "q"), size, src, dst);
.break;
}
}
/* fall-through */
.case "cmp":
.bundle {
opcode12a(
.concat(code, .concat("a_", size)), sm_reg, s_mode, s_reg);
extension(src, size, s_mode, s_reg);
}
.break;
.default:
.error("Invalid destination operand :", dst);
}
} .elif (s_mode :: "dreg" && code !: "cmp") {
.bundle {
opcode12b(.concat(code, "_reg_ea"), s_reg, size, sm_mode, sm_reg);
extension(dst, size, sm_mode, sm_reg);
}
} .else {
.error("Invalid combination of operands :", src, ",", dst);
}
}
.vop
or(src, dst) {
do_alu("or", word, src, dst);
}
.vop
or.b(src, dst) {
do_alu("or", byte, src, dst);
}
.vop
or.w(src, dst) {
do_alu("or", word, src, dst);
}
.vop
or.l(src, dst) {
do_alu("or", long, src, dst);
}
.vop
sub(src, dst) {
do_alu("sub", word, src, dst);
}
.vop
sub.b(src, dst) {
do_alu("sub", byte, src, dst);
}
.vop
sub.w(src, dst) {
do_alu("sub", word, src, dst);
}
.vop
sub.l(src, dst) {
do_alu("sub", long, src, dst);
}
.vop
and(src, dst) {
do_alu("and", word, src, dst);
}
.vop
and.b(src, dst) {
do_alu("and", byte, src, dst);
}
.vop
and.w(src, dst) {
do_alu("and", word, src, dst);
}
.vop
and.l(src, dst) {
do_alu("and", long, src, dst);
}
.vop
add(src, dst) {
do_alu("add", word, src, dst);
}
.vop
add.b(src, dst) {
do_alu("add", byte, src, dst);
}
.vop
add.w(src, dst) {
do_alu("add", word, src, dst);
}
.vop
add.l(src, dst) {
do_alu("add", long, src, dst);
}
.vop
cmp(src, dst) {
do_alu("cmp", word, src, dst);
}
.vop
cmp.b(src, dst) {
do_alu("cmp", byte, src, dst);
}
.vop
cmp.w(src, dst) {
do_alu("cmp", word, src, dst);
}
.vop
cmp.l(src, dst) {
do_alu("cmp", long, src, dst);
}
.vop
eor(src, dst) {
do_alu("eor", word, src, dst);
}
.vop
eor.b(src, dst) {
do_alu("eor", byte, src, dst);
}
.vop
eor.w(src, dst) {
do_alu("eor", word, src, dst);
}
.vop
eor.l(src, dst) {
do_alu("eor", long, src, dst);
}
.vop
adda(src, dst) {
do_alu("add", word, src, dst);
}
.vop
adda.w(src, dst) {
do_alu("add", word, src, dst);
}
.vop
adda.l(src, dst) {
do_alu("add", long, src, dst);
}
.vop
suba(src, dst) {
do_alu("sub", word, src, dst);
}
.vop
suba.w(src, dst) {
do_alu("sub", word, src, dst);
}
.vop
suba.l(src, dst) {
do_alu("sub", long, src, dst);
}
.vop
cmpa(src, dst) {
do_alu("cmp", word, src, dst);
}
.vop
cmpa.w(src, dst) {
do_alu("cmp", word, src, dst);
}
.vop
cmpa.l(src, dst) {
do_alu("cmp", long, src, dst);
}
.func
div_mul(code, src, dst) {
.if (.search(dst, "d[0-7]") != 2)
.error("Invalid destination operand :", dst);
set_mode_reg(src);
.if (sm_mode :: "areg")
.error("Invalid source operand :", src);
.bundle {
opcode12a(code, dst, sm_mode, sm_reg);
extension(src, "", sm_mode, sm_reg);
}
}
.vop
divu(src, dst) {
div_mul(divu, src, dst);
}
.vop
divs(src, dst) {
div_mul(divs, src, dst);
}
.vop
mulu(src, dst) {
div_mul(mulu, src, dst);
}
.vop
muls(src, dst) {
div_mul(muls, src, dst);
}
.func
do_shift(code, size, src, dst) {
.numvar data;
.if (dst :: "") {
do_opcode6(.concat(code, "_mem"), 3, src);
.done;
}
.if (.search(dst, "d[0-7]") != 2)
.error("Invalid destination operand :", dst);
.if (.substr(src, 0, 0) :: "#") {
data = .number(.substr(src, 1));
.if (data == 8)
data = 0;
.elif (data < 1 || 7 < data)
.error("Operand", src, "is out of range (1..8).");
opcode12c(.concat(code, "_imm"), data, size, dst);
} .elif (.search(src, "d[0-7]") == 2) {
opcode12c(.concat(code, "_reg"), src, size, dst);
} .else {
.error("Invalid source operand :", src);
}
}
.vop
asr(src, dst) {
do_shift("asr", word, src, dst);
}
.vop
asr.b(src, dst) {
do_shift("asr", byte, src, dst);
}
.vop
asr.w(src, dst) {
do_shift("asr", word, src, dst);
}
.vop
asr.l(src, dst) {
do_shift("asr", long, src, dst);
}
.vop
asl(src, dst) {
do_shift("asl", word, src, dst);
}
.vop
asl.b(src, dst) {
do_shift("asl", byte, src, dst);
}
.vop
asl.w(src, dst) {
do_shift("asl", word, src, dst);
}
.vop
asl.l(src, dst) {
do_shift("asl", long, src, dst);
}
.vop
lsr(src, dst) {
do_shift("lsr", word, src, dst);
}
.vop
lsr.b(src, dst) {
do_shift("lsr", byte, src, dst);
}
.vop
lsr.w(src, dst) {
do_shift("lsr", word, src, dst);
}
.vop
lsr.l(src, dst) {
do_shift("lsr", long, src, dst);
}
.vop
lsl(src, dst) {
do_shift("lsl", word, src, dst);
}
.vop
lsl.b(src, dst) {
do_shift("lsl", byte, src, dst);
}
.vop
lsl.w(src, dst) {
do_shift("lsl", word, src, dst);
}
.vop
lsl.l(src, dst) {
do_shift("lsl", long, src, dst);
}
.vop
roxr(src, dst) {
do_shift("roxr", word, src, dst);
}
.vop
roxr.b(src, dst) {
do_shift("roxr", byte, src, dst);
}
.vop
roxr.w(src, dst) {
do_shift("roxr", word, src, dst);
}
.vop
roxr.l(src, dst) {
do_shift("roxr", long, src, dst);
}
.vop
roxl(src, dst) {
do_shift("roxl", word, src, dst);
}
.vop
roxl.b(src, dst) {
do_shift("roxl", byte, src, dst);
}
.vop
roxl.w(src, dst) {
do_shift("roxl", word, src, dst);
}
.vop
roxl.l(src, dst) {
do_shift("roxl", long, src, dst);
}
.vop
ror(src, dst) {
do_shift("ror", word, src, dst);
}
.vop
ror.b(src, dst) {
do_shift("ror", byte, src, dst);
}
.vop
ror.w(src, dst) {
do_shift("ror", word, src, dst);
}
.vop
ror.l(src, dst) {
do_shift("ror", long, src, dst);
}
.vop
rol(src, dst) {
do_shift("rol", word, src, dst);
}
.vop
rol.b(src, dst) {
do_shift("rol", byte, src, dst);
}
.vop
rol.w(src, dst) {
do_shift("rol", word, src, dst);
}
.vop
rol.l(src, dst) {
do_shift("rol", long, src, dst);
}
.func
do_opcode12c(code, size, src, dst) {
.strvar s_mode, s_reg;
set_mode_reg(src);
s_mode = sm_mode;
s_reg = sm_reg;
set_mode_reg(dst);
.if (code :: "cmpm" && s_mode :: "postinc" && sm_mode :: "postinc")
opcode12c(code, sm_reg, size, s_reg);
.elif (s_mode :: "predec" && sm_mode :: "predec")
opcode12c(.concat(code, "_mem_mem"), sm_reg, size, s_reg);
.elif (s_mode :: "dreg" && sm_mode :: "dreg")
opcode12c(.concat(code, "_reg_reg"), sm_reg, size, s_reg);
.else
.error("Invalid combination of operands :", src, ",", dst);
}
.vop
addx(src, dst) {
do_opcode12c("addx", word, src, dst);
}
.vop
addx.b(src, dst) {
do_opcode12c("addx", byte, src, dst);
}
.vop
addx.w(src, dst) {
do_opcode12c("addx", word, src, dst);
}
.vop
addx.l(src, dst) {
do_opcode12c("addx", long, src, dst);
}
.vop
subx(src, dst) {
do_opcode12c("subx", word, src, dst);
}
.vop
subx.b(src, dst) {
do_opcode12c("subx", byte, src, dst);
}
.vop
subx.w(src, dst) {
do_opcode12c("subx", word, src, dst);
}
.vop
subx.l(src, dst) {
do_opcode12c("subx", long, src, dst);
}
.vop
cmpm(src, dst) {
do_opcode12c("cmpm", word, src, dst);
}
.vop
cmpm.b(src, dst) {
do_opcode12c("cmpm", byte, src, dst);
}
.vop
cmpm.w(src, dst) {
do_opcode12c("cmpm", word, src, dst);
}
.vop
cmpm.l(src, dst) {
do_opcode12c("cmpm", long, src, dst);
}
.func
do_opcode12d(code, src, dst) {
.strvar s_mode, s_reg;
set_mode_reg(src);
s_mode = sm_mode;
s_reg = sm_reg;
set_mode_reg(dst);
.if (code :: "ext") {
.if (s_mode :: "dreg" && sm_mode :: "dreg")
opcode12d(.concat(code, "_dreg_dreg"), sm_reg, s_reg);
.elif (s_mode :: "areg" && sm_mode :: "areg")
opcode12d(.concat(code, "_areg_areg"), sm_reg, s_reg);
.elif (s_mode :: "dreg" && sm_mode :: "areg")
opcode12d(.concat(code, "_dreg_areg"), s_reg, sm_reg);
.elif (s_mode :: "areg" && sm_mode :: "dreg")
opcode12d(.concat(code, "_dreg_areg"), sm_reg, s_reg);
.else
.error("Invalid combination of operands :", src, ",", dst);
} .elif (s_mode :: "predec" && sm_mode :: "predec")
opcode12d(.concat(code, "_mem_mem"), sm_reg, s_reg);
.elif (s_mode :: "dreg" && sm_mode :: "dreg")
opcode12d(.concat(code, "_reg_reg"), sm_reg, s_reg);
.else
.error("Invalid combination of operands :", src, ",", dst);
}
.vop
sbcd(src, dst) {
do_opcode12d("sbcd", src, dst);
}
.vop
abcd(src, dst) {
do_opcode12d("abcd", src, dst);
}
.vop
exg(src, dst) {
do_opcode12d("ext", src, dst);
}