exit(1); \
} while (0)
+#include "masm_tools.h"
+
enum op_flags {
OPF_RMD = (1 << 0), /* removed or optimized out */
OPF_DATA = (1 << 1), /* data processing - writes to dst opr */
return -1;
}
-static unsigned long parse_number(const char *number)
-{
- int len = strlen(number);
- const char *p = number;
- char *endp = NULL;
- unsigned long ret;
- int neg = 0;
- int bad;
-
- if (*p == '-') {
- neg = 1;
- p++;
- }
- if (len > 1 && *p == '0')
- p++;
- if (number[len - 1] == 'h') {
- ret = strtoul(p, &endp, 16);
- bad = (*endp != 'h');
- }
- else {
- ret = strtoul(p, &endp, 10);
- bad = (*endp != 0);
- }
- if (bad)
- aerr("number parsing failed\n");
- if (neg)
- ret = -ret;
- return ret;
-}
-
static int parse_indmode(char *name, int *regmask, int need_c_cvt)
{
enum opr_lenmod lmod;
// most likely var in data segment
opr->type = OPT_LABEL;
- pp = proto_parse(g_fhdr, opr->name);
+ pp = proto_parse(g_fhdr, opr->name, 0);
if (pp != NULL) {
if (pp->is_fptr || pp->is_func) {
opr->lmod = OPLM_DWORD;
ferr(po, "bp_arg arg%d/w offset %d and type '%s' is too small\n",
i + 1, offset, g_func_pp->arg[i].type.name);
}
+ if (popr->is_ptr && popr->lmod != OPLM_DWORD)
+ ferr(po, "bp_arg arg%d: non-dword ptr access\n", i + 1);
}
else
{
{
const struct parsed_proto *pp;
- pp = proto_parse(g_fhdr, name);
+ pp = proto_parse(g_fhdr, name, 0);
if (pp == NULL)
ferr(po, "proto_parse failed for ref '%s'\n", name);
static int scan_for_esp_adjust(int i, int opcnt, int *adj)
{
struct parsed_op *po;
- int i_first = i;
+ int first_pop = -1;
*adj = 0;
for (; i < opcnt; i++) {
ferr(&ops[i], "unaligned esp adjust: %x\n", *adj);
return i;
}
- else if (po->op == OP_PUSH)
+ else if (po->op == OP_PUSH) {
+ if (first_pop == -1)
+ first_pop = -2; // none
*adj -= lmod_bytes(po, po->operand[0].lmod);
- else if (po->op == OP_POP)
+ }
+ else if (po->op == OP_POP) {
+ if (first_pop == -1)
+ first_pop = i;
*adj += lmod_bytes(po, po->operand[0].lmod);
+ }
else if (po->flags & (OPF_JMP|OPF_TAIL)) {
if (po->op != OP_CALL)
break;
}
}
- if (*adj == 4 && ops[i_first].op == OP_POP
- && ops[i_first].operand[0].type == OPT_REG
- && ops[i_first].operand[0].reg == xCX)
+ if (*adj == 4 && first_pop >= 0 && ops[first_pop].op == OP_POP
+ && ops[first_pop].operand[0].type == OPT_REG
+ && ops[first_pop].operand[0].reg == xCX)
{
// probably 'pop ecx' was used..
- return i_first;
+ return first_pop;
}
return -1;
pp = g_func_pp->arg[arg].fptr;
if (pp == NULL)
- ferr(po, "icall: arg%d is not a fptr?\n", arg + 1);
+ ferr(po, "icall sa: arg%d is not a fptr?\n", arg + 1);
if (pp->argc_reg != 0)
- ferr(po, "icall: reg arg in arg-call unhandled yet\n");
+ ferr(po, "icall sa: reg arg in arg-call unhandled yet\n");
}
else if (opr->type == OPT_OFFSET || opr->type == OPT_LABEL) {
- pp = proto_parse(g_fhdr, opr->name);
+ pp = proto_parse(g_fhdr, opr->name, 0);
if (pp == NULL)
ferr(po, "proto_parse failed for icall from '%s'\n", opr->name);
if (pp->argc_reg != 0)
lr = &g_label_refs[i];
for (; lr != NULL; lr = lr->next)
scan_for_call_type(lr->i, opr, magic, pp_found);
- if (i > 0) {
- if (LAST_OP(i - 1))
- return;
- scan_for_call_type(i - 1, opr, magic, pp_found);
- }
- return;
+ if (i > 0 && LAST_OP(i - 1))
+ return;
}
i--;
return;
pp = g_func_pp->arg[i].fptr;
if (pp == NULL)
- ferr(po, "icall: arg%d is not a fptr?\n", i + 1);
+ ferr(po, "icall: arg%d (%s) is not a fptr?\n",
+ i + 1, g_func_pp->arg[i].reg);
if (pp->argc_reg != 0)
ferr(po, "icall: reg arg in arg-call unhandled yet\n");
}
g_bp_frame = g_sp_frame = g_stack_fsz = 0;
g_stack_frame_used = 0;
- g_func_pp = proto_parse(fhdr, funcn);
+ g_func_pp = proto_parse(fhdr, funcn, 0);
if (g_func_pp == NULL)
ferr(ops, "proto_parse failed for '%s'\n", funcn);
if (po->op == OP_CALL) {
if (po->operand[0].type == OPT_LABEL) {
tmpname = opr_name(po, 0);
- pp_c = proto_parse(fhdr, tmpname);
+ if (IS_START(tmpname, "loc_"))
+ ferr(po, "call to loc_*\n");
+ pp_c = proto_parse(fhdr, tmpname, 0);
if (pp_c == NULL)
ferr(po, "proto_parse failed for call '%s'\n", tmpname);
if (pp_c->is_fptr && pp_c->argc_reg != 0)