metasm 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.hgtags +3 -0
- data/Gemfile +1 -0
- data/INSTALL +61 -0
- data/LICENCE +458 -0
- data/README +29 -21
- data/Rakefile +10 -0
- data/TODO +10 -12
- data/doc/code_organisation.txt +2 -0
- data/doc/core/DynLdr.txt +247 -0
- data/doc/core/ExeFormat.txt +43 -0
- data/doc/core/Expression.txt +220 -0
- data/doc/core/GNUExports.txt +27 -0
- data/doc/core/Ia32.txt +236 -0
- data/doc/core/SerialStruct.txt +108 -0
- data/doc/core/VirtualString.txt +145 -0
- data/doc/core/WindowsExports.txt +61 -0
- data/doc/core/index.txt +1 -0
- data/doc/style.css +6 -3
- data/doc/usage/debugger.txt +327 -0
- data/doc/usage/index.txt +1 -0
- data/doc/use_cases.txt +2 -2
- data/metasm.gemspec +22 -0
- data/{lib/metasm.rb → metasm.rb} +11 -3
- data/{lib/metasm → metasm}/compile_c.rb +13 -7
- data/metasm/cpu/arc.rb +8 -0
- data/metasm/cpu/arc/decode.rb +425 -0
- data/metasm/cpu/arc/main.rb +191 -0
- data/metasm/cpu/arc/opcodes.rb +588 -0
- data/{lib/metasm → metasm/cpu}/arm.rb +7 -5
- data/{lib/metasm → metasm/cpu}/arm/debug.rb +2 -2
- data/{lib/metasm → metasm/cpu}/arm/decode.rb +13 -12
- data/{lib/metasm → metasm/cpu}/arm/encode.rb +23 -8
- data/{lib/metasm → metasm/cpu}/arm/main.rb +0 -3
- data/metasm/cpu/arm/opcodes.rb +324 -0
- data/{lib/metasm → metasm/cpu}/arm/parse.rb +25 -13
- data/{lib/metasm → metasm/cpu}/arm/render.rb +2 -2
- data/metasm/cpu/arm64.rb +15 -0
- data/metasm/cpu/arm64/debug.rb +38 -0
- data/metasm/cpu/arm64/decode.rb +289 -0
- data/metasm/cpu/arm64/encode.rb +41 -0
- data/metasm/cpu/arm64/main.rb +105 -0
- data/metasm/cpu/arm64/opcodes.rb +232 -0
- data/metasm/cpu/arm64/parse.rb +20 -0
- data/metasm/cpu/arm64/render.rb +95 -0
- data/{lib/metasm/ppc.rb → metasm/cpu/bpf.rb} +2 -4
- data/metasm/cpu/bpf/decode.rb +142 -0
- data/metasm/cpu/bpf/main.rb +60 -0
- data/metasm/cpu/bpf/opcodes.rb +81 -0
- data/metasm/cpu/bpf/render.rb +41 -0
- data/metasm/cpu/cy16.rb +9 -0
- data/metasm/cpu/cy16/decode.rb +253 -0
- data/metasm/cpu/cy16/main.rb +63 -0
- data/metasm/cpu/cy16/opcodes.rb +78 -0
- data/metasm/cpu/cy16/render.rb +41 -0
- data/metasm/cpu/dalvik.rb +11 -0
- data/{lib/metasm → metasm/cpu}/dalvik/decode.rb +35 -13
- data/{lib/metasm → metasm/cpu}/dalvik/main.rb +51 -2
- data/{lib/metasm → metasm/cpu}/dalvik/opcodes.rb +19 -11
- data/metasm/cpu/ia32.rb +17 -0
- data/{lib/metasm → metasm/cpu}/ia32/compile_c.rb +5 -7
- data/{lib/metasm → metasm/cpu}/ia32/debug.rb +5 -5
- data/{lib/metasm → metasm/cpu}/ia32/decode.rb +246 -59
- data/{lib/metasm → metasm/cpu}/ia32/decompile.rb +7 -7
- data/{lib/metasm → metasm/cpu}/ia32/encode.rb +19 -13
- data/{lib/metasm → metasm/cpu}/ia32/main.rb +51 -8
- data/metasm/cpu/ia32/opcodes.rb +1424 -0
- data/{lib/metasm → metasm/cpu}/ia32/parse.rb +47 -16
- data/{lib/metasm → metasm/cpu}/ia32/render.rb +31 -4
- data/metasm/cpu/mips.rb +14 -0
- data/{lib/metasm → metasm/cpu}/mips/compile_c.rb +1 -1
- data/metasm/cpu/mips/debug.rb +42 -0
- data/{lib/metasm → metasm/cpu}/mips/decode.rb +46 -16
- data/{lib/metasm → metasm/cpu}/mips/encode.rb +4 -3
- data/{lib/metasm → metasm/cpu}/mips/main.rb +11 -4
- data/{lib/metasm → metasm/cpu}/mips/opcodes.rb +86 -17
- data/{lib/metasm → metasm/cpu}/mips/parse.rb +1 -1
- data/{lib/metasm → metasm/cpu}/mips/render.rb +1 -1
- data/{lib/metasm/dalvik.rb → metasm/cpu/msp430.rb} +1 -1
- data/metasm/cpu/msp430/decode.rb +247 -0
- data/metasm/cpu/msp430/main.rb +62 -0
- data/metasm/cpu/msp430/opcodes.rb +101 -0
- data/{lib/metasm → metasm/cpu}/pic16c/decode.rb +6 -7
- data/{lib/metasm → metasm/cpu}/pic16c/main.rb +0 -0
- data/{lib/metasm → metasm/cpu}/pic16c/opcodes.rb +1 -1
- data/{lib/metasm/mips.rb → metasm/cpu/ppc.rb} +4 -4
- data/{lib/metasm → metasm/cpu}/ppc/decode.rb +18 -12
- data/{lib/metasm → metasm/cpu}/ppc/decompile.rb +3 -3
- data/{lib/metasm → metasm/cpu}/ppc/encode.rb +2 -2
- data/{lib/metasm → metasm/cpu}/ppc/main.rb +17 -12
- data/{lib/metasm → metasm/cpu}/ppc/opcodes.rb +11 -5
- data/metasm/cpu/ppc/parse.rb +55 -0
- data/metasm/cpu/python.rb +8 -0
- data/metasm/cpu/python/decode.rb +136 -0
- data/metasm/cpu/python/main.rb +36 -0
- data/metasm/cpu/python/opcodes.rb +180 -0
- data/{lib/metasm → metasm/cpu}/sh4.rb +1 -1
- data/{lib/metasm → metasm/cpu}/sh4/decode.rb +48 -17
- data/{lib/metasm → metasm/cpu}/sh4/main.rb +13 -4
- data/{lib/metasm → metasm/cpu}/sh4/opcodes.rb +7 -8
- data/metasm/cpu/x86_64.rb +15 -0
- data/{lib/metasm → metasm/cpu}/x86_64/compile_c.rb +28 -17
- data/{lib/metasm → metasm/cpu}/x86_64/debug.rb +4 -4
- data/{lib/metasm → metasm/cpu}/x86_64/decode.rb +57 -15
- data/{lib/metasm → metasm/cpu}/x86_64/encode.rb +55 -26
- data/{lib/metasm → metasm/cpu}/x86_64/main.rb +14 -6
- data/metasm/cpu/x86_64/opcodes.rb +136 -0
- data/{lib/metasm → metasm/cpu}/x86_64/parse.rb +10 -2
- data/metasm/cpu/x86_64/render.rb +35 -0
- data/metasm/cpu/z80.rb +9 -0
- data/metasm/cpu/z80/decode.rb +313 -0
- data/metasm/cpu/z80/main.rb +67 -0
- data/metasm/cpu/z80/opcodes.rb +224 -0
- data/metasm/cpu/z80/render.rb +59 -0
- data/{lib/metasm/os/main.rb → metasm/debug.rb} +160 -401
- data/{lib/metasm → metasm}/decode.rb +35 -4
- data/{lib/metasm → metasm}/decompile.rb +15 -16
- data/{lib/metasm → metasm}/disassemble.rb +201 -45
- data/{lib/metasm → metasm}/disassemble_api.rb +651 -87
- data/{lib/metasm → metasm}/dynldr.rb +220 -133
- data/{lib/metasm → metasm}/encode.rb +10 -1
- data/{lib/metasm → metasm}/exe_format/a_out.rb +9 -6
- data/{lib/metasm → metasm}/exe_format/autoexe.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/bflt.rb +57 -27
- data/{lib/metasm → metasm}/exe_format/coff.rb +11 -3
- data/{lib/metasm → metasm}/exe_format/coff_decode.rb +53 -20
- data/{lib/metasm → metasm}/exe_format/coff_encode.rb +11 -13
- data/{lib/metasm → metasm}/exe_format/dex.rb +13 -5
- data/{lib/metasm → metasm}/exe_format/dol.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/elf.rb +93 -57
- data/{lib/metasm → metasm}/exe_format/elf_decode.rb +143 -34
- data/{lib/metasm → metasm}/exe_format/elf_encode.rb +122 -31
- data/metasm/exe_format/gb.rb +65 -0
- data/metasm/exe_format/javaclass.rb +424 -0
- data/{lib/metasm → metasm}/exe_format/macho.rb +204 -16
- data/{lib/metasm → metasm}/exe_format/main.rb +26 -3
- data/{lib/metasm → metasm}/exe_format/mz.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/nds.rb +7 -4
- data/{lib/metasm → metasm}/exe_format/pe.rb +71 -8
- data/metasm/exe_format/pyc.rb +167 -0
- data/{lib/metasm → metasm}/exe_format/serialstruct.rb +67 -14
- data/{lib/metasm → metasm}/exe_format/shellcode.rb +7 -3
- data/metasm/exe_format/shellcode_rwx.rb +114 -0
- data/metasm/exe_format/swf.rb +205 -0
- data/{lib/metasm → metasm}/exe_format/xcoff.rb +7 -7
- data/metasm/exe_format/zip.rb +335 -0
- data/metasm/gui.rb +13 -0
- data/{lib/metasm → metasm}/gui/cstruct.rb +35 -41
- data/{lib/metasm → metasm}/gui/dasm_coverage.rb +11 -11
- data/{lib/metasm → metasm}/gui/dasm_decomp.rb +7 -20
- data/{lib/metasm → metasm}/gui/dasm_funcgraph.rb +0 -0
- data/metasm/gui/dasm_graph.rb +1695 -0
- data/{lib/metasm → metasm}/gui/dasm_hex.rb +12 -8
- data/{lib/metasm → metasm}/gui/dasm_listing.rb +43 -28
- data/{lib/metasm → metasm}/gui/dasm_main.rb +310 -53
- data/{lib/metasm → metasm}/gui/dasm_opcodes.rb +5 -19
- data/{lib/metasm → metasm}/gui/debug.rb +93 -27
- data/{lib/metasm → metasm}/gui/gtk.rb +162 -40
- data/{lib/metasm → metasm}/gui/qt.rb +12 -2
- data/{lib/metasm → metasm}/gui/win32.rb +179 -42
- data/{lib/metasm → metasm}/gui/x11.rb +59 -59
- data/{lib/metasm → metasm}/main.rb +389 -264
- data/{lib/metasm/os/remote.rb → metasm/os/gdbremote.rb} +146 -54
- data/{lib/metasm → metasm}/os/gnu_exports.rb +1 -1
- data/{lib/metasm → metasm}/os/linux.rb +628 -151
- data/metasm/os/main.rb +330 -0
- data/{lib/metasm → metasm}/os/windows.rb +132 -42
- data/{lib/metasm → metasm}/os/windows_exports.rb +141 -0
- data/{lib/metasm → metasm}/parse.rb +26 -24
- data/{lib/metasm → metasm}/parse_c.rb +221 -116
- data/{lib/metasm → metasm}/preprocessor.rb +55 -40
- data/{lib/metasm → metasm}/render.rb +14 -38
- data/misc/hexdump.rb +2 -1
- data/misc/lint.rb +58 -0
- data/misc/txt2html.rb +9 -7
- data/samples/bindiff.rb +3 -4
- data/samples/dasm-plugins/bindiff.rb +15 -0
- data/samples/dasm-plugins/bookmark.rb +133 -0
- data/samples/dasm-plugins/c_constants.rb +57 -0
- data/samples/dasm-plugins/colortheme_solarized.rb +125 -0
- data/samples/dasm-plugins/cppobj_funcall.rb +60 -0
- data/samples/dasm-plugins/dasm_all.rb +70 -0
- data/samples/dasm-plugins/demangle_cpp.rb +31 -0
- data/samples/dasm-plugins/deobfuscate.rb +251 -0
- data/samples/dasm-plugins/dump_text.rb +35 -0
- data/samples/dasm-plugins/export_graph_svg.rb +86 -0
- data/samples/dasm-plugins/findgadget.rb +75 -0
- data/samples/dasm-plugins/hl_opcode.rb +32 -0
- data/samples/dasm-plugins/hotfix_gtk_dbg.rb +19 -0
- data/samples/dasm-plugins/imm2off.rb +34 -0
- data/samples/dasm-plugins/match_libsigs.rb +93 -0
- data/samples/dasm-plugins/patch_file.rb +95 -0
- data/samples/dasm-plugins/scanfuncstart.rb +36 -0
- data/samples/dasm-plugins/scanxrefs.rb +26 -0
- data/samples/dasm-plugins/selfmodify.rb +197 -0
- data/samples/dasm-plugins/stringsxrefs.rb +28 -0
- data/samples/dasmnavig.rb +1 -1
- data/samples/dbg-apihook.rb +24 -9
- data/samples/dbg-plugins/heapscan.rb +283 -0
- data/samples/dbg-plugins/heapscan/compiled_heapscan_lin.c +155 -0
- data/samples/dbg-plugins/heapscan/compiled_heapscan_win.c +128 -0
- data/samples/dbg-plugins/heapscan/graphheap.rb +616 -0
- data/samples/dbg-plugins/heapscan/heapscan.rb +709 -0
- data/samples/dbg-plugins/heapscan/winheap.h +174 -0
- data/samples/dbg-plugins/heapscan/winheap7.h +307 -0
- data/samples/dbg-plugins/trace_func.rb +214 -0
- data/samples/disassemble-gui.rb +35 -5
- data/samples/disassemble.rb +31 -6
- data/samples/dump_upx.rb +24 -12
- data/samples/dynamic_ruby.rb +12 -3
- data/samples/exeencode.rb +6 -5
- data/samples/factorize-headers-peimports.rb +1 -1
- data/samples/lindebug.rb +175 -381
- data/samples/metasm-shell.rb +1 -2
- data/samples/peldr.rb +2 -2
- data/tests/all.rb +1 -1
- data/tests/arc.rb +26 -0
- data/tests/dynldr.rb +22 -4
- data/tests/expression.rb +55 -0
- data/tests/graph_layout.rb +285 -0
- data/tests/ia32.rb +79 -26
- data/tests/mips.rb +9 -2
- data/tests/x86_64.rb +66 -18
- metadata +330 -218
- data/lib/metasm/arm/opcodes.rb +0 -177
- data/lib/metasm/gui.rb +0 -23
- data/lib/metasm/gui/dasm_graph.rb +0 -1354
- data/lib/metasm/ia32.rb +0 -14
- data/lib/metasm/ia32/opcodes.rb +0 -873
- data/lib/metasm/ppc/parse.rb +0 -52
- data/lib/metasm/x86_64.rb +0 -12
- data/lib/metasm/x86_64/opcodes.rb +0 -118
- data/samples/gdbclient.rb +0 -583
- data/samples/rubstop.rb +0 -399
|
@@ -9,31 +9,31 @@ module Metasm
|
|
|
9
9
|
module Gui
|
|
10
10
|
class XGui < DynLdr
|
|
11
11
|
new_api_c <<EOS, 'libX11.so'
|
|
12
|
-
#define KeyPressMask (1L<<0)
|
|
13
|
-
#define KeyReleaseMask (1L<<1)
|
|
14
|
-
#define ButtonPressMask (1L<<2)
|
|
15
|
-
#define ButtonReleaseMask (1L<<3)
|
|
16
|
-
#define EnterWindowMask (1L<<4)
|
|
17
|
-
#define LeaveWindowMask (1L<<5)
|
|
18
|
-
#define PointerMotionMask (1L<<6)
|
|
19
|
-
#define PointerMotionHintMask (1L<<7)
|
|
20
|
-
#define Button1MotionMask (1L<<8)
|
|
21
|
-
#define Button2MotionMask (1L<<9)
|
|
22
|
-
#define Button3MotionMask (1L<<10)
|
|
23
|
-
#define Button4MotionMask (1L<<11)
|
|
24
|
-
#define Button5MotionMask (1L<<12)
|
|
25
|
-
#define ButtonMotionMask (1L<<13)
|
|
12
|
+
#define KeyPressMask (1L<<0)
|
|
13
|
+
#define KeyReleaseMask (1L<<1)
|
|
14
|
+
#define ButtonPressMask (1L<<2)
|
|
15
|
+
#define ButtonReleaseMask (1L<<3)
|
|
16
|
+
#define EnterWindowMask (1L<<4)
|
|
17
|
+
#define LeaveWindowMask (1L<<5)
|
|
18
|
+
#define PointerMotionMask (1L<<6)
|
|
19
|
+
#define PointerMotionHintMask (1L<<7)
|
|
20
|
+
#define Button1MotionMask (1L<<8)
|
|
21
|
+
#define Button2MotionMask (1L<<9)
|
|
22
|
+
#define Button3MotionMask (1L<<10)
|
|
23
|
+
#define Button4MotionMask (1L<<11)
|
|
24
|
+
#define Button5MotionMask (1L<<12)
|
|
25
|
+
#define ButtonMotionMask (1L<<13)
|
|
26
26
|
#define KeymapStateMask (1L<<14)
|
|
27
|
-
#define ExposureMask (1L<<15)
|
|
28
|
-
#define VisibilityChangeMask (1L<<16)
|
|
29
|
-
#define StructureNotifyMask (1L<<17)
|
|
30
|
-
#define ResizeRedirectMask (1L<<18)
|
|
31
|
-
#define SubstructureNotifyMask (1L<<19)
|
|
32
|
-
#define SubstructureRedirectMask (1L<<20)
|
|
33
|
-
#define FocusChangeMask (1L<<21)
|
|
34
|
-
#define PropertyChangeMask (1L<<22)
|
|
35
|
-
#define ColormapChangeMask (1L<<23)
|
|
36
|
-
#define OwnerGrabButtonMask (1L<<24)
|
|
27
|
+
#define ExposureMask (1L<<15)
|
|
28
|
+
#define VisibilityChangeMask (1L<<16)
|
|
29
|
+
#define StructureNotifyMask (1L<<17)
|
|
30
|
+
#define ResizeRedirectMask (1L<<18)
|
|
31
|
+
#define SubstructureNotifyMask (1L<<19)
|
|
32
|
+
#define SubstructureRedirectMask (1L<<20)
|
|
33
|
+
#define FocusChangeMask (1L<<21)
|
|
34
|
+
#define PropertyChangeMask (1L<<22)
|
|
35
|
+
#define ColormapChangeMask (1L<<23)
|
|
36
|
+
#define OwnerGrabButtonMask (1L<<24)
|
|
37
37
|
|
|
38
38
|
#define KeyPress 2
|
|
39
39
|
#define KeyRelease 3
|
|
@@ -84,7 +84,7 @@ typedef struct _XGC *GC;
|
|
|
84
84
|
typedef XID Pixmap;
|
|
85
85
|
typedef XID Window;
|
|
86
86
|
|
|
87
|
-
typedef
|
|
87
|
+
typedef
|
|
88
88
|
struct {
|
|
89
89
|
int type;
|
|
90
90
|
unsigned long serial;
|
|
@@ -92,7 +92,7 @@ struct {
|
|
|
92
92
|
Display *display;
|
|
93
93
|
Window window;
|
|
94
94
|
} XAnyEvent;
|
|
95
|
-
typedef
|
|
95
|
+
typedef
|
|
96
96
|
struct {
|
|
97
97
|
int type;
|
|
98
98
|
unsigned long serial;
|
|
@@ -110,7 +110,7 @@ struct {
|
|
|
110
110
|
unsigned int button;
|
|
111
111
|
int same_screen;
|
|
112
112
|
} XButtonEvent;
|
|
113
|
-
typedef
|
|
113
|
+
typedef
|
|
114
114
|
struct {
|
|
115
115
|
int type;
|
|
116
116
|
unsigned long serial;
|
|
@@ -120,7 +120,7 @@ struct {
|
|
|
120
120
|
Window window;
|
|
121
121
|
int place;
|
|
122
122
|
} XCirculateEvent;
|
|
123
|
-
typedef
|
|
123
|
+
typedef
|
|
124
124
|
struct {
|
|
125
125
|
int type;
|
|
126
126
|
unsigned long serial;
|
|
@@ -130,7 +130,7 @@ struct {
|
|
|
130
130
|
Window window;
|
|
131
131
|
int place;
|
|
132
132
|
} XCirculateRequestEvent;
|
|
133
|
-
typedef
|
|
133
|
+
typedef
|
|
134
134
|
struct {
|
|
135
135
|
int type;
|
|
136
136
|
unsigned long serial;
|
|
@@ -146,7 +146,7 @@ struct {
|
|
|
146
146
|
long l[5];
|
|
147
147
|
} data;
|
|
148
148
|
} XClientMessageEvent;
|
|
149
|
-
typedef
|
|
149
|
+
typedef
|
|
150
150
|
struct {
|
|
151
151
|
int type;
|
|
152
152
|
unsigned long serial;
|
|
@@ -157,7 +157,7 @@ struct {
|
|
|
157
157
|
int new;
|
|
158
158
|
int state;
|
|
159
159
|
} XColormapEvent;
|
|
160
|
-
typedef
|
|
160
|
+
typedef
|
|
161
161
|
struct {
|
|
162
162
|
int type;
|
|
163
163
|
unsigned long serial;
|
|
@@ -173,7 +173,7 @@ struct {
|
|
|
173
173
|
Window above;
|
|
174
174
|
int override_redirect;
|
|
175
175
|
} XConfigureEvent;
|
|
176
|
-
typedef
|
|
176
|
+
typedef
|
|
177
177
|
struct {
|
|
178
178
|
int type;
|
|
179
179
|
unsigned long serial;
|
|
@@ -190,7 +190,7 @@ struct {
|
|
|
190
190
|
int detail;
|
|
191
191
|
unsigned long value_mask;
|
|
192
192
|
} XConfigureRequestEvent;
|
|
193
|
-
typedef
|
|
193
|
+
typedef
|
|
194
194
|
struct {
|
|
195
195
|
int type;
|
|
196
196
|
unsigned long serial;
|
|
@@ -205,7 +205,7 @@ struct {
|
|
|
205
205
|
int border_width;
|
|
206
206
|
int override_redirect;
|
|
207
207
|
} XCreateWindowEvent;
|
|
208
|
-
typedef
|
|
208
|
+
typedef
|
|
209
209
|
struct {
|
|
210
210
|
int type;
|
|
211
211
|
unsigned long serial;
|
|
@@ -225,7 +225,7 @@ struct {
|
|
|
225
225
|
int focus;
|
|
226
226
|
unsigned int state;
|
|
227
227
|
} XCrossingEvent;
|
|
228
|
-
typedef
|
|
228
|
+
typedef
|
|
229
229
|
struct {
|
|
230
230
|
int type;
|
|
231
231
|
unsigned long serial;
|
|
@@ -234,7 +234,7 @@ struct {
|
|
|
234
234
|
Window event;
|
|
235
235
|
Window window;
|
|
236
236
|
} XDestroyWindowEvent;
|
|
237
|
-
typedef
|
|
237
|
+
typedef
|
|
238
238
|
struct {
|
|
239
239
|
int type;
|
|
240
240
|
Display *display;
|
|
@@ -244,7 +244,7 @@ struct {
|
|
|
244
244
|
unsigned char request_code;
|
|
245
245
|
unsigned char minor_code;
|
|
246
246
|
} XErrorEvent;
|
|
247
|
-
typedef
|
|
247
|
+
typedef
|
|
248
248
|
struct {
|
|
249
249
|
int type;
|
|
250
250
|
unsigned long serial;
|
|
@@ -257,7 +257,7 @@ struct {
|
|
|
257
257
|
int height;
|
|
258
258
|
int count;
|
|
259
259
|
} XExposeEvent;
|
|
260
|
-
typedef
|
|
260
|
+
typedef
|
|
261
261
|
struct {
|
|
262
262
|
int type;
|
|
263
263
|
unsigned long serial;
|
|
@@ -267,7 +267,7 @@ struct {
|
|
|
267
267
|
int mode;
|
|
268
268
|
int detail;
|
|
269
269
|
} XFocusChangeEvent;
|
|
270
|
-
typedef
|
|
270
|
+
typedef
|
|
271
271
|
struct {
|
|
272
272
|
int function;
|
|
273
273
|
unsigned long plane_mask;
|
|
@@ -293,7 +293,7 @@ struct {
|
|
|
293
293
|
int dash_offset;
|
|
294
294
|
char dashes;
|
|
295
295
|
} XGCValues;
|
|
296
|
-
typedef
|
|
296
|
+
typedef
|
|
297
297
|
struct {
|
|
298
298
|
int type;
|
|
299
299
|
unsigned long serial;
|
|
@@ -302,7 +302,7 @@ struct {
|
|
|
302
302
|
int extension;
|
|
303
303
|
int evtype;
|
|
304
304
|
} XGenericEvent;
|
|
305
|
-
typedef
|
|
305
|
+
typedef
|
|
306
306
|
struct {
|
|
307
307
|
int type;
|
|
308
308
|
unsigned long serial;
|
|
@@ -313,7 +313,7 @@ struct {
|
|
|
313
313
|
unsigned int cookie;
|
|
314
314
|
void *data;
|
|
315
315
|
} XGenericEventCookie;
|
|
316
|
-
typedef
|
|
316
|
+
typedef
|
|
317
317
|
struct {
|
|
318
318
|
int type;
|
|
319
319
|
unsigned long serial;
|
|
@@ -328,7 +328,7 @@ struct {
|
|
|
328
328
|
int major_code;
|
|
329
329
|
int minor_code;
|
|
330
330
|
} XGraphicsExposeEvent;
|
|
331
|
-
typedef
|
|
331
|
+
typedef
|
|
332
332
|
struct {
|
|
333
333
|
int type;
|
|
334
334
|
unsigned long serial;
|
|
@@ -339,7 +339,7 @@ struct {
|
|
|
339
339
|
int x;
|
|
340
340
|
int y;
|
|
341
341
|
} XGravityEvent;
|
|
342
|
-
typedef
|
|
342
|
+
typedef
|
|
343
343
|
struct {
|
|
344
344
|
int type;
|
|
345
345
|
unsigned long serial;
|
|
@@ -357,7 +357,7 @@ struct {
|
|
|
357
357
|
unsigned int keycode;
|
|
358
358
|
int same_screen;
|
|
359
359
|
} XKeyEvent;
|
|
360
|
-
typedef
|
|
360
|
+
typedef
|
|
361
361
|
struct {
|
|
362
362
|
int type;
|
|
363
363
|
unsigned long serial;
|
|
@@ -366,7 +366,7 @@ struct {
|
|
|
366
366
|
Window window;
|
|
367
367
|
char key_vector[32];
|
|
368
368
|
} XKeymapEvent;
|
|
369
|
-
typedef
|
|
369
|
+
typedef
|
|
370
370
|
struct {
|
|
371
371
|
int type;
|
|
372
372
|
unsigned long serial;
|
|
@@ -376,7 +376,7 @@ struct {
|
|
|
376
376
|
Window window;
|
|
377
377
|
int override_redirect;
|
|
378
378
|
} XMapEvent;
|
|
379
|
-
typedef
|
|
379
|
+
typedef
|
|
380
380
|
struct {
|
|
381
381
|
int type;
|
|
382
382
|
unsigned long serial;
|
|
@@ -385,7 +385,7 @@ struct {
|
|
|
385
385
|
Window parent;
|
|
386
386
|
Window window;
|
|
387
387
|
} XMapRequestEvent;
|
|
388
|
-
typedef
|
|
388
|
+
typedef
|
|
389
389
|
struct {
|
|
390
390
|
int type;
|
|
391
391
|
unsigned long serial;
|
|
@@ -396,7 +396,7 @@ struct {
|
|
|
396
396
|
int first_keycode;
|
|
397
397
|
int count;
|
|
398
398
|
} XMappingEvent;
|
|
399
|
-
typedef
|
|
399
|
+
typedef
|
|
400
400
|
struct {
|
|
401
401
|
int type;
|
|
402
402
|
unsigned long serial;
|
|
@@ -414,7 +414,7 @@ struct {
|
|
|
414
414
|
char is_hint;
|
|
415
415
|
int same_screen;
|
|
416
416
|
} XMotionEvent;
|
|
417
|
-
typedef
|
|
417
|
+
typedef
|
|
418
418
|
struct {
|
|
419
419
|
int type;
|
|
420
420
|
unsigned long serial;
|
|
@@ -424,7 +424,7 @@ struct {
|
|
|
424
424
|
int major_code;
|
|
425
425
|
int minor_code;
|
|
426
426
|
} XNoExposeEvent;
|
|
427
|
-
typedef
|
|
427
|
+
typedef
|
|
428
428
|
struct {
|
|
429
429
|
int type;
|
|
430
430
|
unsigned long serial;
|
|
@@ -435,7 +435,7 @@ struct {
|
|
|
435
435
|
Time time;
|
|
436
436
|
int state;
|
|
437
437
|
} XPropertyEvent;
|
|
438
|
-
typedef
|
|
438
|
+
typedef
|
|
439
439
|
struct {
|
|
440
440
|
int type;
|
|
441
441
|
unsigned long serial;
|
|
@@ -448,7 +448,7 @@ struct {
|
|
|
448
448
|
int y;
|
|
449
449
|
int override_redirect;
|
|
450
450
|
} XReparentEvent;
|
|
451
|
-
typedef
|
|
451
|
+
typedef
|
|
452
452
|
struct {
|
|
453
453
|
int type;
|
|
454
454
|
unsigned long serial;
|
|
@@ -458,7 +458,7 @@ struct {
|
|
|
458
458
|
int width;
|
|
459
459
|
int height;
|
|
460
460
|
} XResizeRequestEvent;
|
|
461
|
-
typedef
|
|
461
|
+
typedef
|
|
462
462
|
struct {
|
|
463
463
|
int type;
|
|
464
464
|
unsigned long serial;
|
|
@@ -468,7 +468,7 @@ struct {
|
|
|
468
468
|
Atom selection;
|
|
469
469
|
Time time;
|
|
470
470
|
} XSelectionClearEvent;
|
|
471
|
-
typedef
|
|
471
|
+
typedef
|
|
472
472
|
struct {
|
|
473
473
|
int type;
|
|
474
474
|
unsigned long serial;
|
|
@@ -480,7 +480,7 @@ struct {
|
|
|
480
480
|
Atom property;
|
|
481
481
|
Time time;
|
|
482
482
|
} XSelectionEvent;
|
|
483
|
-
typedef
|
|
483
|
+
typedef
|
|
484
484
|
struct {
|
|
485
485
|
int type;
|
|
486
486
|
unsigned long serial;
|
|
@@ -493,7 +493,7 @@ struct {
|
|
|
493
493
|
Atom property;
|
|
494
494
|
Time time;
|
|
495
495
|
} XSelectionRequestEvent;
|
|
496
|
-
typedef
|
|
496
|
+
typedef
|
|
497
497
|
struct {
|
|
498
498
|
int type;
|
|
499
499
|
unsigned long serial;
|
|
@@ -503,7 +503,7 @@ struct {
|
|
|
503
503
|
Window window;
|
|
504
504
|
int from_configure;
|
|
505
505
|
} XUnmapEvent;
|
|
506
|
-
typedef
|
|
506
|
+
typedef
|
|
507
507
|
struct {
|
|
508
508
|
int type;
|
|
509
509
|
unsigned long serial;
|
|
@@ -579,7 +579,7 @@ EOS
|
|
|
579
579
|
def self.test
|
|
580
580
|
d = xopendisplay(nil)
|
|
581
581
|
s = xdefaultscreen(d)
|
|
582
|
-
cmap = xdefaultcolormap(d, s)
|
|
582
|
+
#cmap = xdefaultcolormap(d, s)
|
|
583
583
|
w = xcreatesimplewindow(d, xdefaultrootwindow(d), 0, 0, 28, 28, 0, xblackpixel(d, s), xblackpixel(d, s))
|
|
584
584
|
xstorename(d, w, "lol")
|
|
585
585
|
gc = xcreategc(d, w, 0, 0)
|
|
@@ -23,7 +23,7 @@ class CPU
|
|
|
23
23
|
attr_accessor :valid_args, :valid_props, :fields_mask
|
|
24
24
|
attr_accessor :endianness, :size
|
|
25
25
|
attr_accessor :generate_PIC
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
def opcode_list
|
|
28
28
|
@opcode_list ||= init_opcode_list
|
|
29
29
|
end
|
|
@@ -32,8 +32,8 @@ class CPU
|
|
|
32
32
|
def initialize
|
|
33
33
|
@fields_mask = {}
|
|
34
34
|
@fields_shift= {}
|
|
35
|
-
@valid_args =
|
|
36
|
-
@valid_props =
|
|
35
|
+
@valid_args = {}
|
|
36
|
+
@valid_props = { :setip => true, :saveip => true, :stopexec => true }
|
|
37
37
|
@generate_PIC = true
|
|
38
38
|
end
|
|
39
39
|
|
|
@@ -81,6 +81,17 @@ class CPU
|
|
|
81
81
|
def shortname
|
|
82
82
|
self.class.name.sub(/.*::/, '').downcase
|
|
83
83
|
end
|
|
84
|
+
|
|
85
|
+
# some userinterface wants to hilight a word, return a regexp
|
|
86
|
+
# useful for register aliases
|
|
87
|
+
# the regexp will be enclosed in \b and should not contain captures
|
|
88
|
+
def gui_hilight_word_regexp(word)
|
|
89
|
+
Regexp.escape(word)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# returns true if the name is invalid as a label name (eg register name)
|
|
93
|
+
def check_reserved_name(name)
|
|
94
|
+
end
|
|
84
95
|
end
|
|
85
96
|
|
|
86
97
|
# generic CPU, with no instructions, just size/endianness
|
|
@@ -120,6 +131,15 @@ class Opcode
|
|
|
120
131
|
def basename
|
|
121
132
|
@name.sub(/\..*/, '')
|
|
122
133
|
end
|
|
134
|
+
|
|
135
|
+
def dup
|
|
136
|
+
o = Opcode.new(@name.dup, @bin)
|
|
137
|
+
o.bin = @bin.dup if @bin.kind_of?(::Array)
|
|
138
|
+
o.args = @args.dup
|
|
139
|
+
o.fields = @fields.dup
|
|
140
|
+
o.props = @props.dup
|
|
141
|
+
o
|
|
142
|
+
end
|
|
123
143
|
end
|
|
124
144
|
|
|
125
145
|
# defines an attribute self.backtrace (array of filename/lineno)
|
|
@@ -341,7 +361,7 @@ class Expression < ExpressionType
|
|
|
341
361
|
if not op
|
|
342
362
|
raise ArgumentError, 'invalid Expression[nil]' if not l
|
|
343
363
|
return l if l.kind_of? Expression
|
|
344
|
-
if l.kind_of?
|
|
364
|
+
if l.kind_of?(::Numeric) and l < 0
|
|
345
365
|
r = -l
|
|
346
366
|
op = :'-'
|
|
347
367
|
else
|
|
@@ -354,9 +374,9 @@ class Expression < ExpressionType
|
|
|
354
374
|
end
|
|
355
375
|
l = nil
|
|
356
376
|
else
|
|
357
|
-
l = self[*l] if l.kind_of?
|
|
377
|
+
l = self[*l] if l.kind_of?(::Array)
|
|
358
378
|
end
|
|
359
|
-
r = self[*r] if r.kind_of?
|
|
379
|
+
r = self[*r] if r.kind_of?(::Array)
|
|
360
380
|
new(op, r, l)
|
|
361
381
|
end
|
|
362
382
|
|
|
@@ -364,7 +384,7 @@ class Expression < ExpressionType
|
|
|
364
384
|
# returns true if it is, false if it overflows, and nil if cannot be determined (eg unresolved variable)
|
|
365
385
|
def self.in_range?(val, type)
|
|
366
386
|
val = val.reduce if val.kind_of? self
|
|
367
|
-
return unless val.kind_of?
|
|
387
|
+
return unless val.kind_of?(::Numeric)
|
|
368
388
|
|
|
369
389
|
if INT_MIN[type]
|
|
370
390
|
val == val.to_i and
|
|
@@ -374,8 +394,11 @@ class Expression < ExpressionType
|
|
|
374
394
|
|
|
375
395
|
# casts an unsigned value to a two-complement signed if the sign bit is set
|
|
376
396
|
def self.make_signed(val, bitlength)
|
|
377
|
-
|
|
378
|
-
|
|
397
|
+
case val
|
|
398
|
+
when Integer
|
|
399
|
+
val = val - (1 << bitlength) if val > 0 and val >> (bitlength - 1) == 1
|
|
400
|
+
when Expression
|
|
401
|
+
val = Expression[val, :-, [(1<<bitlength), :*, [[val, :>>, (bitlength-1)], :==, 1]]]
|
|
379
402
|
end
|
|
380
403
|
val
|
|
381
404
|
end
|
|
@@ -390,8 +413,10 @@ class Expression < ExpressionType
|
|
|
390
413
|
# basic constructor
|
|
391
414
|
# XXX funny args order, you should use +Expression[]+ instead
|
|
392
415
|
def initialize(op, rexpr, lexpr)
|
|
393
|
-
raise ArgumentError, "Expression: invalid arg order: #{[lexpr, op, rexpr].inspect}" if not op.kind_of?
|
|
394
|
-
@op
|
|
416
|
+
raise ArgumentError, "Expression: invalid arg order: #{[lexpr, op, rexpr].inspect}" if not op.kind_of?(::Symbol)
|
|
417
|
+
@op = op
|
|
418
|
+
@lexpr = lexpr
|
|
419
|
+
@rexpr = rexpr
|
|
395
420
|
end
|
|
396
421
|
|
|
397
422
|
# recursive check of equity using #==
|
|
@@ -415,20 +440,21 @@ class Expression < ExpressionType
|
|
|
415
440
|
return binding[self].dup
|
|
416
441
|
end
|
|
417
442
|
|
|
418
|
-
l
|
|
443
|
+
l = @lexpr
|
|
444
|
+
r = @rexpr
|
|
419
445
|
if l and binding[l]
|
|
420
|
-
raise "internal error - bound #{l.inspect}" if l.kind_of?
|
|
446
|
+
raise "internal error - bound #{l.inspect}" if l.kind_of?(::Numeric)
|
|
421
447
|
l = binding[l]
|
|
422
448
|
elsif l.kind_of? ExpressionType
|
|
423
449
|
l = l.bind(binding)
|
|
424
450
|
end
|
|
425
451
|
if r and binding[r]
|
|
426
|
-
raise "internal error - bound #{r.inspect}" if r.kind_of?
|
|
452
|
+
raise "internal error - bound #{r.inspect}" if r.kind_of?(::Numeric)
|
|
427
453
|
r = binding[r]
|
|
428
454
|
elsif r.kind_of? ExpressionType
|
|
429
455
|
r = r.bind(binding)
|
|
430
456
|
end
|
|
431
|
-
Expression
|
|
457
|
+
Expression.new(@op, r, l)
|
|
432
458
|
end
|
|
433
459
|
|
|
434
460
|
# bind in place (replace self.lexpr/self.rexpr with the binding value)
|
|
@@ -492,10 +518,13 @@ class Expression < ExpressionType
|
|
|
492
518
|
end
|
|
493
519
|
|
|
494
520
|
v =
|
|
495
|
-
if r.kind_of?(::Numeric) and (l
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
521
|
+
if r.kind_of?(::Numeric) and (not l or l.kind_of?(::Numeric))
|
|
522
|
+
case @op
|
|
523
|
+
when :+; l ? l + r : r
|
|
524
|
+
when :-; l ? l - r : -r
|
|
525
|
+
when :'!'; raise 'internal error' if l ; (r == 0) ? 1 : 0
|
|
526
|
+
when :'~'; raise 'internal error' if l ; ~r
|
|
527
|
+
when :'&&', :'||', :'>', :'<', :'>=', :'<=', :'==', :'!='
|
|
499
528
|
raise 'internal error' if not l
|
|
500
529
|
case @op
|
|
501
530
|
when :'&&'; (l != 0) && (r != 0)
|
|
@@ -507,194 +536,18 @@ class Expression < ExpressionType
|
|
|
507
536
|
when :'=='; l == r
|
|
508
537
|
when :'!='; l != r
|
|
509
538
|
end ? 1 : 0
|
|
510
|
-
elsif not l
|
|
511
|
-
case @op
|
|
512
|
-
when :'!'; (r == 0) ? 1 : 0
|
|
513
|
-
when :+; r
|
|
514
|
-
when :-; -r
|
|
515
|
-
when :~; ~r
|
|
516
|
-
end
|
|
517
539
|
else
|
|
518
|
-
# use ruby evaluator
|
|
519
540
|
l.send(@op, r)
|
|
520
541
|
end
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
if l == 0 # shortcircuit eval
|
|
524
|
-
0
|
|
525
|
-
elsif l == 1
|
|
526
|
-
Expression[r, :'!=', 0].reduce_rec
|
|
527
|
-
elsif r == 0
|
|
528
|
-
0 # XXX l could be a special ExprType with sideeffects ?
|
|
529
|
-
end
|
|
530
|
-
elsif @op == :'||'
|
|
531
|
-
if l.kind_of? ::Numeric and l != 0 # shortcircuit eval
|
|
532
|
-
1
|
|
533
|
-
elsif l == 0
|
|
534
|
-
Expression[r, :'!=', 0].reduce_rec
|
|
535
|
-
elsif r == 0
|
|
536
|
-
Expression[l, :'!=', 0].reduce_rec
|
|
537
|
-
end
|
|
538
|
-
elsif @op == :>> or @op == :<<
|
|
539
|
-
if l == 0; 0
|
|
540
|
-
elsif r == 0; l
|
|
541
|
-
elsif l.kind_of? Expression and l.op == @op
|
|
542
|
-
Expression[l.lexpr, @op, [l.rexpr, :+, r]].reduce_rec
|
|
543
|
-
# XXX (a >> 1) << 1 != a (lose low bit)
|
|
544
|
-
# XXX (a << 1) >> 1 != a (with real cpus, lose high bit)
|
|
545
|
-
# (a | b) << i
|
|
546
|
-
elsif r.kind_of? Integer and l.kind_of? Expression and [:&, :|, :^].include? l.op
|
|
547
|
-
Expression[[l.lexpr, @op, r], l.op, [l.rexpr, @op, r]].reduce_rec
|
|
548
|
-
end
|
|
549
|
-
elsif @op == :'!'
|
|
550
|
-
if r.kind_of? Expression and op = {:'==' => :'!=', :'!=' => :'==', :< => :>=, :> => :<=, :<= => :>, :>= => :<}[r.op]
|
|
551
|
-
Expression[r.lexpr, op, r.rexpr].reduce_rec
|
|
552
|
-
end
|
|
553
|
-
elsif @op == :==
|
|
554
|
-
if l == r; 1
|
|
555
|
-
elsif r == 0 and l.kind_of? Expression and op = {:'==' => :'!=', :'!=' => :'==', :< => :>=, :> => :<=, :<= => :>, :>= => :<}[l.op]
|
|
556
|
-
Expression[l.lexpr, op, l.rexpr].reduce_rec
|
|
557
|
-
elsif r == 1 and l.kind_of? Expression and op = {:'==' => :'!=', :'!=' => :'==', :< => :>=, :> => :<=, :<= => :>, :>= => :<}[l.op]
|
|
558
|
-
l
|
|
559
|
-
elsif r == 0 and l.kind_of? Expression and l.op == :+
|
|
560
|
-
if l.rexpr.kind_of? Expression and l.rexpr.op == :- and not l.rexpr.lexpr
|
|
561
|
-
Expression[l.lexpr, @op, l.rexpr.rexpr].reduce_rec
|
|
562
|
-
elsif l.rexpr.kind_of? ::Integer
|
|
563
|
-
Expression[l.lexpr, @op, -l.rexpr].reduce_rec
|
|
564
|
-
end
|
|
565
|
-
end
|
|
566
|
-
elsif @op == :'!='
|
|
567
|
-
if l == r; 0
|
|
568
|
-
end
|
|
569
|
-
elsif @op == :^
|
|
570
|
-
if l == :unknown or r == :unknown; :unknown
|
|
571
|
-
elsif l == 0; r
|
|
572
|
-
elsif r == 0; l
|
|
573
|
-
elsif l == r; 0
|
|
574
|
-
elsif r == 1 and l.kind_of? Expression and [:'==', :'!=', :<, :>, :<=, :>=].include? l.op
|
|
575
|
-
Expression[nil, :'!', l].reduce_rec
|
|
576
|
-
elsif l.kind_of?(::Numeric)
|
|
577
|
-
if r.kind_of? Expression and r.op == :^
|
|
578
|
-
# 1^(x^y) => x^(y^1)
|
|
579
|
-
Expression[r.lexpr, :^, [r.rexpr, :^, l]].reduce_rec
|
|
580
|
-
else
|
|
581
|
-
# 1^a => a^1
|
|
582
|
-
Expression[r, :^, l].reduce_rec
|
|
583
|
-
end
|
|
584
|
-
elsif l.kind_of? Expression and l.op == :^
|
|
585
|
-
# (a^b)^c => a^(b^c)
|
|
586
|
-
Expression[l.lexpr, :^, [l.rexpr, :^, r]].reduce_rec
|
|
587
|
-
elsif r.kind_of? Expression and r.op == :^
|
|
588
|
-
if r.rexpr == l
|
|
589
|
-
# a^(a^b) => b
|
|
590
|
-
r.lexpr
|
|
591
|
-
elsif r.lexpr == l
|
|
592
|
-
# a^(b^a) => b
|
|
593
|
-
r.rexpr
|
|
594
|
-
else
|
|
595
|
-
# a^(b^(c^(a^d))) => b^(a^(c^(a^d)))
|
|
596
|
-
# XXX ugly..
|
|
597
|
-
tr = r
|
|
598
|
-
found = false
|
|
599
|
-
while not found and tr.kind_of?(Expression) and tr.op == :^
|
|
600
|
-
found = true if tr.lexpr == l or tr.rexpr == l
|
|
601
|
-
tr = tr.rexpr
|
|
602
|
-
end
|
|
603
|
-
if found
|
|
604
|
-
Expression[r.lexpr, :^, [l, :^, r.rexpr]].reduce_rec
|
|
605
|
-
end
|
|
606
|
-
end
|
|
607
|
-
elsif l.kind_of?(Expression) and l.op == :& and l.rexpr.kind_of?(::Integer) and (l.rexpr & (l.rexpr+1)) == 0
|
|
608
|
-
if r.kind_of?(::Integer) and r & l.rexpr == r
|
|
609
|
-
# (a&0xfff)^12 => (a^12)&0xfff
|
|
610
|
-
Expression[[l.lexpr, :^, r], :&, l.rexpr].reduce_rec
|
|
611
|
-
elsif r.kind_of?(Expression) and r.op == :& and r.rexpr.kind_of?(::Integer) and r.rexpr == l.rexpr
|
|
612
|
-
# (a&0xfff)^(b&0xfff) => (a^b)&0xfff
|
|
613
|
-
Expression[[l.lexpr, :^, r.lexpr], :&, l.rexpr].reduce_rec
|
|
614
|
-
end
|
|
615
|
-
end
|
|
616
|
-
elsif @op == :&
|
|
617
|
-
if l == 0 or r == 0; 0
|
|
618
|
-
elsif r == 1 and l.kind_of?(Expression) and [:'==', :'!=', :<, :>, :<=, :>=].include?(l.op)
|
|
619
|
-
l
|
|
620
|
-
elsif l == r; l
|
|
621
|
-
elsif l.kind_of?(Integer); Expression[r, @op, l].reduce_rec
|
|
622
|
-
elsif l.kind_of?(Expression) and l.op == @op; Expression[l.lexpr, @op, [l.rexpr, @op, r]].reduce_rec
|
|
623
|
-
elsif l.kind_of?(Expression) and [:|, :^].include?(l.op) and r.kind_of?(Integer) and (l.op == :| or (r & (r+1)) != 0)
|
|
624
|
-
# (a ^| b) & i => (a&i ^| b&i)
|
|
625
|
-
Expression[[l.lexpr, :&, r], l.op, [l.rexpr, :&, r]].reduce_rec
|
|
626
|
-
elsif r.kind_of?(::Integer) and l.kind_of?(Expression) and (r & (r+1)) == 0
|
|
627
|
-
# foo & 0xffff
|
|
628
|
-
reduce_rec_mod2(l, r)
|
|
629
|
-
end
|
|
630
|
-
elsif @op == :|
|
|
631
|
-
if l == 0; r
|
|
632
|
-
elsif r == 0; l
|
|
633
|
-
elsif l == -1 or r == -1; -1
|
|
634
|
-
elsif l == r; l
|
|
635
|
-
elsif l.kind_of? Integer; Expression[r, @op, l].reduce_rec
|
|
636
|
-
elsif l.kind_of? Expression and l.op == @op; Expression[l.lexpr, @op, [l.rexpr, @op, r]].reduce_rec
|
|
637
|
-
end
|
|
638
|
-
elsif @op == :*
|
|
639
|
-
if l == 0 or r == 0; 0
|
|
640
|
-
elsif l == 1; r
|
|
641
|
-
elsif r == 1; l
|
|
642
|
-
elsif r.kind_of? Integer; Expression[r, @op, l].reduce_rec
|
|
643
|
-
elsif r.kind_of? Expression and r.op == @op; Expression[[l, @op, r.lexpr], @op, r.rexpr].reduce_rec
|
|
644
|
-
elsif l.kind_of? Integer and r.kind_of? Expression and r.op == :* and r.lexpr.kind_of? Integer; Expression[l*r.lexpr, :*, r.rexpr].reduce_rec # XXX need & regsize..
|
|
645
|
-
elsif l.kind_of? Integer and r.kind_of? Expression and r.op == :+ and r.rexpr.kind_of? Integer; Expression[[l, :*, r.lexpr], :+, l*r.rexpr].reduce_rec
|
|
646
|
-
end
|
|
647
|
-
elsif @op == :/
|
|
648
|
-
if r == 0
|
|
649
|
-
elsif r.kind_of? Integer and l.kind_of? Expression and l.op == :+ and l.rexpr.kind_of? Integer and l.rexpr % r == 0
|
|
650
|
-
Expression[[l.lexpr, :/, r], :+, l.rexpr/r].reduce_rec
|
|
651
|
-
elsif r.kind_of? Integer and l.kind_of? Expression and l.op == :* and l.lexpr % r == 0
|
|
652
|
-
Expression[l.lexpr/r, :*, l.rexpr].reduce_rec
|
|
653
|
-
end
|
|
654
|
-
elsif @op == :-
|
|
655
|
-
if l == :unknown or r == :unknown; :unknown
|
|
656
|
-
elsif not l and r.kind_of? Expression and (r.op == :- or r.op == :+)
|
|
657
|
-
if r.op == :- # no lexpr (reduced)
|
|
658
|
-
# -(-x) => x
|
|
659
|
-
r.rexpr
|
|
660
|
-
else # :+ and lexpr (r is reduced)
|
|
661
|
-
# -(a+b) => (-a)+(-b)
|
|
662
|
-
Expression[[:-, r.lexpr], :+, [:-, r.rexpr]].reduce_rec
|
|
663
|
-
end
|
|
664
|
-
elsif l.kind_of? Expression and l.op == :+ and l.lexpr == r
|
|
665
|
-
# shortcircuit for a common occurence [citation needed]
|
|
666
|
-
# (a+b)-a
|
|
667
|
-
l.rexpr
|
|
668
|
-
elsif l
|
|
669
|
-
# a-b => a+(-b)
|
|
670
|
-
Expression[l, :+, [:-, r]].reduce_rec
|
|
671
|
-
end
|
|
672
|
-
elsif @op == :+
|
|
673
|
-
if l == :unknown or r == :unknown; :unknown
|
|
674
|
-
elsif not l; r # +x => x
|
|
675
|
-
elsif r == 0; l # x+0 => x
|
|
676
|
-
elsif l.kind_of?(::Numeric)
|
|
677
|
-
if r.kind_of? Expression and r.op == :+
|
|
678
|
-
# 1+(x+y) => x+(y+1)
|
|
679
|
-
Expression[r.lexpr, :+, [r.rexpr, :+, l]].reduce_rec
|
|
680
|
-
else
|
|
681
|
-
# 1+a => a+1
|
|
682
|
-
Expression[r, :+, l].reduce_rec
|
|
683
|
-
end
|
|
684
|
-
# (a+b)+foo => a+(b+foo)
|
|
685
|
-
elsif l.kind_of? Expression and l.op == @op; Expression[l.lexpr, @op, [l.rexpr, @op, r]].reduce_rec
|
|
686
|
-
elsif l.kind_of? Expression and r.kind_of? Expression and l.op == :% and r.op == :% and l.rexpr.kind_of?(::Integer) and l.rexpr == r.rexpr
|
|
687
|
-
Expression[[l.lexpr, :+, r.lexpr], :%, l.rexpr].reduce_rec
|
|
688
|
-
else
|
|
689
|
-
reduce_rec_add(l, r)
|
|
690
|
-
end
|
|
542
|
+
elsif rp = @@reduce_op[@op]
|
|
543
|
+
rp[self, l, r]
|
|
691
544
|
end
|
|
692
545
|
|
|
693
546
|
ret = case v
|
|
694
547
|
when nil
|
|
695
548
|
# no dup if no new value
|
|
696
549
|
(r == :unknown or l == :unknown) ? :unknown :
|
|
697
|
-
((r == @rexpr and l == @lexpr) ? self : Expression
|
|
550
|
+
((r == @rexpr and l == @lexpr) ? self : Expression.new(@op, r, l))
|
|
698
551
|
when Expression
|
|
699
552
|
(v.lexpr == :unknown or v.rexpr == :unknown) ? :unknown : v
|
|
700
553
|
else v
|
|
@@ -709,54 +562,248 @@ class Expression < ExpressionType
|
|
|
709
562
|
ret
|
|
710
563
|
end
|
|
711
564
|
|
|
565
|
+
@@reduce_op = {
|
|
566
|
+
:+ => lambda { |e, l, r| e.reduce_op_plus(l, r) },
|
|
567
|
+
:- => lambda { |e, l, r| e.reduce_op_minus(l, r) },
|
|
568
|
+
:'&&' => lambda { |e, l, r| e.reduce_op_andand(l, r) },
|
|
569
|
+
:'||' => lambda { |e, l, r| e.reduce_op_oror(l, r) },
|
|
570
|
+
:>> => lambda { |e, l, r| e.reduce_op_shr(l, r) },
|
|
571
|
+
:<< => lambda { |e, l, r| e.reduce_op_shl(l, r) },
|
|
572
|
+
:'!' => lambda { |e, l, r| e.reduce_op_not(l, r) },
|
|
573
|
+
:== => lambda { |e, l, r| e.reduce_op_eql(l, r) },
|
|
574
|
+
:'!=' => lambda { |e, l, r| e.reduce_op_neq(l, r) },
|
|
575
|
+
:^ => lambda { |e, l, r| e.reduce_op_xor(l, r) },
|
|
576
|
+
:& => lambda { |e, l, r| e.reduce_op_and(l, r) },
|
|
577
|
+
:| => lambda { |e, l, r| e.reduce_op_or(l, r) },
|
|
578
|
+
:* => lambda { |e, l, r| e.reduce_op_times(l, r) },
|
|
579
|
+
:/ => lambda { |e, l, r| e.reduce_op_div(l, r) },
|
|
580
|
+
:% => lambda { |e, l, r| e.reduce_op_mod(l, r) },
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
def self.reduce_op
|
|
585
|
+
@@reduce_op
|
|
586
|
+
end
|
|
712
587
|
|
|
713
|
-
|
|
714
|
-
#
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
588
|
+
def reduce_op_plus(l, r)
|
|
589
|
+
if not l; r # +x => x
|
|
590
|
+
elsif r == 0; l # x+0 => x
|
|
591
|
+
elsif l == :unknown or r == :unknown; :unknown
|
|
592
|
+
elsif l.kind_of?(::Numeric)
|
|
593
|
+
if r.kind_of? Expression and r.op == :+
|
|
594
|
+
# 1+(x+y) => x+(y+1)
|
|
595
|
+
Expression[r.lexpr, :+, [r.rexpr, :+, l]].reduce_rec
|
|
596
|
+
else
|
|
597
|
+
# 1+a => a+1
|
|
598
|
+
Expression[r, :+, l].reduce_rec
|
|
599
|
+
end
|
|
600
|
+
# (a+b)+foo => a+(b+foo)
|
|
601
|
+
elsif l.kind_of? Expression and l.op == :+; Expression[l.lexpr, :+, [l.rexpr, :+, r]].reduce_rec
|
|
602
|
+
elsif l.kind_of? Expression and r.kind_of? Expression and l.op == :% and r.op == :% and l.rexpr.kind_of?(::Integer) and l.rexpr == r.rexpr
|
|
603
|
+
Expression[[l.lexpr, :+, r.lexpr], :%, l.rexpr].reduce_rec
|
|
604
|
+
elsif l.kind_of? Expression and l.op == :- and not l.lexpr
|
|
605
|
+
reduce_rec_add_rec(r, l.rexpr)
|
|
606
|
+
elsif l.kind_of? Expression and r.kind_of? Expression and l.op == :& and r.op == :& and l.rexpr.kind_of?(::Integer) and r.rexpr.kind_of?(::Integer) and l.rexpr & r.rexpr == 0
|
|
607
|
+
# (a&0xf0)+(b&0x0f) => (a&0xf0)|(b&0x0f)
|
|
608
|
+
Expression[l, :|, r].reduce_rec
|
|
718
609
|
else
|
|
719
|
-
|
|
610
|
+
reduce_rec_add_rec(r, Expression.new(:-, l, nil))
|
|
720
611
|
end
|
|
612
|
+
end
|
|
613
|
+
|
|
614
|
+
def reduce_rec_add_rec(cur, neg_l)
|
|
615
|
+
if neg_l == cur
|
|
616
|
+
# -l found
|
|
617
|
+
0
|
|
618
|
+
elsif cur.kind_of?(Expression) and cur.op == :+
|
|
619
|
+
# recurse
|
|
620
|
+
if newl = reduce_rec_add_rec(cur.lexpr, neg_l)
|
|
621
|
+
Expression[newl, cur.op, cur.rexpr].reduce_rec
|
|
622
|
+
elsif newr = reduce_rec_add_rec(cur.rexpr, neg_l)
|
|
623
|
+
Expression[cur.lexpr, cur.op, newr].reduce_rec
|
|
624
|
+
end
|
|
625
|
+
end
|
|
626
|
+
end
|
|
721
627
|
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
628
|
+
def reduce_op_minus(l, r)
|
|
629
|
+
if l == :unknown or r == :unknown; :unknown
|
|
630
|
+
elsif not l and r.kind_of? Expression and (r.op == :- or r.op == :+)
|
|
631
|
+
if r.op == :- # no lexpr (reduced)
|
|
632
|
+
# -(-x) => x
|
|
633
|
+
r.rexpr
|
|
634
|
+
else # :+ and lexpr (r is reduced)
|
|
635
|
+
# -(a+b) => (-a)+(-b)
|
|
636
|
+
Expression.new(:+, Expression.new(:-, r.rexpr, nil), Expression.new(:-, r.lexpr, nil)).reduce_rec
|
|
637
|
+
end
|
|
638
|
+
elsif l.kind_of? Expression and l.op == :+ and l.lexpr == r
|
|
639
|
+
# shortcircuit for a common occurence [citation needed]
|
|
640
|
+
# (a+b)-a
|
|
641
|
+
l.rexpr
|
|
642
|
+
elsif l
|
|
643
|
+
# a-b => a+(-b)
|
|
644
|
+
Expression[l, :+, [:-, r]].reduce_rec
|
|
645
|
+
end
|
|
646
|
+
end
|
|
647
|
+
|
|
648
|
+
def reduce_op_andand(l, r)
|
|
649
|
+
if l == 0 # shortcircuit eval
|
|
650
|
+
0
|
|
651
|
+
elsif l == 1
|
|
652
|
+
Expression[r, :'!=', 0].reduce_rec
|
|
653
|
+
elsif r == 0
|
|
654
|
+
0 # XXX l could be a special ExprType with sideeffects ?
|
|
655
|
+
end
|
|
656
|
+
end
|
|
657
|
+
|
|
658
|
+
def reduce_op_oror(l, r)
|
|
659
|
+
if l.kind_of?(::Numeric) and l != 0 # shortcircuit eval
|
|
660
|
+
1
|
|
661
|
+
elsif l == 0
|
|
662
|
+
Expression[r, :'!=', 0].reduce_rec
|
|
663
|
+
elsif r == 0
|
|
664
|
+
Expression[l, :'!=', 0].reduce_rec
|
|
665
|
+
end
|
|
666
|
+
end
|
|
667
|
+
|
|
668
|
+
def reduce_op_shr(l, r)
|
|
669
|
+
if l == 0; 0
|
|
670
|
+
elsif r == 0; l
|
|
671
|
+
elsif l.kind_of? Expression and l.op == :>>
|
|
672
|
+
Expression[l.lexpr, :>>, [l.rexpr, :+, r]].reduce_rec
|
|
673
|
+
elsif r.kind_of? Integer and l.kind_of? Expression and [:&, :|, :^].include? l.op
|
|
674
|
+
# (a | b) << i => (a<<i | b<<i)
|
|
675
|
+
Expression[[l.lexpr, :>>, r], l.op, [l.rexpr, :>>, r]].reduce_rec
|
|
676
|
+
end
|
|
677
|
+
end
|
|
678
|
+
|
|
679
|
+
def reduce_op_shl(l, r)
|
|
680
|
+
if l == 0; 0
|
|
681
|
+
elsif r == 0; l
|
|
682
|
+
elsif l.kind_of? Expression and l.op == :<<
|
|
683
|
+
Expression[l.lexpr, :<<, [l.rexpr, :+, r]].reduce_rec
|
|
684
|
+
elsif l.kind_of? Expression and l.op == :>> and r.kind_of? Integer and l.rexpr.kind_of? Integer
|
|
685
|
+
# (a >> 1) << 1 == a & 0xfffffe
|
|
686
|
+
if r == l.rexpr
|
|
687
|
+
Expression[l.lexpr, :&, (-1 << r)].reduce_rec
|
|
688
|
+
elsif r > l.rexpr
|
|
689
|
+
Expression[[l.lexpr, :<<, r-l.rexpr], :&, (-1 << r)].reduce_rec
|
|
690
|
+
else
|
|
691
|
+
Expression[[l.lexpr, :>>, l.rexpr-r], :&, (-1 << r)].reduce_rec
|
|
692
|
+
end
|
|
693
|
+
elsif r.kind_of? Integer and l.kind_of? Expression and [:&, :|, :^].include? l.op
|
|
694
|
+
# (a | b) << i => (a<<i | b<<i)
|
|
695
|
+
Expression[[l.lexpr, :<<, r], l.op, [l.rexpr, :<<, r]].reduce_rec
|
|
696
|
+
end
|
|
697
|
+
end
|
|
698
|
+
|
|
699
|
+
NEG_OP = {:'==' => :'!=', :'!=' => :'==', :< => :>=, :> => :<=, :<= => :>, :>= => :<}
|
|
700
|
+
|
|
701
|
+
def reduce_op_not(l, r)
|
|
702
|
+
if r.kind_of? Expression and nop = NEG_OP[r.op]
|
|
703
|
+
Expression[r.lexpr, nop, r.rexpr].reduce_rec
|
|
704
|
+
end
|
|
705
|
+
end
|
|
706
|
+
|
|
707
|
+
def reduce_op_eql(l, r)
|
|
708
|
+
if l == r; 1
|
|
709
|
+
elsif r == 0 and l.kind_of? Expression and nop = NEG_OP[l.op]
|
|
710
|
+
Expression[l.lexpr, nop, l.rexpr].reduce_rec
|
|
711
|
+
elsif r == 1 and l.kind_of? Expression and NEG_OP[l.op]
|
|
712
|
+
l
|
|
713
|
+
elsif r == 0 and l.kind_of? Expression and l.op == :+
|
|
714
|
+
if l.rexpr.kind_of? Expression and l.rexpr.op == :- and not l.rexpr.lexpr
|
|
715
|
+
Expression[l.lexpr, :==, l.rexpr.rexpr].reduce_rec
|
|
716
|
+
elsif l.rexpr.kind_of?(::Integer)
|
|
717
|
+
Expression[l.lexpr, :==, -l.rexpr].reduce_rec
|
|
718
|
+
end
|
|
719
|
+
end
|
|
720
|
+
end
|
|
721
|
+
|
|
722
|
+
def reduce_op_neq(l, r)
|
|
723
|
+
if l == r; 0
|
|
724
|
+
end
|
|
725
|
+
end
|
|
726
|
+
|
|
727
|
+
def reduce_op_xor(l, r)
|
|
728
|
+
if l == :unknown or r == :unknown; :unknown
|
|
729
|
+
elsif l == 0; r
|
|
730
|
+
elsif r == 0; l
|
|
731
|
+
elsif l == r; 0
|
|
732
|
+
elsif r == 1 and l.kind_of? Expression and NEG_OP[l.op]
|
|
733
|
+
Expression[nil, :'!', l].reduce_rec
|
|
734
|
+
elsif l.kind_of?(::Numeric)
|
|
735
|
+
if r.kind_of? Expression and r.op == :^
|
|
736
|
+
# 1^(x^y) => x^(y^1)
|
|
737
|
+
Expression[r.lexpr, :^, [r.rexpr, :^, l]].reduce_rec
|
|
738
|
+
else
|
|
739
|
+
# 1^a => a^1
|
|
740
|
+
Expression[r, :^, l].reduce_rec
|
|
741
|
+
end
|
|
742
|
+
elsif l.kind_of? Expression and l.op == :^
|
|
743
|
+
# (a^b)^c => a^(b^c)
|
|
744
|
+
Expression[l.lexpr, :^, [l.rexpr, :^, r]].reduce_rec
|
|
745
|
+
elsif r.kind_of? Expression and r.op == :^
|
|
746
|
+
if r.rexpr == l
|
|
747
|
+
# a^(a^b) => b
|
|
748
|
+
r.lexpr
|
|
749
|
+
elsif r.lexpr == l
|
|
750
|
+
# a^(b^a) => b
|
|
751
|
+
r.rexpr
|
|
752
|
+
else
|
|
753
|
+
# a^(b^(c^(a^d))) => b^(a^(c^(a^d)))
|
|
754
|
+
# XXX ugly..
|
|
755
|
+
tr = r
|
|
756
|
+
found = false
|
|
757
|
+
while not found and tr.kind_of?(Expression) and tr.op == :^
|
|
758
|
+
found = true if tr.lexpr == l or tr.rexpr == l
|
|
759
|
+
tr = tr.rexpr
|
|
760
|
+
end
|
|
761
|
+
if found
|
|
762
|
+
Expression[r.lexpr, :^, [l, :^, r.rexpr]].reduce_rec
|
|
733
763
|
end
|
|
734
764
|
end
|
|
735
|
-
|
|
765
|
+
elsif l.kind_of?(Expression) and l.op == :& and l.rexpr.kind_of?(::Integer) and (l.rexpr & (l.rexpr+1)) == 0
|
|
766
|
+
if r.kind_of?(::Integer) and r & l.rexpr == r
|
|
767
|
+
# (a&0xfff)^12 => (a^12)&0xfff
|
|
768
|
+
Expression[[l.lexpr, :^, r], :&, l.rexpr].reduce_rec
|
|
769
|
+
elsif r.kind_of?(Expression) and r.op == :& and r.rexpr.kind_of?(::Integer) and r.rexpr == l.rexpr
|
|
770
|
+
# (a&0xfff)^(b&0xfff) => (a^b)&0xfff
|
|
771
|
+
Expression[[l.lexpr, :^, r.lexpr], :&, l.rexpr].reduce_rec
|
|
772
|
+
end
|
|
773
|
+
end
|
|
774
|
+
end
|
|
736
775
|
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
776
|
+
def reduce_op_and(l, r)
|
|
777
|
+
if l == 0 or r == 0; 0
|
|
778
|
+
elsif r == 1 and l.kind_of?(Expression) and [:'==', :'!=', :<, :>, :<=, :>=].include?(l.op)
|
|
779
|
+
l
|
|
780
|
+
elsif l == r; l
|
|
781
|
+
elsif l.kind_of?(Integer); Expression[r, :&, l].reduce_rec
|
|
782
|
+
elsif l.kind_of?(Expression) and l.op == :&; Expression[l.lexpr, :&, [l.rexpr, :&, r]].reduce_rec
|
|
783
|
+
elsif l.kind_of?(Expression) and [:|, :^].include?(l.op) and r.kind_of?(Integer) and (l.op == :| or (r & (r+1)) != 0)
|
|
784
|
+
# (a ^| b) & i => (a&i ^| b&i)
|
|
785
|
+
Expression[[l.lexpr, :&, r], l.op, [l.rexpr, :&, r]].reduce_rec
|
|
786
|
+
elsif r.kind_of?(::Integer) and l.kind_of?(Expression) and (r & (r+1)) == 0
|
|
787
|
+
# foo & 0xffff
|
|
788
|
+
case l.op
|
|
789
|
+
when :+, :^
|
|
790
|
+
if l.lexpr.kind_of?(Expression) and l.lexpr.op == :& and
|
|
791
|
+
l.lexpr.rexpr.kind_of?(::Integer) and l.lexpr.rexpr & r == r
|
|
792
|
+
# ((a&m) + b) & m => (a+b) & m
|
|
793
|
+
Expression[[l.lexpr.lexpr, l.op, l.rexpr], :&, r].reduce_rec
|
|
794
|
+
elsif l.rexpr.kind_of?(Expression) and l.rexpr.op == :& and
|
|
795
|
+
l.rexpr.rexpr.kind_of?(::Integer) and l.rexpr.rexpr & r == r
|
|
796
|
+
# (a + (b&m)) & m => (a+b) & m
|
|
797
|
+
Expression[[l.lexpr, l.op, l.rexpr.lexpr], :&, r].reduce_rec
|
|
798
|
+
else
|
|
799
|
+
Expression[l, :&, r]
|
|
800
|
+
end
|
|
801
|
+
when :|
|
|
802
|
+
# rol/ror composition
|
|
803
|
+
reduce_rec_composerol l, r
|
|
752
804
|
else
|
|
753
|
-
Expression[
|
|
805
|
+
Expression[l, :&, r]
|
|
754
806
|
end
|
|
755
|
-
when :|
|
|
756
|
-
# rol/ror composition
|
|
757
|
-
reduce_rec_composerol e, mask
|
|
758
|
-
else
|
|
759
|
-
Expression[e, :&, mask]
|
|
760
807
|
end
|
|
761
808
|
end
|
|
762
809
|
|
|
@@ -766,14 +813,14 @@ class Expression < ExpressionType
|
|
|
766
813
|
m = Expression[['var', :sh_op, 'amt'], :|, ['var', :inv_sh_op, 'inv_amt']]
|
|
767
814
|
if vars = e.match(m, 'var', :sh_op, 'amt', :inv_sh_op, 'inv_amt') and vars[:sh_op] == {:>> => :<<, :<< => :>>}[vars[:inv_sh_op]] and
|
|
768
815
|
((vars['amt'].kind_of?(::Integer) and vars['inv_amt'].kind_of?(::Integer) and ampl = vars['amt'] + vars['inv_amt']) or
|
|
769
|
-
(vars['amt'].kind_of? Expression and vars['amt'].op == :% and vars['amt'].rexpr.kind_of?
|
|
816
|
+
(vars['amt'].kind_of? Expression and vars['amt'].op == :% and vars['amt'].rexpr.kind_of?(::Integer) and
|
|
770
817
|
vars['inv_amt'].kind_of? Expression and vars['inv_amt'].op == :% and vars['amt'].rexpr == vars['inv_amt'].rexpr and ampl = vars['amt'].rexpr)) and
|
|
771
818
|
mask == (1<<ampl)-1 and vars['var'].kind_of? Expression and # it's a rotation
|
|
772
819
|
|
|
773
820
|
vars['var'].op == :& and vars['var'].rexpr == mask and
|
|
774
821
|
ivars = vars['var'].lexpr.match(m, 'var', :sh_op, 'amt', :inv_sh_op, 'inv_amt') and ivars[:sh_op] == {:>> => :<<, :<< => :>>}[ivars[:inv_sh_op]] and
|
|
775
822
|
((ivars['amt'].kind_of?(::Integer) and ivars['inv_amt'].kind_of?(::Integer) and ampl = ivars['amt'] + ivars['inv_amt']) or
|
|
776
|
-
(ivars['amt'].kind_of? Expression and ivars['amt'].op == :% and ivars['amt'].rexpr.kind_of?
|
|
823
|
+
(ivars['amt'].kind_of? Expression and ivars['amt'].op == :% and ivars['amt'].rexpr.kind_of?(::Integer) and
|
|
777
824
|
ivars['inv_amt'].kind_of? Expression and ivars['inv_amt'].op == :% and ivars['amt'].rexpr == ivars['inv_amt'].rexpr and ampl = ivars['amt'].rexpr))
|
|
778
825
|
if ivars[:sh_op] != vars[:sh_op]
|
|
779
826
|
# ensure the rotations are the same orientation
|
|
@@ -788,6 +835,48 @@ class Expression < ExpressionType
|
|
|
788
835
|
end
|
|
789
836
|
end
|
|
790
837
|
|
|
838
|
+
def reduce_op_or(l, r)
|
|
839
|
+
if l == 0; r
|
|
840
|
+
elsif r == 0; l
|
|
841
|
+
elsif l == -1 or r == -1; -1
|
|
842
|
+
elsif l == r; l
|
|
843
|
+
elsif l.kind_of? Integer; Expression[r, :|, l].reduce_rec
|
|
844
|
+
elsif l.kind_of? Expression and l.op == :|
|
|
845
|
+
# (a|b)|c => a|(b|c)
|
|
846
|
+
Expression[l.lexpr, :|, [l.rexpr, :|, r]].reduce_rec
|
|
847
|
+
elsif l.kind_of? Expression and l.op == :& and r.kind_of? Expression and r.op == :& and l.lexpr == r.lexpr
|
|
848
|
+
# (a&b)|(a&c) => a&(b|c)
|
|
849
|
+
Expression[l.lexpr, :&, [l.rexpr, :|, r.rexpr]].reduce_rec
|
|
850
|
+
end
|
|
851
|
+
end
|
|
852
|
+
|
|
853
|
+
def reduce_op_times(l, r)
|
|
854
|
+
if l == 0 or r == 0; 0
|
|
855
|
+
elsif l == 1; r
|
|
856
|
+
elsif r == 1; l
|
|
857
|
+
elsif r.kind_of? Integer; Expression[r, :*, l].reduce_rec
|
|
858
|
+
elsif r.kind_of? Expression and r.op == :*; Expression[[l, :*, r.lexpr], :*, r.rexpr].reduce_rec
|
|
859
|
+
elsif l.kind_of? Integer and r.kind_of? Expression and r.op == :* and r.lexpr.kind_of? Integer; Expression[l*r.lexpr, :*, r.rexpr].reduce_rec # XXX need & regsize..
|
|
860
|
+
elsif l.kind_of? Integer and r.kind_of? Expression and r.op == :+ and r.rexpr.kind_of? Integer; Expression[[l, :*, r.lexpr], :+, l*r.rexpr].reduce_rec
|
|
861
|
+
end
|
|
862
|
+
end
|
|
863
|
+
|
|
864
|
+
def reduce_op_div(l, r)
|
|
865
|
+
if r == 0
|
|
866
|
+
elsif r.kind_of? Integer and l.kind_of? Expression and l.op == :+ and l.rexpr.kind_of? Integer and l.rexpr % r == 0
|
|
867
|
+
Expression[[l.lexpr, :/, r], :+, l.rexpr/r].reduce_rec
|
|
868
|
+
elsif r.kind_of? Integer and l.kind_of? Expression and l.op == :* and l.lexpr % r == 0
|
|
869
|
+
Expression[l.lexpr/r, :*, l.rexpr].reduce_rec
|
|
870
|
+
end
|
|
871
|
+
end
|
|
872
|
+
|
|
873
|
+
def reduce_op_mod(l, r)
|
|
874
|
+
if r.kind_of?(Integer) and r != 0 and (r & (r-1) == 0)
|
|
875
|
+
Expression[l, :&, r-1].reduce_rec
|
|
876
|
+
end
|
|
877
|
+
end
|
|
878
|
+
|
|
879
|
+
|
|
791
880
|
# a pattern-matching method
|
|
792
881
|
# Expression[42, :+, 28].match(Expression['any', :+, 28], 'any') => {'any' => 42}
|
|
793
882
|
# Expression[42, :+, 28].match(Expression['any', :+, 'any'], 'any') => false
|
|
@@ -816,24 +905,29 @@ class Expression < ExpressionType
|
|
|
816
905
|
# returns the array of non-numeric members of the expression
|
|
817
906
|
# if a variables appears 3 times, it will be present 3 times in the returned array
|
|
818
907
|
def externals
|
|
819
|
-
|
|
908
|
+
a = []
|
|
909
|
+
[@rexpr, @lexpr].each { |e|
|
|
820
910
|
case e
|
|
821
911
|
when ExpressionType; a.concat e.externals
|
|
822
912
|
when nil, ::Numeric; a
|
|
823
913
|
else a << e
|
|
824
914
|
end
|
|
825
915
|
}
|
|
916
|
+
a
|
|
826
917
|
end
|
|
827
918
|
|
|
828
919
|
# returns the externals that appears in the expression, does not walk through other ExpressionType
|
|
829
|
-
def expr_externals
|
|
830
|
-
|
|
920
|
+
def expr_externals(include_exprs=false)
|
|
921
|
+
a = []
|
|
922
|
+
[@rexpr, @lexpr].each { |e|
|
|
831
923
|
case e
|
|
832
|
-
when Expression; a.concat e.expr_externals
|
|
833
|
-
when nil, ::Numeric
|
|
924
|
+
when Expression; a.concat e.expr_externals(include_exprs)
|
|
925
|
+
when nil, ::Numeric; a
|
|
926
|
+
when ExpressionType; include_exprs ? a << e : a
|
|
834
927
|
else a << e
|
|
835
928
|
end
|
|
836
929
|
}
|
|
930
|
+
a
|
|
837
931
|
end
|
|
838
932
|
|
|
839
933
|
def inspect
|
|
@@ -843,6 +937,25 @@ class Expression < ExpressionType
|
|
|
843
937
|
Unknown = self[:unknown]
|
|
844
938
|
end
|
|
845
939
|
|
|
940
|
+
# An Expression with a custom string representation
|
|
941
|
+
# used to show #define constants, struct offsets, func local vars, etc
|
|
942
|
+
class ExpressionString < ExpressionType
|
|
943
|
+
attr_accessor :expr, :str, :type, :hide_str
|
|
944
|
+
def reduce; expr.reduce; end
|
|
945
|
+
def reduce_rec; expr.reduce_rec; end
|
|
946
|
+
def bind(*a); expr.bind(*a); end
|
|
947
|
+
def externals; expr.externals; end
|
|
948
|
+
def expr_externals; expr.expr_externals; end
|
|
949
|
+
def match_rec(*a); expr.match_rec(*a); end
|
|
950
|
+
def initialize(expr, str, type=nil)
|
|
951
|
+
@expr = Expression[expr]
|
|
952
|
+
@str = str
|
|
953
|
+
@type = type
|
|
954
|
+
end
|
|
955
|
+
def render_str ; [str] ; end
|
|
956
|
+
def inspect ; "ExpressionString.new(#{@expr.inspect}, #{str.inspect}, #{type.inspect})" ; end
|
|
957
|
+
end
|
|
958
|
+
|
|
846
959
|
# an EncodedData relocation, specifies a value to patch in
|
|
847
960
|
class Relocation
|
|
848
961
|
# the relocation value (an Expression)
|
|
@@ -855,7 +968,7 @@ class Relocation
|
|
|
855
968
|
include Backtrace
|
|
856
969
|
|
|
857
970
|
def initialize(target, type, endianness, backtrace = nil)
|
|
858
|
-
raise ArgumentError, "bad args #{[target, type, endianness].inspect}" if not target.kind_of? Expression or not type.kind_of?
|
|
971
|
+
raise ArgumentError, "bad args #{[target, type, endianness].inspect}" if not target.kind_of? Expression or not type.kind_of?(::Symbol) or not endianness.kind_of?(::Symbol)
|
|
859
972
|
@target, @type, @endianness, @backtrace = target, type, endianness, backtrace
|
|
860
973
|
end
|
|
861
974
|
|
|
@@ -890,7 +1003,11 @@ class EncodedData
|
|
|
890
1003
|
def ptr=(p) @ptr = @export[p] || p end
|
|
891
1004
|
|
|
892
1005
|
# opts' keys in :reloc, :export, :virtsize, defaults to empty/empty/data.length
|
|
893
|
-
def initialize(data
|
|
1006
|
+
def initialize(data='', opts={})
|
|
1007
|
+
if data.respond_to?(:force_encoding) and data.encoding.name != 'ASCII-8BIT' and data.length > 0
|
|
1008
|
+
puts "Forcing edata.data.encoding = BINARY at", caller if $DEBUG
|
|
1009
|
+
data = data.dup.force_encoding('binary')
|
|
1010
|
+
end
|
|
894
1011
|
@data = data
|
|
895
1012
|
@reloc = opts[:reloc] || {}
|
|
896
1013
|
@export = opts[:export] || {}
|
|
@@ -904,9 +1021,10 @@ class EncodedData
|
|
|
904
1021
|
if set_inv or not @inv_export[off]
|
|
905
1022
|
@inv_export[off] = label
|
|
906
1023
|
end
|
|
1024
|
+
label
|
|
907
1025
|
end
|
|
908
1026
|
|
|
909
|
-
def del_export(label, off=@
|
|
1027
|
+
def del_export(label, off=@export[label])
|
|
910
1028
|
@export.delete label
|
|
911
1029
|
if e = @export.index(off)
|
|
912
1030
|
@inv_export[off] = e
|
|
@@ -942,6 +1060,7 @@ class EncodedData
|
|
|
942
1060
|
# if numeric, replace the raw data with the encoding of this value (+fill+s preceding data if needed) and remove the reloc
|
|
943
1061
|
# if replace_target is true, the reloc target is replaced with its bound counterpart
|
|
944
1062
|
def fixup_choice(binding, replace_target)
|
|
1063
|
+
return if binding.empty?
|
|
945
1064
|
@reloc.keys.each { |off|
|
|
946
1065
|
val = @reloc[off].target.bind(binding).reduce
|
|
947
1066
|
if val.kind_of? Integer
|
|
@@ -973,13 +1092,15 @@ class EncodedData
|
|
|
973
1092
|
return {} if not key
|
|
974
1093
|
base = (@export[key] == 0 ? key : Expression[key, :-, @export[key]])
|
|
975
1094
|
end
|
|
976
|
-
|
|
1095
|
+
binding = {}
|
|
1096
|
+
@export.each { |n, o| binding.update n => Expression.new(:+, o, base) }
|
|
1097
|
+
binding
|
|
977
1098
|
end
|
|
978
1099
|
|
|
979
1100
|
# returns an array of variables that needs to be defined for a complete #fixup
|
|
980
1101
|
# ie the list of externals for all relocations
|
|
981
|
-
def reloc_externals
|
|
982
|
-
@reloc.values.map { |r| r.target.externals }.flatten.uniq -
|
|
1102
|
+
def reloc_externals(interns = @export.keys)
|
|
1103
|
+
@reloc.values.map { |r| r.target.externals }.flatten.uniq - interns
|
|
983
1104
|
end
|
|
984
1105
|
|
|
985
1106
|
# returns the offset where the relocation for target t is to be applied
|
|
@@ -1008,7 +1129,7 @@ class EncodedData
|
|
|
1008
1129
|
end
|
|
1009
1130
|
|
|
1010
1131
|
# concatenation of another +EncodedData+ (or nil/Fixnum/anything supporting String#<<)
|
|
1011
|
-
def <<
|
|
1132
|
+
def <<(other)
|
|
1012
1133
|
case other
|
|
1013
1134
|
when nil
|
|
1014
1135
|
when ::Fixnum
|
|
@@ -1036,6 +1157,10 @@ class EncodedData
|
|
|
1036
1157
|
@virtsize += other.virtsize
|
|
1037
1158
|
else
|
|
1038
1159
|
fill
|
|
1160
|
+
if other.respond_to?(:force_encoding) and other.encoding.name != 'ASCII-8BIT'
|
|
1161
|
+
puts "Forcing edata.data.encoding = BINARY at", caller if $DEBUG
|
|
1162
|
+
other = other.dup.force_encoding('binary')
|
|
1163
|
+
end
|
|
1039
1164
|
if @data.empty?; @data = other.dup
|
|
1040
1165
|
elsif not @data.kind_of?(String); @data = @data.to_str << other
|
|
1041
1166
|
else @data << other
|
|
@@ -1047,7 +1172,7 @@ class EncodedData
|
|
|
1047
1172
|
end
|
|
1048
1173
|
|
|
1049
1174
|
# equivalent to dup << other, filters out Integers & nil
|
|
1050
|
-
def +
|
|
1175
|
+
def +(other)
|
|
1051
1176
|
raise ArgumentError if not other or other.kind_of?(Integer)
|
|
1052
1177
|
dup << other
|
|
1053
1178
|
end
|
|
@@ -1092,7 +1217,7 @@ class EncodedData
|
|
|
1092
1217
|
val = len
|
|
1093
1218
|
len = nil
|
|
1094
1219
|
end
|
|
1095
|
-
if not len and from.kind_of?
|
|
1220
|
+
if not len and from.kind_of?(::Range)
|
|
1096
1221
|
b = from.begin
|
|
1097
1222
|
e = from.end
|
|
1098
1223
|
b = @export[b] if @export[b]
|
|
@@ -1104,14 +1229,14 @@ class EncodedData
|
|
|
1104
1229
|
from = b
|
|
1105
1230
|
end
|
|
1106
1231
|
from = @export[from] || from
|
|
1107
|
-
raise "invalid offset #{from}" if not from.kind_of?
|
|
1232
|
+
raise "invalid offset #{from}" if not from.kind_of?(::Integer)
|
|
1108
1233
|
from = from + @virtsize if from < 0
|
|
1109
1234
|
|
|
1110
1235
|
if not len
|
|
1111
|
-
val = val.chr if val.kind_of?
|
|
1236
|
+
val = val.chr if val.kind_of?(::Integer)
|
|
1112
1237
|
len = val.length
|
|
1113
1238
|
end
|
|
1114
|
-
raise "invalid slice length #{len}" if not len.kind_of?
|
|
1239
|
+
raise "invalid slice length #{len}" if not len.kind_of?(::Integer) or len < 0
|
|
1115
1240
|
|
|
1116
1241
|
if from >= @virtsize
|
|
1117
1242
|
len = 0
|
|
@@ -1170,24 +1295,24 @@ class EncodedData
|
|
|
1170
1295
|
def pattern_scan(pat, chunksz=nil, margin=nil)
|
|
1171
1296
|
chunksz ||= 4*1024*1024 # scan 4MB at a time
|
|
1172
1297
|
margin ||= 65536 # add this much bytes at each chunk to find /pat/ over chunk boundaries
|
|
1173
|
-
pat = Regexp.new(Regexp.escape(pat)) if pat.kind_of?
|
|
1298
|
+
pat = Regexp.new(Regexp.escape(pat)) if pat.kind_of?(::String)
|
|
1174
1299
|
|
|
1175
1300
|
found = []
|
|
1176
1301
|
chunkoff = 0
|
|
1177
1302
|
while chunkoff < @data.length
|
|
1178
1303
|
chunk = @data[chunkoff, chunksz+margin].to_str
|
|
1179
1304
|
off = 0
|
|
1180
|
-
while
|
|
1181
|
-
|
|
1182
|
-
|
|
1305
|
+
while match = chunk[off..-1].match(pat)
|
|
1306
|
+
off += match.pre_match.length
|
|
1307
|
+
m_l = match[0].length
|
|
1308
|
+
break if off >= chunksz # match fully in margin
|
|
1309
|
+
match_addr = chunkoff + off
|
|
1183
1310
|
found << match_addr if not block_given? or yield(match_addr)
|
|
1184
|
-
off +=
|
|
1185
|
-
# XXX +1 or +lastmatch.length ?
|
|
1186
|
-
# 'aaaabc'.pattern_scan(/a*bc/) will match 5 times here
|
|
1311
|
+
off += m_l
|
|
1187
1312
|
end
|
|
1188
1313
|
chunkoff += chunksz
|
|
1189
1314
|
end
|
|
1190
|
-
|
|
1315
|
+
found
|
|
1191
1316
|
end
|
|
1192
1317
|
end
|
|
1193
1318
|
end
|