diff options
author | mrb0nk500 <b0nk@b0nk.xyz> | 2021-02-25 12:43:11 -0500 |
---|---|---|
committer | mrb0nk500 <b0nk@b0nk.xyz> | 2021-02-25 12:43:11 -0500 |
commit | 35a18609864470b3dc49f3a9a6cb6ec93e57300d (patch) | |
tree | c52364211b25723b2cf4595ed6c4bc2d45195062 /assemble.c | |
parent | 8d7f27d9a0b61d3694a62f3e54be885d8073f02b (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.c | 78 |
1 files changed, 60 insertions, 18 deletions
@@ -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) { |