# HG changeset patch # User lost@l-w.ca # Date 1312934935 21600 # Node ID 7b07162642512e005390629f8f62008933b6a91b # Parent 344cfc25afecde47aceb07996ceecee71c61ff91 Pragma autobranchlength implementation completed diff -r 344cfc25afec -r 7b0716264251 lwasm/insn_rel.c --- a/lwasm/insn_rel.c Mon Aug 08 23:00:27 2011 -0600 +++ b/lwasm/insn_rel.c Tue Aug 09 18:08:55 2011 -0600 @@ -22,98 +22,205 @@ for handling relative mode instructions */ +#include #include +#include #include #include "lwasm.h" #include "instab.h" -PARSEFUNC(insn_parse_rel8) +/* +For generic relative, the first "opcode" is the natural opcode for the +mneumonic. The second "opcode" is the natural size of the relative offset. +These will be used when pragma autobranchlength is NOT in effect. + +The third "opcode" is the short (8 bit) version of the branch. The final one +is the long (16 bit) version of the branch. These will be used when pragma +autobranchlength is in effect. + +When autobranchlength is in effect, the branch target can be prefixed with +either < or > to force a short or long branch. Note that in this mode, +a > or < on its own still specifies a branch point. + +*/ +PARSEFUNC(insn_parse_relgen) { -// int v; lw_expr_t t, e1, e2; -// int r; - + + l -> lint = -1; + if (CURPRAGMA(l, PRAGMA_AUTOBRANCHLENGTH) == 0) + { + l -> lint = instab[l -> insn].ops[1]; + } + else + { + if (**p == '>' && (((*p)[1]) && !isspace((*p)[1]))) + { + (*p)++; + l -> lint = 16; + } + else if (**p == '<' && (((*p)[1]) && !isspace((*p)[1]))) + { + (*p)++; + l -> lint = 8; + } + } + + /* forced sizes handled */ + // sometimes there is a "#", ignore if there if (**p == '#') (*p)++; t = lwasm_parse_expr(as, p); + if (!t) { lwasm_register_error(as, l, "Bad operand"); return; } - l -> len = OPLEN(instab[l -> insn].ops[0]) + 1; - - e1 = lw_expr_build(lw_expr_type_special, lwasm_expr_linelen, l); - e2 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_plus, e1, l -> addr); - lw_expr_destroy(e1); + + // if we know the length of the instruction, set it now + if (l -> lint == 8) + { + l -> len = OPLEN(instab[l -> insn].ops[2]) + 1; + } + else if (l -> lint == 16) + { + l -> len = OPLEN(instab[l -> insn].ops[3]) + 1; + } + + // the offset calculation here depends on the length of this line! + // how to calculate requirements? + // this is the same problem faced by ,pcr indexing + e2 = lw_expr_build(lw_expr_type_special, lwasm_expr_linelen, l); e1 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_minus, t, e2); lw_expr_destroy(e2); + e2 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_minus, e1, l -> addr); + lw_expr_destroy(e1); + lwasm_save_expr(l, 0, e2); lw_expr_destroy(t); - lwasm_save_expr(l, 0, e1); + + if (l -> len == -1) + { + e1 = lw_expr_copy(e2); + l -> len = OPLEN(instab[l -> insn].ops[2]) + 1; + lwasm_reduce_expr(as, e1); + l -> len = -1; + if (lw_expr_istype(e1, lw_expr_type_int)) + { + int v; + v = lw_expr_intval(e1); + if (v >= -128 && v <= 127) + { + l -> lint = 8; + l -> len = OPLEN(instab[l -> insn].ops[2]) + 1; + } + else + { + l -> lint = 16; + l -> len = OPLEN(instab[l -> insn].ops[3]) + 2; + } + } + lw_expr_destroy(e1); + } } -EMITFUNC(insn_emit_rel8) +RESOLVEFUNC(insn_resolve_relgen) +{ + lw_expr_t e, e2; + int offs; + + if (l -> lint == -1) + { + e = lwasm_fetch_expr(l, 0); + if (!lw_expr_istype(e, lw_expr_type_int)) + { + // temporarily set the instruction length to see if we get a + // constant for our expression; if so, we can select an instruction + // size + e2 = lw_expr_copy(e); + // size of 8-bit opcode + 8 bit offset + l -> len = OPLEN(instab[l -> insn].ops[2]) + 1; + lwasm_reduce_expr(as, e2); + l -> len = -1; + if (lw_expr_istype(e2, lw_expr_type_int)) + { + // it reduced to an integer; is it in 8 bit range? + offs = lw_expr_intval(e2); + if (offs >= -128 && offs <= 127) + { + // fits in 8 bits + l -> len = OPLEN(instab[l -> insn].ops[2]) + 1; + l -> lint = 8; + } + else + { + // requires 16 bits + l -> len = OPLEN(instab[l -> insn].ops[3]) + 2; + l -> lint = 16; + } + } + lw_expr_destroy(e2); + } + if (lw_expr_istype(e, lw_expr_type_int)) + { + // it reduced to an integer; is it in 8 bit range? + offs = lw_expr_intval(e); + if (offs >= -128 && offs <= 127) + { + // fits in 8 bits + l -> len = OPLEN(instab[l -> insn].ops[2]) + 1; + l -> lint = 8; + } + else + { + // requires 16 bits + l -> len = OPLEN(instab[l -> insn].ops[3]) + 2; + l -> lint = 16; + } + } + } + if (!force) + return; + + if (l -> len == -1) + { + l -> len = OPLEN(instab[l -> insn].ops[3]) + 2; + l -> lint = 16; + } +} + +EMITFUNC(insn_emit_relgen) { lw_expr_t e; int offs; e = lwasm_fetch_expr(l, 0); - if (!lw_expr_istype(e, lw_expr_type_int)) + if (l -> lint == 8) { - lwasm_register_error(as, l, "Illegal non-constant expression"); - return; - } - - offs = lw_expr_intval(e); - if (offs < -128 || offs > 127) - { - lwasm_register_error(as, l, "Byte overflow"); - return; - } + if (!lw_expr_istype(e, lw_expr_type_int)) + { + lwasm_register_error(as, l, "Illegal non-constant expression"); + return; + } - lwasm_emitop(l, instab[l -> insn].ops[0]); - lwasm_emit(l, offs); -} - -PARSEFUNC(insn_parse_rel16) -{ -// int v; - lw_expr_t t, e1, e2; -// int r; - - // sometimes there is a "#", ignore if there - if (**p == '#') - (*p)++; + offs = lw_expr_intval(e); + if (l -> lint == 8 && (offs < -128 || offs > 127)) + { + lwasm_register_error(as, l, "Byte overflow"); + return; + } + - t = lwasm_parse_expr(as, p); - if (!t) - { - lwasm_register_error(as, l, "Bad operand"); - lw_expr_destroy(t); - return; + lwasm_emitop(l, instab[l -> insn].ops[2]); + lwasm_emit(l, offs); } - l -> len = OPLEN(instab[l -> insn].ops[0]) + 2; - - e1 = lw_expr_build(lw_expr_type_special, lwasm_expr_linelen, l); - e2 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_plus, e1, l -> addr); - lw_expr_destroy(e1); - e1 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_minus, t, e2); - lw_expr_destroy(e2); - lw_expr_destroy(t); - lwasm_save_expr(l, 0, e1); + else + { + lwasm_emitop(l, instab[l -> insn].ops[3]); + lwasm_emitexpr(l, e, 2); + } } - -EMITFUNC(insn_emit_rel16) -{ - lw_expr_t e; -// int offs; - - e = lwasm_fetch_expr(l, 0); - - lwasm_emitop(l, instab[l -> insn].ops[0]); - lwasm_emitexpr(l, e, 2); -} diff -r 344cfc25afec -r 7b0716264251 lwasm/instab.c --- a/lwasm/instab.c Mon Aug 08 23:00:27 2011 -0600 +++ b/lwasm/instab.c Tue Aug 09 18:08:55 2011 -0600 @@ -97,6 +97,11 @@ #define insn_resolve_rel16 NULL extern EMITFUNC(insn_emit_rel16); +// generic 8/16 bit relative +extern PARSEFUNC(insn_parse_relgen); +extern RESOLVEFUNC(insn_resolve_relgen); +extern EMITFUNC(insn_emit_relgen); + // MACRO pseudo op extern PARSEFUNC(pseudo_parse_macro); #define pseudo_resolve_macro NULL @@ -338,14 +343,14 @@ { "asrd", { 0x1047, -1, -1, -1 }, insn_parse_inh, insn_resolve_inh, insn_emit_inh, lwasm_insn_is6309}, { "band", { 0x1130, -1, -1, -1 }, insn_parse_bitbit, insn_resolve_bitbit, insn_emit_bitbit, lwasm_insn_is6309}, - { "bcc", { 0x24, -1, 0x24, 0x1024},insn_parse_rel8, insn_resolve_rel8, insn_emit_rel8, lwasm_insn_normal}, - { "bcs", { 0x25, -1, 0x25, 0x1025},insn_parse_rel8, insn_resolve_rel8, insn_emit_rel8, lwasm_insn_normal}, + { "bcc", { 0x24, 8, 0x24, 0x1024},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "bcs", { 0x25, 8, 0x25, 0x1025},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, { "beor", { 0x1134, -1, -1, -1 }, insn_parse_bitbit, insn_resolve_bitbit, insn_emit_bitbit, lwasm_insn_is6309}, - { "beq", { 0x27, -1, 0x27, 0x1027},insn_parse_rel8, insn_resolve_rel8, insn_emit_rel8, lwasm_insn_normal}, - { "bge", { 0x2c, -1, 0x2c, 0x102c},insn_parse_rel8, insn_resolve_rel8, insn_emit_rel8, lwasm_insn_normal}, - { "bgt", { 0x2e, -1, 0x2e, 0x102e},insn_parse_rel8, insn_resolve_rel8, insn_emit_rel8, lwasm_insn_normal}, - { "bhi", { 0x22, -1, 0x22, 0x1022},insn_parse_rel8, insn_resolve_rel8, insn_emit_rel8, lwasm_insn_normal}, - { "bhs", { 0x24, -1, 0x24, 0x1024},insn_parse_rel8, insn_resolve_rel8, insn_emit_rel8, lwasm_insn_normal}, + { "beq", { 0x27, 8, 0x27, 0x1027},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "bge", { 0x2c, 8, 0x2c, 0x102c},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "bgt", { 0x2e, 8, 0x2e, 0x102e},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "bhi", { 0x22, 8, 0x22, 0x1022},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "bhs", { 0x24, 8, 0x24, 0x1024},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, { "biand", { 0x1131, -1, -1, -1 }, insn_parse_bitbit, insn_resolve_bitbit, insn_emit_bitbit, lwasm_insn_is6309}, { "bieor", { 0x1135, -1, -1, -1 }, insn_parse_bitbit, insn_resolve_bitbit, insn_emit_bitbit, lwasm_insn_is6309}, { "bior", { 0x1133, -1, -1, -1 }, insn_parse_bitbit, insn_resolve_bitbit, insn_emit_bitbit, lwasm_insn_is6309}, @@ -353,19 +358,19 @@ { "bitb", { 0xd5, 0xe5, 0xf5, 0xc5}, insn_parse_gen8, insn_resolve_gen8, insn_emit_gen8, lwasm_insn_normal}, { "bitd", { 0x1095, 0x10a5, 0x10b5, 0x1085},insn_parse_gen16, insn_resolve_gen16, insn_emit_gen16, lwasm_insn_is6309}, { "bitmd", { 0x113c, -1, -1, 0x113c},insn_parse_imm8, insn_resolve_imm8, insn_emit_imm8, lwasm_insn_is6309}, - { "ble", { 0x2f, -1, 0x2f, 0x102f},insn_parse_rel8, insn_resolve_rel8, insn_emit_rel8, lwasm_insn_normal}, - { "blo", { 0x25, -1, 0x25, 0x1025},insn_parse_rel8, insn_resolve_rel8, insn_emit_rel8, lwasm_insn_normal}, - { "bls", { 0x23, -1, 0x23, 0x1023},insn_parse_rel8, insn_resolve_rel8, insn_emit_rel8, lwasm_insn_normal}, - { "blt", { 0x2d, -1, 0x2d, 0x102d},insn_parse_rel8, insn_resolve_rel8, insn_emit_rel8, lwasm_insn_normal}, - { "bmi", { 0x2b, -1, 0x2b, 0x102b},insn_parse_rel8, insn_resolve_rel8, insn_emit_rel8, lwasm_insn_normal}, - { "bne", { 0x26, -1, 0x26, 0x1026},insn_parse_rel8, insn_resolve_rel8, insn_emit_rel8, lwasm_insn_normal}, + { "ble", { 0x2f, 8, 0x2f, 0x102f},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "blo", { 0x25, 8, 0x25, 0x1025},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "bls", { 0x23, 8, 0x23, 0x1023},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "blt", { 0x2d, 8, 0x2d, 0x102d},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "bmi", { 0x2b, 8, 0x2b, 0x102b},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "bne", { 0x26, 8, 0x26, 0x1026},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, { "bor", { 0x1132, -1, -1, -1 }, insn_parse_bitbit, insn_resolve_bitbit, insn_emit_bitbit, lwasm_insn_is6309}, - { "bpl", { 0x2a, -1, 0x2a, 0x102a},insn_parse_rel8, insn_resolve_rel8, insn_emit_rel8, lwasm_insn_normal}, - { "bra", { 0x20, -1, 0x20, 0x16}, insn_parse_rel8, insn_resolve_rel8, insn_emit_rel8, lwasm_insn_normal}, - { "brn", { 0x21, -1, 0x21, 0x1021},insn_parse_rel8, insn_resolve_rel8, insn_emit_rel8, lwasm_insn_normal}, - { "bsr", { 0x8d, -1, 0x8d, 0x17}, insn_parse_rel8, insn_resolve_rel8, insn_emit_rel8, lwasm_insn_normal}, - { "bvc", { 0x28, -1, 0x28, 0x1028},insn_parse_rel8, insn_resolve_rel8, insn_emit_rel8, lwasm_insn_normal}, - { "bvs", { 0x29, -1, 0x29, 0x1029}, insn_parse_rel8, insn_resolve_rel8, insn_emit_rel8, lwasm_insn_normal}, + { "bpl", { 0x2a, 8, 0x2a, 0x102a},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "bra", { 0x20, 8, 0x20, 0x16}, insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "brn", { 0x21, 8, 0x21, 0x1021},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "bsr", { 0x8d, 8, 0x8d, 0x17}, insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "bvc", { 0x28, 8, 0x28, 0x1028},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "bvs", { 0x29, 8, 0x29, 0x1029}, insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, { "clr", { 0x0f, 0x6f, 0x7f, -1 }, insn_parse_gen0, insn_resolve_gen0, insn_emit_gen0, lwasm_insn_normal}, { "clra", { 0x4f, -1, -1, -1 }, insn_parse_inh, insn_resolve_inh, insn_emit_inh, lwasm_insn_normal}, @@ -423,25 +428,25 @@ { "jmp", { 0x0e, 0x6e, 0x7e, -1 }, insn_parse_gen0, insn_resolve_gen0, insn_emit_gen0, lwasm_insn_normal}, { "jsr", { 0x9d, 0xad, 0xbd, -1 }, insn_parse_gen0, insn_resolve_gen0, insn_emit_gen0, lwasm_insn_normal}, - { "lbcc", { 0x1024, -1, 0x24, 0x1024},insn_parse_rel16, insn_resolve_rel16, insn_emit_rel16, lwasm_insn_normal}, - { "lbcs", { 0x1025, -1, 0x25, 0x1025},insn_parse_rel16, insn_resolve_rel16, insn_emit_rel16, lwasm_insn_normal}, - { "lbeq", { 0x1027, -1, 0x27, 0x1027},insn_parse_rel16, insn_resolve_rel16, insn_emit_rel16, lwasm_insn_normal}, - { "lbge", { 0x102c, -1, 0x2c, 0x102c},insn_parse_rel16, insn_resolve_rel16, insn_emit_rel16, lwasm_insn_normal}, - { "lbgt", { 0x102e, -1, 0x2e, 0x102e},insn_parse_rel16, insn_resolve_rel16, insn_emit_rel16, lwasm_insn_normal}, - { "lbhi", { 0x1022, -1, 0x22, 0x1022},insn_parse_rel16, insn_resolve_rel16, insn_emit_rel16, lwasm_insn_normal}, - { "lbhs", { 0x1024, -1, 0x24, 0x1024},insn_parse_rel16, insn_resolve_rel16, insn_emit_rel16, lwasm_insn_normal}, - { "lble", { 0x102f, -1, 0x2f, 0x102f},insn_parse_rel16, insn_resolve_rel16, insn_emit_rel16, lwasm_insn_normal}, - { "lblo", { 0x1025, -1, 0x25, 0x1025},insn_parse_rel16, insn_resolve_rel16, insn_emit_rel16, lwasm_insn_normal}, - { "lbls", { 0x1023, -1, 0x23, 0x1023},insn_parse_rel16, insn_resolve_rel16, insn_emit_rel16, lwasm_insn_normal}, - { "lblt", { 0x102d, -1, 0x2d, 0x102d},insn_parse_rel16, insn_resolve_rel16, insn_emit_rel16, lwasm_insn_normal}, - { "lbmi", { 0x102b, -1, 0x2b, 0x102b},insn_parse_rel16, insn_resolve_rel16, insn_emit_rel16, lwasm_insn_normal}, - { "lbne", { 0x1026, -1, 0x26, 0x1026},insn_parse_rel16, insn_resolve_rel16, insn_emit_rel16, lwasm_insn_normal}, - { "lbpl", { 0x102a, -1, 0x2a, 0x102a},insn_parse_rel16, insn_resolve_rel16, insn_emit_rel16, lwasm_insn_normal}, - { "lbra", { 0x16, -1, 0x20, 0x16}, insn_parse_rel16, insn_resolve_rel16, insn_emit_rel16, lwasm_insn_normal}, - { "lbrn", { 0x1021, -1, 0x21, 0x1021},insn_parse_rel16, insn_resolve_rel16, insn_emit_rel16, lwasm_insn_normal}, - { "lbsr", { 0x17, -1, 0x8d, 0x17}, insn_parse_rel16, insn_resolve_rel16, insn_emit_rel16, lwasm_insn_normal}, - { "lbvc", { 0x1028, -1, 0x28, 0x1028},insn_parse_rel16, insn_resolve_rel16, insn_emit_rel16, lwasm_insn_normal}, - { "lbvs", { 0x1029, -1, 0x29, 0x1029},insn_parse_rel16, insn_resolve_rel16, insn_emit_rel16, lwasm_insn_normal}, + { "lbcc", { 0x1024, 16, 0x24, 0x1024},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "lbcs", { 0x1025, 16, 0x25, 0x1025},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "lbeq", { 0x1027, 16, 0x27, 0x1027},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "lbge", { 0x102c, 16, 0x2c, 0x102c},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "lbgt", { 0x102e, 16, 0x2e, 0x102e},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "lbhi", { 0x1022, 16, 0x22, 0x1022},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "lbhs", { 0x1024, 16, 0x24, 0x1024},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "lble", { 0x102f, 16, 0x2f, 0x102f},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "lblo", { 0x1025, 16, 0x25, 0x1025},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "lbls", { 0x1023, 16, 0x23, 0x1023},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "lblt", { 0x102d, 16, 0x2d, 0x102d},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "lbmi", { 0x102b, 16, 0x2b, 0x102b},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "lbne", { 0x1026, 16, 0x26, 0x1026},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "lbpl", { 0x102a, 16, 0x2a, 0x102a},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "lbra", { 0x16, 16, 0x20, 0x16}, insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "lbrn", { 0x1021, 16, 0x21, 0x1021},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "lbsr", { 0x17, 16, 0x8d, 0x17}, insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "lbvc", { 0x1028, 16, 0x28, 0x1028},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, + { "lbvs", { 0x1029, 16, 0x29, 0x1029},insn_parse_relgen, insn_resolve_relgen, insn_emit_relgen, lwasm_insn_normal}, { "lda", { 0x96, 0xa6, 0xb6, 0x86}, insn_parse_gen8, insn_resolve_gen8, insn_emit_gen8, lwasm_insn_normal}, { "ldb", { 0xd6, 0xe6, 0xf6, 0xc6}, insn_parse_gen8, insn_resolve_gen8, insn_emit_gen8, lwasm_insn_normal}, { "ldbt", { 0x1136, -1, -1, -1 }, insn_parse_bitbit, insn_resolve_bitbit, insn_emit_bitbit, lwasm_insn_is6309},