1 //: instructions that (immediately) contain an argument to act with
  2 
  3 :(scenario add_imm32_to_r32)
  4 % Reg[3].i = 1;
  5 # op  ModRM   SIB   displacement  immediate
  6   81  c3                          0a 0b 0c 0d  # add 0x0d0c0b0a to EBX (reg 3)
  7 +run: combine imm32 0x0d0c0b0a with effective address
  8 +run: effective address is reg 3
  9 +run: subop add
 10 +run: storing 0x0d0c0b0b
 11 
 12 :(before "End Single-Byte Opcodes")
 13 case 0x81: {  // combine imm32 with r/m32
 14   uint8_t modrm = next();
 15   int32_t arg2 = imm32();
 16   trace(2, "run") << "combine imm32 0x" << HEXWORD << arg2 << " with effective address" << end();
 17   int32_t* arg1 = effective_address(modrm);
 18   uint8_t subop = (modrm>>3)&0x7;  // middle 3 'reg opcode' bits
 19   switch (subop) {
 20   case 0:
 21   ¦ trace(2, "run") << "subop add" << end();
 22   ¦ BINARY_ARITHMETIC_OP(+, *arg1, arg2);
 23   ¦ break;
 24   // End Op 81 Subops
 25   default:
 26   ¦ cerr << "unrecognized sub-opcode after 81: " << NUM(subop) << '\n';
 27   ¦ exit(1);
 28   }
 29   break;
 30 }
 31 
 32 //:
 33 
 34 :(scenario add_imm32_to_mem_at_r32)
 35 % Reg[3].i = 0x60;
 36 % Mem.at(0x60) = 1;
 37 # op  ModR/M  SIB   displacement  immediate
 38   81  03                          0a 0b 0c 0d  # add 0x0d0c0b0a to *EBX (reg 3)
 39 +run: combine imm32 0x0d0c0b0a with effective address
 40 +run: effective address is mem at address 0x60 (reg 3)
 41 +run: subop add
 42 +run: storing 0x0d0c0b0b
 43 
 44 //:: subtract
 45 
 46 :(scenario subtract_imm32_from_eax)
 47 % Reg[EAX].i = 0x0d0c0baa;
 48 # op  ModR/M  SIB   displacement  immediate
 49   2d                              0a 0b 0c 0d  # subtract 0x0d0c0b0a from EAX (reg 0)
 50 +run: subtract imm32 0x0d0c0b0a from reg EAX
 51 +run: storing 0x000000a0
 52 
 53 :(before "End Single-Byte Opcodes")
 54 case 0x2d: {  // subtract imm32 from EAX
 55   int32_t arg2 = imm32();
 56   trace(2, "run") << "subtract imm32 0x" << HEXWORD << arg2 << " from reg EAX" << end();
 57   BINARY_ARITHMETIC_OP(-, Reg[EAX].i, arg2);
 58   break;
 59 }
 60 
 61 //:
 62 
 63 :(scenario subtract_imm32_from_mem_at_r32)
 64 % Reg[3].i = 0x60;
 65 % Mem.at(0x60) = 10;
 66 # op  ModRM   SIB   displacement  immediate
 67   81  2b                          01 00 00 00  # subtract 1 from *EBX (reg 3)
 68 +run: combine imm32 0x00000001 with effective address
 69 +run: effective address is mem at address 0x60 (reg 3)
 70 +run: subop subtract
 71 +run: storing 0x00000009
 72 
 73 //:
 74 
 75 :(scenario subtract_imm32_from_r32)
 76 % Reg[3].i = 10;
 77 # op  ModRM   SIB   displacement  immediate
 78   81  eb                          01 00 00 00  # subtract 1 from EBX (reg 3)
 79 +run: combine imm32 0x00000001 with effective address
 80 +run: effective address is reg 3
 81 +run: subop subtract
 82 +run: storing 0x00000009
 83 
 84 :(before "End Op 81 Subops")
 85 case 5: {
 86   trace(2, "run") << "subop subtract" << end();
 87   BINARY_ARITHMETIC_OP(-, *arg1, arg2);
 88   break;
 89 }
 90 
 91 //:: and
 92 
 93 :(scenario and_imm32_with_eax)
 94 % Reg[EAX].i = 0xff;
 95 # op  ModR/M  SIB   displacement  immediate
 96   25                              0a 0b 0c 0d  # and 0x0d0c0b0a with EAX (reg 0)
 97 +run: and imm32 0x0d0c0b0a with reg EAX
 98 +run: storing 0x0000000a
 99 
