2 * Copyright (C) 2009-2011 Marcelina KoĆcielnicka <mwk@0x04.net>
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
25 #include "dis-intern.h"
30 const struct disisa
*isa
;
31 struct varinfo
*varinfo
;
37 struct matches
*emptymatches() {
38 struct matches
*res
= calloc(sizeof *res
, 1);
42 struct matches
*alwaysmatches(int lpos
) {
43 struct matches
*res
= calloc(sizeof *res
, 1);
44 struct match m
= { .lpos
= lpos
};
49 struct matches
*catmatches(struct matches
*a
, struct matches
*b
) {
51 for (i
= 0; i
< b
->mnum
; i
++)
52 ADDARRAY(a
->m
, b
->m
[i
]);
58 struct matches
*mergematches(struct match a
, struct matches
*b
) {
59 struct matches
*res
= emptymatches();
61 for (i
= 0; i
< b
->mnum
; i
++) {
62 for (j
= 0; j
< MAXOPLEN
; j
++) {
63 ull cmask
= a
.m
[j
] & b
->m
[i
].m
[j
];
64 if ((a
.a
[j
] & cmask
) != (b
->m
[i
].a
[j
] & cmask
))
68 struct match nm
= b
->m
[i
];
71 for (j
= 0; j
< MAXOPLEN
; j
++) {
76 assert (a
.nrelocs
+ nm
.nrelocs
<= 8);
77 for (j
= 0; j
< a
.nrelocs
; j
++)
78 nm
.relocs
[nm
.nrelocs
+ j
] = a
.relocs
[j
];
79 nm
.nrelocs
+= a
.nrelocs
;
88 static inline ull
bf_(int s
, int l
, ull
*a
, ull
*m
) {
92 ull m0
= (((1ull << l
) - 1) << bit
);
94 res
|= (a
[idx
] & m0
) >> bit
;
96 ull m1
= (((1ull << l
) - 1) >> (0x40 - bit
));
98 res
|= (a
[idx
+1] & m1
) << (0x40 - bit
);
102 #define BF(s, l) bf_(s, l, a, m)
104 ull
getrbf_as(const struct rbitfield
*bf
, ull
*a
, ull
*m
, ull cpos
) {
108 for (i
= 0; i
< sizeof(bf
->sbf
) / sizeof(bf
->sbf
[0]); i
++) {
109 res
|= BF(bf
->sbf
[i
].pos
, bf
->sbf
[i
].len
) << pos
;
110 pos
+= bf
->sbf
[i
].len
;
116 if (res
& 1ull << (pos
- 1))
119 case RBF_SLIGHTLY_SIGNED
:
120 if (res
& 1ull << (pos
- 1) && res
& 1ull << (pos
- 2))
123 case RBF_ULTRASIGNED
:
129 res
+= (cpos
+ bf
->pospreadd
) & -(1ull << bf
->shr
);
135 ull
getbf_as(const struct bitfield
*bf
, ull
*a
, ull
*m
) {
139 for (i
= 0; i
< sizeof(bf
->sbf
) / sizeof(bf
->sbf
[0]); i
++) {
140 res
|= BF(bf
->sbf
[i
].pos
, bf
->sbf
[i
].len
) << pos
;
141 pos
+= bf
->sbf
[i
].len
;
147 if (res
& 1ull << (pos
- 1))
150 case BF_SLIGHTLY_SIGNED
:
151 if (res
& 1ull << (pos
- 1) && res
& 1ull << (pos
- 2))
166 int setsbf (struct match
*res
, int pos
, int len
, ull num
) {
169 int idx
= pos
/ 0x40;
171 ull m
= ((1ull << len
) - 1) << pos
;
172 ull a
= (num
<< pos
) & m
;
173 if ((a
& m
& res
->m
[idx
]) == (res
->a
[idx
] & m
& res
->m
[idx
])) {
179 if (pos
+ len
> 0x40) {
180 ull m1
= (((1ull << len
) - 1) >> (0x40 - pos
));
181 ull a1
= (num
>> (0x40 - pos
)) & m1
;
182 if ((a1
& m1
& res
->m
[idx
+1]) == (res
->a
[idx
+1] & m1
& res
->m
[idx
+1])) {
192 static int setrbf (struct match
*res
, const struct rbitfield
*bf
, struct easm_expr
*expr
) {
193 if (!easm_isimm(expr
))
195 if (expr
->type
!= EASM_EXPR_NUM
|| bf
->pcrel
) {
196 assert (res
->nrelocs
!= 8);
197 res
->relocs
[res
->nrelocs
].bf
= bf
;
198 res
->relocs
[res
->nrelocs
].expr
= expr
;
202 ull num
= expr
->num
- bf
->addend
;
204 setsbf(res
, bf
->sbf
[0].pos
, bf
->sbf
[0].len
, num
);
205 num
>>= bf
->sbf
[0].len
;
206 setsbf(res
, bf
->sbf
[1].pos
, bf
->sbf
[1].len
, num
);
208 ull totalsz
= bf
->shr
+ bf
->sbf
[0].len
+ bf
->sbf
[1].len
;
209 if (bf
->wrapok
&& totalsz
< 64)
210 mask
= (1ull << totalsz
) - 1;
211 return (getrbf_as(bf
, res
->a
, res
->m
, 0) & mask
) == (expr
->num
& mask
);
214 static int setbf (struct match
*res
, const struct bitfield
*bf
, ull num
) {
216 num
= (num
- bf
->addend
) ^ bf
->xorend
;
218 int max
= 1 << (bf
->sbf
[0].len
+ bf
->sbf
[1].len
);
220 for (j
= 0; j
< max
; j
++)
221 if (bf
->lut
[j
] == num
)
228 setsbf(res
, bf
->sbf
[0].pos
, bf
->sbf
[0].len
, num
);
229 num
>>= bf
->sbf
[0].len
;
230 setsbf(res
, bf
->sbf
[1].pos
, bf
->sbf
[1].len
, num
);
232 return (getbf_as(bf
, res
->a
, res
->m
) & mask
) == (onum
& mask
);
235 struct matches
*tabdesc (struct iasctx
*ctx
, struct match m
, const struct atom
*atoms
) {
236 if (!atoms
->fun_as
) {
237 struct matches
*res
= emptymatches();
241 struct matches
*ms
= atoms
->fun_as(ctx
, atoms
->arg
, m
.lpos
);
244 ms
= mergematches(m
, ms
);
248 struct matches
*res
= emptymatches();
250 for (i
= 0; i
< ms
->mnum
; i
++) {
251 struct matches
*tmp
= tabdesc(ctx
, ms
->m
[i
], atoms
);
253 res
= catmatches(res
, tmp
);
260 struct matches
*atomtab_a APROTO
{
261 const struct insn
*tab
= v
;
262 struct matches
*res
= emptymatches();
265 if (var_ok(tab
[i
].fmask
, tab
[i
].ptype
, ctx
->varinfo
)) {
266 struct match sm
= { 0, .a
= {tab
[i
].val
}, .m
= {tab
[i
].mask
}, .lpos
= spos
};
267 struct matches
*subm
= tabdesc(ctx
, sm
, tab
[i
].atoms
);
269 res
= catmatches(res
, subm
);
271 if (!tab
[i
].mask
&& !tab
[i
].fmask
&& !tab
[i
].ptype
) break;
276 struct matches
*atomopl_a APROTO
{
277 struct matches
*res
= alwaysmatches(spos
);
278 res
->m
[0].oplen
= *(int*)v
;
282 struct matches
*atomsestart_a APROTO
{
283 struct litem
*li
= ctx
->atoms
[spos
];
284 if (li
->type
== LITEM_SESTART
)
285 return alwaysmatches(spos
+1);
290 struct matches
*atomseend_a APROTO
{
291 struct litem
*li
= ctx
->atoms
[spos
];
292 if (li
->type
== LITEM_SEEND
)
293 return alwaysmatches(spos
+1);
298 struct matches
*atomname_a APROTO
{
299 if (spos
== ctx
->atomsnum
)
301 struct litem
*li
= ctx
->atoms
[spos
];
302 if (li
->type
== LITEM_NAME
&& !strcmp(li
->str
, v
))
303 return alwaysmatches(spos
+1);
308 struct matches
*atomcmd_a APROTO
{
309 if (spos
== ctx
->atomsnum
|| ctx
->atoms
[spos
]->type
!= LITEM_EXPR
)
311 struct easm_expr
*e
= ctx
->atoms
[spos
]->expr
;
312 if (e
->type
== EASM_EXPR_LABEL
&& !strcmp(e
->str
, v
))
313 return alwaysmatches(spos
+1);
318 struct matches
*atomunk_a APROTO
{
322 struct matches
*atomimm_a APROTO
{
323 const struct bitfield
*bf
= v
;
324 if (spos
== ctx
->atomsnum
|| ctx
->atoms
[spos
]->type
!= LITEM_EXPR
)
326 struct matches
*res
= alwaysmatches(spos
+1);
327 struct easm_expr
*expr
= ctx
->atoms
[spos
]->expr
;
328 if (expr
->type
== EASM_EXPR_NUM
&& setbf(res
->m
, bf
, expr
->num
))
337 struct matches
*atomrimm_a APROTO
{
338 const struct rbitfield
*bf
= v
;
339 if (spos
== ctx
->atomsnum
|| ctx
->atoms
[spos
]->type
!= LITEM_EXPR
)
341 struct matches
*res
= alwaysmatches(spos
+1);
342 if (setrbf(res
->m
, bf
, ctx
->atoms
[spos
]->expr
))
351 struct matches
*atomnop_a APROTO
{
352 return alwaysmatches(spos
);
355 int matchreg (struct match
*res
, const struct reg
*reg
, const struct easm_expr
*expr
, struct iasctx
*ctx
) {
358 for (i
= 0; reg
->specials
[i
].num
!= -1; i
++) {
359 if (!var_ok(reg
->specials
[i
].fmask
, 0, ctx
->varinfo
))
361 switch (reg
->specials
[i
].mode
) {
363 if (expr
->type
== EASM_EXPR_REG
&& !strcmp(expr
->str
, reg
->specials
[i
].name
))
364 return setbf(res
, reg
->bf
, reg
->specials
[i
].num
);
367 if (expr
->type
== EASM_EXPR_NUM
&& expr
->num
== 0)
368 return setbf(res
, reg
->bf
, reg
->specials
[i
].num
);
371 if (expr
->type
== EASM_EXPR_NUM
&& expr
->num
== 1)
372 return setbf(res
, reg
->bf
, reg
->specials
[i
].num
);
375 if (expr
->type
== EASM_EXPR_DISCARD
)
376 return setbf(res
, reg
->bf
, reg
->specials
[i
].num
);
381 if (expr
->type
!= EASM_EXPR_REG
)
383 if (strncmp(expr
->str
, reg
->name
, strlen(reg
->name
)))
385 const char *str
= expr
->str
+ strlen(reg
->name
);
387 ull num
= strtoull(str
, &end
, 10);
389 if (strcmp(end
, (reg
->suffix
?reg
->suffix
:"")))
392 if (strlen(end
) != 1)
394 if (*end
!= 'h' && *end
!= 'l')
401 return setbf(res
, reg
->bf
, num
);
406 int matchshreg (struct match
*res
, const struct reg
*reg
, const struct easm_expr
*expr
, int shl
, struct iasctx
*ctx
) {
409 if (expr
->type
== EASM_EXPR_SHL
&& expr
->e2
->type
== EASM_EXPR_NUM
) {
412 } else if (expr
->type
== EASM_EXPR_MUL
&& expr
->e2
->type
== EASM_EXPR_NUM
) {
413 ull num
= expr
->e2
->num
;
414 if (!num
|| (num
& (num
-1)))
419 } else if (expr
->type
== EASM_EXPR_MUL
&& expr
->e1
->type
== EASM_EXPR_NUM
) {
420 ull num
= expr
->e1
->num
;
421 if (!num
|| (num
& (num
-1)))
432 return matchreg(res
, reg
, expr
, ctx
);
435 struct matches
*atomreg_a APROTO
{
436 const struct reg
*reg
= v
;
437 if (spos
== ctx
->atomsnum
|| ctx
->atoms
[spos
]->type
!= LITEM_EXPR
)
439 struct easm_expr
*e
= ctx
->atoms
[spos
]->expr
;
440 struct matches
*res
= alwaysmatches(spos
+1);
441 if (matchreg(res
->m
, reg
, e
, ctx
))
450 struct matches
*atomdiscard_a APROTO
{
451 if (spos
== ctx
->atomsnum
|| ctx
->atoms
[spos
]->type
!= LITEM_EXPR
)
453 struct easm_expr
*e
= ctx
->atoms
[spos
]->expr
;
454 if (e
->type
== EASM_EXPR_DISCARD
) {
455 return alwaysmatches(spos
+1);
461 int addexpr (struct easm_expr
**iex
, struct easm_expr
*expr
, int flip
) {
464 *iex
= easm_expr_un(EASM_EXPR_NEG
, expr
);
466 *iex
= easm_expr_bin(EASM_EXPR_SUB
, *iex
, expr
);
471 *iex
= easm_expr_bin(EASM_EXPR_ADD
, *iex
, expr
);
476 int matchmemaddr(struct easm_expr
**iex
, struct easm_expr
**niex1
, struct easm_expr
**niex2
, struct easm_expr
*expr
, int flip
) {
477 if (easm_isimm(expr
))
478 return addexpr(iex
, expr
, flip
);
479 if (expr
->type
== EASM_EXPR_ADD
)
480 return matchmemaddr(iex
, niex1
, niex2
, expr
->e1
, flip
) && matchmemaddr(iex
, niex1
, niex2
, expr
->e2
, flip
);
481 if (expr
->type
== EASM_EXPR_SUB
)
482 return matchmemaddr(iex
, niex1
, niex2
, expr
->e1
, flip
) && matchmemaddr(iex
, niex1
, niex2
, expr
->e2
, !flip
);
483 if (expr
->type
== EASM_EXPR_NEG
)
484 return matchmemaddr(iex
, niex1
, niex2
, expr
->e1
, !flip
);
487 if (niex1
&& !*niex1
)
489 else if (niex2
&& !*niex2
)
496 struct matches
*atommem_a APROTO
{
497 const struct mem
*mem
= v
;
498 if (spos
== ctx
->atomsnum
|| ctx
->atoms
[spos
]->type
!= LITEM_EXPR
)
500 struct easm_expr
*expr
= ctx
->atoms
[spos
]->expr
;
501 struct easm_expr
*pexpr
= 0;
502 struct match res
= { 0, .lpos
= spos
+1 };
503 int ismem
= expr
->type
>= EASM_EXPR_MEM
&& expr
->type
<= EASM_EXPR_MEMME
;
504 if (ismem
&& !mem
->name
)
506 if (!ismem
&& mem
->name
)
509 if (strncmp(expr
->str
, mem
->name
, strlen(mem
->name
)))
512 const char *str
= expr
->str
+ strlen(mem
->name
);
516 ull num
= strtoull(str
, &end
, 10);
519 if (!setbf(&res
, mem
->idx
, num
))
522 if (strlen(expr
->str
) != strlen(mem
->name
))
525 if (expr
->type
== EASM_EXPR_MEMPP
)
526 addexpr(&pexpr
, expr
->e2
, 0);
527 else if (expr
->type
== EASM_EXPR_MEMMM
)
528 addexpr(&pexpr
, expr
->e2
, 1);
529 else if (expr
->type
!= EASM_EXPR_MEM
)
533 struct easm_expr
*iex
= 0;
534 struct easm_expr
*niex1
= 0;
535 struct easm_expr
*niex2
= 0;
536 matchmemaddr(&iex
, &niex1
, &niex2
, expr
, 0);
541 if (!setrbf(&res
, mem
->imm
, pexpr
))
547 if (!setrbf(&res
, mem
->imm
, iex
))
550 if (!setrbf(&res
, mem
->imm
, easm_expr_num(EASM_EXPR_NUM
, 0)))
558 if (mem
->reg
&& mem
->reg2
) {
560 niex1
= easm_expr_num(EASM_EXPR_NUM
, 0);
562 niex2
= easm_expr_num(EASM_EXPR_NUM
, 0);
563 struct match sres
= res
;
564 if (!matchreg(&res
, mem
->reg
, niex1
, ctx
) || !matchshreg(&res
, mem
->reg2
, niex2
, mem
->reg2shr
, ctx
)) {
566 if (!matchreg(&res
, mem
->reg
, niex2
, ctx
) || !matchshreg(&res
, mem
->reg2
, niex1
, mem
->reg2shr
, ctx
))
569 } else if (mem
->reg
) {
573 niex1
= easm_expr_num(EASM_EXPR_NUM
, 0);
574 if (!matchreg(&res
, mem
->reg
, niex1
, ctx
))
576 } else if (mem
->reg2
) {
580 niex1
= easm_expr_num(EASM_EXPR_NUM
, 0);
581 if (!matchshreg(&res
, mem
->reg2
, niex1
, mem
->reg2shr
, ctx
))
587 struct matches
*rres
= emptymatches();
588 ADDARRAY(rres
->m
, res
);
592 struct matches
*atomvec_a APROTO
{
593 const struct vec
*vec
= v
;
594 if (spos
== ctx
->atomsnum
|| ctx
->atoms
[spos
]->type
!= LITEM_EXPR
)
596 struct match res
= { 0, .lpos
= spos
+1 };
597 const struct easm_expr
*expr
= ctx
->atoms
[spos
]->expr
;
598 const struct easm_expr
**vexprs
= 0;
601 if (expr
->type
!= EASM_EXPR_ZVEC
) {
602 while (expr
->type
== EASM_EXPR_VEC
) {
603 ADDARRAY(vexprs
, expr
->e2
);
606 ADDARRAY(vexprs
, expr
);
609 for (i
= 0; i
< vexprsnum
/2; i
++) {
610 const struct easm_expr
*tmp
= vexprs
[i
];
611 vexprs
[i
] = vexprs
[vexprsnum
-1-i
];
612 vexprs
[vexprsnum
-1-i
] = tmp
;
614 ull start
= 0, cnt
= vexprsnum
, mask
= 0, cur
= 0;
615 for (i
= 0; i
< cnt
; i
++) {
616 const struct easm_expr
*e
= vexprs
[i
];
617 if (e
->type
== EASM_EXPR_DISCARD
) {
618 } else if (e
->type
== EASM_EXPR_REG
) {
619 if (strncmp(e
->str
, vec
->name
, strlen(vec
->name
)))
622 ull num
= strtoull(e
->str
+ strlen(vec
->name
), &end
, 10);
638 if (!setbf(&res
, vec
->bf
, start
))
640 if (!setbf(&res
, vec
->cnt
, cnt
))
643 if (!setbf(&res
, vec
->mask
, mask
))
646 if (mask
!= (1ull << cnt
) - 1)
649 struct matches
*rres
= emptymatches();
650 ADDARRAY(rres
->m
, res
);
654 struct matches
*atombf_a APROTO
{
655 const struct bitfield
*bf
= v
;
656 if (spos
== ctx
->atomsnum
|| ctx
->atoms
[spos
]->type
!= LITEM_EXPR
)
658 struct match res
= { 0, .lpos
= spos
+1 };
659 const struct easm_expr
*expr
= ctx
->atoms
[spos
]->expr
;
660 if (expr
->type
!= EASM_EXPR_VEC
|| expr
->e1
->type
!= EASM_EXPR_NUM
|| expr
->e2
->type
!= EASM_EXPR_NUM
)
662 uint64_t a
= expr
->e1
->num
;
663 uint64_t b
= expr
->e2
->num
- a
;
664 if (!setbf(&res
, &bf
[0], a
))
666 if (!setbf(&res
, &bf
[1], b
))
668 struct matches
*rres
= emptymatches();
669 ADDARRAY(rres
->m
, res
);
673 void convert_expr_top(struct iasctx
*ctx
, struct easm_expr
*expr
);
675 void convert_mods(struct iasctx
*ctx
, struct easm_mods
*mods
) {
677 for (i
= 0; i
< mods
->modsnum
; i
++) {
678 struct litem
*li
= calloc(sizeof *li
, 1);
679 li
->type
= LITEM_NAME
;
680 li
->str
= mods
->mods
[i
]->str
;
681 ADDARRAY(ctx
->atoms
, li
);
685 void convert_operand(struct iasctx
*ctx
, struct easm_operand
*operand
) {
687 convert_mods(ctx
, operand
->mods
);
688 for (i
= 0; i
< operand
->exprsnum
; i
++) {
690 convert_expr_top(ctx
, operand
->exprs
[i
]);
694 void convert_sinsn(struct iasctx
*ctx
, struct easm_sinsn
*sinsn
) {
696 struct litem
*li
= calloc(sizeof *li
, 1);
697 li
->type
= LITEM_NAME
;
698 li
->str
= sinsn
->str
;
699 ADDARRAY(ctx
->atoms
, li
);
700 for (i
= 0; i
< sinsn
->operandsnum
; i
++) {
701 convert_operand(ctx
, sinsn
->operands
[i
]);
703 convert_mods(ctx
, sinsn
->mods
);
706 void convert_subinsn(struct iasctx
*ctx
, struct easm_subinsn
*subinsn
) {
708 for (i
= 0; i
< subinsn
->prefsnum
; i
++) {
709 convert_expr_top(ctx
, subinsn
->prefs
[i
]);
711 convert_sinsn(ctx
, subinsn
->sinsn
);
714 void convert_expr_top(struct iasctx
*ctx
, struct easm_expr
*expr
) {
715 if (expr
->type
== EASM_EXPR_SINSN
) {
716 struct litem
*ses
= calloc(sizeof *ses
, 1);
717 struct litem
*see
= calloc(sizeof *see
, 1);
718 ses
->type
= LITEM_SESTART
;
719 see
->type
= LITEM_SEEND
;
720 ADDARRAY(ctx
->atoms
, ses
);
721 convert_sinsn(ctx
, expr
->sinsn
);
722 ADDARRAY(ctx
->atoms
, see
);
724 struct litem
*li
= calloc(sizeof *li
, 1);
725 li
->type
= LITEM_EXPR
;
727 ADDARRAY(ctx
->atoms
, li
);
731 void convert_insn(struct iasctx
*ctx
, struct easm_insn
*insn
) {
733 for (i
= 0; i
< insn
->subinsnsnum
; i
++) {
735 convert_subinsn(ctx
, insn
->subinsns
[i
]);
739 struct matches
*do_as(const struct disisa
*isa
, struct varinfo
*varinfo
, struct easm_insn
*insn
) {
740 struct matches
*res
= calloc(sizeof *res
, 1);
741 struct iasctx c
= { isa
, varinfo
};
742 struct iasctx
*ctx
= &c
;
743 convert_insn(ctx
, insn
);
744 const struct insn
*root
= isa
->trootas
? isa
->trootas
: isa
->troot
;
745 struct matches
*m
= atomtab_a(ctx
, root
, 0);
747 for (i
= 0; i
< m
->mnum
; i
++)
748 if (m
->m
[i
].lpos
== ctx
->atomsnum
) {
749 ADDARRAY(res
->m
, m
->m
[i
]);