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); }