100 :(before "End Single-Byte Opcodes")
101 case 0x25: {  // and imm32 with EAX
102   int32_t arg2 = imm32();
103   trace(2, "run") << "and imm32 0x" << HEXWORD << arg2 << " with reg EAX" << end();
104   BINARY_BITWISE_OP(&, Reg[EAX].i, arg2);
105   break;
106 }
107 
108 //:
109 
110 :(scenario and_imm32_with_mem_at_r32)
111 % Reg[3].i = 0x60;
112 % Mem.at(0x60) = 0xff;
113 # op  ModRM   SIB   displacement  immediate
114   81  23                          0a 0b 0c 0d  # and 0x0d0c0b0a with *EBX (reg 3)
115 +run: combine imm32 0x0d0c0b0a with effective address
116 +run: effective address is mem at address 0x60 (reg 3)
117 +run: subop and
118 +run: storing 0x0000000a
119 
120 //:
121 
122 :(scenario and_imm32_with_r32)
123 % Reg[3].i = 0xff;
124 # op  ModRM   SIB   displacement  immediate
125   81  e3                          0a 0b 0c 0d  # and 0x0d0c0b0a with EBX (reg 3)
126 +run: combine imm32 0x0d0c0b0a with effective address
127 +run: effective address is reg 3
128 +run: subop and
129 +run: storing 0x0000000a
130 
131 :(before "End Op 81 Subops")
132 case 4: {
133   trace(2, "run") << "subop and" << end();
134   BINARY_BITWISE_OP(&, *arg1, arg2);
135   break;
136 }
137 
138 //:: or
139 
140 :(scenario or_imm32_with_eax)
141 % Reg[EAX].i = 0xd0c0b0a0;
142 # op  ModR/M  SIB   displacement  immediate
143   0d                              0a 0b 0c 0d  # or 0x0d0c0b0a with EAX (reg 0)
144 +run: or imm32 0x0d0c0b0a with reg EAX
145 +run: storing 0xddccbbaa
146 
147 :(before "End Single-Byte Opcodes")
148 case 0x0d: {  // or imm32 with EAX
149   int32_t arg2 = imm32();
150   trace(2, "run") << "or imm32 0x" << HEXWORD << arg2 << " with reg EAX" << end();
151   BINARY_BITWISE_OP(|, Reg[EAX].i, arg2);
152   break;
153 }
154 
155 //:
156 
157 :(scenario or_imm32_with_mem_at_r32)
158 % Reg[3].i = 0x60;
159 % Mem.at(0x60) = 0xa0;
160 % Mem.at(0x61) = 0xb0;
161 % Mem.at(0x62) = 0xc0;
162 % Mem.at(0x63) = 0xd0;
163 # op  ModRM   SIB   displacement  immediate
164   81  0b                          0a 0b 0c 0d  # or 0x0d0c0b0a with *EBX (reg 3)
165 +run: combine imm32 0x0d0c0b0a with effective address
166 +run: effective address is mem at address 0x60 (reg 3)
167 +run: subop or
168 +run: storing 0xddccbbaa
169 
170 //:
171 
172 :(scenario or_imm32_with_r32)
173 % Reg[3].i = 0xd0c0b0a0;
174 # op  ModRM   SIB   displacement  immediate
175   81  cb                          0a 0b 0c 0d  # or 0x0d0c0b0a with EBX (reg 3)
176 +run: combine imm32 0x0d0c0b0a with effective address
177 +run: effective address is reg 3
178 +run: subop or
179 +run: storing 0xddccbbaa
180 
181 :(before "End Op 81 Subops")
182 case 1: {
183   trace(2, "run") << "subop or" << end();
184   BINARY_BITWISE_OP(|, *arg1, arg2);
185   break;
186 }
187 
188 //:: xor
189 
190 :(scenario xor_imm32_with_eax)
191 % Reg[EAX].i = 0xddccb0a0;
192 # op  ModR/M  SIB   displacement  immediate
193   35                              0a 0b 0c 0d  # xor 0x0d0c0b0a with EAX (reg 0)
194 +run: xor imm32 0x0d0c0b0a with reg EAX
195 +run: storing 0xd0c0bbaa
196 
197 :(before "End Single-Byte Opcodes")
198 case 0x35: {  // xor imm32 with EAX
199   int32_t arg2 = imm32();
200   trace(2, "run") << "xor imm32 0x" << HEXWORD << arg2 << " with reg EAX" << end();
201   BINARY_BITWISE_OP(^, Reg[EAX].i, arg2);
202   break;
203 }
204 
205 //:
206 
207 :(scenario xor_imm32_with_mem_at_r32)
208 % Reg[3].i = 0x60;
209 % Mem.at(0x60) = 0xa0;
210 % Mem.at(0x61) = 0xb0;
211 % Mem.at(0x62) = 0xc0;
212 % Mem.at(0x63) = 0xd0;
213 # op  ModRM   SIB   displacement  immediate
214   81  33                          0a 0b 0c 0d  # xor 0x0d0c0b0a with *EBX (reg 3)
215 +run: combine imm32 0x0d0c0b0a with effective address
216 +run: effective address is mem at address 0x60 (reg 3)
217 +run: subop xor
218 +run: storing 0xddccbbaa
219 
220 //:
221 
222 :(scenario xor_imm32_with_r32)
223 % Reg[3].i = 0xd0c0b0a0;
224 # op  ModRM   SIB   displacement  immediate
225   81  f3                          0a 0b 0c 0d  # xor 0x0d0c0b0a with EBX (reg 3)
226 +run: combine imm32 0x0d0c0b0a with effective address
227 +run: effective address is reg 3
228 +run: subop xor
229 +run: storing 0xddccbbaa
230 
231 :(before "End Op 81 Subops")
232 case 6: {
233   trace(2, "run") << "subop xor" << end();
234   BINARY_BITWISE_OP(^, *arg1, arg2);
235   break;
236 }