diff options
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) { |