diff options
| -rw-r--r-- | main.c | 158 | ||||
| -rwxr-xr-x | test.sh | 1 | ||||
| -rw-r--r-- | tests/test1.S | 40 | ||||
| -rw-r--r-- | tests/test2.S | 44 | 
4 files changed, 133 insertions, 110 deletions
| @@ -2152,6 +2152,65 @@ static int pars_parse_arg_starts_with_minus(      return pars_parse_arg_after_prefix_expr(self, arg);  } +struct inside_parens_state { +    bool an1_found, an2_found, dn_found, pc_found; +    uint8_t an1, an2, dn, parts; +}; + +static int pars_parse_arg_inside_parens_single_item( +        struct pars *const self, +        struct arg *const arg, +        struct inside_parens_state *const state) +{ +    const struct token token0 = pars_peek(self); +    if (token0.type == TT_ID) { +        // It it may be An/Dn/PC register +        struct token_recognition r = pars_recognize_token(self, token0); +        if (r.type == RTT_REG) { +            // This is definitely a register or regmask. +            switch (r.reg) { +            case REG_DN: +                state->dn_found = true; +                state->dn = r.reg_num; +                break; +            case REG_AN: +                if (!state->an1_found) { +                    state->an1_found = true; +                    state->an1 = r.reg_num; +                } else if (!state->an2_found) { +                    state->an2_found = true; +                    state->an2 = r.reg_num; +                } else { +                    return pars_yield_error(self, pars_commit(self), E_EA_PART_NOT_AN); +                } +                break; +            case REG_PC: +                state->pc_found = true; +                break; +            case REG_NONE: +                UNREACHABLE(); +            case REG_SR: +            case REG_CCR: +            case REG_USP: +                return pars_yield_error(self, pars_commit(self), E_EA_PART); +            } +            pars_commit(self); +        } +    } else if (arg->expr.first_token == 0) { +        const int ret = pars_parse_expr(self, &arg->expr); +        if (ret != OK) { +            return ret; +        } +    } else { +        return pars_yield_error(self, self->cur_tok_id, E_EA_PART_NOT_EXPR); +    } +    state->parts++; +    if (pars_is_eof_reached(self)) { +        return pars_yield_error_eof(self, E_EA_PART_DELIM); +    } +    return OK; +} +  static int pars_parse_arg_inside_parens(          struct pars *const self, struct arg *const arg)  { @@ -2160,75 +2219,34 @@ static int pars_parse_arg_inside_parens(      // It can be      // - (expr)(An)      // - (expr)(An,Xi) or (expr)(Xi,An) +    // - (expr)(An,Xi.w) or (expr)(Xi.w,An)      // - (expr)(PC,Xi) or (expr)(Xi,PC) +    // - (expr)(PC,Xi.w) or (expr)(Xi.w,PC)      // - (An) or (An)+      // - (An,expr) or (expr,An)      // - (PC,expr) or (expr,PC) -    // - (An,expr,Xi), (An,Xi,expr), (expr,An,Xi), (expr,Xi,An), (Xi,expr,An) or -    // (Xi,An,expr) -    // - (PC,expr,Xi), (PC,Xi,expr), (expr,PC,Xi), (expr,Xi,PC), (Xi,expr,PC) or -    // (Xi,PC,expr) -    bool an1_found = false, an2_found = false, dn_found = false; -    bool pc_found = false; -    uint8_t an1 = 0, an2 = 0, dn = 0; -    unsigned parts = arg->expr.first_token ? 1 : 0; -    while (parts < 3) { +    // - (An,expr,Xi) in any order (6 variants) +    // - (An,expr,Xi.w) in any order (6 variants) +    // - (PC,expr,Xi) in any order (6 variants) +    // - (PC,expr,Xi.w) in any order (6 variants) +    struct inside_parens_state state = { +        .parts = arg->expr.first_token ? 1 : 0, +    }; +    while (state.parts < 3) {          if (pars_is_eof_reached(self)) {              return pars_yield_error_eof(self, E_EA_PART);          } -        const struct token token0 = pars_peek(self); -        if (token0.type == TT_ID) { -            // It it may be An/Dn/PC register -            struct token_recognition r = pars_recognize_token(self, token0); -            if (r.type == RTT_REG) { -                // This is definitely a register or regmask. -                switch (r.reg) { -                case REG_DN: -                    dn_found = true; -                    dn = r.reg_num; -                    break; -                case REG_AN: -                    if (!an1_found) { -                        an1_found = true; -                        an1 = r.reg_num; -                    } else if (!an2_found) { -                        an2_found = true; -                        an2 = r.reg_num; -                    } else { -                        return pars_yield_error(self, pars_commit(self), E_EA_PART_NOT_AN); -                    } -                    break; -                case REG_PC: -                    pc_found = true; -                    break; -                case REG_NONE: -                    UNREACHABLE(); -                case REG_SR: -                case REG_CCR: -                case REG_USP: -                    return pars_yield_error(self, pars_commit(self), E_EA_PART); -                } -                pars_commit(self); -            } -        } else if (arg->expr.first_token == 0) { -            const int ret = pars_parse_expr(self, &arg->expr); -            if (ret != OK) { -                return ret; -            } -        } else { -            return pars_yield_error(self, self->cur_tok_id, E_EA_PART_NOT_EXPR); -        } -        parts++; -        if (pars_is_eof_reached(self)) { -            return pars_yield_error_eof(self, E_EA_PART_DELIM); +        const int ret = pars_parse_arg_inside_parens_single_item(self, arg, &state); +        if (ret != OK) { +            return ret;          }          const struct token delim = pars_peek(self);          const size_t delim_id = pars_commit(self);          if (delim.type == TT_COMMA) {              continue;          } else if (delim.type == TT_RPAREN) { -            if (parts == 1 && arg->expr.first_token) { -                assert(!an1_found && !an2_found && !dn_found && !pc_found); +            if (state.parts == 1 && arg->expr.first_token) { +                assert(!state.an1_found && !state.an2_found && !state.dn_found && !state.pc_found);                  // It turns out we are inside of expression, so this closing                  // parenthesis is part of it. Let's accumulate it and move                  // on. @@ -2242,9 +2260,9 @@ static int pars_parse_arg_inside_parens(              return pars_yield_error(self, delim_id, E_EA_PART);          }      } -    if (parts == 1 && an1_found) { +    if (state.parts == 1 && state.an1_found) {          // It is either (An) or (An)+ -        assert(!pc_found && !dn_found && !arg->expr.first_token); +        assert(!state.pc_found && !state.dn_found && !arg->expr.first_token);          if (pars_is_eof_reached(self)) {              arg->type = ARG_AN_ADDR;          } else { @@ -2256,34 +2274,34 @@ static int pars_parse_arg_inside_parens(                  arg->type = ARG_AN_ADDR;              }          } -        arg->xn = an1; +        arg->xn = state.an1;          arg->num_tokens = self->cur_tok_id - arg->first_token;          return OK; -    } else if (parts == 2 && an1_found && arg->expr.first_token) { +    } else if (state.parts == 2 && state.an1_found && arg->expr.first_token) {          // It is (An,d16) or (d16,An) -        assert(!an2_found && !pc_found && !dn_found); +        assert(!state.an2_found && !state.pc_found && !state.dn_found);          arg->type = ARG_AN_ADDR_16; -        arg->xn = an1; +        arg->xn = state.an1;          arg->num_tokens = self->cur_tok_id - arg->first_token;          return OK; -    } else if (parts == 2 && pc_found && arg->expr.first_token) { +    } else if (state.parts == 2 && state.pc_found && arg->expr.first_token) {          // It is (PC,d16) or (d16,PC) -        assert(!an1_found && !an2_found && !dn_found); +        assert(!state.an1_found && !state.an2_found && !state.dn_found);          arg->type = ARG_PC_ADDR_16;          arg->num_tokens = self->cur_tok_id - arg->first_token;          return OK; -    } else if (parts == 3 && pc_found && arg->expr.first_token && (an1_found || dn_found)) { +    } else if (state.parts == 3 && state.pc_found && arg->expr.first_token && (state.an1_found || state.dn_found)) {          // It is (d8,PC,Xn) -        assert((an1_found && !dn_found) || (!an1_found && dn_found)); +        assert((state.an1_found && !state.dn_found) || (!state.an1_found && state.dn_found));          arg->type = ARG_PC_ADDR_8_XI; -        arg->xi = an1_found ? (an1 | 0x8) : dn; +        arg->xi = state.an1_found ? (state.an1 | 0x8) : state.dn;          arg->num_tokens = self->cur_tok_id - arg->first_token;          return OK; -    } else if (parts == 3 && an1_found && arg->expr.first_token && (an2_found || dn_found)) { +    } else if (state.parts == 3 && state.an1_found && arg->expr.first_token && (state.an2_found || state.dn_found)) {          // It is (d8,An,Xn) -        assert((an2_found && !dn_found) || (!an2_found && dn_found)); +        assert((state.an2_found && !state.dn_found) || (!state.an2_found && state.dn_found));          arg->type = ARG_AN_ADDR_8_XI; -        arg->xi = an2_found ? (an2 | 0x8) : dn; +        arg->xi = state.an2_found ? (state.an2 | 0x8) : state.dn;          arg->num_tokens = self->cur_tok_id - arg->first_token;          return OK;      } @@ -11,4 +11,5 @@ set INCLUDE68=e:\\sierra\\include  set TEMP=c:\\tmp  END  echo "asm68 -l -Q -o test1.o test1.S" >>"$dosbuild_dir/build.bat" +echo "asm68 -l -Q -o test2.o test2.S" >>"$dosbuild_dir/build.bat"  dosemu -quiet -K "$dosbuild_dir" -E'build.bat' diff --git a/tests/test1.S b/tests/test1.S index 5b79cec..07d1ce1 100644 --- a/tests/test1.S +++ b/tests/test1.S @@ -13,61 +13,21 @@ move (32767,pc),d1  move (pc,32767),d1  move 127(a1,d1),d1 -move 127(a1,d1.l),d1 -move 127(a1,d1.l),d1 -move 127.l(a1,d1.l),d1  move 127(d1,a1),d1 -move 127(d1.l,a1),d1 -move 127(d1.l,a1),d1 -move 127.l(d1.l,a1),d1  move 127(pc,d1),d1 -move 127(pc,d1.l),d1 -move 127.l(pc,d1),d1 -move 127.l(pc,d1.l),d1  move 127(d1,pc),d1 -move 127(d1.l,pc),d1 -move 127.l(d1,pc),d1 -move 127.l(d1.l,pc),d1  move (a1,d1,127),d1 -move (a1,d1.l,127),d1 -move (a1,d1.l,127.l),d1 -move (a1,d1,127.l),d1  move (d1,a1,127),d1 -move (d1.l,a1,127),d1 -move (d1,a1,127.l),d1 -move (d1.l,a1,127.l),d1  move (a1,127,d1),d1 -move (a1,127,d1.l),d1 -move (a1,127.l,d1),d1 -move (a1,127.l,d1.l),d1  move (d1,127,a1),d1 -move (d1.l,127,a1),d1 -move (d1,127.l,a1),d1 -move (d1.l,127.l,a1),d1 -move (d1.l,127.l,a1),d1 -move (a1.l,127.l,a1),d1  move (pc,d1,127),d1 -move (pc,d1.l,127),d1 -move (pc,d1,127.l),d1  move (d1,pc,127),d1 -move (d1.l,pc,127),d1 -move (d1,pc,127.l),d1 -move (d1.l,pc,127.l),d1  move (pc,127,d1),d1 -move (pc,127,d1.l),d1 -move (pc,127.l,d1),d1 -move (pc,127.l,d1.l),d1  move (d1,127,pc),d1 -move (d1.l,127,pc),d1 -move (d1,127.l,pc),d1 -move (d1.l,127.l,pc),d1 -loc: -move 0.l,d1 -move loc.l,d1  move #127,d1  move #-128,d1  move #255,d1 diff --git a/tests/test2.S b/tests/test2.S new file mode 100644 index 0000000..4a8ee7d --- /dev/null +++ b/tests/test2.S @@ -0,0 +1,44 @@ +move 127(a1,d1.l),d1 +move 127(a1,d1.l),d1 +move 127.l(a1,d1.l),d1 +move 127(d1.l,a1),d1 +move 127(d1.l,a1),d1 +move 127.l(d1.l,a1),d1 + +move 127(pc,d1.l),d1 +move 127.l(pc,d1),d1 +move 127.l(pc,d1.l),d1 +move 127(d1.l,pc),d1 +move 127.l(d1,pc),d1 +move 127.l(d1.l,pc),d1 + +move (a1,d1.l,127),d1 +move (a1,d1.l,127.l),d1 +move (a1,d1,127.l),d1 +move (d1.l,a1,127),d1 +move (d1,a1,127.l),d1 +move (d1.l,a1,127.l),d1 +move (a1,127,d1.l),d1 +move (a1,127.l,d1),d1 +move (a1,127.l,d1.l),d1 +move (d1.l,127,a1),d1 +move (d1,127.l,a1),d1 +move (d1.l,127.l,a1),d1 +move (d1.l,127.l,a1),d1 +move (a1.l,127.l,a1),d1 + +move (pc,d1.l,127),d1 +move (pc,d1,127.l),d1 +move (d1.l,pc,127),d1 +move (d1,pc,127.l),d1 +move (d1.l,pc,127.l),d1 +move (pc,127,d1.l),d1 +move (pc,127.l,d1),d1 +move (pc,127.l,d1.l),d1 +move (d1.l,127,pc),d1 +move (d1,127.l,pc),d1 +move (d1.l,127.l,pc),d1 + +loc: +move 0.l,d1 +move loc.l,d1 | 
