Compare commits
77 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b58f315c98 | ||
|
|
7687c2b7d2 | ||
|
|
0abbce6f4e | ||
|
|
8ffdf657ec | ||
|
|
2232a76033 | ||
|
|
d6af9c1555 | ||
|
|
d7acc8cd4d | ||
|
|
a5f1d17e83 | ||
|
|
29efcd5be1 | ||
|
|
4656db9484 | ||
|
|
b33d7239e5 | ||
|
|
e1f0c084f8 | ||
|
|
e2a6b25345 | ||
|
|
f210ed78c2 | ||
|
|
ccc8cc526b | ||
|
|
cd6797499f | ||
|
|
b60903306f | ||
|
|
1df7cb3be4 | ||
|
|
a7265f06b0 | ||
|
|
58532f4402 | ||
|
|
7d986ef661 | ||
|
|
7f4197acc1 | ||
|
|
e71c8051c3 | ||
|
|
73cf949e25 | ||
|
|
b2be1cf2da | ||
|
|
94e3016a5b | ||
|
|
145a50369e | ||
|
|
d77927c608 | ||
|
|
3bb72987a6 | ||
|
|
c782892db4 | ||
|
|
a944ea5da8 | ||
|
|
d1738ea630 | ||
|
|
5f39236ba2 | ||
|
|
ede09ddae3 | ||
|
|
34b1f4f4fe | ||
|
|
d6249916e1 | ||
|
|
9cd3226536 | ||
|
|
3f217e83da | ||
|
|
652cfb67c3 | ||
|
|
c0e9ba2fb3 | ||
|
|
5963f5fd4d | ||
|
|
12ee08f87e | ||
|
|
5c85c92d1a | ||
|
|
b509d0fcf0 | ||
|
|
bb007ddefc | ||
|
|
9129d48429 | ||
|
|
d105182051 | ||
|
|
157a968372 | ||
|
|
bae2a582f1 | ||
|
|
19191876e2 | ||
|
|
fcfe3c1f4b | ||
|
|
97f093feaa | ||
|
|
3561de6e12 | ||
|
|
e84d09b97c | ||
|
|
d8a4fe1c04 | ||
|
|
e4e6ad6415 | ||
|
|
2543617930 | ||
|
|
bc5784a8f2 | ||
|
|
842687726f | ||
|
|
c5c9196561 | ||
|
|
a697ad05c0 | ||
|
|
d8c66e7791 | ||
|
|
337a6c44aa | ||
|
|
cde4484821 | ||
|
|
36b063c183 | ||
|
|
3603877f42 | ||
|
|
50950028e0 | ||
|
|
1c5e1c2fce | ||
|
|
5c7799b778 | ||
|
|
0209b7ceb2 | ||
|
|
f6118dc0c4 | ||
|
|
d5e1fc733f | ||
|
|
c1eb8df114 | ||
|
|
ca129c5177 | ||
|
|
c19231a1bd | ||
|
|
5087a051b5 | ||
|
|
ba110a64cb |
6
.gitattributes
vendored
Normal file
6
.gitattributes
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
* text=auto
|
||||
*.c text
|
||||
*.cpp text
|
||||
*.ui text
|
||||
*.qrc text
|
||||
*.h text
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@ -4,4 +4,6 @@ tests/prev
|
||||
tests/outputs/*
|
||||
tests/errors
|
||||
*.autosave
|
||||
bld*
|
||||
bld*
|
||||
*.user
|
||||
*.idb
|
||||
|
||||
68
3rd_party/libdisasm/INTEL_BUGS
vendored
Normal file
68
3rd_party/libdisasm/INTEL_BUGS
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
PMOVMSKB
|
||||
Gd, Pq1H
|
||||
PMOVMSKB
|
||||
(66)
|
||||
Gd, Vdq1H
|
||||
|
||||
should be
|
||||
|
||||
PMOVMSKB
|
||||
Gd, Qq1H
|
||||
PMOVMSKB
|
||||
(66)
|
||||
Gd, Wdq1H
|
||||
|
||||
The instruction represented by this opcode expression does not support any
|
||||
operand to be a memory location.
|
||||
|
||||
MASKMOVQ
|
||||
Pq, Pq1H
|
||||
MASKMOVDQU
|
||||
(66)
|
||||
Vdq, Vdq1H
|
||||
|
||||
should be
|
||||
|
||||
MASKMOVQ
|
||||
Pq, Pq1H
|
||||
MASKMOVDQU
|
||||
(66)
|
||||
Vdq, Wdq1H
|
||||
|
||||
MOVMSKPS
|
||||
Gd, Vps1H
|
||||
MOVMSKPD
|
||||
(66)
|
||||
Gd, Vpd1H
|
||||
|
||||
should be
|
||||
|
||||
MOVMSKPS
|
||||
Gd, Wps1H
|
||||
MOVMSKPD
|
||||
(66)
|
||||
Gd, Wpd1H
|
||||
|
||||
The opcode table entries for LFS, LGS, and LSS
|
||||
|
||||
L[FGS]S
|
||||
Mp
|
||||
|
||||
should be
|
||||
|
||||
L[FGS]S
|
||||
Gv,Mp
|
||||
|
||||
MOVHLPS
|
||||
Vps, Vps
|
||||
|
||||
MOVLHPS
|
||||
Vps, Vps
|
||||
|
||||
should be
|
||||
|
||||
MOVHLPS
|
||||
Vps, Wps
|
||||
|
||||
MOVLHPS
|
||||
Vps, Wps
|
||||
137
3rd_party/libdisasm/LICENSE
vendored
Normal file
137
3rd_party/libdisasm/LICENSE
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
|
||||
|
||||
|
||||
|
||||
The "Clarified Artistic License"
|
||||
|
||||
Preamble
|
||||
|
||||
The intent of this document is to state the conditions under which a
|
||||
Package may be copied, such that the Copyright Holder maintains some
|
||||
semblance of artistic control over the development of the package,
|
||||
while giving the users of the package the right to use and distribute
|
||||
the Package in a more-or-less customary fashion, plus the right to make
|
||||
reasonable modifications.
|
||||
|
||||
Definitions:
|
||||
|
||||
"Package" refers to the collection of files distributed by the
|
||||
Copyright Holder, and derivatives of that collection of files
|
||||
created through textual modification.
|
||||
|
||||
"Standard Version" refers to such a Package if it has not been
|
||||
modified, or has been modified in accordance with the wishes
|
||||
of the Copyright Holder as specified below.
|
||||
|
||||
"Copyright Holder" is whoever is named in the copyright or
|
||||
copyrights for the package.
|
||||
|
||||
"You" is you, if you're thinking about copying or distributing
|
||||
this Package.
|
||||
|
||||
"Distribution fee" is a fee you charge for providing a copy of this
|
||||
Package to another party.
|
||||
|
||||
"Freely Available" means that no fee is charged for the right to use
|
||||
the item, though there may be fees involved in handling the item.
|
||||
|
||||
1. You may make and give away verbatim copies of the source form of the
|
||||
Standard Version of this Package without restriction, provided that you
|
||||
duplicate all of the original copyright notices and associated disclaimers.
|
||||
|
||||
2. You may apply bug fixes, portability fixes and other modifications
|
||||
derived from the Public Domain, or those made Freely Available, or from
|
||||
the Copyright Holder. A Package modified in such a way shall still be
|
||||
considered the Standard Version.
|
||||
|
||||
3. You may otherwise modify your copy of this Package in any way, provided
|
||||
that you insert a prominent notice in each changed file stating how and
|
||||
when you changed that file, and provided that you do at least ONE of the
|
||||
following:
|
||||
|
||||
a) place your modifications in the Public Domain or otherwise make them
|
||||
Freely Available, such as by posting said modifications to Usenet or
|
||||
an equivalent medium, or placing the modifications on a major archive
|
||||
site allowing unrestricted access to them, or by allowing the Copyright
|
||||
Holder to include your modifications in the Standard Version of the
|
||||
Package.
|
||||
|
||||
b) use the modified Package only within your corporation or organization.
|
||||
|
||||
c) rename any non-standard executables so the names do not conflict
|
||||
with standard executables, which must also be provided, and provide
|
||||
a separate manual page for each non-standard executable that clearly
|
||||
documents how it differs from the Standard Version.
|
||||
|
||||
d) make other distribution arrangements with the Copyright Holder.
|
||||
|
||||
e) permit and encourge anyone who receives a copy of the modified Package
|
||||
permission to make your modifications Freely Available in some specific
|
||||
way.
|
||||
|
||||
4. You may distribute the programs of this Package in object code or
|
||||
executable form, provided that you do at least ONE of the following:
|
||||
|
||||
a) distribute a Standard Version of the executables and library files,
|
||||
together with instructions (in the manual page or equivalent) on where
|
||||
to get the Standard Version.
|
||||
|
||||
b) accompany the distribution with the machine-readable source of
|
||||
the Package with your modifications.
|
||||
|
||||
c) give non-standard executables non-standard names, and clearly
|
||||
document the differences in manual pages (or equivalent), together
|
||||
with instructions on where to get the Standard Version.
|
||||
|
||||
d) make other distribution arrangements with the Copyright Holder.
|
||||
|
||||
e) offer the machine-readable source of the Package, with your
|
||||
modifications, by mail order.
|
||||
|
||||
5. You may charge a distribution fee for any distribution of this Package.
|
||||
If you offer support for this Package, you may charge any fee you choose
|
||||
for that support. You may not charge a license fee for the right to use
|
||||
this Package itself. You may distribute this Package in aggregate with
|
||||
other (possibly commercial and possibly nonfree) programs as part of a
|
||||
larger (possibly commercial and possibly nonfree) software distribution,
|
||||
and charge license fees for other parts of that software distribution,
|
||||
provided that you do not advertise this Package as a product of your own.
|
||||
If the Package includes an interpreter, You may embed this Package's
|
||||
interpreter within an executable of yours (by linking); this shall be
|
||||
construed as a mere form of aggregation, provided that the complete
|
||||
Standard Version of the interpreter is so embedded.
|
||||
|
||||
6. The scripts and library files supplied as input to or produced as
|
||||
output from the programs of this Package do not automatically fall
|
||||
under the copyright of this Package, but belong to whoever generated
|
||||
them, and may be sold commercially, and may be aggregated with this
|
||||
Package. If such scripts or library files are aggregated with this
|
||||
Package via the so-called "undump" or "unexec" methods of producing a
|
||||
binary executable image, then distribution of such an image shall
|
||||
neither be construed as a distribution of this Package nor shall it
|
||||
fall under the restrictions of Paragraphs 3 and 4, provided that you do
|
||||
not represent such an executable image as a Standard Version of this
|
||||
Package.
|
||||
|
||||
7. C subroutines (or comparably compiled subroutines in other
|
||||
languages) supplied by you and linked into this Package in order to
|
||||
emulate subroutines and variables of the language defined by this
|
||||
Package shall not be considered part of this Package, but are the
|
||||
equivalent of input as in Paragraph 6, provided these subroutines do
|
||||
not change the language in any way that would cause it to fail the
|
||||
regression tests for the language.
|
||||
|
||||
8. Aggregation of the Standard Version of the Package with a commercial
|
||||
distribution is always permitted provided that the use of this Package is
|
||||
embedded; that is, when no overt attempt is made to make this Package's
|
||||
interfaces visible to the end user of the commercial distribution.
|
||||
Such use shall not be construed as a distribution of this Package.
|
||||
|
||||
9. The name of the Copyright Holder may not be used to endorse or promote
|
||||
products derived from this software without specific prior written permission.
|
||||
|
||||
10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
The End
|
||||
12
3rd_party/libdisasm/NAMESPACE.TXT
vendored
Normal file
12
3rd_party/libdisasm/NAMESPACE.TXT
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
The rewritten libdisasm code uses the following namespaces:
|
||||
|
||||
|
||||
Prefix Namespace
|
||||
----------------------------------------------------
|
||||
x86_ Global 'libdisasm' namespace
|
||||
ia32_ Internal IA32 ISA namespace
|
||||
ia64_ Internal IA64 ISA namespace
|
||||
ix64_ Internal X86-64 ISA namespace
|
||||
|
||||
Note that the 64-bit ISAs are not yet supported/written.
|
||||
2
3rd_party/libdisasm/README
vendored
Normal file
2
3rd_party/libdisasm/README
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
This is a cut-up version of libdisasm originally from the bastard project http://bastard.sourceforge.net/
|
||||
|
||||
43
3rd_party/libdisasm/TODO
vendored
Normal file
43
3rd_party/libdisasm/TODO
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
x86_format.c
|
||||
------------
|
||||
intel: jmpf -> jmp, callf -> call
|
||||
att: jmpf -> ljmp, callf -> lcall
|
||||
|
||||
opcode table
|
||||
------------
|
||||
finish typing instructions
|
||||
fix flag clear/set/toggle types
|
||||
|
||||
ix64 stuff
|
||||
----------
|
||||
document output file formats in web page
|
||||
features doc: register aliases, implicit operands, stack mods,
|
||||
ring0 flags, eflags, cpu model/isa
|
||||
|
||||
ia32_handle_* implementation
|
||||
|
||||
fix operand 0F C2
|
||||
CMPPS
|
||||
|
||||
* sysenter, sysexit as CALL types -- preceded by MSR writes
|
||||
* SYSENTER/SYSEXIT stack : overwrites SS, ESP
|
||||
* stos, cmps, scas, movs, ins, outs, lods -> OP_PTR
|
||||
* OP_SIZE in implicit operands
|
||||
* use OP_SIZE to choose reg sizes!
|
||||
|
||||
DONE?? :
|
||||
implicit operands: provide action ?
|
||||
e.g. add/inc for stach, write, etc
|
||||
replace table numbers in opcodes.dat with
|
||||
#defines for table names
|
||||
|
||||
replace 0 with INSN_INVALID [or maybe FF for imnvalid and 00 for Not Applicable */
|
||||
no wait that is only for prefix tables -- n/p
|
||||
|
||||
if ( prefx) only use if insn != invalid
|
||||
|
||||
these should cover all the wacky disasm exceptions
|
||||
|
||||
for the rep one we can chet, match only a 0x90
|
||||
|
||||
todo: privilege | ring
|
||||
36
3rd_party/libdisasm/ia32_fixup.cpp
vendored
Normal file
36
3rd_party/libdisasm/ia32_fixup.cpp
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
#include <stdio.h>
|
||||
|
||||
static const char * mem_fixup[256] = {
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 00 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 08 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 10 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 18 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 20 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 28 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 30 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 38 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 40 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 48 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 50 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 58 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 60 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 68 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 70 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 78 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 80 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 88 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 90 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 98 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* A0 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* A8 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* B0 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* B8 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* C0 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* C8 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* D0 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* D8 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* E0 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* E8 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* F0 */
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL /* F8 */
|
||||
};
|
||||
126
3rd_party/libdisasm/ia32_implicit.cpp
vendored
126
3rd_party/libdisasm/ia32_implicit.cpp
vendored
@ -20,81 +20,81 @@ typedef struct {
|
||||
static op_implicit_list_t list_aaa[] =
|
||||
/* 37 : AAA : rw AL */
|
||||
/* 3F : AAS : rw AL */
|
||||
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}}; /* aaa */
|
||||
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0,0}}; /* aaa */
|
||||
|
||||
static op_implicit_list_t list_aad[] =
|
||||
/* D5 0A, D5 (ib) : AAD : rw AX */
|
||||
/* D4 0A, D4 (ib) : AAM : rw AX */
|
||||
{{ OP_R | OP_W, REG_WORD_OFFSET }, {0}}; /* aad */
|
||||
{{ OP_R | OP_W, REG_WORD_OFFSET }, {0,0}}; /* aad */
|
||||
|
||||
static op_implicit_list_t list_call[] =
|
||||
/* E8, FF, 9A, FF : CALL : rw ESP, rw EIP */
|
||||
/* C2, C3, CA, CB : RET : rw ESP, rw EIP */
|
||||
{{ OP_R | OP_W, REG_EIP_INDEX },
|
||||
{ OP_R | OP_W, REG_ESP_INDEX }, {0}}; /* call, ret */
|
||||
{ OP_R | OP_W, REG_ESP_INDEX }, {0,0}}; /* call, ret */
|
||||
|
||||
static op_implicit_list_t list_cbw[] =
|
||||
/* 98 : CBW : r AL, rw AX */
|
||||
{{ OP_R | OP_W, REG_WORD_OFFSET },
|
||||
{ OP_R, REG_BYTE_OFFSET}, {0}}; /* cbw */
|
||||
{ OP_R, REG_BYTE_OFFSET}, {0,0}}; /* cbw */
|
||||
|
||||
static op_implicit_list_t list_cwde[] =
|
||||
/* 98 : CWDE : r AX, rw EAX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET },
|
||||
{ OP_R, REG_WORD_OFFSET }, {0}}; /* cwde */
|
||||
{ OP_R, REG_WORD_OFFSET }, {0,0}}; /* cwde */
|
||||
|
||||
static op_implicit_list_t list_clts[] =
|
||||
/* 0F 06 : CLTS : rw CR0 */
|
||||
{{ OP_R | OP_W, REG_CTRL_OFFSET}, {0}}; /* clts */
|
||||
{{ OP_R | OP_W, REG_CTRL_OFFSET}, {0,0}}; /* clts */
|
||||
|
||||
static op_implicit_list_t list_cmpxchg[] =
|
||||
/* 0F B0 : CMPXCHG : rw AL */
|
||||
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}}; /* cmpxchg */
|
||||
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0,0}}; /* cmpxchg */
|
||||
|
||||
static op_implicit_list_t list_cmpxchgb[] =
|
||||
/* 0F B1 : CMPXCHG : rw EAX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET }, {0}}; /* cmpxchg */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET }, {0,0}}; /* cmpxchg */
|
||||
|
||||
static op_implicit_list_t list_cmpxchg8b[] =
|
||||
/* 0F C7 : CMPXCHG8B : rw EDX, rw EAX, r ECX, r EBX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET },
|
||||
{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 3 }, {0}}; /* cmpxchg8b */
|
||||
{ OP_R, REG_DWORD_OFFSET + 3 }, {0,0}}; /* cmpxchg8b */
|
||||
|
||||
static op_implicit_list_t list_cpuid[] =
|
||||
/* 0F A2 : CPUID : rw EAX, w EBX, w ECX, w EDX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET },
|
||||
{ OP_W, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 3 }, {0}}; /* cpuid */
|
||||
{ OP_W, REG_DWORD_OFFSET + 3 }, {0,0}}; /* cpuid */
|
||||
|
||||
static op_implicit_list_t list_cwd[] =
|
||||
/* 99 : CWD/CWQ : rw EAX, w EDX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 }, {0}}; /* cwd */
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 }, {0,0}}; /* cwd */
|
||||
|
||||
static op_implicit_list_t list_daa[] =
|
||||
/* 27 : DAA : rw AL */
|
||||
/* 2F : DAS : rw AL */
|
||||
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}}; /* daa */
|
||||
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0,0}}; /* daa */
|
||||
|
||||
static op_implicit_list_t list_idiv[] =
|
||||
/* F6 : DIV, IDIV : r AX, w AL, w AH */
|
||||
/* FIXED: first op was EAX, not Aw. TODO: verify! */
|
||||
{{ OP_R, REG_WORD_OFFSET },
|
||||
{ OP_W, REG_BYTE_OFFSET },
|
||||
{ OP_W, REG_BYTE_OFFSET + 4 }, {0}}; /* div */
|
||||
{ OP_W, REG_BYTE_OFFSET + 4 }, {0,0}}; /* div */
|
||||
|
||||
static op_implicit_list_t list_div[] =
|
||||
/* F7 : DIV, IDIV : rw EDX, rw EAX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_R | OP_W, REG_DWORD_OFFSET }, {0}}; /* div */
|
||||
{ OP_R | OP_W, REG_DWORD_OFFSET }, {0,0}}; /* div */
|
||||
|
||||
static op_implicit_list_t list_enter[] =
|
||||
/* C8 : ENTER : rw ESP w EBP */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 4 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 5 }, {0}}; /* enter */
|
||||
{ OP_R, REG_DWORD_OFFSET + 5 }, {0,0}}; /* enter */
|
||||
|
||||
static op_implicit_list_t list_f2xm1[] =
|
||||
/* D9 F0 : F2XM1 : rw ST(0) */
|
||||
@ -109,7 +109,7 @@ static op_implicit_list_t list_f2xm1[] =
|
||||
/* D9 FE : FSIN : rw ST(0) */
|
||||
/* D9 FA : FSQRT : rw ST(0) */
|
||||
/* D9 F4 : FXTRACT : rw ST(0) */
|
||||
{{ OP_R | OP_W, REG_FPU_OFFSET }, {0}}; /* f2xm1 */
|
||||
{{ OP_R | OP_W, REG_FPU_OFFSET }, {0,0}}; /* f2xm1 */
|
||||
|
||||
static op_implicit_list_t list_fcom[] =
|
||||
/* D8, DC, DE D9 : FCOM : r ST(0) */
|
||||
@ -117,17 +117,17 @@ static op_implicit_list_t list_fcom[] =
|
||||
/* DF, D8 : FIST : r ST(0) */
|
||||
/* D9 E4 : FTST : r ST(0) */
|
||||
/* D9 E5 : FXAM : r ST(0) */
|
||||
{{ OP_R, REG_FPU_OFFSET }, {0}}; /* fcom */
|
||||
{{ OP_R, REG_FPU_OFFSET }, {0,0}}; /* fcom */
|
||||
|
||||
static op_implicit_list_t list_fpatan[] =
|
||||
/* D9 F3 : FPATAN : r ST(0), rw ST(1) */
|
||||
{{ OP_R, REG_FPU_OFFSET }, {0}}; /* fpatan */
|
||||
{{ OP_R, REG_FPU_OFFSET }, {0,0}}; /* fpatan */
|
||||
|
||||
static op_implicit_list_t list_fprem[] =
|
||||
/* D9 F8, D9 F5 : FPREM : rw ST(0) r ST(1) */
|
||||
/* D9 FD : FSCALE : rw ST(0), r ST(1) */
|
||||
{{ OP_R | OP_W, REG_FPU_OFFSET },
|
||||
{ OP_R, REG_FPU_OFFSET + 1 }, {0}}; /* fprem */
|
||||
{ OP_R, REG_FPU_OFFSET + 1 }, {0,0}}; /* fprem */
|
||||
|
||||
static op_implicit_list_t list_faddp[] =
|
||||
/* DE C1 : FADDP : r ST(0), rw ST(1) */
|
||||
@ -135,67 +135,67 @@ static op_implicit_list_t list_faddp[] =
|
||||
/* D9 F1 : FYL2X : r ST(0), rw ST(1) */
|
||||
/* D9 F9 : FYL2XP1 : r ST(0), rw ST(1) */
|
||||
{{ OP_R, REG_FPU_OFFSET },
|
||||
{ OP_R | OP_W, REG_FPU_OFFSET + 1 }, {0}}; /* faddp */
|
||||
{ OP_R | OP_W, REG_FPU_OFFSET + 1 }, {0,0}}; /* faddp */
|
||||
|
||||
static op_implicit_list_t list_fucompp[] =
|
||||
/* DA E9 : FUCOMPP : r ST(0), r ST(1) */
|
||||
{{ OP_R, REG_FPU_OFFSET },
|
||||
{ OP_R, REG_FPU_OFFSET + 1 }, {0}}; /* fucompp */
|
||||
{ OP_R, REG_FPU_OFFSET + 1 }, {0,0}}; /* fucompp */
|
||||
|
||||
static op_implicit_list_t list_imul[] =
|
||||
/* F6 : IMUL : r AL, w AX */
|
||||
/* F6 : MUL : r AL, w AX */
|
||||
{{ OP_R, REG_BYTE_OFFSET },
|
||||
{ OP_W, REG_WORD_OFFSET }, {0}}; /* imul */
|
||||
{ OP_W, REG_WORD_OFFSET }, {0,0}}; /* imul */
|
||||
|
||||
static op_implicit_list_t list_mul[] =
|
||||
/* F7 : IMUL : rw EAX, w EDX */
|
||||
/* F7 : MUL : rw EAX, w EDX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 }, {0}}; /* imul */
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 }, {0,0}}; /* imul */
|
||||
|
||||
static op_implicit_list_t list_lahf[] =
|
||||
/* 9F : LAHF : r EFLAGS, w AH */
|
||||
{{ OP_R, REG_FLAGS_INDEX },
|
||||
{ OP_W, REG_BYTE_OFFSET + 4 }, {0}}; /* lahf */
|
||||
{ OP_W, REG_BYTE_OFFSET + 4 }, {0,0}}; /* lahf */
|
||||
|
||||
static op_implicit_list_t list_ldmxcsr[] =
|
||||
/* 0F AE : LDMXCSR : w MXCSR SSE Control Status Reg */
|
||||
{{ OP_W, REG_MXCSG_INDEX }, {0}}; /* ldmxcsr */
|
||||
{{ OP_W, REG_MXCSG_INDEX }, {0,0}}; /* ldmxcsr */
|
||||
|
||||
static op_implicit_list_t list_leave[] =
|
||||
/* C9 : LEAVE : rw ESP, w EBP */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX },
|
||||
{ OP_W, REG_DWORD_OFFSET + 5 }, {0}}; /* leave */
|
||||
{ OP_W, REG_DWORD_OFFSET + 5 }, {0,0}}; /* leave */
|
||||
|
||||
static op_implicit_list_t list_lgdt[] =
|
||||
/* 0F 01 : LGDT : w GDTR */
|
||||
{{ OP_W, REG_GDTR_INDEX }, {0}}; /* lgdt */
|
||||
{{ OP_W, REG_GDTR_INDEX }, {0,0}}; /* lgdt */
|
||||
|
||||
static op_implicit_list_t list_lidt[] =
|
||||
/* 0F 01 : LIDT : w IDTR */
|
||||
{{ OP_W, REG_IDTR_INDEX }, {0}}; /* lidt */
|
||||
{{ OP_W, REG_IDTR_INDEX }, {0,0}}; /* lidt */
|
||||
|
||||
static op_implicit_list_t list_lldt[] =
|
||||
/* 0F 00 : LLDT : w LDTR */
|
||||
{{ OP_W, REG_LDTR_INDEX }, {0}}; /* lldt */
|
||||
{{ OP_W, REG_LDTR_INDEX }, {0,0}}; /* lldt */
|
||||
|
||||
static op_implicit_list_t list_lmsw[] =
|
||||
/* 0F 01 : LMSW : w CR0 */
|
||||
{{ OP_W, REG_CTRL_OFFSET }, {0}}; /* lmsw */
|
||||
{{ OP_W, REG_CTRL_OFFSET }, {0,0}}; /* lmsw */
|
||||
|
||||
static op_implicit_list_t list_loop[] =
|
||||
/* E0, E1, E2 : LOOP : rw ECX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0}};/* loop */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0,0}};/* loop */
|
||||
|
||||
static op_implicit_list_t list_ltr[] =
|
||||
/* 0F 00 : LTR : w Task Register */
|
||||
{{ OP_W, REG_TR_INDEX }, {0}}; /* ltr */
|
||||
{{ OP_W, REG_TR_INDEX }, {0,0}}; /* ltr */
|
||||
|
||||
static op_implicit_list_t list_pop[] =
|
||||
/* 8F, 58, 1F, 07, 17, 0F A1, 0F A9 : POP : rw ESP */
|
||||
/* FF, 50, 6A, 68, 0E, 16, 1E, 06, 0F A0, 0F A8 : PUSH : rw ESP */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX }, {0}}; /* pop, push */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX }, {0,0}}; /* pop, push */
|
||||
|
||||
static op_implicit_list_t list_popad[] =
|
||||
/* 61 : POPAD : rw esp, w edi esi ebp ebx edx ecx eax */
|
||||
@ -206,12 +206,12 @@ static op_implicit_list_t list_popad[] =
|
||||
{ OP_W, REG_DWORD_OFFSET + 3 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_W, REG_DWORD_OFFSET }, {0}}; /* popad */
|
||||
{ OP_W, REG_DWORD_OFFSET }, {0,0}}; /* popad */
|
||||
|
||||
static op_implicit_list_t list_popfd[] =
|
||||
/* 9D : POPFD : rw esp, w eflags */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX },
|
||||
{ OP_W, REG_FLAGS_INDEX }, {0}}; /* popfd */
|
||||
{ OP_W, REG_FLAGS_INDEX }, {0,0}}; /* popfd */
|
||||
|
||||
static op_implicit_list_t list_pushad[] =
|
||||
/* FF, 50, 6A, 68, 0E, 16, 1E, 06, 0F A0, 0F A8 : PUSH : rw ESP */
|
||||
@ -223,102 +223,102 @@ static op_implicit_list_t list_pushad[] =
|
||||
{ OP_R, REG_DWORD_OFFSET + 3 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 5 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 6 },
|
||||
{ OP_R, REG_DWORD_OFFSET + 7 }, {0}}; /* pushad */
|
||||
{ OP_R, REG_DWORD_OFFSET + 7 }, {0,0}}; /* pushad */
|
||||
|
||||
static op_implicit_list_t list_pushfd[] =
|
||||
/* 9C : PUSHFD : rw esp, r eflags */
|
||||
{{ OP_R | OP_W, REG_ESP_INDEX },
|
||||
{ OP_R, REG_FLAGS_INDEX }, {0}}; /* pushfd */
|
||||
{ OP_R, REG_FLAGS_INDEX }, {0,0}}; /* pushfd */
|
||||
|
||||
static op_implicit_list_t list_rdmsr[] =
|
||||
/* 0F 32 : RDMSR : r ECX, w EDX, w EAX */
|
||||
{{ OP_R, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_W, REG_DWORD_OFFSET }, {0}}; /* rdmsr */
|
||||
{ OP_W, REG_DWORD_OFFSET }, {0,0}}; /* rdmsr */
|
||||
|
||||
static op_implicit_list_t list_rdpmc[] =
|
||||
/* 0F 33 : RDPMC : r ECX, w EDX, w EAX */
|
||||
{{ OP_R, REG_DWORD_OFFSET + 1 },
|
||||
{ OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_W, REG_DWORD_OFFSET }, {0}}; /* rdpmc */
|
||||
{ OP_W, REG_DWORD_OFFSET }, {0,0}}; /* rdpmc */
|
||||
|
||||
static op_implicit_list_t list_rdtsc[] =
|
||||
/* 0F 31 : RDTSC : rw EDX, rw EAX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
|
||||
{ OP_R | OP_W, REG_DWORD_OFFSET }, {0}}; /* rdtsc */
|
||||
{ OP_R | OP_W, REG_DWORD_OFFSET }, {0,0}}; /* rdtsc */
|
||||
|
||||
static op_implicit_list_t list_rep[] =
|
||||
/* F3, F2 ... : REP : rw ECX */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0}};/* rep */
|
||||
{{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0,0}};/* rep */
|
||||
|
||||
static op_implicit_list_t list_rsm[] =
|
||||
/* 0F AA : RSM : r CR4, r CR0 */
|
||||
{{ OP_R, REG_CTRL_OFFSET + 4 },
|
||||
{ OP_R, REG_CTRL_OFFSET }, {0}}; /* rsm */
|
||||
{ OP_R, REG_CTRL_OFFSET }, {0,0}}; /* rsm */
|
||||
|
||||
static op_implicit_list_t list_sahf[] =
|
||||
/* 9E : SAHF : r ah, rw eflags (set SF ZF AF PF CF) */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sahf */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sahf */
|
||||
|
||||
static op_implicit_list_t list_sgdt[] =
|
||||
/* 0F : SGDT : r gdtr */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sgdt */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sgdt */
|
||||
|
||||
static op_implicit_list_t list_sidt[] =
|
||||
/* 0F : SIDT : r idtr */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sidt */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sidt */
|
||||
|
||||
static op_implicit_list_t list_sldt[] =
|
||||
/* 0F : SLDT : r ldtr */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sldt */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sldt */
|
||||
|
||||
static op_implicit_list_t list_smsw[] =
|
||||
/* 0F : SMSW : r CR0 */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* smsw */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* smsw */
|
||||
|
||||
static op_implicit_list_t list_stmxcsr[] =
|
||||
/* 0F AE : STMXCSR : r MXCSR */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* stmxcsr */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* stmxcsr */
|
||||
|
||||
static op_implicit_list_t list_str[] =
|
||||
/* 0F 00 : STR : r TR (task register) */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* str */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* str */
|
||||
|
||||
static op_implicit_list_t list_sysenter[] =
|
||||
/* 0F 34 : SYSENTER : w cs, w eip, w ss, w esp, r CR0, w eflags
|
||||
* r sysenter_cs_msr, sysenter_esp_msr, sysenter_eip_msr */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sysenter */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sysenter */
|
||||
|
||||
static op_implicit_list_t list_sysexit[] =
|
||||
/* 0F 35 : SYSEXIT : r edx, r ecx, w cs, w eip, w ss, w esp
|
||||
* r sysenter_cs_msr */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sysexit */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* sysexit */
|
||||
|
||||
static op_implicit_list_t list_wrmsr[] =
|
||||
/* 0F 30 : WRMST : r edx, r eax, r ecx */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* wrmsr */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* wrmsr */
|
||||
|
||||
static op_implicit_list_t list_xlat[] =
|
||||
/* D7 : XLAT : rw al r ebx (ptr) */
|
||||
/* TODO: finish this! */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* xlat */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* xlat */
|
||||
/* TODO:
|
||||
* monitor 0f 01 c8 eax OP_R ecx OP_R edx OP_R
|
||||
* mwait 0f 01 c9 eax OP_R ecx OP_R
|
||||
*/
|
||||
static op_implicit_list_t list_monitor[] =
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* monitor */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* monitor */
|
||||
static op_implicit_list_t list_mwait[] =
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* mwait */
|
||||
{{ OP_R, REG_DWORD_OFFSET }, {0,0}}; /* mwait */
|
||||
|
||||
op_implicit_list_t *op_implicit_list[] = {
|
||||
/* This is a list of implicit operands which are read/written by
|
||||
@ -407,7 +407,21 @@ unsigned int Ia32_Decoder::ia32_insn_implicit_ops( unsigned int impl_idx ) {
|
||||
if (!op) {
|
||||
op = m_decoded->x86_operand_new();
|
||||
/* all implicit operands are registers */
|
||||
handle_impl_reg( op, list->operand );
|
||||
if(m_decoded->addr_size==2)
|
||||
{
|
||||
if(list->operand==REG_EIP_INDEX)
|
||||
handle_impl_reg( op, REG_IP_INDEX );
|
||||
else if(list->operand<REG_WORD_OFFSET)
|
||||
{
|
||||
handle_impl_reg( op, (list->operand-REG_DWORD_OFFSET)+REG_WORD_OFFSET);
|
||||
assert((list->operand-REG_DWORD_OFFSET)<REG_WORD_OFFSET-REG_DWORD_OFFSET);
|
||||
}
|
||||
else
|
||||
handle_impl_reg( op, list->operand);
|
||||
|
||||
}
|
||||
else
|
||||
handle_impl_reg( op, list->operand );
|
||||
/* decrement the 'explicit count' incremented by default in
|
||||
* x86_operand_new */
|
||||
m_decoded->explicit_count = m_decoded->explicit_count -1;
|
||||
|
||||
7
3rd_party/libdisasm/ia32_insn.cpp
vendored
7
3rd_party/libdisasm/ia32_insn.cpp
vendored
@ -240,7 +240,7 @@ void Ia32_Decoder::ia32_handle_prefix( unsigned int prefixes ) {
|
||||
}
|
||||
|
||||
|
||||
static void reg_32_to_16( x86_op_t *op, x86_insn_t *insn, void *arg ) {
|
||||
static void reg_32_to_16( x86_op_t *op, x86_insn_t */*insn*/, void */*arg*/ ) {
|
||||
|
||||
/* if this is a 32-bit register and it is a general register ... */
|
||||
if ( op->type == op_register && op->data.reg.size == 4 &&
|
||||
@ -539,12 +539,11 @@ size_t ia32_table_lookup( unsigned char *buf, size_t buf_len,
|
||||
|
||||
size_t Ia32_Decoder::handle_insn_suffix( unsigned char *buf, size_t buf_len,
|
||||
ia32_insn_t *raw_insn ) {
|
||||
ia32_table_desc_t *table_desc;
|
||||
// ia32_table_desc_t *table_desc;
|
||||
ia32_insn_t *sfx_insn;
|
||||
size_t size;
|
||||
unsigned int prefixes = 0;
|
||||
|
||||
table_desc = &ia32_tables[raw_insn->table];
|
||||
//table_desc = &ia32_tables[raw_insn->table];
|
||||
size = ia32_table_lookup( buf, buf_len, raw_insn->table, &sfx_insn,
|
||||
&prefixes );
|
||||
if (size == INVALID_INSN || sfx_insn->mnem_flag == INS_INVALID ) {
|
||||
|
||||
9
3rd_party/libdisasm/ia32_invariant.cpp
vendored
9
3rd_party/libdisasm/ia32_invariant.cpp
vendored
@ -137,7 +137,7 @@ static int ia32_invariant_modrm( unsigned char *in, unsigned char *out,
|
||||
}
|
||||
|
||||
|
||||
static int ia32_decode_invariant( unsigned char *buf, size_t buf_len,
|
||||
static int ia32_decode_invariant( unsigned char *buf, size_t /*buf_len*/,
|
||||
ia32_insn_t *t, unsigned char *out,
|
||||
unsigned int prefixes, x86_invariant_t *inv) {
|
||||
|
||||
@ -251,13 +251,13 @@ static int ia32_decode_invariant( unsigned char *buf, size_t buf_len,
|
||||
case ADDRMETH_X:
|
||||
inv->operands[x].flags.op_signed=true;
|
||||
inv->operands[x].flags.op_pointer=true;
|
||||
inv->operands[x].flags.op_seg=x86_op_flags::op_ds_seg;
|
||||
inv->operands[x].flags.op_seg=(x86_op_flags::op_ds_seg)>>8;
|
||||
inv->operands[x].flags.op_string=true;
|
||||
break;
|
||||
case ADDRMETH_Y:
|
||||
inv->operands[x].flags.op_signed=true;
|
||||
inv->operands[x].flags.op_pointer=true;
|
||||
inv->operands[x].flags.op_seg=x86_op_flags::op_es_seg;
|
||||
inv->operands[x].flags.op_seg=x86_op_flags::op_es_seg>>8;
|
||||
inv->operands[x].flags.op_string=true;
|
||||
break;
|
||||
case ADDRMETH_RR:
|
||||
@ -307,6 +307,7 @@ size_t ia32_disasm_invariant( unsigned char * buf, size_t buf_len,
|
||||
}
|
||||
|
||||
size_t ia32_disasm_size( unsigned char *buf, size_t buf_len ) {
|
||||
x86_invariant_t inv = { {0} };
|
||||
x86_invariant_t inv;
|
||||
memset(&inv,0,sizeof(x86_invariant_t));
|
||||
return( ia32_disasm_invariant( buf, buf_len, &inv ) );
|
||||
}
|
||||
|
||||
6
3rd_party/libdisasm/ia32_modrm.cpp
vendored
6
3rd_party/libdisasm/ia32_modrm.cpp
vendored
@ -155,12 +155,12 @@ static size_t modrm_decode16( unsigned char *buf, unsigned int buf_len,
|
||||
ia32_handle_register(&ea->base, REG_WORD_OFFSET + 3);
|
||||
ia32_handle_register(&ea->index, REG_WORD_OFFSET + 7);
|
||||
case MOD16_RM_BPSI:
|
||||
op->flags.op_seg = x86_op_flags::op_ss_seg;
|
||||
op->flags.op_seg = x86_op_flags::op_ss_seg>>8;
|
||||
ia32_handle_register(&ea->base, REG_WORD_OFFSET + 5);
|
||||
ia32_handle_register(&ea->index, REG_WORD_OFFSET + 6);
|
||||
break;
|
||||
case MOD16_RM_BPDI:
|
||||
op->flags.op_seg = x86_op_flags::op_ss_seg;
|
||||
op->flags.op_seg = x86_op_flags::op_ss_seg>>8;
|
||||
ia32_handle_register(&ea->base, REG_WORD_OFFSET + 5);
|
||||
ia32_handle_register(&ea->index, REG_WORD_OFFSET + 7);
|
||||
break;
|
||||
@ -172,7 +172,7 @@ static size_t modrm_decode16( unsigned char *buf, unsigned int buf_len,
|
||||
break;
|
||||
case MOD16_RM_BP:
|
||||
if ( modrm->mod != MOD16_MOD_NODISP ) {
|
||||
op->flags.op_seg = x86_op_flags::op_ss_seg;
|
||||
op->flags.op_seg = x86_op_flags::op_ss_seg>>8;
|
||||
ia32_handle_register(&ea->base,
|
||||
REG_WORD_OFFSET + 5);
|
||||
}
|
||||
|
||||
3206
3rd_party/libdisasm/ia32_opcode.dat
vendored
Normal file
3206
3rd_party/libdisasm/ia32_opcode.dat
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5146
3rd_party/libdisasm/ia32_opcode_tables.cpp
vendored
5146
3rd_party/libdisasm/ia32_opcode_tables.cpp
vendored
File diff suppressed because it is too large
Load Diff
71
3rd_party/libdisasm/ia32_operand.cpp
vendored
71
3rd_party/libdisasm/ia32_operand.cpp
vendored
@ -20,17 +20,17 @@ static void apply_seg( x86_op_t *op, unsigned int prefixes ) {
|
||||
switch ( prefixes & PREFIX_REG_MASK ) {
|
||||
/* NOTE: that op->flags for segment override are not a bitfield */
|
||||
case PREFIX_CS:
|
||||
op->flags.op_seg = x86_op_flags::op_cs_seg; break;
|
||||
op->flags.op_seg = x86_op_flags::op_cs_seg>>8; break;
|
||||
case PREFIX_SS:
|
||||
op->flags.op_seg = x86_op_flags::op_ss_seg; break;
|
||||
op->flags.op_seg = x86_op_flags::op_ss_seg>>8; break;
|
||||
case PREFIX_DS:
|
||||
op->flags.op_seg = x86_op_flags::op_ds_seg; break;
|
||||
op->flags.op_seg = x86_op_flags::op_ds_seg>>8; break;
|
||||
case PREFIX_ES:
|
||||
op->flags.op_seg = x86_op_flags::op_es_seg; break;
|
||||
op->flags.op_seg = x86_op_flags::op_es_seg>>8; break;
|
||||
case PREFIX_FS:
|
||||
op->flags.op_seg = x86_op_flags::op_fs_seg; break;
|
||||
op->flags.op_seg = x86_op_flags::op_fs_seg>>8; break;
|
||||
case PREFIX_GS:
|
||||
op->flags.op_seg = x86_op_flags::op_gs_seg; break;
|
||||
op->flags.op_seg = x86_op_flags::op_gs_seg>>8; break;
|
||||
}
|
||||
|
||||
return;
|
||||
@ -107,19 +107,17 @@ size_t Ia32_Decoder::decode_operand_value( unsigned char *buf, size_t buf_len,
|
||||
/* No MODRM : note these set operand type explicitly */
|
||||
case ADDRMETH_A: /* No modR/M -- direct addr */
|
||||
op->type = op_absolute;
|
||||
|
||||
//according to Intel Manuals, offset goes first
|
||||
/* segment:offset address used in far calls */
|
||||
x86_imm_sized( buf, buf_len,
|
||||
&op->data.absolute.segment, 2 );
|
||||
if ( m_decoded->addr_size == 4 ) {
|
||||
x86_imm_sized( buf, buf_len,
|
||||
&op->data.absolute.offset.off32, 4 );
|
||||
size = 6;
|
||||
} else {
|
||||
x86_imm_sized( buf, buf_len,
|
||||
&op->data.absolute.offset.off16, 2 );
|
||||
x86_imm_sized( buf, buf_len, &op->data.absolute.offset.off32, 4 );
|
||||
size = 4;
|
||||
} else {
|
||||
x86_imm_sized( buf, buf_len, &op->data.absolute.offset.off16, 2 );
|
||||
size = 2;
|
||||
}
|
||||
x86_imm_sized( buf+size, buf_len-size, &op->data.absolute.segment, 2 );
|
||||
size+=2;
|
||||
|
||||
break;
|
||||
case ADDRMETH_I: /* Immediate val */
|
||||
@ -136,21 +134,28 @@ size_t Ia32_Decoder::decode_operand_value( unsigned char *buf, size_t buf_len,
|
||||
size = op_size;
|
||||
break;
|
||||
case ADDRMETH_J: /* Rel offset to add to IP [jmp] */
|
||||
/* this fills op->data.near_offset or
|
||||
/* this fills op->data.near_offset or
|
||||
op->data.far_offset depending on the size of
|
||||
the operand */
|
||||
op->flags.op_signed = true;
|
||||
if ( op_size == 1 ) {
|
||||
/* one-byte near offset */
|
||||
op->type = op_relative_near;
|
||||
x86_imm_signsized(buf, buf_len, &op->data.relative_near, 1);
|
||||
} else {
|
||||
/* far offset...is this truly signed? */
|
||||
op->type = op_relative_far;
|
||||
x86_imm_signsized(buf, buf_len,
|
||||
&op->data.relative_far, op_size );
|
||||
switch(op_size)
|
||||
{
|
||||
case 1:
|
||||
/* one-byte near offset */
|
||||
op->type = op_relative_near;
|
||||
size = x86_imm_signsized(buf, buf_len, &op->data.relative_near, 1);
|
||||
break;
|
||||
case 2:
|
||||
/* far offset...is this truly signed? */
|
||||
op->type = op_relative_far;
|
||||
int16_t offset_val; // easier upcast to int32_t
|
||||
size = x86_imm_signsized(buf, buf_len, &offset_val, 2 );
|
||||
op->data.relative_far=offset_val;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
size=0;
|
||||
}
|
||||
size = op_size;
|
||||
break;
|
||||
case ADDRMETH_O: /* No ModR/M; op is word/dword offset */
|
||||
/* NOTE: these are actually RVAs not offsets to seg!! */
|
||||
@ -172,20 +177,20 @@ size_t Ia32_Decoder::decode_operand_value( unsigned char *buf, size_t buf_len,
|
||||
case ADDRMETH_X: /* Memory addressed by DS:SI [string] */
|
||||
op->type = op_expression;
|
||||
op->flags.op_hardcode = true;
|
||||
op->flags.op_seg = x86_op_flags::op_ds_seg;
|
||||
op->flags.op_seg = x86_op_flags::op_ds_seg>>8;
|
||||
op->flags.op_pointer = true;
|
||||
op->flags.op_string = true;
|
||||
ia32_handle_register( &op->data.expression.base,
|
||||
REG_DWORD_OFFSET + 6 );
|
||||
gen_regs + 6 );
|
||||
break;
|
||||
case ADDRMETH_Y: /* Memory addressed by ES:DI [string] */
|
||||
op->type = op_expression;
|
||||
op->flags.op_hardcode = true;
|
||||
op->flags.op_seg = x86_op_flags::op_es_seg;
|
||||
op->flags.op_seg = x86_op_flags::op_es_seg>>8;
|
||||
op->flags.op_pointer = true;
|
||||
op->flags.op_string = true;
|
||||
ia32_handle_register( &op->data.expression.base,
|
||||
REG_DWORD_OFFSET + 7 );
|
||||
gen_regs + 7 );
|
||||
break;
|
||||
case ADDRMETH_RR: /* Gen Register hard-coded in opcode */
|
||||
op->type = op_register;
|
||||
@ -255,10 +260,10 @@ size_t Ia32_Decoder::decode_operand_size( unsigned int op_type, x86_op_t *op ) {
|
||||
break;
|
||||
case OPTYPE_p: /* 32/48-bit ptr [op size attr] */
|
||||
/* technically these flags are not accurate: the
|
||||
* value s a 16:16 pointer or a 16:32 pointer, where
|
||||
* the first '16' is a segment */
|
||||
* value s a 16:16 pointer or a 16:32 pointer, where
|
||||
* the first '16' is a segment */
|
||||
size = (m_decoded->addr_size == 4) ? 6 : 4;
|
||||
op->datatype = (size == 4) ? op_descr32 : op_descr16;
|
||||
op->datatype = (size == 6) ? op_descr32 : op_descr16;
|
||||
break;
|
||||
case OPTYPE_b: /* byte, ignore op-size */
|
||||
size = 1;
|
||||
|
||||
124
3rd_party/libdisasm/ia32_reg.cpp
vendored
124
3rd_party/libdisasm/ia32_reg.cpp
vendored
@ -31,45 +31,45 @@
|
||||
* of the MMX registers, so this aliasing is not 100% accurate.
|
||||
* */
|
||||
static struct {
|
||||
unsigned char alias; /* id of register this is an alias for */
|
||||
unsigned char shift; /* # of bits register must be shifted */
|
||||
unsigned char alias; /* id of register this is an alias for */
|
||||
unsigned char shift; /* # of bits register must be shifted */
|
||||
} ia32_reg_aliases[] = {
|
||||
{ 0,0 },
|
||||
{ REG_DWORD_OFFSET, 0 }, /* al : 1 */
|
||||
{ REG_DWORD_OFFSET, 8 }, /* ah : 2 */
|
||||
{ REG_DWORD_OFFSET, 0 }, /* ax : 3 */
|
||||
{ REG_DWORD_OFFSET + 1, 0 }, /* cl : 4 */
|
||||
{ REG_DWORD_OFFSET + 1, 8 }, /* ch : 5 */
|
||||
{ REG_DWORD_OFFSET + 1, 0 }, /* cx : 6 */
|
||||
{ REG_DWORD_OFFSET + 2, 0 }, /* dl : 7 */
|
||||
{ REG_DWORD_OFFSET + 2, 8 }, /* dh : 8 */
|
||||
{ REG_DWORD_OFFSET + 2, 0 }, /* dx : 9 */
|
||||
{ REG_DWORD_OFFSET + 3, 0 }, /* bl : 10 */
|
||||
{ REG_DWORD_OFFSET + 3, 8 }, /* bh : 11 */
|
||||
{ REG_DWORD_OFFSET + 3, 0 }, /* bx : 12 */
|
||||
{ REG_DWORD_OFFSET + 4, 0 }, /* sp : 13 */
|
||||
{ REG_DWORD_OFFSET + 5, 0 }, /* bp : 14 */
|
||||
{ REG_DWORD_OFFSET + 6, 0 }, /* si : 15 */
|
||||
{ REG_DWORD_OFFSET + 7, 0 }, /* di : 16 */
|
||||
{ REG_EIP_INDEX, 0 }, /* ip : 17 */
|
||||
{ REG_FPU_OFFSET, 0 }, /* mm0 : 18 */
|
||||
{ REG_FPU_OFFSET + 1, 0 }, /* mm1 : 19 */
|
||||
{ REG_FPU_OFFSET + 2, 0 }, /* mm2 : 20 */
|
||||
{ REG_FPU_OFFSET + 3, 0 }, /* mm3 : 21 */
|
||||
{ REG_FPU_OFFSET + 4, 0 }, /* mm4 : 22 */
|
||||
{ REG_FPU_OFFSET + 5, 0 }, /* mm5 : 23 */
|
||||
{ REG_FPU_OFFSET + 6, 0 }, /* mm6 : 24 */
|
||||
{ REG_FPU_OFFSET + 7, 0 } /* mm7 : 25 */
|
||||
};
|
||||
{ 0,0 },
|
||||
{ REG_DWORD_OFFSET, 0 }, /* al : 1 */
|
||||
{ REG_DWORD_OFFSET, 8 }, /* ah : 2 */
|
||||
{ REG_DWORD_OFFSET, 0 }, /* ax : 3 */
|
||||
{ REG_DWORD_OFFSET + 1, 0 }, /* cl : 4 */
|
||||
{ REG_DWORD_OFFSET + 1, 8 }, /* ch : 5 */
|
||||
{ REG_DWORD_OFFSET + 1, 0 }, /* cx : 6 */
|
||||
{ REG_DWORD_OFFSET + 2, 0 }, /* dl : 7 */
|
||||
{ REG_DWORD_OFFSET + 2, 8 }, /* dh : 8 */
|
||||
{ REG_DWORD_OFFSET + 2, 0 }, /* dx : 9 */
|
||||
{ REG_DWORD_OFFSET + 3, 0 }, /* bl : 10 */
|
||||
{ REG_DWORD_OFFSET + 3, 8 }, /* bh : 11 */
|
||||
{ REG_DWORD_OFFSET + 3, 0 }, /* bx : 12 */
|
||||
{ REG_DWORD_OFFSET + 4, 0 }, /* sp : 13 */
|
||||
{ REG_DWORD_OFFSET + 5, 0 }, /* bp : 14 */
|
||||
{ REG_DWORD_OFFSET + 6, 0 }, /* si : 15 */
|
||||
{ REG_DWORD_OFFSET + 7, 0 }, /* di : 16 */
|
||||
{ REG_EIP_INDEX, 0 }, /* ip : 17 */
|
||||
{ REG_FPU_OFFSET, 0 }, /* mm0 : 18 */
|
||||
{ REG_FPU_OFFSET + 1, 0 }, /* mm1 : 19 */
|
||||
{ REG_FPU_OFFSET + 2, 0 }, /* mm2 : 20 */
|
||||
{ REG_FPU_OFFSET + 3, 0 }, /* mm3 : 21 */
|
||||
{ REG_FPU_OFFSET + 4, 0 }, /* mm4 : 22 */
|
||||
{ REG_FPU_OFFSET + 5, 0 }, /* mm5 : 23 */
|
||||
{ REG_FPU_OFFSET + 6, 0 }, /* mm6 : 24 */
|
||||
{ REG_FPU_OFFSET + 7, 0 } /* mm7 : 25 */
|
||||
};
|
||||
|
||||
/* REGISTER TABLE: size, type, and name of every register in the
|
||||
* CPU. Does not include MSRs since the are, after all,
|
||||
* model specific. */
|
||||
static struct {
|
||||
unsigned int size;
|
||||
enum x86_reg_type type;
|
||||
unsigned int alias;
|
||||
char mnemonic[8];
|
||||
unsigned int size;
|
||||
enum x86_reg_type type;
|
||||
unsigned int alias;
|
||||
char mnemonic[8];
|
||||
} ia32_reg_table[NUM_X86_REGS + 2] = {
|
||||
{ 0, reg_undef, 0, "" },
|
||||
/* REG_DWORD_OFFSET */
|
||||
@ -189,7 +189,7 @@ static struct {
|
||||
{ REG_DWORD_SIZE, reg_sys, 0, "esp_msr" },
|
||||
/* REG_EIPMSR_INDEX : SYSENTER_EIP_MSR : 92 */
|
||||
{ REG_DWORD_SIZE, reg_sys, 0, "eip_msr" },
|
||||
{ 0 }
|
||||
{ 0,reg_undef,0,"" }
|
||||
};
|
||||
|
||||
|
||||
@ -197,38 +197,38 @@ static size_t sz_regtable = NUM_X86_REGS + 1;
|
||||
|
||||
|
||||
void ia32_handle_register( x86_reg_t *reg, size_t id ) {
|
||||
unsigned int alias;
|
||||
if (! id || id > sz_regtable ) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset( reg, 0, sizeof(x86_reg_t) );
|
||||
|
||||
strncpy( reg->name, ia32_reg_table[id].mnemonic, MAX_REGNAME );
|
||||
|
||||
reg->type = ia32_reg_table[id].type;
|
||||
reg->size = ia32_reg_table[id].size;
|
||||
|
||||
alias = ia32_reg_table[id].alias;
|
||||
if ( alias ) {
|
||||
reg->alias = ia32_reg_aliases[alias].alias;
|
||||
reg->shift = ia32_reg_aliases[alias].shift;
|
||||
}
|
||||
reg->id = id;
|
||||
|
||||
unsigned int alias;
|
||||
if (! id || id > sz_regtable ) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset( reg, 0, sizeof(x86_reg_t) );
|
||||
|
||||
strncpy( reg->name, ia32_reg_table[id].mnemonic, MAX_REGNAME );
|
||||
|
||||
reg->type = ia32_reg_table[id].type;
|
||||
reg->size = ia32_reg_table[id].size;
|
||||
|
||||
alias = ia32_reg_table[id].alias;
|
||||
if ( alias ) {
|
||||
reg->alias = ia32_reg_aliases[alias].alias;
|
||||
reg->shift = ia32_reg_aliases[alias].shift;
|
||||
}
|
||||
reg->id = id;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
size_t ia32_true_register_id( size_t id ) {
|
||||
size_t reg;
|
||||
size_t reg;
|
||||
|
||||
if (! id || id > sz_regtable ) {
|
||||
return 0;
|
||||
}
|
||||
if (! id || id > sz_regtable ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
reg = id;
|
||||
if (ia32_reg_table[reg].alias) {
|
||||
reg = ia32_reg_aliases[ia32_reg_table[reg].alias].alias;
|
||||
}
|
||||
return reg;
|
||||
reg = id;
|
||||
if (ia32_reg_table[reg].alias) {
|
||||
reg = ia32_reg_aliases[ia32_reg_table[reg].alias].alias;
|
||||
}
|
||||
return reg;
|
||||
}
|
||||
|
||||
177
3rd_party/libdisasm/libdis.h
vendored
177
3rd_party/libdisasm/libdis.h
vendored
@ -6,6 +6,7 @@
|
||||
#endif
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <stdint.h>
|
||||
|
||||
/* 'NEW" types
|
||||
@ -89,7 +90,7 @@ enum x86_options { /* these can be ORed together */
|
||||
opt_none= 0,
|
||||
opt_ignore_nulls=1, /* ignore sequences of > 4 NULL bytes */
|
||||
opt_16_bit=2, /* 16-bit/DOS disassembly */
|
||||
opt_att_mnemonics=4, /* use AT&T syntax names for alternate opcode mnemonics */
|
||||
opt_att_mnemonics=4 /* use AT&T syntax names for alternate opcode mnemonics */
|
||||
};
|
||||
|
||||
/* ========================================= Instruction Representation */
|
||||
@ -133,12 +134,12 @@ enum x86_reg_type { /* NOTE: these may be ORed together */
|
||||
|
||||
/* x86_reg_t : an X86 CPU register */
|
||||
struct x86_reg_t {
|
||||
char name[MAX_REGNAME];
|
||||
enum x86_reg_type type; /* what register is used for */
|
||||
unsigned int size; /* size of register in bytes */
|
||||
unsigned int id; /* register ID #, for quick compares */
|
||||
unsigned int alias; /* ID of reg this is an alias for */
|
||||
unsigned int shift; /* amount to shift aliased reg by */
|
||||
char name[MAX_REGNAME];
|
||||
enum x86_reg_type type; /* what register is used for */
|
||||
unsigned int size; /* size of register in bytes */
|
||||
unsigned int id; /* register ID #, for quick compares */
|
||||
unsigned int alias; /* ID of reg this is an alias for */
|
||||
unsigned int shift; /* amount to shift aliased reg by */
|
||||
x86_reg_t * aliased_reg( ) {
|
||||
x86_reg_t * reg = (x86_reg_t * )calloc( sizeof(x86_reg_t), 1 );
|
||||
reg->x86_reg_from_id( id );
|
||||
@ -158,11 +159,11 @@ typedef struct {
|
||||
|
||||
/* x86_absolute_t : an X86 segment:offset address (descriptor) */
|
||||
typedef struct {
|
||||
unsigned short segment; /* loaded directly into CS */
|
||||
union {
|
||||
unsigned short off16; /* loaded directly into IP */
|
||||
uint32_t off32; /* loaded directly into EIP */
|
||||
} offset;
|
||||
unsigned short segment; /* loaded directly into CS */
|
||||
union {
|
||||
unsigned short off16; /* loaded directly into IP */
|
||||
uint32_t off32; /* loaded directly into EIP */
|
||||
} offset;
|
||||
} x86_absolute_t;
|
||||
|
||||
enum x86_op_type { /* mutually exclusive */
|
||||
@ -250,57 +251,87 @@ struct x86_op_flags { /* ORed together, but segs are mutually exclusive */
|
||||
/* x86_op_t : an X86 instruction operand */
|
||||
struct x86_op_t{
|
||||
friend struct x86_insn_t;
|
||||
enum x86_op_type type; /* operand type */
|
||||
enum x86_op_datatype datatype; /* operand size */
|
||||
enum x86_op_access access; /* operand access [RWX] */
|
||||
x86_op_flags flags; /* misc flags */
|
||||
union {
|
||||
/* sizeof will have to work on these union members! */
|
||||
/* immediate values */
|
||||
char sbyte;
|
||||
short sword;
|
||||
int32_t sdword;
|
||||
qword_t sqword;
|
||||
unsigned char byte;
|
||||
unsigned short word;
|
||||
uint32_t dword;
|
||||
qword_t qword;
|
||||
float sreal;
|
||||
double dreal;
|
||||
/* misc large/non-native types */
|
||||
unsigned char extreal[10];
|
||||
unsigned char bcd[10];
|
||||
qword_t dqword[2];
|
||||
unsigned char simd[16];
|
||||
unsigned char fpuenv[28];
|
||||
/* offset from segment */
|
||||
uint32_t offset;
|
||||
x86_reg_t reg; /* ID of CPU register */
|
||||
char relative_near; /* offsets from current insn */
|
||||
int32_t relative_far;
|
||||
x86_absolute_t absolute; /* segment:offset */
|
||||
x86_ea_t expression; /* effective address [expression] */
|
||||
} data;
|
||||
/* this is needed to make formatting operands more sane */
|
||||
void * insn; /* pointer to x86_insn_t owning operand */
|
||||
size_t size()
|
||||
enum x86_op_type type; /* operand type */
|
||||
enum x86_op_datatype datatype; /* operand size */
|
||||
enum x86_op_access access; /* operand access [RWX] */
|
||||
x86_op_flags flags; /* misc flags */
|
||||
union {
|
||||
/* sizeof will have to work on these union members! */
|
||||
/* immediate values */
|
||||
char sbyte;
|
||||
short sword;
|
||||
int32_t sdword;
|
||||
qword_t sqword;
|
||||
unsigned char byte;
|
||||
unsigned short word;
|
||||
uint32_t dword;
|
||||
qword_t qword;
|
||||
float sreal;
|
||||
double dreal;
|
||||
/* misc large/non-native types */
|
||||
unsigned char extreal[10];
|
||||
unsigned char bcd[10];
|
||||
qword_t dqword[2];
|
||||
unsigned char simd[16];
|
||||
unsigned char fpuenv[28];
|
||||
/* offset from segment */
|
||||
uint32_t offset;
|
||||
/* ID of CPU register */
|
||||
x86_reg_t reg;
|
||||
/* offsets from current insn */
|
||||
char relative_near;
|
||||
int32_t relative_far;
|
||||
/* segment:offset */
|
||||
x86_absolute_t absolute;
|
||||
/* effective address [expression] */
|
||||
x86_ea_t expression;
|
||||
} data;
|
||||
/* this is needed to make formatting operands more sane */
|
||||
void * insn; /* pointer to x86_insn_t owning operand */
|
||||
size_t size() const
|
||||
{
|
||||
return operand_size();
|
||||
}
|
||||
/* get size of operand data in bytes */
|
||||
size_t operand_size();
|
||||
size_t operand_size() const;
|
||||
/* format (sprintf) an operand into 'buf' using specified syntax */
|
||||
int x86_format_operand(char *buf, int len, enum x86_asm_format format );
|
||||
bool is_address( ) {
|
||||
bool is_address( ) const {
|
||||
return ( type == op_absolute || type == op_offset );
|
||||
}
|
||||
bool is_relative( ) {
|
||||
bool is_relative( ) const {
|
||||
return ( type == op_relative_near || type == op_relative_far );
|
||||
}
|
||||
bool is_immediate( ) const { return ( type == op_immediate ); }
|
||||
int32_t getAddress()
|
||||
{
|
||||
assert(is_address()||is_relative());
|
||||
switch ( type ) {
|
||||
case op_relative_near:
|
||||
return (int32_t) data.relative_near;
|
||||
case op_absolute:
|
||||
if(datatype==op_descr16)
|
||||
return int32_t((data.absolute.segment)<<4) + data.absolute.offset.off16;
|
||||
else
|
||||
return int32_t((data.absolute.segment)<<4) + data.absolute.offset.off32;
|
||||
case op_offset:
|
||||
return data.offset;
|
||||
case op_relative_far:
|
||||
if (data.relative_far & 0x8000)
|
||||
return (data.relative_far & 0xFFFF) | 0xFFFF0000;
|
||||
else
|
||||
return (int32_t)data.relative_far;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
return ~0;
|
||||
}
|
||||
char * format( enum x86_asm_format format );
|
||||
x86_op_t * copy()
|
||||
{
|
||||
x86_op_t *op = (x86_op_t *) calloc( sizeof(x86_op_t), 1 );
|
||||
|
||||
if ( op ) {
|
||||
memcpy( op, this, sizeof(x86_op_t) );
|
||||
}
|
||||
@ -439,7 +470,7 @@ enum x86_insn_note {
|
||||
insn_note_smm = 2, /* "" in System Management Mode */
|
||||
insn_note_serial = 4, /* Serializing instruction */
|
||||
insn_note_nonswap = 8, /* Does not swap arguments in att-style formatting */
|
||||
insn_note_nosuffix = 16, /* Does not have size suffix in att-style formatting */
|
||||
insn_note_nosuffix = 16 /* Does not have size suffix in att-style formatting */
|
||||
};
|
||||
|
||||
/* This specifies what effects the instruction has on the %eflags register */
|
||||
@ -520,7 +551,6 @@ enum x86_insn_prefix {
|
||||
|
||||
|
||||
/* TODO: maybe provide insn_new/free(), and have disasm return new insn_t */
|
||||
|
||||
/* FOREACH types: these are used to limit the foreach results to
|
||||
* operands which match a certain "type" (implicit or explicit)
|
||||
* or which are accessed in certain ways (e.g. read or write). Note
|
||||
@ -572,8 +602,8 @@ private:
|
||||
void x86_oplist_append(x86_oplist_t *op);
|
||||
public:
|
||||
/* information about the instruction */
|
||||
uint32_t addr; /* load address */
|
||||
uint32_t offset; /* offset into file/buffer */
|
||||
uint32_t addr; /* load address */
|
||||
uint32_t offset; /* offset into file/buffer */
|
||||
x86_insn_group group; /* meta-type, e.g. INS_EXEC */
|
||||
x86_insn_type type; /* type, e.g. INS_BRANCH */
|
||||
x86_insn_note note; /* note, e.g. RING0 */
|
||||
@ -604,29 +634,36 @@ public:
|
||||
void *block; /* code block containing this insn */
|
||||
void *function; /* function containing this insn */
|
||||
int tag; /* tag the insn as seen/processed */
|
||||
x86_op_t * x86_operand_new();
|
||||
size_t x86_operand_count( enum x86_op_foreach_type type );
|
||||
x86_op_t *x86_operand_new();
|
||||
/* convenience routine: returns count of operands matching 'type' */
|
||||
size_t x86_operand_count( enum x86_op_foreach_type type );
|
||||
/* accessor functions for the operands */
|
||||
x86_op_t * x86_operand_1st( );
|
||||
x86_op_t * x86_operand_2nd( );
|
||||
x86_op_t * x86_operand_3rd( );
|
||||
x86_op_t * get_dest();
|
||||
int32_t x86_get_rel_offset( );
|
||||
x86_op_t * x86_get_branch_target( );
|
||||
x86_op_t * x86_get_imm( );
|
||||
uint8_t * x86_get_raw_imm( );
|
||||
x86_op_t * operand_1st( );
|
||||
x86_op_t * operand_2nd( );
|
||||
x86_op_t * operand_3rd( );
|
||||
const x86_op_t * get_dest() const;
|
||||
int32_t x86_get_rel_offset( );
|
||||
x86_op_t * x86_get_branch_target( );
|
||||
x86_op_t * x86_get_imm( );
|
||||
/* More accessor fuctions, this time for user-defined info... */
|
||||
void x86_set_insn_addr( uint32_t addr );
|
||||
int x86_format_mnemonic( char *buf, int len, enum x86_asm_format format);
|
||||
int x86_format_insn( char *buf, int len, enum x86_asm_format);
|
||||
void x86_oplist_free( );
|
||||
uint8_t * x86_get_raw_imm( );
|
||||
/* set the address (usually RVA) of the insn */
|
||||
void x86_set_insn_addr( uint32_t addr );
|
||||
/* format (sprintf) an instruction mnemonic into 'buf' using specified syntax */
|
||||
int x86_format_mnemonic( char *buf, int len, enum x86_asm_format format);
|
||||
int x86_format_insn( char *buf, int len, enum x86_asm_format);
|
||||
void x86_oplist_free( );
|
||||
/* returns 0 if an instruction is invalid, 1 if valid */
|
||||
bool is_valid( );
|
||||
uint32_t x86_get_address( );
|
||||
void make_invalid(unsigned char *buf);
|
||||
void make_invalid(unsigned char *buf);
|
||||
/* instruction tagging: these routines allow the programmer to mark
|
||||
* instructions as "seen" in a DFS, for example. libdisasm does not use
|
||||
* the tag field.*/
|
||||
/* set insn->tag to 1 */
|
||||
void x86_tag_insn( );
|
||||
|
||||
/* return insn->tag */
|
||||
int x86_insn_is_tagged();
|
||||
/* set insn->tag to 0 */
|
||||
void x86_untag_insn();
|
||||
@ -722,7 +759,7 @@ public:
|
||||
* offset : Offset in buffer to disassemble
|
||||
* insn : Structure to fill with disassembled instruction
|
||||
*/
|
||||
unsigned int x86_disasm( unsigned char *buf, unsigned int buf_len,
|
||||
unsigned int x86_disasm(const unsigned char *buf, unsigned int buf_len,
|
||||
uint32_t buf_rva, unsigned int offset,
|
||||
x86_insn_t * insn );
|
||||
/* x86_disasm_range: Sequential disassembly of a range of bytes in a buffer,
|
||||
@ -803,7 +840,7 @@ public:
|
||||
* void x86_get_aliased_reg( x86_reg_t *alias_reg, x86_reg_t *output_reg )
|
||||
* where 'alias_reg' is a reg operand and 'output_reg' is filled with the
|
||||
* register that the operand is an alias for */
|
||||
//#define x86_get_aliased_reg( alias_reg, output_reg ) \
|
||||
//#define x86_get_aliased_reg( alias_reg, output_reg )
|
||||
// x86_reg_from_id( alias_reg->alias, output_reg )
|
||||
|
||||
|
||||
|
||||
49
3rd_party/libdisasm/libdisasm.def
vendored
Normal file
49
3rd_party/libdisasm/libdisasm.def
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
;libdisasm.def : Declares the module parameters
|
||||
|
||||
LIBRARY "libdisasm.dll"
|
||||
DESCRIPTION "libdisasm exported functions"
|
||||
EXPORTS
|
||||
x86_addr_size @1
|
||||
x86_cleanup @2
|
||||
x86_disasm @3
|
||||
x86_disasm_forward @4
|
||||
x86_disasm_range @5
|
||||
x86_endian @6
|
||||
x86_format_header @7
|
||||
x86_format_insn @8
|
||||
x86_format_mnemonic @9
|
||||
x86_format_operand @10
|
||||
x86_fp_reg @11
|
||||
x86_get_branch_target @12
|
||||
x86_get_imm @13
|
||||
x86_get_options @14
|
||||
x86_get_raw_imm @15
|
||||
x86_get_rel_offset @16
|
||||
x86_imm_signsized @17
|
||||
x86_imm_sized @18
|
||||
x86_init @19
|
||||
x86_insn_is_tagged @20
|
||||
x86_insn_is_valid @21
|
||||
x86_invariant_disasm @22
|
||||
x86_ip_reg @23
|
||||
x86_max_insn_size @24
|
||||
x86_op_size @25
|
||||
x86_operand_1st @26
|
||||
x86_operand_2nd @27
|
||||
x86_operand_3rd @28
|
||||
x86_operand_count @29
|
||||
x86_operand_foreach @30
|
||||
x86_operand_new @31
|
||||
x86_operand_size @32
|
||||
x86_oplist_free @33
|
||||
x86_reg_from_id @34
|
||||
x86_report_error @35
|
||||
x86_set_insn_addr @36
|
||||
x86_set_insn_block @37
|
||||
x86_set_insn_function @38
|
||||
x86_set_insn_offset @39
|
||||
x86_set_options @40
|
||||
x86_set_reporter @41
|
||||
x86_size_disasm @42
|
||||
x86_sp_reg @43
|
||||
x86_tag_insn @44
|
||||
231
3rd_party/libdisasm/x86_disasm.cpp
vendored
231
3rd_party/libdisasm/x86_disasm.cpp
vendored
@ -9,8 +9,8 @@
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define snprintf _snprintf
|
||||
#define inline __inline
|
||||
#define snprintf _snprintf
|
||||
#define inline __inline
|
||||
#endif
|
||||
void x86_insn_t::make_invalid(unsigned char *buf)
|
||||
{
|
||||
@ -21,9 +21,9 @@ void x86_insn_t::make_invalid(unsigned char *buf)
|
||||
type = insn_invalid;
|
||||
memcpy( bytes, buf, 1 );
|
||||
}
|
||||
unsigned int X86_Disasm::x86_disasm( unsigned char *buf, unsigned int buf_len,
|
||||
uint32_t buf_rva, unsigned int offset,
|
||||
x86_insn_t *insn ){
|
||||
unsigned int X86_Disasm::x86_disasm( const unsigned char *buf, unsigned int buf_len,
|
||||
uint32_t buf_rva, unsigned int offset,
|
||||
x86_insn_t *insn ){
|
||||
int len, size;
|
||||
unsigned char bytes[MAX_INSTRUCTION_SIZE];
|
||||
|
||||
@ -52,8 +52,8 @@ unsigned int X86_Disasm::x86_disasm( unsigned char *buf, unsigned int buf_len,
|
||||
/* copy enough bytes for disassembly into buffer : this
|
||||
* helps prevent buffer overruns at the end of a file */
|
||||
memset( bytes, 0, MAX_INSTRUCTION_SIZE );
|
||||
memcpy( bytes, &buf[offset], (len < MAX_INSTRUCTION_SIZE) ? len :
|
||||
MAX_INSTRUCTION_SIZE );
|
||||
memcpy( bytes, &buf[offset], (len < MAX_INSTRUCTION_SIZE) ? len :
|
||||
MAX_INSTRUCTION_SIZE );
|
||||
|
||||
/* actually do the disassembly */
|
||||
/* TODO: allow switching when more disassemblers are added */
|
||||
@ -81,140 +81,139 @@ unsigned int X86_Disasm::x86_disasm( unsigned char *buf, unsigned int buf_len,
|
||||
}
|
||||
|
||||
unsigned int X86_Disasm::x86_disasm_range( unsigned char *buf, uint32_t buf_rva,
|
||||
unsigned int offset, unsigned int len,
|
||||
DISASM_CALLBACK func, void *arg ) {
|
||||
x86_insn_t insn;
|
||||
unsigned int buf_len, size, count = 0, bytes = 0;
|
||||
unsigned int offset, unsigned int len,
|
||||
DISASM_CALLBACK func, void *arg ) {
|
||||
x86_insn_t insn;
|
||||
unsigned int buf_len, size, count = 0, bytes = 0;
|
||||
|
||||
/* buf_len is implied by the arguments */
|
||||
buf_len = len + offset;
|
||||
/* buf_len is implied by the arguments */
|
||||
buf_len = len + offset;
|
||||
|
||||
while ( bytes < len ) {
|
||||
size = x86_disasm( buf, buf_len, buf_rva, offset + bytes,
|
||||
&insn );
|
||||
if ( size ) {
|
||||
/* invoke callback if it exists */
|
||||
if ( func ) {
|
||||
(*func)( &insn, arg );
|
||||
}
|
||||
bytes += size;
|
||||
count ++;
|
||||
} else {
|
||||
/* error */
|
||||
bytes++; /* try next byte */
|
||||
}
|
||||
|
||||
insn.x86_oplist_free();
|
||||
while ( bytes < len ) {
|
||||
size = x86_disasm( buf, buf_len, buf_rva, offset + bytes,
|
||||
&insn );
|
||||
if ( size ) {
|
||||
/* invoke callback if it exists */
|
||||
if ( func ) {
|
||||
(*func)( &insn, arg );
|
||||
}
|
||||
bytes += size;
|
||||
count ++;
|
||||
} else {
|
||||
/* error */
|
||||
bytes++; /* try next byte */
|
||||
}
|
||||
|
||||
return( count );
|
||||
insn.x86_oplist_free();
|
||||
}
|
||||
|
||||
return( count );
|
||||
}
|
||||
|
||||
static inline int follow_insn_dest( x86_insn_t *insn ) {
|
||||
if ( insn->type == insn_jmp || insn->type == insn_jcc ||
|
||||
insn->type == insn_call || insn->type == insn_callcc ) {
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
if ( insn->type == insn_jmp || insn->type == insn_jcc ||
|
||||
insn->type == insn_call || insn->type == insn_callcc ) {
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static inline int insn_doesnt_return( x86_insn_t *insn ) {
|
||||
return( (insn->type == insn_jmp || insn->type == insn_return) ? 1: 0 );
|
||||
return( (insn->type == insn_jmp || insn->type == insn_return) ? 1: 0 );
|
||||
}
|
||||
|
||||
static int32_t internal_resolver( x86_op_t *op, x86_insn_t *insn ){
|
||||
int32_t next_addr = -1;
|
||||
if ( x86_optype_is_address(op->type) ) {
|
||||
next_addr = op->data.sdword;
|
||||
} else if ( op->type == op_relative_near ) {
|
||||
next_addr = insn->addr + insn->size + op->data.relative_near;
|
||||
} else if ( op->type == op_relative_far ) {
|
||||
next_addr = insn->addr + insn->size + op->data.relative_far;
|
||||
}
|
||||
return( next_addr );
|
||||
int32_t next_addr = -1;
|
||||
if ( x86_optype_is_address(op->type) ) {
|
||||
next_addr = op->data.sdword;
|
||||
} else if ( op->type == op_relative_near ) {
|
||||
next_addr = insn->addr + insn->size + op->data.relative_near;
|
||||
} else if ( op->type == op_relative_far ) {
|
||||
next_addr = insn->addr + insn->size + op->data.relative_far;
|
||||
}
|
||||
return( next_addr );
|
||||
}
|
||||
|
||||
unsigned int X86_Disasm::x86_disasm_forward( unsigned char *buf, unsigned int buf_len,
|
||||
uint32_t buf_rva, unsigned int offset,
|
||||
DISASM_CALLBACK func, void *arg,
|
||||
DISASM_RESOLVER resolver, void *r_arg ){
|
||||
x86_insn_t insn;
|
||||
x86_op_t *op;
|
||||
int32_t next_addr;
|
||||
uint32_t next_offset;
|
||||
unsigned int size, count = 0, bytes = 0, cont = 1;
|
||||
uint32_t buf_rva, unsigned int offset,
|
||||
DISASM_CALLBACK func, void *arg,
|
||||
DISASM_RESOLVER resolver, void *r_arg ){
|
||||
x86_insn_t insn;
|
||||
x86_op_t *op;
|
||||
int32_t next_addr;
|
||||
int32_t next_offset;
|
||||
unsigned int size, count = 0, bytes = 0, cont = 1;
|
||||
|
||||
while ( cont && bytes < buf_len ) {
|
||||
size = x86_disasm( buf, buf_len, buf_rva, offset + bytes,
|
||||
while ( cont && bytes < buf_len ) {
|
||||
size = x86_disasm( buf, buf_len, buf_rva, offset + bytes,
|
||||
&insn );
|
||||
|
||||
if ( size ) {
|
||||
/* invoke callback if it exists */
|
||||
if ( func ) {
|
||||
(*func)( &insn, arg );
|
||||
}
|
||||
bytes += size;
|
||||
count ++;
|
||||
} else {
|
||||
/* error */
|
||||
bytes++; /* try next byte */
|
||||
}
|
||||
|
||||
if ( follow_insn_dest(&insn) ) {
|
||||
op = insn.x86_operand_1st();//x86_get_dest_operand
|
||||
next_addr = -1;
|
||||
|
||||
/* if caller supplied a resolver, use it to determine
|
||||
* the address to disassemble */
|
||||
if ( resolver ) {
|
||||
next_addr = resolver(op, &insn, r_arg);
|
||||
} else {
|
||||
next_addr = internal_resolver(op, &insn);
|
||||
}
|
||||
|
||||
if (next_addr != -1 ) {
|
||||
next_offset = next_addr - buf_rva;
|
||||
/* if offset is in this buffer... */
|
||||
if ( next_offset >= 0 &&
|
||||
next_offset < buf_len ) {
|
||||
/* go ahead and disassemble */
|
||||
count += x86_disasm_forward( buf,
|
||||
buf_len,
|
||||
buf_rva,
|
||||
next_offset,
|
||||
func, arg,
|
||||
resolver, r_arg );
|
||||
} else {
|
||||
/* report unresolved address */
|
||||
x86_report_error( report_disasm_bounds,
|
||||
(void*)(long)next_addr );
|
||||
}
|
||||
}
|
||||
} /* end follow_insn */
|
||||
|
||||
if ( insn_doesnt_return(&insn) ) {
|
||||
/* stop disassembling */
|
||||
cont = 0;
|
||||
}
|
||||
|
||||
insn.x86_oplist_free( );
|
||||
if ( size ) {
|
||||
/* invoke callback if it exists */
|
||||
if ( func ) {
|
||||
(*func)( &insn, arg );
|
||||
}
|
||||
bytes += size;
|
||||
count ++;
|
||||
} else {
|
||||
/* error */
|
||||
bytes++; /* try next byte */
|
||||
}
|
||||
return( count );
|
||||
|
||||
if ( follow_insn_dest(&insn) ) {
|
||||
op = insn.operand_1st();//x86_get_dest_operand
|
||||
next_addr = -1;
|
||||
|
||||
/* if caller supplied a resolver, use it to determine
|
||||
* the address to disassemble */
|
||||
if ( resolver ) {
|
||||
next_addr = resolver(op, &insn, r_arg);
|
||||
} else {
|
||||
next_addr = internal_resolver(op, &insn);
|
||||
}
|
||||
|
||||
if (next_addr != -1 ) {
|
||||
next_offset = next_addr - buf_rva;
|
||||
/* if offset is in this buffer... */
|
||||
if ( next_offset >= 0 && next_offset < buf_len ) {
|
||||
/* go ahead and disassemble */
|
||||
count += x86_disasm_forward( buf,
|
||||
buf_len,
|
||||
buf_rva,
|
||||
next_offset,
|
||||
func, arg,
|
||||
resolver, r_arg );
|
||||
} else {
|
||||
/* report unresolved address */
|
||||
x86_report_error( report_disasm_bounds,
|
||||
(void*)(long)next_addr );
|
||||
}
|
||||
}
|
||||
} /* end follow_insn */
|
||||
|
||||
if ( insn_doesnt_return(&insn) ) {
|
||||
/* stop disassembling */
|
||||
cont = 0;
|
||||
}
|
||||
|
||||
insn.x86_oplist_free( );
|
||||
}
|
||||
return( count );
|
||||
}
|
||||
|
||||
/* invariant instruction representation */
|
||||
size_t x86_invariant_disasm( unsigned char *buf, int buf_len,
|
||||
x86_invariant_t *inv ){
|
||||
if (! buf || ! buf_len || ! inv ) {
|
||||
return(0);
|
||||
}
|
||||
size_t x86_invariant_disasm( unsigned char *buf, int buf_len,
|
||||
x86_invariant_t *inv ){
|
||||
if (! buf || ! buf_len || ! inv ) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
return ia32_disasm_invariant(buf, buf_len, inv);
|
||||
return ia32_disasm_invariant(buf, buf_len, inv);
|
||||
}
|
||||
size_t x86_size_disasm( unsigned char *buf, unsigned int buf_len ) {
|
||||
if (! buf || ! buf_len ) {
|
||||
return(0);
|
||||
}
|
||||
if (! buf || ! buf_len ) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
return ia32_disasm_size(buf, buf_len);
|
||||
return ia32_disasm_size(buf, buf_len);
|
||||
}
|
||||
|
||||
98
3rd_party/libdisasm/x86_format.cpp
vendored
98
3rd_party/libdisasm/x86_format.cpp
vendored
@ -46,7 +46,7 @@
|
||||
} \
|
||||
} while( 0 )
|
||||
|
||||
static char *prefix_strings[] = {
|
||||
static const char *prefix_strings[] = {
|
||||
"", /* no prefix */
|
||||
"repz ", /* the trailing spaces make it easy to prepend to mnemonic */
|
||||
"repnz ",
|
||||
@ -115,7 +115,7 @@ static void get_operand_data_str( x86_op_t *op, char *str, int len ){
|
||||
static void get_operand_regtype_str( int regtype, char *str, int len )
|
||||
{
|
||||
static struct {
|
||||
char *name;
|
||||
const char *name;
|
||||
int value;
|
||||
} operand_regtypes[] = {
|
||||
{"reg_gen" , 0x00001},
|
||||
@ -284,7 +284,7 @@ static int format_expr( x86_ea_t *ea, char *buf, int len,
|
||||
static int format_seg( x86_op_t *op, char *buf, int len,
|
||||
enum x86_asm_format format ) {
|
||||
int len_orig = len;
|
||||
char *reg = "";
|
||||
const char *reg = "";
|
||||
|
||||
if (! op || ! buf || ! len || ! op->flags.whole) {
|
||||
return(0);
|
||||
@ -295,8 +295,9 @@ static int format_seg( x86_op_t *op, char *buf, int len,
|
||||
if (! (int) op->flags.op_seg) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
switch (op->flags.op_seg) {
|
||||
uint16_t seg_ov=uint16_t(op->flags.op_seg)<<8;
|
||||
switch (seg_ov)
|
||||
{
|
||||
case x86_op_flags::op_es_seg: reg = "es"; break;
|
||||
case x86_op_flags::op_cs_seg: reg = "cs"; break;
|
||||
case x86_op_flags::op_ss_seg: reg = "ss"; break;
|
||||
@ -328,9 +329,9 @@ static int format_seg( x86_op_t *op, char *buf, int len,
|
||||
return( len_orig - len ); /* return length of appended string */
|
||||
}
|
||||
|
||||
static char *get_operand_datatype_str( x86_op_t *op ){
|
||||
static const char *get_operand_datatype_str( x86_op_t *op ){
|
||||
|
||||
static char *types[] = {
|
||||
static const char *types[] = {
|
||||
"sbyte", /* 0 */
|
||||
"sword",
|
||||
"sqword",
|
||||
@ -405,7 +406,7 @@ static int format_insn_eflags_str( enum x86_flag_status flags, char *buf,
|
||||
int len) {
|
||||
|
||||
static struct {
|
||||
char *name;
|
||||
const char *name;
|
||||
int value;
|
||||
} insn_flags[] = {
|
||||
{ "carry_set ", 0x0001 },
|
||||
@ -440,9 +441,9 @@ static int format_insn_eflags_str( enum x86_flag_status flags, char *buf,
|
||||
return( len_orig - len );
|
||||
}
|
||||
|
||||
static char *get_insn_group_str( enum x86_insn_t::x86_insn_group gp ) {
|
||||
static const char *get_insn_group_str( enum x86_insn_t::x86_insn_group gp ) {
|
||||
|
||||
static char *types[] = {
|
||||
static const char *types[] = {
|
||||
"", // 0
|
||||
"controlflow",// 1
|
||||
"arithmetic", // 2
|
||||
@ -467,10 +468,10 @@ static char *get_insn_group_str( enum x86_insn_t::x86_insn_group gp ) {
|
||||
return types[gp];
|
||||
}
|
||||
|
||||
static char *get_insn_type_str( enum x86_insn_type type ) {
|
||||
static const char *get_insn_type_str( enum x86_insn_type type ) {
|
||||
|
||||
static struct {
|
||||
char *name;
|
||||
const char *name;
|
||||
int value;
|
||||
} types[] = {
|
||||
/* insn_controlflow */
|
||||
@ -592,8 +593,8 @@ static char *get_insn_type_str( enum x86_insn_type type ) {
|
||||
return "";
|
||||
}
|
||||
|
||||
static char *get_insn_cpu_str( enum x86_insn_cpu cpu ) {
|
||||
static char *intel[] = {
|
||||
static const char *get_insn_cpu_str( enum x86_insn_cpu cpu ) {
|
||||
static const char *intel[] = {
|
||||
"", // 0
|
||||
"8086", // 1
|
||||
"80286", // 2
|
||||
@ -620,8 +621,8 @@ static char *get_insn_cpu_str( enum x86_insn_cpu cpu ) {
|
||||
return "";
|
||||
}
|
||||
|
||||
static char *get_insn_isa_str( enum x86_insn_isa isa ) {
|
||||
static char *subset[] = {
|
||||
static const char *get_insn_isa_str( enum x86_insn_isa isa ) {
|
||||
static const char *subset[] = {
|
||||
NULL, // 0
|
||||
"General Purpose", // 1
|
||||
"Floating Point", // 2
|
||||
@ -880,11 +881,11 @@ static int format_operand_xml( x86_op_t *op, x86_insn_t *insn, char *buf,
|
||||
return( strlen( buf ) );
|
||||
}
|
||||
|
||||
static int format_operand_raw( x86_op_t *op, x86_insn_t *insn, char *buf,
|
||||
static int format_operand_raw( x86_op_t *op, x86_insn_t */*insn*/, char *buf,
|
||||
int len){
|
||||
|
||||
char str[MAX_OP_RAW_STRING];
|
||||
char *datatype = get_operand_datatype_str(op);
|
||||
const char *datatype = get_operand_datatype_str(op);
|
||||
|
||||
switch (op->type) {
|
||||
case op_register:
|
||||
@ -1042,7 +1043,7 @@ char * x86_op_t::format( enum x86_asm_format format ) {
|
||||
|
||||
static int format_att_mnemonic( x86_insn_t *insn, char *buf, int len) {
|
||||
int size = 0;
|
||||
char *suffix;
|
||||
const char *suffix;
|
||||
|
||||
if (! insn || ! buf || ! len )
|
||||
return(0);
|
||||
@ -1051,8 +1052,8 @@ static int format_att_mnemonic( x86_insn_t *insn, char *buf, int len) {
|
||||
|
||||
/* do long jump/call prefix */
|
||||
if ( insn->type == insn_jmp || insn->type == insn_call ) {
|
||||
if (! is_imm_jmp( insn->x86_operand_1st() ) ||
|
||||
(insn->x86_operand_1st())->datatype != op_byte ) {
|
||||
if (! is_imm_jmp( insn->operand_1st() ) ||
|
||||
(insn->operand_1st())->datatype != op_byte ) {
|
||||
/* far jump/call, use "l" prefix */
|
||||
STRNCAT( buf, "l", len );
|
||||
}
|
||||
@ -1076,11 +1077,11 @@ static int format_att_mnemonic( x86_insn_t *insn, char *buf, int len) {
|
||||
insn->type == insn_out
|
||||
)) {
|
||||
if ( insn->x86_operand_count( op_explicit ) > 0 &&
|
||||
is_memory_op( insn->x86_operand_1st() ) ){
|
||||
size = insn->x86_operand_1st()->operand_size();
|
||||
is_memory_op( insn->operand_1st() ) ){
|
||||
size = insn->operand_1st()->operand_size();
|
||||
} else if ( insn->x86_operand_count( op_explicit ) > 1 &&
|
||||
is_memory_op( insn->x86_operand_2nd() ) ){
|
||||
size = insn->x86_operand_2nd()->operand_size();
|
||||
is_memory_op( insn->operand_2nd() ) ){
|
||||
size = insn->operand_2nd()->operand_size();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1094,7 +1095,6 @@ static int format_att_mnemonic( x86_insn_t *insn, char *buf, int len) {
|
||||
return ( strlen( buf ) );
|
||||
}
|
||||
|
||||
/** format (sprintf) an instruction mnemonic into 'buf' using specified syntax */
|
||||
int x86_format_mnemonic(x86_insn_t *insn, char *buf, int len,
|
||||
enum x86_asm_format format){
|
||||
char str[MAX_OP_STRING];
|
||||
@ -1137,7 +1137,7 @@ static int format_insn_note(x86_insn_t *insn, char *buf, int len){
|
||||
return( len_orig - len );
|
||||
}
|
||||
|
||||
static int format_raw_insn( x86_insn_t *insn, char *buf, int len ){
|
||||
static int format_raw_insn( x86_insn_t *insn, char *buf, size_t len ){
|
||||
struct op_string opstr = { buf, len };
|
||||
int i;
|
||||
|
||||
@ -1223,24 +1223,24 @@ static int format_xml_insn( x86_insn_t *insn, char *buf, int len ) {
|
||||
len -= format_insn_eflags_str( insn->flags_tested, buf, len );
|
||||
STRNCAT( buf, "\"/>\n\t</flags>\n", len );
|
||||
|
||||
if ( insn->x86_operand_1st() ) {
|
||||
insn->x86_operand_1st()->x86_format_operand(str,
|
||||
if ( insn->operand_1st() ) {
|
||||
insn->operand_1st()->x86_format_operand(str,
|
||||
sizeof str, xml_syntax);
|
||||
STRNCAT( buf, "\t<operand name=dest>\n", len );
|
||||
STRNCAT( buf, str, len );
|
||||
STRNCAT( buf, "\t</operand>\n", len );
|
||||
}
|
||||
|
||||
if ( insn->x86_operand_2nd() ) {
|
||||
insn->x86_operand_2nd()->x86_format_operand(str,sizeof str,
|
||||
if ( insn->operand_2nd() ) {
|
||||
insn->operand_2nd()->x86_format_operand(str,sizeof str,
|
||||
xml_syntax);
|
||||
STRNCAT( buf, "\t<operand name=src>\n", len );
|
||||
STRNCAT( buf, str, len );
|
||||
STRNCAT( buf, "\t</operand>\n", len );
|
||||
}
|
||||
|
||||
if ( insn->x86_operand_3rd() ) {
|
||||
insn->x86_operand_3rd()->x86_format_operand(str,sizeof str,
|
||||
if ( insn->operand_3rd() ) {
|
||||
insn->operand_3rd()->x86_format_operand(str,sizeof str,
|
||||
xml_syntax);
|
||||
STRNCAT( buf, "\t<operand name=imm>\n", len );
|
||||
STRNCAT( buf, str, len );
|
||||
@ -1342,13 +1342,13 @@ int x86_insn_t::x86_format_insn( char *buf, int len,
|
||||
STRNCAT( buf, "\t", len );
|
||||
|
||||
/* dest */
|
||||
if ( (dst = x86_operand_1st()) && !(dst->flags.op_implied) ) {
|
||||
if ( (dst = operand_1st()) && !(dst->flags.op_implied) ) {
|
||||
dst->x86_format_operand(str, MAX_OP_STRING, format);
|
||||
STRNCAT( buf, str, len );
|
||||
}
|
||||
|
||||
/* src */
|
||||
if ( (src = x86_operand_2nd()) ) {
|
||||
if ( (src = operand_2nd()) ) {
|
||||
if ( !(dst->flags.op_implied) ) {
|
||||
STRNCAT( buf, ", ", len );
|
||||
}
|
||||
@ -1357,9 +1357,9 @@ int x86_insn_t::x86_format_insn( char *buf, int len,
|
||||
}
|
||||
|
||||
/* imm */
|
||||
if ( x86_operand_3rd()) {
|
||||
if ( operand_3rd()) {
|
||||
STRNCAT( buf, ", ", len );
|
||||
x86_operand_3rd()->x86_format_operand(str, MAX_OP_STRING,format);
|
||||
operand_3rd()->x86_format_operand(str, MAX_OP_STRING,format);
|
||||
STRNCAT( buf, str, len );
|
||||
}
|
||||
|
||||
@ -1373,8 +1373,8 @@ int x86_insn_t::x86_format_insn( char *buf, int len,
|
||||
/* not sure which is correct? sometimes GNU as requires
|
||||
* an imm as the first operand, sometimes as the third... */
|
||||
/* imm */
|
||||
if ( x86_operand_3rd() ) {
|
||||
x86_operand_3rd()->x86_format_operand(str, MAX_OP_STRING,format);
|
||||
if ( operand_3rd() ) {
|
||||
operand_3rd()->x86_format_operand(str, MAX_OP_STRING,format);
|
||||
STRNCAT( buf, str, len );
|
||||
/* there is always 'dest' operand if there is 'src' */
|
||||
STRNCAT( buf, ", ", len );
|
||||
@ -1382,13 +1382,13 @@ int x86_insn_t::x86_format_insn( char *buf, int len,
|
||||
|
||||
if ( (note & insn_note_nonswap ) == 0 ) {
|
||||
/* regular AT&T style swap */
|
||||
src = x86_operand_2nd();
|
||||
dst = x86_operand_1st();
|
||||
src = operand_2nd();
|
||||
dst = operand_1st();
|
||||
}
|
||||
else {
|
||||
/* special-case instructions */
|
||||
src = x86_operand_1st();
|
||||
dst = x86_operand_2nd();
|
||||
src = operand_1st();
|
||||
dst = operand_2nd();
|
||||
}
|
||||
|
||||
/* src */
|
||||
@ -1431,20 +1431,20 @@ int x86_insn_t::x86_format_insn( char *buf, int len,
|
||||
|
||||
/* print operands */
|
||||
/* dest */
|
||||
if ( x86_operand_1st() ) {
|
||||
x86_operand_1st()->x86_format_operand(str, MAX_OP_STRING,format);
|
||||
if ( operand_1st() ) {
|
||||
operand_1st()->x86_format_operand(str, MAX_OP_STRING,format);
|
||||
STRNCATF( buf, "%s\t", str, len );
|
||||
}
|
||||
|
||||
/* src */
|
||||
if ( x86_operand_2nd() ) {
|
||||
x86_operand_2nd()->x86_format_operand(str, MAX_OP_STRING,format);
|
||||
if ( operand_2nd() ) {
|
||||
operand_2nd()->x86_format_operand(str, MAX_OP_STRING,format);
|
||||
STRNCATF( buf, "%s\t", str, len );
|
||||
}
|
||||
|
||||
/* imm */
|
||||
if ( x86_operand_3rd()) {
|
||||
x86_operand_3rd()->x86_format_operand(str, MAX_OP_STRING,format);
|
||||
if ( operand_3rd()) {
|
||||
operand_3rd()->x86_format_operand(str, MAX_OP_STRING,format);
|
||||
STRNCAT( buf, str, len );
|
||||
}
|
||||
}
|
||||
|
||||
13
3rd_party/libdisasm/x86_insn.cpp
vendored
13
3rd_party/libdisasm/x86_insn.cpp
vendored
@ -17,7 +17,6 @@ int x86_insn_is_valid( x86_insn_t *insn ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** \returns false if an instruction is invalid, true if valid */
|
||||
bool x86_insn_t::is_valid( )
|
||||
{
|
||||
if ( this && this->type != insn_invalid && this->size > 0 )
|
||||
@ -94,13 +93,12 @@ x86_op_t * x86_insn_t::x86_get_branch_target() {
|
||||
|
||||
return NULL;
|
||||
}
|
||||
x86_op_t * x86_insn_t::get_dest() {
|
||||
const x86_op_t * x86_insn_t::get_dest() const {
|
||||
x86_oplist_t *op_lst;
|
||||
assert(this);
|
||||
if ( ! operands ) {
|
||||
return NULL;
|
||||
}
|
||||
assert(this->x86_operand_count(op_dest)==1);
|
||||
for (op_lst = operands; op_lst; op_lst = op_lst->next ) {
|
||||
if ( op_lst->op.access & op_write)
|
||||
return &(op_lst->op);
|
||||
@ -171,7 +169,7 @@ uint8_t *x86_insn_t::x86_get_raw_imm() {
|
||||
}
|
||||
|
||||
|
||||
size_t x86_op_t::operand_size() {
|
||||
size_t x86_op_t::operand_size() const {
|
||||
switch (datatype ) {
|
||||
case op_byte: return 1;
|
||||
case op_word: return 2;
|
||||
@ -203,13 +201,12 @@ size_t x86_op_t::operand_size() {
|
||||
return(4); /* default size */
|
||||
}
|
||||
|
||||
/** set the address (usually RVA) of the insn */
|
||||
void x86_insn_t::x86_set_insn_addr( uint32_t _addr ) {
|
||||
addr = _addr;
|
||||
}
|
||||
|
||||
void x86_insn_t::x86_set_insn_offset( unsigned int offset ){
|
||||
offset = offset;
|
||||
void x86_insn_t::x86_set_insn_offset( unsigned int _offset ){
|
||||
offset = _offset;
|
||||
}
|
||||
|
||||
void x86_insn_t::x86_set_insn_function( void * func ){
|
||||
@ -220,7 +217,6 @@ void x86_insn_t::x86_set_insn_block( void * _block ){
|
||||
block = _block;
|
||||
}
|
||||
|
||||
/** set insn->tag to 1 */
|
||||
void x86_insn_t::x86_tag_insn(){
|
||||
tag = 1;
|
||||
}
|
||||
@ -229,7 +225,6 @@ void x86_insn_t::x86_untag_insn(){
|
||||
tag = 0;
|
||||
}
|
||||
|
||||
/** \return insn->tag */
|
||||
int x86_insn_t::x86_insn_is_tagged(){
|
||||
return tag;
|
||||
}
|
||||
|
||||
255
3rd_party/libdisasm/x86_operand_list.cpp
vendored
255
3rd_party/libdisasm/x86_operand_list.cpp
vendored
@ -4,31 +4,31 @@
|
||||
|
||||
|
||||
void x86_insn_t::x86_oplist_append( x86_oplist_t *op ) {
|
||||
x86_oplist_t *list;
|
||||
x86_oplist_t *list;
|
||||
assert(this);
|
||||
|
||||
list = operands;
|
||||
if (! list ) {
|
||||
operand_count = 1;
|
||||
/* Note that we have no way of knowing if this is an
|
||||
list = operands;
|
||||
if (! list ) {
|
||||
operand_count = 1;
|
||||
/* Note that we have no way of knowing if this is an
|
||||
* exlicit operand or not, since the caller fills
|
||||
* the x86_op_t after we return. We increase the
|
||||
* explicit count automatically, and ia32_insn_implicit_ops
|
||||
* decrements it */
|
||||
explicit_count = 1;
|
||||
operands = op;
|
||||
explicit_count = 1;
|
||||
operands = op;
|
||||
return;
|
||||
}
|
||||
|
||||
/* get to end of list */
|
||||
for ( ; list->next; list = list->next )
|
||||
;
|
||||
|
||||
operand_count = operand_count + 1;
|
||||
explicit_count = explicit_count + 1;
|
||||
list->next = op;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* get to end of list */
|
||||
for ( ; list->next; list = list->next )
|
||||
;
|
||||
|
||||
operand_count = operand_count + 1;
|
||||
explicit_count = explicit_count + 1;
|
||||
list->next = op;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool x86_insn_t::containsFlag(x86_eflags tofind, x86_flag_status in)
|
||||
@ -48,7 +48,7 @@ bool x86_insn_t::containsFlag(x86_eflags tofind, x86_flag_status in)
|
||||
return (in & (insn_dir_set | insn_dir_clear))!=0;
|
||||
case insn_eflag_sign:
|
||||
return (in & (insn_sign_set | insn_sign_clear | insn_zero_set_or_sign_ne_oflow |
|
||||
insn_sign_eq_oflow | insn_sign_ne_oflow))!=0;
|
||||
insn_sign_eq_oflow | insn_sign_ne_oflow))!=0;
|
||||
case insn_eflag_parity:
|
||||
return (in & (insn_parity_set | insn_parity_clear))!=0;
|
||||
}
|
||||
@ -56,31 +56,31 @@ bool x86_insn_t::containsFlag(x86_eflags tofind, x86_flag_status in)
|
||||
}
|
||||
|
||||
x86_op_t * x86_insn_t::x86_operand_new( ) {
|
||||
x86_oplist_t *op;
|
||||
x86_oplist_t *op;
|
||||
assert(this);
|
||||
op = (x86_oplist_t *)calloc( sizeof(x86_oplist_t), 1 );
|
||||
op->op.insn = this;
|
||||
x86_oplist_append( op );
|
||||
return( &(op->op) );
|
||||
op = (x86_oplist_t *)calloc( sizeof(x86_oplist_t), 1 );
|
||||
op->op.insn = this;
|
||||
x86_oplist_append( op );
|
||||
return( &(op->op) );
|
||||
}
|
||||
|
||||
/** free the operand list associated with an instruction -- useful for
|
||||
* preventing memory leaks when free()ing an x86_insn_t */
|
||||
void x86_insn_t::x86_oplist_free( )
|
||||
{
|
||||
x86_oplist_t *op, *list;
|
||||
x86_oplist_t *op, *list;
|
||||
assert(this);
|
||||
for ( list = operands; list; ) {
|
||||
op = list;
|
||||
list = list->next;
|
||||
free(op);
|
||||
}
|
||||
for ( list = operands; list; ) {
|
||||
op = list;
|
||||
list = list->next;
|
||||
free(op);
|
||||
}
|
||||
|
||||
operands = NULL;
|
||||
operand_count = 0;
|
||||
explicit_count = 0;
|
||||
operands = NULL;
|
||||
operand_count = 0;
|
||||
explicit_count = 0;
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
/* ================================================== LIBDISASM API */
|
||||
@ -88,122 +88,121 @@ void x86_insn_t::x86_oplist_free( )
|
||||
enum... yet one more confusing thing in the API */
|
||||
int x86_insn_t::x86_operand_foreach( x86_operand_fn func, void *arg, enum x86_op_foreach_type type )
|
||||
{
|
||||
x86_oplist_t *list;
|
||||
char _explicit = 1, implicit = 1;
|
||||
x86_oplist_t *list;
|
||||
char _explicit = 1, implicit = 1;
|
||||
assert(this);
|
||||
if ( ! func ) {
|
||||
return 0;
|
||||
}
|
||||
if ( ! func ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* note: explicit and implicit can be ORed together to
|
||||
/* note: explicit and implicit can be ORed together to
|
||||
* allow an "all" limited by access type, even though the
|
||||
* user is stupid to do this since it is default behavior :) */
|
||||
if ( (type & op_explicit) && ! (type & op_implicit) ) {
|
||||
implicit = 0;
|
||||
}
|
||||
if ( (type & op_implicit) && ! (type & op_explicit) ) {
|
||||
_explicit = 0;
|
||||
}
|
||||
|
||||
type = (x86_op_foreach_type)((int)type & 0x0F); /* mask out explicit/implicit operands */
|
||||
|
||||
for ( list = operands; list; list = list->next ) {
|
||||
if (! implicit && (list->op.flags.op_implied) ) {
|
||||
/* operand is implicit */
|
||||
continue;
|
||||
if ( (type & op_explicit) && ! (type & op_implicit) ) {
|
||||
implicit = 0;
|
||||
}
|
||||
if ( (type & op_implicit) && ! (type & op_explicit) ) {
|
||||
_explicit = 0;
|
||||
}
|
||||
|
||||
if (! _explicit && ! (list->op.flags.op_implied) ) {
|
||||
/* operand is not implicit */
|
||||
continue;
|
||||
type = (x86_op_foreach_type)((int)type & 0x0F); /* mask out explicit/implicit operands */
|
||||
|
||||
for ( list = operands; list; list = list->next ) {
|
||||
if (! implicit && (list->op.flags.op_implied) ) {
|
||||
/* operand is implicit */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! _explicit && ! (list->op.flags.op_implied) ) {
|
||||
/* operand is not implicit */
|
||||
continue;
|
||||
}
|
||||
|
||||
switch ( type ) {
|
||||
case op_any:
|
||||
break;
|
||||
case op_dest:
|
||||
if (! (list->op.access & op_write) ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case op_src:
|
||||
if (! (list->op.access & op_read) ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case op_ro:
|
||||
if (! (list->op.access & op_read) ||
|
||||
(list->op.access & op_write ) ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case op_wo:
|
||||
if (! (list->op.access & op_write) ||
|
||||
(list->op.access & op_read ) ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case op_xo:
|
||||
if (! (list->op.access & op_execute) ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case op_rw:
|
||||
if (! (list->op.access & op_write) ||
|
||||
! (list->op.access & op_read ) ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case op_implicit: case op_explicit: /* make gcc happy */
|
||||
break;
|
||||
}
|
||||
/* any non-continue ends up here: invoke the callback */
|
||||
(*func)( &list->op, this, arg );
|
||||
}
|
||||
|
||||
switch ( type ) {
|
||||
case op_any:
|
||||
break;
|
||||
case op_dest:
|
||||
if (! (list->op.access & op_write) ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case op_src:
|
||||
if (! (list->op.access & op_read) ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case op_ro:
|
||||
if (! (list->op.access & op_read) ||
|
||||
(list->op.access & op_write ) ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case op_wo:
|
||||
if (! (list->op.access & op_write) ||
|
||||
(list->op.access & op_read ) ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case op_xo:
|
||||
if (! (list->op.access & op_execute) ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case op_rw:
|
||||
if (! (list->op.access & op_write) ||
|
||||
! (list->op.access & op_read ) ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case op_implicit: case op_explicit: /* make gcc happy */
|
||||
break;
|
||||
}
|
||||
/* any non-continue ends up here: invoke the callback */
|
||||
(*func)( &list->op, this, arg );
|
||||
}
|
||||
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void count_operand( x86_op_t *op, x86_insn_t *insn, void *arg ) {
|
||||
size_t * count = (size_t *) arg;
|
||||
*count = *count + 1;
|
||||
static void count_operand( x86_op_t */*op*/, x86_insn_t */*insn*/, void *arg ) {
|
||||
size_t * count = (size_t *) arg;
|
||||
*count = *count + 1;
|
||||
}
|
||||
|
||||
/** convenience routine: returns count of operands matching 'type' */
|
||||
size_t x86_insn_t::x86_operand_count( enum x86_op_foreach_type type ) {
|
||||
size_t count = 0;
|
||||
size_t count = 0;
|
||||
|
||||
/* save us a list traversal for common counts... */
|
||||
if ( type == op_any ) {
|
||||
return operand_count;
|
||||
} else if ( type == op_explicit ) {
|
||||
return explicit_count;
|
||||
}
|
||||
/* save us a list traversal for common counts... */
|
||||
if ( type == op_any ) {
|
||||
return operand_count;
|
||||
} else if ( type == op_explicit ) {
|
||||
return explicit_count;
|
||||
}
|
||||
|
||||
x86_operand_foreach( count_operand, &count, type );
|
||||
return count;
|
||||
x86_operand_foreach( count_operand, &count, type );
|
||||
return count;
|
||||
}
|
||||
|
||||
/* accessor functions */
|
||||
x86_op_t * x86_insn_t::x86_operand_1st() {
|
||||
if (! explicit_count ) {
|
||||
return NULL;
|
||||
}
|
||||
x86_op_t * x86_insn_t::operand_1st() {
|
||||
if (! explicit_count ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &(operands->op);
|
||||
return &(operands->op);
|
||||
}
|
||||
|
||||
x86_op_t * x86_insn_t::x86_operand_2nd( ) {
|
||||
if ( explicit_count < 2 ) {
|
||||
return NULL;
|
||||
}
|
||||
x86_op_t * x86_insn_t::operand_2nd( ) {
|
||||
if ( explicit_count < 2 ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &(operands->next->op);
|
||||
return &(operands->next->op);
|
||||
}
|
||||
|
||||
x86_op_t * x86_insn_t::x86_operand_3rd( ) {
|
||||
if ( explicit_count < 3 ) {
|
||||
return NULL;
|
||||
}
|
||||
return &(operands->next->next->op);
|
||||
x86_op_t * x86_insn_t::operand_3rd( ) {
|
||||
if ( explicit_count < 3 ) {
|
||||
return NULL;
|
||||
}
|
||||
return &(operands->next->next->op);
|
||||
}
|
||||
|
||||
@ -1,38 +1,47 @@
|
||||
PROJECT(dcc_original)
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
find_package(Qt5Core)
|
||||
|
||||
OPTION(dcc_build_tests "Enable unit tests." OFF)
|
||||
|
||||
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__ -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS)
|
||||
IF(CMAKE_BUILD_TOOL MATCHES "(msdev|devenv|nmake)")
|
||||
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__ -D_CRT_NONSTDC_NO_DEPRECATE)
|
||||
#SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR})
|
||||
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__ -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS)
|
||||
IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__ -D_CRT_NONSTDC_NO_DEPRECATE -DNOMINMAX)
|
||||
ADD_DEFINITIONS(/W4)
|
||||
ELSE()
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall --std=c++0x")
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_GLIBCXX_DEBUG " ) #--coverage
|
||||
#-D_GLIBCXX_DEBUG
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11")
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} " ) #--coverage
|
||||
ENDIF()
|
||||
|
||||
SET(CMAKE_CXX_STANDARD 11)
|
||||
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeScripts;${CMAKE_MODULE_PATH})
|
||||
|
||||
FIND_PACKAGE(LLVM)
|
||||
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR})
|
||||
include(cotire)
|
||||
FIND_PACKAGE(Boost)
|
||||
IF(dcc_build_tests)
|
||||
enable_testing()
|
||||
FIND_PACKAGE(GMock)
|
||||
ENDIF()
|
||||
|
||||
ADD_SUBDIRECTORY(3rd_party)
|
||||
|
||||
llvm_map_components_to_libraries(REQ_LLVM_LIBRARIES jit native mc support)
|
||||
INCLUDE_DIRECTORIES(
|
||||
3rd_party/libdisasm
|
||||
include
|
||||
include/idioms
|
||||
common
|
||||
${Boost_INCLUDE_DIRS}
|
||||
${LLVM_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(dcc_SOURCES
|
||||
src/dcc.cpp
|
||||
|
||||
ADD_SUBDIRECTORY(3rd_party)
|
||||
ADD_SUBDIRECTORY(common)
|
||||
ADD_SUBDIRECTORY(tools)
|
||||
|
||||
|
||||
set(dcc_LIB_SOURCES
|
||||
src/CallConvention.cpp
|
||||
src/ast.cpp
|
||||
src/backend.cpp
|
||||
src/bundle.cpp
|
||||
@ -41,13 +50,15 @@ set(dcc_SOURCES
|
||||
src/control.cpp
|
||||
src/dataflow.cpp
|
||||
src/disassem.cpp
|
||||
src/DccFrontend.cpp
|
||||
src/error.cpp
|
||||
src/fixwild.cpp
|
||||
src/frontend.cpp
|
||||
src/graph.cpp
|
||||
src/hlicode.cpp
|
||||
src/hltype.cpp
|
||||
src/machine_x86.cpp
|
||||
src/icode.cpp
|
||||
src/RegisterNode
|
||||
src/idioms.cpp
|
||||
src/idioms/idiom1.cpp
|
||||
src/idioms/arith_idioms.cpp
|
||||
@ -58,8 +69,8 @@ set(dcc_SOURCES
|
||||
src/idioms/shift_idioms.cpp
|
||||
src/idioms/xor_idioms.cpp
|
||||
src/locident.cpp
|
||||
src/liveness_set.cpp
|
||||
src/parser.cpp
|
||||
src/perfhlib.cpp
|
||||
src/procs.cpp
|
||||
src/project.cpp
|
||||
src/Procedure.cpp
|
||||
@ -69,11 +80,17 @@ set(dcc_SOURCES
|
||||
src/symtab.cpp
|
||||
src/udm.cpp
|
||||
src/BasicBlock.cpp
|
||||
src/dcc_interface.cpp
|
||||
)
|
||||
set(dcc_SOURCES
|
||||
src/dcc.cpp
|
||||
)
|
||||
set(dcc_HEADERS
|
||||
include/ast.h
|
||||
include/bundle.h
|
||||
include/BinaryImage.h
|
||||
include/DccFrontend.h
|
||||
include/Enums.h
|
||||
include/dcc.h
|
||||
include/disassem.h
|
||||
include/dosdcc.h
|
||||
@ -92,7 +109,7 @@ set(dcc_HEADERS
|
||||
include/idioms/shift_idioms.h
|
||||
include/idioms/xor_idioms.h
|
||||
include/locident.h
|
||||
include/perfhlib.h
|
||||
include/CallConvention.h
|
||||
include/project.h
|
||||
include/scanner.h
|
||||
include/state.h
|
||||
@ -101,14 +118,25 @@ set(dcc_HEADERS
|
||||
include/Procedure.h
|
||||
include/StackFrame.h
|
||||
include/BasicBlock.h
|
||||
include/dcc_interface.h
|
||||
|
||||
)
|
||||
|
||||
SOURCE_GROUP(Source FILES ${dcc_SOURCES})
|
||||
SOURCE_GROUP(Headers FILES ${dcc_HEADERS})
|
||||
|
||||
ADD_LIBRARY(dcc_lib STATIC ${dcc_LIB_SOURCES} ${dcc_HEADERS})
|
||||
qt5_use_modules(dcc_lib Core)
|
||||
#cotire(dcc_lib)
|
||||
|
||||
ADD_EXECUTABLE(dcc_original ${dcc_SOURCES} ${dcc_HEADERS})
|
||||
TARGET_LINK_LIBRARIES(dcc_original disasm_s ${REQ_LLVM_LIBRARIES})
|
||||
ADD_DEPENDENCIES(dcc_original dcc_lib)
|
||||
TARGET_LINK_LIBRARIES(dcc_original dcc_lib dcc_hash disasm_s)
|
||||
qt5_use_modules(dcc_original Core)
|
||||
SET_PROPERTY(TARGET dcc_original PROPERTY CXX_STANDARD 11)
|
||||
SET_PROPERTY(TARGET dcc_original PROPERTY CXX_STANDARD_REQUIRED ON)
|
||||
#ADD_SUBDIRECTORY(gui)
|
||||
if(dcc_build_tests)
|
||||
ADD_SUBDIRECTORY(src)
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
3392
CMakeScripts/cotire.cmake
Normal file
3392
CMakeScripts/cotire.cmake
Normal file
File diff suppressed because it is too large
Load Diff
339
LICENSE
Normal file
339
LICENSE
Normal file
@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
129
Readme.md
Normal file
129
Readme.md
Normal file
@ -0,0 +1,129 @@
|
||||
I've fixed many issues in this codebase, among other things - memory reallocation during decompilation.
|
||||
|
||||
To reflect those fixes, I've edited the original readme a bit.
|
||||
|
||||
* * *
|
||||
dcc Distribution
|
||||
================
|
||||
|
||||
[](https://gitter.im/nemerle/dcc?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
The code provided in this distribution is (C) by their authors:
|
||||
- Cristina Cifuentes (most of dcc code)
|
||||
- Mike van Emmerik (signatures and prototype code)
|
||||
- Jeff Ledermann (some disassembly code)
|
||||
|
||||
and is provided "as is". Additional contributor list is available
|
||||
[on GitHub](https://github.com/nemerle/dcc/graphs/contributors).
|
||||
|
||||
The following files are included in the dccoo.tar.gz distribution:
|
||||
- dcc.zip (dcc.exe DOS program, 1995)
|
||||
- dccsrc.zip (source code *.c, *.h for dcc, 1993-1994)
|
||||
- dcc32.zip (dcc_oo.exe 32 bit console (Win95/Win-NT) program, 1997)
|
||||
- dccsrcoo.zip (source code *.cpp, *.h for "oo" dcc, 1993-1997)
|
||||
- dccbsig.zip (library signatures for Borland C compilers, 1994)
|
||||
- dccmsig.zip (library signatures for Microsoft C compilers, 1994)
|
||||
- dcctpsig.zip (library signatures for Turbo Pascal compilers, 1994)
|
||||
- dcclibs.dat (prototype file for C headers, 1994)
|
||||
- test.zip (sample test files: *.c *.exe *.b, 1993-1996)
|
||||
- makedsig.zip (creates a .sig file from a .lib C file, 1994)
|
||||
- makedstp.zip (creates a .sig file from a Pascal library file, 1994)
|
||||
- readsig.zip (reads signatures in a .sig file, 1994)
|
||||
- dispsrch.zip (displays the name of a function given a signature, 1994)
|
||||
- parsehdr.zip (generates a prototype file (dcclibs.dat) from C *.h files, 1994)
|
||||
|
||||
Note that the dcc_oo.exe program (in dcc32.zip) is a 32 bit program,
|
||||
so it won't work under Windows 3.1. Also, it is a console mode program,
|
||||
meaning that it has to be run in the "Command Prompt" window (sometimes
|
||||
known as the "Dos Box"). It is not a GUI program.
|
||||
|
||||
The following files are included in the test.zip file: fibo,
|
||||
benchsho, benchlng, benchfn, benchmul, byteops, intops, longops,
|
||||
max, testlong, matrixmu, strlen, dhamp.
|
||||
The version of dcc included in this distribution (dccsrcoo.zip and
|
||||
dcc32.exe) is a bit better than the first release, but it is still
|
||||
broken in some cases, and we do not have the time to work in this
|
||||
project at present so we cannot provide any changes.
|
||||
Comments on individual files:
|
||||
- fibo (fibonacci): the small model (fibos.exe) decompiles correctly,
|
||||
the large model (fibol.exe) expects an extra argument for
|
||||
`scanf()`. This argument is the segment and is not displayed.
|
||||
- benchsho: the first `scanf()` takes loc0 as an argument. This is
|
||||
part of a long variable, but dcc does not have any clue at that
|
||||
stage that the stack offset pushed on the stack is to be used
|
||||
as a long variable rather than an integer variable.
|
||||
- benchlng: as part of the `main()` code, `LO(loc1) | HI(loc1)` should
|
||||
be displayed instead of `loc3 | loc9`. These two integer variables
|
||||
are equivalent to the one long loc1 variable.
|
||||
- benchfn: see benchsho.
|
||||
- benchmul: see benchsho.
|
||||
- byteops: decompiles correctly.
|
||||
- intops: the du analysis for `DIV` and `MOD` is broken. dcc currently
|
||||
generates code for a long and an integer temporary register that
|
||||
were used as part of the analysis.
|
||||
- longops: decompiles correctly.
|
||||
- max: decompiles correctly.
|
||||
- testlong: this example decompiles correctly given the algorithms
|
||||
implemented in dcc. However, it shows that when long variables
|
||||
are defined and used as integers (or long) without giving dcc
|
||||
any hint that this is happening, the variable will be treated as
|
||||
two integer variables. This is due to the fact that the assembly
|
||||
code is in terms of integer registers, and long registers are not
|
||||
available in 80286, so a long variable is equivalent to two integer
|
||||
registers. dcc only knows of this through idioms such as add two
|
||||
long variables.
|
||||
- matrixmu: decompiles correctly. Shows that arrays are not supported
|
||||
in dcc.
|
||||
- strlen: decompiles correctly. Shows that pointers are partially
|
||||
supported by dcc.
|
||||
- dhamp: this program has far more data types than what dcc recognizes
|
||||
at present.
|
||||
|
||||
Our thanks to Gary Shaffstall for some debugging work. Current bugs
|
||||
are:
|
||||
- [ ] if the code generated in the one line is too long, the (static)
|
||||
buffer used for that line is clobbered. Solution: make the buffer
|
||||
larger (currently 200 chars).
|
||||
- [ ] the large memory model problem & `scanf()`
|
||||
- [ ] dcc's error message shows a p option available which doesn't
|
||||
exist, and doesn't show an i option which exists.
|
||||
- [x] there is a nasty problem whereby some arrays can get reallocated
|
||||
to a new address, and some pointers can become invalid. This mainly
|
||||
tends to happen to larger executable files. A major rewrite will
|
||||
probably be required to fix this.
|
||||
|
||||
For more information refer to the thesis "Reverse Compilation
|
||||
Techniques" by Cristina Cifuentes, Queensland University of
|
||||
Technology, 1994, and the dcc home page:
|
||||
http://www.it.uq.edu.au/groups/csm/dcc_readme.html
|
||||
|
||||
Please note that the executable version of dcc provided in this
|
||||
distribution does not necessarily match the source code provided,
|
||||
some changes were done without us keeping track of every change.
|
||||
|
||||
Using dcc
|
||||
---------
|
||||
|
||||
Here is a very brief summary of switches for dcc:
|
||||
|
||||
* `a1`, `a2`: assembler output, before and after re-ordering of input code
|
||||
* `c`: Attempt to follow control through indirect call instructions
|
||||
* `i`: Enter interactive disassembler
|
||||
* `m`: Memory map
|
||||
* `s`: Statistics summary
|
||||
* `v`, `V`: verbose (and Very verbose)
|
||||
* `o` filename: Use filename as assembler output file
|
||||
|
||||
If dcc encounters illegal instructions, it will attempt to enter the so called
|
||||
interactive disassembler. The idea of this was to allow commands to fix the
|
||||
problem so that dcc could continue, but no such changes are implemented
|
||||
as yet. (Note: the Unix versions do not have the interactive disassembler). If
|
||||
you get into this, you can get out of it by pressing `^X` (control-X). Once dcc
|
||||
has entered the interactive disassembler, however, there is little chance that
|
||||
it will recover and produce useful output.
|
||||
|
||||
If dcc loads the signature file `dccxxx.sig`, this means that it has not
|
||||
recognised the compiler library used. You can place the signatures in a
|
||||
different direcory to where you are working if you set the DCC environment
|
||||
variable to point to their path. Note that if dcc can't find its signature
|
||||
files, it will be severely handicapped.
|
||||
@ -1,6 +1,7 @@
|
||||
#!/bin/bash
|
||||
cd bld
|
||||
make -j5
|
||||
cd ..
|
||||
#cd bld
|
||||
#make -j5
|
||||
#cd ..
|
||||
mkdir -p tests/outputs
|
||||
./test_use_base.sh
|
||||
./regression_tester.rb ./bld/dcc_original -s -c 2>stderr >stdout; diff tests/prev/ tests/outputs/
|
||||
./regression_tester.rb ./dcc_original -s -c 2>stderr >stdout; diff -wB tests/prev/ tests/outputs/
|
||||
|
||||
7
common/CMakeLists.txt
Normal file
7
common/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
set(SRC
|
||||
perfhlib.cpp
|
||||
perfhlib.h
|
||||
PatternCollector.h
|
||||
|
||||
)
|
||||
add_library(dcc_hash STATIC ${SRC})
|
||||
82
common/PatternCollector.h
Normal file
82
common/PatternCollector.h
Normal file
@ -0,0 +1,82 @@
|
||||
#ifndef PATTERNCOLLECTOR
|
||||
#define PATTERNCOLLECTOR
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
|
||||
#define SYMLEN 16 /* Number of chars in the symbol name, incl null */
|
||||
#define PATLEN 23 /* Number of bytes in the pattern part */
|
||||
|
||||
struct HASHENTRY
|
||||
{
|
||||
char name[SYMLEN]; /* The symbol name */
|
||||
uint8_t pat [PATLEN]; /* The pattern */
|
||||
uint16_t offset; /* Offset (needed temporarily) */
|
||||
};
|
||||
|
||||
struct PatternCollector {
|
||||
uint8_t buf[100], bufSave[7]; /* Temp buffer for reading the file */
|
||||
uint16_t readShort(FILE *f)
|
||||
{
|
||||
uint8_t b1, b2;
|
||||
|
||||
if (fread(&b1, 1, 1, f) != 1)
|
||||
{
|
||||
printf("Could not read\n");
|
||||
exit(11);
|
||||
}
|
||||
if (fread(&b2, 1, 1, f) != 1)
|
||||
{
|
||||
printf("Could not read\n");
|
||||
exit(11);
|
||||
}
|
||||
return (b2 << 8) + b1;
|
||||
}
|
||||
|
||||
void grab(FILE *f,int n)
|
||||
{
|
||||
if (fread(buf, 1, n, f) != (size_t)n)
|
||||
{
|
||||
printf("Could not read\n");
|
||||
exit(11);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t readByte(FILE *f)
|
||||
{
|
||||
uint8_t b;
|
||||
|
||||
if (fread(&b, 1, 1, f) != 1)
|
||||
{
|
||||
printf("Could not read\n");
|
||||
exit(11);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
uint16_t readWord(FILE *fl)
|
||||
{
|
||||
uint8_t b1, b2;
|
||||
|
||||
b1 = readByte(fl);
|
||||
b2 = readByte(fl);
|
||||
|
||||
return b1 + (b2 << 8);
|
||||
}
|
||||
|
||||
/* Called by map(). Return the i+1th key in *pKeys */
|
||||
uint8_t *getKey(int i)
|
||||
{
|
||||
return keys[i].pat;
|
||||
}
|
||||
/* Display key i */
|
||||
void dispKey(int i)
|
||||
{
|
||||
printf("%s", keys[i].name);
|
||||
}
|
||||
std::vector<HASHENTRY> keys; /* array of keys */
|
||||
virtual int readSyms(FILE *f)=0;
|
||||
};
|
||||
#endif // PATTERNCOLLECTOR
|
||||
|
||||
438
common/perfhlib.cpp
Normal file
438
common/perfhlib.cpp
Normal file
@ -0,0 +1,438 @@
|
||||
/*
|
||||
*$Log: perfhlib.c,v $
|
||||
* Revision 1.5 93/09/29 14:45:02 emmerik
|
||||
* Oops, didn't do the casts last check in
|
||||
*
|
||||
* Revision 1.4 93/09/29 14:41:45 emmerik
|
||||
* Added casts to mod instructions to keep the SVR4 compiler happy
|
||||
*
|
||||
*
|
||||
* Perfect hashing function library. Contains functions to generate perfect
|
||||
* hashing functions
|
||||
*/
|
||||
#include "perfhlib.h"
|
||||
#include "PatternCollector.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <cassert>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
/* Private data structures */
|
||||
|
||||
//static int NumEntry; /* Number of entries in the hash table (# keys) */
|
||||
//static int EntryLen; /* Size (bytes) of each entry (size of keys) */
|
||||
//static int SetSize; /* Size of the char set */
|
||||
//static char SetMin; /* First char in the set */
|
||||
//static int NumVert; /* c times NumEntry */
|
||||
|
||||
//static uint16_t *T1base, *T2base; /* Pointers to start of T1, T2 */
|
||||
static uint16_t *T1, *T2; /* Pointers to T1[i], T2[i] */
|
||||
|
||||
static int *graphNode; /* The array of edges */
|
||||
static int *graphNext; /* Linked list of edges */
|
||||
static int *graphFirst;/* First edge at a vertex */
|
||||
|
||||
|
||||
static int numEdges; /* An edge counter */
|
||||
static bool *visited; /* Array of bools: whether visited */
|
||||
static bool *deleted; /* Array of bools: whether deleted */
|
||||
|
||||
/* Private prototypes */
|
||||
static void duplicateKeys(int v1, int v2);
|
||||
|
||||
void PerfectHash::setHashParams(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin,
|
||||
int _NumVert)
|
||||
{
|
||||
/* These parameters are stored in statics so as to obviate the need for
|
||||
passing all these (or defererencing pointers) for every call to hash()
|
||||
*/
|
||||
|
||||
NumEntry = _NumEntry;
|
||||
EntryLen = _EntryLen;
|
||||
SetSize = _SetSize;
|
||||
SetMin = _SetMin;
|
||||
NumVert = _NumVert;
|
||||
|
||||
/* Allocate the variable sized tables etc */
|
||||
if ((T1base = (uint16_t *)malloc(EntryLen * SetSize * sizeof(uint16_t))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
if ((T2base = (uint16_t *)malloc(EntryLen * SetSize * sizeof(uint16_t))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
|
||||
if ((graphNode = (int *)malloc((NumEntry*2 + 1) * sizeof(int))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
if ((graphNext = (int *)malloc((NumEntry*2 + 1) * sizeof(int))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
if ((graphFirst = (int *)malloc((NumVert + 1) * sizeof(int))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
|
||||
if ((g = (short *)malloc((NumVert+1) * sizeof(short))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
if ((visited = (bool *)malloc((NumVert+1) * sizeof(bool))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
if ((deleted = (bool *)malloc((NumEntry+1) * sizeof(bool))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
return;
|
||||
|
||||
BadAlloc:
|
||||
printf("Could not allocate memory\n");
|
||||
hashCleanup();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void PerfectHash::hashCleanup(void)
|
||||
{
|
||||
/* Free the storage for variable sized tables etc */
|
||||
if (T1base) free(T1base);
|
||||
if (T2base) free(T2base);
|
||||
if (graphNode) free(graphNode);
|
||||
if (graphNext) free(graphNext);
|
||||
if (graphFirst) free(graphFirst);
|
||||
if (g) free(g);
|
||||
if (visited) free(visited);
|
||||
if (deleted) free(deleted);
|
||||
}
|
||||
|
||||
void PerfectHash::map(PatternCollector *collector)
|
||||
{
|
||||
m_collector = collector;
|
||||
assert(nullptr!=collector);
|
||||
int i, j, c;
|
||||
uint16_t f1, f2;
|
||||
bool cycle;
|
||||
uint8_t *keys;
|
||||
|
||||
c = 0;
|
||||
|
||||
do
|
||||
{
|
||||
initGraph();
|
||||
cycle = false;
|
||||
|
||||
/* Randomly generate T1 and T2 */
|
||||
for (i=0; i < SetSize*EntryLen; i++)
|
||||
{
|
||||
T1base[i] = rand() % NumVert;
|
||||
T2base[i] = rand() % NumVert;
|
||||
}
|
||||
|
||||
for (i=0; i < NumEntry; i++)
|
||||
{
|
||||
f1 = 0; f2 = 0;
|
||||
keys = m_collector->getKey(i);
|
||||
for (j=0; j < EntryLen; j++)
|
||||
{
|
||||
T1 = T1base + j * SetSize;
|
||||
T2 = T2base + j * SetSize;
|
||||
f1 += T1[keys[j] - SetMin];
|
||||
f2 += T2[keys[j] - SetMin];
|
||||
}
|
||||
f1 %= (uint16_t)NumVert;
|
||||
f2 %= (uint16_t)NumVert;
|
||||
if (f1 == f2)
|
||||
{
|
||||
/* A self loop. Reject! */
|
||||
printf("Self loop on vertex %d!\n", f1);
|
||||
cycle = true;
|
||||
break;
|
||||
}
|
||||
addToGraph(numEdges++, f1, f2);
|
||||
}
|
||||
if (cycle or (cycle = isCycle())) /* OK - is there a cycle? */
|
||||
{
|
||||
printf("Iteration %d\n", ++c);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (/* there is a cycle */ 1);
|
||||
|
||||
}
|
||||
|
||||
/* Initialise the graph */
|
||||
void PerfectHash::initGraph()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=1; i <= NumVert; i++)
|
||||
{
|
||||
graphFirst[i] = 0;
|
||||
}
|
||||
|
||||
for (i= -NumEntry; i <= NumEntry; i++)
|
||||
{
|
||||
/* No need to init graphNode[] as they will all be filled by successive
|
||||
calls to addToGraph() */
|
||||
graphNext[NumEntry+i] = 0;
|
||||
}
|
||||
|
||||
numEdges = 0;
|
||||
}
|
||||
|
||||
/* Add an edge e between vertices v1 and v2 */
|
||||
/* e, v1, v2 are 0 based */
|
||||
void PerfectHash::addToGraph(int e, int v1, int v2)
|
||||
{
|
||||
e++; v1++; v2++; /* So much more convenient */
|
||||
|
||||
graphNode[NumEntry+e] = v2; /* Insert the edge information */
|
||||
graphNode[NumEntry-e] = v1;
|
||||
|
||||
graphNext[NumEntry+e] = graphFirst[v1]; /* Insert v1 to list of alphas */
|
||||
graphFirst[v1]= e;
|
||||
graphNext[NumEntry-e] = graphFirst[v2]; /* Insert v2 to list of omegas */
|
||||
graphFirst[v2]= -e;
|
||||
|
||||
}
|
||||
|
||||
bool PerfectHash::DFS(int parentE, int v)
|
||||
{
|
||||
int e, w;
|
||||
|
||||
/* Depth first search of the graph, starting at vertex v, looking for
|
||||
cycles. parent and v are origin 1. Note parent is an EDGE,
|
||||
not a vertex */
|
||||
|
||||
visited[v] = true;
|
||||
|
||||
/* For each e incident with v .. */
|
||||
for (e = graphFirst[v]; e; e = graphNext[NumEntry+e])
|
||||
{
|
||||
uint8_t *key1;
|
||||
|
||||
if (deleted[abs(e)])
|
||||
{
|
||||
/* A deleted key. Just ignore it */
|
||||
continue;
|
||||
}
|
||||
key1 = m_collector->getKey(abs(e)-1);
|
||||
w = graphNode[NumEntry+e];
|
||||
if (visited[w])
|
||||
{
|
||||
/* Did we just come through this edge? If so, ignore it. */
|
||||
if (abs(e) != abs(parentE))
|
||||
{
|
||||
/* There is a cycle in the graph. There is some subtle code here
|
||||
to work around the distinct possibility that there may be
|
||||
duplicate keys. Duplicate keys will always cause unit
|
||||
cycles, since f1 and f2 (used to select v and w) will be the
|
||||
same for both. The edges (representing an index into the
|
||||
array of keys) are distinct, but the key values are not.
|
||||
The logic is as follows: for the candidate edge e, check to
|
||||
see if it terminates in the parent vertex. If so, we test
|
||||
the keys associated with e and the parent, and if they are
|
||||
the same, we can safely ignore e for the purposes of cycle
|
||||
detection, since edge e adds nothing to the cycle. Cycles
|
||||
involving v, w, and e0 will still be found. The parent
|
||||
edge was not similarly eliminated because at the time when
|
||||
it was a candidate, v was not yet visited.
|
||||
We still have to remove the key from further consideration,
|
||||
since each edge is visited twice, but with a different
|
||||
parent edge each time.
|
||||
*/
|
||||
/* We save some stack space by calculating the parent vertex
|
||||
for these relatively few cases where it is needed */
|
||||
int parentV = graphNode[NumEntry-parentE];
|
||||
|
||||
if (w == parentV)
|
||||
{
|
||||
uint8_t *key2;
|
||||
|
||||
key2=m_collector->getKey(abs(parentE)-1);
|
||||
if (memcmp(key1, key2, EntryLen) == 0)
|
||||
{
|
||||
printf("Duplicate keys with edges %d and %d (",
|
||||
e, parentE);
|
||||
m_collector->dispKey(abs(e)-1);
|
||||
printf(" & ");
|
||||
m_collector->dispKey(abs(parentE)-1);
|
||||
printf(")\n");
|
||||
deleted[abs(e)] = true; /* Wipe the key */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* A genuine (unit) cycle. */
|
||||
printf("There is a unit cycle involving vertex %d and edge %d\n", v, e);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We have reached a previously visited vertex not the
|
||||
parent. Therefore, we have uncovered a genuine cycle */
|
||||
printf("There is a cycle involving vertex %d and edge %d\n", v, e);
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* Not yet seen. Traverse it */
|
||||
{
|
||||
if (DFS(e, w))
|
||||
{
|
||||
/* Cycle found deeper down. Exit */
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PerfectHash::isCycle(void)
|
||||
{
|
||||
int v, e;
|
||||
|
||||
for (v=1; v <= NumVert; v++)
|
||||
{
|
||||
visited[v] = false;
|
||||
}
|
||||
for (e=1; e <= NumEntry; e++)
|
||||
{
|
||||
deleted[e] = false;
|
||||
}
|
||||
for (v=1; v <= NumVert; v++)
|
||||
{
|
||||
if (not visited[v])
|
||||
{
|
||||
if (DFS(-32767, v))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PerfectHash::traverse(int u)
|
||||
{
|
||||
int w, e;
|
||||
|
||||
visited[u] = true;
|
||||
/* Find w, the neighbours of u, by searching the edges e associated with u */
|
||||
e = graphFirst[1+u];
|
||||
while (e)
|
||||
{
|
||||
w = graphNode[NumEntry+e]-1;
|
||||
if (not visited[w])
|
||||
{
|
||||
g[w] = (abs(e)-1 - g[u]) % NumEntry;
|
||||
if (g[w] < 0) g[w] += NumEntry; /* Keep these positive */
|
||||
traverse(w);
|
||||
}
|
||||
e = graphNext[NumEntry+e];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void PerfectHash::assign(void)
|
||||
{
|
||||
int v;
|
||||
|
||||
|
||||
for (v=0; v < NumVert; v++)
|
||||
{
|
||||
g[v] = 0; /* g is sparse; leave the gaps 0 */
|
||||
visited[v] = false;
|
||||
}
|
||||
|
||||
for (v=0; v < NumVert; v++)
|
||||
{
|
||||
if (not visited[v])
|
||||
{
|
||||
g[v] = 0;
|
||||
traverse(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int PerfectHash::hash(uint8_t *string)
|
||||
{
|
||||
uint16_t u, v;
|
||||
int j;
|
||||
|
||||
u = 0;
|
||||
for (j=0; j < EntryLen; j++)
|
||||
{
|
||||
T1 = T1base + j * SetSize;
|
||||
u += T1[string[j] - SetMin];
|
||||
}
|
||||
u %= NumVert;
|
||||
|
||||
v = 0;
|
||||
for (j=0; j < EntryLen; j++)
|
||||
{
|
||||
T2 = T2base + j * SetSize;
|
||||
v += T2[string[j] - SetMin];
|
||||
}
|
||||
v %= NumVert;
|
||||
|
||||
return (g[u] + g[v]) % NumEntry;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void dispRecord(int i);
|
||||
|
||||
void
|
||||
duplicateKeys(int v1, int v2)
|
||||
{
|
||||
int i, j;
|
||||
uint8_t *keys;
|
||||
int u, v;
|
||||
|
||||
v1--; v2--; /* These guys are origin 1 */
|
||||
|
||||
printf("Duplicate keys:\n");
|
||||
|
||||
for (i=0; i < NumEntry; i++)
|
||||
{
|
||||
getKey(i, &keys);
|
||||
u = 0;
|
||||
for (j=0; j < EntryLen; j++)
|
||||
{
|
||||
T1 = T1base + j * SetSize;
|
||||
u += T1[keys[j] - SetMin];
|
||||
}
|
||||
u %= NumVert;
|
||||
if ((u != v1) and (u != v2)) continue;
|
||||
|
||||
v = 0;
|
||||
for (j=0; j < EntryLen; j++)
|
||||
{
|
||||
T2 = T2base + j * SetSize;
|
||||
v += T2[keys[j] - SetMin];
|
||||
}
|
||||
v %= NumVert;
|
||||
|
||||
if ((v == v2) or (v == v1))
|
||||
{
|
||||
printf("Entry #%d key: ", i+1);
|
||||
for (j=0; j < EntryLen; j++) printf("%02X ", keys[j]);
|
||||
printf("\n");
|
||||
dispRecord(i+1);
|
||||
}
|
||||
}
|
||||
exit(1);
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
38
common/perfhlib.h
Normal file
38
common/perfhlib.h
Normal file
@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
/** Perfect hashing function library. Contains functions to generate perfect
|
||||
hashing functions */
|
||||
struct PatternCollector;
|
||||
struct PerfectHash {
|
||||
uint16_t *T1base;
|
||||
uint16_t *T2base; /* Pointers to start of T1, T2 */
|
||||
short *g; /* g[] */
|
||||
|
||||
int NumEntry; /* Number of entries in the hash table (# keys) */
|
||||
int EntryLen; /* Size (bytes) of each entry (size of keys) */
|
||||
int SetSize; /* Size of the char set */
|
||||
char SetMin; /* First char in the set */
|
||||
int NumVert; /* c times NumEntry */
|
||||
/** Set the parameters for the hash table */
|
||||
void setHashParams(int _numEntry, int _entryLen, int _setSize, char _setMin, int _numVert);
|
||||
|
||||
public:
|
||||
void map(PatternCollector * collector); /* Part 1 of creating the tables */
|
||||
void hashCleanup(); /* Frees memory allocated by setHashParams() */
|
||||
void assign(); /* Part 2 of creating the tables */
|
||||
int hash(uint8_t *string); /* Hash the string to an int 0 .. NUMENTRY-1 */
|
||||
const uint16_t *readT1(void) const { return T1base; }
|
||||
const uint16_t *readT2(void) const { return T2base; }
|
||||
const uint16_t *readG(void) const { return (uint16_t *)g; }
|
||||
uint16_t *readT1(void){ return T1base; }
|
||||
uint16_t *readT2(void){ return T2base; }
|
||||
uint16_t *readG(void) { return (uint16_t *)g; }
|
||||
private:
|
||||
void initGraph();
|
||||
void addToGraph(int e, int v1, int v2);
|
||||
bool isCycle();
|
||||
bool DFS(int parentE, int v);
|
||||
void traverse(int u);
|
||||
PatternCollector *m_collector; /* used to retrieve the keys */
|
||||
|
||||
};
|
||||
@ -1,3 +1,4 @@
|
||||
#!/bin/bash
|
||||
makedir -p tests/outputs
|
||||
./test_use_all.sh
|
||||
./regression_tester.rb ./bld/dcc_original -s -c 2>stderr >stdout; diff tests/prev/ tests/outputs/
|
||||
./regression_tester.rb ./dcc_original -s -c 2>stderr >stdout; diff -wB tests/prev/ tests/outputs/
|
||||
|
||||
@ -3,9 +3,7 @@
|
||||
#include <vector>
|
||||
#include <bitset>
|
||||
#include <string>
|
||||
#include <llvm/ADT/ilist.h>
|
||||
#include <llvm/ADT/ilist_node.h>
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include "icode.h"
|
||||
#include "types.h"
|
||||
#include "graph.h"
|
||||
@ -16,24 +14,28 @@ class CIcodeRec;
|
||||
struct BB;
|
||||
struct LOCAL_ID;
|
||||
struct interval;
|
||||
|
||||
//TODO: consider default address value -> INVALID
|
||||
struct TYPEADR_TYPE
|
||||
{
|
||||
uint32_t ip; /* Out edge icode address */
|
||||
BB * BBptr; /* Out edge pointer to next BB */
|
||||
interval *intPtr; /* Out edge ptr to next interval*/
|
||||
TYPEADR_TYPE(uint32_t addr=0) : ip(addr),BBptr(nullptr),intPtr(nullptr)
|
||||
{}
|
||||
TYPEADR_TYPE(interval *v) : ip(0),BBptr(nullptr),intPtr(v)
|
||||
{}
|
||||
};
|
||||
|
||||
struct BB : public llvm::ilist_node<BB>
|
||||
struct BB
|
||||
{
|
||||
friend struct Function;
|
||||
private:
|
||||
BB(const BB&);
|
||||
BB() : nodeType(0),traversed(DFS_NONE),
|
||||
numHlIcodes(0),flg(0),
|
||||
inEdges(0),
|
||||
edges(0),beenOnH(0),inEdgeCount(0),reachingInt(0),
|
||||
inInterval(0),correspInt(0),liveUse(0),def(0),liveIn(0),liveOut(0),
|
||||
dfsFirstNum(0),dfsLastNum(0),immedDom(0),ifFollow(0),loopType(0),latchNode(0),
|
||||
inInterval(0),correspInt(0),
|
||||
dfsFirstNum(0),dfsLastNum(0),immedDom(0),ifFollow(0),loopType(NO_TYPE),latchNode(0),
|
||||
numBackEdges(0),loopHead(0),loopFollow(0),caseHead(0),caseTail(0),index(0)
|
||||
{
|
||||
|
||||
@ -41,6 +43,7 @@ private:
|
||||
//friend class SymbolTableListTraits<BB, Function>;
|
||||
typedef boost::iterator_range<iICODE> rCODE;
|
||||
rCODE instructions;
|
||||
rCODE &my_range() {return instructions;}
|
||||
|
||||
public:
|
||||
struct ValidFunctor
|
||||
@ -54,10 +57,10 @@ public:
|
||||
ICODE &front();
|
||||
ICODE &back();
|
||||
size_t size();
|
||||
uint8_t nodeType; /* Type of node */
|
||||
eDFS traversed; /* last traversal id is held here traversed yet? */
|
||||
int numHlIcodes; /* No. of high-level icodes */
|
||||
uint32_t flg; /* BB flags */
|
||||
uint8_t nodeType; /* Type of node */
|
||||
eDFS traversed; /* last traversal id is held here traversed yet? */
|
||||
int numHlIcodes; /* No. of high-level icodes */
|
||||
uint32_t flg; /* BB flags */
|
||||
|
||||
/* In edges and out edges */
|
||||
std::vector<BB *> inEdges; // does not own held pointers
|
||||
@ -72,36 +75,31 @@ public:
|
||||
interval *inInterval; /* Node's interval */
|
||||
|
||||
/* For derived sequence construction */
|
||||
interval *correspInt; /* Corresponding interval in
|
||||
* derived graph Gi-1 */
|
||||
|
||||
/* For live register analysis
|
||||
* LiveIn(b) = LiveUse(b) U (LiveOut(b) - Def(b)) */
|
||||
std::bitset<32> liveUse; /* LiveUse(b) */
|
||||
std::bitset<32> def; /* Def(b) */
|
||||
std::bitset<32> liveIn; /* LiveIn(b) */
|
||||
std::bitset<32> liveOut; /* LiveOut(b) */
|
||||
interval *correspInt; //!< Corresponding interval in derived graph Gi-1
|
||||
// For live register analysis
|
||||
// LiveIn(b) = LiveUse(b) U (LiveOut(b) - Def(b))
|
||||
LivenessSet liveUse; /* LiveUse(b) */
|
||||
LivenessSet def; /* Def(b) */
|
||||
LivenessSet liveIn; /* LiveIn(b) */
|
||||
LivenessSet liveOut; /* LiveOut(b) */
|
||||
|
||||
/* For structuring analysis */
|
||||
int dfsFirstNum; /* DFS #: first visit of node */
|
||||
int dfsLastNum; /* DFS #: last visit of node */
|
||||
int immedDom; /* Immediate dominator (dfsLast
|
||||
* index) */
|
||||
int immedDom; /* Immediate dominator (dfsLast index) */
|
||||
int ifFollow; /* node that ends the if */
|
||||
int loopType; /* Type of loop (if any) */
|
||||
eNodeHeaderType loopType; /* Type of loop (if any) */
|
||||
int latchNode; /* latching node of the loop */
|
||||
int numBackEdges; /* # of back edges */
|
||||
int loopHead; /* most nested loop head to which
|
||||
* thcis node belongs (dfsLast) */
|
||||
size_t numBackEdges; /* # of back edges */
|
||||
int loopHead; /* most nested loop head to which this node belongs (dfsLast) */
|
||||
int loopFollow; /* node that follows the loop */
|
||||
int caseHead; /* most nested case to which this
|
||||
node belongs (dfsLast) */
|
||||
int caseHead; /* most nested case to which this node belongs (dfsLast) */
|
||||
int caseTail; /* tail node for the case */
|
||||
|
||||
int index; /* Index, used in several ways */
|
||||
static BB * Create(void *ctx=0,const std::string &s="",Function *parent=0,BB *insertBefore=0);
|
||||
static BB * Create(int start, int ip, uint8_t nodeType, int numOutEdges, Function * parent);
|
||||
static BB * Create(iICODE start, iICODE fin, uint8_t _nodeType, int numOutEdges, Function *parent);
|
||||
static BB * CreateIntervalBB(Function *parent);
|
||||
static BB * Create(const rCODE &r, eBBKind _nodeType, Function *parent);
|
||||
void writeCode(int indLevel, Function *pProc, int *numLoc, int latchNode, int ifFollow);
|
||||
void mergeFallThrough(CIcodeRec &Icode);
|
||||
void dfsNumbering(std::vector<BB *> &dfsLast, int *first, int *last);
|
||||
@ -111,21 +109,26 @@ public:
|
||||
///
|
||||
const Function *getParent() const { return Parent; }
|
||||
Function *getParent() { return Parent; }
|
||||
void writeBB(std::ostream &ostr, int lev, Function *pProc, int *numLoc);
|
||||
void writeBB(QTextStream & ostr, int lev, Function *pProc, int *numLoc);
|
||||
BB * rmJMP(int marker, BB *pBB);
|
||||
void genDU1();
|
||||
int findBBExps(LOCAL_ID &locals, Function *f);
|
||||
void findBBExps(LOCAL_ID &locals, Function *f);
|
||||
bool valid() {return 0==(flg & INVALID_BB); }
|
||||
bool wasTraversedAtLevel(int l) const {return traversed==l;}
|
||||
ICODE * writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&latch, boolT &repCond);
|
||||
void addOutEdge(uint32_t ip) // TODO: fix this
|
||||
ICODE * writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&latch, bool &repCond);
|
||||
void addOutEdge(uint32_t ip) // TODO: fix this
|
||||
{
|
||||
edges[0].ip = ip;
|
||||
edges.push_back(TYPEADR_TYPE(ip));
|
||||
}
|
||||
void addOutEdgeInterval(interval *i) // TODO: fix this
|
||||
{
|
||||
edges.push_back(TYPEADR_TYPE(i));
|
||||
}
|
||||
|
||||
void RemoveUnusedDefs(eReg regi, int defRegIdx, iICODE picode);
|
||||
private:
|
||||
bool FindUseBeforeDef(eReg regi, int defRegIdx, iICODE start_at);
|
||||
void ProcessUseDefForFunc(eReg regi, int defRegIdx, iICODE picode);
|
||||
void ProcessUseDefForFunc(eReg regi, int defRegIdx, ICODE &picode);
|
||||
bool isEndOfPath(int latch_node_idx) const;
|
||||
Function *Parent;
|
||||
|
||||
|
||||
@ -1,20 +1,25 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
struct PROG /* Loaded program image parameters */
|
||||
{
|
||||
int16_t initCS;
|
||||
int16_t initIP; /* These are initial load values */
|
||||
int16_t initSS; /* Probably not of great interest */
|
||||
uint16_t initSP;
|
||||
bool fCOM; /* Flag set if COM program (else EXE)*/
|
||||
int cReloc; /* No. of relocation table entries */
|
||||
uint32_t * relocTable; /* Ptr. to relocation table */
|
||||
uint8_t * map; /* Memory bitmap ptr */
|
||||
int cProcs; /* Number of procedures so far */
|
||||
int offMain; /* The offset of the main() proc */
|
||||
uint16_t segMain; /* The segment of the main() proc */
|
||||
bool bSigs; /* True if signatures loaded */
|
||||
int cbImage; /* Length of image in bytes */
|
||||
uint8_t * Image; /* Allocated by loader to hold entire program image */
|
||||
uint16_t initCS=0;
|
||||
uint16_t initIP=0; /* These are initial load values */
|
||||
uint16_t initSS=0; /* Probably not of great interest */
|
||||
uint16_t initSP=0;
|
||||
bool fCOM=false; /* Flag set if COM program (else EXE)*/
|
||||
int cReloc=0; /* No. of relocation table entries */
|
||||
std::vector<uint32_t> relocTable; /* Ptr. to relocation table */
|
||||
uint8_t * map=nullptr; /* Memory bitmap ptr */
|
||||
int cProcs=0; /* Number of procedures so far */
|
||||
int offMain=0; /* The offset of the main() proc */
|
||||
uint16_t segMain=0; /* The segment of the main() proc */
|
||||
bool bSigs=false; /* True if signatures loaded */
|
||||
int cbImage=0; /* Length of image in bytes */
|
||||
uint8_t * Imagez=nullptr; /* Allocated by loader to hold entire program image */
|
||||
int addressingMode=0;
|
||||
public:
|
||||
const uint8_t *image() const {return Imagez;}
|
||||
void displayLoadInfo();
|
||||
};
|
||||
|
||||
|
||||
33
include/CallConvention.h
Normal file
33
include/CallConvention.h
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
#include "ast.h"
|
||||
|
||||
class QTextStream;
|
||||
|
||||
struct CConv {
|
||||
enum Type {
|
||||
eUnknown=0,
|
||||
eCdecl,
|
||||
ePascal
|
||||
};
|
||||
virtual void processHLI(Function *func, Expr *_exp, iICODE picode)=0;
|
||||
virtual void writeComments(QTextStream &)=0;
|
||||
static CConv * create(Type v);
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
struct C_CallingConvention : public CConv {
|
||||
virtual void processHLI(Function *func, Expr *_exp, iICODE picode);
|
||||
virtual void writeComments(QTextStream &);
|
||||
|
||||
private:
|
||||
int processCArg(Function *callee, Function *pProc, ICODE *picode, size_t numArgs);
|
||||
};
|
||||
struct Pascal_CallingConvention : public CConv {
|
||||
virtual void processHLI(Function *func, Expr *_exp, iICODE picode);
|
||||
virtual void writeComments(QTextStream &);
|
||||
};
|
||||
struct Unknown_CallingConvention : public CConv {
|
||||
void processHLI(Function *func, Expr *_exp, iICODE picode) {}
|
||||
virtual void writeComments(QTextStream &);
|
||||
};
|
||||
19
include/CallGraph.h
Normal file
19
include/CallGraph.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include "Procedure.h"
|
||||
/* CALL GRAPH NODE */
|
||||
struct CALL_GRAPH
|
||||
{
|
||||
ilFunction proc; /* Pointer to procedure in pProcList */
|
||||
std::vector<CALL_GRAPH *> outEdges; /* array of out edges */
|
||||
public:
|
||||
void write();
|
||||
CALL_GRAPH()
|
||||
{
|
||||
}
|
||||
public:
|
||||
void writeNodeCallGraph(int indIdx);
|
||||
bool insertCallGraph(ilFunction caller, ilFunction callee);
|
||||
bool insertCallGraph(Function *caller, ilFunction callee);
|
||||
void insertArc(ilFunction newProc);
|
||||
};
|
||||
//extern CALL_GRAPH * callGraph; /* Pointer to the head of the call graph */
|
||||
17
include/DccFrontend.h
Normal file
17
include/DccFrontend.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include <QObject>
|
||||
class Project;
|
||||
class DccFrontend : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
void LoadImage();
|
||||
void parse(Project &proj);
|
||||
std::string m_fname;
|
||||
public:
|
||||
explicit DccFrontend(QObject *parent = 0);
|
||||
bool FrontEnd(); /* frontend.c */
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
};
|
||||
@ -8,6 +8,7 @@ enum regType
|
||||
};
|
||||
enum condId
|
||||
{
|
||||
UNDEF=0,
|
||||
GLOB_VAR, /* global variable */
|
||||
REGISTER, /* register */
|
||||
LOCAL_VAR, /* negative disp */
|
||||
@ -31,19 +32,19 @@ enum condOp
|
||||
GREATER_EQUAL, /* >= */
|
||||
/* For general expressions */
|
||||
AND, /* & */
|
||||
OR, /* | */
|
||||
XOR, /* ^ */
|
||||
NOT, /* ~ */ /* 1's complement */
|
||||
ADD, /* + */
|
||||
SUB, /* - */
|
||||
MUL, /* * */
|
||||
DIV, /* / */
|
||||
SHR, /* >> */
|
||||
SHL, /* << */
|
||||
MOD, /* % */
|
||||
DBL_AND, /* && */
|
||||
DBL_OR, /* || */
|
||||
DUMMY /* */
|
||||
OR, /* | */
|
||||
XOR, /* ^ */
|
||||
NOT, /* ~ */ /* 1's complement */
|
||||
ADD, /* + */
|
||||
SUB, /* - */
|
||||
MUL, /* * */
|
||||
DIV, /* / */
|
||||
SHR, /* >> */
|
||||
SHL, /* << */
|
||||
MOD, /* % */
|
||||
DBL_AND, /* && */
|
||||
DBL_OR, /* || */
|
||||
DUMMY /* */
|
||||
};
|
||||
/* LOW_LEVEL operand location: source or destination */
|
||||
enum opLoc
|
||||
@ -57,48 +58,48 @@ enum opLoc
|
||||
enum eLLFlags
|
||||
{
|
||||
|
||||
B =0x0000001, /* uint8_t operands (value implicitly used) */
|
||||
I =0x0000002, /* Immed. source */
|
||||
NOT_HLL =0x0000004, /* Not HLL inst. */
|
||||
FLOAT_OP =0x0000008, /* ESC or WAIT */
|
||||
SEG_IMMED =0x0000010, /* Number is relocated segment value */
|
||||
IMPURE =0x0000020, /* Instruction modifies code */
|
||||
WORD_OFF =0x0000040, /* Inst has uint16_t offset ie.could be address */
|
||||
TERMINATES =0x0000080, /* Instruction terminates program */
|
||||
CASE =0x0000100, /* Label as case part of switch */
|
||||
SWITCH =0x0000200, /* Treat indirect JMP as switch stmt */
|
||||
TARGET =0x0000400, /* Jump target */
|
||||
SYNTHETIC =0x0000800, /* Synthetic jump instruction */
|
||||
NO_LABEL =0x0001000, /* Immed. jump cannot be linked to a label */
|
||||
NO_CODE =0x0002000, /* Hole in Icode array */
|
||||
SYM_USE =0x0004000, /* Instruction uses a symbol */
|
||||
SYM_DEF =0x0008000, /* Instruction defines a symbol */
|
||||
NO_SRC =0x0010000, /* Opcode takes no source */
|
||||
NO_OPS =0x0020000, /* Opcode takes no operands */
|
||||
IM_OPS =0x0040000, /* Opcode takes implicit operands */
|
||||
SRC_B =0x0080000, /* Source operand is uint8_t (dest is uint16_t) */
|
||||
HLL_LABEL =0x0100000, /* Icode has a high level language label */
|
||||
IM_DST =0x0200000, /* Implicit DST for opcode (SIGNEX) */
|
||||
IM_SRC =0x0400000, /* Implicit SRC for opcode (dx:ax) */
|
||||
IM_TMP_DST =0x0800000, /* Implicit rTMP DST for opcode (DIV/IDIV) */
|
||||
JMP_ICODE =0x1000000, /* Jmp dest immed.op converted to icode index */
|
||||
JX_LOOP =0x2000000, /* Cond jump is part of loop conditional exp */
|
||||
REST_STK =0x4000000 /* Stack needs to be restored after CALL */
|
||||
B = 0x0000001, /* uint8_t operands (value implicitly used) */
|
||||
I = 0x0000002, /* Immed. source */
|
||||
NOT_HLL = 0x0000004, /* Not HLL inst. */
|
||||
FLOAT_OP = 0x0000008, /* ESC or WAIT */
|
||||
SEG_IMMED = 0x0000010, /* Number is relocated segment value */
|
||||
IMPURE = 0x0000020, /* Instruction modifies code */
|
||||
WORD_OFF = 0x0000040, /* Inst has uint16_t offset ie.could be address */
|
||||
TERMINATES = 0x0000080, /* Instruction terminates program */
|
||||
CASE = 0x0000100, /* Label as case part of switch */
|
||||
SWITCH = 0x0000200, /* Treat indirect JMP as switch stmt */
|
||||
TARGET = 0x0000400, /* Jump target */
|
||||
SYNTHETIC = 0x0000800, /* Synthetic jump instruction */
|
||||
NO_LABEL = 0x0001000, /* Immed. jump cannot be linked to a label */
|
||||
NO_CODE = 0x0002000, /* Hole in Icode array */
|
||||
SYM_USE = 0x0004000, /* Instruction uses a symbol */
|
||||
SYM_DEF = 0x0008000, /* Instruction defines a symbol */
|
||||
NO_SRC = 0x0010000, /* Opcode takes no source */
|
||||
NO_OPS = 0x0020000, /* Opcode takes no operands */
|
||||
IM_OPS = 0x0040000, /* Opcode takes implicit operands */
|
||||
SRC_B = 0x0080000, /* Source operand is uint8_t (dest is uint16_t) */
|
||||
HLL_LABEL = 0x0100000, /* Icode has a high level language label */
|
||||
IM_DST = 0x0200000, /* Implicit DST for opcode (SIGNEX) */
|
||||
IM_SRC = 0x0400000, /* Implicit SRC for opcode (dx:ax) */
|
||||
IM_TMP_DST = 0x0800000, /* Implicit rTMP DST for opcode (DIV/IDIV) */
|
||||
JMP_ICODE = 0x1000000, /* Jmp dest immed.op converted to icode index */
|
||||
JX_LOOP = 0x2000000, /* Cond jump is part of loop conditional exp */
|
||||
REST_STK = 0x4000000 /* Stack needs to be restored after CALL */
|
||||
#define ICODEMASK 0x0FF00FF /* Masks off parser flags */
|
||||
};
|
||||
/* Types of icodes */
|
||||
enum icodeType
|
||||
{
|
||||
NOT_SCANNED = 0, // not even scanned yet
|
||||
LOW_LEVEL, // low-level icode
|
||||
HIGH_LEVEL // high-level icode
|
||||
NOT_SCANNED_ICODE = 0, // not even scanned yet
|
||||
LOW_LEVEL_ICODE, // low-level icode
|
||||
HIGH_LEVEL_ICODE // high-level icode
|
||||
};
|
||||
|
||||
|
||||
/* LOW_LEVEL icode opcodes */
|
||||
enum llIcode
|
||||
{
|
||||
//iINVALID,
|
||||
iINVALID=-1,
|
||||
iCBW, /* 0 */
|
||||
iAAA,
|
||||
iAAD,
|
||||
@ -176,7 +177,7 @@ enum llIcode
|
||||
iPOP,
|
||||
iPOPA,
|
||||
iPOPF,
|
||||
iPUSH,
|
||||
iPUSH, // 77
|
||||
iPUSHA,
|
||||
iPUSHF,
|
||||
iRCL, /* 80 */
|
||||
@ -216,6 +217,7 @@ enum condNodeType
|
||||
{
|
||||
UNKNOWN_OP=0,
|
||||
BOOLEAN_OP, /* condOps */
|
||||
|
||||
NEGATION, /* not (2's complement) */
|
||||
ADDRESSOF, /* addressOf (&) */
|
||||
DEREFERENCE, /* contents of (*) */
|
||||
@ -237,7 +239,7 @@ enum hlFirst
|
||||
/* HIGH_LEVEL icodes opcodes */
|
||||
enum hlIcode
|
||||
{
|
||||
HLI_INVALID,
|
||||
HLI_INVALID=0,
|
||||
HLI_ASSIGN, /* := */
|
||||
HLI_CALL, /* Call procedure */
|
||||
HLI_JCOND, /* Conditional jump */
|
||||
|
||||
@ -2,32 +2,29 @@
|
||||
#include "ast.h"
|
||||
#include "types.h"
|
||||
#include "machine_x86.h"
|
||||
|
||||
struct GlobalVariable;
|
||||
struct AstIdent;
|
||||
struct IDENTTYPE
|
||||
{
|
||||
friend struct GlobalVariable;
|
||||
friend struct Constant;
|
||||
friend struct AstIdent;
|
||||
protected:
|
||||
condId idType;
|
||||
regType regiType; /* for REGISTER only */
|
||||
public:
|
||||
condId type() {return idType;}
|
||||
void type(condId t) {idType=t;}
|
||||
union _idNode {
|
||||
int regiIdx; /* index into localId, REGISTER */
|
||||
int globIdx; /* index into symtab for GLOB_VAR */
|
||||
int localIdx; /* idx into localId, LOCAL_VAR */
|
||||
int paramIdx; /* idx into args symtab, PARAMS */
|
||||
int idxGlbIdx; /* idx into localId, GLOB_VAR_IDX */
|
||||
struct _kte
|
||||
{ /* for CONSTANT only */
|
||||
uint32_t kte; /* value of the constant */
|
||||
uint8_t size; /* #bytes size constant */
|
||||
} kte;
|
||||
uint32_t strIdx; /* idx into image, for STRING */
|
||||
int longIdx; /* idx into LOCAL_ID table, LONG_VAR*/
|
||||
struct _call { /* for FUNCTION only */
|
||||
Function *proc;
|
||||
STKFRAME *args;
|
||||
} call;
|
||||
struct { /* for OTHER; tmp struct */
|
||||
eReg seg; /* segment */
|
||||
eReg regi; /* index mode */
|
||||
int16_t off; /* offset */
|
||||
} other;
|
||||
} idNode;
|
||||
IDENTTYPE() : idType(UNDEF)
|
||||
{}
|
||||
};
|
||||
|
||||
@ -1,46 +1,28 @@
|
||||
#pragma once
|
||||
#include <llvm/ADT/ilist.h>
|
||||
#include <llvm/ADT/ilist_node.h>
|
||||
#include <bitset>
|
||||
#include "BasicBlock.h"
|
||||
#include "locident.h"
|
||||
#include "state.h"
|
||||
#include "icode.h"
|
||||
#include "StackFrame.h"
|
||||
#include "CallConvention.h"
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <bitset>
|
||||
#include <map>
|
||||
|
||||
class QIODevice;
|
||||
class QTextStream;
|
||||
|
||||
/* PROCEDURE NODE */
|
||||
struct CALL_GRAPH;
|
||||
struct COND_EXPR;
|
||||
struct Expr;
|
||||
struct Disassembler;
|
||||
struct Function;
|
||||
struct CALL_GRAPH;
|
||||
struct PROG;
|
||||
|
||||
typedef llvm::iplist<Function> FunctionListType;
|
||||
typedef FunctionListType lFunction;
|
||||
typedef lFunction::iterator ilFunction;
|
||||
struct Function;
|
||||
|
||||
namespace llvm
|
||||
{
|
||||
// Traits for intrusive list of basic blocks...
|
||||
template<>
|
||||
struct ilist_traits<BB> : public ilist_default_traits<BB>
|
||||
{
|
||||
|
||||
// createSentinel is used to get hold of the node that marks the end of the
|
||||
// list... (same trick used here as in ilist_traits<Instruction>)
|
||||
BB *createSentinel() const {
|
||||
return static_cast<BB*>(&Sentinel);
|
||||
}
|
||||
static void destroySentinel(BB*) {}
|
||||
|
||||
BB *provideInitialHead() const { return createSentinel(); }
|
||||
BB *ensureHead(BB*) const { return createSentinel(); }
|
||||
static void noteHead(BB*, BB*) {}
|
||||
|
||||
//static ValueSymbolTable *getSymTab(Function *ItemParent);
|
||||
private:
|
||||
mutable ilist_half_node<BB> Sentinel;
|
||||
};
|
||||
}
|
||||
/* Procedure FLAGS */
|
||||
enum PROC_FLAGS
|
||||
{
|
||||
@ -48,9 +30,9 @@ enum PROC_FLAGS
|
||||
PROC_IJMP =0x00000200,/* Proc incomplete due to indirect jmp */
|
||||
PROC_ICALL =0x00000400, /* Proc incomplete due to indirect call */
|
||||
PROC_HLL =0x00001000, /* Proc is likely to be from a HLL */
|
||||
CALL_PASCAL =0x00002000, /* Proc uses Pascal calling convention */
|
||||
CALL_C =0x00004000, /* Proc uses C calling convention */
|
||||
CALL_UNKNOWN=0x00008000, /* Proc uses unknown calling convention */
|
||||
// CALL_PASCAL =0x00002000, /* Proc uses Pascal calling convention */
|
||||
// CALL_C =0x00004000, /* Proc uses C calling convention */
|
||||
// CALL_UNKNOWN=0x00008000, /* Proc uses unknown calling convention */
|
||||
PROC_NEAR =0x00010000, /* Proc exits with near return */
|
||||
PROC_FAR =0x00020000, /* Proc exits with far return */
|
||||
GRAPH_IRRED =0x00100000, /* Proc generates an irreducible graph */
|
||||
@ -58,24 +40,24 @@ enum PROC_FLAGS
|
||||
DI_REGVAR =0x00400000, /* DI is used as a stack variable */
|
||||
PROC_IS_FUNC=0x00800000, /* Proc is a function */
|
||||
REG_ARGS =0x01000000, /* Proc has registers as arguments */
|
||||
PROC_VARARG =0x02000000, /* Proc has variable arguments */
|
||||
// PROC_VARARG =0x02000000, /* Proc has variable arguments */
|
||||
PROC_OUTPUT =0x04000000, /* C for this proc has been output */
|
||||
PROC_RUNTIME=0x08000000, /* Proc is part of the runtime support */
|
||||
PROC_ISLIB =0x10000000, /* Proc is a library function */
|
||||
PROC_ASM =0x20000000, /* Proc is an intrinsic assembler routine */
|
||||
PROC_IS_HLL =0x40000000 /* Proc has HLL prolog code */
|
||||
#define CALL_MASK 0xFFFF9FFF /* Masks off CALL_C and CALL_PASCAL */
|
||||
//#define CALL_MASK 0xFFFF9FFF /* Masks off CALL_C and CALL_PASCAL */
|
||||
};
|
||||
|
||||
struct FunctionType
|
||||
{
|
||||
bool m_vararg;
|
||||
bool m_vararg=false;
|
||||
bool isVarArg() const {return m_vararg;}
|
||||
};
|
||||
struct Assignment
|
||||
{
|
||||
COND_EXPR *lhs;
|
||||
COND_EXPR *rhs;
|
||||
Expr *lhs;
|
||||
Expr *rhs;
|
||||
};
|
||||
struct JumpTable
|
||||
{
|
||||
@ -86,61 +68,92 @@ struct JumpTable
|
||||
size_t entrySize() { return 2;}
|
||||
void pruneEntries(uint16_t cs);
|
||||
};
|
||||
|
||||
struct Function : public llvm::ilist_node<Function>
|
||||
class FunctionCfg
|
||||
{
|
||||
typedef llvm::iplist<BB> BasicBlockListType;
|
||||
std::list<BB*> m_listBB; /* Ptr. to BB list/CFG */
|
||||
public:
|
||||
typedef std::list<BB*>::iterator iterator;
|
||||
iterator begin() {
|
||||
return m_listBB.begin();
|
||||
}
|
||||
iterator end() {
|
||||
return m_listBB.end();
|
||||
}
|
||||
BB * &front() { return m_listBB.front();}
|
||||
void nodeSplitting()
|
||||
{
|
||||
/* Converts the irreducible graph G into an equivalent reducible one, by
|
||||
* means of node splitting. */
|
||||
fprintf(stderr,"Attempt to perform node splitting: NOT IMPLEMENTED\n");
|
||||
}
|
||||
void push_back(BB *v) { m_listBB.push_back(v);}
|
||||
};
|
||||
struct Function
|
||||
{
|
||||
typedef std::list<BB *> BasicBlockListType;
|
||||
// BasicBlock iterators...
|
||||
typedef BasicBlockListType::iterator iterator;
|
||||
typedef BasicBlockListType::const_iterator const_iterator;
|
||||
private:
|
||||
protected:
|
||||
BasicBlockListType BasicBlocks; ///< The basic blocks
|
||||
Function(FunctionType */*ty*/) : procEntry(0),depth(0),flg(0),cbParam(0),m_dfsLast(0),numBBs(0),
|
||||
hasCase(false),liveAnal(0)
|
||||
{
|
||||
type = new FunctionType;
|
||||
callingConv(CConv::eUnknown);
|
||||
}
|
||||
|
||||
public:
|
||||
FunctionType * type;
|
||||
CConv * m_call_conv;
|
||||
uint32_t procEntry; /* label number */
|
||||
std::string name; /* Meaningful name for this proc */
|
||||
STATE state; /* Entry state */
|
||||
QString name; /* Meaningful name for this proc */
|
||||
STATE state; /* Entry state */
|
||||
int depth; /* Depth at which we found it - for printing */
|
||||
uint32_t flg; /* Combination of Icode & Proc flags */
|
||||
int16_t cbParam; /* Probable no. of bytes of parameters */
|
||||
uint32_t flg; /* Combination of Icode & Proc flags */
|
||||
int16_t cbParam; /* Probable no. of bytes of parameters */
|
||||
STKFRAME args; /* Array of arguments */
|
||||
LOCAL_ID localId; /* Local identifiers */
|
||||
ID retVal; /* Return value - identifier */
|
||||
|
||||
/* Icodes and control flow graph */
|
||||
CIcodeRec Icode; /* Object with ICODE records */
|
||||
std::list<BB*> m_cfg; /* Ptr. to BB list/CFG */
|
||||
FunctionCfg m_actual_cfg;
|
||||
std::vector<BB*> m_dfsLast;
|
||||
std::list<BB*> heldBBs;
|
||||
//BB * *dfsLast; /* Array of pointers to BBs in dfsLast
|
||||
std::map<int,BB*> m_ip_to_bb;
|
||||
// * (reverse postorder) order */
|
||||
size_t numBBs; /* Number of BBs in the graph cfg */
|
||||
bool hasCase; /* Procedure has a case node */
|
||||
|
||||
/* For interprocedural live analysis */
|
||||
std::bitset<32> liveIn; /* Registers used before defined */
|
||||
std::bitset<32> liveOut; /* Registers that may be used in successors */
|
||||
bool liveAnal; /* Procedure has been analysed already */
|
||||
LivenessSet liveIn; /* Registers used before defined */
|
||||
LivenessSet liveOut; /* Registers that may be used in successors */
|
||||
bool liveAnal; /* Procedure has been analysed already */
|
||||
|
||||
Function(void *ty=0) : procEntry(0),depth(0),flg(0),cbParam(0),m_cfg(0),m_dfsLast(0),numBBs(0),
|
||||
hasCase(false),liveIn(0),liveOut(0),liveAnal(0)//,next(0),prev(0)
|
||||
{
|
||||
virtual ~Function() {
|
||||
delete type;
|
||||
}
|
||||
public:
|
||||
static Function *Create(void *ty=0,int Linkage=0,const std::string &nm="",void *module=0)
|
||||
static Function *Create(FunctionType *ty=0,int /*Linkage*/=0,const QString &nm="",void */*module*/=0)
|
||||
{
|
||||
Function *r=new Function(ty);
|
||||
r->name = nm;
|
||||
return r;
|
||||
}
|
||||
bool anyFlagsSet(uint32_t t) { return (flg&t)!=0;}
|
||||
FunctionType *getFunctionType() const {
|
||||
return type;
|
||||
}
|
||||
CConv *callingConv() const { return m_call_conv;}
|
||||
void callingConv(CConv::Type v);
|
||||
|
||||
// bool anyFlagsSet(uint32_t t) { return (flg&t)!=0;}
|
||||
bool hasRegArgs() const { return (flg & REG_ARGS)!=0;}
|
||||
bool isLibrary() const { return (flg & PROC_ISLIB)!=0;}
|
||||
void compoundCond();
|
||||
void writeProcComments();
|
||||
void lowLevelAnalysis();
|
||||
void bindIcodeOff();
|
||||
void dataFlow(std::bitset<32> &liveOut);
|
||||
void dataFlow(LivenessSet &liveOut);
|
||||
void compressCFG();
|
||||
void highLevelGen();
|
||||
void structure(derSeq *derivedG);
|
||||
@ -151,22 +164,27 @@ public:
|
||||
void FollowCtrl(CALL_GRAPH *pcallGraph, STATE *pstate);
|
||||
void process_operands(ICODE &pIcode, STATE *pstate);
|
||||
bool process_JMP(ICODE &pIcode, STATE *pstate, CALL_GRAPH *pcallGraph);
|
||||
boolT process_CALL(ICODE &pIcode, CALL_GRAPH *pcallGraph, STATE *pstate);
|
||||
bool process_CALL(ICODE &pIcode, CALL_GRAPH *pcallGraph, STATE *pstate);
|
||||
void freeCFG();
|
||||
void codeGen(std::ostream &fs);
|
||||
void codeGen(QIODevice & fs);
|
||||
void mergeFallThrough(BB *pBB);
|
||||
void structIfs();
|
||||
void structLoops(derSeq *derivedG);
|
||||
void buildCFG(Disassembler &ds);
|
||||
void controlFlowAnalysis();
|
||||
void newRegArg(iICODE picode, iICODE ticode);
|
||||
void writeProcComments(std::ostream &ostr);
|
||||
void writeProcComments(QTextStream & ostr);
|
||||
|
||||
void displayCFG();
|
||||
void displayStats();
|
||||
void processHliCall(COND_EXPR *exp, iICODE picode);
|
||||
void processHliCall(Expr *exp, iICODE picode);
|
||||
|
||||
void preprocessReturnDU(std::bitset<32> &_liveOut);
|
||||
void preprocessReturnDU(LivenessSet &_liveOut);
|
||||
Expr * adjustActArgType(Expr *_exp, hlType forType);
|
||||
QString writeCall(Function *tproc, STKFRAME &args, int *numLoc);
|
||||
void processDosInt(STATE *pstate, PROG &prog, bool done);
|
||||
ICODE *translate_DIV(LLInst *ll, ICODE &_Icode);
|
||||
ICODE *translate_XCHG(LLInst *ll, ICODE &_Icode);
|
||||
protected:
|
||||
void extractJumpTableRange(ICODE& pIcode, STATE *pstate, JumpTable &table);
|
||||
bool followAllTableEntries(JumpTable &table, uint32_t cs, ICODE &pIcode, CALL_GRAPH *pcallGraph, STATE *pstate);
|
||||
@ -190,10 +208,18 @@ protected:
|
||||
void findExps();
|
||||
void genDU1();
|
||||
void elimCondCodes();
|
||||
void liveRegAnalysis(std::bitset<32> &in_liveOut);
|
||||
void liveRegAnalysis(LivenessSet &in_liveOut);
|
||||
void findIdioms();
|
||||
void propLong();
|
||||
void genLiveKtes();
|
||||
uint8_t findDerivedSeq (derSeq &derivedGi);
|
||||
bool findDerivedSeq(derSeq &derivedGi);
|
||||
bool nextOrderGraph(derSeq &derivedGi);
|
||||
void addOutEdgesForConditionalJump(BB* pBB, int next_ip, LLInst *ll);
|
||||
|
||||
private:
|
||||
bool decodeIndirectJMP(ICODE &pIcode, STATE *pstate, CALL_GRAPH *pcallGraph);
|
||||
bool decodeIndirectJMP2(ICODE &pIcode, STATE *pstate, CALL_GRAPH *pcallGraph);
|
||||
};
|
||||
typedef std::list<Function> FunctionListType;
|
||||
typedef FunctionListType lFunction;
|
||||
typedef lFunction::iterator ilFunction;
|
||||
|
||||
@ -13,7 +13,7 @@ struct STKFRAME : public SymbolTableCommon<STKSYM>
|
||||
int16_t maxOff; /* Maximum offset in stack frame*/
|
||||
int cb; /* Number of bytes in arguments */
|
||||
int numArgs; /* No. of arguments in the table*/
|
||||
void adjustForArgType(int numArg_, hlType actType_);
|
||||
void adjustForArgType(size_t numArg_, hlType actType_);
|
||||
STKFRAME() : m_minOff(0),maxOff(0),cb(0),numArgs(0)
|
||||
{
|
||||
|
||||
|
||||
373
include/ast.h
373
include/ast.h
@ -5,10 +5,15 @@
|
||||
* (C) Cristina Cifuentes
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "Enums.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <stdint.h>
|
||||
#include <cstring>
|
||||
#include <list>
|
||||
#include "Enums.h"
|
||||
#include <boost/range.hpp>
|
||||
|
||||
static const int operandSize=20;
|
||||
/* The following definitions and types define the Conditional Expression
|
||||
* attributed syntax tree, as defined by the following EBNF:
|
||||
@ -20,131 +25,164 @@ static const int operandSize=20;
|
||||
*/
|
||||
/* High-level BOOLEAN conditions for iJB..iJNS icodes */
|
||||
static const condOp condOpJCond[12] = {LESS, LESS_EQUAL, GREATER_EQUAL, GREATER,
|
||||
EQUAL, NOT_EQUAL, LESS, GREATER_EQUAL,
|
||||
LESS_EQUAL, GREATER, GREATER_EQUAL, LESS};
|
||||
|
||||
EQUAL, NOT_EQUAL, LESS, GREATER_EQUAL,
|
||||
LESS_EQUAL, GREATER, GREATER_EQUAL, LESS};
|
||||
struct AstIdent;
|
||||
struct Function;
|
||||
struct STKFRAME;
|
||||
struct LOCAL_ID;
|
||||
struct ICODE;
|
||||
struct LLInst;
|
||||
struct LLOperand;
|
||||
struct ID;
|
||||
typedef std::list<ICODE>::iterator iICODE;
|
||||
typedef boost::iterator_range<iICODE> rICODE;
|
||||
#include "IdentType.h"
|
||||
|
||||
/* Expression data type */
|
||||
struct COND_EXPR
|
||||
struct Expr
|
||||
{
|
||||
protected:
|
||||
struct /* for BOOLEAN_OP */
|
||||
{
|
||||
condOp op;
|
||||
COND_EXPR *lhs;
|
||||
COND_EXPR *rhs;
|
||||
} boolExpr;
|
||||
public:
|
||||
condNodeType m_type; /* Conditional Expression Node Type */
|
||||
public:
|
||||
static bool insertSubTreeLongReg(Expr *exp, Expr *&tree, int longIdx);
|
||||
static bool insertSubTreeReg(Expr *&tree, Expr *_expr, eReg regi, const LOCAL_ID *locsym);
|
||||
static bool insertSubTreeReg(AstIdent *&tree, Expr *_expr, eReg regi, const LOCAL_ID *locsym);
|
||||
public:
|
||||
|
||||
public:
|
||||
condNodeType m_type; /* Conditional Expression Node Type */
|
||||
union _exprNode { /* Different cond expr nodes */
|
||||
COND_EXPR *unaryExp; /* for NEGATION,ADDRESSOF,DEREFERENCE*/
|
||||
IDENTTYPE ident; /* for IDENTIFIER */
|
||||
} expr;
|
||||
COND_EXPR *lhs()
|
||||
virtual Expr *clone() const=0; //!< Makes a deep copy of the given expression
|
||||
Expr(condNodeType t=UNKNOWN_OP) : m_type(t)
|
||||
{
|
||||
assert(m_type==BOOLEAN_OP);
|
||||
return boolExpr.lhs;
|
||||
}
|
||||
const COND_EXPR *lhs() const
|
||||
{
|
||||
assert(m_type==BOOLEAN_OP);
|
||||
return boolExpr.lhs;
|
||||
}
|
||||
COND_EXPR *rhs()
|
||||
{
|
||||
assert(m_type==BOOLEAN_OP);
|
||||
return boolExpr.rhs;
|
||||
}
|
||||
const COND_EXPR *rhs() const
|
||||
{
|
||||
assert(m_type==BOOLEAN_OP);
|
||||
return boolExpr.rhs;
|
||||
}
|
||||
condOp op() const { return boolExpr.op;}
|
||||
public:
|
||||
static COND_EXPR *idRegIdx(int idx, regType reg_type);
|
||||
static COND_EXPR *idKte(uint32_t kte, uint8_t size);
|
||||
static COND_EXPR *idLoc(int off, LOCAL_ID *localId);
|
||||
static COND_EXPR *idReg(eReg regi, uint32_t icodeFlg, LOCAL_ID *locsym);
|
||||
static COND_EXPR *idLongIdx(int idx);
|
||||
static COND_EXPR *idOther(eReg seg, eReg regi, int16_t off);
|
||||
static COND_EXPR *idParam(int off, const STKFRAME *argSymtab);
|
||||
static COND_EXPR *unary(condNodeType t, COND_EXPR *sub_expr);
|
||||
static COND_EXPR *idLong(LOCAL_ID *localId, opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, LLInst &atOffset);
|
||||
static COND_EXPR *idFunc(Function *pproc, STKFRAME *args);
|
||||
static COND_EXPR *idID(const ID *retVal, LOCAL_ID *locsym, iICODE ix_);
|
||||
static COND_EXPR * id(const LLInst &ll_insn, opLoc sd, Function *pProc, iICODE ix_, ICODE &duIcode, operDu du);
|
||||
static COND_EXPR *boolOp(COND_EXPR *_lhs, COND_EXPR *_rhs, condOp _op);
|
||||
static bool insertSubTreeLongReg(COND_EXPR *exp, COND_EXPR **tree, int longIdx);
|
||||
static bool insertSubTreeReg(COND_EXPR *&tree, COND_EXPR *_expr, eReg regi, const LOCAL_ID *locsym);
|
||||
public:
|
||||
virtual COND_EXPR *clone() const;
|
||||
void release();
|
||||
void changeBoolOp(condOp newOp);
|
||||
COND_EXPR(const COND_EXPR &other)
|
||||
{
|
||||
m_type=other.m_type;
|
||||
expr=other.expr;
|
||||
boolExpr=other.boolExpr;
|
||||
}
|
||||
COND_EXPR(condNodeType t=UNKNOWN_OP) : m_type(t)
|
||||
{
|
||||
memset(&expr,0,sizeof(_exprNode));
|
||||
memset(&boolExpr,0,sizeof(boolExpr));
|
||||
|
||||
}
|
||||
virtual ~COND_EXPR() {}
|
||||
/** Recursively deallocates the abstract syntax tree rooted at *exp */
|
||||
virtual ~Expr() {}
|
||||
public:
|
||||
virtual COND_EXPR *inverse() const; // return new COND_EXPR that is invarse of this
|
||||
virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locId);
|
||||
virtual COND_EXPR *insertSubTreeReg(COND_EXPR *_expr, eReg regi, const LOCAL_ID *locsym);
|
||||
virtual COND_EXPR *insertSubTreeLongReg(COND_EXPR *_expr, int longIdx);
|
||||
virtual hlType expType(Function *pproc) const;
|
||||
virtual QString walkCondExpr (Function * pProc, int* numLoc) const=0;
|
||||
virtual Expr *inverse() const=0; // return new COND_EXPR that is invarse of this
|
||||
virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locId)=0;
|
||||
virtual Expr *insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym)=0;
|
||||
virtual Expr *insertSubTreeLongReg(Expr *_expr, int longIdx)=0;
|
||||
virtual hlType expType(Function *pproc) const=0;
|
||||
virtual int hlTypeSize(Function *pproc) const=0;
|
||||
virtual Expr * performLongRemoval(eReg regi, LOCAL_ID *locId) { return this; }
|
||||
};
|
||||
struct BinaryOperator : public COND_EXPR
|
||||
struct UnaryOperator : public Expr
|
||||
{
|
||||
UnaryOperator(condNodeType t=UNKNOWN_OP) : Expr(t),unaryExp(nullptr) {}
|
||||
Expr *unaryExp;
|
||||
virtual Expr *inverse() const
|
||||
{
|
||||
if (m_type == NEGATION) //TODO: memleak here
|
||||
{
|
||||
return unaryExp->clone();
|
||||
}
|
||||
return this->clone();
|
||||
}
|
||||
virtual Expr *clone() const
|
||||
{
|
||||
UnaryOperator *newExp = new UnaryOperator(*this);
|
||||
newExp->unaryExp = unaryExp->clone();
|
||||
return newExp;
|
||||
}
|
||||
virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locs);
|
||||
static UnaryOperator *Create(condNodeType t, Expr *sub_expr)
|
||||
{
|
||||
UnaryOperator *newExp = new UnaryOperator();
|
||||
newExp->m_type = t;
|
||||
newExp->unaryExp = sub_expr;
|
||||
return (newExp);
|
||||
}
|
||||
~UnaryOperator()
|
||||
{
|
||||
delete unaryExp;
|
||||
unaryExp=nullptr;
|
||||
}
|
||||
public:
|
||||
int hlTypeSize(Function *pproc) const;
|
||||
virtual QString walkCondExpr(Function *pProc, int *numLoc) const;
|
||||
virtual Expr *insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym);
|
||||
virtual hlType expType(Function *pproc) const;
|
||||
virtual Expr *insertSubTreeLongReg(Expr *_expr, int longIdx);
|
||||
private:
|
||||
QString wrapUnary(Function *pProc, int *numLoc, QChar op) const;
|
||||
};
|
||||
|
||||
struct BinaryOperator : public Expr
|
||||
{
|
||||
condOp m_op;
|
||||
COND_EXPR *m_lhs;
|
||||
COND_EXPR *m_rhs;
|
||||
BinaryOperator(condOp o)
|
||||
Expr *m_lhs;
|
||||
Expr *m_rhs;
|
||||
BinaryOperator(condOp o) : Expr(BOOLEAN_OP)
|
||||
{
|
||||
m_op = o;
|
||||
m_lhs=m_rhs=nullptr;
|
||||
}
|
||||
static BinaryOperator *Create(condOp o,COND_EXPR *l,COND_EXPR *r);
|
||||
static BinaryOperator *CreateAdd(COND_EXPR *l,COND_EXPR *r);
|
||||
virtual COND_EXPR *inverse();
|
||||
virtual COND_EXPR *clone();
|
||||
virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locs);
|
||||
virtual COND_EXPR *insertSubTreeReg(COND_EXPR *_expr, eReg regi, LOCAL_ID *locsym);
|
||||
virtual COND_EXPR *insertSubTreeLongReg(COND_EXPR *_expr, int longIdx);
|
||||
BinaryOperator(condOp o,Expr *l,Expr *r) : Expr(BOOLEAN_OP)
|
||||
{
|
||||
m_op = o;
|
||||
m_lhs=l;
|
||||
m_rhs=r;
|
||||
}
|
||||
~BinaryOperator()
|
||||
{
|
||||
assert(m_lhs!=m_rhs or m_lhs==nullptr);
|
||||
delete m_lhs;
|
||||
delete m_rhs;
|
||||
m_lhs=m_rhs=nullptr;
|
||||
}
|
||||
static BinaryOperator *Create(condOp o,Expr *l,Expr *r)
|
||||
{
|
||||
BinaryOperator *res = new BinaryOperator(o);
|
||||
res->m_lhs = l;
|
||||
res->m_rhs = r;
|
||||
return res;
|
||||
}
|
||||
static BinaryOperator *LogicAnd(Expr *l,Expr *r)
|
||||
{
|
||||
return Create(DBL_AND,l,r);
|
||||
}
|
||||
static BinaryOperator *createSHL(Expr *l,Expr *r)
|
||||
{
|
||||
return Create(SHL,l,r);
|
||||
}
|
||||
static BinaryOperator *And(Expr *l,Expr *r)
|
||||
{
|
||||
return Create(AND,l,r);
|
||||
}
|
||||
static BinaryOperator *Or(Expr *l,Expr *r)
|
||||
{
|
||||
return Create(OR,l,r);
|
||||
}
|
||||
static BinaryOperator *LogicOr(Expr *l,Expr *r)
|
||||
{
|
||||
return Create(DBL_OR,l,r);
|
||||
}
|
||||
static BinaryOperator *CreateAdd(Expr *l,Expr *r) {
|
||||
return Create(ADD,l,r);
|
||||
|
||||
COND_EXPR *lhs()
|
||||
}
|
||||
void changeBoolOp(condOp newOp);
|
||||
virtual Expr *inverse() const;
|
||||
virtual Expr *clone() const;
|
||||
virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locs);
|
||||
virtual Expr *insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym);
|
||||
virtual Expr *insertSubTreeLongReg(Expr *_expr, int longIdx);
|
||||
const Expr *lhs() const
|
||||
{
|
||||
return const_cast<const Expr *>(const_cast<BinaryOperator *>(this)->lhs());
|
||||
}
|
||||
const Expr *rhs() const
|
||||
{
|
||||
return const_cast<const Expr *>(const_cast<BinaryOperator *>(this)->rhs());
|
||||
}
|
||||
|
||||
Expr *lhs()
|
||||
{
|
||||
assert(m_type==BOOLEAN_OP);
|
||||
return m_lhs;
|
||||
}
|
||||
const COND_EXPR *lhs() const
|
||||
{
|
||||
assert(m_type==BOOLEAN_OP);
|
||||
return m_lhs;
|
||||
}
|
||||
COND_EXPR *rhs()
|
||||
{
|
||||
assert(m_type==BOOLEAN_OP);
|
||||
return m_rhs;
|
||||
}
|
||||
const COND_EXPR *rhs() const
|
||||
Expr *rhs()
|
||||
{
|
||||
assert(m_type==BOOLEAN_OP);
|
||||
return m_rhs;
|
||||
@ -152,26 +190,131 @@ struct BinaryOperator : public COND_EXPR
|
||||
condOp op() const { return m_op;}
|
||||
/* Changes the boolean conditional operator at the root of this expression */
|
||||
void op(condOp o) { m_op=o;}
|
||||
QString walkCondExpr(Function * pProc, int* numLoc) const;
|
||||
public:
|
||||
hlType expType(Function *pproc) const;
|
||||
int hlTypeSize(Function *pproc) const;
|
||||
};
|
||||
struct UnaryOperator : public COND_EXPR
|
||||
struct AstIdent : public UnaryOperator
|
||||
{
|
||||
condOp op;
|
||||
COND_EXPR *unaryExp;
|
||||
virtual COND_EXPR *inverse();
|
||||
virtual COND_EXPR *clone();
|
||||
virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locs);
|
||||
static UnaryOperator *Create(condNodeType t, COND_EXPR *sub_expr)
|
||||
AstIdent() : UnaryOperator(IDENTIFIER)
|
||||
{
|
||||
UnaryOperator *newExp = new UnaryOperator();
|
||||
newExp->m_type=t;
|
||||
newExp->unaryExp = sub_expr;
|
||||
return (newExp);
|
||||
}
|
||||
};
|
||||
IDENTTYPE ident; /* for IDENTIFIER */
|
||||
static AstIdent * Loc(int off, LOCAL_ID *localId);
|
||||
static AstIdent * LongIdx(int idx);
|
||||
static AstIdent * String(uint32_t idx);
|
||||
static AstIdent * Other(eReg seg, eReg regi, int16_t off);
|
||||
static AstIdent * Param(int off, const STKFRAME *argSymtab);
|
||||
static AstIdent * Long(LOCAL_ID *localId, opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, LLInst &atOffset);
|
||||
static AstIdent * idID(const ID *retVal, LOCAL_ID *locsym, iICODE ix_);
|
||||
static Expr * id(const LLInst &ll_insn, opLoc sd, Function *pProc, iICODE ix_, ICODE &duIcode, operDu du);
|
||||
|
||||
struct GlobalVariable : public COND_EXPR
|
||||
{
|
||||
static COND_EXPR *Create(int16_t segValue, int16_t off);
|
||||
virtual Expr *clone() const
|
||||
{
|
||||
return new AstIdent(*this);
|
||||
}
|
||||
virtual int hlTypeSize(Function *pproc) const;
|
||||
virtual hlType expType(Function *pproc) const;
|
||||
virtual Expr * performLongRemoval(eReg regi, LOCAL_ID *locId);
|
||||
virtual QString walkCondExpr(Function *pProc, int *numLoc) const;
|
||||
virtual Expr *insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym);
|
||||
virtual Expr *insertSubTreeLongReg(Expr *_expr, int longIdx);
|
||||
virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locId);
|
||||
};
|
||||
struct GlobalVariable : public AstIdent
|
||||
{
|
||||
bool valid;
|
||||
int globIdx;
|
||||
virtual Expr *clone() const
|
||||
{
|
||||
return new GlobalVariable(*this);
|
||||
}
|
||||
GlobalVariable(int16_t segValue, int16_t off);
|
||||
QString walkCondExpr(Function *pProc, int *numLoc) const;
|
||||
int hlTypeSize(Function *pproc) const;
|
||||
hlType expType(Function *pproc) const;
|
||||
};
|
||||
struct GlobalVariableIdx : public AstIdent
|
||||
{
|
||||
bool valid;
|
||||
int idxGlbIdx; /* idx into localId, GLOB_VAR_IDX */
|
||||
|
||||
virtual Expr *clone() const
|
||||
{
|
||||
return new GlobalVariableIdx(*this);
|
||||
}
|
||||
GlobalVariableIdx(int16_t segValue, int16_t off, uint8_t regi, const LOCAL_ID *locSym);
|
||||
QString walkCondExpr(Function *pProc, int *numLoc) const;
|
||||
int hlTypeSize(Function *pproc) const;
|
||||
hlType expType(Function *pproc) const;
|
||||
};
|
||||
struct Constant : public AstIdent
|
||||
{
|
||||
struct _kte
|
||||
{ /* for CONSTANT only */
|
||||
uint32_t kte; /* value of the constant */
|
||||
uint8_t size; /* #bytes size constant */
|
||||
} kte;
|
||||
|
||||
Constant(uint32_t _kte, uint8_t size)
|
||||
{
|
||||
ident.idType = CONSTANT;
|
||||
kte.kte = _kte;
|
||||
kte.size = size;
|
||||
}
|
||||
virtual Expr *clone() const
|
||||
{
|
||||
return new Constant(*this);
|
||||
}
|
||||
QString walkCondExpr(Function *pProc, int *numLoc) const;
|
||||
int hlTypeSize(Function *pproc) const;
|
||||
hlType expType(Function *pproc) const { return TYPE_CONST; }
|
||||
};
|
||||
struct FuncNode : public AstIdent
|
||||
{
|
||||
struct _call { /* for FUNCTION only */
|
||||
Function *proc;
|
||||
STKFRAME *args;
|
||||
} call;
|
||||
|
||||
FuncNode(Function *pproc, STKFRAME *args)
|
||||
{
|
||||
call.proc = pproc;
|
||||
call.args = args;
|
||||
}
|
||||
virtual Expr *clone() const
|
||||
{
|
||||
return new FuncNode(*this);
|
||||
}
|
||||
QString walkCondExpr(Function *pProc, int *numLoc) const;
|
||||
int hlTypeSize(Function *pproc) const;
|
||||
hlType expType(Function *pproc) const;
|
||||
};
|
||||
struct RegisterNode : public AstIdent
|
||||
{
|
||||
const LOCAL_ID *m_syms;
|
||||
regType regiType; /* for REGISTER only */
|
||||
int regiIdx; /* index into localId, REGISTER */
|
||||
|
||||
virtual Expr *insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym);
|
||||
|
||||
RegisterNode(int idx, regType reg_type,const LOCAL_ID *syms)
|
||||
{
|
||||
m_syms= syms;
|
||||
ident.type(REGISTER);
|
||||
regiType = reg_type;
|
||||
regiIdx = idx;
|
||||
}
|
||||
RegisterNode(const LLOperand &, LOCAL_ID *locsym);
|
||||
|
||||
//RegisterNode(eReg regi, uint32_t icodeFlg, LOCAL_ID *locsym);
|
||||
virtual Expr *clone() const
|
||||
{
|
||||
return new RegisterNode(*this);
|
||||
}
|
||||
QString walkCondExpr(Function *pProc, int *numLoc) const;
|
||||
int hlTypeSize(Function *) const;
|
||||
hlType expType(Function *pproc) const;
|
||||
bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locId);
|
||||
};
|
||||
struct Constant : public COND_EXPR
|
||||
{};
|
||||
|
||||
@ -7,8 +7,10 @@
|
||||
#pragma once
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
struct strTable : std::vector<std::string>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QIODevice>
|
||||
|
||||
struct strTable : std::vector<QString>
|
||||
{
|
||||
/* Returns the next available index into the table */
|
||||
size_t nextIdx() {return size();}
|
||||
@ -20,9 +22,9 @@ struct bundle
|
||||
{
|
||||
public:
|
||||
void appendCode(const char *format, ...);
|
||||
void appendCode(const std::string &s);
|
||||
void appendCode(const QString &s);
|
||||
void appendDecl(const char *format, ...);
|
||||
void appendDecl(const std::string &);
|
||||
void appendDecl(const QString &);
|
||||
void init()
|
||||
{
|
||||
decl.clear();
|
||||
@ -33,10 +35,10 @@ public:
|
||||
int current_indent;
|
||||
};
|
||||
|
||||
|
||||
extern bundle cCode;
|
||||
#define lineSize 360 /* 3 lines in the mean time */
|
||||
|
||||
//void newBundle (bundle *procCode);
|
||||
void writeBundle (std::ostream &ios, bundle procCode);
|
||||
void writeBundle (QIODevice & ios, bundle procCode);
|
||||
void freeBundle (bundle *procCode);
|
||||
|
||||
|
||||
@ -5,10 +5,10 @@
|
||||
#pragma once
|
||||
//TODO: Remove boolT
|
||||
|
||||
#include <llvm/ADT/ilist.h>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
#include <bitset>
|
||||
#include <QtCore/QString>
|
||||
|
||||
#include "Enums.h"
|
||||
#include "types.h"
|
||||
@ -20,54 +20,32 @@
|
||||
#include "bundle.h"
|
||||
#include "Procedure.h"
|
||||
#include "BasicBlock.h"
|
||||
struct Project;
|
||||
class Project;
|
||||
/* CALL GRAPH NODE */
|
||||
struct CALL_GRAPH
|
||||
{
|
||||
ilFunction proc; /* Pointer to procedure in pProcList */
|
||||
std::vector<CALL_GRAPH *> outEdges; /* array of out edges */
|
||||
public:
|
||||
void write();
|
||||
CALL_GRAPH() : outEdges(0)
|
||||
{
|
||||
}
|
||||
public:
|
||||
void writeNodeCallGraph(int indIdx);
|
||||
bool insertCallGraph(ilFunction caller, ilFunction callee);
|
||||
bool insertCallGraph(Function *caller, ilFunction callee);
|
||||
void insertArc(ilFunction newProc);
|
||||
};
|
||||
//#define NUM_PROCS_DELTA 5 /* delta # procs a proc invokes */
|
||||
//extern std::list<Function> pProcList;
|
||||
//extern FunctionListType pProcList;
|
||||
//extern CALL_GRAPH * callGraph; /* Pointer to the head of the call graph */
|
||||
extern bundle cCode; /* Output C procedure's declaration and code */
|
||||
|
||||
/**** Global variables ****/
|
||||
|
||||
extern char *asm1_name, *asm2_name; /* Assembler output filenames */
|
||||
extern QString asm1_name, asm2_name; /* Assembler output filenames */
|
||||
|
||||
typedef struct { /* Command line option flags */
|
||||
unsigned verbose : 1;
|
||||
unsigned VeryVerbose : 1;
|
||||
unsigned asm1 : 1; /* Early disassembly listing */
|
||||
unsigned asm2 : 1; /* Disassembly listing after restruct */
|
||||
unsigned Map : 1;
|
||||
unsigned Stats : 1;
|
||||
unsigned Interact : 1; /* Interactive mode */
|
||||
unsigned Calls : 1; /* Follow register indirect calls */
|
||||
char filename[80]; /* The input filename */
|
||||
} OPTION;
|
||||
/** Command line option flags */
|
||||
struct OPTION
|
||||
{
|
||||
bool verbose;
|
||||
bool VeryVerbose;
|
||||
bool asm1; /* Early disassembly listing */
|
||||
bool asm2; /* Disassembly listing after restruct */
|
||||
bool Map;
|
||||
bool Stats;
|
||||
bool Interact; /* Interactive mode */
|
||||
bool Calls; /* Follow register indirect calls */
|
||||
QString filename; /* The input filename */
|
||||
uint32_t CustomEntryPoint;
|
||||
};
|
||||
|
||||
extern OPTION option; /* Command line options */
|
||||
|
||||
#include "BinaryImage.h"
|
||||
extern std::bitset<32> duReg[30]; /* def/use bits for registers */
|
||||
|
||||
//extern uint32_t duReg[30]; /* def/use bits for registers */
|
||||
extern std::bitset<32> maskDuReg[30]; /* masks off du bits for regs */
|
||||
|
||||
/* Registers used by icode instructions */
|
||||
|
||||
/* Memory map states */
|
||||
enum eAreaType
|
||||
@ -94,56 +72,33 @@ extern STATS stats; /* Icode statistics */
|
||||
|
||||
|
||||
/**** Global function prototypes ****/
|
||||
class DccFrontend
|
||||
{
|
||||
void LoadImage(Project &proj);
|
||||
void parse(Project &proj);
|
||||
std::string m_fname;
|
||||
public:
|
||||
DccFrontend(const std::string &fname) : m_fname(fname)
|
||||
{
|
||||
}
|
||||
bool FrontEnd(); /* frontend.c */
|
||||
};
|
||||
|
||||
void udm(void); /* udm.c */
|
||||
void freeCFG(BB * cfg); /* graph.c */
|
||||
BB * newBB(BB *, int, int, uint8_t, int, Function *); /* graph.c */
|
||||
void BackEnd(char *filename, CALL_GRAPH *); /* backend.c */
|
||||
char *cChar(uint8_t c); /* backend.c */
|
||||
void BackEnd(CALL_GRAPH *); /* backend.c */
|
||||
extern char *cChar(uint8_t c); /* backend.c */
|
||||
eErrorId scan(uint32_t ip, ICODE &p); /* scanner.c */
|
||||
void parse (CALL_GRAPH * *); /* parser.c */
|
||||
|
||||
int strSize (uint8_t *, char); /* parser.c */
|
||||
extern int strSize (const uint8_t *, char); /* parser.c */
|
||||
//void disassem(int pass, Function * pProc); /* disassem.c */
|
||||
void interactDis(Function * initProc, int initIC); /* disassem.c */
|
||||
void interactDis(Function *, int initIC); /* disassem.c */
|
||||
bool JmpInst(llIcode opcode); /* idioms.c */
|
||||
queue::iterator appendQueue(queue &Q, BB *node); /* reducible.c */
|
||||
|
||||
void SetupLibCheck(void); /* chklib.c */
|
||||
bool SetupLibCheck(void); /* chklib.c */
|
||||
void CleanupLibCheck(void); /* chklib.c */
|
||||
bool LibCheck(Function &p); /* chklib.c */
|
||||
|
||||
/* Exported functions from procs.c */
|
||||
boolT insertCallGraph (CALL_GRAPH *, ilFunction, ilFunction);
|
||||
void adjustActArgType (COND_EXPR *, hlType, Function *);
|
||||
|
||||
/* Exported functions from ast.c */
|
||||
std::string walkCondExpr (const COND_EXPR *exp, Function * pProc, int *);
|
||||
int hlTypeSize (const COND_EXPR *, Function *);
|
||||
//hlType expType (const COND_EXPR *, Function *);
|
||||
|
||||
|
||||
/* Exported functions from hlicode.c */
|
||||
std::string writeCall (Function *, STKFRAME &, Function *, int *);
|
||||
char *writeJcond (const HLTYPE &, Function *, int *);
|
||||
char *writeJcondInv (HLTYPE, Function *, int *);
|
||||
QString writeJcond(const HLTYPE &, Function *, int *);
|
||||
QString writeJcondInv(HLTYPE, Function *, int *);
|
||||
|
||||
|
||||
/* Exported funcions from locident.c */
|
||||
boolT checkLongEq (LONG_STKID_TYPE, iICODE, int, Function *, Assignment &asgn, LLInst &atOffset);
|
||||
boolT checkLongRegEq (LONGID_TYPE, iICODE, int, Function *, Assignment &asgn, LLInst &);
|
||||
eReg otherLongRegi(eReg, int, LOCAL_ID *);
|
||||
|
||||
bool checkLongEq(LONG_STKID_TYPE, iICODE, int, Function *, Assignment &asgn, LLInst &atOffset);
|
||||
bool checkLongRegEq(LONGID_TYPE, iICODE, int, Function *, Assignment &asgn, LLInst &);
|
||||
|
||||
extern const char *indentStr(int level);
|
||||
|
||||
24
include/dcc_interface.h
Normal file
24
include/dcc_interface.h
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include "Procedure.h"
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QDir>
|
||||
|
||||
class IXmlTarget;
|
||||
|
||||
struct IDcc {
|
||||
static IDcc *get();
|
||||
virtual void BaseInit()=0;
|
||||
virtual void Init(QObject *tgt)=0;
|
||||
virtual lFunction::iterator GetFirstFuncHandle()=0;
|
||||
virtual lFunction::iterator GetCurFuncHandle()=0;
|
||||
virtual void analysis_Once()=0;
|
||||
virtual void load(QString name)=0; // load and preprocess -> find entry point
|
||||
virtual void prtout_asm(IXmlTarget *,int level=0)=0;
|
||||
virtual void prtout_cpp(IXmlTarget *,int level=0)=0;
|
||||
virtual size_t getFuncCount()=0;
|
||||
virtual const lFunction &validFunctions() const =0;
|
||||
virtual void SetCurFunc_by_Name(QString )=0;
|
||||
virtual QDir installDir()=0;
|
||||
virtual QDir dataDir(QString kind)=0;
|
||||
};
|
||||
@ -1,20 +1,26 @@
|
||||
/****************************************************************************
|
||||
* dcc project disassembler header
|
||||
* (C) Mike van Emmerik
|
||||
****************************************************************************/
|
||||
/*
|
||||
***************************************************************************
|
||||
dcc project disassembler header
|
||||
(C) Mike van Emmerik
|
||||
***************************************************************************
|
||||
*/
|
||||
#pragma once
|
||||
#include <sstream>
|
||||
#include "bundle.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include "bundle.h"
|
||||
#include <QString>
|
||||
#include <QTextStream>
|
||||
struct LLInst;
|
||||
struct Function;
|
||||
struct Disassembler
|
||||
{
|
||||
protected:
|
||||
int pass;
|
||||
int g_lab;
|
||||
//bundle &cCode;
|
||||
std::ofstream m_fp;
|
||||
QIODevice *m_disassembly_target;
|
||||
QTextStream m_fp;
|
||||
std::vector<std::string> m_decls;
|
||||
std::vector<std::string> m_code;
|
||||
|
||||
@ -32,24 +38,6 @@ public:
|
||||
|
||||
#define EXT 0x100 /* "Extended" flag */
|
||||
|
||||
#ifdef __MSDOS__
|
||||
#define KEY_DOWN EXT+'P'
|
||||
#define KEY_LEFT EXT+'K'
|
||||
#define KEY_UP EXT+'H'
|
||||
#define KEY_RIGHT EXT+'M'
|
||||
#define KEY_NPAGE EXT+'Q'
|
||||
#define KEY_PPAGE EXT+'I'
|
||||
#endif
|
||||
|
||||
#ifdef _CONSOLE
|
||||
#define KEY_DOWN 0x50 /* Same as keypad scancodes */
|
||||
#define KEY_LEFT 0x4B
|
||||
#define KEY_UP 0x48
|
||||
#define KEY_RIGHT 0x4D
|
||||
#define KEY_NPAGE 0x51
|
||||
#define KEY_PPAGE 0x49
|
||||
#endif
|
||||
|
||||
#ifdef __UNIX__
|
||||
#define KEY_DOWN EXT+'B'
|
||||
#define KEY_LEFT EXT+'D'
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
/***************************************************************************
|
||||
/*
|
||||
|
||||
=**************************************************************************
|
||||
* File : dosdcc.h
|
||||
* Purpose : include file for files decompiled by dcc.
|
||||
* Copyright (c) Cristina Cifuentes - QUT - 1992
|
||||
**************************************************************************/
|
||||
*************************************************************************
|
||||
*/
|
||||
|
||||
/* Type definitions for intel 80x86 architecture */
|
||||
typedef unsigned int uint16_t; /* 16 bits */
|
||||
@ -18,7 +21,7 @@ typedef struct {
|
||||
uint16_t lowBitWord : 1;
|
||||
uint16_t filler1 : 6;
|
||||
uint16_t highBitByte : 1;
|
||||
/* high uint8_t */
|
||||
/* high uint8_t */
|
||||
uint16_t lowBitByte : 1;
|
||||
uint16_t filler2 : 6;
|
||||
uint16_t highBitWord : 1;
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
/*****************************************************************************
|
||||
/*
|
||||
|
||||
****************************************************************************
|
||||
* Error codes
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
***************************************************************************
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/* These definitions refer to errorMessage in error.c */
|
||||
|
||||
@ -1,10 +1,13 @@
|
||||
/*****************************************************************************
|
||||
/*
|
||||
****************************************************************************
|
||||
* CFG, BB and interval related definitions
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
* ( C ) Cristina Cifuentes
|
||||
****************************************************************************
|
||||
*/
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
struct Function;
|
||||
/* Types of basic block nodes */
|
||||
/* Real basic blocks: type defined according to their out-edges */
|
||||
@ -55,6 +58,7 @@ enum eNodeHeaderType
|
||||
#define ELSE 1 /* else edge */
|
||||
|
||||
/* Basic Block (BB) flags */
|
||||
|
||||
#define INVALID_BB 0x0001 /* BB is not valid any more */
|
||||
#define IS_LATCH_NODE 0x0002 /* BB is the latching node of a loop */
|
||||
|
||||
@ -64,30 +68,24 @@ typedef std::list<BB *> queue;
|
||||
|
||||
struct interval
|
||||
{
|
||||
uint8_t numInt; /* # of the interval */
|
||||
uint8_t numOutEdges; /* Number of out edges */
|
||||
uint8_t numInt=0; /* # of the interval */
|
||||
uint8_t numOutEdges=0; /* Number of out edges */
|
||||
queue nodes; /* Nodes of the interval*/
|
||||
queue::iterator currNode; /* Current node */
|
||||
interval *next; /* Next interval */
|
||||
BB *firstOfInt();
|
||||
interval()
|
||||
{
|
||||
numInt=numOutEdges=0;
|
||||
currNode=nodes.end();
|
||||
next=0;
|
||||
}
|
||||
interval * next=0; /* Next interval */
|
||||
BB * firstOfInt();
|
||||
interval() : currNode(nodes.end()){
|
||||
}
|
||||
void appendNodeInt(queue &pqH, BB *node);
|
||||
};
|
||||
|
||||
|
||||
/* Derived Sequence structure */
|
||||
struct derSeq_Entry
|
||||
{
|
||||
BB * Gi; /* Graph pointer */
|
||||
interval * Ii; /* Interval list of Gi */
|
||||
derSeq_Entry() : Gi(0),Ii(0)
|
||||
{
|
||||
|
||||
}
|
||||
BB * Gi=nullptr; /* Graph pointer */
|
||||
std::list<interval *> m_intervals;
|
||||
interval * Ii=nullptr; /* Interval list of Gi */
|
||||
~derSeq_Entry();
|
||||
public:
|
||||
void findIntervals(Function *c);
|
||||
|
||||
458
include/icode.h
458
include/icode.h
@ -3,21 +3,23 @@
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#include "msvc_fixes.h"
|
||||
#include "BinaryImage.h"
|
||||
#include "libdis.h"
|
||||
#include "Enums.h"
|
||||
#include "state.h" // State depends on INDEXBASE, but later need STATE
|
||||
#include "CallConvention.h"
|
||||
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <QtCore/QString>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <bitset>
|
||||
#include <llvm/ADT/ilist.h>
|
||||
#include <llvm/ADT/ilist_node.h>
|
||||
#include <llvm/CodeGen/MachineInstr.h>
|
||||
#include <llvm/MC/MCInst.h>
|
||||
#include <llvm/MC/MCAsmInfo.h>
|
||||
#include <llvm/Value.h>
|
||||
#include <llvm/Instruction.h>
|
||||
#include <boost/range.hpp>
|
||||
#include "libdis.h"
|
||||
#include "Enums.h"
|
||||
#include "state.h" // State depends on INDEXBASE, but later need STATE
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <initializer_list>
|
||||
|
||||
//enum condId;
|
||||
|
||||
@ -25,13 +27,97 @@ struct LOCAL_ID;
|
||||
struct BB;
|
||||
struct Function;
|
||||
struct STKFRAME;
|
||||
struct CIcodeRec;
|
||||
class CIcodeRec;
|
||||
struct ICODE;
|
||||
struct bundle;
|
||||
typedef std::list<ICODE>::iterator iICODE;
|
||||
typedef std::list<ICODE>::reverse_iterator riICODE;
|
||||
typedef boost::iterator_range<iICODE> rCODE;
|
||||
extern std::bitset<32> duReg[30];
|
||||
|
||||
struct LivenessSet
|
||||
{
|
||||
std::set<eReg> registers;
|
||||
public:
|
||||
LivenessSet(const std::initializer_list<eReg> &init) : registers(init) {}
|
||||
LivenessSet() {}
|
||||
LivenessSet(const LivenessSet &other) : registers(other.registers)
|
||||
{
|
||||
}
|
||||
void reset()
|
||||
{
|
||||
registers.clear();
|
||||
}
|
||||
|
||||
// LivenessSet(LivenessSet &&other) : LivenessSet()
|
||||
// {
|
||||
// swap(*this,other);
|
||||
// }
|
||||
LivenessSet &operator=(LivenessSet other)
|
||||
{
|
||||
swap(*this,other);
|
||||
return *this;
|
||||
}
|
||||
friend void swap(LivenessSet& first, LivenessSet& second) // nothrow
|
||||
{
|
||||
std::swap(first.registers, second.registers);
|
||||
}
|
||||
LivenessSet &operator|=(const LivenessSet &other)
|
||||
{
|
||||
registers.insert(other.registers.begin(),other.registers.end());
|
||||
return *this;
|
||||
}
|
||||
LivenessSet &operator&=(const LivenessSet &other)
|
||||
{
|
||||
std::set<eReg> res;
|
||||
std::set_intersection(registers.begin(),registers.end(),
|
||||
other.registers.begin(),other.registers.end(),
|
||||
std::inserter(res, res.end()));
|
||||
registers = res;
|
||||
return *this;
|
||||
}
|
||||
LivenessSet &operator-=(const LivenessSet &other)
|
||||
{
|
||||
std::set<eReg> res;
|
||||
std::set_difference(registers.begin(),registers.end(),
|
||||
other.registers.begin(),other.registers.end(),
|
||||
std::inserter(res, res.end()));
|
||||
registers = res;
|
||||
return *this;
|
||||
}
|
||||
LivenessSet operator-(const LivenessSet &other) const
|
||||
{
|
||||
return LivenessSet(*this) -= other;
|
||||
}
|
||||
LivenessSet operator+(const LivenessSet &other) const
|
||||
{
|
||||
return LivenessSet(*this) |= other;
|
||||
}
|
||||
LivenessSet operator &(const LivenessSet &other) const
|
||||
{
|
||||
return LivenessSet(*this) &= other;
|
||||
}
|
||||
bool any() const
|
||||
{
|
||||
return not registers.empty();
|
||||
}
|
||||
bool operator==(const LivenessSet &other) const
|
||||
{
|
||||
return registers==other.registers;
|
||||
}
|
||||
bool operator!=(const LivenessSet &other) const { return not(*this==other);}
|
||||
|
||||
LivenessSet &setReg(int r);
|
||||
LivenessSet &addReg(int r);
|
||||
bool testReg(int r) const
|
||||
{
|
||||
return registers.find(eReg(r))!=registers.end();
|
||||
}
|
||||
bool testRegAndSubregs(int r) const;
|
||||
LivenessSet &clrReg(int r);
|
||||
private:
|
||||
void postProcessCompositeRegs();
|
||||
};
|
||||
|
||||
/* uint8_t and uint16_t registers */
|
||||
|
||||
/* Def/use of flags - low 4 bits represent flags */
|
||||
@ -45,14 +131,16 @@ struct DU
|
||||
#define MAX_REGS_DEF 4 /* 2 regs def'd for long-reg vars */
|
||||
|
||||
|
||||
struct COND_EXPR;
|
||||
struct Expr;
|
||||
struct AstIdent;
|
||||
struct UnaryOperator;
|
||||
struct HlTypeSupport
|
||||
{
|
||||
//hlIcode opcode; /* hlIcode opcode */
|
||||
virtual bool removeRegFromLong(eReg regi, LOCAL_ID *locId)=0;
|
||||
virtual std::string writeOut(Function *pProc, int *numLoc)=0;
|
||||
virtual bool removeRegFromLong(eReg regi, LOCAL_ID *locId)=0;
|
||||
virtual QString writeOut(Function *pProc, int *numLoc) const=0;
|
||||
protected:
|
||||
void performLongRemoval (eReg regi, LOCAL_ID *locId, COND_EXPR *tree);
|
||||
Expr * performLongRemoval (eReg regi, LOCAL_ID *locId, Expr *tree);
|
||||
};
|
||||
|
||||
struct CallType : public HlTypeSupport
|
||||
@ -61,41 +149,41 @@ struct CallType : public HlTypeSupport
|
||||
Function * proc;
|
||||
STKFRAME * args; // actual arguments
|
||||
void allocStkArgs (int num);
|
||||
bool newStkArg(COND_EXPR *exp, llIcode opcode, Function *pproc);
|
||||
void placeStkArg(COND_EXPR *exp, int pos);
|
||||
virtual COND_EXPR * toId();
|
||||
bool newStkArg(Expr *exp, llIcode opcode, Function *pproc);
|
||||
void placeStkArg(Expr *exp, int pos);
|
||||
virtual Expr * toAst();
|
||||
public:
|
||||
bool removeRegFromLong(eReg regi, LOCAL_ID *locId)
|
||||
bool removeRegFromLong(eReg /*regi*/, LOCAL_ID * /*locId*/)
|
||||
{
|
||||
printf("CallType : removeRegFromLong not supproted");
|
||||
printf("CallType : removeRegFromLong not supproted\n");
|
||||
return false;
|
||||
}
|
||||
std::string writeOut(Function *pProc, int *numLoc);
|
||||
QString writeOut(Function *pProc, int *numLoc) const;
|
||||
};
|
||||
struct AssignType : public HlTypeSupport
|
||||
{
|
||||
/* for HLI_ASSIGN */
|
||||
COND_EXPR *lhs;
|
||||
COND_EXPR *rhs;
|
||||
AssignType() : lhs(0),rhs(0) {}
|
||||
bool removeRegFromLong(eReg regi, LOCAL_ID *locId)
|
||||
{
|
||||
performLongRemoval(regi,locId,lhs);
|
||||
return true;
|
||||
}
|
||||
std::string writeOut(Function *pProc, int *numLoc);
|
||||
protected:
|
||||
public:
|
||||
Expr * m_lhs;
|
||||
Expr * m_rhs;
|
||||
AssignType() {}
|
||||
Expr *lhs() const {return m_lhs;}
|
||||
void lhs(Expr *l);
|
||||
bool removeRegFromLong(eReg regi, LOCAL_ID *locId);
|
||||
QString writeOut(Function *pProc, int *numLoc) const;
|
||||
};
|
||||
struct ExpType : public HlTypeSupport
|
||||
{
|
||||
/* for HLI_JCOND, HLI_RET, HLI_PUSH, HLI_POP*/
|
||||
COND_EXPR *v;
|
||||
ExpType() : v(0) {}
|
||||
Expr * v;
|
||||
ExpType() : v(nullptr) {}
|
||||
bool removeRegFromLong(eReg regi, LOCAL_ID *locId)
|
||||
{
|
||||
performLongRemoval(regi,locId,v);
|
||||
v=performLongRemoval(regi,locId,v);
|
||||
return true;
|
||||
}
|
||||
std::string writeOut(Function *pProc, int *numLoc);
|
||||
QString writeOut(Function *pProc, int *numLoc) const;
|
||||
};
|
||||
|
||||
struct HLTYPE
|
||||
@ -106,35 +194,27 @@ public:
|
||||
hlIcode opcode; /* hlIcode opcode */
|
||||
AssignType asgn;
|
||||
CallType call;
|
||||
HlTypeSupport *get()
|
||||
HlTypeSupport *get();
|
||||
const HlTypeSupport *get() const
|
||||
{
|
||||
switch(opcode)
|
||||
{
|
||||
case HLI_ASSIGN: return &asgn;
|
||||
case HLI_RET:
|
||||
case HLI_POP:
|
||||
case HLI_JCOND:
|
||||
case HLI_PUSH: return &exp;
|
||||
case HLI_CALL: return &call;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return const_cast<const HlTypeSupport *>(const_cast<HLTYPE*>(this)->get());
|
||||
}
|
||||
|
||||
void expr(COND_EXPR *e)
|
||||
void expr(Expr *e)
|
||||
{
|
||||
assert(e);
|
||||
exp.v=e;
|
||||
}
|
||||
void replaceExpr(COND_EXPR *e)
|
||||
Expr *getMyExpr()
|
||||
{
|
||||
assert(e);
|
||||
delete exp.v;
|
||||
exp.v=e;
|
||||
if(opcode==HLI_CALL)
|
||||
return call.toAst();
|
||||
return expr();
|
||||
}
|
||||
COND_EXPR * expr() { return exp.v;}
|
||||
const COND_EXPR * const expr() const { return exp.v;}
|
||||
void set(hlIcode i,COND_EXPR *e)
|
||||
void replaceExpr(Expr *e);
|
||||
Expr * expr() { return exp.v;}
|
||||
const Expr * expr() const { return exp.v;}
|
||||
void set(hlIcode i,Expr *e)
|
||||
{
|
||||
if(i!=HLI_RET)
|
||||
assert(e);
|
||||
@ -142,106 +222,128 @@ public:
|
||||
opcode=i;
|
||||
exp.v=e;
|
||||
}
|
||||
void set(COND_EXPR *l,COND_EXPR *r)
|
||||
{
|
||||
assert(l);
|
||||
assert(r);
|
||||
opcode = HLI_ASSIGN;
|
||||
assert((asgn.lhs==0) and (asgn.rhs==0)); //prevent memory leaks
|
||||
asgn.lhs=l;
|
||||
asgn.rhs=r;
|
||||
}
|
||||
void set(Expr *l,Expr *r);
|
||||
void setCall(Function *proc);
|
||||
HLTYPE(hlIcode op=HLI_INVALID) : opcode(op)
|
||||
{}
|
||||
// HLTYPE() // help valgrind find uninitialized HLTYPES
|
||||
// {}
|
||||
HLTYPE & operator=(const HLTYPE &l)
|
||||
{
|
||||
exp=l.exp;
|
||||
opcode=l.opcode;
|
||||
asgn=l.asgn;
|
||||
call=l.call;
|
||||
exp = l.exp;
|
||||
opcode = l.opcode;
|
||||
asgn = l.asgn;
|
||||
call = l.call;
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
std::string write1HlIcode(Function *pProc, int *numLoc);
|
||||
void setAsgn(COND_EXPR *lhs, COND_EXPR *rhs);
|
||||
QString write1HlIcode(Function *pProc, int *numLoc) const;
|
||||
void setAsgn(Expr *lhs, Expr *rhs);
|
||||
} ;
|
||||
/* LOW_LEVEL icode operand record */
|
||||
struct LLOperand
|
||||
{
|
||||
llvm::MCOperand llvm_op;
|
||||
eReg seg; /* CS, DS, ES, SS */
|
||||
eReg segOver; /* CS, DS, ES, SS if segment override */
|
||||
int16_t segValue; /* Value of segment seg during analysis */
|
||||
eReg regi; /* 0 < regs < INDEXBASE <= index modes */
|
||||
int16_t off; /* memory address offset */
|
||||
uint32_t opz; /* idx of immed src op */
|
||||
bool immed;
|
||||
bool is_offset; // set by jumps
|
||||
bool is_compound;
|
||||
size_t width;
|
||||
//union {/* Source operand if (flg & I) */
|
||||
struct { /* Call & # actual arg bytes */
|
||||
Function *proc; /* pointer to target proc (for CALL(F))*/
|
||||
int cb; /* # actual arg bytes */
|
||||
} proc;
|
||||
LLOperand() : seg(rUNDEF),segValue(0),segOver(rUNDEF),regi(rUNDEF),off(0),opz(0)
|
||||
LLOperand() : seg(rUNDEF),segOver(rUNDEF),segValue(0),regi(rUNDEF),off(0),
|
||||
opz(0),immed(0),is_offset(false),is_compound(0),width(0)
|
||||
{
|
||||
proc.proc=0;
|
||||
proc.cb=0;
|
||||
}
|
||||
LLOperand(eReg r,size_t w) : LLOperand()
|
||||
{
|
||||
regi=r;
|
||||
width=w;
|
||||
}
|
||||
bool operator==(const LLOperand &with) const
|
||||
{
|
||||
return (seg==with.seg) and
|
||||
(segOver==with.segOver) and
|
||||
(segValue==with.segValue) and
|
||||
(regi == with.regi) and
|
||||
(off == with.off) and
|
||||
(opz==with.opz) and
|
||||
(proc.proc==with.proc.proc);
|
||||
}
|
||||
int64_t getImm2() const {return opz;}
|
||||
void SetImmediateOp(uint32_t dw)
|
||||
{
|
||||
opz=dw;
|
||||
}
|
||||
eReg getReg2() {return regi;}
|
||||
eReg getReg2() const {return regi;}
|
||||
bool isReg() const;
|
||||
static LLOperand CreateImm2(int64_t Val)
|
||||
static LLOperand CreateImm2(int64_t Val,uint8_t wdth=2)
|
||||
{
|
||||
LLOperand Op;
|
||||
//Op.Kind = kImmediate;
|
||||
//Op.ImmVal = Val;
|
||||
Op.immed=true;
|
||||
Op.opz = Val;
|
||||
Op.width = wdth;
|
||||
return Op;
|
||||
}
|
||||
static LLOperand CreateReg2(unsigned Val)
|
||||
{
|
||||
LLOperand Op;
|
||||
// Op.Kind = kRegister;
|
||||
// Op.RegVal = Reg;
|
||||
Op.regi = (eReg)Val;
|
||||
return Op;
|
||||
}
|
||||
void addProcInformation(int param_count,uint32_t call_conv);
|
||||
bool isSet()
|
||||
{
|
||||
return not (*this == LLOperand());
|
||||
}
|
||||
void addProcInformation(int param_count, CConv::Type call_conv);
|
||||
bool isImmediate() const { return immed;}
|
||||
void setImmediate(bool x) { immed=x;}
|
||||
bool compound() const {return is_compound;} // dx:ax pair
|
||||
size_t byteWidth() const { assert(width<=4); return width;}
|
||||
};
|
||||
struct LLInst : public llvm::MCInst //: public llvm::ilist_node<LLInst>
|
||||
struct LLInst
|
||||
{
|
||||
protected:
|
||||
uint32_t flg; /* icode flags */
|
||||
LLOperand m_src; /* source operand */
|
||||
llIcode m_opcode; // Low level opcode identifier
|
||||
uint32_t flg; /* icode flags */
|
||||
LLOperand m_src; /* source operand */
|
||||
public:
|
||||
int codeIdx; /* Index into cCode.code */
|
||||
uint8_t numBytes; /* Number of bytes this instr */
|
||||
uint32_t label; /* offset in image (20-bit adr) */
|
||||
LLOperand dst; /* destination operand */
|
||||
DU flagDU; /* def/use of flags */
|
||||
int caseEntry;
|
||||
int codeIdx; /* Index into cCode.code */
|
||||
uint8_t numBytes; /* Number of bytes this instr */
|
||||
uint32_t label; /* offset in image (20-bit adr) */
|
||||
LLOperand m_dst; /* destination operand */
|
||||
DU flagDU; /* def/use of flags */
|
||||
int caseEntry;
|
||||
std::vector<uint32_t> caseTbl2;
|
||||
int hllLabNum; /* label # for hll codegen */
|
||||
bool conditionalJump()
|
||||
{
|
||||
return (getOpcode() >= iJB) && (getOpcode() < iJCXZ);
|
||||
}
|
||||
bool testFlags(uint32_t x) const { return (flg & x)!=0;}
|
||||
void setFlags(uint32_t flag) {flg |= flag;}
|
||||
void clrFlags(uint32_t flag)
|
||||
{
|
||||
if(getOpcode()==iMOD)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
flg &= ~flag;
|
||||
}
|
||||
uint32_t getFlag() const {return flg;}
|
||||
//llIcode getOpcode() const { return opcode; }
|
||||
|
||||
uint32_t GetLlLabel() const { return label;}
|
||||
llIcode getOpcode() const { return m_opcode;}
|
||||
void setOpcode(uint32_t op) { m_opcode=(llIcode)op; }
|
||||
bool conditionalJump()
|
||||
{
|
||||
return (getOpcode() >= iJB) and (getOpcode() < iJCXZ);
|
||||
}
|
||||
bool testFlags(uint32_t x) const { return (flg & x)!=0;}
|
||||
void setFlags(uint32_t flag) {flg |= flag;}
|
||||
void clrFlags(uint32_t flag)
|
||||
{
|
||||
if(getOpcode()==iMOD)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
flg &= ~flag;
|
||||
}
|
||||
uint32_t getFlag() const {return flg;}
|
||||
uint32_t GetLlLabel() const { return label;}
|
||||
|
||||
void SetImmediateOp(uint32_t dw) {m_src.SetImmediateOp(dw);}
|
||||
|
||||
@ -250,25 +352,29 @@ public:
|
||||
{
|
||||
return (getOpcode()==op);
|
||||
}
|
||||
bool matchWithRegDst(llIcode op)
|
||||
{
|
||||
return (getOpcode()==op) and m_dst.isReg();
|
||||
}
|
||||
bool match(llIcode op,eReg dest)
|
||||
{
|
||||
return (getOpcode()==op)&&dst.regi==dest;
|
||||
return (getOpcode()==op)&&m_dst.regi==dest;
|
||||
}
|
||||
bool match(llIcode op,eReg dest,uint32_t flgs)
|
||||
{
|
||||
return (getOpcode()==op) and (dst.regi==dest) and testFlags(flgs);
|
||||
return (getOpcode()==op) and (m_dst.regi==dest) and testFlags(flgs);
|
||||
}
|
||||
bool match(llIcode op,eReg dest,eReg src_reg)
|
||||
{
|
||||
return (getOpcode()==op)&&(dst.regi==dest)&&(m_src.regi==src_reg);
|
||||
return (getOpcode()==op) and (m_dst.regi==dest) and (m_src.regi==src_reg);
|
||||
}
|
||||
bool match(eReg dest,eReg src_reg)
|
||||
{
|
||||
return (dst.regi==dest)&&(m_src.regi==src_reg);
|
||||
return (m_dst.regi==dest) and (m_src.regi==src_reg);
|
||||
}
|
||||
bool match(eReg dest)
|
||||
{
|
||||
return (dst.regi==dest);
|
||||
return (m_dst.regi==dest);
|
||||
}
|
||||
bool match(llIcode op,uint32_t flgs)
|
||||
{
|
||||
@ -279,15 +385,27 @@ public:
|
||||
setOpcode(op);
|
||||
flg =flags;
|
||||
}
|
||||
void set(llIcode op,uint32_t flags,eReg dst_reg)
|
||||
{
|
||||
setOpcode(op);
|
||||
m_dst = LLOperand::CreateReg2(dst_reg);
|
||||
flg =flags;
|
||||
}
|
||||
void set(llIcode op,uint32_t flags,eReg dst_reg,const LLOperand &src_op)
|
||||
{
|
||||
setOpcode(op);
|
||||
m_dst = LLOperand::CreateReg2(dst_reg);
|
||||
m_src = src_op;
|
||||
flg =flags;
|
||||
}
|
||||
void emitGotoLabel(int indLevel);
|
||||
void findJumpTargets(CIcodeRec &_pc);
|
||||
void writeIntComment(std::ostringstream &s);
|
||||
void writeIntComment(QTextStream & s);
|
||||
void dis1Line(int loc_ip, int pass);
|
||||
std::ostringstream &strSrc(std::ostringstream &os,bool skip_comma=false);
|
||||
QTextStream & strSrc(QTextStream & os, bool skip_comma=false);
|
||||
|
||||
void flops(std::ostringstream &out);
|
||||
void flops(QTextStream & out);
|
||||
bool isJmpInst();
|
||||
HLTYPE toHighLevel(COND_EXPR *lhs, COND_EXPR *rhs, Function *func);
|
||||
HLTYPE createCall();
|
||||
LLInst(ICODE *container) : flg(0),codeIdx(0),numBytes(0),m_link(container)
|
||||
{
|
||||
@ -309,16 +427,16 @@ public:
|
||||
}
|
||||
void replaceDst(const LLOperand &with)
|
||||
{
|
||||
dst = with;
|
||||
}
|
||||
void replaceDst(eReg r)
|
||||
{
|
||||
dst = LLOperand::CreateReg2(r);
|
||||
m_dst = with;
|
||||
}
|
||||
// void replaceDst(eReg r)
|
||||
// {
|
||||
// dst = LLOperand::CreateReg2(r);
|
||||
// }
|
||||
ICODE *m_link;
|
||||
condId idType(opLoc sd) const;
|
||||
const LLOperand * get(opLoc sd) const { return (sd == SRC) ? &src() : &dst; }
|
||||
LLOperand * get(opLoc sd) { return (sd == SRC) ? &src() : &dst; }
|
||||
const LLOperand * get(opLoc sd) const { return (sd == SRC) ? &src() : &m_dst; }
|
||||
LLOperand * get(opLoc sd) { return (sd == SRC) ? &src() : &m_dst; }
|
||||
};
|
||||
|
||||
/* Icode definition: LOW_LEVEL and HIGH_LEVEL */
|
||||
@ -342,17 +460,17 @@ public:
|
||||
template<int TYPE>
|
||||
struct TypeFilter
|
||||
{
|
||||
bool operator()(ICODE *ic) {return ic->type==HIGH_LEVEL;}
|
||||
bool operator()(ICODE &ic) {return ic.type==HIGH_LEVEL;}
|
||||
bool operator()(ICODE *ic) {return ic->type==TYPE;}
|
||||
bool operator()(ICODE &ic) {return ic.type==TYPE;}
|
||||
};
|
||||
template<int TYPE>
|
||||
struct TypeAndValidFilter
|
||||
{
|
||||
bool operator()(ICODE *ic) {return (ic->type==HIGH_LEVEL)&&(ic->valid());}
|
||||
bool operator()(ICODE &ic) {return (ic.type==HIGH_LEVEL)&&ic.valid();}
|
||||
bool operator()(ICODE *ic) {return (ic->type==TYPE) and (ic->valid());}
|
||||
bool operator()(ICODE &ic) {return (ic.type==TYPE) and ic.valid();}
|
||||
};
|
||||
static TypeFilter<HIGH_LEVEL> select_high_level;
|
||||
static TypeAndValidFilter<HIGH_LEVEL> select_valid_high_level;
|
||||
static TypeFilter<HIGH_LEVEL_ICODE> select_high_level;
|
||||
static TypeAndValidFilter<HIGH_LEVEL_ICODE> select_valid_high_level;
|
||||
/* Def/Use of registers and stack variables */
|
||||
struct DU_ICODE
|
||||
{
|
||||
@ -362,18 +480,21 @@ public:
|
||||
use.reset();
|
||||
lastDefRegi.reset();
|
||||
}
|
||||
std::bitset<32> def; // For Registers: position in bitset is reg index
|
||||
std::bitset<32> use; // For Registers: position in uint32_t is reg index
|
||||
std::bitset<32> lastDefRegi;// Bit set if last def of this register in BB
|
||||
LivenessSet def; // For Registers: position in bitset is reg index
|
||||
LivenessSet use; // For Registers: position in uint32_t is reg index
|
||||
LivenessSet lastDefRegi;// Bit set if last def of this register in BB
|
||||
void addDefinedAndUsed(eReg r)
|
||||
{
|
||||
def |= duReg[r];
|
||||
use |= duReg[r];
|
||||
|
||||
def.addReg(r);
|
||||
use.addReg(r);
|
||||
}
|
||||
};
|
||||
struct DU1
|
||||
{
|
||||
protected:
|
||||
int numRegsDef; /* # registers defined by this inst */
|
||||
|
||||
public:
|
||||
struct Use
|
||||
{
|
||||
int Reg; // used register
|
||||
@ -385,11 +506,10 @@ public:
|
||||
if(iter==uses.end())
|
||||
return;
|
||||
uses.erase(iter);
|
||||
assert("Same user more then once!" && uses.end()==std::find(uses.begin(),uses.end(),us));
|
||||
assert("Same user more then once!" and uses.end()==std::find(uses.begin(),uses.end(),us));
|
||||
}
|
||||
|
||||
};
|
||||
int numRegsDef; /* # registers defined by this inst */
|
||||
uint8_t regi[MAX_REGS_DEF+1]; /* registers defined by this inst */
|
||||
Use idx[MAX_REGS_DEF+1];
|
||||
//int idx[MAX_REGS_DEF][MAX_USES]; /* inst that uses this def */
|
||||
@ -414,20 +534,33 @@ public:
|
||||
Use &u(idx[regIdx]);
|
||||
u.removeUser(ic);
|
||||
}
|
||||
int getNumRegsDef() const {return numRegsDef;}
|
||||
void clearAllDefs() {numRegsDef=0;}
|
||||
DU1 &addDef(eReg r) {numRegsDef++; return *this;}
|
||||
DU1 &setDef(eReg r) {numRegsDef=1; return *this;}
|
||||
void removeDef(eReg r) {numRegsDef--;}
|
||||
DU1() : numRegsDef(0)
|
||||
{
|
||||
}
|
||||
};
|
||||
icodeType type; /* Icode type */
|
||||
DU_ICODE du; /* Def/use regs/vars */
|
||||
DU1 du1; /* du chain 1 */
|
||||
DU_ICODE du; /* Def/use regs/vars */
|
||||
DU1 du1; /* du chain 1 */
|
||||
int loc_ip; // used by CICodeRec to number ICODEs
|
||||
|
||||
LLInst * ll() { return &m_ll;}
|
||||
const LLInst * ll() const { return &m_ll;}
|
||||
|
||||
HLTYPE * hl() { return &m_hl;}
|
||||
const HLTYPE * hl() const { return &m_hl;}
|
||||
HLTYPE * hlU() {
|
||||
// assert(type==HIGH_LEVEL);
|
||||
// assert(m_hl.opcode!=HLI_INVALID);
|
||||
return &m_hl;
|
||||
}
|
||||
const HLTYPE * hl() const {
|
||||
// assert(type==HIGH_LEVEL);
|
||||
// assert(m_hl.opcode!=HLI_INVALID);
|
||||
return &m_hl;
|
||||
}
|
||||
void hl(const HLTYPE &v) { m_hl=v;}
|
||||
|
||||
void setRegDU(eReg regi, operDu du_in);
|
||||
@ -437,13 +570,13 @@ public:
|
||||
condId idType(opLoc sd);
|
||||
// HLL setting functions
|
||||
// set this icode to be an assign
|
||||
void setAsgn(COND_EXPR *lhs, COND_EXPR *rhs)
|
||||
void setAsgn(Expr *lhs, Expr *rhs)
|
||||
{
|
||||
type=HIGH_LEVEL;
|
||||
hl()->setAsgn(lhs,rhs);
|
||||
type=HIGH_LEVEL_ICODE;
|
||||
hlU()->setAsgn(lhs,rhs);
|
||||
}
|
||||
void setUnary(hlIcode op, COND_EXPR *_exp);
|
||||
void setJCond(COND_EXPR *cexp);
|
||||
void setUnary(hlIcode op, Expr *_exp);
|
||||
void setJCond(Expr *cexp);
|
||||
|
||||
void emitGotoLabel(int indLevel);
|
||||
void copyDU(const ICODE &duIcode, operDu _du, operDu duDu);
|
||||
@ -452,39 +585,38 @@ public:
|
||||
public:
|
||||
bool removeDefRegi(eReg regi, int thisDefIdx, LOCAL_ID *locId);
|
||||
void checkHlCall();
|
||||
bool newStkArg(COND_EXPR *exp, llIcode opcode, Function *pproc)
|
||||
bool newStkArg(Expr *exp, llIcode opcode, Function *pproc)
|
||||
{
|
||||
return hl()->call.newStkArg(exp,opcode,pproc);
|
||||
return hlU()->call.newStkArg(exp,opcode,pproc);
|
||||
}
|
||||
ICODE() : m_ll(this),type(NOT_SCANNED),Parent(0),loc_ip(0),invalid(false)
|
||||
ICODE() : m_ll(this),Parent(0),invalid(false),type(NOT_SCANNED_ICODE),loc_ip(0)
|
||||
{
|
||||
}
|
||||
public:
|
||||
const MachineBasicBlock* getParent() const { return Parent; }
|
||||
MachineBasicBlock* getParent() { return Parent; }
|
||||
//unsigned getNumOperands() const { return (unsigned)Operands.size(); }
|
||||
const MachineBasicBlock* getParent() const { return Parent; }
|
||||
MachineBasicBlock* getParent() { return Parent; }
|
||||
//unsigned getNumOperands() const { return (unsigned)Operands.size(); }
|
||||
|
||||
};
|
||||
/** Map n low level instructions to m high level instructions
|
||||
*/
|
||||
struct MappingLLtoML
|
||||
{
|
||||
typedef llvm::iplist<llvm::Instruction> InstListType;
|
||||
typedef boost::iterator_range<iICODE> rSourceRange;
|
||||
typedef boost::iterator_range<InstListType::iterator> rTargetRange;
|
||||
rSourceRange m_low_level;
|
||||
rTargetRange m_middle_level;
|
||||
};
|
||||
//struct MappingLLtoML
|
||||
//{
|
||||
// typedef boost::iterator_range<iICODE> rSourceRange;
|
||||
// typedef boost::iterator_range<InstListType::iterator> rTargetRange;
|
||||
// rSourceRange m_low_level;
|
||||
// rTargetRange m_middle_level;
|
||||
//};
|
||||
// This is the icode array object.
|
||||
class CIcodeRec : public std::list<ICODE>
|
||||
{
|
||||
public:
|
||||
CIcodeRec(); // Constructor
|
||||
|
||||
ICODE * addIcode(ICODE *pIcode);
|
||||
void SetInBB(rCODE &rang, BB* pnewBB);
|
||||
bool labelSrch(uint32_t target, uint32_t &pIndex);
|
||||
ICODE * addIcode(ICODE *pIcode);
|
||||
void SetInBB(rCODE &rang, BB* pnewBB);
|
||||
bool labelSrch(uint32_t target, uint32_t &pIndex);
|
||||
iterator labelSrch(uint32_t target);
|
||||
ICODE * GetIcode(int ip);
|
||||
ICODE * GetIcode(size_t ip);
|
||||
bool alreadyDecoded(uint32_t target);
|
||||
};
|
||||
|
||||
@ -37,6 +37,8 @@ struct Idiom18 : public Idiom
|
||||
protected:
|
||||
iICODE m_icodes[4];
|
||||
bool m_is_dec;
|
||||
/* type of variable: 1 = reg-var, 2 = local */
|
||||
int m_idiom_type;
|
||||
public:
|
||||
Idiom18(Function *f) : Idiom(f)
|
||||
{
|
||||
@ -64,7 +66,7 @@ struct Idiom20 : public Idiom
|
||||
{
|
||||
protected:
|
||||
iICODE m_icodes[4];
|
||||
bool m_is_dec;
|
||||
condNodeType m_is_dec;
|
||||
public:
|
||||
Idiom20(Function *f) : Idiom(f)
|
||||
{
|
||||
|
||||
11
include/loader.h
Normal file
11
include/loader.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
class ILoader
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
class LoaderManger
|
||||
{
|
||||
|
||||
};
|
||||
@ -6,102 +6,144 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "msvc_fixes.h"
|
||||
#include "types.h"
|
||||
#include "Enums.h"
|
||||
#include "machine_x86.h"
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include "types.h"
|
||||
#include "Enums.h"
|
||||
#include "machine_x86.h"
|
||||
|
||||
/* Type definition */
|
||||
// this array has to stay in-order of addition i.e. not std::set<iICODE,std::less<iICODE> >
|
||||
// TODO: why ?
|
||||
struct COND_EXPR;
|
||||
struct Expr;
|
||||
struct AstIdent;
|
||||
struct ICODE;
|
||||
struct LLInst;
|
||||
typedef std::list<ICODE>::iterator iICODE;
|
||||
struct IDX_ARRAY : public std::vector<iICODE>
|
||||
{
|
||||
bool inList(iICODE idx)
|
||||
bool inList(iICODE idx) const
|
||||
{
|
||||
return std::find(begin(),end(),idx)!=end();
|
||||
}
|
||||
};
|
||||
|
||||
typedef enum
|
||||
enum frameType
|
||||
{
|
||||
STK_FRAME, /* For stack vars */
|
||||
REG_FRAME, /* For register variables */
|
||||
GLB_FRAME /* For globals */
|
||||
} frameType;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
struct BWGLB_TYPE
|
||||
{
|
||||
int16_t seg; /* segment value */
|
||||
int16_t off; /* offset */
|
||||
eReg regi; /* optional indexed register */
|
||||
} BWGLB_TYPE;
|
||||
} ;
|
||||
|
||||
|
||||
typedef struct
|
||||
{ /* For TYPE_LONG_(UN)SIGN on the stack */
|
||||
/* For TYPE_LONG_(UN)SIGN on the stack */
|
||||
struct LONG_STKID_TYPE
|
||||
{
|
||||
int offH; /* high offset from BP */
|
||||
int offL; /* low offset from BP */
|
||||
} LONG_STKID_TYPE;
|
||||
LONG_STKID_TYPE(int h,int l) : offH(h),offL(l) {}
|
||||
};
|
||||
/* For TYPE_LONG_(UN)SIGN registers */
|
||||
struct LONGID_TYPE
|
||||
{ /* For TYPE_LONG_(UN)SIGN registers */
|
||||
eReg h; /* high register */
|
||||
eReg l; /* low register */
|
||||
{
|
||||
protected:
|
||||
eReg m_h; /* high register */
|
||||
eReg m_l; /* low register */
|
||||
public:
|
||||
void set(eReg highpart,eReg lowpart)
|
||||
{
|
||||
m_h = highpart;
|
||||
m_l = lowpart;
|
||||
}
|
||||
eReg l() const { return m_l; }
|
||||
eReg h() const { return m_h; }
|
||||
bool srcDstRegMatch(iICODE a,iICODE b) const;
|
||||
LONGID_TYPE() {} // uninitializing constructor to help valgrind catch uninit accesses
|
||||
LONGID_TYPE(eReg h,eReg l) : m_h(h),m_l(l) {}
|
||||
};
|
||||
|
||||
|
||||
struct LONGGLB_TYPE /* For TYPE_LONG_(UN)SIGN globals */
|
||||
{
|
||||
int16_t seg; /* segment value */
|
||||
int16_t offH; /* offset high */
|
||||
int16_t offL; /* offset low */
|
||||
uint8_t regi; /* optional indexed register */
|
||||
LONGGLB_TYPE(int16_t _seg,int16_t _H,int16_t _L,int8_t _reg=0)
|
||||
{
|
||||
seg=_seg;
|
||||
offH=_H;
|
||||
offL=_L;
|
||||
regi=_reg;
|
||||
}
|
||||
};
|
||||
/* ID, LOCAL_ID */
|
||||
struct ID
|
||||
{
|
||||
protected:
|
||||
LONGID_TYPE m_longId; /* For TYPE_LONG_(UN)SIGN registers */
|
||||
public:
|
||||
hlType type; /* Probable type */
|
||||
bool illegal; /* Boolean: not a valid field any more */
|
||||
//std::vector<iICODE> idx;
|
||||
IDX_ARRAY idx; /* Index into icode array (REG_FRAME only) */
|
||||
frameType loc; /* Frame location */
|
||||
bool illegal; /* Boolean: not a valid field any more */
|
||||
bool hasMacro; /* Identifier requires a macro */
|
||||
char macro[10]; /* Macro for this identifier */
|
||||
std::string name; /* Identifier's name */
|
||||
union { /* Different types of identifiers */
|
||||
eReg regi; /* For TYPE_BYTE(uint16_t)_(UN)SIGN registers */
|
||||
struct { /* For TYPE_BYTE(uint16_t)_(UN)SIGN on the stack */
|
||||
QString name; /* Identifier's name */
|
||||
union ID_UNION { /* Different types of identifiers */
|
||||
friend struct ID;
|
||||
protected:
|
||||
LONG_STKID_TYPE longStkId; /* For TYPE_LONG_(UN)SIGN on the stack */
|
||||
public:
|
||||
eReg regi; /* For TYPE_BYTE(WORD)_(UN)SIGN registers */
|
||||
struct { /* For TYPE_BYTE(WORD)_(UN)SIGN on the stack */
|
||||
uint8_t regOff; /* register offset (if any) */
|
||||
int off; /* offset from BP */
|
||||
} bwId;
|
||||
} bwId;
|
||||
BWGLB_TYPE bwGlb; /* For TYPE_BYTE(uint16_t)_(UN)SIGN globals */
|
||||
LONGID_TYPE longId; /* For TYPE_LONG_(UN)SIGN registers */
|
||||
LONG_STKID_TYPE longStkId; /* For TYPE_LONG_(UN)SIGN on the stack */
|
||||
struct { /* For TYPE_LONG_(UN)SIGN globals */
|
||||
int16_t seg; /* segment value */
|
||||
int16_t offH; /* offset high */
|
||||
int16_t offL; /* offset low */
|
||||
uint8_t regi; /* optional indexed register */
|
||||
} longGlb;
|
||||
LONGGLB_TYPE longGlb;
|
||||
struct { /* For TYPE_LONG_(UN)SIGN constants */
|
||||
uint32_t h; /* high uint16_t */
|
||||
uint32_t l; /* low uint16_t */
|
||||
} longKte;
|
||||
ID_UNION() { /*new (&longStkId) LONG_STKID_TYPE();*/}
|
||||
} id;
|
||||
ID();
|
||||
ID(hlType t, frameType f);
|
||||
bool isSigned() const { return (type==TYPE_BYTE_SIGN)||(type==TYPE_WORD_SIGN)||(type==TYPE_LONG_SIGN);}
|
||||
uint16_t typeBitsize() const
|
||||
{
|
||||
return TypeContainer::typeSize(type)*8;
|
||||
}
|
||||
void setLocalName(int i)
|
||||
{
|
||||
char buf[32];
|
||||
sprintf (buf, "loc%ld", i);
|
||||
name=buf;
|
||||
}
|
||||
|
||||
LONGID_TYPE & longId() {assert(isLong() and loc==REG_FRAME); return m_longId;}
|
||||
const LONGID_TYPE & longId() const {assert(isLong() and loc==REG_FRAME); return m_longId;}
|
||||
LONG_STKID_TYPE & longStkId() {assert(isLong() and loc==STK_FRAME); return id.longStkId;}
|
||||
const LONG_STKID_TYPE & longStkId() const {assert(isLong() and loc==STK_FRAME); return id.longStkId;}
|
||||
ID();
|
||||
ID(hlType t, frameType f);
|
||||
ID(hlType t, const LONGID_TYPE &s);
|
||||
ID(hlType t, const LONG_STKID_TYPE &s);
|
||||
ID(hlType t, const LONGGLB_TYPE &s);
|
||||
bool isSigned() const { return (type==TYPE_BYTE_SIGN) or (type==TYPE_WORD_SIGN) or (type==TYPE_LONG_SIGN);}
|
||||
uint16_t typeBitsize() const
|
||||
{
|
||||
return TypeContainer::typeSize(type)*8;
|
||||
}
|
||||
bool isLong() const { return (type==TYPE_LONG_UNSIGN) or (type==TYPE_LONG_SIGN); }
|
||||
void setLocalName(int i)
|
||||
{
|
||||
char buf[32];
|
||||
sprintf (buf, "loc%d", i);
|
||||
name=buf;
|
||||
}
|
||||
bool isLongRegisterPair() const { return (loc == REG_FRAME) and isLong();}
|
||||
eReg getPairedRegister(eReg first) const;
|
||||
};
|
||||
|
||||
struct LOCAL_ID
|
||||
@ -121,18 +163,19 @@ public:
|
||||
std::vector<ID>::iterator end() {return id_arr.end();}
|
||||
int newByteWordReg(hlType t, eReg regi);
|
||||
int newByteWordStk(hlType t, int off, uint8_t regOff);
|
||||
int newIntIdx(int16_t seg, int16_t off, eReg regi, int ix, hlType t);
|
||||
int newLongReg(hlType t, eReg regH, eReg regL, iICODE ix_);
|
||||
int newIntIdx(int16_t seg, int16_t off, eReg regi, hlType t);
|
||||
int newLongReg(hlType t, const LONGID_TYPE &longT, iICODE ix_);
|
||||
int newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, int off);
|
||||
int newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, LLInst &atOffset);
|
||||
void newIdent(hlType t, frameType f);
|
||||
void flagByteWordId(int off);
|
||||
void propLongId(uint8_t regL, uint8_t regH, const char *name);
|
||||
void propLongId(uint8_t regL, uint8_t regH, const QString & name);
|
||||
size_t csym() const {return id_arr.size();}
|
||||
void newRegArg(iICODE picode, iICODE ticode) const;
|
||||
void processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode, bool isLong) const;
|
||||
void forwardSubs(COND_EXPR *lhs, COND_EXPR *rhs, iICODE picode, iICODE ticode, int &numHlIcodes) const;
|
||||
COND_EXPR *createId(const ID *retVal, iICODE ix_);
|
||||
void newRegArg(ICODE & picode, ICODE & ticode) const;
|
||||
void processTargetIcode(ICODE & picode, int &numHlIcodes, ICODE & ticode, bool isLong) const;
|
||||
void forwardSubs(Expr *lhs, Expr *rhs, ICODE & picode, ICODE & ticode, int &numHlIcodes) const;
|
||||
AstIdent *createId(const ID *retVal, iICODE ix_);
|
||||
eReg getPairedRegisterAt(int idx,eReg first) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <bitset>
|
||||
|
||||
class QTextStream;
|
||||
|
||||
struct LivenessSet;
|
||||
/* Machine registers */
|
||||
enum eReg
|
||||
{
|
||||
@ -32,8 +35,9 @@ enum eReg
|
||||
rBH = 20,
|
||||
|
||||
rTMP= 21, /* temp register for DIV/IDIV/MOD */
|
||||
rTMP2= 22, /* temp register for DIV/IDIV/MOD */
|
||||
/* Indexed modes go from INDEXBASE to INDEXBASE+7 */
|
||||
INDEX_BX_SI = 22, // "bx+si"
|
||||
INDEX_BX_SI = 23, // "bx+si"
|
||||
INDEX_BX_DI, // "bx+di"
|
||||
INDEX_BP_SI, // "bp+si"
|
||||
INDEX_BP_DI, // "bp+di"
|
||||
@ -58,25 +62,20 @@ class Machine_X86 : public SourceMachine
|
||||
public:
|
||||
Machine_X86();
|
||||
virtual ~Machine_X86() {}
|
||||
static const std::string ®Name(eReg r);
|
||||
static const std::string &opcodeName(unsigned r);
|
||||
static const std::string &floatOpName(unsigned r);
|
||||
static const QString & regName(eReg r);
|
||||
static const QString & opcodeName(unsigned r);
|
||||
static const QString & floatOpName(unsigned r);
|
||||
bool physicalReg(eReg r);
|
||||
/* Writes the registers that are set in the bitvector */
|
||||
//TODO: move this into Machine_X86 ?
|
||||
static void writeRegVector (std::ostream &ostr,const std::bitset<32> ®i)
|
||||
{
|
||||
int j;
|
||||
for (j = rAX; j < INDEX_BX_SI; j++)
|
||||
{
|
||||
if (regi.test(j-1))
|
||||
ostr << regName(eReg(j))<<" ";
|
||||
}
|
||||
}
|
||||
static eReg subRegH(eReg reg); //TODO: move these into machine_x86
|
||||
static void writeRegVector (QTextStream & ostr, const LivenessSet ®i);
|
||||
static eReg subRegH(eReg reg);
|
||||
static eReg subRegL(eReg reg);
|
||||
|
||||
static bool isMemOff(eReg r);
|
||||
static bool isSubRegisterOf(eReg reg, eReg parent);
|
||||
static bool hasSubregisters(eReg reg);
|
||||
|
||||
static bool isPartOfComposite(eReg reg);
|
||||
static eReg compositeParent(eReg reg);
|
||||
|
||||
};
|
||||
|
||||
3
include/msvc_fixes.h
Normal file
3
include/msvc_fixes.h
Normal file
@ -0,0 +1,3 @@
|
||||
#ifdef _MSC_VER
|
||||
#include <iso646.h>
|
||||
#endif
|
||||
@ -1,41 +0,0 @@
|
||||
#pragma once
|
||||
/* Perfect hashing function library. Contains functions to generate perfect
|
||||
hashing functions
|
||||
* (C) Mike van Emmerik
|
||||
*/
|
||||
|
||||
//#define bool unsigned char
|
||||
#define uint8_t unsigned char
|
||||
#define uint16_t unsigned short
|
||||
|
||||
/* Prototypes */
|
||||
void hashCleanup(void); /* Frees memory allocated by hashParams() */
|
||||
void map(void); /* Part 1 of creating the tables */
|
||||
|
||||
/* The application must provide these functions: */
|
||||
void getKey(int i, uint8_t **pKeys);/* Set *keys to point to the i+1th key */
|
||||
void dispKey(int i); /* Display the key */
|
||||
class PatternHasher
|
||||
{
|
||||
uint16_t *T1base, *T2base; /* Pointers to start of T1, T2 */
|
||||
int NumEntry; /* Number of entries in the hash table (# keys) */
|
||||
int EntryLen; /* Size (bytes) of each entry (size of keys) */
|
||||
int SetSize; /* Size of the char set */
|
||||
char SetMin; /* First char in the set */
|
||||
int NumVert; /* c times NumEntry */
|
||||
int *graphNode; /* The array of edges */
|
||||
int *graphNext; /* Linked list of edges */
|
||||
int *graphFirst;/* First edge at a vertex */
|
||||
public:
|
||||
uint16_t *readT1(void); /* Returns a pointer to the T1 table */
|
||||
uint16_t *readT2(void); /* Returns a pointer to the T2 table */
|
||||
uint16_t *readG(void); /* Returns a pointer to the g table */
|
||||
void init(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin,int _NumVert); /* Set the parameters for the hash table */
|
||||
void cleanup();
|
||||
int hash(unsigned char *string); //!< Hash the string to an int 0 .. NUMENTRY-1
|
||||
};
|
||||
extern PatternHasher g_pattern_hasher;
|
||||
/* Macro reads a LH uint16_t from the image regardless of host convention */
|
||||
#ifndef LH
|
||||
#define LH(p) ((int)((uint8_t *)(p))[0] + ((int)((uint8_t *)(p))[1] << 8))
|
||||
#endif
|
||||
@ -3,75 +3,72 @@
|
||||
#include <stdint.h>
|
||||
#include <cassert>
|
||||
#include <list>
|
||||
#include <llvm/ADT/ilist.h>
|
||||
#include <boost/icl/interval.hpp>
|
||||
#include <boost/icl/interval_map.hpp>
|
||||
#include <boost/icl/split_interval_map.hpp>
|
||||
#include <unordered_set>
|
||||
#include <QtCore/QString>
|
||||
#include "symtab.h"
|
||||
#include "BinaryImage.h"
|
||||
struct Function;
|
||||
struct SourceMachine;
|
||||
#include "Procedure.h"
|
||||
class QString;
|
||||
class SourceMachine;
|
||||
struct CALL_GRAPH;
|
||||
|
||||
typedef llvm::iplist<Function> FunctionListType;
|
||||
typedef FunctionListType lFunction;
|
||||
typedef lFunction::iterator ilFunction;
|
||||
|
||||
|
||||
struct Project
|
||||
class IProject
|
||||
{
|
||||
SYMTAB symtab; /* Global symbol table */
|
||||
virtual PROG *binary()=0;
|
||||
virtual const QString & project_name() const =0;
|
||||
virtual const QString & binary_path() const =0;
|
||||
};
|
||||
class Project : public IProject
|
||||
{
|
||||
static Project *s_instance;
|
||||
QString m_fname;
|
||||
QString m_project_name;
|
||||
QString m_output_path;
|
||||
public:
|
||||
|
||||
std::string m_fname;
|
||||
FunctionListType pProcList;
|
||||
CALL_GRAPH * callGraph; /* Pointer to the head of the call graph */
|
||||
PROG prog; /* Loaded program image parameters */
|
||||
Project() {}
|
||||
// no copies
|
||||
Project(const Project&) = delete;
|
||||
const Project &operator=(const Project & l) =delete;
|
||||
// only moves
|
||||
Project(Project && l)
|
||||
{
|
||||
m_fname =l.m_fname;
|
||||
size_t before=l.pProcList.size();
|
||||
pProcList.splice(pProcList.end(),l.pProcList);
|
||||
callGraph=l.callGraph;
|
||||
l.m_fname.clear();
|
||||
l.pProcList.clear();
|
||||
l.callGraph=0;
|
||||
assert(before==pProcList.size());
|
||||
}
|
||||
Project &operator=(Project && l)
|
||||
{
|
||||
if(this == &l)
|
||||
return *this;
|
||||
m_fname =l.m_fname;
|
||||
size_t before=l.pProcList.size();
|
||||
pProcList.splice(pProcList.end(),l.pProcList);
|
||||
callGraph=l.callGraph;
|
||||
l.m_fname.clear();
|
||||
l.pProcList.clear();
|
||||
l.callGraph=0;
|
||||
assert(before==pProcList.size());
|
||||
return *this;
|
||||
}
|
||||
typedef std::list<Function> FunctionListType;
|
||||
typedef FunctionListType lFunction;
|
||||
typedef FunctionListType::iterator ilFunction;
|
||||
|
||||
SYMTAB symtab; /* Global symbol table */
|
||||
FunctionListType pProcList;
|
||||
CALL_GRAPH * callGraph; /* Pointer to the head of the call graph */
|
||||
PROG prog; /* Loaded program image parameters */
|
||||
// no copies
|
||||
Project(const Project&) = delete;
|
||||
const Project & operator=(const Project & l) =delete;
|
||||
// only moves
|
||||
Project(); // default constructor,
|
||||
|
||||
public:
|
||||
ilFunction funcIter(Function *to_find);
|
||||
ilFunction findByEntry(uint32_t entry);
|
||||
ilFunction createFunction();
|
||||
bool valid(ilFunction iter);
|
||||
void create(const QString &a);
|
||||
bool load();
|
||||
const QString & output_path() const {return m_output_path;}
|
||||
const QString & project_name() const {return m_project_name;}
|
||||
const QString & binary_path() const {return m_fname;}
|
||||
QString output_name(const char *ext);
|
||||
ilFunction funcIter(Function *to_find);
|
||||
ilFunction findByEntry(uint32_t entry);
|
||||
ilFunction createFunction(FunctionType *f, const QString & name);
|
||||
bool valid(ilFunction iter);
|
||||
|
||||
int getSymIdxByAdd(uint32_t adr);
|
||||
bool validSymIdx(size_t idx);
|
||||
size_t symbolSize(size_t idx);
|
||||
hlType symbolType(size_t idx);
|
||||
const std::string &symbolName(size_t idx);
|
||||
const SYM &getSymByIdx(size_t idx) const;
|
||||
int getSymIdxByAddr(uint32_t adr);
|
||||
bool validSymIdx(size_t idx);
|
||||
size_t symbolSize(size_t idx);
|
||||
hlType symbolType(size_t idx);
|
||||
const QString & symbolName(size_t idx);
|
||||
const SYM & getSymByIdx(size_t idx) const;
|
||||
|
||||
static Project *get();
|
||||
PROG * binary() {return &prog;}
|
||||
SourceMachine *machine();
|
||||
static Project * get();
|
||||
PROG * binary() {return &prog;}
|
||||
SourceMachine *machine();
|
||||
|
||||
const FunctionListType &functions() const { return pProcList; }
|
||||
FunctionListType &functions() { return pProcList; }
|
||||
protected:
|
||||
void writeGlobSymTable();
|
||||
void initialize();
|
||||
void writeGlobSymTable();
|
||||
};
|
||||
//extern Project g_proj;
|
||||
|
||||
@ -4,9 +4,9 @@
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include "error.h"
|
||||
/* Extracts reg bits from middle of mod-reg-rm uint8_t */
|
||||
|
||||
#define REG(x) ((uint8_t)(x & 0x38) >> 3)
|
||||
|
||||
//#define LH(p) ((int)((uint8_t *)(p))[0] + ((int)((uint8_t *)(p))[1] << 8))
|
||||
struct ICODE;
|
||||
|
||||
/* Extracts reg bits from middle of mod-reg-rm uint8_t */
|
||||
extern eErrorId scan(uint32_t ip, ICODE &p);
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
struct STATE
|
||||
{
|
||||
uint32_t IP; /* Offset into Image */
|
||||
int16_t r[INDEX_BX_SI]; /* Value of segs and AX */
|
||||
uint16_t r[INDEX_BX_SI]; /* Value of segs and AX */
|
||||
bool f[INDEX_BX_SI]; /* True if r[.] has a value */
|
||||
struct
|
||||
{ /* For case stmt indexed reg */
|
||||
@ -30,6 +30,10 @@ struct STATE
|
||||
memset(r,0,sizeof(int16_t)*INDEX_BX_SI); //TODO: move this to machine_x86
|
||||
memset(f,0,sizeof(uint8_t)*INDEX_BX_SI);
|
||||
}
|
||||
void setMemoryByte(uint32_t addr,uint8_t val)
|
||||
{
|
||||
//TODO: make this into a full scale value tracking class !
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -3,18 +3,22 @@
|
||||
* (C) Mike van Emmerik
|
||||
*/
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include "Enums.h"
|
||||
#include "types.h"
|
||||
struct COND_EXPR;
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
struct Expr;
|
||||
struct AstIdent;
|
||||
struct TypeContainer;
|
||||
/* * * * * * * * * * * * * * * * * */
|
||||
/* Symbol table structs and protos */
|
||||
/* * * * * * * * * * * * * * * * * */
|
||||
struct SymbolCommon
|
||||
{
|
||||
std::string name; /* New name for this variable/symbol/argument */
|
||||
QString name; /* New name for this variable/symbol/argument */
|
||||
int size; /* Size/maximum size */
|
||||
hlType type; /* probable type */
|
||||
eDuVal duVal; /* DEF, USE, VAL */
|
||||
@ -23,30 +27,25 @@ struct SymbolCommon
|
||||
};
|
||||
struct SYM : public SymbolCommon
|
||||
{
|
||||
typedef uint32_t tLabel;
|
||||
SYM() : label(0),flg(0)
|
||||
{
|
||||
|
||||
}
|
||||
int32_t label; /* physical address (20 bit) */
|
||||
uint32_t label; /* physical address (20 bit) */
|
||||
uint32_t flg; /* SEG_IMMED, IMPURE, WORD_OFF */
|
||||
};
|
||||
/* STACK FRAME */
|
||||
struct STKSYM : public SymbolCommon
|
||||
{
|
||||
COND_EXPR *actual; /* Expression tree of actual parameter */
|
||||
COND_EXPR *regs; /* For register arguments only */
|
||||
int16_t label; /* Immediate off from BP (+:args, -:params) */
|
||||
uint8_t regOff; /* Offset is a register (e.g. SI, DI) */
|
||||
bool hasMacro; /* This type needs a macro */
|
||||
std::string macro; /* Macro name */
|
||||
bool invalid; /* Boolean: invalid entry in formal arg list*/
|
||||
STKSYM()
|
||||
{
|
||||
actual=regs=0;
|
||||
label=0;
|
||||
regOff=0;
|
||||
invalid=hasMacro = false;
|
||||
}
|
||||
typedef int16_t tLabel;
|
||||
Expr * actual=0; /* Expression tree of actual parameter */
|
||||
AstIdent * regs=0; /* For register arguments only */
|
||||
tLabel label=0; /* Immediate off from BP (+:args, -:params) */
|
||||
uint8_t regOff=0; /* Offset is a register (e.g. SI, DI) */
|
||||
bool hasMacro=false; /* This type needs a macro */
|
||||
QString macro; /* Macro name */
|
||||
bool invalid=false; /* Boolean: invalid entry in formal arg list*/
|
||||
void setArgName(int i)
|
||||
{
|
||||
char buf[32];
|
||||
@ -60,13 +59,13 @@ class SymbolTableCommon : public std::vector<T>
|
||||
public:
|
||||
typedef typename std::vector<T>::iterator iterator;
|
||||
typedef typename std::vector<T>::const_iterator const_iterator;
|
||||
iterator findByLabel(int lab)
|
||||
iterator findByLabel(typename T::tLabel lab)
|
||||
{
|
||||
auto iter = std::find_if(this->begin(),this->end(),
|
||||
[lab](T &s)->bool {return s.label==lab;});
|
||||
return iter;
|
||||
}
|
||||
const_iterator findByLabel(int lab) const
|
||||
const_iterator findByLabel(typename T::tLabel lab) const
|
||||
{
|
||||
auto iter = std::find_if(this->begin(),this->end(),
|
||||
[lab](const T &s)->bool {return s.label==lab;});
|
||||
@ -95,19 +94,19 @@ struct SYMTABLE
|
||||
{
|
||||
// does not yse pSymName, to ease finding by symOff/symProc combo
|
||||
// in map<SYMTABLE,X>
|
||||
return (symOff==other.symOff) && symProc==(other.symProc);
|
||||
return (symOff==other.symOff) and symProc==(other.symProc);
|
||||
}
|
||||
};
|
||||
|
||||
enum tableType /* The table types */
|
||||
{
|
||||
Label=0, /* The label table */
|
||||
Comment, /* The comment table */
|
||||
NUM_TABLE_TYPES /* Number of entries: must be last */
|
||||
Comment /* The comment table */
|
||||
};
|
||||
constexpr int NUM_TABLE_TYPES = int(Comment)+1; /* Number of entries: must be last */
|
||||
|
||||
void createSymTables(void);
|
||||
void destroySymTables(void);
|
||||
boolT readVal (std::ostringstream &symName, uint32_t symOff, Function *symProc);
|
||||
bool readVal (QTextStream & symName, uint32_t symOff, Function *symProc);
|
||||
void selectTable(tableType); /* Select a particular table */
|
||||
|
||||
|
||||
@ -1,19 +1,21 @@
|
||||
/****************************************************************************
|
||||
/*
|
||||
***************************************************************************
|
||||
* dcc project general header
|
||||
* (C) Cristina Cifuentes, Mike van Emmerik
|
||||
****************************************************************************/
|
||||
***************************************************************************
|
||||
*/
|
||||
#pragma once
|
||||
#include "Enums.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <stdint.h>
|
||||
#include "Enums.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/**** Common definitions and macros ****/
|
||||
#define MAX 0x7FFFFFFF
|
||||
|
||||
/* Type definitions used in the program */
|
||||
typedef unsigned char byte; /* 8 bits */
|
||||
typedef unsigned short word;/* 16 bits */
|
||||
typedef short int16; /* 16 bits */
|
||||
typedef unsigned char boolT; /* 8 bits */
|
||||
|
||||
#define SYNTHESIZED_MIN 0x100000 /* Synthesized labs use bits 21..32 */
|
||||
|
||||
@ -22,17 +24,17 @@ typedef unsigned char boolT; /* 8 bits */
|
||||
#define PATLEN 23 /* Length of proc patterns */
|
||||
#define WILD 0xF4 /* The wild byte */
|
||||
|
||||
/****** MACROS *******/
|
||||
/* MACROS */
|
||||
|
||||
/* Macro reads a LH word from the image regardless of host convention */
|
||||
/* Returns a 16 bit quantity, e.g. C000 is read into an Int as C000 */
|
||||
// Macro reads a LH word from the image regardless of host convention
|
||||
// Returns a 16 bit quantity, e.g. C000 is read into an Int as C000
|
||||
//#define LH(p) ((int16)((byte *)(p))[0] + ((int16)((byte *)(p))[1] << 8))
|
||||
#define LH(p) ((word)((byte *)(p))[0] + ((word)((byte *)(p))[1] << 8))
|
||||
#define LH(p) ((uint16_t)((uint8_t *)(p))[0] + ((uint16_t)((uint8_t *)(p))[1] << 8))
|
||||
|
||||
|
||||
/* Macro reads a LH word from the image regardless of host convention */
|
||||
/* Returns a signed quantity, e.g. C000 is read into an Int as FFFFC000 */
|
||||
#define LH_SIGNED(p) (((byte *)(p))[0] + (((char *)(p))[1] << 8))
|
||||
#define LH_SIGNED(p) (((uint8_t *)(p))[0] + (((char *)(p))[1] << 8))
|
||||
|
||||
/* Macro tests bit b for type t in prog.map */
|
||||
#define BITMAP(b, t) (prog.map[(b) >> 2] & ((t) << (((b) & 3) << 1)))
|
||||
@ -53,24 +55,35 @@ struct eDuVal
|
||||
USE=2,
|
||||
VAL=4
|
||||
};
|
||||
int def :1; /* Variable was first defined than used */
|
||||
int use :1; /* Variable was first used than defined */
|
||||
int val :1; /* Variable has an initial value. 2 cases:
|
||||
* 1. When variable is used first (ie. global)
|
||||
* 2. When a value is moved into the variable
|
||||
* for the first time. */
|
||||
uint8_t def :1; //!< Variable was first defined than used
|
||||
uint8_t use :1; //!< Variable was first used than defined
|
||||
uint8_t val :1; /* Variable has an initial value. 2 cases:
|
||||
1. When variable is used first (ie. global)
|
||||
2. When a value is moved into the variable
|
||||
for the first time.
|
||||
*/
|
||||
void setFlags(uint16_t x)
|
||||
{
|
||||
def = x&DEF;
|
||||
use = x&USE;
|
||||
val = x&VAL;
|
||||
}
|
||||
bool isUSE_VAL() {return use&&val;} /* Use and Val */
|
||||
bool isUSE_VAL() {return use and val;} //Use and Val
|
||||
};
|
||||
static constexpr const char * hlTypes[13] = {
|
||||
"", "char", "unsigned char", "int", "unsigned int",
|
||||
"long", "unsigned long", "record", "int *", "char *",
|
||||
"", "float", "double"
|
||||
"",
|
||||
"char",
|
||||
"unsigned char",
|
||||
"int",
|
||||
"unsigned int",
|
||||
"long",
|
||||
"unsigned long",
|
||||
"record",
|
||||
"int *",
|
||||
"char *",
|
||||
"",
|
||||
"float",
|
||||
"double"
|
||||
};
|
||||
|
||||
struct TypeContainer
|
||||
@ -88,6 +101,12 @@ struct TypeContainer
|
||||
return 2;
|
||||
case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN:
|
||||
return 1;
|
||||
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
|
||||
return 4;
|
||||
case TYPE_FLOAT:
|
||||
return 4;
|
||||
default:
|
||||
return ~0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
BIN
prototypes/dcclibs.dat
Normal file
BIN
prototypes/dcclibs.dat
Normal file
Binary file not shown.
@ -14,8 +14,10 @@ def perform_test(exepath,filepath,outname,args)
|
||||
filepath=path_local(filepath)
|
||||
joined_args = args.join(' ')
|
||||
printf("calling:" + "#{exepath} -a1 #{joined_args} -o#{output_path}.a1 #{filepath}\n")
|
||||
result = `#{exepath} -a1 -o#{output_path}.a1 #{filepath}`
|
||||
result = `#{exepath} -a2 #{joined_args} -o#{output_path}.a2 #{filepath}`
|
||||
STDERR << "Errors for : #{filepath}\n"
|
||||
result = `#{exepath} -a 1 -o#{output_path}.a1 #{filepath}`
|
||||
result = `#{exepath} -a 2 #{joined_args} -o#{output_path}.a2 #{filepath}`
|
||||
result = `#{exepath} #{joined_args} -o#{output_path} #{filepath}`
|
||||
puts result
|
||||
p $?
|
||||
end
|
||||
|
||||
BIN
sigs/dccb2s.sig
Normal file
BIN
sigs/dccb2s.sig
Normal file
Binary file not shown.
@ -1,15 +1,20 @@
|
||||
#include "BasicBlock.h"
|
||||
|
||||
#include "msvc_fixes.h"
|
||||
#include "Procedure.h"
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
#include <QtCore/QTextStream>
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <boost/range/rbegin.hpp>
|
||||
#include <boost/range/rend.hpp>
|
||||
#include <boost/range/adaptors.hpp>
|
||||
#include "BasicBlock.h"
|
||||
#include "Procedure.h"
|
||||
#include "dcc.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
|
||||
BB *BB::Create(void *ctx, const string &s, Function *parent, BB *insertBefore)
|
||||
BB *BB::Create(void */*ctx*/, const string &/*s*/, Function *parent, BB */*insertBefore*/)
|
||||
{
|
||||
BB *pnewBB = new BB;
|
||||
pnewBB->Parent = parent;
|
||||
@ -19,7 +24,7 @@ BB *BB::Create(void *ctx, const string &s, Function *parent, BB *insertBefore)
|
||||
* @arg start - basic block starts here, might be parent->Icode.end()
|
||||
* @arg fin - last of basic block's instructions
|
||||
*/
|
||||
BB *BB::Create(iICODE start, iICODE fin, uint8_t _nodeType, int numOutEdges, Function *parent)
|
||||
BB *BB::Create(const rCODE &r,eBBKind _nodeType, Function *parent)
|
||||
{
|
||||
BB* pnewBB;
|
||||
pnewBB = new BB;
|
||||
@ -27,47 +32,30 @@ BB *BB::Create(iICODE start, iICODE fin, uint8_t _nodeType, int numOutEdges, Fun
|
||||
pnewBB->immedDom = NO_DOM;
|
||||
pnewBB->loopHead = pnewBB->caseHead = pnewBB->caseTail =
|
||||
pnewBB->latchNode= pnewBB->loopFollow = NO_NODE;
|
||||
pnewBB->instructions = make_iterator_range(start,fin);
|
||||
if(start==parent->Icode.end())
|
||||
{
|
||||
pnewBB->instructions = make_iterator_range(parent->Icode.end(),parent->Icode.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
pnewBB->instructions.advance_end(1); // 1 after fin, to create range where fin is inclusive
|
||||
}
|
||||
if (numOutEdges)
|
||||
pnewBB->edges.resize(numOutEdges);
|
||||
|
||||
pnewBB->instructions = r;
|
||||
/* Mark the basic block to which the icodes belong to, but only for
|
||||
* real code basic blocks (ie. not interval bbs) */
|
||||
* real code basic blocks (ie. not interval bbs) */
|
||||
if(parent)
|
||||
{
|
||||
if (start != parent->Icode.end())
|
||||
parent->Icode.SetInBB(pnewBB->instructions, pnewBB);
|
||||
parent->heldBBs.push_back(pnewBB);
|
||||
parent->m_cfg.push_back(pnewBB);
|
||||
int addr = pnewBB->begin()->loc_ip;
|
||||
//setInBB should automatically handle if our range is empty
|
||||
parent->Icode.SetInBB(pnewBB->instructions, pnewBB);
|
||||
|
||||
assert(parent->m_ip_to_bb.find(addr)==parent->m_ip_to_bb.end());
|
||||
parent->m_ip_to_bb[addr] = pnewBB;
|
||||
parent->m_actual_cfg.push_back(pnewBB);
|
||||
pnewBB->Parent = parent;
|
||||
}
|
||||
if ( start != parent->Icode.end() ) /* Only for code BB's */
|
||||
|
||||
if ( r.begin() != parent->Icode.end() ) /* Only for code BB's */
|
||||
stats.numBBbef++;
|
||||
}
|
||||
return pnewBB;
|
||||
|
||||
}
|
||||
BB *BB::Create(int start, int ip, uint8_t _nodeType, int numOutEdges, Function *parent)
|
||||
BB *BB::CreateIntervalBB(Function *parent)
|
||||
{
|
||||
iICODE st(parent->Icode.begin());
|
||||
iICODE fin(parent->Icode.begin());
|
||||
if(start==-1)
|
||||
{
|
||||
st = parent->Icode.end();
|
||||
fin = parent->Icode.end();
|
||||
}
|
||||
else
|
||||
{
|
||||
advance(st,start);
|
||||
advance(fin,ip);
|
||||
}
|
||||
return Create(st,fin,_nodeType,numOutEdges,parent);
|
||||
iICODE endOfParent = parent->Icode.end();
|
||||
return Create(make_iterator_range(endOfParent,endOfParent),INTERVAL_NODE,nullptr);
|
||||
}
|
||||
|
||||
static const char *const s_nodeType[] = {"branch", "if", "case", "fall", "return", "call",
|
||||
@ -81,14 +69,14 @@ static const char *const s_loopType[] = {"noLoop", "while", "repeat", "loop", "f
|
||||
void BB::display()
|
||||
{
|
||||
printf("\nnode type = %s, ", s_nodeType[nodeType]);
|
||||
printf("start = %ld, length = %ld, #out edges = %ld\n", begin()->loc_ip, size(), edges.size());
|
||||
printf("start = %d, length = %zd, #out edges = %zd\n", begin()->loc_ip, size(), edges.size());
|
||||
|
||||
for (size_t i = 0; i < edges.size(); i++)
|
||||
{
|
||||
if(edges[i].BBptr==0)
|
||||
printf(" outEdge[%2d] = Unlinked out edge to %d\n",i, edges[i].ip);
|
||||
if(edges[i].BBptr==nullptr)
|
||||
printf(" outEdge[%2zd] = Unlinked out edge to %d\n",i, edges[i].ip);
|
||||
else
|
||||
printf(" outEdge[%2d] = %d\n",i, edges[i].BBptr->begin()->loc_ip);
|
||||
printf(" outEdge[%2zd] = %d\n",i, edges[i].BBptr->begin()->loc_ip);
|
||||
}
|
||||
}
|
||||
/*****************************************************************************
|
||||
@ -101,29 +89,29 @@ void BB::displayDfs()
|
||||
traversed = DFS_DISP;
|
||||
|
||||
printf("node type = %s, ", s_nodeType[nodeType]);
|
||||
printf("start = %ld, length = %ld, #in-edges = %ld, #out-edges = %ld\n",
|
||||
printf("start = %d, length = %zd, #in-edges = %zd, #out-edges = %zd\n",
|
||||
begin()->loc_ip, size(), inEdges.size(), edges.size());
|
||||
printf("dfsFirst = %ld, dfsLast = %ld, immed dom = %ld\n",
|
||||
printf("dfsFirst = %d, dfsLast = %d, immed dom = %d\n",
|
||||
dfsFirstNum, dfsLastNum,
|
||||
immedDom == MAX ? -1 : immedDom);
|
||||
printf("loopType = %s, loopHead = %ld, latchNode = %ld, follow = %ld\n",
|
||||
s_loopType[loopType],
|
||||
printf("loopType = %s, loopHead = %d, latchNode = %d, follow = %d\n",
|
||||
s_loopType[(int)loopType],
|
||||
loopHead == MAX ? -1 : loopHead,
|
||||
latchNode == MAX ? -1 : latchNode,
|
||||
loopFollow == MAX ? -1 : loopFollow);
|
||||
printf ("ifFollow = %ld, caseHead = %ld, caseTail = %ld\n",
|
||||
printf ("ifFollow = %d, caseHead = %d, caseTail = %d\n",
|
||||
ifFollow == MAX ? -1 : ifFollow,
|
||||
caseHead == MAX ? -1 : caseHead,
|
||||
caseTail == MAX ? -1 : caseTail);
|
||||
|
||||
if (nodeType == INTERVAL_NODE)
|
||||
printf("corresponding interval = %ld\n", correspInt->numInt);
|
||||
printf("corresponding interval = %d\n", correspInt->numInt);
|
||||
else
|
||||
{
|
||||
int edge_idx=0;
|
||||
for(BB *node : inEdges)
|
||||
{
|
||||
printf (" inEdge[%ld] = %ld\n", edge_idx, node->begin()->loc_ip);
|
||||
printf (" inEdge[%d] = %d\n", edge_idx, node->begin()->loc_ip);
|
||||
edge_idx++;
|
||||
}
|
||||
}
|
||||
@ -132,9 +120,9 @@ void BB::displayDfs()
|
||||
for(TYPEADR_TYPE &edg : edges)
|
||||
{
|
||||
if (nodeType == INTERVAL_NODE)
|
||||
printf(" outEdge[%ld] = %ld\n", i, edg.BBptr->correspInt->numInt);
|
||||
printf(" outEdge[%d] = %d\n", i, edg.BBptr->correspInt->numInt);
|
||||
else
|
||||
printf(" outEdge[%d] = %ld\n", i, edg.BBptr->begin()->loc_ip);
|
||||
printf(" outEdge[%d] = %d\n", i, edg.BBptr->begin()->loc_ip);
|
||||
++i;
|
||||
}
|
||||
printf("----\n");
|
||||
@ -146,21 +134,22 @@ void BB::displayDfs()
|
||||
pb.BBptr->displayDfs();
|
||||
}
|
||||
}
|
||||
/* Recursive procedure that writes the code for the given procedure, pointed
|
||||
* to by pBB.
|
||||
* Parameters: pBB: pointer to the cfg.
|
||||
* Icode: pointer to the Icode array for the cfg graph of the
|
||||
* current procedure.
|
||||
* indLevel: indentation level - used for formatting.
|
||||
* numLoc: last # assigned to local variables */
|
||||
ICODE* BB::writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&latch, boolT &repCond)
|
||||
/** Recursive procedure that writes the code for the given procedure, pointed
|
||||
to by pBB.
|
||||
\param indLevel indentation level - used for formatting.
|
||||
\param numLoc: last # assigned to local variables
|
||||
*/
|
||||
ICODE* BB::writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&latch, bool &repCond)
|
||||
{
|
||||
if(loopType == eNodeHeaderType::NO_TYPE)
|
||||
return nullptr;
|
||||
latch = pProc->m_dfsLast[this->latchNode];
|
||||
std::ostringstream ostr;
|
||||
QString ostr_contents;
|
||||
QTextStream ostr(&ostr_contents);
|
||||
ICODE* picode;
|
||||
switch (loopType)
|
||||
{
|
||||
case WHILE_TYPE:
|
||||
case eNodeHeaderType::WHILE_TYPE:
|
||||
picode = &this->back();
|
||||
|
||||
/* Check for error in while condition */
|
||||
@ -179,45 +168,48 @@ ICODE* BB::writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&lat
|
||||
* the THEN path of the header node */
|
||||
if (edges[ELSE].BBptr->dfsLastNum == loopFollow)
|
||||
{
|
||||
picode->hl()->replaceExpr(picode->hl()->expr()->inverse());
|
||||
picode->hlU()->replaceExpr(picode->hl()->expr()->inverse());
|
||||
}
|
||||
{
|
||||
string e=walkCondExpr (picode->hl()->expr(), pProc, numLoc);
|
||||
QString e=picode->hl()->expr()->walkCondExpr (pProc, numLoc);
|
||||
ostr << "\n"<<indentStr(indLevel)<<"while ("<<e<<") {\n";
|
||||
}
|
||||
picode->invalidate();
|
||||
break;
|
||||
|
||||
case REPEAT_TYPE:
|
||||
case eNodeHeaderType::REPEAT_TYPE:
|
||||
ostr << "\n"<<indentStr(indLevel)<<"do {\n";
|
||||
picode = &latch->back();
|
||||
picode->invalidate();
|
||||
break;
|
||||
|
||||
case ENDLESS_TYPE:
|
||||
case eNodeHeaderType::ENDLESS_TYPE:
|
||||
ostr << "\n"<<indentStr(indLevel)<<"for (;;) {\n";
|
||||
picode = &latch->back();
|
||||
break;
|
||||
}
|
||||
cCode.appendCode(ostr.str());
|
||||
ostr.flush();
|
||||
cCode.appendCode(ostr_contents);
|
||||
stats.numHLIcode += 1;
|
||||
indLevel++;
|
||||
return picode;
|
||||
}
|
||||
bool BB::isEndOfPath(int latch_node_idx) const
|
||||
{
|
||||
return nodeType == RETURN_NODE || nodeType == TERMINATE_NODE ||
|
||||
nodeType == NOWHERE_NODE || (dfsLastNum == latch_node_idx);
|
||||
return nodeType == RETURN_NODE or nodeType == TERMINATE_NODE or
|
||||
nodeType == NOWHERE_NODE or dfsLastNum == latch_node_idx;
|
||||
}
|
||||
void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode, int _ifFollow)
|
||||
{
|
||||
int follow; /* ifFollow */
|
||||
BB * succ, *latch; /* Successor and latching node */
|
||||
BB * succ, *latch; /* Successor and latching node */
|
||||
ICODE * picode; /* Pointer to HLI_JCOND instruction */
|
||||
char *l; /* Pointer to HLI_JCOND expression */
|
||||
boolT emptyThen, /* THEN clause is empty */
|
||||
repCond; /* Repeat condition for while() */
|
||||
QString l; /* Pointer to HLI_JCOND expression */
|
||||
bool emptyThen, /* THEN clause is empty */
|
||||
repCond; /* Repeat condition for while() */
|
||||
|
||||
/* Check if this basic block should be analysed */
|
||||
if ((_ifFollow != UN_INIT) && (this == pProc->m_dfsLast[_ifFollow]))
|
||||
if ((_ifFollow != UN_INIT) and (this == pProc->m_dfsLast[_ifFollow]))
|
||||
return;
|
||||
|
||||
if (wasTraversedAtLevel(DFS_ALPHA))
|
||||
@ -226,18 +218,17 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
|
||||
|
||||
/* Check for start of loop */
|
||||
repCond = false;
|
||||
latch = NULL;
|
||||
if (loopType)
|
||||
{
|
||||
latch = nullptr;
|
||||
picode=writeLoopHeader(indLevel, pProc, numLoc, latch, repCond);
|
||||
}
|
||||
|
||||
/* Write the code for this basic block */
|
||||
if (repCond == false)
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
QString ostr_contents;
|
||||
QTextStream ostr(&ostr_contents);
|
||||
writeBB(ostr,indLevel, pProc, numLoc);
|
||||
cCode.appendCode(ostr.str());
|
||||
ostr.flush();
|
||||
cCode.appendCode(ostr_contents);
|
||||
}
|
||||
|
||||
/* Check for end of path */
|
||||
@ -245,12 +236,12 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
|
||||
return;
|
||||
|
||||
/* Check type of loop/node and process code */
|
||||
if ( loopType) /* there is a loop */
|
||||
if ( loopType!=eNodeHeaderType::NO_TYPE ) /* there is a loop */
|
||||
{
|
||||
assert(latch);
|
||||
if (this != latch) /* loop is over several bbs */
|
||||
{
|
||||
if (loopType == WHILE_TYPE)
|
||||
if (loopType == eNodeHeaderType::WHILE_TYPE)
|
||||
{
|
||||
succ = edges[THEN].BBptr;
|
||||
if (succ->dfsLastNum == loopFollow)
|
||||
@ -266,9 +257,10 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
|
||||
|
||||
/* Loop epilogue: generate the loop trailer */
|
||||
indLevel--;
|
||||
if (loopType == WHILE_TYPE)
|
||||
if (loopType == eNodeHeaderType::WHILE_TYPE)
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
QString ostr_contents;
|
||||
QTextStream ostr(&ostr_contents);
|
||||
/* Check if there is need to repeat other statements involved
|
||||
* in while condition, then, emit the loop trailer */
|
||||
if (repCond)
|
||||
@ -276,18 +268,23 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
|
||||
writeBB(ostr,indLevel+1, pProc, numLoc);
|
||||
}
|
||||
ostr <<indentStr(indLevel)<< "} /* end of while */\n";
|
||||
cCode.appendCode(ostr.str());
|
||||
ostr.flush();
|
||||
cCode.appendCode(ostr_contents);
|
||||
}
|
||||
else if (loopType == ENDLESS_TYPE)
|
||||
else if (loopType == eNodeHeaderType::ENDLESS_TYPE)
|
||||
cCode.appendCode( "%s} /* end of loop */\n",indentStr(indLevel));
|
||||
else if (loopType == REPEAT_TYPE)
|
||||
else if (loopType == eNodeHeaderType::REPEAT_TYPE)
|
||||
{
|
||||
QString e = "//*failed*//";
|
||||
if (picode->hl()->opcode != HLI_JCOND)
|
||||
reportError (REPEAT_FAIL);
|
||||
{
|
||||
string e=walkCondExpr (picode->hl()->expr(), pProc, numLoc);
|
||||
cCode.appendCode( "%s} while (%s);\n", indentStr(indLevel),e.c_str());
|
||||
reportError (REPEAT_FAIL);
|
||||
}
|
||||
else
|
||||
{
|
||||
e=picode->hl()->expr()->walkCondExpr (pProc, numLoc);
|
||||
}
|
||||
cCode.appendCode( "%s} while (%s);\n", indentStr(indLevel),qPrintable(e));
|
||||
}
|
||||
|
||||
/* Recurse on the loop follow */
|
||||
@ -319,13 +316,13 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
|
||||
if (succ->dfsLastNum != follow) /* THEN part */
|
||||
{
|
||||
l = writeJcond ( *back().hl(), pProc, numLoc);
|
||||
cCode.appendCode( "\n%s%s", indentStr(indLevel-1), l);
|
||||
cCode.appendCode( "\n%s%s", indentStr(indLevel-1), qPrintable(l));
|
||||
succ->writeCode (indLevel, pProc, numLoc, _latchNode,follow);
|
||||
}
|
||||
else /* empty THEN part => negate ELSE part */
|
||||
{
|
||||
l = writeJcondInv ( *back().hl(), pProc, numLoc);
|
||||
cCode.appendCode( "\n%s%s", indentStr(indLevel-1), l);
|
||||
cCode.appendCode( "\n%s%s", indentStr(indLevel-1), qPrintable(l));
|
||||
edges[ELSE].BBptr->writeCode (indLevel, pProc, numLoc, _latchNode, follow);
|
||||
emptyThen = true;
|
||||
}
|
||||
@ -345,7 +342,7 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
|
||||
}
|
||||
/* else (empty ELSE part) */
|
||||
}
|
||||
else if (! emptyThen) /* already visited => emit label */
|
||||
else if (not emptyThen) /* already visited => emit label */
|
||||
{
|
||||
cCode.appendCode( "%s}\n%selse {\n",
|
||||
indentStr(indLevel-1), indentStr(indLevel - 1));
|
||||
@ -361,7 +358,7 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
|
||||
else /* no follow => if..then..else */
|
||||
{
|
||||
l = writeJcond ( *back().hl(), pProc, numLoc);
|
||||
cCode.appendCode( "%s%s", indentStr(indLevel-1), l);
|
||||
cCode.appendCode( "%s%s", indentStr(indLevel-1), qPrintable(l));
|
||||
edges[THEN].BBptr->writeCode (indLevel, pProc, numLoc, _latchNode, _ifFollow);
|
||||
cCode.appendCode( "%s}\n%selse {\n", indentStr(indLevel-1), indentStr(indLevel - 1));
|
||||
edges[ELSE].BBptr->writeCode (indLevel, pProc, numLoc, _latchNode, _ifFollow);
|
||||
@ -384,7 +381,7 @@ void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int _latchNode,
|
||||
* Args: pBB: pointer to the current basic block.
|
||||
* Icode: pointer to the array of icodes for current procedure.
|
||||
* lev: indentation level - used for formatting. */
|
||||
void BB::writeBB(std::ostream &ostr,int lev, Function * pProc, int *numLoc)
|
||||
void BB::writeBB(QTextStream &ostr,int lev, Function * pProc, int *numLoc)
|
||||
{
|
||||
/* Save the index into the code table in case there is a later goto
|
||||
* into this instruction (first instruction of the BB) */
|
||||
@ -394,10 +391,10 @@ void BB::writeBB(std::ostream &ostr,int lev, Function * pProc, int *numLoc)
|
||||
|
||||
for(ICODE &pHli : instructions)
|
||||
{
|
||||
if ((pHli.type == HIGH_LEVEL) && ( pHli.valid() )) //TODO: use filtering range here.
|
||||
if ((pHli.type == HIGH_LEVEL_ICODE) and ( pHli.valid() )) //TODO: use filtering range here.
|
||||
{
|
||||
std::string line = pHli.hl()->write1HlIcode(pProc, numLoc);
|
||||
if (!line.empty())
|
||||
QString line = pHli.hl()->write1HlIcode(pProc, numLoc);
|
||||
if (not line.isEmpty())
|
||||
{
|
||||
ostr<<indentStr(lev)<<line;
|
||||
stats.numHLIcode++;
|
||||
@ -410,27 +407,26 @@ void BB::writeBB(std::ostream &ostr,int lev, Function * pProc, int *numLoc)
|
||||
|
||||
iICODE BB::begin()
|
||||
{
|
||||
return instructions.begin();//range_start;
|
||||
return instructions.begin();
|
||||
}
|
||||
|
||||
iICODE BB::end() const
|
||||
{
|
||||
return instructions.end();//range_end
|
||||
return instructions.end();
|
||||
}
|
||||
ICODE &BB::back()
|
||||
{
|
||||
return instructions.back();//*rbegin();
|
||||
return instructions.back();
|
||||
}
|
||||
|
||||
size_t BB::size()
|
||||
{
|
||||
|
||||
return distance(instructions.begin(),instructions.end());
|
||||
}
|
||||
|
||||
ICODE &BB::front()
|
||||
{
|
||||
return instructions.front();//*begin();
|
||||
return instructions.front();
|
||||
}
|
||||
|
||||
riICODE BB::rbegin()
|
||||
|
||||
@ -1,7 +1,13 @@
|
||||
SET(dcc_test_SOURCES tests/comwrite.cpp)
|
||||
SET(dcc_test_SOURCES
|
||||
tests/comwrite.cpp
|
||||
tests/project.cpp
|
||||
tests/loader.cpp
|
||||
|
||||
)
|
||||
include_directories(${GMOCK_INCLUDE_DIRS} ${GMOCK_ROOT}/gtest/include)
|
||||
enable_testing()
|
||||
add_executable(tester ${dcc_test_SOURCES})
|
||||
target_link_libraries(tester
|
||||
ADD_DEPENDENCIES(tester dcc_lib)
|
||||
|
||||
target_link_libraries(tester dcc_lib disasm_s
|
||||
${GMOCK_BOTH_LIBRARIES} ${REQ_LLVM_LIBRARIES})
|
||||
add_test(dcc-tests tester)
|
||||
|
||||
37
src/CallConvention.cpp
Normal file
37
src/CallConvention.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
#include <ostream>
|
||||
#include <cassert>
|
||||
#include "CallConvention.h"
|
||||
#include <QtCore/QTextStream>
|
||||
|
||||
CConv *CConv::create(Type v)
|
||||
{
|
||||
static C_CallingConvention *c_call = nullptr;
|
||||
static Pascal_CallingConvention *p_call = nullptr;
|
||||
static Unknown_CallingConvention *u_call= nullptr;
|
||||
if(nullptr==c_call)
|
||||
c_call = new C_CallingConvention;
|
||||
if(nullptr==p_call)
|
||||
p_call = new Pascal_CallingConvention;
|
||||
if(nullptr==u_call)
|
||||
u_call = new Unknown_CallingConvention;
|
||||
switch(v) {
|
||||
case eUnknown: return u_call;
|
||||
case eCdecl: return c_call;
|
||||
case ePascal: return p_call;
|
||||
}
|
||||
assert(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void C_CallingConvention::writeComments(QTextStream & ostr)
|
||||
{
|
||||
ostr << " * C calling convention.\n";
|
||||
}
|
||||
void Pascal_CallingConvention::writeComments(QTextStream & ostr)
|
||||
{
|
||||
ostr << " * Pascal calling convention.\n";
|
||||
}
|
||||
void Unknown_CallingConvention::writeComments(QTextStream & ostr)
|
||||
{
|
||||
ostr << " * Unknown calling convention.\n";
|
||||
}
|
||||
535
src/DccFrontend.cpp
Normal file
535
src/DccFrontend.cpp
Normal file
@ -0,0 +1,535 @@
|
||||
#include "DccFrontend.h"
|
||||
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
#include "project.h"
|
||||
#include "disassem.h"
|
||||
#include "CallGraph.h"
|
||||
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QDebug>
|
||||
#include <cstdio>
|
||||
|
||||
|
||||
class Loader
|
||||
{
|
||||
bool loadIntoProject(IProject *);
|
||||
};
|
||||
|
||||
struct PSP { /* PSP structure */
|
||||
uint16_t int20h; /* interrupt 20h */
|
||||
uint16_t eof; /* segment, end of allocation block */
|
||||
uint8_t res1; /* reserved */
|
||||
uint8_t dosDisp[5]; /* far call to DOS function dispatcher */
|
||||
uint8_t int22h[4]; /* vector for terminate routine */
|
||||
uint8_t int23h[4]; /* vector for ctrl+break routine */
|
||||
uint8_t int24h[4]; /* vector for error routine */
|
||||
uint8_t res2[22]; /* reserved */
|
||||
uint16_t segEnv; /* segment address of environment block */
|
||||
uint8_t res3[34]; /* reserved */
|
||||
uint8_t int21h[6]; /* opcode for int21h and far return */
|
||||
uint8_t res4[6]; /* reserved */
|
||||
uint8_t fcb1[16]; /* default file control block 1 */
|
||||
uint8_t fcb2[16]; /* default file control block 2 */
|
||||
uint8_t res5[4]; /* reserved */
|
||||
uint8_t cmdTail[0x80]; /* command tail and disk transfer area */
|
||||
};
|
||||
|
||||
static struct MZHeader { /* EXE file header */
|
||||
uint8_t sigLo; /* .EXE signature: 0x4D 0x5A */
|
||||
uint8_t sigHi;
|
||||
uint16_t lastPageSize; /* Size of the last page */
|
||||
uint16_t numPages; /* Number of pages in the file */
|
||||
uint16_t numReloc; /* Number of relocation items */
|
||||
uint16_t numParaHeader; /* # of paragraphs in the header */
|
||||
uint16_t minAlloc; /* Minimum number of paragraphs */
|
||||
uint16_t maxAlloc; /* Maximum number of paragraphs */
|
||||
uint16_t initSS; /* Segment displacement of stack */
|
||||
uint16_t initSP; /* Contents of SP at entry */
|
||||
uint16_t checkSum; /* Complemented checksum */
|
||||
uint16_t initIP; /* Contents of IP at entry */
|
||||
uint16_t initCS; /* Segment displacement of code */
|
||||
uint16_t relocTabOffset; /* Relocation table offset */
|
||||
uint16_t overlayNum; /* Overlay number */
|
||||
} header;
|
||||
|
||||
#define EXE_RELOCATION 0x10 /* EXE images rellocated to above PSP */
|
||||
|
||||
//static void LoadImage(char *filename);
|
||||
static void displayMemMap(void);
|
||||
/****************************************************************************
|
||||
* displayLoadInfo - Displays low level loader type info.
|
||||
***************************************************************************/
|
||||
void PROG::displayLoadInfo(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("File type is %s\n", (fCOM)?"COM":"EXE");
|
||||
if (not fCOM) {
|
||||
printf("Signature = %02X%02X\n", header.sigLo, header.sigHi);
|
||||
printf("File size %% 512 = %04X\n", LH(&header.lastPageSize));
|
||||
printf("File size / 512 = %04X pages\n", LH(&header.numPages));
|
||||
printf("# relocation items = %04X\n", LH(&header.numReloc));
|
||||
printf("Offset to load image = %04X paras\n", LH(&header.numParaHeader));
|
||||
printf("Minimum allocation = %04X paras\n", LH(&header.minAlloc));
|
||||
printf("Maximum allocation = %04X paras\n", LH(&header.maxAlloc));
|
||||
}
|
||||
printf("Load image size = %08lX\n", cbImage - sizeof(PSP));
|
||||
printf("Initial SS:SP = %04X:%04X\n", initSS, initSP);
|
||||
printf("Initial CS:IP = %04X:%04X\n", initCS, initIP);
|
||||
|
||||
if (option.VeryVerbose and cReloc)
|
||||
{
|
||||
printf("\nRelocation Table\n");
|
||||
for (i = 0; i < cReloc; i++)
|
||||
{
|
||||
printf("%06X -> [%04X]\n", relocTable[i],LH(image() + relocTable[i]));
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* fill - Fills line for displayMemMap()
|
||||
****************************************************************************/
|
||||
static void fill(int ip, char *bf)
|
||||
{
|
||||
PROG &prog(Project::get()->prog);
|
||||
static uint8_t type[4] = {'.', 'd', 'c', 'x'};
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < 16; i++, ip++)
|
||||
{
|
||||
*bf++ = ' ';
|
||||
*bf++ = (ip < prog.cbImage)? type[(prog.map[ip >> 2] >> ((ip & 3) * 2)) & 3]: ' ';
|
||||
}
|
||||
*bf = '\0';
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* displayMemMap - Displays the memory bitmap
|
||||
****************************************************************************/
|
||||
static void displayMemMap(void)
|
||||
{
|
||||
PROG &prog(Project::get()->prog);
|
||||
|
||||
char c, b1[33], b2[33], b3[33];
|
||||
uint8_t i;
|
||||
int ip = 0;
|
||||
|
||||
printf("\nMemory Map\n");
|
||||
while (ip < prog.cbImage)
|
||||
{
|
||||
fill(ip, b1);
|
||||
printf("%06X %s\n", ip, b1);
|
||||
ip += 16;
|
||||
for (i = 3, c = b1[1]; i < 32 and c == b1[i]; i += 2)
|
||||
; /* Check if all same */
|
||||
if (i > 32)
|
||||
{
|
||||
fill(ip, b2); /* Skip until next two are not same */
|
||||
fill(ip+16, b3);
|
||||
if (not (strcmp(b1, b2) || strcmp(b1, b3)))
|
||||
{
|
||||
printf(" :\n");
|
||||
do
|
||||
{
|
||||
ip += 16;
|
||||
fill(ip+16, b1);
|
||||
} while (0==strcmp(b1, b2));
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
DccFrontend::DccFrontend(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* FrontEnd - invokes the loader, parser, disassembler (if asm1), icode
|
||||
* rewritter, and displays any useful information.
|
||||
****************************************************************************/
|
||||
bool DccFrontend::FrontEnd ()
|
||||
{
|
||||
|
||||
/* Do depth first flow analysis building call graph and procedure list,
|
||||
* and attaching the I-code to each procedure */
|
||||
parse (*Project::get());
|
||||
|
||||
if (option.asm1)
|
||||
{
|
||||
qWarning() << "dcc: writing assembler file "<<asm1_name<<'\n';
|
||||
}
|
||||
|
||||
/* Search through code looking for impure references and flag them */
|
||||
Disassembler ds(1);
|
||||
for(Function &f : Project::get()->pProcList)
|
||||
{
|
||||
f.markImpure();
|
||||
if (option.asm1)
|
||||
{
|
||||
ds.disassem(&f);
|
||||
}
|
||||
}
|
||||
if (option.Interact)
|
||||
{
|
||||
interactDis(&Project::get()->pProcList.front(), 0); /* Interactive disassembler */
|
||||
}
|
||||
|
||||
/* Converts jump target addresses to icode offsets */
|
||||
for(Function &f : Project::get()->pProcList)
|
||||
{
|
||||
f.bindIcodeOff();
|
||||
}
|
||||
/* Print memory bitmap */
|
||||
if (option.Map)
|
||||
displayMemMap();
|
||||
return(true); // we no longer own proj !
|
||||
}
|
||||
struct DosLoader {
|
||||
protected:
|
||||
void prepareImage(PROG &prog,size_t sz,QFile &fp) {
|
||||
/* Allocate a block of memory for the program. */
|
||||
prog.cbImage = sz + sizeof(PSP);
|
||||
prog.Imagez = new uint8_t [prog.cbImage];
|
||||
prog.Imagez[0] = 0xCD; /* Fill in PSP int 20h location */
|
||||
prog.Imagez[1] = 0x20; /* for termination checking */
|
||||
/* Read in the image past where a PSP would go */
|
||||
if (sz != fp.read((char *)prog.Imagez + sizeof(PSP),sz))
|
||||
fatalError(CANNOT_READ, fp.fileName().toLocal8Bit().data());
|
||||
}
|
||||
};
|
||||
struct ComLoader : public DosLoader {
|
||||
bool canLoad(QFile &fp) {
|
||||
fp.seek(0);
|
||||
char sig[2];
|
||||
if(2==fp.read(sig,2)) {
|
||||
return not (sig[0] == 0x4D and sig[1] == 0x5A);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool load(PROG &prog,QFile &fp) {
|
||||
fp.seek(0);
|
||||
/* COM file
|
||||
* In this case the load module size is just the file length
|
||||
*/
|
||||
auto cb = fp.size();
|
||||
|
||||
/* COM programs start off with an ORG 100H (to leave room for a PSP)
|
||||
* This is also the implied start address so if we load the image
|
||||
* at offset 100H addresses should all line up properly again.
|
||||
*/
|
||||
prog.initCS = 0;
|
||||
prog.initIP = 0x100;
|
||||
prog.initSS = 0;
|
||||
prog.initSP = 0xFFFE;
|
||||
prog.cReloc = 0;
|
||||
|
||||
prepareImage(prog, cb, fp);
|
||||
|
||||
/* Set up memory map */
|
||||
cb = (prog.cbImage + 3) / 4;
|
||||
prog.map = (uint8_t *)malloc(cb);
|
||||
memset(prog.map, BM_UNKNOWN, (size_t)cb);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
#if 0
|
||||
struct RomLoader {
|
||||
bool canLoad(QFile &fp) {
|
||||
fp.seek(0xFFF0);
|
||||
uint8_t sig[1];
|
||||
if(fp.read((char *)sig,1) == 1)
|
||||
{
|
||||
return (sig[0] == 0xEA);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool load(PROG &prog,QFile &fp) {
|
||||
printf("Loading ROM...\n");
|
||||
fp.seek(0);
|
||||
/* ROM file
|
||||
* In this case the load module size is just the file length
|
||||
*/
|
||||
auto cb = fp.size();
|
||||
|
||||
fp.seek(cb - 0x10);
|
||||
uint8_t buf[5];
|
||||
printf("Going to get CS/IP...\n");
|
||||
if(fp.read((char *)buf, 5) != 5)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
fp.seek(0);
|
||||
|
||||
/* ROM File, Hard to say where it is suppose to start, so try to trust the
|
||||
*/
|
||||
prog.initIP = (buf[2] << 8) | buf[1];
|
||||
//prog.initCS = 0;
|
||||
prog.initCS = (buf[4] << 8) | buf[3];
|
||||
|
||||
prog.initSS = 0;
|
||||
prog.initSP = 0xFFFE;
|
||||
|
||||
prog.cReloc = 0;
|
||||
|
||||
prepareImage(prog, cb, fp);
|
||||
|
||||
/* Set up memory map */
|
||||
cb = (prog.cbImage + 3) / 4;
|
||||
prog.map = (uint8_t *)malloc(cb);
|
||||
memset(prog.map, BM_UNKNOWN, (size_t)cb);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
void prepareImage(PROG &prog, size_t sz, QFile &fp)
|
||||
{
|
||||
int32_t start = 0x100000 - sz;
|
||||
/* Allocate a block of memory for the program. */
|
||||
prog.cbImage = 1 * 1024 * 1024; /* Allocate the whole 1MB memory */
|
||||
//prog.cbImage = 64 * 1024; /* Allocate the whole 1MB memory */
|
||||
prog.Imagez = new uint8_t [prog.cbImage];
|
||||
|
||||
if (fp.read((char *)prog.Imagez + start, sz) != sz)
|
||||
//if (fp.read((char *)prog.Imagez, sz) != sz)
|
||||
{
|
||||
fatalError(CANNOT_READ, fp.fileName().toLocal8Bit().data());
|
||||
}
|
||||
}
|
||||
};
|
||||
#else
|
||||
struct RomLoader {
|
||||
bool canLoad(QFile &fp) {
|
||||
fp.seek(0xFFF0);
|
||||
uint8_t sig[1];
|
||||
if(fp.read((char *)sig,1) == 1)
|
||||
{
|
||||
return (sig[0] == 0xEA);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool load(PROG &prog,QFile &fp) {
|
||||
fp.seek(0);
|
||||
/* COM file
|
||||
* In this case the load module size is just the file length
|
||||
*/
|
||||
auto cb = fp.size();
|
||||
|
||||
/* COM programs start off with an ORG 100H (to leave room for a PSP)
|
||||
* This is also the implied start address so if we load the image
|
||||
* at offset 100H addresses should all line up properly again.
|
||||
*/
|
||||
prog.initCS = 0;
|
||||
prog.initIP = 0x000;
|
||||
prog.initSS = 0;
|
||||
prog.initSP = 0xFFFE;
|
||||
prog.cReloc = 0;
|
||||
|
||||
prepareImage(prog, cb, fp);
|
||||
|
||||
/* Set up memory map */
|
||||
cb = (prog.cbImage + 3) / 4;
|
||||
prog.map = (uint8_t *)malloc(cb);
|
||||
memset(prog.map, BM_UNKNOWN, (size_t)cb);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
void prepareImage(PROG &prog, size_t sz, QFile &fp)
|
||||
{
|
||||
/* Allocate a block of memory for the program. */
|
||||
prog.cbImage = sz;
|
||||
prog.Imagez = new uint8_t[prog.cbImage];
|
||||
|
||||
if (sz != fp.read((char *)prog.Imagez, sz))
|
||||
fatalError(CANNOT_READ, fp.fileName().toLocal8Bit().data());
|
||||
}
|
||||
};
|
||||
#endif
|
||||
struct ExeLoader : public DosLoader {
|
||||
bool canLoad(QFile &fp) {
|
||||
if(fp.size()<sizeof(header))
|
||||
return false;
|
||||
MZHeader tmp_header;
|
||||
fp.seek(0);
|
||||
fp.read((char *)&tmp_header, sizeof(header));
|
||||
if(not (tmp_header.sigLo == 0x4D and tmp_header.sigHi == 0x5A))
|
||||
return false;
|
||||
|
||||
/* This is a typical DOS kludge! */
|
||||
if (LH(&header.relocTabOffset) == 0x40)
|
||||
{
|
||||
qDebug() << "Don't understand new EXE format";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool load(PROG &prog,QFile &fp) {
|
||||
/* Read rest of header */
|
||||
fp.seek(0);
|
||||
if (fp.read((char *)&header, sizeof(header)) != sizeof(header))
|
||||
return false;
|
||||
|
||||
/* Calculate the load module size.
|
||||
* This is the number of pages in the file
|
||||
* less the length of the header and reloc table
|
||||
* less the number of bytes unused on last page
|
||||
*/
|
||||
uint32_t cb = (uint32_t)LH(&header.numPages) * 512 - (uint32_t)LH(&header.numParaHeader) * 16;
|
||||
if (header.lastPageSize)
|
||||
{
|
||||
cb -= 512 - LH(&header.lastPageSize);
|
||||
}
|
||||
|
||||
/* We quietly ignore minAlloc and maxAlloc since for our
|
||||
* purposes it doesn't really matter where in real memory
|
||||
* the program would end up. EXE programs can't really rely on
|
||||
* their load location so setting the PSP segment to 0 is fine.
|
||||
* Certainly programs that prod around in DOS or BIOS are going
|
||||
* to have to load DS from a constant so it'll be pretty
|
||||
* obvious.
|
||||
*/
|
||||
prog.initCS = (int16_t)LH(&header.initCS) + EXE_RELOCATION;
|
||||
prog.initIP = (int16_t)LH(&header.initIP);
|
||||
prog.initSS = (int16_t)LH(&header.initSS) + EXE_RELOCATION;
|
||||
prog.initSP = (int16_t)LH(&header.initSP);
|
||||
prog.cReloc = (int16_t)LH(&header.numReloc);
|
||||
|
||||
/* Allocate the relocation table */
|
||||
if (prog.cReloc)
|
||||
{
|
||||
prog.relocTable.resize(prog.cReloc);
|
||||
fp.seek(LH(&header.relocTabOffset));
|
||||
|
||||
/* Read in seg:offset pairs and convert to Image ptrs */
|
||||
uint8_t buf[4];
|
||||
for (int i = 0; i < prog.cReloc; i++)
|
||||
{
|
||||
fp.read((char *)buf,4);
|
||||
prog.relocTable[i] = LH(buf) + (((int)LH(buf+2) + EXE_RELOCATION)<<4);
|
||||
}
|
||||
}
|
||||
/* Seek to start of image */
|
||||
uint32_t start_of_image= LH(&header.numParaHeader) * 16;
|
||||
fp.seek(start_of_image);
|
||||
/* Allocate a block of memory for the program. */
|
||||
prepareImage(prog,cb,fp);
|
||||
|
||||
/* Set up memory map */
|
||||
cb = (prog.cbImage + 3) / 4;
|
||||
prog.map = (uint8_t *)malloc(cb);
|
||||
memset(prog.map, BM_UNKNOWN, (size_t)cb);
|
||||
|
||||
/* Relocate segment constants */
|
||||
for(uint32_t v : prog.relocTable) {
|
||||
uint8_t *p = &prog.Imagez[v];
|
||||
uint16_t w = (uint16_t)LH(p) + EXE_RELOCATION;
|
||||
*p++ = (uint8_t)(w & 0x00FF);
|
||||
*p = (uint8_t)((w & 0xFF00) >> 8);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
/*****************************************************************************
|
||||
* LoadImage
|
||||
****************************************************************************/
|
||||
bool Project::load()
|
||||
{
|
||||
// addTask(loaderSelection,PreCond(BinaryImage))
|
||||
// addTask(applyLoader,PreCond(Loader))
|
||||
const char *fname = binary_path().toLocal8Bit().data();
|
||||
QFile finfo(binary_path());
|
||||
/* Open the input file */
|
||||
if(not finfo.open(QFile::ReadOnly)) {
|
||||
fatalError(CANNOT_OPEN, fname);
|
||||
}
|
||||
/* Read in first 2 bytes to check EXE signature */
|
||||
if (finfo.size()<=2)
|
||||
{
|
||||
fatalError(CANNOT_READ, fname);
|
||||
}
|
||||
RomLoader rom_loader;
|
||||
ComLoader com_loader;
|
||||
ExeLoader exe_loader;
|
||||
if(rom_loader.canLoad(finfo)) {
|
||||
/* We have no relacation and code should be on 64K only,
|
||||
* So let's consider it as a COM file
|
||||
*/
|
||||
prog.fCOM = true;
|
||||
return rom_loader.load(prog,finfo);
|
||||
}
|
||||
if(exe_loader.canLoad(finfo)) {
|
||||
prog.fCOM = false;
|
||||
return exe_loader.load(prog,finfo);
|
||||
}
|
||||
if(com_loader.canLoad(finfo)) {
|
||||
prog.fCOM = true;
|
||||
return com_loader.load(prog,finfo);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
uint32_t SynthLab;
|
||||
/* Parses the program, builds the call graph, and returns the list of
|
||||
* procedures found */
|
||||
void DccFrontend::parse(Project &proj)
|
||||
{
|
||||
PROG &prog(proj.prog);
|
||||
STATE state;
|
||||
|
||||
/* Set initial state */
|
||||
state.setState(rES, 0); /* PSP segment */
|
||||
state.setState(rDS, 0);
|
||||
state.setState(rCS, prog.initCS);
|
||||
state.setState(rSS, prog.initSS);
|
||||
state.setState(rSP, prog.initSP);
|
||||
state.IP = ((uint32_t)prog.initCS << 4) + prog.initIP;
|
||||
SynthLab = SYNTHESIZED_MIN;
|
||||
|
||||
/* Check for special settings of initial state, based on idioms of the
|
||||
startup code */
|
||||
state.checkStartup();
|
||||
ilFunction start_proc;
|
||||
/* Make a struct for the initial procedure */
|
||||
if (prog.offMain != -1)
|
||||
{
|
||||
start_proc = proj.createFunction(0,"main");
|
||||
start_proc->retVal.loc = REG_FRAME;
|
||||
start_proc->retVal.type = TYPE_WORD_SIGN;
|
||||
start_proc->retVal.id.regi = rAX;
|
||||
/* We know where main() is. Start the flow of control from there */
|
||||
start_proc->procEntry = prog.offMain;
|
||||
/* In medium and large models, the segment of main may (will?) not be
|
||||
the same as the initial CS segment (of the startup code) */
|
||||
state.setState(rCS, prog.segMain);
|
||||
state.IP = prog.offMain;
|
||||
}
|
||||
else
|
||||
{
|
||||
start_proc = proj.createFunction(0,"start");
|
||||
/* Create initial procedure at program start address */
|
||||
start_proc->procEntry = (uint32_t)state.IP;
|
||||
}
|
||||
|
||||
/* The state info is for the first procedure */
|
||||
start_proc->state = state;
|
||||
|
||||
/* Set up call graph initial node */
|
||||
proj.callGraph = new CALL_GRAPH;
|
||||
proj.callGraph->proc = start_proc;
|
||||
|
||||
/* This proc needs to be called to set things up for LibCheck(), which
|
||||
checks a proc to see if it is a know C (etc) library */
|
||||
prog.bSigs = SetupLibCheck();
|
||||
//BUG: proj and g_proj are 'live' at this point !
|
||||
|
||||
/* Recursively build entire procedure list */
|
||||
start_proc->FollowCtrl(proj.callGraph, &state);
|
||||
|
||||
/* This proc needs to be called to clean things up from SetupLibCheck() */
|
||||
CleanupLibCheck();
|
||||
}
|
||||
@ -1,6 +1,9 @@
|
||||
#include "Procedure.h"
|
||||
|
||||
#include "msvc_fixes.h"
|
||||
#include "project.h"
|
||||
#include "scanner.h"
|
||||
|
||||
//FunctionType *Function::getFunctionType() const
|
||||
//{
|
||||
// return &m_type;
|
||||
@ -14,8 +17,8 @@ void JumpTable::pruneEntries(uint16_t cs)
|
||||
PROG *prg(Project::get()->binary());
|
||||
for (uint32_t i = start; i < finish; i += 2)
|
||||
{
|
||||
uint32_t target = cs + LH(&prg->Image[i]);
|
||||
if (target < finish && target >= start)
|
||||
uint32_t target = cs + LH(&prg->image()[i]);
|
||||
if (target < finish and target >= start)
|
||||
finish = target;
|
||||
else if (target >= (uint32_t)prg->cbImage)
|
||||
finish = i;
|
||||
@ -23,10 +26,15 @@ void JumpTable::pruneEntries(uint16_t cs)
|
||||
ICODE _Icode; // used as scan input
|
||||
for (uint32_t i = start; i < finish; i += 2)
|
||||
{
|
||||
uint32_t target = cs + LH(&prg->Image[i]);
|
||||
uint32_t target = cs + LH(&prg->image()[i]);
|
||||
/* Be wary of 00 00 as code - it's probably data */
|
||||
if (! (prg->Image[target] || prg->Image[target+1]) || scan(target, _Icode))
|
||||
if (not (prg->image()[target] or prg->image()[target+1]) or scan(target, _Icode))
|
||||
finish = i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Function::callingConv(CConv::Type v) {
|
||||
m_call_conv=CConv::create(v);
|
||||
}
|
||||
|
||||
122
src/RegisterNode.cpp
Normal file
122
src/RegisterNode.cpp
Normal file
@ -0,0 +1,122 @@
|
||||
#include "types.h"
|
||||
#include "msvc_fixes.h"
|
||||
#include "ast.h"
|
||||
#include "bundle.h"
|
||||
#include "machine_x86.h"
|
||||
#include "project.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <boost/range/adaptor/filtered.hpp>
|
||||
#include <boost/range.hpp>
|
||||
//#include <boost/range/algorithm.hpp>
|
||||
//#include <boost/assign.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace boost::adaptors;
|
||||
RegisterNode::RegisterNode(const LLOperand &op, LOCAL_ID *locsym)
|
||||
{
|
||||
m_syms = locsym;
|
||||
ident.type(REGISTER);
|
||||
hlType type_sel;
|
||||
regType reg_type;
|
||||
if (op.byteWidth()==1)
|
||||
{
|
||||
type_sel = TYPE_BYTE_SIGN;
|
||||
reg_type = BYTE_REG;
|
||||
}
|
||||
else /* uint16_t */
|
||||
{
|
||||
type_sel = TYPE_WORD_SIGN;
|
||||
reg_type = WORD_REG;
|
||||
}
|
||||
regiIdx = locsym->newByteWordReg(type_sel, op.regi);
|
||||
regiType = reg_type;
|
||||
}
|
||||
|
||||
//RegisterNode::RegisterNode(eReg regi, uint32_t icodeFlg, LOCAL_ID *locsym)
|
||||
//{
|
||||
// ident.type(REGISTER);
|
||||
// hlType type_sel;
|
||||
// regType reg_type;
|
||||
// if ((icodeFlg & B) or (icodeFlg & SRC_B))
|
||||
// {
|
||||
// type_sel = TYPE_BYTE_SIGN;
|
||||
// reg_type = BYTE_REG;
|
||||
// }
|
||||
// else /* uint16_t */
|
||||
// {
|
||||
// type_sel = TYPE_WORD_SIGN;
|
||||
// reg_type = WORD_REG;
|
||||
// }
|
||||
// regiIdx = locsym->newByteWordReg(type_sel, regi);
|
||||
// regiType = reg_type;
|
||||
//}
|
||||
|
||||
QString RegisterNode::walkCondExpr(Function *pProc, int *numLoc) const
|
||||
{
|
||||
QString codeOut;
|
||||
|
||||
QString o;
|
||||
assert(&pProc->localId==m_syms);
|
||||
ID *id = &pProc->localId.id_arr[regiIdx];
|
||||
if (id->name[0] == '\0') /* no name */
|
||||
{
|
||||
id->setLocalName(++(*numLoc));
|
||||
codeOut += QString("%1 %2; ").arg(TypeContainer::typeName(id->type)).arg(id->name);
|
||||
codeOut += QString("/* %1 */\n").arg(Machine_X86::regName(id->id.regi));
|
||||
}
|
||||
if (id->hasMacro)
|
||||
o += QString("%1(%2)").arg(id->macro).arg(id->name);
|
||||
else
|
||||
o += id->name;
|
||||
|
||||
cCode.appendDecl(codeOut);
|
||||
return o;
|
||||
}
|
||||
|
||||
int RegisterNode::hlTypeSize(Function *) const
|
||||
{
|
||||
if (regiType == BYTE_REG)
|
||||
return 1;
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
|
||||
hlType RegisterNode::expType(Function *pproc) const
|
||||
{
|
||||
if (regiType == BYTE_REG)
|
||||
return TYPE_BYTE_SIGN;
|
||||
else
|
||||
return TYPE_WORD_SIGN;
|
||||
}
|
||||
|
||||
Expr *RegisterNode::insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym)
|
||||
{
|
||||
assert(locsym==m_syms);
|
||||
eReg treeReg = locsym->id_arr[regiIdx].id.regi;
|
||||
if (treeReg == regi) /* uint16_t reg */
|
||||
{
|
||||
return _expr;
|
||||
}
|
||||
else if(Machine_X86::isSubRegisterOf(treeReg,regi)) /* uint16_t/uint8_t reg */
|
||||
{
|
||||
return _expr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
bool RegisterNode::xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locId)
|
||||
{
|
||||
uint8_t regi = locId.id_arr[regiIdx].id.regi;
|
||||
range_to_check.advance_begin(1);
|
||||
auto all_valid_and_high_level_after_start = range_to_check | filtered(ICODE::select_valid_high_level);
|
||||
for (ICODE &i : all_valid_and_high_level_after_start)
|
||||
if (i.du.def.testRegAndSubregs(regi))
|
||||
return false;
|
||||
if (all_valid_and_high_level_after_start.end().base() != lastBBinst)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
1238
src/ast.cpp
1238
src/ast.cpp
File diff suppressed because it is too large
Load Diff
174
src/backend.cpp
174
src/backend.cpp
@ -4,20 +4,34 @@
|
||||
* Purpose: Back-end module. Generates C code for each procedure.
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
#include "disassem.h"
|
||||
#include "project.h"
|
||||
#include "CallGraph.h"
|
||||
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QDebug>
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/range/adaptor/filtered.hpp>
|
||||
#include <boost/range/algorithm.hpp>
|
||||
|
||||
#include "dcc.h"
|
||||
#include "disassem.h"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "project.h"
|
||||
bundle cCode; /* Procedure declaration and code */
|
||||
|
||||
using namespace boost;
|
||||
using namespace boost::adaptors;
|
||||
using namespace std;
|
||||
|
||||
bundle cCode; /* Procedure declaration and code */
|
||||
|
||||
/* Returns a unique index to the next label */
|
||||
int getNextLabel()
|
||||
{
|
||||
@ -29,14 +43,14 @@ int getNextLabel()
|
||||
/* displays statistics on the subroutine */
|
||||
void Function::displayStats ()
|
||||
{
|
||||
printf("\nStatistics - Subroutine %s\n", name.c_str());
|
||||
printf ("Number of Icode instructions:\n");
|
||||
printf (" Low-level : %4d\n", stats.numLLIcode);
|
||||
if (! (flg & PROC_ASM))
|
||||
qDebug() << "\nStatistics - Subroutine" << name;
|
||||
qDebug() << "Number of Icode instructions:";
|
||||
qDebug() << " Low-level :" << stats.numLLIcode;
|
||||
if (not (flg & PROC_ASM))
|
||||
{
|
||||
printf (" High-level: %4d\n", stats.numHLIcode);
|
||||
printf (" Percentage reduction: %2.2f%%\n", 100.0 - (stats.numHLIcode *
|
||||
100.0) / stats.numLLIcode);
|
||||
qDebug() << " High-level:"<<stats.numHLIcode;
|
||||
qDebug() << QString(" Percentage reduction: %1%%").arg(100.0 - (stats.numHLIcode *
|
||||
100.0) / stats.numLLIcode,4,'f',2,QChar('0'));
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,7 +108,7 @@ char *cChar (uint8_t c)
|
||||
* Note: to get to the value of the variable:
|
||||
* com file: prog.Image[operand]
|
||||
* exe file: prog.Image[operand+0x100] */
|
||||
static void printGlobVar (std::ostream &ostr,SYM * psym)
|
||||
static void printGlobVar (QTextStream &ostr,SYM * psym)
|
||||
{
|
||||
int j;
|
||||
PROG &prog(Project::get()->prog);
|
||||
@ -103,24 +117,24 @@ static void printGlobVar (std::ostream &ostr,SYM * psym)
|
||||
switch (psym->size)
|
||||
{
|
||||
case 1:
|
||||
ostr << "uint8_t\t"<<psym->name<<" = "<<prog.Image[relocOp]<<";\n";
|
||||
ostr << "uint8_t\t"<<psym->name<<" = "<<prog.image()[relocOp]<<";\n";
|
||||
break;
|
||||
case 2:
|
||||
ostr << "uint16_t\t"<<psym->name<<" = "<<LH(prog.Image+relocOp)<<";\n";
|
||||
ostr << "uint16_t\t"<<psym->name<<" = "<<LH(prog.image()+relocOp)<<";\n";
|
||||
break;
|
||||
case 4: if (psym->type == TYPE_PTR) /* pointer */
|
||||
ostr << "uint16_t *\t"<<psym->name<<" = "<<LH(prog.Image+relocOp)<<";\n";
|
||||
ostr << "uint16_t *\t"<<psym->name<<" = "<<LH(prog.image()+relocOp)<<";\n";
|
||||
else /* char */
|
||||
ostr << "char\t"<<psym->name<<"[4] = \""<<
|
||||
prog.Image[relocOp]<<prog.Image[relocOp+1]<<
|
||||
prog.Image[relocOp+2]<<prog.Image[relocOp+3]<<";\n";
|
||||
prog.image()[relocOp]<<prog.image()[relocOp+1]<<
|
||||
prog.image()[relocOp+2]<<prog.image()[relocOp+3]<<";\n";
|
||||
break;
|
||||
default:
|
||||
{
|
||||
ostringstream strContents;
|
||||
QString strContents;
|
||||
for (j=0; j < psym->size; j++)
|
||||
strContents << cChar(prog.Image[relocOp + j]);
|
||||
ostr << "char\t*"<<psym->name<<" = \""<<strContents.str()<<"\";\n";
|
||||
strContents += cChar(prog.image()[relocOp + j]);
|
||||
ostr << "char\t*"<<psym->name<<" = \""<<strContents<<"\";\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -131,7 +145,8 @@ static void printGlobVar (std::ostream &ostr,SYM * psym)
|
||||
* initialization. */
|
||||
void Project::writeGlobSymTable()
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
QString contents;
|
||||
QTextStream ostr(&contents);
|
||||
|
||||
if (symtab.empty())
|
||||
return;
|
||||
@ -139,13 +154,13 @@ void Project::writeGlobSymTable()
|
||||
for (SYM &sym : symtab)
|
||||
{
|
||||
if (sym.duVal.isUSE_VAL()) /* first used */
|
||||
printGlobVar (ostr,&sym);
|
||||
printGlobVar (ostr,&sym);
|
||||
else { /* first defined */
|
||||
switch (sym.size) {
|
||||
case 1: ostr<<"uint8_t\t"; break;
|
||||
case 2: ostr<<"int\t"; break;
|
||||
case 2: ostr<<"int16_t\t"; break;
|
||||
case 4: if (sym.type == TYPE_PTR)
|
||||
ostr<<"int\t*";
|
||||
ostr<<"int32_t\t*";
|
||||
else
|
||||
ostr<<"char\t*";
|
||||
break;
|
||||
@ -155,19 +170,20 @@ void Project::writeGlobSymTable()
|
||||
}
|
||||
}
|
||||
ostr<< "\n";
|
||||
cCode.appendDecl( ostr.str() );
|
||||
ostr.flush();
|
||||
cCode.appendDecl( contents );
|
||||
}
|
||||
|
||||
|
||||
/* Writes the header information and global variables to the output C file
|
||||
* fp. */
|
||||
static void writeHeader (std::ostream &_ios, char *fileName)
|
||||
static void writeHeader (QIODevice &_ios, const std::string &fileName)
|
||||
{
|
||||
PROG &prog(Project::get()->prog);
|
||||
/* Write header information */
|
||||
cCode.init();
|
||||
cCode.appendDecl( "/*\n");
|
||||
cCode.appendDecl( " * Input file\t: %s\n", fileName);
|
||||
cCode.appendDecl( " * Input file\t: %s\n", fileName.c_str());
|
||||
cCode.appendDecl( " * File type\t: %s\n", (prog.fCOM)?"COM":"EXE");
|
||||
cCode.appendDecl( " */\n\n#include \"dcc.h\"\n\n");
|
||||
|
||||
@ -178,11 +194,12 @@ static void writeHeader (std::ostream &_ios, char *fileName)
|
||||
}
|
||||
|
||||
// Note: Not currently called!
|
||||
/* Checks the given icode to determine whether it has a label associated
|
||||
/** Checks the given icode to determine whether it has a label associated
|
||||
* to it. If so, a goto is emitted to this label; otherwise, a new label
|
||||
* is created and a goto is also emitted.
|
||||
* Note: this procedure is to be used when the label is to be forward on
|
||||
* the code; that is, the target code has not been traversed yet. */
|
||||
#if 0
|
||||
static void emitFwdGotoLabel (ICODE * pt, int indLevel)
|
||||
{
|
||||
if ( not pt->ll()->testFlags(HLL_LABEL)) /* node hasn't got a lab */
|
||||
@ -193,14 +210,15 @@ static void emitFwdGotoLabel (ICODE * pt, int indLevel)
|
||||
}
|
||||
cCode.appendCode( "%sgoto l%ld;\n", indentStr(indLevel), pt->ll()->hllLabNum);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Writes the procedure's declaration (including arguments), local variables,
|
||||
* and invokes the procedure that writes the code of the given record *hli */
|
||||
void Function::codeGen (std::ostream &fs)
|
||||
void Function::codeGen (QIODevice &fs)
|
||||
{
|
||||
int numLoc;
|
||||
ostringstream ostr;
|
||||
QString ostr_contents;
|
||||
QTextStream ostr(&ostr_contents);
|
||||
//STKFRAME * args; /* Procedure arguments */
|
||||
//char buf[200], /* Procedure's definition */
|
||||
// arg[30]; /* One argument */
|
||||
@ -209,26 +227,27 @@ void Function::codeGen (std::ostream &fs)
|
||||
/* Write procedure/function header */
|
||||
cCode.init();
|
||||
if (flg & PROC_IS_FUNC) /* Function */
|
||||
ostr<< "\n"<<TypeContainer::typeName(retVal.type)<<" "<<name<<" (";
|
||||
ostr << QString("\n%1 %2 (").arg(TypeContainer::typeName(retVal.type)).arg(name);
|
||||
else /* Procedure */
|
||||
ostr<< "\nvoid "<<name<<" (";
|
||||
ostr << "\nvoid "+name+" (";
|
||||
|
||||
/* Write arguments */
|
||||
for (size_t i = 0; i < args.size(); i++)
|
||||
struct validArg
|
||||
{
|
||||
if ( args[i].invalid )
|
||||
continue;
|
||||
ostr<<hlTypes[args[i].type]<<" "<<args[i].name;
|
||||
if (i < (args.size() - 1))
|
||||
ostr<<", ";
|
||||
bool operator()(STKSYM &s) { return s.invalid==false;}
|
||||
};
|
||||
QStringList parts;
|
||||
for (STKSYM &arg : (args | filtered(validArg())))
|
||||
{
|
||||
parts << QString("%1 %2").arg(hlTypes[arg.type]).arg(arg.name);
|
||||
}
|
||||
ostr<<")\n";
|
||||
ostr << parts.join(", ")+")\n";
|
||||
|
||||
/* Write comments */
|
||||
writeProcComments( ostr );
|
||||
|
||||
/* Write local variables */
|
||||
if (! (flg & PROC_ASM))
|
||||
if (not (flg & PROC_ASM))
|
||||
{
|
||||
numLoc = 0;
|
||||
for (ID &refId : localId )
|
||||
@ -239,8 +258,8 @@ void Function::codeGen (std::ostream &fs)
|
||||
if (refId.loc == REG_FRAME)
|
||||
{
|
||||
/* Register variables are assigned to a local variable */
|
||||
if (((flg & SI_REGVAR) && (refId.id.regi == rSI)) ||
|
||||
((flg & DI_REGVAR) && (refId.id.regi == rDI)))
|
||||
if (((flg & SI_REGVAR) and (refId.id.regi == rSI)) or
|
||||
((flg & DI_REGVAR) and (refId.id.regi == rDI)))
|
||||
{
|
||||
refId.setLocalName(++numLoc);
|
||||
ostr << "int "<<refId.name<<";\n";
|
||||
@ -256,7 +275,9 @@ void Function::codeGen (std::ostream &fs)
|
||||
}
|
||||
}
|
||||
}
|
||||
fs<<ostr.str();
|
||||
ostr.flush();
|
||||
fs.write(ostr_contents.toLatin1());
|
||||
|
||||
/* Write procedure's code */
|
||||
if (flg & PROC_ASM) /* generate assembler */
|
||||
{
|
||||
@ -265,7 +286,7 @@ void Function::codeGen (std::ostream &fs)
|
||||
}
|
||||
else /* generate C */
|
||||
{
|
||||
m_cfg.front()->writeCode (1, this, &numLoc, MAX, UN_INIT);
|
||||
m_actual_cfg.front()->writeCode (1, this, &numLoc, MAX, UN_INIT);
|
||||
}
|
||||
|
||||
cCode.appendCode( "}\n\n");
|
||||
@ -273,44 +294,49 @@ void Function::codeGen (std::ostream &fs)
|
||||
freeBundle (&cCode);
|
||||
|
||||
/* Write Live register analysis information */
|
||||
if (option.verbose)
|
||||
if (option.verbose) {
|
||||
QString debug_contents;
|
||||
QTextStream debug_stream(&debug_contents);
|
||||
for (size_t i = 0; i < numBBs; i++)
|
||||
{
|
||||
pBB = m_dfsLast[i];
|
||||
if (pBB->flg & INVALID_BB) continue; /* skip invalid BBs */
|
||||
cout << "BB "<<i<<"\n";
|
||||
cout << " Start = "<<pBB->begin()->loc_ip;
|
||||
cout << ", end = "<<pBB->begin()->loc_ip+pBB->size()<<"\n";
|
||||
cout << " LiveUse = ";
|
||||
Machine_X86::writeRegVector(cout,pBB->liveUse);
|
||||
cout << "\n Def = ";
|
||||
Machine_X86::writeRegVector(cout,pBB->def);
|
||||
cout << "\n LiveOut = ";
|
||||
Machine_X86::writeRegVector(cout,pBB->liveOut);
|
||||
cout << "\n LiveIn = ";
|
||||
Machine_X86::writeRegVector(cout,pBB->liveIn);
|
||||
cout <<"\n\n";
|
||||
debug_stream << "BB "<<i<<"\n";
|
||||
debug_stream << " Start = "<<pBB->begin()->loc_ip;
|
||||
debug_stream << ", end = "<<pBB->begin()->loc_ip+pBB->size()<<"\n";
|
||||
debug_stream << " LiveUse = ";
|
||||
Machine_X86::writeRegVector(debug_stream,pBB->liveUse);
|
||||
debug_stream << "\n Def = ";
|
||||
Machine_X86::writeRegVector(debug_stream,pBB->def);
|
||||
debug_stream << "\n LiveOut = ";
|
||||
Machine_X86::writeRegVector(debug_stream,pBB->liveOut);
|
||||
debug_stream << "\n LiveIn = ";
|
||||
Machine_X86::writeRegVector(debug_stream,pBB->liveIn);
|
||||
debug_stream <<"\n\n";
|
||||
}
|
||||
debug_stream.flush();
|
||||
qDebug() << debug_contents.toLatin1();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Recursive procedure. Displays the procedure's code in depth-first order
|
||||
* of the call graph. */
|
||||
static void backBackEnd (char *filename, CALL_GRAPH * pcallGraph, std::ostream &_ios)
|
||||
static void backBackEnd (CALL_GRAPH * pcallGraph, QIODevice &_ios)
|
||||
{
|
||||
|
||||
// IFace.Yield(); /* This is a good place to yield to other apps */
|
||||
|
||||
/* Check if this procedure has been processed already */
|
||||
if ((pcallGraph->proc->flg & PROC_OUTPUT) ||
|
||||
if ((pcallGraph->proc->flg & PROC_OUTPUT) or
|
||||
(pcallGraph->proc->flg & PROC_ISLIB))
|
||||
return;
|
||||
pcallGraph->proc->flg |= PROC_OUTPUT;
|
||||
|
||||
/* Dfs if this procedure has any successors */
|
||||
for (size_t i = 0; i < pcallGraph->outEdges.size(); i++)
|
||||
for (auto & elem : pcallGraph->outEdges)
|
||||
{
|
||||
backBackEnd (filename, pcallGraph->outEdges[i], _ios);
|
||||
backBackEnd (elem, _ios);
|
||||
}
|
||||
|
||||
/* Generate code for this procedure */
|
||||
@ -321,7 +347,7 @@ static void backBackEnd (char *filename, CALL_GRAPH * pcallGraph, std::ostream &
|
||||
/* Generate statistics */
|
||||
if (option.Stats)
|
||||
pcallGraph->proc->displayStats ();
|
||||
if (! (pcallGraph->proc->flg & PROC_ASM))
|
||||
if (not (pcallGraph->proc->flg & PROC_ASM))
|
||||
{
|
||||
stats.totalLL += stats.numLLIcode;
|
||||
stats.totalHL += stats.numHLIcode;
|
||||
@ -330,33 +356,31 @@ static void backBackEnd (char *filename, CALL_GRAPH * pcallGraph, std::ostream &
|
||||
|
||||
|
||||
/* Invokes the necessary routines to produce code one procedure at a time. */
|
||||
void BackEnd (char *fileName, CALL_GRAPH * pcallGraph)
|
||||
void BackEnd(CALL_GRAPH * pcallGraph)
|
||||
{
|
||||
std::ofstream fs; /* Output C file */
|
||||
|
||||
/* Get output file name */
|
||||
std::string outNam(fileName);
|
||||
outNam = outNam.substr(0,outNam.rfind("."))+".b"; /* b for beta */
|
||||
QString outNam(Project::get()->output_name("b")); /* b for beta */
|
||||
QFile fs(outNam); /* Output C file */
|
||||
|
||||
/* Open output file */
|
||||
fs.open(outNam);
|
||||
if(!fs.is_open())
|
||||
fatalError (CANNOT_OPEN, outNam.c_str());
|
||||
printf ("dcc: Writing C beta file %s\n", outNam.c_str());
|
||||
if(not fs.open(QFile::WriteOnly|QFile::Text))
|
||||
fatalError (CANNOT_OPEN, outNam.toStdString().c_str());
|
||||
|
||||
qDebug()<<"dcc: Writing C beta file"<<outNam;
|
||||
|
||||
/* Header information */
|
||||
writeHeader (fs, fileName);
|
||||
writeHeader (fs, option.filename.toStdString());
|
||||
|
||||
/* Initialize total Icode instructions statistics */
|
||||
stats.totalLL = 0;
|
||||
stats.totalHL = 0;
|
||||
|
||||
/* Process each procedure at a time */
|
||||
backBackEnd (fileName, pcallGraph, fs);
|
||||
backBackEnd (pcallGraph, fs);
|
||||
|
||||
/* Close output file */
|
||||
fs.close();
|
||||
printf ("dcc: Finished writing C beta file\n");
|
||||
qDebug() << "dcc: Finished writing C beta file";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
#include <memory.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <QtCore/QIODevice>
|
||||
#define deltaProcLines 20
|
||||
|
||||
using namespace std;
|
||||
@ -21,26 +21,26 @@ using namespace std;
|
||||
* tab is removed and replaced by this label */
|
||||
void strTable::addLabelBundle (int idx, int label)
|
||||
{
|
||||
char s[16];
|
||||
sprintf (s, "l%d: ", label);
|
||||
if(at(idx).size()<4)
|
||||
at(idx)=s;
|
||||
QString &processedLine(at(idx));
|
||||
QString s = QString("l%1: ").arg(label);
|
||||
if(processedLine.size()<4)
|
||||
processedLine = s;
|
||||
else
|
||||
at(idx) = string(s)+at(idx).substr(4);
|
||||
processedLine = s+processedLine.mid(4);
|
||||
}
|
||||
|
||||
|
||||
/* Writes the contents of the string table on the file fp. */
|
||||
static void writeStrTab (std::ostream &ios, strTable &strTab)
|
||||
static void writeStrTab (QIODevice &ios, strTable &strTab)
|
||||
{
|
||||
for (size_t i = 0; i < strTab.size(); i++)
|
||||
ios << strTab[i];
|
||||
ios.write(strTab[i].toLatin1());
|
||||
}
|
||||
|
||||
|
||||
/* Writes the contents of the bundle (procedure code and declaration) to
|
||||
* a file. */
|
||||
void writeBundle (std::ostream &ios, bundle procCode)
|
||||
void writeBundle (QIODevice &ios, bundle procCode)
|
||||
{
|
||||
writeStrTab (ios, procCode.decl);
|
||||
writeStrTab (ios, procCode.code);
|
||||
@ -70,7 +70,7 @@ void bundle::appendCode(const char *format,...)
|
||||
code.push_back(buf);
|
||||
va_end (args);
|
||||
}
|
||||
void bundle::appendCode(const std::string &s)
|
||||
void bundle::appendCode(const QString & s)
|
||||
{
|
||||
code.push_back(s);
|
||||
}
|
||||
@ -85,7 +85,7 @@ void bundle::appendDecl(const char *format,...)
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
void bundle::appendDecl(const std::string &v)
|
||||
void bundle::appendDecl(const QString &v)
|
||||
{
|
||||
decl.push_back(v);
|
||||
}
|
||||
|
||||
284
src/chklib.cpp
284
src/chklib.cpp
@ -5,18 +5,21 @@
|
||||
* (C) Mike van Emmerik
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef __BORLAND__
|
||||
#include <mem.h>
|
||||
#else
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
#include "project.h"
|
||||
#include "perfhlib.h"
|
||||
#include "dcc_interface.h"
|
||||
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QDebug>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
|
||||
PerfectHash g_pattern_hasher;
|
||||
#define NIL -1 /* Used like NULL, but 0 is valid */
|
||||
|
||||
/* Hash table structure */
|
||||
@ -50,13 +53,13 @@ int numVert; /* Number of vertices in the graph (also size of g[]
|
||||
unsigned PatLen; /* Size of the keys (pattern length) */
|
||||
unsigned SymLen; /* Max size of the symbols, including null */
|
||||
static FILE *g_file; /* File being read */
|
||||
static char sSigName[100]; /* Full path name of .sig file */
|
||||
static QString sSigName; /* Full path name of .sig file */
|
||||
|
||||
static uint16_t *T1base, *T2base; /* Pointers to start of T1, T2 */
|
||||
static uint16_t *g; /* g[] */
|
||||
static HT *ht; /* The hash table */
|
||||
static PH_FUNC_STRUCT *pFunc; /* Points to the array of func names */
|
||||
static hlType *pArg=0; /* Points to the array of param types */
|
||||
static hlType *pArg=nullptr; /* Points to the array of param types */
|
||||
static int numFunc; /* Number of func names actually stored */
|
||||
static int numArg; /* Number of param names actually stored */
|
||||
#define DCCLIBS "dcclibs.dat" /* Name of the prototypes data file */
|
||||
@ -68,13 +71,12 @@ void readFileSection(uint16_t* p, int len, FILE *_file);
|
||||
void cleanup(void);
|
||||
void checkStartup(STATE *state);
|
||||
void readProtoFile(void);
|
||||
void fixNewline(char *s);
|
||||
int searchPList(char *name);
|
||||
void checkHeap(char *msg); /* For debugging */
|
||||
|
||||
void fixWildCards(uint8_t pat[]); /* In fixwild.c */
|
||||
|
||||
static boolT locatePattern(uint8_t *source, int iMin, int iMax, uint8_t *pattern,
|
||||
static bool locatePattern(const uint8_t *source, int iMin, int iMax, uint8_t *pattern,
|
||||
int iPatLen, int *index);
|
||||
|
||||
/* * * * * * * * * * * * * * * *\
|
||||
@ -219,8 +221,8 @@ static uint8_t pattMainSmall[] =
|
||||
0xFF, 0x36, WILD, WILD, /* Push argv */
|
||||
0xFF, 0x36, WILD, WILD, /* Push argc */
|
||||
0xE8, WILD, WILD /* call _main */
|
||||
/* 0x50, /* push ax... not in Borland V3 */
|
||||
/* 0xE8 /* call _exit */
|
||||
// 0x50, /* push ax... not in Borland V3 */
|
||||
// 0xE8 /* call _exit */
|
||||
};
|
||||
/* Num bytes from start pattern to the relative offset of main() */
|
||||
#define OFFMAINSMALL 13
|
||||
@ -232,9 +234,9 @@ static uint8_t pattMainMedium[] =
|
||||
0xFF, 0x36, WILD, WILD, /* Push argv */
|
||||
0xFF, 0x36, WILD, WILD, /* Push argc */
|
||||
0x9A, WILD, WILD, WILD, WILD /* call far _main */
|
||||
/* 0x50 /* push ax */
|
||||
/* 0x0E, /* push cs NB not tested Borland */
|
||||
/* 0xE8 /* call _exit */
|
||||
// 0x50 /* push ax */
|
||||
// 0x0E, /* push cs NB not tested Borland */
|
||||
// 0xE8 /* call _exit */
|
||||
};
|
||||
/* Num bytes from start pattern to the relative offset of main() */
|
||||
#define OFFMAINMEDIUM 13
|
||||
@ -248,8 +250,8 @@ static uint8_t pattMainCompact[] =
|
||||
0xFF, 0x36, WILD, WILD, /* Push argv hi */
|
||||
0xFF, 0x36, WILD, WILD, /* Push argc */
|
||||
0xE8, WILD, WILD, /* call _main */
|
||||
/* 0x50, /* push ax */
|
||||
/* 0xE8 /* call _exit */
|
||||
// 0x50, /* push ax */
|
||||
// 0xE8 /* call _exit */
|
||||
};
|
||||
/* Num bytes from start pattern to the relative offset of main() */
|
||||
#define OFFMAINCOMPACT 21
|
||||
@ -263,9 +265,9 @@ static uint8_t pattMainLarge[] =
|
||||
0xFF, 0x36, WILD, WILD, /* Push argv hi */
|
||||
0xFF, 0x36, WILD, WILD, /* Push argc */
|
||||
0x9A, WILD, WILD, WILD, WILD /* call far _main */
|
||||
/* 0x50 /* push ax */
|
||||
/* 0x0E, /* push cs */
|
||||
/* 0xE8 /* call _exit */
|
||||
// 0x50 /* push ax */
|
||||
// 0x0E, /* push cs */
|
||||
// 0xE8 /* call _exit */
|
||||
};
|
||||
/* Num bytes from start pattern to the relative offset of main() */
|
||||
#define OFFMAINLARGE 21
|
||||
@ -296,22 +298,21 @@ static uint8_t pattMsChkstk[] =
|
||||
|
||||
|
||||
/* This procedure is called to initialise the library check code */
|
||||
void SetupLibCheck(void)
|
||||
bool SetupLibCheck(void)
|
||||
{
|
||||
PROG &prog(Project::get()->prog);
|
||||
uint16_t w, len;
|
||||
int i;
|
||||
|
||||
if ((g_file = fopen(sSigName, "rb")) == NULL)
|
||||
IDcc *dcc = IDcc::get();
|
||||
QString fpath = dcc->dataDir("sigs").absoluteFilePath(sSigName);
|
||||
if ((g_file = fopen(qPrintable(fpath), "rb")) == nullptr)
|
||||
{
|
||||
printf("Warning: cannot open signature file %s\n", sSigName);
|
||||
return;
|
||||
printf("Warning: cannot open signature file %s\n", qPrintable(fpath));
|
||||
return false;
|
||||
}
|
||||
|
||||
readProtoFile();
|
||||
|
||||
|
||||
prog.bSigs = false; /* False unless everything goes right */
|
||||
/* Read the parameters */
|
||||
grab(4, g_file);
|
||||
if (memcmp("dccs", buf, 4) != 0)
|
||||
@ -323,22 +324,20 @@ void SetupLibCheck(void)
|
||||
numVert = readFileShort(g_file);
|
||||
PatLen = readFileShort(g_file);
|
||||
SymLen = readFileShort(g_file);
|
||||
if ((PatLen != PATLEN) || (SymLen != SYMLEN))
|
||||
if ((PatLen != PATLEN) or (SymLen != SYMLEN))
|
||||
{
|
||||
printf("Sorry! Compiled for sym and pattern lengths of %d and %d\n",
|
||||
SYMLEN, PATLEN);
|
||||
exit(1);
|
||||
printf("Sorry! Compiled for sym and pattern lengths of %d and %d\n", SYMLEN, PATLEN);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Initialise the perfhlib stuff. Also allocates T1, T2, g, etc */
|
||||
/* Set the parameters for the hash table */
|
||||
g_pattern_hasher.init(
|
||||
g_pattern_hasher.setHashParams(
|
||||
numKeys, /* The number of symbols */
|
||||
PatLen, /* The length of the pattern to be hashed */
|
||||
256, /* The character set of the pattern (0-FF) */
|
||||
0, /* Minimum pattern character value */
|
||||
numVert); /* Specifies c, the sparseness of the graph.
|
||||
See Czech, Havas and Majewski for details */
|
||||
numVert); /* Specifies c, the sparseness of the graph. See Czech, Havas and Majewski for details */
|
||||
T1base = g_pattern_hasher.readT1();
|
||||
T2base = g_pattern_hasher.readT2();
|
||||
g = g_pattern_hasher.readG();
|
||||
@ -355,7 +354,7 @@ void SetupLibCheck(void)
|
||||
if (w != len)
|
||||
{
|
||||
printf("Problem with size of T1: file %d, calc %d\n", w, len);
|
||||
exit(4);
|
||||
return false;
|
||||
}
|
||||
readFileSection(T1base, len, g_file);
|
||||
|
||||
@ -363,13 +362,13 @@ void SetupLibCheck(void)
|
||||
if (memcmp("T2", buf, 2) != 0)
|
||||
{
|
||||
printf("Expected 'T2'\n");
|
||||
exit(3);
|
||||
return false;
|
||||
}
|
||||
w = readFileShort(g_file);
|
||||
if (w != len)
|
||||
{
|
||||
printf("Problem with size of T2: file %d, calc %d\n", w, len);
|
||||
exit(4);
|
||||
return false;
|
||||
}
|
||||
readFileSection(T2base, len, g_file);
|
||||
|
||||
@ -378,14 +377,14 @@ void SetupLibCheck(void)
|
||||
if (memcmp("gg", buf, 2) != 0)
|
||||
{
|
||||
printf("Expected 'gg'\n");
|
||||
exit(3);
|
||||
return false;
|
||||
}
|
||||
len = (uint16_t)(numVert * sizeof(uint16_t));
|
||||
w = readFileShort(g_file);
|
||||
if (w != len)
|
||||
{
|
||||
printf("Problem with size of g[]: file %d, calc %d\n", w, len);
|
||||
exit(4);
|
||||
return false;
|
||||
}
|
||||
readFileSection(g, len, g_file);
|
||||
|
||||
@ -393,22 +392,22 @@ void SetupLibCheck(void)
|
||||
/* This is now the hash table */
|
||||
/* First allocate space for the table */
|
||||
ht = new HT[numKeys];
|
||||
if ( 0 == ht)
|
||||
if ( nullptr == ht)
|
||||
{
|
||||
printf("Could not allocate hash table\n");
|
||||
exit(1);
|
||||
return false;
|
||||
}
|
||||
grab(2, g_file);
|
||||
if (memcmp("ht", buf, 2) != 0)
|
||||
{
|
||||
printf("Expected 'ht'\n");
|
||||
exit(3);
|
||||
return false;
|
||||
}
|
||||
w = readFileShort(g_file);
|
||||
if (w != numKeys * (SymLen + PatLen + sizeof(uint16_t)))
|
||||
{
|
||||
printf("Problem with size of hash table: file %d, calc %d\n", w, len);
|
||||
exit(6);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -417,11 +416,11 @@ void SetupLibCheck(void)
|
||||
if (fread(&ht[i], 1, SymLen + PatLen, g_file) != SymLen + PatLen)
|
||||
{
|
||||
printf("Could not read signature\n");
|
||||
exit(11);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
fclose(g_file);
|
||||
prog.bSigs = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -447,7 +446,7 @@ bool LibCheck(Function & pProc)
|
||||
if (prog.bSigs == false)
|
||||
{
|
||||
/* No signatures... can't rely on hash parameters to be initialised
|
||||
so always return false */
|
||||
so always return false */
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -458,25 +457,27 @@ bool LibCheck(Function & pProc)
|
||||
pProc.name = "main";
|
||||
return false;
|
||||
}
|
||||
memcpy(pat, &prog.Image[fileOffset], PATLEN);
|
||||
//memmove(pat, &prog.Image[fileOffset], PATLEN);
|
||||
if(fileOffset + PATLEN > prog.cbImage)
|
||||
return false;
|
||||
memcpy(pat, &prog.image()[fileOffset], PATLEN);
|
||||
//memmove(pat, &prog.image()[fileOffset], PATLEN);
|
||||
fixWildCards(pat); /* Fix wild cards in the copy */
|
||||
h = g_pattern_hasher.hash(pat); /* Hash the found proc */
|
||||
/* We always have to compare keys, because the hash function will
|
||||
always return a valid index */
|
||||
/* We always have to compare keys, because the hash function will always return a valid index */
|
||||
if (memcmp(ht[h].htPat, pat, PATLEN) == 0)
|
||||
{
|
||||
/* We have a match. Save the name, if not already set */
|
||||
if (pProc.name.empty() ) /* Don't overwrite existing name */
|
||||
if (pProc.name.isEmpty() ) /* Don't overwrite existing name */
|
||||
{
|
||||
/* Give proc the new name */
|
||||
pProc.name = ht[h].htSym;
|
||||
}
|
||||
/* But is it a real library function? */
|
||||
i = NIL;
|
||||
if ((numFunc == 0) || (i=searchPList(ht[h].htSym)) != NIL)
|
||||
if ((numFunc == 0) or (i=searchPList(ht[h].htSym)) != NIL)
|
||||
{
|
||||
pProc.flg |= PROC_ISLIB; /* It's a lib function */
|
||||
pProc.callingConv(CConv::eCdecl);
|
||||
if (i != NIL)
|
||||
{
|
||||
/* Allocate space for the arg struct, and copy the hlType to
|
||||
@ -494,19 +495,26 @@ bool LibCheck(Function & pProc)
|
||||
pProc.flg |= PROC_IS_FUNC;
|
||||
switch (pProc.retVal.type) {
|
||||
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
|
||||
pProc.liveOut = duReg[rDX] | duReg[rAX];
|
||||
pProc.liveOut.setReg(rDX).addReg(rAX);
|
||||
break;
|
||||
case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN:
|
||||
pProc.liveOut = duReg[rAX];
|
||||
pProc.liveOut.setReg(rAX);
|
||||
break;
|
||||
case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN:
|
||||
pProc.liveOut = duReg[rAL];
|
||||
pProc.liveOut.setReg(rAL);
|
||||
break;
|
||||
case TYPE_STR:
|
||||
case TYPE_PTR:
|
||||
fprintf(stderr,"Warning assuming Large memory model\n");
|
||||
pProc.liveOut.setReg(rAX).addReg(rDS);
|
||||
break;
|
||||
default:
|
||||
qCritical() << QString("Unknown retval type %1 for %2 in LibCheck")
|
||||
.arg(pProc.retVal.type).arg(pProc.name);
|
||||
/*** other types are not considered yet ***/
|
||||
}
|
||||
}
|
||||
if (pFunc[i].bVararg)
|
||||
pProc.flg |= PROC_VARARG;
|
||||
pProc.getFunctionType()->m_vararg = pFunc[i].bVararg;
|
||||
}
|
||||
}
|
||||
else if (i == NIL)
|
||||
@ -516,7 +524,7 @@ bool LibCheck(Function & pProc)
|
||||
pProc.flg |= PROC_RUNTIME; /* => is a runtime routine */
|
||||
}
|
||||
}
|
||||
if (locatePattern(prog.Image, pProc.procEntry,
|
||||
if (locatePattern(prog.image(), pProc.procEntry,
|
||||
pProc.procEntry+sizeof(pattMsChkstk),
|
||||
pattMsChkstk, sizeof(pattMsChkstk), &Idx))
|
||||
{
|
||||
@ -526,7 +534,7 @@ bool LibCheck(Function & pProc)
|
||||
pProc.args.numArgs = 0; /* With no args */
|
||||
}
|
||||
|
||||
return (boolT)((pProc.flg & PROC_ISLIB) != 0);
|
||||
return pProc.isLibrary();
|
||||
}
|
||||
|
||||
|
||||
@ -540,8 +548,7 @@ void grab(int n, FILE *_file)
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t
|
||||
readFileShort(FILE *f)
|
||||
uint16_t readFileShort(FILE *f)
|
||||
{
|
||||
uint8_t b1, b2;
|
||||
|
||||
@ -559,8 +566,7 @@ readFileShort(FILE *f)
|
||||
}
|
||||
|
||||
// Read a section of the file, considering endian issues
|
||||
void
|
||||
readFileSection(uint16_t* p, int len, FILE* f)
|
||||
void readFileSection(uint16_t* p, int len, FILE* f)
|
||||
{
|
||||
for (int i=0; i < len; i += 2)
|
||||
{
|
||||
@ -569,12 +575,12 @@ readFileSection(uint16_t* p, int len, FILE* f)
|
||||
}
|
||||
|
||||
/* The following two functions are dummies, since we don't call map() */
|
||||
void getKey(int i, uint8_t **keys)
|
||||
void getKey(int /*i*/, uint8_t **/*keys*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void dispKey(int i)
|
||||
void dispKey(int /*i*/)
|
||||
{
|
||||
|
||||
}
|
||||
@ -583,11 +589,11 @@ void dispKey(int i)
|
||||
iPatLen). The pattern can contain wild bytes; if you really want to match
|
||||
for the pattern that is used up by the WILD uint8_t, tough - it will match with
|
||||
everything else as well. */
|
||||
static boolT locatePattern(uint8_t *source, int iMin, int iMax, uint8_t *pattern, int iPatLen,
|
||||
static bool locatePattern(const uint8_t *source, int iMin, int iMax, uint8_t *pattern, int iPatLen,
|
||||
int *index)
|
||||
{
|
||||
int i, j;
|
||||
uint8_t *pSrc; /* Pointer to start of considered source */
|
||||
const uint8_t *pSrc; /* Pointer to start of considered source */
|
||||
int iLast;
|
||||
|
||||
iLast = iMax - iPatLen; /* Last source uint8_t to consider */
|
||||
@ -599,7 +605,7 @@ static boolT locatePattern(uint8_t *source, int iMin, int iMax, uint8_t *pattern
|
||||
for (j=0; j < iPatLen; j++)
|
||||
{
|
||||
/* j is the index of the uint8_t being considered in the pattern. */
|
||||
if ((*pSrc != pattern[j]) && (pattern[j] != WILD))
|
||||
if ((*pSrc != pattern[j]) and (pattern[j] != WILD))
|
||||
{
|
||||
/* A definite mismatch */
|
||||
break; /* Break to outer loop */
|
||||
@ -634,25 +640,24 @@ void STATE::checkStartup()
|
||||
char chModel = 'x';
|
||||
char chVendor = 'x';
|
||||
char chVersion = 'x';
|
||||
char *pPath;
|
||||
char temp[4];
|
||||
|
||||
startOff = ((uint32_t)prog.initCS << 4) + prog.initIP;
|
||||
|
||||
/* Check the Turbo Pascal signatures first, since they involve only the
|
||||
first 3 bytes, and false positives may be founf with the others later */
|
||||
if (locatePattern(prog.Image, startOff, startOff+5, pattBorl4on,sizeof(pattBorl4on), &i))
|
||||
if (locatePattern(prog.image(), startOff, startOff+5, pattBorl4on,sizeof(pattBorl4on), &i))
|
||||
{
|
||||
/* The first 5 bytes are a far call. Follow that call and
|
||||
determine the version from that */
|
||||
rel = LH(&prog.Image[startOff+1]); /* This is abs off of init */
|
||||
para= LH(&prog.Image[startOff+3]);/* This is abs seg of init */
|
||||
rel = LH(&prog.image()[startOff+1]); /* This is abs off of init */
|
||||
para= LH(&prog.image()[startOff+3]);/* This is abs seg of init */
|
||||
init = ((uint32_t)para << 4) + rel;
|
||||
if (locatePattern(prog.Image, init, init+26, pattBorl4Init,
|
||||
if (locatePattern(prog.image(), init, init+26, pattBorl4Init,
|
||||
sizeof(pattBorl4Init), &i))
|
||||
{
|
||||
|
||||
setState(rDS, LH(&prog.Image[i+1]));
|
||||
setState(rDS, LH(&prog.image()[i+1]));
|
||||
printf("Borland Pascal v4 detected\n");
|
||||
chVendor = 't'; /* Trubo */
|
||||
chModel = 'p'; /* Pascal */
|
||||
@ -661,11 +666,11 @@ void STATE::checkStartup()
|
||||
prog.segMain = prog.initCS; /* At the 5 uint8_t jump */
|
||||
goto gotVendor; /* Already have vendor */
|
||||
}
|
||||
else if (locatePattern(prog.Image, init, init+26, pattBorl5Init,
|
||||
else if (locatePattern(prog.image(), init, init+26, pattBorl5Init,
|
||||
sizeof(pattBorl5Init), &i))
|
||||
{
|
||||
|
||||
setState( rDS, LH(&prog.Image[i+1]));
|
||||
setState( rDS, LH(&prog.image()[i+1]));
|
||||
printf("Borland Pascal v5.0 detected\n");
|
||||
chVendor = 't'; /* Trubo */
|
||||
chModel = 'p'; /* Pascal */
|
||||
@ -674,11 +679,11 @@ void STATE::checkStartup()
|
||||
prog.segMain = prog.initCS;
|
||||
goto gotVendor; /* Already have vendor */
|
||||
}
|
||||
else if (locatePattern(prog.Image, init, init+26, pattBorl7Init,
|
||||
else if (locatePattern(prog.image(), init, init+26, pattBorl7Init,
|
||||
sizeof(pattBorl7Init), &i))
|
||||
{
|
||||
|
||||
setState( rDS, LH(&prog.Image[i+1]));
|
||||
setState( rDS, LH(&prog.image()[i+1]));
|
||||
printf("Borland Pascal v7 detected\n");
|
||||
chVendor = 't'; /* Trubo */
|
||||
chModel = 'p'; /* Pascal */
|
||||
@ -695,45 +700,45 @@ void STATE::checkStartup()
|
||||
but decides the model required. Note: must do the far data models
|
||||
(large and compact) before the others, since they are the same pattern
|
||||
as near data, just more pushes at the start. */
|
||||
if(prog.cbImage>startOff+0x180+sizeof(pattMainLarge))
|
||||
if(prog.cbImage>int(startOff+0x180+sizeof(pattMainLarge)))
|
||||
{
|
||||
if (locatePattern(prog.Image, startOff, startOff+0x180, pattMainLarge,sizeof(pattMainLarge), &i))
|
||||
if (locatePattern(prog.image(), startOff, startOff+0x180, pattMainLarge,sizeof(pattMainLarge), &i))
|
||||
{
|
||||
rel = LH(&prog.Image[i+OFFMAINLARGE]); /* This is abs off of main */
|
||||
para= LH(&prog.Image[i+OFFMAINLARGE+2]);/* This is abs seg of main */
|
||||
rel = LH(&prog.image()[i+OFFMAINLARGE]); /* This is abs off of main */
|
||||
para= LH(&prog.image()[i+OFFMAINLARGE+2]);/* This is abs seg of main */
|
||||
/* Save absolute image offset */
|
||||
prog.offMain = ((uint32_t)para << 4) + rel;
|
||||
prog.segMain = (uint16_t)para;
|
||||
chModel = 'l'; /* Large model */
|
||||
}
|
||||
else if (locatePattern(prog.Image, startOff, startOff+0x180, pattMainCompact,
|
||||
else if (locatePattern(prog.image(), startOff, startOff+0x180, pattMainCompact,
|
||||
sizeof(pattMainCompact), &i))
|
||||
{
|
||||
rel = LH_SIGNED(&prog.Image[i+OFFMAINCOMPACT]);/* This is the rel addr of main */
|
||||
rel = LH_SIGNED(&prog.image()[i+OFFMAINCOMPACT]);/* This is the rel addr of main */
|
||||
prog.offMain = i+OFFMAINCOMPACT+2+rel; /* Save absolute image offset */
|
||||
prog.segMain = prog.initCS;
|
||||
chModel = 'c'; /* Compact model */
|
||||
}
|
||||
else if (locatePattern(prog.Image, startOff, startOff+0x180, pattMainMedium,
|
||||
else if (locatePattern(prog.image(), startOff, startOff+0x180, pattMainMedium,
|
||||
sizeof(pattMainMedium), &i))
|
||||
{
|
||||
rel = LH(&prog.Image[i+OFFMAINMEDIUM]); /* This is abs off of main */
|
||||
para= LH(&prog.Image[i+OFFMAINMEDIUM+2]);/* This is abs seg of main */
|
||||
rel = LH(&prog.image()[i+OFFMAINMEDIUM]); /* This is abs off of main */
|
||||
para= LH(&prog.image()[i+OFFMAINMEDIUM+2]);/* This is abs seg of main */
|
||||
prog.offMain = ((uint32_t)para << 4) + rel;
|
||||
prog.segMain = (uint16_t)para;
|
||||
chModel = 'm'; /* Medium model */
|
||||
}
|
||||
else if (locatePattern(prog.Image, startOff, startOff+0x180, pattMainSmall,
|
||||
else if (locatePattern(prog.image(), startOff, startOff+0x180, pattMainSmall,
|
||||
sizeof(pattMainSmall), &i))
|
||||
{
|
||||
rel = LH_SIGNED(&prog.Image[i+OFFMAINSMALL]); /* This is rel addr of main */
|
||||
rel = LH_SIGNED(&prog.image()[i+OFFMAINSMALL]); /* This is rel addr of main */
|
||||
prog.offMain = i+OFFMAINSMALL+2+rel; /* Save absolute image offset */
|
||||
prog.segMain = prog.initCS;
|
||||
chModel = 's'; /* Small model */
|
||||
}
|
||||
else if (memcmp(&prog.Image[startOff], pattTPasStart, sizeof(pattTPasStart)) == 0)
|
||||
else if (memcmp(&prog.image()[startOff], pattTPasStart, sizeof(pattTPasStart)) == 0)
|
||||
{
|
||||
rel = LH_SIGNED(&prog.Image[startOff+1]); /* Get the jump offset */
|
||||
rel = LH_SIGNED(&prog.image()[startOff+1]); /* Get the jump offset */
|
||||
prog.offMain = rel+startOff+3; /* Save absolute image offset */
|
||||
prog.offMain += 0x20; /* These first 32 bytes are setting up */
|
||||
prog.segMain = prog.initCS;
|
||||
@ -757,30 +762,30 @@ void STATE::checkStartup()
|
||||
}
|
||||
|
||||
printf("Model: %c\n", chModel);
|
||||
|
||||
prog.addressingMode = chModel;
|
||||
|
||||
/* Now decide the compiler vendor and version number */
|
||||
if (memcmp(&prog.Image[startOff], pattMsC5Start, sizeof(pattMsC5Start)) == 0)
|
||||
if (memcmp(&prog.image()[startOff], pattMsC5Start, sizeof(pattMsC5Start)) == 0)
|
||||
{
|
||||
/* Yes, this is Microsoft startup code. The DS is sitting right here
|
||||
in the next 2 bytes */
|
||||
setState( rDS, LH(&prog.Image[startOff+sizeof(pattMsC5Start)]));
|
||||
setState( rDS, LH(&prog.image()[startOff+sizeof(pattMsC5Start)]));
|
||||
chVendor = 'm'; /* Microsoft compiler */
|
||||
chVersion = '5'; /* Version 5 */
|
||||
printf("MSC 5 detected\n");
|
||||
}
|
||||
|
||||
/* The C8 startup pattern is different from C5's */
|
||||
else if (memcmp(&prog.Image[startOff], pattMsC8Start, sizeof(pattMsC8Start)) == 0)
|
||||
else if (memcmp(&prog.image()[startOff], pattMsC8Start, sizeof(pattMsC8Start)) == 0)
|
||||
{
|
||||
setState( rDS, LH(&prog.Image[startOff+sizeof(pattMsC8Start)]));
|
||||
setState( rDS, LH(&prog.image()[startOff+sizeof(pattMsC8Start)]));
|
||||
printf("MSC 8 detected\n");
|
||||
chVendor = 'm'; /* Microsoft compiler */
|
||||
chVersion = '8'; /* Version 8 */
|
||||
}
|
||||
|
||||
/* The C8 .com startup pattern is different again! */
|
||||
else if (memcmp(&prog.Image[startOff], pattMsC8ComStart,
|
||||
else if (memcmp(&prog.image()[startOff], pattMsC8ComStart,
|
||||
sizeof(pattMsC8ComStart)) == 0)
|
||||
{
|
||||
printf("MSC 8 .com detected\n");
|
||||
@ -788,27 +793,27 @@ void STATE::checkStartup()
|
||||
chVersion = '8'; /* Version 8 */
|
||||
}
|
||||
|
||||
else if (locatePattern(prog.Image, startOff, startOff+0x30, pattBorl2Start,
|
||||
else if (locatePattern(prog.image(), startOff, startOff+0x30, pattBorl2Start,
|
||||
sizeof(pattBorl2Start), &i))
|
||||
{
|
||||
/* Borland startup. DS is at the second uint8_t (offset 1) */
|
||||
setState( rDS, LH(&prog.Image[i+1]));
|
||||
setState( rDS, LH(&prog.image()[i+1]));
|
||||
printf("Borland v2 detected\n");
|
||||
chVendor = 'b'; /* Borland compiler */
|
||||
chVersion = '2'; /* Version 2 */
|
||||
}
|
||||
|
||||
else if (locatePattern(prog.Image, startOff, startOff+0x30, pattBorl3Start,
|
||||
else if (locatePattern(prog.image(), startOff, startOff+0x30, pattBorl3Start,
|
||||
sizeof(pattBorl3Start), &i))
|
||||
{
|
||||
/* Borland startup. DS is at the second uint8_t (offset 1) */
|
||||
setState( rDS, LH(&prog.Image[i+1]));
|
||||
setState( rDS, LH(&prog.image()[i+1]));
|
||||
printf("Borland v3 detected\n");
|
||||
chVendor = 'b'; /* Borland compiler */
|
||||
chVersion = '3'; /* Version 3 */
|
||||
}
|
||||
|
||||
else if (locatePattern(prog.Image, startOff, startOff+0x30, pattLogiStart,
|
||||
else if (locatePattern(prog.image(), startOff, startOff+0x30, pattLogiStart,
|
||||
sizeof(pattLogiStart), &i))
|
||||
{
|
||||
/* Logitech modula startup. DS is 0, despite appearances */
|
||||
@ -825,31 +830,12 @@ void STATE::checkStartup()
|
||||
|
||||
gotVendor:
|
||||
|
||||
/* Use the DCC environment variable to set where the .sig files will
|
||||
be found. Otherwise, assume current directory */
|
||||
pPath = getenv("DCC");
|
||||
if (pPath)
|
||||
{
|
||||
strcpy(sSigName, pPath); /* Use path given */
|
||||
if (sSigName[strlen(sSigName)-1] != '/')
|
||||
{
|
||||
strcat(sSigName, "/"); /* Append a slash if necessary */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(sSigName, "./"); /* Current directory */
|
||||
}
|
||||
strcat(sSigName, "dcc");
|
||||
temp[1] = '\0';
|
||||
temp[0] = chVendor;
|
||||
strcat(sSigName, temp); /* Add vendor */
|
||||
temp[0] = chVersion;
|
||||
strcat(sSigName, temp); /* Add version */
|
||||
temp[0] = chModel;
|
||||
strcat(sSigName, temp); /* Add model */
|
||||
strcat(sSigName, ".sig"); /* Add extension */
|
||||
printf("Signature file: %s\n", sSigName);
|
||||
sSigName = QString("dcc%1%2%3.sig")
|
||||
.arg(QChar(chVendor)) /* Add vendor */
|
||||
.arg(QChar(chVersion)) /* Add version */
|
||||
.arg(QChar(chModel)) /* Add model */
|
||||
;
|
||||
printf("Signature file: %s\n", qPrintable(sSigName));
|
||||
|
||||
}
|
||||
|
||||
@ -862,45 +848,29 @@ gotVendor:
|
||||
*/
|
||||
void readProtoFile(void)
|
||||
{
|
||||
IDcc *dcc = IDcc::get();
|
||||
QString szProFName = dcc->dataDir("prototypes").absoluteFilePath(DCCLIBS); /* Full name of dclibs.lst */
|
||||
|
||||
FILE *fProto;
|
||||
char *pPath; /* Point to the environment string */
|
||||
char szProFName[81]; /* Full name of dclibs.lst */
|
||||
int i;
|
||||
|
||||
/* Use the DCC environment variable to set where the dcclibs.lst file will
|
||||
be found. Otherwise, assume current directory */
|
||||
pPath = getenv("DCC");
|
||||
if (pPath)
|
||||
if ((fProto = fopen(qPrintable(szProFName), "rb")) == nullptr)
|
||||
{
|
||||
strcpy(szProFName, pPath); /* Use path given */
|
||||
if (szProFName[strlen(szProFName)-1] != '/')
|
||||
{
|
||||
strcat(szProFName, "/"); /* Append a slash if necessary */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(szProFName, "./"); /* Current directory */
|
||||
}
|
||||
strcat(szProFName, DCCLIBS);
|
||||
|
||||
if ((fProto = fopen(szProFName, "rb")) == NULL)
|
||||
{
|
||||
printf("Warning: cannot open library prototype data file %s\n", szProFName);
|
||||
printf("Warning: cannot open library prototype data file %s\n", qPrintable(szProFName));
|
||||
return;
|
||||
}
|
||||
|
||||
grab(4, fProto);
|
||||
if (strncmp(buf, "dccp", 4) != 0)
|
||||
{
|
||||
printf("%s is not a dcc prototype file\n", szProFName);
|
||||
printf("%s is not a dcc prototype file\n", qPrintable(szProFName));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
grab(2, fProto);
|
||||
if (strncmp(buf, "FN", 2) != 0)
|
||||
{
|
||||
printf("FN (Function Name) subsection expected in %s\n", szProFName);
|
||||
printf("FN (Function Name) subsection expected in %s\n", qPrintable(szProFName));
|
||||
exit(2);
|
||||
}
|
||||
|
||||
@ -927,7 +897,7 @@ void readProtoFile(void)
|
||||
grab(2, fProto);
|
||||
if (strncmp(buf, "PM", 2) != 0)
|
||||
{
|
||||
printf("PM (Parameter) subsection expected in %s\n", szProFName);
|
||||
printf("PM (Parameter) subsection expected in %s\n", qPrintable(szProFName));
|
||||
exit(2);
|
||||
}
|
||||
|
||||
@ -947,8 +917,7 @@ void readProtoFile(void)
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
searchPList(char *name)
|
||||
int searchPList(char *name)
|
||||
{
|
||||
/* Search through the symbol names for the name */
|
||||
/* Use binary search */
|
||||
@ -985,10 +954,7 @@ searchPList(char *name)
|
||||
{
|
||||
return mn; /* Found! */
|
||||
}
|
||||
else
|
||||
{
|
||||
return NIL;
|
||||
}
|
||||
return NIL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -7,9 +7,12 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
#include "machine_x86.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <sstream>
|
||||
#include <QTextStream>
|
||||
using namespace std;
|
||||
#define intSize 40
|
||||
|
||||
@ -148,33 +151,33 @@ static const char *intOthers[] = {
|
||||
|
||||
/* Writes the description of the current interrupt. Appends it to the
|
||||
* string s. */
|
||||
void LLInst::writeIntComment (std::ostringstream &s)
|
||||
void LLInst::writeIntComment (QTextStream &s)
|
||||
{
|
||||
uint32_t src_immed=src().getImm2();
|
||||
s<<"\t/* ";
|
||||
if (src_immed == 0x21)
|
||||
{
|
||||
s <<int21h[dst.off];
|
||||
s <<int21h[m_dst.off];
|
||||
}
|
||||
else if (src_immed > 0x1F && src_immed < 0x2F)
|
||||
else if (src_immed > 0x1F and src_immed < 0x2F)
|
||||
{
|
||||
s <<intOthers[src_immed - 0x20];
|
||||
}
|
||||
else if (src_immed == 0x2F)
|
||||
{
|
||||
switch (dst.off)
|
||||
switch (m_dst.off)
|
||||
{
|
||||
case 0x01 :
|
||||
s << "Print spooler";
|
||||
break;
|
||||
case 0x02:
|
||||
s << "Assign";
|
||||
break;
|
||||
case 0x10:
|
||||
s << "Share";
|
||||
break;
|
||||
case 0xB7:
|
||||
s << "Append";
|
||||
case 0x01 :
|
||||
s << "Print spooler";
|
||||
break;
|
||||
case 0x02:
|
||||
s << "Assign";
|
||||
break;
|
||||
case 0x10:
|
||||
s << "Share";
|
||||
break;
|
||||
case 0xB7:
|
||||
s << "Append";
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -186,12 +189,15 @@ void LLInst::writeIntComment (std::ostringstream &s)
|
||||
//, &cCode.decl
|
||||
void Function::writeProcComments()
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
writeProcComments(ostr);
|
||||
cCode.appendDecl(ostr.str());
|
||||
QString dest_str;
|
||||
{
|
||||
QTextStream ostr(&dest_str);
|
||||
writeProcComments(ostr);
|
||||
}
|
||||
cCode.appendDecl(dest_str);
|
||||
}
|
||||
|
||||
void Function::writeProcComments(std::ostream &ostr)
|
||||
void Function::writeProcComments(QTextStream &ostr)
|
||||
{
|
||||
int i;
|
||||
ID *id; /* Pointer to register argument identifier */
|
||||
@ -207,16 +213,16 @@ void Function::writeProcComments(std::ostream &ostr)
|
||||
{
|
||||
psym = &this->args[i];
|
||||
ostr << " * "<<psym->name<<" = ";
|
||||
if (psym->regs->expr.ident.idType == REGISTER)
|
||||
if (psym->regs->ident.type() == REGISTER)
|
||||
{
|
||||
id = &this->localId.id_arr[psym->regs->expr.ident.idNode.regiIdx];
|
||||
id = &this->localId.id_arr[((RegisterNode *)psym->regs)->regiIdx];
|
||||
ostr << Machine_X86::regName(id->id.regi);
|
||||
}
|
||||
else /* long register */
|
||||
{
|
||||
id = &this->localId.id_arr[psym->regs->expr.ident.idNode.longIdx];
|
||||
ostr << Machine_X86::regName(id->id.longId.h) << ":";
|
||||
ostr << Machine_X86::regName(id->id.longId.l);
|
||||
id = &this->localId.id_arr[psym->regs->ident.idNode.longIdx];
|
||||
ostr << Machine_X86::regName(id->longId().h()) << ":";
|
||||
ostr << Machine_X86::regName(id->longId().l());
|
||||
}
|
||||
ostr << ".\n";
|
||||
|
||||
@ -235,26 +241,23 @@ void Function::writeProcComments(std::ostream &ostr)
|
||||
ostr << " * Untranslatable routine. Assembler provided.\n";
|
||||
if (this->flg & PROC_IS_FUNC)
|
||||
switch (this->retVal.type) { // TODO: Functions return value in various regs
|
||||
case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN:
|
||||
ostr << " * Return value in register al.\n";
|
||||
break;
|
||||
case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN:
|
||||
ostr << " * Return value in register ax.\n";
|
||||
break;
|
||||
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
|
||||
ostr << " * Return value in registers dx:ax.\n";
|
||||
break;
|
||||
case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN:
|
||||
ostr << " * Return value in register al.\n";
|
||||
break;
|
||||
case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN:
|
||||
ostr << " * Return value in register ax.\n";
|
||||
break;
|
||||
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
|
||||
ostr << " * Return value in registers dx:ax.\n";
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"Unknown retval type %d",this->retVal.type);
|
||||
break;
|
||||
} /* eos */
|
||||
}
|
||||
|
||||
/* Calling convention */
|
||||
if (this->flg & CALL_PASCAL)
|
||||
ostr << " * Pascal calling convention.\n";
|
||||
else if (this->flg & CALL_C)
|
||||
ostr << " * C calling convention.\n";
|
||||
else if (this->flg & CALL_UNKNOWN)
|
||||
ostr << " * Unknown calling convention.\n";
|
||||
|
||||
callingConv()->writeComments(ostr);
|
||||
/* Other flags */
|
||||
if (this->flg & (PROC_BADINST | PROC_IJMP))
|
||||
{
|
||||
|
||||
644
src/control.cpp
644
src/control.cpp
@ -2,33 +2,34 @@
|
||||
* Description : Performs control flow analysis on the CFG
|
||||
* (C) Cristina Cifuentes
|
||||
********************************************************************/
|
||||
#include <boost/range/algorithm.hpp>
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <cassert>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
//typedef struct list {
|
||||
// int nodeIdx;
|
||||
// struct list *next;
|
||||
//} nodeList;
|
||||
#include <boost/range/algorithm.hpp>
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
|
||||
namespace {
|
||||
typedef std::list<int> nodeList; /* dfsLast index to the node */
|
||||
|
||||
#define ancestor(a,b) ((a->dfsLastNum < b->dfsLastNum) && (a->dfsFirstNum < b->dfsFirstNum))
|
||||
/* there is a path on the DFST from a to b if the a was first visited in a
|
||||
* dfs, and a was later visited than b when doing the last visit of each
|
||||
* node. */
|
||||
bool inline ancestor(BB *a,BB *b)
|
||||
{
|
||||
return (a->dfsLastNum < b->dfsLastNum) and (a->dfsFirstNum < b->dfsFirstNum);
|
||||
}
|
||||
|
||||
|
||||
/* Checks if the edge (p,s) is a back edge. If node s was visited first
|
||||
/** Checks if the edge (p,s) is a back edge. If node s was visited first
|
||||
* during the dfs traversal (ie. s has a smaller dfsFirst number) or s == p,
|
||||
* then it is a backedge.
|
||||
* Also incrementes the number of backedges entries to the header node. */
|
||||
static bool isBackEdge (BB * p,BB * s)
|
||||
bool isBackEdge (BB * p,BB * s)
|
||||
{
|
||||
if (p->dfsFirstNum >= s->dfsFirstNum)
|
||||
{
|
||||
@ -39,16 +40,16 @@ static bool isBackEdge (BB * p,BB * s)
|
||||
}
|
||||
|
||||
|
||||
/* Finds the common dominator of the current immediate dominator
|
||||
/** Finds the common dominator of the current immediate dominator
|
||||
* currImmDom and its predecessor's immediate dominator predImmDom */
|
||||
static int commonDom (int currImmDom, int predImmDom, Function * pProc)
|
||||
int commonDom (int currImmDom, int predImmDom, Function * pProc)
|
||||
{
|
||||
if (currImmDom == NO_DOM)
|
||||
return (predImmDom);
|
||||
if (predImmDom == NO_DOM) /* predecessor is the root */
|
||||
return (currImmDom);
|
||||
|
||||
while ((currImmDom != NO_DOM) && (predImmDom != NO_DOM) &&
|
||||
while ((currImmDom != NO_DOM) and (predImmDom != NO_DOM) and
|
||||
(currImmDom != predImmDom))
|
||||
{
|
||||
if (currImmDom < predImmDom)
|
||||
@ -58,9 +59,214 @@ static int commonDom (int currImmDom, int predImmDom, Function * pProc)
|
||||
}
|
||||
return (currImmDom);
|
||||
}
|
||||
/* Returns whether or not the node n (dfsLast numbering of a basic block)
|
||||
* is on the list l. */
|
||||
bool inList (const nodeList &l, int n)
|
||||
{
|
||||
return std::find(l.begin(),l.end(),n)!=l.end();
|
||||
}
|
||||
/* Returns whether the node n belongs to the queue list q. */
|
||||
bool inInt(BB * n, queue &q)
|
||||
{
|
||||
return std::find(q.begin(),q.end(),n)!=q.end();
|
||||
}
|
||||
/** Recursive procedure to find nodes that belong to the interval (ie. nodes
|
||||
* from G1). */
|
||||
void findNodesInInt (queue &intNodes, int level, interval *Ii)
|
||||
{
|
||||
if (level == 1)
|
||||
{
|
||||
for(BB *en : Ii->nodes)
|
||||
{
|
||||
appendQueue(intNodes,en);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(BB *en : Ii->nodes)
|
||||
{
|
||||
findNodesInInt(intNodes,level-1,en->correspInt);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Finds the follow of the endless loop headed at node head (if any).
|
||||
* The follow node is the closest node to the loop. */
|
||||
void findEndlessFollow (Function * pProc, nodeList &loopNodes, BB * head)
|
||||
{
|
||||
head->loopFollow = MAX;
|
||||
for( int loop_node : loopNodes)
|
||||
{
|
||||
for (const TYPEADR_TYPE &typeaddr: pProc->m_dfsLast[loop_node]->edges)
|
||||
{
|
||||
int succ = typeaddr.BBptr->dfsLastNum;
|
||||
if ((not inList(loopNodes, succ)) and (succ < head->loopFollow))
|
||||
head->loopFollow = succ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Finds the immediate dominator of each node in the graph pProc->cfg.
|
||||
//static void findNodesInLoop(BB * latchNode,BB * head,PPROC pProc,queue *intNodes)
|
||||
/* Flags nodes that belong to the loop determined by (latchNode, head) and
|
||||
* determines the type of loop. */
|
||||
void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &intNodes)
|
||||
{
|
||||
int i, headDfsNum, intNodeType;
|
||||
nodeList loopNodes;
|
||||
int immedDom, /* dfsLast index to immediate dominator */
|
||||
thenDfs, elseDfs; /* dsfLast index for THEN and ELSE nodes */
|
||||
BB * pbb;
|
||||
|
||||
/* Flag nodes in loop headed by head (except header node) */
|
||||
headDfsNum = head->dfsLastNum;
|
||||
head->loopHead = headDfsNum;
|
||||
loopNodes.push_back(headDfsNum);
|
||||
for (i = headDfsNum + 1; i < latchNode->dfsLastNum; i++)
|
||||
{
|
||||
if (pProc->m_dfsLast[i]->flg & INVALID_BB) /* skip invalid BBs */
|
||||
continue;
|
||||
|
||||
immedDom = pProc->m_dfsLast[i]->immedDom;
|
||||
if (inList (loopNodes, immedDom) and inInt(pProc->m_dfsLast[i], intNodes))
|
||||
{
|
||||
loopNodes.push_back(i);
|
||||
if (pProc->m_dfsLast[i]->loopHead == NO_NODE)/*not in other loop*/
|
||||
pProc->m_dfsLast[i]->loopHead = headDfsNum;
|
||||
}
|
||||
}
|
||||
latchNode->loopHead = headDfsNum;
|
||||
if (latchNode != head)
|
||||
loopNodes.push_back(latchNode->dfsLastNum);
|
||||
|
||||
/* Determine type of loop and follow node */
|
||||
intNodeType = head->nodeType;
|
||||
if (latchNode->nodeType == TWO_BRANCH)
|
||||
if ((intNodeType == TWO_BRANCH) or (latchNode == head))
|
||||
if ((latchNode == head) or
|
||||
(inList (loopNodes, head->edges[THEN].BBptr->dfsLastNum) and
|
||||
inList (loopNodes, head->edges[ELSE].BBptr->dfsLastNum)))
|
||||
{
|
||||
head->loopType = eNodeHeaderType::REPEAT_TYPE;
|
||||
if (latchNode->edges[0].BBptr == head)
|
||||
head->loopFollow = latchNode->edges[ELSE].BBptr->dfsLastNum;
|
||||
else
|
||||
head->loopFollow = latchNode->edges[THEN].BBptr->dfsLastNum;
|
||||
latchNode->back().ll()->setFlags(JX_LOOP);
|
||||
}
|
||||
else
|
||||
{
|
||||
head->loopType = eNodeHeaderType::WHILE_TYPE;
|
||||
if (inList (loopNodes, head->edges[THEN].BBptr->dfsLastNum))
|
||||
head->loopFollow = head->edges[ELSE].BBptr->dfsLastNum;
|
||||
else
|
||||
head->loopFollow = head->edges[THEN].BBptr->dfsLastNum;
|
||||
head->back().ll()->setFlags(JX_LOOP);
|
||||
}
|
||||
else /* head = anything besides 2-way, latch = 2-way */
|
||||
{
|
||||
head->loopType = eNodeHeaderType::REPEAT_TYPE;
|
||||
if (latchNode->edges[THEN].BBptr == head)
|
||||
head->loopFollow = latchNode->edges[ELSE].BBptr->dfsLastNum;
|
||||
else
|
||||
head->loopFollow = latchNode->edges[THEN].BBptr->dfsLastNum;
|
||||
latchNode->back().ll()->setFlags(JX_LOOP);
|
||||
}
|
||||
else /* latch = 1-way */
|
||||
if (latchNode->nodeType == LOOP_NODE)
|
||||
{
|
||||
head->loopType = eNodeHeaderType::REPEAT_TYPE;
|
||||
head->loopFollow = latchNode->edges[0].BBptr->dfsLastNum;
|
||||
}
|
||||
else if (intNodeType == TWO_BRANCH)
|
||||
{
|
||||
head->loopType = eNodeHeaderType::WHILE_TYPE;
|
||||
pbb = latchNode;
|
||||
thenDfs = head->edges[THEN].BBptr->dfsLastNum;
|
||||
elseDfs = head->edges[ELSE].BBptr->dfsLastNum;
|
||||
while (1)
|
||||
{
|
||||
if (pbb->dfsLastNum == thenDfs)
|
||||
{
|
||||
head->loopFollow = elseDfs;
|
||||
break;
|
||||
}
|
||||
else if (pbb->dfsLastNum == elseDfs)
|
||||
{
|
||||
head->loopFollow = thenDfs;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check if couldn't find it, then it is a strangely formed
|
||||
* loop, so it is safer to consider it an endless loop */
|
||||
if (pbb->dfsLastNum <= head->dfsLastNum)
|
||||
{
|
||||
head->loopType = eNodeHeaderType::ENDLESS_TYPE;
|
||||
findEndlessFollow (pProc, loopNodes, head);
|
||||
break;
|
||||
}
|
||||
pbb = pProc->m_dfsLast[pbb->immedDom];
|
||||
}
|
||||
if (pbb->dfsLastNum > head->dfsLastNum)
|
||||
pProc->m_dfsLast[head->loopFollow]->loopHead = NO_NODE; /*****/
|
||||
head->back().ll()->setFlags(JX_LOOP);
|
||||
}
|
||||
else
|
||||
{
|
||||
head->loopType = eNodeHeaderType::ENDLESS_TYPE;
|
||||
findEndlessFollow (pProc, loopNodes, head);
|
||||
}
|
||||
|
||||
loopNodes.clear();
|
||||
}
|
||||
/** \returns whether the BB indexed by s is a successor of the BB indexed by \arg h
|
||||
* \note that h is a case node.
|
||||
*/
|
||||
bool successor (int s, int h, Function * pProc)
|
||||
{
|
||||
BB * header = pProc->m_dfsLast[h];
|
||||
auto iter = std::find_if(header->edges.begin(),
|
||||
header->edges.end(),
|
||||
[s](const TYPEADR_TYPE &te)->bool{ return te.BBptr->dfsLastNum == s;});
|
||||
return iter!=header->edges.end();
|
||||
}
|
||||
|
||||
|
||||
/** Recursive procedure to tag nodes that belong to the case described by
|
||||
* the list l, head and tail (dfsLast index to first and exit node of the
|
||||
* case). */
|
||||
void tagNodesInCase (BB * pBB, nodeList &l, int head, int tail)
|
||||
{
|
||||
int current; /* index to current node */
|
||||
|
||||
pBB->traversed = DFS_CASE;
|
||||
current = pBB->dfsLastNum;
|
||||
if ((current != tail) and (pBB->nodeType != MULTI_BRANCH) and (inList (l, pBB->immedDom)))
|
||||
{
|
||||
l.push_back(current);
|
||||
pBB->caseHead = head;
|
||||
for(TYPEADR_TYPE &edge : pBB->edges)
|
||||
{
|
||||
if (edge.BBptr->traversed != DFS_CASE)
|
||||
tagNodesInCase (edge.BBptr, l, head, tail);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Flags all nodes in the list l as having follow node f, and deletes all
|
||||
* nodes from the list. */
|
||||
void flagNodes (nodeList &l, int f, Function * pProc)
|
||||
{
|
||||
for(int idx : l)
|
||||
{
|
||||
pProc->m_dfsLast[idx]->ifFollow = f;
|
||||
}
|
||||
l.clear();
|
||||
}
|
||||
|
||||
|
||||
} // end of anonymouse namespace
|
||||
|
||||
/** Finds the immediate dominator of each node in the graph pProc->cfg.
|
||||
* Adapted version of the dominators algorithm by Hecht and Ullman; finds
|
||||
* immediate dominators only.
|
||||
* Note: graph should be reducible */
|
||||
@ -82,188 +288,7 @@ void Function::findImmedDom ()
|
||||
}
|
||||
|
||||
|
||||
/* Inserts the node n to the list l. */
|
||||
static void insertList (nodeList &l, int n)
|
||||
{
|
||||
l.push_back(n);
|
||||
}
|
||||
|
||||
|
||||
/* Returns whether or not the node n (dfsLast numbering of a basic block)
|
||||
* is on the list l. */
|
||||
static bool inList (const nodeList &l, int n)
|
||||
{
|
||||
return std::find(l.begin(),l.end(),n)!=l.end();
|
||||
}
|
||||
|
||||
|
||||
/* Frees space allocated by the list l. */
|
||||
static void freeList (nodeList &l)
|
||||
{
|
||||
l.clear();
|
||||
}
|
||||
|
||||
|
||||
/* Returns whether the node n belongs to the queue list q. */
|
||||
static boolT inInt(BB * n, queue &q)
|
||||
{
|
||||
return std::find(q.begin(),q.end(),n)!=q.end();
|
||||
}
|
||||
|
||||
|
||||
/* Finds the follow of the endless loop headed at node head (if any).
|
||||
* The follow node is the closest node to the loop. */
|
||||
static void findEndlessFollow (Function * pProc, nodeList &loopNodes, BB * head)
|
||||
{
|
||||
head->loopFollow = MAX;
|
||||
for( int loop_node : loopNodes)
|
||||
{
|
||||
for (TYPEADR_TYPE &typeaddr: pProc->m_dfsLast[loop_node]->edges)
|
||||
{
|
||||
int succ = typeaddr.BBptr->dfsLastNum;
|
||||
if ((! inList(loopNodes, succ)) && (succ < head->loopFollow))
|
||||
head->loopFollow = succ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//static void findNodesInLoop(BB * latchNode,BB * head,PPROC pProc,queue *intNodes)
|
||||
/* Flags nodes that belong to the loop determined by (latchNode, head) and
|
||||
* determines the type of loop. */
|
||||
static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &intNodes)
|
||||
{
|
||||
int i, headDfsNum, intNodeType;
|
||||
nodeList loopNodes;
|
||||
int immedDom, /* dfsLast index to immediate dominator */
|
||||
thenDfs, elseDfs; /* dsfLast index for THEN and ELSE nodes */
|
||||
BB * pbb;
|
||||
|
||||
/* Flag nodes in loop headed by head (except header node) */
|
||||
headDfsNum = head->dfsLastNum;
|
||||
head->loopHead = headDfsNum;
|
||||
insertList (loopNodes, headDfsNum);
|
||||
for (i = headDfsNum + 1; i < latchNode->dfsLastNum; i++)
|
||||
{
|
||||
if (pProc->m_dfsLast[i]->flg & INVALID_BB) /* skip invalid BBs */
|
||||
continue;
|
||||
|
||||
immedDom = pProc->m_dfsLast[i]->immedDom;
|
||||
if (inList (loopNodes, immedDom) && inInt(pProc->m_dfsLast[i], intNodes))
|
||||
{
|
||||
insertList (loopNodes, i);
|
||||
if (pProc->m_dfsLast[i]->loopHead == NO_NODE)/*not in other loop*/
|
||||
pProc->m_dfsLast[i]->loopHead = headDfsNum;
|
||||
}
|
||||
}
|
||||
latchNode->loopHead = headDfsNum;
|
||||
if (latchNode != head)
|
||||
insertList (loopNodes, latchNode->dfsLastNum);
|
||||
|
||||
/* Determine type of loop and follow node */
|
||||
intNodeType = head->nodeType;
|
||||
if (latchNode->nodeType == TWO_BRANCH)
|
||||
if ((intNodeType == TWO_BRANCH) || (latchNode == head))
|
||||
if ((latchNode == head) ||
|
||||
(inList (loopNodes, head->edges[THEN].BBptr->dfsLastNum) &&
|
||||
inList (loopNodes, head->edges[ELSE].BBptr->dfsLastNum)))
|
||||
{
|
||||
head->loopType = REPEAT_TYPE;
|
||||
if (latchNode->edges[0].BBptr == head)
|
||||
head->loopFollow = latchNode->edges[ELSE].BBptr->dfsLastNum;
|
||||
else
|
||||
head->loopFollow = latchNode->edges[THEN].BBptr->dfsLastNum;
|
||||
latchNode->back().ll()->setFlags(JX_LOOP);
|
||||
}
|
||||
else
|
||||
{
|
||||
head->loopType = WHILE_TYPE;
|
||||
if (inList (loopNodes, head->edges[THEN].BBptr->dfsLastNum))
|
||||
head->loopFollow = head->edges[ELSE].BBptr->dfsLastNum;
|
||||
else
|
||||
head->loopFollow = head->edges[THEN].BBptr->dfsLastNum;
|
||||
head->back().ll()->setFlags(JX_LOOP);
|
||||
}
|
||||
else /* head = anything besides 2-way, latch = 2-way */
|
||||
{
|
||||
head->loopType = REPEAT_TYPE;
|
||||
if (latchNode->edges[THEN].BBptr == head)
|
||||
head->loopFollow = latchNode->edges[ELSE].BBptr->dfsLastNum;
|
||||
else
|
||||
head->loopFollow = latchNode->edges[THEN].BBptr->dfsLastNum;
|
||||
latchNode->back().ll()->setFlags(JX_LOOP);
|
||||
}
|
||||
else /* latch = 1-way */
|
||||
if (latchNode->nodeType == LOOP_NODE)
|
||||
{
|
||||
head->loopType = REPEAT_TYPE;
|
||||
head->loopFollow = latchNode->edges[0].BBptr->dfsLastNum;
|
||||
}
|
||||
else if (intNodeType == TWO_BRANCH)
|
||||
{
|
||||
head->loopType = WHILE_TYPE;
|
||||
pbb = latchNode;
|
||||
thenDfs = head->edges[THEN].BBptr->dfsLastNum;
|
||||
elseDfs = head->edges[ELSE].BBptr->dfsLastNum;
|
||||
while (1)
|
||||
{
|
||||
if (pbb->dfsLastNum == thenDfs)
|
||||
{
|
||||
head->loopFollow = elseDfs;
|
||||
break;
|
||||
}
|
||||
else if (pbb->dfsLastNum == elseDfs)
|
||||
{
|
||||
head->loopFollow = thenDfs;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check if couldn't find it, then it is a strangely formed
|
||||
* loop, so it is safer to consider it an endless loop */
|
||||
if (pbb->dfsLastNum <= head->dfsLastNum)
|
||||
{
|
||||
head->loopType = ENDLESS_TYPE;
|
||||
findEndlessFollow (pProc, loopNodes, head);
|
||||
break;
|
||||
}
|
||||
pbb = pProc->m_dfsLast[pbb->immedDom];
|
||||
}
|
||||
if (pbb->dfsLastNum > head->dfsLastNum)
|
||||
pProc->m_dfsLast[head->loopFollow]->loopHead = NO_NODE; /*****/
|
||||
head->back().ll()->setFlags(JX_LOOP);
|
||||
}
|
||||
else
|
||||
{
|
||||
head->loopType = ENDLESS_TYPE;
|
||||
findEndlessFollow (pProc, loopNodes, head);
|
||||
}
|
||||
|
||||
freeList(loopNodes);
|
||||
}
|
||||
|
||||
//static void findNodesInInt (queue **intNodes, int level, interval *Ii)
|
||||
/* Recursive procedure to find nodes that belong to the interval (ie. nodes
|
||||
* from G1). */
|
||||
static void findNodesInInt (queue &intNodes, int level, interval *Ii)
|
||||
{
|
||||
if (level == 1)
|
||||
{
|
||||
for(BB *en : Ii->nodes)
|
||||
{
|
||||
appendQueue(intNodes,en);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(BB *en : Ii->nodes)
|
||||
{
|
||||
findNodesInInt(intNodes,level-1,en->correspInt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Algorithm for structuring loops */
|
||||
/** Algorithm for structuring loops */
|
||||
void Function::structLoops(derSeq *derivedG)
|
||||
{
|
||||
interval *Ii;
|
||||
@ -276,13 +301,12 @@ void Function::structLoops(derSeq *derivedG)
|
||||
|
||||
/* Structure loops */
|
||||
/* for all derived sequences Gi */
|
||||
for(derSeq::iterator iter=derivedG->begin(); iter!=derivedG->end(); ++iter)
|
||||
for(auto & elem : *derivedG)
|
||||
{
|
||||
level++;
|
||||
Ii = iter->Ii;
|
||||
while (Ii) /* for all intervals Ii of Gi */
|
||||
for (Ii = elem.Ii; Ii!=nullptr; Ii = Ii->next) /* for all intervals Ii of Gi */
|
||||
{
|
||||
latchNode = NULL;
|
||||
latchNode = nullptr;
|
||||
intNodes.clear();
|
||||
|
||||
/* Find interval head (original BB node in G1) and create
|
||||
@ -299,14 +323,13 @@ void Function::structLoops(derSeq *derivedG)
|
||||
for (size_t i = 0; i < intHead->inEdges.size(); i++)
|
||||
{
|
||||
pred = intHead->inEdges[i];
|
||||
if (inInt(pred, intNodes) && isBackEdge(pred, intHead))
|
||||
if (! latchNode)
|
||||
if (inInt(pred, intNodes) and isBackEdge(pred, intHead))
|
||||
{
|
||||
if (nullptr == latchNode)
|
||||
latchNode = pred;
|
||||
else
|
||||
{
|
||||
if (pred->dfsLastNum > latchNode->dfsLastNum)
|
||||
latchNode = pred;
|
||||
}
|
||||
else if (pred->dfsLastNum > latchNode->dfsLastNum)
|
||||
latchNode = pred;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find nodes in the loop and the type of loop */
|
||||
@ -315,7 +338,7 @@ void Function::structLoops(derSeq *derivedG)
|
||||
/* Check latching node is at the same nesting level of case
|
||||
* statements (if any) and that the node doesn't belong to
|
||||
* another loop. */
|
||||
if ((latchNode->caseHead == intHead->caseHead) &&
|
||||
if ((latchNode->caseHead == intHead->caseHead) and
|
||||
(latchNode->loopHead == NO_NODE))
|
||||
{
|
||||
intHead->latchNode = latchNode->dfsLastNum;
|
||||
@ -323,48 +346,6 @@ void Function::structLoops(derSeq *derivedG)
|
||||
latchNode->flg |= IS_LATCH_NODE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Next interval */
|
||||
Ii = Ii->next;
|
||||
}
|
||||
|
||||
/* Next derived sequence */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Returns whether the BB indexed by s is a successor of the BB indexed by
|
||||
* h. Note that h is a case node. */
|
||||
static bool successor (int s, int h, Function * pProc)
|
||||
{
|
||||
BB * header;
|
||||
|
||||
header = pProc->m_dfsLast[h];
|
||||
auto iter = std::find_if(header->edges.begin(),
|
||||
header->edges.end(),
|
||||
[s](const TYPEADR_TYPE &te)->bool{ return te.BBptr->dfsLastNum == s;});
|
||||
return iter!=header->edges.end();
|
||||
}
|
||||
|
||||
|
||||
/* Recursive procedure to tag nodes that belong to the case described by
|
||||
* the list l, head and tail (dfsLast index to first and exit node of the
|
||||
* case). */
|
||||
static void tagNodesInCase (BB * pBB, nodeList &l, int head, int tail)
|
||||
{
|
||||
int current, /* index to current node */
|
||||
i;
|
||||
|
||||
pBB->traversed = DFS_CASE;
|
||||
current = pBB->dfsLastNum;
|
||||
if ((current != tail) && (pBB->nodeType != MULTI_BRANCH) && (inList (l, pBB->immedDom)))
|
||||
{
|
||||
insertList (l, current);
|
||||
pBB->caseHead = head;
|
||||
for(TYPEADR_TYPE &edge : pBB->edges)
|
||||
{
|
||||
if (edge.BBptr->traversed != DFS_CASE)
|
||||
tagNodesInCase (edge.BBptr, l, head, tail);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -374,72 +355,58 @@ static void tagNodesInCase (BB * pBB, nodeList &l, int head, int tail)
|
||||
* has a case node. */
|
||||
void Function::structCases()
|
||||
{
|
||||
int i, j;
|
||||
BB * caseHeader; /* case header node */
|
||||
int exitNode = NO_NODE; /* case exit node */
|
||||
nodeList caseNodes; /* temporary: list of nodes in case */
|
||||
|
||||
/* Linear scan of the nodes in reverse dfsLast order, searching for
|
||||
* case nodes */
|
||||
for (i = numBBs - 1; i >= 0; i--)
|
||||
if (m_dfsLast[i]->nodeType == MULTI_BRANCH)
|
||||
{
|
||||
caseHeader = m_dfsLast[i];
|
||||
|
||||
/* Find descendant node which has as immediate predecessor
|
||||
* the current header node, and is not a successor. */
|
||||
for (j = i + 2; j < numBBs; j++)
|
||||
{
|
||||
if ((!successor(j, i, this)) &&
|
||||
(m_dfsLast[j]->immedDom == i))
|
||||
if (exitNode == NO_NODE)
|
||||
exitNode = j;
|
||||
else if (m_dfsLast[exitNode]->inEdges.size() < m_dfsLast[j]->inEdges.size())
|
||||
exitNode = j;
|
||||
}
|
||||
m_dfsLast[i]->caseTail = exitNode;
|
||||
|
||||
/* Tag nodes that belong to the case by recording the
|
||||
* header field with caseHeader. */
|
||||
insertList (caseNodes, i);
|
||||
m_dfsLast[i]->caseHead = i;
|
||||
for(TYPEADR_TYPE &pb : caseHeader->edges)
|
||||
{
|
||||
tagNodesInCase(pb.BBptr, caseNodes, i, exitNode);
|
||||
}
|
||||
//for (j = 0; j < caseHeader->edges[j]; j++)
|
||||
// tagNodesInCase (caseHeader->edges[j].BBptr, caseNodes, i, exitNode);
|
||||
if (exitNode != NO_NODE)
|
||||
m_dfsLast[exitNode]->caseHead = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Flags all nodes in the list l as having follow node f, and deletes all
|
||||
* nodes from the list. */
|
||||
static void flagNodes (nodeList &l, int f, Function * pProc)
|
||||
{
|
||||
nodeList::iterator p;
|
||||
for(int idx : l)
|
||||
for (int i = numBBs - 1; i >= 0; i--)
|
||||
{
|
||||
pProc->m_dfsLast[idx]->ifFollow = f;
|
||||
}
|
||||
l.clear();
|
||||
}
|
||||
if ((m_dfsLast[i]->nodeType != MULTI_BRANCH))
|
||||
continue;
|
||||
BB * caseHeader = m_dfsLast[i];; /* case header node */
|
||||
|
||||
/* Find descendant node which has as immediate predecessor
|
||||
* the current header node, and is not a successor. */
|
||||
for (size_t j = i + 2; j < numBBs; j++)
|
||||
{
|
||||
if ((not successor(j, i, this)) and (m_dfsLast[j]->immedDom == i))
|
||||
{
|
||||
if (exitNode == NO_NODE)
|
||||
exitNode = j;
|
||||
else if (m_dfsLast[exitNode]->inEdges.size() < m_dfsLast[j]->inEdges.size())
|
||||
exitNode = j;
|
||||
}
|
||||
}
|
||||
m_dfsLast[i]->caseTail = exitNode;
|
||||
|
||||
/* Tag nodes that belong to the case by recording the
|
||||
* header field with caseHeader. */
|
||||
caseNodes.push_back(i);
|
||||
m_dfsLast[i]->caseHead = i;
|
||||
for(TYPEADR_TYPE &pb : caseHeader->edges)
|
||||
{
|
||||
tagNodesInCase(pb.BBptr, caseNodes, i, exitNode);
|
||||
}
|
||||
//for (j = 0; j < caseHeader->edges[j]; j++)
|
||||
// tagNodesInCase (caseHeader->edges[j].BBptr, caseNodes, i, exitNode);
|
||||
if (exitNode != NO_NODE)
|
||||
m_dfsLast[exitNode]->caseHead = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* Structures if statements */
|
||||
void Function::structIfs ()
|
||||
{
|
||||
size_t followInEdges; /* Largest # in-edges so far */
|
||||
int curr, /* Index for linear scan of nodes */
|
||||
desc, /* Index for descendant */
|
||||
followInEdges, /* Largest # in-edges so far */
|
||||
/*desc,*/ /* Index for descendant */
|
||||
follow; /* Possible follow node */
|
||||
nodeList domDesc, /* List of nodes dominated by curr */
|
||||
unresolved /* List of unresolved if nodes */
|
||||
;
|
||||
BB * currNode, /* Pointer to current node */
|
||||
* pbb;
|
||||
* pbb;
|
||||
|
||||
/* Linear scan of nodes in reverse dfsLast order */
|
||||
for (curr = numBBs - 1; curr >= 0; curr--)
|
||||
@ -448,17 +415,17 @@ void Function::structIfs ()
|
||||
if (currNode->flg & INVALID_BB) /* Do not process invalid BBs */
|
||||
continue;
|
||||
|
||||
if ((currNode->nodeType == TWO_BRANCH) && (!currNode->back().ll()->testFlags(JX_LOOP)))
|
||||
if ((currNode->nodeType == TWO_BRANCH) and (not currNode->back().ll()->testFlags(JX_LOOP)))
|
||||
{
|
||||
followInEdges = 0;
|
||||
follow = 0;
|
||||
|
||||
/* Find all nodes that have this node as immediate dominator */
|
||||
for (desc = curr+1; desc < numBBs; desc++)
|
||||
for (size_t desc = curr+1; desc < numBBs; desc++)
|
||||
{
|
||||
if (m_dfsLast[desc]->immedDom == curr)
|
||||
{
|
||||
insertList (domDesc, desc);
|
||||
domDesc.push_back(desc);
|
||||
pbb = m_dfsLast[desc];
|
||||
if ((pbb->inEdges.size() - pbb->numBackEdges) >= followInEdges)
|
||||
{
|
||||
@ -470,16 +437,16 @@ void Function::structIfs ()
|
||||
|
||||
/* Determine follow according to number of descendants
|
||||
* immediately dominated by this node */
|
||||
if ((follow != 0) && (followInEdges > 1))
|
||||
if ((follow != 0) and (followInEdges > 1))
|
||||
{
|
||||
currNode->ifFollow = follow;
|
||||
if (!unresolved.empty())
|
||||
if (not unresolved.empty())
|
||||
flagNodes (unresolved, follow, this);
|
||||
}
|
||||
else
|
||||
insertList (unresolved, curr);
|
||||
unresolved.push_back(curr);
|
||||
}
|
||||
freeList (domDesc);
|
||||
domDesc.clear();
|
||||
}
|
||||
}
|
||||
bool Function::removeInEdge_Flag_and_ProcessLatch(BB *pbb,BB *a,BB *b)
|
||||
@ -507,14 +474,14 @@ void Function::replaceInEdge(BB* where, BB* which,BB* with)
|
||||
}
|
||||
bool Function::Case_notX_or_Y(BB* pbb, BB* thenBB, BB* elseBB)
|
||||
{
|
||||
HLTYPE &hl1(*pbb->back().hl());
|
||||
HLTYPE &hl2(*thenBB->back().hl());
|
||||
HLTYPE &hl1(*pbb->back().hlU());
|
||||
HLTYPE &hl2(*thenBB->back().hlU());
|
||||
|
||||
BB* obb = elseBB->edges[THEN].BBptr;
|
||||
|
||||
/* Construct compound DBL_OR expression */
|
||||
hl1.replaceExpr(hl1.expr()->inverse());
|
||||
hl1.expr(COND_EXPR::boolOp (hl1.expr(), hl2.expr(), DBL_OR));
|
||||
hl1.expr(BinaryOperator::Create(DBL_OR,hl1.expr(), hl2.expr()));
|
||||
|
||||
/* Replace in-edge to obb from e to pbb */
|
||||
replaceInEdge(obb,elseBB,pbb);
|
||||
@ -528,12 +495,14 @@ bool Function::Case_notX_or_Y(BB* pbb, BB* thenBB, BB* elseBB)
|
||||
}
|
||||
bool Function::Case_X_and_Y(BB* pbb, BB* thenBB, BB* elseBB)
|
||||
{
|
||||
HLTYPE &hl1(*pbb->back().hl());
|
||||
HLTYPE &hl2(*thenBB->back().hl());
|
||||
HLTYPE &hl1(*pbb->back().hlU());
|
||||
HLTYPE &hl2(*thenBB->back().hlU());
|
||||
BB* obb = elseBB->edges[ELSE].BBptr;
|
||||
|
||||
Expr * hl2_expr = hl2.getMyExpr();
|
||||
/* Construct compound DBL_AND expression */
|
||||
hl1.expr(COND_EXPR::boolOp (hl1.expr(),hl2.expr(), DBL_AND));
|
||||
assert(hl1.expr());
|
||||
assert(hl2_expr);
|
||||
hl1.expr(BinaryOperator::Create(DBL_AND,hl1.expr(),hl2_expr));
|
||||
|
||||
/* Replace in-edge to obb from e to pbb */
|
||||
replaceInEdge(obb,elseBB,pbb);
|
||||
@ -547,15 +516,15 @@ bool Function::Case_X_and_Y(BB* pbb, BB* thenBB, BB* elseBB)
|
||||
|
||||
bool Function::Case_notX_and_Y(BB* pbb, BB* thenBB, BB* elseBB)
|
||||
{
|
||||
HLTYPE &hl1(*pbb->back().hl());
|
||||
HLTYPE &hl2(*thenBB->back().hl());
|
||||
HLTYPE &hl1(*pbb->back().hlU());
|
||||
HLTYPE &hl2(*thenBB->back().hlU());
|
||||
|
||||
BB* obb = thenBB->edges[ELSE].BBptr;
|
||||
|
||||
/* Construct compound DBL_AND expression */
|
||||
|
||||
hl1.replaceExpr(hl1.expr()->inverse());
|
||||
hl1.expr(COND_EXPR::boolOp (hl1.expr(), hl2.expr(), DBL_AND));
|
||||
hl1.expr(BinaryOperator::LogicAnd(hl1.expr(), hl2.expr()));
|
||||
|
||||
/* Replace in-edge to obb from t to pbb */
|
||||
replaceInEdge(obb,thenBB,pbb);
|
||||
@ -570,13 +539,13 @@ bool Function::Case_notX_and_Y(BB* pbb, BB* thenBB, BB* elseBB)
|
||||
|
||||
bool Function::Case_X_or_Y(BB* pbb, BB* thenBB, BB* elseBB)
|
||||
{
|
||||
HLTYPE &hl1(*pbb->back().hl());
|
||||
HLTYPE &hl2(*thenBB->back().hl());
|
||||
HLTYPE &hl1(*pbb->back().hlU());
|
||||
HLTYPE &hl2(*thenBB->back().hlU());
|
||||
|
||||
BB * obb = thenBB->edges[THEN].BBptr;
|
||||
|
||||
/* Construct compound DBL_OR expression */
|
||||
hl1.expr(COND_EXPR::boolOp (hl1.expr(), hl2.expr(), DBL_OR));
|
||||
hl1.expr(BinaryOperator::LogicOr(hl1.expr(), hl2.expr()));
|
||||
|
||||
/* Replace in-edge to obb from t to pbb */
|
||||
|
||||
@ -603,7 +572,7 @@ void Function::compoundCond()
|
||||
|
||||
/* Traverse nodes in postorder, this way, the header node of a
|
||||
* compound condition is analysed first */
|
||||
for (int i = 0; i < this->numBBs; i++)
|
||||
for (size_t i = 0; i < this->numBBs; i++)
|
||||
{
|
||||
pbb = this->m_dfsLast[i];
|
||||
if (pbb->flg & INVALID_BB)
|
||||
@ -617,33 +586,33 @@ void Function::compoundCond()
|
||||
|
||||
change = true; //assume change
|
||||
|
||||
/* Check (X || Y) case */
|
||||
if ((thenBB->nodeType == TWO_BRANCH) && (thenBB->numHlIcodes == 1) &&
|
||||
(thenBB->inEdges.size() == 1) && (thenBB->edges[ELSE].BBptr == elseBB))
|
||||
/* Check (X or Y) case */
|
||||
if ((thenBB->nodeType == TWO_BRANCH) and (thenBB->numHlIcodes == 1) and
|
||||
(thenBB->inEdges.size() == 1) and (thenBB->edges[ELSE].BBptr == elseBB))
|
||||
{
|
||||
if(Case_X_or_Y(pbb, thenBB, elseBB))
|
||||
--i;
|
||||
}
|
||||
|
||||
/* Check (!X && Y) case */
|
||||
else if ((thenBB->nodeType == TWO_BRANCH) && (thenBB->numHlIcodes == 1) &&
|
||||
(thenBB->inEdges.size() == 1) && (thenBB->edges[THEN].BBptr == elseBB))
|
||||
/* Check (not X and Y) case */
|
||||
else if ((thenBB->nodeType == TWO_BRANCH) and (thenBB->numHlIcodes == 1) and
|
||||
(thenBB->inEdges.size() == 1) and (thenBB->edges[THEN].BBptr == elseBB))
|
||||
{
|
||||
if(Case_notX_and_Y(pbb, thenBB, elseBB))
|
||||
--i;
|
||||
}
|
||||
|
||||
/* Check (X && Y) case */
|
||||
else if ((elseBB->nodeType == TWO_BRANCH) && (elseBB->numHlIcodes == 1) &&
|
||||
(elseBB->inEdges.size()==1) && (elseBB->edges[THEN].BBptr == thenBB))
|
||||
/* Check (X and Y) case */
|
||||
else if ((elseBB->nodeType == TWO_BRANCH) and (elseBB->numHlIcodes == 1) and
|
||||
(elseBB->inEdges.size()==1) and (elseBB->edges[THEN].BBptr == thenBB))
|
||||
{
|
||||
if(Case_X_and_Y(pbb, thenBB, elseBB ))
|
||||
--i;
|
||||
}
|
||||
|
||||
/* Check (!X || Y) case */
|
||||
else if ((elseBB->nodeType == TWO_BRANCH) && (elseBB->numHlIcodes == 1) &&
|
||||
(elseBB->inEdges.size() == 1) && (elseBB->edges[ELSE].BBptr == thenBB))
|
||||
/* Check (not X or Y) case */
|
||||
else if ((elseBB->nodeType == TWO_BRANCH) and (elseBB->numHlIcodes == 1) and
|
||||
(elseBB->inEdges.size() == 1) and (elseBB->edges[ELSE].BBptr == thenBB))
|
||||
{
|
||||
if(Case_notX_or_Y(pbb, thenBB, elseBB ))
|
||||
--i;
|
||||
@ -654,8 +623,7 @@ void Function::compoundCond()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Structuring algorithm to find the structures of the graph pProc->cfg */
|
||||
/** Structuring algorithm to find the structures of the graph pProc->cfg */
|
||||
void Function::structure(derSeq *derivedG)
|
||||
{
|
||||
/* Find immediate dominators of the graph */
|
||||
|
||||
1231
src/dataflow.cpp
1231
src/dataflow.cpp
File diff suppressed because it is too large
Load Diff
209
src/dcc.cpp
209
src/dcc.cpp
@ -5,156 +5,141 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "dcc.h"
|
||||
|
||||
#include "msvc_fixes.h"
|
||||
#include "project.h"
|
||||
#include <string.h>
|
||||
#include "CallGraph.h"
|
||||
#include "DccFrontend.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QCommandLineParser>
|
||||
|
||||
#include <QtCore/QFile>
|
||||
|
||||
|
||||
/* Global variables - extern to other modules */
|
||||
char *asm1_name, *asm2_name; /* Assembler output filenames */
|
||||
SYMTAB symtab; /* Global symbol table */
|
||||
STATS stats; /* cfg statistics */
|
||||
//PROG prog; /* programs fields */
|
||||
OPTION option; /* Command line options */
|
||||
//Function * pProcList; /* List of procedures, topologically sort */
|
||||
//Function * pLastProc; /* Pointer to last node in procedure list */
|
||||
//FunctionListType pProcList;
|
||||
//CALL_GRAPH *callGraph; /* Call graph of the program */
|
||||
|
||||
static char *initargs(int argc, char *argv[]);
|
||||
static void displayTotalStats(void);
|
||||
#include <llvm/Support/raw_os_ostream.h>
|
||||
extern QString asm1_name, asm2_name; /* Assembler output filenames */
|
||||
extern SYMTAB symtab; /* Global symbol table */
|
||||
extern STATS stats; /* cfg statistics */
|
||||
extern OPTION option; /* Command line options */
|
||||
|
||||
static void displayTotalStats();
|
||||
/****************************************************************************
|
||||
* main
|
||||
***************************************************************************/
|
||||
#include <iostream>
|
||||
extern Project g_proj;
|
||||
int main(int argc, char *argv[])
|
||||
void setupOptions(const QCoreApplication &app) {
|
||||
//[-a1a2cmsi]
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription("dcc");
|
||||
parser.addHelpOption();
|
||||
//parser.addVersionOption();
|
||||
//QCommandLineOption showProgressOption("p", QCoreApplication::translate("main", "Show progress during copy"));
|
||||
QCommandLineOption boolOpts[] {
|
||||
QCommandLineOption {"v", QCoreApplication::translate("main", "verbose")},
|
||||
QCommandLineOption {"V", QCoreApplication::translate("main", "very verbose")},
|
||||
QCommandLineOption {"c", QCoreApplication::translate("main", "Follow register indirect calls")},
|
||||
QCommandLineOption {"m", QCoreApplication::translate("main", "Print memory maps of program")},
|
||||
QCommandLineOption {"s", QCoreApplication::translate("main", "Print stats")}
|
||||
};
|
||||
for(QCommandLineOption &o : boolOpts) {
|
||||
parser.addOption(o);
|
||||
}
|
||||
QCommandLineOption assembly("a", QCoreApplication::translate("main", "Produce assembly"),"assembly_level");
|
||||
QCommandLineOption targetFileOption(QStringList() << "o" << "output",
|
||||
QCoreApplication::translate("main", "Place output into <file>."),
|
||||
QCoreApplication::translate("main", "file"));
|
||||
QCommandLineOption entryPointOption(QStringList() << "E",
|
||||
QCoreApplication::translate("main", "Custom entry point as hex"),
|
||||
QCoreApplication::translate("main", "offset"),
|
||||
"0"
|
||||
);
|
||||
parser.addOption(targetFileOption);
|
||||
parser.addOption(assembly);
|
||||
parser.addOption(entryPointOption);
|
||||
//parser.addOption(forceOption);
|
||||
// Process the actual command line arguments given by the user
|
||||
parser.addPositionalArgument("source", QCoreApplication::translate("main", "Dos Executable file to decompile."));
|
||||
parser.process(app);
|
||||
|
||||
const QStringList args = parser.positionalArguments();
|
||||
if(args.empty()) {
|
||||
parser.showHelp();
|
||||
}
|
||||
// source is args.at(0), destination is args.at(1)
|
||||
option.verbose = parser.isSet(boolOpts[0]);
|
||||
option.VeryVerbose = parser.isSet(boolOpts[1]);
|
||||
if(parser.isSet(assembly)) {
|
||||
option.asm1 = parser.value(assembly).toInt()==1;
|
||||
option.asm2 = parser.value(assembly).toInt()==2;
|
||||
}
|
||||
option.Map = parser.isSet(boolOpts[3]);
|
||||
option.Stats = parser.isSet(boolOpts[4]);
|
||||
option.Interact = false;
|
||||
option.Calls = parser.isSet(boolOpts[2]);
|
||||
option.filename = args.first();
|
||||
option.CustomEntryPoint = parser.value(entryPointOption).toUInt(nullptr,16);
|
||||
if(parser.isSet(targetFileOption))
|
||||
asm1_name = asm2_name = parser.value(targetFileOption);
|
||||
else if(option.asm1 or option.asm2) {
|
||||
asm1_name = option.filename+".a1";
|
||||
asm2_name = option.filename+".a2";
|
||||
}
|
||||
|
||||
}
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// llvm::MCOperand op=llvm::MCOperand::CreateImm(11);
|
||||
// llvm::MCAsmInfo info;
|
||||
// llvm::raw_os_ostream wrap(std::cerr);
|
||||
// op.print(wrap,&info);
|
||||
// wrap.flush();
|
||||
/* Extract switches and filename */
|
||||
strcpy(option.filename, initargs(argc, argv));
|
||||
QCoreApplication app(argc,argv);
|
||||
|
||||
QCoreApplication::setApplicationVersion("0.1");
|
||||
setupOptions(app);
|
||||
|
||||
/* Front end reads in EXE or COM file, parses it into I-code while
|
||||
* building the call graph and attaching appropriate bits of code for
|
||||
* each procedure.
|
||||
*/
|
||||
DccFrontend fe(option.filename);
|
||||
Project::get()->create(option.filename);
|
||||
|
||||
DccFrontend fe(&app);
|
||||
if(not Project::get()->load()) {
|
||||
return -1;
|
||||
}
|
||||
if (option.verbose)
|
||||
Project::get()->prog.displayLoadInfo();
|
||||
if(false==fe.FrontEnd ())
|
||||
return -1;
|
||||
|
||||
if(option.asm1)
|
||||
return 0;
|
||||
/* In the middle is a so called Universal Decompiling Machine.
|
||||
* It processes the procedure list and I-code and attaches where it can
|
||||
* to each procedure an optimised cfg and ud lists
|
||||
*/
|
||||
udm();
|
||||
if(option.asm2)
|
||||
return 0;
|
||||
|
||||
/* Back end converts each procedure into C using I-code, interval
|
||||
* analysis, data flow etc. and outputs it to output file ready for
|
||||
* re-compilation.
|
||||
*/
|
||||
BackEnd(option.filename, g_proj.callGraph);
|
||||
BackEnd(Project::get()->callGraph);
|
||||
|
||||
g_proj.callGraph->write();
|
||||
Project::get()->callGraph->write();
|
||||
|
||||
if (option.Stats)
|
||||
displayTotalStats();
|
||||
|
||||
/*
|
||||
freeDataStructures(pProcList);
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* initargs - Extract command line arguments
|
||||
***************************************************************************/
|
||||
static char *initargs(int argc, char *argv[])
|
||||
{
|
||||
char *pc;
|
||||
|
||||
while (--argc > 0 && (*++argv)[0] == '-')
|
||||
{
|
||||
for (pc = argv[0]+1; *pc; pc++)
|
||||
switch (*pc)
|
||||
{
|
||||
case 'a': /* Print assembler listing */
|
||||
if (*(pc+1) == '2')
|
||||
option.asm2 = true;
|
||||
else
|
||||
option.asm1 = true;
|
||||
if (*(pc+1) == '1' || *(pc+1) == '2')
|
||||
pc++;
|
||||
break;
|
||||
case 'c':
|
||||
option.Calls = true;
|
||||
break;
|
||||
case 'i':
|
||||
option.Interact = true;
|
||||
break;
|
||||
case 'm': /* Print memory map */
|
||||
option.Map = true;
|
||||
break;
|
||||
case 's': /* Print Stats */
|
||||
option.Stats = true;
|
||||
break;
|
||||
case 'V': /* Very verbose => verbose */
|
||||
option.VeryVerbose = true;
|
||||
case 'v':
|
||||
option.verbose = true; /* Make everything verbose */
|
||||
break;
|
||||
case 'o': /* assembler output file */
|
||||
if (*(pc+1)) {
|
||||
asm1_name = asm2_name = pc+1;
|
||||
goto NextArg;
|
||||
}
|
||||
else if (--argc > 0) {
|
||||
asm1_name = asm2_name = *++argv;
|
||||
goto NextArg;
|
||||
}
|
||||
default:
|
||||
fatalError(INVALID_ARG, *pc);
|
||||
return *argv;
|
||||
}
|
||||
NextArg:;
|
||||
}
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
if (option.asm1 || option.asm2)
|
||||
{
|
||||
if (! asm1_name)
|
||||
{
|
||||
asm1_name = strcpy((char*)malloc(strlen(*argv)+4), *argv);
|
||||
pc = strrchr(asm1_name, '.');
|
||||
if (pc > strrchr(asm1_name, '/'))
|
||||
{
|
||||
*pc = '\0';
|
||||
}
|
||||
asm2_name = (char*)malloc(strlen(asm1_name)+4) ;
|
||||
strcat(strcpy(asm2_name, asm1_name), ".a2");
|
||||
unlink(asm2_name);
|
||||
strcat(asm1_name, ".a1");
|
||||
}
|
||||
unlink(asm1_name); /* Remove asm output files */
|
||||
}
|
||||
return *argv; /* filename of the program to decompile */
|
||||
}
|
||||
|
||||
fatalError(USAGE);
|
||||
return *argv; // does not reach this.
|
||||
}
|
||||
|
||||
static void
|
||||
displayTotalStats ()
|
||||
/* Displays final statistics for the complete program */
|
||||
{
|
||||
printf ("\nFinal Program Statistics\n");
|
||||
printf (" Total number of low-level Icodes : %ld\n", stats.totalLL);
|
||||
printf (" Total number of high-level Icodes: %ld\n", stats.totalHL);
|
||||
printf (" Total number of low-level Icodes : %d\n", stats.totalLL);
|
||||
printf (" Total number of high-level Icodes: %d\n", stats.totalHL);
|
||||
printf (" Total reduction of instructions : %2.2f%%\n", 100.0 -
|
||||
(stats.totalHL * 100.0) / stats.totalLL);
|
||||
}
|
||||
|
||||
70
src/dcc_interface.cpp
Normal file
70
src/dcc_interface.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
#include "dcc_interface.h"
|
||||
#include "dcc.h"
|
||||
#include "project.h"
|
||||
struct DccImpl : public IDcc {
|
||||
ilFunction m_current_func;
|
||||
// IDcc interface
|
||||
public:
|
||||
void BaseInit()
|
||||
{
|
||||
m_current_func = Project::get()->functions().end();
|
||||
}
|
||||
void Init(QObject *tgt)
|
||||
{
|
||||
}
|
||||
ilFunction GetFirstFuncHandle()
|
||||
{
|
||||
return Project::get()->functions().begin();
|
||||
}
|
||||
ilFunction GetCurFuncHandle()
|
||||
{
|
||||
return m_current_func;
|
||||
}
|
||||
void analysis_Once()
|
||||
{
|
||||
}
|
||||
void load(QString name)
|
||||
{
|
||||
option.filename = name;
|
||||
Project::get()->create(name);
|
||||
}
|
||||
void prtout_asm(IXmlTarget *, int level)
|
||||
{
|
||||
}
|
||||
void prtout_cpp(IXmlTarget *, int level)
|
||||
{
|
||||
}
|
||||
size_t getFuncCount()
|
||||
{
|
||||
return Project::get()->functions().size();
|
||||
}
|
||||
const lFunction &validFunctions() const
|
||||
{
|
||||
return Project::get()->functions();
|
||||
}
|
||||
void SetCurFunc_by_Name(QString v)
|
||||
{
|
||||
lFunction & funcs(Project::get()->functions());
|
||||
for(auto iter=funcs.begin(),fin=funcs.end(); iter!=fin; ++iter) {
|
||||
if(iter->name==v) {
|
||||
m_current_func = iter;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
QDir installDir() {
|
||||
return QDir(".");
|
||||
}
|
||||
QDir dataDir(QString kind) { // return directory containing decompilation helper data -> signatures/includes/etc.
|
||||
QDir res(installDir());
|
||||
res.cd(kind);
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
IDcc* IDcc::get() {
|
||||
static IDcc *v=0;
|
||||
if(nullptr == v)
|
||||
v = new DccImpl;
|
||||
return v;
|
||||
}
|
||||
224
src/disassem.cpp
224
src/disassem.cpp
@ -2,6 +2,15 @@
|
||||
* dcc project disassembler
|
||||
* (C) Cristina Cifuentes, Mike van Emmerik, Jeff Ledermann
|
||||
****************************************************************************/
|
||||
#include "disassem.h"
|
||||
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
#include "symtab.h"
|
||||
#include "project.h"
|
||||
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QDebug>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
@ -10,10 +19,6 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dcc.h"
|
||||
#include "symtab.h"
|
||||
#include "disassem.h"
|
||||
#include "project.h"
|
||||
// Note: for the time being, there is no interactive disassembler
|
||||
// for unix
|
||||
|
||||
@ -70,21 +75,21 @@ static const char *szFlops3C[] =
|
||||
|
||||
static const char *szPtr[2] = { "word ptr ", "byte ptr " };
|
||||
|
||||
static void formatRM(ostringstream &p, uint32_t flg, const LLOperand &pm);
|
||||
static ostringstream &strDst(ostringstream &os, uint32_t flg, const LLOperand &pm);
|
||||
static void formatRM(QTextStream & p, const LLOperand &pm);
|
||||
static QTextStream & strDst(QTextStream & os, uint32_t flg, const LLOperand &pm);
|
||||
|
||||
static char *strHex(uint32_t d);
|
||||
//static int checkScanned(uint32_t pcCur);
|
||||
//static void setProc(Function * proc);
|
||||
//static void dispData(uint16_t dataSeg);
|
||||
boolT callArg(uint16_t off, char *temp); /* Check for procedure name */
|
||||
bool callArg(uint16_t off, char *temp); /* Check for procedure name */
|
||||
|
||||
//static FILE *dis_g_fp;
|
||||
static CIcodeRec pc;
|
||||
static int cb, j, numIcode, allocIcode;
|
||||
static map<int,int> pl;
|
||||
static uint32_t nextInst;
|
||||
static boolT fImpure;
|
||||
static bool fImpure;
|
||||
//static int g_lab;
|
||||
static Function * pProc; /* Points to current proc struct */
|
||||
|
||||
@ -94,7 +99,7 @@ struct POSSTACK_ENTRY
|
||||
Function * pProc; /* A pointer to a PROCEDURE structure */
|
||||
} ;
|
||||
static vector<POSSTACK_ENTRY> posStack; /* position stack */
|
||||
static uint8_t iPS; /* Index into the stack */
|
||||
//static uint8_t iPS; /* Index into the stack */
|
||||
|
||||
|
||||
// These are "curses equivalent" functions. (Used to use curses for all this,
|
||||
@ -107,7 +112,7 @@ static uint8_t iPS; /* Index into the stack */
|
||||
|
||||
void LLInst::findJumpTargets(CIcodeRec &_pc)
|
||||
{
|
||||
if (testFlags(I) && ! testFlags(JMP_ICODE) && isJmpInst())
|
||||
if (testFlags(I) and not testFlags(JMP_ICODE) and isJmpInst())
|
||||
{
|
||||
/* Replace the immediate operand with an icode index */
|
||||
iICODE labTgt=_pc.labelSrch(src().getImm2());
|
||||
@ -150,11 +155,11 @@ void Disassembler::disassem(Function * ppProc)
|
||||
if (pass != 3)
|
||||
{
|
||||
auto p = (pass == 1)? asm1_name: asm2_name;
|
||||
m_fp.open(p,ios_base::app);
|
||||
if (!m_fp.is_open())
|
||||
{
|
||||
fatalError(CANNOT_OPEN, p);
|
||||
m_disassembly_target = new QFile(p);
|
||||
if(!m_disassembly_target->open(QFile::WriteOnly|QFile::Text|QFile::Append)) {
|
||||
fatalError(CANNOT_OPEN, p.toStdString().c_str());
|
||||
}
|
||||
m_fp.setDevice(m_disassembly_target);
|
||||
}
|
||||
/* Create temporary code array */
|
||||
// Mike: needs objectising!
|
||||
@ -177,7 +182,7 @@ void Disassembler::disassem(Function * ppProc)
|
||||
/* Write procedure header */
|
||||
if (pass != 3)
|
||||
{
|
||||
std::string near_far=(pProc->flg & PROC_FAR)? "FAR": "NEAR";
|
||||
const char * near_far=(pProc->flg & PROC_FAR)? "FAR": "NEAR";
|
||||
m_fp << "\t\t"<<pProc->name<<" PROC "<< near_far<<"\n";
|
||||
}
|
||||
|
||||
@ -192,7 +197,10 @@ void Disassembler::disassem(Function * ppProc)
|
||||
if (pass != 3)
|
||||
{
|
||||
m_fp << "\n\t\t"<<pProc->name<<" ENDP\n\n";
|
||||
m_fp.close();
|
||||
m_fp.setDevice(nullptr);
|
||||
m_disassembly_target->close();
|
||||
delete m_disassembly_target;
|
||||
|
||||
}
|
||||
|
||||
pc.clear();
|
||||
@ -206,19 +214,23 @@ void Disassembler::disassem(Function * ppProc)
|
||||
void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
|
||||
{
|
||||
PROG &prog(Project::get()->prog);
|
||||
ostringstream oper_stream;
|
||||
ostringstream hex_bytes;
|
||||
ostringstream result_stream;
|
||||
ostringstream opcode_with_mods;
|
||||
ostringstream operands_s;
|
||||
oper_stream << uppercase;
|
||||
hex_bytes << uppercase;
|
||||
QString oper_contents;
|
||||
QTextStream oper_stream(&oper_contents);
|
||||
QString hex_bytes;
|
||||
QString result_contents;
|
||||
QTextStream result_stream(&result_contents);
|
||||
QString opcode_with_mods;
|
||||
|
||||
QString operands_contents;
|
||||
QTextStream operands_s(&operands_contents);
|
||||
oper_stream.setNumberFlags(QTextStream::UppercaseBase|QTextStream::UppercaseDigits);
|
||||
|
||||
/* Disassembly stage 1 --
|
||||
* Do not try to display NO_CODE entries or synthetic instructions,
|
||||
* other than JMPs, that have been introduced for def/use analysis. */
|
||||
if ((option.asm1) &&
|
||||
( inst.testFlags(NO_CODE) ||
|
||||
(inst.testFlags(SYNTHETIC) && (inst.getOpcode() != iJMP))))
|
||||
* Do not try to display NO_CODE entries or synthetic instructions,
|
||||
* other than JMPs, that have been introduced for def/use analysis. */
|
||||
if ((option.asm1) and
|
||||
( inst.testFlags(NO_CODE) or
|
||||
(inst.testFlags(SYNTHETIC) and (inst.getOpcode() != iJMP))))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -242,25 +254,28 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
|
||||
cb = (uint32_t) inst.numBytes;
|
||||
nextInst = inst.label + cb;
|
||||
|
||||
/* Output hexa code in program image */
|
||||
/* Output hex code in program image */
|
||||
if (pass != 3)
|
||||
{
|
||||
for (j = 0; j < cb; j++)
|
||||
{
|
||||
hex_bytes << hex << setw(2) << setfill('0') << uint16_t(prog.Image[inst.label + j]);
|
||||
hex_bytes += QString("%1").arg(uint16_t(prog.image()[inst.label + j]),2,16,QChar('0')).toUpper();
|
||||
}
|
||||
hex_bytes << ' ';
|
||||
hex_bytes += ' ';
|
||||
}
|
||||
}
|
||||
oper_stream << setw(POS_LAB) << left<< hex_bytes.str();
|
||||
oper_stream.setFieldWidth(POS_LAB);
|
||||
oper_stream.setFieldAlignment(QTextStream::AlignLeft);
|
||||
oper_stream << hex_bytes;
|
||||
/* Check if there is a symbol here */
|
||||
selectTable(Label);
|
||||
oper_stream << setw(5)<<left; // align for the labels
|
||||
oper_stream.setFieldWidth(5); // align for the labels
|
||||
{
|
||||
ostringstream lab_contents;
|
||||
if (readVal(lab_contents, inst.label, 0))
|
||||
QString lab_contents;
|
||||
QTextStream lab_stream(&lab_contents);
|
||||
if (readVal(lab_stream, inst.label, nullptr))
|
||||
{
|
||||
lab_contents << ':'; /* Also removes the null */
|
||||
lab_stream << ':'; /* Also removes the null */
|
||||
}
|
||||
else if (inst.testFlags(TARGET)) /* Symbols override Lnn labels */
|
||||
{
|
||||
@ -269,21 +284,23 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
|
||||
{
|
||||
pl[loc_ip] = ++g_lab;
|
||||
}
|
||||
lab_contents<< "L"<<pl[loc_ip]<<':';
|
||||
lab_stream<< "L"<<pl[loc_ip]<<':';
|
||||
}
|
||||
oper_stream<< lab_contents.str();
|
||||
lab_stream.flush();
|
||||
oper_stream << lab_contents;
|
||||
oper_stream.setFieldWidth(0);
|
||||
}
|
||||
if ((inst.getOpcode()==iSIGNEX )&& inst.testFlags(B))
|
||||
if ((inst.getOpcode()==iSIGNEX )and inst.testFlags(B))
|
||||
{
|
||||
inst.setOpcode(iCBW);
|
||||
}
|
||||
opcode_with_mods<<Machine_X86::opcodeName(inst.getOpcode());
|
||||
opcode_with_mods += Machine_X86::opcodeName(inst.getOpcode());
|
||||
|
||||
switch ( inst.getOpcode() )
|
||||
{
|
||||
case iADD: case iADC: case iSUB: case iSBB: case iAND: case iOR:
|
||||
case iXOR: case iTEST: case iCMP: case iMOV: case iLEA: case iXCHG:
|
||||
strDst(operands_s,inst.getFlag(), inst.dst);
|
||||
strDst(operands_s,inst.getFlag(), inst.m_dst);
|
||||
inst.strSrc(operands_s);
|
||||
break;
|
||||
|
||||
@ -293,7 +310,7 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
|
||||
|
||||
case iSAR: case iSHL: case iSHR: case iRCL: case iRCR: case iROL:
|
||||
case iROR:
|
||||
strDst(operands_s,inst.getFlag() | I, inst.dst);
|
||||
strDst(operands_s,inst.getFlag() | I, inst.m_dst);
|
||||
if(inst.testFlags(I))
|
||||
inst.strSrc(operands_s);
|
||||
else
|
||||
@ -301,7 +318,7 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
|
||||
break;
|
||||
|
||||
case iINC: case iDEC: case iNEG: case iNOT: case iPOP:
|
||||
strDst(operands_s,inst.getFlag() | I, inst.dst);
|
||||
strDst(operands_s,inst.getFlag() | I, inst.m_dst);
|
||||
break;
|
||||
|
||||
case iPUSH:
|
||||
@ -311,15 +328,15 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
|
||||
}
|
||||
else
|
||||
{
|
||||
strDst(operands_s,inst.getFlag() | I, inst.dst);
|
||||
strDst(operands_s,inst.getFlag() | I, inst.m_dst);
|
||||
}
|
||||
break;
|
||||
|
||||
case iDIV: case iIDIV: case iMUL: case iIMUL: case iMOD:
|
||||
if (inst.testFlags(I))
|
||||
{
|
||||
strDst(operands_s,inst.getFlag(), inst.dst) <<", ";
|
||||
formatRM(operands_s, inst.getFlag(), inst.src());
|
||||
strDst(operands_s,inst.getFlag(), inst.m_dst) <<", ";
|
||||
formatRM(operands_s, inst.src());
|
||||
inst.strSrc(operands_s);
|
||||
}
|
||||
else
|
||||
@ -327,7 +344,7 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
|
||||
break;
|
||||
|
||||
case iLDS: case iLES: case iBOUND:
|
||||
strDst(operands_s,inst.getFlag(), inst.dst)<<", dword ptr";
|
||||
strDst(operands_s,inst.getFlag(), inst.m_dst)<<", dword ptr";
|
||||
inst.strSrc(operands_s,true);
|
||||
break;
|
||||
|
||||
@ -339,15 +356,15 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
|
||||
case iJMP: case iJMPF:
|
||||
|
||||
/* Check if there is a symbol here */
|
||||
{
|
||||
ICODE *lab=pc.GetIcode(inst.src().getImm2());
|
||||
{
|
||||
ICODE *lab=pc.GetIcode(inst.src().getImm2());
|
||||
selectTable(Label);
|
||||
if ((inst.src().getImm2() < (uint32_t)numIcode) && /* Ensure in range */
|
||||
readVal(operands_s, lab->ll()->label, 0))
|
||||
if ((inst.src().getImm2() < (uint32_t)numIcode) and /* Ensure in range */
|
||||
readVal(operands_s, lab->ll()->label, nullptr))
|
||||
{
|
||||
break; /* Symbolic label. Done */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inst.testFlags(NO_LABEL))
|
||||
{
|
||||
@ -381,11 +398,10 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
|
||||
case iCALL: case iCALLF:
|
||||
if (inst.testFlags(I))
|
||||
{
|
||||
if((inst.getOpcode() == iCALL))
|
||||
operands_s<< "near";
|
||||
else
|
||||
operands_s<< " far";
|
||||
operands_s<<" ptr "<<(inst.src().proc.proc)->name;
|
||||
QString oper = QString("%1 ptr %2")
|
||||
.arg((inst.getOpcode() == iCALL) ? "near" : "far")
|
||||
.arg((inst.src().proc.proc)->name);
|
||||
operands_s<< qPrintable(oper);
|
||||
}
|
||||
else if (inst.getOpcode() == iCALLF)
|
||||
{
|
||||
@ -397,8 +413,7 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
|
||||
break;
|
||||
|
||||
case iENTER:
|
||||
operands_s<<strHex(inst.dst.off)<<", ";
|
||||
operands_s<<strHex(inst.src().getImm2());
|
||||
operands_s<<strHex(inst.m_dst.off) << ", " << strHex(inst.src().getImm2());
|
||||
break;
|
||||
|
||||
case iRET: case iRETF: case iINT:
|
||||
@ -417,15 +432,15 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
|
||||
case iOUTS: case iREP_OUTS:
|
||||
if (inst.src().segOver)
|
||||
{
|
||||
bool is_dx_src=(inst.getOpcode() == iOUTS || inst.getOpcode() == iREP_OUTS);
|
||||
bool is_dx_src=(inst.getOpcode() == iOUTS or inst.getOpcode() == iREP_OUTS);
|
||||
if(is_dx_src)
|
||||
operands_s<<"dx, "<<szPtr[inst.getFlag() & B];
|
||||
else
|
||||
operands_s<<szPtr[inst.getFlag() & B];
|
||||
if (inst.getOpcode() == iLODS ||
|
||||
inst.getOpcode() == iREP_LODS ||
|
||||
inst.getOpcode() == iOUTS ||
|
||||
inst.getOpcode() == iREP_OUTS)
|
||||
if (inst.getOpcode() == iLODS or
|
||||
inst.getOpcode() == iREP_LODS or
|
||||
inst.getOpcode() == iOUTS or
|
||||
inst.getOpcode() == iREP_OUTS)
|
||||
{
|
||||
operands_s<<Machine_X86::regName(inst.src().segOver); // szWreg[src.segOver-rAX]
|
||||
}
|
||||
@ -437,9 +452,12 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
|
||||
}
|
||||
else
|
||||
{
|
||||
(inst.getFlag() & B)? opcode_with_mods<< "B": opcode_with_mods<< "W";
|
||||
if(inst.getFlag() & B)
|
||||
opcode_with_mods+='B';
|
||||
else
|
||||
opcode_with_mods+='W';
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case iXLAT:
|
||||
if (inst.src().segOver)
|
||||
@ -456,17 +474,18 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
|
||||
|
||||
case iOUT:
|
||||
{
|
||||
std::string d1=((inst.testFlags(I))? strHex(inst.src().getImm2()): "dx");
|
||||
std::string d2=((inst.getFlag() & B) ? ", al": ", ax");
|
||||
QString d1=((inst.testFlags(I))? strHex(inst.src().getImm2()): "dx");
|
||||
QString d2=((inst.getFlag() & B) ? ", al": ", ax");
|
||||
operands_s<<d1 << d2;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
oper_stream << setw(15) << left <<opcode_with_mods.str();
|
||||
oper_stream << operands_s.str();
|
||||
oper_stream.setFieldWidth(15);
|
||||
operands_s.flush();
|
||||
oper_stream << qSetFieldWidth(15) << opcode_with_mods << qSetFieldWidth(0) << operands_contents;
|
||||
/* Comments */
|
||||
if (inst.testFlags(SYNTHETIC))
|
||||
{
|
||||
@ -474,21 +493,26 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
|
||||
}
|
||||
else
|
||||
{
|
||||
for (j = inst.label, fImpure = 0; j > 0 && j < (int)nextInst; j++)
|
||||
for (j = inst.label, fImpure = 0; j > 0 and j < (int)nextInst; j++)
|
||||
{
|
||||
fImpure |= BITMAP(j, BM_DATA);
|
||||
}
|
||||
}
|
||||
|
||||
result_stream << setw(54) << left << oper_stream.str();
|
||||
result_stream.setFieldWidth(54);
|
||||
result_stream.setFieldAlignment(QTextStream::AlignLeft);
|
||||
oper_stream.flush();
|
||||
result_stream << oper_contents;
|
||||
result_stream.setFieldWidth(0);
|
||||
/* Check for user supplied comment */
|
||||
selectTable(Comment);
|
||||
ostringstream cbuf;
|
||||
if (readVal(cbuf, inst.label, 0))
|
||||
QString cbuf_contents;
|
||||
QTextStream cbuf(&cbuf_contents);
|
||||
if (readVal(cbuf, inst.label, nullptr))
|
||||
{
|
||||
result_stream <<"; "<<cbuf.str();
|
||||
cbuf.flush();
|
||||
result_stream <<"; "<<*cbuf.string();
|
||||
}
|
||||
else if (fImpure || (inst.testFlags(SWITCH | CASE | SEG_IMMED | IMPURE | SYNTHETIC | TERMINATES)))
|
||||
else if (fImpure or (inst.testFlags(SWITCH | CASE | SEG_IMMED | IMPURE | SYNTHETIC | TERMINATES)))
|
||||
{
|
||||
if (inst.testFlags(CASE))
|
||||
{
|
||||
@ -526,8 +550,9 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
|
||||
/* output to .b code buffer */
|
||||
if (inst.testFlags(SYNTHETIC))
|
||||
result_stream<<";Synthetic inst";
|
||||
if (pass == 3) /* output to .b code buffer */
|
||||
cCode.appendCode("%s\n", result_stream.str().c_str());
|
||||
if (pass == 3) { /* output to .b code buffer */
|
||||
cCode.appendCode("%s\n", qPrintable(result_contents));
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
@ -543,7 +568,8 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
|
||||
sprintf(buf,"%03d ",loc_ip);
|
||||
result_stream<<";Synthetic inst";
|
||||
}
|
||||
m_fp<<buf<< " " << result_stream.str() << "\n";
|
||||
result_stream.flush();
|
||||
m_fp<<buf<< " " << result_contents << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
@ -552,7 +578,7 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
|
||||
/****************************************************************************
|
||||
* formatRM
|
||||
***************************************************************************/
|
||||
static void formatRM(std::ostringstream &p, uint32_t flg, const LLOperand &pm)
|
||||
static void formatRM(QTextStream &p, const LLOperand &pm)
|
||||
{
|
||||
//char seg[4];
|
||||
|
||||
@ -589,13 +615,13 @@ static void formatRM(std::ostringstream &p, uint32_t flg, const LLOperand &pm)
|
||||
/*****************************************************************************
|
||||
* strDst
|
||||
****************************************************************************/
|
||||
static ostringstream & strDst(ostringstream &os,uint32_t flg, const LLOperand &pm)
|
||||
static QTextStream & strDst(QTextStream &os,uint32_t flg, const LLOperand &pm)
|
||||
{
|
||||
/* Immediates to memory require size descriptor */
|
||||
//os << setw(WID_PTR);
|
||||
if ((flg & I) and not pm.isReg())
|
||||
os << szPtr[flg & B];
|
||||
formatRM(os, flg, pm);
|
||||
formatRM(os, pm);
|
||||
return os;
|
||||
}
|
||||
|
||||
@ -603,7 +629,7 @@ static ostringstream & strDst(ostringstream &os,uint32_t flg, const LLOperand &p
|
||||
/****************************************************************************
|
||||
* strSrc *
|
||||
****************************************************************************/
|
||||
ostringstream &LLInst::strSrc(ostringstream &os,bool skip_comma)
|
||||
QTextStream &LLInst::strSrc(QTextStream &os,bool skip_comma)
|
||||
{
|
||||
if(false==skip_comma)
|
||||
os<<", ";
|
||||
@ -612,7 +638,7 @@ ostringstream &LLInst::strSrc(ostringstream &os,bool skip_comma)
|
||||
else if (testFlags(IM_SRC)) /* level 2 */
|
||||
os<<"dx:ax";
|
||||
else
|
||||
formatRM(os, getFlag(), src());
|
||||
formatRM(os, src());
|
||||
|
||||
return os;
|
||||
}
|
||||
@ -627,7 +653,7 @@ static char *strHex(uint32_t d)
|
||||
static char buf[10];
|
||||
|
||||
d &= 0xFFFF;
|
||||
sprintf(buf, "0%lX%s", d, (d > 9)? "h": "");
|
||||
sprintf(buf, "0%X%s", d, (d > 9)? "h": "");
|
||||
return (buf + (buf[1] <= '9'));
|
||||
}
|
||||
|
||||
@ -636,25 +662,29 @@ static char *strHex(uint32_t d)
|
||||
****************************************************************************/
|
||||
void interactDis(Function * initProc, int initIC)
|
||||
{
|
||||
printf("Sorry - interactive disasassembler option not available for Unix\n");
|
||||
QString procname = "UNKNOWN";
|
||||
if(initProc)
|
||||
procname = initProc->name;
|
||||
|
||||
qDebug() << "Wanted to start interactive disasassembler for "<<procname<<":"<<initIC;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Handle the floating point opcodes (icode iESC) */
|
||||
void LLInst::flops(std::ostringstream &out)
|
||||
void LLInst::flops(QTextStream &out)
|
||||
{
|
||||
char bf[30];
|
||||
//char bf[30];
|
||||
uint8_t op = (uint8_t)src().getImm2();
|
||||
|
||||
/* Note that op is set to the escape number, e.g.
|
||||
esc 0x38 is FILD */
|
||||
|
||||
if ( not dst.isReg() )
|
||||
if ( not m_dst.isReg() )
|
||||
{
|
||||
/* The mod/rm mod bits are not set to 11 (i.e. register). This is the normal floating point opcode */
|
||||
out<<Machine_X86::floatOpName(op)<<' ';
|
||||
out <<setw(10);
|
||||
if ((op == 0x29) || (op == 0x1F))
|
||||
out.setFieldWidth(10);
|
||||
if ((op == 0x29) or (op == 0x1F))
|
||||
{
|
||||
out << "tbyte ptr ";
|
||||
}
|
||||
@ -684,8 +714,8 @@ void LLInst::flops(std::ostringstream &out)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
formatRM(out, getFlag(), dst);
|
||||
out.setFieldWidth(0);
|
||||
formatRM(out, m_dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -694,7 +724,7 @@ void LLInst::flops(std::ostringstream &out)
|
||||
normal opcodes. Because the opcodes are slightly different for
|
||||
this case (e.g. op=04 means FSUB if reg != 3, but FSUBR for
|
||||
reg == 3), a separate table is used (szFlops2). */
|
||||
int destRegIdx=dst.regi - rAX;
|
||||
int destRegIdx=m_dst.regi - rAX;
|
||||
switch (op)
|
||||
{
|
||||
case 0x0C:
|
||||
@ -723,7 +753,7 @@ void LLInst::flops(std::ostringstream &out)
|
||||
break;
|
||||
default:
|
||||
out << Machine_X86::floatOpName(0x40+op);
|
||||
if ((op >= 0x20) && (op <= 0x27))
|
||||
if ((op >= 0x20) and (op <= 0x27))
|
||||
{
|
||||
/* This is the ST(i), ST form. */
|
||||
out << "ST("<<destRegIdx - rAX<<"),ST";
|
||||
|
||||
@ -11,36 +11,37 @@
|
||||
|
||||
#include "dcc.h"
|
||||
|
||||
static std::map<eErrorId,std::string> errorMessage =
|
||||
{
|
||||
{INVALID_ARG ,"Invalid option -%c\n"},
|
||||
{INVALID_OPCODE ,"Invalid instruction %02X at location %06lX\n"},
|
||||
{INVALID_386OP ,"Don't understand 80386 instruction %02X at location %06lX\n"},
|
||||
{FUNNY_SEGOVR ,"Segment override with no memory operand at location %06lX\n"},
|
||||
{FUNNY_REP ,"REP prefix without a string instruction at location %06lX\n"},
|
||||
{CANNOT_OPEN ,"Cannot open %s\n"},
|
||||
{CANNOT_READ ,"Error while reading %s\n"},
|
||||
{MALLOC_FAILED ,"malloc of %ld bytes failed\n"},
|
||||
{NEWEXE_FORMAT ,"Don't understand new EXE format\n"},
|
||||
{NO_BB ,"Failed to find a BB for jump to %ld in proc %s\n"},
|
||||
{INVALID_SYNTHETIC_BB,"Basic Block is a synthetic jump\n"},
|
||||
{INVALID_INT_BB ,"Failed to find a BB for interval\n"},
|
||||
{IP_OUT_OF_RANGE ,"Instruction at location %06lX goes beyond loaded image\n"},
|
||||
{DEF_NOT_FOUND ,"Definition not found for condition code usage at opcode %d\n"},
|
||||
{JX_NOT_DEF ,"JX use, definition not supported at opcode #%d\n"},
|
||||
{NOT_DEF_USE ,"Def - use not supported. Def op = %d, use op = %d.\n"},
|
||||
{REPEAT_FAIL ,"Failed to construct repeat..until() condition.\n"},
|
||||
{WHILE_FAIL ,"Failed to construct while() condition.\n"},
|
||||
};
|
||||
static const std::map<eErrorId,std::string> errorMessage =
|
||||
{
|
||||
{INVALID_ARG ,"Invalid option -%c\n"},
|
||||
{INVALID_OPCODE ,"Invalid instruction %02X at location %06lX\n"},
|
||||
{INVALID_386OP ,"Don't understand 80386 instruction %02X at location %06lX\n"},
|
||||
{FUNNY_SEGOVR ,"Segment override with no memory operand at location %06lX\n"},
|
||||
{FUNNY_REP ,"REP prefix without a string instruction at location %06lX\n"},
|
||||
{CANNOT_OPEN ,"Cannot open %s\n"},
|
||||
{CANNOT_READ ,"Error while reading %s\n"},
|
||||
{MALLOC_FAILED ,"malloc of %ld bytes failed\n"},
|
||||
{NEWEXE_FORMAT ,"Don't understand new EXE format\n"},
|
||||
{NO_BB ,"Failed to find a BB for jump to %ld in proc %s\n"},
|
||||
{INVALID_SYNTHETIC_BB,"Basic Block is a synthetic jump\n"},
|
||||
{INVALID_INT_BB ,"Failed to find a BB for interval\n"},
|
||||
{IP_OUT_OF_RANGE ,"Instruction at location %06lX goes beyond loaded image\n"},
|
||||
{DEF_NOT_FOUND ,"Definition not found for condition code usage at opcode %d\n"},
|
||||
{JX_NOT_DEF ,"JX use, definition not supported at opcode #%d\n"},
|
||||
{NOT_DEF_USE ,"%x: Def - use not supported. Def op = %d, use op = %d.\n"},
|
||||
{REPEAT_FAIL ,"Failed to construct repeat..until() condition.\n"},
|
||||
{WHILE_FAIL ,"Failed to construct while() condition.\n"},
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
fatalError: displays error message and exits the program.
|
||||
****************************************************************************/
|
||||
void fatalError(eErrorId errId, ...)
|
||||
{ va_list args;
|
||||
//#ifdef __UNIX__ /* ultrix */
|
||||
{
|
||||
va_list args;
|
||||
//#ifdef __UNIX__ /* ultrix */
|
||||
#if 0
|
||||
int errId;
|
||||
int errId;
|
||||
|
||||
va_start(args);
|
||||
errId = va_arg(args, int);
|
||||
@ -49,10 +50,12 @@ void fatalError(eErrorId errId, ...)
|
||||
#endif
|
||||
|
||||
if (errId == USAGE)
|
||||
fprintf(stderr,"Usage: dcc [-a1a2cmpsvVi][-o asmfile] DOS_executable\n");
|
||||
fprintf(stderr,"Usage: dcc [-a1a2cmpsvVi][-o asmfile] DOS_executable\n");
|
||||
else {
|
||||
auto msg_iter = errorMessage.find(errId);
|
||||
assert(msg_iter!=errorMessage.end());
|
||||
fprintf(stderr, "dcc: ");
|
||||
vfprintf(stderr, errorMessage[errId].c_str(), args);
|
||||
vfprintf(stderr, msg_iter->second.c_str(), args);
|
||||
}
|
||||
va_end(args);
|
||||
exit((int)errId);
|
||||
@ -63,10 +66,11 @@ void fatalError(eErrorId errId, ...)
|
||||
reportError: reports the warning/error and continues with the program.
|
||||
****************************************************************************/
|
||||
void reportError(eErrorId errId, ...)
|
||||
{ va_list args;
|
||||
//#ifdef __UNIX__ /* ultrix */
|
||||
{
|
||||
va_list args;
|
||||
//#ifdef __UNIX__ /* ultrix */
|
||||
#if 0
|
||||
int errId;
|
||||
int errId;
|
||||
|
||||
va_start(args);
|
||||
errId = va_arg(args, int);
|
||||
@ -74,6 +78,8 @@ void reportError(eErrorId errId, ...)
|
||||
va_start(args, errId);
|
||||
#endif
|
||||
fprintf(stderr, "dcc: ");
|
||||
vfprintf(stderr, errorMessage[errId].c_str(), args);
|
||||
auto msg_iter = errorMessage.find(errId);
|
||||
assert(msg_iter!=errorMessage.end());
|
||||
vfprintf(stderr, msg_iter->second.c_str(), args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
@ -9,18 +9,15 @@
|
||||
* *
|
||||
\* * * * * * * * * * * * */
|
||||
|
||||
#include "msvc_fixes.h"
|
||||
#include <memory.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef PATLEN
|
||||
#define PATLEN 23
|
||||
#define WILD 0xF4
|
||||
#endif
|
||||
|
||||
#ifndef bool
|
||||
#define bool unsigned char
|
||||
#define uint8_t unsigned char
|
||||
#endif
|
||||
|
||||
static int pc; /* Indexes into pat[] */
|
||||
|
||||
/* prototypes */
|
||||
@ -82,8 +79,9 @@ TwoWild(uint8_t pat[])
|
||||
static bool
|
||||
FourWild(uint8_t pat[])
|
||||
{
|
||||
TwoWild(pat);
|
||||
return TwoWild(pat);
|
||||
if(TwoWild(pat))
|
||||
return true;
|
||||
return TwoWild(pat);
|
||||
}
|
||||
|
||||
/* Chop from the current point by wiping with zeroes. Can't rely on anything
|
||||
@ -180,8 +178,7 @@ static bool op0F(uint8_t pat[])
|
||||
processor is in 16 bit address mode (real mode).
|
||||
PATLEN bytes are scanned.
|
||||
*/
|
||||
void
|
||||
fixWildCards(uint8_t pat[])
|
||||
void fixWildCards(uint8_t pat[])
|
||||
{
|
||||
|
||||
uint8_t op, quad, intArg;
|
||||
@ -339,7 +336,7 @@ fixWildCards(uint8_t pat[])
|
||||
if (op & 1) pc += 2;
|
||||
else pc += 1;
|
||||
continue;
|
||||
|
||||
|
||||
}
|
||||
case 0xB0: /* B0 - BF */
|
||||
{
|
||||
@ -410,7 +407,7 @@ fixWildCards(uint8_t pat[])
|
||||
|
||||
case 0xCD: /* int nn */
|
||||
intArg = pat[pc++];
|
||||
if ((intArg >= 0x34) && (intArg <= 0x3B))
|
||||
if ((intArg >= 0x34) and (intArg <= 0x3B))
|
||||
{
|
||||
/* Borland/Microsoft FP emulations */
|
||||
if (ModRM(pat)) return;
|
||||
|
||||
@ -7,10 +7,17 @@
|
||||
#include "dcc.h"
|
||||
#include "disassem.h"
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h> /* For malloc, free, realloc */
|
||||
#include "project.h"
|
||||
class Loader
|
||||
{
|
||||
bool loadIntoProject(IProject *);
|
||||
};
|
||||
|
||||
typedef struct { /* PSP structure */
|
||||
uint16_t int20h; /* interrupt 20h */
|
||||
uint16_t eof; /* segment, end of allocation block */
|
||||
@ -50,7 +57,7 @@ static struct { /* EXE file header */
|
||||
|
||||
#define EXE_RELOCATION 0x10 /* EXE images rellocated to above PSP */
|
||||
|
||||
static void LoadImage(char *filename);
|
||||
//static void LoadImage(char *filename);
|
||||
static void displayLoadInfo(void);
|
||||
static void displayMemMap(void);
|
||||
|
||||
@ -58,31 +65,29 @@ static void displayMemMap(void);
|
||||
* FrontEnd - invokes the loader, parser, disassembler (if asm1), icode
|
||||
* rewritter, and displays any useful information.
|
||||
****************************************************************************/
|
||||
extern Project g_proj;
|
||||
bool DccFrontend::FrontEnd ()
|
||||
{
|
||||
|
||||
g_proj.callGraph = 0;
|
||||
g_proj.m_fname = m_fname;
|
||||
Project::get()->callGraph = nullptr;
|
||||
Project::get()->create(m_fname);
|
||||
|
||||
/* Load program into memory */
|
||||
LoadImage(g_proj);
|
||||
LoadImage(*Project::get());
|
||||
|
||||
if (option.verbose)
|
||||
displayLoadInfo();
|
||||
|
||||
/* Do depth first flow analysis building call graph and procedure list,
|
||||
* and attaching the I-code to each procedure */
|
||||
parse (g_proj);
|
||||
parse (*Project::get());
|
||||
|
||||
if (option.asm1)
|
||||
{
|
||||
printf("dcc: writing assembler file %s\n", asm1_name);
|
||||
printf("dcc: writing assembler file %s\n", asm1_name.c_str());
|
||||
}
|
||||
|
||||
/* Search through code looking for impure references and flag them */
|
||||
Disassembler ds(1);
|
||||
for(Function &f : g_proj.pProcList)
|
||||
for(Function &f : Project::get()->pProcList)
|
||||
{
|
||||
f.markImpure();
|
||||
if (option.asm1)
|
||||
@ -92,11 +97,11 @@ bool DccFrontend::FrontEnd ()
|
||||
}
|
||||
if (option.Interact)
|
||||
{
|
||||
interactDis(&g_proj.pProcList.front(), 0); /* Interactive disassembler */
|
||||
interactDis(&Project::get()->pProcList.front(), 0); /* Interactive disassembler */
|
||||
}
|
||||
|
||||
/* Converts jump target addresses to icode offsets */
|
||||
for(Function &f : g_proj.pProcList)
|
||||
for(Function &f : Project::get()->pProcList)
|
||||
{
|
||||
f.bindIcodeOff();
|
||||
}
|
||||
@ -125,7 +130,7 @@ static void displayLoadInfo(void)
|
||||
printf("Minimum allocation = %04X paras\n", LH(&header.minAlloc));
|
||||
printf("Maximum allocation = %04X paras\n", LH(&header.maxAlloc));
|
||||
}
|
||||
printf("Load image size = %04X\n", prog.cbImage - sizeof(PSP));
|
||||
printf("Load image size = %04" PRIiPTR "\n", prog.cbImage - sizeof(PSP));
|
||||
printf("Initial SS:SP = %04X:%04X\n", prog.initSS, prog.initSP);
|
||||
printf("Initial CS:IP = %04X:%04X\n", prog.initCS, prog.initIP);
|
||||
|
||||
@ -134,7 +139,7 @@ static void displayLoadInfo(void)
|
||||
printf("\nRelocation Table\n");
|
||||
for (i = 0; i < prog.cReloc; i++)
|
||||
{
|
||||
printf("%06X -> [%04X]\n", prog.relocTable[i],LH(prog.Image + prog.relocTable[i]));
|
||||
printf("%06X -> [%04X]\n", prog.relocTable[i],LH(prog.image() + prog.relocTable[i]));
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
@ -208,23 +213,23 @@ void DccFrontend::LoadImage(Project &proj)
|
||||
uint8_t buf[4];
|
||||
|
||||
/* Open the input file */
|
||||
if ((fp = fopen(proj.m_fname.c_str(), "rb")) == NULL)
|
||||
if ((fp = fopen(proj.binary_path().c_str(), "rb")) == nullptr)
|
||||
{
|
||||
fatalError(CANNOT_OPEN, proj.m_fname.c_str());
|
||||
fatalError(CANNOT_OPEN, proj.binary_path().c_str());
|
||||
}
|
||||
|
||||
/* Read in first 2 bytes to check EXE signature */
|
||||
if (fread(&header, 1, 2, fp) != 2)
|
||||
{
|
||||
fatalError(CANNOT_READ, proj.m_fname.c_str());
|
||||
fatalError(CANNOT_READ, proj.binary_path().c_str());
|
||||
}
|
||||
|
||||
if (! (prog.fCOM = (boolT)(header.sigLo != 0x4D || header.sigHi != 0x5A))) {
|
||||
prog.fCOM = (header.sigLo != 0x4D || header.sigHi != 0x5A);
|
||||
if (! prog.fCOM ) {
|
||||
/* Read rest of header */
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
if (fread(&header, sizeof(header), 1, fp) != 1)
|
||||
{
|
||||
fatalError(CANNOT_READ, proj.m_fname.c_str());
|
||||
fatalError(CANNOT_READ, proj.binary_path().c_str());
|
||||
}
|
||||
|
||||
/* This is a typical DOS kludge! */
|
||||
@ -245,13 +250,13 @@ void DccFrontend::LoadImage(Project &proj)
|
||||
}
|
||||
|
||||
/* We quietly ignore minAlloc and maxAlloc since for our
|
||||
* purposes it doesn't really matter where in real memory
|
||||
* the program would end up. EXE programs can't really rely on
|
||||
* their load location so setting the PSP segment to 0 is fine.
|
||||
* Certainly programs that prod around in DOS or BIOS are going
|
||||
* to have to load DS from a constant so it'll be pretty
|
||||
* obvious.
|
||||
*/
|
||||
* purposes it doesn't really matter where in real memory
|
||||
* the program would end up. EXE programs can't really rely on
|
||||
* their load location so setting the PSP segment to 0 is fine.
|
||||
* Certainly programs that prod around in DOS or BIOS are going
|
||||
* to have to load DS from a constant so it'll be pretty
|
||||
* obvious.
|
||||
*/
|
||||
prog.initCS = (int16_t)LH(&header.initCS) + EXE_RELOCATION;
|
||||
prog.initIP = (int16_t)LH(&header.initIP);
|
||||
prog.initSS = (int16_t)LH(&header.initSS) + EXE_RELOCATION;
|
||||
@ -298,14 +303,14 @@ void DccFrontend::LoadImage(Project &proj)
|
||||
|
||||
/* Allocate a block of memory for the program. */
|
||||
prog.cbImage = cb + sizeof(PSP);
|
||||
prog.Image = new uint8_t [prog.cbImage];
|
||||
prog.Image[0] = 0xCD; /* Fill in PSP int 20h location */
|
||||
prog.Image[1] = 0x20; /* for termination checking */
|
||||
prog.Imagez = new uint8_t [prog.cbImage];
|
||||
prog.Imagez[0] = 0xCD; /* Fill in PSP int 20h location */
|
||||
prog.Imagez[1] = 0x20; /* for termination checking */
|
||||
|
||||
/* Read in the image past where a PSP would go */
|
||||
if (cb != (int)fread(prog.Image + sizeof(PSP), 1, (size_t)cb, fp))
|
||||
if (cb != (int)fread(prog.Imagez + sizeof(PSP), 1, (size_t)cb, fp))
|
||||
{
|
||||
fatalError(CANNOT_READ, proj.m_fname.c_str());
|
||||
fatalError(CANNOT_READ, proj.binary_path().c_str());
|
||||
}
|
||||
|
||||
/* Set up memory map */
|
||||
@ -318,7 +323,7 @@ void DccFrontend::LoadImage(Project &proj)
|
||||
{
|
||||
for (i = 0; i < prog.cReloc; i++)
|
||||
{
|
||||
uint8_t *p = &prog.Image[prog.relocTable[i]];
|
||||
uint8_t *p = &prog.Imagez[prog.relocTable[i]];
|
||||
uint16_t w = (uint16_t)LH(p) + EXE_RELOCATION;
|
||||
*p++ = (uint8_t)(w & 0x00FF);
|
||||
*p = (uint8_t)((w & 0xFF00) >> 8);
|
||||
|
||||
273
src/graph.cpp
273
src/graph.cpp
@ -3,15 +3,30 @@
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
|
||||
#include "dcc.h"
|
||||
#include <string.h>
|
||||
#include <malloc.h> /* For free() */
|
||||
#include "graph.h"
|
||||
|
||||
#include "msvc_fixes.h"
|
||||
#include "dcc.h"
|
||||
#include "project.h"
|
||||
|
||||
#include <boost/range/rbegin.hpp>
|
||||
#include <boost/range/rend.hpp>
|
||||
#include <string.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
extern Project g_proj;
|
||||
//static BB * rmJMP(Function * pProc, int marker, BB * pBB);
|
||||
static void mergeFallThrough(Function * pProc, BB * pBB);
|
||||
static void dfsNumbering(BB * pBB, std::vector<BB*> &dfsLast, int *first, int *last);
|
||||
//static void mergeFallThrough(Function * pProc, BB * pBB);
|
||||
//static void dfsNumbering(BB * pBB, std::vector<BB*> &dfsLast, int *first, int *last);
|
||||
|
||||
void Function::addOutEdgesForConditionalJump(BB * pBB,int next_ip, LLInst *ll)
|
||||
{
|
||||
pBB->addOutEdge(next_ip);
|
||||
/* This is checking for jumps off into nowhere */
|
||||
if ( not ll->testFlags(NO_LABEL) )
|
||||
pBB->addOutEdge(ll->src().getImm2());
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* createCFG - Create the basic control flow graph
|
||||
@ -29,142 +44,119 @@ void Function::createCFG()
|
||||
* 5) Repeated string instructions
|
||||
* 6) End of procedure
|
||||
*/
|
||||
int i;
|
||||
int ip;
|
||||
|
||||
BB * psBB;
|
||||
BB * pBB;
|
||||
iICODE pIcode = Icode.begin();
|
||||
iICODE iStart = Icode.begin();
|
||||
|
||||
stats.numBBbef = stats.numBBaft = 0;
|
||||
for (; pIcode!=Icode.end(); ++pIcode)
|
||||
rICODE current_range=make_iterator_range(pIcode,++iICODE(pIcode));
|
||||
for (; pIcode!=Icode.end(); ++pIcode,current_range.advance_end(1))
|
||||
{
|
||||
iICODE nextIcode = ++iICODE(pIcode);
|
||||
pBB = nullptr;
|
||||
|
||||
LLInst *ll = pIcode->ll();
|
||||
/* Only process icodes that have valid instructions */
|
||||
if(ll->testFlags(NO_CODE))
|
||||
continue;
|
||||
/* Stick a NOWHERE_NODE on the end if we terminate
|
||||
* with anything other than a ret, jump or terminate */
|
||||
* with anything other than a ret, jump or terminate */
|
||||
if (nextIcode == Icode.end() and
|
||||
(not ll->testFlags(TERMINATES)) and
|
||||
(not ll->match(iJMP)) and (not ll->match(iJMPF)) and
|
||||
(not ll->match(iRET)) and (not ll->match(iRETF)))
|
||||
{
|
||||
//pBB=BB::Create(start, ip, NOWHERE_NODE, 0, this);
|
||||
pBB=BB::Create(iStart, pIcode, NOWHERE_NODE, 0, this);
|
||||
|
||||
pBB=BB::Create(current_range, NOWHERE_NODE, this);
|
||||
}
|
||||
|
||||
/* Only process icodes that have valid instructions */
|
||||
else if (not ll->testFlags(NO_CODE) )
|
||||
{
|
||||
else
|
||||
switch (ll->getOpcode()) {
|
||||
case iJB: case iJBE: case iJAE: case iJA:
|
||||
case iJL: case iJLE: case iJGE: case iJG:
|
||||
case iJE: case iJNE: case iJS: case iJNS:
|
||||
case iJO: case iJNO: case iJP: case iJNP:
|
||||
case iJCXZ:
|
||||
pBB = BB::Create(iStart, pIcode, TWO_BRANCH, 2, this);
|
||||
CondJumps:
|
||||
//start = ip + 1;
|
||||
iStart = ++iICODE(pIcode);
|
||||
pBB->edges[0].ip = (uint32_t)iStart->loc_ip;
|
||||
/* This is for jumps off into nowhere */
|
||||
if ( ll->testFlags(NO_LABEL) )
|
||||
{
|
||||
pBB->edges.pop_back();
|
||||
}
|
||||
else
|
||||
pBB->edges[1].ip = ll->src().getImm2();
|
||||
break;
|
||||
case iJB: case iJBE: case iJAE: case iJA:
|
||||
case iJL: case iJLE: case iJGE: case iJG:
|
||||
case iJE: case iJNE: case iJS: case iJNS:
|
||||
case iJO: case iJNO: case iJP: case iJNP:
|
||||
case iJCXZ:
|
||||
pBB = BB::Create(current_range, TWO_BRANCH, this);
|
||||
addOutEdgesForConditionalJump(pBB,nextIcode->loc_ip, ll);
|
||||
break;
|
||||
|
||||
case iLOOP: case iLOOPE: case iLOOPNE:
|
||||
//pBB = BB::Create(start, ip, LOOP_NODE, 2, this);
|
||||
pBB = BB::Create(iStart, pIcode, LOOP_NODE, 2, this);
|
||||
goto CondJumps;
|
||||
case iLOOP: case iLOOPE: case iLOOPNE:
|
||||
pBB = BB::Create(current_range, LOOP_NODE, this);
|
||||
addOutEdgesForConditionalJump(pBB,nextIcode->loc_ip, ll);
|
||||
break;
|
||||
|
||||
case iJMPF: case iJMP:
|
||||
if (ll->testFlags(SWITCH))
|
||||
{
|
||||
//pBB = BB::Create(start, ip, MULTI_BRANCH, ll->caseTbl.numEntries, this);
|
||||
pBB = BB::Create(iStart, pIcode, MULTI_BRANCH, ll->caseTbl2.size(), this);
|
||||
for (i = 0; i < ll->caseTbl2.size(); i++)
|
||||
pBB->edges[i].ip = ll->caseTbl2[i];
|
||||
hasCase = true;
|
||||
}
|
||||
else if ((ll->getFlag() & (I | NO_LABEL)) == I) //TODO: WHY NO_LABEL TESTIT
|
||||
{
|
||||
//pBB = BB::Create(start, ip, ONE_BRANCH, 1, this);
|
||||
pBB = BB::Create(iStart, pIcode, ONE_BRANCH, 1, this);
|
||||
|
||||
pBB->edges[0].ip = ll->src().getImm2();
|
||||
}
|
||||
else
|
||||
BB::Create(iStart, pIcode, NOWHERE_NODE, 0, this);
|
||||
iStart = ++iICODE(pIcode);
|
||||
break;
|
||||
|
||||
case iCALLF: case iCALL:
|
||||
case iJMPF: case iJMP:
|
||||
if (ll->testFlags(SWITCH))
|
||||
{
|
||||
Function * p = ll->src().proc.proc;
|
||||
if (p)
|
||||
i = ((p->flg) & TERMINATES) ? 0 : 1;
|
||||
else
|
||||
i = 1;
|
||||
pBB = BB::Create(iStart, pIcode, CALL_NODE, i, this);
|
||||
iStart = ++iICODE(pIcode);//start = ip + 1;
|
||||
if (i)
|
||||
pBB->edges[0].ip = iStart->loc_ip;//(uint32_t)start;
|
||||
pBB = BB::Create(current_range, MULTI_BRANCH, this);
|
||||
for (auto & elem : ll->caseTbl2)
|
||||
pBB->addOutEdge(elem);
|
||||
hasCase = true;
|
||||
}
|
||||
break;
|
||||
else if ((ll->getFlag() & (I | NO_LABEL)) == I) //TODO: WHY NO_LABEL TESTIT
|
||||
{
|
||||
pBB = BB::Create(current_range, ONE_BRANCH, this);
|
||||
pBB->addOutEdge(ll->src().getImm2());
|
||||
}
|
||||
else
|
||||
pBB = BB::Create(current_range, NOWHERE_NODE, this);
|
||||
break;
|
||||
|
||||
case iRET: case iRETF:
|
||||
//BB::Create(start, ip, RETURN_NODE, 0, this);
|
||||
BB::Create(iStart, pIcode, RETURN_NODE, 0, this);
|
||||
iStart = ++iICODE(pIcode);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Check for exit to DOS */
|
||||
iICODE next1=++iICODE(pIcode);
|
||||
if ( ll->testFlags(TERMINATES) )
|
||||
{
|
||||
pBB = BB::Create(iStart, pIcode, TERMINATE_NODE, 0, this);
|
||||
//pBB = BB::Create(start, ip, TERMINATE_NODE, 0, this);
|
||||
iStart = ++iICODE(pIcode); // start = ip + 1;
|
||||
}
|
||||
/* Check for a fall through */
|
||||
else if (next1 != Icode.end())
|
||||
{
|
||||
if (next1->ll()->testFlags(TARGET | CASE))
|
||||
{
|
||||
//pBB = BB::Create(start, ip, FALL_NODE, 1, this);
|
||||
pBB = BB::Create(iStart, pIcode, FALL_NODE, 1, this);
|
||||
iStart = ++iICODE(pIcode); // start = ip + 1;
|
||||
pBB->addOutEdge(iStart->loc_ip);
|
||||
pBB->edges[0].ip = iStart->loc_ip;//(uint32_t)start;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case iCALLF: case iCALL:
|
||||
{
|
||||
Function * p = ll->src().proc.proc;
|
||||
pBB = BB::Create(current_range, CALL_NODE, this);
|
||||
if (p and not ((p->flg) & TERMINATES) )
|
||||
pBB->addOutEdge(nextIcode->loc_ip);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
auto iter=heldBBs.begin();
|
||||
/* Convert list of BBs into a graph */
|
||||
for (; iter!=heldBBs.end(); ++iter)
|
||||
{
|
||||
pBB = *iter;
|
||||
for (size_t edeg_idx = 0; edeg_idx < pBB->edges.size(); edeg_idx++)
|
||||
|
||||
case iRET: case iRETF:
|
||||
pBB = BB::Create(current_range, RETURN_NODE, this);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Check for exit to DOS */
|
||||
if ( ll->testFlags(TERMINATES) )
|
||||
{
|
||||
pBB = BB::Create(current_range, TERMINATE_NODE, this);
|
||||
}
|
||||
/* Check for a fall through */
|
||||
else if (nextIcode != Icode.end())
|
||||
{
|
||||
if (nextIcode->ll()->testFlags(TARGET | CASE))
|
||||
{
|
||||
pBB = BB::Create(current_range, FALL_NODE, this);
|
||||
pBB->addOutEdge(nextIcode->loc_ip);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(pBB!=nullptr) // created a new Basic block
|
||||
{
|
||||
uint32_t ip = pBB->edges[edeg_idx].ip;
|
||||
// restart the range
|
||||
// end iterator will be updated by expression in for statement
|
||||
current_range=make_iterator_range(nextIcode,nextIcode);
|
||||
}
|
||||
if (nextIcode == Icode.end())
|
||||
break;
|
||||
}
|
||||
for (auto pr : m_ip_to_bb)
|
||||
{
|
||||
BB* pBB=pr.second;
|
||||
for (auto & elem : pBB->edges)
|
||||
{
|
||||
int32_t ip = elem.ip;
|
||||
if (ip >= SYNTHESIZED_MIN)
|
||||
{
|
||||
fatalError (INVALID_SYNTHETIC_BB);
|
||||
return;
|
||||
}
|
||||
auto iter2=std::find_if(heldBBs.begin(),heldBBs.end(),
|
||||
[ip](BB *psBB)->bool {return psBB->begin()->loc_ip==ip;});
|
||||
if(iter2==heldBBs.end())
|
||||
fatalError(NO_BB, ip, name.c_str());
|
||||
psBB = *iter2;
|
||||
pBB->edges[edeg_idx].BBptr = psBB;
|
||||
auto iter2=m_ip_to_bb.find(ip);
|
||||
if(iter2==m_ip_to_bb.end())
|
||||
fatalError(NO_BB, ip, qPrintable(name));
|
||||
psBB = iter2->second;
|
||||
elem.BBptr = psBB;
|
||||
psBB->inEdges.push_back((BB *)nullptr);
|
||||
}
|
||||
}
|
||||
@ -179,8 +171,8 @@ void Function::markImpure()
|
||||
continue;
|
||||
//assert that case tbl has less entries then symbol table ????
|
||||
//WARNING: Case entries are held in symbol table !
|
||||
assert(g_proj.validSymIdx(icod.ll()->caseEntry));
|
||||
const SYM &psym(g_proj.getSymByIdx(icod.ll()->caseEntry));
|
||||
assert(Project::get()->validSymIdx(icod.ll()->caseEntry));
|
||||
const SYM &psym(Project::get()->getSymByIdx(icod.ll()->caseEntry));
|
||||
for (int c = (int)psym.label; c < (int)psym.label+psym.size; c++)
|
||||
{
|
||||
if (BITMAP(c, BM_CODE))
|
||||
@ -194,21 +186,16 @@ void Function::markImpure()
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* newBB - Allocate new BB and link to end of list
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* freeCFG - Deallocates a cfg
|
||||
****************************************************************************/
|
||||
void Function::freeCFG()
|
||||
{
|
||||
for(BB *p : heldBBs)
|
||||
for(auto p : m_ip_to_bb)
|
||||
{
|
||||
delete p;
|
||||
delete p.second;
|
||||
}
|
||||
m_ip_to_bb.clear();
|
||||
}
|
||||
|
||||
|
||||
@ -222,9 +209,9 @@ void Function::compressCFG()
|
||||
|
||||
/* First pass over BB list removes redundant jumps of the form
|
||||
* (Un)Conditional -> Unconditional jump */
|
||||
for (BB *pBB : m_cfg)
|
||||
for (BB *pBB : m_actual_cfg) //m_cfg
|
||||
{
|
||||
if(pBB->inEdges.empty() || (pBB->nodeType != ONE_BRANCH && pBB->nodeType != TWO_BRANCH))
|
||||
if(pBB->inEdges.empty() or (pBB->nodeType != ONE_BRANCH and pBB->nodeType != TWO_BRANCH))
|
||||
continue;
|
||||
for (TYPEADR_TYPE &edgeRef : pBB->edges)
|
||||
{
|
||||
@ -244,18 +231,17 @@ void Function::compressCFG()
|
||||
/* Next is a depth-first traversal merging any FALL_NODE or
|
||||
* ONE_BRANCH that fall through to a node with that as their only
|
||||
* in-edge. */
|
||||
m_cfg.front()->mergeFallThrough(Icode);
|
||||
m_actual_cfg.front()->mergeFallThrough(Icode);
|
||||
|
||||
/* Remove redundant BBs created by the above compressions
|
||||
* and allocate in-edge arrays as required. */
|
||||
stats.numBBaft = stats.numBBbef;
|
||||
|
||||
for(auto iter=m_cfg.begin(); iter!=m_cfg.end(); ++iter)
|
||||
bool entry_node=true;
|
||||
for(BB *pBB : m_actual_cfg)
|
||||
{
|
||||
BB * pBB = *iter;
|
||||
if (pBB->inEdges.empty())
|
||||
{
|
||||
if (iter == m_cfg.begin()) /* Init it misses out on */
|
||||
if (entry_node) /* Init it misses out on */
|
||||
pBB->index = UN_INIT;
|
||||
else
|
||||
{
|
||||
@ -267,15 +253,16 @@ void Function::compressCFG()
|
||||
{
|
||||
pBB->inEdgeCount = pBB->inEdges.size();
|
||||
}
|
||||
entry_node=false;
|
||||
}
|
||||
|
||||
/* Allocate storage for dfsLast[] array */
|
||||
numBBs = stats.numBBaft;
|
||||
m_dfsLast.resize(numBBs,0); // = (BB **)allocMem(numBBs * sizeof(BB *))
|
||||
m_dfsLast.resize(numBBs,nullptr); // = (BB **)allocMem(numBBs * sizeof(BB *))
|
||||
|
||||
/* Now do a dfs numbering traversal and fill in the inEdges[] array */
|
||||
last = numBBs - 1;
|
||||
m_cfg.front()->dfsNumbering(m_dfsLast, &first, &last);
|
||||
m_actual_cfg.front()->dfsNumbering(m_dfsLast, &first, &last);
|
||||
}
|
||||
|
||||
|
||||
@ -286,7 +273,7 @@ BB *BB::rmJMP(int marker, BB * pBB)
|
||||
{
|
||||
marker += (int)DFS_JMP;
|
||||
|
||||
while (pBB->nodeType == ONE_BRANCH && pBB->size() == 1)
|
||||
while (pBB->nodeType == ONE_BRANCH and pBB->size() == 1)
|
||||
{
|
||||
if (pBB->traversed != marker)
|
||||
{
|
||||
@ -313,7 +300,7 @@ BB *BB::rmJMP(int marker, BB * pBB)
|
||||
do {
|
||||
pBB = pBB->edges[0].BBptr;
|
||||
pBB->inEdges.pop_back(); // was --numInedges
|
||||
if (! pBB->inEdges.empty())
|
||||
if (not pBB->inEdges.empty())
|
||||
{
|
||||
pBB->front().ll()->setFlags(NO_CODE);
|
||||
pBB->front().invalidate();
|
||||
@ -335,13 +322,11 @@ BB *BB::rmJMP(int marker, BB * pBB)
|
||||
void BB::mergeFallThrough( CIcodeRec &Icode)
|
||||
{
|
||||
BB * pChild;
|
||||
int i;
|
||||
|
||||
if (!this)
|
||||
if (nullptr==this)
|
||||
{
|
||||
printf("mergeFallThrough on empty BB!\n");
|
||||
}
|
||||
while (nodeType == FALL_NODE || nodeType == ONE_BRANCH)
|
||||
while (nodeType == FALL_NODE or nodeType == ONE_BRANCH)
|
||||
{
|
||||
pChild = edges[0].BBptr;
|
||||
/* Jump to next instruction can always be removed */
|
||||
@ -375,9 +360,11 @@ void BB::mergeFallThrough( CIcodeRec &Icode)
|
||||
traversed = DFS_MERGE;
|
||||
|
||||
/* Process all out edges recursively */
|
||||
for (i = 0; i < edges.size(); i++)
|
||||
if (edges[i].BBptr->traversed != DFS_MERGE)
|
||||
edges[i].BBptr->mergeFallThrough(Icode);
|
||||
for (auto & elem : edges)
|
||||
{
|
||||
if (elem.BBptr->traversed != DFS_MERGE)
|
||||
elem.BBptr->mergeFallThrough(Icode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -399,7 +386,7 @@ void BB::dfsNumbering(std::vector<BB *> &dfsLast, int *first, int *last)
|
||||
pChild->inEdges[pChild->index++] = this;
|
||||
|
||||
/* Is this the last visit? */
|
||||
if (pChild->index == pChild->inEdges.size())
|
||||
if (pChild->index == int(pChild->inEdges.size()))
|
||||
pChild->index = UN_INIT;
|
||||
|
||||
if (pChild->traversed != DFS_NUM)
|
||||
|
||||
435
src/hlicode.cpp
435
src/hlicode.cpp
@ -4,51 +4,38 @@
|
||||
* Date: September-October 1993
|
||||
* (C) Cristina Cifuentes
|
||||
*/
|
||||
#include "dcc.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QString>
|
||||
|
||||
#include <cassert>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include "dcc.h"
|
||||
using namespace std;
|
||||
#define ICODE_DELTA 25
|
||||
|
||||
/* Masks off bits set by duReg[] */
|
||||
std::bitset<32> maskDuReg[] = { 0x00,
|
||||
0xFEEFFE, 0xFDDFFD, 0xFBB00B, 0xF77007, /* uint16_t regs */
|
||||
0xFFFFEF, 0xFFFFDF, 0xFFFFBF, 0xFFFF7F,
|
||||
0xFFFEFF, 0xFFFDFF, 0xFFFBFF, 0xFFF7FF, /* seg regs */
|
||||
0xFFEFFF, 0xFFDFFF, 0xFFBFFF, 0xFF7FFF, /* uint8_t regs */
|
||||
0xFEFFFF, 0xFDFFFF, 0xFBFFFF, 0xF7FFFF,
|
||||
0xEFFFFF, /* tmp reg */
|
||||
0xFFFFB7, 0xFFFF77, 0xFFFF9F, 0xFFFF5F, /* index regs */
|
||||
0xFFFFBF, 0xFFFF7F, 0xFFFFDF, 0xFFFFF7 };
|
||||
|
||||
static char buf[lineSize]; /* Line buffer for hl icode output */
|
||||
|
||||
|
||||
|
||||
/* Places the new HLI_ASSIGN high-level operand in the high-level icode array */
|
||||
void HLTYPE::setAsgn(COND_EXPR *lhs, COND_EXPR *rhs)
|
||||
void HLTYPE::setAsgn(Expr *lhs, Expr *rhs)
|
||||
{
|
||||
assert(lhs);
|
||||
set(lhs,rhs);
|
||||
|
||||
}
|
||||
void ICODE::checkHlCall()
|
||||
{
|
||||
//assert((ll()->immed.proc.cb != 0)||ll()->immed.proc.proc!=0);
|
||||
//assert((ll()->immed.proc.cb != 0) or ll()->immed.proc.proc!=0);
|
||||
}
|
||||
/* Places the new HLI_CALL high-level operand in the high-level icode array */
|
||||
void ICODE::newCallHl()
|
||||
{
|
||||
type = HIGH_LEVEL;
|
||||
hl()->opcode = HLI_CALL;
|
||||
hl()->call.proc = ll()->src().proc.proc;
|
||||
hl()->call.args = new STKFRAME;
|
||||
type = HIGH_LEVEL_ICODE;
|
||||
hlU()->setCall(ll()->src().proc.proc);
|
||||
|
||||
if (ll()->src().proc.cb != 0)
|
||||
hl()->call.args->cb = ll()->src().proc.cb;
|
||||
hlU()->call.args->cb = ll()->src().proc.cb;
|
||||
else if(hl()->call.proc)
|
||||
hl()->call.args->cb =hl()->call.proc->cbParam;
|
||||
hlU()->call.args->cb = hl()->call.proc->cbParam;
|
||||
else
|
||||
{
|
||||
printf("Function with no cb set, and no valid oper.call.proc , probaby indirect call\n");
|
||||
@ -59,18 +46,18 @@ void ICODE::newCallHl()
|
||||
|
||||
/* Places the new HLI_POP/HLI_PUSH/HLI_RET high-level operand in the high-level icode
|
||||
* array */
|
||||
void ICODE::setUnary(hlIcode op, COND_EXPR *_exp)
|
||||
void ICODE::setUnary(hlIcode op, Expr *_exp)
|
||||
{
|
||||
type = HIGH_LEVEL;
|
||||
hl()->set(op,_exp);
|
||||
type = HIGH_LEVEL_ICODE;
|
||||
hlU()->set(op,_exp);
|
||||
}
|
||||
|
||||
|
||||
/* Places the new HLI_JCOND high-level operand in the high-level icode array */
|
||||
void ICODE::setJCond(COND_EXPR *cexp)
|
||||
void ICODE::setJCond(Expr *cexp)
|
||||
{
|
||||
type = HIGH_LEVEL;
|
||||
hl()->set(HLI_JCOND,cexp);
|
||||
type = HIGH_LEVEL_ICODE;
|
||||
hlU()->set(HLI_JCOND,cexp);
|
||||
}
|
||||
|
||||
|
||||
@ -90,13 +77,13 @@ bool ICODE::removeDefRegi (eReg regi, int thisDefIdx, LOCAL_ID *locId)
|
||||
{
|
||||
int numDefs;
|
||||
|
||||
numDefs = du1.numRegsDef;
|
||||
numDefs = du1.getNumRegsDef();
|
||||
if (numDefs == thisDefIdx)
|
||||
{
|
||||
for ( ; numDefs > 0; numDefs--)
|
||||
{
|
||||
|
||||
if (du1.used(numDefs-1)||(du.lastDefRegi[regi]))
|
||||
if (du1.used(numDefs-1) or (du.lastDefRegi.testReg(regi)))
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -106,11 +93,12 @@ bool ICODE::removeDefRegi (eReg regi, int thisDefIdx, LOCAL_ID *locId)
|
||||
invalidate();
|
||||
return true;
|
||||
}
|
||||
HlTypeSupport *p=hl()->get();
|
||||
HlTypeSupport *p=hlU()->get();
|
||||
if(p and p->removeRegFromLong(regi,locId))
|
||||
{
|
||||
du1.numRegsDef--;
|
||||
du.def &= maskDuReg[regi];
|
||||
du1.removeDef(regi); //du1.numRegsDef--;
|
||||
//du.def &= maskDuReg[regi];
|
||||
du.def.clrReg(regi);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -158,7 +146,7 @@ HLTYPE LLInst::toHighLevel(COND_EXPR *lhs,COND_EXPR *rhs,Function *func)
|
||||
break;
|
||||
|
||||
case iDEC:
|
||||
rhs = COND_EXPR::idKte (1, 2);
|
||||
rhs = AstIdent::idKte (1, 2);
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, SUB);
|
||||
res.setAsgn(lhs, rhs);
|
||||
break;
|
||||
@ -168,12 +156,12 @@ HLTYPE LLInst::toHighLevel(COND_EXPR *lhs,COND_EXPR *rhs,Function *func)
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, DIV);
|
||||
if ( ll->testFlags(B) )
|
||||
{
|
||||
lhs = COND_EXPR::idReg (rAL, 0, &localId);
|
||||
lhs = AstIdent::idReg (rAL, 0, &localId);
|
||||
pIcode->setRegDU( rAL, eDEF);
|
||||
}
|
||||
else
|
||||
{
|
||||
lhs = COND_EXPR::idReg (rAX, 0, &localId);
|
||||
lhs = AstIdent::idReg (rAX, 0, &localId);
|
||||
pIcode->setRegDU( rAX, eDEF);
|
||||
}
|
||||
res.setAsgn(lhs, rhs);
|
||||
@ -181,12 +169,12 @@ HLTYPE LLInst::toHighLevel(COND_EXPR *lhs,COND_EXPR *rhs,Function *func)
|
||||
|
||||
case iIMUL:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, MUL);
|
||||
lhs = COND_EXPR::id (*pIcode, LHS_OP, func, i, *pIcode, NONE);
|
||||
lhs = AstIdent::id (*pIcode, LHS_OP, func, i, *pIcode, NONE);
|
||||
res.setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iINC:
|
||||
rhs = COND_EXPR::idKte (1, 2);
|
||||
rhs = AstIdent::idKte (1, 2);
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, ADD);
|
||||
res.setAsgn(lhs, rhs);
|
||||
break;
|
||||
@ -200,12 +188,12 @@ HLTYPE LLInst::toHighLevel(COND_EXPR *lhs,COND_EXPR *rhs,Function *func)
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, MOD);
|
||||
if ( ll->testFlags(B) )
|
||||
{
|
||||
lhs = COND_EXPR::idReg (rAH, 0, &localId);
|
||||
lhs = AstIdent::idReg (rAH, 0, &localId);
|
||||
pIcode->setRegDU( rAH, eDEF);
|
||||
}
|
||||
else
|
||||
{
|
||||
lhs = COND_EXPR::idReg (rDX, 0, &localId);
|
||||
lhs = AstIdent::idReg (rDX, 0, &localId);
|
||||
pIcode->setRegDU( rDX, eDEF);
|
||||
}
|
||||
res.setAsgn(lhs, rhs);
|
||||
@ -216,7 +204,7 @@ HLTYPE LLInst::toHighLevel(COND_EXPR *lhs,COND_EXPR *rhs,Function *func)
|
||||
|
||||
case iMUL:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, MUL);
|
||||
lhs = COND_EXPR::id (*pIcode, LHS_OP, this, i, *pIcode, NONE);
|
||||
lhs = AstIdent::id (*pIcode, LHS_OP, this, i, *pIcode, NONE);
|
||||
res.setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
@ -277,147 +265,184 @@ HLTYPE LLInst::toHighLevel(COND_EXPR *lhs,COND_EXPR *rhs,Function *func)
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
static bool needsLhs(unsigned opc)
|
||||
{
|
||||
switch (opc)
|
||||
{
|
||||
case iCALL:
|
||||
case iCALLF:
|
||||
case iRET:
|
||||
case iRETF:
|
||||
default: return false;
|
||||
case iADD:
|
||||
case iAND:
|
||||
case iDEC:
|
||||
case iDIV:
|
||||
case iIDIV:/* should be signed div */
|
||||
case iIMUL:
|
||||
case iINC:
|
||||
case iLEA:
|
||||
case iMOD:
|
||||
case iMOV:
|
||||
case iMUL:
|
||||
case iNEG:
|
||||
case iNOT:
|
||||
case iOR:
|
||||
case iPOP:
|
||||
case iPUSH:
|
||||
case iSHL:
|
||||
case iSAR: /* signed */
|
||||
case iSHR:
|
||||
case iSIGNEX:
|
||||
case iSUB:
|
||||
case iXCHG:
|
||||
case iXOR:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/* Translates LOW_LEVEL icodes to HIGH_LEVEL icodes - 1st stage.
|
||||
* Note: this process should be done before data flow analysis, which
|
||||
* refines the HIGH_LEVEL icodes. */
|
||||
void Function::highLevelGen()
|
||||
{
|
||||
int numIcode; /* number of icode instructions */
|
||||
iICODE pIcode; /* ptr to current icode node */
|
||||
COND_EXPR *lhs, *rhs; /* left- and right-hand side of expression */
|
||||
size_t numIcode; /* number of icode instructions */
|
||||
iICODE pIcode; /* ptr to current icode node */
|
||||
Expr *rhs; /* left- and right-hand side of expression */
|
||||
uint32_t _flg; /* icode flags */
|
||||
numIcode = Icode.size();
|
||||
for (iICODE i = Icode.begin(); i!=Icode.end() ; ++i)
|
||||
{
|
||||
Expr *lhs=nullptr;
|
||||
assert(numIcode==Icode.size());
|
||||
pIcode = i; //Icode.GetIcode(i)
|
||||
LLInst *ll = pIcode->ll();
|
||||
LLOperand *dst_ll = ll->get(DST);
|
||||
LLOperand *src_ll = ll->get(SRC);
|
||||
if ( ll->testFlags(NOT_HLL) )
|
||||
pIcode->invalidate();
|
||||
if ((pIcode->type != LOW_LEVEL) or not pIcode->valid() )
|
||||
if ((pIcode->type != LOW_LEVEL_ICODE) or not pIcode->valid() )
|
||||
continue;
|
||||
_flg = ll->getFlag();
|
||||
if ((_flg & IM_OPS) != IM_OPS) /* not processing IM_OPS yet */
|
||||
if ((_flg & NO_OPS) != NO_OPS) /* if there are opers */
|
||||
if (not ll->testFlags(IM_OPS)) /* not processing IM_OPS yet */
|
||||
if ( not ll->testFlags(NO_OPS) ) /* if there are opers */
|
||||
{
|
||||
if ( not ll->testFlags(NO_SRC) ) /* if there is src op */
|
||||
rhs = COND_EXPR::id (*pIcode->ll(), SRC, this, i, *pIcode, NONE);
|
||||
lhs = COND_EXPR::id (*pIcode->ll(), DST, this, i, *pIcode, NONE);
|
||||
rhs = AstIdent::id (*pIcode->ll(), SRC, this, i, *pIcode, NONE);
|
||||
if(ll->m_dst.isSet() or (ll->getOpcode()==iMOD))
|
||||
lhs = AstIdent::id (*pIcode->ll(), DST, this, i, *pIcode, NONE);
|
||||
}
|
||||
if(ll->getOpcode()==iPUSH) {
|
||||
if(ll->testFlags(I)) {
|
||||
lhs = new Constant(src_ll->opz,src_ll->byteWidth());
|
||||
}
|
||||
// lhs = AstIdent::id (*pIcode->ll(), DST, this, i, *pIcode, NONE);
|
||||
}
|
||||
if(needsLhs(ll->getOpcode()))
|
||||
assert(lhs!=nullptr);
|
||||
switch (ll->getOpcode())
|
||||
{
|
||||
case iADD:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, ADD);
|
||||
rhs = new BinaryOperator(ADD,lhs, rhs);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iAND:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, AND);
|
||||
rhs = BinaryOperator::And(lhs, rhs);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iCALL:
|
||||
case iCALLF:
|
||||
pIcode->type = HIGH_LEVEL;
|
||||
pIcode->type = HIGH_LEVEL_ICODE;
|
||||
pIcode->hl( ll->createCall() );
|
||||
break;
|
||||
|
||||
case iDEC:
|
||||
rhs = COND_EXPR::idKte (1, 2);
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, SUB);
|
||||
rhs = new BinaryOperator(SUB,lhs, new Constant(1, 2));
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iDIV:
|
||||
case iIDIV:/* should be signed div */
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, DIV);
|
||||
if ( ll->testFlags(B) )
|
||||
{
|
||||
lhs = COND_EXPR::idReg (rAL, 0, &localId);
|
||||
pIcode->setRegDU( rAL, eDEF);
|
||||
}
|
||||
else
|
||||
{
|
||||
lhs = COND_EXPR::idReg (rAX, 0, &localId);
|
||||
pIcode->setRegDU( rAX, eDEF);
|
||||
}
|
||||
{
|
||||
eReg v = ( dst_ll->byteWidth()==1) ? rAL:rAX;
|
||||
rhs = new BinaryOperator(DIV,lhs, rhs);
|
||||
lhs = new RegisterNode(LLOperand(v, dst_ll->byteWidth()), &localId);
|
||||
pIcode->setRegDU( v, eDEF);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
}
|
||||
break;
|
||||
|
||||
case iIMUL:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, MUL);
|
||||
lhs = COND_EXPR::id (*ll, LHS_OP, this, i, *pIcode, NONE);
|
||||
rhs = new BinaryOperator(MUL,lhs, rhs);
|
||||
lhs = AstIdent::id (*ll, LHS_OP, this, i, *pIcode, NONE);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iINC:
|
||||
rhs = COND_EXPR::idKte (1, 2);
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, ADD);
|
||||
rhs = new BinaryOperator(ADD,lhs, new Constant(1, 2));
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iLEA:
|
||||
rhs = COND_EXPR::unary (ADDRESSOF, rhs);
|
||||
rhs =UnaryOperator::Create(ADDRESSOF, rhs);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iMOD:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, MOD);
|
||||
if ( ll->testFlags(B) )
|
||||
{
|
||||
lhs = COND_EXPR::idReg (rAH, 0, &localId);
|
||||
pIcode->setRegDU( rAH, eDEF);
|
||||
}
|
||||
else
|
||||
{
|
||||
lhs = COND_EXPR::idReg (rDX, 0, &localId);
|
||||
pIcode->setRegDU( rDX, eDEF);
|
||||
}
|
||||
{
|
||||
rhs = new BinaryOperator(MOD,lhs, rhs);
|
||||
eReg lhs_reg = (dst_ll->byteWidth()==1) ? rAH : rDX;
|
||||
lhs = new RegisterNode(LLOperand(lhs_reg, dst_ll->byteWidth()), &localId);
|
||||
pIcode->setRegDU( lhs_reg, eDEF);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
}
|
||||
break;
|
||||
|
||||
case iMOV: pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iMUL:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, MUL);
|
||||
lhs = COND_EXPR::id (*ll, LHS_OP, this, i, *pIcode, NONE);
|
||||
rhs = new BinaryOperator(MUL,lhs, rhs);
|
||||
lhs = AstIdent::id (*ll, LHS_OP, this, i, *pIcode, NONE);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iNEG:
|
||||
rhs = COND_EXPR::unary (NEGATION, lhs);
|
||||
rhs = UnaryOperator::Create(NEGATION, lhs);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iNOT:
|
||||
rhs = COND_EXPR::boolOp (NULL, rhs, NOT);
|
||||
rhs = new BinaryOperator(NOT,nullptr, rhs); // TODO: change this to unary NOT ?
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iOR:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, OR);
|
||||
rhs = new BinaryOperator(OR,lhs, rhs);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iPOP: pIcode->setUnary(HLI_POP, lhs);
|
||||
case iPOP:
|
||||
pIcode->setUnary(HLI_POP, lhs);
|
||||
break;
|
||||
|
||||
case iPUSH: pIcode->setUnary(HLI_PUSH, lhs);
|
||||
case iPUSH:
|
||||
pIcode->setUnary(HLI_PUSH, lhs);
|
||||
break;
|
||||
|
||||
case iRET:
|
||||
case iRETF: pIcode->setUnary(HLI_RET, NULL);
|
||||
case iRETF: pIcode->setUnary(HLI_RET, nullptr);
|
||||
break;
|
||||
|
||||
case iSHL:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, SHL);
|
||||
rhs = new BinaryOperator(SHL,lhs, rhs);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iSAR: /* signed */
|
||||
case iSHR:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, SHR); /* unsigned*/
|
||||
rhs = new BinaryOperator(SHR,lhs, rhs); /* unsigned*/
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
@ -425,7 +450,7 @@ void Function::highLevelGen()
|
||||
break;
|
||||
|
||||
case iSUB:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, SUB);
|
||||
rhs = new BinaryOperator(SUB,lhs, rhs);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
@ -433,7 +458,7 @@ void Function::highLevelGen()
|
||||
break;
|
||||
|
||||
case iXOR:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, XOR);
|
||||
rhs = new BinaryOperator(XOR,lhs, rhs);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
}
|
||||
@ -442,151 +467,125 @@ void Function::highLevelGen()
|
||||
}
|
||||
|
||||
|
||||
/* Modifies the given conditional operator to its inverse. This is used
|
||||
* in if..then[..else] statements, to reflect the condition that takes the
|
||||
* then part. */
|
||||
COND_EXPR *COND_EXPR::inverse () const
|
||||
{
|
||||
static condOp invCondOp[] = {GREATER, GREATER_EQUAL, NOT_EQUAL, EQUAL,
|
||||
LESS_EQUAL, LESS, DUMMY,DUMMY,DUMMY,DUMMY,
|
||||
DUMMY, DUMMY, DUMMY, DUMMY, DUMMY, DUMMY,
|
||||
DUMMY, DBL_OR, DBL_AND};
|
||||
COND_EXPR *res=0;
|
||||
if (m_type == BOOLEAN_OP)
|
||||
{
|
||||
switch ( op() )
|
||||
{
|
||||
case LESS_EQUAL: case LESS: case EQUAL:
|
||||
case NOT_EQUAL: case GREATER: case GREATER_EQUAL:
|
||||
res = this->clone();
|
||||
res->boolExpr.op = invCondOp[op()];
|
||||
return res;
|
||||
/**
|
||||
\fn COND_EXPR::inverse
|
||||
Modifies the given conditional operator to its inverse. This is used
|
||||
in if..then[..else] statements, to reflect the condition that takes the
|
||||
then part.
|
||||
*/
|
||||
|
||||
case AND: case OR: case XOR: case NOT: case ADD:
|
||||
case SUB: case MUL: case DIV: case SHR: case SHL: case MOD:
|
||||
return COND_EXPR::unary (NEGATION, this->clone());
|
||||
|
||||
case DBL_AND: case DBL_OR:
|
||||
// Binary::Create(invertop,lhs->inverse(),rhs->inverse());
|
||||
res = this->clone();
|
||||
res->boolExpr.op = invCondOp[op()];
|
||||
res->boolExpr.lhs=lhs()->inverse ();
|
||||
res->boolExpr.rhs=rhs()->inverse ();
|
||||
return res;
|
||||
} /* eos */
|
||||
|
||||
}
|
||||
else if (m_type == NEGATION) //TODO: memleak here
|
||||
{
|
||||
return expr.unaryExp->clone();
|
||||
}
|
||||
return this->clone();
|
||||
/* other types are left unmodified */
|
||||
}
|
||||
|
||||
/* Returns the string that represents the procedure call of tproc (ie. with
|
||||
* actual parameters) */
|
||||
std::string writeCall (Function * tproc, STKFRAME & args, Function * pproc, int *numLoc)
|
||||
QString Function::writeCall (Function * tproc, STKFRAME & args, int *numLoc)
|
||||
{
|
||||
int i; /* counter of # arguments */
|
||||
string condExp;
|
||||
ostringstream ostr;
|
||||
ostr<<tproc->name<<" (";
|
||||
//string condExp;
|
||||
QString ostr;
|
||||
ostr+=tproc->name+" (";
|
||||
for(const STKSYM &sym : args)
|
||||
{
|
||||
ostr << walkCondExpr (sym.actual, pproc, numLoc);
|
||||
if(sym.actual)
|
||||
ostr += sym.actual->walkCondExpr(this, numLoc);
|
||||
else
|
||||
ostr += "";
|
||||
if((&sym)!=&(args.back()))
|
||||
ostr << ", ";
|
||||
ostr += ", ";
|
||||
}
|
||||
ostr << ")";
|
||||
return ostr.str();
|
||||
ostr += ")";
|
||||
return ostr;
|
||||
}
|
||||
|
||||
|
||||
/* Displays the output of a HLI_JCOND icode. */
|
||||
char *writeJcond (const HLTYPE &h, Function * pProc, int *numLoc)
|
||||
QString writeJcond (const HLTYPE &h, Function * pProc, int *numLoc)
|
||||
{
|
||||
if(h.opcode==HLI_INVALID)
|
||||
{
|
||||
return "if (*HLI_INVALID*) {\n";
|
||||
}
|
||||
|
||||
assert(h.expr());
|
||||
memset (buf, ' ', sizeof(buf));
|
||||
buf[0] = '\0';
|
||||
strcat (buf, "if ");
|
||||
COND_EXPR *inverted=h.expr()->inverse();
|
||||
Expr *inverted=h.expr()->inverse();
|
||||
//inverseCondOp (&h.exp);
|
||||
std::string e = walkCondExpr (inverted, pProc, numLoc);
|
||||
QString inverted_form = inverted->walkCondExpr (pProc, numLoc);
|
||||
delete inverted;
|
||||
strcat (buf, e.c_str());
|
||||
strcat (buf, " {\n");
|
||||
return (buf);
|
||||
|
||||
return QString("if %1 {\n").arg(inverted_form);
|
||||
}
|
||||
|
||||
|
||||
/* Displays the inverse output of a HLI_JCOND icode. This is used in the case
|
||||
* when the THEN clause of an if..then..else is empty. The clause is
|
||||
* negated and the ELSE clause is used instead. */
|
||||
char *writeJcondInv (HLTYPE h, Function * pProc, int *numLoc)
|
||||
QString writeJcondInv(HLTYPE h, Function * pProc, int *numLoc)
|
||||
{
|
||||
memset (buf, ' ', sizeof(buf));
|
||||
buf[0] = '\0';
|
||||
strcat (buf, "if ");
|
||||
std::string e = walkCondExpr (h.expr(), pProc, numLoc);
|
||||
strcat (buf, e.c_str());
|
||||
strcat (buf, " {\n");
|
||||
return (buf);
|
||||
QString _form;
|
||||
|
||||
if(h.expr()==nullptr)
|
||||
_form = "( *failed condition recovery* )";
|
||||
else
|
||||
_form = h.expr()->walkCondExpr (pProc, numLoc);
|
||||
return QString("if %1 {\n").arg(_form);
|
||||
}
|
||||
|
||||
string AssignType::writeOut(Function *pProc, int *numLoc)
|
||||
QString AssignType::writeOut(Function *pProc, int *numLoc) const
|
||||
{
|
||||
ostringstream ostr;
|
||||
ostr << walkCondExpr (lhs, pProc, numLoc);
|
||||
ostr << " = ";
|
||||
ostr << walkCondExpr (rhs, pProc, numLoc);
|
||||
ostr << ";\n";
|
||||
return ostr.str();
|
||||
return QString("%1 = %2;\n")
|
||||
.arg(m_lhs->walkCondExpr (pProc, numLoc))
|
||||
.arg(m_rhs->walkCondExpr (pProc, numLoc));
|
||||
}
|
||||
string CallType::writeOut(Function *pProc, int *numLoc)
|
||||
QString CallType::writeOut(Function *pProc, int *numLoc) const
|
||||
{
|
||||
ostringstream ostr;
|
||||
ostr << writeCall (proc, *args, pProc,numLoc);
|
||||
ostr << ";\n";
|
||||
return ostr.str();
|
||||
return pProc->writeCall (proc, *args, numLoc) + ";\n";
|
||||
}
|
||||
string ExpType::writeOut(Function *pProc, int *numLoc)
|
||||
QString ExpType::writeOut(Function *pProc, int *numLoc) const
|
||||
{
|
||||
return walkCondExpr (v, pProc, numLoc);
|
||||
if(v==nullptr)
|
||||
return "";
|
||||
return v->walkCondExpr (pProc, numLoc);
|
||||
}
|
||||
|
||||
void HLTYPE::set(Expr *l, Expr *r)
|
||||
{
|
||||
assert(l);
|
||||
assert(r);
|
||||
opcode = HLI_ASSIGN;
|
||||
//assert((asgn.lhs==0) and (asgn.rhs==0)); //prevent memory leaks
|
||||
assert(dynamic_cast<UnaryOperator *>(l));
|
||||
asgn.m_lhs=l;
|
||||
asgn.m_rhs=r;
|
||||
}
|
||||
/* Returns a string with the contents of the current high-level icode.
|
||||
* Note: this routine does not output the contens of HLI_JCOND icodes. This is
|
||||
* done in a separate routine to be able to support the removal of
|
||||
* empty THEN clauses on an if..then..else. */
|
||||
string HLTYPE::write1HlIcode (Function * pProc, int *numLoc)
|
||||
QString HLTYPE::write1HlIcode (Function * pProc, int *numLoc) const
|
||||
{
|
||||
string e;
|
||||
ostringstream ostr;
|
||||
HlTypeSupport *p = get();
|
||||
const HlTypeSupport *p = get();
|
||||
switch (opcode)
|
||||
{
|
||||
case HLI_ASSIGN:
|
||||
return p->writeOut(pProc,numLoc);
|
||||
case HLI_CALL:
|
||||
return p->writeOut(pProc,numLoc);
|
||||
case HLI_RET:
|
||||
e = p->writeOut(pProc,numLoc);
|
||||
if (! e.empty())
|
||||
ostr << "return (" << e << ");\n";
|
||||
break;
|
||||
case HLI_POP:
|
||||
ostr << "HLI_POP ";
|
||||
ostr << p->writeOut(pProc,numLoc);
|
||||
ostr << "\n";
|
||||
break;
|
||||
case HLI_PUSH:
|
||||
ostr << "HLI_PUSH ";
|
||||
ostr << p->writeOut(pProc,numLoc);
|
||||
ostr << "\n";
|
||||
break;
|
||||
case HLI_ASSIGN:
|
||||
return p->writeOut(pProc,numLoc);
|
||||
case HLI_CALL:
|
||||
return p->writeOut(pProc,numLoc);
|
||||
case HLI_RET:
|
||||
{
|
||||
QString e;
|
||||
e = p->writeOut(pProc,numLoc);
|
||||
if (not e.isEmpty())
|
||||
return QString("return (%1);\n").arg(e);
|
||||
break;
|
||||
}
|
||||
return ostr.str();
|
||||
case HLI_POP:
|
||||
return QString("HLI_POP %1\n").arg(p->writeOut(pProc,numLoc));
|
||||
case HLI_PUSH:
|
||||
return QString("HLI_PUSH %1\n").arg(p->writeOut(pProc,numLoc));
|
||||
case HLI_JCOND: //Handled elsewhere
|
||||
break;
|
||||
default:
|
||||
qCritical() << " HLTYPE::write1HlIcode - Unhandled opcode" << opcode;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
@ -601,30 +600,36 @@ void ICODE::writeDU()
|
||||
{
|
||||
int my_idx = loc_ip;
|
||||
{
|
||||
ostringstream ostr;
|
||||
Machine_X86::writeRegVector(ostr,du.def);
|
||||
if (!ostr.str().empty())
|
||||
printf ("Def (reg) = %s\n", ostr.str().c_str());
|
||||
QString ostr_contents;
|
||||
{
|
||||
QTextStream ostr(&ostr_contents);
|
||||
Machine_X86::writeRegVector(ostr,du.def);
|
||||
}
|
||||
if (not ostr_contents.isEmpty())
|
||||
qDebug() << QString("Def (reg) = %1\n").arg(ostr_contents);
|
||||
}
|
||||
{
|
||||
ostringstream ostr;
|
||||
Machine_X86::writeRegVector(ostr,du.use);
|
||||
if (!ostr.str().empty())
|
||||
printf ("Use (reg) = %s\n", ostr.str().c_str());
|
||||
QString ostr_contents;
|
||||
{
|
||||
QTextStream ostr(&ostr_contents);
|
||||
Machine_X86::writeRegVector(ostr,du.use);
|
||||
}
|
||||
if (not ostr_contents.isEmpty())
|
||||
qDebug() << QString("Use (reg) = %1\n").arg(ostr_contents);
|
||||
}
|
||||
|
||||
/* Print du1 chain */
|
||||
printf ("# regs defined = %d\n", du1.numRegsDef);
|
||||
printf ("# regs defined = %d\n", du1.getNumRegsDef());
|
||||
for (int i = 0; i < MAX_REGS_DEF; i++)
|
||||
{
|
||||
if (not du1.used(i))
|
||||
continue;
|
||||
printf ("%d: du1[%d][] = ", my_idx, i);
|
||||
for(auto j : du1.idx[i].uses)
|
||||
{
|
||||
printf ("%d ", j->loc_ip);
|
||||
}
|
||||
printf ("\n");
|
||||
printf ("%d: du1[%d][] = ", my_idx, i);
|
||||
for(auto j : du1.idx[i].uses)
|
||||
{
|
||||
printf ("%d ", j->loc_ip);
|
||||
}
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
/* For HLI_CALL, print # parameter bytes */
|
||||
|
||||
25
src/hltype.cpp
Normal file
25
src/hltype.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
#include "icode.h"
|
||||
#include "ast.h"
|
||||
|
||||
void HLTYPE::replaceExpr(Expr *e)
|
||||
{
|
||||
assert(e);
|
||||
delete exp.v;
|
||||
exp.v=e;
|
||||
}
|
||||
|
||||
|
||||
HlTypeSupport *HLTYPE::get()
|
||||
{
|
||||
switch(opcode)
|
||||
{
|
||||
case HLI_ASSIGN: return &asgn;
|
||||
case HLI_RET:
|
||||
case HLI_POP:
|
||||
case HLI_JCOND:
|
||||
case HLI_PUSH: return &exp;
|
||||
case HLI_CALL: return &call;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@ -1,19 +1,16 @@
|
||||
// Object oriented icode code for dcc
|
||||
// (C) 1997 Mike Van Emmerik
|
||||
#include "icode.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <memory.h>
|
||||
|
||||
#include "msvc_fixes.h"
|
||||
#include "dcc.h"
|
||||
#include "types.h" // Common types like uint8_t, etc
|
||||
#include "ast.h" // Some icode types depend on these
|
||||
#include "icode.h"
|
||||
|
||||
#define ICODE_DELTA 25 // Amount to allocate for new chunk
|
||||
#include <stdlib.h>
|
||||
|
||||
ICODE::TypeFilter<HIGH_LEVEL> ICODE::select_high_level;
|
||||
ICODE::TypeAndValidFilter<HIGH_LEVEL> ICODE::select_valid_high_level;
|
||||
ICODE::TypeFilter<HIGH_LEVEL_ICODE> ICODE::select_high_level;
|
||||
ICODE::TypeAndValidFilter<HIGH_LEVEL_ICODE> ICODE::select_valid_high_level;
|
||||
CIcodeRec::CIcodeRec()
|
||||
{
|
||||
}
|
||||
@ -31,9 +28,7 @@ ICODE * CIcodeRec::addIcode(ICODE *pIcode)
|
||||
void CIcodeRec::SetInBB(rCODE &rang, BB *pnewBB)
|
||||
{
|
||||
for(ICODE &ic : rang)
|
||||
{
|
||||
ic.setParent(pnewBB);
|
||||
}
|
||||
}
|
||||
|
||||
/* labelSrchRepl - Searches the icodes for instruction with label = target, and
|
||||
@ -57,9 +52,9 @@ CIcodeRec::iterator CIcodeRec::labelSrch(uint32_t target)
|
||||
{
|
||||
return find_if(begin(),end(),[target](ICODE &l) -> bool {return l.ll()->label==target;});
|
||||
}
|
||||
ICODE * CIcodeRec::GetIcode(int ip)
|
||||
ICODE * CIcodeRec::GetIcode(size_t ip)
|
||||
{
|
||||
assert(ip>=0 && ip<size());
|
||||
assert(ip<size());
|
||||
iICODE res=begin();
|
||||
advance(res,ip);
|
||||
return &(*res);
|
||||
@ -92,11 +87,28 @@ void LLInst::emitGotoLabel (int indLevel)
|
||||
|
||||
bool LLOperand::isReg() const
|
||||
{
|
||||
return (regi>=rAX) && (regi<=rTMP);
|
||||
return (regi>=rAX) and (regi<=rTMP);
|
||||
}
|
||||
void LLOperand::addProcInformation(int param_count, uint32_t call_conv)
|
||||
void LLOperand::addProcInformation(int param_count, CConv::Type call_conv)
|
||||
{
|
||||
proc.proc->cbParam = (int16_t)param_count;
|
||||
proc.cb = param_count;
|
||||
proc.proc->flg |= call_conv;
|
||||
proc.proc->callingConv(call_conv);
|
||||
}
|
||||
void HLTYPE::setCall(Function *proc)
|
||||
{
|
||||
opcode = HLI_CALL;
|
||||
call.proc = proc;
|
||||
call.args = new STKFRAME;
|
||||
}
|
||||
bool AssignType::removeRegFromLong(eReg regi, LOCAL_ID *locId)
|
||||
{
|
||||
m_lhs=lhs()->performLongRemoval(regi,locId);
|
||||
return true;
|
||||
}
|
||||
void AssignType::lhs(Expr *l)
|
||||
{
|
||||
assert(dynamic_cast<UnaryOperator *>(l));
|
||||
m_lhs=l;
|
||||
}
|
||||
|
||||
|
||||
@ -3,8 +3,12 @@
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
|
||||
#include <cstring>
|
||||
#include <deque>
|
||||
//#include <llvm/Config/llvm-config.h>
|
||||
//#if( (LLVM_VERSION_MAJOR==3 ) and (LLVM_VERSION_MINOR>3) )
|
||||
//#include <llvm/IR/PatternMatch.h>
|
||||
//#else
|
||||
//#include <llvm/Support/PatternMatch.h>
|
||||
//#endif
|
||||
#include "idiom.h"
|
||||
#include "idiom1.h"
|
||||
#include "epilogue_idioms.h"
|
||||
@ -15,8 +19,11 @@
|
||||
#include "shift_idioms.h"
|
||||
#include "arith_idioms.h"
|
||||
#include "dcc.h"
|
||||
#include <llvm/Support/PatternMatch.h>
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
#include <boost/iterator/filter_iterator.hpp>
|
||||
#include <cstring>
|
||||
#include <deque>
|
||||
/*****************************************************************************
|
||||
* JmpInst - Returns true if opcode is a conditional or unconditional jump
|
||||
****************************************************************************/
|
||||
@ -116,13 +123,13 @@ void Function::findIdioms()
|
||||
case iCALL: case iCALLF:
|
||||
/* Check for library functions that return a long register.
|
||||
* Propagate this result */
|
||||
if (pIcode->ll()->src().proc.proc != 0)
|
||||
if ((pIcode->ll()->src().proc.proc->flg & PROC_ISLIB) &&
|
||||
if (pIcode->ll()->src().proc.proc != nullptr)
|
||||
if ((pIcode->ll()->src().proc.proc->flg & PROC_ISLIB) and
|
||||
(pIcode->ll()->src().proc.proc->flg & PROC_IS_FUNC))
|
||||
{
|
||||
if ((pIcode->ll()->src().proc.proc->retVal.type==TYPE_LONG_SIGN)
|
||||
|| (pIcode->ll()->src().proc.proc->retVal.type == TYPE_LONG_UNSIGN))
|
||||
localId.newLongReg(TYPE_LONG_SIGN, rDX, rAX, pIcode/*ip*/);
|
||||
or (pIcode->ll()->src().proc.proc->retVal.type == TYPE_LONG_UNSIGN))
|
||||
localId.newLongReg(TYPE_LONG_SIGN, LONGID_TYPE(rDX,rAX), pIcode/*ip*/);
|
||||
}
|
||||
|
||||
/* Check for idioms */
|
||||
@ -204,14 +211,14 @@ void Function::findIdioms()
|
||||
}
|
||||
|
||||
/* Check if number of parameter bytes match their calling convention */
|
||||
if ((flg & PROC_HLL) && (!args.empty()))
|
||||
if ((flg & PROC_HLL) and (not args.empty()))
|
||||
{
|
||||
args.m_minOff += (flg & PROC_FAR ? 4 : 2);
|
||||
args.m_minOff += ((flg & PROC_FAR)!=0 ? 4 : 2);
|
||||
delta = args.maxOff - args.m_minOff;
|
||||
if (cbParam != delta)
|
||||
{
|
||||
cbParam = delta;
|
||||
flg |= (CALL_MASK & CALL_UNKNOWN);
|
||||
callingConv(CConv::eUnknown);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -231,7 +238,7 @@ void Function::bindIcodeOff()
|
||||
for(ICODE &c : Icode) // TODO: use filtered here
|
||||
{
|
||||
LLInst *ll=c.ll();
|
||||
if (ll->testFlags(I) && ll->isJmpInst())
|
||||
if (ll->testFlags(I) and ll->isJmpInst())
|
||||
{
|
||||
iICODE loc=Icode.labelSrch(ll->src().getImm2());
|
||||
if (loc!=Icode.end())
|
||||
@ -251,7 +258,7 @@ void Function::bindIcodeOff()
|
||||
if (ll->testFlags(I) )
|
||||
{
|
||||
uint32_t found;
|
||||
if (! Icode.labelSrch(ll->src().getImm2(), found))
|
||||
if (not Icode.labelSrch(ll->src().getImm2(), found))
|
||||
ll->setFlags( NO_LABEL );
|
||||
else
|
||||
ll->replaceSrc(LLOperand::CreateImm2(found));
|
||||
|
||||
@ -1,5 +1,10 @@
|
||||
#include "dcc.h"
|
||||
#include "arith_idioms.h"
|
||||
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*****************************************************************************
|
||||
@ -25,10 +30,11 @@ bool Idiom5::match(iICODE pIcode)
|
||||
|
||||
int Idiom5::action()
|
||||
{
|
||||
COND_EXPR *rhs,*lhs,*expr;
|
||||
lhs = COND_EXPR::idLong (&m_func->localId, DST, m_icodes[0], LOW_FIRST, m_icodes[0], USE_DEF, *m_icodes[1]->ll());
|
||||
rhs = COND_EXPR::idLong (&m_func->localId, SRC, m_icodes[0], LOW_FIRST, m_icodes[0], eUSE, *m_icodes[1]->ll());
|
||||
expr = COND_EXPR::boolOp (lhs, rhs, ADD);
|
||||
AstIdent *rhs,*lhs;
|
||||
Expr *expr;
|
||||
lhs = AstIdent::Long (&m_func->localId, DST, m_icodes[0], LOW_FIRST, m_icodes[0], USE_DEF, *m_icodes[1]->ll());
|
||||
rhs = AstIdent::Long (&m_func->localId, SRC, m_icodes[0], LOW_FIRST, m_icodes[0], eUSE, *m_icodes[1]->ll());
|
||||
expr = new BinaryOperator(ADD,lhs, rhs);
|
||||
m_icodes[0]->setAsgn(lhs, expr);
|
||||
m_icodes[1]->invalidate();
|
||||
return 2;
|
||||
@ -58,10 +64,12 @@ bool Idiom6::match(iICODE pIcode)
|
||||
|
||||
int Idiom6::action()
|
||||
{
|
||||
COND_EXPR *rhs,*lhs,*expr;
|
||||
lhs = COND_EXPR::idLong (&m_func->localId, DST, m_icodes[0], LOW_FIRST, m_icodes[0], USE_DEF, *m_icodes[1]->ll());
|
||||
rhs = COND_EXPR::idLong (&m_func->localId, SRC, m_icodes[0], LOW_FIRST, m_icodes[0], eUSE, *m_icodes[1]->ll());
|
||||
expr = COND_EXPR::boolOp (lhs, rhs, SUB);
|
||||
|
||||
AstIdent *rhs,*lhs;
|
||||
Expr *expr;
|
||||
lhs = AstIdent::Long (&m_func->localId, DST, m_icodes[0], LOW_FIRST, m_icodes[0], USE_DEF, *m_icodes[1]->ll());
|
||||
rhs = AstIdent::Long (&m_func->localId, SRC, m_icodes[0], LOW_FIRST, m_icodes[0], eUSE, *m_icodes[1]->ll());
|
||||
expr = new BinaryOperator(SUB,lhs, rhs);
|
||||
m_icodes[0]->setAsgn(lhs, expr);
|
||||
m_icodes[1]->invalidate();
|
||||
return 2;
|
||||
@ -95,77 +103,80 @@ bool Idiom18::match(iICODE picode)
|
||||
for(int i=0; i<4; ++i)
|
||||
m_icodes[i] =picode++;
|
||||
|
||||
m_idiom_type=-1;
|
||||
m_is_dec = m_icodes[1]->ll()->match(iDEC);
|
||||
int type = -1; /* type of variable: 1 = reg-var, 2 = local */
|
||||
uint8_t regi; /* register of the MOV */
|
||||
|
||||
uint8_t regi; /* register of the MOV */
|
||||
if(not m_icodes[0]->ll()->matchWithRegDst(iMOV) )
|
||||
return false;
|
||||
regi = m_icodes[0]->ll()->m_dst.regi;
|
||||
if( not ( m_icodes[2]->ll()->match(iCMP,regi) and
|
||||
m_icodes[3]->ll()->conditionalJump() ) )
|
||||
return false;
|
||||
// Simple matching finished, select apropriate matcher based on dst type
|
||||
/* Get variable */
|
||||
if (m_icodes[1]->ll()->dst.regi == 0) /* global variable */
|
||||
if (m_icodes[1]->ll()->m_dst.regi == 0) /* global variable */
|
||||
{
|
||||
/* not supported yet */
|
||||
type = 0;
|
||||
m_idiom_type = 0;
|
||||
}
|
||||
else if ( m_icodes[1]->ll()->dst.isReg() ) /* register */
|
||||
else if ( m_icodes[1]->ll()->m_dst.isReg() ) /* register */
|
||||
{
|
||||
if ((m_icodes[1]->ll()->dst.regi == rSI) && (m_func->flg & SI_REGVAR))
|
||||
type = 1;
|
||||
else if ((m_icodes[1]->ll()->dst.regi == rDI) && (m_func->flg & DI_REGVAR))
|
||||
type = 1;
|
||||
m_idiom_type = 1;
|
||||
// if ((m_icodes[1]->ll()->dst.regi == rSI) and (m_func->flg & SI_REGVAR))
|
||||
// m_idiom_type = 1;
|
||||
// else if ((m_icodes[1]->ll()->dst.regi == rDI) and (m_func->flg & DI_REGVAR))
|
||||
// m_idiom_type = 1;
|
||||
}
|
||||
else if (m_icodes[1]->ll()->dst.off) /* local variable */
|
||||
type = 2;
|
||||
else if (m_icodes[1]->ll()->m_dst.off) /* local variable */
|
||||
m_idiom_type = 2;
|
||||
else /* indexed */
|
||||
{
|
||||
type=3;
|
||||
m_idiom_type=3;
|
||||
/* not supported yet */
|
||||
printf("Unsupported idiom18 type: indexed");
|
||||
ICODE &ic(*picode);
|
||||
const Function *my_proc(ic.getParent()->getParent());
|
||||
qWarning() << "Unsupported idiom18 type at"<< QString::number(ic.loc_ip,16)
|
||||
<< "in"<< my_proc->name <<':'<< QString::number(my_proc->procEntry,16) << "- indexed";
|
||||
}
|
||||
|
||||
switch(type)
|
||||
switch(m_idiom_type)
|
||||
{
|
||||
case 0: // global
|
||||
printf("Unsupported idiom18 type: global variable");
|
||||
break;
|
||||
case 1: /* register variable */
|
||||
/* Check previous instruction for a MOV */
|
||||
if (m_icodes[0]->ll()->match(iMOV) && (m_icodes[0]->ll()->src().regi == m_icodes[1]->ll()->dst.regi))
|
||||
{
|
||||
regi = m_icodes[0]->ll()->dst.regi;
|
||||
if ( m_icodes[0]->ll()->dst.isReg() )
|
||||
case 0: // global
|
||||
printf("Unsupported idiom18 type at %x : global variable\n",picode->loc_ip);
|
||||
break;
|
||||
case 1: /* register variable */
|
||||
/* Check previous instruction for a MOV */
|
||||
if ( m_icodes[0]->ll()->src().regi == m_icodes[1]->ll()->m_dst.regi)
|
||||
{
|
||||
if ( m_icodes[2]->ll()->match(iCMP) && (m_icodes[2]->ll()->dst.regi == regi) &&
|
||||
m_icodes[3]->ll()->conditionalJump() )
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2: /* local */
|
||||
if (m_icodes[0]->ll()->match(iMOV) && (m_icodes[0]->ll()->src().off == m_icodes[1]->ll()->dst.off))
|
||||
{
|
||||
regi = m_icodes[0]->ll()->dst.regi;
|
||||
if ( m_icodes[0]->ll()->dst.isReg() )
|
||||
break;
|
||||
case 2: /* local */
|
||||
if (m_icodes[0]->ll()->src().off == m_icodes[1]->ll()->m_dst.off)
|
||||
{
|
||||
if ( m_icodes[2]->ll()->match(iCMP) && (m_icodes[2]->ll()->dst.regi == regi) &&
|
||||
m_icodes[3]->ll()->conditionalJump() )
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3: // indexed
|
||||
printf("Unsupported idiom18 type: indexed");
|
||||
break;
|
||||
break;
|
||||
case 3: // indexed
|
||||
printf("Untested idiom18 type: indexed\n");
|
||||
if ((m_icodes[0]->ll()->src() == m_icodes[1]->ll()->m_dst))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int Idiom18::action() // action length
|
||||
{
|
||||
COND_EXPR *rhs, *lhs; /* Pointers to left and right hand side exps */
|
||||
COND_EXPR *expr;
|
||||
lhs = COND_EXPR::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[1], *m_icodes[1], eUSE);
|
||||
lhs = COND_EXPR::unary ( m_is_dec ? POST_DEC : POST_INC, lhs);
|
||||
rhs = COND_EXPR::id (*m_icodes[2]->ll(), SRC, m_func, m_icodes[1], *m_icodes[3], eUSE);
|
||||
expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[3]->ll()->getOpcode() - iJB]);
|
||||
Expr *rhs,*lhs;/* Pointers to left and right hand side exps */
|
||||
Expr *expr;
|
||||
lhs = AstIdent::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[1], *m_icodes[1], eUSE);
|
||||
lhs = UnaryOperator::Create(m_is_dec ? POST_DEC : POST_INC, lhs);
|
||||
rhs = AstIdent::id (*m_icodes[2]->ll(), SRC, m_func, m_icodes[1], *m_icodes[3], eUSE);
|
||||
expr = new BinaryOperator(condOpJCond[m_icodes[3]->ll()->getOpcode() - iJB],lhs, rhs);
|
||||
m_icodes[3]->setJCond(expr);
|
||||
|
||||
m_icodes[0]->invalidate();
|
||||
@ -188,35 +199,41 @@ bool Idiom19::match(iICODE picode)
|
||||
{
|
||||
if(std::distance(picode,m_end)<2)
|
||||
return false;
|
||||
|
||||
ICODE &ic(*picode);
|
||||
int type;
|
||||
for(int i=0; i<2; ++i)
|
||||
m_icodes[i] =picode++;
|
||||
m_is_dec = m_icodes[0]->ll()->match(iDEC);
|
||||
if (m_icodes[0]->ll()->dst.regi == 0) /* global variable */
|
||||
if ( not m_icodes[1]->ll()->conditionalJump() )
|
||||
return false;
|
||||
if (m_icodes[0]->ll()->m_dst.regi == 0) /* global variable */
|
||||
/* not supported yet */ ;
|
||||
else if ( m_icodes[0]->ll()->dst.isReg() ) /* register */
|
||||
else if ( m_icodes[0]->ll()->m_dst.isReg() ) /* register */
|
||||
{
|
||||
// if (((picode->ll()->dst.regi == rSI) && (pproc->flg & SI_REGVAR)) ||
|
||||
// ((picode->ll()->dst.regi == rDI) && (pproc->flg & DI_REGVAR)))
|
||||
if (m_icodes[1]->ll()->conditionalJump())
|
||||
return true;
|
||||
// if (((picode->ll()->dst.regi == rSI) and (pproc->flg & SI_REGVAR)) or
|
||||
// ((picode->ll()->dst.regi == rDI) and (pproc->flg & DI_REGVAR)))
|
||||
return true;
|
||||
}
|
||||
else if (m_icodes[0]->ll()->dst.off) /* stack variable */
|
||||
else if (m_icodes[0]->ll()->m_dst.off) /* stack variable */
|
||||
{
|
||||
if ( m_icodes[1]->ll()->conditionalJump() )
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
else /* indexed */
|
||||
/* not supported yet */ ;
|
||||
{
|
||||
fprintf(stderr,"idiom19 : Untested type [indexed]\n");
|
||||
return true;
|
||||
|
||||
/* not supported yet */
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int Idiom19::action()
|
||||
{
|
||||
COND_EXPR *lhs,*rhs,*expr;
|
||||
lhs = COND_EXPR::id (*m_icodes[1]->ll(), DST, m_func, m_icodes[0], *m_icodes[1], eUSE);
|
||||
lhs = COND_EXPR::unary (m_is_dec ? PRE_DEC : PRE_INC, lhs);
|
||||
rhs = COND_EXPR::idKte (0, 2);
|
||||
expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[1]->ll()->getOpcode() - iJB]);
|
||||
Expr *lhs,*expr;
|
||||
|
||||
lhs = AstIdent::id (*m_icodes[0]->ll(), DST, m_func, m_icodes[0], *m_icodes[1], eUSE);
|
||||
lhs = UnaryOperator::Create(m_is_dec ? PRE_DEC : PRE_INC, lhs);
|
||||
expr = new BinaryOperator(condOpJCond[m_icodes[1]->ll()->getOpcode() - iJB],lhs, new Constant(0, 2));
|
||||
m_icodes[1]->setJCond(expr);
|
||||
m_icodes[0]->invalidate();
|
||||
return 2;
|
||||
@ -245,10 +262,13 @@ bool Idiom20::match(iICODE picode)
|
||||
return false;
|
||||
for(int i=0; i<4; ++i)
|
||||
m_icodes[i] =picode++;
|
||||
/* Check second instruction for a MOV */
|
||||
if( not m_icodes[1]->ll()->matchWithRegDst(iMOV) )
|
||||
return false;
|
||||
|
||||
m_is_dec = m_icodes[0]->ll()->match(iDEC);
|
||||
m_is_dec = m_icodes[0]->ll()->match(iDEC) ? PRE_DEC : PRE_INC;
|
||||
|
||||
LLOperand &ll_dest(m_icodes[0]->ll()->dst);
|
||||
const LLOperand &ll_dest(m_icodes[0]->ll()->m_dst);
|
||||
/* Get variable */
|
||||
if (ll_dest.regi == 0) /* global variable */
|
||||
{
|
||||
@ -256,57 +276,56 @@ bool Idiom20::match(iICODE picode)
|
||||
}
|
||||
else if ( ll_dest.isReg() ) /* register */
|
||||
{
|
||||
if ((ll_dest.regi == rSI) && (m_func->flg & SI_REGVAR))
|
||||
type = 1;
|
||||
else if ((ll_dest.regi == rDI) && (m_func->flg & DI_REGVAR))
|
||||
type = 1;
|
||||
type = 1;
|
||||
// if ((ll_dest.regi == rSI) and (m_func->flg & SI_REGVAR))
|
||||
// type = 1;
|
||||
// else if ((ll_dest.regi == rDI) and (m_func->flg & DI_REGVAR))
|
||||
// type = 1;
|
||||
}
|
||||
else if (ll_dest.off) /* local variable */
|
||||
type = 2;
|
||||
else /* indexed */
|
||||
{
|
||||
printf("idiom20 : Unsupported type [indexed]\n");
|
||||
printf("idiom20 : Untested type [indexed]\n");
|
||||
type = 3;
|
||||
/* not supported yet */ ;
|
||||
}
|
||||
|
||||
/* Check previous instruction for a MOV */
|
||||
if (type == 1) /* register variable */
|
||||
regi = m_icodes[1]->ll()->m_dst.regi;
|
||||
const LLOperand &mov_src(m_icodes[1]->ll()->src());
|
||||
if (m_icodes[2]->ll()->match(iCMP,(eReg)regi) and m_icodes[3]->ll()->conditionalJump())
|
||||
{
|
||||
if (m_icodes[1]->ll()->match(iMOV) &&
|
||||
(m_icodes[1]->ll()->src().regi == ll_dest.regi))
|
||||
switch(type)
|
||||
{
|
||||
regi = m_icodes[1]->ll()->dst.regi;
|
||||
if ( m_icodes[1]->ll()->dst.isReg() )
|
||||
{
|
||||
if (m_icodes[2]->ll()->match(iCMP,(eReg)regi) &&
|
||||
m_icodes[3]->ll()->conditionalJump())
|
||||
case 1: /* register variable */
|
||||
if ((mov_src.regi == ll_dest.regi))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type == 2) /* local */
|
||||
{
|
||||
if ( m_icodes[0]->ll()->match(iMOV) &&
|
||||
(m_icodes[1]->ll()->src().off == ll_dest.off))
|
||||
{
|
||||
regi = m_icodes[1]->ll()->dst.regi;
|
||||
if ( m_icodes[1]->ll()->dst.isReg() )
|
||||
{
|
||||
if (m_icodes[2]->ll()->match(iCMP,(eReg)regi) &&
|
||||
m_icodes[3]->ll()->conditionalJump())
|
||||
}
|
||||
break;
|
||||
case 2: // local
|
||||
if ((mov_src.off == ll_dest.off))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
fprintf(stderr,"Test 3 ");
|
||||
if ((mov_src == ll_dest))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int Idiom20::action()
|
||||
{
|
||||
COND_EXPR *lhs,*rhs,*expr;
|
||||
lhs = COND_EXPR::id (*m_icodes[1]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], eUSE);
|
||||
lhs = COND_EXPR::unary (m_is_dec ? PRE_DEC : PRE_INC, lhs);
|
||||
rhs = COND_EXPR::id (*m_icodes[2]->ll(), SRC, m_func, m_icodes[0], *m_icodes[3], eUSE);
|
||||
expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[3]->ll()->getOpcode() - iJB]);
|
||||
Expr *lhs,*rhs,*expr;
|
||||
lhs = AstIdent::id (*m_icodes[1]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], eUSE);
|
||||
lhs = UnaryOperator::Create(m_is_dec, lhs);
|
||||
rhs = AstIdent::id (*m_icodes[2]->ll(), SRC, m_func, m_icodes[0], *m_icodes[3], eUSE);
|
||||
expr = new BinaryOperator(condOpJCond[m_icodes[3]->ll()->getOpcode() - iJB],lhs, rhs);
|
||||
m_icodes[3]->setJCond(expr);
|
||||
for(int i=0; i<3; ++i)
|
||||
m_icodes[i]->invalidate();
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
#include "dcc.h"
|
||||
#include "call_idioms.h"
|
||||
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
using namespace std;
|
||||
/*****************************************************************************
|
||||
* idiom3 - C calling convention.
|
||||
@ -22,7 +25,7 @@ bool Idiom3::match(iICODE picode)
|
||||
/* Match ADD SP, immed */
|
||||
for(int i=0; i<2; ++i)
|
||||
m_icodes[i] = picode++;
|
||||
if ( m_icodes[1]->ll()->testFlags(I) && m_icodes[1]->ll()->match(iADD,rSP))
|
||||
if ( m_icodes[1]->ll()->testFlags(I) and m_icodes[1]->ll()->match(iADD,rSP))
|
||||
{
|
||||
m_param_count = m_icodes[1]->ll()->src().getImm2();
|
||||
return true;
|
||||
@ -38,7 +41,7 @@ int Idiom3::action()
|
||||
{
|
||||
if (m_icodes[0]->ll()->testFlags(I) )
|
||||
{
|
||||
m_icodes[0]->ll()->src().addProcInformation(m_param_count,CALL_C);
|
||||
m_icodes[0]->ll()->src().addProcInformation(m_param_count,CConv::eCdecl);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -77,13 +80,13 @@ bool Idiom17::match(iICODE picode)
|
||||
if (m_icodes[1]->ll()->match(iPOP))
|
||||
{
|
||||
int i=0;
|
||||
regi = m_icodes[1]->ll()->dst.regi;
|
||||
if ((regi >= rAX) && (regi <= rBX))
|
||||
regi = m_icodes[1]->ll()->m_dst.regi;
|
||||
if ((regi >= rAX) and (regi <= rBX))
|
||||
i++;
|
||||
|
||||
while (picode != m_end && picode->ll()->match(iPOP))
|
||||
while (picode != m_end and picode->ll()->match(iPOP))
|
||||
{
|
||||
if (picode->ll()->dst.regi != regi)
|
||||
if (picode->ll()->m_dst.regi != regi)
|
||||
break;
|
||||
i++;
|
||||
m_icodes.push_back(picode++);
|
||||
@ -96,7 +99,7 @@ int Idiom17::action()
|
||||
{
|
||||
if (m_icodes[0]->ll()->testFlags(I))
|
||||
{
|
||||
m_icodes[0]->ll()->src().addProcInformation(m_param_count,CALL_C);
|
||||
m_icodes[0]->ll()->src().addProcInformation(m_param_count,CConv::eCdecl);
|
||||
for(size_t idx=1; idx<m_icodes.size(); ++idx)
|
||||
{
|
||||
m_icodes[idx]->invalidate();
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
#include "dcc.h"
|
||||
#include "epilogue_idioms.h"
|
||||
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* popStkVars - checks for
|
||||
* [POP DI]
|
||||
@ -14,9 +16,9 @@ void EpilogIdiom::popStkVars(iICODE pIcode)
|
||||
/* Match [POP DI] */
|
||||
if (pIcode->ll()->match(iPOP))
|
||||
{
|
||||
if ((m_func->flg & DI_REGVAR) && pIcode->ll()->match(rDI))
|
||||
if ((m_func->flg & DI_REGVAR) and pIcode->ll()->match(rDI))
|
||||
m_icodes.push_front(pIcode);
|
||||
else if ((m_func->flg & SI_REGVAR) && pIcode->ll()->match(rSI))
|
||||
else if ((m_func->flg & SI_REGVAR) and pIcode->ll()->match(rSI))
|
||||
m_icodes.push_front(pIcode);
|
||||
}
|
||||
++pIcode;
|
||||
@ -25,9 +27,9 @@ void EpilogIdiom::popStkVars(iICODE pIcode)
|
||||
/* Match [POP SI] */
|
||||
if (pIcode->ll()->match(iPOP))
|
||||
{
|
||||
if ((m_func->flg & SI_REGVAR) && pIcode->ll()->match(rSI))
|
||||
if ((m_func->flg & SI_REGVAR) and pIcode->ll()->match(rSI))
|
||||
m_icodes.push_front(pIcode);
|
||||
else if ((m_func->flg & DI_REGVAR) && pIcode->ll()->match(rDI))
|
||||
else if ((m_func->flg & DI_REGVAR) and pIcode->ll()->match(rDI))
|
||||
m_icodes.push_front(pIcode);
|
||||
}
|
||||
}
|
||||
@ -46,7 +48,7 @@ bool Idiom2::match(iICODE pIcode)
|
||||
iICODE nicode;
|
||||
if(pIcode==m_func->Icode.begin()) // pIcode->loc_ip == 0
|
||||
return false;
|
||||
if ( pIcode->ll()->testFlags(I) || (not pIcode->ll()->match(rSP,rBP)) )
|
||||
if ( pIcode->ll()->testFlags(I) or (not pIcode->ll()->match(rSP,rBP)) )
|
||||
return false;
|
||||
if(distance(pIcode,m_end)<3)
|
||||
return false;
|
||||
@ -55,21 +57,21 @@ bool Idiom2::match(iICODE pIcode)
|
||||
m_icodes.push_back(pIcode);
|
||||
/* Get next icode, skip over holes in the icode array */
|
||||
nicode = ++iICODE(pIcode);
|
||||
while (nicode->ll()->testFlags(NO_CODE) && (nicode != m_end))
|
||||
while (nicode->ll()->testFlags(NO_CODE) and (nicode != m_end))
|
||||
{
|
||||
nicode++;
|
||||
}
|
||||
if(nicode == m_end)
|
||||
return false;
|
||||
|
||||
if (nicode->ll()->match(iPOP,rBP) && ! (nicode->ll()->testFlags(I | TARGET | CASE)) )
|
||||
if (nicode->ll()->match(iPOP,rBP) and not (nicode->ll()->testFlags(I | TARGET | CASE)) )
|
||||
{
|
||||
m_icodes.push_back(nicode++); // Matched POP BP
|
||||
|
||||
/* Match RET(F) */
|
||||
if ( nicode != m_end &&
|
||||
!(nicode->ll()->testFlags(I | TARGET | CASE)) &&
|
||||
(nicode->ll()->match(iRET) || nicode->ll()->match(iRETF))
|
||||
if ( nicode != m_end and
|
||||
not (nicode->ll()->testFlags(I | TARGET | CASE)) and
|
||||
(nicode->ll()->match(iRET) or nicode->ll()->match(iRETF))
|
||||
)
|
||||
{
|
||||
m_icodes.push_back(nicode); // Matched RET
|
||||
@ -118,7 +120,7 @@ bool Idiom4::match(iICODE pIcode)
|
||||
{
|
||||
iICODE prev1 = --iICODE(pIcode);
|
||||
/* Check for POP BP */
|
||||
if (prev1->ll()->match(iPOP,rBP) && not prev1->ll()->testFlags(I) )
|
||||
if (prev1->ll()->match(iPOP,rBP) and not prev1->ll()->testFlags(I) )
|
||||
m_icodes.push_back(prev1);
|
||||
else if(prev1!=m_func->Icode.begin())
|
||||
{
|
||||
@ -138,7 +140,7 @@ bool Idiom4::match(iICODE pIcode)
|
||||
}
|
||||
int Idiom4::action()
|
||||
{
|
||||
if( ! m_icodes.empty()) // if not an empty RET[F] N
|
||||
if( not m_icodes.empty()) // if not an empty RET[F] N
|
||||
{
|
||||
for(size_t idx=0; idx<m_icodes.size()-1; ++idx) // don't invalidate last entry
|
||||
m_icodes[idx]->invalidate();
|
||||
@ -146,7 +148,7 @@ int Idiom4::action()
|
||||
if(m_param_count)
|
||||
{
|
||||
m_func->cbParam = (int16_t)m_param_count;
|
||||
m_func->flg |= CALL_PASCAL;
|
||||
m_func->callingConv(CConv::ePascal);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
#include "idiom1.h"
|
||||
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
/* checkStkVars - Checks for PUSH SI
|
||||
* checkStkVars - Checks for PUSH SI
|
||||
* [PUSH DI]
|
||||
* or PUSH DI
|
||||
* [PUSH SI]
|
||||
@ -19,14 +22,14 @@ int Idiom1::checkStkVars (iICODE pIcode)
|
||||
{
|
||||
si_matched = 1;
|
||||
++pIcode;
|
||||
if ((pIcode != m_end) && pIcode->ll()->match(iPUSH,rDI)) // Look for PUSH DI
|
||||
if ((pIcode != m_end) and pIcode->ll()->match(iPUSH,rDI)) // Look for PUSH DI
|
||||
di_matched = 1;
|
||||
}
|
||||
else if (pIcode->ll()->match(iPUSH,rDI))
|
||||
{
|
||||
di_matched = 1;
|
||||
++pIcode;
|
||||
if ((pIcode != m_end) && pIcode->ll()->match(iPUSH,rSI)) // Look for PUSH SI
|
||||
if ((pIcode != m_end) and pIcode->ll()->match(iPUSH,rSI)) // Look for PUSH SI
|
||||
si_matched = 1;
|
||||
}
|
||||
m_func->flg |= (si_matched ? SI_REGVAR : 0) | (di_matched ? DI_REGVAR : 0);
|
||||
@ -60,13 +63,13 @@ bool Idiom1::match(iICODE picode)
|
||||
m_icodes.clear();
|
||||
m_min_off = 0;
|
||||
/* PUSH BP as first instruction of procedure */
|
||||
if ( (not picode->ll()->testFlags(I)) && picode->ll()->src().regi == rBP)
|
||||
if ( (not picode->ll()->testFlags(I)) and picode->ll()->src().regi == rBP)
|
||||
{
|
||||
m_icodes.push_back( picode++ ); // insert iPUSH
|
||||
if(picode==m_end)
|
||||
return false;
|
||||
/* MOV BP, SP as next instruction */
|
||||
if ( !picode->ll()->testFlags(I | TARGET | CASE) && picode->ll()->match(iMOV ,rBP,rSP) )
|
||||
if ( not picode->ll()->testFlags(I | TARGET | CASE) and picode->ll()->match(iMOV ,rBP,rSP) )
|
||||
{
|
||||
m_icodes.push_back( picode++ ); // insert iMOV
|
||||
if(picode==m_end)
|
||||
@ -75,7 +78,7 @@ bool Idiom1::match(iICODE picode)
|
||||
|
||||
/* Look for SUB SP, immed */
|
||||
if (
|
||||
picode->ll()->testFlags(I | TARGET | CASE) && picode->ll()->match(iSUB,rSP)
|
||||
picode->ll()->testFlags(I | TARGET | CASE) and picode->ll()->match(iSUB,rSP)
|
||||
)
|
||||
{
|
||||
m_icodes.push_back( picode++ ); // insert iSUB
|
||||
@ -98,8 +101,8 @@ bool Idiom1::match(iICODE picode)
|
||||
if(picode == m_end)
|
||||
return false;
|
||||
/* Look for MOV BP, SP */
|
||||
if ( picode != m_end &&
|
||||
!picode->ll()->testFlags(I | TARGET | CASE) &&
|
||||
if ( picode != m_end and
|
||||
not picode->ll()->testFlags(I | TARGET | CASE) and
|
||||
picode->ll()->match(iMOV,rBP,rSP))
|
||||
{
|
||||
m_icodes.push_back(picode);
|
||||
@ -115,11 +118,11 @@ bool Idiom1::match(iICODE picode)
|
||||
else // push di [push si] / push si [push di]
|
||||
{
|
||||
size_t n = checkStkVars (picode);
|
||||
for(int i=0; i<n; ++i)
|
||||
for(size_t i=0; i<n; ++i)
|
||||
m_icodes.push_back(picode++);
|
||||
|
||||
}
|
||||
return !m_icodes.empty();
|
||||
return not m_icodes.empty();
|
||||
}
|
||||
int Idiom1::action()
|
||||
{
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
#include "dcc.h"
|
||||
#include "mov_idioms.h"
|
||||
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*****************************************************************************
|
||||
@ -27,19 +30,20 @@ bool Idiom14::match(iICODE pIcode)
|
||||
return false;
|
||||
m_icodes[0]=pIcode++;
|
||||
m_icodes[1]=pIcode++;
|
||||
LLInst * matched [] {m_icodes[0]->ll(),m_icodes[1]->ll()};
|
||||
/* Check for regL */
|
||||
m_regL = m_icodes[0]->ll()->dst.regi;
|
||||
if (not m_icodes[0]->ll()->testFlags(I) && ((m_regL == rAX) || (m_regL ==rBX)))
|
||||
m_regL = matched[0]->m_dst.regi;
|
||||
if (not matched[0]->testFlags(I) and ((m_regL == rAX) or (m_regL ==rBX)))
|
||||
{
|
||||
/* Check for XOR regH, regH */
|
||||
if (m_icodes[1]->ll()->match(iXOR) && not m_icodes[1]->ll()->testFlags(I))
|
||||
if (matched[1]->match(iXOR) and not matched[1]->testFlags(I))
|
||||
{
|
||||
m_regH = m_icodes[1]->ll()->dst.regi;
|
||||
if (m_regH == m_icodes[1]->ll()->src().getReg2())
|
||||
m_regH = matched[1]->m_dst.regi;
|
||||
if (m_regH == matched[1]->src().getReg2())
|
||||
{
|
||||
if ((m_regL == rAX) && (m_regH == rDX))
|
||||
if ((m_regL == rAX) and (m_regH == rDX))
|
||||
return true;
|
||||
if ((m_regL == rBX) && (m_regH == rCX))
|
||||
if ((m_regL == rBX) and (m_regH == rCX))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -48,12 +52,11 @@ bool Idiom14::match(iICODE pIcode)
|
||||
}
|
||||
int Idiom14::action()
|
||||
{
|
||||
int idx;
|
||||
COND_EXPR *lhs,*rhs;
|
||||
idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, m_regH, m_regL, m_icodes[0]);
|
||||
lhs = COND_EXPR::idLongIdx (idx);
|
||||
|
||||
int idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, LONGID_TYPE(m_regH,m_regL), m_icodes[0]);
|
||||
AstIdent *lhs = AstIdent::LongIdx (idx);
|
||||
m_icodes[0]->setRegDU( m_regH, eDEF);
|
||||
rhs = COND_EXPR::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], NONE);
|
||||
Expr *rhs = AstIdent::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], NONE);
|
||||
m_icodes[0]->setAsgn(lhs, rhs);
|
||||
m_icodes[1]->invalidate();
|
||||
return 2;
|
||||
@ -80,13 +83,13 @@ bool Idiom13::match(iICODE pIcode)
|
||||
eReg regi;
|
||||
|
||||
/* Check for regL */
|
||||
regi = m_icodes[0]->ll()->dst.regi;
|
||||
if (not m_icodes[0]->ll()->testFlags(I) && (regi >= rAL) && (regi <= rBH))
|
||||
regi = m_icodes[0]->ll()->m_dst.regi;
|
||||
if (not m_icodes[0]->ll()->testFlags(I) and (regi >= rAL) and (regi <= rBH))
|
||||
{
|
||||
/* Check for MOV regH, 0 */
|
||||
if (m_icodes[1]->ll()->match(iMOV,I) && (m_icodes[1]->ll()->src().getImm2() == 0))
|
||||
if (m_icodes[1]->ll()->match(iMOV,I) and (m_icodes[1]->ll()->src().getImm2() == 0))
|
||||
{
|
||||
if (m_icodes[1]->ll()->dst.regi == (regi + 4)) //WARNING: based on distance between AH-AL,BH-BL etc.
|
||||
if (m_icodes[1]->ll()->m_dst.regi == (regi + 4)) //WARNING: based on distance between AH-AL,BH-BL etc.
|
||||
{
|
||||
m_loaded_reg=(eReg)(regi - rAL + rAX);
|
||||
return true;
|
||||
@ -98,11 +101,14 @@ bool Idiom13::match(iICODE pIcode)
|
||||
|
||||
int Idiom13::action()
|
||||
{
|
||||
COND_EXPR *lhs,*rhs;
|
||||
lhs = COND_EXPR::idReg (m_loaded_reg, 0, &m_func->localId);
|
||||
AstIdent *lhs;
|
||||
Expr *rhs;
|
||||
eReg regi = m_icodes[0]->ll()->m_dst.regi;
|
||||
m_icodes[0]->du1.removeDef(regi);
|
||||
//m_icodes[0]->du1.numRegsDef--; /* prev uint8_t reg def */
|
||||
lhs = new RegisterNode(LLOperand(m_loaded_reg, 0), &m_func->localId);
|
||||
m_icodes[0]->setRegDU( m_loaded_reg, eDEF);
|
||||
m_icodes[0]->du1.numRegsDef--; /* prev uint8_t reg def */
|
||||
rhs = COND_EXPR::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], NONE);
|
||||
rhs = AstIdent::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], NONE);
|
||||
m_icodes[0]->setAsgn(lhs, rhs);
|
||||
m_icodes[1]->invalidate();
|
||||
return 2;
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
#include "dcc.h"
|
||||
#include "neg_idioms.h"
|
||||
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
@ -16,14 +19,14 @@ using namespace std;
|
||||
****************************************************************************/
|
||||
bool Idiom11::match (iICODE picode)
|
||||
{
|
||||
const char *matchstring="(oNEG rH) (oNEG rL) (SBB \rH i0)";
|
||||
//const char *matchstring="(oNEG rH) (oNEG rL) (SBB \rH i0)";
|
||||
condId type; /* type of argument */
|
||||
if(distance(picode,m_end)<3)
|
||||
return false;
|
||||
for(int i=0; i<3; ++i)
|
||||
m_icodes[i]=picode++;
|
||||
type = m_icodes[0]->ll()->idType(DST);
|
||||
if(type==CONSTANT || type == OTHER)
|
||||
if(type==CONSTANT or type == OTHER)
|
||||
return false;
|
||||
/* Check NEG reg/mem
|
||||
* SBB reg/mem, 0*/
|
||||
@ -31,28 +34,31 @@ bool Idiom11::match (iICODE picode)
|
||||
return false;
|
||||
switch (type)
|
||||
{
|
||||
case GLOB_VAR:
|
||||
if ((m_icodes[2]->ll()->dst.segValue == m_icodes[0]->ll()->dst.segValue) &&
|
||||
(m_icodes[2]->ll()->dst.off == m_icodes[0]->ll()->dst.off))
|
||||
return true;
|
||||
break;
|
||||
case REGISTER:
|
||||
if (m_icodes[2]->ll()->dst.regi == m_icodes[0]->ll()->dst.regi)
|
||||
return true;
|
||||
break;
|
||||
case PARAM:
|
||||
case LOCAL_VAR:
|
||||
if (m_icodes[2]->ll()->dst.off == m_icodes[0]->ll()->dst.off)
|
||||
return true;
|
||||
break;
|
||||
case GLOB_VAR:
|
||||
if ((m_icodes[2]->ll()->m_dst.segValue == m_icodes[0]->ll()->m_dst.segValue) and
|
||||
(m_icodes[2]->ll()->m_dst.off == m_icodes[0]->ll()->m_dst.off))
|
||||
return true;
|
||||
break;
|
||||
case REGISTER:
|
||||
if (m_icodes[2]->ll()->m_dst.regi == m_icodes[0]->ll()->m_dst.regi)
|
||||
return true;
|
||||
break;
|
||||
case PARAM:
|
||||
case LOCAL_VAR:
|
||||
if (m_icodes[2]->ll()->m_dst.off == m_icodes[0]->ll()->m_dst.off)
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"Idiom11::match unhandled type %d\n",type);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int Idiom11::action()
|
||||
{
|
||||
COND_EXPR *lhs,*rhs;
|
||||
lhs = COND_EXPR::idLong (&m_func->localId, DST, m_icodes[0], HIGH_FIRST,m_icodes[0], USE_DEF, *m_icodes[1]->ll());
|
||||
rhs = COND_EXPR::unary (NEGATION, lhs);
|
||||
AstIdent *lhs;
|
||||
Expr *rhs;
|
||||
lhs = AstIdent::Long (&m_func->localId, DST, m_icodes[0], HIGH_FIRST,m_icodes[0], USE_DEF, *m_icodes[1]->ll());
|
||||
rhs = UnaryOperator::Create(NEGATION, lhs);
|
||||
m_icodes[0]->setAsgn(lhs, rhs);
|
||||
m_icodes[1]->invalidate();
|
||||
m_icodes[2]->invalidate();
|
||||
@ -73,18 +79,18 @@ int Idiom11::action()
|
||||
****************************************************************************/
|
||||
bool Idiom16::match (iICODE picode)
|
||||
{
|
||||
const char *matchstring="(oNEG rR) (oSBB rR rR) (oINC rR)";
|
||||
//const char *matchstring="(oNEG rR) (oSBB rR rR) (oINC rR)";
|
||||
if(distance(picode,m_end)<3)
|
||||
return false;
|
||||
for(int i=0; i<3; ++i)
|
||||
m_icodes[i]=picode++;
|
||||
|
||||
uint8_t regi = m_icodes[0]->ll()->dst.regi;
|
||||
if ((regi >= rAX) && (regi < INDEX_BX_SI))
|
||||
uint8_t regi = m_icodes[0]->ll()->m_dst.regi;
|
||||
if ((regi >= rAX) and (regi < INDEX_BX_SI))
|
||||
{
|
||||
if (m_icodes[1]->ll()->match(iSBB) && m_icodes[2]->ll()->match(iINC))
|
||||
if ((m_icodes[1]->ll()->dst.regi == (m_icodes[1]->ll()->src().getReg2())) &&
|
||||
m_icodes[1]->ll()->match((eReg)regi) &&
|
||||
if (m_icodes[1]->ll()->match(iSBB) and m_icodes[2]->ll()->match(iINC))
|
||||
if ((m_icodes[1]->ll()->m_dst.regi == (m_icodes[1]->ll()->src().getReg2())) and
|
||||
m_icodes[1]->ll()->match((eReg)regi) and
|
||||
m_icodes[2]->ll()->match((eReg)regi))
|
||||
return true;
|
||||
}
|
||||
@ -92,9 +98,10 @@ bool Idiom16::match (iICODE picode)
|
||||
}
|
||||
int Idiom16::action()
|
||||
{
|
||||
COND_EXPR *lhs,*rhs;
|
||||
lhs = COND_EXPR::idReg (m_icodes[0]->ll()->dst.regi, m_icodes[0]->ll()->getFlag(),&m_func->localId);
|
||||
rhs = COND_EXPR::unary (NEGATION, lhs->clone());
|
||||
AstIdent *lhs;
|
||||
Expr *rhs;
|
||||
lhs = new RegisterNode(*m_icodes[0]->ll()->get(DST),&m_func->localId);
|
||||
rhs = UnaryOperator::Create(NEGATION, lhs->clone());
|
||||
m_icodes[0]->setAsgn(lhs, rhs);
|
||||
m_icodes[1]->invalidate();
|
||||
m_icodes[2]->invalidate();
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
#include "dcc.h"
|
||||
#include "shift_idioms.h"
|
||||
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
@ -18,8 +21,8 @@ bool Idiom8::match(iICODE pIcode)
|
||||
return false;
|
||||
m_icodes[0]=pIcode++;
|
||||
m_icodes[1]=pIcode++;
|
||||
if (m_icodes[0]->ll()->testFlags(I) && (m_icodes[0]->ll()->src().getImm2() == 1))
|
||||
if ( m_icodes[1]->ll()->match(iRCR,I) &&
|
||||
if (m_icodes[0]->ll()->testFlags(I) and (m_icodes[0]->ll()->src().getImm2() == 1))
|
||||
if ( m_icodes[1]->ll()->match(iRCR,I) and
|
||||
(m_icodes[1]->ll()->src().getImm2() == 1))
|
||||
return true;
|
||||
return false;
|
||||
@ -28,16 +31,16 @@ bool Idiom8::match(iICODE pIcode)
|
||||
int Idiom8::action()
|
||||
{
|
||||
int idx;
|
||||
COND_EXPR *rhs,*lhs,*expr;
|
||||
AstIdent *lhs;
|
||||
Expr *expr;
|
||||
eReg regH,regL;
|
||||
regH=m_icodes[0]->ll()->dst.regi;
|
||||
regL=m_icodes[1]->ll()->dst.regi;
|
||||
idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, regH, regL, m_icodes[0]);
|
||||
lhs = COND_EXPR::idLongIdx (idx);
|
||||
regH=m_icodes[0]->ll()->m_dst.regi;
|
||||
regL=m_icodes[1]->ll()->m_dst.regi;
|
||||
idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, LONGID_TYPE(regH,regL), m_icodes[0]);
|
||||
lhs = AstIdent::LongIdx (idx);
|
||||
m_icodes[0]->setRegDU( regL, USE_DEF);
|
||||
|
||||
rhs = COND_EXPR::idKte(1,2);
|
||||
expr = COND_EXPR::boolOp(lhs, rhs, SHR);
|
||||
expr = new BinaryOperator(SHR,lhs, new Constant(1, 2));
|
||||
m_icodes[0]->setAsgn(lhs, expr);
|
||||
m_icodes[1]->invalidate();
|
||||
return 2;
|
||||
@ -65,7 +68,7 @@ bool Idiom15::match(iICODE pIcode)
|
||||
if (not pIcode->ll()->testFlags(I) or (pIcode->ll()->src().getImm2() != 1))
|
||||
return false;
|
||||
m_icodes.clear();
|
||||
regi = pIcode->ll()->dst.regi;
|
||||
regi = pIcode->ll()->m_dst.regi;
|
||||
m_icodes.push_back(pIcode++);
|
||||
while( (pIcode!=m_end) and
|
||||
pIcode->ll()->match(iSHL,(eReg)regi,I) and
|
||||
@ -78,12 +81,12 @@ bool Idiom15::match(iICODE pIcode)
|
||||
|
||||
int Idiom15::action()
|
||||
{
|
||||
COND_EXPR *lhs,*rhs,*_exp;
|
||||
lhs = COND_EXPR::idReg (m_icodes[0]->ll()->dst.regi,
|
||||
m_icodes[0]->ll()->getFlag() & NO_SRC_B,
|
||||
&m_func->localId);
|
||||
rhs = COND_EXPR::idKte (m_icodes.size(), 2);
|
||||
_exp = COND_EXPR::boolOp (lhs, rhs, SHL);
|
||||
AstIdent *lhs;
|
||||
|
||||
Expr *rhs,*_exp;
|
||||
lhs = new RegisterNode(*m_icodes[0]->ll()->get(DST), &m_func->localId);
|
||||
rhs = new Constant(m_icodes.size(), 2);
|
||||
_exp = new BinaryOperator(SHL,lhs, rhs);
|
||||
m_icodes[0]->setAsgn(lhs, _exp);
|
||||
for (size_t i=1; i<m_icodes.size()-1; ++i)
|
||||
{
|
||||
@ -107,8 +110,8 @@ bool Idiom12::match(iICODE pIcode)
|
||||
return false;
|
||||
m_icodes[0]=pIcode++;
|
||||
m_icodes[1]=pIcode++;
|
||||
if (m_icodes[0]->ll()->testFlags(I) && (m_icodes[0]->ll()->src().getImm2() == 1))
|
||||
if (m_icodes[1]->ll()->match(iRCL,I) && (m_icodes[1]->ll()->src().getImm2() == 1))
|
||||
if (m_icodes[0]->ll()->testFlags(I) and (m_icodes[0]->ll()->src().getImm2() == 1))
|
||||
if (m_icodes[1]->ll()->match(iRCL,I) and (m_icodes[1]->ll()->src().getImm2() == 1))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@ -116,16 +119,17 @@ bool Idiom12::match(iICODE pIcode)
|
||||
int Idiom12::action()
|
||||
{
|
||||
int idx;
|
||||
COND_EXPR *rhs,*lhs,*expr;
|
||||
eReg regH,regL;
|
||||
regL=m_icodes[0]->ll()->dst.regi;
|
||||
regH=m_icodes[1]->ll()->dst.regi;
|
||||
Expr *expr;
|
||||
AstIdent *lhs;
|
||||
|
||||
idx = m_func->localId.newLongReg (TYPE_LONG_UNSIGN, regH, regL,m_icodes[0]);
|
||||
lhs = COND_EXPR::idLongIdx (idx);
|
||||
eReg regH,regL;
|
||||
regL=m_icodes[0]->ll()->m_dst.regi;
|
||||
regH=m_icodes[1]->ll()->m_dst.regi;
|
||||
|
||||
idx = m_func->localId.newLongReg (TYPE_LONG_UNSIGN, LONGID_TYPE(regH,regL),m_icodes[0]);
|
||||
lhs = AstIdent::LongIdx (idx);
|
||||
m_icodes[0]->setRegDU( regH, USE_DEF);
|
||||
rhs = COND_EXPR::idKte (1, 2);
|
||||
expr = COND_EXPR::boolOp (lhs, rhs, SHL);
|
||||
expr = new BinaryOperator(SHL,lhs, new Constant(1, 2));
|
||||
m_icodes[0]->setAsgn(lhs, expr);
|
||||
m_icodes[1]->invalidate();
|
||||
return 2;
|
||||
@ -146,8 +150,8 @@ bool Idiom9::match(iICODE pIcode)
|
||||
return false;
|
||||
m_icodes[0]=pIcode++;
|
||||
m_icodes[1]=pIcode++;
|
||||
if (m_icodes[0]->ll()->testFlags(I) && (m_icodes[0]->ll()->src().getImm2() == 1))
|
||||
if (m_icodes[1]->ll()->match(iRCR,I) && (m_icodes[1]->ll()->src().getImm2() == 1))
|
||||
if (m_icodes[0]->ll()->testFlags(I) and (m_icodes[0]->ll()->src().getImm2() == 1))
|
||||
if (m_icodes[1]->ll()->match(iRCR,I) and (m_icodes[1]->ll()->src().getImm2() == 1))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@ -155,15 +159,15 @@ bool Idiom9::match(iICODE pIcode)
|
||||
int Idiom9::action()
|
||||
{
|
||||
int idx;
|
||||
COND_EXPR *rhs,*lhs,*expr;
|
||||
AstIdent *lhs;
|
||||
Expr *expr;
|
||||
eReg regH,regL;
|
||||
regL=m_icodes[1]->ll()->dst.regi;
|
||||
regH=m_icodes[0]->ll()->dst.regi;
|
||||
idx = m_func->localId.newLongReg (TYPE_LONG_UNSIGN,regH,regL,m_icodes[0]);
|
||||
lhs = COND_EXPR::idLongIdx (idx);
|
||||
regL=m_icodes[1]->ll()->m_dst.regi;
|
||||
regH=m_icodes[0]->ll()->m_dst.regi;
|
||||
idx = m_func->localId.newLongReg (TYPE_LONG_UNSIGN,LONGID_TYPE(regH,regL),m_icodes[0]);
|
||||
lhs = AstIdent::LongIdx (idx);
|
||||
m_icodes[0]->setRegDU(regL, USE_DEF);
|
||||
rhs = COND_EXPR::idKte (1, 2);
|
||||
expr = COND_EXPR::boolOp (lhs, rhs, SHR);
|
||||
expr = new BinaryOperator(SHR,lhs, new Constant(1, 2));
|
||||
m_icodes[0]->setAsgn(lhs, expr);
|
||||
m_icodes[1]->invalidate();
|
||||
return 2;
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
#include "dcc.h"
|
||||
#include "xor_idioms.h"
|
||||
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*****************************************************************************
|
||||
@ -26,24 +29,26 @@ bool Idiom21::match (iICODE picode)
|
||||
if (not m_icodes[1]->ll()->testFlags(I))
|
||||
return false;
|
||||
|
||||
dst = &m_icodes[0]->ll()->dst;
|
||||
dst = &m_icodes[0]->ll()->m_dst;
|
||||
src = &m_icodes[0]->ll()->src();
|
||||
if ((dst->regi == src->getReg2()) && (dst->getReg2() > 0) && (dst->getReg2() < INDEX_BX_SI))
|
||||
if ((dst->regi == src->getReg2()) and (dst->getReg2() > 0) and (dst->getReg2() < INDEX_BX_SI))
|
||||
{
|
||||
if ((dst->getReg2() == rDX) && m_icodes[1]->ll()->match(rAX))
|
||||
if ((dst->getReg2() == rDX) and m_icodes[1]->ll()->match(rAX))
|
||||
return true;
|
||||
if ((dst->getReg2() == rCX) && m_icodes[1]->ll()->match(rBX))
|
||||
if ((dst->getReg2() == rCX) and m_icodes[1]->ll()->match(rBX))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int Idiom21::action()
|
||||
{
|
||||
COND_EXPR *lhs,*rhs;
|
||||
lhs = COND_EXPR::idLong (&m_func->localId, DST, m_icodes[0],HIGH_FIRST, m_icodes[0], eDEF, *m_icodes[1]->ll());
|
||||
rhs = COND_EXPR::idKte (m_icodes[1]->ll()->src().getImm2() , 4);
|
||||
Expr *rhs;
|
||||
AstIdent *lhs;
|
||||
|
||||
lhs = AstIdent::Long (&m_func->localId, DST, m_icodes[0],HIGH_FIRST, m_icodes[0], eDEF, *m_icodes[1]->ll());
|
||||
rhs = new Constant(m_icodes[1]->ll()->src().getImm2(), 4);
|
||||
m_icodes[0]->setAsgn(lhs, rhs);
|
||||
m_icodes[0]->du.use = 0; /* clear register used in iXOR */
|
||||
m_icodes[0]->du.use.reset(); /* clear register used in iXOR */
|
||||
m_icodes[1]->invalidate();
|
||||
return 2;
|
||||
}
|
||||
@ -61,11 +66,11 @@ bool Idiom7::match(iICODE picode)
|
||||
return false;
|
||||
const LLOperand *dst, *src;
|
||||
m_icode=picode;
|
||||
dst = &picode->ll()->dst;
|
||||
dst = &picode->ll()->m_dst;
|
||||
src = &picode->ll()->src();
|
||||
if (dst->regi == 0) /* global variable */
|
||||
{
|
||||
if ((dst->segValue == src->segValue) && (dst->off == src->off))
|
||||
if ((dst->segValue == src->segValue) and (dst->off == src->off))
|
||||
return true;
|
||||
}
|
||||
else if (dst->regi < INDEX_BX_SI) /* register */
|
||||
@ -73,20 +78,19 @@ bool Idiom7::match(iICODE picode)
|
||||
if (dst->regi == src->regi)
|
||||
return true;
|
||||
}
|
||||
else if ((dst->off) && (dst->seg == rSS) && (dst->regi == INDEX_BP)) /* offset from BP */
|
||||
else if ((dst->off) and (dst->seg == rSS) and (dst->regi == INDEX_BP)) /* offset from BP */
|
||||
{
|
||||
if ((dst->off == src->off) && (dst->seg == src->seg) && (dst->regi == src->regi))
|
||||
if ((dst->off == src->off) and (dst->seg == src->seg) and (dst->regi == src->regi))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int Idiom7::action()
|
||||
{
|
||||
COND_EXPR *lhs,*rhs;
|
||||
lhs = COND_EXPR::id (*m_icode->ll(), DST, m_func, m_icode, *m_icode, NONE);
|
||||
rhs = COND_EXPR::idKte (0, 2);
|
||||
m_icode->setAsgn(lhs, rhs);
|
||||
m_icode->du.use = 0; /* clear register used in iXOR */
|
||||
Expr *lhs;
|
||||
lhs = AstIdent::id (*m_icode->ll(), DST, m_func, m_icode, *m_icode, NONE);
|
||||
m_icode->setAsgn(dynamic_cast<AstIdent *>(lhs), new Constant(0, 2));
|
||||
m_icode->du.use.reset(); /* clear register used in iXOR */
|
||||
m_icode->ll()->setFlags(I);
|
||||
return 1;
|
||||
}
|
||||
@ -113,9 +117,9 @@ bool Idiom10::match(iICODE pIcode)
|
||||
m_icodes[0]=pIcode++;
|
||||
m_icodes[1]=pIcode++;
|
||||
/* Check OR reg, reg */
|
||||
if (not m_icodes[0]->ll()->testFlags(I) &&
|
||||
m_icodes[0]->ll()->src().isReg() &&
|
||||
(m_icodes[0]->ll()->src().getReg2() == m_icodes[0]->ll()->dst.getReg2()))
|
||||
if (not m_icodes[0]->ll()->testFlags(I) and
|
||||
m_icodes[0]->ll()->src().isReg() and
|
||||
(m_icodes[0]->ll()->src().getReg2() == m_icodes[0]->ll()->m_dst.getReg2()))
|
||||
if (m_icodes[1]->ll()->match(iJNE)) //.conditionalJump()
|
||||
{
|
||||
return true;
|
||||
@ -127,8 +131,9 @@ int Idiom10::action()
|
||||
{
|
||||
m_icodes[0]->ll()->set(iCMP,I);
|
||||
m_icodes[0]->ll()->replaceSrc(LLOperand::CreateImm2(0));
|
||||
m_icodes[0]->du.def = 0;
|
||||
m_icodes[0]->du1.numRegsDef = 0;
|
||||
m_icodes[0]->du.def.reset(); //TODO: this defines FLAGS
|
||||
m_icodes[0]->du1.clearAllDefs();
|
||||
//m_icodes[0]->du1.numRegsDef = 0;
|
||||
return 2;
|
||||
|
||||
}
|
||||
|
||||
54
src/liveness_set.cpp
Normal file
54
src/liveness_set.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
#include "BasicBlock.h"
|
||||
#include "machine_x86.h"
|
||||
|
||||
/* DU bit definitions for each reg value - including index registers */
|
||||
LivenessSet duReg[] = { {},
|
||||
//AH AL . . AX, BH
|
||||
{rAH,rAL,rAX},{rCH,rCL,rCX},{rDH,rDL,rDX},{rBH,rBL,rBX},
|
||||
/* uint16_t regs */
|
||||
{rSP},{rBP},{rSI},{rDI},
|
||||
/* seg regs */
|
||||
{rES},{rCS},{rSS},{rDS},
|
||||
/* uint8_t regs */
|
||||
{rAL},{rCL},{rDL},{rBL},
|
||||
{rAH},{rCH},{rDH},{rBH},
|
||||
/* tmp reg */
|
||||
{rTMP},{rTMP2},
|
||||
/* index regs */
|
||||
{rBX,rSI},{rBX,rDI},{rBP,rSI},{rBP,rDI},
|
||||
{rSI},{rDI},{rBP},{rBX}
|
||||
};
|
||||
|
||||
LivenessSet &LivenessSet::setReg(int r)
|
||||
{
|
||||
this->reset();
|
||||
*this |= duReg[r];
|
||||
return *this;
|
||||
}
|
||||
LivenessSet &LivenessSet::clrReg(int r)
|
||||
{
|
||||
return *this -= duReg[r];
|
||||
}
|
||||
|
||||
LivenessSet &LivenessSet::addReg(int r)
|
||||
{
|
||||
*this |= duReg[r];
|
||||
// postProcessCompositeRegs();
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool LivenessSet::testRegAndSubregs(int r) const
|
||||
{
|
||||
return (*this & duReg[r]).any();
|
||||
}
|
||||
void LivenessSet::postProcessCompositeRegs()
|
||||
{
|
||||
if(testReg(rAL) and testReg(rAH))
|
||||
registers.insert(rAX);
|
||||
if(testReg(rCL) and testReg(rCH))
|
||||
registers.insert(rCX);
|
||||
if(testReg(rDL) and testReg(rDH))
|
||||
registers.insert(rDX);
|
||||
if(testReg(rBL) and testReg(rBH))
|
||||
registers.insert(rBX);
|
||||
}
|
||||
302
src/locident.cpp
302
src/locident.cpp
@ -4,33 +4,69 @@
|
||||
* Date: October 1993
|
||||
* (C) Cristina Cifuentes
|
||||
*/
|
||||
#include "locident.h"
|
||||
|
||||
#include "dcc.h"
|
||||
#include "msvc_fixes.h"
|
||||
|
||||
#include <cstring>
|
||||
#include "locident.h"
|
||||
#include "dcc.h"
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
static const int LOCAL_ID_DELTA = 25;
|
||||
static const int IDX_ARRAY_DELTA = 5;
|
||||
|
||||
|
||||
bool LONGID_TYPE::srcDstRegMatch(iICODE a, iICODE b) const
|
||||
{
|
||||
return (a->ll()->src().getReg2()==l) and (b->ll()->dst.getReg2()==h);
|
||||
return (a->ll()->src().getReg2()==m_l) and (b->ll()->m_dst.getReg2()==m_h);
|
||||
}
|
||||
|
||||
|
||||
ID::ID() : type(TYPE_UNKNOWN),illegal(false),loc(STK_FRAME),hasMacro(false)
|
||||
{
|
||||
name[0]=0;
|
||||
macro[0]=0;
|
||||
memset(&id,0,sizeof(id));
|
||||
}
|
||||
ID::ID(hlType t, frameType f) : type(t),illegal(false),hasMacro(false)
|
||||
{
|
||||
name[0]=0;
|
||||
macro[0]=0;
|
||||
memset(&id,0,sizeof(id));
|
||||
loc=f;
|
||||
assert(not ((t==TYPE_LONG_SIGN) or (t==TYPE_LONG_UNSIGN)));
|
||||
}
|
||||
ID::ID(hlType t,const LONGID_TYPE &s) : type(t),illegal(false),hasMacro(false)
|
||||
{
|
||||
macro[0]=0;
|
||||
memset(&id,0,sizeof(id));
|
||||
loc=REG_FRAME;
|
||||
m_longId = s;
|
||||
assert((t==TYPE_LONG_SIGN) or (t==TYPE_LONG_UNSIGN));
|
||||
}
|
||||
ID::ID(hlType t,const LONG_STKID_TYPE &s) : type(t),illegal(false),hasMacro(false)
|
||||
{
|
||||
macro[0]=0;
|
||||
memset(&id,0,sizeof(id));
|
||||
loc=STK_FRAME;
|
||||
id.longStkId = s;
|
||||
assert((t==TYPE_LONG_SIGN) or (t==TYPE_LONG_UNSIGN));
|
||||
}
|
||||
|
||||
ID::ID(hlType t, const LONGGLB_TYPE &s) : type(t),illegal(false)
|
||||
{
|
||||
macro[0]=0;
|
||||
memset(&id,0,sizeof(id));
|
||||
loc=GLB_FRAME;
|
||||
id.longGlb = s;
|
||||
assert((t==TYPE_LONG_SIGN) or (t==TYPE_LONG_UNSIGN));
|
||||
}
|
||||
|
||||
eReg ID::getPairedRegister(eReg first) const {
|
||||
if (longId().h() == first)
|
||||
return (longId().l());
|
||||
else if (longId().l() == first)
|
||||
return (longId().h());
|
||||
return rUNDEF;
|
||||
}
|
||||
|
||||
#define LOCAL_ID_DELTA 25
|
||||
#define IDX_ARRAY_DELTA 5
|
||||
|
||||
/* Creates a new identifier node of type t and returns it.
|
||||
* Arguments: locSym : local long symbol table
|
||||
@ -39,8 +75,7 @@ ID::ID(hlType t, frameType f) : type(t),illegal(false),hasMacro(false)
|
||||
* ix : index into icode array where this var is used */
|
||||
void LOCAL_ID::newIdent(hlType t, frameType f)
|
||||
{
|
||||
ID newid(t,f);
|
||||
id_arr.push_back(newid);
|
||||
id_arr.emplace_back(t,f);
|
||||
}
|
||||
|
||||
|
||||
@ -48,19 +83,16 @@ void LOCAL_ID::newIdent(hlType t, frameType f)
|
||||
* TYPE_WORD_(UN)SIGN type. Returns the index to this new entry. */
|
||||
int LOCAL_ID::newByteWordReg(hlType t, eReg regi)
|
||||
{
|
||||
int idx;
|
||||
|
||||
/* Check for entry in the table */
|
||||
auto found=std::find_if(id_arr.begin(),id_arr.end(),[t,regi](ID &el)->bool {
|
||||
return ((el.type == t) && (el.id.regi == regi));
|
||||
});
|
||||
return ((el.type == t) and (el.id.regi == regi));
|
||||
});
|
||||
if(found!=id_arr.end())
|
||||
return found-id_arr.begin();
|
||||
/* Not in table, create new identifier */
|
||||
newIdent (t, REG_FRAME);
|
||||
idx = id_arr.size() - 1;
|
||||
id_arr[idx].id.regi = regi;
|
||||
return (idx);
|
||||
id_arr.back().id.regi = regi;
|
||||
return id_arr.size() - 1;
|
||||
}
|
||||
|
||||
|
||||
@ -72,13 +104,9 @@ int LOCAL_ID::newByteWordReg(hlType t, eReg regi)
|
||||
* flagging this entry as illegal is all that can be done. */
|
||||
void LOCAL_ID::flagByteWordId (int off)
|
||||
{
|
||||
int idx;
|
||||
auto found=std::find_if(id_arr.begin(),id_arr.end(),[off](ID &en)->bool {
|
||||
//if (((en.type == TYPE_WORD_SIGN) || (en.type == TYPE_BYTE_SIGN)) &&
|
||||
if ((en.typeBitsize()<=16) &&
|
||||
(en.id.bwId.off == off) && (en.id.bwId.regOff == 0))
|
||||
return true;
|
||||
return false;
|
||||
//if (((en.type == TYPE_WORD_SIGN) or (en.type == TYPE_BYTE_SIGN)) and
|
||||
return ((en.typeBitsize()<=16) and (en.id.bwId.off == off) and (en.id.bwId.regOff == 0));
|
||||
});
|
||||
if(found==id_arr.end())
|
||||
{
|
||||
@ -92,23 +120,21 @@ void LOCAL_ID::flagByteWordId (int off)
|
||||
* TYPE_WORD_(UN)SIGN type. Returns the index to this new entry. */
|
||||
int LOCAL_ID::newByteWordStk(hlType t, int off, uint8_t regOff)
|
||||
{
|
||||
int idx;
|
||||
|
||||
/* Check for entry in the table */
|
||||
auto found=std::find_if(id_arr.begin(),id_arr.end(),[off,regOff](ID &el)->bool {
|
||||
if ((el.id.bwId.off == off) && (el.id.bwId.regOff == regOff))
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
if ((el.id.bwId.off == off) and (el.id.bwId.regOff == regOff))
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
if(found!=id_arr.end())
|
||||
return found-id_arr.begin(); //return Index to found element
|
||||
|
||||
/* Not in table, create new identifier */
|
||||
newIdent (t, STK_FRAME);
|
||||
idx = id_arr.size() - 1;
|
||||
id_arr[idx].id.bwId.regOff = regOff;
|
||||
id_arr[idx].id.bwId.off = off;
|
||||
return (idx);
|
||||
ID &last_id(id_arr.back());
|
||||
last_id.id.bwId.regOff = regOff;
|
||||
last_id.id.bwId.off = off;
|
||||
return id_arr.size()-1;
|
||||
}
|
||||
|
||||
|
||||
@ -121,71 +147,68 @@ int LOCAL_ID::newByteWordStk(hlType t, int off, uint8_t regOff)
|
||||
* regi: indexed register into global variable
|
||||
* ix: index into icode array
|
||||
* t: HIGH_LEVEL type */
|
||||
int LOCAL_ID::newIntIdx(int16_t seg, int16_t off, eReg regi, int ix, hlType t)
|
||||
int LOCAL_ID::newIntIdx(int16_t seg, int16_t off, eReg regi, hlType t)
|
||||
{
|
||||
int idx;
|
||||
|
||||
/* Check for entry in the table */
|
||||
for (idx = 0; idx < id_arr.size(); idx++)
|
||||
for (size_t idx = 0; idx < id_arr.size(); idx++)
|
||||
{
|
||||
if (/*(locSym->id[idx].type == t) && Not checking type */
|
||||
(id_arr[idx].id.bwGlb.seg == seg) &&
|
||||
(id_arr[idx].id.bwGlb.off == off) &&
|
||||
(id_arr[idx].id.bwGlb.regi == regi))
|
||||
if (/*(locSym->id[idx].type == t) and Not checking type */
|
||||
(id_arr[idx].id.bwGlb.seg == seg) and
|
||||
(id_arr[idx].id.bwGlb.off == off) and
|
||||
(id_arr[idx].id.bwGlb.regi == regi))
|
||||
return (idx);
|
||||
}
|
||||
|
||||
/* Not in the table, create new identifier */
|
||||
newIdent (t, GLB_FRAME);
|
||||
idx = id_arr.size() - 1;
|
||||
id_arr[idx].id.bwGlb.seg = seg;
|
||||
id_arr[idx].id.bwGlb.off = off;
|
||||
id_arr[idx].id.bwGlb.regi = regi;
|
||||
return (idx);
|
||||
id_arr.back().id.bwGlb.seg = seg;
|
||||
id_arr.back().id.bwGlb.off = off;
|
||||
id_arr.back().id.bwGlb.regi = regi;
|
||||
return id_arr.size() - 1;
|
||||
}
|
||||
|
||||
|
||||
/* Checks if the entry exists in the locSym, if so, returns the idx to this
|
||||
* entry; otherwise creates a new register identifier node of type
|
||||
* TYPE_LONG_(UN)SIGN and returns the index to this new entry. */
|
||||
int LOCAL_ID::newLongReg(hlType t, eReg regH, eReg regL, iICODE ix_)
|
||||
int LOCAL_ID::newLongReg(hlType t, const LONGID_TYPE &longT, iICODE ix_)
|
||||
{
|
||||
eReg regH,regL;
|
||||
regL = longT.l();
|
||||
regH = longT.h();
|
||||
size_t idx;
|
||||
//iICODE ix_;
|
||||
/* Check for entry in the table */
|
||||
for (idx = 0; idx < id_arr.size(); idx++)
|
||||
{
|
||||
ID &entry(id_arr[idx]);
|
||||
if (/*(locSym->id[idx].type == t) && Not checking type */
|
||||
(entry.id.longId.h == regH) &&
|
||||
(entry.id.longId.l == regL))
|
||||
if(not entry.isLongRegisterPair())
|
||||
continue;
|
||||
if (/*(locSym->id[idx].type == t) and Not checking type */
|
||||
(entry.longId().h() == regH) and
|
||||
(entry.longId().l() == regL))
|
||||
{
|
||||
/* Check for occurrence in the list */
|
||||
if (entry.idx.inList(ix_))
|
||||
return (idx);
|
||||
return idx;
|
||||
else
|
||||
{
|
||||
/* Insert icode index in list */
|
||||
entry.idx.push_back(ix_);
|
||||
//entry.idx.insert(ix_);
|
||||
return (idx);
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Not in the table, create new identifier */
|
||||
newIdent (t, REG_FRAME);
|
||||
id_arr[id_arr.size()-1].idx.push_back(ix_);//insert(ix_);
|
||||
idx = id_arr.size() - 1;
|
||||
id_arr[idx].id.longId.h = regH;
|
||||
id_arr[idx].id.longId.l = regL;
|
||||
return (idx);
|
||||
id_arr.emplace_back(t, LONGID_TYPE(regH,regL));
|
||||
id_arr.back().idx.push_back(ix_);
|
||||
return (id_arr.size() - 1);
|
||||
}
|
||||
/* Returns an identifier conditional expression node of type TYPE_LONG or
|
||||
* TYPE_WORD_SIGN */
|
||||
COND_EXPR * LOCAL_ID::createId(const ID *retVal, iICODE ix_)
|
||||
/** \returns an identifier conditional expression node of type TYPE_LONG or TYPE_WORD_SIGN */
|
||||
AstIdent * LOCAL_ID::createId(const ID *retVal, iICODE ix_)
|
||||
{
|
||||
return COND_EXPR::idID(retVal,this,ix_);
|
||||
return AstIdent::idID(retVal,this,ix_);
|
||||
}
|
||||
|
||||
/* Checks if the entry exists in the locSym, if so, returns the idx to this
|
||||
@ -198,20 +221,17 @@ int LOCAL_ID::newLongGlb(int16_t seg, int16_t offH, int16_t offL,hlType t)
|
||||
/* Check for entry in the table */
|
||||
for (idx = 0; idx < id_arr.size(); idx++)
|
||||
{
|
||||
if (/*(locSym->id[idx].type == t) && Not checking type */
|
||||
(id_arr[idx].id.longGlb.seg == seg) &&
|
||||
(id_arr[idx].id.longGlb.offH == offH) &&
|
||||
(id_arr[idx].id.longGlb.offL == offL))
|
||||
if (/*(locSym->id[idx].type == t) and Not checking type */
|
||||
(id_arr[idx].id.longGlb.seg == seg) and
|
||||
(id_arr[idx].id.longGlb.offH == offH) and
|
||||
(id_arr[idx].id.longGlb.offL == offL))
|
||||
return (idx);
|
||||
}
|
||||
|
||||
printf("%d",t);
|
||||
/* Not in the table, create new identifier */
|
||||
newIdent (t, GLB_FRAME);
|
||||
idx = id_arr.size() - 1;
|
||||
id_arr[idx].id.longGlb.seg = seg;
|
||||
id_arr[idx].id.longGlb.offH = offH;
|
||||
id_arr[idx].id.longGlb.offL = offL;
|
||||
return (idx);
|
||||
id_arr.emplace_back(t, LONGGLB_TYPE(seg,offH,offL));
|
||||
return id_arr.size() - 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -220,27 +240,20 @@ int LOCAL_ID::newLongGlb(int16_t seg, int16_t offH, int16_t offL,hlType t)
|
||||
* TYPE_LONG_(UN)SIGN and returns the index to this new entry. */
|
||||
int LOCAL_ID::newLongIdx( int16_t seg, int16_t offH, int16_t offL,uint8_t regi, hlType t)
|
||||
{
|
||||
size_t idx;
|
||||
|
||||
/* Check for entry in the table */
|
||||
for (idx = 0; idx < id_arr.size(); idx++)
|
||||
for (size_t idx = 0; idx < id_arr.size(); idx++)
|
||||
{
|
||||
if (/*(locSym->id[idx].type == t) && Not checking type */
|
||||
(id_arr[idx].id.longGlb.seg == seg) &&
|
||||
(id_arr[idx].id.longGlb.offH == offH) &&
|
||||
(id_arr[idx].id.longGlb.offL == offL) &&
|
||||
(id_arr[idx].id.longGlb.regi == regi))
|
||||
if (/*(locSym->id[idx].type == t) and Not checking type */
|
||||
(id_arr[idx].id.longGlb.seg == seg) and
|
||||
(id_arr[idx].id.longGlb.offH == offH) and
|
||||
(id_arr[idx].id.longGlb.offL == offL) and
|
||||
(id_arr[idx].id.longGlb.regi == regi))
|
||||
return (idx);
|
||||
}
|
||||
|
||||
/* Not in the table, create new identifier */
|
||||
newIdent (t, GLB_FRAME);
|
||||
idx = id_arr.size() - 1;
|
||||
id_arr[idx].id.longGlb.seg = seg;
|
||||
id_arr[idx].id.longGlb.offH = offH;
|
||||
id_arr[idx].id.longGlb.offL = offL;
|
||||
id_arr[idx].id.longGlb.regi = regi;
|
||||
return (idx);
|
||||
id_arr.emplace_back(t,LONGGLB_TYPE(seg,offH,offL,regi));
|
||||
return id_arr.size() - 1;
|
||||
}
|
||||
|
||||
|
||||
@ -253,9 +266,11 @@ int LOCAL_ID::newLongStk(hlType t, int offH, int offL)
|
||||
/* Check for entry in the table */
|
||||
for (idx = 0; idx < id_arr.size(); idx++)
|
||||
{
|
||||
if ((id_arr[idx].type == t) &&
|
||||
(id_arr[idx].id.longStkId.offH == offH) &&
|
||||
(id_arr[idx].id.longStkId.offL == offL))
|
||||
if(id_arr[idx].loc!=STK_FRAME)
|
||||
continue;
|
||||
if ((id_arr[idx].type == t) and
|
||||
(id_arr[idx].longStkId().offH == offH) and
|
||||
(id_arr[idx].longStkId().offL == offL))
|
||||
return (idx);
|
||||
}
|
||||
|
||||
@ -264,11 +279,8 @@ int LOCAL_ID::newLongStk(hlType t, int offH, int offL)
|
||||
flagByteWordId (offL);
|
||||
|
||||
/* Create new identifier */
|
||||
newIdent (t, STK_FRAME);
|
||||
idx = id_arr.size() - 1;
|
||||
id_arr[idx].id.longStkId.offH = offH;
|
||||
id_arr[idx].id.longStkId.offL = offL;
|
||||
return (idx);
|
||||
id_arr.emplace_back(t,LONG_STKID_TYPE(offH,offL));
|
||||
return (id_arr.size() - 1);
|
||||
}
|
||||
|
||||
|
||||
@ -277,9 +289,9 @@ int LOCAL_ID::newLongStk(hlType t, int offH, int offL)
|
||||
* number in an expression record. */
|
||||
int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, LLInst &atOffset)
|
||||
{
|
||||
size_t idx;
|
||||
size_t idx = ~0; //WARNING: clients of this method might propagate this bogus value!
|
||||
const LLOperand *pmH, *pmL;
|
||||
LLInst &p_ll(*pIcode->ll());
|
||||
LLInst &p_ll(*pIcode->ll());
|
||||
if (f == LOW_FIRST)
|
||||
{
|
||||
pmL = p_ll.get(sd);
|
||||
@ -296,7 +308,7 @@ int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, L
|
||||
|
||||
else if (pmL->regi < INDEX_BX_SI) /* register */
|
||||
{
|
||||
idx = newLongReg(TYPE_LONG_SIGN, pmH->regi, pmL->regi, ix);
|
||||
idx = newLongReg(TYPE_LONG_SIGN, LONGID_TYPE(pmH->regi, pmL->regi), ix);
|
||||
if (f == HIGH_FIRST)
|
||||
pIcode->setRegDU( pmL->regi, du); /* low part */
|
||||
else
|
||||
@ -304,9 +316,9 @@ int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, L
|
||||
}
|
||||
|
||||
else if (pmL->off) { /* offset */
|
||||
if ((pmL->seg == rSS) && (pmL->regi == INDEX_BP)) /* idx on bp */
|
||||
if ((pmL->seg == rSS) and (pmL->regi == INDEX_BP)) /* idx on bp */
|
||||
idx = newLongStk(TYPE_LONG_SIGN, pmH->off, pmL->off);
|
||||
else if ((pmL->seg == rDS) && (pmL->regi == INDEX_BX)) /* bx */
|
||||
else if ((pmL->seg == rDS) and (pmL->regi == INDEX_BX)) /* bx */
|
||||
{ /* glb var indexed on bx */
|
||||
printf("Bx indexed global, BX is an unused parameter to newLongIdx\n");
|
||||
idx = newLongIdx(pmH->segValue, pmH->off, pmL->off,rBX,TYPE_LONG_SIGN);
|
||||
@ -316,10 +328,10 @@ int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, L
|
||||
printf ("long not supported, idx <> bp\n");
|
||||
}
|
||||
|
||||
else /* (pm->regi >= INDEXBASE && pm->off = 0) => indexed && no off */
|
||||
printf ("long not supported, idx && no off\n");
|
||||
else /* (pm->regi >= INDEXBASE and pm->off = 0) => indexed and no off */
|
||||
printf ("long not supported, idx and no off\n");
|
||||
|
||||
return (idx);
|
||||
return idx;
|
||||
}
|
||||
|
||||
|
||||
@ -332,30 +344,46 @@ int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, L
|
||||
* idx : idx into icode array
|
||||
* pProc : ptr to current procedure record
|
||||
* rhs, lhs : return expressions if successful. */
|
||||
boolT checkLongEq (LONG_STKID_TYPE longId, iICODE pIcode, int i, Function * pProc, Assignment &asgn, LLInst &atOffset)
|
||||
bool checkLongEq (LONG_STKID_TYPE longId, iICODE pIcode, int i, Function * pProc, Assignment &asgn, LLInst &atOffset)
|
||||
{
|
||||
/* pointers to LOW_LEVEL icodes */
|
||||
const LLOperand *pmHdst, *pmLdst, *pmHsrc, *pmLsrc;
|
||||
|
||||
pmHdst = &pIcode->ll()->dst;
|
||||
pmLdst = &atOffset.dst;
|
||||
pmHdst = &pIcode->ll()->m_dst;
|
||||
pmLdst = &atOffset.m_dst;
|
||||
pmHsrc = &pIcode->ll()->src();
|
||||
pmLsrc = &atOffset.src();
|
||||
// if ((longId.offH == pmHsrc->off) and (longId.offL == pmLsrc->off))
|
||||
// {
|
||||
// asgn.lhs = AstIdent::LongIdx (i);
|
||||
|
||||
if ((longId.offH == pmHdst->off) && (longId.offL == pmLdst->off))
|
||||
// if ( not pIcode->ll()->testFlags(NO_SRC) )
|
||||
// {
|
||||
// asgn.rhs = AstIdent::Long (&pProc->localId, SRC, pIcode, HIGH_FIRST, pIcode, eUSE, atOffset);
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
// else if ((longId.offH == pmHdst->off) and (longId.offL == pmLdst->off))
|
||||
// {
|
||||
// asgn.lhs = AstIdent::Long (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode,eDEF, atOffset);
|
||||
// asgn.rhs = AstIdent::LongIdx (i);
|
||||
// return true;
|
||||
// }
|
||||
|
||||
if ((longId.offH == pmHdst->off) and (longId.offL == pmLdst->off))
|
||||
{
|
||||
asgn.lhs = COND_EXPR::idLongIdx (i);
|
||||
asgn.lhs = AstIdent::LongIdx (i);
|
||||
|
||||
if ( not pIcode->ll()->testFlags(NO_SRC) )
|
||||
{
|
||||
asgn.rhs = COND_EXPR::idLong (&pProc->localId, SRC, pIcode, HIGH_FIRST, pIcode, eUSE, atOffset);
|
||||
asgn.rhs = AstIdent::Long (&pProc->localId, SRC, pIcode, HIGH_FIRST, pIcode, eUSE, atOffset);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if ((longId.offH == pmHsrc->off) && (longId.offL == pmLsrc->off))
|
||||
else if ((longId.offH == pmHsrc->off) and (longId.offL == pmLsrc->off))
|
||||
{
|
||||
asgn.lhs = COND_EXPR::idLong (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode,eDEF, atOffset);
|
||||
asgn.rhs = COND_EXPR::idLongIdx (i);
|
||||
asgn.lhs = AstIdent::Long (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode,eDEF, atOffset);
|
||||
asgn.rhs = AstIdent::LongIdx (i);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -371,54 +399,48 @@ boolT checkLongEq (LONG_STKID_TYPE longId, iICODE pIcode, int i, Function * pPro
|
||||
* idx : idx into icode array
|
||||
* pProc : ptr to current procedure record
|
||||
* rhs, lhs : return expressions if successful. */
|
||||
boolT checkLongRegEq (LONGID_TYPE longId, iICODE pIcode, int i,
|
||||
Function * pProc, Assignment &asgn, LLInst &atOffset)
|
||||
bool checkLongRegEq (LONGID_TYPE longId, iICODE pIcode, int i,
|
||||
Function * pProc, Assignment &asgn, LLInst &atOffset)
|
||||
{
|
||||
/* pointers to LOW_LEVEL icodes */
|
||||
const LLOperand *pmHdst, *pmLdst, *pmHsrc, *pmLsrc;
|
||||
|
||||
pmHdst = &pIcode->ll()->dst;
|
||||
pmLdst = &atOffset.dst;
|
||||
pmHdst = &pIcode->ll()->m_dst;
|
||||
pmLdst = &atOffset.m_dst;
|
||||
pmHsrc = &pIcode->ll()->src();
|
||||
pmLsrc = &atOffset.src();
|
||||
|
||||
if ((longId.h == pmHdst->regi) && (longId.l == pmLdst->regi))
|
||||
if ((longId.h() == pmHdst->regi) and (longId.l() == pmLdst->regi))
|
||||
{
|
||||
asgn.lhs = COND_EXPR::idLongIdx (i);
|
||||
asgn.lhs = AstIdent::LongIdx (i);
|
||||
if ( not pIcode->ll()->testFlags(NO_SRC) )
|
||||
{
|
||||
asgn.rhs = COND_EXPR::idLong (&pProc->localId, SRC, pIcode, HIGH_FIRST, pIcode, eUSE, atOffset);
|
||||
asgn.rhs = AstIdent::Long (&pProc->localId, SRC, pIcode, HIGH_FIRST, pIcode, eUSE, atOffset);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if ((longId.h == pmHsrc->regi) && (longId.l == pmLsrc->regi))
|
||||
else if ((longId.h() == pmHsrc->regi) and (longId.l() == pmLsrc->regi))
|
||||
{
|
||||
asgn.lhs = COND_EXPR::idLong (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode, eDEF, atOffset);
|
||||
asgn.rhs = COND_EXPR::idLongIdx (i);
|
||||
asgn.lhs = AstIdent::Long (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode, eDEF, atOffset);
|
||||
asgn.rhs = AstIdent::LongIdx (i);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Given an index into the local identifier table for a long register
|
||||
* variable, determines whether regi is the high or low part, and returns
|
||||
* the other part */
|
||||
eReg otherLongRegi (eReg regi, int idx, LOCAL_ID *locTbl)
|
||||
eReg LOCAL_ID::getPairedRegisterAt(int idx,eReg regi) const
|
||||
{
|
||||
ID *id;
|
||||
|
||||
id = &locTbl->id_arr[idx];
|
||||
if ((id->loc == REG_FRAME) && ((id->type == TYPE_LONG_SIGN) ||
|
||||
(id->type == TYPE_LONG_UNSIGN)))
|
||||
eReg res=rUNDEF; // Cristina: please check this!
|
||||
const ID *id = &id_arr[idx];
|
||||
if (id->isLongRegisterPair())
|
||||
{
|
||||
if (id->id.longId.h == regi)
|
||||
return (id->id.longId.l);
|
||||
else if (id->id.longId.l == regi)
|
||||
return (id->id.longId.h);
|
||||
res = id->getPairedRegister(regi);
|
||||
}
|
||||
return rUNDEF; // Cristina: please check this!
|
||||
qWarning() << "Cannot find paired register";
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@ -426,7 +448,7 @@ eReg otherLongRegi (eReg regi, int idx, LOCAL_ID *locTbl)
|
||||
* the local identifier table. If so, macros for these registers are
|
||||
* placed in the local identifier table, as these registers belong to a
|
||||
* long register identifier. */
|
||||
void LOCAL_ID::propLongId (uint8_t regL, uint8_t regH, const char *name)
|
||||
void LOCAL_ID::propLongId (uint8_t regL, uint8_t regH, const QString &name)
|
||||
{
|
||||
for (ID &rid : id_arr)
|
||||
{
|
||||
@ -441,9 +463,9 @@ void LOCAL_ID::propLongId (uint8_t regL, uint8_t regH, const char *name)
|
||||
if (rid.id.regi == regL)
|
||||
{
|
||||
strcpy (rid.macro, "LO");
|
||||
}
|
||||
}
|
||||
else // if (rid.id.regi == regH)
|
||||
{
|
||||
{
|
||||
strcpy (rid.macro, "HI");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,14 +1,20 @@
|
||||
#include <cassert>
|
||||
#include "machine_x86.h"
|
||||
|
||||
#include "msvc_fixes.h"
|
||||
#include "icode.h"
|
||||
|
||||
#include <QtCore/QTextStream>
|
||||
#include <cassert>
|
||||
|
||||
// Index registers **** temp solution
|
||||
static const std::string regNames[] = {
|
||||
static const QString regNames[] = {
|
||||
"undef",
|
||||
"ax", "cx", "dx", "bx",
|
||||
"sp", "bp", "si", "di",
|
||||
"es", "cs", "ss", "ds",
|
||||
"al", "cl", "dl", "bl",
|
||||
"ah", "ch", "dh", "bh",
|
||||
"tmp",
|
||||
"tmp","tmp2",
|
||||
"bx+si", "bx+di", "bp+si", "bp+di",
|
||||
"si", "di", "bp", "bx"
|
||||
};
|
||||
@ -16,17 +22,17 @@ static const std::string regNames[] = {
|
||||
/* uint8_t and uint16_t registers */
|
||||
Machine_X86::Machine_X86()
|
||||
{
|
||||
static_assert((sizeof(regNames)/sizeof(std::string))==LAST_REG,
|
||||
"Reg count not equal number of strings");
|
||||
static_assert((sizeof(regNames)/sizeof(QString))==LAST_REG,
|
||||
"Reg count not equal number of strings");
|
||||
}
|
||||
|
||||
const std::string &Machine_X86::regName(eReg r)
|
||||
const QString &Machine_X86::regName(eReg r)
|
||||
{
|
||||
assert(r<(sizeof(regNames)/sizeof(std::string)));
|
||||
assert(r<(sizeof(regNames)/sizeof(QString)));
|
||||
return regNames[r];
|
||||
}
|
||||
|
||||
static const std::string szOps[] =
|
||||
static const QString szOps[] =
|
||||
{
|
||||
"CBW", "AAA", "AAD", "AAM", "AAS", "ADC", "ADD", "AND",
|
||||
"BOUND","CALL", "CALL", "CLC", "CLD", "CLI", "CMC", "CMP",
|
||||
@ -44,7 +50,7 @@ static const std::string szOps[] =
|
||||
"XLAT", "XOR", "INTO", "NOP", "REPNE", "REPE", "MOD"
|
||||
};
|
||||
/* The following opcodes are for mod != 3 */
|
||||
static std::string szFlops1[] =
|
||||
static const QString szFlops1[] =
|
||||
{
|
||||
/* 0 1 2 3 4 5 6 7 */
|
||||
"FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 00 */
|
||||
@ -57,7 +63,7 @@ static std::string szFlops1[] =
|
||||
"FILD", "???", "FIST", "FISTP", "FBLD", "???", "FBSTP", "FISTP" /* 38 */
|
||||
};
|
||||
/* The following opcodes are for mod == 3 */
|
||||
static std::string szFlops2[] =
|
||||
static const QString szFlops2[] =
|
||||
{
|
||||
/* 0 1 2 3 4 5 6 7 */
|
||||
"FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 00 */
|
||||
@ -70,17 +76,17 @@ static std::string szFlops2[] =
|
||||
"FILD", "???", "FIST", "FISTP", "", "???", "FBSTP", "FISTP" /* 38 */
|
||||
};
|
||||
|
||||
const std::string &Machine_X86::opcodeName(unsigned r)
|
||||
const QString &Machine_X86::opcodeName(unsigned r)
|
||||
{
|
||||
assert(r<(sizeof(szOps)/sizeof(std::string)));
|
||||
assert(r<(sizeof(szOps)/sizeof(QString)));
|
||||
return szOps[r];
|
||||
}
|
||||
const std::string &Machine_X86::floatOpName(unsigned r)
|
||||
const QString &Machine_X86::floatOpName(unsigned r)
|
||||
{
|
||||
if(r>=(sizeof(szFlops1)/sizeof(std::string)))
|
||||
if(r>=(sizeof(szFlops1)/sizeof(QString)))
|
||||
{
|
||||
r-= (sizeof(szFlops1)/sizeof(std::string));
|
||||
assert(r<(sizeof(szFlops2)/sizeof(std::string)));
|
||||
r-= (sizeof(szFlops1)/sizeof(QString));
|
||||
assert(r<(sizeof(szFlops2)/sizeof(QString)));
|
||||
return szFlops2[r];
|
||||
}
|
||||
return szFlops1[r];
|
||||
@ -88,11 +94,11 @@ const std::string &Machine_X86::floatOpName(unsigned r)
|
||||
|
||||
bool Machine_X86::physicalReg(eReg r)
|
||||
{
|
||||
return (r>=rAX) && (r<rTMP);
|
||||
return (r>=rAX) and (r<rTMP);
|
||||
}
|
||||
bool Machine_X86::isMemOff(eReg r)
|
||||
{
|
||||
return r == 0 || r >= INDEX_BX_SI;
|
||||
return r == 0 or r >= INDEX_BX_SI;
|
||||
}
|
||||
//TODO: Move these to Machine_X86
|
||||
eReg Machine_X86::subRegH(eReg reg)
|
||||
@ -105,7 +111,39 @@ eReg Machine_X86::subRegL(eReg reg)
|
||||
}
|
||||
bool Machine_X86::isSubRegisterOf(eReg reg,eReg parent)
|
||||
{
|
||||
if ((parent < rAX) || (parent > rBX))
|
||||
if ((parent < rAX) or (parent > rBX))
|
||||
return false; // only AX -> BX are coverede by subregisters
|
||||
return ((reg==subRegH(parent)) || (reg == subRegL(parent)));
|
||||
return ((reg==subRegH(parent)) or (reg == subRegL(parent)));
|
||||
}
|
||||
bool Machine_X86::hasSubregisters(eReg reg)
|
||||
{
|
||||
return ((reg >= rAX) and (reg <= rBX));
|
||||
}
|
||||
|
||||
bool Machine_X86::isPartOfComposite(eReg reg)
|
||||
{
|
||||
return ((reg >= rAL) and (reg <= rBH));
|
||||
}
|
||||
|
||||
eReg Machine_X86::compositeParent(eReg reg)
|
||||
{
|
||||
switch(reg)
|
||||
{
|
||||
case rAL: case rAH: return rAX;
|
||||
case rCL: case rCH: return rCX;
|
||||
case rDL: case rDH: return rDX;
|
||||
case rBL: case rBH: return rBX;
|
||||
default:
|
||||
return rUNDEF;
|
||||
}
|
||||
return rUNDEF;
|
||||
}
|
||||
void Machine_X86::writeRegVector (QTextStream &ostr,const LivenessSet ®i)
|
||||
{
|
||||
int j;
|
||||
for (j = rAX; j < INDEX_BX_SI; j++)
|
||||
{
|
||||
if (regi.testReg(j))
|
||||
ostr << regName(eReg(j))<<" ";
|
||||
}
|
||||
}
|
||||
|
||||
923
src/parser.cpp
923
src/parser.cpp
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user