# HG changeset patch # User William Astle # Date 1436844394 21600 # Node ID 4fd16faa4d9330a743fd8c1f01184e435cd9b8d4 # Parent 6ee9c67a0f8d1fc11cb23ad735be1ce25a84b134 Add various "convenience" ops These are things like "NEGD" in 6809 mode or NEGQ in 6309 mode. These require either 6809conv or 6309conv pragmas. Also fix a problem with "CPX" in the 6800 mode. Thanks to Erik G for the patch. diff -r 6ee9c67a0f8d -r 4fd16faa4d93 lwasm/cycle.c --- a/lwasm/cycle.c Mon Jul 13 21:20:30 2015 -0600 +++ b/lwasm/cycle.c Mon Jul 13 21:26:34 2015 -0600 @@ -238,7 +238,7 @@ { 0x63, 6, 6, CYCLE_ADJ }, { 0x73, 7, 6, 0 }, - { 0x3c, 22, 20, 0 }, // CWAI + { 0x3c, 22, 20, CYCLE_ESTIMATED }, // CWAI { 0x19, 2, 1, 0 }, // DAA diff -r 6ee9c67a0f8d -r 4fd16faa4d93 lwasm/insn_inh.c --- a/lwasm/insn_inh.c Mon Jul 13 21:20:30 2015 -0600 +++ b/lwasm/insn_inh.c Mon Jul 13 21:26:34 2015 -0600 @@ -39,6 +39,7 @@ l -> len = OPLEN(instab[l -> insn].ops[0]); if (instab[l -> insn].ops[1] >= 0) l -> len += OPLEN(instab[l -> insn].ops[1]); + skip_operand(p); } EMITFUNC(insn_emit_inh6800) @@ -47,6 +48,48 @@ lwasm_emitop(l, instab[l -> insn].ops[0]); if (instab[l -> insn].ops[1] >= 0) lwasm_emitop(l, instab[l -> insn].ops[1]); + l -> cycle_base = instab[l -> insn].ops[3]; +} - l -> cycle_adj = instab[l -> insn].ops[3]; +int negq_ops[] = { 0x10, 0x43, 0x10, 0x53, 0x10, 0x31, 0xc6, 0x10, 0x31, 0xc0 }; +#define negq_size (sizeof(negq_ops)/sizeof(int)) + +PARSEFUNC(insn_parse_conv) +{ + int i; + l -> len = 0; + for (i = 0; i <= 2; i++) + { + if (instab[l -> insn].ops[i] >= 0) + l -> len += OPLEN(instab[l -> insn].ops[i]); + } + + /* negq */ + if (instab[l -> insn].ops[0] == -1) + l -> len = negq_size; + skip_operand(p); } + +EMITFUNC(insn_emit_conv) +{ + int i; + for (i = 0; i <= 2; i++) + { + if (instab[l -> insn].ops[i] >= 0) + lwasm_emitop(l, instab[l -> insn].ops[i]); + } + + /* special case for negq */ + if (instab[l -> insn].ops[0] == -1) + { + // 1043 (2) comd + // 1053 (2) comw + // 1031C6 (4) adcr 0,w + // 1031C0 (4) adcr 0,d + + for (i = 0; i < negq_size; i++) + lwasm_emitop(l, negq_ops[i]); + } + + l->cycle_base = instab[l -> insn].ops[3]; +} \ No newline at end of file diff -r 6ee9c67a0f8d -r 4fd16faa4d93 lwasm/instab.c --- a/lwasm/instab.c Mon Jul 13 21:20:30 2015 -0600 +++ b/lwasm/instab.c Mon Jul 13 21:26:34 2015 -0600 @@ -340,8 +340,35 @@ #define pseudo_resolve_endstruct NULL #define pseudo_emit_endstruct NULL +// convenience ops +PARSEFUNC(insn_parse_conv); +#define insn_resolve_conv NULL +EMITFUNC(insn_emit_conv); + instab_t instab[] = { + // 6809 convenience instructions + { "asrd", { 0x4756, -1, -1, 4 }, insn_parse_conv, insn_resolve_conv, insn_emit_conv, lwasm_insn_is6809conv }, + { "clrd", { 0x4f5f, -1, -1, 4 }, insn_parse_conv, insn_resolve_conv, insn_emit_conv, lwasm_insn_is6809conv }, + { "comd", { 0x4353, -1, -1, 4 }, insn_parse_conv, insn_resolve_conv, insn_emit_conv, lwasm_insn_is6809conv }, + { "lsld", { 0x5849, -1, -1, 4 }, insn_parse_conv, insn_resolve_conv, insn_emit_conv, lwasm_insn_is6809conv }, + { "lsrd", { 0x4456, -1, -1, 4 }, insn_parse_conv, insn_resolve_conv, insn_emit_conv, lwasm_insn_is6809conv }, + { "negd", { 0x4353, 0x83ff, 0xff, 8 }, insn_parse_conv, insn_resolve_conv, insn_emit_conv, lwasm_insn_is6809conv }, + { "tstd", { 0xed7e, -1, -1, 6 }, insn_parse_conv, insn_resolve_conv, insn_emit_conv, lwasm_insn_is6809conv }, + + // 6309 convenience instructions + { "asrq", { 0x1047, 0x1056, -1, 4 }, insn_parse_conv, insn_resolve_conv, insn_emit_conv, lwasm_insn_is6309conv }, + { "clrq", { 0x4f5f, 0x1F06, -1, 6 }, insn_parse_conv, insn_resolve_conv, insn_emit_conv, lwasm_insn_is6309conv }, + { "comq", { 0x1043, 0x1053, -1, 4 }, insn_parse_conv, insn_resolve_conv, insn_emit_conv, lwasm_insn_is6309conv }, + { "lsle", { 0x1030, 0xee, -1, 4 }, insn_parse_conv, insn_resolve_conv, insn_emit_conv, lwasm_insn_is6309conv }, + { "lslf", { 0x1030, 0xff, -1, 4 }, insn_parse_conv, insn_resolve_conv, insn_emit_conv, lwasm_insn_is6309conv }, + { "lslq", { 0x1030, 0x6610, 0x49, 6 }, insn_parse_conv, insn_resolve_conv, insn_emit_conv, lwasm_insn_is6309conv }, + { "lsrq", { 0x1044, 0x1056, -1, 4 }, insn_parse_conv, insn_resolve_conv, insn_emit_conv, lwasm_insn_is6309conv }, + { "nege", { 0x1032, 0xce, -1, 4 }, insn_parse_conv, insn_resolve_conv, insn_emit_conv, lwasm_insn_is6309conv }, + { "negf", { 0x1032, 0xcf, -1, 4 }, insn_parse_conv, insn_resolve_conv, insn_emit_conv, lwasm_insn_is6309conv }, + { "negw", { 0x1032, 0xc6, -1, 4 }, insn_parse_conv, insn_resolve_conv, insn_emit_conv, lwasm_insn_is6309conv }, + { "negq", { -1, -1, -1, 12 }, insn_parse_conv, insn_resolve_conv, insn_emit_conv, lwasm_insn_is6309conv }, + { "tstq", { 0x10ed, 0x7c, -1, 9 }, insn_parse_conv, insn_resolve_conv, insn_emit_conv, lwasm_insn_is6309conv }, { "abx", { 0x3a, -1, -1, -1 }, insn_parse_inh, insn_resolve_inh, insn_emit_inh, lwasm_insn_normal}, { "adca", { 0x99, 0xa9, 0xb9, 0x89}, insn_parse_gen8, insn_resolve_gen8, insn_emit_gen8, lwasm_insn_normal}, @@ -445,6 +472,8 @@ { "eorr", { 0x1036, -1, -1, -1 }, insn_parse_rtor, insn_resolve_rtor, insn_emit_rtor, lwasm_insn_is6309}, { "exg", { 0x1e, -1, -1, -1 }, insn_parse_rtor, insn_resolve_rtor, insn_emit_rtor, lwasm_insn_normal}, + { "hcf", { 0x14, -1, -1, -1 }, insn_parse_inh, insn_resolve_inh, insn_emit_inh, lwasm_insn_is6809}, + { "inc", { 0x0c, 0x6c, 0x7c, -1 }, insn_parse_gen0, insn_resolve_gen0, insn_emit_gen0, lwasm_insn_normal}, { "inca", { 0x4c, -1, -1, -1 }, insn_parse_inh, insn_resolve_inh, insn_emit_inh, lwasm_insn_normal}, { "incb", { 0x5c, -1, -1, -1 }, insn_parse_inh, insn_resolve_inh, insn_emit_inh, lwasm_insn_normal}, @@ -529,6 +558,7 @@ { "puluw", { 0x103b, -1, -1, -1 }, insn_parse_inh, insn_resolve_inh, insn_emit_inh, lwasm_insn_is6309}, { "reset", { 0x3e, -1, -1, -1 }, insn_parse_inh, insn_resolve_inh, insn_emit_inh, lwasm_insn_is6809}, + { "rhf", { 0x14, -1, -1, -1 }, insn_parse_inh, insn_resolve_inh, insn_emit_inh, lwasm_insn_is6809}, { "rol", { 0x09, 0x69, 0x79, -1 }, insn_parse_gen0, insn_resolve_gen0, insn_emit_gen0, lwasm_insn_normal}, { "rola", { 0x49, -1, -1, -1 }, insn_parse_inh, insn_resolve_inh, insn_emit_inh, lwasm_insn_normal}, { "rolb", { 0x59, -1, -1, -1 }, insn_parse_inh, insn_resolve_inh, insn_emit_inh, lwasm_insn_normal}, @@ -743,33 +773,33 @@ { ".bank", { -1, -1, -1, -1 }, pseudo_parse_noop, pseudo_resolve_noop, pseudo_emit_noop, lwasm_insn_normal}, // for 6800 compatibility - { "aba", { 0x3404, 0xabe0, -1, -1 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, - { "cba", { 0x3404, 0xa1e0, -1, -1 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, - { "clc", { 0x1cfe, -1, -1, -1 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, - { "clf", { 0x1cbf, -1, -1, -1 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, - { "cli", { 0x1cef, -1, -1, -1 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, - { "clif", { 0x1caf, -1, -1, -1 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, - { "clv", { 0x1cfd, -1, -1, -1 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, - { "cpx", { 0x9c, 0xac, 0xbc, 0x8c }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, - { "des", { 0x327f, -1, -1, -1 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, - { "dex", { 0x301f, -1, -1, -1 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, - { "dey", { 0x313f, -1, -1, -1 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, - { "ins", { 0x3261, -1, -1, -1 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, - { "inx", { 0x3001, -1, -1, -1 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, - { "iny", { 0x3121, -1, -1, -1 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, - { "sba", { 0x3404, 0xa0e0, -1, -1 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, - { "sec", { 0x1a01, -1, -1, -1 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, - { "sef", { 0x1a40, -1, -1, -1 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, - { "sei", { 0x1a10, -1, -1, -1 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, - { "seif", { 0x1a50, -1, -1, -1 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, - { "sev", { 0x1a02, -1, -1, -1 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, - { "tab", { 0x1f89, 0x4d, -1, -1 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, - { "tap", { 0x1f8a, -1, -1, -1 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, - { "tba", { 0x1f98, 0x4d, -1, -1 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, - { "tpa", { 0x1fa8, -1, -1, -1 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, - { "tsx", { 0x1f41, -1, -1, -1 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, - { "txs", { 0x1f14, -1, -1, -1 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, - { "wai", { 0x3cff, -1, -1, -1 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, + { "aba", { 0x3404, 0xabe0, -1, 12 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, + { "cba", { 0x3404, 0xa1e0, -1, 12 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, + { "clc", { 0x1cfe, -1, -1, 3 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, + { "clf", { 0x1cbf, -1, -1, 3 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, + { "cli", { 0x1cef, -1, -1, 3 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, + { "clif", { 0x1caf, -1, -1, 3 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, + { "clv", { 0x1cfd, -1, -1, 3 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, + { "cpx", { 0x9c, 0xac, 0xbc, 0x8c}, insn_parse_gen16, insn_resolve_gen16, insn_emit_gen16, lwasm_insn_is6800}, + { "des", { 0x327f, -1, -1, 5 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, + { "dex", { 0x301f, -1, -1, 5 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, + { "dey", { 0x313f, -1, -1, 5 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, + { "ins", { 0x3261, -1, -1, 5 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, + { "inx", { 0x3001, -1, -1, 5 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, + { "iny", { 0x3121, -1, -1, 5 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, + { "sba", { 0x3404, 0xa0e0, -1, 12 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, + { "sec", { 0x1a01, -1, -1, 3 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, + { "sef", { 0x1a40, -1, -1, 3 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, + { "sei", { 0x1a10, -1, -1, 3 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, + { "seif", { 0x1a50, -1, -1, 3 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, + { "sev", { 0x1a02, -1, -1, 3 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, + { "tab", { 0x1f89, 0x4d, -1, 8 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, + { "tap", { 0x1f8a, -1, -1, 6 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, + { "tba", { 0x1f98, 0x4d, -1, 8 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, + { "tpa", { 0x1fa8, -1, -1, 6 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, + { "tsx", { 0x1f41, -1, -1, 6 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, + { "txs", { 0x1f14, -1, -1, 6 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, + { "wai", { 0x3cff, -1, -1, 22 }, insn_parse_inh6800, insn_resolve_inh6800, insn_emit_inh6800, lwasm_insn_is6800 }, // flag end of table { NULL, { -1, -1, -1, -1 }, NULL, NULL, NULL, lwasm_insn_normal} diff -r 6ee9c67a0f8d -r 4fd16faa4d93 lwasm/instab.h --- a/lwasm/instab.h Mon Jul 13 21:20:30 2015 -0600 +++ b/lwasm/instab.h Mon Jul 13 21:26:34 2015 -0600 @@ -38,15 +38,17 @@ enum { - lwasm_insn_cond = 1, /* conditional instruction */ - lwasm_insn_endm = 2, /* end of macro */ - lwasm_insn_setsym = 4, /* insn sets symbol address */ - lwasm_insn_is6309 = 8, /* insn is 6309 only */ - lwasm_insn_struct = 16, /* insn allowed in a struct */ - lwasm_insn_setdata = 32, /* insn uses the data address for symbols */ - lwasm_insn_is6800 = 64, /* insn is a 6800 compatibility operation */ - lwasm_insn_is6809 = 128, /* insn is 6809 only */ - lwasm_insn_normal = 0 + lwasm_insn_cond = 1, /* conditional instruction */ + lwasm_insn_endm = 1 << 1, /* end of macro */ + lwasm_insn_setsym = 1 << 2, /* insn sets symbol address */ + lwasm_insn_is6309 = 1 << 3, /* insn is 6309 only */ + lwasm_insn_struct = 1 << 4, /* insn allowed in a struct */ + lwasm_insn_setdata = 1 << 5, /* insn uses the data address for symbols */ + lwasm_insn_is6800 = 1 << 6, /* insn is a 6800 compatibility operation */ + lwasm_insn_is6809 = 1 << 7, /* insn is 6809 only */ + lwasm_insn_is6809conv = 1 << 8, /* insn is 6809 convenience only */ + lwasm_insn_is6309conv = 1 << 9, /* insn is 6309 convenience only */ + lwasm_insn_normal = 0 }; diff -r 6ee9c67a0f8d -r 4fd16faa4d93 lwasm/lwasm.h --- a/lwasm/lwasm.h Mon Jul 13 21:20:30 2015 -0600 +++ b/lwasm/lwasm.h Mon Jul 13 21:26:34 2015 -0600 @@ -100,6 +100,8 @@ PRAGMA_CC = 1 << 19, // clear cycle count running total PRAGMA_QRTS = 1 << 20, // enable BRA ?RTS support PRAGMA_M80EXT = 1 << 21, // enable Macro-80C assembler extensions + PRAGMA_6809CONV = 1 << 22, // enable 6809 convenience ops + PRAGMA_6309CONV = 1 << 23, // enable 6309 convenience ops PRAGMA_CLEARBIT = 1 << 31 // reserved to indicate negated pragma flag status }; diff -r 6ee9c67a0f8d -r 4fd16faa4d93 lwasm/pass1.c --- a/lwasm/pass1.c Mon Jul 13 21:20:30 2015 -0600 +++ b/lwasm/pass1.c Mon Jul 13 21:26:34 2015 -0600 @@ -279,9 +279,15 @@ for (opnum = 0; instab[opnum].opcode; opnum++) { - // ignore 6800 compatibility entries unless asked for - if ((instab[opnum].flags & lwasm_insn_is6800) && !CURPRAGMA(cl, PRAGMA_6800COMPAT)) - continue; + // ignore 6800 compatibility opcodes unless asked for + if ((instab[opnum].flags & lwasm_insn_is6800) && !CURPRAGMA(cl, PRAGMA_6800COMPAT)) continue; + // ignore 6809 convenience opcodes unless asked for + if ((instab[opnum].flags & lwasm_insn_is6809conv) && !CURPRAGMA(cl, PRAGMA_6809CONV)) continue; + // ignore 6809 convenience opcodes in 6309 mode + if ((instab[opnum].flags & lwasm_insn_is6809conv) && !CURPRAGMA(cl, PRAGMA_6809)) continue; + // ignore 6309 convenience opcodes unless asked for + if ((instab[opnum].flags & lwasm_insn_is6309conv) && !CURPRAGMA(cl, PRAGMA_6309CONV)) continue; + if (!strcasecmp(instab[opnum].opcode, sym)) break; } diff -r 6ee9c67a0f8d -r 4fd16faa4d93 lwasm/pragma.c --- a/lwasm/pragma.c Mon Jul 13 21:20:30 2015 -0600 +++ b/lwasm/pragma.c Mon Jul 13 21:26:34 2015 -0600 @@ -70,6 +70,8 @@ { "ct", "noct", PRAGMA_CT }, { "qrts", "noqrts", PRAGMA_QRTS }, { "m80ext", "nom80ext", PRAGMA_M80EXT }, + { "6809conv", "no6809conv", PRAGMA_6809CONV }, + { "6309conv", "no6309conv", PRAGMA_6309CONV }, { 0, 0, 0 } };