summaryrefslogtreecommitdiff
path: root/assemble.c
diff options
context:
space:
mode:
authormrb0nk500 <b0nk@b0nk.xyz>2021-02-25 12:43:11 -0500
committermrb0nk500 <b0nk@b0nk.xyz>2021-02-25 12:43:11 -0500
commit35a18609864470b3dc49f3a9a6cb6ec93e57300d (patch)
treec52364211b25723b2cf4595ed6c4bc2d45195062 /assemble.c
parent8d7f27d9a0b61d3694a62f3e54be885d8073f02b (diff)
- Implemented the multiply expression into the assembler.
- Implemented support for the SIB addressing mode into the assembler. SIB is short for "Scale Index, and Base", and works much like x86's version of SIB (scale*index+base), although my version supports any scale value between 1, and 256. - Redid the line shifting routine in SuBEditor. It now uses memcpy, and memset to do that, and also supports shifting the line left, or right by any number of characters.
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) {