SymEval for POWER: WIP
[dyninst.git] / symEval / rose / x86InstructionSemantics.h
1 #ifndef ROSE_X86INSTRUCTIONSEMANTICS_H
2 #define ROSE_X86INSTRUCTIONSEMANTICS_H
3
4 //#include "rose.h"
5 #include "semanticsModule.h"
6 #include <cassert>
7 #include <cstdio>
8 #include <iostream>
9 #include "rose.h"
10
11 #include "integerOps.h"
12
13
14 #include "SgAsmx86Instruction.h"
15 #include "SgAsmExpression.h"
16 #include "conversions.h"
17
18 /* Returns the segment register corresponding to the specified register reference address expression. */
19 static inline X86SegmentRegister getSegregFromMemoryReference(SgAsmMemoryReferenceExpression* mr) {
20     X86SegmentRegister segreg = x86_segreg_none;
21     SgAsmx86RegisterReferenceExpression* seg = isSgAsmx86RegisterReferenceExpression(mr->get_segment());
22     if (seg) {
23         ROSE_ASSERT(seg->get_register_class() == x86_regclass_segment);
24         segreg = (X86SegmentRegister)(seg->get_register_number());
25     } else {
26         ROSE_ASSERT(!"Bad segment expr");
27     }
28     if (segreg == x86_segreg_none) segreg = x86_segreg_ds;
29     return segreg;
30 }
31
32 template <typename Policy, template <size_t> class WordType>
33 struct X86InstructionSemantics {
34 #   ifdef Word
35 #       error "Having a macro called \"Word\" conflicts with x86InstructionSemantics.h"
36 #   else
37 #       define Word(Len) WordType<(Len)>
38 #   endif
39
40     Policy& policy;
41
42     X86InstructionSemantics(Policy& policy)
43         : policy(policy)
44         {}
45     virtual ~X86InstructionSemantics() {}
46
47     /* If the counter (cx register) is non-zero then decrement it. The return value is a flag indicating whether cx was
48      * originally non-zero. */
49     Word(1) stringop_setup_loop() {
50         Word(1) ecxNotZero = policy.invert(policy.equalToZero(policy.readGPR(x86_gpr_cx)));
51         policy.writeGPR(x86_gpr_cx,
52                         policy.add(policy.readGPR(x86_gpr_cx),
53                                    policy.ite(ecxNotZero, number<32>(-1), number<32>(0))));
54         return ecxNotZero;
55     }
56
57     /* Instruction semantics for rep_stosN where N is 1(b), 2(w), or 4(d).
58      * This method handles semantics for one iteration of stosN.
59      * See https://siyobik.info/index.php?module=x86&id=279 */
60     template<size_t N>
61     void rep_stos_semantics(SgAsmx86Instruction *insn) {
62         Word(1) ecxNotZero = policy.invert(policy.equalToZero(policy.readGPR(x86_gpr_cx)));
63
64         /* Fill memory pointed to by ES:[DI] with contents of AX register if counter was not zero. */
65         policy.writeMemory(x86_segreg_es,
66                            policy.readGPR(x86_gpr_di),
67                            extract<0, 8*N>(policy.readGPR(x86_gpr_ax)),
68                            ecxNotZero);
69
70         /* Update DI by incrementing or decrementing by number of bytes copied (only if counter is nonzero) */
71         policy.writeGPR(x86_gpr_di,
72                         policy.add(policy.readGPR(x86_gpr_di),
73                                    policy.ite(ecxNotZero,
74                                               policy.ite(policy.readFlag(x86_flag_df), number<32>(-N), number<32>(N)),
75                                               number<32>(0))));
76
77         /* Decrement the counter if not already zero. */
78         policy.writeGPR(x86_gpr_cx,
79                         policy.add(policy.readGPR(x86_gpr_cx),
80                                    policy.ite(ecxNotZero, number<32>(-1), number<32>(0))));
81
82         /* If counter is now nonzero then repeat this instruction, otherwise go to the next one. */
83         ecxNotZero = policy.invert(policy.equalToZero(policy.readGPR(x86_gpr_cx)));
84         policy.writeIP(policy.ite(ecxNotZero, number<32>((uint32_t)(insn->get_address())), policy.readIP()));
85     }
86
87     /* Instruction semantics for stosN where N is 1(b), 2(w), or 4(d) */
88     template<size_t N>
89     void stos_semantics(SgAsmx86Instruction *insn) {
90         const SgAsmExpressionPtrList& operands = insn->get_operandList()->get_operands();
91         ROSE_ASSERT(operands.size() == 0);
92         ROSE_ASSERT(insn->get_addressSize() == x86_insnsize_32);
93
94         /* Fill memory pointed to by ES:[DI] with contents of AX. */
95         policy.writeMemory(x86_segreg_es,
96                            policy.readGPR(x86_gpr_di),
97                            extract<0, 8*N>(policy.readGPR(x86_gpr_ax)),
98                            policy.true_());
99
100         /* Update DI */ /*FIXME: Is this correct? */
101         policy.writeGPR(x86_gpr_di,
102                         policy.add(policy.readGPR(x86_gpr_di),
103                                    policy.ite(policy.readFlag(x86_flag_df), number<32>(-N), number<32>(N))));
104     }
105     
106
107     template <size_t Len>
108     Word(Len) invertMaybe(const Word(Len)& w, bool inv) {
109         if (inv) {
110             return policy.invert(w);
111         } else {
112             return w;
113         }
114     }
115
116     template <size_t Len>
117     Word(Len) number(uintmax_t v) {
118         return policy.template number<Len>(v);
119     }
120
121     template <size_t From, size_t To, size_t Len>
122         Word(To - From) extract(Word(Len) w) {
123         return policy.template extract<From, To>(w);
124     }
125
126     template <size_t From, size_t To>
127         Word(To) signExtend(Word(From) w) {
128         return policy.template signExtend<From, To>(w);
129     }
130
131     template <size_t Len>
132     Word(1) greaterOrEqualToTen(Word(Len) w) {
133         Word(Len) carries = number<Len>(0);
134         policy.addWithCarries(w, number<Len>(6), policy.false_(), carries);
135         return extract<Len - 1, Len>(carries);
136     }
137
138     Word(32) readEflags() {
139         return policy.concat(readFlags(), number<16>(0x0000));
140     }
141
142     Word(16) readFlags() {
143         return policy.concat(policy.readFlag((X86Flag)0 ),
144                              policy.concat(policy.readFlag((X86Flag)1 ),
145                              policy.concat(policy.readFlag((X86Flag)2 ),
146                              policy.concat(policy.readFlag((X86Flag)3 ),
147                              policy.concat(policy.readFlag((X86Flag)4 ),
148                              policy.concat(policy.readFlag((X86Flag)5 ),
149                              policy.concat(policy.readFlag((X86Flag)6 ),
150                              policy.concat(policy.readFlag((X86Flag)7 ),
151                              policy.concat(policy.readFlag((X86Flag)8 ),
152                              policy.concat(policy.readFlag((X86Flag)9 ),
153                              policy.concat(policy.readFlag((X86Flag)10),
154                              policy.concat(policy.readFlag((X86Flag)11),
155                              policy.concat(policy.readFlag((X86Flag)12),
156                              policy.concat(policy.readFlag((X86Flag)13),
157                              policy.concat(policy.readFlag((X86Flag)14),
158                                            policy.readFlag((X86Flag)15))))))))))))))));
159     }
160
161     template <size_t Len/*bits*/>
162     Word(Len) readMemory(X86SegmentRegister segreg, const Word(32)& addr, Word(1) cond) {
163         return policy.template readMemory<Len>(segreg, addr, cond);
164     }
165
166     Word(32) readEffectiveAddress(SgAsmExpression* expr) {
167         assert (isSgAsmMemoryReferenceExpression(expr));
168         return read32(isSgAsmMemoryReferenceExpression(expr)->get_address());
169     }
170
171     /* Returns an eight-bit value desribed by an instruction operand. */
172     Word(8) read8(SgAsmExpression* e) {
173         switch (e->variantT()) {
174             case V_SgAsmx86RegisterReferenceExpression: {
175                 SgAsmx86RegisterReferenceExpression* rre = isSgAsmx86RegisterReferenceExpression(e);
176                 switch (rre->get_register_class()) {
177                     case x86_regclass_gpr: {
178                         X86GeneralPurposeRegister reg = (X86GeneralPurposeRegister)(rre->get_register_number());
179                         Word(32) rawValue = policy.readGPR(reg);
180                         switch (rre->get_position_in_register()) {
181                             case x86_regpos_low_byte: return extract<0, 8>(rawValue);
182                             case x86_regpos_high_byte: return extract<8, 16>(rawValue);
183                             default: ROSE_ASSERT(!"Bad position in register");
184                         }
185                     }
186                     default: {
187                         fprintf(stderr, "Bad register class %s\n", regclassToString(rre->get_register_class()));
188                         abort();
189                     }
190                 }
191                 break;
192             }
193             case V_SgAsmBinaryAdd: {
194                 return policy.add(read8(isSgAsmBinaryAdd(e)->get_lhs()), read8(isSgAsmBinaryAdd(e)->get_rhs()));
195             }
196             case V_SgAsmBinaryMultiply: {
197                 SgAsmByteValueExpression* rhs = isSgAsmByteValueExpression(isSgAsmBinaryMultiply(e)->get_rhs());
198                 ROSE_ASSERT(rhs);
199                 SgAsmExpression* lhs = isSgAsmBinaryMultiply(e)->get_lhs();
200                 return extract<0, 8>(policy.unsignedMultiply(read8(lhs), read8(rhs)));
201             }
202             case V_SgAsmMemoryReferenceExpression: {
203                 return readMemory<8>(getSegregFromMemoryReference(isSgAsmMemoryReferenceExpression(e)),
204                                      readEffectiveAddress(e), policy.true_());
205             }
206             case V_SgAsmByteValueExpression:
207             case V_SgAsmWordValueExpression:
208             case V_SgAsmDoubleWordValueExpression:
209             case V_SgAsmQuadWordValueExpression: {
210                 uint64_t val = SageInterface::getAsmSignedConstant(isSgAsmValueExpression(e));
211                 return number<8>(val & 0xFFU);
212             }
213             default: {
214                 fprintf(stderr, "Bad variant %s in read8\n", e->class_name().c_str());
215                 abort();
216             }
217         }
218     }
219
220     /* Returns a 16-bit value described by an instruction operand. */
221     Word(16) read16(SgAsmExpression* e) {
222         switch (e->variantT()) {
223             case V_SgAsmx86RegisterReferenceExpression: {
224                 SgAsmx86RegisterReferenceExpression* rre = isSgAsmx86RegisterReferenceExpression(e);
225                 ROSE_ASSERT(rre->get_position_in_register() == x86_regpos_word);
226                 switch (rre->get_register_class()) {
227                     case x86_regclass_gpr: {
228                         X86GeneralPurposeRegister reg = (X86GeneralPurposeRegister)(rre->get_register_number());
229                         Word(32) rawValue = policy.readGPR(reg);
230                         return extract<0, 16>(rawValue);
231                     }
232                     case x86_regclass_segment: {
233                         X86SegmentRegister sr = (X86SegmentRegister)(rre->get_register_number());
234                         Word(16) value = policy.readSegreg(sr);
235                         return value;
236                     }
237                     default: {
238                         fprintf(stderr, "Bad register class %s\n", regclassToString(rre->get_register_class()));
239                         abort();
240                     }
241                 }
242                 break;
243             }
244             case V_SgAsmBinaryAdd: {
245                 return policy.add(read16(isSgAsmBinaryAdd(e)->get_lhs()), read16(isSgAsmBinaryAdd(e)->get_rhs()));
246             }
247             case V_SgAsmBinaryMultiply: {
248                 SgAsmByteValueExpression* rhs = isSgAsmByteValueExpression(isSgAsmBinaryMultiply(e)->get_rhs());
249                 ROSE_ASSERT(rhs);
250                 SgAsmExpression* lhs = isSgAsmBinaryMultiply(e)->get_lhs();
251                 return extract<0, 16>(policy.unsignedMultiply(read16(lhs), read8(rhs)));
252             }
253             case V_SgAsmMemoryReferenceExpression: {
254                 return readMemory<16>(getSegregFromMemoryReference(isSgAsmMemoryReferenceExpression(e)),
255                                       readEffectiveAddress(e), policy.true_());
256             }
257             case V_SgAsmByteValueExpression:
258             case V_SgAsmWordValueExpression:
259             case V_SgAsmDoubleWordValueExpression:
260             case V_SgAsmQuadWordValueExpression: {
261                 uint64_t val = SageInterface::getAsmSignedConstant(isSgAsmValueExpression(e));
262                 return number<16>(val & 0xFFFFU);
263             }
264             default: {
265                 fprintf(stderr, "Bad variant %s in read16\n", e->class_name().c_str());
266                 abort();
267             }
268         }
269     }
270
271     /* Returns a 32-bit value described by an instruction operand. */
272     Word(32) read32(SgAsmExpression* e) {
273         switch (e->variantT()) {
274             case V_SgAsmx86RegisterReferenceExpression: {
275                 SgAsmx86RegisterReferenceExpression* rre = isSgAsmx86RegisterReferenceExpression(e);
276                 switch (rre->get_register_class()) {
277                     case x86_regclass_gpr: {
278                         X86GeneralPurposeRegister reg = (X86GeneralPurposeRegister)(rre->get_register_number());
279                         Word(32) rawValue = policy.readGPR(reg);
280                         switch (rre->get_position_in_register()) {
281                             case x86_regpos_dword:
282                             case x86_regpos_all:
283                                 return rawValue;
284                             case x86_regpos_word:
285                                 return policy.concat(extract<0, 16>(rawValue), number<16>(0));
286                             default:
287                               fprintf(stderr, "Error: position %d\n", rre->get_position_in_register());
288                               ROSE_ASSERT(!"bad position in register");
289                         }
290                     }
291                     case x86_regclass_segment: {
292                         ROSE_ASSERT(rre->get_position_in_register() == x86_regpos_dword ||
293                                     rre->get_position_in_register() == x86_regpos_all);
294                         X86SegmentRegister sr = (X86SegmentRegister)(rre->get_register_number());
295                         Word(16) value = policy.readSegreg(sr);
296                         return policy.concat(value, number<16>(0));
297                     }
298                     default: {
299                         fprintf(stderr, "Bad register class %s\n", regclassToString(rre->get_register_class()));
300                         abort();
301                     }
302                 }
303                 break;
304             }
305             case V_SgAsmBinaryAdd: {
306                 return policy.add(read32(isSgAsmBinaryAdd(e)->get_lhs()), read32(isSgAsmBinaryAdd(e)->get_rhs()));
307             }
308             case V_SgAsmBinaryMultiply: {
309                 SgAsmByteValueExpression* rhs = isSgAsmByteValueExpression(isSgAsmBinaryMultiply(e)->get_rhs());
310                 ROSE_ASSERT(rhs);
311                 SgAsmExpression* lhs = isSgAsmBinaryMultiply(e)->get_lhs();
312                 return extract<0, 32>(policy.unsignedMultiply(read32(lhs), read8(rhs)));
313             }
314             case V_SgAsmMemoryReferenceExpression: {
315                 return readMemory<32>(getSegregFromMemoryReference(isSgAsmMemoryReferenceExpression(e)),
316                                       readEffectiveAddress(e), policy.true_());
317             }
318             case V_SgAsmByteValueExpression:
319             case V_SgAsmWordValueExpression:
320             case V_SgAsmDoubleWordValueExpression:
321             case V_SgAsmQuadWordValueExpression: {
322                 uint64_t val = SageInterface::getAsmSignedConstant(isSgAsmValueExpression(e));
323                 return number<32>(val & 0xFFFFFFFFU);
324             }
325             default: {
326                 fprintf(stderr, "Bad variant %s in read32\n", e->class_name().c_str());
327                 abort();
328             }
329         }
330     }
331
332     /* Replaces the least significant byte of a general purpose register with a new value. */
333     void updateGPRLowByte(X86GeneralPurposeRegister reg, const Word(8)& value) {
334         Word(32) oldValue = policy.readGPR(reg);
335         policy.writeGPR(reg, policy.concat(value, extract<8, 32>(oldValue)));
336     }
337
338     /* Replaces bits 8 through 15 of a 32-bit register with the specified 8-bit value. */
339     void updateGPRHighByte(X86GeneralPurposeRegister reg, const Word(8)& value) {
340         Word(32) oldValue = policy.readGPR(reg);
341         policy.writeGPR(reg, policy.concat(extract<0, 8>(oldValue),
342                                            policy.concat(value, extract<16, 32>(oldValue))));
343     }
344
345     /* Replaces the least significant 16 bits of a general purpose register with a new value. */
346     void updateGPRLowWord(X86GeneralPurposeRegister reg, const Word(16)& value) {
347         Word(32) oldValue = policy.readGPR(reg);
348         policy.writeGPR(reg, policy.concat(value, extract<16, 32>(oldValue)));
349     }
350
351     /* Writes the specified eight-bit value to the location specified by an instruction operand. */
352     void write8(SgAsmExpression* e, const Word(8)& value) {
353         switch (e->variantT()) {
354             case V_SgAsmx86RegisterReferenceExpression: {
355                 SgAsmx86RegisterReferenceExpression* rre = isSgAsmx86RegisterReferenceExpression(e);
356                 switch (rre->get_register_class()) {
357                     case x86_regclass_gpr: {
358                         X86GeneralPurposeRegister reg = (X86GeneralPurposeRegister)(rre->get_register_number());
359                         switch (rre->get_position_in_register()) {
360                             case x86_regpos_low_byte: updateGPRLowByte(reg, value); break;
361                             case x86_regpos_high_byte: updateGPRHighByte(reg, value); break;
362                             default: ROSE_ASSERT(!"Bad position in register");
363                         }
364                         break;
365                     }
366                     default: {
367                         fprintf(stderr, "Bad register class %s\n", regclassToString(rre->get_register_class()));
368                         abort();
369                     }
370                 }
371                 break;
372             }
373             case V_SgAsmMemoryReferenceExpression: {
374                 policy.writeMemory(getSegregFromMemoryReference(isSgAsmMemoryReferenceExpression(e)),
375                                    readEffectiveAddress(e), value, policy.true_());
376                 break;
377             }
378             default: {
379                 fprintf(stderr, "Bad variant %s in write8\n", e->class_name().c_str());
380                 abort();
381             }
382         }
383     }
384
385     /* Writes the specified 16-bit value to the location specified by an instruction operand. */
386     void write16(SgAsmExpression* e, const Word(16)& value) {
387         switch (e->variantT()) {
388             case V_SgAsmx86RegisterReferenceExpression: {
389                 SgAsmx86RegisterReferenceExpression* rre = isSgAsmx86RegisterReferenceExpression(e);
390                 switch (rre->get_register_class()) {
391                     case x86_regclass_gpr: {
392                         X86GeneralPurposeRegister reg = (X86GeneralPurposeRegister)(rre->get_register_number());
393                         switch (rre->get_position_in_register()) {
394                             case x86_regpos_word: updateGPRLowWord(reg, value); break;
395                             default: ROSE_ASSERT(!"Bad position in register");
396                         }
397                         break;
398                     }
399                     case x86_regclass_segment: {
400                         X86SegmentRegister sr = (X86SegmentRegister)(rre->get_register_number());
401                         policy.writeSegreg(sr, value);
402                         break;
403                     }
404                     default: {
405                         fprintf(stderr, "Bad register class %s\n", regclassToString(rre->get_register_class()));
406                         abort();
407                     }
408                 }
409                 break;
410             }
411             case V_SgAsmMemoryReferenceExpression: {
412                 policy.writeMemory(getSegregFromMemoryReference(isSgAsmMemoryReferenceExpression(e)),
413                                    readEffectiveAddress(e), value, policy.true_());
414                 break;
415             }
416             default: {
417                 fprintf(stderr, "Bad variant %s in write16\n", e->class_name().c_str());
418                 abort();
419             }
420         }
421     }
422
423     /* Writes the specified 32-bit value to the location specified by an instruction operand. */
424     void write32(SgAsmExpression* e, const Word(32)& value) {
425         switch (e->variantT()) {
426             case V_SgAsmx86RegisterReferenceExpression: {
427                 SgAsmx86RegisterReferenceExpression* rre = isSgAsmx86RegisterReferenceExpression(e);
428                 switch (rre->get_register_class()) {
429                     case x86_regclass_gpr: {
430                         X86GeneralPurposeRegister reg = (X86GeneralPurposeRegister)(rre->get_register_number());
431                         switch (rre->get_position_in_register()) {
432                             case x86_regpos_dword:
433                             case x86_regpos_all: {
434                                 break;
435                             }
436                             default: ROSE_ASSERT(!"Bad position in register");
437                         }
438                         policy.writeGPR(reg, value);
439                         break;
440                     }
441                     case x86_regclass_segment: { // Used for pop of segment registers
442                         X86SegmentRegister sr = (X86SegmentRegister)(rre->get_register_number());
443                         policy.writeSegreg(sr, extract<0, 16>(value));
444                         break;
445                     }
446                     default: {
447                         fprintf(stderr, "Bad register class %s\n", regclassToString(rre->get_register_class()));
448                         abort();
449                     }
450                 }
451                 break;
452             }
453             case V_SgAsmMemoryReferenceExpression: {
454                 policy.writeMemory(getSegregFromMemoryReference(isSgAsmMemoryReferenceExpression(e)),
455                                    readEffectiveAddress(e), value, policy.true_());
456                 break;
457             }
458             default: {
459                 fprintf(stderr, "Bad variant %s in write32\n", e->class_name().c_str());
460                 abort();
461             }
462         }
463     }
464
465     /* Returns true if W has an even number of bits set; false for an odd number */
466     Word(1) parity(Word(8) w) {
467         Word(1) p01 = policy.xor_(extract<0, 1>(w), extract<1, 2>(w));
468         Word(1) p23 = policy.xor_(extract<2, 3>(w), extract<3, 4>(w));
469         Word(1) p45 = policy.xor_(extract<4, 5>(w), extract<5, 6>(w));
470         Word(1) p67 = policy.xor_(extract<6, 7>(w), extract<7, 8>(w));
471         Word(1) p0123 = policy.xor_(p01, p23);
472         Word(1) p4567 = policy.xor_(p45, p67);
473         return policy.invert(policy.xor_(p0123, p4567));
474     }
475
476     /* Sets flags: parity, sign, and zero */
477     template <size_t Len>
478     void setFlagsForResult(const Word(Len)& result) {
479         policy.writeFlag(x86_flag_pf, parity(extract<0, 8>(result)));
480         policy.writeFlag(x86_flag_sf, extract<Len - 1, Len>(result));
481         policy.writeFlag(x86_flag_zf, policy.equalToZero(result));
482     }
483
484     /* Sets flags conditionally. Sets parity, sign, and zero flags if COND is true. */
485     template <size_t Len>
486     void setFlagsForResult(const Word(Len)& result, Word(1) cond) {
487         policy.writeFlag(x86_flag_pf, policy.ite(cond, parity(extract<0, 8>(result)), policy.readFlag(x86_flag_pf)));
488         policy.writeFlag(x86_flag_sf, policy.ite(cond, extract<Len - 1, Len>(result), policy.readFlag(x86_flag_sf)));
489         policy.writeFlag(x86_flag_zf, policy.ite(cond, policy.equalToZero(result), policy.readFlag(x86_flag_zf)));
490     }
491
492     /* Adds A and B and adjusts condition flags. Can be used for subtraction if B is two's complement and invertCarries is set. */
493     template <size_t Len>
494     Word(Len) doAddOperation(const Word(Len)& a, const Word(Len)& b, bool invertCarries, Word(1) carryIn) {
495         Word(Len) carries = number<Len>(0);
496         Word(Len) result = policy.addWithCarries(a, b, invertMaybe(carryIn, invertCarries), carries/*out*/);
497         setFlagsForResult<Len>(result);
498         policy.writeFlag(x86_flag_af, invertMaybe(extract<3, 4>(carries), invertCarries));
499         policy.writeFlag(x86_flag_cf, invertMaybe(extract<Len - 1, Len>(carries), invertCarries));
500         policy.writeFlag(x86_flag_of, policy.xor_(extract<Len - 1, Len>(carries), extract<Len - 2, Len - 1>(carries)));
501         return result;
502     }
503
504     /* Conditionally adds A and B and adjusts condition flags. Can be used for subtraction if B is two's complement and
505      * invertCarries is set. Does nothing if COND is false. */ 
506     template <size_t Len>
507     Word(Len) doAddOperation(const Word(Len)& a, const Word(Len)& b, bool invertCarries, Word(1) carryIn, Word(1) cond) {
508         Word(Len) carries = number<Len>(0);
509         Word(Len) result = policy.addWithCarries(a, b, invertMaybe(carryIn, invertCarries), carries/*out*/);
510         setFlagsForResult<Len>(result, cond);
511         policy.writeFlag(x86_flag_af,
512                          policy.ite(cond,
513                                     invertMaybe(extract<3, 4>(carries), invertCarries),
514                                     policy.readFlag(x86_flag_af)));
515         policy.writeFlag(x86_flag_cf,
516                          policy.ite(cond,
517                                     invertMaybe(extract<Len - 1, Len>(carries), invertCarries),
518                                     policy.readFlag(x86_flag_cf)));
519         policy.writeFlag(x86_flag_of,
520                          policy.ite(cond,
521                                     policy.xor_(extract<Len - 1, Len>(carries), extract<Len - 2, Len - 1>(carries)),
522                                     policy.readFlag(x86_flag_of)));
523         return result;
524     }
525
526     /* Does increment (decrement with DEC set), and adjusts condition flags. */
527     template <size_t Len>
528     Word(Len) doIncOperation(const Word(Len)& a, bool dec, bool setCarry) {
529         Word(Len) carries = number<Len>(0);
530         Word(Len) result = policy.addWithCarries(a, number<Len>(dec ? -1 : 1), policy.false_(), carries/*out*/);
531         setFlagsForResult<Len>(result);
532         policy.writeFlag(x86_flag_af, invertMaybe(extract<3, 4>(carries), dec));
533         policy.writeFlag(x86_flag_of, policy.xor_(extract<Len - 1, Len>(carries), extract<Len - 2, Len - 1>(carries)));
534         if (setCarry)
535             policy.writeFlag(x86_flag_cf, invertMaybe(extract<Len - 1, Len>(carries), dec));
536         return result;
537     }
538
539     /* Virtual so that we can subclass X86InstructionSemantics and have an opportunity to override the translation of any
540      * instruction. */
541     virtual void translate(SgAsmx86Instruction* insn) {
542       // BERNAT, 16MAR10 - keep the IP symbolic.
543       // PATCH
544       policy.writeIP(policy.add(policy.readIP(), number<32>(insn->get_raw_bytes().size())));
545       //policy.writeIP(number<32>((unsigned int)(insn->get_address() + insn->get_raw_bytes().size())));
546       // END PATCH
547         X86InstructionKind kind = insn->get_kind();
548         const SgAsmExpressionPtrList& operands = insn->get_operandList()->get_operands();
549         switch (kind) {
550
551             case x86_mov: {
552                 ROSE_ASSERT(operands.size() == 2);
553                 switch (numBytesInAsmType(operands[0]->get_type())) {
554                     case 1: write8(operands[0], read8(operands[1])); break;
555                     case 2: write16(operands[0], read16(operands[1])); break;
556                     case 4: write32(operands[0], read32(operands[1])); break;
557                     default: ROSE_ASSERT("Bad size"); break;
558                 }
559                 break;
560             }
561
562             case x86_xchg: {
563                 ROSE_ASSERT(operands.size() == 2);
564                 switch (numBytesInAsmType(operands[0]->get_type())) {
565                     case 1: {
566                         Word(8) temp = read8(operands[1]);
567                         write8(operands[1], read8(operands[0]));
568                         write8(operands[0], temp);
569                         break;
570                     }
571                     case 2: {
572                         Word(16) temp = read16(operands[1]);
573                         write16(operands[1], read16(operands[0]));
574                         write16(operands[0], temp);
575                         break;
576                     }
577                     case 4: {
578                         Word(32) temp = read32(operands[1]);
579                         write32(operands[1], read32(operands[0]));
580                         write32(operands[0], temp);
581                         break;
582                     }
583                     default:
584                         ROSE_ASSERT("Bad size");
585                         break;
586                 }
587                 break;
588             }
589
590             case x86_movzx: {
591                 ROSE_ASSERT(operands.size() == 2);
592                 switch (numBytesInAsmType(operands[0]->get_type())) {
593                     case 2: {
594                         write16(operands[0], policy.concat(read8(operands[1]), number<8>(0)));
595                         break;
596                     }
597                     case 4: {
598                         switch (numBytesInAsmType(operands[1]->get_type())) {
599                             case 1: write32(operands[0], policy.concat(read8(operands[1]), number<24>(0))); break;
600                             case 2: write32(operands[0], policy.concat(read16(operands[1]), number<16>(0))); break;
601                             default: ROSE_ASSERT("Bad size");
602                         }
603                         break;
604                     }
605                     default:
606                         ROSE_ASSERT("Bad size");
607                         break;
608                 }
609                 break;
610             }
611
612             case x86_movsx: {
613                 ROSE_ASSERT(operands.size() == 2);
614                 switch (numBytesInAsmType(operands[0]->get_type())) {
615                     case 2: {
616                         Word(8) op1 = read8(operands[1]);
617                         Word(16) result = signExtend<8, 16>(op1);
618                         write16(operands[0], result);
619                         break;
620                     }
621                     case 4: {
622                         switch (numBytesInAsmType(operands[1]->get_type())) {
623                             case 1: {
624                                 Word(8) op1 = read8(operands[1]);
625                                 Word(32) result = signExtend<8, 32>(op1);
626                                 write32(operands[0], result);
627                                 break;
628                             }
629                             case 2: {
630                                 Word(16) op1 = read16(operands[1]);
631                                 Word(32) result = signExtend<16, 32>(op1);
632                                 write32(operands[0], result);
633                                 break;
634                             }
635                             default:
636                                 ROSE_ASSERT("Bad size");
637                         }
638                         break;
639                     }
640                     default:
641                         ROSE_ASSERT("Bad size");
642                         break;
643                 }
644                 break;
645             }
646
647             case x86_cbw: {
648                 ROSE_ASSERT(operands.size() == 0);
649                 updateGPRLowWord(x86_gpr_ax, signExtend<8, 16>(extract<0, 8>(policy.readGPR(x86_gpr_ax))));
650                 break;
651             }
652
653             case x86_cwde: {
654                 ROSE_ASSERT(operands.size() == 0);
655                 policy.writeGPR(x86_gpr_ax, signExtend<16, 32>(extract<0, 16>(policy.readGPR(x86_gpr_ax))));
656                 break;
657             }
658
659             case x86_cwd: {
660                 ROSE_ASSERT(operands.size() == 0);
661                 updateGPRLowWord(x86_gpr_dx, extract<16, 32>(signExtend<16, 32>(extract<0, 16>(policy.readGPR(x86_gpr_ax)))));
662                 break;
663             }
664
665             case x86_cdq: {
666                 ROSE_ASSERT(operands.size() == 0);
667                 policy.writeGPR(x86_gpr_dx, extract<32, 64>(signExtend<32, 64>(policy.readGPR(x86_gpr_ax))));
668                 break;
669             }
670
671             case x86_lea: {
672                 ROSE_ASSERT(operands.size() == 2);
673                 write32(operands[0], readEffectiveAddress(operands[1]));
674                 break;
675             }
676
677             case x86_and: {
678                 ROSE_ASSERT(operands.size() == 2);
679                 switch (numBytesInAsmType(operands[0]->get_type())) {
680                     case 1: {
681                         Word(8) result = policy.and_(read8(operands[0]), read8(operands[1]));
682                         setFlagsForResult<8>(result);
683                         write8(operands[0], result);
684                         break;
685                     }
686                     case 2: {
687                         Word(16) result = policy.and_(read16(operands[0]), read16(operands[1]));
688                         setFlagsForResult<16>(result);
689                         write16(operands[0], result);
690                         break;
691                     }
692                     case 4: {
693                         Word(32) result = policy.and_(read32(operands[0]), read32(operands[1]));
694                         setFlagsForResult<32>(result);
695                         write32(operands[0], result);
696                         break;
697                     }
698                     default:
699                         ROSE_ASSERT(!"Bad size");
700                         break;
701                 }
702                 policy.writeFlag(x86_flag_of, policy.false_());
703                 policy.writeFlag(x86_flag_af, policy.undefined_());
704                 policy.writeFlag(x86_flag_cf, policy.false_());
705                 break;
706             }
707
708             case x86_or: {
709                 ROSE_ASSERT(operands.size() == 2);
710                 switch (numBytesInAsmType(operands[0]->get_type())) {
711                     case 1: {
712                         Word(8) result = policy.or_(read8(operands[0]), read8(operands[1]));
713                         setFlagsForResult<8>(result);
714                         write8(operands[0], result);
715                         break;
716                     }
717                     case 2: {
718                         Word(16) result = policy.or_(read16(operands[0]), read16(operands[1]));
719                         setFlagsForResult<16>(result);
720                         write16(operands[0], result);
721                         break;
722                     }
723                     case 4: {
724                         Word(32) result = policy.or_(read32(operands[0]), read32(operands[1]));
725                         setFlagsForResult<32>(result);
726                         write32(operands[0], result);
727                         break;
728                     }
729                     default:
730                         ROSE_ASSERT(!"Bad size");
731                         break;
732                 }
733                 policy.writeFlag(x86_flag_of, policy.false_());
734                 policy.writeFlag(x86_flag_af, policy.undefined_());
735                 policy.writeFlag(x86_flag_cf, policy.false_());
736                 break;
737             }
738
739             case x86_test: {
740                 ROSE_ASSERT(operands.size() == 2);
741                 switch (numBytesInAsmType(operands[0]->get_type())) {
742                     case 1: {
743                         Word(8) result = policy.and_(read8(operands[0]), read8(operands[1]));
744                         setFlagsForResult<8>(result);
745                         break;
746                     }
747                     case 2: {
748                         Word(16) result = policy.and_(read16(operands[0]), read16(operands[1]));
749                         setFlagsForResult<16>(result);
750                         break;
751                     }
752                     case 4: {
753                         Word(32) result = policy.and_(read32(operands[0]), read32(operands[1]));
754                         setFlagsForResult<32>(result);
755                         break;
756                     }
757                     default:
758                         ROSE_ASSERT(!"Bad size");
759                         break;
760                 }
761                 policy.writeFlag(x86_flag_of, policy.false_());
762                 policy.writeFlag(x86_flag_af, policy.undefined_());
763                 policy.writeFlag(x86_flag_cf, policy.false_());
764                 break;
765             }
766
767             case x86_xor: {
768                 ROSE_ASSERT(operands.size() == 2);
769                 switch (numBytesInAsmType(operands[0]->get_type())) {
770                     case 1: {
771                         Word(8) result = policy.xor_(read8(operands[0]), read8(operands[1]));
772                         setFlagsForResult<8>(result);
773                         write8(operands[0], result);
774                         break;
775                     }
776                     case 2: {
777                         Word(16) result = policy.xor_(read16(operands[0]), read16(operands[1]));
778                         setFlagsForResult<16>(result);
779                         write16(operands[0], result);
780                         break;
781                     }
782                     case 4: {
783                         Word(32) result = policy.xor_(read32(operands[0]), read32(operands[1]));
784                         setFlagsForResult<32>(result);
785                         write32(operands[0], result);
786                         break;
787                     }
788                     default:
789                         ROSE_ASSERT(!"Bad size");
790                         break;
791                 }
792                 policy.writeFlag(x86_flag_of, policy.false_());
793                 policy.writeFlag(x86_flag_af, policy.undefined_());
794                 policy.writeFlag(x86_flag_cf, policy.false_());
795                 break;
796             }
797
798             case x86_not: {
799                 ROSE_ASSERT(operands.size() == 1);
800                 switch (numBytesInAsmType(operands[0]->get_type())) {
801                     case 1: {
802                         Word(8) result = policy.invert(read8(operands[0]));
803                         write8(operands[0], result);
804                         break;
805                     }
806                     case 2: {
807                         Word(16) result = policy.invert(read16(operands[0]));
808                         write16(operands[0], result);
809                         break;
810                     }
811                     case 4: {
812                         Word(32) result = policy.invert(read32(operands[0]));
813                         write32(operands[0], result);
814                         break;
815                     }
816                     default:
817                         ROSE_ASSERT(!"Bad size");
818                         break;
819                 }
820                 break;
821             }
822
823             case x86_add: {
824                 ROSE_ASSERT(operands.size() == 2);
825                 switch (numBytesInAsmType(operands[0]->get_type())) {
826                     case 1: {
827                         Word(8) result = doAddOperation<8>(read8(operands[0]), read8(operands[1]), false, policy.false_());
828                         write8(operands[0], result);
829                         break;
830                     }
831                     case 2: {
832                         Word(16) result = doAddOperation<16>(read16(operands[0]), read16(operands[1]), false, policy.false_());
833                         write16(operands[0], result);
834                         break;
835                     }
836                     case 4: {
837                         Word(32) result = doAddOperation<32>(read32(operands[0]), read32(operands[1]), false, policy.false_());
838                         write32(operands[0], result);
839                         break;
840                     }
841                     default:
842                         ROSE_ASSERT(!"Bad size");
843                         break;
844                 }
845                 break;
846             }
847
848             case x86_adc: {
849                 ROSE_ASSERT(operands.size() == 2);
850                 switch (numBytesInAsmType(operands[0]->get_type())) {
851                     case 1: {
852                         Word(8) result = doAddOperation<8>(read8(operands[0]), read8(operands[1]), false,
853                                                            policy.readFlag(x86_flag_cf));
854                         write8(operands[0], result);
855                         break;
856                     }
857                     case 2: {
858                         Word(16) result = doAddOperation<16>(read16(operands[0]), read16(operands[1]), false,
859                                                              policy.readFlag(x86_flag_cf));
860                         write16(operands[0], result);
861                         break;
862                     }
863                     case 4: {
864                         Word(32) result = doAddOperation<32>(read32(operands[0]), read32(operands[1]), false,
865                                                              policy.readFlag(x86_flag_cf));
866                         write32(operands[0], result);
867                         break;
868                     }
869                     default:
870                         ROSE_ASSERT(!"Bad size");
871                         break;
872                 }
873                 break;
874             }
875
876             case x86_sub: {
877                 ROSE_ASSERT(operands.size() == 2);
878                 switch (numBytesInAsmType(operands[0]->get_type())) {
879                     case 1: {
880                         Word(8) result = doAddOperation<8>(read8(operands[0]), policy.invert(read8(operands[1])), true,
881                                                            policy.false_());
882                         write8(operands[0], result);
883                         break;
884                     }
885                     case 2: {
886                         Word(16) result = doAddOperation<16>(read16(operands[0]), policy.invert(read16(operands[1])), true,
887                                                              policy.false_());
888                         write16(operands[0], result);
889                         break;
890                     }
891                     case 4: {
892                         Word(32) result = doAddOperation<32>(read32(operands[0]), policy.invert(read32(operands[1])), true,
893                                                              policy.false_());
894                         write32(operands[0], result);
895                         break;
896                     }
897                     default:
898                         ROSE_ASSERT(!"Bad size");
899                         break;
900                 }
901                 break;
902             }
903
904             case x86_sbb: {
905                 ROSE_ASSERT(operands.size() == 2);
906                 switch (numBytesInAsmType(operands[0]->get_type())) {
907                     case 1: {
908                         Word(8) result = doAddOperation<8>(read8(operands[0]), policy.invert(read8(operands[1])), true,
909                                                            policy.readFlag(x86_flag_cf));
910                         write8(operands[0], result);
911                         break;
912                     }
913                     case 2: {
914                         Word(16) result = doAddOperation<16>(read16(operands[0]), policy.invert(read16(operands[1])), true,
915                                                              policy.readFlag(x86_flag_cf));
916                         write16(operands[0], result);
917                         break;
918                     }
919                     case 4: {
920                         Word(32) result = doAddOperation<32>(read32(operands[0]), policy.invert(read32(operands[1])), true,
921                                                              policy.readFlag(x86_flag_cf));
922                         write32(operands[0], result);
923                         break;
924                     }
925                     default:
926                         ROSE_ASSERT(!"Bad size");
927                         break;
928                 }
929                 break;
930             }
931
932             case x86_cmp: {
933                 ROSE_ASSERT(operands.size() == 2);
934                 switch (numBytesInAsmType(operands[0]->get_type())) {
935                     case 1: {
936                         doAddOperation<8>(read8(operands[0]), policy.invert(read8(operands[1])), true, policy.false_());
937                         break;
938                     }
939                     case 2: {
940                         doAddOperation<16>(read16(operands[0]), policy.invert(read16(operands[1])), true, policy.false_());
941                         break;
942                     }
943                     case 4: {
944                         doAddOperation<32>(read32(operands[0]), policy.invert(read32(operands[1])), true, policy.false_());
945                         break;
946                     }
947                     default:
948                         ROSE_ASSERT(!"Bad size");
949                         break;
950                 }
951                 break;
952             }
953
954             case x86_neg: {
955                 ROSE_ASSERT(operands.size() == 1);
956                 switch (numBytesInAsmType(operands[0]->get_type())) {
957                     case 1: {
958                         Word(8) result = doAddOperation<8>(number<8>(0), policy.invert(read8(operands[0])), true,
959                                                            policy.false_());
960                         write8(operands[0], result);
961                         break;
962                     }
963                     case 2: {
964                         Word(16) result = doAddOperation<16>(number<16>(0), policy.invert(read16(operands[0])), true,
965                                                              policy.false_());
966                         write16(operands[0], result);
967                         break;
968                     }
969                     case 4: {
970                         Word(32) result = doAddOperation<32>(number<32>(0), policy.invert(read32(operands[0])), true,
971                                                              policy.false_());
972                         write32(operands[0], result);
973                         break;
974                     }
975                     default:
976                         ROSE_ASSERT(!"Bad size");
977                         break;
978                 }
979                 break;
980             }
981
982             case x86_inc: {
983                 ROSE_ASSERT(operands.size() == 1);
984                 switch (numBytesInAsmType(operands[0]->get_type())) {
985                     case 1: {
986                         Word(8) result = doIncOperation<8>(read8(operands[0]), false, false);
987                         write8(operands[0], result);
988                         break;
989                     }
990                     case 2: {
991                         Word(16) result = doIncOperation<16>(read16(operands[0]), false, false);
992                         write16(operands[0], result);
993                         break;
994                     }
995                     case 4: {
996                         Word(32) result = doIncOperation<32>(read32(operands[0]), false, false);
997                         write32(operands[0], result);
998                         break;
999                     }
1000                     default:
1001                         ROSE_ASSERT(!"Bad size");
1002                         break;
1003                 }
1004                 break;
1005             }
1006
1007             case x86_dec: {
1008                 ROSE_ASSERT(operands.size() == 1);
1009                 switch (numBytesInAsmType(operands[0]->get_type())) {
1010                     case 1: {
1011                         Word(8) result = doIncOperation<8>(read8(operands[0]), true, false);
1012                         write8(operands[0], result);
1013                         break;
1014                     }
1015                     case 2: {
1016                         Word(16) result = doIncOperation<16>(read16(operands[0]), true, false);
1017                         write16(operands[0], result);
1018                         break;
1019                     }
1020                     case 4: {
1021                         Word(32) result = doIncOperation<32>(read32(operands[0]), true, false);
1022                         write32(operands[0], result);
1023                         break;
1024                     }
1025                     default:
1026                         ROSE_ASSERT(!"Bad size");
1027                         break;
1028                 }
1029                 break;
1030             }
1031
1032             case x86_cmpxchg: {
1033                 ROSE_ASSERT(operands.size() == 2);
1034                 switch (numBytesInAsmType(operands[0]->get_type())) {
1035                     case 1: {
1036                         Word(8) op0 = read8(operands[0]);
1037                         Word(8) oldAx = extract<0, 8>(policy.readGPR(x86_gpr_ax));
1038                         doAddOperation<8>(oldAx, policy.invert(op0), true, policy.false_());
1039                         write8(operands[0], policy.ite(policy.readFlag(x86_flag_zf), read8(operands[1]), op0));
1040                         updateGPRLowByte(x86_gpr_ax, policy.ite(policy.readFlag(x86_flag_zf), oldAx, op0));
1041                         break;
1042                     }
1043                     case 2: {
1044                         Word(16) op0 = read16(operands[0]);
1045                         Word(16) oldAx = extract<0, 16>(policy.readGPR(x86_gpr_ax));
1046                         doAddOperation<16>(oldAx, policy.invert(op0), true, policy.false_());
1047                         write16(operands[0], policy.ite(policy.readFlag(x86_flag_zf), read16(operands[1]), op0));
1048                         updateGPRLowWord(x86_gpr_ax, policy.ite(policy.readFlag(x86_flag_zf), oldAx, op0));
1049                         break;
1050                     }
1051                     case 4: {
1052                         Word(32) op0 = read32(operands[0]);
1053                         Word(32) oldAx = policy.readGPR(x86_gpr_ax);
1054                         doAddOperation<32>(oldAx, policy.invert(op0), true, policy.false_());
1055                         write32(operands[0], policy.ite(policy.readFlag(x86_flag_zf), read32(operands[1]), op0));
1056                         policy.writeGPR(x86_gpr_ax, policy.ite(policy.readFlag(x86_flag_zf), oldAx, op0));
1057                         break;
1058                     }
1059                     default:
1060                         ROSE_ASSERT(!"Bad size");
1061                         break;
1062                 }
1063                 break;
1064             }
1065
1066             case x86_shl: {
1067                 Word(5) shiftCount = extract<0, 5>(read8(operands[1]));
1068                 Word(1) shiftCountZero = policy.equalToZero(shiftCount);
1069                 policy.writeFlag(x86_flag_af, policy.ite(shiftCountZero, policy.readFlag(x86_flag_af), policy.undefined_()));
1070                 switch (numBytesInAsmType(operands[0]->get_type())) {
1071                     case 1: {
1072                         Word(8) op = read8(operands[0]);
1073                         Word(8) output = policy.shiftLeft(op, shiftCount);
1074                         Word(1) newCf = policy.ite(shiftCountZero,
1075                                                    policy.readFlag(x86_flag_cf),
1076                                                    extract<7, 8>(policy.shiftLeft(op, policy.add(shiftCount, number<5>(7)))));
1077                         policy.writeFlag(x86_flag_cf, newCf);
1078                         policy.writeFlag(x86_flag_of, policy.ite(shiftCountZero,
1079                                                                  policy.readFlag(x86_flag_of),
1080                                                                  policy.xor_(extract<7, 8>(output), newCf)));
1081                         write8(operands[0], output);
1082                         setFlagsForResult<8>(output, policy.invert(shiftCountZero));
1083                         break;
1084                     }
1085                     case 2: {
1086                         Word(16) op = read16(operands[0]);
1087                         Word(16) output = policy.shiftLeft(op, shiftCount);
1088                         Word(1) newCf = policy.ite(shiftCountZero,
1089                                                    policy.readFlag(x86_flag_cf),
1090                                                    extract<15, 16>(policy.shiftLeft(op, policy.add(shiftCount, number<5>(15)))));
1091                         policy.writeFlag(x86_flag_cf, newCf);
1092                         policy.writeFlag(x86_flag_of, policy.ite(shiftCountZero,
1093                                                                  policy.readFlag(x86_flag_of),
1094                                                                  policy.xor_(extract<15, 16>(output), newCf)));
1095                         write16(operands[0], output);
1096                         setFlagsForResult<16>(output, policy.invert(shiftCountZero));
1097                         break;
1098                     }
1099                     case 4: {
1100                         Word(32) op = read32(operands[0]);
1101                         Word(32) output = policy.shiftLeft(op, shiftCount);
1102                         Word(1) newCf = policy.ite(shiftCountZero,
1103                                                    policy.readFlag(x86_flag_cf),
1104                                                    extract<31, 32>(policy.shiftLeft(op, policy.add(shiftCount, number<5>(31)))));
1105                         policy.writeFlag(x86_flag_cf, newCf);
1106                         policy.writeFlag(x86_flag_of, policy.ite(shiftCountZero,
1107                                                                  policy.readFlag(x86_flag_of),
1108                                                                  policy.xor_(extract<31, 32>(output), newCf)));
1109                         write32(operands[0], output);
1110                         setFlagsForResult<32>(output, policy.invert(shiftCountZero));
1111                         break;
1112                     }
1113                     default:
1114                         ROSE_ASSERT(!"Bad size");
1115                 }
1116                 break;
1117             }
1118
1119             case x86_shr: {
1120                 Word(5) shiftCount = extract<0, 5>(read8(operands[1]));
1121                 Word(1) shiftCountZero = policy.equalToZero(shiftCount);
1122                 policy.writeFlag(x86_flag_af, policy.ite(shiftCountZero, policy.readFlag(x86_flag_af), policy.undefined_()));
1123                 switch (numBytesInAsmType(operands[0]->get_type())) {
1124                     case 1: {
1125                         Word(8) op = read8(operands[0]);
1126                         Word(8) output = policy.shiftRight(op, shiftCount);
1127                         Word(1) newCf = policy.ite(shiftCountZero,
1128                                                    policy.readFlag(x86_flag_cf),
1129                                                    extract<0, 1>(policy.shiftRight(op, policy.add(shiftCount, number<5>(7)))));
1130                         policy.writeFlag(x86_flag_cf, newCf);
1131                         policy.writeFlag(x86_flag_of, policy.ite(shiftCountZero, policy.readFlag(x86_flag_of), extract<7, 8>(op)));
1132                         write8(operands[0], output);
1133                         setFlagsForResult<8>(output, policy.invert(shiftCountZero));
1134                         break;
1135                     }
1136                     case 2: {
1137                         Word(16) op = read16(operands[0]);
1138                         Word(16) output = policy.shiftRight(op, shiftCount);
1139                         Word(1) newCf = policy.ite(shiftCountZero,
1140                                                    policy.readFlag(x86_flag_cf),
1141                                                    extract<0, 1>(policy.shiftRight(op, policy.add(shiftCount, number<5>(15)))));
1142                         policy.writeFlag(x86_flag_cf, newCf);
1143                         policy.writeFlag(x86_flag_of,
1144                                          policy.ite(shiftCountZero, policy.readFlag(x86_flag_of), extract<15, 16>(op)));
1145                         write16(operands[0], output);
1146                         setFlagsForResult<16>(output, policy.invert(shiftCountZero));
1147                         break;
1148                     }
1149                     case 4: {
1150                         Word(32) op = read32(operands[0]);
1151                         Word(32) output = policy.shiftRight(op, shiftCount);
1152                         Word(1) newCf = policy.ite(shiftCountZero,
1153                                                    policy.readFlag(x86_flag_cf),
1154                                                    extract<0, 1>(policy.shiftRight(op, policy.add(shiftCount, number<5>(31)))));
1155                         policy.writeFlag(x86_flag_cf, newCf);
1156                         policy.writeFlag(x86_flag_of, policy.ite(shiftCountZero,
1157                                                                  policy.readFlag(x86_flag_of),
1158                                                                  extract<31, 32>(op)));
1159                         write32(operands[0], output);
1160                         setFlagsForResult<32>(output, policy.invert(shiftCountZero));
1161                         break;
1162                     }
1163                     default:
1164                         ROSE_ASSERT(!"Bad size");
1165                 }
1166                 break;
1167             }
1168
1169             case x86_sar: {
1170                 Word(5) shiftCount = extract<0, 5>(read8(operands[1]));
1171                 Word(1) shiftCountZero = policy.equalToZero(shiftCount);
1172                 Word(1) shiftCountNotZero = policy.invert(shiftCountZero);
1173                 policy.writeFlag(x86_flag_af, policy.ite(shiftCountZero, policy.readFlag(x86_flag_af), policy.undefined_()));
1174                 switch (numBytesInAsmType(operands[0]->get_type())) {
1175                     case 1: {
1176                         Word(8) op = read8(operands[0]);
1177                         Word(8) output = policy.shiftRightArithmetic(op, shiftCount);
1178                         Word(1) newCf = policy.ite(shiftCountZero,
1179                                                    policy.readFlag(x86_flag_cf),
1180                                                    extract<0, 1>(policy.shiftRight(op, policy.add(shiftCount, number<5>(7)))));
1181                         policy.writeFlag(x86_flag_cf, newCf);
1182                         /* No change with sc = 0, clear when sc = 1, undefined otherwise */
1183                         policy.writeFlag(x86_flag_of, policy.ite(shiftCountZero,
1184                                                                  policy.readFlag(x86_flag_of),
1185                                                                  policy.false_()));
1186                         write8(operands[0], output);
1187                         setFlagsForResult<8>(output, shiftCountNotZero);
1188                         break;
1189                     }
1190                     case 2: {
1191                         Word(16) op = read16(operands[0]);
1192                         Word(16) output = policy.shiftRightArithmetic(op, shiftCount);
1193                         Word(1) newCf = policy.ite(shiftCountZero,
1194                                                    policy.readFlag(x86_flag_cf),
1195                                                    extract<0, 1>(policy.shiftRight(op, policy.add(shiftCount, number<5>(15)))));
1196                         policy.writeFlag(x86_flag_cf, newCf);
1197                         /* No change with sc = 0, clear when sc = 1, undefined otherwise */
1198                         policy.writeFlag(x86_flag_of, policy.ite(shiftCountZero,
1199                                                                  policy.readFlag(x86_flag_of),
1200                                                                  policy.false_()));
1201                         write16(operands[0], output);
1202                         setFlagsForResult<16>(output, shiftCountNotZero);
1203                         break;
1204                     }
1205                     case 4: {
1206                         Word(32) op = read32(operands[0]);
1207                         Word(32) output = policy.shiftRightArithmetic(op, shiftCount);
1208                         Word(1) newCf = policy.ite(shiftCountZero,
1209                                                    policy.readFlag(x86_flag_cf),
1210                                                    extract<0, 1>(policy.shiftRight(op, policy.add(shiftCount, number<5>(31)))));
1211                         policy.writeFlag(x86_flag_cf, newCf);
1212                         /* No change with sc = 0, clear when sc = 1, undefined otherwise */
1213                         policy.writeFlag(x86_flag_of, policy.ite(shiftCountZero,
1214                                                                  policy.readFlag(x86_flag_of),
1215                                                                  policy.false_()));
1216                         write32(operands[0], output);
1217                         setFlagsForResult<32>(output, shiftCountNotZero);
1218                         break;
1219                     }
1220                     default:
1221                         ROSE_ASSERT(!"Bad size");
1222                 }
1223                 break;
1224             }
1225
1226             case x86_rol: {
1227                 switch (numBytesInAsmType(operands[0]->get_type())) {
1228                     case 1: {
1229                         Word(8) op = read8(operands[0]);
1230                         Word(5) shiftCount = extract<0, 5>(read8(operands[1]));
1231                         Word(8) output = policy.rotateLeft(op, shiftCount);
1232                         policy.writeFlag(x86_flag_cf, policy.ite(policy.equalToZero(shiftCount),
1233                                                                  policy.readFlag(x86_flag_cf),
1234                                                                  extract<0, 1>(output)));
1235                         policy.writeFlag(x86_flag_of, policy.ite(policy.equalToZero(shiftCount),
1236                                                                  policy.readFlag(x86_flag_of),
1237                                                                  policy.xor_(extract<0, 1>(output), extract<7, 8>(output))));
1238                         write8(operands[0], output);
1239                         break;
1240                     }
1241                     case 2: {
1242                         Word(16) op = read16(operands[0]);
1243                         Word(5) shiftCount = extract<0, 5>(read8(operands[1]));
1244                         Word(16) output = policy.rotateLeft(op, shiftCount);
1245                         policy.writeFlag(x86_flag_cf, policy.ite(policy.equalToZero(shiftCount),
1246                                                                  policy.readFlag(x86_flag_cf),
1247                                                                  extract<0, 1>(output)));
1248                         policy.writeFlag(x86_flag_of, policy.ite(policy.equalToZero(shiftCount),
1249                                                                  policy.readFlag(x86_flag_of),
1250                                                                  policy.xor_(extract<0, 1>(output), extract<15, 16>(output))));
1251                         write16(operands[0], output);
1252                         break;
1253                     }
1254                     case 4: {
1255                         Word(32) op = read32(operands[0]);
1256                         Word(5) shiftCount = extract<0, 5>(read8(operands[1]));
1257                         Word(32) output = policy.rotateLeft(op, shiftCount);
1258                         policy.writeFlag(x86_flag_cf, policy.ite(policy.equalToZero(shiftCount),
1259                                                                  policy.readFlag(x86_flag_cf),
1260                                                                  extract<0, 1>(output)));
1261                         policy.writeFlag(x86_flag_of, policy.ite(policy.equalToZero(shiftCount),
1262                                                                  policy.readFlag(x86_flag_of),
1263                                                                  policy.xor_(extract<0, 1>(output), extract<31, 32>(output))));
1264                         write32(operands[0], output);
1265                         break;
1266                     }
1267                     default:
1268                         ROSE_ASSERT(!"Bad size");
1269                 }
1270                 break;
1271             }
1272
1273             case x86_ror: {
1274                 switch (numBytesInAsmType(operands[0]->get_type())) {
1275                     case 1: {
1276                         Word(8) op = read8(operands[0]);
1277                         Word(5) shiftCount = extract<0, 5>(read8(operands[1]));
1278                         Word(8) output = policy.rotateRight(op, shiftCount);
1279                         policy.writeFlag(x86_flag_cf, policy.ite(policy.equalToZero(shiftCount),
1280                                                                  policy.readFlag(x86_flag_cf),
1281                                                                  extract<7, 8>(output)));
1282                         policy.writeFlag(x86_flag_of, policy.ite(policy.equalToZero(shiftCount),
1283                                                                  policy.readFlag(x86_flag_of),
1284                                                                  policy.xor_(extract<6, 7>(output), extract<7, 8>(output))));
1285                         write8(operands[0], output);
1286                         break;
1287                     }
1288                     case 2: {
1289                         Word(16) op = read16(operands[0]);
1290                         Word(5) shiftCount = extract<0, 5>(read8(operands[1]));
1291                         Word(16) output = policy.rotateRight(op, shiftCount);
1292                         policy.writeFlag(x86_flag_cf, policy.ite(policy.equalToZero(shiftCount),
1293                                                                  policy.readFlag(x86_flag_cf),
1294                                                                  extract<15, 16>(output)));
1295                         policy.writeFlag(x86_flag_of, policy.ite(policy.equalToZero(shiftCount),
1296                                                                  policy.readFlag(x86_flag_of),
1297                                                                  policy.xor_(extract<14, 15>(output), extract<15, 16>(output))));
1298                         write16(operands[0], output);
1299                         break;
1300                     }
1301                     case 4: {
1302                         Word(32) op = read32(operands[0]);
1303                         Word(5) shiftCount = extract<0, 5>(read8(operands[1]));
1304                         Word(32) output = policy.rotateRight(op, shiftCount);
1305                         policy.writeFlag(x86_flag_cf, policy.ite(policy.equalToZero(shiftCount),
1306                                                                  policy.readFlag(x86_flag_cf),
1307                                                                  extract<31, 32>(output)));
1308                         policy.writeFlag(x86_flag_of, policy.ite(policy.equalToZero(shiftCount),
1309                                                                  policy.readFlag(x86_flag_of),
1310                                                                  policy.xor_(extract<30, 31>(output), extract<31, 32>(output))));
1311                         write32(operands[0], output);
1312                         break;
1313                     }
1314                     default:
1315                         ROSE_ASSERT(!"Bad size");
1316                 }
1317                 break;
1318             }
1319
1320             case x86_shld: {
1321                 Word(5) shiftCount = extract<0, 5>(read8(operands[2]));
1322                 switch (numBytesInAsmType(operands[0]->get_type())) {
1323                     case 2: {
1324                         Word(16) op1 = read16(operands[0]);
1325                         Word(16) op2 = read16(operands[1]);
1326                         Word(16) output1 = policy.shiftLeft(op1, shiftCount);
1327                         Word(16) output2 = policy.ite(policy.equalToZero(shiftCount),
1328                                                       number<16>(0),
1329                                                       policy.shiftRight(op2, policy.negate(shiftCount)));
1330                         Word(16) output = policy.or_(output1, output2);
1331                         Word(1) newCf = policy.ite(policy.equalToZero(shiftCount),
1332                                                    policy.readFlag(x86_flag_cf),
1333                                                    extract<15, 16>(policy.shiftLeft(op1, policy.add(shiftCount, number<5>(15)))));
1334                         policy.writeFlag(x86_flag_cf, newCf);
1335                         Word(1) newOf = policy.ite(policy.equalToZero(shiftCount),
1336                                                    policy.readFlag(x86_flag_of), 
1337                                                    policy.xor_(extract<15, 16>(output), newCf));
1338                         policy.writeFlag(x86_flag_of, newOf);
1339                         write16(operands[0], output);
1340                         setFlagsForResult<16>(output);
1341                         policy.writeFlag(x86_flag_af, policy.ite(policy.equalToZero(shiftCount),
1342                                                                  policy.readFlag(x86_flag_af),
1343                                                                  policy.undefined_()));
1344                         break;
1345                     }
1346                     case 4: {
1347                         Word(32) op1 = read32(operands[0]);
1348                         Word(32) op2 = read32(operands[1]);
1349                         Word(5) shiftCount = extract<0, 5>(read8(operands[2]));
1350                         Word(32) output1 = policy.shiftLeft(op1, shiftCount);
1351                         Word(32) output2 = policy.ite(policy.equalToZero(shiftCount),
1352                                                       number<32>(0),
1353                                                       policy.shiftRight(op2, policy.negate(shiftCount)));
1354                         Word(32) output = policy.or_(output1, output2);
1355                         Word(1) newCf = policy.ite(policy.equalToZero(shiftCount),
1356                                                    policy.readFlag(x86_flag_cf),
1357                                                    extract<31, 32>(policy.shiftLeft(op1, policy.add(shiftCount, number<5>(31)))));
1358                         policy.writeFlag(x86_flag_cf, newCf);
1359                         Word(1) newOf = policy.ite(policy.equalToZero(shiftCount),
1360                                                    policy.readFlag(x86_flag_of), 
1361                                                    policy.xor_(extract<31, 32>(output), newCf));
1362                         policy.writeFlag(x86_flag_of, newOf);
1363                         write32(operands[0], output);
1364                         setFlagsForResult<32>(output);
1365                         policy.writeFlag(x86_flag_af, policy.ite(policy.equalToZero(shiftCount),
1366                                                                  policy.readFlag(x86_flag_af),
1367                                                                  policy.undefined_()));
1368                         break;
1369                     }
1370                     default:
1371                         ROSE_ASSERT(!"Bad size");
1372                 }
1373                 break;
1374             }
1375
1376             case x86_shrd: {
1377                 Word(5) shiftCount = extract<0, 5>(read8(operands[2]));
1378                 switch (numBytesInAsmType(operands[0]->get_type())) {
1379                     case 2: {
1380                         Word(16) op1 = read16(operands[0]);
1381                         Word(16) op2 = read16(operands[1]);
1382                         Word(16) output1 = policy.shiftRight(op1, shiftCount);
1383                         Word(16) output2 = policy.ite(policy.equalToZero(shiftCount),
1384                                                       number<16>(0),
1385                                                       policy.shiftLeft(op2, policy.negate(shiftCount)));
1386                         Word(16) output = policy.or_(output1, output2);
1387                         Word(1) newCf = policy.ite(policy.equalToZero(shiftCount),
1388                                                    policy.readFlag(x86_flag_cf),
1389                                                    extract<0, 1>(policy.shiftRight(op1, policy.add(shiftCount, number<5>(15)))));
1390                         policy.writeFlag(x86_flag_cf, newCf);
1391                         Word(1) newOf = policy.ite(policy.equalToZero(shiftCount),
1392                                                    policy.readFlag(x86_flag_of), 
1393                                                    policy.xor_(extract<15, 16>(output),
1394                                                                extract<15, 16>(op1)));
1395                         policy.writeFlag(x86_flag_of, newOf);
1396                         write16(operands[0], output);
1397                         setFlagsForResult<16>(output);
1398                         policy.writeFlag(x86_flag_af, policy.ite(policy.equalToZero(shiftCount),
1399                                                                  policy.readFlag(x86_flag_af),
1400                                                                  policy.undefined_()));
1401                         break;
1402                     }
1403                     case 4: {
1404                         Word(32) op1 = read32(operands[0]);
1405                         Word(32) op2 = read32(operands[1]);
1406                         Word(32) output1 = policy.shiftRight(op1, shiftCount);
1407                         Word(32) output2 = policy.ite(policy.equalToZero(shiftCount),
1408                                                       number<32>(0),
1409                                                       policy.shiftLeft(op2, policy.negate(shiftCount)));
1410                         Word(32) output = policy.or_(output1, output2);
1411                         Word(1) newCf = policy.ite(policy.equalToZero(shiftCount),
1412                                                    policy.readFlag(x86_flag_cf),
1413                                                    extract<0, 1>(policy.shiftRight(op1, policy.add(shiftCount, number<5>(31)))));
1414                         policy.writeFlag(x86_flag_cf, newCf);
1415                         Word(1) newOf = policy.ite(policy.equalToZero(shiftCount),
1416                                                    policy.readFlag(x86_flag_of), 
1417                                                    policy.xor_(extract<31, 32>(output),
1418                                                                extract<31, 32>(op1)));
1419                         policy.writeFlag(x86_flag_of, newOf);
1420                         write32(operands[0], output);
1421                         setFlagsForResult<32>(output);
1422                         policy.writeFlag(x86_flag_af, policy.ite(policy.equalToZero(shiftCount),
1423                                                                  policy.readFlag(x86_flag_af),
1424                                                                  policy.undefined_()));
1425                         break;
1426                     }
1427                     default:
1428                         ROSE_ASSERT(!"Bad size");
1429                 }
1430                 break;
1431             }
1432
1433             case x86_bsf: {
1434                 policy.writeFlag(x86_flag_of, policy.undefined_());
1435                 policy.writeFlag(x86_flag_sf, policy.undefined_());
1436                 policy.writeFlag(x86_flag_af, policy.undefined_());
1437                 policy.writeFlag(x86_flag_pf, policy.undefined_());
1438                 policy.writeFlag(x86_flag_cf, policy.undefined_());
1439                 switch (numBytesInAsmType(operands[0]->get_type())) {
1440                     case 2: {
1441                         Word(16) op = read16(operands[1]);
1442                         policy.writeFlag(x86_flag_zf, policy.equalToZero(op));
1443                         Word(16) result = policy.ite(policy.readFlag(x86_flag_zf),
1444                                                      read16(operands[0]),
1445                                                      policy.leastSignificantSetBit(op));
1446                         write16(operands[0], result);
1447                         break;
1448                     }
1449                     case 4: {
1450                         Word(32) op = read32(operands[1]);
1451                         policy.writeFlag(x86_flag_zf, policy.equalToZero(op));
1452                         Word(32) result = policy.ite(policy.readFlag(x86_flag_zf),
1453                                                      read32(operands[0]),
1454                                                      policy.leastSignificantSetBit(op));
1455                         write32(operands[0], result);
1456                         break;
1457                     }
1458                     default:
1459                         ROSE_ASSERT(!"Bad size");
1460                 }
1461                 break;
1462             }
1463
1464             case x86_bsr: {
1465                 policy.writeFlag(x86_flag_of, policy.undefined_());
1466                 policy.writeFlag(x86_flag_sf, policy.undefined_());
1467                 policy.writeFlag(x86_flag_af, policy.undefined_());
1468                 policy.writeFlag(x86_flag_pf, policy.undefined_());
1469                 policy.writeFlag(x86_flag_cf, policy.undefined_());
1470                 switch (numBytesInAsmType(operands[0]->get_type())) {
1471                     case 2: {
1472                         Word(16) op = read16(operands[1]);
1473                         policy.writeFlag(x86_flag_zf, policy.equalToZero(op));
1474                         Word(16) result = policy.ite(policy.readFlag(x86_flag_zf),
1475                                                      read16(operands[0]),
1476                                                      policy.mostSignificantSetBit(op));
1477                         write16(operands[0], result);
1478                         break;
1479                     }
1480                     case 4: {
1481                         Word(32) op = read32(operands[1]);
1482                         policy.writeFlag(x86_flag_zf, policy.equalToZero(op));
1483                         Word(32) result = policy.ite(policy.readFlag(x86_flag_zf),
1484                                                      read32(operands[0]),
1485                                                      policy.mostSignificantSetBit(op));
1486                         write32(operands[0], result);
1487                         break;
1488                     }
1489                     default:
1490                         ROSE_ASSERT(!"Bad size");
1491                 }
1492                 break;
1493             }
1494
1495             case x86_bts: {
1496                 ROSE_ASSERT(operands.size() == 2);
1497                 /* All flags except CF are undefined */
1498                 policy.writeFlag(x86_flag_of, policy.undefined_());
1499                 policy.writeFlag(x86_flag_sf, policy.undefined_());
1500                 policy.writeFlag(x86_flag_zf, policy.undefined_());
1501                 policy.writeFlag(x86_flag_af, policy.undefined_());
1502                 policy.writeFlag(x86_flag_pf, policy.undefined_());
1503                 if (isSgAsmMemoryReferenceExpression(operands[0]) && isSgAsmx86RegisterReferenceExpression(operands[1])) {
1504                     /* Special case allowing multi-word offsets into memory */
1505                     Word(32) addr = readEffectiveAddress(operands[0]);
1506                     int numBytes = numBytesInAsmType(operands[1]->get_type());
1507                     Word(32) bitnum = numBytes == 2 ? signExtend<16, 32>(read16(operands[1])) : read32(operands[1]);
1508                     Word(32) adjustedAddr = policy.add(addr, signExtend<29, 32>(extract<3, 32>(bitnum)));
1509                     Word(8) val = readMemory<8>(getSegregFromMemoryReference(isSgAsmMemoryReferenceExpression(operands[0])),
1510                                                 adjustedAddr, policy.true_());
1511                     Word(1) bitval = extract<0, 1>(policy.rotateRight(val, extract<0, 3>(bitnum)));
1512                     Word(8) result = policy.or_(val, policy.rotateLeft(number<8>(1), extract<0, 3>(bitnum)));
1513                     policy.writeFlag(x86_flag_cf, bitval);
1514                     policy.writeMemory(getSegregFromMemoryReference(isSgAsmMemoryReferenceExpression(operands[0])),
1515                                        adjustedAddr, result, policy.true_());
1516                 } else {
1517                     /* Simple case */
1518                     switch (numBytesInAsmType(operands[0]->get_type())) {
1519                         case 2: {
1520                             Word(16) op0 = read16(operands[0]);
1521                             Word(4) bitnum = extract<0, 4>(read16(operands[1]));
1522                             Word(1) bitval = extract<0, 1>(policy.rotateRight(op0, bitnum));
1523                             Word(16) result = policy.or_(op0, policy.rotateLeft(number<16>(1), bitnum));
1524                             policy.writeFlag(x86_flag_cf, bitval);
1525                             write16(operands[0], result);
1526                             break;
1527                         }
1528                         case 4: {
1529                             Word(32) op0 = read32(operands[0]);
1530                             Word(5) bitnum = extract<0, 5>(read32(operands[1]));
1531                             Word(1) bitval = extract<0, 1>(policy.rotateRight(op0, bitnum));
1532                             Word(32) result = policy.or_(op0, policy.rotateLeft(number<32>(1), bitnum));
1533                             policy.writeFlag(x86_flag_cf, bitval);
1534                             write32(operands[0], result);
1535                             break;
1536                         }
1537                         default:
1538                             ROSE_ASSERT(!"Bad size");
1539                     }
1540                 }
1541                 break;
1542             }
1543
1544             case x86_imul: {
1545                 switch (numBytesInAsmType(operands[0]->get_type())) {
1546                     case 1: {
1547                         Word(8) op0 = extract<0, 8>(policy.readGPR(x86_gpr_ax));
1548                         Word(8) op1 = read8(operands[0]);
1549                         Word(16) mulResult = policy.signedMultiply(op0, op1);
1550                         updateGPRLowWord(x86_gpr_ax, mulResult);
1551                         Word(1) carry = policy.invert(policy.or_(policy.equalToZero(policy.invert(extract<7, 16>(mulResult))),
1552                                                                  policy.equalToZero(extract<7, 16>(mulResult))));
1553                         policy.writeFlag(x86_flag_cf, carry);
1554                         policy.writeFlag(x86_flag_of, carry);
1555                         break;
1556                     }
1557                     case 2: {
1558                         Word(16) op0 = operands.size() == 1 ?
1559                                        extract<0, 16>(policy.readGPR(x86_gpr_ax)) :
1560                                        read16(operands[operands.size() - 2]);
1561                         Word(16) op1 = read16(operands[operands.size() - 1]);
1562                         Word(32) mulResult = policy.signedMultiply(op0, op1);
1563                         if (operands.size() == 1) {
1564                             updateGPRLowWord(x86_gpr_ax, extract<0, 16>(mulResult));
1565                             updateGPRLowWord(x86_gpr_dx, extract<16, 32>(mulResult));
1566                         } else {
1567                             write16(operands[0], extract<0, 16>(mulResult));
1568                         }
1569                         Word(1) carry = policy.invert(policy.or_(policy.equalToZero(policy.invert(extract<7, 32>(mulResult))),
1570                                                                  policy.equalToZero(extract<7, 32>(mulResult))));
1571                         policy.writeFlag(x86_flag_cf, carry);
1572                         policy.writeFlag(x86_flag_of, carry);
1573                         break;
1574                     }
1575                     case 4: {
1576                         Word(32) op0 = operands.size() == 1 ? policy.readGPR(x86_gpr_ax) : read32(operands[operands.size() - 2]);
1577                         Word(32) op1 = read32(operands[operands.size() - 1]);
1578                         Word(64) mulResult = policy.signedMultiply(op0, op1);
1579                         if (operands.size() == 1) {
1580                             policy.writeGPR(x86_gpr_ax, extract<0, 32>(mulResult));
1581                             policy.writeGPR(x86_gpr_dx, extract<32, 64>(mulResult));
1582                         } else {
1583                             write32(operands[0], extract<0, 32>(mulResult));
1584                         }
1585                         Word(1) carry = policy.invert(policy.or_(policy.equalToZero(policy.invert(extract<7, 64>(mulResult))),
1586                                                                  policy.equalToZero(extract<7, 64>(mulResult))));
1587                         policy.writeFlag(x86_flag_cf, carry);
1588                         policy.writeFlag(x86_flag_of, carry);
1589                         break;
1590                     }
1591                     default:
1592                         ROSE_ASSERT(!"Bad size");
1593                 }
1594                 policy.writeFlag(x86_flag_sf, policy.undefined_());
1595                 policy.writeFlag(x86_flag_zf, policy.undefined_());
1596                 policy.writeFlag(x86_flag_af, policy.undefined_());
1597                 policy.writeFlag(x86_flag_pf, policy.undefined_());
1598                 break;
1599             }
1600
1601             case x86_mul: {
1602                 switch (numBytesInAsmType(operands[0]->get_type())) {
1603                     case 1: {
1604                         Word(8) op0 = extract<0, 8>(policy.readGPR(x86_gpr_ax));
1605                         Word(8) op1 = read8(operands[0]);
1606                         Word(16) mulResult = policy.unsignedMultiply(op0, op1);
1607                         updateGPRLowWord(x86_gpr_ax, mulResult);
1608                         Word(1) carry = policy.invert(policy.equalToZero(extract<8, 16>(mulResult)));
1609                         policy.writeFlag(x86_flag_cf, carry);
1610                         policy.writeFlag(x86_flag_of, carry);
1611                         break;
1612                     }
1613                     case 2: {
1614                         Word(16) op0 = extract<0, 16>(policy.readGPR(x86_gpr_ax));
1615                         Word(16) op1 = read16(operands[0]);
1616                         Word(32) mulResult = policy.unsignedMultiply(op0, op1);
1617                         updateGPRLowWord(x86_gpr_ax, extract<0, 16>(mulResult));
1618                         updateGPRLowWord(x86_gpr_dx, extract<16, 32>(mulResult));
1619                         Word(1) carry = policy.invert(policy.equalToZero(extract<16, 32>(mulResult)));
1620                         policy.writeFlag(x86_flag_cf, carry);
1621                         policy.writeFlag(x86_flag_of, carry);
1622                         break;
1623                     }
1624                     case 4: {
1625                         Word(32) op0 = policy.readGPR(x86_gpr_ax);
1626                         Word(32) op1 = read32(operands[0]);
1627                         Word(64) mulResult = policy.unsignedMultiply(op0, op1);
1628                         policy.writeGPR(x86_gpr_ax, extract<0, 32>(mulResult));
1629                         policy.writeGPR(x86_gpr_dx, extract<32, 64>(mulResult));
1630                         Word(1) carry = policy.invert(policy.equalToZero(extract<32, 64>(mulResult)));
1631                         policy.writeFlag(x86_flag_cf, carry);
1632                         policy.writeFlag(x86_flag_of, carry);
1633                         break;
1634                     }
1635                     default:
1636                         ROSE_ASSERT(!"Bad size");
1637                 }
1638                 policy.writeFlag(x86_flag_sf, policy.undefined_());
1639                 policy.writeFlag(x86_flag_zf, policy.undefined_());
1640                 policy.writeFlag(x86_flag_af, policy.undefined_());
1641                 policy.writeFlag(x86_flag_pf, policy.undefined_());
1642                 break;
1643             }
1644
1645             case x86_idiv: {
1646                 switch (numBytesInAsmType(operands[0]->get_type())) {
1647                     case 1: {
1648                         Word(16) op0 = extract<0, 16>(policy.readGPR(x86_gpr_ax));
1649                         Word(8) op1 = read8(operands[0]);
1650                         /* if op1 == 0, we should trap */
1651                         Word(16) divResult = policy.signedDivide(op0, op1);
1652                         Word(8) modResult = policy.signedModulo(op0, op1);
1653                         /* if result overflows, we should trap */
1654                         updateGPRLowWord(x86_gpr_ax, policy.concat(extract<0, 8>(divResult), modResult));
1655                         break;
1656                     }
1657                     case 2: {
1658                         Word(32) op0 = policy.concat(extract<0, 16>(policy.readGPR(x86_gpr_ax)),
1659                                                      extract<0, 16>(policy.readGPR(x86_gpr_dx)));
1660                         Word(16) op1 = read16(operands[0]);
1661                         /* if op1 == 0, we should trap */
1662                         Word(32) divResult = policy.signedDivide(op0, op1);
1663                         Word(16) modResult = policy.signedModulo(op0, op1);
1664                         /* if result overflows, we should trap */
1665                         updateGPRLowWord(x86_gpr_ax, extract<0, 16>(divResult));
1666                         updateGPRLowWord(x86_gpr_dx, modResult);
1667                         break;
1668                     }
1669                     case 4: {
1670                         Word(64) op0 = policy.concat(policy.readGPR(x86_gpr_ax), policy.readGPR(x86_gpr_dx));
1671                         Word(32) op1 = read32(operands[0]);
1672                         /* if op1 == 0, we should trap */
1673                         Word(64) divResult = policy.signedDivide(op0, op1);
1674                         Word(32) modResult = policy.signedModulo(op0, op1);
1675                         /* if result overflows, we should trap */
1676                         policy.writeGPR(x86_gpr_ax, extract<0, 32>(divResult));
1677                         policy.writeGPR(x86_gpr_dx, modResult);
1678                         break;
1679                     }
1680                     default:
1681                         ROSE_ASSERT(!"Bad size");
1682                 }
1683                 policy.writeFlag(x86_flag_sf, policy.undefined_());
1684                 policy.writeFlag(x86_flag_zf, policy.undefined_());
1685                 policy.writeFlag(x86_flag_af, policy.undefined_());
1686                 policy.writeFlag(x86_flag_pf, policy.undefined_());
1687                 policy.writeFlag(x86_flag_cf, policy.undefined_());
1688                 policy.writeFlag(x86_flag_of, policy.undefined_());
1689                 break;
1690             }
1691
1692             case x86_div: {
1693                 switch (numBytesInAsmType(operands[0]->get_type())) {
1694                     case 1: {
1695                         Word(16) op0 = extract<0, 16>(policy.readGPR(x86_gpr_ax));
1696                         Word(8) op1 = read8(operands[0]);
1697                         /* if op1 == 0, we should trap */
1698                         Word(16) divResult = policy.unsignedDivide(op0, op1);
1699                         Word(8) modResult = policy.unsignedModulo(op0, op1);
1700                         /* if extract<8, 16> of divResult is non-zero (overflow), we should trap */
1701                         updateGPRLowWord(x86_gpr_ax, policy.concat(extract<0, 8>(divResult), modResult));
1702                         break;
1703                     }
1704                     case 2: {
1705                         Word(32) op0 = policy.concat(extract<0, 16>(policy.readGPR(x86_gpr_ax)),
1706                                                      extract<0, 16>(policy.readGPR(x86_gpr_dx)));
1707                         Word(16) op1 = read16(operands[0]);
1708                         /* if op1 == 0, we should trap */
1709                         Word(32) divResult = policy.unsignedDivide(op0, op1);
1710                         Word(16) modResult = policy.unsignedModulo(op0, op1);
1711                         /* if extract<16, 32> of divResult is non-zero (overflow), we should trap */
1712                         updateGPRLowWord(x86_gpr_ax, extract<0, 16>(divResult));
1713                         updateGPRLowWord(x86_gpr_dx, modResult);
1714                         break;
1715                     }
1716                     case 4: {
1717                         Word(64) op0 = policy.concat(policy.readGPR(x86_gpr_ax), policy.readGPR(x86_gpr_dx));
1718                         Word(32) op1 = read32(operands[0]);
1719                         /* if op1 == 0, we should trap */
1720                         Word(64) divResult = policy.unsignedDivide(op0, op1);
1721                         Word(32) modResult = policy.unsignedModulo(op0, op1);
1722                         /* if extract<32, 64> of divResult is non-zero (overflow), we should trap */
1723                         policy.writeGPR(x86_gpr_ax, extract<0, 32>(divResult));
1724                         policy.writeGPR(x86_gpr_dx, modResult);
1725                         break;
1726                     }
1727                     default:
1728                         ROSE_ASSERT(!"Bad size");
1729                 }
1730                 policy.writeFlag(x86_flag_sf, policy.undefined_());
1731                 policy.writeFlag(x86_flag_zf, policy.undefined_());
1732                 policy.writeFlag(x86_flag_af, policy.undefined_());
1733                 policy.writeFlag(x86_flag_pf, policy.undefined_());
1734                 policy.writeFlag(x86_flag_cf, policy.undefined_());
1735                 policy.writeFlag(x86_flag_of, policy.undefined_());
1736                 break;
1737             }
1738
1739             case x86_aaa: {
1740                 ROSE_ASSERT(operands.size() == 0);
1741                 Word(1) incAh = policy.or_(policy.readFlag(x86_flag_af),
1742                                            greaterOrEqualToTen(extract<0, 4>(policy.readGPR(x86_gpr_ax))));
1743                 updateGPRLowWord(x86_gpr_ax,
1744                                  policy.concat(policy.add(policy.ite(incAh, number<4>(6), number<4>(0)),
1745                                                           extract<0, 4>(policy.readGPR(x86_gpr_ax))),
1746                                                policy.concat(number<4>(0),
1747                                                              policy.add(policy.ite(incAh, number<8>(1), number<8>(0)),
1748                                                                         extract<8, 16>(policy.readGPR(x86_gpr_ax))))));
1749                 policy.writeFlag(x86_flag_of, policy.undefined_());
1750                 policy.writeFlag(x86_flag_sf, policy.undefined_());
1751                 policy.writeFlag(x86_flag_zf, policy.undefined_());
1752                 policy.writeFlag(x86_flag_pf, policy.undefined_());
1753                 policy.writeFlag(x86_flag_af, incAh);
1754                 policy.writeFlag(x86_flag_cf, incAh);
1755                 break;
1756             }
1757
1758             case x86_aas: {
1759                 ROSE_ASSERT(operands.size() == 0);
1760                 Word(1) decAh = policy.or_(policy.readFlag(x86_flag_af),
1761                                            greaterOrEqualToTen(extract<0, 4>(policy.readGPR(x86_gpr_ax))));
1762                 updateGPRLowWord(x86_gpr_ax,
1763                                  policy.concat(policy.add(policy.ite(decAh, number<4>(-6), number<4>(0)),
1764                                                           extract<0, 4>(policy.readGPR(x86_gpr_ax))),
1765                                                policy.concat(number<4>(0),
1766                                                              policy.add(policy.ite(decAh, number<8>(-1), number<8>(0)),
1767                                                                         extract<8, 16>(policy.readGPR(x86_gpr_ax))))));
1768                 policy.writeFlag(x86_flag_of, policy.undefined_());
1769                 policy.writeFlag(x86_flag_sf, policy.undefined_());
1770                 policy.writeFlag(x86_flag_zf, policy.undefined_());
1771                 policy.writeFlag(x86_flag_pf, policy.undefined_());
1772                 policy.writeFlag(x86_flag_af, decAh);
1773                 policy.writeFlag(x86_flag_cf, decAh);
1774                 break;
1775             }
1776
1777             case x86_aam: {
1778                 ROSE_ASSERT(operands.size() == 1);
1779                 Word(8) al = extract<0, 8>(policy.readGPR(x86_gpr_ax));
1780                 Word(8) divisor = read8(operands[0]);
1781                 Word(8) newAh = policy.unsignedDivide(al, divisor);
1782                 Word(8) newAl = policy.unsignedModulo(al, divisor);
1783                 updateGPRLowWord(x86_gpr_ax, policy.concat(newAl, newAh));
1784                 policy.writeFlag(x86_flag_of, policy.undefined_());
1785                 policy.writeFlag(x86_flag_af, policy.undefined_());
1786                 policy.writeFlag(x86_flag_cf, policy.undefined_());
1787                 setFlagsForResult<8>(newAl);
1788                 break;
1789             }
1790
1791             case x86_aad: {
1792                 ROSE_ASSERT(operands.size() == 1);
1793                 Word(8) al = extract<0, 8>(policy.readGPR(x86_gpr_ax));
1794                 Word(8) ah = extract<8, 16>(policy.readGPR(x86_gpr_ax));
1795                 Word(8) divisor = read8(operands[0]);
1796                 Word(8) newAl = policy.add(al, extract<0, 8>(policy.unsignedMultiply(ah, divisor)));
1797                 updateGPRLowWord(x86_gpr_ax, policy.concat(newAl, number<8>(0)));
1798                 policy.writeFlag(x86_flag_of, policy.undefined_());
1799                 policy.writeFlag(x86_flag_af, policy.undefined_());
1800                 policy.writeFlag(x86_flag_cf, policy.undefined_());
1801                 setFlagsForResult<8>(newAl);
1802                 break;
1803             }
1804
1805             case x86_bswap: {
1806                 ROSE_ASSERT(operands.size() == 1);
1807                 Word(32) oldVal = read32(operands[0]);
1808                 Word(32) newVal = policy.concat(extract<24, 32>(oldVal),
1809                                                 policy.concat(extract<16, 24>(oldVal),
1810                                                               policy.concat(extract<8, 16>(oldVal),
1811                                                                             extract<0, 8>(oldVal))));
1812                 write32(operands[0], newVal);
1813                 break;
1814             }
1815
1816             case x86_push: {
1817                 ROSE_ASSERT(operands.size() == 1);
1818                 ROSE_ASSERT(insn->get_addressSize() == x86_insnsize_32);
1819                 ROSE_ASSERT(insn->get_operandSize() == x86_insnsize_32);
1820                 Word(32) oldSp = policy.readGPR(x86_gpr_sp);
1821                 Word(32) newSp = policy.add(oldSp, number<32>(-4));
1822                 policy.writeMemory(x86_segreg_ss, newSp, read32(operands[0]), policy.true_());
1823                 policy.writeGPR(x86_gpr_sp, newSp);
1824                 break;
1825             }
1826
1827             case x86_pushad: {
1828                 ROSE_ASSERT(operands.size() == 0);
1829                 ROSE_ASSERT(insn->get_addressSize() == x86_insnsize_32);
1830                 Word(32) oldSp = policy.readGPR(x86_gpr_sp);
1831                 Word(32) newSp = policy.add(oldSp, number<32>(-32));
1832                 policy.writeMemory(x86_segreg_ss, newSp, policy.readGPR(x86_gpr_di), policy.true_());
1833                 policy.writeMemory(x86_segreg_ss, policy.add(newSp, number<32>(4)), policy.readGPR(x86_gpr_si), policy.true_());
1834                 policy.writeMemory(x86_segreg_ss, policy.add(newSp, number<32>(8)), policy.readGPR(x86_gpr_bp), policy.true_());
1835                 policy.writeMemory(x86_segreg_ss, policy.add(newSp, number<32>(12)), oldSp, policy.true_());
1836                 policy.writeMemory(x86_segreg_ss, policy.add(newSp, number<32>(16)), policy.readGPR(x86_gpr_bx), policy.true_());
1837                 policy.writeMemory(x86_segreg_ss, policy.add(newSp, number<32>(20)), policy.readGPR(x86_gpr_dx), policy.true_());
1838                 policy.writeMemory(x86_segreg_ss, policy.add(newSp, number<32>(24)), policy.readGPR(x86_gpr_cx), policy.true_());
1839                 policy.writeMemory(x86_segreg_ss, policy.add(newSp, number<32>(28)), policy.readGPR(x86_gpr_ax), policy.true_());
1840                 policy.writeGPR(x86_gpr_sp, newSp);
1841                 break;
1842             }
1843
1844             case x86_pushfd: {
1845                 ROSE_ASSERT(operands.size() == 0);
1846                 ROSE_ASSERT(insn->get_addressSize() == x86_insnsize_32);
1847                 Word(32) oldSp = policy.readGPR(x86_gpr_sp);
1848                 Word(32) newSp = policy.add(oldSp, number<32>(-4));
1849                 policy.writeMemory(x86_segreg_ss, newSp, readEflags(), policy.true_());
1850                 policy.writeGPR(x86_gpr_sp, newSp);
1851                 break;
1852             }
1853
1854             case x86_pop: {
1855                 ROSE_ASSERT(operands.size() == 1);
1856                 ROSE_ASSERT(insn->get_addressSize() == x86_insnsize_32);
1857                 ROSE_ASSERT(insn->get_operandSize() == x86_insnsize_32);
1858                 Word(32) oldSp = policy.readGPR(x86_gpr_sp);
1859                 Word(32) newSp = policy.add(oldSp, number<32>(4));
1860                 write32(operands[0], readMemory<32>(x86_segreg_ss, oldSp, policy.true_()));
1861                 policy.writeGPR(x86_gpr_sp, newSp);
1862                 break;
1863             }
1864
1865             case x86_popad: {
1866                 ROSE_ASSERT(operands.size() == 0);
1867                 ROSE_ASSERT(insn->get_addressSize() == x86_insnsize_32);
1868                 Word(32) oldSp = policy.readGPR(x86_gpr_sp);
1869                 Word(32) newSp = policy.add(oldSp, number<32>(32));
1870                 policy.writeGPR(x86_gpr_di, readMemory<32>(x86_segreg_ss, oldSp, policy.true_()));
1871                 policy.writeGPR(x86_gpr_si, readMemory<32>(x86_segreg_ss, policy.add(oldSp, number<32>(4)), policy.true_()));
1872                 policy.writeGPR(x86_gpr_bp, readMemory<32>(x86_segreg_ss, policy.add(oldSp, number<32>(8)), policy.true_()));
1873                 policy.writeGPR(x86_gpr_bx, readMemory<32>(x86_segreg_ss, policy.add(oldSp, number<32>(16)), policy.true_()));
1874                 policy.writeGPR(x86_gpr_dx, readMemory<32>(x86_segreg_ss, policy.add(oldSp, number<32>(20)), policy.true_()));
1875                 policy.writeGPR(x86_gpr_cx, readMemory<32>(x86_segreg_ss, policy.add(oldSp, number<32>(24)), policy.true_()));
1876                 policy.writeGPR(x86_gpr_ax, readMemory<32>(x86_segreg_ss, policy.add(oldSp, number<32>(28)), policy.true_()));
1877                 readMemory<32>(x86_segreg_ss, policy.add(oldSp, number<32>(12)), policy.true_());
1878                 policy.writeGPR(x86_gpr_sp, newSp);
1879                 break;
1880             }
1881
1882             case x86_leave: {
1883                 ROSE_ASSERT(operands.size() == 0);
1884                 policy.writeGPR(x86_gpr_sp, policy.readGPR(x86_gpr_bp));
1885                 ROSE_ASSERT(insn->get_addressSize() == x86_insnsize_32);
1886                 ROSE_ASSERT(insn->get_operandSize() == x86_insnsize_32);
1887                 Word(32) oldSp = policy.readGPR(x86_gpr_sp);
1888                 Word(32) newSp = policy.add(oldSp, number<32>(4));
1889                 policy.writeGPR(x86_gpr_bp, readMemory<32>(x86_segreg_ss, oldSp, policy.true_()));
1890                 policy.writeGPR(x86_gpr_sp, newSp);
1891                 break;
1892             }
1893
1894             case x86_call: {
1895                 ROSE_ASSERT(operands.size() == 1);
1896                 ROSE_ASSERT(insn->get_addressSize() == x86_insnsize_32);
1897                 ROSE_ASSERT(insn->get_operandSize() == x86_insnsize_32);
1898                 Word(32) oldSp = policy.readGPR(x86_gpr_sp);
1899                 Word(32) newSp = policy.add(oldSp, number<32>(-4));
1900                 policy.writeMemory(x86_segreg_ss, newSp, policy.readIP(), policy.true_());
1901                 policy.writeIP(policy.filterCallTarget(read32(operands[0])));
1902                 policy.writeGPR(x86_gpr_sp, newSp);
1903                 break;
1904             }
1905
1906             case x86_ret: {
1907                 ROSE_ASSERT(operands.size() <= 1);
1908                 ROSE_ASSERT(insn->get_addressSize() == x86_insnsize_32);
1909                 ROSE_ASSERT(insn->get_operandSize() == x86_insnsize_32);
1910                 Word(32) extraBytes = (operands.size() == 1 ? read32(operands[0]) : number<32>(0));
1911                 Word(32) oldSp = policy.readGPR(x86_gpr_sp);
1912                 Word(32) newSp = policy.add(oldSp, policy.add(number<32>(4), extraBytes));
1913                 policy.writeIP(policy.filterReturnTarget(readMemory<32>(x86_segreg_ss, oldSp, policy.true_())));
1914                 policy.writeGPR(x86_gpr_sp, newSp);
1915                 break;
1916             }
1917
1918             case x86_loop: {
1919                 ROSE_ASSERT(insn->get_addressSize() == x86_insnsize_32);
1920                 ROSE_ASSERT(insn->get_operandSize() == x86_insnsize_32);
1921                 ROSE_ASSERT(operands.size() == 1);
1922                 Word(32) oldCx = policy.readGPR(x86_gpr_cx);
1923                 Word(32) newCx = policy.add(number<32>(-1), oldCx);
1924                 policy.writeGPR(x86_gpr_cx, newCx);
1925                 Word(1) doLoop = policy.invert(policy.equalToZero(newCx));
1926                 policy.writeIP(policy.ite(doLoop, read32(operands[0]), policy.readIP()));
1927                 break;
1928             }
1929             case x86_loopz: {
1930                 ROSE_ASSERT(insn->get_addressSize() == x86_insnsize_32);
1931                 ROSE_ASSERT(insn->get_operandSize() == x86_insnsize_32);
1932                 ROSE_ASSERT(operands.size() == 1);
1933                 Word(32) oldCx = policy.readGPR(x86_gpr_cx);
1934                 Word(32) newCx = policy.add(number<32>(-1), oldCx);
1935                 policy.writeGPR(x86_gpr_cx, newCx);
1936                 Word(1) doLoop = policy.and_(policy.invert(policy.equalToZero(newCx)), policy.readFlag(x86_flag_zf));
1937                 policy.writeIP(policy.ite(doLoop, read32(operands[0]), policy.readIP()));
1938                 break;
1939             }
1940             case x86_loopnz: {
1941                 ROSE_ASSERT(insn->get_addressSize() == x86_insnsize_32);
1942                 ROSE_ASSERT(insn->get_operandSize() == x86_insnsize_32);
1943                 ROSE_ASSERT(operands.size() == 1);
1944                 Word(32) oldCx = policy.readGPR(x86_gpr_cx);
1945                 Word(32) newCx = policy.add(number<32>(-1), oldCx);
1946                 policy.writeGPR(x86_gpr_cx, newCx);
1947                 Word(1) doLoop = policy.and_(policy.invert(policy.equalToZero(newCx)),
1948                                              policy.invert(policy.readFlag(x86_flag_zf)));
1949                 policy.writeIP(policy.ite(doLoop, read32(operands[0]), policy.readIP()));
1950                 break;
1951             }
1952
1953             case x86_jmp: {
1954                 ROSE_ASSERT(operands.size() == 1);
1955                 policy.writeIP(policy.filterIndirectJumpTarget(read32(operands[0])));
1956                 break;
1957             }
1958
1959
1960             /* Flag expressions that must be true for a conditional jump to occur. */
1961 #           define FLAGCOMBO_ne    policy.invert(policy.readFlag(x86_flag_zf))
1962 #           define FLAGCOMBO_e     policy.readFlag(x86_flag_zf)
1963 #           define FLAGCOMBO_no    policy.invert(policy.readFlag(x86_flag_of))
1964 #           define FLAGCOMBO_o     policy.readFlag(x86_flag_of)
1965 #           define FLAGCOMBO_ns    policy.invert(policy.readFlag(x86_flag_sf))
1966 #           define FLAGCOMBO_s     policy.readFlag(x86_flag_sf)
1967 #           define FLAGCOMBO_po    policy.invert(policy.readFlag(x86_flag_pf))
1968 #           define FLAGCOMBO_pe    policy.readFlag(x86_flag_pf)
1969 #           define FLAGCOMBO_ae    policy.invert(policy.readFlag(x86_flag_cf))
1970 #           define FLAGCOMBO_b     policy.readFlag(x86_flag_cf)
1971 #           define FLAGCOMBO_be    policy.or_(FLAGCOMBO_b, FLAGCOMBO_e)
1972 #           define FLAGCOMBO_a     policy.and_(FLAGCOMBO_ae, FLAGCOMBO_ne)
1973 #           define FLAGCOMBO_l     policy.xor_(policy.readFlag(x86_flag_sf), policy.readFlag(x86_flag_of))
1974 #           define FLAGCOMBO_ge    policy.invert(policy.xor_(policy.readFlag(x86_flag_sf), policy.readFlag(x86_flag_of)))
1975 #           define FLAGCOMBO_le    policy.or_(FLAGCOMBO_e, FLAGCOMBO_l)
1976 #           define FLAGCOMBO_g     policy.and_(FLAGCOMBO_ge, FLAGCOMBO_ne)
1977 #           define FLAGCOMBO_cxz   policy.equalToZero(extract<0, 16>(policy.readGPR(x86_gpr_cx)))
1978 #           define FLAGCOMBO_ecxz  policy.equalToZero(policy.readGPR(x86_gpr_cx))
1979
1980 #           define JUMP(tag) {                                                                                                 \
1981                 ROSE_ASSERT(operands.size() == 1);                                                                             \
1982                 policy.writeIP(policy.ite(FLAGCOMBO_##tag,                                                                     \
1983                                           read32(operands[0]),                                                                 \
1984                                           policy.readIP()));                                                                   \
1985             }
1986             case x86_jne:   JUMP(ne);   break;
1987             case x86_je:    JUMP(e);    break;
1988             case x86_jno:   JUMP(no);   break;
1989             case x86_jo:    JUMP(o);    break;
1990             case x86_jpo:   JUMP(po);   break;
1991             case x86_jpe:   JUMP(pe);   break;
1992             case x86_jns:   JUMP(ns);   break;
1993             case x86_js:    JUMP(s);    break;
1994             case x86_jae:   JUMP(ae);   break;
1995             case x86_jb:    JUMP(b);    break;
1996             case x86_jbe:   JUMP(be);   break;
1997             case x86_ja:    JUMP(a);    break;
1998             case x86_jle:   JUMP(le);   break;
1999             case x86_jg:    JUMP(g);    break;
2000             case x86_jge:   JUMP(ge);   break;
2001             case x86_jl:    JUMP(l);    break;
2002             case x86_jcxz:  JUMP(cxz);  break;
2003             case x86_jecxz: JUMP(ecxz); break;
2004 #           undef JUMP
2005
2006 #           define SET(tag) {                                                                                                  \
2007                 ROSE_ASSERT(operands.size() == 1);                                                                             \
2008                 write8(operands[0], policy.concat(FLAGCOMBO_##tag, number<7>(0)));                                             \
2009             }
2010             case x86_setne: SET(ne); break;
2011             case x86_sete:  SET(e);  break;
2012             case x86_setno: SET(no); break;
2013             case x86_seto:  SET(o);  break;
2014             case x86_setpo: SET(po); break;
2015             case x86_setpe: SET(pe); break;
2016             case x86_setns: SET(ns); break;
2017             case x86_sets:  SET(s);  break;
2018             case x86_setae: SET(ae); break;
2019             case x86_setb:  SET(b);  break;
2020             case x86_setbe: SET(be); break;
2021             case x86_seta:  SET(a);  break;
2022             case x86_setle: SET(le); break;
2023             case x86_setg:  SET(g);  break;
2024             case x86_setge: SET(ge); break;
2025             case x86_setl:  SET(l);  break;
2026 #           undef SET
2027                 
2028 #           define CMOV(tag) {                                                                                                 \
2029                 ROSE_ASSERT(operands.size() == 2);                                                                             \
2030                 switch (numBytesInAsmType(operands[0]->get_type())) {                                                          \
2031                     case 2: write16(operands[0], policy.ite(FLAGCOMBO_##tag, read16(operands[1]), read16(operands[0]))); break; \
2032                     case 4: write32(operands[0], policy.ite(FLAGCOMBO_##tag, read32(operands[1]), read32(operands[0]))); break; \
2033                     default: ROSE_ASSERT("Bad size"); break;                                                                   \
2034                 }                                                                                                              \
2035             }
2036             case x86_cmovne:    CMOV(ne);       break;
2037             case x86_cmove:     CMOV(e);        break;
2038             case x86_cmovno:    CMOV(no);       break;
2039             case x86_cmovo:     CMOV(o);        break;
2040             case x86_cmovpo:    CMOV(po);       break;
2041             case x86_cmovpe:    CMOV(pe);       break;
2042             case x86_cmovns:    CMOV(ns);       break;
2043             case x86_cmovs:     CMOV(s);        break;
2044             case x86_cmovae:    CMOV(ae);       break;
2045             case x86_cmovb:     CMOV(b);        break;
2046             case x86_cmovbe:    CMOV(be);       break;
2047             case x86_cmova:     CMOV(a);        break;
2048             case x86_cmovle:    CMOV(le);       break;
2049             case x86_cmovg:     CMOV(g);        break;
2050             case x86_cmovge:    CMOV(ge);       break;
2051             case x86_cmovl:     CMOV(l);        break;
2052 #           undef CMOV
2053
2054             /* The flag expressions are no longer needed */
2055 #           undef FLAGCOMBO_ne
2056 #           undef FLAGCOMBO_e
2057 #           undef FLAGCOMBO_ns
2058 #           undef FLAGCOMBO_s
2059 #           undef FLAGCOMBO_ae
2060 #           undef FLAGCOMBO_b
2061 #           undef FLAGCOMBO_be
2062 #           undef FLAGCOMBO_a
2063 #           undef FLAGCOMBO_l
2064 #           undef FLAGCOMBO_ge
2065 #           undef FLAGCOMBO_le
2066 #           undef FLAGCOMBO_g
2067 #           undef FLAGCOMBO_cxz
2068 #           undef FLAGCOMBO_ecxz
2069
2070             case x86_cld: {
2071                 ROSE_ASSERT(operands.size() == 0);
2072                 policy.writeFlag(x86_flag_df, policy.false_());
2073                 break;
2074             }
2075
2076             case x86_std: {
2077                 ROSE_ASSERT(operands.size() == 0);
2078                 policy.writeFlag(x86_flag_df, policy.true_());
2079                 break;
2080             }
2081
2082             case x86_clc: {
2083                 ROSE_ASSERT(operands.size() == 0);
2084                 policy.writeFlag(x86_flag_cf, policy.false_());
2085                 break;
2086             }
2087
2088             case x86_stc: {
2089                 ROSE_ASSERT(operands.size() == 0);
2090                 policy.writeFlag(x86_flag_cf, policy.true_());
2091                 break;
2092             }
2093
2094             case x86_cmc: {
2095                 ROSE_ASSERT(operands.size() == 0);
2096                 policy.writeFlag(x86_flag_cf, policy.invert(policy.readFlag(x86_flag_cf)));
2097                 break;
2098             }
2099
2100             case x86_nop:
2101                 break;
2102
2103 #           define STRINGOP_LOAD_SI(len, cond)                                                                                 \
2104                 readMemory<(8 * (len))>((insn->get_segmentOverride() == x86_segreg_none ?                                      \
2105                                          x86_segreg_ds :                                                                       \
2106                                          insn->get_segmentOverride()),                                                         \
2107                                         policy.readGPR(x86_gpr_si),                                                            \
2108                                         (cond))
2109             
2110 #           define STRINGOP_LOAD_DI(len, cond)                                                                                 \
2111                 readMemory<(8 * (len))>(x86_segreg_es, policy.readGPR(x86_gpr_di), (cond))
2112
2113             /* If true, repeat this instruction, otherwise go to the next one */
2114 #           define STRINGOP_LOOP_E                                                                                             \
2115                 policy.writeIP(policy.ite(policy.and_(ecxNotZero, policy.readFlag(x86_flag_zf)),                               \
2116                                           number<32>((uint32_t)(insn->get_address())),                                         \
2117                                           policy.readIP()))
2118
2119             /* If true, repeat this instruction, otherwise go to the next one */
2120 #           define STRINGOP_LOOP_NE                                                                                            \
2121                 policy.writeIP(policy.ite(policy.and_(ecxNotZero, policy.invert(policy.readFlag(x86_flag_zf))),                \
2122                                           number<32>((uint32_t)(insn->get_address())),                                         \
2123                                           policy.readIP()))
2124
2125 #           define REP_SCAS(suffix, len, repsuffix, loopmacro) {                                                               \
2126                 ROSE_ASSERT(operands.size() == 0);                                                                             \
2127                 ROSE_ASSERT(insn->get_addressSize() == x86_insnsize_32);                                                       \
2128                 Word(1) ecxNotZero = stringop_setup_loop();                                                                    \
2129                 doAddOperation<(len * 8)>(extract<0, (len * 8)>(policy.readGPR(x86_gpr_ax)),                                   \
2130                                           policy.invert(STRINGOP_LOAD_DI(len, ecxNotZero)),                                    \
2131                                           true,                                                                                \
2132                                           policy.false_(),                                                                     \
2133                                           ecxNotZero);                                                                         \
2134                 policy.writeGPR(x86_gpr_di,                                                                                    \
2135                                 policy.add(policy.readGPR(x86_gpr_di),                                                         \
2136                                            policy.ite(policy.readFlag(x86_flag_df), number<32>(-(len)), number<32>(len))));    \
2137                 loopmacro;                                                                                                     \
2138             }
2139             case x86_repne_scasb: REP_SCAS(b, 1, ne, STRINGOP_LOOP_NE); break;
2140             case x86_repne_scasw: REP_SCAS(w, 2, ne, STRINGOP_LOOP_NE); break;
2141             case x86_repne_scasd: REP_SCAS(d, 4, ne, STRINGOP_LOOP_NE); break;
2142             case x86_repe_scasb:  REP_SCAS(b, 1, e,  STRINGOP_LOOP_E);  break;
2143             case x86_repe_scasw:  REP_SCAS(w, 2, e,  STRINGOP_LOOP_E);  break;
2144             case x86_repe_scasd:  REP_SCAS(d, 4, e,  STRINGOP_LOOP_E);  break;
2145 #           undef REP_SCAS
2146
2147 #           define SCAS(suffix, len) {                                                                                         \
2148                 ROSE_ASSERT(operands.size() == 0);                                                                             \
2149                 ROSE_ASSERT(insn->get_addressSize() == x86_insnsize_32);                                                       \
2150                 doAddOperation<(len * 8)>(extract<0, (len * 8)>(policy.readGPR(x86_gpr_ax)),                                   \
2151                                           policy.invert(STRINGOP_LOAD_DI(len, policy.true_())),                                \
2152                                           true,                                                                                \
2153                                           policy.false_(),                                                                     \
2154                                           policy.true_());                                                                     \
2155                 policy.writeGPR(x86_gpr_di,                                                                                    \
2156                                 policy.add(policy.readGPR(x86_gpr_di),                                                         \
2157                                            policy.ite(policy.readFlag(x86_flag_df), number<32>(-(len)), number<32>(len))));    \
2158             }
2159             case x86_scasb: SCAS(b, 1); break;
2160             case x86_scasw: SCAS(w, 2); break;
2161             case x86_scasd: SCAS(d, 4); break;
2162 #           undef SCAS
2163
2164 #           define REP_CMPS(suffix, len, repsuffix, loopmacro) {                                                               \
2165                 ROSE_ASSERT(operands.size() == 0);                                                                             \
2166                 ROSE_ASSERT(insn->get_addressSize() == x86_insnsize_32);                                                       \
2167                 Word(1) ecxNotZero = stringop_setup_loop();                                                                    \
2168                 doAddOperation<(len * 8)>(STRINGOP_LOAD_SI(len, ecxNotZero),                                                   \
2169                                           policy.invert(STRINGOP_LOAD_DI(len, ecxNotZero)),                                    \
2170                                           true,                                                                                \
2171                                           policy.false_(),                                                                     \
2172                                           ecxNotZero);                                                                         \
2173                 policy.writeGPR(x86_gpr_si,                                                                                    \
2174                                 policy.add(policy.readGPR(x86_gpr_si),                                                         \
2175                                            policy.ite(ecxNotZero,                                                              \
2176                                                       policy.ite(policy.readFlag(x86_flag_df),                                 \
2177                                                                  number<32>(-(len)),                                           \
2178                                                                  number<32>(len)),                                             \
2179                                                       number<32>(0))));                                                        \
2180                 policy.writeGPR(x86_gpr_di,                                                                                    \
2181                                 policy.add(policy.readGPR(x86_gpr_di),                                                         \
2182                                            policy.ite(ecxNotZero,                                                              \
2183                                                       policy.ite(policy.readFlag(x86_flag_df),                                 \
2184                                                                  number<32>(-(len)),                                           \
2185                                                                  number<32>(len)),                                             \
2186                                                       number<32>(0))));                                                        \
2187                 loopmacro;                                                                                                     \
2188             }
2189             case x86_repne_cmpsb: REP_CMPS(b, 1, ne, STRINGOP_LOOP_NE); break;
2190             case x86_repne_cmpsw: REP_CMPS(w, 2, ne, STRINGOP_LOOP_NE); break;
2191             case x86_repne_cmpsd: REP_CMPS(d, 4, ne, STRINGOP_LOOP_NE); break;
2192             case x86_repe_cmpsb:  REP_CMPS(b, 1, e,  STRINGOP_LOOP_E);  break;
2193             case x86_repe_cmpsw:  REP_CMPS(w, 2, e,  STRINGOP_LOOP_E);  break;
2194             case x86_repe_cmpsd:  REP_CMPS(d, 4, e,  STRINGOP_LOOP_E);  break;
2195 #           undef REP_CMPS
2196
2197 #           define CMPS(suffix, len) {                                                                                         \
2198                 ROSE_ASSERT(operands.size() == 0);                                                                             \
2199                 ROSE_ASSERT(insn->get_addressSize() == x86_insnsize_32);                                                       \
2200                 doAddOperation<(len * 8)>(STRINGOP_LOAD_SI(len, policy.true_()),                                               \
2201                                           policy.invert(STRINGOP_LOAD_DI(len, policy.true_())),                                \
2202                                           true,                                                                                \
2203                                           policy.false_(),                                                                     \
2204                                           policy.true_());                                                                     \
2205                 policy.writeGPR(x86_gpr_si,                                                                                    \
2206                                 policy.add(policy.readGPR(x86_gpr_si),                                                         \
2207                                            policy.ite(policy.readFlag(x86_flag_df), number<32>(-(len)), number<32>(len))));    \
2208                 policy.writeGPR(x86_gpr_di,                                                                                    \
2209                                 policy.add(policy.readGPR(x86_gpr_di),                                                         \
2210                                            policy.ite(policy.readFlag(x86_flag_df), number<32>(-(len)), number<32>(len))));    \
2211             }
2212             case x86_cmpsb: CMPS(b, 1); break;
2213             case x86_cmpsw: CMPS(w, 2); break;
2214             case x86_cmpsd: CMPS(d, 4); break;
2215 #           undef CMPS
2216
2217 #           define MOVS(suffix, len) {                                                                                         \
2218                 ROSE_ASSERT(operands.size() == 0);                                                                             \
2219                 ROSE_ASSERT(insn->get_addressSize() == x86_insnsize_32);                                                       \
2220                 policy.writeMemory(x86_segreg_es,                                                                              \
2221                                    policy.readGPR(x86_gpr_di),                                                                 \
2222                                    STRINGOP_LOAD_SI(len, policy.true_()),                                                      \
2223                                    policy.true_());                                                                            \
2224                 policy.writeGPR(x86_gpr_si,                                                                                    \
2225                                 policy.add(policy.readGPR(x86_gpr_si),                                                         \
2226                                            policy.ite(policy.readFlag(x86_flag_df), number<32>(-(len)), number<32>(len))));    \
2227                 policy.writeGPR(x86_gpr_di,                                                                                    \
2228                                 policy.add(policy.readGPR(x86_gpr_di),                                                         \
2229                                            policy.ite(policy.readFlag(x86_flag_df), number<32>(-(len)), number<32>(len))));    \
2230             }
2231             case x86_movsb: MOVS(b, 1); break;
2232             case x86_movsw: MOVS(w, 2); break;
2233             case x86_movsd: MOVS(d, 4); break;
2234 #           undef MOVS
2235
2236 #           define REP_MOVS(suffix, len) {                                                                                     \
2237                 ROSE_ASSERT(operands.size() == 0);                                                                             \
2238                 ROSE_ASSERT(insn->get_addressSize() == x86_insnsize_32);                                                       \
2239                 Word(1) ecxNotZero = stringop_setup_loop();                                                                    \
2240                 policy.writeMemory(x86_segreg_es, policy.readGPR(x86_gpr_di), STRINGOP_LOAD_SI(len, ecxNotZero), ecxNotZero);  \
2241                 policy.writeGPR(x86_gpr_si,                                                                                    \
2242                                 policy.add(policy.readGPR(x86_gpr_si),                                                         \
2243                                            policy.ite(ecxNotZero,                                                              \
2244                                                       policy.ite(policy.readFlag(x86_flag_df),                                 \
2245                                                                  number<32>(-(len)),                                           \
2246                                                                  number<32>(len)),                                             \
2247                                                       number<32>(0))));                                                        \
2248                 policy.writeGPR(x86_gpr_di,                                                                                    \
2249                                 policy.add(policy.readGPR(x86_gpr_di),                                                         \
2250                                            policy.ite(ecxNotZero,                                                              \
2251                                                       policy.ite(policy.readFlag(x86_flag_df),                                 \
2252                                                                  number<32>(-(len)),                                           \
2253                                                                  number<32>(len)),                                             \
2254                                                       number<32>(0))));                                                        \
2255                 policy.writeIP(policy.ite(ecxNotZero, /* If true, repeat this instruction, otherwise go to the next one */     \
2256                                           number<32>((uint32_t)(insn->get_address())),                                         \
2257                                           policy.readIP()));                                                                   \
2258             }
2259             case x86_rep_movsb: REP_MOVS(b, 1); break;
2260             case x86_rep_movsw: REP_MOVS(w, 2); break;
2261             case x86_rep_movsd: REP_MOVS(d, 4); break;
2262 #           undef MOVS
2263
2264             case x86_stosb: {
2265                 stos_semantics<1>(insn);
2266                 break;
2267             }
2268
2269             case x86_rep_stosb: {
2270                 rep_stos_semantics<1>(insn);
2271                 break;
2272             }
2273
2274             case x86_stosw: {
2275                 stos_semantics<2>(insn);
2276                 break;
2277             }
2278
2279             case x86_rep_stosw: {
2280                 rep_stos_semantics<2>(insn);
2281                 break;
2282             }
2283
2284             case x86_stosd: {
2285                 stos_semantics<4>(insn);
2286                 break;
2287             }
2288
2289             case x86_rep_stosd: {
2290                 rep_stos_semantics<4>(insn);
2291                 break;
2292             }
2293
2294 #           define LODS(suffix, len, regupdate) {                                                                              \
2295                 ROSE_ASSERT(operands.size() == 0);                                                                             \
2296                 ROSE_ASSERT(insn->get_addressSize() == x86_insnsize_32);                                                       \
2297                 regupdate(x86_gpr_ax, STRINGOP_LOAD_SI(len, policy.true_()));                                                  \
2298                 policy.writeGPR(x86_gpr_si,                                                                                    \
2299                                 policy.add(policy.readGPR(x86_gpr_si),                                                         \
2300                                            policy.ite(policy.readFlag(x86_flag_df), number<32>(-(len)), number<32>(len))));    \
2301             }
2302             case x86_lodsb: LODS(b, 1, updateGPRLowByte); break;
2303             case x86_lodsw: LODS(w, 2, updateGPRLowWord); break;
2304             case x86_lodsd: LODS(d, 4, policy.writeGPR);  break;
2305 #           undef LODS
2306
2307 #undef STRINGOP_LOAD_SI
2308 #undef STRINGOP_LOAD_DI
2309 #undef STRINGOP_UPDATE_CX
2310 #undef STRINGOP_LOOP_E
2311 #undef STRINGOP_LOOP_NE
2312
2313             case x86_hlt: {
2314                 ROSE_ASSERT(operands.size() == 0);
2315                 policy.hlt();
2316                 policy.writeIP(number<32>((uint32_t)(insn->get_address())));
2317                 break;
2318             }
2319
2320             case x86_rdtsc: {
2321                 ROSE_ASSERT(operands.size() == 0);
2322                 Word(64) tsc = policy.rdtsc();
2323                 policy.writeGPR(x86_gpr_ax, extract<0, 32>(tsc));
2324                 policy.writeGPR(x86_gpr_dx, extract<32, 64>(tsc));
2325                 break;
2326             }
2327
2328             case x86_int: {
2329                 ROSE_ASSERT(operands.size() == 1);
2330                 SgAsmByteValueExpression* bv = isSgAsmByteValueExpression(operands[0]);
2331                 ROSE_ASSERT(bv);
2332                 policy.interrupt(bv->get_value());
2333                 break;
2334             }
2335
2336                 /* This is a dummy version that should be replaced later FIXME */
2337             case x86_fnstcw: {
2338                 ROSE_ASSERT(operands.size() == 1);
2339                 write16(operands[0], number<16>(0x37f));
2340                 break;
2341             }
2342
2343             case x86_fldcw: {
2344                 ROSE_ASSERT(operands.size() == 1);
2345                 read16(operands[0]); /* To catch access control violations */
2346                 break;
2347             }
2348
2349             default: {
2350 #if 0
2351                 std::cerr <<"Bad instruction [0x" <<std::hex <<insn->get_address() <<": " <<unparseInstruction(insn) <<"]"
2352                           <<" (skipping semantic analysis)\n";
2353 #endif
2354                 break;
2355             }
2356         }
2357     }
2358
2359     void processInstruction(SgAsmx86Instruction* insn) {
2360         ROSE_ASSERT(insn);
2361         policy.startInstruction(insn);
2362         translate(insn);
2363         policy.finishInstruction(insn);
2364     }
2365
2366     /*
2367     void processBlock(const SgAsmStatementPtrList& stmts, size_t begin, size_t end) {
2368         if (begin == end) return;
2369         policy.startBlock(stmts[begin]->get_address());
2370         for (size_t i = begin; i < end; ++i) {
2371             processInstruction(isSgAsmx86Instruction(stmts[i]));
2372         }
2373         policy.finishBlock(stmts[begin]->get_address());
2374     }
2375     */
2376
2377     static bool isRepeatedStringOp(SgAsmx86Instruction* insn) {
2378         //SgAsmx86Instruction* insn = isSgAsmx86Instruction(s);
2379         if (!insn) return false;
2380         switch (insn->get_kind()) {
2381             case x86_repe_cmpsb: return true;
2382             case x86_repe_cmpsd: return true;
2383             case x86_repe_cmpsq: return true;
2384             case x86_repe_cmpsw: return true;
2385             case x86_repe_scasb: return true;
2386             case x86_repe_scasd: return true;
2387             case x86_repe_scasq: return true;
2388             case x86_repe_scasw: return true;
2389             case x86_rep_insb: return true;
2390             case x86_rep_insd: return true;
2391             case x86_rep_insw: return true;
2392             case x86_rep_lodsb: return true;
2393             case x86_rep_lodsd: return true;
2394             case x86_rep_lodsq: return true;
2395             case x86_rep_lodsw: return true;
2396             case x86_rep_movsb: return true;
2397             case x86_rep_movsd: return true;
2398             case x86_rep_movsq: return true;
2399             case x86_rep_movsw: return true;
2400             case x86_repne_cmpsb: return true;
2401             case x86_repne_cmpsd: return true;
2402             case x86_repne_cmpsq: return true;
2403             case x86_repne_cmpsw: return true;
2404             case x86_repne_scasb: return true;
2405             case x86_repne_scasd: return true;
2406             case x86_repne_scasq: return true;
2407             case x86_repne_scasw: return true;
2408             case x86_rep_outsb: return true;
2409             case x86_rep_outsd: return true;
2410             case x86_rep_outsw: return true;
2411             case x86_rep_stosb: return true;
2412             case x86_rep_stosd: return true;
2413             case x86_rep_stosq: return true;
2414             case x86_rep_stosw: return true;
2415             default: return false;
2416         }
2417     }
2418
2419     static bool isHltOrInt(SgAsmx86Instruction* insn) {
2420         //SgAsmx86Instruction* insn = isSgAsmx86Instruction(s);
2421         if (!insn) return false;
2422         switch (insn->get_kind()) {
2423             case x86_hlt: return true;
2424             case x86_int: return true;
2425             default: return false;
2426         }
2427     }
2428
2429 #if 0
2430     void processBlock(SgAsmBlock* b) {
2431         const SgAsmStatementPtrList& stmts = b->get_statementList();
2432         if (stmts.empty()) return;
2433         if (!isSgAsmInstruction(stmts[0])) return; /* A block containing functions or something */
2434         size_t i = 0;
2435         while (i < stmts.size()) {
2436             size_t oldI = i;
2437             /* Advance until either i points to a repeated string op or it is just after a hlt or int */
2438             while (i < stmts.size() && !isRepeatedStringOp(stmts[i]) && (i == oldI || !isHltOrInt(stmts[i - 1]))) ++i;
2439             processBlock(stmts, oldI, i);
2440             if (i >= stmts.size()) break;
2441             if (isRepeatedStringOp(stmts[i])) {
2442                 processBlock(stmts, i, i + 1);
2443                 ++i;
2444             }
2445             ROSE_ASSERT(i != oldI);
2446         }
2447     }
2448 #endif
2449
2450 };
2451
2452 #undef Word
2453
2454 #endif // ROSE_X86INSTRUCTIONSEMANTICS_H