summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2023-08-07 00:15:22 +0300
committerOxore <oxore@protonmail.com>2023-08-07 00:15:22 +0300
commite73d751459a5777809a18ec322e3e7f6db59ce9d (patch)
tree1072cfc2e3afd4092f541a8fc034d2296186bf99
parent85139bd2345bd8b76cb1725ad08eea4a27fabb13 (diff)
Extract function to parse sub arg inside parens
-rw-r--r--main.c158
-rwxr-xr-xtest.sh1
-rw-r--r--tests/test1.S40
-rw-r--r--tests/test2.S44
4 files changed, 133 insertions, 110 deletions
diff --git a/main.c b/main.c
index db4dca3..b8f39cd 100644
--- a/main.c
+++ b/main.c
@@ -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;
}
diff --git a/test.sh b/test.sh
index 399f65e..41bfa8c 100755
--- a/test.sh
+++ b/test.sh
@@ -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