summaryrefslogtreecommitdiff
path: root/assemble.c
diff options
context:
space:
mode:
Diffstat (limited to 'assemble.c')
-rw-r--r--assemble.c78
1 files changed, 60 insertions, 18 deletions
diff --git a/assemble.c b/assemble.c
index a3791d3..713c297 100644
--- a/assemble.c
+++ b/assemble.c
@@ -120,13 +120,20 @@ uint64_t get_val(expr *tree, uint64_t addr, uint8_t size, int depth, uint8_t dbg
uint64_t expr_val = 0;
int type;
- int is_start = (!depth && tree->left && tree->right == NULL);
+ int has_lvalue = (tree && tree->left != NULL);
+ int has_rvalue = (tree && tree->right != NULL);
- if (tree->left) {
+ int is_start = (!depth && has_lvalue && !has_rvalue);
+
+ if (tree == NULL) {
+ return 0;
+ }
+
+ if (has_lvalue) {
lvalue = get_val(tree->left, addr, size, depth+1, dbg);
}
- if (tree->right) {
+ if (has_rvalue) {
rvalue = get_val(tree->right, addr, size, depth+1, dbg);
}
@@ -141,9 +148,10 @@ uint64_t get_val(expr *tree, uint64_t addr, uint8_t size, int depth, uint8_t dbg
case EXPR_SYM: value = (tree->value.sym) ? tree->value.sym->val : addr; break;
case EXPR_PLUS: value = lvalue + rvalue; break;
case EXPR_MINUS: (is_start) ? (value = -lvalue) : (value = lvalue - rvalue); break;
- case EXPR_OR: value = lvalue | rvalue; break;
- case EXPR_LSHFT: value = lvalue << rvalue; break;
- case EXPR_RSHFT: value = lvalue >> rvalue; break;
+ case EXPR_MUL : value = (has_rvalue) ? lvalue * rvalue : lvalue; break;
+ case EXPR_OR : value = (has_rvalue) ? lvalue | rvalue : lvalue; break;
+ case EXPR_LSHFT : value = (has_rvalue) ? lvalue << rvalue : lvalue; break;
+ case EXPR_RSHFT : value = (has_rvalue) ? lvalue >> rvalue : lvalue; break;
case EXPR_LOW:
case EXPR_HIGH:
value = lvalue;
@@ -403,6 +411,7 @@ int is_value(expr *e, expr **found) {
if (e == NULL) {
return 0;
}
+
switch (e->type) {
case EXPR_HEX :
case EXPR_DEC :
@@ -414,11 +423,8 @@ int is_value(expr *e, expr **found) {
}
return 1;
default:
- if (e->left) {
- return is_value(e->left, found);
- }
- if (e->right) {
- return is_value(e->right, found);
+ if ((e->left && is_value(e->left, found)) || (e->right && is_value(e->right, found))) {
+ return 1;
}
break;
}
@@ -428,6 +434,27 @@ int is_value(expr *e, expr **found) {
return 0;
}
+expr *find_expr(expr *tree, int type) {
+ if (tree != NULL) {
+ expr *left = NULL;
+ expr *right = NULL;
+
+ if (tree->type == type) {
+ return tree;
+ }
+ if (tree->left) {
+ left = find_expr(tree->left, type);
+ }
+ if (tree->right) {
+ right = find_expr(tree->right, type);
+ }
+ if (left || right) {
+ return (left) ? left : right;
+ }
+ }
+ return NULL;
+}
+
token *get_operands(token *t, operand *op, uint64_t address, uint8_t rs, uint8_t dbg) {
uint8_t op_type;
uint8_t op_inst;
@@ -475,13 +502,13 @@ token *get_operands(token *t, operand *op, uint64_t address, uint8_t rs, uint8_t
case TOK_EXPR:
isvalue = is_value(t->expr, NULL);
if (!got_value) {
- expr *e = t->expr;
+ expr *e = find_expr(t->expr, EXPR_MUL);
if (isvalue) {
if (expr_type == 0xFF && e) {
- expr_type = (e->right) ? e->right->type : e->type;
+ expr_type = e->type;
}
stop_comma = (expr_type != EXPR_MUL);
- value = get_val(e, address, (rs != 0xFF) ? rs : 0, 0, dbg);
+ value = get_val(t->expr, address, (rs != 0xFF) ? rs : 0, 0, dbg);
} else {
break;
}
@@ -507,8 +534,6 @@ token *get_operands(token *t, operand *op, uint64_t address, uint8_t rs, uint8_t
if (old_i != i) {
op[i].type = 1; /* Set type to memory. */
op[i].id = (t->id == TOK_MEM) ? t->type : 0xFF;
- op[i].id = (is_sib) ? MEM_SIB : op[i].id;
- op[i].scale = (is_sib) ? value : op[i].scale;
old_i = i;
} else {
if (!op[i].type && !is_sib) {
@@ -528,12 +553,26 @@ token *get_operands(token *t, operand *op, uint64_t address, uint8_t rs, uint8_t
old_i = i;
} else {
if (op[i].type == 1) {
- if (op[i].id == MEM_IND) {
+ if (op[i].id == MEM_IND && !is_sib) {
op[i].id = ((!brack_done || brack_done == 2) && got_value) ? MEM_ZRIND : MEM_RIND;
op[i].id = (brack_done == 1 && got_value) ? MEM_ZINDR : op[i].id;
brack_done = 0;
} else {
- op[i].id = (got_value) ? MEM_ZMR : op[i].id;
+ if (!is_sib) {
+ op[i].id = (got_value) ? MEM_ZMR : op[i].id;
+ } else if (op[i].id != MEM_SIB) {
+ op[i].type = 1;
+ op[i].id = MEM_SIB;
+ /* An invalid scale value was found.
+ * If we're doing error checking, print an error here.
+ * If not, clamp it to either the minimum, or maximum scale value.
+ */
+ if (!value || value > 256) {
+ value = (!value) ? 1 : 256;
+ }
+ op[i].scale = value-1;
+ op[i].value = 0;
+ }
}
op[i].rind[reg] = t->type;
reg++;
@@ -904,6 +943,7 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,
if (op[i].type == 1 && (am & (AM_ORTHO|AM_ORTHO2))) {
switch (op[i].id) {
+ case MEM_SIB : break;
case MEM_RIND: break;
case MEM_IMM:
rs = (rs != 0xFF) ? rs : 0;
@@ -936,6 +976,7 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,
}
}
}
+
switch (opsize-1) {
case 0: case 2: case 5: case 3: type = ZM ; break;
case 1: case 4: case 6: case 7: type = ABS; break;
@@ -947,6 +988,7 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,
case MEM_ZINDR: op[i].id = (type == ABS) ? MEM_AINDR : op[i].id; break;
case 0xFF : op[i].id = (type == ABS) ? MEM_ABS : MEM_ZM; break;
}
+
if (opsize) {
uint8_t is_abs = (type == ABS);
/*if (!is_abs) {