├── check.h ├── LICENSE ├── readme.md ├── lra86.cpp └── file.asm /check.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2021, Alexey Frunze 3 | 2-clause BSD license. 4 | */ 5 | #ifndef CHECK_H_ 6 | #define CHECK_H_ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | struct LogAndAbort 13 | { 14 | LogAndAbort() = delete; 15 | LogAndAbort(const char* file, int line) : file_(file), line_(line) {} 16 | ~LogAndAbort() 17 | { 18 | std::cerr << "\n" << oss_.str() << "\n@ " << file_ << ":" << line_ << "\n"; 19 | exit(EXIT_FAILURE); 20 | } 21 | const char* file_; 22 | int line_; 23 | std::ostringstream oss_; 24 | }; 25 | 26 | // This is like assert(), except you may output additional information 27 | // when the condition E is false, e.g. 28 | // CHECK(0) << 0 << " is false!"; 29 | // will output: 30 | // Check failed: 0 31 | // 0 is false! 32 | // @ lra86.cpp:1914 33 | 34 | #define CHECK(E) \ 35 | if (!(E)) LogAndAbort(__FILE__, __LINE__).oss_ << "Check failed: " #E << "\n" 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2021, Alexey Frunze 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Local Register Allocator for 8086 2 | 3 | ## Table of contents 4 | 5 | [What is this?](#what-is-this) 6 | 7 | [Motivation](#motivation) 8 | 9 | [Scope](#scope) 10 | 11 | [Basic algorithm](#basic-algorithm) 12 | 13 | [8086-specific approach](#8086-specific-approach) 14 | 15 | [Resources](#resources) 16 | 17 | ## What is this? 18 | 19 | This is an implementation of a greedy bottom-up local register allocator for 20 | the intel 8086 CPU. It may be used as part of a simple compiler. In particular, 21 | it can be used in a C compiler whose `int` is 16-bit and `char` is 8-bit. 22 | 23 | To make things interesting and interactive it comes with a code generator 24 | capable of generating 8086 assembly code (compilable into DOS .COM programs) 25 | from trees representing expressions with 16-bit integer ALU operations, 26 | constants and memory loads and stores. A few extra instructions generated by 27 | the code check the results of expression evaluation in the output register and 28 | the output memory locations, if any. 29 | 30 | Thus you can actually execute the generated code and tweak things around to see 31 | how your changes affect code generation. 32 | 33 | Sample assembly output from the register allocator/code generator: 34 | 35 | ; 7 (vr4) 36 | ; mul (vr5) 37 | ; 5 (vr3) 38 | ; add (vr6) 39 | ; 3 (vr1) 40 | ; mul (vr2) 41 | ; 2 (vr0) 42 | ; ---- 43 | ; Regs needed (approximately): 3 44 | ; -------- 45 | ; ; vr0 46 | mov ax, 2 ; vr0 47 | mov cx, 3 ; vr1 48 | mul cx ; vr2 49 | mov cx, 5 ; vr3 50 | mov dx, 7 ; vr4 51 | xchg ax, cx ; vr5 52 | mul dx ; vr5 53 | add cx, ax ; vr6 54 | ; ; vr6 55 | cmp cx, 41 ; vr6 56 | jne failure ; vr6 57 | 58 | N.B. This register allocator will not allocate registers perfectly in all 59 | circumstances. It will occasionally generate unnecessary register moves and 60 | exchanges. Bear in mind, optimal register allocation is an NP-complete problem. 61 | 62 | ## Motivation 63 | 64 | The intel 8086 architecture has a number of instructions with fixed input 65 | and/or output registers and it's not entirely trivial to connect the ins and 66 | outs of these instructions. There's obviously a long history of implementing 67 | compilers for this and similar architectures, but it's a bit odd that it's 68 | hard to find a conceptually simple algorithm like this. The "Dragon" book and 69 | many other sources either consider architectures without instructions with such 70 | fixed register operands or solve the problem using graph coloring, which for 71 | certain reasons may be impractical. 72 | 73 | The intel 8086 architecture survives to this day in the modern intel Pentium 74 | CPUs that are compatible descendants of the old 8086 and with it survive some 75 | of the instructions with fixed in/out register operands. So, the problem 76 | persists to this day, although there are fewer limitations to deal with when 77 | using newer 32-bit and 64-bit x86 instructions and registers today. 78 | 79 | 8086 registers by special uses in expression evaluation (pardon the mixture of 80 | C and assembly operators, instructions and syntax and ASCII art): 81 | 82 | +-- can be freely used in most ALU instructions as src/dst 83 | | +-- can be used as address to access memory 84 | | | +-- has individual 8-bit subregisters 85 | | | | +-- can be sign-extended with cbw 86 | | | | | +-- can be shifted 87 | | | | | | +-- can be shift count 88 | v v v v v v 89 | +-<&|^~ [r] 8bit cbw < 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "check.h" 12 | 13 | #define OCO << ", " << 14 | 15 | // Lower this from 6 to 4 to see occasional spills. 16 | #define USE_REGS 6 17 | 18 | enum HReg : int 19 | { 20 | // Specific regs begin 21 | HReg0, HRegAX = HReg0, 22 | HReg1, HRegCX = HReg1, 23 | HReg2, HRegDX = HReg2, 24 | HReg3, HRegBX = HReg3, 25 | #if USE_REGS >= 5 26 | HReg4, HRegSI = HReg4, 27 | #endif 28 | #if USE_REGS >= 6 29 | HReg5, HRegDI = HReg5, 30 | #endif 31 | // Specific regs end 32 | HRegCnt, 33 | // Constants representing multiple-choice desired regs: 34 | HRegAny = HRegCnt, // unspecified, any reg at all is OK 35 | HRegNotCX, // prefer regs other than cx (for shifts) 36 | HRegNotDXNotAX, // prefer regs other than dx and ax (for (i)div) 37 | HRegNotDXNotCXNotAX, // prefer regs other than dx, cx and ax 38 | HRegByte, // prefer those with individual byte components: ax, cx, dx, bx 39 | HRegByteNotCX, // prefer those with individual byte components except cx: ax, dx, bx 40 | HRegAddr, // prefer those that can be a memory operand: bx, si, di 41 | }; 42 | 43 | struct Node; 44 | // The only global variables of the allocator. 45 | Node* NodeFromHReg[HRegCnt]; 46 | Node* CurrentOutputNode; 47 | 48 | // For HRegAny, HRegByte 49 | static const HReg alloc_order_normal[HRegCnt] = 50 | { 51 | HRegAX, HRegCX, HRegDX, HRegBX, 52 | #if USE_REGS >= 5 53 | HRegSI, 54 | #endif 55 | #if USE_REGS >= 6 56 | HRegDI, 57 | #endif 58 | }; 59 | 60 | // For HRegNotCX 61 | static const HReg alloc_order_not_cx[HRegCnt] = 62 | { 63 | HRegAX, HRegDX, HRegBX, 64 | #if USE_REGS >= 5 65 | HRegSI, 66 | #endif 67 | #if USE_REGS >= 6 68 | HRegDI, 69 | #endif 70 | HRegCX, 71 | }; 72 | 73 | // For HRegNotDXNotAX 74 | static const HReg alloc_order_not_dx_not_ax[HRegCnt] = 75 | { 76 | HRegCX, HRegBX, 77 | #if USE_REGS >= 5 78 | HRegSI, 79 | #endif 80 | #if USE_REGS >= 6 81 | HRegDI, 82 | #endif 83 | HRegAX, HRegDX, 84 | }; 85 | 86 | // For HRegNotDXNotCXNotAX 87 | static const HReg alloc_order_not_dx_not_cx_not_ax[HRegCnt] = 88 | { 89 | HRegBX, 90 | #if USE_REGS >= 5 91 | HRegSI, 92 | #endif 93 | #if USE_REGS >= 6 94 | HRegDI, 95 | #endif 96 | HRegAX, HRegCX, HRegDX, 97 | }; 98 | 99 | // For HRegByteNotCX 100 | static const HReg alloc_order_byte_not_cx[HRegCnt] = 101 | { 102 | HRegAX, HRegDX, HRegBX, HRegCX, 103 | #if USE_REGS >= 5 104 | HRegSI, 105 | #endif 106 | #if USE_REGS >= 6 107 | HRegDI, 108 | #endif 109 | }; 110 | 111 | // For HRegAddr 112 | static const HReg alloc_order_addr[HRegCnt] = 113 | { 114 | HRegBX, 115 | #if USE_REGS >= 5 116 | HRegSI, 117 | #endif 118 | #if USE_REGS >= 6 119 | HRegDI, 120 | #endif 121 | HRegAX, HRegCX, HRegDX, 122 | }; 123 | 124 | const HReg* RegsOrderedForAllocSearch(HReg desired) 125 | { 126 | const HReg* ordered_regs; 127 | switch (desired) 128 | { 129 | case HRegNotCX: 130 | ordered_regs = alloc_order_not_cx; 131 | break; 132 | case HRegNotDXNotAX: 133 | ordered_regs = alloc_order_not_dx_not_ax; 134 | break; 135 | case HRegNotDXNotCXNotAX: 136 | ordered_regs = alloc_order_not_dx_not_cx_not_ax; 137 | break; 138 | case HRegByteNotCX: 139 | ordered_regs = alloc_order_byte_not_cx; 140 | break; 141 | case HRegAddr: 142 | ordered_regs = alloc_order_addr; 143 | break; 144 | default: 145 | ordered_regs = alloc_order_normal; 146 | } 147 | return ordered_regs; 148 | } 149 | 150 | bool SpecificHReg(HReg hr) 151 | { 152 | return (hr >= HReg0) && (hr < HRegCnt); 153 | } 154 | 155 | // Whether the register has 8-bit subregisters. 156 | bool ByteHReg(HReg hr) 157 | { 158 | switch(hr) 159 | { 160 | case HRegAX: case HRegCX: case HRegDX: case HRegBX: 161 | return true; 162 | default: 163 | return false; 164 | } 165 | } 166 | 167 | // Whether the register can be used as a memory address for a load or store. 168 | bool AddrHReg(HReg hr) 169 | { 170 | switch(hr) 171 | { 172 | case HRegBX: 173 | #if USE_REGS >= 5 174 | case HRegSI: 175 | #endif 176 | #if USE_REGS >= 6 177 | case HRegDI: 178 | #endif 179 | return true; 180 | default: 181 | return false; 182 | } 183 | } 184 | 185 | std::ostream &operator<<(std::ostream &os, HReg hr) 186 | { 187 | switch(hr) 188 | { 189 | case HRegAX: 190 | return os << "ax"; 191 | case HRegCX: 192 | return os << "cx"; 193 | case HRegDX: 194 | return os << "dx"; 195 | case HRegBX: 196 | return os << "bx"; 197 | #if USE_REGS >= 5 198 | case HRegSI: 199 | return os << "si"; 200 | #endif 201 | #if USE_REGS >= 6 202 | case HRegDI: 203 | return os << "di"; 204 | #endif 205 | default: 206 | CHECK(0); 207 | return os << "r?"; 208 | } 209 | } 210 | 211 | const char* HRegHi(HReg hr) 212 | { 213 | switch(hr) 214 | { 215 | case HRegAX: 216 | return "ah"; 217 | case HRegCX: 218 | return "ch"; 219 | case HRegDX: 220 | return "dh"; 221 | case HRegBX: 222 | return "bh"; 223 | default: 224 | CHECK(0); 225 | return "?h"; 226 | } 227 | } 228 | 229 | const char* HRegLo(HReg hr) 230 | { 231 | switch(hr) 232 | { 233 | case HRegAX: 234 | return "al"; 235 | case HRegCX: 236 | return "cl"; 237 | case HRegDX: 238 | return "dl"; 239 | case HRegBX: 240 | return "bl"; 241 | default: 242 | CHECK(0); 243 | return "?l"; 244 | } 245 | } 246 | 247 | struct Node 248 | { 249 | Node() : Node(nullptr, nullptr) {} 250 | Node(Node* left) : Node(left, nullptr) {} 251 | Node(Node* left, Node* right) : 252 | child_ { left, right }, 253 | first_(-1), 254 | vr_(-1), 255 | user_vr_(-1), 256 | loc_(LocNowhere), 257 | loc_hr_(HRegAny), 258 | hr_ { HRegAny, HRegAny, HRegAny }, 259 | val_(0) {} 260 | 261 | virtual ~Node() { delete child_[0]; delete child_[1]; } 262 | 263 | virtual bool IsSymmetric() const { return false; } // some override 264 | virtual bool LeftFirst() const { return false; } 265 | virtual bool RightFirst() const { return false; } 266 | virtual bool PrefersRight() const { return false; } // shifts override 267 | virtual int SameRegCntAddend() const { return 1; } 268 | virtual int MinRegCnt() const { return 0; } // (i)div, (i)rem override 269 | virtual std::string PrintOperation() const = 0; // all override 270 | virtual std::string PrintInstruction() const // (i)rem, loads, stores override 271 | { 272 | return PrintOperation(); 273 | } 274 | 275 | virtual int SelectFirst(); // args, calls override 276 | void AssignVReg(int vr) { vr_ = vr; } 277 | void SetUserVReg(int user_vr) { user_vr_ = user_vr; } 278 | void AssignVRegs(int* p_vr_cnt = nullptr); 279 | 280 | virtual void Eval() = 0; // all override 281 | 282 | virtual void GenMemValue() {} // loads override 283 | void GenMemValues(); 284 | 285 | virtual void GenMemCheck() {} // stores override 286 | void GenMemChecks(); 287 | 288 | void GenRegCheck(); 289 | 290 | void SetLocNowhere() { loc_ = LocNowhere; loc_hr_ = HRegAny; } 291 | void SetLocReg(HReg hr) 292 | { 293 | CHECK(SpecificHReg(hr)); 294 | loc_ = LocReg; loc_hr_ = hr; 295 | } 296 | void SetLocSpilled() { loc_ = LocSpilled; loc_hr_ = HRegAny; } 297 | bool IsNowhere() const { return loc_ == LocNowhere; } 298 | bool InReg() const { return loc_ == LocReg; } 299 | bool IsSpilled() const { return loc_ == LocSpilled; } 300 | 301 | virtual void AllocHRegs(HReg desired = HRegAny); // some override 302 | 303 | void PrintExprTree(std::ostream& os, int level = 0); 304 | void PrintInstructions(std::ostream& os); 305 | 306 | Node* child_[2]; 307 | int first_; // which child_[] to handle first to minimize register usage 308 | 309 | int vr_; // "virtual" register holding the output value from this node 310 | int user_vr_; // vr_ of the parent node that uses this node as input 311 | 312 | enum : int { LocNowhere, LocReg, LocSpilled } loc_; // location of vr_ 313 | HReg loc_hr_; // Register for LocReg 314 | 315 | HReg hr_[3]; // AllocHRegs() sets these 316 | 317 | unsigned short val_; // Expected value in test 318 | 319 | std::vector instructions; // Generated instructions 320 | }; 321 | 322 | // Recursively selects which node to generate code for first 323 | // (sets this->first_ to 0 (left's 1st), 1 (right's 1st) or 324 | // -1 (either can be 1st)), returns the number of registers 325 | // needed for the node. 326 | // This number is known as Ershov number. 327 | // See also Strahler number and Sethi-Ullman algorithm. 328 | int Node::SelectFirst() 329 | { 330 | first_ = 0; 331 | if (!child_[0]) 332 | { 333 | // Leaf. 334 | return 1; 335 | } 336 | int nl = child_[0]->SelectFirst(); 337 | if (!child_[1]) 338 | { 339 | // Unary. 340 | return nl; 341 | } 342 | // Binary. 343 | int nr = child_[1]->SelectFirst(); 344 | if (RightFirst()) 345 | first_ = 1; 346 | else if (!LeftFirst()) 347 | first_ = (nl == nr) ? -1 : ((nl > nr) ? 0 : 1); 348 | // else `first_ = 0;` by default above. 349 | int lrmax = (nl == nr) ? (nl + SameRegCntAddend()) : ((nl > nr) ? nl : nr); 350 | // (i)div uses ax, another register for the divisor and also clobbers dx 351 | // (not just by way of producing a remainder in dx, but also by requiring 352 | // the dividend zero- or sign-extended from ax into dx before (i)div, 353 | // which bars any input (dividend or divisor) from being in dx). 354 | // That is, (i)div needs at least 3 registers to compute a quotient or 355 | // remainder regardless of how few registers are needed to compute its 356 | // dividend and divisor. Otherwise (i)div needs the same number of 357 | // registers as e.g. add, sub, etc. 358 | int rmin = MinRegCnt(); 359 | return (lrmax < rmin) ? rmin : lrmax; 360 | } 361 | 362 | // Recursively assigns virtual register numbers to this->vr_ 363 | // in every node (from the leaves towards the root). 364 | // this->user_vr_ is assigned parent node's vr_. 365 | void Node::AssignVRegs(int* p_vr_cnt) 366 | { 367 | int vr_cnt = 0; 368 | p_vr_cnt = p_vr_cnt ? p_vr_cnt : &vr_cnt; 369 | // Every node gets its own output VReg and 370 | // that's also the order of evaluation / code generation. 371 | // Each VReg is used as an input only once. 372 | if (child_[1]) 373 | { 374 | // Generally prefer recursing left if all else is equal. 375 | // For shifts prefer recursing right if all else is equal. 376 | int first_idx = (PrefersRight() 377 | ? (first_ == 0) 378 | : (first_ <= 0)) ? 0 : 1; 379 | 380 | child_[first_idx]->AssignVRegs(p_vr_cnt); 381 | child_[!first_idx]->AssignVRegs(p_vr_cnt); 382 | // Record where (at which node) inputs are used/consumed. 383 | child_[first_idx]->SetUserVReg(*p_vr_cnt); 384 | child_[!first_idx]->SetUserVReg(*p_vr_cnt); 385 | } 386 | else if (child_[0]) 387 | { 388 | child_[0]->AssignVRegs(p_vr_cnt); 389 | // Record where (at which node) input is used/consumed. 390 | child_[0]->SetUserVReg(*p_vr_cnt); 391 | } 392 | AssignVReg((*p_vr_cnt)++); 393 | // Unknown location for this VReg for now. 394 | // Also don't know yet if this output is going to be used/consumed. 395 | // That is, root's user_vr_ will remain -1. 396 | } 397 | 398 | // Free the given hardware register with or without spilling. 399 | void Free(HReg hr, bool spill = false) 400 | { 401 | CHECK(SpecificHReg(hr)); 402 | Node* n = NodeFromHReg[hr]; 403 | CHECK(n); 404 | if (spill) 405 | { 406 | // N.B. It should be safe to push/pop instead of storing/loading at 407 | // bp+offset. 408 | // Reasons: 409 | // - furthest used VReg won't be needed earlier and won't have a chance to 410 | // be mistakenly used earlier 411 | // - there will not be 2 VRegs spilled that are used by the same 412 | // node/instruction because if one VReg has been spilled, the other VReg 413 | // at that node/instruction is still being computed in the sibling branch; 414 | // this is true for unary and binary operators. 415 | n->SetLocSpilled(); 416 | 417 | std::ostringstream oss; 418 | oss << "push " << hr; 419 | CurrentOutputNode->instructions.push_back(oss.str()); 420 | } 421 | else 422 | { 423 | n->SetLocNowhere(); 424 | } 425 | NodeFromHReg[hr] = nullptr; 426 | } 427 | 428 | // Allocate a hardware register to hold the result of the given node. 429 | // May be different from the desired register. 430 | HReg Allocate(Node* n, HReg desired = HRegAny) 431 | { 432 | CHECK(n); 433 | int furthest = -1; 434 | bool spill_needed = true; 435 | #if 01 436 | for (int hr = 0; hr < HRegCnt; hr++) 437 | CHECK(NodeFromHReg[hr] != n); 438 | #endif 439 | if (SpecificHReg(desired) && !NodeFromHReg[desired]) 440 | { 441 | furthest = desired; 442 | spill_needed = false; 443 | } 444 | else 445 | { 446 | const HReg* order = RegsOrderedForAllocSearch(desired); 447 | for (int i = 0; i < HRegCnt; i++) 448 | { 449 | HReg hr = order[i]; 450 | if (!NodeFromHReg[hr]) 451 | { 452 | furthest = hr; 453 | spill_needed = false; 454 | break; 455 | } 456 | if (furthest == -1) 457 | furthest = hr; 458 | CHECK(NodeFromHReg[furthest]->user_vr_ != -1); 459 | CHECK(NodeFromHReg[hr]->user_vr_ != -1); 460 | if (NodeFromHReg[furthest]->user_vr_ < NodeFromHReg[hr]->user_vr_) 461 | furthest = hr; 462 | } 463 | } 464 | CHECK(furthest != -1); 465 | HReg hr = HReg(furthest); 466 | if (spill_needed) 467 | Free(hr, /*spill*/true); 468 | n->SetLocReg(hr); 469 | NodeFromHReg[hr] = n; 470 | CHECK(SpecificHReg(hr)); 471 | return hr; 472 | } 473 | 474 | // Make sure the value of the given node is in a hardware register. 475 | // May be different from the desired register. 476 | HReg Ensure(Node* n, HReg desired = HRegAny) 477 | { 478 | CHECK(n); 479 | HReg hr = HRegAny; 480 | if (n->IsNowhere()) 481 | { 482 | hr = Allocate(n, desired); 483 | } 484 | else if (n->InReg()) 485 | { 486 | hr = n->loc_hr_; 487 | } 488 | else 489 | { 490 | CHECK(n->IsSpilled()); 491 | hr = Allocate(n, desired); 492 | // N.B. It should be safe to push/pop instead of storing/loading at 493 | // bp+offset. 494 | // Reasons: 495 | // - furthest used VReg won't be needed earlier and won't have a chance to 496 | // be mistakenly used earlier 497 | // - there will not be 2 VRegs spilled that are used by the same 498 | // node/instruction because if one VReg has been spilled, the other VReg 499 | // at that node/instruction is still being computed in the sibling branch; 500 | // this is true for unary and binary operators. 501 | 502 | std::ostringstream oss; 503 | oss << "pop " << hr; 504 | CurrentOutputNode->instructions.push_back(oss.str()); 505 | } 506 | CHECK(SpecificHReg(hr)); 507 | return hr; 508 | } 509 | 510 | // When something isn't in the desired HReg, 511 | // move there or exchange. 512 | void MoveToDesired(HReg hr_desired, HReg hr_actual) 513 | { 514 | CHECK(SpecificHReg(hr_desired)); 515 | CHECK(SpecificHReg(hr_actual)); 516 | CHECK(hr_desired != hr_actual); 517 | Node* n_desired = NodeFromHReg[hr_desired]; 518 | Node* n_actual = NodeFromHReg[hr_actual]; 519 | CHECK(n_actual); 520 | 521 | std::ostringstream oss; 522 | 523 | if (!n_desired) 524 | { 525 | Free(hr_actual); 526 | HReg hr = Allocate(n_actual, hr_desired); 527 | CHECK(hr == hr_desired); 528 | oss << "mov " << hr_desired OCO hr_actual; 529 | } 530 | else 531 | { 532 | NodeFromHReg[hr_desired] = n_actual; 533 | NodeFromHReg[hr_actual] = n_desired; 534 | n_desired->SetLocReg(hr_actual); 535 | n_actual->SetLocReg(hr_desired); 536 | oss << "xchg " << hr_desired OCO hr_actual; 537 | } 538 | 539 | CurrentOutputNode->instructions.push_back(oss.str()); 540 | } 541 | 542 | // Commonly used helper for Node::AllocHRegs(). 543 | void RecurseToAndEnsureIns(Node* n, const HReg desired[/*1 or 2*/]) 544 | { 545 | CHECK(n->child_[0]); 546 | bool binary = n->child_[1] != nullptr; 547 | 548 | int first_idx = 549 | binary ? ((n->child_[0]->vr_ <= n->child_[1]->vr_) ? 0 : 1) : 0; 550 | 551 | n->child_[first_idx]->AllocHRegs(desired[first_idx]); 552 | if (binary) 553 | n->child_[!first_idx]->AllocHRegs(desired[!first_idx]); 554 | 555 | CurrentOutputNode = n; // Associate generated instructions with this node. 556 | 557 | n->hr_[first_idx] = Ensure(n->child_[first_idx], desired[first_idx]); 558 | if (binary) 559 | n->hr_[!first_idx] = Ensure(n->child_[!first_idx], desired[!first_idx]); 560 | } 561 | 562 | // Commonly used helper for Node::AllocHRegs(). 563 | void FreeInsAllocOut(Node* n) 564 | { 565 | CHECK(n->child_[0]); 566 | bool binary = n->child_[1] != nullptr; 567 | 568 | Free(n->hr_[0]); 569 | if (binary) 570 | Free(n->hr_[1]); 571 | 572 | n->hr_[2] = Allocate(n, n->hr_[0]); 573 | 574 | CHECK(n->hr_[2] == n->hr_[0]); 575 | if (binary) 576 | CHECK(n->hr_[2] != n->hr_[1]); 577 | } 578 | 579 | // Generic implementation of the register allocator. 580 | void Node::AllocHRegs(HReg desired) 581 | { 582 | HReg desired2[2] = { desired, desired }; 583 | if (child_[1]) 584 | { 585 | // Binary. 586 | RecurseToAndEnsureIns(this, desired2); 587 | 588 | // If the operation is symmetric and 589 | // the desired out register is hr_[1], 590 | // swap it with hr_[0] so that hr_[0] is in/out. 591 | if (IsSymmetric() && (hr_[1] == desired)) 592 | { 593 | hr_[1] = hr_[0]; 594 | hr_[0] = desired; 595 | } 596 | 597 | FreeInsAllocOut(this); 598 | } 599 | else if (child_[0]) 600 | { 601 | // Unary. 602 | RecurseToAndEnsureIns(this, desired2); 603 | FreeInsAllocOut(this); 604 | } 605 | else 606 | { 607 | // Leaf. 608 | CurrentOutputNode = this; // Associate generated instructions with this node. 609 | hr_[2] = Allocate(this, desired); 610 | } 611 | 612 | std::ostringstream oss; 613 | if (child_[1]) 614 | oss << PrintInstruction() << ' ' << hr_[2] OCO hr_[1]; 615 | else if (child_[0]) 616 | oss << PrintInstruction() << ' ' << hr_[2]; 617 | else 618 | oss << "mov " << hr_[2] OCO PrintInstruction(); // NodeInt 619 | CurrentOutputNode->instructions.push_back(oss.str()); 620 | } 621 | 622 | // Generates instructions to set the memory values 623 | // that the expression code will load. 624 | void Node::GenMemValues() 625 | { 626 | CHECK(vr_ != -1); 627 | 628 | if (child_[1]) 629 | { 630 | int first_idx = (child_[0]->vr_ <= child_[1]->vr_) ? 0 : 1; 631 | child_[first_idx]->GenMemValues(); 632 | child_[!first_idx]->GenMemValues(); 633 | } 634 | else if (child_[0]) 635 | { 636 | child_[0]->GenMemValues(); 637 | } 638 | 639 | if (!vr_) 640 | CurrentOutputNode = this; 641 | CHECK(CurrentOutputNode); 642 | GenMemValue(); 643 | } 644 | 645 | // Generates instructions to check the memory values 646 | // that the expression code will store. 647 | void Node::GenMemChecks() 648 | { 649 | CHECK(vr_ != -1); 650 | 651 | if (child_[1]) 652 | { 653 | int first_idx = (child_[0]->vr_ <= child_[1]->vr_) ? 0 : 1; 654 | child_[first_idx]->GenMemChecks(); 655 | child_[!first_idx]->GenMemChecks(); 656 | } 657 | else if (child_[0]) 658 | { 659 | child_[0]->GenMemChecks(); 660 | } 661 | 662 | CHECK(CurrentOutputNode); 663 | CHECK(vr_ <= CurrentOutputNode->vr_); 664 | GenMemCheck(); 665 | } 666 | 667 | // Generates instructions to check the register value 668 | // that the expression code will produce for the root node. 669 | void Node::GenRegCheck() 670 | { 671 | CHECK(CurrentOutputNode); 672 | std::ostringstream oss, oss2; 673 | oss << "cmp " << hr_[2] OCO val_; 674 | CurrentOutputNode->instructions.push_back(oss.str()); 675 | oss2 << "jne failure"; 676 | CurrentOutputNode->instructions.push_back(oss2.str()); 677 | } 678 | 679 | // Prints the expression tree. 680 | void Node::PrintExprTree(std::ostream& os, int level) 681 | { 682 | if (child_[1]) 683 | child_[1]->PrintExprTree(os, level + 4); 684 | 685 | os << "; " << std::string(level, ' ') << PrintOperation(); 686 | if (vr_ >= 0) 687 | { 688 | os << " (vr" << vr_; 689 | #if 0 690 | os << "; u@" << user_vr_; 691 | #endif 692 | os << ")"; 693 | } 694 | os << '\n'; 695 | 696 | if (child_[0]) 697 | child_[0]->PrintExprTree(os, level + 4); 698 | } 699 | 700 | // Prints all generated instructions. 701 | void Node::PrintInstructions(std::ostream& os) 702 | { 703 | CHECK(vr_ != -1); 704 | if (child_[1]) 705 | { 706 | int first_idx = (child_[0]->vr_ <= child_[1]->vr_) ? 0 : 1; 707 | child_[first_idx]->PrintInstructions(os); 708 | child_[!first_idx]->PrintInstructions(os); 709 | } 710 | else if (child_[0]) 711 | { 712 | child_[0]->PrintInstructions(os); 713 | } 714 | for (const auto& s : instructions) 715 | { 716 | os << " "; 717 | os << s; 718 | os << std::string(28 - s.length(), ' '); 719 | os << "; vr" << vr_; 720 | os << '\n'; 721 | } 722 | } 723 | 724 | // 16-bit integer (leaf node). 725 | struct NodeInt : Node 726 | { 727 | NodeInt() = delete; 728 | NodeInt(unsigned short val) { val_ = val; } 729 | virtual std::string PrintOperation() const 730 | { 731 | std::ostringstream oss; 732 | oss << val_; 733 | return oss.str(); 734 | } 735 | virtual void Eval() {} 736 | }; 737 | 738 | // label (leaf node). 739 | struct NodeLabel : Node 740 | { 741 | NodeLabel() = delete; 742 | NodeLabel(const std::string& label) { label_ = label; } 743 | virtual std::string PrintOperation() const 744 | { 745 | return label_; 746 | } 747 | virtual void Eval() {} 748 | std::string label_; 749 | }; 750 | 751 | struct NodeNeg : Node 752 | { 753 | NodeNeg() = delete; 754 | NodeNeg(Node* left) : Node(left) {} 755 | virtual std::string PrintOperation() const { return "neg "; } 756 | virtual void Eval() 757 | { 758 | child_[0]->Eval(); 759 | val_ = -child_[0]->val_; 760 | } 761 | }; 762 | 763 | struct NodeNot : Node 764 | { 765 | NodeNot() = delete; 766 | NodeNot(Node* left) : Node(left) {} 767 | virtual std::string PrintOperation() const { return "not "; } 768 | virtual void Eval() 769 | { 770 | child_[0]->Eval(); 771 | val_ = ~child_[0]->val_; 772 | } 773 | }; 774 | 775 | // Zero extension from 8 to 16 bits. 776 | struct NodeZext : Node 777 | { 778 | NodeZext() = delete; 779 | NodeZext(Node* left) : Node(left) {} 780 | virtual std::string PrintOperation() const { return "zext "; } 781 | virtual void Eval() 782 | { 783 | child_[0]->Eval(); 784 | val_ = child_[0]->val_ & 0xFF; 785 | } 786 | virtual void AllocHRegs(HReg desired) 787 | { 788 | child_[0]->AllocHRegs(desired); 789 | 790 | CurrentOutputNode = this; // Associate generated instructions with this node. 791 | 792 | hr_[0] = Ensure(child_[0], desired); 793 | 794 | Free(hr_[0]); 795 | hr_[2] = Allocate(this, hr_[0]); 796 | 797 | std::ostringstream oss; 798 | if (ByteHReg(hr_[2])) 799 | oss << "xor " << HRegHi(hr_[2]) OCO HRegHi(hr_[2]); 800 | else 801 | oss << "and " << hr_[2] OCO 255; 802 | CurrentOutputNode->instructions.push_back(oss.str()); 803 | } 804 | }; 805 | 806 | // Sign extension from 8 to 16 bits. 807 | struct NodeSext : Node 808 | { 809 | NodeSext() = delete; 810 | NodeSext(Node* left) : Node(left) {} 811 | virtual std::string PrintOperation() const { return "sext "; } 812 | virtual void Eval() 813 | { 814 | child_[0]->Eval(); 815 | val_ = child_[0]->val_ & 0xFF; 816 | val_ -= (val_ & 0x80) << 1; 817 | } 818 | virtual void AllocHRegs(HReg desired) 819 | { 820 | (void)desired; 821 | HReg desired2 = HRegAX; 822 | child_[0]->AllocHRegs(desired2); 823 | 824 | CurrentOutputNode = this; // Associate generated instructions with this node. 825 | 826 | hr_[0] = Ensure(child_[0], desired2); 827 | 828 | if (hr_[0] != desired2) 829 | { 830 | MoveToDesired(desired2, hr_[0]); 831 | hr_[0] = desired2; 832 | } 833 | 834 | Free(hr_[0]); 835 | hr_[2] = Allocate(this, hr_[0]); 836 | 837 | CurrentOutputNode->instructions.push_back("cbw"); 838 | } 839 | }; 840 | 841 | struct NodeAnd : Node 842 | { 843 | NodeAnd() = delete; 844 | NodeAnd(Node* left, Node* right) : Node(left, right) {} 845 | virtual bool IsSymmetric() const { return true; } 846 | virtual std::string PrintOperation() const { return "and "; } 847 | virtual void Eval() 848 | { 849 | child_[0]->Eval(); 850 | child_[1]->Eval(); 851 | val_ = child_[0]->val_ & child_[1]->val_; 852 | } 853 | }; 854 | 855 | struct NodeOr : Node 856 | { 857 | NodeOr() = delete; 858 | NodeOr(Node* left, Node* right) : Node(left, right) {} 859 | virtual bool IsSymmetric() const { return true; } 860 | virtual std::string PrintOperation() const { return "or "; } 861 | virtual void Eval() 862 | { 863 | child_[0]->Eval(); 864 | child_[1]->Eval(); 865 | val_ = child_[0]->val_ | child_[1]->val_; 866 | } 867 | }; 868 | 869 | struct NodeXor : Node 870 | { 871 | NodeXor() = delete; 872 | NodeXor(Node* left, Node* right) : Node(left, right) {} 873 | virtual bool IsSymmetric() const { return true; } 874 | virtual std::string PrintOperation() const { return "xor "; } 875 | virtual void Eval() 876 | { 877 | child_[0]->Eval(); 878 | child_[1]->Eval(); 879 | val_ = child_[0]->val_ ^ child_[1]->val_; 880 | } 881 | }; 882 | 883 | struct NodeAdd : Node 884 | { 885 | NodeAdd() = delete; 886 | NodeAdd(Node* left, Node* right) : Node(left, right) {} 887 | virtual bool IsSymmetric() const { return true; } 888 | virtual std::string PrintOperation() const { return "add "; } 889 | virtual void Eval() 890 | { 891 | child_[0]->Eval(); 892 | child_[1]->Eval(); 893 | val_ = child_[0]->val_ + child_[1]->val_; 894 | } 895 | }; 896 | 897 | struct NodeSub : Node 898 | { 899 | NodeSub() = delete; 900 | NodeSub(Node* minuend, Node* subtrahend) : Node(minuend, subtrahend) {} 901 | virtual std::string PrintOperation() const { return "sub "; } 902 | virtual void Eval() 903 | { 904 | child_[0]->Eval(); 905 | child_[1]->Eval(); 906 | val_ = child_[0]->val_ - child_[1]->val_; 907 | } 908 | }; 909 | 910 | void AllocHRegs_ShiftX(Node* n, HReg desired) 911 | { 912 | HReg (&hr_)[3] = n->hr_; 913 | 914 | // Simulate the shl instruction requiring 915 | // its right input in HRegCX. 916 | HReg desired2[2] = { desired, HRegCX }; 917 | switch (desired) 918 | { 919 | case HRegAX: 920 | case HRegDX: 921 | case HRegBX: 922 | #if USE_REGS >= 5 923 | case HRegSI: 924 | #endif 925 | #if USE_REGS >= 6 926 | case HRegDI: 927 | #endif 928 | case HRegNotCX: 929 | case HRegNotDXNotCXNotAX: 930 | case HRegByteNotCX: 931 | case HRegAddr: 932 | break; 933 | case HRegCX: 934 | case HRegAny: 935 | desired2[0] = HRegNotCX; 936 | break; 937 | case HRegNotDXNotAX: 938 | desired2[0] = HRegNotDXNotCXNotAX; 939 | break; 940 | case HRegByte: 941 | desired2[0] = HRegByteNotCX; 942 | break; 943 | default: 944 | CHECK(0); 945 | break; 946 | } 947 | 948 | // N.B. For shifts we prefer recursing right if all else is equal. 949 | // The idea is to get HRegCX for the count operand ASAP. 950 | RecurseToAndEnsureIns(n, desired2); 951 | 952 | if (hr_[1] != desired2[1]) 953 | { 954 | MoveToDesired(desired2[1], hr_[1]); 955 | if (hr_[0] == desired2[1]) 956 | hr_[0] = hr_[1]; 957 | hr_[1] = desired2[1]; 958 | } 959 | 960 | FreeInsAllocOut(n); 961 | 962 | std::ostringstream oss; 963 | oss << n->PrintInstruction() << ' ' << hr_[2] OCO HRegLo(hr_[1]); 964 | CurrentOutputNode->instructions.push_back(oss.str()); 965 | } 966 | 967 | // Shift left. 968 | struct NodeShLft : Node 969 | { 970 | NodeShLft() = delete; 971 | NodeShLft(Node* value, Node* count) : Node(value, count) {} 972 | virtual bool PrefersRight() const { return true; } 973 | virtual std::string PrintOperation() const { return "shl "; } 974 | virtual void AllocHRegs(HReg desired) { AllocHRegs_ShiftX(this, desired); } 975 | virtual void Eval() 976 | { 977 | child_[0]->Eval(); 978 | child_[1]->Eval(); 979 | val_ = child_[0]->val_ << (child_[1]->val_ & 0xF); 980 | } 981 | }; 982 | 983 | // Logical shift right. 984 | struct NodeShRht : Node 985 | { 986 | NodeShRht() = delete; 987 | NodeShRht(Node* value, Node* count) : Node(value, count) {} 988 | virtual bool PrefersRight() const { return true; } 989 | virtual std::string PrintOperation() const { return "shr "; } 990 | virtual void AllocHRegs(HReg desired) { AllocHRegs_ShiftX(this, desired); } 991 | virtual void Eval() 992 | { 993 | child_[0]->Eval(); 994 | child_[1]->Eval(); 995 | val_ = child_[0]->val_ >> (child_[1]->val_ & 0xF); 996 | } 997 | }; 998 | 999 | // Arithmetic/sign-extending shift right. 1000 | struct NodeShArRht : Node 1001 | { 1002 | NodeShArRht() = delete; 1003 | NodeShArRht(Node* value, Node* count) : Node(value, count) {} 1004 | virtual bool PrefersRight() const { return true; } 1005 | virtual std::string PrintOperation() const { return "sar "; } 1006 | virtual void AllocHRegs(HReg desired) { AllocHRegs_ShiftX(this, desired); } 1007 | virtual void Eval() 1008 | { 1009 | child_[0]->Eval(); 1010 | child_[1]->Eval(); 1011 | unsigned short sign = -(child_[0]->val_ >> 15); 1012 | int count = child_[1]->val_ & 0xF; 1013 | val_ = child_[0]->val_ >> count; 1014 | val_ |= (unsigned)sign << (15 - count) << 1; 1015 | } 1016 | }; 1017 | 1018 | // Mul works for both signed and unsigned values. 1019 | struct NodeMul : Node 1020 | { 1021 | NodeMul() = delete; 1022 | NodeMul(Node* left, Node* right) : Node(left, right) {} 1023 | virtual bool IsSymmetric() const { return true; } 1024 | virtual std::string PrintOperation() const { return "mul "; } 1025 | virtual void AllocHRegs(HReg desired) 1026 | { 1027 | // Simulate the mul instruction requiring its 1028 | // output and one of its inputs in HRegAX. 1029 | desired = HRegAX; 1030 | HReg desired1[2] = { HRegAX, HRegAX }; 1031 | 1032 | RecurseToAndEnsureIns(this, desired1); 1033 | bool swapped = (hr_[1] == desired); 1034 | 1035 | // Also simulate modification of HRegDX (or, rather, avoid trashing 1036 | // something useful in HRegDX; mul modifies it). 1037 | // If HRegDX holds some value, swap HRegDX with the HReg holding 1038 | // the right multiplicand (N.B. the left is in HRegAX). 1039 | // The right multiplicand can be HRegDX and isn't needed after mul. 1040 | HReg desired2 = HRegDX; 1041 | bool has_ax = (hr_[0] == desired) || (hr_[1] == desired); 1042 | bool has_dx = (hr_[0] == desired2) || (hr_[1] == desired2); 1043 | bool need_to_save_dx = !has_dx && NodeFromHReg[desired2]; 1044 | // 1045 | // ax dx nothing 1046 | // dx ax ditto 1047 | // ax !dx possibly preserve dx by swapping !dx with dx 1048 | // !dx ax ditto 1049 | // !ax dx swap !ax with ax 1050 | // dx !ax ditto 1051 | // !ax !dx swap !ax with ax; possibly preserve dx by swapping !dx with dx 1052 | // !dx !ax ditto 1053 | // 1054 | if (!has_ax) 1055 | { 1056 | bool idx = (hr_[0] == desired2); 1057 | MoveToDesired(desired, hr_[int(idx)]); 1058 | hr_[idx] = desired; 1059 | swapped = idx; 1060 | } 1061 | // The operation is symmetric, so, 1062 | // if the desired out register is hr_[1], 1063 | // swap it with hr_[0] so that hr_[0] is in/out. 1064 | if (swapped) 1065 | { 1066 | HReg t = hr_[1]; 1067 | hr_[1] = hr_[0]; 1068 | hr_[0] = t; 1069 | } 1070 | CHECK(hr_[0] == desired); 1071 | if (need_to_save_dx) 1072 | { 1073 | MoveToDesired(desired2, hr_[1]); 1074 | hr_[1] = desired2; 1075 | } 1076 | CHECK((hr_[1] == desired2) || !NodeFromHReg[desired2]); 1077 | 1078 | FreeInsAllocOut(this); 1079 | 1080 | std::ostringstream oss; 1081 | oss << PrintInstruction() << ' ' << hr_[1]; 1082 | CurrentOutputNode->instructions.push_back(oss.str()); 1083 | } 1084 | virtual void Eval() 1085 | { 1086 | child_[0]->Eval(); 1087 | child_[1]->Eval(); 1088 | val_ = (unsigned long)child_[0]->val_ * child_[1]->val_; 1089 | } 1090 | }; 1091 | 1092 | void AllocHRegs_DivRemX(Node* n, bool rem_not_div, bool signed_) 1093 | { 1094 | HReg (&hr_)[3] = n->hr_; 1095 | 1096 | // Simulate the idiv instruction requiring its 1097 | // output and its left input in HRegAX. 1098 | HReg desired2[2] = { HRegAX, HRegNotDXNotAX }; 1099 | 1100 | RecurseToAndEnsureIns(n, desired2); 1101 | 1102 | if (hr_[0] != desired2[0]) 1103 | { 1104 | MoveToDesired(desired2[0], hr_[0]); 1105 | if (hr_[1] == desired2[0]) 1106 | hr_[1] = hr_[0]; 1107 | hr_[0] = desired2[0]; 1108 | } 1109 | CHECK(hr_[0] == desired2[0]); 1110 | 1111 | // Also simulate modification of HRegDX 1112 | // (or, rather, avoid trashing something useful in HRegDX; 1113 | // (i)div's user must modify dx before (i)div). 1114 | // 1115 | // ax dx alloc tmp and move dx there, div by tmp 1116 | // ax !dx possibly alloc tmp and move dx there, div by right 1117 | // 1118 | HReg undesired = HRegDX; 1119 | if ((hr_[1] == undesired) || NodeFromHReg[undesired]) 1120 | { 1121 | HReg t = Allocate(n); // This is a temp HReg. 1122 | Free(t); // And it is free now. 1123 | MoveToDesired(t, undesired); // This finally frees up HRegDX. 1124 | if (hr_[1] == undesired) 1125 | hr_[1] = t; 1126 | } 1127 | CHECK(hr_[1] != undesired); 1128 | CHECK(!NodeFromHReg[undesired]); 1129 | if (rem_not_div) 1130 | { 1131 | Free(hr_[0]); 1132 | hr_[0] = Allocate(n, undesired); 1133 | CHECK(hr_[0] == undesired); 1134 | } 1135 | 1136 | FreeInsAllocOut(n); 1137 | 1138 | { 1139 | std::ostringstream oss; 1140 | // This is what would trash HRegDX. 1141 | if (signed_) 1142 | oss << "cwd"; 1143 | else 1144 | oss << "xor " << undesired OCO undesired; 1145 | CurrentOutputNode->instructions.push_back(oss.str()); 1146 | } 1147 | { 1148 | std::ostringstream oss; 1149 | oss << n->PrintInstruction() << ' ' << hr_[1]; 1150 | CurrentOutputNode->instructions.push_back(oss.str()); 1151 | } 1152 | } 1153 | 1154 | // Signed division. 1155 | struct NodeIDiv : Node 1156 | { 1157 | NodeIDiv() = delete; 1158 | NodeIDiv(Node* dividend, Node* divisor) : Node(dividend, divisor) {} 1159 | virtual int MinRegCnt() const { return 3; } // HRegDX is clobbered early. 1160 | virtual std::string PrintOperation() const { return "idiv"; } 1161 | virtual void AllocHRegs(HReg desired) 1162 | { 1163 | (void)desired; 1164 | AllocHRegs_DivRemX(this, /*rem_not_div*/false, /*signed_*/true); 1165 | } 1166 | virtual void Eval() 1167 | { 1168 | child_[0]->Eval(); 1169 | child_[1]->Eval(); 1170 | unsigned short dividend = child_[0]->val_; 1171 | unsigned short divisor = child_[1]->val_; 1172 | CHECK(divisor); 1173 | CHECK((dividend != 0x8000) || (divisor != 0xFFFF)); 1174 | bool neg = false; 1175 | if (dividend & 0x8000) 1176 | { 1177 | dividend = -dividend; 1178 | neg = true; 1179 | } 1180 | if (divisor & 0x8000) 1181 | { 1182 | divisor = -divisor; 1183 | neg = !neg; 1184 | } 1185 | val_ = dividend / divisor; 1186 | val_ = neg ? -val_ : val_; 1187 | } 1188 | }; 1189 | 1190 | // Signed remainder. 1191 | struct NodeIRem : Node 1192 | { 1193 | NodeIRem() = delete; 1194 | NodeIRem(Node* dividend, Node* divisor) : Node(dividend, divisor) {} 1195 | virtual int MinRegCnt() const { return 3; } // HRegDX is clobbered early. 1196 | virtual std::string PrintOperation() const { return "irem"; } 1197 | virtual std::string PrintInstruction() const { return "idiv"; } 1198 | virtual void AllocHRegs(HReg desired) 1199 | { 1200 | (void)desired; 1201 | AllocHRegs_DivRemX(this, /*rem_not_div*/true, /*signed_*/true); 1202 | } 1203 | virtual void Eval() 1204 | { 1205 | child_[0]->Eval(); 1206 | child_[1]->Eval(); 1207 | unsigned short dividend = child_[0]->val_; 1208 | unsigned short divisor = child_[1]->val_; 1209 | CHECK(divisor); 1210 | CHECK((dividend != 0x8000) || (divisor != 0xFFFF)); 1211 | bool neg = false; 1212 | if (dividend & 0x8000) 1213 | { 1214 | dividend = -dividend; 1215 | neg = true; 1216 | } 1217 | if (divisor & 0x8000) 1218 | divisor = -divisor; 1219 | val_ = dividend % divisor; 1220 | val_ = neg ? -val_ : val_; 1221 | } 1222 | }; 1223 | 1224 | // Unsigned division. 1225 | struct NodeDiv : Node 1226 | { 1227 | NodeDiv() = delete; 1228 | NodeDiv(Node* dividend, Node* divisor) : Node(dividend, divisor) {} 1229 | virtual int MinRegCnt() const { return 3; } // HRegDX is clobbered early. 1230 | virtual std::string PrintOperation() const { return "div "; } 1231 | virtual void AllocHRegs(HReg desired) 1232 | { 1233 | (void)desired; 1234 | AllocHRegs_DivRemX(this, /*rem_not_div*/false, /*signed_*/false); 1235 | } 1236 | virtual void Eval() 1237 | { 1238 | child_[0]->Eval(); 1239 | child_[1]->Eval(); 1240 | CHECK(child_[1]->val_); 1241 | val_ = child_[0]->val_ / child_[1]->val_; 1242 | } 1243 | }; 1244 | 1245 | // Unsigned remainder. 1246 | struct NodeRem : Node 1247 | { 1248 | NodeRem() = delete; 1249 | NodeRem(Node* dividend, Node* divisor) : Node(dividend, divisor) {} 1250 | virtual int MinRegCnt() const { return 3; } // HRegDX is clobbered early. 1251 | virtual std::string PrintOperation() const { return "rem "; } 1252 | virtual std::string PrintInstruction() const { return "div "; } 1253 | virtual void AllocHRegs(HReg desired) 1254 | { 1255 | (void)desired; 1256 | AllocHRegs_DivRemX(this, /*rem_not_div*/true, /*signed_*/false); 1257 | } 1258 | virtual void Eval() 1259 | { 1260 | child_[0]->Eval(); 1261 | child_[1]->Eval(); 1262 | CHECK(child_[1]->val_); 1263 | val_ = child_[0]->val_ % child_[1]->val_; 1264 | } 1265 | }; 1266 | 1267 | enum LoadKind : int 1268 | { 1269 | LoadKindWord, 1270 | LoadKindByte, // not extended to 16 bits: top 8 bits are undefined 1271 | LoadKindByteSignExtended, 1272 | LoadKindByteZeroExtended 1273 | }; 1274 | 1275 | // Helper for loads from memory into a register. 1276 | void AllocHRegs_LoadX(Node* n, HReg desired, LoadKind kind) 1277 | { 1278 | HReg (&hr_)[3] = n->hr_; 1279 | Node* (&child_)[2] = n->child_; 1280 | 1281 | child_[0]->AllocHRegs(HRegAddr); 1282 | 1283 | CurrentOutputNode = n; // Associate generated instructions with this node. 1284 | 1285 | hr_[0] = Ensure(child_[0], HRegAddr); 1286 | 1287 | if (!AddrHReg(hr_[0])) 1288 | { 1289 | HReg t = HRegBX; 1290 | MoveToDesired(t, hr_[0]); 1291 | hr_[0] = t; 1292 | } 1293 | CHECK(AddrHReg(hr_[0])); 1294 | 1295 | Free(hr_[0]); 1296 | if (kind == LoadKindWord) 1297 | { 1298 | HReg desired2 = hr_[0]; 1299 | switch (desired) 1300 | { 1301 | case HRegAX: 1302 | case HRegCX: 1303 | case HRegDX: 1304 | case HRegBX: 1305 | #if USE_REGS >= 5 1306 | case HRegSI: 1307 | #endif 1308 | #if USE_REGS >= 6 1309 | case HRegDI: 1310 | #endif 1311 | if (!NodeFromHReg[desired]) 1312 | desired2 = desired; 1313 | break; 1314 | case HRegAny: 1315 | case HRegAddr: 1316 | case HRegNotCX: 1317 | case HRegNotDXNotAX: 1318 | case HRegNotDXNotCXNotAX: 1319 | break; 1320 | case HRegByte: 1321 | case HRegByteNotCX: 1322 | desired2 = desired; 1323 | break; 1324 | default: 1325 | CHECK(0); 1326 | break; 1327 | } 1328 | hr_[2] = Allocate(n, desired2); 1329 | } 1330 | else 1331 | { 1332 | if (kind == LoadKindByteSignExtended) 1333 | { 1334 | HReg desired2 = HRegAX; 1335 | hr_[2] = Allocate(n, desired2); 1336 | if (hr_[2] != desired2) 1337 | { 1338 | Free(hr_[2]); // This is a free/temp HReg. 1339 | MoveToDesired(hr_[2], desired2); // This frees up HRegAX. 1340 | CHECK(!NodeFromHReg[desired2]); 1341 | hr_[2] = Allocate(n, desired2); // We can now use HRegAX. 1342 | } 1343 | CHECK(hr_[2] == desired2); 1344 | } 1345 | else 1346 | { 1347 | HReg desired2 = HRegByte; 1348 | switch (desired) 1349 | { 1350 | case HRegAX: 1351 | case HRegCX: 1352 | case HRegDX: 1353 | case HRegBX: 1354 | if (!NodeFromHReg[desired]) 1355 | desired2 = desired; 1356 | break; 1357 | #if USE_REGS >= 5 1358 | case HRegSI: 1359 | #endif 1360 | #if USE_REGS >= 6 1361 | case HRegDI: 1362 | #endif 1363 | case HRegAny: 1364 | case HRegByte: 1365 | if (ByteHReg(hr_[0])) 1366 | desired2 = hr_[0]; 1367 | break; 1368 | case HRegNotCX: 1369 | case HRegByteNotCX: 1370 | desired2 = HRegByteNotCX; 1371 | break; 1372 | case HRegNotDXNotAX: 1373 | if (!NodeFromHReg[HRegCX]) 1374 | desired2 = HRegCX; 1375 | else if (!NodeFromHReg[HRegBX]) 1376 | desired2 = HRegBX; 1377 | break; 1378 | case HRegNotDXNotCXNotAX: 1379 | case HRegAddr: 1380 | if (!NodeFromHReg[HRegBX]) 1381 | desired2 = HRegBX; 1382 | break; 1383 | default: 1384 | CHECK(0); 1385 | break; 1386 | } 1387 | hr_[2] = Allocate(n, desired2); 1388 | if (!ByteHReg(hr_[2])) 1389 | { 1390 | desired2 = HRegAX; 1391 | Free(hr_[2]); // This is a free/temp HReg. 1392 | MoveToDesired(hr_[2], desired2); // This frees up HRegAX. 1393 | CHECK(!NodeFromHReg[desired2]); 1394 | hr_[2] = Allocate(n, desired2); // We can now use HRegAX. 1395 | CHECK(hr_[2] == desired2); 1396 | } 1397 | } 1398 | CHECK(ByteHReg(hr_[2])); 1399 | } 1400 | 1401 | std::ostringstream oss, oss2; 1402 | if (kind == LoadKindWord) 1403 | oss << n->PrintInstruction() 1404 | << ' ' << hr_[2] OCO '[' << hr_[0] << ']'; 1405 | else 1406 | oss << n->PrintInstruction() 1407 | << ' ' << HRegLo(hr_[2]) OCO '[' << hr_[0] << ']'; 1408 | CurrentOutputNode->instructions.push_back(oss.str()); 1409 | 1410 | if ((kind == LoadKindByteSignExtended) || 1411 | (kind == LoadKindByteZeroExtended)) 1412 | { 1413 | if (kind == LoadKindByteSignExtended) 1414 | oss2 << "cbw"; 1415 | else 1416 | oss2 << "xor " << HRegHi(hr_[2]) OCO HRegHi(hr_[2]); 1417 | CurrentOutputNode->instructions.push_back(oss2.str()); 1418 | } 1419 | } 1420 | 1421 | // Loads 16 bits from memory. 1422 | struct NodeLw : Node 1423 | { 1424 | NodeLw() = delete; 1425 | NodeLw(unsigned short test_val, Node* address) : Node(address) 1426 | { 1427 | val_ = test_val; 1428 | } 1429 | virtual std::string PrintOperation() const { return "lw "; } 1430 | virtual std::string PrintInstruction() const { return "mov "; } 1431 | virtual void AllocHRegs(HReg desired) 1432 | { 1433 | AllocHRegs_LoadX(this, desired, LoadKindWord); 1434 | } 1435 | virtual void Eval() 1436 | { 1437 | child_[0]->Eval(); 1438 | } 1439 | virtual void GenMemValue() 1440 | { 1441 | std::ostringstream oss; 1442 | oss << "mov word [" << child_[0]->val_ << "]" OCO val_; 1443 | CurrentOutputNode->instructions.push_back(oss.str()); 1444 | } 1445 | }; 1446 | 1447 | // Loads 8 bits from memory, doesn't extend to 16 bits. 1448 | struct NodeLb : Node 1449 | { 1450 | NodeLb() = delete; 1451 | NodeLb(unsigned short test_val, Node* address) : Node(address) 1452 | { 1453 | val_ = test_val & 0xFF; 1454 | } 1455 | virtual std::string PrintOperation() const { return "lb "; } 1456 | virtual std::string PrintInstruction() const { return "mov "; } 1457 | virtual void AllocHRegs(HReg desired) 1458 | { 1459 | AllocHRegs_LoadX(this, desired, LoadKindByte); 1460 | } 1461 | virtual void Eval() 1462 | { 1463 | child_[0]->Eval(); 1464 | } 1465 | virtual void GenMemValue() 1466 | { 1467 | std::ostringstream oss; 1468 | oss << "mov byte [" << child_[0]->val_ << "]" OCO (val_ & 0xFF); 1469 | CurrentOutputNode->instructions.push_back(oss.str()); 1470 | } 1471 | }; 1472 | 1473 | // Loads 8 bits from memory, sign-extends to 16 bits. 1474 | struct NodeLbs : Node 1475 | { 1476 | NodeLbs() = delete; 1477 | NodeLbs(unsigned short test_val, Node* address) : Node(address) 1478 | { 1479 | CHECK(!(test_val >> 7) || ((test_val >> 7) == 0x1FF)); 1480 | val_ = test_val; 1481 | } 1482 | virtual std::string PrintOperation() const { return "lbs "; } 1483 | virtual std::string PrintInstruction() const { return "mov "; } 1484 | virtual void AllocHRegs(HReg desired) 1485 | { 1486 | AllocHRegs_LoadX(this, desired, LoadKindByteSignExtended); 1487 | } 1488 | virtual void Eval() 1489 | { 1490 | child_[0]->Eval(); 1491 | } 1492 | virtual void GenMemValue() 1493 | { 1494 | std::ostringstream oss; 1495 | oss << "mov byte [" << child_[0]->val_ << "]" OCO (val_ & 0xFF); 1496 | CurrentOutputNode->instructions.push_back(oss.str()); 1497 | } 1498 | }; 1499 | 1500 | // Loads 8 bits from memory, zero-extends to 16 bits. 1501 | struct NodeLbz : Node 1502 | { 1503 | NodeLbz() = delete; 1504 | NodeLbz(unsigned short test_val, Node* address) : Node(address) 1505 | { 1506 | CHECK(test_val <= 0xFF); 1507 | val_ = test_val; 1508 | } 1509 | virtual std::string PrintOperation() const { return "lbz "; } 1510 | virtual std::string PrintInstruction() const { return "mov "; } 1511 | virtual void AllocHRegs(HReg desired) 1512 | { 1513 | AllocHRegs_LoadX(this, desired, LoadKindByteZeroExtended); 1514 | } 1515 | virtual void Eval() 1516 | { 1517 | child_[0]->Eval(); 1518 | } 1519 | virtual void GenMemValue() 1520 | { 1521 | std::ostringstream oss; 1522 | oss << "mov byte [" << child_[0]->val_ << "]" OCO (val_ & 0xFF); 1523 | CurrentOutputNode->instructions.push_back(oss.str()); 1524 | } 1525 | }; 1526 | 1527 | enum StoreKind : int 1528 | { 1529 | StoreKindWord, 1530 | StoreKindByte 1531 | }; 1532 | 1533 | // Helper for stores to memory from a register. 1534 | void AllocHRegs_StoreX(Node* n, HReg desired, StoreKind kind) 1535 | { 1536 | HReg (&hr_)[3] = n->hr_; 1537 | 1538 | HReg desired2[2] = { desired, HRegAddr }; 1539 | if (kind == StoreKindByte) 1540 | { 1541 | switch (desired) 1542 | { 1543 | case HRegAX: 1544 | case HRegCX: 1545 | case HRegDX: 1546 | case HRegBX: 1547 | break; 1548 | #if USE_REGS >= 5 1549 | case HRegSI: 1550 | #endif 1551 | #if USE_REGS >= 6 1552 | case HRegDI: 1553 | #endif 1554 | case HRegAny: 1555 | case HRegAddr: 1556 | case HRegByte: 1557 | desired2[0] = HRegByte; 1558 | break; 1559 | case HRegNotCX: 1560 | case HRegByteNotCX: 1561 | desired2[0] = HRegByteNotCX; 1562 | break; 1563 | case HRegNotDXNotAX: 1564 | desired2[0] = HRegCX; 1565 | break; 1566 | case HRegNotDXNotCXNotAX: 1567 | desired2[0] = HRegBX; 1568 | break; 1569 | default: 1570 | CHECK(0); 1571 | break; 1572 | } 1573 | } 1574 | 1575 | RecurseToAndEnsureIns(n, desired2); 1576 | 1577 | if (!AddrHReg(hr_[1])) 1578 | { 1579 | desired2[1] = HRegBX; 1580 | MoveToDesired(desired2[1], hr_[1]); 1581 | if (hr_[0] == desired2[1]) 1582 | hr_[0] = hr_[1]; 1583 | hr_[1] = desired2[1]; 1584 | } 1585 | CHECK(AddrHReg(hr_[1])); 1586 | 1587 | if (kind == StoreKindByte) 1588 | { 1589 | if (!ByteHReg(hr_[0])) 1590 | { 1591 | desired2[0] = HRegAX; 1592 | MoveToDesired(desired2[0], hr_[0]); 1593 | CHECK(hr_[1] != desired2[0]); 1594 | hr_[0] = desired2[0]; 1595 | } 1596 | CHECK(ByteHReg(hr_[0])); 1597 | } 1598 | 1599 | FreeInsAllocOut(n); 1600 | 1601 | std::ostringstream oss; 1602 | if (kind == StoreKindWord) 1603 | oss << n->PrintInstruction() 1604 | << " [" << hr_[1] << "]" OCO hr_[2]; 1605 | else 1606 | oss << n->PrintInstruction() 1607 | << " [" << hr_[1] << "]" OCO HRegLo(hr_[2]); 1608 | CurrentOutputNode->instructions.push_back(oss.str()); 1609 | } 1610 | 1611 | // Stores 16 bits to memory. 1612 | struct NodeSw : Node 1613 | { 1614 | NodeSw() = delete; 1615 | NodeSw(Node* value, Node* address) : Node(value, address) {} 1616 | virtual std::string PrintOperation() const { return "sw "; } 1617 | virtual std::string PrintInstruction() const { return "mov "; } 1618 | virtual void AllocHRegs(HReg desired) 1619 | { 1620 | AllocHRegs_StoreX(this, desired, StoreKindWord); 1621 | } 1622 | virtual void Eval() 1623 | { 1624 | child_[0]->Eval(); 1625 | child_[1]->Eval(); 1626 | val_ = child_[0]->val_; 1627 | } 1628 | virtual void GenMemCheck() 1629 | { 1630 | std::ostringstream oss, oss2; 1631 | oss << "cmp word [" << child_[1]->val_ << "]" OCO val_; 1632 | CurrentOutputNode->instructions.push_back(oss.str()); 1633 | oss2 << "jne failure"; 1634 | CurrentOutputNode->instructions.push_back(oss2.str()); 1635 | } 1636 | }; 1637 | 1638 | // Stores 8 bits to memory. 1639 | struct NodeSb : Node 1640 | { 1641 | NodeSb() = delete; 1642 | NodeSb(Node* value, Node* address) : Node(value, address) {} 1643 | virtual std::string PrintOperation() const { return "sb "; } 1644 | virtual std::string PrintInstruction() const { return "mov "; } 1645 | virtual void AllocHRegs(HReg desired) 1646 | { 1647 | AllocHRegs_StoreX(this, desired, StoreKindByte); 1648 | } 1649 | virtual void Eval() 1650 | { 1651 | child_[0]->Eval(); 1652 | child_[1]->Eval(); 1653 | val_ = child_[0]->val_; 1654 | } 1655 | virtual void GenMemCheck() 1656 | { 1657 | std::ostringstream oss, oss2; 1658 | oss << "cmp byte [" << child_[1]->val_ << "]" OCO (val_ & 0xFF); 1659 | CurrentOutputNode->instructions.push_back(oss.str()); 1660 | oss2 << "jne failure"; 1661 | CurrentOutputNode->instructions.push_back(oss2.str()); 1662 | } 1663 | }; 1664 | 1665 | // Holds an argument node (in left child) and chains 1666 | // with the next argument holder (in right child, if any). 1667 | struct NodeArgHolder : Node 1668 | { 1669 | NodeArgHolder() = delete; 1670 | NodeArgHolder(Node* left, NodeArgHolder* right = nullptr) : Node(left, right) {} 1671 | virtual std::string PrintOperation() const { return "arg "; } 1672 | virtual int SelectFirst() 1673 | { 1674 | int nr, nl, n; 1675 | first_ = 0; 1676 | if (child_[1]) 1677 | { 1678 | // Recurse into chained args 1679 | // (rightmost/last arg is evaluated first). 1680 | first_ = 1; 1681 | nr = child_[1]->SelectFirst(); 1682 | } 1683 | nl = child_[0]->SelectFirst(); 1684 | // Each arg will be evaluated and pushed onto the stack. 1685 | // Somewhat meaningful number of registers needed by 1686 | // all chained args: just take the maximum. 1687 | n = (child_[1] && nr > nl) ? nr : nl; 1688 | return n; 1689 | } 1690 | virtual void AllocHRegs(HReg desired) 1691 | { 1692 | (void)desired; 1693 | 1694 | CHECK(first_ == (child_[1] != nullptr)); 1695 | 1696 | if (child_[1]) 1697 | child_[1]->AllocHRegs(HRegAny); 1698 | 1699 | child_[0]->AllocHRegs(HRegAny); 1700 | CHECK(child_[0]->InReg()); 1701 | hr_[2] = hr_[0] = Ensure(child_[0], HRegAny); // A no-op. 1702 | Free(hr_[2]); 1703 | 1704 | CurrentOutputNode = this; // Associate generated instructions with this node. 1705 | 1706 | std::ostringstream oss; 1707 | oss << "push " << hr_[2]; 1708 | CurrentOutputNode->instructions.push_back(oss.str()); 1709 | } 1710 | unsigned short ChainedArgCount() 1711 | { 1712 | return 1 + (child_[1] ? 1713 | static_cast(child_[1])->ChainedArgCount() : 1714 | 0); 1715 | } 1716 | virtual void Eval() 1717 | { 1718 | CHECK(false); 1719 | } 1720 | }; 1721 | 1722 | struct NodeCall : Node 1723 | { 1724 | NodeCall() = delete; 1725 | NodeCall(unsigned short test_val, 1726 | Node* left, NodeArgHolder* right = nullptr) : Node(left, right) 1727 | { 1728 | val_ = test_val; 1729 | } 1730 | virtual std::string PrintOperation() const { return "() "; } 1731 | virtual int SelectFirst() 1732 | { 1733 | int nr, nl, n; 1734 | first_ = 0; 1735 | if (child_[1]) 1736 | { 1737 | // Args are evaluated before subroutine address. 1738 | first_ = 1; 1739 | nr = child_[1]->SelectFirst(); 1740 | } 1741 | nl = child_[0]->SelectFirst(); 1742 | // Somewhat meaningful number of registers needed by a 1743 | // call: just take the maximum between the chained args 1744 | // and subroutine address. 1745 | n = (child_[1] && nr > nl) ? nr : nl; 1746 | // Since all regs live across a call are spilled, that 1747 | // number can't be less than the total number of allocatable 1748 | // registers, HRegCnt. 1749 | n = (n < HRegCnt) ? HRegCnt : n; 1750 | return n; 1751 | } 1752 | virtual void AllocHRegs(HReg desired) 1753 | { 1754 | struct Spill { Node* n; HReg r; } spills[HRegCnt]; 1755 | int spillCnt = 0; 1756 | 1757 | (void)desired; 1758 | 1759 | CHECK(first_ == (child_[1] != nullptr)); 1760 | 1761 | // For simplicity always spill all regs live across a call. 1762 | 1763 | // Find live regs. 1764 | for (int i = 0; i < HRegCnt; i++) 1765 | if (NodeFromHReg[i]) 1766 | { 1767 | spills[spillCnt].n = NodeFromHReg[i]; 1768 | spills[spillCnt++].r = HReg(i); 1769 | } 1770 | // Descending sort them by user_vr_. 1771 | std::sort(std::begin(spills), 1772 | std::begin(spills) + spillCnt, 1773 | [](struct Spill s1, struct Spill s2)->bool { 1774 | return s1.n->user_vr_ > s2.n->user_vr_; 1775 | }); 1776 | // And spill them. 1777 | for (int i = 0; i < spillCnt; i++) 1778 | Free(spills[i].r, /*spill*/true); 1779 | 1780 | // Recursively AllocHRegs(HRegAny) for args (last/right to first/left), 1781 | // each arg being pushed and its reg freed. 1782 | if (child_[1]) 1783 | child_[1]->AllocHRegs(HRegAny); 1784 | 1785 | // AllocHRegs(HRegAny) for the call address, call and free the reg. 1786 | 1787 | child_[0]->AllocHRegs(HRegAny); 1788 | CHECK(child_[0]->InReg()); 1789 | hr_[0] = Ensure(child_[0], HRegAny); // A no-op. 1790 | Free(hr_[0]); 1791 | 1792 | for (int i = 0; i < HRegCnt; i++) 1793 | CHECK(!NodeFromHReg[i]); 1794 | 1795 | CurrentOutputNode = this; // Associate generated instructions with this node. 1796 | 1797 | // Set output to AX. 1798 | hr_[2] = Allocate(this, HRegAX); 1799 | CHECK(hr_[2] == HRegAX); 1800 | 1801 | // Actual call. 1802 | std::ostringstream oss; 1803 | oss << "call " << hr_[0]; 1804 | CurrentOutputNode->instructions.push_back(oss.str()); 1805 | 1806 | // Remove args from stack, if any. 1807 | if (child_[1]) 1808 | { 1809 | std::ostringstream oss; 1810 | oss << "add sp, " 1811 | << static_cast(child_[1])->ChainedArgCount() * 2; 1812 | CurrentOutputNode->instructions.push_back(oss.str()); 1813 | } 1814 | } 1815 | virtual void Eval() 1816 | { 1817 | // Can't eval a call. 1818 | // Just use the value received in the constructor. 1819 | } 1820 | }; 1821 | 1822 | void Run(Node* n) 1823 | { 1824 | std::cout << '\n'; 1825 | 1826 | // Reinitialize the globals. 1827 | for (int hr = 0; hr < HRegCnt; hr++) 1828 | NodeFromHReg[hr] = nullptr; 1829 | CurrentOutputNode = nullptr; 1830 | 1831 | // Preprocess the expression tree. 1832 | int regs_needed = n->SelectFirst(); 1833 | n->AssignVRegs(); 1834 | 1835 | // Print the expression tree. 1836 | n->PrintExprTree(std::cout); 1837 | std::cout << "; ----\n"; 1838 | std::cout << "; Regs needed (approximately): " << regs_needed << '\n'; 1839 | std::cout << "; --------\n"; 1840 | 1841 | // Evaluate the expression and generate instructions to 1842 | // initialize input memory values. 1843 | n->Eval(); 1844 | CHECK(!CurrentOutputNode); 1845 | n->GenMemValues(); 1846 | CHECK(CurrentOutputNode); 1847 | CurrentOutputNode->instructions.push_back(";"); 1848 | 1849 | // Allocate hardware registers and generate code 1850 | // for the expression tree. 1851 | #if 01 1852 | n->AllocHRegs(); 1853 | #else 1854 | // If needed, we may force the result into a specific register. 1855 | HReg desired = HRegAX; 1856 | n->AllocHRegs(desired); 1857 | if (SpecificHReg(desired) && (n->hr_[2] != desired)) 1858 | { 1859 | MoveToDesired(desired, n->hr_[2]); 1860 | n->hr_[2] = desired; 1861 | } 1862 | #endif 1863 | // Some more sanity checks. 1864 | HReg out_reg = n->hr_[2]; 1865 | CHECK(SpecificHReg(out_reg)); 1866 | for (int hr = 0; hr < out_reg; hr++) 1867 | CHECK(!NodeFromHReg[hr]); 1868 | for (int hr = out_reg + 1; hr < HRegCnt; hr++) 1869 | CHECK(!NodeFromHReg[hr]); 1870 | CHECK(NodeFromHReg[out_reg] == n); 1871 | 1872 | // Generate register and memory checks. 1873 | CHECK(CurrentOutputNode == n); 1874 | CurrentOutputNode->instructions.push_back(";"); 1875 | n->GenRegCheck(); 1876 | n->GenMemChecks(); 1877 | 1878 | // Print generated instructions. 1879 | n->PrintInstructions(std::cout); 1880 | 1881 | delete n; 1882 | } 1883 | 1884 | #define USE_MANY_REGS5() \ 1885 | new NodeAdd( \ 1886 | new NodeAdd(new NodeAdd(new NodeAdd(new NodeInt(1), new NodeInt(2)), \ 1887 | new NodeAdd(new NodeInt(3), new NodeInt(4))), \ 1888 | new NodeAdd(new NodeAdd(new NodeInt(5), new NodeInt(6)), \ 1889 | new NodeAdd(new NodeInt(7), new NodeInt(8)))), \ 1890 | new NodeAdd(new NodeAdd(new NodeAdd(new NodeInt(9), new NodeInt(10)), \ 1891 | new NodeAdd(new NodeInt(11), new NodeInt(12))), \ 1892 | new NodeAdd(new NodeAdd(new NodeInt(13), new NodeInt(14)), \ 1893 | new NodeAdd(new NodeInt(15), new NodeInt(16))))) 1894 | #define USE_MANY_REGS6() new NodeAdd(USE_MANY_REGS5(), USE_MANY_REGS5()) 1895 | #define USE_MANY_REGS7() new NodeAdd(USE_MANY_REGS6(), USE_MANY_REGS6()) 1896 | #define USE_MANY_REGS8() new NodeAdd(USE_MANY_REGS7(), USE_MANY_REGS7()) 1897 | 1898 | int main() 1899 | { 1900 | std::cout << "; Compile this file with nasm:\n" 1901 | "; nasm file.asm -o file.com\n" 1902 | "; Run file.com in DOS, 32-bit Windows or DOSBox.\n\n"; 1903 | 1904 | std::cout << "bits 16\ncpu 8086\norg 0x100\n\n"; 1905 | 1906 | std::cout << "; Shrink/extend the PSP block to 64KB.\n" 1907 | " mov ah, 0x4a\n" 1908 | " mov bx, 4096\n" 1909 | " int 0x21\n" 1910 | " jc no_memory\n" 1911 | " mov sp, 0 ; stack at end of 64KB block\n"; 1912 | 1913 | Run(new NodeInt(5)); 1914 | Run(new NodeNeg(new NodeInt(7))); 1915 | Run(new NodeNot(new NodeInt(7))); 1916 | 1917 | Run(new NodeAdd(new NodeInt(3), new NodeInt(4))); 1918 | Run(new NodeXor(new NodeAnd(new NodeInt(1), new NodeInt(3)), 1919 | new NodeOr(new NodeInt(2), new NodeInt(4)))); 1920 | 1921 | Run(new NodeAdd(new NodeInt(2), new NodeMul(new NodeInt(3), new NodeInt(5)))); 1922 | Run(new NodeAdd(new NodeMul(new NodeInt(2), new NodeInt(3)), 1923 | new NodeMul(new NodeInt(5), new NodeInt(7)))); 1924 | Run(new NodeAdd( 1925 | new NodeAdd(new NodeAdd(new NodeAdd(new NodeInt(1), new NodeInt(2)), 1926 | new NodeAdd(new NodeInt(3), new NodeInt(4))), 1927 | new NodeAdd(new NodeAdd(new NodeInt(5), new NodeInt(6)), 1928 | new NodeAdd(new NodeInt(7), new NodeInt(8)))), 1929 | new NodeAdd(new NodeAdd(new NodeAdd(new NodeInt(9), new NodeInt(10)), 1930 | new NodeAdd(new NodeInt(11), new NodeInt(12))), 1931 | new NodeAdd(new NodeAdd(new NodeInt(13), new NodeInt(14)), 1932 | new NodeAdd(new NodeInt(15), new NodeInt(16)))) 1933 | )); 1934 | Run(new NodeSub( 1935 | new NodeSub(new NodeSub(new NodeSub(new NodeInt(1), new NodeInt(2)), 1936 | new NodeSub(new NodeInt(3), new NodeInt(4))), 1937 | new NodeSub(new NodeSub(new NodeInt(5), new NodeInt(6)), 1938 | new NodeSub(new NodeInt(7), new NodeInt(8)))), 1939 | new NodeSub(new NodeSub(new NodeSub(new NodeInt(9), new NodeInt(10)), 1940 | new NodeSub(new NodeInt(11), new NodeInt(12))), 1941 | new NodeSub(new NodeSub(new NodeInt(13), new NodeInt(14)), 1942 | new NodeSub(new NodeInt(15), new NodeInt(16)))) 1943 | )); 1944 | 1945 | Run(new NodeMul(new NodeInt(2), 1946 | new NodeMul(new NodeInt(3), 1947 | new NodeMul(new NodeInt(4), new NodeInt(5))))); 1948 | Run(new NodeMul(new NodeAdd(new NodeMul(new NodeInt(1), new NodeInt(2)), 1949 | new NodeMul(new NodeInt(3), new NodeInt(4))), 1950 | new NodeAdd(new NodeMul(new NodeInt(5), new NodeInt(6)), 1951 | new NodeMul(new NodeInt(7), new NodeInt(8))))); 1952 | Run(new NodeShLft(new NodeInt(4), new NodeInt(3))); 1953 | Run(new NodeShRht(new NodeInt(63), new NodeInt(3))); 1954 | Run(new NodeShArRht(new NodeInt(-57), new NodeInt(3))); 1955 | Run(new NodeShLft(new NodeShLft(new NodeInt(4), new NodeInt(3)), 1956 | new NodeInt(5))); 1957 | Run(new NodeShLft(new NodeInt(5), 1958 | new NodeShLft(new NodeInt(4), new NodeInt(3)))); 1959 | Run(new NodeMul(new NodeInt(3), 1960 | new NodeShLft(new NodeInt(1), new NodeInt(2)))); 1961 | Run(new NodeShLft(new NodeMul(new NodeInt(1), new NodeInt(2)), 1962 | new NodeInt(3))); 1963 | Run(new NodeShLft(new NodeInt(3), 1964 | new NodeMul(new NodeInt(1), new NodeInt(2)))); 1965 | Run(new NodeShLft(new NodeMul(new NodeInt(1), new NodeInt(2)), 1966 | new NodeMul(new NodeInt(3), new NodeInt(4)))); 1967 | Run(new NodeMul(new NodeShLft(new NodeInt(1), new NodeInt(2)), 1968 | new NodeShLft(new NodeInt(3), new NodeInt(4)))); 1969 | Run(new NodeShLft(new NodeAdd(new NodeInt(1), new NodeInt(2)), 1970 | new NodeAdd(new NodeInt(3), new NodeInt(4)))); 1971 | Run(new NodeMul( 1972 | new NodeMul(new NodeAdd(new NodeMul(new NodeInt(1), new NodeInt(2)), 1973 | new NodeMul(new NodeInt(3), new NodeInt(4))), 1974 | new NodeAdd(new NodeMul(new NodeInt(5), new NodeInt(6)), 1975 | new NodeMul(new NodeInt(7), new NodeInt(8)))), 1976 | new NodeMul(new NodeAdd(new NodeMul(new NodeInt(9), new NodeInt(10)), 1977 | new NodeMul(new NodeInt(11), new NodeInt(12))), 1978 | new NodeAdd(new NodeMul(new NodeInt(13), new NodeInt(14)), 1979 | new NodeMul(new NodeInt(15), new NodeInt(16)))) 1980 | )); 1981 | Run(new NodeMul( 1982 | new NodeMul(new NodeSub(new NodeMul(new NodeInt(1), new NodeInt(2)), 1983 | new NodeMul(new NodeInt(3), new NodeInt(4))), 1984 | new NodeSub(new NodeMul(new NodeInt(5), new NodeInt(6)), 1985 | new NodeMul(new NodeInt(7), new NodeInt(8)))), 1986 | new NodeMul(new NodeSub(new NodeMul(new NodeInt(9), new NodeInt(10)), 1987 | new NodeMul(new NodeInt(11), new NodeInt(12))), 1988 | new NodeSub(new NodeMul(new NodeInt(13), new NodeInt(14)), 1989 | new NodeMul(new NodeInt(15), new NodeInt(16)))) 1990 | )); 1991 | 1992 | Run(new NodeIDiv(new NodeInt(-8), new NodeInt(3))); 1993 | Run(new NodeIDiv(new NodeInt(8), new NodeInt(-3))); 1994 | Run(new NodeDiv(new NodeInt(8), new NodeInt(3))); 1995 | Run(new NodeIDiv(new NodeIDiv(new NodeInt(3*4*5), new NodeInt(-5)), 1996 | new NodeInt(4))); 1997 | Run(new NodeIDiv(new NodeInt(-3*4*5), 1998 | new NodeIDiv(new NodeInt(3*4*5), new NodeInt(-4)))); 1999 | Run(new NodeIDiv(new NodeInt(2*3*5*7), 2000 | new NodeIDiv(new NodeInt(2*3*5), 2001 | new NodeIDiv(new NodeInt(2*5), 2002 | new NodeInt(2))))); 2003 | Run(new NodeIDiv(new NodeIDiv(new NodeIDiv(new NodeInt(-2*3*5*7), 2004 | new NodeInt(7)), 2005 | new NodeInt(5)), 2006 | new NodeInt(3))); 2007 | Run(new NodeIDiv(new NodeAdd(new NodeIDiv(new NodeInt(2*7), new NodeInt(2)), 2008 | new NodeIDiv(new NodeInt(3*5), new NodeInt(3))), 2009 | new NodeAdd(new NodeIDiv(new NodeInt(2*3), new NodeInt(3)), 2010 | new NodeIDiv(new NodeInt(2*11), 2011 | new NodeInt(11))))); 2012 | Run(new NodeIDiv(new NodeInt(3*4), 2013 | new NodeShLft(new NodeInt(-1), new NodeInt(2)))); 2014 | Run(new NodeShLft(new NodeIDiv(new NodeInt(2*3), new NodeInt(3)), 2015 | new NodeInt(10))); 2016 | Run(new NodeShLft(new NodeInt(2), 2017 | new NodeIDiv(new NodeInt(-5*7), new NodeInt(-7)))); 2018 | Run(new NodeShLft(new NodeIDiv(new NodeInt(9), new NodeInt(3)), 2019 | new NodeIDiv(new NodeInt(8), new NodeInt(4)))); 2020 | Run(new NodeIDiv(new NodeShLft(new NodeInt(-2*3*5), new NodeInt(5)), 2021 | new NodeShLft(new NodeInt(2*3*5), new NodeInt(3)))); 2022 | 2023 | Run(new NodeIRem(new NodeInt(5), new NodeInt(3))); 2024 | Run(new NodeIRem(new NodeInt(-5), new NodeInt(3))); 2025 | Run(new NodeIRem(new NodeInt(5), new NodeInt(-3))); 2026 | Run(new NodeIRem(new NodeInt(-5), new NodeInt(-3))); 2027 | Run(new NodeRem(new NodeInt(5), new NodeInt(3))); 2028 | Run(new NodeIRem(new NodeInt(7), 2029 | new NodeShLft(new NodeInt(1), new NodeInt(2)))); 2030 | Run(new NodeShLft(new NodeIRem(new NodeInt(1), new NodeInt(2)), 2031 | new NodeInt(3))); 2032 | Run(new NodeShLft(new NodeInt(-3), 2033 | new NodeIRem(new NodeInt(1), new NodeInt(2)))); 2034 | Run(new NodeShLft(new NodeIRem(new NodeInt(1), new NodeInt(2)), 2035 | new NodeIRem(new NodeInt(3), new NodeInt(4)))); 2036 | Run(new NodeIRem(new NodeShLft(new NodeInt(1), new NodeInt(2)), 2037 | new NodeShLft(new NodeInt(3), new NodeInt(4)))); 2038 | 2039 | Run(new NodeAdd(new NodeInt(1000), new NodeLw(-1, new NodeInt(32768)))); 2040 | Run(new NodeShLft(new NodeInt(123), 2041 | new NodeLw(32768, 2042 | new NodeLw(32768, new NodeInt(32768))))); 2043 | Run(new NodeSw(new NodeInt(12345), new NodeInt(40000))); 2044 | Run(new NodeSw(new NodeLw(54321, new NodeInt(32768)), new NodeInt(40000))); 2045 | Run(new NodeSw(new NodeSw(new NodeLw(0x55AA, new NodeInt(50000)), 2046 | new NodeInt(32768)), 2047 | new NodeInt(40000))); 2048 | Run(new NodeMul(new NodeLw(-3*5, new NodeInt(40000)), 2049 | new NodeLw(-4*7, new NodeInt(50000)))); 2050 | Run(new NodeSw(new NodeSw(new NodeMul(new NodeLw(1000, new NodeInt(32768)), 2051 | new NodeLw(-1, new NodeInt(49152))), 2052 | new NodeInt(40000)), 2053 | new NodeInt(50000))); 2054 | Run(new NodeSw(new NodeAdd(new NodeLbz(255, new NodeInt(32768)), 2055 | new NodeLbs(-1, new NodeInt(49152))), 2056 | new NodeInt(40000))); 2057 | Run(new NodeSw(new NodeAdd(new NodeLbs(-1, new NodeInt(50000)), 2058 | new NodeLbz(255, new NodeInt(49152))), 2059 | new NodeInt(32768))); 2060 | Run(new NodeSb(new NodeLbs(0x5A, new NodeInt(40000)), new NodeInt(50000))); 2061 | Run(new NodeSb(new NodeLbs(0xFFA5, new NodeInt(32768)), new NodeInt(49152))); 2062 | Run(new NodeSb(new NodeLbz(0xA5, new NodeInt(40000)), new NodeInt(50000))); 2063 | Run(new NodeZext(new NodeSb(new NodeLb(0x5A, new NodeInt(40000)), 2064 | new NodeInt(50000)))); 2065 | Run(new NodeSext(new NodeSb(new NodeLb(0xFF, new NodeInt(40000)), 2066 | new NodeInt(50000)))); 2067 | Run(new NodeLw(55555, 2068 | new NodeAdd(new NodeLw(40000, new NodeInt(32768)), 2069 | new NodeShLft(new NodeLw(10, new NodeInt(50000)), 2070 | new NodeInt(1))))); 2071 | 2072 | Run(new NodeAdd(new NodeShLft(new NodeLbz(10, 2073 | new NodeAdd(new NodeInt(32768), 2074 | new NodeInt(0))), 2075 | new NodeInt(4)), 2076 | new NodeIDiv(new NodeInt(2), new NodeInt(1)))); 2077 | 2078 | Run(USE_MANY_REGS5()); // Use 5 regs out of 6, no spills. 2079 | Run(USE_MANY_REGS6()); // Use 6 regs out of 6, no spills. 2080 | Run(USE_MANY_REGS7()); // Use 7 regs, 1 spill. 2081 | Run(USE_MANY_REGS8()); // Use 8 regs, 2 spills in a branch. 2082 | 2083 | Run(new NodeCall(10, new NodeLabel("_ten"))); 2084 | Run(new NodeCall(8, 2085 | new NodeLabel("_popcnt"), 2086 | new NodeArgHolder(new NodeInt(0x55AA)))); 2087 | Run(new NodeCall(3, 2088 | new NodeLabel("_add"), 2089 | new NodeArgHolder(new NodeInt(1), 2090 | new NodeArgHolder(new NodeInt(2))))); 2091 | 2092 | Run(new NodeIDiv( 2093 | new NodeShLft( 2094 | new NodeInt(1), 2095 | new NodeCall( 2096 | 8, 2097 | new NodeLabel("_add"), 2098 | new NodeArgHolder(new NodeIRem(new NodeInt(5), new NodeInt(3)), 2099 | new NodeArgHolder(new NodeMul(new NodeInt(2), new NodeInt(3))) 2100 | ) 2101 | ) 2102 | ), 2103 | new NodeInt(4) 2104 | )); 2105 | 2106 | Run(new NodeAdd( 2107 | new NodeCall(3, 2108 | new NodeLabel("_add"), 2109 | new NodeArgHolder(new NodeInt(1), 2110 | new NodeArgHolder(new NodeInt(2)))), 2111 | // First call's result is spilled by second call. 2112 | new NodeCall(12, 2113 | new NodeLabel("_add"), 2114 | new NodeArgHolder(new NodeInt(4), 2115 | new NodeArgHolder(new NodeInt(8)))) 2116 | )); 2117 | 2118 | Run(new NodeCall( 2119 | 15, 2120 | new NodeLabel("_add"), 2121 | new NodeArgHolder( 2122 | new NodeCall( 2123 | 3, 2124 | new NodeLabel("_add"), 2125 | new NodeArgHolder( 2126 | new NodeInt(1), 2127 | new NodeArgHolder(new NodeInt(2))) 2128 | ), 2129 | new NodeArgHolder( 2130 | new NodeCall( 2131 | 12, 2132 | new NodeLabel("_add"), 2133 | new NodeArgHolder( 2134 | new NodeInt(4), 2135 | new NodeArgHolder(new NodeInt(8))) 2136 | ) 2137 | ) 2138 | ) 2139 | )); 2140 | 2141 | Run(new NodeAdd( 2142 | new NodeSub( 2143 | USE_MANY_REGS6(), 2144 | USE_MANY_REGS6() // One USE_MANY_REGS6()'s result is spilled. 2145 | ), 2146 | new NodeSub( 2147 | USE_MANY_REGS6(), // Spills result of above NodeSub(). 2148 | new NodeCall(10, // Spills result of above USE_MANY_REGS6(). 2149 | new NodeLabel("_ten")) 2150 | ) 2151 | )); 2152 | 2153 | std::cout << "\n" 2154 | " mov dx, msg_success\n" 2155 | " mov ah, 9\n" 2156 | " int 0x21\n" 2157 | " mov ax, 0x4C00\n" 2158 | " int 0x21\n"; 2159 | std::cout << "\n" 2160 | "no_memory:\n" 2161 | " mov dx, msg_memory\n" 2162 | " mov ah, 9\n" 2163 | " int 0x21\n" 2164 | " mov ax, 0x4C01\n" 2165 | " int 0x21\n"; 2166 | std::cout << "\n" 2167 | "failure:\n" 2168 | " mov dx, msg_failure\n" 2169 | " mov ah, 9\n" 2170 | " int 0x21\n" 2171 | " mov ax, 0x4C01\n" 2172 | " int 0x21\n"; 2173 | std::cout << "\n" 2174 | "msg_success:\n" 2175 | " db \"SUCCESS!\", 13, 10, \"$\"\n"; 2176 | std::cout << "\n" 2177 | "msg_memory:\n" 2178 | " db \"OUT OF MEMORY!\", 13, 10, \"$\"\n"; 2179 | std::cout << "\n" 2180 | "msg_failure:\n" 2181 | " db \"FAILURE!\", 13, 10, \"$\"\n"; 2182 | 2183 | std::cout << "\n" 2184 | "_ten:\n" 2185 | " mov ax, 10\n" 2186 | " ret\n"; 2187 | 2188 | std::cout << "\n" 2189 | "_popcnt:\n" 2190 | " push bp\n" 2191 | " mov bp, sp\n" 2192 | " mov dx, [bp+4]\n" 2193 | " mov cx, 16\n" 2194 | " xor ax, ax\n" 2195 | "_popcnt_loop:\n" 2196 | " add dx, dx\n" 2197 | " adc ax, 0\n" 2198 | " loop _popcnt_loop\n" 2199 | " pop bp\n" 2200 | " ret\n"; 2201 | 2202 | std::cout << "\n" 2203 | "_add:\n" 2204 | " push bp\n" 2205 | " mov bp, sp\n" 2206 | " mov ax, [bp+4]\n" 2207 | " add ax, [bp+6]\n" 2208 | " pop bp\n" 2209 | " ret\n"; 2210 | 2211 | return 0; 2212 | } 2213 | -------------------------------------------------------------------------------- /file.asm: -------------------------------------------------------------------------------- 1 | ; Compile this file with nasm: 2 | ; nasm file.asm -o file.com 3 | ; Run file.com in DOS, 32-bit Windows or DOSBox. 4 | 5 | bits 16 6 | cpu 8086 7 | org 0x100 8 | 9 | ; Shrink/extend the PSP block to 64KB. 10 | mov ah, 0x4a 11 | mov bx, 4096 12 | int 0x21 13 | jc no_memory 14 | mov sp, 0 ; stack at end of 64KB block 15 | 16 | ; 5 (vr0) 17 | ; ---- 18 | ; Regs needed (approximately): 1 19 | ; -------- 20 | ; ; vr0 21 | mov ax, 5 ; vr0 22 | ; ; vr0 23 | cmp ax, 5 ; vr0 24 | jne failure ; vr0 25 | 26 | ; neg (vr1) 27 | ; 7 (vr0) 28 | ; ---- 29 | ; Regs needed (approximately): 1 30 | ; -------- 31 | ; ; vr0 32 | mov ax, 7 ; vr0 33 | neg ax ; vr1 34 | ; ; vr1 35 | cmp ax, 65529 ; vr1 36 | jne failure ; vr1 37 | 38 | ; not (vr1) 39 | ; 7 (vr0) 40 | ; ---- 41 | ; Regs needed (approximately): 1 42 | ; -------- 43 | ; ; vr0 44 | mov ax, 7 ; vr0 45 | not ax ; vr1 46 | ; ; vr1 47 | cmp ax, 65528 ; vr1 48 | jne failure ; vr1 49 | 50 | ; 4 (vr1) 51 | ; add (vr2) 52 | ; 3 (vr0) 53 | ; ---- 54 | ; Regs needed (approximately): 2 55 | ; -------- 56 | ; ; vr0 57 | mov ax, 3 ; vr0 58 | mov cx, 4 ; vr1 59 | add ax, cx ; vr2 60 | ; ; vr2 61 | cmp ax, 7 ; vr2 62 | jne failure ; vr2 63 | 64 | ; 4 (vr4) 65 | ; or (vr5) 66 | ; 2 (vr3) 67 | ; xor (vr6) 68 | ; 3 (vr1) 69 | ; and (vr2) 70 | ; 1 (vr0) 71 | ; ---- 72 | ; Regs needed (approximately): 3 73 | ; -------- 74 | ; ; vr0 75 | mov ax, 1 ; vr0 76 | mov cx, 3 ; vr1 77 | and ax, cx ; vr2 78 | mov cx, 2 ; vr3 79 | mov dx, 4 ; vr4 80 | or cx, dx ; vr5 81 | xor ax, cx ; vr6 82 | ; ; vr6 83 | cmp ax, 7 ; vr6 84 | jne failure ; vr6 85 | 86 | ; 5 (vr1) 87 | ; mul (vr2) 88 | ; 3 (vr0) 89 | ; add (vr4) 90 | ; 2 (vr3) 91 | ; ---- 92 | ; Regs needed (approximately): 2 93 | ; -------- 94 | ; ; vr0 95 | mov ax, 3 ; vr0 96 | mov cx, 5 ; vr1 97 | mul cx ; vr2 98 | mov cx, 2 ; vr3 99 | add cx, ax ; vr4 100 | ; ; vr4 101 | cmp cx, 17 ; vr4 102 | jne failure ; vr4 103 | 104 | ; 7 (vr4) 105 | ; mul (vr5) 106 | ; 5 (vr3) 107 | ; add (vr6) 108 | ; 3 (vr1) 109 | ; mul (vr2) 110 | ; 2 (vr0) 111 | ; ---- 112 | ; Regs needed (approximately): 3 113 | ; -------- 114 | ; ; vr0 115 | mov ax, 2 ; vr0 116 | mov cx, 3 ; vr1 117 | mul cx ; vr2 118 | mov cx, 5 ; vr3 119 | mov dx, 7 ; vr4 120 | xchg ax, cx ; vr5 121 | mul dx ; vr5 122 | add cx, ax ; vr6 123 | ; ; vr6 124 | cmp cx, 41 ; vr6 125 | jne failure ; vr6 126 | 127 | ; 16 (vr26) 128 | ; add (vr27) 129 | ; 15 (vr25) 130 | ; add (vr28) 131 | ; 14 (vr23) 132 | ; add (vr24) 133 | ; 13 (vr22) 134 | ; add (vr29) 135 | ; 12 (vr19) 136 | ; add (vr20) 137 | ; 11 (vr18) 138 | ; add (vr21) 139 | ; 10 (vr16) 140 | ; add (vr17) 141 | ; 9 (vr15) 142 | ; add (vr30) 143 | ; 8 (vr11) 144 | ; add (vr12) 145 | ; 7 (vr10) 146 | ; add (vr13) 147 | ; 6 (vr8) 148 | ; add (vr9) 149 | ; 5 (vr7) 150 | ; add (vr14) 151 | ; 4 (vr4) 152 | ; add (vr5) 153 | ; 3 (vr3) 154 | ; add (vr6) 155 | ; 2 (vr1) 156 | ; add (vr2) 157 | ; 1 (vr0) 158 | ; ---- 159 | ; Regs needed (approximately): 5 160 | ; -------- 161 | ; ; vr0 162 | mov ax, 1 ; vr0 163 | mov cx, 2 ; vr1 164 | add ax, cx ; vr2 165 | mov cx, 3 ; vr3 166 | mov dx, 4 ; vr4 167 | add cx, dx ; vr5 168 | add ax, cx ; vr6 169 | mov cx, 5 ; vr7 170 | mov dx, 6 ; vr8 171 | add cx, dx ; vr9 172 | mov dx, 7 ; vr10 173 | mov bx, 8 ; vr11 174 | add dx, bx ; vr12 175 | add cx, dx ; vr13 176 | add ax, cx ; vr14 177 | mov cx, 9 ; vr15 178 | mov dx, 10 ; vr16 179 | add cx, dx ; vr17 180 | mov dx, 11 ; vr18 181 | mov bx, 12 ; vr19 182 | add dx, bx ; vr20 183 | add cx, dx ; vr21 184 | mov dx, 13 ; vr22 185 | mov bx, 14 ; vr23 186 | add dx, bx ; vr24 187 | mov bx, 15 ; vr25 188 | mov si, 16 ; vr26 189 | add bx, si ; vr27 190 | add dx, bx ; vr28 191 | add cx, dx ; vr29 192 | add ax, cx ; vr30 193 | ; ; vr30 194 | cmp ax, 136 ; vr30 195 | jne failure ; vr30 196 | 197 | ; 16 (vr26) 198 | ; sub (vr27) 199 | ; 15 (vr25) 200 | ; sub (vr28) 201 | ; 14 (vr23) 202 | ; sub (vr24) 203 | ; 13 (vr22) 204 | ; sub (vr29) 205 | ; 12 (vr19) 206 | ; sub (vr20) 207 | ; 11 (vr18) 208 | ; sub (vr21) 209 | ; 10 (vr16) 210 | ; sub (vr17) 211 | ; 9 (vr15) 212 | ; sub (vr30) 213 | ; 8 (vr11) 214 | ; sub (vr12) 215 | ; 7 (vr10) 216 | ; sub (vr13) 217 | ; 6 (vr8) 218 | ; sub (vr9) 219 | ; 5 (vr7) 220 | ; sub (vr14) 221 | ; 4 (vr4) 222 | ; sub (vr5) 223 | ; 3 (vr3) 224 | ; sub (vr6) 225 | ; 2 (vr1) 226 | ; sub (vr2) 227 | ; 1 (vr0) 228 | ; ---- 229 | ; Regs needed (approximately): 5 230 | ; -------- 231 | ; ; vr0 232 | mov ax, 1 ; vr0 233 | mov cx, 2 ; vr1 234 | sub ax, cx ; vr2 235 | mov cx, 3 ; vr3 236 | mov dx, 4 ; vr4 237 | sub cx, dx ; vr5 238 | sub ax, cx ; vr6 239 | mov cx, 5 ; vr7 240 | mov dx, 6 ; vr8 241 | sub cx, dx ; vr9 242 | mov dx, 7 ; vr10 243 | mov bx, 8 ; vr11 244 | sub dx, bx ; vr12 245 | sub cx, dx ; vr13 246 | sub ax, cx ; vr14 247 | mov cx, 9 ; vr15 248 | mov dx, 10 ; vr16 249 | sub cx, dx ; vr17 250 | mov dx, 11 ; vr18 251 | mov bx, 12 ; vr19 252 | sub dx, bx ; vr20 253 | sub cx, dx ; vr21 254 | mov dx, 13 ; vr22 255 | mov bx, 14 ; vr23 256 | sub dx, bx ; vr24 257 | mov bx, 15 ; vr25 258 | mov si, 16 ; vr26 259 | sub bx, si ; vr27 260 | sub dx, bx ; vr28 261 | sub cx, dx ; vr29 262 | sub ax, cx ; vr30 263 | ; ; vr30 264 | cmp ax, 0 ; vr30 265 | jne failure ; vr30 266 | 267 | ; 5 (vr1) 268 | ; mul (vr2) 269 | ; 4 (vr0) 270 | ; mul (vr4) 271 | ; 3 (vr3) 272 | ; mul (vr6) 273 | ; 2 (vr5) 274 | ; ---- 275 | ; Regs needed (approximately): 2 276 | ; -------- 277 | ; ; vr0 278 | mov ax, 4 ; vr0 279 | mov cx, 5 ; vr1 280 | mul cx ; vr2 281 | mov cx, 3 ; vr3 282 | mul cx ; vr4 283 | mov cx, 2 ; vr5 284 | mul cx ; vr6 285 | ; ; vr6 286 | cmp ax, 120 ; vr6 287 | jne failure ; vr6 288 | 289 | ; 8 (vr11) 290 | ; mul (vr12) 291 | ; 7 (vr10) 292 | ; add (vr13) 293 | ; 6 (vr8) 294 | ; mul (vr9) 295 | ; 5 (vr7) 296 | ; mul (vr14) 297 | ; 4 (vr4) 298 | ; mul (vr5) 299 | ; 3 (vr3) 300 | ; add (vr6) 301 | ; 2 (vr1) 302 | ; mul (vr2) 303 | ; 1 (vr0) 304 | ; ---- 305 | ; Regs needed (approximately): 4 306 | ; -------- 307 | ; ; vr0 308 | mov ax, 1 ; vr0 309 | mov cx, 2 ; vr1 310 | mul cx ; vr2 311 | mov cx, 3 ; vr3 312 | mov dx, 4 ; vr4 313 | xchg ax, cx ; vr5 314 | mul dx ; vr5 315 | add ax, cx ; vr6 316 | mov cx, 5 ; vr7 317 | mov dx, 6 ; vr8 318 | xchg ax, cx ; vr9 319 | mul dx ; vr9 320 | mov dx, 7 ; vr10 321 | mov bx, 8 ; vr11 322 | xchg ax, bx ; vr12 323 | mul dx ; vr12 324 | add ax, bx ; vr13 325 | mul cx ; vr14 326 | ; ; vr14 327 | cmp ax, 1204 ; vr14 328 | jne failure ; vr14 329 | 330 | ; 3 (vr0) 331 | ; shl (vr2) 332 | ; 4 (vr1) 333 | ; ---- 334 | ; Regs needed (approximately): 2 335 | ; -------- 336 | ; ; vr0 337 | mov cx, 3 ; vr0 338 | mov ax, 4 ; vr1 339 | shl ax, cl ; vr2 340 | ; ; vr2 341 | cmp ax, 32 ; vr2 342 | jne failure ; vr2 343 | 344 | ; 3 (vr0) 345 | ; shr (vr2) 346 | ; 63 (vr1) 347 | ; ---- 348 | ; Regs needed (approximately): 2 349 | ; -------- 350 | ; ; vr0 351 | mov cx, 3 ; vr0 352 | mov ax, 63 ; vr1 353 | shr ax, cl ; vr2 354 | ; ; vr2 355 | cmp ax, 7 ; vr2 356 | jne failure ; vr2 357 | 358 | ; 3 (vr0) 359 | ; sar (vr2) 360 | ; 65479 (vr1) 361 | ; ---- 362 | ; Regs needed (approximately): 2 363 | ; -------- 364 | ; ; vr0 365 | mov cx, 3 ; vr0 366 | mov ax, 65479 ; vr1 367 | sar ax, cl ; vr2 368 | ; ; vr2 369 | cmp ax, 65528 ; vr2 370 | jne failure ; vr2 371 | 372 | ; 5 (vr3) 373 | ; shl (vr4) 374 | ; 3 (vr0) 375 | ; shl (vr2) 376 | ; 4 (vr1) 377 | ; ---- 378 | ; Regs needed (approximately): 2 379 | ; -------- 380 | ; ; vr0 381 | mov cx, 3 ; vr0 382 | mov ax, 4 ; vr1 383 | shl ax, cl ; vr2 384 | mov cx, 5 ; vr3 385 | shl ax, cl ; vr4 386 | ; ; vr4 387 | cmp ax, 1024 ; vr4 388 | jne failure ; vr4 389 | 390 | ; 3 (vr0) 391 | ; shl (vr2) 392 | ; 4 (vr1) 393 | ; shl (vr4) 394 | ; 5 (vr3) 395 | ; ---- 396 | ; Regs needed (approximately): 2 397 | ; -------- 398 | ; ; vr0 399 | mov cx, 3 ; vr0 400 | mov ax, 4 ; vr1 401 | shl ax, cl ; vr2 402 | mov dx, 5 ; vr3 403 | mov cx, ax ; vr4 404 | shl dx, cl ; vr4 405 | ; ; vr4 406 | cmp dx, 5 ; vr4 407 | jne failure ; vr4 408 | 409 | ; 2 (vr0) 410 | ; shl (vr2) 411 | ; 1 (vr1) 412 | ; mul (vr4) 413 | ; 3 (vr3) 414 | ; ---- 415 | ; Regs needed (approximately): 2 416 | ; -------- 417 | ; ; vr0 418 | mov cx, 2 ; vr0 419 | mov ax, 1 ; vr1 420 | shl ax, cl ; vr2 421 | mov cx, 3 ; vr3 422 | mul cx ; vr4 423 | ; ; vr4 424 | cmp ax, 12 ; vr4 425 | jne failure ; vr4 426 | 427 | ; 3 (vr3) 428 | ; shl (vr4) 429 | ; 2 (vr1) 430 | ; mul (vr2) 431 | ; 1 (vr0) 432 | ; ---- 433 | ; Regs needed (approximately): 2 434 | ; -------- 435 | ; ; vr0 436 | mov ax, 1 ; vr0 437 | mov cx, 2 ; vr1 438 | mul cx ; vr2 439 | mov cx, 3 ; vr3 440 | shl ax, cl ; vr4 441 | ; ; vr4 442 | cmp ax, 16 ; vr4 443 | jne failure ; vr4 444 | 445 | ; 2 (vr1) 446 | ; mul (vr2) 447 | ; 1 (vr0) 448 | ; shl (vr4) 449 | ; 3 (vr3) 450 | ; ---- 451 | ; Regs needed (approximately): 2 452 | ; -------- 453 | ; ; vr0 454 | mov ax, 1 ; vr0 455 | mov cx, 2 ; vr1 456 | mul cx ; vr2 457 | mov dx, 3 ; vr3 458 | mov cx, ax ; vr4 459 | shl dx, cl ; vr4 460 | ; ; vr4 461 | cmp dx, 12 ; vr4 462 | jne failure ; vr4 463 | 464 | ; 4 (vr1) 465 | ; mul (vr2) 466 | ; 3 (vr0) 467 | ; shl (vr6) 468 | ; 2 (vr4) 469 | ; mul (vr5) 470 | ; 1 (vr3) 471 | ; ---- 472 | ; Regs needed (approximately): 3 473 | ; -------- 474 | ; ; vr0 475 | mov ax, 3 ; vr0 476 | mov cx, 4 ; vr1 477 | mul cx ; vr2 478 | mov cx, 1 ; vr3 479 | mov dx, 2 ; vr4 480 | xchg ax, cx ; vr5 481 | mul dx ; vr5 482 | shl ax, cl ; vr6 483 | ; ; vr6 484 | cmp ax, 8192 ; vr6 485 | jne failure ; vr6 486 | 487 | ; 4 (vr3) 488 | ; shl (vr5) 489 | ; 3 (vr4) 490 | ; mul (vr6) 491 | ; 2 (vr0) 492 | ; shl (vr2) 493 | ; 1 (vr1) 494 | ; ---- 495 | ; Regs needed (approximately): 3 496 | ; -------- 497 | ; ; vr0 498 | mov cx, 2 ; vr0 499 | mov ax, 1 ; vr1 500 | shl ax, cl ; vr2 501 | mov cx, 4 ; vr3 502 | mov dx, 3 ; vr4 503 | shl dx, cl ; vr5 504 | mul dx ; vr6 505 | ; ; vr6 506 | cmp ax, 192 ; vr6 507 | jne failure ; vr6 508 | 509 | ; 4 (vr1) 510 | ; add (vr2) 511 | ; 3 (vr0) 512 | ; shl (vr6) 513 | ; 2 (vr4) 514 | ; add (vr5) 515 | ; 1 (vr3) 516 | ; ---- 517 | ; Regs needed (approximately): 3 518 | ; -------- 519 | ; ; vr0 520 | mov cx, 3 ; vr0 521 | mov ax, 4 ; vr1 522 | add cx, ax ; vr2 523 | mov ax, 1 ; vr3 524 | mov dx, 2 ; vr4 525 | add ax, dx ; vr5 526 | shl ax, cl ; vr6 527 | ; ; vr6 528 | cmp ax, 384 ; vr6 529 | jne failure ; vr6 530 | 531 | ; 16 (vr26) 532 | ; mul (vr27) 533 | ; 15 (vr25) 534 | ; add (vr28) 535 | ; 14 (vr23) 536 | ; mul (vr24) 537 | ; 13 (vr22) 538 | ; mul (vr29) 539 | ; 12 (vr19) 540 | ; mul (vr20) 541 | ; 11 (vr18) 542 | ; add (vr21) 543 | ; 10 (vr16) 544 | ; mul (vr17) 545 | ; 9 (vr15) 546 | ; mul (vr30) 547 | ; 8 (vr11) 548 | ; mul (vr12) 549 | ; 7 (vr10) 550 | ; add (vr13) 551 | ; 6 (vr8) 552 | ; mul (vr9) 553 | ; 5 (vr7) 554 | ; mul (vr14) 555 | ; 4 (vr4) 556 | ; mul (vr5) 557 | ; 3 (vr3) 558 | ; add (vr6) 559 | ; 2 (vr1) 560 | ; mul (vr2) 561 | ; 1 (vr0) 562 | ; ---- 563 | ; Regs needed (approximately): 5 564 | ; -------- 565 | ; ; vr0 566 | mov ax, 1 ; vr0 567 | mov cx, 2 ; vr1 568 | mul cx ; vr2 569 | mov cx, 3 ; vr3 570 | mov dx, 4 ; vr4 571 | xchg ax, cx ; vr5 572 | mul dx ; vr5 573 | add ax, cx ; vr6 574 | mov cx, 5 ; vr7 575 | mov dx, 6 ; vr8 576 | xchg ax, cx ; vr9 577 | mul dx ; vr9 578 | mov dx, 7 ; vr10 579 | mov bx, 8 ; vr11 580 | xchg ax, bx ; vr12 581 | mul dx ; vr12 582 | add ax, bx ; vr13 583 | mul cx ; vr14 584 | mov cx, 9 ; vr15 585 | mov dx, 10 ; vr16 586 | xchg ax, cx ; vr17 587 | mul dx ; vr17 588 | mov dx, 11 ; vr18 589 | mov bx, 12 ; vr19 590 | xchg ax, bx ; vr20 591 | mul dx ; vr20 592 | add ax, bx ; vr21 593 | mov dx, 13 ; vr22 594 | mov bx, 14 ; vr23 595 | xchg ax, bx ; vr24 596 | mul dx ; vr24 597 | mov dx, 15 ; vr25 598 | mov si, 16 ; vr26 599 | xchg ax, si ; vr27 600 | mul dx ; vr27 601 | add ax, si ; vr28 602 | mul bx ; vr29 603 | mul cx ; vr30 604 | ; ; vr30 605 | cmp ax, 8080 ; vr30 606 | jne failure ; vr30 607 | 608 | ; 16 (vr26) 609 | ; mul (vr27) 610 | ; 15 (vr25) 611 | ; sub (vr28) 612 | ; 14 (vr23) 613 | ; mul (vr24) 614 | ; 13 (vr22) 615 | ; mul (vr29) 616 | ; 12 (vr19) 617 | ; mul (vr20) 618 | ; 11 (vr18) 619 | ; sub (vr21) 620 | ; 10 (vr16) 621 | ; mul (vr17) 622 | ; 9 (vr15) 623 | ; mul (vr30) 624 | ; 8 (vr11) 625 | ; mul (vr12) 626 | ; 7 (vr10) 627 | ; sub (vr13) 628 | ; 6 (vr8) 629 | ; mul (vr9) 630 | ; 5 (vr7) 631 | ; mul (vr14) 632 | ; 4 (vr4) 633 | ; mul (vr5) 634 | ; 3 (vr3) 635 | ; sub (vr6) 636 | ; 2 (vr1) 637 | ; mul (vr2) 638 | ; 1 (vr0) 639 | ; ---- 640 | ; Regs needed (approximately): 5 641 | ; -------- 642 | ; ; vr0 643 | mov ax, 1 ; vr0 644 | mov cx, 2 ; vr1 645 | mul cx ; vr2 646 | mov cx, 3 ; vr3 647 | mov dx, 4 ; vr4 648 | xchg ax, cx ; vr5 649 | mul dx ; vr5 650 | sub cx, ax ; vr6 651 | mov ax, 5 ; vr7 652 | mov dx, 6 ; vr8 653 | mul dx ; vr9 654 | mov dx, 7 ; vr10 655 | mov bx, 8 ; vr11 656 | xchg ax, bx ; vr12 657 | mul dx ; vr12 658 | sub bx, ax ; vr13 659 | mov ax, cx ; vr14 660 | mul bx ; vr14 661 | mov cx, 9 ; vr15 662 | mov dx, 10 ; vr16 663 | xchg ax, cx ; vr17 664 | mul dx ; vr17 665 | mov dx, 11 ; vr18 666 | mov bx, 12 ; vr19 667 | xchg ax, bx ; vr20 668 | mul dx ; vr20 669 | sub bx, ax ; vr21 670 | mov ax, 13 ; vr22 671 | mov dx, 14 ; vr23 672 | mul dx ; vr24 673 | mov dx, 15 ; vr25 674 | mov si, 16 ; vr26 675 | xchg ax, si ; vr27 676 | mul dx ; vr27 677 | sub si, ax ; vr28 678 | mov ax, bx ; vr29 679 | mul si ; vr29 680 | mul cx ; vr30 681 | ; ; vr30 682 | cmp ax, 43536 ; vr30 683 | jne failure ; vr30 684 | 685 | ; 3 (vr1) 686 | ; idiv (vr2) 687 | ; 65528 (vr0) 688 | ; ---- 689 | ; Regs needed (approximately): 3 690 | ; -------- 691 | ; ; vr0 692 | mov ax, 65528 ; vr0 693 | mov cx, 3 ; vr1 694 | cwd ; vr2 695 | idiv cx ; vr2 696 | ; ; vr2 697 | cmp ax, 65534 ; vr2 698 | jne failure ; vr2 699 | 700 | ; 65533 (vr1) 701 | ; idiv (vr2) 702 | ; 8 (vr0) 703 | ; ---- 704 | ; Regs needed (approximately): 3 705 | ; -------- 706 | ; ; vr0 707 | mov ax, 8 ; vr0 708 | mov cx, 65533 ; vr1 709 | cwd ; vr2 710 | idiv cx ; vr2 711 | ; ; vr2 712 | cmp ax, 65534 ; vr2 713 | jne failure ; vr2 714 | 715 | ; 3 (vr1) 716 | ; div (vr2) 717 | ; 8 (vr0) 718 | ; ---- 719 | ; Regs needed (approximately): 3 720 | ; -------- 721 | ; ; vr0 722 | mov ax, 8 ; vr0 723 | mov cx, 3 ; vr1 724 | xor dx, dx ; vr2 725 | div cx ; vr2 726 | ; ; vr2 727 | cmp ax, 2 ; vr2 728 | jne failure ; vr2 729 | 730 | ; 4 (vr3) 731 | ; idiv (vr4) 732 | ; 65531 (vr1) 733 | ; idiv (vr2) 734 | ; 60 (vr0) 735 | ; ---- 736 | ; Regs needed (approximately): 3 737 | ; -------- 738 | ; ; vr0 739 | mov ax, 60 ; vr0 740 | mov cx, 65531 ; vr1 741 | cwd ; vr2 742 | idiv cx ; vr2 743 | mov cx, 4 ; vr3 744 | cwd ; vr4 745 | idiv cx ; vr4 746 | ; ; vr4 747 | cmp ax, 65533 ; vr4 748 | jne failure ; vr4 749 | 750 | ; 65532 (vr1) 751 | ; idiv (vr2) 752 | ; 60 (vr0) 753 | ; idiv (vr4) 754 | ; 65476 (vr3) 755 | ; ---- 756 | ; Regs needed (approximately): 3 757 | ; -------- 758 | ; ; vr0 759 | mov ax, 60 ; vr0 760 | mov cx, 65532 ; vr1 761 | cwd ; vr2 762 | idiv cx ; vr2 763 | mov cx, 65476 ; vr3 764 | xchg ax, cx ; vr4 765 | cwd ; vr4 766 | idiv cx ; vr4 767 | ; ; vr4 768 | cmp ax, 4 ; vr4 769 | jne failure ; vr4 770 | 771 | ; 2 (vr1) 772 | ; idiv (vr2) 773 | ; 10 (vr0) 774 | ; idiv (vr4) 775 | ; 30 (vr3) 776 | ; idiv (vr6) 777 | ; 210 (vr5) 778 | ; ---- 779 | ; Regs needed (approximately): 3 780 | ; -------- 781 | ; ; vr0 782 | mov ax, 10 ; vr0 783 | mov cx, 2 ; vr1 784 | cwd ; vr2 785 | idiv cx ; vr2 786 | mov cx, 30 ; vr3 787 | xchg ax, cx ; vr4 788 | cwd ; vr4 789 | idiv cx ; vr4 790 | mov cx, 210 ; vr5 791 | xchg ax, cx ; vr6 792 | cwd ; vr6 793 | idiv cx ; vr6 794 | ; ; vr6 795 | cmp ax, 35 ; vr6 796 | jne failure ; vr6 797 | 798 | ; 3 (vr5) 799 | ; idiv (vr6) 800 | ; 5 (vr3) 801 | ; idiv (vr4) 802 | ; 7 (vr1) 803 | ; idiv (vr2) 804 | ; 65326 (vr0) 805 | ; ---- 806 | ; Regs needed (approximately): 3 807 | ; -------- 808 | ; ; vr0 809 | mov ax, 65326 ; vr0 810 | mov cx, 7 ; vr1 811 | cwd ; vr2 812 | idiv cx ; vr2 813 | mov cx, 5 ; vr3 814 | cwd ; vr4 815 | idiv cx ; vr4 816 | mov cx, 3 ; vr5 817 | cwd ; vr6 818 | idiv cx ; vr6 819 | ; ; vr6 820 | cmp ax, 65534 ; vr6 821 | jne failure ; vr6 822 | 823 | ; 11 (vr11) 824 | ; idiv (vr12) 825 | ; 22 (vr10) 826 | ; add (vr13) 827 | ; 3 (vr8) 828 | ; idiv (vr9) 829 | ; 6 (vr7) 830 | ; idiv (vr14) 831 | ; 3 (vr4) 832 | ; idiv (vr5) 833 | ; 15 (vr3) 834 | ; add (vr6) 835 | ; 2 (vr1) 836 | ; idiv (vr2) 837 | ; 14 (vr0) 838 | ; ---- 839 | ; Regs needed (approximately): 5 840 | ; -------- 841 | ; ; vr0 842 | mov ax, 14 ; vr0 843 | mov cx, 2 ; vr1 844 | cwd ; vr2 845 | idiv cx ; vr2 846 | mov cx, 15 ; vr3 847 | mov bx, 3 ; vr4 848 | xchg ax, cx ; vr5 849 | cwd ; vr5 850 | idiv bx ; vr5 851 | add ax, cx ; vr6 852 | mov cx, 6 ; vr7 853 | mov bx, 3 ; vr8 854 | xchg ax, cx ; vr9 855 | cwd ; vr9 856 | idiv bx ; vr9 857 | mov dx, 22 ; vr10 858 | mov bx, 11 ; vr11 859 | xchg ax, dx ; vr12 860 | mov si, dx ; vr12 861 | cwd ; vr12 862 | idiv bx ; vr12 863 | add si, ax ; vr13 864 | mov ax, cx ; vr14 865 | cwd ; vr14 866 | idiv si ; vr14 867 | ; ; vr14 868 | cmp ax, 3 ; vr14 869 | jne failure ; vr14 870 | 871 | ; 2 (vr0) 872 | ; shl (vr2) 873 | ; 65535 (vr1) 874 | ; idiv (vr4) 875 | ; 12 (vr3) 876 | ; ---- 877 | ; Regs needed (approximately): 3 878 | ; -------- 879 | ; ; vr0 880 | mov cx, 2 ; vr0 881 | mov bx, 65535 ; vr1 882 | shl bx, cl ; vr2 883 | mov ax, 12 ; vr3 884 | cwd ; vr4 885 | idiv bx ; vr4 886 | ; ; vr4 887 | cmp ax, 65533 ; vr4 888 | jne failure ; vr4 889 | 890 | ; 10 (vr3) 891 | ; shl (vr4) 892 | ; 3 (vr1) 893 | ; idiv (vr2) 894 | ; 6 (vr0) 895 | ; ---- 896 | ; Regs needed (approximately): 3 897 | ; -------- 898 | ; ; vr0 899 | mov ax, 6 ; vr0 900 | mov cx, 3 ; vr1 901 | cwd ; vr2 902 | idiv cx ; vr2 903 | mov cx, 10 ; vr3 904 | shl ax, cl ; vr4 905 | ; ; vr4 906 | cmp ax, 2048 ; vr4 907 | jne failure ; vr4 908 | 909 | ; 65529 (vr1) 910 | ; idiv (vr2) 911 | ; 65501 (vr0) 912 | ; shl (vr4) 913 | ; 2 (vr3) 914 | ; ---- 915 | ; Regs needed (approximately): 3 916 | ; -------- 917 | ; ; vr0 918 | mov ax, 65501 ; vr0 919 | mov cx, 65529 ; vr1 920 | cwd ; vr2 921 | idiv cx ; vr2 922 | mov dx, 2 ; vr3 923 | mov cx, ax ; vr4 924 | shl dx, cl ; vr4 925 | ; ; vr4 926 | cmp dx, 64 ; vr4 927 | jne failure ; vr4 928 | 929 | ; 4 (vr1) 930 | ; idiv (vr2) 931 | ; 8 (vr0) 932 | ; shl (vr6) 933 | ; 3 (vr4) 934 | ; idiv (vr5) 935 | ; 9 (vr3) 936 | ; ---- 937 | ; Regs needed (approximately): 4 938 | ; -------- 939 | ; ; vr0 940 | mov ax, 8 ; vr0 941 | mov cx, 4 ; vr1 942 | cwd ; vr2 943 | idiv cx ; vr2 944 | mov cx, 9 ; vr3 945 | mov bx, 3 ; vr4 946 | xchg ax, cx ; vr5 947 | cwd ; vr5 948 | idiv bx ; vr5 949 | shl ax, cl ; vr6 950 | ; ; vr6 951 | cmp ax, 12 ; vr6 952 | jne failure ; vr6 953 | 954 | ; 3 (vr3) 955 | ; shl (vr5) 956 | ; 30 (vr4) 957 | ; idiv (vr6) 958 | ; 5 (vr0) 959 | ; shl (vr2) 960 | ; 65506 (vr1) 961 | ; ---- 962 | ; Regs needed (approximately): 3 963 | ; -------- 964 | ; ; vr0 965 | mov cx, 5 ; vr0 966 | mov ax, 65506 ; vr1 967 | shl ax, cl ; vr2 968 | mov cx, 3 ; vr3 969 | mov bx, 30 ; vr4 970 | shl bx, cl ; vr5 971 | cwd ; vr6 972 | idiv bx ; vr6 973 | ; ; vr6 974 | cmp ax, 65532 ; vr6 975 | jne failure ; vr6 976 | 977 | ; 3 (vr1) 978 | ; irem (vr2) 979 | ; 5 (vr0) 980 | ; ---- 981 | ; Regs needed (approximately): 3 982 | ; -------- 983 | ; ; vr0 984 | mov ax, 5 ; vr0 985 | mov cx, 3 ; vr1 986 | cwd ; vr2 987 | idiv cx ; vr2 988 | ; ; vr2 989 | cmp dx, 2 ; vr2 990 | jne failure ; vr2 991 | 992 | ; 3 (vr1) 993 | ; irem (vr2) 994 | ; 65531 (vr0) 995 | ; ---- 996 | ; Regs needed (approximately): 3 997 | ; -------- 998 | ; ; vr0 999 | mov ax, 65531 ; vr0 1000 | mov cx, 3 ; vr1 1001 | cwd ; vr2 1002 | idiv cx ; vr2 1003 | ; ; vr2 1004 | cmp dx, 65534 ; vr2 1005 | jne failure ; vr2 1006 | 1007 | ; 65533 (vr1) 1008 | ; irem (vr2) 1009 | ; 5 (vr0) 1010 | ; ---- 1011 | ; Regs needed (approximately): 3 1012 | ; -------- 1013 | ; ; vr0 1014 | mov ax, 5 ; vr0 1015 | mov cx, 65533 ; vr1 1016 | cwd ; vr2 1017 | idiv cx ; vr2 1018 | ; ; vr2 1019 | cmp dx, 2 ; vr2 1020 | jne failure ; vr2 1021 | 1022 | ; 65533 (vr1) 1023 | ; irem (vr2) 1024 | ; 65531 (vr0) 1025 | ; ---- 1026 | ; Regs needed (approximately): 3 1027 | ; -------- 1028 | ; ; vr0 1029 | mov ax, 65531 ; vr0 1030 | mov cx, 65533 ; vr1 1031 | cwd ; vr2 1032 | idiv cx ; vr2 1033 | ; ; vr2 1034 | cmp dx, 65534 ; vr2 1035 | jne failure ; vr2 1036 | 1037 | ; 3 (vr1) 1038 | ; rem (vr2) 1039 | ; 5 (vr0) 1040 | ; ---- 1041 | ; Regs needed (approximately): 3 1042 | ; -------- 1043 | ; ; vr0 1044 | mov ax, 5 ; vr0 1045 | mov cx, 3 ; vr1 1046 | xor dx, dx ; vr2 1047 | div cx ; vr2 1048 | ; ; vr2 1049 | cmp dx, 2 ; vr2 1050 | jne failure ; vr2 1051 | 1052 | ; 2 (vr0) 1053 | ; shl (vr2) 1054 | ; 1 (vr1) 1055 | ; irem (vr4) 1056 | ; 7 (vr3) 1057 | ; ---- 1058 | ; Regs needed (approximately): 3 1059 | ; -------- 1060 | ; ; vr0 1061 | mov cx, 2 ; vr0 1062 | mov bx, 1 ; vr1 1063 | shl bx, cl ; vr2 1064 | mov ax, 7 ; vr3 1065 | cwd ; vr4 1066 | idiv bx ; vr4 1067 | ; ; vr4 1068 | cmp dx, 3 ; vr4 1069 | jne failure ; vr4 1070 | 1071 | ; 3 (vr3) 1072 | ; shl (vr4) 1073 | ; 2 (vr1) 1074 | ; irem (vr2) 1075 | ; 1 (vr0) 1076 | ; ---- 1077 | ; Regs needed (approximately): 3 1078 | ; -------- 1079 | ; ; vr0 1080 | mov ax, 1 ; vr0 1081 | mov cx, 2 ; vr1 1082 | cwd ; vr2 1083 | idiv cx ; vr2 1084 | mov cx, 3 ; vr3 1085 | shl dx, cl ; vr4 1086 | ; ; vr4 1087 | cmp dx, 8 ; vr4 1088 | jne failure ; vr4 1089 | 1090 | ; 2 (vr1) 1091 | ; irem (vr2) 1092 | ; 1 (vr0) 1093 | ; shl (vr4) 1094 | ; 65533 (vr3) 1095 | ; ---- 1096 | ; Regs needed (approximately): 3 1097 | ; -------- 1098 | ; ; vr0 1099 | mov ax, 1 ; vr0 1100 | mov cx, 2 ; vr1 1101 | cwd ; vr2 1102 | idiv cx ; vr2 1103 | mov ax, 65533 ; vr3 1104 | mov cx, dx ; vr4 1105 | shl ax, cl ; vr4 1106 | ; ; vr4 1107 | cmp ax, 65530 ; vr4 1108 | jne failure ; vr4 1109 | 1110 | ; 4 (vr1) 1111 | ; irem (vr2) 1112 | ; 3 (vr0) 1113 | ; shl (vr6) 1114 | ; 2 (vr4) 1115 | ; irem (vr5) 1116 | ; 1 (vr3) 1117 | ; ---- 1118 | ; Regs needed (approximately): 4 1119 | ; -------- 1120 | ; ; vr0 1121 | mov ax, 3 ; vr0 1122 | mov cx, 4 ; vr1 1123 | cwd ; vr2 1124 | idiv cx ; vr2 1125 | mov ax, 1 ; vr3 1126 | mov cx, 2 ; vr4 1127 | mov bx, dx ; vr5 1128 | cwd ; vr5 1129 | idiv cx ; vr5 1130 | mov cx, bx ; vr6 1131 | shl dx, cl ; vr6 1132 | ; ; vr6 1133 | cmp dx, 8 ; vr6 1134 | jne failure ; vr6 1135 | 1136 | ; 4 (vr3) 1137 | ; shl (vr5) 1138 | ; 3 (vr4) 1139 | ; irem (vr6) 1140 | ; 2 (vr0) 1141 | ; shl (vr2) 1142 | ; 1 (vr1) 1143 | ; ---- 1144 | ; Regs needed (approximately): 3 1145 | ; -------- 1146 | ; ; vr0 1147 | mov cx, 2 ; vr0 1148 | mov ax, 1 ; vr1 1149 | shl ax, cl ; vr2 1150 | mov cx, 4 ; vr3 1151 | mov bx, 3 ; vr4 1152 | shl bx, cl ; vr5 1153 | cwd ; vr6 1154 | idiv bx ; vr6 1155 | ; ; vr6 1156 | cmp dx, 4 ; vr6 1157 | jne failure ; vr6 1158 | 1159 | ; lw (vr2) 1160 | ; 32768 (vr1) 1161 | ; add (vr3) 1162 | ; 1000 (vr0) 1163 | ; ---- 1164 | ; Regs needed (approximately): 2 1165 | ; -------- 1166 | mov word [32768], 65535 ; vr0 1167 | ; ; vr0 1168 | mov ax, 1000 ; vr0 1169 | mov bx, 32768 ; vr1 1170 | mov bx, [bx] ; vr2 1171 | add ax, bx ; vr3 1172 | ; ; vr3 1173 | cmp ax, 999 ; vr3 1174 | jne failure ; vr3 1175 | 1176 | ; lw (vr2) 1177 | ; lw (vr1) 1178 | ; 32768 (vr0) 1179 | ; shl (vr4) 1180 | ; 123 (vr3) 1181 | ; ---- 1182 | ; Regs needed (approximately): 2 1183 | ; -------- 1184 | mov word [32768], 32768 ; vr0 1185 | mov word [32768], 32768 ; vr0 1186 | ; ; vr0 1187 | mov bx, 32768 ; vr0 1188 | mov bx, [bx] ; vr1 1189 | mov cx, [bx] ; vr2 1190 | mov ax, 123 ; vr3 1191 | shl ax, cl ; vr4 1192 | ; ; vr4 1193 | cmp ax, 123 ; vr4 1194 | jne failure ; vr4 1195 | 1196 | ; 40000 (vr1) 1197 | ; sw (vr2) 1198 | ; 12345 (vr0) 1199 | ; ---- 1200 | ; Regs needed (approximately): 2 1201 | ; -------- 1202 | ; ; vr0 1203 | mov ax, 12345 ; vr0 1204 | mov bx, 40000 ; vr1 1205 | mov [bx], ax ; vr2 1206 | ; ; vr2 1207 | cmp ax, 12345 ; vr2 1208 | jne failure ; vr2 1209 | cmp word [40000], 12345 ; vr2 1210 | jne failure ; vr2 1211 | 1212 | ; 40000 (vr2) 1213 | ; sw (vr3) 1214 | ; lw (vr1) 1215 | ; 32768 (vr0) 1216 | ; ---- 1217 | ; Regs needed (approximately): 2 1218 | ; -------- 1219 | mov word [32768], 54321 ; vr0 1220 | ; ; vr0 1221 | mov bx, 32768 ; vr0 1222 | mov bx, [bx] ; vr1 1223 | mov si, 40000 ; vr2 1224 | mov [si], bx ; vr3 1225 | ; ; vr3 1226 | cmp bx, 54321 ; vr3 1227 | jne failure ; vr3 1228 | cmp word [40000], 54321 ; vr3 1229 | jne failure ; vr3 1230 | 1231 | ; 40000 (vr4) 1232 | ; sw (vr5) 1233 | ; 32768 (vr2) 1234 | ; sw (vr3) 1235 | ; lw (vr1) 1236 | ; 50000 (vr0) 1237 | ; ---- 1238 | ; Regs needed (approximately): 2 1239 | ; -------- 1240 | mov word [50000], 21930 ; vr0 1241 | ; ; vr0 1242 | mov bx, 50000 ; vr0 1243 | mov bx, [bx] ; vr1 1244 | mov si, 32768 ; vr2 1245 | mov [si], bx ; vr3 1246 | mov si, 40000 ; vr4 1247 | mov [si], bx ; vr5 1248 | ; ; vr5 1249 | cmp bx, 21930 ; vr5 1250 | jne failure ; vr5 1251 | cmp word [32768], 21930 ; vr5 1252 | jne failure ; vr5 1253 | cmp word [40000], 21930 ; vr5 1254 | jne failure ; vr5 1255 | 1256 | ; lw (vr3) 1257 | ; 50000 (vr2) 1258 | ; mul (vr4) 1259 | ; lw (vr1) 1260 | ; 40000 (vr0) 1261 | ; ---- 1262 | ; Regs needed (approximately): 2 1263 | ; -------- 1264 | mov word [40000], 65521 ; vr0 1265 | mov word [50000], 65508 ; vr0 1266 | ; ; vr0 1267 | mov bx, 40000 ; vr0 1268 | mov ax, [bx] ; vr1 1269 | mov bx, 50000 ; vr2 1270 | mov bx, [bx] ; vr3 1271 | mul bx ; vr4 1272 | ; ; vr4 1273 | cmp ax, 420 ; vr4 1274 | jne failure ; vr4 1275 | 1276 | ; 50000 (vr7) 1277 | ; sw (vr8) 1278 | ; 40000 (vr5) 1279 | ; sw (vr6) 1280 | ; lw (vr3) 1281 | ; 49152 (vr2) 1282 | ; mul (vr4) 1283 | ; lw (vr1) 1284 | ; 32768 (vr0) 1285 | ; ---- 1286 | ; Regs needed (approximately): 2 1287 | ; -------- 1288 | mov word [32768], 1000 ; vr0 1289 | mov word [49152], 65535 ; vr0 1290 | ; ; vr0 1291 | mov bx, 32768 ; vr0 1292 | mov ax, [bx] ; vr1 1293 | mov bx, 49152 ; vr2 1294 | mov bx, [bx] ; vr3 1295 | mul bx ; vr4 1296 | mov bx, 40000 ; vr5 1297 | mov [bx], ax ; vr6 1298 | mov bx, 50000 ; vr7 1299 | mov [bx], ax ; vr8 1300 | ; ; vr8 1301 | cmp ax, 64536 ; vr8 1302 | jne failure ; vr8 1303 | cmp word [40000], 64536 ; vr8 1304 | jne failure ; vr8 1305 | cmp word [50000], 64536 ; vr8 1306 | jne failure ; vr8 1307 | 1308 | ; 40000 (vr5) 1309 | ; sw (vr6) 1310 | ; lbs (vr3) 1311 | ; 49152 (vr2) 1312 | ; add (vr4) 1313 | ; lbz (vr1) 1314 | ; 32768 (vr0) 1315 | ; ---- 1316 | ; Regs needed (approximately): 2 1317 | ; -------- 1318 | mov byte [32768], 255 ; vr0 1319 | mov byte [49152], 255 ; vr0 1320 | ; ; vr0 1321 | mov bx, 32768 ; vr0 1322 | mov bl, [bx] ; vr1 1323 | xor bh, bh ; vr1 1324 | mov si, 49152 ; vr2 1325 | mov al, [si] ; vr3 1326 | cbw ; vr3 1327 | add bx, ax ; vr4 1328 | mov si, 40000 ; vr5 1329 | mov [si], bx ; vr6 1330 | ; ; vr6 1331 | cmp bx, 254 ; vr6 1332 | jne failure ; vr6 1333 | cmp word [40000], 254 ; vr6 1334 | jne failure ; vr6 1335 | 1336 | ; 32768 (vr5) 1337 | ; sw (vr6) 1338 | ; lbz (vr3) 1339 | ; 49152 (vr2) 1340 | ; add (vr4) 1341 | ; lbs (vr1) 1342 | ; 50000 (vr0) 1343 | ; ---- 1344 | ; Regs needed (approximately): 2 1345 | ; -------- 1346 | mov byte [50000], 255 ; vr0 1347 | mov byte [49152], 255 ; vr0 1348 | ; ; vr0 1349 | mov bx, 50000 ; vr0 1350 | mov al, [bx] ; vr1 1351 | cbw ; vr1 1352 | mov bx, 49152 ; vr2 1353 | mov bl, [bx] ; vr3 1354 | xor bh, bh ; vr3 1355 | add ax, bx ; vr4 1356 | mov bx, 32768 ; vr5 1357 | mov [bx], ax ; vr6 1358 | ; ; vr6 1359 | cmp ax, 254 ; vr6 1360 | jne failure ; vr6 1361 | cmp word [32768], 254 ; vr6 1362 | jne failure ; vr6 1363 | 1364 | ; 50000 (vr2) 1365 | ; sb (vr3) 1366 | ; lbs (vr1) 1367 | ; 40000 (vr0) 1368 | ; ---- 1369 | ; Regs needed (approximately): 2 1370 | ; -------- 1371 | mov byte [40000], 90 ; vr0 1372 | ; ; vr0 1373 | mov bx, 40000 ; vr0 1374 | mov al, [bx] ; vr1 1375 | cbw ; vr1 1376 | mov bx, 50000 ; vr2 1377 | mov [bx], al ; vr3 1378 | ; ; vr3 1379 | cmp ax, 90 ; vr3 1380 | jne failure ; vr3 1381 | cmp byte [50000], 90 ; vr3 1382 | jne failure ; vr3 1383 | 1384 | ; 49152 (vr2) 1385 | ; sb (vr3) 1386 | ; lbs (vr1) 1387 | ; 32768 (vr0) 1388 | ; ---- 1389 | ; Regs needed (approximately): 2 1390 | ; -------- 1391 | mov byte [32768], 165 ; vr0 1392 | ; ; vr0 1393 | mov bx, 32768 ; vr0 1394 | mov al, [bx] ; vr1 1395 | cbw ; vr1 1396 | mov bx, 49152 ; vr2 1397 | mov [bx], al ; vr3 1398 | ; ; vr3 1399 | cmp ax, 65445 ; vr3 1400 | jne failure ; vr3 1401 | cmp byte [49152], 165 ; vr3 1402 | jne failure ; vr3 1403 | 1404 | ; 50000 (vr2) 1405 | ; sb (vr3) 1406 | ; lbz (vr1) 1407 | ; 40000 (vr0) 1408 | ; ---- 1409 | ; Regs needed (approximately): 2 1410 | ; -------- 1411 | mov byte [40000], 165 ; vr0 1412 | ; ; vr0 1413 | mov bx, 40000 ; vr0 1414 | mov bl, [bx] ; vr1 1415 | xor bh, bh ; vr1 1416 | mov si, 50000 ; vr2 1417 | mov [si], bl ; vr3 1418 | ; ; vr3 1419 | cmp bx, 165 ; vr3 1420 | jne failure ; vr3 1421 | cmp byte [50000], 165 ; vr3 1422 | jne failure ; vr3 1423 | 1424 | ; zext (vr4) 1425 | ; 50000 (vr2) 1426 | ; sb (vr3) 1427 | ; lb (vr1) 1428 | ; 40000 (vr0) 1429 | ; ---- 1430 | ; Regs needed (approximately): 2 1431 | ; -------- 1432 | mov byte [40000], 90 ; vr0 1433 | ; ; vr0 1434 | mov bx, 40000 ; vr0 1435 | mov bl, [bx] ; vr1 1436 | mov si, 50000 ; vr2 1437 | mov [si], bl ; vr3 1438 | xor bh, bh ; vr4 1439 | ; ; vr4 1440 | cmp bx, 90 ; vr4 1441 | jne failure ; vr4 1442 | cmp byte [50000], 90 ; vr4 1443 | jne failure ; vr4 1444 | 1445 | ; sext (vr4) 1446 | ; 50000 (vr2) 1447 | ; sb (vr3) 1448 | ; lb (vr1) 1449 | ; 40000 (vr0) 1450 | ; ---- 1451 | ; Regs needed (approximately): 2 1452 | ; -------- 1453 | mov byte [40000], 255 ; vr0 1454 | ; ; vr0 1455 | mov bx, 40000 ; vr0 1456 | mov al, [bx] ; vr1 1457 | mov bx, 50000 ; vr2 1458 | mov [bx], al ; vr3 1459 | cbw ; vr4 1460 | ; ; vr4 1461 | cmp ax, 65535 ; vr4 1462 | jne failure ; vr4 1463 | cmp byte [50000], 255 ; vr4 1464 | jne failure ; vr4 1465 | 1466 | ; lw (vr7) 1467 | ; 1 (vr0) 1468 | ; shl (vr3) 1469 | ; lw (vr2) 1470 | ; 50000 (vr1) 1471 | ; add (vr6) 1472 | ; lw (vr5) 1473 | ; 32768 (vr4) 1474 | ; ---- 1475 | ; Regs needed (approximately): 2 1476 | ; -------- 1477 | mov word [50000], 10 ; vr0 1478 | mov word [32768], 40000 ; vr0 1479 | mov word [40020], 55555 ; vr0 1480 | ; ; vr0 1481 | mov cx, 1 ; vr0 1482 | mov bx, 50000 ; vr1 1483 | mov bx, [bx] ; vr2 1484 | shl bx, cl ; vr3 1485 | mov si, 32768 ; vr4 1486 | mov si, [si] ; vr5 1487 | add si, bx ; vr6 1488 | mov si, [si] ; vr7 1489 | ; ; vr7 1490 | cmp si, 55555 ; vr7 1491 | jne failure ; vr7 1492 | 1493 | ; 1 (vr1) 1494 | ; idiv (vr2) 1495 | ; 2 (vr0) 1496 | ; add (vr9) 1497 | ; 4 (vr7) 1498 | ; shl (vr8) 1499 | ; lbz (vr6) 1500 | ; 0 (vr4) 1501 | ; add (vr5) 1502 | ; 32768 (vr3) 1503 | ; ---- 1504 | ; Regs needed (approximately): 3 1505 | ; -------- 1506 | mov byte [32768], 10 ; vr0 1507 | ; ; vr0 1508 | mov ax, 2 ; vr0 1509 | mov cx, 1 ; vr1 1510 | cwd ; vr2 1511 | idiv cx ; vr2 1512 | mov bx, 32768 ; vr3 1513 | mov si, 0 ; vr4 1514 | add bx, si ; vr5 1515 | mov dl, [bx] ; vr6 1516 | xor dh, dh ; vr6 1517 | mov cx, 4 ; vr7 1518 | shl dx, cl ; vr8 1519 | add dx, ax ; vr9 1520 | ; ; vr9 1521 | cmp dx, 162 ; vr9 1522 | jne failure ; vr9 1523 | 1524 | ; 16 (vr26) 1525 | ; add (vr27) 1526 | ; 15 (vr25) 1527 | ; add (vr28) 1528 | ; 14 (vr23) 1529 | ; add (vr24) 1530 | ; 13 (vr22) 1531 | ; add (vr29) 1532 | ; 12 (vr19) 1533 | ; add (vr20) 1534 | ; 11 (vr18) 1535 | ; add (vr21) 1536 | ; 10 (vr16) 1537 | ; add (vr17) 1538 | ; 9 (vr15) 1539 | ; add (vr30) 1540 | ; 8 (vr11) 1541 | ; add (vr12) 1542 | ; 7 (vr10) 1543 | ; add (vr13) 1544 | ; 6 (vr8) 1545 | ; add (vr9) 1546 | ; 5 (vr7) 1547 | ; add (vr14) 1548 | ; 4 (vr4) 1549 | ; add (vr5) 1550 | ; 3 (vr3) 1551 | ; add (vr6) 1552 | ; 2 (vr1) 1553 | ; add (vr2) 1554 | ; 1 (vr0) 1555 | ; ---- 1556 | ; Regs needed (approximately): 5 1557 | ; -------- 1558 | ; ; vr0 1559 | mov ax, 1 ; vr0 1560 | mov cx, 2 ; vr1 1561 | add ax, cx ; vr2 1562 | mov cx, 3 ; vr3 1563 | mov dx, 4 ; vr4 1564 | add cx, dx ; vr5 1565 | add ax, cx ; vr6 1566 | mov cx, 5 ; vr7 1567 | mov dx, 6 ; vr8 1568 | add cx, dx ; vr9 1569 | mov dx, 7 ; vr10 1570 | mov bx, 8 ; vr11 1571 | add dx, bx ; vr12 1572 | add cx, dx ; vr13 1573 | add ax, cx ; vr14 1574 | mov cx, 9 ; vr15 1575 | mov dx, 10 ; vr16 1576 | add cx, dx ; vr17 1577 | mov dx, 11 ; vr18 1578 | mov bx, 12 ; vr19 1579 | add dx, bx ; vr20 1580 | add cx, dx ; vr21 1581 | mov dx, 13 ; vr22 1582 | mov bx, 14 ; vr23 1583 | add dx, bx ; vr24 1584 | mov bx, 15 ; vr25 1585 | mov si, 16 ; vr26 1586 | add bx, si ; vr27 1587 | add dx, bx ; vr28 1588 | add cx, dx ; vr29 1589 | add ax, cx ; vr30 1590 | ; ; vr30 1591 | cmp ax, 136 ; vr30 1592 | jne failure ; vr30 1593 | 1594 | ; 16 (vr57) 1595 | ; add (vr58) 1596 | ; 15 (vr56) 1597 | ; add (vr59) 1598 | ; 14 (vr54) 1599 | ; add (vr55) 1600 | ; 13 (vr53) 1601 | ; add (vr60) 1602 | ; 12 (vr50) 1603 | ; add (vr51) 1604 | ; 11 (vr49) 1605 | ; add (vr52) 1606 | ; 10 (vr47) 1607 | ; add (vr48) 1608 | ; 9 (vr46) 1609 | ; add (vr61) 1610 | ; 8 (vr42) 1611 | ; add (vr43) 1612 | ; 7 (vr41) 1613 | ; add (vr44) 1614 | ; 6 (vr39) 1615 | ; add (vr40) 1616 | ; 5 (vr38) 1617 | ; add (vr45) 1618 | ; 4 (vr35) 1619 | ; add (vr36) 1620 | ; 3 (vr34) 1621 | ; add (vr37) 1622 | ; 2 (vr32) 1623 | ; add (vr33) 1624 | ; 1 (vr31) 1625 | ; add (vr62) 1626 | ; 16 (vr26) 1627 | ; add (vr27) 1628 | ; 15 (vr25) 1629 | ; add (vr28) 1630 | ; 14 (vr23) 1631 | ; add (vr24) 1632 | ; 13 (vr22) 1633 | ; add (vr29) 1634 | ; 12 (vr19) 1635 | ; add (vr20) 1636 | ; 11 (vr18) 1637 | ; add (vr21) 1638 | ; 10 (vr16) 1639 | ; add (vr17) 1640 | ; 9 (vr15) 1641 | ; add (vr30) 1642 | ; 8 (vr11) 1643 | ; add (vr12) 1644 | ; 7 (vr10) 1645 | ; add (vr13) 1646 | ; 6 (vr8) 1647 | ; add (vr9) 1648 | ; 5 (vr7) 1649 | ; add (vr14) 1650 | ; 4 (vr4) 1651 | ; add (vr5) 1652 | ; 3 (vr3) 1653 | ; add (vr6) 1654 | ; 2 (vr1) 1655 | ; add (vr2) 1656 | ; 1 (vr0) 1657 | ; ---- 1658 | ; Regs needed (approximately): 6 1659 | ; -------- 1660 | ; ; vr0 1661 | mov ax, 1 ; vr0 1662 | mov cx, 2 ; vr1 1663 | add ax, cx ; vr2 1664 | mov cx, 3 ; vr3 1665 | mov dx, 4 ; vr4 1666 | add cx, dx ; vr5 1667 | add ax, cx ; vr6 1668 | mov cx, 5 ; vr7 1669 | mov dx, 6 ; vr8 1670 | add cx, dx ; vr9 1671 | mov dx, 7 ; vr10 1672 | mov bx, 8 ; vr11 1673 | add dx, bx ; vr12 1674 | add cx, dx ; vr13 1675 | add ax, cx ; vr14 1676 | mov cx, 9 ; vr15 1677 | mov dx, 10 ; vr16 1678 | add cx, dx ; vr17 1679 | mov dx, 11 ; vr18 1680 | mov bx, 12 ; vr19 1681 | add dx, bx ; vr20 1682 | add cx, dx ; vr21 1683 | mov dx, 13 ; vr22 1684 | mov bx, 14 ; vr23 1685 | add dx, bx ; vr24 1686 | mov bx, 15 ; vr25 1687 | mov si, 16 ; vr26 1688 | add bx, si ; vr27 1689 | add dx, bx ; vr28 1690 | add cx, dx ; vr29 1691 | add ax, cx ; vr30 1692 | mov cx, 1 ; vr31 1693 | mov dx, 2 ; vr32 1694 | add cx, dx ; vr33 1695 | mov dx, 3 ; vr34 1696 | mov bx, 4 ; vr35 1697 | add dx, bx ; vr36 1698 | add cx, dx ; vr37 1699 | mov dx, 5 ; vr38 1700 | mov bx, 6 ; vr39 1701 | add dx, bx ; vr40 1702 | mov bx, 7 ; vr41 1703 | mov si, 8 ; vr42 1704 | add bx, si ; vr43 1705 | add dx, bx ; vr44 1706 | add cx, dx ; vr45 1707 | mov dx, 9 ; vr46 1708 | mov bx, 10 ; vr47 1709 | add dx, bx ; vr48 1710 | mov bx, 11 ; vr49 1711 | mov si, 12 ; vr50 1712 | add bx, si ; vr51 1713 | add dx, bx ; vr52 1714 | mov bx, 13 ; vr53 1715 | mov si, 14 ; vr54 1716 | add bx, si ; vr55 1717 | mov si, 15 ; vr56 1718 | mov di, 16 ; vr57 1719 | add si, di ; vr58 1720 | add bx, si ; vr59 1721 | add dx, bx ; vr60 1722 | add cx, dx ; vr61 1723 | add ax, cx ; vr62 1724 | ; ; vr62 1725 | cmp ax, 272 ; vr62 1726 | jne failure ; vr62 1727 | 1728 | ; 16 (vr120) 1729 | ; add (vr121) 1730 | ; 15 (vr119) 1731 | ; add (vr122) 1732 | ; 14 (vr117) 1733 | ; add (vr118) 1734 | ; 13 (vr116) 1735 | ; add (vr123) 1736 | ; 12 (vr113) 1737 | ; add (vr114) 1738 | ; 11 (vr112) 1739 | ; add (vr115) 1740 | ; 10 (vr110) 1741 | ; add (vr111) 1742 | ; 9 (vr109) 1743 | ; add (vr124) 1744 | ; 8 (vr105) 1745 | ; add (vr106) 1746 | ; 7 (vr104) 1747 | ; add (vr107) 1748 | ; 6 (vr102) 1749 | ; add (vr103) 1750 | ; 5 (vr101) 1751 | ; add (vr108) 1752 | ; 4 (vr98) 1753 | ; add (vr99) 1754 | ; 3 (vr97) 1755 | ; add (vr100) 1756 | ; 2 (vr95) 1757 | ; add (vr96) 1758 | ; 1 (vr94) 1759 | ; add (vr125) 1760 | ; 16 (vr89) 1761 | ; add (vr90) 1762 | ; 15 (vr88) 1763 | ; add (vr91) 1764 | ; 14 (vr86) 1765 | ; add (vr87) 1766 | ; 13 (vr85) 1767 | ; add (vr92) 1768 | ; 12 (vr82) 1769 | ; add (vr83) 1770 | ; 11 (vr81) 1771 | ; add (vr84) 1772 | ; 10 (vr79) 1773 | ; add (vr80) 1774 | ; 9 (vr78) 1775 | ; add (vr93) 1776 | ; 8 (vr74) 1777 | ; add (vr75) 1778 | ; 7 (vr73) 1779 | ; add (vr76) 1780 | ; 6 (vr71) 1781 | ; add (vr72) 1782 | ; 5 (vr70) 1783 | ; add (vr77) 1784 | ; 4 (vr67) 1785 | ; add (vr68) 1786 | ; 3 (vr66) 1787 | ; add (vr69) 1788 | ; 2 (vr64) 1789 | ; add (vr65) 1790 | ; 1 (vr63) 1791 | ; add (vr126) 1792 | ; 16 (vr57) 1793 | ; add (vr58) 1794 | ; 15 (vr56) 1795 | ; add (vr59) 1796 | ; 14 (vr54) 1797 | ; add (vr55) 1798 | ; 13 (vr53) 1799 | ; add (vr60) 1800 | ; 12 (vr50) 1801 | ; add (vr51) 1802 | ; 11 (vr49) 1803 | ; add (vr52) 1804 | ; 10 (vr47) 1805 | ; add (vr48) 1806 | ; 9 (vr46) 1807 | ; add (vr61) 1808 | ; 8 (vr42) 1809 | ; add (vr43) 1810 | ; 7 (vr41) 1811 | ; add (vr44) 1812 | ; 6 (vr39) 1813 | ; add (vr40) 1814 | ; 5 (vr38) 1815 | ; add (vr45) 1816 | ; 4 (vr35) 1817 | ; add (vr36) 1818 | ; 3 (vr34) 1819 | ; add (vr37) 1820 | ; 2 (vr32) 1821 | ; add (vr33) 1822 | ; 1 (vr31) 1823 | ; add (vr62) 1824 | ; 16 (vr26) 1825 | ; add (vr27) 1826 | ; 15 (vr25) 1827 | ; add (vr28) 1828 | ; 14 (vr23) 1829 | ; add (vr24) 1830 | ; 13 (vr22) 1831 | ; add (vr29) 1832 | ; 12 (vr19) 1833 | ; add (vr20) 1834 | ; 11 (vr18) 1835 | ; add (vr21) 1836 | ; 10 (vr16) 1837 | ; add (vr17) 1838 | ; 9 (vr15) 1839 | ; add (vr30) 1840 | ; 8 (vr11) 1841 | ; add (vr12) 1842 | ; 7 (vr10) 1843 | ; add (vr13) 1844 | ; 6 (vr8) 1845 | ; add (vr9) 1846 | ; 5 (vr7) 1847 | ; add (vr14) 1848 | ; 4 (vr4) 1849 | ; add (vr5) 1850 | ; 3 (vr3) 1851 | ; add (vr6) 1852 | ; 2 (vr1) 1853 | ; add (vr2) 1854 | ; 1 (vr0) 1855 | ; ---- 1856 | ; Regs needed (approximately): 7 1857 | ; -------- 1858 | ; ; vr0 1859 | mov ax, 1 ; vr0 1860 | mov cx, 2 ; vr1 1861 | add ax, cx ; vr2 1862 | mov cx, 3 ; vr3 1863 | mov dx, 4 ; vr4 1864 | add cx, dx ; vr5 1865 | add ax, cx ; vr6 1866 | mov cx, 5 ; vr7 1867 | mov dx, 6 ; vr8 1868 | add cx, dx ; vr9 1869 | mov dx, 7 ; vr10 1870 | mov bx, 8 ; vr11 1871 | add dx, bx ; vr12 1872 | add cx, dx ; vr13 1873 | add ax, cx ; vr14 1874 | mov cx, 9 ; vr15 1875 | mov dx, 10 ; vr16 1876 | add cx, dx ; vr17 1877 | mov dx, 11 ; vr18 1878 | mov bx, 12 ; vr19 1879 | add dx, bx ; vr20 1880 | add cx, dx ; vr21 1881 | mov dx, 13 ; vr22 1882 | mov bx, 14 ; vr23 1883 | add dx, bx ; vr24 1884 | mov bx, 15 ; vr25 1885 | mov si, 16 ; vr26 1886 | add bx, si ; vr27 1887 | add dx, bx ; vr28 1888 | add cx, dx ; vr29 1889 | add ax, cx ; vr30 1890 | mov cx, 1 ; vr31 1891 | mov dx, 2 ; vr32 1892 | add cx, dx ; vr33 1893 | mov dx, 3 ; vr34 1894 | mov bx, 4 ; vr35 1895 | add dx, bx ; vr36 1896 | add cx, dx ; vr37 1897 | mov dx, 5 ; vr38 1898 | mov bx, 6 ; vr39 1899 | add dx, bx ; vr40 1900 | mov bx, 7 ; vr41 1901 | mov si, 8 ; vr42 1902 | add bx, si ; vr43 1903 | add dx, bx ; vr44 1904 | add cx, dx ; vr45 1905 | mov dx, 9 ; vr46 1906 | mov bx, 10 ; vr47 1907 | add dx, bx ; vr48 1908 | mov bx, 11 ; vr49 1909 | mov si, 12 ; vr50 1910 | add bx, si ; vr51 1911 | add dx, bx ; vr52 1912 | mov bx, 13 ; vr53 1913 | mov si, 14 ; vr54 1914 | add bx, si ; vr55 1915 | mov si, 15 ; vr56 1916 | mov di, 16 ; vr57 1917 | add si, di ; vr58 1918 | add bx, si ; vr59 1919 | add dx, bx ; vr60 1920 | add cx, dx ; vr61 1921 | add ax, cx ; vr62 1922 | mov cx, 1 ; vr63 1923 | mov dx, 2 ; vr64 1924 | add cx, dx ; vr65 1925 | mov dx, 3 ; vr66 1926 | mov bx, 4 ; vr67 1927 | add dx, bx ; vr68 1928 | add cx, dx ; vr69 1929 | mov dx, 5 ; vr70 1930 | mov bx, 6 ; vr71 1931 | add dx, bx ; vr72 1932 | mov bx, 7 ; vr73 1933 | mov si, 8 ; vr74 1934 | add bx, si ; vr75 1935 | add dx, bx ; vr76 1936 | add cx, dx ; vr77 1937 | mov dx, 9 ; vr78 1938 | mov bx, 10 ; vr79 1939 | add dx, bx ; vr80 1940 | mov bx, 11 ; vr81 1941 | mov si, 12 ; vr82 1942 | add bx, si ; vr83 1943 | add dx, bx ; vr84 1944 | mov bx, 13 ; vr85 1945 | mov si, 14 ; vr86 1946 | add bx, si ; vr87 1947 | mov si, 15 ; vr88 1948 | mov di, 16 ; vr89 1949 | add si, di ; vr90 1950 | add bx, si ; vr91 1951 | add dx, bx ; vr92 1952 | add cx, dx ; vr93 1953 | mov dx, 1 ; vr94 1954 | mov bx, 2 ; vr95 1955 | add dx, bx ; vr96 1956 | mov bx, 3 ; vr97 1957 | mov si, 4 ; vr98 1958 | add bx, si ; vr99 1959 | add dx, bx ; vr100 1960 | mov bx, 5 ; vr101 1961 | mov si, 6 ; vr102 1962 | add bx, si ; vr103 1963 | mov si, 7 ; vr104 1964 | mov di, 8 ; vr105 1965 | add si, di ; vr106 1966 | add bx, si ; vr107 1967 | add dx, bx ; vr108 1968 | mov bx, 9 ; vr109 1969 | mov si, 10 ; vr110 1970 | add bx, si ; vr111 1971 | mov si, 11 ; vr112 1972 | mov di, 12 ; vr113 1973 | add si, di ; vr114 1974 | add bx, si ; vr115 1975 | mov si, 13 ; vr116 1976 | mov di, 14 ; vr117 1977 | add si, di ; vr118 1978 | mov di, 15 ; vr119 1979 | push ax ; vr120 1980 | mov ax, 16 ; vr120 1981 | add di, ax ; vr121 1982 | add si, di ; vr122 1983 | add bx, si ; vr123 1984 | add dx, bx ; vr124 1985 | add cx, dx ; vr125 1986 | pop ax ; vr126 1987 | add ax, cx ; vr126 1988 | ; ; vr126 1989 | cmp ax, 544 ; vr126 1990 | jne failure ; vr126 1991 | 1992 | ; 16 (vr247) 1993 | ; add (vr248) 1994 | ; 15 (vr246) 1995 | ; add (vr249) 1996 | ; 14 (vr244) 1997 | ; add (vr245) 1998 | ; 13 (vr243) 1999 | ; add (vr250) 2000 | ; 12 (vr240) 2001 | ; add (vr241) 2002 | ; 11 (vr239) 2003 | ; add (vr242) 2004 | ; 10 (vr237) 2005 | ; add (vr238) 2006 | ; 9 (vr236) 2007 | ; add (vr251) 2008 | ; 8 (vr232) 2009 | ; add (vr233) 2010 | ; 7 (vr231) 2011 | ; add (vr234) 2012 | ; 6 (vr229) 2013 | ; add (vr230) 2014 | ; 5 (vr228) 2015 | ; add (vr235) 2016 | ; 4 (vr225) 2017 | ; add (vr226) 2018 | ; 3 (vr224) 2019 | ; add (vr227) 2020 | ; 2 (vr222) 2021 | ; add (vr223) 2022 | ; 1 (vr221) 2023 | ; add (vr252) 2024 | ; 16 (vr216) 2025 | ; add (vr217) 2026 | ; 15 (vr215) 2027 | ; add (vr218) 2028 | ; 14 (vr213) 2029 | ; add (vr214) 2030 | ; 13 (vr212) 2031 | ; add (vr219) 2032 | ; 12 (vr209) 2033 | ; add (vr210) 2034 | ; 11 (vr208) 2035 | ; add (vr211) 2036 | ; 10 (vr206) 2037 | ; add (vr207) 2038 | ; 9 (vr205) 2039 | ; add (vr220) 2040 | ; 8 (vr201) 2041 | ; add (vr202) 2042 | ; 7 (vr200) 2043 | ; add (vr203) 2044 | ; 6 (vr198) 2045 | ; add (vr199) 2046 | ; 5 (vr197) 2047 | ; add (vr204) 2048 | ; 4 (vr194) 2049 | ; add (vr195) 2050 | ; 3 (vr193) 2051 | ; add (vr196) 2052 | ; 2 (vr191) 2053 | ; add (vr192) 2054 | ; 1 (vr190) 2055 | ; add (vr253) 2056 | ; 16 (vr184) 2057 | ; add (vr185) 2058 | ; 15 (vr183) 2059 | ; add (vr186) 2060 | ; 14 (vr181) 2061 | ; add (vr182) 2062 | ; 13 (vr180) 2063 | ; add (vr187) 2064 | ; 12 (vr177) 2065 | ; add (vr178) 2066 | ; 11 (vr176) 2067 | ; add (vr179) 2068 | ; 10 (vr174) 2069 | ; add (vr175) 2070 | ; 9 (vr173) 2071 | ; add (vr188) 2072 | ; 8 (vr169) 2073 | ; add (vr170) 2074 | ; 7 (vr168) 2075 | ; add (vr171) 2076 | ; 6 (vr166) 2077 | ; add (vr167) 2078 | ; 5 (vr165) 2079 | ; add (vr172) 2080 | ; 4 (vr162) 2081 | ; add (vr163) 2082 | ; 3 (vr161) 2083 | ; add (vr164) 2084 | ; 2 (vr159) 2085 | ; add (vr160) 2086 | ; 1 (vr158) 2087 | ; add (vr189) 2088 | ; 16 (vr153) 2089 | ; add (vr154) 2090 | ; 15 (vr152) 2091 | ; add (vr155) 2092 | ; 14 (vr150) 2093 | ; add (vr151) 2094 | ; 13 (vr149) 2095 | ; add (vr156) 2096 | ; 12 (vr146) 2097 | ; add (vr147) 2098 | ; 11 (vr145) 2099 | ; add (vr148) 2100 | ; 10 (vr143) 2101 | ; add (vr144) 2102 | ; 9 (vr142) 2103 | ; add (vr157) 2104 | ; 8 (vr138) 2105 | ; add (vr139) 2106 | ; 7 (vr137) 2107 | ; add (vr140) 2108 | ; 6 (vr135) 2109 | ; add (vr136) 2110 | ; 5 (vr134) 2111 | ; add (vr141) 2112 | ; 4 (vr131) 2113 | ; add (vr132) 2114 | ; 3 (vr130) 2115 | ; add (vr133) 2116 | ; 2 (vr128) 2117 | ; add (vr129) 2118 | ; 1 (vr127) 2119 | ; add (vr254) 2120 | ; 16 (vr120) 2121 | ; add (vr121) 2122 | ; 15 (vr119) 2123 | ; add (vr122) 2124 | ; 14 (vr117) 2125 | ; add (vr118) 2126 | ; 13 (vr116) 2127 | ; add (vr123) 2128 | ; 12 (vr113) 2129 | ; add (vr114) 2130 | ; 11 (vr112) 2131 | ; add (vr115) 2132 | ; 10 (vr110) 2133 | ; add (vr111) 2134 | ; 9 (vr109) 2135 | ; add (vr124) 2136 | ; 8 (vr105) 2137 | ; add (vr106) 2138 | ; 7 (vr104) 2139 | ; add (vr107) 2140 | ; 6 (vr102) 2141 | ; add (vr103) 2142 | ; 5 (vr101) 2143 | ; add (vr108) 2144 | ; 4 (vr98) 2145 | ; add (vr99) 2146 | ; 3 (vr97) 2147 | ; add (vr100) 2148 | ; 2 (vr95) 2149 | ; add (vr96) 2150 | ; 1 (vr94) 2151 | ; add (vr125) 2152 | ; 16 (vr89) 2153 | ; add (vr90) 2154 | ; 15 (vr88) 2155 | ; add (vr91) 2156 | ; 14 (vr86) 2157 | ; add (vr87) 2158 | ; 13 (vr85) 2159 | ; add (vr92) 2160 | ; 12 (vr82) 2161 | ; add (vr83) 2162 | ; 11 (vr81) 2163 | ; add (vr84) 2164 | ; 10 (vr79) 2165 | ; add (vr80) 2166 | ; 9 (vr78) 2167 | ; add (vr93) 2168 | ; 8 (vr74) 2169 | ; add (vr75) 2170 | ; 7 (vr73) 2171 | ; add (vr76) 2172 | ; 6 (vr71) 2173 | ; add (vr72) 2174 | ; 5 (vr70) 2175 | ; add (vr77) 2176 | ; 4 (vr67) 2177 | ; add (vr68) 2178 | ; 3 (vr66) 2179 | ; add (vr69) 2180 | ; 2 (vr64) 2181 | ; add (vr65) 2182 | ; 1 (vr63) 2183 | ; add (vr126) 2184 | ; 16 (vr57) 2185 | ; add (vr58) 2186 | ; 15 (vr56) 2187 | ; add (vr59) 2188 | ; 14 (vr54) 2189 | ; add (vr55) 2190 | ; 13 (vr53) 2191 | ; add (vr60) 2192 | ; 12 (vr50) 2193 | ; add (vr51) 2194 | ; 11 (vr49) 2195 | ; add (vr52) 2196 | ; 10 (vr47) 2197 | ; add (vr48) 2198 | ; 9 (vr46) 2199 | ; add (vr61) 2200 | ; 8 (vr42) 2201 | ; add (vr43) 2202 | ; 7 (vr41) 2203 | ; add (vr44) 2204 | ; 6 (vr39) 2205 | ; add (vr40) 2206 | ; 5 (vr38) 2207 | ; add (vr45) 2208 | ; 4 (vr35) 2209 | ; add (vr36) 2210 | ; 3 (vr34) 2211 | ; add (vr37) 2212 | ; 2 (vr32) 2213 | ; add (vr33) 2214 | ; 1 (vr31) 2215 | ; add (vr62) 2216 | ; 16 (vr26) 2217 | ; add (vr27) 2218 | ; 15 (vr25) 2219 | ; add (vr28) 2220 | ; 14 (vr23) 2221 | ; add (vr24) 2222 | ; 13 (vr22) 2223 | ; add (vr29) 2224 | ; 12 (vr19) 2225 | ; add (vr20) 2226 | ; 11 (vr18) 2227 | ; add (vr21) 2228 | ; 10 (vr16) 2229 | ; add (vr17) 2230 | ; 9 (vr15) 2231 | ; add (vr30) 2232 | ; 8 (vr11) 2233 | ; add (vr12) 2234 | ; 7 (vr10) 2235 | ; add (vr13) 2236 | ; 6 (vr8) 2237 | ; add (vr9) 2238 | ; 5 (vr7) 2239 | ; add (vr14) 2240 | ; 4 (vr4) 2241 | ; add (vr5) 2242 | ; 3 (vr3) 2243 | ; add (vr6) 2244 | ; 2 (vr1) 2245 | ; add (vr2) 2246 | ; 1 (vr0) 2247 | ; ---- 2248 | ; Regs needed (approximately): 8 2249 | ; -------- 2250 | ; ; vr0 2251 | mov ax, 1 ; vr0 2252 | mov cx, 2 ; vr1 2253 | add ax, cx ; vr2 2254 | mov cx, 3 ; vr3 2255 | mov dx, 4 ; vr4 2256 | add cx, dx ; vr5 2257 | add ax, cx ; vr6 2258 | mov cx, 5 ; vr7 2259 | mov dx, 6 ; vr8 2260 | add cx, dx ; vr9 2261 | mov dx, 7 ; vr10 2262 | mov bx, 8 ; vr11 2263 | add dx, bx ; vr12 2264 | add cx, dx ; vr13 2265 | add ax, cx ; vr14 2266 | mov cx, 9 ; vr15 2267 | mov dx, 10 ; vr16 2268 | add cx, dx ; vr17 2269 | mov dx, 11 ; vr18 2270 | mov bx, 12 ; vr19 2271 | add dx, bx ; vr20 2272 | add cx, dx ; vr21 2273 | mov dx, 13 ; vr22 2274 | mov bx, 14 ; vr23 2275 | add dx, bx ; vr24 2276 | mov bx, 15 ; vr25 2277 | mov si, 16 ; vr26 2278 | add bx, si ; vr27 2279 | add dx, bx ; vr28 2280 | add cx, dx ; vr29 2281 | add ax, cx ; vr30 2282 | mov cx, 1 ; vr31 2283 | mov dx, 2 ; vr32 2284 | add cx, dx ; vr33 2285 | mov dx, 3 ; vr34 2286 | mov bx, 4 ; vr35 2287 | add dx, bx ; vr36 2288 | add cx, dx ; vr37 2289 | mov dx, 5 ; vr38 2290 | mov bx, 6 ; vr39 2291 | add dx, bx ; vr40 2292 | mov bx, 7 ; vr41 2293 | mov si, 8 ; vr42 2294 | add bx, si ; vr43 2295 | add dx, bx ; vr44 2296 | add cx, dx ; vr45 2297 | mov dx, 9 ; vr46 2298 | mov bx, 10 ; vr47 2299 | add dx, bx ; vr48 2300 | mov bx, 11 ; vr49 2301 | mov si, 12 ; vr50 2302 | add bx, si ; vr51 2303 | add dx, bx ; vr52 2304 | mov bx, 13 ; vr53 2305 | mov si, 14 ; vr54 2306 | add bx, si ; vr55 2307 | mov si, 15 ; vr56 2308 | mov di, 16 ; vr57 2309 | add si, di ; vr58 2310 | add bx, si ; vr59 2311 | add dx, bx ; vr60 2312 | add cx, dx ; vr61 2313 | add ax, cx ; vr62 2314 | mov cx, 1 ; vr63 2315 | mov dx, 2 ; vr64 2316 | add cx, dx ; vr65 2317 | mov dx, 3 ; vr66 2318 | mov bx, 4 ; vr67 2319 | add dx, bx ; vr68 2320 | add cx, dx ; vr69 2321 | mov dx, 5 ; vr70 2322 | mov bx, 6 ; vr71 2323 | add dx, bx ; vr72 2324 | mov bx, 7 ; vr73 2325 | mov si, 8 ; vr74 2326 | add bx, si ; vr75 2327 | add dx, bx ; vr76 2328 | add cx, dx ; vr77 2329 | mov dx, 9 ; vr78 2330 | mov bx, 10 ; vr79 2331 | add dx, bx ; vr80 2332 | mov bx, 11 ; vr81 2333 | mov si, 12 ; vr82 2334 | add bx, si ; vr83 2335 | add dx, bx ; vr84 2336 | mov bx, 13 ; vr85 2337 | mov si, 14 ; vr86 2338 | add bx, si ; vr87 2339 | mov si, 15 ; vr88 2340 | mov di, 16 ; vr89 2341 | add si, di ; vr90 2342 | add bx, si ; vr91 2343 | add dx, bx ; vr92 2344 | add cx, dx ; vr93 2345 | mov dx, 1 ; vr94 2346 | mov bx, 2 ; vr95 2347 | add dx, bx ; vr96 2348 | mov bx, 3 ; vr97 2349 | mov si, 4 ; vr98 2350 | add bx, si ; vr99 2351 | add dx, bx ; vr100 2352 | mov bx, 5 ; vr101 2353 | mov si, 6 ; vr102 2354 | add bx, si ; vr103 2355 | mov si, 7 ; vr104 2356 | mov di, 8 ; vr105 2357 | add si, di ; vr106 2358 | add bx, si ; vr107 2359 | add dx, bx ; vr108 2360 | mov bx, 9 ; vr109 2361 | mov si, 10 ; vr110 2362 | add bx, si ; vr111 2363 | mov si, 11 ; vr112 2364 | mov di, 12 ; vr113 2365 | add si, di ; vr114 2366 | add bx, si ; vr115 2367 | mov si, 13 ; vr116 2368 | mov di, 14 ; vr117 2369 | add si, di ; vr118 2370 | mov di, 15 ; vr119 2371 | push ax ; vr120 2372 | mov ax, 16 ; vr120 2373 | add di, ax ; vr121 2374 | add si, di ; vr122 2375 | add bx, si ; vr123 2376 | add dx, bx ; vr124 2377 | add cx, dx ; vr125 2378 | pop ax ; vr126 2379 | add ax, cx ; vr126 2380 | mov cx, 1 ; vr127 2381 | mov dx, 2 ; vr128 2382 | add cx, dx ; vr129 2383 | mov dx, 3 ; vr130 2384 | mov bx, 4 ; vr131 2385 | add dx, bx ; vr132 2386 | add cx, dx ; vr133 2387 | mov dx, 5 ; vr134 2388 | mov bx, 6 ; vr135 2389 | add dx, bx ; vr136 2390 | mov bx, 7 ; vr137 2391 | mov si, 8 ; vr138 2392 | add bx, si ; vr139 2393 | add dx, bx ; vr140 2394 | add cx, dx ; vr141 2395 | mov dx, 9 ; vr142 2396 | mov bx, 10 ; vr143 2397 | add dx, bx ; vr144 2398 | mov bx, 11 ; vr145 2399 | mov si, 12 ; vr146 2400 | add bx, si ; vr147 2401 | add dx, bx ; vr148 2402 | mov bx, 13 ; vr149 2403 | mov si, 14 ; vr150 2404 | add bx, si ; vr151 2405 | mov si, 15 ; vr152 2406 | mov di, 16 ; vr153 2407 | add si, di ; vr154 2408 | add bx, si ; vr155 2409 | add dx, bx ; vr156 2410 | add cx, dx ; vr157 2411 | mov dx, 1 ; vr158 2412 | mov bx, 2 ; vr159 2413 | add dx, bx ; vr160 2414 | mov bx, 3 ; vr161 2415 | mov si, 4 ; vr162 2416 | add bx, si ; vr163 2417 | add dx, bx ; vr164 2418 | mov bx, 5 ; vr165 2419 | mov si, 6 ; vr166 2420 | add bx, si ; vr167 2421 | mov si, 7 ; vr168 2422 | mov di, 8 ; vr169 2423 | add si, di ; vr170 2424 | add bx, si ; vr171 2425 | add dx, bx ; vr172 2426 | mov bx, 9 ; vr173 2427 | mov si, 10 ; vr174 2428 | add bx, si ; vr175 2429 | mov si, 11 ; vr176 2430 | mov di, 12 ; vr177 2431 | add si, di ; vr178 2432 | add bx, si ; vr179 2433 | mov si, 13 ; vr180 2434 | mov di, 14 ; vr181 2435 | add si, di ; vr182 2436 | mov di, 15 ; vr183 2437 | push ax ; vr184 2438 | mov ax, 16 ; vr184 2439 | add di, ax ; vr185 2440 | add si, di ; vr186 2441 | add bx, si ; vr187 2442 | add dx, bx ; vr188 2443 | add cx, dx ; vr189 2444 | mov ax, 1 ; vr190 2445 | mov dx, 2 ; vr191 2446 | add ax, dx ; vr192 2447 | mov dx, 3 ; vr193 2448 | mov bx, 4 ; vr194 2449 | add dx, bx ; vr195 2450 | add ax, dx ; vr196 2451 | mov dx, 5 ; vr197 2452 | mov bx, 6 ; vr198 2453 | add dx, bx ; vr199 2454 | mov bx, 7 ; vr200 2455 | mov si, 8 ; vr201 2456 | add bx, si ; vr202 2457 | add dx, bx ; vr203 2458 | add ax, dx ; vr204 2459 | mov dx, 9 ; vr205 2460 | mov bx, 10 ; vr206 2461 | add dx, bx ; vr207 2462 | mov bx, 11 ; vr208 2463 | mov si, 12 ; vr209 2464 | add bx, si ; vr210 2465 | add dx, bx ; vr211 2466 | mov bx, 13 ; vr212 2467 | mov si, 14 ; vr213 2468 | add bx, si ; vr214 2469 | mov si, 15 ; vr215 2470 | mov di, 16 ; vr216 2471 | add si, di ; vr217 2472 | add bx, si ; vr218 2473 | add dx, bx ; vr219 2474 | add ax, dx ; vr220 2475 | mov dx, 1 ; vr221 2476 | mov bx, 2 ; vr222 2477 | add dx, bx ; vr223 2478 | mov bx, 3 ; vr224 2479 | mov si, 4 ; vr225 2480 | add bx, si ; vr226 2481 | add dx, bx ; vr227 2482 | mov bx, 5 ; vr228 2483 | mov si, 6 ; vr229 2484 | add bx, si ; vr230 2485 | mov si, 7 ; vr231 2486 | mov di, 8 ; vr232 2487 | add si, di ; vr233 2488 | add bx, si ; vr234 2489 | add dx, bx ; vr235 2490 | mov bx, 9 ; vr236 2491 | mov si, 10 ; vr237 2492 | add bx, si ; vr238 2493 | mov si, 11 ; vr239 2494 | mov di, 12 ; vr240 2495 | add si, di ; vr241 2496 | add bx, si ; vr242 2497 | mov si, 13 ; vr243 2498 | mov di, 14 ; vr244 2499 | add si, di ; vr245 2500 | mov di, 15 ; vr246 2501 | push cx ; vr247 2502 | mov cx, 16 ; vr247 2503 | add di, cx ; vr248 2504 | add si, di ; vr249 2505 | add bx, si ; vr250 2506 | add dx, bx ; vr251 2507 | add ax, dx ; vr252 2508 | pop cx ; vr253 2509 | add cx, ax ; vr253 2510 | pop ax ; vr254 2511 | add ax, cx ; vr254 2512 | ; ; vr254 2513 | cmp ax, 1088 ; vr254 2514 | jne failure ; vr254 2515 | 2516 | ; () (vr1) 2517 | ; _ten (vr0) 2518 | ; ---- 2519 | ; Regs needed (approximately): 6 2520 | ; -------- 2521 | ; ; vr0 2522 | mov ax, _ten ; vr0 2523 | call ax ; vr1 2524 | ; ; vr1 2525 | cmp ax, 10 ; vr1 2526 | jne failure ; vr1 2527 | 2528 | ; arg (vr1) 2529 | ; 21930 (vr0) 2530 | ; () (vr3) 2531 | ; _popcnt (vr2) 2532 | ; ---- 2533 | ; Regs needed (approximately): 6 2534 | ; -------- 2535 | ; ; vr0 2536 | mov ax, 21930 ; vr0 2537 | push ax ; vr1 2538 | mov ax, _popcnt ; vr2 2539 | call ax ; vr3 2540 | add sp, 2 ; vr3 2541 | ; ; vr3 2542 | cmp ax, 8 ; vr3 2543 | jne failure ; vr3 2544 | 2545 | ; arg (vr1) 2546 | ; 2 (vr0) 2547 | ; arg (vr3) 2548 | ; 1 (vr2) 2549 | ; () (vr5) 2550 | ; _add (vr4) 2551 | ; ---- 2552 | ; Regs needed (approximately): 6 2553 | ; -------- 2554 | ; ; vr0 2555 | mov ax, 2 ; vr0 2556 | push ax ; vr1 2557 | mov ax, 1 ; vr2 2558 | push ax ; vr3 2559 | mov ax, _add ; vr4 2560 | call ax ; vr5 2561 | add sp, 4 ; vr5 2562 | ; ; vr5 2563 | cmp ax, 3 ; vr5 2564 | jne failure ; vr5 2565 | 2566 | ; 4 (vr12) 2567 | ; idiv (vr13) 2568 | ; arg (vr3) 2569 | ; 3 (vr1) 2570 | ; mul (vr2) 2571 | ; 2 (vr0) 2572 | ; arg (vr7) 2573 | ; 3 (vr5) 2574 | ; irem (vr6) 2575 | ; 5 (vr4) 2576 | ; () (vr9) 2577 | ; _add (vr8) 2578 | ; shl (vr11) 2579 | ; 1 (vr10) 2580 | ; ---- 2581 | ; Regs needed (approximately): 6 2582 | ; -------- 2583 | ; ; vr0 2584 | mov ax, 2 ; vr0 2585 | mov cx, 3 ; vr1 2586 | mul cx ; vr2 2587 | push ax ; vr3 2588 | mov ax, 5 ; vr4 2589 | mov cx, 3 ; vr5 2590 | cwd ; vr6 2591 | idiv cx ; vr6 2592 | push dx ; vr7 2593 | mov ax, _add ; vr8 2594 | call ax ; vr9 2595 | add sp, 4 ; vr9 2596 | mov cx, 1 ; vr10 2597 | xchg cx, ax ; vr11 2598 | shl ax, cl ; vr11 2599 | mov cx, 4 ; vr12 2600 | cwd ; vr13 2601 | idiv cx ; vr13 2602 | ; ; vr13 2603 | cmp ax, 64 ; vr13 2604 | jne failure ; vr13 2605 | 2606 | ; arg (vr7) 2607 | ; 8 (vr6) 2608 | ; arg (vr9) 2609 | ; 4 (vr8) 2610 | ; () (vr11) 2611 | ; _add (vr10) 2612 | ; add (vr12) 2613 | ; arg (vr1) 2614 | ; 2 (vr0) 2615 | ; arg (vr3) 2616 | ; 1 (vr2) 2617 | ; () (vr5) 2618 | ; _add (vr4) 2619 | ; ---- 2620 | ; Regs needed (approximately): 7 2621 | ; -------- 2622 | ; ; vr0 2623 | mov ax, 2 ; vr0 2624 | push ax ; vr1 2625 | mov ax, 1 ; vr2 2626 | push ax ; vr3 2627 | mov ax, _add ; vr4 2628 | call ax ; vr5 2629 | add sp, 4 ; vr5 2630 | push ax ; vr5 2631 | mov ax, 8 ; vr6 2632 | push ax ; vr7 2633 | mov ax, 4 ; vr8 2634 | push ax ; vr9 2635 | mov ax, _add ; vr10 2636 | call ax ; vr11 2637 | add sp, 4 ; vr11 2638 | pop cx ; vr12 2639 | add cx, ax ; vr12 2640 | ; ; vr12 2641 | cmp cx, 15 ; vr12 2642 | jne failure ; vr12 2643 | 2644 | ; arg (vr6) 2645 | ; arg (vr1) 2646 | ; 8 (vr0) 2647 | ; arg (vr3) 2648 | ; 4 (vr2) 2649 | ; () (vr5) 2650 | ; _add (vr4) 2651 | ; arg (vr13) 2652 | ; arg (vr8) 2653 | ; 2 (vr7) 2654 | ; arg (vr10) 2655 | ; 1 (vr9) 2656 | ; () (vr12) 2657 | ; _add (vr11) 2658 | ; () (vr15) 2659 | ; _add (vr14) 2660 | ; ---- 2661 | ; Regs needed (approximately): 6 2662 | ; -------- 2663 | ; ; vr0 2664 | mov ax, 8 ; vr0 2665 | push ax ; vr1 2666 | mov ax, 4 ; vr2 2667 | push ax ; vr3 2668 | mov ax, _add ; vr4 2669 | call ax ; vr5 2670 | add sp, 4 ; vr5 2671 | push ax ; vr6 2672 | mov ax, 2 ; vr7 2673 | push ax ; vr8 2674 | mov ax, 1 ; vr9 2675 | push ax ; vr10 2676 | mov ax, _add ; vr11 2677 | call ax ; vr12 2678 | add sp, 4 ; vr12 2679 | push ax ; vr13 2680 | mov ax, _add ; vr14 2681 | call ax ; vr15 2682 | add sp, 4 ; vr15 2683 | ; ; vr15 2684 | cmp ax, 15 ; vr15 2685 | jne failure ; vr15 2686 | 2687 | ; () (vr191) 2688 | ; _ten (vr190) 2689 | ; sub (vr192) 2690 | ; 16 (vr184) 2691 | ; add (vr185) 2692 | ; 15 (vr183) 2693 | ; add (vr186) 2694 | ; 14 (vr181) 2695 | ; add (vr182) 2696 | ; 13 (vr180) 2697 | ; add (vr187) 2698 | ; 12 (vr177) 2699 | ; add (vr178) 2700 | ; 11 (vr176) 2701 | ; add (vr179) 2702 | ; 10 (vr174) 2703 | ; add (vr175) 2704 | ; 9 (vr173) 2705 | ; add (vr188) 2706 | ; 8 (vr169) 2707 | ; add (vr170) 2708 | ; 7 (vr168) 2709 | ; add (vr171) 2710 | ; 6 (vr166) 2711 | ; add (vr167) 2712 | ; 5 (vr165) 2713 | ; add (vr172) 2714 | ; 4 (vr162) 2715 | ; add (vr163) 2716 | ; 3 (vr161) 2717 | ; add (vr164) 2718 | ; 2 (vr159) 2719 | ; add (vr160) 2720 | ; 1 (vr158) 2721 | ; add (vr189) 2722 | ; 16 (vr153) 2723 | ; add (vr154) 2724 | ; 15 (vr152) 2725 | ; add (vr155) 2726 | ; 14 (vr150) 2727 | ; add (vr151) 2728 | ; 13 (vr149) 2729 | ; add (vr156) 2730 | ; 12 (vr146) 2731 | ; add (vr147) 2732 | ; 11 (vr145) 2733 | ; add (vr148) 2734 | ; 10 (vr143) 2735 | ; add (vr144) 2736 | ; 9 (vr142) 2737 | ; add (vr157) 2738 | ; 8 (vr138) 2739 | ; add (vr139) 2740 | ; 7 (vr137) 2741 | ; add (vr140) 2742 | ; 6 (vr135) 2743 | ; add (vr136) 2744 | ; 5 (vr134) 2745 | ; add (vr141) 2746 | ; 4 (vr131) 2747 | ; add (vr132) 2748 | ; 3 (vr130) 2749 | ; add (vr133) 2750 | ; 2 (vr128) 2751 | ; add (vr129) 2752 | ; 1 (vr127) 2753 | ; add (vr193) 2754 | ; 16 (vr120) 2755 | ; add (vr121) 2756 | ; 15 (vr119) 2757 | ; add (vr122) 2758 | ; 14 (vr117) 2759 | ; add (vr118) 2760 | ; 13 (vr116) 2761 | ; add (vr123) 2762 | ; 12 (vr113) 2763 | ; add (vr114) 2764 | ; 11 (vr112) 2765 | ; add (vr115) 2766 | ; 10 (vr110) 2767 | ; add (vr111) 2768 | ; 9 (vr109) 2769 | ; add (vr124) 2770 | ; 8 (vr105) 2771 | ; add (vr106) 2772 | ; 7 (vr104) 2773 | ; add (vr107) 2774 | ; 6 (vr102) 2775 | ; add (vr103) 2776 | ; 5 (vr101) 2777 | ; add (vr108) 2778 | ; 4 (vr98) 2779 | ; add (vr99) 2780 | ; 3 (vr97) 2781 | ; add (vr100) 2782 | ; 2 (vr95) 2783 | ; add (vr96) 2784 | ; 1 (vr94) 2785 | ; add (vr125) 2786 | ; 16 (vr89) 2787 | ; add (vr90) 2788 | ; 15 (vr88) 2789 | ; add (vr91) 2790 | ; 14 (vr86) 2791 | ; add (vr87) 2792 | ; 13 (vr85) 2793 | ; add (vr92) 2794 | ; 12 (vr82) 2795 | ; add (vr83) 2796 | ; 11 (vr81) 2797 | ; add (vr84) 2798 | ; 10 (vr79) 2799 | ; add (vr80) 2800 | ; 9 (vr78) 2801 | ; add (vr93) 2802 | ; 8 (vr74) 2803 | ; add (vr75) 2804 | ; 7 (vr73) 2805 | ; add (vr76) 2806 | ; 6 (vr71) 2807 | ; add (vr72) 2808 | ; 5 (vr70) 2809 | ; add (vr77) 2810 | ; 4 (vr67) 2811 | ; add (vr68) 2812 | ; 3 (vr66) 2813 | ; add (vr69) 2814 | ; 2 (vr64) 2815 | ; add (vr65) 2816 | ; 1 (vr63) 2817 | ; sub (vr126) 2818 | ; 16 (vr57) 2819 | ; add (vr58) 2820 | ; 15 (vr56) 2821 | ; add (vr59) 2822 | ; 14 (vr54) 2823 | ; add (vr55) 2824 | ; 13 (vr53) 2825 | ; add (vr60) 2826 | ; 12 (vr50) 2827 | ; add (vr51) 2828 | ; 11 (vr49) 2829 | ; add (vr52) 2830 | ; 10 (vr47) 2831 | ; add (vr48) 2832 | ; 9 (vr46) 2833 | ; add (vr61) 2834 | ; 8 (vr42) 2835 | ; add (vr43) 2836 | ; 7 (vr41) 2837 | ; add (vr44) 2838 | ; 6 (vr39) 2839 | ; add (vr40) 2840 | ; 5 (vr38) 2841 | ; add (vr45) 2842 | ; 4 (vr35) 2843 | ; add (vr36) 2844 | ; 3 (vr34) 2845 | ; add (vr37) 2846 | ; 2 (vr32) 2847 | ; add (vr33) 2848 | ; 1 (vr31) 2849 | ; add (vr62) 2850 | ; 16 (vr26) 2851 | ; add (vr27) 2852 | ; 15 (vr25) 2853 | ; add (vr28) 2854 | ; 14 (vr23) 2855 | ; add (vr24) 2856 | ; 13 (vr22) 2857 | ; add (vr29) 2858 | ; 12 (vr19) 2859 | ; add (vr20) 2860 | ; 11 (vr18) 2861 | ; add (vr21) 2862 | ; 10 (vr16) 2863 | ; add (vr17) 2864 | ; 9 (vr15) 2865 | ; add (vr30) 2866 | ; 8 (vr11) 2867 | ; add (vr12) 2868 | ; 7 (vr10) 2869 | ; add (vr13) 2870 | ; 6 (vr8) 2871 | ; add (vr9) 2872 | ; 5 (vr7) 2873 | ; add (vr14) 2874 | ; 4 (vr4) 2875 | ; add (vr5) 2876 | ; 3 (vr3) 2877 | ; add (vr6) 2878 | ; 2 (vr1) 2879 | ; add (vr2) 2880 | ; 1 (vr0) 2881 | ; ---- 2882 | ; Regs needed (approximately): 8 2883 | ; -------- 2884 | ; ; vr0 2885 | mov ax, 1 ; vr0 2886 | mov cx, 2 ; vr1 2887 | add ax, cx ; vr2 2888 | mov cx, 3 ; vr3 2889 | mov dx, 4 ; vr4 2890 | add cx, dx ; vr5 2891 | add ax, cx ; vr6 2892 | mov cx, 5 ; vr7 2893 | mov dx, 6 ; vr8 2894 | add cx, dx ; vr9 2895 | mov dx, 7 ; vr10 2896 | mov bx, 8 ; vr11 2897 | add dx, bx ; vr12 2898 | add cx, dx ; vr13 2899 | add ax, cx ; vr14 2900 | mov cx, 9 ; vr15 2901 | mov dx, 10 ; vr16 2902 | add cx, dx ; vr17 2903 | mov dx, 11 ; vr18 2904 | mov bx, 12 ; vr19 2905 | add dx, bx ; vr20 2906 | add cx, dx ; vr21 2907 | mov dx, 13 ; vr22 2908 | mov bx, 14 ; vr23 2909 | add dx, bx ; vr24 2910 | mov bx, 15 ; vr25 2911 | mov si, 16 ; vr26 2912 | add bx, si ; vr27 2913 | add dx, bx ; vr28 2914 | add cx, dx ; vr29 2915 | add ax, cx ; vr30 2916 | mov cx, 1 ; vr31 2917 | mov dx, 2 ; vr32 2918 | add cx, dx ; vr33 2919 | mov dx, 3 ; vr34 2920 | mov bx, 4 ; vr35 2921 | add dx, bx ; vr36 2922 | add cx, dx ; vr37 2923 | mov dx, 5 ; vr38 2924 | mov bx, 6 ; vr39 2925 | add dx, bx ; vr40 2926 | mov bx, 7 ; vr41 2927 | mov si, 8 ; vr42 2928 | add bx, si ; vr43 2929 | add dx, bx ; vr44 2930 | add cx, dx ; vr45 2931 | mov dx, 9 ; vr46 2932 | mov bx, 10 ; vr47 2933 | add dx, bx ; vr48 2934 | mov bx, 11 ; vr49 2935 | mov si, 12 ; vr50 2936 | add bx, si ; vr51 2937 | add dx, bx ; vr52 2938 | mov bx, 13 ; vr53 2939 | mov si, 14 ; vr54 2940 | add bx, si ; vr55 2941 | mov si, 15 ; vr56 2942 | mov di, 16 ; vr57 2943 | add si, di ; vr58 2944 | add bx, si ; vr59 2945 | add dx, bx ; vr60 2946 | add cx, dx ; vr61 2947 | add ax, cx ; vr62 2948 | mov cx, 1 ; vr63 2949 | mov dx, 2 ; vr64 2950 | add cx, dx ; vr65 2951 | mov dx, 3 ; vr66 2952 | mov bx, 4 ; vr67 2953 | add dx, bx ; vr68 2954 | add cx, dx ; vr69 2955 | mov dx, 5 ; vr70 2956 | mov bx, 6 ; vr71 2957 | add dx, bx ; vr72 2958 | mov bx, 7 ; vr73 2959 | mov si, 8 ; vr74 2960 | add bx, si ; vr75 2961 | add dx, bx ; vr76 2962 | add cx, dx ; vr77 2963 | mov dx, 9 ; vr78 2964 | mov bx, 10 ; vr79 2965 | add dx, bx ; vr80 2966 | mov bx, 11 ; vr81 2967 | mov si, 12 ; vr82 2968 | add bx, si ; vr83 2969 | add dx, bx ; vr84 2970 | mov bx, 13 ; vr85 2971 | mov si, 14 ; vr86 2972 | add bx, si ; vr87 2973 | mov si, 15 ; vr88 2974 | mov di, 16 ; vr89 2975 | add si, di ; vr90 2976 | add bx, si ; vr91 2977 | add dx, bx ; vr92 2978 | add cx, dx ; vr93 2979 | mov dx, 1 ; vr94 2980 | mov bx, 2 ; vr95 2981 | add dx, bx ; vr96 2982 | mov bx, 3 ; vr97 2983 | mov si, 4 ; vr98 2984 | add bx, si ; vr99 2985 | add dx, bx ; vr100 2986 | mov bx, 5 ; vr101 2987 | mov si, 6 ; vr102 2988 | add bx, si ; vr103 2989 | mov si, 7 ; vr104 2990 | mov di, 8 ; vr105 2991 | add si, di ; vr106 2992 | add bx, si ; vr107 2993 | add dx, bx ; vr108 2994 | mov bx, 9 ; vr109 2995 | mov si, 10 ; vr110 2996 | add bx, si ; vr111 2997 | mov si, 11 ; vr112 2998 | mov di, 12 ; vr113 2999 | add si, di ; vr114 3000 | add bx, si ; vr115 3001 | mov si, 13 ; vr116 3002 | mov di, 14 ; vr117 3003 | add si, di ; vr118 3004 | mov di, 15 ; vr119 3005 | push ax ; vr120 3006 | mov ax, 16 ; vr120 3007 | add di, ax ; vr121 3008 | add si, di ; vr122 3009 | add bx, si ; vr123 3010 | add dx, bx ; vr124 3011 | add cx, dx ; vr125 3012 | pop ax ; vr126 3013 | sub ax, cx ; vr126 3014 | mov cx, 1 ; vr127 3015 | mov dx, 2 ; vr128 3016 | add cx, dx ; vr129 3017 | mov dx, 3 ; vr130 3018 | mov bx, 4 ; vr131 3019 | add dx, bx ; vr132 3020 | add cx, dx ; vr133 3021 | mov dx, 5 ; vr134 3022 | mov bx, 6 ; vr135 3023 | add dx, bx ; vr136 3024 | mov bx, 7 ; vr137 3025 | mov si, 8 ; vr138 3026 | add bx, si ; vr139 3027 | add dx, bx ; vr140 3028 | add cx, dx ; vr141 3029 | mov dx, 9 ; vr142 3030 | mov bx, 10 ; vr143 3031 | add dx, bx ; vr144 3032 | mov bx, 11 ; vr145 3033 | mov si, 12 ; vr146 3034 | add bx, si ; vr147 3035 | add dx, bx ; vr148 3036 | mov bx, 13 ; vr149 3037 | mov si, 14 ; vr150 3038 | add bx, si ; vr151 3039 | mov si, 15 ; vr152 3040 | mov di, 16 ; vr153 3041 | add si, di ; vr154 3042 | add bx, si ; vr155 3043 | add dx, bx ; vr156 3044 | add cx, dx ; vr157 3045 | mov dx, 1 ; vr158 3046 | mov bx, 2 ; vr159 3047 | add dx, bx ; vr160 3048 | mov bx, 3 ; vr161 3049 | mov si, 4 ; vr162 3050 | add bx, si ; vr163 3051 | add dx, bx ; vr164 3052 | mov bx, 5 ; vr165 3053 | mov si, 6 ; vr166 3054 | add bx, si ; vr167 3055 | mov si, 7 ; vr168 3056 | mov di, 8 ; vr169 3057 | add si, di ; vr170 3058 | add bx, si ; vr171 3059 | add dx, bx ; vr172 3060 | mov bx, 9 ; vr173 3061 | mov si, 10 ; vr174 3062 | add bx, si ; vr175 3063 | mov si, 11 ; vr176 3064 | mov di, 12 ; vr177 3065 | add si, di ; vr178 3066 | add bx, si ; vr179 3067 | mov si, 13 ; vr180 3068 | mov di, 14 ; vr181 3069 | add si, di ; vr182 3070 | mov di, 15 ; vr183 3071 | push ax ; vr184 3072 | mov ax, 16 ; vr184 3073 | add di, ax ; vr185 3074 | add si, di ; vr186 3075 | add bx, si ; vr187 3076 | add dx, bx ; vr188 3077 | add cx, dx ; vr189 3078 | push cx ; vr189 3079 | mov ax, _ten ; vr190 3080 | call ax ; vr191 3081 | pop cx ; vr192 3082 | sub cx, ax ; vr192 3083 | pop ax ; vr193 3084 | add ax, cx ; vr193 3085 | ; ; vr193 3086 | cmp ax, 262 ; vr193 3087 | jne failure ; vr193 3088 | 3089 | mov dx, msg_success 3090 | mov ah, 9 3091 | int 0x21 3092 | mov ax, 0x4C00 3093 | int 0x21 3094 | 3095 | no_memory: 3096 | mov dx, msg_memory 3097 | mov ah, 9 3098 | int 0x21 3099 | mov ax, 0x4C01 3100 | int 0x21 3101 | 3102 | failure: 3103 | mov dx, msg_failure 3104 | mov ah, 9 3105 | int 0x21 3106 | mov ax, 0x4C01 3107 | int 0x21 3108 | 3109 | msg_success: 3110 | db "SUCCESS!", 13, 10, "$" 3111 | 3112 | msg_memory: 3113 | db "OUT OF MEMORY!", 13, 10, "$" 3114 | 3115 | msg_failure: 3116 | db "FAILURE!", 13, 10, "$" 3117 | 3118 | _ten: 3119 | mov ax, 10 3120 | ret 3121 | 3122 | _popcnt: 3123 | push bp 3124 | mov bp, sp 3125 | mov dx, [bp+4] 3126 | mov cx, 16 3127 | xor ax, ax 3128 | _popcnt_loop: 3129 | add dx, dx 3130 | adc ax, 0 3131 | loop _popcnt_loop 3132 | pop bp 3133 | ret 3134 | 3135 | _add: 3136 | push bp 3137 | mov bp, sp 3138 | mov ax, [bp+4] 3139 | add ax, [bp+6] 3140 | pop bp 3141 | ret 3142 | --------------------------------------------------------------------------------