From ee0e67b9d7c275480827d856b926d2c403057bb8 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Fri, 6 Mar 2020 18:39:16 -0800 Subject: 6091 --- html/013direct_addressing.cc.html | 1878 +++++---- html/014indirect_addressing.cc.html | 6 +- html/015immediate_addressing.cc.html | 39 + html/017jump_disp8.cc.html | 2 +- html/018jump_disp32.cc.html | 2 +- html/019functions.cc.html | 2 +- html/021byte_addressing.cc.html | 103 +- html/033check_operands.cc.html | 880 ++--- html/034check_operand_bounds.cc.html | 2 +- html/067parse-hex.subx.html | 1081 +++--- html/079emit.subx.html | 2 +- html/100array-equal.subx.html | 2 +- html/apps/assort.subx.html | 4 +- html/apps/crenshaw2-1.subx.html | 12 +- html/apps/crenshaw2-1b.subx.html | 12 +- html/apps/dquotes.subx.html | 4 +- html/apps/ex1.subx.html | 4 +- html/apps/ex10.subx.html | 4 +- html/apps/ex11.subx.html | 4 +- html/apps/ex12.subx.html | 4 +- html/apps/ex13.subx.html | 87 + html/apps/ex14.subx.html | 88 + html/apps/ex2.subx.html | 4 +- html/apps/ex3.subx.html | 4 +- html/apps/ex4.subx.html | 4 +- html/apps/ex5.subx.html | 4 +- html/apps/ex6.subx.html | 4 +- html/apps/ex7.subx.html | 4 +- html/apps/ex8.subx.html | 4 +- html/apps/ex9.subx.html | 4 +- html/apps/factorial.subx.html | 6 +- html/apps/factorial2.subx.html | 4 +- html/apps/factorial3.subx.html | 4 +- html/apps/factorial4.subx.html | 4 +- html/apps/handle.subx.html | 4 +- html/apps/hex.subx.html | 10 +- html/apps/mu.subx.html | 6994 +++++++++++++++++----------------- html/apps/pack.subx.html | 6 +- html/apps/random.subx.html | 4 +- html/apps/sigils.subx.html | 24 +- html/apps/survey.subx.html | 6 +- html/apps/tests.subx.html | 2 +- 42 files changed, 5848 insertions(+), 5474 deletions(-) create mode 100644 html/apps/ex13.subx.html create mode 100644 html/apps/ex14.subx.html diff --git a/html/013direct_addressing.cc.html b/html/013direct_addressing.cc.html index d99526d4..2e868413 100644 --- a/html/013direct_addressing.cc.html +++ b/html/013direct_addressing.cc.html @@ -382,962 +382,960 @@ if ('onhashchange' in window) { 321 trace(Callstack_depth+1, "run") << "multiply " << rname(arg1) << " by r/m32" << end(); 322 const int32_t* arg2 = effective_address(modrm); 323 int32_t result = Reg[arg1].i * (*arg2); - 324 SF = (Reg[arg1].i < 0); - 325 ZF = (Reg[arg1].i == 0); - 326 int64_t full_result = static_cast<int64_t>(Reg[arg1].i) * (*arg2); - 327 OF = (Reg[arg1].i != full_result); - 328 CF = OF; - 329 trace(Callstack_depth+1, "run") << "SF=" << SF << "; ZF=" << ZF << "; CF=" << CF << "; OF=" << OF << end(); - 330 Reg[arg1].i = result; - 331 trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << Reg[arg1].i << end(); - 332 break; - 333 } + 324 int64_t full_result = static_cast<int64_t>(Reg[arg1].i) * (*arg2); + 325 OF = (result != full_result); + 326 CF = OF; + 327 trace(Callstack_depth+1, "run") << "SF=" << SF << "; ZF=" << ZF << "; CF=" << CF << "; OF=" << OF << end(); + 328 Reg[arg1].i = result; + 329 trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << Reg[arg1].i << end(); + 330 break; + 331 } + 332 + 333 //:: negate 334 - 335 //:: negate - 336 - 337 :(code) - 338 void test_negate_r32() { - 339 Reg[EBX].i = 1; - 340 run( - 341 "== code 0x1\n" // code segment - 342 // op ModR/M SIB displacement immediate - 343 " f7 db \n" // negate EBX - 344 // ModR/M in binary: 11 (direct mode) 011 (subop negate) 011 (dest EBX) - 345 ); - 346 CHECK_TRACE_CONTENTS( - 347 "run: operate on r/m32\n" - 348 "run: r/m32 is EBX\n" - 349 "run: subop: negate\n" - 350 "run: storing 0xffffffff\n" - 351 ); - 352 } - 353 - 354 :(before "End Op f7 Subops") - 355 case 3: { // negate r/m32 - 356 trace(Callstack_depth+1, "run") << "subop: negate" << end(); - 357 // one case that can overflow - 358 if (static_cast<uint32_t>(*arg1) == 0x80000000) { - 359 trace(Callstack_depth+1, "run") << "overflow" << end(); - 360 SF = true; - 361 ZF = false; - 362 OF = true; - 363 break; - 364 } - 365 int32_t result = -(*arg1); - 366 SF = (result >> 31); - 367 ZF = (result == 0); - 368 OF = false; - 369 CF = (*arg1 != 0); - 370 trace(Callstack_depth+1, "run") << "SF=" << SF << "; ZF=" << ZF << "; CF=" << CF << "; OF=" << OF << end(); - 371 *arg1 = result; - 372 trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << *arg1 << end(); - 373 break; - 374 } - 375 - 376 :(code) - 377 // negate can overflow in exactly one situation - 378 void test_negate_can_overflow() { - 379 Reg[EBX].i = 0x80000000; // INT_MIN - 380 run( - 381 "== code 0x1\n" // code segment - 382 // op ModR/M SIB displacement immediate - 383 " f7 db \n" // negate EBX - 384 // ModR/M in binary: 11 (direct mode) 011 (subop negate) 011 (dest EBX) - 385 ); - 386 CHECK_TRACE_CONTENTS( - 387 "run: operate on r/m32\n" - 388 "run: r/m32 is EBX\n" - 389 "run: subop: negate\n" - 390 "run: overflow\n" - 391 ); - 392 } + 335 :(code) + 336 void test_negate_r32() { + 337 Reg[EBX].i = 1; + 338 run( + 339 "== code 0x1\n" // code segment + 340 // op ModR/M SIB displacement immediate + 341 " f7 db \n" // negate EBX + 342 // ModR/M in binary: 11 (direct mode) 011 (subop negate) 011 (dest EBX) + 343 ); + 344 CHECK_TRACE_CONTENTS( + 345 "run: operate on r/m32\n" + 346 "run: r/m32 is EBX\n" + 347 "run: subop: negate\n" + 348 "run: storing 0xffffffff\n" + 349 ); + 350 } + 351 + 352 :(before "End Op f7 Subops") + 353 case 3: { // negate r/m32 + 354 trace(Callstack_depth+1, "run") << "subop: negate" << end(); + 355 // one case that can overflow + 356 if (static_cast<uint32_t>(*arg1) == 0x80000000) { + 357 trace(Callstack_depth+1, "run") << "overflow" << end(); + 358 SF = true; + 359 ZF = false; + 360 OF = true; + 361 break; + 362 } + 363 int32_t result = -(*arg1); + 364 SF = (result >> 31); + 365 ZF = (result == 0); + 366 OF = false; + 367 CF = (*arg1 != 0); + 368 trace(Callstack_depth+1, "run") << "SF=" << SF << "; ZF=" << ZF << "; CF=" << CF << "; OF=" << OF << end(); + 369 *arg1 = result; + 370 trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << *arg1 << end(); + 371 break; + 372 } + 373 + 374 :(code) + 375 // negate can overflow in exactly one situation + 376 void test_negate_can_overflow() { + 377 Reg[EBX].i = 0x80000000; // INT_MIN + 378 run( + 379 "== code 0x1\n" // code segment + 380 // op ModR/M SIB displacement immediate + 381 " f7 db \n" // negate EBX + 382 // ModR/M in binary: 11 (direct mode) 011 (subop negate) 011 (dest EBX) + 383 ); + 384 CHECK_TRACE_CONTENTS( + 385 "run: operate on r/m32\n" + 386 "run: r/m32 is EBX\n" + 387 "run: subop: negate\n" + 388 "run: overflow\n" + 389 ); + 390 } + 391 + 392 //:: divide with remainder 393 - 394 //:: divide with remainder - 395 - 396 void test_divide_EAX_by_rm32() { - 397 Reg[EAX].u = 7; - 398 Reg[EDX].u = 0; - 399 Reg[ECX].i = 3; - 400 run( - 401 "== code 0x1\n" // code segment - 402 // op ModR/M SIB displacement immediate - 403 " f7 f9 \n" // multiply EAX by ECX - 404 // ModR/M in binary: 11 (direct mode) 111 (subop idiv) 001 (divisor ECX) - 405 ); - 406 CHECK_TRACE_CONTENTS( - 407 "run: operate on r/m32\n" - 408 "run: r/m32 is ECX\n" - 409 "run: subop: divide EDX:EAX by r/m32, storing quotient in EAX and remainder in EDX\n" - 410 "run: quotient: 0x00000002\n" - 411 "run: remainder: 0x00000001\n" - 412 ); - 413 } - 414 - 415 :(before "End Op f7 Subops") - 416 case 7: { // divide EDX:EAX by r/m32, storing quotient in EAX and remainder in EDX - 417 trace(Callstack_depth+1, "run") << "subop: divide EDX:EAX by r/m32, storing quotient in EAX and remainder in EDX" << end(); - 418 int64_t dividend = static_cast<int64_t>((static_cast<uint64_t>(Reg[EDX].u) << 32) | Reg[EAX].u); - 419 int32_t divisor = *arg1; - 420 assert(divisor != 0); - 421 Reg[EAX].i = dividend/divisor; // quotient - 422 Reg[EDX].i = dividend%divisor; // remainder - 423 // flag state undefined - 424 trace(Callstack_depth+1, "run") << "quotient: 0x" << HEXWORD << Reg[EAX].i << end(); - 425 trace(Callstack_depth+1, "run") << "remainder: 0x" << HEXWORD << Reg[EDX].i << end(); - 426 break; - 427 } - 428 - 429 :(code) - 430 void test_divide_EAX_by_negative_rm32() { - 431 Reg[EAX].u = 7; - 432 Reg[EDX].u = 0; - 433 Reg[ECX].i = -3; - 434 run( - 435 "== code 0x1\n" // code segment - 436 // op ModR/M SIB displacement immediate - 437 " f7 f9 \n" // multiply EAX by ECX - 438 // ModR/M in binary: 11 (direct mode) 111 (subop idiv) 001 (divisor ECX) - 439 ); - 440 CHECK_TRACE_CONTENTS( - 441 "run: operate on r/m32\n" - 442 "run: r/m32 is ECX\n" - 443 "run: subop: divide EDX:EAX by r/m32, storing quotient in EAX and remainder in EDX\n" - 444 "run: quotient: 0xfffffffe\n" // -2 - 445 "run: remainder: 0x00000001\n" - 446 ); - 447 } - 448 - 449 void test_divide_negative_EAX_by_rm32() { - 450 Reg[EAX].i = -7; - 451 Reg[EDX].i = -1; // sign extend - 452 Reg[ECX].i = 3; - 453 run( - 454 "== code 0x1\n" // code segment - 455 // op ModR/M SIB displacement immediate - 456 " f7 f9 \n" // multiply EAX by ECX - 457 // ModR/M in binary: 11 (direct mode) 111 (subop idiv) 001 (divisor ECX) - 458 ); - 459 CHECK_TRACE_CONTENTS( - 460 "run: operate on r/m32\n" - 461 "run: r/m32 is ECX\n" - 462 "run: subop: divide EDX:EAX by r/m32, storing quotient in EAX and remainder in EDX\n" - 463 "run: quotient: 0xfffffffe\n" // -2 - 464 "run: remainder: 0xffffffff\n" // -1, same sign as divident (EDX:EAX) - 465 ); - 466 } - 467 - 468 void test_divide_negative_EDX_EAX_by_rm32() { - 469 Reg[EAX].i = 0; // lower 32 bits are clear - 470 Reg[EDX].i = -7; - 471 Reg[ECX].i = 0x40000000; // 2^30 (largest positive power of 2) - 472 run( - 473 "== code 0x1\n" // code segment - 474 // op ModR/M SIB displacement immediate - 475 " f7 f9 \n" // multiply EAX by ECX - 476 // ModR/M in binary: 11 (direct mode) 111 (subop idiv) 001 (divisor ECX) - 477 ); - 478 CHECK_TRACE_CONTENTS( - 479 "run: operate on r/m32\n" - 480 "run: r/m32 is ECX\n" - 481 "run: subop: divide EDX:EAX by r/m32, storing quotient in EAX and remainder in EDX\n" - 482 "run: quotient: 0xffffffe4\n" // (-7 << 32) / (1 << 30) = -7 << 2 = -28 - 483 "run: remainder: 0x00000000\n" - 484 ); - 485 } + 394 void test_divide_EAX_by_rm32() { + 395 Reg[EAX].u = 7; + 396 Reg[EDX].u = 0; + 397 Reg[ECX].i = 3; + 398 run( + 399 "== code 0x1\n" // code segment + 400 // op ModR/M SIB displacement immediate + 401 " f7 f9 \n" // multiply EAX by ECX + 402 // ModR/M in binary: 11 (direct mode) 111 (subop idiv) 001 (divisor ECX) + 403 ); + 404 CHECK_TRACE_CONTENTS( + 405 "run: operate on r/m32\n" + 406 "run: r/m32 is ECX\n" + 407 "run: subop: divide EDX:EAX by r/m32, storing quotient in EAX and remainder in EDX\n" + 408 "run: quotient: 0x00000002\n" + 409 "run: remainder: 0x00000001\n" + 410 ); + 411 } + 412 + 413 :(before "End Op f7 Subops") + 414 case 7: { // divide EDX:EAX by r/m32, storing quotient in EAX and remainder in EDX + 415 trace(Callstack_depth+1, "run") << "subop: divide EDX:EAX by r/m32, storing quotient in EAX and remainder in EDX" << end(); + 416 int64_t dividend = static_cast<int64_t>((static_cast<uint64_t>(Reg[EDX].u) << 32) | Reg[EAX].u); + 417 int32_t divisor = *arg1; + 418 assert(divisor != 0); + 419 Reg[EAX].i = dividend/divisor; // quotient + 420 Reg[EDX].i = dividend%divisor; // remainder + 421 // flag state undefined + 422 trace(Callstack_depth+1, "run") << "quotient: 0x" << HEXWORD << Reg[EAX].i << end(); + 423 trace(Callstack_depth+1, "run") << "remainder: 0x" << HEXWORD << Reg[EDX].i << end(); + 424 break; + 425 } + 426 + 427 :(code) + 428 void test_divide_EAX_by_negative_rm32() { + 429 Reg[EAX].u = 7; + 430 Reg[EDX].u = 0; + 431 Reg[ECX].i = -3; + 432 run( + 433 "== code 0x1\n" // code segment + 434 // op ModR/M SIB displacement immediate + 435 " f7 f9 \n" // multiply EAX by ECX + 436 // ModR/M in binary: 11 (direct mode) 111 (subop idiv) 001 (divisor ECX) + 437 ); + 438 CHECK_TRACE_CONTENTS( + 439 "run: operate on r/m32\n" + 440 "run: r/m32 is ECX\n" + 441 "run: subop: divide EDX:EAX by r/m32, storing quotient in EAX and remainder in EDX\n" + 442 "run: quotient: 0xfffffffe\n" // -2 + 443 "run: remainder: 0x00000001\n" + 444 ); + 445 } + 446 + 447 void test_divide_negative_EAX_by_rm32() { + 448 Reg[EAX].i = -7; + 449 Reg[EDX].i = -1; // sign extend + 450 Reg[ECX].i = 3; + 451 run( + 452 "== code 0x1\n" // code segment + 453 // op ModR/M SIB displacement immediate + 454 " f7 f9 \n" // multiply EAX by ECX + 455 // ModR/M in binary: 11 (direct mode) 111 (subop idiv) 001 (divisor ECX) + 456 ); + 457 CHECK_TRACE_CONTENTS( + 458 "run: operate on r/m32\n" + 459 "run: r/m32 is ECX\n" + 460 "run: subop: divide EDX:EAX by r/m32, storing quotient in EAX and remainder in EDX\n" + 461 "run: quotient: 0xfffffffe\n" // -2 + 462 "run: remainder: 0xffffffff\n" // -1, same sign as divident (EDX:EAX) + 463 ); + 464 } + 465 + 466 void test_divide_negative_EDX_EAX_by_rm32() { + 467 Reg[EAX].i = 0; // lower 32 bits are clear + 468 Reg[EDX].i = -7; + 469 Reg[ECX].i = 0x40000000; // 2^30 (largest positive power of 2) + 470 run( + 471 "== code 0x1\n" // code segment + 472 // op ModR/M SIB displacement immediate + 473 " f7 f9 \n" // multiply EAX by ECX + 474 // ModR/M in binary: 11 (direct mode) 111 (subop idiv) 001 (divisor ECX) + 475 ); + 476 CHECK_TRACE_CONTENTS( + 477 "run: operate on r/m32\n" + 478 "run: r/m32 is ECX\n" + 479 "run: subop: divide EDX:EAX by r/m32, storing quotient in EAX and remainder in EDX\n" + 480 "run: quotient: 0xffffffe4\n" // (-7 << 32) / (1 << 30) = -7 << 2 = -28 + 481 "run: remainder: 0x00000000\n" + 482 ); + 483 } + 484 + 485 //:: shift left 486 - 487 //:: shift left - 488 - 489 :(before "End Initialize Op Names") - 490 put_new(Name, "d3", "shift rm32 by CL bits depending on subop (sal/sar/shl/shr)"); - 491 - 492 :(code) - 493 void test_shift_left_r32_with_cl() { - 494 Reg[EBX].i = 13; - 495 Reg[ECX].i = 1; - 496 run( - 497 "== code 0x1\n" // code segment - 498 // op ModR/M SIB displacement immediate - 499 " d3 e3 \n" // shift EBX left by CL bits - 500 // ModR/M in binary: 11 (direct mode) 100 (subop shift left) 011 (dest EBX) - 501 ); - 502 CHECK_TRACE_CONTENTS( - 503 "run: operate on r/m32\n" - 504 "run: r/m32 is EBX\n" - 505 "run: subop: shift left by CL bits\n" - 506 "run: storing 0x0000001a\n" - 507 ); - 508 } - 509 - 510 :(before "End Single-Byte Opcodes") - 511 case 0xd3: { - 512 const uint8_t modrm = next(); - 513 trace(Callstack_depth+1, "run") << "operate on r/m32" << end(); - 514 int32_t* arg1 = effective_address(modrm); - 515 const uint8_t subop = (modrm>>3)&0x7; // middle 3 'reg opcode' bits - 516 switch (subop) { - 517 case 4: { // shift left r/m32 by CL - 518 trace(Callstack_depth+1, "run") << "subop: shift left by CL bits" << end(); - 519 uint8_t count = Reg[ECX].u & 0x1f; - 520 // OF is only defined if count is 1 - 521 if (count == 1) { - 522 bool msb = (*arg1 & 0x80000000) >> 1; - 523 bool pnsb = (*arg1 & 0x40000000); - 524 OF = (msb != pnsb); - 525 } - 526 int32_t result = (*arg1 << count); - 527 ZF = (result == 0); - 528 SF = (result < 0); - 529 CF = (*arg1 << (count-1)) & 0x80000000; - 530 trace(Callstack_depth+1, "run") << "SF=" << SF << "; ZF=" << ZF << "; CF=" << CF << "; OF=" << OF << end(); - 531 *arg1 = result; - 532 trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << *arg1 << end(); - 533 break; - 534 } - 535 // End Op d3 Subops - 536 default: - 537 cerr << "unrecognized subop for opcode d3: " << NUM(subop) << '\n'; - 538 exit(1); - 539 } - 540 break; - 541 } + 487 :(before "End Initialize Op Names") + 488 put_new(Name, "d3", "shift rm32 by CL bits depending on subop (sal/sar/shl/shr)"); + 489 + 490 :(code) + 491 void test_shift_left_r32_with_cl() { + 492 Reg[EBX].i = 13; + 493 Reg[ECX].i = 1; + 494 run( + 495 "== code 0x1\n" // code segment + 496 // op ModR/M SIB displacement immediate + 497 " d3 e3 \n" // shift EBX left by CL bits + 498 // ModR/M in binary: 11 (direct mode) 100 (subop shift left) 011 (dest EBX) + 499 ); + 500 CHECK_TRACE_CONTENTS( + 501 "run: operate on r/m32\n" + 502 "run: r/m32 is EBX\n" + 503 "run: subop: shift left by CL bits\n" + 504 "run: storing 0x0000001a\n" + 505 ); + 506 } + 507 + 508 :(before "End Single-Byte Opcodes") + 509 case 0xd3: { + 510 const uint8_t modrm = next(); + 511 trace(Callstack_depth+1, "run") << "operate on r/m32" << end(); + 512 int32_t* arg1 = effective_address(modrm); + 513 const uint8_t subop = (modrm>>3)&0x7; // middle 3 'reg opcode' bits + 514 switch (subop) { + 515 case 4: { // shift left r/m32 by CL + 516 trace(Callstack_depth+1, "run") << "subop: shift left by CL bits" << end(); + 517 uint8_t count = Reg[ECX].u & 0x1f; + 518 // OF is only defined if count is 1 + 519 if (count == 1) { + 520 bool msb = (*arg1 & 0x80000000) >> 1; + 521 bool pnsb = (*arg1 & 0x40000000); + 522 OF = (msb != pnsb); + 523 } + 524 int32_t result = (*arg1 << count); + 525 ZF = (result == 0); + 526 SF = (result < 0); + 527 CF = (*arg1 << (count-1)) & 0x80000000; + 528 trace(Callstack_depth+1, "run") << "SF=" << SF << "; ZF=" << ZF << "; CF=" << CF << "; OF=" << OF << end(); + 529 *arg1 = result; + 530 trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << *arg1 << end(); + 531 break; + 532 } + 533 // End Op d3 Subops + 534 default: + 535 cerr << "unrecognized subop for opcode d3: " << NUM(subop) << '\n'; + 536 exit(1); + 537 } + 538 break; + 539 } + 540 + 541 //:: shift right arithmetic 542 - 543 //:: shift right arithmetic - 544 - 545 :(code) - 546 void test_shift_right_arithmetic_r32_with_cl() { - 547 Reg[EBX].i = 26; - 548 Reg[ECX].i = 1; - 549 run( - 550 "== code 0x1\n" // code segment - 551 // op ModR/M SIB displacement immediate - 552 " d3 fb \n" // shift EBX right by CL bits, while preserving sign - 553 // ModR/M in binary: 11 (direct mode) 111 (subop shift right arithmetic) 011 (dest EBX) - 554 ); - 555 CHECK_TRACE_CONTENTS( - 556 "run: operate on r/m32\n" - 557 "run: r/m32 is EBX\n" - 558 "run: subop: shift right by CL bits, while preserving sign\n" - 559 "run: storing 0x0000000d\n" - 560 ); - 561 } - 562 - 563 :(before "End Op d3 Subops") - 564 case 7: { // shift right r/m32 by CL, preserving sign - 565 trace(Callstack_depth+1, "run") << "subop: shift right by CL bits, while preserving sign" << end(); - 566 uint8_t count = Reg[ECX].u & 0x1f; - 567 *arg1 = (*arg1 >> count); - 568 ZF = (*arg1 == 0); - 569 SF = (*arg1 < 0); - 570 // OF is only defined if count is 1 - 571 if (count == 1) OF = false; - 572 // CF undefined - 573 trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << *arg1 << end(); - 574 break; - 575 } - 576 - 577 :(code) - 578 void test_shift_right_arithmetic_odd_r32_with_cl() { - 579 Reg[EBX].i = 27; - 580 Reg[ECX].i = 1; - 581 run( - 582 "== code 0x1\n" // code segment - 583 // op ModR/M SIB displacement immediate - 584 " d3 fb \n" // shift EBX right by CL bits, while preserving sign - 585 // ModR/M in binary: 11 (direct mode) 111 (subop shift right arithmetic) 011 (dest EBX) - 586 ); - 587 CHECK_TRACE_CONTENTS( - 588 "run: operate on r/m32\n" - 589 "run: r/m32 is EBX\n" - 590 "run: subop: shift right by CL bits, while preserving sign\n" - 591 // result: 13 - 592 "run: storing 0x0000000d\n" - 593 ); - 594 } - 595 - 596 void test_shift_right_arithmetic_negative_r32_with_cl() { - 597 Reg[EBX].i = 0xfffffffd; // -3 - 598 Reg[ECX].i = 1; - 599 run( - 600 "== code 0x1\n" // code segment - 601 // op ModR/M SIB displacement immediate - 602 " d3 fb \n" // shift EBX right by CL bits, while preserving sign - 603 // ModR/M in binary: 11 (direct mode) 111 (subop shift right arithmetic) 011 (dest EBX) - 604 ); - 605 CHECK_TRACE_CONTENTS( - 606 "run: operate on r/m32\n" - 607 "run: r/m32 is EBX\n" - 608 "run: subop: shift right by CL bits, while preserving sign\n" - 609 // result: -2 - 610 "run: storing 0xfffffffe\n" - 611 ); - 612 } + 543 :(code) + 544 void test_shift_right_arithmetic_r32_with_cl() { + 545 Reg[EBX].i = 26; + 546 Reg[ECX].i = 1; + 547 run( + 548 "== code 0x1\n" // code segment + 549 // op ModR/M SIB displacement immediate + 550 " d3 fb \n" // shift EBX right by CL bits, while preserving sign + 551 // ModR/M in binary: 11 (direct mode) 111 (subop shift right arithmetic) 011 (dest EBX) + 552 ); + 553 CHECK_TRACE_CONTENTS( + 554 "run: operate on r/m32\n" + 555 "run: r/m32 is EBX\n" + 556 "run: subop: shift right by CL bits, while preserving sign\n" + 557 "run: storing 0x0000000d\n" + 558 ); + 559 } + 560 + 561 :(before "End Op d3 Subops") + 562 case 7: { // shift right r/m32 by CL, preserving sign + 563 trace(Callstack_depth+1, "run") << "subop: shift right by CL bits, while preserving sign" << end(); + 564 uint8_t count = Reg[ECX].u & 0x1f; + 565 *arg1 = (*arg1 >> count); + 566 ZF = (*arg1 == 0); + 567 SF = (*arg1 < 0); + 568 // OF is only defined if count is 1 + 569 if (count == 1) OF = false; + 570 // CF undefined + 571 trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << *arg1 << end(); + 572 break; + 573 } + 574 + 575 :(code) + 576 void test_shift_right_arithmetic_odd_r32_with_cl() { + 577 Reg[EBX].i = 27; + 578 Reg[ECX].i = 1; + 579 run( + 580 "== code 0x1\n" // code segment + 581 // op ModR/M SIB displacement immediate + 582 " d3 fb \n" // shift EBX right by CL bits, while preserving sign + 583 // ModR/M in binary: 11 (direct mode) 111 (subop shift right arithmetic) 011 (dest EBX) + 584 ); + 585 CHECK_TRACE_CONTENTS( + 586 "run: operate on r/m32\n" + 587 "run: r/m32 is EBX\n" + 588 "run: subop: shift right by CL bits, while preserving sign\n" + 589 // result: 13 + 590 "run: storing 0x0000000d\n" + 591 ); + 592 } + 593 + 594 void test_shift_right_arithmetic_negative_r32_with_cl() { + 595 Reg[EBX].i = 0xfffffffd; // -3 + 596 Reg[ECX].i = 1; + 597 run( + 598 "== code 0x1\n" // code segment + 599 // op ModR/M SIB displacement immediate + 600 " d3 fb \n" // shift EBX right by CL bits, while preserving sign + 601 // ModR/M in binary: 11 (direct mode) 111 (subop shift right arithmetic) 011 (dest EBX) + 602 ); + 603 CHECK_TRACE_CONTENTS( + 604 "run: operate on r/m32\n" + 605 "run: r/m32 is EBX\n" + 606 "run: subop: shift right by CL bits, while preserving sign\n" + 607 // result: -2 + 608 "run: storing 0xfffffffe\n" + 609 ); + 610 } + 611 + 612 //:: shift right logical 613 - 614 //:: shift right logical - 615 - 616 :(code) - 617 void test_shift_right_logical_r32_with_cl() { - 618 Reg[EBX].i = 26; - 619 Reg[ECX].i = 1; - 620 run( - 621 "== code 0x1\n" // code segment - 622 // op ModR/M SIB displacement immediate - 623 " d3 eb \n" // shift EBX right by CL bits, while padding zeroes - 624 // ModR/M in binary: 11 (direct mode) 101 (subop shift right logical) 011 (dest EBX) - 625 ); - 626 CHECK_TRACE_CONTENTS( - 627 "run: operate on r/m32\n" - 628 "run: r/m32 is EBX\n" - 629 "run: subop: shift right by CL bits, while padding zeroes\n" - 630 // result: 13 - 631 "run: storing 0x0000000d\n" - 632 ); - 633 } - 634 - 635 :(before "End Op d3 Subops") - 636 case 5: { // shift right r/m32 by CL, padding zeroes - 637 trace(Callstack_depth+1, "run") << "subop: shift right by CL bits, while padding zeroes" << end(); - 638 uint8_t count = Reg[ECX].u & 0x1f; - 639 // OF is only defined if count is 1 - 640 if (count == 1) { - 641 bool msb = (*arg1 & 0x80000000) >> 1; - 642 bool pnsb = (*arg1 & 0x40000000); - 643 OF = (msb != pnsb); - 644 } - 645 uint32_t* uarg1 = reinterpret_cast<uint32_t*>(arg1); - 646 *uarg1 = (*uarg1 >> count); - 647 ZF = (*uarg1 == 0); - 648 // result is always positive by definition - 649 SF = false; - 650 // CF undefined - 651 trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << *arg1 << end(); - 652 break; - 653 } - 654 - 655 :(code) - 656 void test_shift_right_logical_odd_r32_with_cl() { - 657 Reg[EBX].i = 27; - 658 Reg[ECX].i = 1; - 659 run( - 660 "== code 0x1\n" // code segment - 661 // op ModR/M SIB displacement immediate - 662 " d3 eb \n" // shift EBX right by CL bits, while padding zeroes - 663 // ModR/M in binary: 11 (direct mode) 101 (subop shift right logical) 011 (dest EBX) - 664 ); - 665 CHECK_TRACE_CONTENTS( - 666 "run: operate on r/m32\n" - 667 "run: r/m32 is EBX\n" - 668 "run: subop: shift right by CL bits, while padding zeroes\n" - 669 // result: 13 - 670 "run: storing 0x0000000d\n" - 671 ); - 672 } - 673 - 674 void test_shift_right_logical_negative_r32_with_cl() { - 675 Reg[EBX].i = 0xfffffffd; - 676 Reg[ECX].i = 1; - 677 run( - 678 "== code 0x1\n" // code segment - 679 // op ModR/M SIB displacement immediate - 680 " d3 eb \n" // shift EBX right by CL bits, while padding zeroes - 681 // ModR/M in binary: 11 (direct mode) 101 (subop shift right logical) 011 (dest EBX) - 682 ); - 683 CHECK_TRACE_CONTENTS( - 684 "run: operate on r/m32\n" - 685 "run: r/m32 is EBX\n" - 686 "run: subop: shift right by CL bits, while padding zeroes\n" - 687 "run: storing 0x7ffffffe\n" - 688 ); - 689 } + 614 :(code) + 615 void test_shift_right_logical_r32_with_cl() { + 616 Reg[EBX].i = 26; + 617 Reg[ECX].i = 1; + 618 run( + 619 "== code 0x1\n" // code segment + 620 // op ModR/M SIB displacement immediate + 621 " d3 eb \n" // shift EBX right by CL bits, while padding zeroes + 622 // ModR/M in binary: 11 (direct mode) 101 (subop shift right logical) 011 (dest EBX) + 623 ); + 624 CHECK_TRACE_CONTENTS( + 625 "run: operate on r/m32\n" + 626 "run: r/m32 is EBX\n" + 627 "run: subop: shift right by CL bits, while padding zeroes\n" + 628 // result: 13 + 629 "run: storing 0x0000000d\n" + 630 ); + 631 } + 632 + 633 :(before "End Op d3 Subops") + 634 case 5: { // shift right r/m32 by CL, padding zeroes + 635 trace(Callstack_depth+1, "run") << "subop: shift right by CL bits, while padding zeroes" << end(); + 636 uint8_t count = Reg[ECX].u & 0x1f; + 637 // OF is only defined if count is 1 + 638 if (count == 1) { + 639 bool msb = (*arg1 & 0x80000000) >> 1; + 640 bool pnsb = (*arg1 & 0x40000000); + 641 OF = (msb != pnsb); + 642 } + 643 uint32_t* uarg1 = reinterpret_cast<uint32_t*>(arg1); + 644 *uarg1 = (*uarg1 >> count); + 645 ZF = (*uarg1 == 0); + 646 // result is always positive by definition + 647 SF = false; + 648 // CF undefined + 649 trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << *arg1 << end(); + 650 break; + 651 } + 652 + 653 :(code) + 654 void test_shift_right_logical_odd_r32_with_cl() { + 655 Reg[EBX].i = 27; + 656 Reg[ECX].i = 1; + 657 run( + 658 "== code 0x1\n" // code segment + 659 // op ModR/M SIB displacement immediate + 660 " d3 eb \n" // shift EBX right by CL bits, while padding zeroes + 661 // ModR/M in binary: 11 (direct mode) 101 (subop shift right logical) 011 (dest EBX) + 662 ); + 663 CHECK_TRACE_CONTENTS( + 664 "run: operate on r/m32\n" + 665 "run: r/m32 is EBX\n" + 666 "run: subop: shift right by CL bits, while padding zeroes\n" + 667 // result: 13 + 668 "run: storing 0x0000000d\n" + 669 ); + 670 } + 671 + 672 void test_shift_right_logical_negative_r32_with_cl() { + 673 Reg[EBX].i = 0xfffffffd; + 674 Reg[ECX].i = 1; + 675 run( + 676 "== code 0x1\n" // code segment + 677 // op ModR/M SIB displacement immediate + 678 " d3 eb \n" // shift EBX right by CL bits, while padding zeroes + 679 // ModR/M in binary: 11 (direct mode) 101 (subop shift right logical) 011 (dest EBX) + 680 ); + 681 CHECK_TRACE_CONTENTS( + 682 "run: operate on r/m32\n" + 683 "run: r/m32 is EBX\n" + 684 "run: subop: shift right by CL bits, while padding zeroes\n" + 685 "run: storing 0x7ffffffe\n" + 686 ); + 687 } + 688 + 689 //:: and 690 - 691 //:: and - 692 - 693 :(before "End Initialize Op Names") - 694 put_new(Name, "21", "rm32 = bitwise AND of r32 with rm32 (and)"); - 695 - 696 :(code) - 697 void test_and_r32_with_r32() { - 698 Reg[EAX].i = 0x0a0b0c0d; - 699 Reg[EBX].i = 0x000000ff; - 700 run( - 701 "== code 0x1\n" // code segment - 702 // op ModR/M SIB displacement immediate - 703 " 21 d8 \n" // and EBX with destination EAX - 704 // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) - 705 ); - 706 CHECK_TRACE_CONTENTS( - 707 "run: and EBX with r/m32\n" - 708 "run: r/m32 is EAX\n" - 709 "run: storing 0x0000000d\n" - 710 ); - 711 } - 712 - 713 :(before "End Single-Byte Opcodes") - 714 case 0x21: { // and r32 with r/m32 - 715 const uint8_t modrm = next(); - 716 const uint8_t arg2 = (modrm>>3)&0x7; - 717 trace(Callstack_depth+1, "run") << "and " << rname(arg2) << " with r/m32" << end(); - 718 // bitwise ops technically operate on unsigned numbers, but it makes no - 719 // difference - 720 int32_t* signed_arg1 = effective_address(modrm); - 721 *signed_arg1 &= Reg[arg2].i; - 722 trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << *signed_arg1 << end(); - 723 SF = (*signed_arg1 >> 31); - 724 ZF = (*signed_arg1 == 0); - 725 CF = false; - 726 OF = false; - 727 trace(Callstack_depth+1, "run") << "SF=" << SF << "; ZF=" << ZF << "; CF=" << CF << "; OF=" << OF << end(); - 728 break; - 729 } + 691 :(before "End Initialize Op Names") + 692 put_new(Name, "21", "rm32 = bitwise AND of r32 with rm32 (and)"); + 693 + 694 :(code) + 695 void test_and_r32_with_r32() { + 696 Reg[EAX].i = 0x0a0b0c0d; + 697 Reg[EBX].i = 0x000000ff; + 698 run( + 699 "== code 0x1\n" // code segment + 700 // op ModR/M SIB displacement immediate + 701 " 21 d8 \n" // and EBX with destination EAX + 702 // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) + 703 ); + 704 CHECK_TRACE_CONTENTS( + 705 "run: and EBX with r/m32\n" + 706 "run: r/m32 is EAX\n" + 707 "run: storing 0x0000000d\n" + 708 ); + 709 } + 710 + 711 :(before "End Single-Byte Opcodes") + 712 case 0x21: { // and r32 with r/m32 + 713 const uint8_t modrm = next(); + 714 const uint8_t arg2 = (modrm>>3)&0x7; + 715 trace(Callstack_depth+1, "run") << "and " << rname(arg2) << " with r/m32" << end(); + 716 // bitwise ops technically operate on unsigned numbers, but it makes no + 717 // difference + 718 int32_t* signed_arg1 = effective_address(modrm); + 719 *signed_arg1 &= Reg[arg2].i; + 720 trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << *signed_arg1 << end(); + 721 SF = (*signed_arg1 >> 31); + 722 ZF = (*signed_arg1 == 0); + 723 CF = false; + 724 OF = false; + 725 trace(Callstack_depth+1, "run") << "SF=" << SF << "; ZF=" << ZF << "; CF=" << CF << "; OF=" << OF << end(); + 726 break; + 727 } + 728 + 729 //:: or 730 - 731 //:: or - 732 - 733 :(before "End Initialize Op Names") - 734 put_new(Name, "09", "rm32 = bitwise OR of r32 with rm32 (or)"); - 735 - 736 :(code) - 737 void test_or_r32_with_r32() { - 738 Reg[EAX].i = 0x0a0b0c0d; - 739 Reg[EBX].i = 0xa0b0c0d0; - 740 run( - 741 "== code 0x1\n" // code segment - 742 // op ModR/M SIB displacement immediate - 743 " 09 d8 \n" // or EBX with destination EAX - 744 // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) - 745 ); - 746 CHECK_TRACE_CONTENTS( - 747 "run: or EBX with r/m32\n" - 748 "run: r/m32 is EAX\n" - 749 "run: storing 0xaabbccdd\n" - 750 ); - 751 } - 752 - 753 :(before "End Single-Byte Opcodes") - 754 case 0x09: { // or r32 with r/m32 - 755 const uint8_t modrm = next(); - 756 const uint8_t arg2 = (modrm>>3)&0x7; - 757 trace(Callstack_depth+1, "run") << "or " << rname(arg2) << " with r/m32" << end(); - 758 // bitwise ops technically operate on unsigned numbers, but it makes no - 759 // difference - 760 int32_t* signed_arg1 = effective_address(modrm); - 761 *signed_arg1 |= Reg[arg2].i; - 762 trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << *signed_arg1 << end(); - 763 SF = (*signed_arg1 >> 31); - 764 ZF = (*signed_arg1 == 0); - 765 CF = false; - 766 OF = false; - 767 trace(Callstack_depth+1, "run") << "SF=" << SF << "; ZF=" << ZF << "; CF=" << CF << "; OF=" << OF << end(); - 768 break; - 769 } + 731 :(before "End Initialize Op Names") + 732 put_new(Name, "09", "rm32 = bitwise OR of r32 with rm32 (or)"); + 733 + 734 :(code) + 735 void test_or_r32_with_r32() { + 736 Reg[EAX].i = 0x0a0b0c0d; + 737 Reg[EBX].i = 0xa0b0c0d0; + 738 run( + 739 "== code 0x1\n" // code segment + 740 // op ModR/M SIB displacement immediate + 741 " 09 d8 \n" // or EBX with destination EAX + 742 // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) + 743 ); + 744 CHECK_TRACE_CONTENTS( + 745 "run: or EBX with r/m32\n" + 746 "run: r/m32 is EAX\n" + 747 "run: storing 0xaabbccdd\n" + 748 ); + 749 } + 750 + 751 :(before "End Single-Byte Opcodes") + 752 case 0x09: { // or r32 with r/m32 + 753 const uint8_t modrm = next(); + 754 const uint8_t arg2 = (modrm>>3)&0x7; + 755 trace(Callstack_depth+1, "run") << "or " << rname(arg2) << " with r/m32" << end(); + 756 // bitwise ops technically operate on unsigned numbers, but it makes no + 757 // difference + 758 int32_t* signed_arg1 = effective_address(modrm); + 759 *signed_arg1 |= Reg[arg2].i; + 760 trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << *signed_arg1 << end(); + 761 SF = (*signed_arg1 >> 31); + 762 ZF = (*signed_arg1 == 0); + 763 CF = false; + 764 OF = false; + 765 trace(Callstack_depth+1, "run") << "SF=" << SF << "; ZF=" << ZF << "; CF=" << CF << "; OF=" << OF << end(); + 766 break; + 767 } + 768 + 769 //:: xor 770 - 771 //:: xor - 772 - 773 :(before "End Initialize Op Names") - 774 put_new(Name, "31", "rm32 = bitwise XOR of r32 with rm32 (xor)"); - 775 - 776 :(code) - 777 void test_xor_r32_with_r32() { - 778 Reg[EAX].i = 0x0a0b0c0d; - 779 Reg[EBX].i = 0xaabbc0d0; - 780 run( - 781 "== code 0x1\n" // code segment - 782 // op ModR/M SIB displacement immediate - 783 " 31 d8 \n" // xor EBX with destination EAX - 784 // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) - 785 ); - 786 CHECK_TRACE_CONTENTS( - 787 "run: xor EBX with r/m32\n" - 788 "run: r/m32 is EAX\n" - 789 "run: storing 0xa0b0ccdd\n" - 790 ); - 791 } - 792 - 793 :(before "End Single-Byte Opcodes") - 794 case 0x31: { // xor r32 with r/m32 - 795 const uint8_t modrm = next(); - 796 const uint8_t arg2 = (modrm>>3)&0x7; - 797 trace(Callstack_depth+1, "run") << "xor " << rname(arg2) << " with r/m32" << end(); - 798 // bitwise ops technically operate on unsigned numbers, but it makes no - 799 // difference - 800 int32_t* signed_arg1 = effective_address(modrm); - 801 *signed_arg1 ^= Reg[arg2].i; - 802 trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << *signed_arg1 << end(); - 803 SF = (*signed_arg1 >> 31); - 804 ZF = (*signed_arg1 == 0); - 805 CF = false; - 806 OF = false; - 807 trace(Callstack_depth+1, "run") << "SF=" << SF << "; ZF=" << ZF << "; CF=" << CF << "; OF=" << OF << end(); - 808 break; - 809 } + 771 :(before "End Initialize Op Names") + 772 put_new(Name, "31", "rm32 = bitwise XOR of r32 with rm32 (xor)"); + 773 + 774 :(code) + 775 void test_xor_r32_with_r32() { + 776 Reg[EAX].i = 0x0a0b0c0d; + 777 Reg[EBX].i = 0xaabbc0d0; + 778 run( + 779 "== code 0x1\n" // code segment + 780 // op ModR/M SIB displacement immediate + 781 " 31 d8 \n" // xor EBX with destination EAX + 782 // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) + 783 ); + 784 CHECK_TRACE_CONTENTS( + 785 "run: xor EBX with r/m32\n" + 786 "run: r/m32 is EAX\n" + 787 "run: storing 0xa0b0ccdd\n" + 788 ); + 789 } + 790 + 791 :(before "End Single-Byte Opcodes") + 792 case 0x31: { // xor r32 with r/m32 + 793 const uint8_t modrm = next(); + 794 const uint8_t arg2 = (modrm>>3)&0x7; + 795 trace(Callstack_depth+1, "run") << "xor " << rname(arg2) << " with r/m32" << end(); + 796 // bitwise ops technically operate on unsigned numbers, but it makes no + 797 // difference + 798 int32_t* signed_arg1 = effective_address(modrm); + 799 *signed_arg1 ^= Reg[arg2].i; + 800 trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << *signed_arg1 << end(); + 801 SF = (*signed_arg1 >> 31); + 802 ZF = (*signed_arg1 == 0); + 803 CF = false; + 804 OF = false; + 805 trace(Callstack_depth+1, "run") << "SF=" << SF << "; ZF=" << ZF << "; CF=" << CF << "; OF=" << OF << end(); + 806 break; + 807 } + 808 + 809 //:: not 810 - 811 //:: not - 812 - 813 :(code) - 814 void test_not_r32() { - 815 Reg[EBX].i = 0x0f0f00ff; - 816 run( - 817 "== code 0x1\n" // code segment - 818 // op ModR/M SIB displacement immediate - 819 " f7 d3 \n" // not EBX - 820 // ModR/M in binary: 11 (direct mode) 010 (subop not) 011 (dest EBX) - 821 ); - 822 CHECK_TRACE_CONTENTS( - 823 "run: operate on r/m32\n" - 824 "run: r/m32 is EBX\n" - 825 "run: subop: not\n" - 826 "run: storing 0xf0f0ff00\n" - 827 ); - 828 } - 829 - 830 :(before "End Op f7 Subops") - 831 case 2: { // not r/m32 - 832 trace(Callstack_depth+1, "run") << "subop: not" << end(); - 833 *arg1 = ~(*arg1); - 834 trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << *arg1 << end(); - 835 // no flags affected - 836 break; - 837 } + 811 :(code) + 812 void test_not_r32() { + 813 Reg[EBX].i = 0x0f0f00ff; + 814 run( + 815 "== code 0x1\n" // code segment + 816 // op ModR/M SIB displacement immediate + 817 " f7 d3 \n" // not EBX + 818 // ModR/M in binary: 11 (direct mode) 010 (subop not) 011 (dest EBX) + 819 ); + 820 CHECK_TRACE_CONTENTS( + 821 "run: operate on r/m32\n" + 822 "run: r/m32 is EBX\n" + 823 "run: subop: not\n" + 824 "run: storing 0xf0f0ff00\n" + 825 ); + 826 } + 827 + 828 :(before "End Op f7 Subops") + 829 case 2: { // not r/m32 + 830 trace(Callstack_depth+1, "run") << "subop: not" << end(); + 831 *arg1 = ~(*arg1); + 832 trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << *arg1 << end(); + 833 // no flags affected + 834 break; + 835 } + 836 + 837 //:: compare (cmp) 838 - 839 //:: compare (cmp) - 840 - 841 :(before "End Initialize Op Names") - 842 put_new(Name, "39", "compare: set SF if rm32 < r32 (cmp)"); - 843 - 844 :(code) - 845 void test_compare_r32_with_r32_greater() { - 846 Reg[EAX].i = 0x0a0b0c0d; - 847 Reg[EBX].i = 0x0a0b0c07; - 848 run( - 849 "== code 0x1\n" // code segment - 850 // op ModR/M SIB displacement immediate - 851 " 39 d8 \n" // compare EAX with EBX - 852 // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) - 853 ); - 854 CHECK_TRACE_CONTENTS( - 855 "run: compare r/m32 with EBX\n" - 856 "run: r/m32 is EAX\n" - 857 "run: SF=0; ZF=0; CF=0; OF=0\n" - 858 ); - 859 } - 860 - 861 :(before "End Single-Byte Opcodes") - 862 case 0x39: { // set SF if r/m32 < r32 - 863 const uint8_t modrm = next(); - 864 const uint8_t reg2 = (modrm>>3)&0x7; - 865 trace(Callstack_depth+1, "run") << "compare r/m32 with " << rname(reg2) << end(); - 866 const int32_t* signed_arg1 = effective_address(modrm); - 867 const int32_t signed_difference = *signed_arg1 - Reg[reg2].i; - 868 SF = (signed_difference < 0); - 869 ZF = (signed_difference == 0); - 870 const int64_t signed_full_difference = static_cast<int64_t>(*signed_arg1) - Reg[reg2].i; - 871 OF = (signed_difference != signed_full_difference); - 872 // set CF - 873 const uint32_t unsigned_arg1 = static_cast<uint32_t>(*signed_arg1); - 874 const uint32_t unsigned_difference = unsigned_arg1 - Reg[reg2].u; - 875 const uint64_t unsigned_full_difference = static_cast<uint64_t>(unsigned_arg1) - Reg[reg2].u; - 876 CF = (unsigned_difference != unsigned_full_difference); - 877 trace(Callstack_depth+1, "run") << "SF=" << SF << "; ZF=" << ZF << "; CF=" << CF << "; OF=" << OF << end(); - 878 break; - 879 } - 880 - 881 :(code) - 882 void test_compare_r32_with_r32_lesser_unsigned_and_signed() { - 883 Reg[EAX].i = 0x0a0b0c07; - 884 Reg[EBX].i = 0x0a0b0c0d; - 885 run( - 886 "== code 0x1\n" // code segment - 887 // op ModR/M SIB displacement immediate - 888 " 39 d8 \n" // compare EAX with EBX - 889 // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) - 890 ); - 891 CHECK_TRACE_CONTENTS( - 892 "run: compare r/m32 with EBX\n" - 893 "run: r/m32 is EAX\n" - 894 "run: SF=1; ZF=0; CF=1; OF=0\n" - 895 ); - 896 } - 897 - 898 void test_compare_r32_with_r32_lesser_unsigned_and_signed_due_to_overflow() { - 899 Reg[EAX].i = 0x7fffffff; // largest positive signed integer - 900 Reg[EBX].i = 0x80000000; // smallest negative signed integer - 901 run( - 902 "== code 0x1\n" // code segment - 903 // op ModR/M SIB displacement immediate - 904 " 39 d8 \n" // compare EAX with EBX - 905 // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) - 906 ); - 907 CHECK_TRACE_CONTENTS( - 908 "run: compare r/m32 with EBX\n" - 909 "run: r/m32 is EAX\n" - 910 "run: SF=1; ZF=0; CF=1; OF=1\n" - 911 ); - 912 } - 913 - 914 void test_compare_r32_with_r32_lesser_signed() { - 915 Reg[EAX].i = 0xffffffff; // -1 - 916 Reg[EBX].i = 0x00000001; // 1 - 917 run( - 918 "== code 0x1\n" // code segment - 919 // op ModR/M SIB displacement immediate - 920 " 39 d8 \n" // compare EAX with EBX - 921 // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) - 922 ); - 923 CHECK_TRACE_CONTENTS( - 924 "run: compare r/m32 with EBX\n" - 925 "run: r/m32 is EAX\n" - 926 "run: SF=1; ZF=0; CF=0; OF=0\n" - 927 ); - 928 } - 929 - 930 void test_compare_r32_with_r32_lesser_unsigned() { - 931 Reg[EAX].i = 0x00000001; // 1 - 932 Reg[EBX].i = 0xffffffff; // -1 - 933 run( - 934 "== code 0x1\n" // code segment - 935 // op ModR/M SIB displacement immediate - 936 " 39 d8 \n" // compare EAX with EBX - 937 // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) - 938 ); - 939 CHECK_TRACE_CONTENTS( - 940 "run: compare r/m32 with EBX\n" - 941 "run: r/m32 is EAX\n" - 942 "run: SF=0; ZF=0; CF=1; OF=0\n" - 943 ); - 944 } - 945 - 946 void test_compare_r32_with_r32_equal() { - 947 Reg[EAX].i = 0x0a0b0c0d; - 948 Reg[EBX].i = 0x0a0b0c0d; - 949 run( - 950 "== code 0x1\n" // code segment - 951 // op ModR/M SIB displacement immediate - 952 " 39 d8 \n" // compare EAX and EBX - 953 // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) - 954 ); - 955 CHECK_TRACE_CONTENTS( - 956 "run: compare r/m32 with EBX\n" - 957 "run: r/m32 is EAX\n" - 958 "run: SF=0; ZF=1; CF=0; OF=0\n" - 959 ); - 960 } + 839 :(before "End Initialize Op Names") + 840 put_new(Name, "39", "compare: set SF if rm32 < r32 (cmp)"); + 841 + 842 :(code) + 843 void test_compare_r32_with_r32_greater() { + 844 Reg[EAX].i = 0x0a0b0c0d; + 845 Reg[EBX].i = 0x0a0b0c07; + 846 run( + 847 "== code 0x1\n" // code segment + 848 // op ModR/M SIB displacement immediate + 849 " 39 d8 \n" // compare EAX with EBX + 850 // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) + 851 ); + 852 CHECK_TRACE_CONTENTS( + 853 "run: compare r/m32 with EBX\n" + 854 "run: r/m32 is EAX\n" + 855 "run: SF=0; ZF=0; CF=0; OF=0\n" + 856 ); + 857 } + 858 + 859 :(before "End Single-Byte Opcodes") + 860 case 0x39: { // set SF if r/m32 < r32 + 861 const uint8_t modrm = next(); + 862 const uint8_t reg2 = (modrm>>3)&0x7; + 863 trace(Callstack_depth+1, "run") << "compare r/m32 with " << rname(reg2) << end(); + 864 const int32_t* signed_arg1 = effective_address(modrm); + 865 const int32_t signed_difference = *signed_arg1 - Reg[reg2].i; + 866 SF = (signed_difference < 0); + 867 ZF = (signed_difference == 0); + 868 const int64_t signed_full_difference = static_cast<int64_t>(*signed_arg1) - Reg[reg2].i; + 869 OF = (signed_difference != signed_full_difference); + 870 // set CF + 871 const uint32_t unsigned_arg1 = static_cast<uint32_t>(*signed_arg1); + 872 const uint32_t unsigned_difference = unsigned_arg1 - Reg[reg2].u; + 873 const uint64_t unsigned_full_difference = static_cast<uint64_t>(unsigned_arg1) - Reg[reg2].u; + 874 CF = (unsigned_difference != unsigned_full_difference); + 875 trace(Callstack_depth+1, "run") << "SF=" << SF << "; ZF=" << ZF << "; CF=" << CF << "; OF=" << OF << end(); + 876 break; + 877 } + 878 + 879 :(code) + 880 void test_compare_r32_with_r32_lesser_unsigned_and_signed() { + 881 Reg[EAX].i = 0x0a0b0c07; + 882 Reg[EBX].i = 0x0a0b0c0d; + 883 run( + 884 "== code 0x1\n" // code segment + 885 // op ModR/M SIB displacement immediate + 886 " 39 d8 \n" // compare EAX with EBX + 887 // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) + 888 ); + 889 CHECK_TRACE_CONTENTS( + 890 "run: compare r/m32 with EBX\n" + 891 "run: r/m32 is EAX\n" + 892 "run: SF=1; ZF=0; CF=1; OF=0\n" + 893 ); + 894 } + 895 + 896 void test_compare_r32_with_r32_lesser_unsigned_and_signed_due_to_overflow() { + 897 Reg[EAX].i = 0x7fffffff; // largest positive signed integer + 898 Reg[EBX].i = 0x80000000; // smallest negative signed integer + 899 run( + 900 "== code 0x1\n" // code segment + 901 // op ModR/M SIB displacement immediate + 902 " 39 d8 \n" // compare EAX with EBX + 903 // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) + 904 ); + 905 CHECK_TRACE_CONTENTS( + 906 "run: compare r/m32 with EBX\n" + 907 "run: r/m32 is EAX\n" + 908 "run: SF=1; ZF=0; CF=1; OF=1\n" + 909 ); + 910 } + 911 + 912 void test_compare_r32_with_r32_lesser_signed() { + 913 Reg[EAX].i = 0xffffffff; // -1 + 914 Reg[EBX].i = 0x00000001; // 1 + 915 run( + 916 "== code 0x1\n" // code segment + 917 // op ModR/M SIB displacement immediate + 918 " 39 d8 \n" // compare EAX with EBX + 919 // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) + 920 ); + 921 CHECK_TRACE_CONTENTS( + 922 "run: compare r/m32 with EBX\n" + 923 "run: r/m32 is EAX\n" + 924 "run: SF=1; ZF=0; CF=0; OF=0\n" + 925 ); + 926 } + 927 + 928 void test_compare_r32_with_r32_lesser_unsigned() { + 929 Reg[EAX].i = 0x00000001; // 1 + 930 Reg[EBX].i = 0xffffffff; // -1 + 931 run( + 932 "== code 0x1\n" // code segment + 933 // op ModR/M SIB displacement immediate + 934 " 39 d8 \n" // compare EAX with EBX + 935 // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) + 936 ); + 937 CHECK_TRACE_CONTENTS( + 938 "run: compare r/m32 with EBX\n" + 939 "run: r/m32 is EAX\n" + 940 "run: SF=0; ZF=0; CF=1; OF=0\n" + 941 ); + 942 } + 943 + 944 void test_compare_r32_with_r32_equal() { + 945 Reg[EAX].i = 0x0a0b0c0d; + 946 Reg[EBX].i = 0x0a0b0c0d; + 947 run( + 948 "== code 0x1\n" // code segment + 949 // op ModR/M SIB displacement immediate + 950 " 39 d8 \n" // compare EAX and EBX + 951 // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) + 952 ); + 953 CHECK_TRACE_CONTENTS( + 954 "run: compare r/m32 with EBX\n" + 955 "run: r/m32 is EAX\n" + 956 "run: SF=0; ZF=1; CF=0; OF=0\n" + 957 ); + 958 } + 959 + 960 //:: copy (mov) 961 - 962 //:: copy (mov) - 963 - 964 :(before "End Initialize Op Names") - 965 put_new(Name, "89", "copy r32 to rm32 (mov)"); - 966 - 967 :(code) - 968 void test_copy_r32_to_r32() { - 969 Reg[EBX].i = 0xaf; - 970 run( - 971 "== code 0x1\n" // code segment - 972 // op ModR/M SIB displacement immediate - 973 " 89 d8 \n" // copy EBX to EAX - 974 // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) - 975 ); - 976 CHECK_TRACE_CONTENTS( - 977 "run: copy EBX to r/m32\n" - 978 "run: r/m32 is EAX\n" - 979 "run: storing 0x000000af\n" - 980 ); - 981 } - 982 - 983 :(before "End Single-Byte Opcodes") - 984 case 0x89: { // copy r32 to r/m32 - 985 const uint8_t modrm = next(); - 986 const uint8_t rsrc = (modrm>>3)&0x7; - 987 trace(Callstack_depth+1, "run") << "copy " << rname(rsrc) << " to r/m32" << end(); - 988 int32_t* dest = effective_address(modrm); - 989 *dest = Reg[rsrc].i; // Write multiple elements of vector<uint8_t> at once. Assumes sizeof(int) == 4 on the host as well. - 990 trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << *dest << end(); - 991 break; - 992 } + 962 :(before "End Initialize Op Names") + 963 put_new(Name, "89", "copy r32 to rm32 (mov)"); + 964 + 965 :(code) + 966 void test_copy_r32_to_r32() { + 967 Reg[EBX].i = 0xaf; + 968 run( + 969 "== code 0x1\n" // code segment + 970 // op ModR/M SIB displacement immediate + 971 " 89 d8 \n" // copy EBX to EAX + 972 // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) + 973 ); + 974 CHECK_TRACE_CONTENTS( + 975 "run: copy EBX to r/m32\n" + 976 "run: r/m32 is EAX\n" + 977 "run: storing 0x000000af\n" + 978 ); + 979 } + 980 + 981 :(before "End Single-Byte Opcodes") + 982 case 0x89: { // copy r32 to r/m32 + 983 const uint8_t modrm = next(); + 984 const uint8_t rsrc = (modrm>>3)&0x7; + 985 trace(Callstack_depth+1, "run") << "copy " << rname(rsrc) << " to r/m32" << end(); + 986 int32_t* dest = effective_address(modrm); + 987 *dest = Reg[rsrc].i; // Write multiple elements of vector<uint8_t> at once. Assumes sizeof(int) == 4 on the host as well. + 988 trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << *dest << end(); + 989 break; + 990 } + 991 + 992 //:: xchg 993 - 994 //:: xchg - 995 - 996 :(before "End Initialize Op Names") - 997 put_new(Name, "87", "swap the contents of r32 and rm32 (xchg)"); - 998 - 999 :(code) -1000 void test_xchg_r32_with_r32() { -1001 Reg[EBX].i = 0xaf; -1002 Reg[EAX].i = 0x2e; -1003 run( -1004 "== code 0x1\n" // code segment -1005 // op ModR/M SIB displacement immediate -1006 " 87 d8 \n" // exchange EBX with EAX -1007 // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) -1008 ); -1009 CHECK_TRACE_CONTENTS( -1010 "run: exchange EBX with r/m32\n" -1011 "run: r/m32 is EAX\n" -1012 "run: storing 0x000000af in r/m32\n" -1013 "run: storing 0x0000002e in EBX\n" -1014 ); -1015 } -1016 -1017 :(before "End Single-Byte Opcodes") -1018 case 0x87: { // exchange r32 with r/m32 -1019 const uint8_t modrm = next(); -1020 const uint8_t reg2 = (modrm>>3)&0x7; -1021 trace(Callstack_depth+1, "run") << "exchange " << rname(reg2) << " with r/m32" << end(); -1022 int32_t* arg1 = effective_address(modrm); -1023 const int32_t tmp = *arg1; -1024 *arg1 = Reg[reg2].i; -1025 Reg[reg2].i = tmp; -1026 trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << *arg1 << " in r/m32" << end(); -1027 trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << Reg[reg2].i << " in " << rname(reg2) << end(); -1028 break; -1029 } + 994 :(before "End Initialize Op Names") + 995 put_new(Name, "87", "swap the contents of r32 and rm32 (xchg)"); + 996 + 997 :(code) + 998 void test_xchg_r32_with_r32() { + 999 Reg[EBX].i = 0xaf; +1000 Reg[EAX].i = 0x2e; +1001 run( +1002 "== code 0x1\n" // code segment +1003 // op ModR/M SIB displacement immediate +1004 " 87 d8 \n" // exchange EBX with EAX +1005 // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX) +1006 ); +1007 CHECK_TRACE_CONTENTS( +1008 "run: exchange EBX with r/m32\n" +1009 "run: r/m32 is EAX\n" +1010 "run: storing 0x000000af in r/m32\n" +1011 "run: storing 0x0000002e in EBX\n" +1012 ); +1013 } +1014 +1015 :(before "End Single-Byte Opcodes") +1016 case 0x87: { // exchange r32 with r/m32 +1017 const uint8_t modrm = next(); +1018 const uint8_t reg2 = (modrm>>3)&0x7; +1019 trace(Callstack_depth+1, "run") << "exchange " << rname(reg2) << " with r/m32" << end(); +1020 int32_t* arg1 = effective_address(modrm); +1021 const int32_t tmp = *arg1; +1022 *arg1 = Reg[reg2].i; +1023 Reg[reg2].i = tmp; +1024 trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << *arg1 << " in r/m32" << end(); +1025 trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << Reg[reg2].i << " in " << rname(reg2) << end(); +1026 break; +1027 } +1028 +1029 //:: increment 1030 -1031 //:: increment -1032 -1033 :(before "End Initialize Op Names") -1034 put_new(Name, "40", "increment EAX (inc)"); -1035 put_new(Name, "41", "increment ECX (inc)"); -1036 put_new(Name, "42", "increment EDX (inc)"); -1037 put_new(Name, "43", "increment EBX (inc)"); -1038 put_new(Name, "44", "increment ESP (inc)"); -1039 put_new(Name, "45", "increment EBP (inc)"); -1040 put_new(Name, "46", "increment ESI (inc)"); -1041 put_new(Name, "47", "increment EDI (inc)"); -1042 -1043 :(code) -1044 void test_increment_r32() { -1045 Reg[ECX].u = 0x1f; -1046 run( -1047 "== code 0x1\n" // code segment -1048 // op ModR/M SIB displacement immediate -1049 " 41 \n" // increment ECX -1050 ); -1051 CHECK_TRACE_CONTENTS( -1052 "run: increment ECX\n" -1053 "run: storing value 0x00000020\n" -1054 ); -1055 } -1056 -1057 :(before "End Single-Byte Opcodes") -1058 case 0x40: -1059 case 0x41: -1060 case 0x42: -1061 case 0x43: -1062 case 0x44: -1063 case 0x45: -1064 case 0x46: -1065 case 0x47: { // increment r32 -1066 const uint8_t reg = op & 0x7; -1067 trace(Callstack_depth+1, "run") << "increment " << rname(reg) << end(); -1068 ++Reg[reg].u; -1069 trace(Callstack_depth+1, "run") << "storing value 0x" << HEXWORD << Reg[reg].u << end(); -1070 break; -1071 } -1072 -1073 :(before "End Initialize Op Names") -1074 put_new(Name, "ff", "increment/decrement/jump/push/call rm32 based on subop (inc/dec/jmp/push/call)"); -1075 -1076 :(code) -1077 void test_increment_rm32() { -1078 Reg[EAX].u = 0x20; -1079 run( -1080 "== code 0x1\n" // code segment -1081 // op ModR/M SIB displacement immediate -1082 " ff c0 \n" // increment EAX -1083 // ModR/M in binary: 11 (direct mode) 000 (subop inc) 000 (EAX) -1084 ); -1085 CHECK_TRACE_CONTENTS( -1086 "run: increment r/m32\n" -1087 "run: r/m32 is EAX\n" -1088 "run: storing value 0x00000021\n" -1089 ); -1090 } -1091 -1092 :(before "End Single-Byte Opcodes") -1093 case 0xff: { -1094 const uint8_t modrm = next(); -1095 const uint8_t subop = (modrm>>3)&0x7; // middle 3 'reg opcode' bits -1096 switch (subop) { -1097 case 0: { // increment r/m32 -1098 trace(Callstack_depth+1, "run") << "increment r/m32" << end(); -1099 int32_t* arg = effective_address(modrm); -1100 ++*arg; -1101 trace(Callstack_depth+1, "run") << "storing value 0x" << HEXWORD << *arg << end(); -1102 break; -1103 } -1104 default: -1105 cerr << "unrecognized subop for ff: " << HEXBYTE << NUM(subop) << '\n'; -1106 exit(1); -1107 // End Op ff Subops -1108 } -1109 break; -1110 } +1031 :(before "End Initialize Op Names") +1032 put_new(Name, "40", "increment EAX (inc)"); +1033 put_new(Name, "41", "increment ECX (inc)"); +1034 put_new(Name, "42", "increment EDX (inc)"); +1035 put_new(Name, "43", "increment EBX (inc)"); +1036 put_new(Name, "44", "increment ESP (inc)"); +1037 put_new(Name, "45", "increment EBP (inc)"); +1038 put_new(Name, "46", "increment ESI (inc)"); +1039 put_new(Name, "47", "increment EDI (inc)"); +1040 +1041 :(code) +1042 void test_increment_r32() { +1043 Reg[ECX].u = 0x1f; +1044 run( +1045 "== code 0x1\n" // code segment +1046 // op ModR/M SIB displacement immediate +1047 " 41 \n" // increment ECX +1048 ); +1049 CHECK_TRACE_CONTENTS( +1050 "run: increment ECX\n" +1051 "run: storing value 0x00000020\n" +1052 ); +1053 } +1054 +1055 :(before "End Single-Byte Opcodes") +1056 case 0x40: +1057 case 0x41: +1058 case 0x42: +1059 case 0x43: +1060 case 0x44: +1061 case 0x45: +1062 case 0x46: +1063 case 0x47: { // increment r32 +1064 const uint8_t reg = op & 0x7; +1065 trace(Callstack_depth+1, "run") << "increment " << rname(reg) << end(); +1066 ++Reg[reg].u; +1067 trace(Callstack_depth+1, "run") << "storing value 0x" << HEXWORD << Reg[reg].u << end(); +1068 break; +1069 } +1070 +1071 :(before "End Initialize Op Names") +1072 put_new(Name, "ff", "increment/decrement/jump/push/call rm32 based on subop (inc/dec/jmp/push/call)"); +1073 +1074 :(code) +1075 void test_increment_rm32() { +1076 Reg[EAX].u = 0x20; +1077 run( +1078 "== code 0x1\n" // code segment +1079 // op ModR/M SIB displacement immediate +1080 " ff c0 \n" // increment EAX +1081 // ModR/M in binary: 11 (direct mode) 000 (subop inc) 000 (EAX) +1082 ); +1083 CHECK_TRACE_CONTENTS( +1084 "run: increment r/m32\n" +1085 "run: r/m32 is EAX\n" +1086 "run: storing value 0x00000021\n" +1087 ); +1088 } +1089 +1090 :(before "End Single-Byte Opcodes") +1091 case 0xff: { +1092 const uint8_t modrm = next(); +1093 const uint8_t subop = (modrm>>3)&0x7; // middle 3 'reg opcode' bits +1094 switch (subop) { +1095 case 0: { // increment r/m32 +1096 trace(Callstack_depth+1, "run") << "increment r/m32" << end(); +1097 int32_t* arg = effective_address(modrm); +1098 ++*arg; +1099 trace(Callstack_depth+1, "run") << "storing value 0x" << HEXWORD << *arg << end(); +1100 break; +1101 } +1102 default: +1103 cerr << "unrecognized subop for ff: " << HEXBYTE << NUM(subop) << '\n'; +1104 exit(1); +1105 // End Op ff Subops +1106 } +1107 break; +1108 } +1109 +1110 //:: decrement 1111 -1112 //:: decrement -1113 -1114 :(before "End Initialize Op Names") -1115 put_new(Name, "48", "decrement EAX (dec)"); -1116 put_new(Name, "49", "decrement ECX (dec)"); -1117 put_new(Name, "4a", "decrement EDX (dec)"); -1118 put_new(Name, "4b", "decrement EBX (dec)"); -1119 put_new(Name, "4c", "decrement ESP (dec)"); -1120 put_new(Name, "4d", "decrement EBP (dec)"); -1121 put_new(Name, "4e", "decrement ESI (dec)"); -1122 put_new(Name, "4f", "decrement EDI (dec)"); -1123 -1124 :(code) -1125 void test_decrement_r32() { -1126 Reg[ECX].u = 0x1f; -1127 run( -1128 "== code 0x1\n" // code segment -1129 // op ModR/M SIB displacement immediate -1130 " 49 \n" // decrement ECX -1131 ); -1132 CHECK_TRACE_CONTENTS( -1133 "run: decrement ECX\n" -1134 "run: storing value 0x0000001e\n" -1135 ); -1136 } -1137 -1138 :(before "End Single-Byte Opcodes") -1139 case 0x48: -1140 case 0x49: -1141 case 0x4a: -1142 case 0x4b: -1143 case 0x4c: -1144 case 0x4d: -1145 case 0x4e: -1146 case 0x4f: { // decrement r32 -1147 const uint8_t reg = op & 0x7; -1148 trace(Callstack_depth+1, "run") << "decrement " << rname(reg) << end(); -1149 --Reg[reg].u; -1150 trace(Callstack_depth+1, "run") << "storing value 0x" << HEXWORD << Reg[reg].u << end(); -1151 break; -1152 } -1153 -1154 :(code) -1155 void test_decrement_rm32() { -1156 Reg[EAX].u = 0x20; -1157 run( -1158 "== code 0x1\n" // code segment -1159 // op ModR/M SIB displacement immediate -1160 " ff c8 \n" // decrement EAX -1161 // ModR/M in binary: 11 (direct mode) 001 (subop inc) 000 (EAX) -1162 ); -1163 CHECK_TRACE_CONTENTS( -1164 "run: decrement r/m32\n" -1165 "run: r/m32 is EAX\n" -1166 "run: storing value 0x0000001f\n" -1167 ); -1168 } -1169 -1170 :(before "End Op ff Subops") -1171 case 1: { // decrement r/m32 -1172 trace(Callstack_depth+1, "run") << "decrement r/m32" << end(); -1173 int32_t* arg = effective_address(modrm); -1174 --*arg; -1175 trace(Callstack_depth+1, "run") << "storing value 0x" << HEXWORD << *arg << end(); -1176 break; -1177 } +1112 :(before "End Initialize Op Names") +1113 put_new(Name, "48", "decrement EAX (dec)"); +1114 put_new(Name, "49", "decrement ECX (dec)"); +1115 put_new(Name, "4a", "decrement EDX (dec)"); +1116 put_new(Name, "4b", "decrement EBX (dec)"); +1117 put_new(Name, "4c", "decrement ESP (dec)"); +1118 put_new(Name, "4d", "decrement EBP (dec)"); +1119 put_new(Name, "4e", "decrement ESI (dec)"); +1120 put_new(Name, "4f", "decrement EDI (dec)"); +1121 +1122 :(code) +1123 void test_decrement_r32() { +1124 Reg[ECX].u = 0x1f; +1125 run( +1126 "== code 0x1\n" // code segment +1127 // op ModR/M SIB displacement immediate +1128 " 49 \n" // decrement ECX +1129 ); +1130 CHECK_TRACE_CONTENTS( +1131 "run: decrement ECX\n" +1132 "run: storing value 0x0000001e\n" +1133 ); +1134 } +1135 +1136 :(before "End Single-Byte Opcodes") +1137 case 0x48: +1138 case 0x49: +1139 case 0x4a: +1140 case 0x4b: +1141 case 0x4c: +1142 case 0x4d: +1143 case 0x4e: +1144 case 0x4f: { // decrement r32 +1145 const uint8_t reg = op & 0x7; +1146 trace(Callstack_depth+1, "run") << "decrement " << rname(reg) << end(); +1147 --Reg[reg].u; +1148 trace(Callstack_depth+1, "run") << "storing value 0x" << HEXWORD << Reg[reg].u << end(); +1149 break; +1150 } +1151 +1152 :(code) +1153 void test_decrement_rm32() { +1154 Reg[EAX].u = 0x20; +1155 run( +1156 "== code 0x1\n" // code segment +1157 // op ModR/M SIB displacement immediate +1158 " ff c8 \n" // decrement EAX +1159 // ModR/M in binary: 11 (direct mode) 001 (subop inc) 000 (EAX) +1160 ); +1161 CHECK_TRACE_CONTENTS( +1162 "run: decrement r/m32\n" +1163 "run: r/m32 is EAX\n" +1164 "run: storing value 0x0000001f\n" +1165 ); +1166 } +1167 +1168 :(before "End Op ff Subops") +1169 case 1: { // decrement r/m32 +1170 trace(Callstack_depth+1, "run") << "decrement r/m32" << end(); +1171 int32_t* arg = effective_address(modrm); +1172 --*arg; +1173 trace(Callstack_depth+1, "run") << "storing value 0x" << HEXWORD << *arg << end(); +1174 break; +1175 } +1176 +1177 //:: push 1178 -1179 //:: push -1180 -1181 :(before "End Initialize Op Names") -1182 put_new(Name, "50", "push EAX to stack (push)"); -1183 put_new(Name, "51", "push ECX to stack (push)"); -1184 put_new(Name, "52", "push EDX to stack (push)"); -1185 put_new(Name, "53", "push EBX to stack (push)"); -1186 put_new(Name, "54", "push ESP to stack (push)"); -1187 put_new(Name, "55", "push EBP to stack (push)"); -1188 put_new(Name, "56", "push ESI to stack (push)"); -1189 put_new(Name, "57", "push EDI to stack (push)"); -1190 -1191 :(code) -1192 void test_push_r32() { -1193 Mem.push_back(vma(0xbd000000)); // manually allocate memory -1194 Reg[ESP].u = 0xbd000008; -1195 Reg[EBX].i = 0x0000000a; -1196 run( -1197 "== code 0x1\n" // code segment -1198 // op ModR/M SIB displacement immediate -1199 " 53 \n" // push EBX to stack -1200 ); -1201 CHECK_TRACE_CONTENTS( -1202 "run: push EBX\n" -1203 "run: decrementing ESP to 0xbd000004\n" -1204 "run: pushing value 0x0000000a\n" -1205 ); -1206 } -1207 -1208 :(before "End Single-Byte Opcodes") -1209 case 0x50: -1210 case 0x51: -1211 case 0x52: -1212 case 0x53: -1213 case 0x54: -1214 case 0x55: -1215 case 0x56: -1216 case 0x57: { // push r32 to stack -1217 uint8_t reg = op & 0x7; -1218 trace(Callstack_depth+1, "run") << "push " << rname(reg) << end(); -1219 //? cerr << "push: " << NUM(reg) << ": " << Reg[reg].u << " => " << Reg[ESP].u << '\n'; -1220 push(Reg[reg].u); -1221 break; -1222 } +1179 :(before "End Initialize Op Names") +1180 put_new(Name, "50", "push EAX to stack (push)"); +1181 put_new(Name, "51", "push ECX to stack (push)"); +1182 put_new(Name, "52", "push EDX to stack (push)"); +1183 put_new(Name, "53", "push EBX to stack (push)"); +1184 put_new(Name, "54", "push ESP to stack (push)"); +1185 put_new(Name, "55", "push EBP to stack (push)"); +1186 put_new(Name, "56", "push ESI to stack (push)"); +1187 put_new(Name, "57", "push EDI to stack (push)"); +1188 +1189 :(code) +1190 void test_push_r32() { +1191 Mem.push_back(vma(0xbd000000)); // manually allocate memory +1192 Reg[ESP].u = 0xbd000008; +1193 Reg[EBX].i = 0x0000000a; +1194 run( +1195 "== code 0x1\n" // code segment +1196 // op ModR/M SIB displacement immediate +1197 " 53 \n" // push EBX to stack +1198 ); +1199 CHECK_TRACE_CONTENTS( +1200 "run: push EBX\n" +1201 "run: decrementing ESP to 0xbd000004\n" +1202 "run: pushing value 0x0000000a\n" +1203 ); +1204 } +1205 +1206 :(before "End Single-Byte Opcodes") +1207 case 0x50: +1208 case 0x51: +1209 case 0x52: +1210 case 0x53: +1211 case 0x54: +1212 case 0x55: +1213 case 0x56: +1214 case 0x57: { // push r32 to stack +1215 uint8_t reg = op & 0x7; +1216 trace(Callstack_depth+1, "run") << "push " << rname(reg) << end(); +1217 //? cerr << "push: " << NUM(reg) << ": " << Reg[reg].u << " => " << Reg[ESP].u << '\n'; +1218 push(Reg[reg].u); +1219 break; +1220 } +1221 +1222 //:: pop 1223 -1224 //:: pop -1225 -1226 :(before "End Initialize Op Names") -1227 put_new(Name, "58", "pop top of stack to EAX (pop)"); -1228 put_new(Name, "59", "pop top of stack to ECX (pop)"); -1229 put_new(Name, "5a", "pop top of stack to EDX (pop)"); -1230 put_new(Name, "5b", "pop top of stack to EBX (pop)"); -1231 put_new(Name, "5c", "pop top of stack to ESP (pop)"); -1232 put_new(Name, "5d", "pop top of stack to EBP (pop)"); -1233 put_new(Name, "5e", "pop top of stack to ESI (pop)"); -1234 put_new(Name, "5f", "pop top of stack to EDI (pop)"); -1235 -1236 :(code) -1237 void test_pop_r32() { -1238 Mem.push_back(vma(0xbd000000)); // manually allocate memory -1239 Reg[ESP].u = 0xbd000008; -1240 write_mem_i32(0xbd000008, 0x0000000a); // ..before this write -1241 run( -1242 "== code 0x1\n" // code segment -1243 // op ModR/M SIB displacement immediate -1244 " 5b \n" // pop stack to EBX -1245 "== data 0x2000\n" // data segment -1246 "0a 00 00 00\n" // 0x0000000a -1247 ); -1248 CHECK_TRACE_CONTENTS( -1249 "run: pop into EBX\n" -1250 "run: popping value 0x0000000a\n" -1251 "run: incrementing ESP to 0xbd00000c\n" -1252 ); -1253 } -1254 -1255 :(before "End Single-Byte Opcodes") -1256 case 0x58: -1257 case 0x59: -1258 case 0x5a: -1259 case 0x5b: -1260 case 0x5c: -1261 case 0x5d: -1262 case 0x5e: -1263 case 0x5f: { // pop stack into r32 -1264 const uint8_t reg = op & 0x7; -1265 trace(Callstack_depth+1, "run") << "pop into " << rname(reg) << end(); -1266 //? cerr << "pop from " << Reg[ESP].u << '\n'; -1267 Reg[reg].u = pop(); -1268 //? cerr << "=> " << NUM(reg) << ": " << Reg[reg].u << '\n'; -1269 break; -1270 } -1271 :(code) -1272 uint32_t pop() { -1273 const uint32_t result = read_mem_u32(Reg[ESP].u); -1274 trace(Callstack_depth+1, "run") << "popping value 0x" << HEXWORD << result << end(); -1275 Reg[ESP].u += 4; -1276 trace(Callstack_depth+1, "run") << "incrementing ESP to 0x" << HEXWORD << Reg[ESP].u << end(); -1277 assert(Reg[ESP].u < AFTER_STACK); -1278 return result; -1279 } +1224 :(before "End Initialize Op Names") +1225 put_new(Name, "58", "pop top of stack to EAX (pop)"); +1226 put_new(Name, "59", "pop top of stack to ECX (pop)"); +1227 put_new(Name, "5a", "pop top of stack to EDX (pop)"); +1228 put_new(Name, "5b", "pop top of stack to EBX (pop)"); +1229 put_new(Name, "5c", "pop top of stack to ESP (pop)"); +1230 put_new(Name, "5d", "pop top of stack to EBP (pop)"); +1231 put_new(Name, "5e", "pop top of stack to ESI (pop)"); +1232 put_new(Name, "5f", "pop top of stack to EDI (pop)"); +1233 +1234 :(code) +1235 void test_pop_r32() { +1236 Mem.push_back(vma(0xbd000000)); // manually allocate memory +1237 Reg[ESP].u = 0xbd000008; +1238 write_mem_i32(0xbd000008, 0x0000000a); // ..before this write +1239 run( +1240 "== code 0x1\n" // code segment +1241 // op ModR/M SIB displacement immediate +1242 " 5b \n" // pop stack to EBX +1243 "== data 0x2000\n" // data segment +1244 "0a 00 00 00\n" // 0x0000000a +1245 ); +1246 CHECK_TRACE_CONTENTS( +1247 "run: pop into EBX\n" +1248 "run: popping value 0x0000000a\n" +1249 "run: incrementing ESP to 0xbd00000c\n" +1250 ); +1251 } +1252 +1253 :(before "End Single-Byte Opcodes") +1254 case 0x58: +1255 case 0x59: +1256 case 0x5a: +1257 case 0x5b: +1258 case 0x5c: +1259 case 0x5d: +1260 case 0x5e: +1261 case 0x5f: { // pop stack into r32 +1262 const uint8_t reg = op & 0x7; +1263 trace(Callstack_depth+1, "run") << "pop into " << rname(reg) << end(); +1264 //? cerr << "pop from " << Reg[ESP].u << '\n'; +1265 Reg[reg].u = pop(); +1266 //? cerr << "=> " << NUM(reg) << ": " << Reg[reg].u << '\n'; +1267 break; +1268 } +1269 :(code) +1270 uint32_t pop() { +1271 const uint32_t result = read_mem_u32(Reg[ESP].u); +1272 trace(Callstack_depth+1, "run") << "popping value 0x" << HEXWORD << result << end(); +1273 Reg[ESP].u += 4; +1274 trace(Callstack_depth+1, "run") << "incrementing ESP to 0x" << HEXWORD << Reg[ESP].u << end(); +1275 assert(Reg[ESP].u < AFTER_STACK); +1276 return result; +1277 } diff --git a/html/014indirect_addressing.cc.html b/html/014indirect_addressing.cc.html index bac9cae6..aa64574f 100644 --- a/html/014indirect_addressing.cc.html +++ b/html/014indirect_addressing.cc.html @@ -847,7 +847,7 @@ if ('onhashchange' in window) { 788 //:: pop 789 790 :(before "End Initialize Op Names") - 791 put_new(Name, "8f", "pop top of stack to rm32 (pop)"); + 791 put_new(Name, "8f", "pop top of stack to rm32 (pop)"); 792 793 :(code) 794 void test_pop_mem_at_r32() { @@ -862,7 +862,7 @@ if ('onhashchange' in window) { 803 // ModR/M in binary: 00 (indirect mode) 000 (pop r/m32) 000 (dest EAX) 804 ); 805 CHECK_TRACE_CONTENTS( - 806 "run: pop into r/m32\n" + 806 "run: pop into r/m32\n" 807 "run: effective address is 0x00000060 (EAX)\n" 808 "run: popping value 0x00000030\n" 809 "run: incrementing ESP to 0xbd000004\n" @@ -877,7 +877,7 @@ if ('onhashchange' in window) { 818 case 0: { 819 trace(Callstack_depth+1, "run") << "pop into r/m32" << end(); 820 int32_t* dest = effective_address(modrm); - 821 *dest = pop(); // Write multiple elements of vector<uint8_t> at once. Assumes sizeof(int) == 4 on the host as well. + 821 *dest = pop(); // Write multiple elements of vector<uint8_t> at once. Assumes sizeof(int) == 4 on the host as well. 822 break; 823 } 824 } diff --git a/html/015immediate_addressing.cc.html b/html/015immediate_addressing.cc.html index 34f08f0c..0ca822f8 100644 --- a/html/015immediate_addressing.cc.html +++ b/html/015immediate_addressing.cc.html @@ -1331,6 +1331,45 @@ if ('onhashchange' in window) { 1270 trace(Callstack_depth+1, "run") << "contents at ESP: 0x" << HEXWORD << read_mem_u32(Reg[ESP].u) << end(); 1271 break; 1272 } +1273 +1274 //:: multiply +1275 +1276 :(before "End Initialize Op Names") +1277 put_new(Name, "69", "multiply rm32 by imm32 and store result in r32"); +1278 +1279 :(code) +1280 void test_multiply_imm32() { +1281 Reg[EAX].i = 2; +1282 Reg[EBX].i = 3; +1283 run( +1284 "== code 0x1\n" +1285 // op ModR/M SIB displacement immediate +1286 " 69 c3 04 00 00 00 \n" // EAX = EBX * 4 +1287 // ModR/M in binary: 11 (direct) 000 (dest EAX) 011 (src EBX) +1288 ); +1289 CHECK_TRACE_CONTENTS( +1290 "run: multiply r/m32 by 0x00000004 and store result in EAX\n" +1291 "run: r/m32 is EBX\n" +1292 "run: storing 0x0000000c\n" +1293 ); +1294 } +1295 +1296 :(before "End Single-Byte Opcodes") +1297 case 0x69: { +1298 const uint8_t modrm = next(); +1299 const uint8_t rdest = (modrm>>3)&0x7; +1300 const int32_t val = next32(); +1301 trace(Callstack_depth+1, "run") << "multiply r/m32 by 0x" << HEXWORD << val << " and store result in " << rname(rdest) << end(); +1302 const int32_t* signed_arg1 = effective_address(modrm); +1303 int32_t result = *signed_arg1 * val; +1304 int64_t full_result = static_cast<int64_t>(*signed_arg1) * val; +1305 OF = (result != full_result); +1306 CF = OF; +1307 trace(Callstack_depth+1, "run") << "SF=" << SF << "; ZF=" << ZF << "; CF=" << CF << "; OF=" << OF << end(); +1308 Reg[rdest].i = result; +1309 trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << Reg[rdest].i << end(); +1310 break; +1311 } diff --git a/html/017jump_disp8.cc.html b/html/017jump_disp8.cc.html index 39c3acc3..0db5d9e1 100644 --- a/html/017jump_disp8.cc.html +++ b/html/017jump_disp8.cc.html @@ -164,7 +164,7 @@ if ('onhashchange' in window) { 105 } 106 107 :(before "End Single-Byte Opcodes") -108 case 0x75: { // jump disp8 unless ZF +108 case 0x75: { // jump disp8 if !ZF 109 const int8_t offset = static_cast<int>(next()); 110 if (!ZF) { 111 trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end(); diff --git a/html/018jump_disp32.cc.html b/html/018jump_disp32.cc.html index fe7ef115..bbf6d7ca 100644 --- a/html/018jump_disp32.cc.html +++ b/html/018jump_disp32.cc.html @@ -164,7 +164,7 @@ if ('onhashchange' in window) { 105 } 106 107 :(before "End Two-Byte Opcodes Starting With 0f") -108 case 0x85: { // jump disp32 unless ZF +108 case 0x85: { // jump disp32 if !ZF 109 const int32_t offset = next32(); 110 if (!ZF) { 111 trace(Callstack_depth+1, "run") << "jump " << offset << end(); diff --git a/html/019functions.cc.html b/html/019functions.cc.html index bcb16130..1a0e9ad9 100644 --- a/html/019functions.cc.html +++ b/html/019functions.cc.html @@ -176,7 +176,7 @@ if ('onhashchange' in window) { 116 case 0xc3: { // return from a call 117 trace(Callstack_depth+1, "run") << "return" << end(); 118 --Callstack_depth; -119 EIP = pop(); +119 EIP = pop(); 120 trace(Callstack_depth+1, "run") << "jumping to 0x" << HEXWORD << EIP << end(); 121 break; 122 } diff --git a/html/021byte_addressing.cc.html b/html/021byte_addressing.cc.html index 86eac77e..662dac1d 100644 --- a/html/021byte_addressing.cc.html +++ b/html/021byte_addressing.cc.html @@ -21,6 +21,7 @@ a { color:inherit; } .Special { color: #d70000; } .Identifier { color: #af5f00; } .Normal { color: #000000; background-color: #c6c6c6; padding-bottom: 1px; } +.SalientComment { color: #0000af; } .cSpecial { color: #008000; } --> @@ -125,7 +126,7 @@ if ('onhashchange' in window) { 66 const uint8_t rsrc = (modrm>>3)&0x7; 67 trace(Callstack_depth+1, "run") << "copy " << rname_8bit(rsrc) << " to r8/m8-at-r32" << end(); 68 // use unsigned to zero-extend 8-bit value to 32 bits - 69 uint8_t* dest = reinterpret_cast<uint8_t*>(effective_byte_address(modrm)); + 69 uint8_t* dest = effective_byte_address(modrm); 70 const uint8_t* src = reg_8bit(rsrc); 71 *dest = *src; // Read/write multiple elements of vector<uint8_t> at once. Assumes sizeof(int) == 4 on the host as well. 72 trace(Callstack_depth+1, "run") << "storing 0x" << HEXBYTE << NUM(*dest) << end(); @@ -164,7 +165,7 @@ if ('onhashchange' in window) { 105 const uint8_t rdest = (modrm>>3)&0x7; 106 trace(Callstack_depth+1, "run") << "copy r8/m8-at-r32 to " << rname_8bit(rdest) << end(); 107 // use unsigned to zero-extend 8-bit value to 32 bits -108 const uint8_t* src = reinterpret_cast<uint8_t*>(effective_byte_address(modrm)); +108 const uint8_t* src = effective_byte_address(modrm); 109 uint8_t* dest = reg_8bit(rdest); 110 trace(Callstack_depth+1, "run") << "storing 0x" << HEXBYTE << NUM(*src) << end(); 111 *dest = *src; // Read/write multiple elements of vector<uint8_t> at once. Assumes sizeof(int) == 4 on the host as well. @@ -228,11 +229,107 @@ if ('onhashchange' in window) { 169 exit(1); 170 } 171 // use unsigned to zero-extend 8-bit value to 32 bits -172 uint8_t* dest = reinterpret_cast<uint8_t*>(effective_byte_address(modrm)); +172 uint8_t* dest = effective_byte_address(modrm); 173 *dest = src; // Write multiple elements of vector<uint8_t> at once. Assumes sizeof(int) == 4 on the host as well. 174 trace(Callstack_depth+1, "run") << "storing 0x" << HEXBYTE << NUM(*dest) << end(); 175 break; 176 } +177 +178 //:: set flags (setcc) +179 +180 :(before "End Initialize Op Names") +181 put_new(Name_0f, "94", "set r8/m8-at-rm32 to 1 if equal, if ZF is set, 0 otherwise (setcc/setz/sete)"); +182 put_new(Name_0f, "95", "set r8/m8-at-rm32 to 1 if not equal, if ZF is not set, 0 otherwise (setcc/setnz/setne)"); +183 put_new(Name_0f, "9f", "set r8/m8-at-rm32 to 1 if greater (signed), if ZF is unset and SF == OF, 0 otherwise (setcc/setg/setnle)"); +184 put_new(Name_0f, "97", "set r8/m8-at-rm32 to 1 if greater (unsigned), if ZF is unset and CF is unset, 0 otherwise (setcc/seta/setnbe)"); +185 put_new(Name_0f, "9d", "set r8/m8-at-rm32 to 1 if greater or equal (signed), if SF == OF, 0 otherwise (setcc/setge/setnl)"); +186 put_new(Name_0f, "93", "set r8/m8-at-rm32 to 1 if greater or equal (unsigned), if CF is unset, 0 otherwise (setcc/setae/setnb)"); +187 put_new(Name_0f, "9c", "set r8/m8-at-rm32 to 1 if lesser (signed), if SF != OF, 0 otherwise (setcc/setl/setnge)"); +188 put_new(Name_0f, "92", "set r8/m8-at-rm32 to 1 if lesser (unsigned), if CF is set, 0 otherwise (setcc/setb/setnae)"); +189 put_new(Name_0f, "9e", "set r8/m8-at-rm32 to 1 if lesser or equal (signed), if ZF is set or SF != OF, 0 otherwise (setcc/setle/setng)"); +190 put_new(Name_0f, "96", "set r8/m8-at-rm32 to 1 if lesser or equal (unsigned), if ZF is set or CF is set, 0 otherwise (setcc/setbe/setna)"); +191 +192 :(before "End Two-Byte Opcodes Starting With 0f") +193 case 0x94: { // set r8/m8-at-rm32 if ZF +194 const uint8_t modrm = next(); +195 trace(Callstack_depth+1, "run") << "set r8/m8-at-rm32" << end(); +196 uint8_t* dest = effective_byte_address(modrm); +197 *dest = ZF; +198 trace(Callstack_depth+1, "run") << "storing " << *dest << end(); +199 break; +200 } +201 case 0x95: { // set r8/m8-at-rm32 if !ZF +202 const uint8_t modrm = next(); +203 trace(Callstack_depth+1, "run") << "set r8/m8-at-rm32" << end(); +204 uint8_t* dest = effective_byte_address(modrm); +205 *dest = !ZF; +206 trace(Callstack_depth+1, "run") << "storing " << *dest << end(); +207 break; +208 } +209 case 0x9f: { // set r8/m8-at-rm32 if !SF and !ZF +210 const uint8_t modrm = next(); +211 trace(Callstack_depth+1, "run") << "set r8/m8-at-rm32" << end(); +212 uint8_t* dest = effective_byte_address(modrm); +213 *dest = !ZF && SF == OF; +214 trace(Callstack_depth+1, "run") << "storing " << *dest << end(); +215 break; +216 } +217 case 0x97: { // set r8/m8-at-rm32 if !CF and !ZF +218 const uint8_t modrm = next(); +219 trace(Callstack_depth+1, "run") << "set r8/m8-at-rm32" << end(); +220 uint8_t* dest = effective_byte_address(modrm); +221 *dest = (!CF && !ZF); +222 trace(Callstack_depth+1, "run") << "storing " << *dest << end(); +223 break; +224 } +225 case 0x9d: { // set r8/m8-at-rm32 if !SF +226 const uint8_t modrm = next(); +227 trace(Callstack_depth+1, "run") << "set r8/m8-at-rm32" << end(); +228 uint8_t* dest = effective_byte_address(modrm); +229 *dest = (SF == OF); +230 trace(Callstack_depth+1, "run") << "storing " << *dest << end(); +231 break; +232 } +233 case 0x93: { // set r8/m8-at-rm32 if !CF +234 const uint8_t modrm = next(); +235 trace(Callstack_depth+1, "run") << "set r8/m8-at-rm32" << end(); +236 uint8_t* dest = effective_byte_address(modrm); +237 *dest = !CF; +238 trace(Callstack_depth+1, "run") << "storing " << *dest << end(); +239 break; +240 } +241 case 0x9c: { // set r8/m8-at-rm32 if SF and !ZF +242 const uint8_t modrm = next(); +243 trace(Callstack_depth+1, "run") << "set r8/m8-at-rm32" << end(); +244 uint8_t* dest = effective_byte_address(modrm); +245 *dest = (SF != OF); +246 trace(Callstack_depth+1, "run") << "storing " << *dest << end(); +247 break; +248 } +249 case 0x92: { // set r8/m8-at-rm32 if CF +250 const uint8_t modrm = next(); +251 trace(Callstack_depth+1, "run") << "set r8/m8-at-rm32" << end(); +252 uint8_t* dest = effective_byte_address(modrm); +253 *dest = CF; +254 trace(Callstack_depth+1, "run") << "storing " << *dest << end(); +255 break; +256 } +257 case 0x9e: { // set r8/m8-at-rm32 if SF or ZF +258 const uint8_t modrm = next(); +259 trace(Callstack_depth+1, "run") << "set r8/m8-at-rm32" << end(); +260 uint8_t* dest = effective_byte_address(modrm); +261 *dest = (ZF || SF != OF); +262 trace(Callstack_depth+1, "run") << "storing " << *dest << end(); +263 break; +264 } +265 case 0x96: { // set r8/m8-at-rm32 if ZF or CF +266 const uint8_t modrm = next(); +267 trace(Callstack_depth+1, "run") << "set r8/m8-at-rm32" << end(); +268 uint8_t* dest = effective_byte_address(modrm); +269 *dest = (ZF || CF); +270 trace(Callstack_depth+1, "run") << "storing " << *dest << end(); +271 break; +272 } diff --git a/html/033check_operands.cc.html b/html/033check_operands.cc.html index 72f14492..c362b050 100644 --- a/html/033check_operands.cc.html +++ b/html/033check_operands.cc.html @@ -93,14 +93,14 @@ if ('onhashchange' in window) { 32 return; 33 } 34 if (op.data == "f3") { - 35 check_operands_f3(inst); + 35 check_operands_f3(inst); 36 return; 37 } 38 check_operands(inst, op); 39 } 40 41 word preprocess_op(word/*copy*/ op) { - 42 op.data = tolower(op.data.c_str()); + 42 op.data = tolower(op.data.c_str()); 43 // opcodes can't be negative 44 if (starts_with(op.data, "0x")) 45 op.data = op.data.substr(2); @@ -307,443 +307,459 @@ if ('onhashchange' in window) { 246 put(Permitted_operands, "81", 0x43); // combine 247 put(Permitted_operands, "c7", 0x43); // copy 248 -249 // End Init Permitted Operands -250 } -251 -252 #define HAS(bitvector, bit) ((bitvector) & (1 << (bit))) -253 #define SET(bitvector, bit) ((bitvector) | (1 << (bit))) -254 #define CLEAR(bitvector, bit) ((bitvector) & (~(1 << (bit)))) -255 -256 void check_operands(const line& inst, const word& op) { -257 if (!is_hex_byte(op)) return; -258 uint8_t expected_bitvector = get(Permitted_operands, op.data); -259 if (HAS(expected_bitvector, MODRM)) { -260 check_operands_modrm(inst, op); -261 compare_bitvector_modrm(inst, expected_bitvector, maybe_name(op)); -262 } -263 else { -264 compare_bitvector(inst, expected_bitvector, maybe_name(op)); -265 } -266 } -267 -268 //: Many instructions can be checked just by comparing bitvectors. -269 -270 void compare_bitvector(const line& inst, uint8_t expected, const string& maybe_op_name) { -271 if (all_hex_bytes(inst) && has_operands(inst)) return; // deliberately programming in raw hex; we'll raise a warning elsewhere -272 uint8_t bitvector = compute_expected_operand_bitvector(inst); -273 if (trace_contains_errors()) return; // duplicate operand type -274 if (bitvector == expected) return; // all good with this instruction -275 for (int i = 0; i < NUM_OPERAND_TYPES; ++i, bitvector >>= 1, expected >>= 1) { -276 //? cerr << "comparing " << HEXBYTE << NUM(bitvector) << " with " << NUM(expected) << '\n'; -277 if ((bitvector & 0x1) == (expected & 0x1)) continue; // all good with this operand -278 const string& optype = Operand_type_name.at(i); -279 if ((bitvector & 0x1) > (expected & 0x1)) -280 raise << "'" << to_string(inst) << "'" << maybe_op_name << ": unexpected " << optype << " operand\n" << end(); -281 else -282 raise << "'" << to_string(inst) << "'" << maybe_op_name << ": missing " << optype << " operand\n" << end(); -283 // continue giving all errors for a single instruction -284 } -285 // ignore settings in any unused bits -286 } -287 -288 string maybe_name(const word& op) { -289 if (!is_hex_byte(op)) return ""; -290 if (!contains_key(Name, op.data)) return ""; -291 // strip stuff in parens from the name -292 const string& s = get(Name, op.data); -293 return " ("+s.substr(0, s.find(" ("))+')'; -294 } -295 -296 uint32_t compute_expected_operand_bitvector(const line& inst) { -297 set<string> operands_found; -298 uint32_t bitvector = 0; -299 for (int i = /*skip op*/1; i < SIZE(inst.words); ++i) { -300 bitvector = bitvector | expected_bit_for_received_operand(inst.words.at(i), operands_found, inst); -301 if (trace_contains_errors()) return INVALID_OPERANDS; // duplicate operand type -302 } -303 return bitvector; -304 } -305 -306 bool has_operands(const line& inst) { -307 return SIZE(inst.words) > first_operand(inst); -308 } -309 -310 int first_operand(const line& inst) { -311 if (inst.words.at(0).data == "0f") return 2; -312 if (inst.words.at(0).data == "f2" || inst.words.at(0).data == "f3") { -313 if (inst.words.at(1).data == "0f") -314 return 3; -315 else -316 return 2; -317 } -318 return 1; -319 } -320 -321 // Scan the metadata of 'w' and return the expected bit corresponding to any operand type. -322 // Also raise an error if metadata contains multiple operand types. -323 uint32_t expected_bit_for_received_operand(const word& w, set<string>& instruction_operands, const line& inst) { -324 uint32_t bv = 0; -325 bool found = false; -326 for (int i = 0; i < SIZE(w.metadata); ++i) { -327 string/*copy*/ curr = w.metadata.at(i); -328 string expected_metadata = curr; -329 if (curr == "mod" || curr == "rm32" || curr == "r32" || curr == "scale" || curr == "index" || curr == "base") -330 expected_metadata = "modrm"; -331 else if (!contains_key(Operand_type, curr)) continue; // ignore unrecognized metadata -332 if (found) { -333 raise << "'" << w.original << "' has conflicting operand types; it should have only one\n" << end(); -334 return INVALID_OPERANDS; -335 } -336 if (instruction_operands.find(curr) != instruction_operands.end()) { -337 raise << "'" << to_string(inst) << "': duplicate " << curr << " operand\n" << end(); -338 return INVALID_OPERANDS; -339 } -340 instruction_operands.insert(curr); -341 bv = (1 << get(Operand_type, expected_metadata)); -342 found = true; -343 } -344 return bv; -345 } -346 -347 void test_conflicting_operand_type() { -348 Hide_errors = true; -349 run( -350 "== code 0x1\n" -351 "cd/software-interrupt 80/imm8/imm32\n" -352 ); -353 CHECK_TRACE_CONTENTS( -354 "error: '80/imm8/imm32' has conflicting operand types; it should have only one\n" -355 ); -356 } -357 -358 //: Instructions computing effective addresses have more complex rules, so -359 //: we'll hard-code a common set of instruction-decoding rules. -360 -361 void test_check_missing_mod_operand() { -362 Hide_errors = true; -363 run( -364 "== code 0x1\n" -365 "81 0/add/subop 3/rm32/ebx 1/imm32\n" -366 ); -367 CHECK_TRACE_CONTENTS( -368 "error: '81 0/add/subop 3/rm32/ebx 1/imm32' (combine rm32 with imm32 based on subop): missing mod operand\n" -369 ); -370 } -371 -372 void check_operands_modrm(const line& inst, const word& op) { -373 if (all_hex_bytes(inst)) return; // deliberately programming in raw hex; we'll raise a warning elsewhere -374 check_operand_metadata_present(inst, "mod", op); -375 check_operand_metadata_present(inst, "rm32", op); -376 // no check for r32; some instructions don't use it; just assume it's 0 if missing -377 if (op.data == "81" || op.data == "8f" || op.data == "ff") { // keep sync'd with 'help subop' -378 check_operand_metadata_present(inst, "subop", op); -379 check_operand_metadata_absent(inst, "r32", op, "should be replaced by subop"); -380 } -381 if (trace_contains_errors()) return; -382 if (metadata(inst, "rm32").data != "4") return; -383 // SIB byte checks -384 uint8_t mod = hex_byte(metadata(inst, "mod").data); -385 if (mod != /*direct*/3) { -386 check_operand_metadata_present(inst, "base", op); -387 check_operand_metadata_present(inst, "index", op); // otherwise why go to SIB? -388 } -389 else { -390 check_operand_metadata_absent(inst, "base", op, "direct mode"); -391 check_operand_metadata_absent(inst, "index", op, "direct mode"); -392 } -393 // no check for scale; 0 (2**0 = 1) by default -394 } -395 -396 // same as compare_bitvector, with one additional exception for modrm-based -397 // instructions: they may use an extra displacement on occasion -398 void compare_bitvector_modrm(const line& inst, uint8_t expected, const string& maybe_op_name) { -399 if (all_hex_bytes(inst) && has_operands(inst)) return; // deliberately programming in raw hex; we'll raise a warning elsewhere -400 uint8_t bitvector = compute_expected_operand_bitvector(inst); -401 if (trace_contains_errors()) return; // duplicate operand type -402 // update 'expected' bitvector for the additional exception -403 if (has_operand_metadata(inst, "mod")) { -404 int32_t mod = parse_int(metadata(inst, "mod").data); -405 switch (mod) { -406 case 0: -407 if (has_operand_metadata(inst, "rm32") && parse_int(metadata(inst, "rm32").data) == 5) -408 expected |= (1<<DISP32); -409 break; -410 case 1: -411 expected |= (1<<DISP8); -412 break; -413 case 2: -414 expected |= (1<<DISP32); -415 break; -416 } -417 } -418 if (bitvector == expected) return; // all good with this instruction -419 for (int i = 0; i < NUM_OPERAND_TYPES; ++i, bitvector >>= 1, expected >>= 1) { -420 //? cerr << "comparing for modrm " << HEXBYTE << NUM(bitvector) << " with " << NUM(expected) << '\n'; -421 if ((bitvector & 0x1) == (expected & 0x1)) continue; // all good with this operand -422 const string& optype = Operand_type_name.at(i); -423 if ((bitvector & 0x1) > (expected & 0x1)) -424 raise << "'" << to_string(inst) << "'" << maybe_op_name << ": unexpected " << optype << " operand\n" << end(); -425 else -426 raise << "'" << to_string(inst) << "'" << maybe_op_name << ": missing " << optype << " operand\n" << end(); -427 // continue giving all errors for a single instruction -428 } -429 // ignore settings in any unused bits -430 } -431 -432 void check_operand_metadata_present(const line& inst, const string& type, const word& op) { -433 if (!has_operand_metadata(inst, type)) -434 raise << "'" << to_string(inst) << "'" << maybe_name(op) << ": missing " << type << " operand\n" << end(); +249 //// Class Q: op, ModR/M and imm32 +250 // imm32 imm8 disp32 |disp16 disp8 subop modrm +251 // 1 0 0 |0 0 0 1 +252 put(Permitted_operands, "69", 0x41); // multiply +253 +254 // End Init Permitted Operands +255 } +256 +257 #define HAS(bitvector, bit) ((bitvector) & (1 << (bit))) +258 #define SET(bitvector, bit) ((bitvector) | (1 << (bit))) +259 #define CLEAR(bitvector, bit) ((bitvector) & (~(1 << (bit)))) +260 +261 void check_operands(const line& inst, const word& op) { +262 if (!is_hex_byte(op)) return; +263 uint8_t expected_bitvector = get(Permitted_operands, op.data); +264 if (HAS(expected_bitvector, MODRM)) { +265 check_operands_modrm(inst, op); +266 compare_bitvector_modrm(inst, expected_bitvector, maybe_name(op)); +267 } +268 else { +269 compare_bitvector(inst, expected_bitvector, maybe_name(op)); +270 } +271 } +272 +273 //: Many instructions can be checked just by comparing bitvectors. +274 +275 void compare_bitvector(const line& inst, uint8_t expected, const string& maybe_op_name) { +276 if (all_hex_bytes(inst) && has_operands(inst)) return; // deliberately programming in raw hex; we'll raise a warning elsewhere +277 uint8_t bitvector = compute_expected_operand_bitvector(inst); +278 if (trace_contains_errors()) return; // duplicate operand type +279 if (bitvector == expected) return; // all good with this instruction +280 for (int i = 0; i < NUM_OPERAND_TYPES; ++i, bitvector >>= 1, expected >>= 1) { +281 //? cerr << "comparing " << HEXBYTE << NUM(bitvector) << " with " << NUM(expected) << '\n'; +282 if ((bitvector & 0x1) == (expected & 0x1)) continue; // all good with this operand +283 const string& optype = Operand_type_name.at(i); +284 if ((bitvector & 0x1) > (expected & 0x1)) +285 raise << "'" << to_string(inst) << "'" << maybe_op_name << ": unexpected " << optype << " operand\n" << end(); +286 else +287 raise << "'" << to_string(inst) << "'" << maybe_op_name << ": missing " << optype << " operand\n" << end(); +288 // continue giving all errors for a single instruction +289 } +290 // ignore settings in any unused bits +291 } +292 +293 string maybe_name(const word& op) { +294 if (!is_hex_byte(op)) return ""; +295 if (!contains_key(Name, op.data)) return ""; +296 // strip stuff in parens from the name +297 const string& s = get(Name, op.data); +298 return " ("+s.substr(0, s.find(" ("))+')'; +299 } +300 +301 uint32_t compute_expected_operand_bitvector(const line& inst) { +302 set<string> operands_found; +303 uint32_t bitvector = 0; +304 for (int i = /*skip op*/1; i < SIZE(inst.words); ++i) { +305 bitvector = bitvector | expected_bit_for_received_operand(inst.words.at(i), operands_found, inst); +306 if (trace_contains_errors()) return INVALID_OPERANDS; // duplicate operand type +307 } +308 return bitvector; +309 } +310 +311 bool has_operands(const line& inst) { +312 return SIZE(inst.words) > first_operand(inst); +313 } +314 +315 int first_operand(const line& inst) { +316 if (inst.words.at(0).data == "0f") return 2; +317 if (inst.words.at(0).data == "f2" || inst.words.at(0).data == "f3") { +318 if (inst.words.at(1).data == "0f") +319 return 3; +320 else +321 return 2; +322 } +323 return 1; +324 } +325 +326 // Scan the metadata of 'w' and return the expected bit corresponding to any operand type. +327 // Also raise an error if metadata contains multiple operand types. +328 uint32_t expected_bit_for_received_operand(const word& w, set<string>& instruction_operands, const line& inst) { +329 uint32_t bv = 0; +330 bool found = false; +331 for (int i = 0; i < SIZE(w.metadata); ++i) { +332 string/*copy*/ curr = w.metadata.at(i); +333 string expected_metadata = curr; +334 if (curr == "mod" || curr == "rm32" || curr == "r32" || curr == "scale" || curr == "index" || curr == "base") +335 expected_metadata = "modrm"; +336 else if (!contains_key(Operand_type, curr)) continue; // ignore unrecognized metadata +337 if (found) { +338 raise << "'" << w.original << "' has conflicting operand types; it should have only one\n" << end(); +339 return INVALID_OPERANDS; +340 } +341 if (instruction_operands.find(curr) != instruction_operands.end()) { +342 raise << "'" << to_string(inst) << "': duplicate " << curr << " operand\n" << end(); +343 return INVALID_OPERANDS; +344 } +345 instruction_operands.insert(curr); +346 bv = (1 << get(Operand_type, expected_metadata)); +347 found = true; +348 } +349 return bv; +350 } +351 +352 void test_conflicting_operand_type() { +353 Hide_errors = true; +354 run( +355 "== code 0x1\n" +356 "cd/software-interrupt 80/imm8/imm32\n" +357 ); +358 CHECK_TRACE_CONTENTS( +359 "error: '80/imm8/imm32' has conflicting operand types; it should have only one\n" +360 ); +361 } +362 +363 //: Instructions computing effective addresses have more complex rules, so +364 //: we'll hard-code a common set of instruction-decoding rules. +365 +366 void test_check_missing_mod_operand() { +367 Hide_errors = true; +368 run( +369 "== code 0x1\n" +370 "81 0/add/subop 3/rm32/ebx 1/imm32\n" +371 ); +372 CHECK_TRACE_CONTENTS( +373 "error: '81 0/add/subop 3/rm32/ebx 1/imm32' (combine rm32 with imm32 based on subop): missing mod operand\n" +374 ); +375 } +376 +377 void check_operands_modrm(const line& inst, const word& op) { +378 if (all_hex_bytes(inst)) return; // deliberately programming in raw hex; we'll raise a warning elsewhere +379 check_operand_metadata_present(inst, "mod", op); +380 check_operand_metadata_present(inst, "rm32", op); +381 // no check for r32; some instructions don't use it; just assume it's 0 if missing +382 if (op.data == "81" || op.data == "8f" || op.data == "ff") { // keep sync'd with 'help subop' +383 check_operand_metadata_present(inst, "subop", op); +384 check_operand_metadata_absent(inst, "r32", op, "should be replaced by subop"); +385 } +386 if (trace_contains_errors()) return; +387 if (metadata(inst, "rm32").data != "4") return; +388 // SIB byte checks +389 uint8_t mod = hex_byte(metadata(inst, "mod").data); +390 if (mod != /*direct*/3) { +391 check_operand_metadata_present(inst, "base", op); +392 check_operand_metadata_present(inst, "index", op); // otherwise why go to SIB? +393 } +394 else { +395 check_operand_metadata_absent(inst, "base", op, "direct mode"); +396 check_operand_metadata_absent(inst, "index", op, "direct mode"); +397 } +398 // no check for scale; 0 (2**0 = 1) by default +399 } +400 +401 // same as compare_bitvector, with one additional exception for modrm-based +402 // instructions: they may use an extra displacement on occasion +403 void compare_bitvector_modrm(const line& inst, uint8_t expected, const string& maybe_op_name) { +404 if (all_hex_bytes(inst) && has_operands(inst)) return; // deliberately programming in raw hex; we'll raise a warning elsewhere +405 uint8_t bitvector = compute_expected_operand_bitvector(inst); +406 if (trace_contains_errors()) return; // duplicate operand type +407 // update 'expected' bitvector for the additional exception +408 if (has_operand_metadata(inst, "mod")) { +409 int32_t mod = parse_int(metadata(inst, "mod").data); +410 switch (mod) { +411 case 0: +412 if (has_operand_metadata(inst, "rm32") && parse_int(metadata(inst, "rm32").data) == 5) +413 expected |= (1<<DISP32); +414 break; +415 case 1: +416 expected |= (1<<DISP8); +417 break; +418 case 2: +419 expected |= (1<<DISP32); +420 break; +421 } +422 } +423 if (bitvector == expected) return; // all good with this instruction +424 for (int i = 0; i < NUM_OPERAND_TYPES; ++i, bitvector >>= 1, expected >>= 1) { +425 //? cerr << "comparing for modrm " << HEXBYTE << NUM(bitvector) << " with " << NUM(expected) << '\n'; +426 if ((bitvector & 0x1) == (expected & 0x1)) continue; // all good with this operand +427 const string& optype = Operand_type_name.at(i); +428 if ((bitvector & 0x1) > (expected & 0x1)) +429 raise << "'" << to_string(inst) << "'" << maybe_op_name << ": unexpected " << optype << " operand\n" << end(); +430 else +431 raise << "'" << to_string(inst) << "'" << maybe_op_name << ": missing " << optype << " operand\n" << end(); +432 // continue giving all errors for a single instruction +433 } +434 // ignore settings in any unused bits 435 } 436 -437 void check_operand_metadata_absent(const line& inst, const string& type, const word& op, const string& msg) { -438 if (has_operand_metadata(inst, type)) -439 raise << "'" << to_string(inst) << "'" << maybe_name(op) << ": unexpected " << type << " operand (" << msg << ")\n" << end(); +437 void check_operand_metadata_present(const line& inst, const string& type, const word& op) { +438 if (!has_operand_metadata(inst, type)) +439 raise << "'" << to_string(inst) << "'" << maybe_name(op) << ": missing " << type << " operand\n" << end(); 440 } 441 -442 void test_modrm_with_displacement() { -443 Reg[EAX].u = 0x1; -444 transform( -445 "== code 0x1\n" -446 // just avoid null pointer -447 "8b/copy 1/mod/lookup+disp8 0/rm32/EAX 2/r32/EDX 4/disp8\n" // copy *(EAX+4) to EDX -448 ); -449 CHECK_TRACE_COUNT("error", 0); -450 } -451 -452 void test_check_missing_disp8() { -453 Hide_errors = true; -454 transform( -455 "== code 0x1\n" -456 "89/copy 1/mod/lookup+disp8 0/rm32/EAX 1/r32/ECX\n" // missing disp8 -457 ); -458 CHECK_TRACE_CONTENTS( -459 "error: '89/copy 1/mod/lookup+disp8 0/rm32/EAX 1/r32/ECX' (copy r32 to rm32): missing disp8 operand\n" -460 ); -461 } -462 -463 void test_check_missing_disp32() { -464 Hide_errors = true; -465 transform( -466 "== code 0x1\n" -467 "8b/copy 0/mod/indirect 5/rm32/.disp32 2/r32/EDX\n" // missing disp32 -468 ); -469 CHECK_TRACE_CONTENTS( -470 "error: '8b/copy 0/mod/indirect 5/rm32/.disp32 2/r32/EDX' (copy rm32 to r32): missing disp32 operand\n" -471 ); -472 } -473 -474 void test_conflicting_operands_in_modrm_instruction() { -475 Hide_errors = true; -476 run( -477 "== code 0x1\n" -478 "01/add 0/mod 3/mod\n" -479 ); -480 CHECK_TRACE_CONTENTS( -481 "error: '01/add 0/mod 3/mod' has conflicting mod operands\n" -482 ); -483 } -484 -485 void test_conflicting_operand_type_modrm() { -486 Hide_errors = true; -487 run( -488 "== code 0x1\n" -489 "01/add 0/mod 3/rm32/r32\n" -490 ); -491 CHECK_TRACE_CONTENTS( -492 "error: '3/rm32/r32' has conflicting operand types; it should have only one\n" -493 ); -494 } -495 -496 void test_check_missing_rm32_operand() { -497 Hide_errors = true; -498 run( -499 "== code 0x1\n" -500 "81 0/add/subop 0/mod 1/imm32\n" -501 ); -502 CHECK_TRACE_CONTENTS( -503 "error: '81 0/add/subop 0/mod 1/imm32' (combine rm32 with imm32 based on subop): missing rm32 operand\n" -504 ); -505 } -506 -507 void test_check_missing_subop_operand() { -508 Hide_errors = true; -509 run( -510 "== code 0x1\n" -511 "81 0/mod 3/rm32/ebx 1/imm32\n" -512 ); -513 CHECK_TRACE_CONTENTS( -514 "error: '81 0/mod 3/rm32/ebx 1/imm32' (combine rm32 with imm32 based on subop): missing subop operand\n" -515 ); -516 } -517 -518 void test_check_missing_base_operand() { -519 Hide_errors = true; -520 run( -521 "== code 0x1\n" -522 "81 0/add/subop 0/mod/indirect 4/rm32/use-sib 1/imm32\n" -523 ); -524 CHECK_TRACE_CONTENTS( -525 "error: '81 0/add/subop 0/mod/indirect 4/rm32/use-sib 1/imm32' (combine rm32 with imm32 based on subop): missing base operand\n" -526 ); -527 } -528 -529 void test_check_missing_index_operand() { -530 Hide_errors = true; -531 run( -532 "== code 0x1\n" -533 "81 0/add/subop 0/mod/indirect 4/rm32/use-sib 0/base 1/imm32\n" -534 ); -535 CHECK_TRACE_CONTENTS( -536 "error: '81 0/add/subop 0/mod/indirect 4/rm32/use-sib 0/base 1/imm32' (combine rm32 with imm32 based on subop): missing index operand\n" -537 ); -538 } -539 -540 void test_check_missing_base_operand_2() { -541 Hide_errors = true; -542 run( -543 "== code 0x1\n" -544 "81 0/add/subop 0/mod/indirect 4/rm32/use-sib 2/index 3/scale 1/imm32\n" -545 ); -546 CHECK_TRACE_CONTENTS( -547 "error: '81 0/add/subop 0/mod/indirect 4/rm32/use-sib 2/index 3/scale 1/imm32' (combine rm32 with imm32 based on subop): missing base operand\n" -548 ); -549 } -550 -551 void test_check_extra_displacement() { -552 Hide_errors = true; -553 run( -554 "== code 0x1\n" -555 "89/copy 0/mod/indirect 0/rm32/EAX 1/r32/ECX 4/disp8\n" -556 ); -557 CHECK_TRACE_CONTENTS( -558 "error: '89/copy 0/mod/indirect 0/rm32/EAX 1/r32/ECX 4/disp8' (copy r32 to rm32): unexpected disp8 operand\n" -559 ); -560 } -561 -562 void test_check_duplicate_operand() { -563 Hide_errors = true; -564 run( -565 "== code 0x1\n" -566 "89/copy 0/mod/indirect 0/rm32/EAX 1/r32/ECX 1/r32\n" -567 ); -568 CHECK_TRACE_CONTENTS( -569 "error: '89/copy 0/mod/indirect 0/rm32/EAX 1/r32/ECX 1/r32': duplicate r32 operand\n" -570 ); -571 } -572 -573 void test_check_base_operand_not_needed_in_direct_mode() { -574 run( -575 "== code 0x1\n" -576 "81 0/add/subop 3/mod/indirect 4/rm32/use-sib 1/imm32\n" -577 ); -578 CHECK_TRACE_COUNT("error", 0); -579 } -580 -581 void test_extra_modrm() { -582 Hide_errors = true; -583 run( -584 "== code 0x1\n" -585 "59/pop-to-ECX 3/mod/direct 1/rm32/ECX 4/r32/ESP\n" -586 ); -587 CHECK_TRACE_CONTENTS( -588 "error: '59/pop-to-ECX 3/mod/direct 1/rm32/ECX 4/r32/ESP' (pop top of stack to ECX): unexpected modrm operand\n" -589 ); -590 } -591 -592 //:: similarly handle multi-byte opcodes -593 -594 void check_operands_0f(const line& inst) { -595 assert(inst.words.at(0).data == "0f"); -596 if (SIZE(inst.words) == 1) { -597 raise << "opcode '0f' requires a second opcode\n" << end(); -598 return; -599 } -600 word op = preprocess_op(inst.words.at(1)); -601 if (!contains_key(Name_0f, op.data)) { -602 raise << "unknown 2-byte opcode '0f " << op.data << "'\n" << end(); +442 void check_operand_metadata_absent(const line& inst, const string& type, const word& op, const string& msg) { +443 if (has_operand_metadata(inst, type)) +444 raise << "'" << to_string(inst) << "'" << maybe_name(op) << ": unexpected " << type << " operand (" << msg << ")\n" << end(); +445 } +446 +447 void test_modrm_with_displacement() { +448 Reg[EAX].u = 0x1; +449 transform( +450 "== code 0x1\n" +451 // just avoid null pointer +452 "8b/copy 1/mod/lookup+disp8 0/rm32/EAX 2/r32/EDX 4/disp8\n" // copy *(EAX+4) to EDX +453 ); +454 CHECK_TRACE_COUNT("error", 0); +455 } +456 +457 void test_check_missing_disp8() { +458 Hide_errors = true; +459 transform( +460 "== code 0x1\n" +461 "89/copy 1/mod/lookup+disp8 0/rm32/EAX 1/r32/ECX\n" // missing disp8 +462 ); +463 CHECK_TRACE_CONTENTS( +464 "error: '89/copy 1/mod/lookup+disp8 0/rm32/EAX 1/r32/ECX' (copy r32 to rm32): missing disp8 operand\n" +465 ); +466 } +467 +468 void test_check_missing_disp32() { +469 Hide_errors = true; +470 transform( +471 "== code 0x1\n" +472 "8b/copy 0/mod/indirect 5/rm32/.disp32 2/r32/EDX\n" // missing disp32 +473 ); +474 CHECK_TRACE_CONTENTS( +475 "error: '8b/copy 0/mod/indirect 5/rm32/.disp32 2/r32/EDX' (copy rm32 to r32): missing disp32 operand\n" +476 ); +477 } +478 +479 void test_conflicting_operands_in_modrm_instruction() { +480 Hide_errors = true; +481 run( +482 "== code 0x1\n" +483 "01/add 0/mod 3/mod\n" +484 ); +485 CHECK_TRACE_CONTENTS( +486 "error: '01/add 0/mod 3/mod' has conflicting mod operands\n" +487 ); +488 } +489 +490 void test_conflicting_operand_type_modrm() { +491 Hide_errors = true; +492 run( +493 "== code 0x1\n" +494 "01/add 0/mod 3/rm32/r32\n" +495 ); +496 CHECK_TRACE_CONTENTS( +497 "error: '3/rm32/r32' has conflicting operand types; it should have only one\n" +498 ); +499 } +500 +501 void test_check_missing_rm32_operand() { +502 Hide_errors = true; +503 run( +504 "== code 0x1\n" +505 "81 0/add/subop 0/mod 1/imm32\n" +506 ); +507 CHECK_TRACE_CONTENTS( +508 "error: '81 0/add/subop 0/mod 1/imm32' (combine rm32 with imm32 based on subop): missing rm32 operand\n" +509 ); +510 } +511 +512 void test_check_missing_subop_operand() { +513 Hide_errors = true; +514 run( +515 "== code 0x1\n" +516 "81 0/mod 3/rm32/ebx 1/imm32\n" +517 ); +518 CHECK_TRACE_CONTENTS( +519 "error: '81 0/mod 3/rm32/ebx 1/imm32' (combine rm32 with imm32 based on subop): missing subop operand\n" +520 ); +521 } +522 +523 void test_check_missing_base_operand() { +524 Hide_errors = true; +525 run( +526 "== code 0x1\n" +527 "81 0/add/subop 0/mod/indirect 4/rm32/use-sib 1/imm32\n" +528 ); +529 CHECK_TRACE_CONTENTS( +530 "error: '81 0/add/subop 0/mod/indirect 4/rm32/use-sib 1/imm32' (combine rm32 with imm32 based on subop): missing base operand\n" +531 ); +532 } +533 +534 void test_check_missing_index_operand() { +535 Hide_errors = true; +536 run( +537 "== code 0x1\n" +538 "81 0/add/subop 0/mod/indirect 4/rm32/use-sib 0/base 1/imm32\n" +539 ); +540 CHECK_TRACE_CONTENTS( +541 "error: '81 0/add/subop 0/mod/indirect 4/rm32/use-sib 0/base 1/imm32' (combine rm32 with imm32 based on subop): missing index operand\n" +542 ); +543 } +544 +545 void test_check_missing_base_operand_2() { +546 Hide_errors = true; +547 run( +548 "== code 0x1\n" +549 "81 0/add/subop 0/mod/indirect 4/rm32/use-sib 2/index 3/scale 1/imm32\n" +550 ); +551 CHECK_TRACE_CONTENTS( +552 "error: '81 0/add/subop 0/mod/indirect 4/rm32/use-sib 2/index 3/scale 1/imm32' (combine rm32 with imm32 based on subop): missing base operand\n" +553 ); +554 } +555 +556 void test_check_extra_displacement() { +557 Hide_errors = true; +558 run( +559 "== code 0x1\n" +560 "89/copy 0/mod/indirect 0/rm32/EAX 1/r32/ECX 4/disp8\n" +561 ); +562 CHECK_TRACE_CONTENTS( +563 "error: '89/copy 0/mod/indirect 0/rm32/EAX 1/r32/ECX 4/disp8' (copy r32 to rm32): unexpected disp8 operand\n" +564 ); +565 } +566 +567 void test_check_duplicate_operand() { +568 Hide_errors = true; +569 run( +570 "== code 0x1\n" +571 "89/copy 0/mod/indirect 0/rm32/EAX 1/r32/ECX 1/r32\n" +572 ); +573 CHECK_TRACE_CONTENTS( +574 "error: '89/copy 0/mod/indirect 0/rm32/EAX 1/r32/ECX 1/r32': duplicate r32 operand\n" +575 ); +576 } +577 +578 void test_check_base_operand_not_needed_in_direct_mode() { +579 run( +580 "== code 0x1\n" +581 "81 0/add/subop 3/mod/indirect 4/rm32/use-sib 1/imm32\n" +582 ); +583 CHECK_TRACE_COUNT("error", 0); +584 } +585 +586 void test_extra_modrm() { +587 Hide_errors = true; +588 run( +589 "== code 0x1\n" +590 "59/pop-to-ECX 3/mod/direct 1/rm32/ECX 4/r32/ESP\n" +591 ); +592 CHECK_TRACE_CONTENTS( +593 "error: '59/pop-to-ECX 3/mod/direct 1/rm32/ECX 4/r32/ESP' (pop top of stack to ECX): unexpected modrm operand\n" +594 ); +595 } +596 +597 //:: similarly handle multi-byte opcodes +598 +599 void check_operands_0f(const line& inst) { +600 assert(inst.words.at(0).data == "0f"); +601 if (SIZE(inst.words) == 1) { +602 raise << "opcode '0f' requires a second opcode\n" << end(); 603 return; 604 } -605 check_operands_0f(inst, op); -606 } -607 -608 void check_operands_f3(const line& /*unused*/) { -609 raise << "no supported opcodes starting with f3\n" << end(); -610 } -611 -612 void test_check_missing_disp32_operand() { -613 Hide_errors = true; -614 run( -615 "== code 0x1\n" -616 " 0f 84 # jmp if ZF to ??\n" -617 ); -618 CHECK_TRACE_CONTENTS( -619 "error: '0f 84' (jump disp32 bytes away if equal, if ZF is set): missing disp32 operand\n" -620 ); -621 } -622 -623 void test_0f_opcode_with_modrm() { -624 transform( -625 "== code 0x1\n" -626 "0f af/multiply 2/mod/*+disp32 5/rm32/ebp 8/disp32 0/r32\n" -627 ); -628 CHECK_TRACE_DOESNT_CONTAIN_ERRORS(); -629 } -630 -631 :(before "End Globals") -632 map</*op*/string, /*bitvector*/uint8_t> Permitted_operands_0f; -633 :(before "End Init Permitted Operands") -634 //// Class D: just op and disp32 -635 // imm32 imm8 disp32 |disp16 disp8 subop modrm -636 // 0 0 1 |0 0 0 0 -637 put_new(Permitted_operands_0f, "82", 0x10); -638 put_new(Permitted_operands_0f, "83", 0x10); -639 put_new(Permitted_operands_0f, "84", 0x10); -640 put_new(Permitted_operands_0f, "85", 0x10); -641 put_new(Permitted_operands_0f, "86", 0x10); -642 put_new(Permitted_operands_0f, "87", 0x10); -643 put_new(Permitted_operands_0f, "8c", 0x10); -644 put_new(Permitted_operands_0f, "8d", 0x10); -645 put_new(Permitted_operands_0f, "8e", 0x10); -646 put_new(Permitted_operands_0f, "8f", 0x10); -647 -648 //// Class M: using ModR/M byte -649 // imm32 imm8 disp32 |disp16 disp8 subop modrm -650 // 0 0 0 |0 0 0 1 -651 put_new(Permitted_operands_0f, "af", 0x01); +605 word op = preprocess_op(inst.words.at(1)); +606 if (!contains_key(Name_0f, op.data)) { +607 raise << "unknown 2-byte opcode '0f " << op.data << "'\n" << end(); +608 return; +609 } +610 check_operands_0f(inst, op); +611 } +612 +613 void check_operands_f3(const line& /*unused*/) { +614 raise << "no supported opcodes starting with f3\n" << end(); +615 } +616 +617 void test_check_missing_disp32_operand() { +618 Hide_errors = true; +619 run( +620 "== code 0x1\n" +621 " 0f 84 # jmp if ZF to ??\n" +622 ); +623 CHECK_TRACE_CONTENTS( +624 "error: '0f 84' (jump disp32 bytes away if equal, if ZF is set): missing disp32 operand\n" +625 ); +626 } +627 +628 void test_0f_opcode_with_modrm() { +629 transform( +630 "== code 0x1\n" +631 "0f af/multiply 2/mod/*+disp32 5/rm32/ebp 8/disp32 0/r32\n" +632 ); +633 CHECK_TRACE_DOESNT_CONTAIN_ERRORS(); +634 } +635 +636 :(before "End Globals") +637 map</*op*/string, /*bitvector*/uint8_t> Permitted_operands_0f; +638 :(before "End Init Permitted Operands") +639 //// Class D: just op and disp32 +640 // imm32 imm8 disp32 |disp16 disp8 subop modrm +641 // 0 0 1 |0 0 0 0 +642 put_new(Permitted_operands_0f, "82", 0x10); +643 put_new(Permitted_operands_0f, "83", 0x10); +644 put_new(Permitted_operands_0f, "84", 0x10); +645 put_new(Permitted_operands_0f, "85", 0x10); +646 put_new(Permitted_operands_0f, "86", 0x10); +647 put_new(Permitted_operands_0f, "87", 0x10); +648 put_new(Permitted_operands_0f, "8c", 0x10); +649 put_new(Permitted_operands_0f, "8d", 0x10); +650 put_new(Permitted_operands_0f, "8e", 0x10); +651 put_new(Permitted_operands_0f, "8f", 0x10); 652 -653 :(code) -654 void check_operands_0f(const line& inst, const word& op) { -655 uint8_t expected_bitvector = get(Permitted_operands_0f, op.data); -656 if (HAS(expected_bitvector, MODRM)) { -657 check_operands_modrm(inst, op); -658 compare_bitvector_modrm(inst, expected_bitvector, maybe_name_0f(op)); -659 } -660 else { -661 compare_bitvector(inst, CLEAR(expected_bitvector, MODRM), maybe_name_0f(op)); -662 } -663 } -664 -665 string maybe_name_0f(const word& op) { -666 if (!is_hex_byte(op)) return ""; -667 if (!contains_key(Name_0f, op.data)) return ""; -668 // strip stuff in parens from the name -669 const string& s = get(Name_0f, op.data); -670 return " ("+s.substr(0, s.find(" ("))+')'; -671 } -672 -673 string tolower(const char* s) { -674 ostringstream out; -675 for (/*nada*/; *s; ++s) -676 out << static_cast<char>(tolower(*s)); -677 return out.str(); -678 } -679 -680 #undef HAS -681 #undef SET -682 #undef CLEAR -683 -684 :(before "End Includes") -685 #include<cctype> +653 //// Class M: using ModR/M byte +654 // imm32 imm8 disp32 |disp16 disp8 subop modrm +655 // 0 0 0 |0 0 0 1 +656 put_new(Permitted_operands_0f, "af", 0x01); +657 // setcc +658 put_new(Permitted_operands_0f, "92", 0x01); +659 put_new(Permitted_operands_0f, "93", 0x01); +660 put_new(Permitted_operands_0f, "94", 0x01); +661 put_new(Permitted_operands_0f, "95", 0x01); +662 put_new(Permitted_operands_0f, "96", 0x01); +663 put_new(Permitted_operands_0f, "97", 0x01); +664 put_new(Permitted_operands_0f, "9c", 0x01); +665 put_new(Permitted_operands_0f, "9d", 0x01); +666 put_new(Permitted_operands_0f, "9e", 0x01); +667 put_new(Permitted_operands_0f, "9f", 0x01); +668 +669 :(code) +670 void check_operands_0f(const line& inst, const word& op) { +671 uint8_t expected_bitvector = get(Permitted_operands_0f, op.data); +672 if (HAS(expected_bitvector, MODRM)) { +673 check_operands_modrm(inst, op); +674 compare_bitvector_modrm(inst, expected_bitvector, maybe_name_0f(op)); +675 } +676 else { +677 compare_bitvector(inst, CLEAR(expected_bitvector, MODRM), maybe_name_0f(op)); +678 } +679 } +680 +681 string maybe_name_0f(const word& op) { +682 if (!is_hex_byte(op)) return ""; +683 if (!contains_key(Name_0f, op.data)) return ""; +684 // strip stuff in parens from the name +685 const string& s = get(Name_0f, op.data); +686 return " ("+s.substr(0, s.find(" ("))+')'; +687 } +688 +689 string tolower(const char* s) { +690 ostringstream out; +691 for (/*nada*/; *s; ++s) +692 out << static_cast<char>(tolower(*s)); +693 return out.str(); +694 } +695 +696 #undef HAS +697 #undef SET +698 #undef CLEAR +699 +700 :(before "End Includes") +701 #include<cctype> diff --git a/html/034check_operand_bounds.cc.html b/html/034check_operand_bounds.cc.html index 4f97a676..598e5bd2 100644 --- a/html/034check_operand_bounds.cc.html +++ b/html/034check_operand_bounds.cc.html @@ -95,7 +95,7 @@ if ('onhashchange' in window) { 35 trace(3, "transform") << "-- check operand bounds" << end(); 36 for (int i = 0; i < SIZE(code.lines); ++i) { 37 const line& inst = code.lines.at(i); - 38 for (int j = first_operand(inst); j < SIZE(inst.words); ++j) + 38 for (int j = first_operand(inst); j < SIZE(inst.words); ++j) 39 check_operand_bounds(inst.words.at(j)); 40 if (trace_contains_errors()) return; // stop at the first mal-formed instruction 41 } diff --git a/html/067parse-hex.subx.html b/html/067parse-hex.subx.html index b06ad099..7494f8b9 100644 --- a/html/067parse-hex.subx.html +++ b/html/067parse-hex.subx.html @@ -121,7 +121,7 @@ if ('onhashchange' in window) { 61 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL 62 50/push-eax 63 # . . call - 64 e8/call is-hex-digit?/disp32 + 64 e8/call is-hex-digit?/disp32 65 # . . discard args 66 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 67 # if (eax == false) return false @@ -411,531 +411,592 @@ if ('onhashchange' in window) { 351 5d/pop-to-ebp 352 c3/return 353 -354 parse-hex-int-from-slice: # in: (addr slice) -> result/eax: int +354 parse-hex-int: # in: (addr array byte) -> result/eax: int 355 # . prologue 356 55/push-ebp 357 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 358 # . save registers 359 51/push-ecx 360 52/push-edx -361 53/push-ebx -362 56/push-esi -363 # var result/ebx: int = 0 -364 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx -365 # ecx = in -366 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx -367 # edx = in->end -368 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 2/r32/edx 4/disp8 . # copy *(ecx+4) to edx -369 # var curr/ecx: (addr byte) = in->start -370 8b/copy 0/mod/indirect 1/rm32/ecx . . . 1/r32/ecx . . # copy *ecx to ecx -371 # var negate?/esi: boolean = false -372 31/xor 3/mod/direct 6/rm32/esi . . . 6/r32/esi . . # clear esi -373 $parse-hex-int-from-slice:negative: -374 # if (*curr == '-') ++curr, negate = true -375 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax -376 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL -377 3d/compare-eax-and 0x2d/imm32/- -378 75/jump-if-!= $parse-hex-int-from-slice:initial-0/disp8 -379 # . ++curr -380 41/increment-ecx -381 # . negate = true -382 be/copy-to-esi 1/imm32/true -383 $parse-hex-int-from-slice:initial-0: -384 # skip past leading '0x' -385 # . if (*curr != '0') jump to loop -386 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL -387 3d/compare-eax-and 0x30/imm32/0 -388 75/jump-if-!= $parse-hex-int-from-slice:loop/disp8 -389 # . ++curr -390 41/increment-ecx -391 $parse-hex-int-from-slice:initial-0x: -392 # . if (curr >= in->end) return result -393 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx -394 73/jump-if-addr>= $parse-hex-int-from-slice:end/disp8 -395 # . if (*curr != 'x') jump to loop # the previous '0' is still valid so doesn't need to be checked again -396 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax -397 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL -398 3d/compare-eax-and 0x78/imm32/x -399 75/jump-if-!= $parse-hex-int-from-slice:loop/disp8 -400 # . ++curr -401 41/increment-ecx -402 $parse-hex-int-from-slice:loop: -403 # if (curr >= in->end) break -404 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx -405 73/jump-if-addr>= $parse-hex-int-from-slice:negate/disp8 -406 # var eax: int = from-hex-char(*curr) -407 # . . copy arg to eax -408 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL -409 # . . call -410 e8/call from-hex-char/disp32 -411 # result = result * 16 + eax -412 c1/shift 4/subop/left 3/mod/direct 3/rm32/ebx . . . . . 4/imm8 # shift ebx left by 4 bits -413 01/add 3/mod/direct 3/rm32/ebx . . . 0/r32/eax . . # add eax to ebx -414 # ++curr -415 41/increment-ecx -416 # loop -417 eb/jump $parse-hex-int-from-slice:loop/disp8 -418 $parse-hex-int-from-slice:negate: -419 # if (negate?) result = -result -420 81 7/subop/compare 3/mod/direct 6/rm32/esi . . . . . 0/imm32/false # compare esi -421 74/jump-if-= $parse-hex-int-from-slice:end/disp8 -422 f7 3/subop/negate 3/mod/direct 3/rm32/ebx . . . . . . # negate ebx -423 $parse-hex-int-from-slice:end: -424 # return result -425 89/copy 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # copy ebx to eax -426 # . restore registers -427 5e/pop-to-esi -428 5b/pop-to-ebx -429 5a/pop-to-edx -430 59/pop-to-ecx -431 # . epilogue -432 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -433 5d/pop-to-ebp -434 c3/return -435 -436 test-parse-hex-int-from-slice-single-digit: -437 # . prologue -438 55/push-ebp -439 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -440 # (eax..ecx) = "a" -441 b8/copy-to-eax "a"/imm32 -442 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -443 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx -444 05/add-to-eax 4/imm32 -445 # var slice/ecx: slice = {eax, ecx} -446 51/push-ecx -447 50/push-eax -448 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -449 # eax = parse-hex-int-from-slice(slice) -450 # . . push args -451 51/push-ecx -452 # . . call -453 e8/call parse-hex-int-from-slice/disp32 -454 # . . discard args -455 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -456 # check-ints-equal(eax, 0xa, msg) -457 # . . push args -458 68/push "F - test-parse-hex-int-from-slice-single-digit"/imm32 -459 68/push 0xa/imm32 -460 50/push-eax -461 # . . call -462 e8/call check-ints-equal/disp32 -463 # . . discard args -464 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -465 # . epilogue -466 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -467 5d/pop-to-ebp -468 c3/return -469 -470 test-parse-hex-int-from-slice-multi-digit: -471 # . prologue -472 55/push-ebp -473 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -474 # (eax..ecx) = "34a" -475 b8/copy-to-eax "34a"/imm32 -476 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -477 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx -478 05/add-to-eax 4/imm32 -479 # var slice/ecx: slice = {eax, ecx} -480 51/push-ecx -481 50/push-eax -482 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -483 # eax = parse-hex-int-from-slice(slice) -484 # . . push args -485 51/push-ecx -486 # . . call -487 e8/call parse-hex-int-from-slice/disp32 -488 # . . discard args -489 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -490 # check-ints-equal(eax, 0x34a, msg) -491 # . . push args -492 68/push "F - test-parse-hex-int-from-slice-multi-digit"/imm32 -493 68/push 0x34a/imm32 -494 50/push-eax -495 # . . call -496 e8/call check-ints-equal/disp32 -497 # . . discard args -498 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -499 # . epilogue -500 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -501 5d/pop-to-ebp -502 c3/return -503 -504 test-parse-hex-int-from-slice-0x-prefix: -505 # . prologue -506 55/push-ebp -507 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -508 # (eax..ecx) = "0x34" -509 b8/copy-to-eax "0x34"/imm32 -510 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -511 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx -512 05/add-to-eax 4/imm32 -513 # var slice/ecx: slice = {eax, ecx} -514 51/push-ecx -515 50/push-eax -516 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -517 # eax = parse-hex-int-from-slice(slice) +361 # eax = in +362 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax +363 # var curr/ecx: (addr byte) = &in->data +364 8d/copy-address 1/mod/*+disp8 0/rm32/eax . . . 1/r32/ecx 4/disp8 . # copy eax+4 to ecx +365 # var max/edx: (addr byte) = &in->data[in->length] +366 # . edx = in->length +367 8b/copy 0/mod/indirect 0/rm32/eax . . . 2/r32/edx . . # copy *eax to edx +368 # . edx = in->data + in->length +369 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 2/index/edx . 2/r32/edx 4/disp8 . # copy eax+edx+4 to edx +370 # return parse-hex-int-helper(curr, max) +371 # . . push args +372 52/push-edx +373 51/push-ecx +374 # . . call +375 e8/call parse-hex-int-helper/disp32 +376 # . . discard args +377 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +378 $parse-hex-int:end: +379 # . restore registers +380 5a/pop-to-edx +381 59/pop-to-ecx +382 # . epilogue +383 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +384 5d/pop-to-ebp +385 c3/return +386 +387 parse-hex-int-from-slice: # in: (addr slice) -> result/eax: int +388 # . prologue +389 55/push-ebp +390 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +391 # . save registers +392 51/push-ecx +393 52/push-edx +394 # ecx = in +395 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx +396 # edx = in->end +397 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 2/r32/edx 4/disp8 . # copy *(ecx+4) to edx +398 # var curr/ecx: (addr byte) = in->start +399 8b/copy 0/mod/indirect 1/rm32/ecx . . . 1/r32/ecx . . # copy *ecx to ecx +400 # return parse-hex-int-helper(curr, max) +401 # . . push args +402 52/push-edx +403 51/push-ecx +404 # . . call +405 e8/call parse-hex-int-helper/disp32 +406 # . . discard args +407 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +408 $parse-hex-int-from-slice:end: +409 # . restore registers +410 5a/pop-to-edx +411 59/pop-to-ecx +412 # . epilogue +413 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +414 5d/pop-to-ebp +415 c3/return +416 +417 parse-hex-int-helper: # start: (addr byte), end: (addr byte) -> result/eax: int +418 # . prologue +419 55/push-ebp +420 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +421 # . save registers +422 51/push-ecx +423 52/push-edx +424 53/push-ebx +425 56/push-esi +426 # var curr/ecx: (addr byte) = start +427 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx +428 # edx = max +429 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0xc/disp8 . # copy *(ebp+0xc) to edx +430 # var result/ebx: int = 0 +431 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx +432 # var negate?/esi: boolean = false +433 31/xor 3/mod/direct 6/rm32/esi . . . 6/r32/esi . . # clear esi +434 $parse-hex-int-helper:negative: +435 # if (*curr == '-') ++curr, negate = true +436 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax +437 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL +438 3d/compare-eax-and 0x2d/imm32/- +439 75/jump-if-!= $parse-hex-int-helper:initial-0/disp8 +440 # . ++curr +441 41/increment-ecx +442 # . negate = true +443 be/copy-to-esi 1/imm32/true +444 $parse-hex-int-helper:initial-0: +445 # skip past leading '0x' +446 # . if (*curr != '0') jump to loop +447 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL +448 3d/compare-eax-and 0x30/imm32/0 +449 75/jump-if-!= $parse-hex-int-helper:loop/disp8 +450 # . ++curr +451 41/increment-ecx +452 $parse-hex-int-helper:initial-0x: +453 # . if (curr >= in->end) return result +454 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx +455 73/jump-if-addr>= $parse-hex-int-helper:end/disp8 +456 # . if (*curr != 'x') jump to loop # the previous '0' is still valid so doesn't need to be checked again +457 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax +458 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL +459 3d/compare-eax-and 0x78/imm32/x +460 75/jump-if-!= $parse-hex-int-helper:loop/disp8 +461 # . ++curr +462 41/increment-ecx +463 $parse-hex-int-helper:loop: +464 # if (curr >= in->end) break +465 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx +466 73/jump-if-addr>= $parse-hex-int-helper:negate/disp8 +467 # var eax: int = from-hex-char(*curr) +468 # . . copy arg to eax +469 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL +470 # . . call +471 e8/call from-hex-char/disp32 +472 # result = result * 16 + eax +473 c1/shift 4/subop/left 3/mod/direct 3/rm32/ebx . . . . . 4/imm8 # shift ebx left by 4 bits +474 01/add 3/mod/direct 3/rm32/ebx . . . 0/r32/eax . . # add eax to ebx +475 # ++curr +476 41/increment-ecx +477 # loop +478 eb/jump $parse-hex-int-helper:loop/disp8 +479 $parse-hex-int-helper:negate: +480 # if (negate?) result = -result +481 81 7/subop/compare 3/mod/direct 6/rm32/esi . . . . . 0/imm32/false # compare esi +482 74/jump-if-= $parse-hex-int-helper:end/disp8 +483 f7 3/subop/negate 3/mod/direct 3/rm32/ebx . . . . . . # negate ebx +484 $parse-hex-int-helper:end: +485 # return result +486 89/copy 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # copy ebx to eax +487 # . restore registers +488 5e/pop-to-esi +489 5b/pop-to-ebx +490 5a/pop-to-edx +491 59/pop-to-ecx +492 # . epilogue +493 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +494 5d/pop-to-ebp +495 c3/return +496 +497 test-parse-hex-int-from-slice-single-digit: +498 # . prologue +499 55/push-ebp +500 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +501 # (eax..ecx) = "a" +502 b8/copy-to-eax "a"/imm32 +503 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +504 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx +505 05/add-to-eax 4/imm32 +506 # var slice/ecx: slice = {eax, ecx} +507 51/push-ecx +508 50/push-eax +509 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +510 # eax = parse-hex-int-from-slice(slice) +511 # . . push args +512 51/push-ecx +513 # . . call +514 e8/call parse-hex-int-from-slice/disp32 +515 # . . discard args +516 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +517 # check-ints-equal(eax, 0xa, msg) 518 # . . push args -519 51/push-ecx -520 # . . call -521 e8/call parse-hex-int-from-slice/disp32 -522 # . . discard args -523 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -524 # check-ints-equal(eax, 0x34a, msg) -525 # . . push args -526 68/push "F - test-parse-hex-int-from-slice-0x-prefix"/imm32 -527 68/push 0x34/imm32 -528 50/push-eax -529 # . . call -530 e8/call check-ints-equal/disp32 -531 # . . discard args -532 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -533 # . epilogue -534 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -535 5d/pop-to-ebp -536 c3/return -537 -538 test-parse-hex-int-from-slice-zero: -539 # . prologue -540 55/push-ebp -541 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -542 # (eax..ecx) = "0" -543 b8/copy-to-eax "0"/imm32 -544 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -545 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx -546 05/add-to-eax 4/imm32 -547 # var slice/ecx: slice = {eax, ecx} -548 51/push-ecx -549 50/push-eax -550 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -551 # eax = parse-hex-int-from-slice(slice) +519 68/push "F - test-parse-hex-int-from-slice-single-digit"/imm32 +520 68/push 0xa/imm32 +521 50/push-eax +522 # . . call +523 e8/call check-ints-equal/disp32 +524 # . . discard args +525 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +526 # . epilogue +527 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +528 5d/pop-to-ebp +529 c3/return +530 +531 test-parse-hex-int-from-slice-multi-digit: +532 # . prologue +533 55/push-ebp +534 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +535 # (eax..ecx) = "34a" +536 b8/copy-to-eax "34a"/imm32 +537 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +538 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx +539 05/add-to-eax 4/imm32 +540 # var slice/ecx: slice = {eax, ecx} +541 51/push-ecx +542 50/push-eax +543 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +544 # eax = parse-hex-int-from-slice(slice) +545 # . . push args +546 51/push-ecx +547 # . . call +548 e8/call parse-hex-int-from-slice/disp32 +549 # . . discard args +550 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +551 # check-ints-equal(eax, 0x34a, msg) 552 # . . push args -553 51/push-ecx -554 # . . call -555 e8/call parse-hex-int-from-slice/disp32 -556 # . . discard args -557 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -558 # check-ints-equal(eax, 0x34a, msg) -559 # . . push args -560 68/push "F - test-parse-hex-int-from-slice-zero"/imm32 -561 68/push 0/imm32 -562 50/push-eax -563 # . . call -564 e8/call check-ints-equal/disp32 -565 # . . discard args -566 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -567 # . epilogue -568 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -569 5d/pop-to-ebp -570 c3/return -571 -572 test-parse-hex-int-from-slice-0-prefix: -573 # . prologue -574 55/push-ebp -575 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -576 # (eax..ecx) = "03" -577 b8/copy-to-eax "03"/imm32 -578 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -579 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx -580 05/add-to-eax 4/imm32 -581 # var slice/ecx: slice = {eax, ecx} -582 51/push-ecx -583 50/push-eax -584 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -585 # eax = parse-hex-int-from-slice(slice) +553 68/push "F - test-parse-hex-int-from-slice-multi-digit"/imm32 +554 68/push 0x34a/imm32 +555 50/push-eax +556 # . . call +557 e8/call check-ints-equal/disp32 +558 # . . discard args +559 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +560 # . epilogue +561 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +562 5d/pop-to-ebp +563 c3/return +564 +565 test-parse-hex-int-from-slice-0x-prefix: +566 # . prologue +567 55/push-ebp +568 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +569 # (eax..ecx) = "0x34" +570 b8/copy-to-eax "0x34"/imm32 +571 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +572 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx +573 05/add-to-eax 4/imm32 +574 # var slice/ecx: slice = {eax, ecx} +575 51/push-ecx +576 50/push-eax +577 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +578 # eax = parse-hex-int-from-slice(slice) +579 # . . push args +580 51/push-ecx +581 # . . call +582 e8/call parse-hex-int-from-slice/disp32 +583 # . . discard args +584 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +585 # check-ints-equal(eax, 0x34a, msg) 586 # . . push args -587 51/push-ecx -588 # . . call -589 e8/call parse-hex-int-from-slice/disp32 -590 # . . discard args -591 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -592 # check-ints-equal(eax, 0x3, msg) -593 # . . push args -594 68/push "F - test-parse-hex-int-from-slice-0-prefix"/imm32 -595 68/push 0x3/imm32 -596 50/push-eax -597 # . . call -598 e8/call check-ints-equal/disp32 -599 # . . discard args -600 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -601 # . epilogue -602 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -603 5d/pop-to-ebp -604 c3/return -605 -606 test-parse-hex-int-from-slice-negative: -607 # . prologue -608 55/push-ebp -609 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -610 # (eax..ecx) = "-03" -611 b8/copy-to-eax "-03"/imm32 -612 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -613 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx -614 05/add-to-eax 4/imm32 -615 # var slice/ecx: slice = {eax, ecx} -616 51/push-ecx -617 50/push-eax -618 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -619 # eax = parse-hex-int-from-slice(slice) +587 68/push "F - test-parse-hex-int-from-slice-0x-prefix"/imm32 +588 68/push 0x34/imm32 +589 50/push-eax +590 # . . call +591 e8/call check-ints-equal/disp32 +592 # . . discard args +593 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +594 # . epilogue +595 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +596 5d/pop-to-ebp +597 c3/return +598 +599 test-parse-hex-int-from-slice-zero: +600 # . prologue +601 55/push-ebp +602 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +603 # (eax..ecx) = "0" +604 b8/copy-to-eax "0"/imm32 +605 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +606 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx +607 05/add-to-eax 4/imm32 +608 # var slice/ecx: slice = {eax, ecx} +609 51/push-ecx +610 50/push-eax +611 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +612 # eax = parse-hex-int-from-slice(slice) +613 # . . push args +614 51/push-ecx +615 # . . call +616 e8/call parse-hex-int-from-slice/disp32 +617 # . . discard args +618 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +619 # check-ints-equal(eax, 0x34a, msg) 620 # . . push args -621 51/push-ecx -622 # . . call -623 e8/call parse-hex-int-from-slice/disp32 -624 # . . discard args -625 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -626 # check-ints-equal(eax, -3, msg) -627 # . . push args -628 68/push "F - test-parse-hex-int-from-slice-negative"/imm32 -629 68/push -3/imm32 -630 50/push-eax -631 # . . call -632 e8/call check-ints-equal/disp32 -633 # . . discard args -634 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -635 # . epilogue -636 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -637 5d/pop-to-ebp -638 c3/return -639 -640 is-hex-digit?: # c: byte -> eax: boolean -641 # . prologue -642 55/push-ebp -643 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -644 # . save registers -645 51/push-ecx -646 # ecx = c -647 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx -648 # return false if c < '0' -649 81 7/subop/compare 3/mod/direct 1/rm32/ecx . . . . . 0x30/imm32 # compare ecx -650 7c/jump-if-< $is-hex-digit?:false/disp8 -651 # return true if c <= '9' -652 81 7/subop/compare 3/mod/direct 1/rm32/ecx . . . . . 0x39/imm32 # compare ecx -653 7e/jump-if-<= $is-hex-digit?:true/disp8 -654 # drop case -655 25/and-eax-with 0x5f/imm32 -656 # return false if c > 'f' -657 81 7/subop/compare 3/mod/direct 1/rm32/ecx . . . . . 0x66/imm32 # compare ecx -658 7f/jump-if-> $is-hex-digit?:false/disp8 -659 # return true if c >= 'a' -660 81 7/subop/compare 3/mod/direct 1/rm32/ecx . . . . . 0x61/imm32 # compare ecx -661 7d/jump-if->= $is-hex-digit?:true/disp8 -662 # otherwise return false -663 $is-hex-digit?:false: -664 b8/copy-to-eax 0/imm32/false -665 eb/jump $is-hex-digit?:end/disp8 -666 $is-hex-digit?:true: -667 b8/copy-to-eax 1/imm32/true -668 $is-hex-digit?:end: -669 # . restore registers -670 59/pop-to-ecx -671 # . epilogue -672 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -673 5d/pop-to-ebp -674 c3/return -675 -676 test-hex-below-0: -677 # eax = is-hex-digit?(0x2f) -678 # . . push args -679 68/push 0x2f/imm32 -680 # . . call -681 e8/call is-hex-digit?/disp32 -682 # . . discard args -683 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -684 # check-ints-equal(eax, 0, msg) -685 # . . push args -686 68/push "F - test-hex-below-0"/imm32 -687 68/push 0/imm32/false -688 50/push-eax -689 # . . call -690 e8/call check-ints-equal/disp32 -691 # . . discard args -692 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -693 c3/return -694 -695 test-hex-0-to-9: -696 # eax = is-hex-digit?(0x30) -697 # . . push args -698 68/push 0x30/imm32 -699 # . . call -700 e8/call is-hex-digit?/disp32 -701 # . . discard args -702 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -703 # check-ints-equal(eax, 1, msg) -704 # . . push args -705 68/push "F - test-hex-at-0"/imm32 -706 68/push 1/imm32/true -707 50/push-eax -708 # . . call -709 e8/call check-ints-equal/disp32 -710 # . . discard args -711 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -712 # eax = is-hex-digit?(0x39) -713 # . . push args -714 68/push 0x39/imm32 -715 # . . call -716 e8/call is-hex-digit?/disp32 -717 # . . discard args -718 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -719 # check-ints-equal(eax, 1, msg) -720 # . . push args -721 68/push "F - test-hex-at-9"/imm32 -722 68/push 1/imm32/true -723 50/push-eax -724 # . . call -725 e8/call check-ints-equal/disp32 -726 # . . discard args -727 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -728 c3/return -729 -730 test-hex-above-9-to-a: -731 # eax = is-hex-digit?(0x3a) -732 # . . push args -733 68/push 0x3a/imm32 -734 # . . call -735 e8/call is-hex-digit?/disp32 -736 # . . discard args -737 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -738 # check-ints-equal(eax, 0, msg) +621 68/push "F - test-parse-hex-int-from-slice-zero"/imm32 +622 68/push 0/imm32 +623 50/push-eax +624 # . . call +625 e8/call check-ints-equal/disp32 +626 # . . discard args +627 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +628 # . epilogue +629 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +630 5d/pop-to-ebp +631 c3/return +632 +633 test-parse-hex-int-from-slice-0-prefix: +634 # . prologue +635 55/push-ebp +636 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +637 # (eax..ecx) = "03" +638 b8/copy-to-eax "03"/imm32 +639 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +640 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx +641 05/add-to-eax 4/imm32 +642 # var slice/ecx: slice = {eax, ecx} +643 51/push-ecx +644 50/push-eax +645 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +646 # eax = parse-hex-int-from-slice(slice) +647 # . . push args +648 51/push-ecx +649 # . . call +650 e8/call parse-hex-int-from-slice/disp32 +651 # . . discard args +652 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +653 # check-ints-equal(eax, 0x3, msg) +654 # . . push args +655 68/push "F - test-parse-hex-int-from-slice-0-prefix"/imm32 +656 68/push 0x3/imm32 +657 50/push-eax +658 # . . call +659 e8/call check-ints-equal/disp32 +660 # . . discard args +661 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +662 # . epilogue +663 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +664 5d/pop-to-ebp +665 c3/return +666 +667 test-parse-hex-int-from-slice-negative: +668 # . prologue +669 55/push-ebp +670 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +671 # (eax..ecx) = "-03" +672 b8/copy-to-eax "-03"/imm32 +673 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +674 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx +675 05/add-to-eax 4/imm32 +676 # var slice/ecx: slice = {eax, ecx} +677 51/push-ecx +678 50/push-eax +679 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +680 # eax = parse-hex-int-from-slice(slice) +681 # . . push args +682 51/push-ecx +683 # . . call +684 e8/call parse-hex-int-from-slice/disp32 +685 # . . discard args +686 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +687 # check-ints-equal(eax, -3, msg) +688 # . . push args +689 68/push "F - test-parse-hex-int-from-slice-negative"/imm32 +690 68/push -3/imm32 +691 50/push-eax +692 # . . call +693 e8/call check-ints-equal/disp32 +694 # . . discard args +695 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +696 # . epilogue +697 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +698 5d/pop-to-ebp +699 c3/return +700 +701 is-hex-digit?: # c: byte -> eax: boolean +702 # . prologue +703 55/push-ebp +704 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +705 # . save registers +706 51/push-ecx +707 # ecx = c +708 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx +709 # return false if c < '0' +710 81 7/subop/compare 3/mod/direct 1/rm32/ecx . . . . . 0x30/imm32 # compare ecx +711 7c/jump-if-< $is-hex-digit?:false/disp8 +712 # return true if c <= '9' +713 81 7/subop/compare 3/mod/direct 1/rm32/ecx . . . . . 0x39/imm32 # compare ecx +714 7e/jump-if-<= $is-hex-digit?:true/disp8 +715 # drop case +716 25/and-eax-with 0x5f/imm32 +717 # return false if c > 'f' +718 81 7/subop/compare 3/mod/direct 1/rm32/ecx . . . . . 0x66/imm32 # compare ecx +719 7f/jump-if-> $is-hex-digit?:false/disp8 +720 # return true if c >= 'a' +721 81 7/subop/compare 3/mod/direct 1/rm32/ecx . . . . . 0x61/imm32 # compare ecx +722 7d/jump-if->= $is-hex-digit?:true/disp8 +723 # otherwise return false +724 $is-hex-digit?:false: +725 b8/copy-to-eax 0/imm32/false +726 eb/jump $is-hex-digit?:end/disp8 +727 $is-hex-digit?:true: +728 b8/copy-to-eax 1/imm32/true +729 $is-hex-digit?:end: +730 # . restore registers +731 59/pop-to-ecx +732 # . epilogue +733 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +734 5d/pop-to-ebp +735 c3/return +736 +737 test-hex-below-0: +738 # eax = is-hex-digit?(0x2f) 739 # . . push args -740 68/push "F - test-hex-above-9-to-a"/imm32 -741 68/push 0/imm32/false -742 50/push-eax -743 # . . call -744 e8/call check-ints-equal/disp32 -745 # . . discard args -746 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -747 c3/return -748 -749 test-hex-a-to-f: -750 # eax = is-hex-digit?(0x61) -751 # . . push args -752 68/push 0x61/imm32 -753 # . . call -754 e8/call is-hex-digit?/disp32 -755 # . . discard args -756 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -757 # check-ints-equal(eax, 1, msg) +740 68/push 0x2f/imm32 +741 # . . call +742 e8/call is-hex-digit?/disp32 +743 # . . discard args +744 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +745 # check-ints-equal(eax, 0, msg) +746 # . . push args +747 68/push "F - test-hex-below-0"/imm32 +748 68/push 0/imm32/false +749 50/push-eax +750 # . . call +751 e8/call check-ints-equal/disp32 +752 # . . discard args +753 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +754 c3/return +755 +756 test-hex-0-to-9: +757 # eax = is-hex-digit?(0x30) 758 # . . push args -759 68/push "F - test-hex-at-a"/imm32 -760 68/push 1/imm32/true -761 50/push-eax -762 # . . call -763 e8/call check-ints-equal/disp32 -764 # . . discard args -765 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -766 # eax = is-hex-digit?(0x66) -767 # . . push args -768 68/push 0x66/imm32 +759 68/push 0x30/imm32 +760 # . . call +761 e8/call is-hex-digit?/disp32 +762 # . . discard args +763 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +764 # check-ints-equal(eax, 1, msg) +765 # . . push args +766 68/push "F - test-hex-at-0"/imm32 +767 68/push 1/imm32/true +768 50/push-eax 769 # . . call -770 e8/call is-hex-digit?/disp32 +770 e8/call check-ints-equal/disp32 771 # . . discard args -772 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -773 # check-ints-equal(eax, 1, msg) +772 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +773 # eax = is-hex-digit?(0x39) 774 # . . push args -775 68/push "F - test-hex-at-f"/imm32 -776 68/push 1/imm32/true -777 50/push-eax -778 # . . call -779 e8/call check-ints-equal/disp32 -780 # . . discard args -781 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -782 c3/return -783 -784 test-hex-above-f: -785 # eax = is-hex-digit?(0x67) -786 # . . push args -787 68/push 0x67/imm32 -788 # . . call -789 e8/call is-hex-digit?/disp32 -790 # . . discard args -791 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -792 # check-ints-equal(eax, 0, msg) +775 68/push 0x39/imm32 +776 # . . call +777 e8/call is-hex-digit?/disp32 +778 # . . discard args +779 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +780 # check-ints-equal(eax, 1, msg) +781 # . . push args +782 68/push "F - test-hex-at-9"/imm32 +783 68/push 1/imm32/true +784 50/push-eax +785 # . . call +786 e8/call check-ints-equal/disp32 +787 # . . discard args +788 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +789 c3/return +790 +791 test-hex-above-9-to-a: +792 # eax = is-hex-digit?(0x3a) 793 # . . push args -794 68/push "F - test-hex-above-f"/imm32 -795 68/push 0/imm32/false -796 50/push-eax -797 # . . call -798 e8/call check-ints-equal/disp32 -799 # . . discard args -800 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -801 c3/return -802 -803 from-hex-char: # in/eax: byte -> out/eax: nibble -804 $from-hex-char:check0: -805 # if (eax < '0') goto abort -806 3d/compare-eax-with 0x30/imm32/0 -807 7c/jump-if-< $from-hex-char:abort/disp8 -808 $from-hex-char:check1: -809 # if (eax > 'f') goto abort -810 3d/compare-eax-with 0x66/imm32/f -811 7f/jump-if-> $from-hex-char:abort/disp8 -812 $from-hex-char:check2: -813 # if (eax > '9') goto next check -814 3d/compare-eax-with 0x39/imm32/9 -815 7f/jump-if-> $from-hex-char:check3/disp8 -816 $from-hex-char:digit: -817 # return eax - '0' -818 2d/subtract-from-eax 0x30/imm32/0 -819 c3/return -820 $from-hex-char:check3: -821 # if (eax < 'a') goto abort -822 3d/compare-eax-with 0x61/imm32/a -823 7c/jump-if-< $from-hex-char:abort/disp8 -824 $from-hex-char:letter: -825 # return eax - ('a'-10) -826 2d/subtract-from-eax 0x57/imm32/a-10 -827 c3/return -828 -829 $from-hex-char:abort: -830 # . _write(2/stderr, error) -831 # . . push args -832 68/push "invalid hex char: "/imm32 -833 68/push 2/imm32/stderr -834 # . . call -835 e8/call _write/disp32 -836 # . . discard args -837 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -838 # . clear-stream($Stderr->buffer) -839 # . . save eax -840 50/push-eax -841 # . . push args -842 68/push $Stderr->buffer/imm32 -843 # . . call -844 e8/call clear-stream/disp32 -845 # . . discard args -846 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -847 # . . restore eax -848 58/pop-to-eax -849 # . print-int32-buffered(Stderr, eax) -850 # . . push args -851 50/push-eax -852 68/push Stderr/imm32 -853 # . . call -854 e8/call print-int32-buffered/disp32 -855 # . . discard args -856 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -857 # . flush(Stderr) -858 # . . push args -859 68/push Stderr/imm32 -860 # . . call -861 e8/call flush/disp32 -862 # . . discard args -863 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -864 # . _write(2/stderr, "\n") -865 # . . push args -866 68/push Newline/imm32 -867 68/push 2/imm32/stderr -868 # . . call -869 e8/call _write/disp32 -870 # . . discard args -871 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -872 # . syscall(exit, 1) -873 bb/copy-to-ebx 1/imm32 -874 b8/copy-to-eax 1/imm32/exit -875 cd/syscall 0x80/imm8 -876 # never gets here -877 -878 # . . vim:nowrap:textwidth=0 +794 68/push 0x3a/imm32 +795 # . . call +796 e8/call is-hex-digit?/disp32 +797 # . . discard args +798 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +799 # check-ints-equal(eax, 0, msg) +800 # . . push args +801 68/push "F - test-hex-above-9-to-a"/imm32 +802 68/push 0/imm32/false +803 50/push-eax +804 # . . call +805 e8/call check-ints-equal/disp32 +806 # . . discard args +807 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +808 c3/return +809 +810 test-hex-a-to-f: +811 # eax = is-hex-digit?(0x61) +812 # . . push args +813 68/push 0x61/imm32 +814 # . . call +815 e8/call is-hex-digit?/disp32 +816 # . . discard args +817 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +818 # check-ints-equal(eax, 1, msg) +819 # . . push args +820 68/push "F - test-hex-at-a"/imm32 +821 68/push 1/imm32/true +822 50/push-eax +823 # . . call +824 e8/call check-ints-equal/disp32 +825 # . . discard args +826 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +827 # eax = is-hex-digit?(0x66) +828 # . . push args +829 68/push 0x66/imm32 +830 # . . call +831 e8/call is-hex-digit?/disp32 +832 # . . discard args +833 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +834 # check-ints-equal(eax, 1, msg) +835 # . . push args +836 68/push "F - test-hex-at-f"/imm32 +837 68/push 1/imm32/true +838 50/push-eax +839 # . . call +840 e8/call check-ints-equal/disp32 +841 # . . discard args +842 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +843 c3/return +844 +845 test-hex-above-f: +846 # eax = is-hex-digit?(0x67) +847 # . . push args +848 68/push 0x67/imm32 +849 # . . call +850 e8/call is-hex-digit?/disp32 +851 # . . discard args +852 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +853 # check-ints-equal(eax, 0, msg) +854 # . . push args +855 68/push "F - test-hex-above-f"/imm32 +856 68/push 0/imm32/false +857 50/push-eax +858 # . . call +859 e8/call check-ints-equal/disp32 +860 # . . discard args +861 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +862 c3/return +863 +864 from-hex-char: # in/eax: byte -> out/eax: nibble +865 $from-hex-char:check0: +866 # if (eax < '0') goto abort +867 3d/compare-eax-with 0x30/imm32/0 +868 7c/jump-if-< $from-hex-char:abort/disp8 +869 $from-hex-char:check1: +870 # if (eax > 'f') goto abort +871 3d/compare-eax-with 0x66/imm32/f +872 7f/jump-if-> $from-hex-char:abort/disp8 +873 $from-hex-char:check2: +874 # if (eax > '9') goto next check +875 3d/compare-eax-with 0x39/imm32/9 +876 7f/jump-if-> $from-hex-char:check3/disp8 +877 $from-hex-char:digit: +878 # return eax - '0' +879 2d/subtract-from-eax 0x30/imm32/0 +880 c3/return +881 $from-hex-char:check3: +882 # if (eax < 'a') goto abort +883 3d/compare-eax-with 0x61/imm32/a +884 7c/jump-if-< $from-hex-char:abort/disp8 +885 $from-hex-char:letter: +886 # return eax - ('a'-10) +887 2d/subtract-from-eax 0x57/imm32/a-10 +888 c3/return +889 +890 $from-hex-char:abort: +891 # . _write(2/stderr, error) +892 # . . push args +893 68/push "invalid hex char: "/imm32 +894 68/push 2/imm32/stderr +895 # . . call +896 e8/call _write/disp32 +897 # . . discard args +898 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +899 # . clear-stream($Stderr->buffer) +900 # . . save eax +901 50/push-eax +902 # . . push args +903 68/push $Stderr->buffer/imm32 +904 # . . call +905 e8/call clear-stream/disp32 +906 # . . discard args +907 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +908 # . . restore eax +909 58/pop-to-eax +910 # . print-int32-buffered(Stderr, eax) +911 # . . push args +912 50/push-eax +913 68/push Stderr/imm32 +914 # . . call +915 e8/call print-int32-buffered/disp32 +916 # . . discard args +917 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +918 # . flush(Stderr) +919 # . . push args +920 68/push Stderr/imm32 +921 # . . call +922 e8/call flush/disp32 +923 # . . discard args +924 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +925 # . _write(2/stderr, "\n") +926 # . . push args +927 68/push Newline/imm32 +928 68/push 2/imm32/stderr +929 # . . call +930 e8/call _write/disp32 +931 # . . discard args +932 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +933 # . syscall(exit, 1) +934 bb/copy-to-ebx 1/imm32 +935 b8/copy-to-eax 1/imm32/exit +936 cd/syscall 0x80/imm8 +937 # never gets here +938 +939 # . . vim:nowrap:textwidth=0 diff --git a/html/079emit.subx.html b/html/079emit.subx.html index 7b96917b..57b6d11c 100644 --- a/html/079emit.subx.html +++ b/html/079emit.subx.html @@ -133,7 +133,7 @@ if ('onhashchange' in window) { 72 # . . push args 73 57/push-edi 74 # . . call - 75 e8/call parse-hex-int-from-slice/disp32 + 75 e8/call parse-hex-int-from-slice/disp32 76 # . . discard args 77 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 78 # . emit-hex(out, value, width) diff --git a/html/100array-equal.subx.html b/html/100array-equal.subx.html index 7bc1de5c..452840cb 100644 --- a/html/100array-equal.subx.html +++ b/html/100array-equal.subx.html @@ -426,7 +426,7 @@ if ('onhashchange' in window) { 366 # . . push args 367 51/push-ecx 368 # . . call -369 e8/call parse-hex-int-from-slice/disp32 +369 e8/call parse-hex-int-from-slice/disp32 370 # . . discard args 371 81 0/subop/add %esp 4/imm32 372 # . *out = eax diff --git a/html/apps/assort.subx.html b/html/apps/assort.subx.html index 23f49434..efb6a8f2 100644 --- a/html/apps/assort.subx.html +++ b/html/apps/assort.subx.html @@ -69,13 +69,13 @@ if ('onhashchange' in window) { 7 # because we don't know if they refer to the line above or the line below. 8 # 9 # To run: - 10 # $ ./subx translate init.linux 0*.subx apps/subx-params.subx apps/assort.subx -o apps/assort + 10 # $ ./bootstrap translate init.linux 0*.subx apps/subx-params.subx apps/assort.subx -o apps/assort 11 # $ cat x 12 # == code 13 # abc 14 # == code 15 # def - 16 # $ cat x |./subx run apps/assort + 16 # $ cat x |./bootstrap run apps/assort 17 # == code 18 # abc 19 # def diff --git a/html/apps/crenshaw2-1.subx.html b/html/apps/crenshaw2-1.subx.html index 1c9ae904..42bfe4d6 100644 --- a/html/apps/crenshaw2-1.subx.html +++ b/html/apps/crenshaw2-1.subx.html @@ -64,8 +64,8 @@ if ('onhashchange' in window) { 3 # except that we support hex digits. 4 # 5 # To run: - 6 # $ ./subx translate init.linux 0*.subx apps/crenshaw2-1.subx -o apps/crenshaw2-1 - 7 # $ echo '3' |./subx run apps/crenshaw2-1 + 6 # $ ./bootstrap translate init.linux 0*.subx apps/crenshaw2-1.subx -o apps/crenshaw2-1 + 7 # $ echo '3' |./bootstrap run apps/crenshaw2-1 8 # Expected output: 9 # # syscall(exit, 3) 10 # bb/copy-to-ebx 3/imm32 @@ -73,14 +73,14 @@ if ('onhashchange' in window) { 12 # cd/syscall 0x80/imm8 13 # 14 # To run the generated output: - 15 # $ echo '3' |./subx run apps/crenshaw2-1 > z1.subx - 16 # $ ./subx translate init.linux z1.subx -o z1 - 17 # $ ./subx run z1 + 15 # $ echo '3' |./bootstrap run apps/crenshaw2-1 > z1.subx + 16 # $ ./bootstrap translate init.linux z1.subx -o z1 + 17 # $ ./bootstrap run z1 18 # $ echo $? 19 # 3 20 # 21 # Stdin must contain just a single hex digit. Other input will print an error: - 22 # $ echo 'xyz' |./subx run apps/crenshaw2-1 + 22 # $ echo 'xyz' |./bootstrap run apps/crenshaw2-1 23 # Error: integer expected 24 # 25 # Names in this file sometimes follow Crenshaw's original rather than my usual diff --git a/html/apps/crenshaw2-1b.subx.html b/html/apps/crenshaw2-1b.subx.html index 01b29a6a..67c8891f 100644 --- a/html/apps/crenshaw2-1b.subx.html +++ b/html/apps/crenshaw2-1b.subx.html @@ -64,8 +64,8 @@ if ('onhashchange' in window) { 3 # except that we support hex numbers of multiple digits. 4 # 5 # To run: - 6 # $ ./subx translate init.linux 0*.subx apps/crenshaw2-1b.subx -o apps/crenshaw2-1b - 7 # $ echo '1a' |./subx run apps/crenshaw2-1b + 6 # $ ./bootstrap translate init.linux 0*.subx apps/crenshaw2-1b.subx -o apps/crenshaw2-1b + 7 # $ echo '1a' |./bootstrap run apps/crenshaw2-1b 8 # Expected output: 9 # # syscall(exit, 1a) 10 # bb/copy-to-ebx 3/imm32 @@ -73,14 +73,14 @@ if ('onhashchange' in window) { 12 # cd/syscall 0x80/imm8 13 # 14 # To run the generated output: - 15 # $ echo '1a' |./subx run apps/crenshaw2-1b > z1.subx - 16 # $ ./subx translate init.linux z1.subx -o z1 - 17 # $ ./subx run z1 + 15 # $ echo '1a' |./bootstrap run apps/crenshaw2-1b > z1.subx + 16 # $ ./bootstrap translate init.linux z1.subx -o z1 + 17 # $ ./bootstrap run z1 18 # $ echo $? 19 # 26 # 0x1a in decimal 20 # 21 # Stdin must contain just a single hex digit. Other input will print an error: - 22 # $ echo 'xyz' |./subx run apps/crenshaw2-1b + 22 # $ echo 'xyz' |./bootstrap run apps/crenshaw2-1b 23 # Error: integer expected 24 # 25 # Names in this file sometimes follow Crenshaw's original rather than my usual diff --git a/html/apps/dquotes.subx.html b/html/apps/dquotes.subx.html index 43be5025..1636fde6 100644 --- a/html/apps/dquotes.subx.html +++ b/html/apps/dquotes.subx.html @@ -65,11 +65,11 @@ if ('onhashchange' in window) { 2 # Replace them with references to new variables in the data segment. 3 # 4 # To run: - 5 # $ ./subx translate init.linux 0*.subx apps/subx-params.subx apps/dquotes.subx -o apps/dquotes + 5 # $ ./bootstrap translate init.linux 0*.subx apps/subx-params.subx apps/dquotes.subx -o apps/dquotes 6 # $ cat x 7 # == code 8 # ab "cd ef"/imm32 - 9 # $ cat x |./subx run apps/dquotes + 9 # $ cat x |./bootstrap run apps/dquotes 10 # == code 11 # ab __string1/imm32 12 # == data diff --git a/html/apps/ex1.subx.html b/html/apps/ex1.subx.html index 4cc9e90f..0d3311bc 100644 --- a/html/apps/ex1.subx.html +++ b/html/apps/ex1.subx.html @@ -57,8 +57,8 @@ if ('onhashchange' in window) { 2 # Just return 42. 3 # 4 # To run: - 5 # $ ./subx translate init.linux examples/ex1.2.subx -o examples/ex1 - 6 # $ ./subx run examples/ex1 + 5 # $ ./bootstrap translate init.linux apps/ex1.2.subx -o apps/ex1 + 6 # $ ./bootstrap run apps/ex1 7 # Expected result: 8 # $ echo $? 9 # 42 diff --git a/html/apps/ex10.subx.html b/html/apps/ex10.subx.html index a0a7fd11..ddfd8a6e 100644 --- a/html/apps/ex10.subx.html +++ b/html/apps/ex10.subx.html @@ -60,8 +60,8 @@ if ('onhashchange' in window) { 1 # String comparison: return 1 iff the two args passed in at the commandline are equal. 2 # 3 # To run: - 4 # $ ./subx translate init.linux examples/ex10.subx -o examples/ex10 - 5 # $ ./subx run examples/ex10 abc abd + 4 # $ ./bootstrap translate init.linux apps/ex10.subx -o apps/ex10 + 5 # $ ./bootstrap run apps/ex10 abc abd 6 # Expected result: 7 # $ echo $? 8 # 0 # false diff --git a/html/apps/ex11.subx.html b/html/apps/ex11.subx.html index 199ffcff..275a594b 100644 --- a/html/apps/ex11.subx.html +++ b/html/apps/ex11.subx.html @@ -68,8 +68,8 @@ if ('onhashchange' in window) { 6 # a null-terminated 'kernel string' with a length-prefixed 'SubX string'. 7 # 8 # To run: - 9 # $ ./subx translate init.linux examples/ex11.subx -o examples/ex11 - 10 # $ ./subx run examples/ex11 # runs a series of tests + 9 # $ ./bootstrap translate init.linux apps/ex11.subx -o apps/ex11 + 10 # $ ./bootstrap run apps/ex11 # runs a series of tests 11 # ...... # all tests pass 12 # 13 # (We can't yet run the tests when given a "test" commandline argument, diff --git a/html/apps/ex12.subx.html b/html/apps/ex12.subx.html index 221bec80..4f753e5c 100644 --- a/html/apps/ex12.subx.html +++ b/html/apps/ex12.subx.html @@ -59,8 +59,8 @@ if ('onhashchange' in window) { 2 # Create a new segment using mmap, save the address, write to it. 3 # 4 # To run: - 5 # $ ./subx translate init.linux examples/ex12.subx -o examples/ex12 - 6 # $ ./subx run examples/ex12 + 5 # $ ./bootstrap translate init.linux apps/ex12.subx -o apps/ex12 + 6 # $ ./bootstrap run apps/ex12 7 # You shouldn't get a segmentation fault. 8 9 == code diff --git a/html/apps/ex13.subx.html b/html/apps/ex13.subx.html new file mode 100644 index 00000000..d85c5166 --- /dev/null +++ b/html/apps/ex13.subx.html @@ -0,0 +1,87 @@ + + + + +Mu - apps/ex13.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/apps/ex13.subx +
+ 1 # Compare 3 and 3.
+ 2 #
+ 3 # To run:
+ 4 #   $ ./bootstrap translate init.linux apps/ex13.subx -o apps/ex13
+ 5 #   $ ./bootstrap run apps/ex13
+ 6 # Expected result:
+ 7 #   $ echo $?
+ 8 #   1
+ 9 
+10 == code
+11 #   instruction                     effective address                                                   register    displacement    immediate
+12 # . op          subop               mod             rm32          base        index         scale       r32
+13 # . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
+14 
+15 Entry:
+16     b8/copy-to-eax  3/imm32
+17     3d/compare-eax-and  3/imm32
+18     0f 94/set-if-=                  3/mod/direct    3/rm32/ebx    .           .             .           .           .               .                 # set ebx to ZF
+19     81 4/subop/and                  3/mod/direct    3/rm32/ebx    .           .             .           .           .               0xff/imm32        # AND eax with 0xff
+20 
+21 $exit:
+22     # exit(ebx)
+23     e8/call  syscall_exit/disp32
+24 
+25 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/apps/ex14.subx.html b/html/apps/ex14.subx.html new file mode 100644 index 00000000..ed5fa2ee --- /dev/null +++ b/html/apps/ex14.subx.html @@ -0,0 +1,88 @@ + + + + +Mu - apps/ex14.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/apps/ex14.subx +
+ 1 # Multiply 2 numbers.
+ 2 #
+ 3 # To run:
+ 4 #   $ ./bootstrap translate init.linux apps/ex14.subx -o apps/ex14
+ 5 #   $ ./bootstrap run apps/ex14
+ 6 # Expected result:
+ 7 #   $ echo $?
+ 8 #   6
+ 9 
+10 == code
+11 #   instruction                     effective address                                                   register    displacement    immediate
+12 # . op          subop               mod             rm32          base        index         scale       r32
+13 # . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
+14 
+15 Entry:
+16     b8/copy-to-eax  1/imm32
+17     b9/copy-to-ecx  2/imm32
+18     bb/copy-to-ebx  3/imm32
+19 
+20     69/multiply                     3/mod/direct    1/rm32/ecx    .           .             .           3/r32/ebx                   3/imm32           # ebx = ecx * 3
+21 
+22 $exit:
+23     # exit(ebx)
+24     e8/call  syscall_exit/disp32
+25 
+26 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/apps/ex2.subx.html b/html/apps/ex2.subx.html index f1e4abe9..392f5440 100644 --- a/html/apps/ex2.subx.html +++ b/html/apps/ex2.subx.html @@ -56,8 +56,8 @@ if ('onhashchange' in window) { 1 # Add 1 and 1, and return the result in the exit code. 2 # 3 # To run: - 4 # $ ./subx translate init.linux examples/ex2.subx -o examples/ex2 - 5 # $ ./subx run examples/ex2 + 4 # $ ./bootstrap translate init.linux apps/ex2.subx -o apps/ex2 + 5 # $ ./bootstrap run apps/ex2 6 # Expected result: 7 # $ echo $? 8 # 2 diff --git a/html/apps/ex3.subx.html b/html/apps/ex3.subx.html index 31ff11a1..e267f0fe 100644 --- a/html/apps/ex3.subx.html +++ b/html/apps/ex3.subx.html @@ -59,8 +59,8 @@ if ('onhashchange' in window) { 1 # Add the first 10 numbers, and return the result in the exit code. 2 # 3 # To run: - 4 # $ ./subx translate init.linux examples/ex3.subx -o examples/ex3 - 5 # $ ./subx run examples/ex3 + 4 # $ ./bootstrap translate init.linux apps/ex3.subx -o apps/ex3 + 5 # $ ./bootstrap run apps/ex3 6 # Expected result: 7 # $ echo $? 8 # 55 diff --git a/html/apps/ex4.subx.html b/html/apps/ex4.subx.html index b1e1019b..297576bb 100644 --- a/html/apps/ex4.subx.html +++ b/html/apps/ex4.subx.html @@ -57,8 +57,8 @@ if ('onhashchange' in window) { 1 # Read a character from stdin, save it to a global, write it to stdout. 2 # 3 # To run: - 4 # $ ./subx translate init.linux examples/ex4.subx -o examples/ex4 - 5 # $ ./subx run examples/ex4 + 4 # $ ./bootstrap translate init.linux apps/ex4.subx -o apps/ex4 + 5 # $ ./bootstrap run apps/ex4 6 7 == data 8 diff --git a/html/apps/ex5.subx.html b/html/apps/ex5.subx.html index 26c5700b..c403dcae 100644 --- a/html/apps/ex5.subx.html +++ b/html/apps/ex5.subx.html @@ -58,8 +58,8 @@ if ('onhashchange' in window) { 1 # Read a character from stdin, save it to a local on the stack, write it to stdout. 2 # 3 # To run: - 4 # $ ./subx translate init.linux examples/ex5.subx -o examples/ex5 - 5 # $ ./subx run examples/ex5 + 4 # $ ./bootstrap translate init.linux apps/ex5.subx -o apps/ex5 + 5 # $ ./bootstrap run apps/ex5 6 7 == code 8 # instruction effective address register displacement immediate diff --git a/html/apps/ex6.subx.html b/html/apps/ex6.subx.html index e8f7dbe4..ba8a4037 100644 --- a/html/apps/ex6.subx.html +++ b/html/apps/ex6.subx.html @@ -58,8 +58,8 @@ if ('onhashchange' in window) { 1 # Print out a (global variable) string to stdout. 2 # 3 # To run: - 4 # $ ./subx translate init.linux examples/ex6.subx -o examples/ex6 - 5 # $ ./subx run examples/ex6 + 4 # $ ./bootstrap translate init.linux apps/ex6.subx -o apps/ex6 + 5 # $ ./bootstrap run apps/ex6 6 # Hello, world! 7 8 == code diff --git a/html/apps/ex7.subx.html b/html/apps/ex7.subx.html index 617c44c2..76a1de01 100644 --- a/html/apps/ex7.subx.html +++ b/html/apps/ex7.subx.html @@ -62,8 +62,8 @@ if ('onhashchange' in window) { 5 # the character read. 6 # 7 # To run: - 8 # $ ./subx translate init.linux examples/ex7.subx -o examples/ex7 - 9 # $ ./subx run examples/ex7 + 8 # $ ./bootstrap translate init.linux apps/ex7.subx -o apps/ex7 + 9 # $ ./bootstrap run apps/ex7 10 # Expected result: 11 # $ echo $? 12 # 97 diff --git a/html/apps/ex8.subx.html b/html/apps/ex8.subx.html index 8cf64378..a6458493 100644 --- a/html/apps/ex8.subx.html +++ b/html/apps/ex8.subx.html @@ -60,8 +60,8 @@ if ('onhashchange' in window) { 1 # Example reading commandline arguments: compute length of first arg. 2 # 3 # To run: - 4 # $ ./subx translate init.linux examples/ex8.subx -o examples/ex8 - 5 # $ ./subx run examples/ex8 abc de fghi + 4 # $ ./bootstrap translate init.linux apps/ex8.subx -o apps/ex8 + 5 # $ ./bootstrap run apps/ex8 abc de fghi 6 # Expected result: 7 # $ echo $? 8 # 3 # length of 'abc' diff --git a/html/apps/ex9.subx.html b/html/apps/ex9.subx.html index 3558ac1c..4ac15f83 100644 --- a/html/apps/ex9.subx.html +++ b/html/apps/ex9.subx.html @@ -62,8 +62,8 @@ if ('onhashchange' in window) { 4 # letter of second arg. 5 # 6 # To run: - 7 # $ ./subx translate init.linux examples/ex9.subx -o examples/ex9 - 8 # $ ./subx run examples/ex9 z x + 7 # $ ./bootstrap translate init.linux apps/ex9.subx -o apps/ex9 + 8 # $ ./bootstrap run apps/ex9 z x 9 # Expected result: 10 # $ echo $? 11 # 2 diff --git a/html/apps/factorial.subx.html b/html/apps/factorial.subx.html index 8c637957..bbd42944 100644 --- a/html/apps/factorial.subx.html +++ b/html/apps/factorial.subx.html @@ -62,14 +62,14 @@ if ('onhashchange' in window) { 1 ## compute the factorial of 5, and return the result in the exit code 2 # 3 # To run: - 4 # $ ./subx translate init.linux 0*.subx apps/factorial.subx -o apps/factorial - 5 # $ ./subx run apps/factorial + 4 # $ ./bootstrap translate init.linux 0*.subx apps/factorial.subx -o apps/factorial + 5 # $ ./bootstrap run apps/factorial 6 # Expected result: 7 # $ echo $? 8 # 120 9 # 10 # You can also run the automated test suite: - 11 # $ ./subx run apps/factorial test + 11 # $ ./bootstrap run apps/factorial test 12 # Expected output: 13 # ........ 14 # Every '.' indicates a passing test. Failing tests get a 'F'. diff --git a/html/apps/factorial2.subx.html b/html/apps/factorial2.subx.html index 4d59c774..4e09dcf6 100644 --- a/html/apps/factorial2.subx.html +++ b/html/apps/factorial2.subx.html @@ -65,13 +65,13 @@ if ('onhashchange' in window) { 5 # 6 # To run: 7 # $ ./translate_subx init.linux 0*.subx apps/factorial.subx -o apps/factorial - 8 # $ ./subx run apps/factorial + 8 # $ ./bootstrap run apps/factorial 9 # Expected result: 10 # $ echo $? 11 # 120 12 # 13 # You can also run the automated test suite: - 14 # $ ./subx run apps/factorial test + 14 # $ ./bootstrap run apps/factorial test 15 # Expected output: 16 # ........ 17 # Every '.' indicates a passing test. Failing tests get a 'F'. diff --git a/html/apps/factorial3.subx.html b/html/apps/factorial3.subx.html index 7ad4a9fd..10792365 100644 --- a/html/apps/factorial3.subx.html +++ b/html/apps/factorial3.subx.html @@ -65,13 +65,13 @@ if ('onhashchange' in window) { 6 # 7 # To run: 8 # $ ./translate_subx init.linux 0*.subx apps/factorial.subx -o apps/factorial - 9 # $ ./subx run apps/factorial + 9 # $ ./bootstrap run apps/factorial 10 # Expected result: 11 # $ echo $? 12 # 120 13 # 14 # You can also run the automated test suite: -15 # $ ./subx run apps/factorial test +15 # $ ./bootstrap run apps/factorial test 16 # Expected output: 17 # ........ 18 # Every '.' indicates a passing test. Failing tests get a 'F'. diff --git a/html/apps/factorial4.subx.html b/html/apps/factorial4.subx.html index 8759c2f9..bd41739e 100644 --- a/html/apps/factorial4.subx.html +++ b/html/apps/factorial4.subx.html @@ -66,13 +66,13 @@ if ('onhashchange' in window) { 7 # 8 # To run: 9 # $ ./translate_subx init.linux 0*.subx apps/factorial.subx -o apps/factorial -10 # $ ./subx run apps/factorial +10 # $ ./bootstrap run apps/factorial 11 # Expected result: 12 # $ echo $? 13 # 120 14 # 15 # You can also run the automated test suite: -16 # $ ./subx run apps/factorial test +16 # $ ./bootstrap run apps/factorial test 17 # Expected output: 18 # ........ 19 # Every '.' indicates a passing test. Failing tests get a 'F'. diff --git a/html/apps/handle.subx.html b/html/apps/handle.subx.html index fc0ce1a8..9cf47d93 100644 --- a/html/apps/handle.subx.html +++ b/html/apps/handle.subx.html @@ -76,8 +76,8 @@ if ('onhashchange' in window) { 13 # offset 4: address 14 # 15 # To run: - 16 # $ ./subx translate init.linux 0*.subx apps/handle.subx -o apps/handle - 17 # $ ./subx run apps/handle + 16 # $ ./bootstrap translate init.linux 0*.subx apps/handle.subx -o apps/handle + 17 # $ ./bootstrap run apps/handle 18 # Expected result is a successful lookup followed by a hard abort: 19 # lookup succeeded 20 # lookup failed diff --git a/html/apps/hex.subx.html b/html/apps/hex.subx.html index 4018c82f..936a37e5 100644 --- a/html/apps/hex.subx.html +++ b/html/apps/hex.subx.html @@ -64,8 +64,8 @@ if ('onhashchange' in window) { 3 # comments between '#' and newline. 4 # 5 # To run: - 6 # $ ./subx translate init.linux 0*.subx apps/subx-params.subx apps/hex.subx -o apps/hex - 7 # $ echo '80 81 82 # comment' |./subx run apps/hex |xxd - + 6 # $ ./bootstrap translate init.linux 0*.subx apps/subx-params.subx apps/hex.subx -o apps/hex + 7 # $ echo '80 81 82 # comment' |./bootstrap run apps/hex |xxd - 8 # Expected output: 9 # 00000000: 8081 82 10 # @@ -225,7 +225,7 @@ if ('onhashchange' in window) { 164 3d/compare-eax-and 0xffffffff/imm32/Eof 165 74/jump-if-= $convert-next-octet:end/disp8 166 # eax = from-hex-char(eax) - 167 e8/call from-hex-char/disp32 + 167 e8/call from-hex-char/disp32 168 # ecx = eax 169 89/copy 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # copy eax to ecx 170 # eax = scan-next-byte(in, err, ed) @@ -250,7 +250,7 @@ if ('onhashchange' in window) { 189 e8/call error-byte/disp32 # never returns 190 $convert-next-octet:convert: 191 # eax = from-hex-char(eax) - 192 e8/call from-hex-char/disp32 + 192 e8/call from-hex-char/disp32 193 # eax = (ecx << 4) | eax 194 # . ecx <<= 4 195 c1/shift 4/subop/left 3/mod/direct 1/rm32/ecx . . . . . 4/imm8 # shift ecx left by 4 bits @@ -574,7 +574,7 @@ if ('onhashchange' in window) { 513 # . . push args 514 50/push-eax 515 # . . call - 516 e8/call is-hex-digit?/disp32 + 516 e8/call is-hex-digit?/disp32 517 # . . discard args 518 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 519 # . compare with 'false' diff --git a/html/apps/mu.subx.html b/html/apps/mu.subx.html index e79d755b..cb40e41c 100644 --- a/html/apps/mu.subx.html +++ b/html/apps/mu.subx.html @@ -5705,9 +5705,9 @@ if ('onhashchange' in window) { 5848 # Important: each block's depth during code-generation should be identical 5849 # to what it was during parsing. 5850 c7 0/subop/copy *Curr-block-depth 1/imm32 - 5851 (emit-subx-prologue %edi) - 5852 (emit-subx-block %edi *(ecx+0x10) %edx) # Function-body - 5853 (emit-subx-epilogue %edi) + 5851 (emit-subx-prologue %edi) + 5852 (emit-subx-block %edi *(ecx+0x10) %edx) # Function-body + 5853 (emit-subx-epilogue %edi) 5854 $emit-subx-function:end: 5855 # . reclaim locals 5856 81 0/subop/add %esp 408/imm32 @@ -5747,7 +5747,7 @@ if ('onhashchange' in window) { 5890 81 7/subop/compare *ecx 0/imm32/block # Stmt-tag 5891 75/jump-if-!= break/disp8 5892 $emit-subx-stmt-list:block: - 5893 (emit-subx-block *(ebp+8) %ecx *(ebp+0x10)) + 5893 (emit-subx-block *(ebp+8) %ecx *(ebp+0x10)) 5894 } 5895 { 5896 $emit-subx-stmt-list:check-for-stmt: @@ -5769,7 +5769,7 @@ if ('onhashchange' in window) { 5987 +-- 19 lines: # conditional branches with an explicit target ---------------------------------------------------------------------------------------------------------------------------- 6006 } 6007 $emit-subx-stmt-list:1-to-1: - 6008 (emit-subx-stmt *(ebp+8) %ecx Primitives *_Program-functions) + 6008 (emit-subx-stmt *(ebp+8) %ecx Primitives *_Program-functions) 6009 } 6010 { 6011 $emit-subx-stmt-list:check-for-var-def: @@ -5791,7 +5791,7 @@ if ('onhashchange' in window) { 6027 # register variable definition 6028 (push *(ebp+0x10) %eax) 6029 # emit the instruction as usual - 6030 (emit-subx-stmt *(ebp+8) %ecx Primitives *_Program-functions) + 6030 (emit-subx-stmt *(ebp+8) %ecx Primitives *_Program-functions) 6031 # var-seen? = true 6032 ba/copy-to-edx 1/imm32/true 6033 } @@ -5837,7 +5837,7 @@ if ('onhashchange' in window) { 6073 3d/compare-eax-and 0/imm32/false 6074 75/jump-if-!= $compute-reg-and-maybe-emit-spill:end/disp8 6075 # emit spill - 6076 (emit-indent *(ebp+8) *Curr-block-depth) + 6076 (emit-indent *(ebp+8) *Curr-block-depth) 6077 (write-buffered *(ebp+8) "ff 6/subop/push %") 6078 (write-buffered *(ebp+8) *(ecx+0x10)) # Var-register 6079 (write-buffered *(ebp+8) Newline) @@ -5880,7 +5880,7 @@ if ('onhashchange' in window) { 6116 # clean up until target block 6117 (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %edx) 6118 # emit jump to target block - 6119 (emit-indent *(ebp+8) *Curr-block-depth) + 6119 (emit-indent *(ebp+8) *Curr-block-depth) 6120 (write-buffered *(ebp+8) "e9/jump ") 6121 (write-buffered *(ebp+8) %edx) 6122 (string-starts-with? *(ecx+4) "break") @@ -5936,7 +5936,7 @@ if ('onhashchange' in window) { 6172 8b/-> *(ebp+0xc) 0/r32/eax 6173 # 6174 (get Reverse-branch *(eax+4) 8 "reverse-branch: ") # Stmt1-operation => eax: (addr addr array byte) - 6175 (emit-indent *(ebp+8) *Curr-block-depth) + 6175 (emit-indent *(ebp+8) *Curr-block-depth) 6176 (write-buffered *(ebp+8) *eax) 6177 (write-buffered *(ebp+8) " break/disp32\n") 6178 $emit-reverse-break:end: @@ -6025,7 +6025,7 @@ if ('onhashchange' in window) { 6261 0f 85/jump-if-!= break/disp32 6262 $emit-unconditional-jump-to-depth:label-found: 6263 # emit unconditional jump, then return - 6264 (emit-indent *(ebp+8) *Curr-block-depth) + 6264 (emit-indent *(ebp+8) *Curr-block-depth) 6265 (write-buffered *(ebp+8) "e9/jump ") 6266 (write-buffered *(ebp+8) *ebx) # Var-name 6267 (write-buffered *(ebp+8) ":") @@ -6092,7 +6092,7 @@ if ('onhashchange' in window) { 6328 3d/compare-eax-and 0/imm32/false 6329 0f 85/jump-if-!= break/disp32 6330 $emit-cleanup-code-until-depth:reclaim-var-in-register: - 6331 (emit-indent *(ebp+8) *Curr-block-depth) + 6331 (emit-indent *(ebp+8) *Curr-block-depth) 6332 (write-buffered *(ebp+8) "8f 0/subop/pop %") 6333 (write-buffered *(ebp+8) *(ebx+0x10)) 6334 (write-buffered *(ebp+8) Newline) @@ -6110,7 +6110,7 @@ if ('onhashchange' in window) { 6346 3d/compare-eax-and 0/imm32 6347 74/jump-if-= break/disp8 6348 # - 6349 (emit-indent *(ebp+8) *Curr-block-depth) + 6349 (emit-indent *(ebp+8) *Curr-block-depth) 6350 (write-buffered *(ebp+8) "81 0/subop/add %esp ") 6351 (print-int32-buffered *(ebp+8) %eax) 6352 (write-buffered *(ebp+8) "/imm32\n") @@ -6174,7 +6174,7 @@ if ('onhashchange' in window) { 6410 3d/compare-eax-and 0/imm32/false 6411 75/jump-if-!= break/disp8 6412 $emit-cleanup-code-until-target:reclaim-var-in-register: - 6413 (emit-indent *(ebp+8) *Curr-block-depth) + 6413 (emit-indent *(ebp+8) *Curr-block-depth) 6414 (write-buffered *(ebp+8) "8f 0/subop/pop %") 6415 (write-buffered *(ebp+8) *(ebx+0x10)) 6416 (write-buffered *(ebp+8) Newline) @@ -6191,7 +6191,7 @@ if ('onhashchange' in window) { 6427 3d/compare-eax-and 0/imm32 6428 74/jump-if-= break/disp8 6429 # - 6430 (emit-indent *(ebp+8) *Curr-block-depth) + 6430 (emit-indent *(ebp+8) *Curr-block-depth) 6431 (write-buffered *(ebp+8) "81 0/subop/add %esp ") 6432 (print-int32-buffered *(ebp+8) %eax) 6433 (write-buffered *(ebp+8) "/imm32\n") @@ -6404,7 +6404,7 @@ if ('onhashchange' in window) { 6640 { 6641 3d/compare-eax-with 0/imm32 6642 7e/jump-if-<= break/disp8 - 6643 (emit-indent *(ebp+8) *Curr-block-depth) + 6643 (emit-indent *(ebp+8) *Curr-block-depth) 6644 (write-buffered *(ebp+8) "68/push 0/imm32\n") 6645 # n -= 4 6646 2d/subtract-from-eax 4/imm32 @@ -6438,25 +6438,25 @@ if ('onhashchange' in window) { 6795 # if stmt matches a primitive, emit it 6796 { 6797 $emit-subx-stmt:check-for-primitive: - 6798 (find-matching-primitive *(ebp+0x10) *(ebp+0xc)) # primitives, stmt => curr/eax + 6798 (find-matching-primitive *(ebp+0x10) *(ebp+0xc)) # primitives, stmt => curr/eax 6799 3d/compare-eax-and 0/imm32 6800 74/jump-if-= break/disp8 6801 $emit-subx-stmt:primitive: - 6802 (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr + 6802 (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr 6803 e9/jump $emit-subx-stmt:end/disp32 6804 } 6805 # else if stmt matches a function, emit a call to it 6806 { 6807 $emit-subx-stmt:check-for-call: - 6808 (find-matching-function *(ebp+0x14) *(ebp+0xc)) # functions, stmt => curr/eax + 6808 (find-matching-function *(ebp+0x14) *(ebp+0xc)) # functions, stmt => curr/eax 6809 3d/compare-eax-and 0/imm32 6810 74/jump-if-= break/disp8 6811 $emit-subx-stmt:call: - 6812 (emit-subx-call *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr + 6812 (emit-subx-call *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr 6813 e9/jump $emit-subx-stmt:end/disp32 6814 } 6815 # else assume it's a SubX function (TODO: how to type-check?!) - 6816 (emit-hailmary-call *(ebp+8) *(ebp+0xc)) + 6816 (emit-hailmary-call *(ebp+8) *(ebp+0xc)) 6817 $emit-subx-stmt:end: 6818 # . restore registers 6819 5b/pop-to-ebx @@ -6510,3539 +6510,3527 @@ if ('onhashchange' in window) { 6867 48/decrement-eax 6868 # var tmp2/eax: int = n & tmp 6869 0b/and-> *(ebp+8) 0/r32/eax - 6870 # return (tmp2 == 0) # TODO: replace with setcc + 6870 # return (tmp2 == 0) 6871 3d/compare-eax-and 0/imm32 - 6872 74/jump-if-= $power-of-2?:true/disp8 - 6873 $power-of-2?:false: - 6874 b8/copy-to-eax 0/imm32/false - 6875 eb/jump $power-of-2?:end/disp8 - 6876 $power-of-2?:true: - 6877 b8/copy-to-eax 1/imm32/true - 6878 $power-of-2?:end: - 6879 # . epilogue - 6880 89/<- %esp 5/r32/ebp - 6881 5d/pop-to-ebp - 6882 c3/return - 6883 - 6884 num-shift-rights: # n: int -> result/eax: int - 6885 # precondition: n is a positive power of 2 - 6886 # . prologue - 6887 55/push-ebp - 6888 89/<- %ebp 4/r32/esp - 6889 # . save registers - 6890 51/push-ecx - 6891 # var curr/ecx: int = n - 6892 8b/-> *(ebp+8) 1/r32/ecx - 6893 # result = 0 - 6894 b8/copy-to-eax 0/imm32 - 6895 { - 6896 # if (curr <= 1) break - 6897 81 7/subop/compare %ecx 1/imm32 - 6898 7e/jump-if-<= break/disp8 - 6899 40/increment-eax - 6900 c1/shift 5/subop/arithmetic-right %ecx 1/imm8 - 6901 eb/jump loop/disp8 - 6902 } - 6903 $num-shift-rights:end: - 6904 # . restore registers - 6905 59/pop-to-ecx - 6906 # . epilogue - 6907 89/<- %esp 5/r32/ebp - 6908 5d/pop-to-ebp - 6909 c3/return - 6910 - 6911 print-mu-get-offset: # out: (addr buffered-file), stmt: (handle stmt) - 6912 # . prologue - 6913 55/push-ebp - 6914 89/<- %ebp 4/r32/esp - 6915 # . save registers - 6916 50/push-eax - 6917 # var second-inout/eax: (handle stmt-var) = stmt->inouts->next - 6918 8b/-> *(ebp+0xc) 0/r32/eax - 6919 8b/-> *(eax+8) 0/r32/eax # Stmt1-inouts - 6920 8b/-> *(eax+4) 0/r32/eax # Stmt-var-next - 6921 # var output-var/eax: (handle var) = second-inout->value - 6922 8b/-> *eax 0/r32/eax # Stmt-var-value - 6923 # print offset - 6924 #? (write-buffered Stderr "emitting offset from output var ") - 6925 #? (print-int32-buffered Stderr %eax) - 6926 #? (write-buffered Stderr Newline) - 6927 #? (flush Stderr) - 6928 (print-int32-buffered *(ebp+8) *(eax+0xc)) # Var-offset - 6929 $emit-get-offset:end: - 6930 # . restore registers - 6931 58/pop-to-eax - 6932 # . epilogue - 6933 89/<- %esp 5/r32/ebp - 6934 5d/pop-to-ebp - 6935 c3/return - 6936 - 6937 emit-subx-block: # out: (addr buffered-file), block: (handle block), vars: (addr stack (handle var)) - 6938 # . prologue - 6939 55/push-ebp - 6940 89/<- %ebp 4/r32/esp - 6941 # . save registers - 6942 50/push-eax - 6943 51/push-ecx - 6944 56/push-esi - 6945 # esi = block - 6946 8b/-> *(ebp+0xc) 6/r32/esi - 6947 # var stmts/eax: (handle list stmt) = block->statements - 6948 8b/-> *(esi+4) 0/r32/eax # Block-stmts - 6949 # - 6950 { - 6951 $emit-subx-block:check-empty: - 6952 3d/compare-eax-and 0/imm32 - 6953 0f 84/jump-if-= break/disp32 - 6954 (emit-indent *(ebp+8) *Curr-block-depth) - 6955 (write-buffered *(ebp+8) "{\n") - 6956 # var v/ecx: (addr array byte) = block->var->name - 6957 8b/-> *(esi+8) 1/r32/ecx # Block-var - 6958 (write-buffered *(ebp+8) *ecx) # Var-name - 6959 (write-buffered *(ebp+8) ":loop:\n") - 6960 ff 0/subop/increment *Curr-block-depth - 6961 (push *(ebp+0x10) %ecx) - 6962 (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10)) - 6963 (pop *(ebp+0x10)) # => eax - 6964 ff 1/subop/decrement *Curr-block-depth - 6965 (emit-indent *(ebp+8) *Curr-block-depth) - 6966 (write-buffered *(ebp+8) "}\n") - 6967 (write-buffered *(ebp+8) *ecx) # Var-name - 6968 (write-buffered *(ebp+8) ":break:\n") - 6969 } - 6970 $emit-subx-block:end: - 6971 # . restore registers - 6972 5e/pop-to-esi - 6973 59/pop-to-ecx - 6974 58/pop-to-eax - 6975 # . epilogue - 6976 89/<- %esp 5/r32/ebp - 6977 5d/pop-to-ebp - 6978 c3/return - 6979 - 6980 # Primitives supported - 6981 # For each operation, put variants with hard-coded registers before flexible ones. - 6982 == data - 6983 Primitives: - 6984 # - increment/decrement - 6985 _Primitive-inc-eax: - 6986 # var/eax <- increment => 40/increment-eax - 6987 "increment"/imm32/name - 6988 0/imm32/no-inouts - 6989 Single-int-var-in-eax/imm32/outputs - 6990 "40/increment-eax"/imm32/subx-name - 6991 0/imm32/no-rm32 - 6992 0/imm32/no-r32 - 6993 0/imm32/no-imm32 - 6994 0/imm32/no-disp32 - 6995 0/imm32/output-is-write-only - 6996 _Primitive-inc-ecx/imm32/next - 6997 _Primitive-inc-ecx: - 6998 # var/ecx <- increment => 41/increment-ecx - 6999 "increment"/imm32/name - 7000 0/imm32/no-inouts - 7001 Single-int-var-in-ecx/imm32/outputs - 7002 "41/increment-ecx"/imm32/subx-name - 7003 0/imm32/no-rm32 - 7004 0/imm32/no-r32 - 7005 0/imm32/no-imm32 - 7006 0/imm32/no-disp32 - 7007 0/imm32/output-is-write-only - 7008 _Primitive-inc-edx/imm32/next - 7009 _Primitive-inc-edx: - 7010 # var/edx <- increment => 42/increment-edx - 7011 "increment"/imm32/name - 7012 0/imm32/no-inouts - 7013 Single-int-var-in-edx/imm32/outputs - 7014 "42/increment-edx"/imm32/subx-name - 7015 0/imm32/no-rm32 - 7016 0/imm32/no-r32 - 7017 0/imm32/no-imm32 - 7018 0/imm32/no-disp32 - 7019 0/imm32/output-is-write-only - 7020 _Primitive-inc-ebx/imm32/next - 7021 _Primitive-inc-ebx: - 7022 # var/ebx <- increment => 43/increment-ebx - 7023 "increment"/imm32/name - 7024 0/imm32/no-inouts - 7025 Single-int-var-in-ebx/imm32/outputs - 7026 "43/increment-ebx"/imm32/subx-name - 7027 0/imm32/no-rm32 - 7028 0/imm32/no-r32 - 7029 0/imm32/no-imm32 - 7030 0/imm32/no-disp32 - 7031 0/imm32/output-is-write-only - 7032 _Primitive-inc-esi/imm32/next - 7033 _Primitive-inc-esi: - 7034 # var/esi <- increment => 46/increment-esi - 7035 "increment"/imm32/name - 7036 0/imm32/no-inouts - 7037 Single-int-var-in-esi/imm32/outputs - 7038 "46/increment-esi"/imm32/subx-name - 7039 0/imm32/no-rm32 - 7040 0/imm32/no-r32 - 7041 0/imm32/no-imm32 - 7042 0/imm32/no-disp32 - 7043 0/imm32/output-is-write-only - 7044 _Primitive-inc-edi/imm32/next - 7045 _Primitive-inc-edi: - 7046 # var/edi <- increment => 47/increment-edi - 7047 "increment"/imm32/name - 7048 0/imm32/no-inouts - 7049 Single-int-var-in-edi/imm32/outputs - 7050 "47/increment-edi"/imm32/subx-name - 7051 0/imm32/no-rm32 - 7052 0/imm32/no-r32 - 7053 0/imm32/no-imm32 - 7054 0/imm32/no-disp32 - 7055 0/imm32/output-is-write-only - 7056 _Primitive-dec-eax/imm32/next - 7057 _Primitive-dec-eax: - 7058 # var/eax <- decrement => 48/decrement-eax - 7059 "decrement"/imm32/name - 7060 0/imm32/no-inouts - 7061 Single-int-var-in-eax/imm32/outputs - 7062 "48/decrement-eax"/imm32/subx-name - 7063 0/imm32/no-rm32 - 7064 0/imm32/no-r32 - 7065 0/imm32/no-imm32 - 7066 0/imm32/no-disp32 - 7067 0/imm32/output-is-write-only - 7068 _Primitive-dec-ecx/imm32/next - 7069 _Primitive-dec-ecx: - 7070 # var/ecx <- decrement => 49/decrement-ecx - 7071 "decrement"/imm32/name - 7072 0/imm32/no-inouts - 7073 Single-int-var-in-ecx/imm32/outputs - 7074 "49/decrement-ecx"/imm32/subx-name - 7075 0/imm32/no-rm32 - 7076 0/imm32/no-r32 - 7077 0/imm32/no-imm32 - 7078 0/imm32/no-disp32 - 7079 0/imm32/output-is-write-only - 7080 _Primitive-dec-edx/imm32/next - 7081 _Primitive-dec-edx: - 7082 # var/edx <- decrement => 4a/decrement-edx - 7083 "decrement"/imm32/name - 7084 0/imm32/no-inouts - 7085 Single-int-var-in-edx/imm32/outputs - 7086 "4a/decrement-edx"/imm32/subx-name - 7087 0/imm32/no-rm32 - 7088 0/imm32/no-r32 - 7089 0/imm32/no-imm32 - 7090 0/imm32/no-disp32 - 7091 0/imm32/output-is-write-only - 7092 _Primitive-dec-ebx/imm32/next - 7093 _Primitive-dec-ebx: - 7094 # var/ebx <- decrement => 4b/decrement-ebx - 7095 "decrement"/imm32/name - 7096 0/imm32/no-inouts - 7097 Single-int-var-in-ebx/imm32/outputs - 7098 "4b/decrement-ebx"/imm32/subx-name - 7099 0/imm32/no-rm32 - 7100 0/imm32/no-r32 - 7101 0/imm32/no-imm32 - 7102 0/imm32/no-disp32 - 7103 0/imm32/output-is-write-only - 7104 _Primitive-dec-esi/imm32/next - 7105 _Primitive-dec-esi: - 7106 # var/esi <- decrement => 4e/decrement-esi - 7107 "decrement"/imm32/name - 7108 0/imm32/no-inouts - 7109 Single-int-var-in-esi/imm32/outputs - 7110 "4e/decrement-esi"/imm32/subx-name - 7111 0/imm32/no-rm32 - 7112 0/imm32/no-r32 - 7113 0/imm32/no-imm32 - 7114 0/imm32/no-disp32 - 7115 0/imm32/output-is-write-only - 7116 _Primitive-dec-edi/imm32/next - 7117 _Primitive-dec-edi: - 7118 # var/edi <- decrement => 4f/decrement-edi - 7119 "decrement"/imm32/name - 7120 0/imm32/no-inouts - 7121 Single-int-var-in-edi/imm32/outputs - 7122 "4f/decrement-edi"/imm32/subx-name - 7123 0/imm32/no-rm32 - 7124 0/imm32/no-r32 - 7125 0/imm32/no-imm32 - 7126 0/imm32/no-disp32 - 7127 0/imm32/output-is-write-only - 7128 _Primitive-inc-mem/imm32/next - 7129 _Primitive-inc-mem: - 7130 # increment var => ff 0/subop/increment *(ebp+__) - 7131 "increment"/imm32/name - 7132 Single-int-var-in-mem/imm32/inouts - 7133 0/imm32/no-outputs - 7134 "ff 0/subop/increment"/imm32/subx-name - 7135 1/imm32/rm32-is-first-inout - 7136 0/imm32/no-r32 - 7137 0/imm32/no-imm32 - 7138 0/imm32/no-disp32 - 7139 0/imm32/output-is-write-only - 7140 _Primitive-inc-reg/imm32/next - 7141 _Primitive-inc-reg: - 7142 # var/reg <- increment => ff 0/subop/increment %__ - 7143 "increment"/imm32/name - 7144 0/imm32/no-inouts - 7145 Single-int-var-in-some-register/imm32/outputs - 7146 "ff 0/subop/increment"/imm32/subx-name - 7147 3/imm32/rm32-is-first-output - 7148 0/imm32/no-r32 - 7149 0/imm32/no-imm32 - 7150 0/imm32/no-disp32 - 7151 0/imm32/output-is-write-only - 7152 _Primitive-dec-mem/imm32/next - 7153 _Primitive-dec-mem: - 7154 # decrement var => ff 1/subop/decrement *(ebp+__) - 7155 "decrement"/imm32/name - 7156 Single-int-var-in-mem/imm32/inouts - 7157 0/imm32/no-outputs - 7158 "ff 1/subop/decrement"/imm32/subx-name - 7159 1/imm32/rm32-is-first-inout - 7160 0/imm32/no-r32 - 7161 0/imm32/no-imm32 - 7162 0/imm32/no-disp32 - 7163 0/imm32/output-is-write-only - 7164 _Primitive-dec-reg/imm32/next - 7165 _Primitive-dec-reg: - 7166 # var/reg <- decrement => ff 1/subop/decrement %__ - 7167 "decrement"/imm32/name - 7168 0/imm32/no-inouts - 7169 Single-int-var-in-some-register/imm32/outputs - 7170 "ff 1/subop/decrement"/imm32/subx-name - 7171 3/imm32/rm32-is-first-output - 7172 0/imm32/no-r32 - 7173 0/imm32/no-imm32 - 7174 0/imm32/no-disp32 - 7175 0/imm32/output-is-write-only - 7176 _Primitive-add-to-eax/imm32/next - 7177 # - add - 7178 _Primitive-add-to-eax: - 7179 # var/eax <- add lit => 05/add-to-eax lit/imm32 - 7180 "add"/imm32/name - 7181 Single-lit-var/imm32/inouts - 7182 Single-int-var-in-eax/imm32/outputs - 7183 "05/add-to-eax"/imm32/subx-name - 7184 0/imm32/no-rm32 - 7185 0/imm32/no-r32 - 7186 1/imm32/imm32-is-first-inout - 7187 0/imm32/no-disp32 - 7188 0/imm32/output-is-write-only - 7189 _Primitive-add-reg-to-reg/imm32/next - 7190 _Primitive-add-reg-to-reg: - 7191 # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32 - 7192 "add"/imm32/name - 7193 Single-int-var-in-some-register/imm32/inouts - 7194 Single-int-var-in-some-register/imm32/outputs - 7195 "01/add-to"/imm32/subx-name - 7196 3/imm32/rm32-is-first-output - 7197 1/imm32/r32-is-first-inout - 7198 0/imm32/no-imm32 - 7199 0/imm32/no-disp32 - 7200 0/imm32/output-is-write-only - 7201 _Primitive-add-reg-to-mem/imm32/next - 7202 _Primitive-add-reg-to-mem: - 7203 # add-to var1 var2/reg => 01/add-to var1 var2/r32 - 7204 "add-to"/imm32/name - 7205 Two-args-int-stack-int-reg/imm32/inouts - 7206 0/imm32/outputs - 7207 "01/add-to"/imm32/subx-name - 7208 1/imm32/rm32-is-first-inout - 7209 2/imm32/r32-is-second-inout - 7210 0/imm32/no-imm32 - 7211 0/imm32/no-disp32 - 7212 0/imm32/output-is-write-only - 7213 _Primitive-add-mem-to-reg/imm32/next - 7214 _Primitive-add-mem-to-reg: - 7215 # var1/reg <- add var2 => 03/add var2/rm32 var1/r32 - 7216 "add"/imm32/name - 7217 Single-int-var-in-mem/imm32/inouts - 7218 Single-int-var-in-some-register/imm32/outputs - 7219 "03/add"/imm32/subx-name - 7220 1/imm32/rm32-is-first-inout - 7221 3/imm32/r32-is-first-output - 7222 0/imm32/no-imm32 - 7223 0/imm32/no-disp32 - 7224 0/imm32/output-is-write-only - 7225 _Primitive-add-lit-to-reg/imm32/next - 7226 _Primitive-add-lit-to-reg: - 7227 # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32 - 7228 "add"/imm32/name - 7229 Single-lit-var/imm32/inouts - 7230 Single-int-var-in-some-register/imm32/outputs - 7231 "81 0/subop/add"/imm32/subx-name - 7232 3/imm32/rm32-is-first-output - 7233 0/imm32/no-r32 - 7234 1/imm32/imm32-is-first-inout - 7235 0/imm32/no-disp32 - 7236 0/imm32/output-is-write-only - 7237 _Primitive-add-lit-to-mem/imm32/next - 7238 _Primitive-add-lit-to-mem: - 7239 # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32 - 7240 "add-to"/imm32/name - 7241 Int-var-and-literal/imm32/inouts - 7242 0/imm32/outputs - 7243 "81 0/subop/add"/imm32/subx-name - 7244 1/imm32/rm32-is-first-inout - 7245 0/imm32/no-r32 - 7246 2/imm32/imm32-is-second-inout - 7247 0/imm32/no-disp32 - 7248 0/imm32/output-is-write-only - 7249 _Primitive-subtract-from-eax/imm32/next - 7250 # - subtract - 7251 _Primitive-subtract-from-eax: - 7252 # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32 - 7253 "subtract"/imm32/name - 7254 Single-lit-var/imm32/inouts - 7255 Single-int-var-in-eax/imm32/outputs - 7256 "2d/subtract-from-eax"/imm32/subx-name - 7257 0/imm32/no-rm32 - 7258 0/imm32/no-r32 - 7259 1/imm32/imm32-is-first-inout - 7260 0/imm32/no-disp32 - 7261 0/imm32/output-is-write-only - 7262 _Primitive-subtract-reg-from-reg/imm32/next - 7263 _Primitive-subtract-reg-from-reg: - 7264 # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32 - 7265 "subtract"/imm32/name - 7266 Single-int-var-in-some-register/imm32/inouts - 7267 Single-int-var-in-some-register/imm32/outputs - 7268 "29/subtract-from"/imm32/subx-name - 7269 3/imm32/rm32-is-first-output - 7270 1/imm32/r32-is-first-inout - 7271 0/imm32/no-imm32 - 7272 0/imm32/no-disp32 - 7273 0/imm32/output-is-write-only - 7274 _Primitive-subtract-reg-from-mem/imm32/next - 7275 _Primitive-subtract-reg-from-mem: - 7276 # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32 - 7277 "subtract-from"/imm32/name - 7278 Two-args-int-stack-int-reg/imm32/inouts - 7279 0/imm32/outputs - 7280 "29/subtract-from"/imm32/subx-name - 7281 1/imm32/rm32-is-first-inout - 7282 2/imm32/r32-is-second-inout - 7283 0/imm32/no-imm32 - 7284 0/imm32/no-disp32 - 7285 0/imm32/output-is-write-only - 7286 _Primitive-subtract-mem-from-reg/imm32/next - 7287 _Primitive-subtract-mem-from-reg: - 7288 # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32 - 7289 "subtract"/imm32/name - 7290 Single-int-var-in-mem/imm32/inouts - 7291 Single-int-var-in-some-register/imm32/outputs - 7292 "2b/subtract"/imm32/subx-name - 7293 1/imm32/rm32-is-first-inout - 7294 3/imm32/r32-is-first-output - 7295 0/imm32/no-imm32 - 7296 0/imm32/no-disp32 - 7297 0/imm32/output-is-write-only - 7298 _Primitive-subtract-lit-from-reg/imm32/next - 7299 _Primitive-subtract-lit-from-reg: - 7300 # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32 - 7301 "subtract"/imm32/name - 7302 Single-lit-var/imm32/inouts - 7303 Single-int-var-in-some-register/imm32/outputs - 7304 "81 5/subop/subtract"/imm32/subx-name - 7305 3/imm32/rm32-is-first-output - 7306 0/imm32/no-r32 - 7307 1/imm32/imm32-is-first-inout - 7308 0/imm32/no-disp32 - 7309 0/imm32/output-is-write-only - 7310 _Primitive-subtract-lit-from-mem/imm32/next - 7311 _Primitive-subtract-lit-from-mem: - 7312 # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32 - 7313 "subtract-from"/imm32/name - 7314 Int-var-and-literal/imm32/inouts - 7315 0/imm32/outputs - 7316 "81 5/subop/subtract"/imm32/subx-name - 7317 1/imm32/rm32-is-first-inout - 7318 0/imm32/no-r32 - 7319 2/imm32/imm32-is-first-inout - 7320 0/imm32/no-disp32 - 7321 0/imm32/output-is-write-only - 7322 _Primitive-and-with-eax/imm32/next - 7323 # - and - 7324 _Primitive-and-with-eax: - 7325 # var/eax <- and lit => 25/and-with-eax lit/imm32 - 7326 "and"/imm32/name - 7327 Single-lit-var/imm32/inouts - 7328 Single-int-var-in-eax/imm32/outputs - 7329 "25/and-with-eax"/imm32/subx-name - 7330 0/imm32/no-rm32 - 7331 0/imm32/no-r32 - 7332 1/imm32/imm32-is-first-inout - 7333 0/imm32/no-disp32 - 7334 0/imm32/output-is-write-only - 7335 _Primitive-and-reg-with-reg/imm32/next - 7336 _Primitive-and-reg-with-reg: - 7337 # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32 - 7338 "and"/imm32/name - 7339 Single-int-var-in-some-register/imm32/inouts - 7340 Single-int-var-in-some-register/imm32/outputs - 7341 "21/and-with"/imm32/subx-name - 7342 3/imm32/rm32-is-first-output - 7343 1/imm32/r32-is-first-inout - 7344 0/imm32/no-imm32 - 7345 0/imm32/no-disp32 - 7346 0/imm32/output-is-write-only - 7347 _Primitive-and-reg-with-mem/imm32/next - 7348 _Primitive-and-reg-with-mem: - 7349 # and-with var1 var2/reg => 21/and-with var1 var2/r32 - 7350 "and-with"/imm32/name - 7351 Two-args-int-stack-int-reg/imm32/inouts - 7352 0/imm32/outputs - 7353 "21/and-with"/imm32/subx-name - 7354 1/imm32/rm32-is-first-inout - 7355 2/imm32/r32-is-second-inout - 7356 0/imm32/no-imm32 - 7357 0/imm32/no-disp32 - 7358 0/imm32/output-is-write-only - 7359 _Primitive-and-mem-with-reg/imm32/next - 7360 _Primitive-and-mem-with-reg: - 7361 # var1/reg <- and var2 => 23/and var2/rm32 var1/r32 - 7362 "and"/imm32/name - 7363 Single-int-var-in-mem/imm32/inouts - 7364 Single-int-var-in-some-register/imm32/outputs - 7365 "23/and"/imm32/subx-name - 7366 1/imm32/rm32-is-first-inout - 7367 3/imm32/r32-is-first-output - 7368 0/imm32/no-imm32 - 7369 0/imm32/no-disp32 - 7370 0/imm32/output-is-write-only - 7371 _Primitive-and-lit-with-reg/imm32/next - 7372 _Primitive-and-lit-with-reg: - 7373 # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32 - 7374 "and"/imm32/name - 7375 Single-lit-var/imm32/inouts - 7376 Single-int-var-in-some-register/imm32/outputs - 7377 "81 4/subop/and"/imm32/subx-name - 7378 3/imm32/rm32-is-first-output - 7379 0/imm32/no-r32 - 7380 1/imm32/imm32-is-first-inout - 7381 0/imm32/no-disp32 - 7382 0/imm32/output-is-write-only - 7383 _Primitive-and-lit-with-mem/imm32/next - 7384 _Primitive-and-lit-with-mem: - 7385 # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32 - 7386 "and-with"/imm32/name - 7387 Int-var-and-literal/imm32/inouts - 7388 0/imm32/outputs - 7389 "81 4/subop/and"/imm32/subx-name - 7390 1/imm32/rm32-is-first-inout - 7391 0/imm32/no-r32 - 7392 2/imm32/imm32-is-first-inout - 7393 0/imm32/no-disp32 - 7394 0/imm32/output-is-write-only - 7395 _Primitive-or-with-eax/imm32/next - 7396 # - or - 7397 _Primitive-or-with-eax: - 7398 # var/eax <- or lit => 0d/or-with-eax lit/imm32 - 7399 "or"/imm32/name - 7400 Single-lit-var/imm32/inouts - 7401 Single-int-var-in-eax/imm32/outputs - 7402 "0d/or-with-eax"/imm32/subx-name - 7403 0/imm32/no-rm32 - 7404 0/imm32/no-r32 - 7405 1/imm32/imm32-is-first-inout - 7406 0/imm32/no-disp32 - 7407 0/imm32/output-is-write-only - 7408 _Primitive-or-reg-with-reg/imm32/next - 7409 _Primitive-or-reg-with-reg: - 7410 # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32 - 7411 "or"/imm32/name - 7412 Single-int-var-in-some-register/imm32/inouts - 7413 Single-int-var-in-some-register/imm32/outputs - 7414 "09/or-with"/imm32/subx-name - 7415 3/imm32/rm32-is-first-output - 7416 1/imm32/r32-is-first-inout - 7417 0/imm32/no-imm32 - 7418 0/imm32/no-disp32 - 7419 0/imm32/output-is-write-only - 7420 _Primitive-or-reg-with-mem/imm32/next - 7421 _Primitive-or-reg-with-mem: - 7422 # or-with var1 var2/reg => 09/or-with var1 var2/r32 - 7423 "or-with"/imm32/name - 7424 Two-args-int-stack-int-reg/imm32/inouts - 7425 0/imm32/outputs - 7426 "09/or-with"/imm32/subx-name - 7427 1/imm32/rm32-is-first-inout - 7428 2/imm32/r32-is-second-inout - 7429 0/imm32/no-imm32 - 7430 0/imm32/no-disp32 - 7431 0/imm32/output-is-write-only - 7432 _Primitive-or-mem-with-reg/imm32/next - 7433 _Primitive-or-mem-with-reg: - 7434 # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32 - 7435 "or"/imm32/name - 7436 Single-int-var-in-mem/imm32/inouts - 7437 Single-int-var-in-some-register/imm32/outputs - 7438 "0b/or"/imm32/subx-name - 7439 1/imm32/rm32-is-first-inout - 7440 3/imm32/r32-is-first-output - 7441 0/imm32/no-imm32 - 7442 0/imm32/no-disp32 - 7443 0/imm32/output-is-write-only - 7444 _Primitive-or-lit-with-reg/imm32/next - 7445 _Primitive-or-lit-with-reg: - 7446 # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32 - 7447 "or"/imm32/name - 7448 Single-lit-var/imm32/inouts - 7449 Single-int-var-in-some-register/imm32/outputs - 7450 "81 1/subop/or"/imm32/subx-name - 7451 3/imm32/rm32-is-first-output - 7452 0/imm32/no-r32 - 7453 1/imm32/imm32-is-first-inout - 7454 0/imm32/no-disp32 - 7455 0/imm32/output-is-write-only - 7456 _Primitive-or-lit-with-mem/imm32/next - 7457 _Primitive-or-lit-with-mem: - 7458 # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32 - 7459 "or-with"/imm32/name - 7460 Int-var-and-literal/imm32/inouts - 7461 0/imm32/outputs - 7462 "81 1/subop/or"/imm32/subx-name - 7463 1/imm32/rm32-is-first-inout - 7464 0/imm32/no-r32 - 7465 2/imm32/imm32-is-second-inout - 7466 0/imm32/no-disp32 - 7467 0/imm32/output-is-write-only - 7468 _Primitive-xor-with-eax/imm32/next - 7469 # - xor - 7470 _Primitive-xor-with-eax: - 7471 # var/eax <- xor lit => 35/xor-with-eax lit/imm32 - 7472 "xor"/imm32/name - 7473 Single-lit-var/imm32/inouts - 7474 Single-int-var-in-eax/imm32/outputs - 7475 "35/xor-with-eax"/imm32/subx-name - 7476 0/imm32/no-rm32 - 7477 0/imm32/no-r32 - 7478 1/imm32/imm32-is-first-inout - 7479 0/imm32/no-disp32 - 7480 0/imm32/output-is-write-only - 7481 _Primitive-xor-reg-with-reg/imm32/next - 7482 _Primitive-xor-reg-with-reg: - 7483 # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32 - 7484 "xor"/imm32/name - 7485 Single-int-var-in-some-register/imm32/inouts - 7486 Single-int-var-in-some-register/imm32/outputs - 7487 "31/xor-with"/imm32/subx-name - 7488 3/imm32/rm32-is-first-output - 7489 1/imm32/r32-is-first-inout - 7490 0/imm32/no-imm32 - 7491 0/imm32/no-disp32 - 7492 0/imm32/output-is-write-only - 7493 _Primitive-xor-reg-with-mem/imm32/next - 7494 _Primitive-xor-reg-with-mem: - 7495 # xor-with var1 var2/reg => 31/xor-with var1 var2/r32 - 7496 "xor-with"/imm32/name - 7497 Two-args-int-stack-int-reg/imm32/inouts - 7498 0/imm32/outputs - 7499 "31/xor-with"/imm32/subx-name - 7500 1/imm32/rm32-is-first-inout - 7501 2/imm32/r32-is-second-inout - 7502 0/imm32/no-imm32 - 7503 0/imm32/no-disp32 - 7504 0/imm32/output-is-write-only - 7505 _Primitive-xor-mem-with-reg/imm32/next - 7506 _Primitive-xor-mem-with-reg: - 7507 # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32 - 7508 "xor"/imm32/name - 7509 Single-int-var-in-mem/imm32/inouts - 7510 Single-int-var-in-some-register/imm32/outputs - 7511 "33/xor"/imm32/subx-name - 7512 1/imm32/rm32-is-first-inout - 7513 3/imm32/r32-is-first-output - 7514 0/imm32/no-imm32 - 7515 0/imm32/no-disp32 - 7516 0/imm32/output-is-write-only - 7517 _Primitive-xor-lit-with-reg/imm32/next - 7518 _Primitive-xor-lit-with-reg: - 7519 # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32 - 7520 "xor"/imm32/name - 7521 Single-lit-var/imm32/inouts - 7522 Single-int-var-in-some-register/imm32/outputs - 7523 "81 6/subop/xor"/imm32/subx-name - 7524 3/imm32/rm32-is-first-output - 7525 0/imm32/no-r32 - 7526 1/imm32/imm32-is-first-inout - 7527 0/imm32/no-disp32 - 7528 0/imm32/output-is-write-only - 7529 _Primitive-xor-lit-with-mem/imm32/next - 7530 _Primitive-xor-lit-with-mem: - 7531 # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32 - 7532 "xor-with"/imm32/name - 7533 Int-var-and-literal/imm32/inouts - 7534 0/imm32/outputs - 7535 "81 6/subop/xor"/imm32/subx-name - 7536 1/imm32/rm32-is-first-inout - 7537 0/imm32/no-r32 - 7538 2/imm32/imm32-is-first-inout - 7539 0/imm32/no-disp32 - 7540 0/imm32/output-is-write-only - 7541 _Primitive-copy-to-eax/imm32/next - 7542 # - copy - 7543 _Primitive-copy-to-eax: - 7544 # var/eax <- copy lit => b8/copy-to-eax lit/imm32 - 7545 "copy"/imm32/name - 7546 Single-lit-var/imm32/inouts - 7547 Single-int-var-in-eax/imm32/outputs - 7548 "b8/copy-to-eax"/imm32/subx-name - 7549 0/imm32/no-rm32 - 7550 0/imm32/no-r32 - 7551 1/imm32/imm32-is-first-inout - 7552 0/imm32/no-disp32 - 7553 1/imm32/output-is-write-only - 7554 _Primitive-copy-to-ecx/imm32/next - 7555 _Primitive-copy-to-ecx: - 7556 # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32 - 7557 "copy"/imm32/name - 7558 Single-lit-var/imm32/inouts - 7559 Single-int-var-in-ecx/imm32/outputs - 7560 "b9/copy-to-ecx"/imm32/subx-name - 7561 0/imm32/no-rm32 - 7562 0/imm32/no-r32 - 7563 1/imm32/imm32-is-first-inout - 7564 0/imm32/no-disp32 - 7565 1/imm32/output-is-write-only - 7566 _Primitive-copy-to-edx/imm32/next - 7567 _Primitive-copy-to-edx: - 7568 # var/edx <- copy lit => ba/copy-to-edx lit/imm32 - 7569 "copy"/imm32/name - 7570 Single-lit-var/imm32/inouts - 7571 Single-int-var-in-edx/imm32/outputs - 7572 "ba/copy-to-edx"/imm32/subx-name - 7573 0/imm32/no-rm32 - 7574 0/imm32/no-r32 - 7575 1/imm32/imm32-is-first-inout - 7576 0/imm32/no-disp32 - 7577 1/imm32/output-is-write-only - 7578 _Primitive-copy-to-ebx/imm32/next - 7579 _Primitive-copy-to-ebx: - 7580 # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32 - 7581 "copy"/imm32/name - 7582 Single-lit-var/imm32/inouts - 7583 Single-int-var-in-ebx/imm32/outputs - 7584 "bb/copy-to-ebx"/imm32/subx-name - 7585 0/imm32/no-rm32 - 7586 0/imm32/no-r32 - 7587 1/imm32/imm32-is-first-inout - 7588 0/imm32/no-disp32 - 7589 1/imm32/output-is-write-only - 7590 _Primitive-copy-to-esi/imm32/next - 7591 _Primitive-copy-to-esi: - 7592 # var/esi <- copy lit => be/copy-to-esi lit/imm32 - 7593 "copy"/imm32/name - 7594 Single-lit-var/imm32/inouts - 7595 Single-int-var-in-esi/imm32/outputs - 7596 "be/copy-to-esi"/imm32/subx-name - 7597 0/imm32/no-rm32 - 7598 0/imm32/no-r32 - 7599 1/imm32/imm32-is-first-inout - 7600 0/imm32/no-disp32 - 7601 1/imm32/output-is-write-only - 7602 _Primitive-copy-to-edi/imm32/next - 7603 _Primitive-copy-to-edi: - 7604 # var/edi <- copy lit => bf/copy-to-edi lit/imm32 - 7605 "copy"/imm32/name - 7606 Single-lit-var/imm32/inouts - 7607 Single-int-var-in-edi/imm32/outputs - 7608 "bf/copy-to-edi"/imm32/subx-name - 7609 0/imm32/no-rm32 - 7610 0/imm32/no-r32 - 7611 1/imm32/imm32-is-first-inout - 7612 0/imm32/no-disp32 - 7613 1/imm32/output-is-write-only - 7614 _Primitive-copy-reg-to-reg/imm32/next - 7615 _Primitive-copy-reg-to-reg: - 7616 # var1/reg <- copy var2/reg => 89/copy-to var1/rm32 var2/r32 - 7617 "copy"/imm32/name - 7618 Single-int-var-in-some-register/imm32/inouts - 7619 Single-int-var-in-some-register/imm32/outputs - 7620 "89/copy-to"/imm32/subx-name - 7621 3/imm32/rm32-is-first-output - 7622 1/imm32/r32-is-first-inout - 7623 0/imm32/no-imm32 - 7624 0/imm32/no-disp32 - 7625 1/imm32/output-is-write-only - 7626 _Primitive-copy-reg-to-mem/imm32/next - 7627 _Primitive-copy-reg-to-mem: - 7628 # copy-to var1 var2/reg => 89/copy-to var1 var2/r32 - 7629 "copy-to"/imm32/name - 7630 Two-args-int-stack-int-reg/imm32/inouts - 7631 0/imm32/outputs - 7632 "89/copy-to"/imm32/subx-name - 7633 1/imm32/rm32-is-first-inout - 7634 2/imm32/r32-is-second-inout - 7635 0/imm32/no-imm32 - 7636 0/imm32/no-disp32 - 7637 1/imm32/output-is-write-only - 7638 _Primitive-copy-mem-to-reg/imm32/next - 7639 _Primitive-copy-mem-to-reg: - 7640 # var1/reg <- copy var2 => 8b/copy-from var2/rm32 var1/r32 - 7641 "copy"/imm32/name - 7642 Single-int-var-in-mem/imm32/inouts - 7643 Single-int-var-in-some-register/imm32/outputs - 7644 "8b/copy-from"/imm32/subx-name - 7645 1/imm32/rm32-is-first-inout - 7646 3/imm32/r32-is-first-output - 7647 0/imm32/no-imm32 - 7648 0/imm32/no-disp32 - 7649 1/imm32/output-is-write-only - 7650 _Primitive-copy-lit-to-reg/imm32/next - 7651 _Primitive-copy-lit-to-reg: - 7652 # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32 - 7653 "copy"/imm32/name - 7654 Single-lit-var/imm32/inouts - 7655 Single-int-var-in-some-register/imm32/outputs - 7656 "c7 0/subop/copy"/imm32/subx-name - 7657 3/imm32/rm32-is-first-output - 7658 0/imm32/no-r32 - 7659 1/imm32/imm32-is-first-inout - 7660 0/imm32/no-disp32 - 7661 1/imm32/output-is-write-only - 7662 _Primitive-copy-lit-to-mem/imm32/next - 7663 _Primitive-copy-lit-to-mem: - 7664 # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32 - 7665 "copy-to"/imm32/name - 7666 Int-var-and-literal/imm32/inouts - 7667 0/imm32/outputs - 7668 "c7 0/subop/copy"/imm32/subx-name - 7669 1/imm32/rm32-is-first-inout - 7670 0/imm32/no-r32 - 7671 2/imm32/imm32-is-first-inout - 7672 0/imm32/no-disp32 - 7673 1/imm32/output-is-write-only - 7674 _Primitive-compare-mem-with-reg/imm32/next - 7675 # - compare - 7676 _Primitive-compare-mem-with-reg: - 7677 # compare var1 var2/reg => 39/compare-> var1/rm32 var2/r32 - 7678 "compare"/imm32/name - 7679 Two-args-int-stack-int-reg/imm32/inouts - 7680 0/imm32/outputs - 7681 "39/compare->"/imm32/subx-name - 7682 1/imm32/rm32-is-first-inout - 7683 2/imm32/r32-is-second-inout - 7684 0/imm32/no-imm32 - 7685 0/imm32/no-disp32 - 7686 0/imm32/output-is-write-only - 7687 _Primitive-compare-reg-with-mem/imm32/next - 7688 _Primitive-compare-reg-with-mem: - 7689 # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32 - 7690 "compare"/imm32/name - 7691 Two-args-int-reg-int-stack/imm32/inouts - 7692 0/imm32/outputs - 7693 "3b/compare<-"/imm32/subx-name - 7694 2/imm32/rm32-is-second-inout - 7695 1/imm32/r32-is-first-inout - 7696 0/imm32/no-imm32 - 7697 0/imm32/no-disp32 - 7698 0/imm32/output-is-write-only - 7699 _Primitive-compare-eax-with-literal/imm32/next - 7700 _Primitive-compare-eax-with-literal: - 7701 # compare var1/eax n => 3d/compare-eax-with n/imm32 - 7702 "compare"/imm32/name - 7703 Two-args-int-eax-int-literal/imm32/inouts - 7704 0/imm32/outputs - 7705 "3d/compare-eax-with"/imm32/subx-name - 7706 0/imm32/no-rm32 - 7707 0/imm32/no-r32 - 7708 2/imm32/imm32-is-second-inout - 7709 0/imm32/no-disp32 - 7710 0/imm32/output-is-write-only - 7711 _Primitive-compare-reg-with-literal/imm32/next - 7712 _Primitive-compare-reg-with-literal: - 7713 # compare var1/reg n => 81 7/subop/compare %reg n/imm32 - 7714 "compare"/imm32/name - 7715 Int-var-in-register-and-literal/imm32/inouts - 7716 0/imm32/outputs - 7717 "81 7/subop/compare"/imm32/subx-name - 7718 1/imm32/rm32-is-first-inout - 7719 0/imm32/no-r32 - 7720 2/imm32/imm32-is-second-inout - 7721 0/imm32/no-disp32 - 7722 0/imm32/output-is-write-only - 7723 _Primitive-compare-mem-with-literal/imm32/next - 7724 _Primitive-compare-mem-with-literal: - 7725 # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32 - 7726 "compare"/imm32/name - 7727 Int-var-and-literal/imm32/inouts - 7728 0/imm32/outputs - 7729 "81 7/subop/compare"/imm32/subx-name - 7730 1/imm32/rm32-is-first-inout - 7731 0/imm32/no-r32 - 7732 2/imm32/imm32-is-second-inout - 7733 0/imm32/no-disp32 - 7734 0/imm32/output-is-write-only - 7735 _Primitive-multiply-reg-by-mem/imm32/next - 7736 # - multiply - 7737 _Primitive-multiply-reg-by-mem: - 7738 # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32 - 7739 "multiply"/imm32/name - 7740 Single-int-var-in-mem/imm32/inouts - 7741 Single-int-var-in-some-register/imm32/outputs - 7742 "0f af/multiply"/imm32/subx-name - 7743 1/imm32/rm32-is-first-inout - 7744 3/imm32/r32-is-first-output - 7745 0/imm32/no-imm32 - 7746 0/imm32/no-disp32 - 7747 0/imm32/output-is-write-only - 7748 _Primitive-break-if-addr</imm32/next - 7749 # - branches - 7750 _Primitive-break-if-addr<: - 7751 "break-if-addr<"/imm32/name - 7752 0/imm32/inouts - 7753 0/imm32/outputs - 7754 "0f 82/jump-if-addr< break/disp32"/imm32/subx-name - 7755 0/imm32/no-rm32 - 7756 0/imm32/no-r32 - 7757 0/imm32/no-imm32 - 7758 0/imm32/no-disp32 - 7759 0/imm32/no-output - 7760 _Primitive-break-if-addr>=/imm32/next - 7761 _Primitive-break-if-addr>=: - 7762 "break-if-addr>="/imm32/name - 7763 0/imm32/inouts - 7764 0/imm32/outputs - 7765 "0f 83/jump-if-addr>= break/disp32"/imm32/subx-name - 7766 0/imm32/no-rm32 - 7767 0/imm32/no-r32 - 7768 0/imm32/no-imm32 - 7769 0/imm32/no-disp32 - 7770 0/imm32/no-output - 7771 _Primitive-break-if-=/imm32/next - 7772 _Primitive-break-if-=: - 7773 "break-if-="/imm32/name - 7774 0/imm32/inouts - 7775 0/imm32/outputs - 7776 "0f 84/jump-if-= break/disp32"/imm32/subx-name - 7777 0/imm32/no-rm32 - 7778 0/imm32/no-r32 - 7779 0/imm32/no-imm32 - 7780 0/imm32/no-disp32 - 7781 0/imm32/no-output - 7782 _Primitive-break-if-!=/imm32/next - 7783 _Primitive-break-if-!=: - 7784 "break-if-!="/imm32/name - 7785 0/imm32/inouts - 7786 0/imm32/outputs - 7787 "0f 85/jump-if-!= break/disp32"/imm32/subx-name - 7788 0/imm32/no-rm32 - 7789 0/imm32/no-r32 - 7790 0/imm32/no-imm32 - 7791 0/imm32/no-disp32 - 7792 0/imm32/no-output - 7793 _Primitive-break-if-addr<=/imm32/next - 7794 _Primitive-break-if-addr<=: - 7795 "break-if-addr<="/imm32/name - 7796 0/imm32/inouts - 7797 0/imm32/outputs - 7798 "0f 86/jump-if-addr<= break/disp32"/imm32/subx-name - 7799 0/imm32/no-rm32 - 7800 0/imm32/no-r32 - 7801 0/imm32/no-imm32 - 7802 0/imm32/no-disp32 - 7803 0/imm32/no-output - 7804 _Primitive-break-if-addr>/imm32/next - 7805 _Primitive-break-if-addr>: - 7806 "break-if-addr>"/imm32/name - 7807 0/imm32/inouts - 7808 0/imm32/outputs - 7809 "0f 87/jump-if-addr> break/disp32"/imm32/subx-name - 7810 0/imm32/no-rm32 - 7811 0/imm32/no-r32 - 7812 0/imm32/no-imm32 - 7813 0/imm32/no-disp32 - 7814 0/imm32/no-output - 7815 _Primitive-break-if-</imm32/next - 7816 _Primitive-break-if-<: - 7817 "break-if-<"/imm32/name - 7818 0/imm32/inouts - 7819 0/imm32/outputs - 7820 "0f 8c/jump-if-< break/disp32"/imm32/subx-name - 7821 0/imm32/no-rm32 - 7822 0/imm32/no-r32 - 7823 0/imm32/no-imm32 - 7824 0/imm32/no-disp32 - 7825 0/imm32/no-output - 7826 _Primitive-break-if->=/imm32/next - 7827 _Primitive-break-if->=: - 7828 "break-if->="/imm32/name - 7829 0/imm32/inouts - 7830 0/imm32/outputs - 7831 "0f 8d/jump-if->= break/disp32"/imm32/subx-name - 7832 0/imm32/no-rm32 - 7833 0/imm32/no-r32 - 7834 0/imm32/no-imm32 - 7835 0/imm32/no-disp32 - 7836 0/imm32/no-output - 7837 _Primitive-break-if-<=/imm32/next - 7838 _Primitive-break-if-<=: - 7839 "break-if-<="/imm32/name - 7840 0/imm32/inouts - 7841 0/imm32/outputs - 7842 "0f 8e/jump-if-<= break/disp32"/imm32/subx-name - 7843 0/imm32/no-rm32 - 7844 0/imm32/no-r32 - 7845 0/imm32/no-imm32 - 7846 0/imm32/no-disp32 - 7847 0/imm32/no-output - 7848 _Primitive-break-if->/imm32/next - 7849 _Primitive-break-if->: - 7850 "break-if->"/imm32/name - 7851 0/imm32/inouts - 7852 0/imm32/outputs - 7853 "0f 8f/jump-if-> break/disp32"/imm32/subx-name - 7854 0/imm32/no-rm32 - 7855 0/imm32/no-r32 - 7856 0/imm32/no-imm32 - 7857 0/imm32/no-disp32 - 7858 0/imm32/no-output - 7859 _Primitive-break/imm32/next - 7860 _Primitive-break: - 7861 "break"/imm32/name - 7862 0/imm32/inouts - 7863 0/imm32/outputs - 7864 "e9/jump break/disp32"/imm32/subx-name - 7865 0/imm32/no-rm32 - 7866 0/imm32/no-r32 - 7867 0/imm32/no-imm32 - 7868 0/imm32/no-disp32 - 7869 0/imm32/no-output - 7870 _Primitive-loop-if-addr</imm32/next - 7871 _Primitive-loop-if-addr<: - 7872 "loop-if-addr<"/imm32/name - 7873 0/imm32/inouts - 7874 0/imm32/outputs - 7875 "0f 82/jump-if-addr< loop/disp32"/imm32/subx-name - 7876 0/imm32/no-rm32 - 7877 0/imm32/no-r32 - 7878 0/imm32/no-imm32 - 7879 0/imm32/no-disp32 - 7880 0/imm32/no-output - 7881 _Primitive-loop-if-addr>=/imm32/next - 7882 _Primitive-loop-if-addr>=: - 7883 "loop-if-addr>="/imm32/name - 7884 0/imm32/inouts - 7885 0/imm32/outputs - 7886 "0f 83/jump-if-addr>= loop/disp32"/imm32/subx-name - 7887 0/imm32/no-rm32 - 7888 0/imm32/no-r32 - 7889 0/imm32/no-imm32 - 7890 0/imm32/no-disp32 - 7891 0/imm32/no-output - 7892 _Primitive-loop-if-=/imm32/next - 7893 _Primitive-loop-if-=: - 7894 "loop-if-="/imm32/name - 7895 0/imm32/inouts - 7896 0/imm32/outputs - 7897 "0f 84/jump-if-= loop/disp32"/imm32/subx-name - 7898 0/imm32/no-rm32 - 7899 0/imm32/no-r32 - 7900 0/imm32/no-imm32 - 7901 0/imm32/no-disp32 - 7902 0/imm32/no-output - 7903 _Primitive-loop-if-!=/imm32/next - 7904 _Primitive-loop-if-!=: - 7905 "loop-if-!="/imm32/name - 7906 0/imm32/inouts - 7907 0/imm32/outputs - 7908 "0f 85/jump-if-!= loop/disp32"/imm32/subx-name - 7909 0/imm32/no-rm32 - 7910 0/imm32/no-r32 - 7911 0/imm32/no-imm32 - 7912 0/imm32/no-disp32 - 7913 0/imm32/no-output - 7914 _Primitive-loop-if-addr<=/imm32/next - 7915 _Primitive-loop-if-addr<=: - 7916 "loop-if-addr<="/imm32/name - 7917 0/imm32/inouts - 7918 0/imm32/outputs - 7919 "0f 86/jump-if-addr<= loop/disp32"/imm32/subx-name - 7920 0/imm32/no-rm32 - 7921 0/imm32/no-r32 - 7922 0/imm32/no-imm32 - 7923 0/imm32/no-disp32 - 7924 0/imm32/no-output - 7925 _Primitive-loop-if-addr>/imm32/next - 7926 _Primitive-loop-if-addr>: - 7927 "loop-if-addr>"/imm32/name - 7928 0/imm32/inouts - 7929 0/imm32/outputs - 7930 "0f 87/jump-if-addr> loop/disp32"/imm32/subx-name - 7931 0/imm32/no-rm32 - 7932 0/imm32/no-r32 - 7933 0/imm32/no-imm32 - 7934 0/imm32/no-disp32 - 7935 0/imm32/no-output - 7936 _Primitive-loop-if-</imm32/next - 7937 _Primitive-loop-if-<: - 7938 "loop-if-<"/imm32/name - 7939 0/imm32/inouts - 7940 0/imm32/outputs - 7941 "0f 8c/jump-if-< loop/disp32"/imm32/subx-name - 7942 0/imm32/no-rm32 - 7943 0/imm32/no-r32 - 7944 0/imm32/no-imm32 - 7945 0/imm32/no-disp32 - 7946 0/imm32/no-output - 7947 _Primitive-loop-if->=/imm32/next - 7948 _Primitive-loop-if->=: - 7949 "loop-if->="/imm32/name - 7950 0/imm32/inouts - 7951 0/imm32/outputs - 7952 "0f 8d/jump-if->= loop/disp32"/imm32/subx-name - 7953 0/imm32/no-rm32 - 7954 0/imm32/no-r32 - 7955 0/imm32/no-imm32 - 7956 0/imm32/no-disp32 - 7957 0/imm32/no-output - 7958 _Primitive-loop-if-<=/imm32/next - 7959 _Primitive-loop-if-<=: - 7960 "loop-if-<="/imm32/name - 7961 0/imm32/inouts - 7962 0/imm32/outputs - 7963 "0f 8e/jump-if-<= loop/disp32"/imm32/subx-name - 7964 0/imm32/no-rm32 - 7965 0/imm32/no-r32 - 7966 0/imm32/no-imm32 - 7967 0/imm32/no-disp32 - 7968 0/imm32/no-output - 7969 _Primitive-loop-if->/imm32/next - 7970 _Primitive-loop-if->: - 7971 "loop-if->"/imm32/name - 7972 0/imm32/inouts - 7973 0/imm32/outputs - 7974 "0f 8f/jump-if-> loop/disp32"/imm32/subx-name - 7975 0/imm32/no-rm32 - 7976 0/imm32/no-r32 - 7977 0/imm32/no-imm32 - 7978 0/imm32/no-disp32 - 7979 0/imm32/no-output - 7980 _Primitive-loop/imm32/next # we probably don't need an unconditional break - 7981 _Primitive-loop: - 7982 "loop"/imm32/name - 7983 0/imm32/inouts - 7984 0/imm32/outputs - 7985 "e9/jump loop/disp32"/imm32/subx-name - 7986 0/imm32/no-rm32 - 7987 0/imm32/no-r32 - 7988 0/imm32/no-imm32 - 7989 0/imm32/no-disp32 - 7990 0/imm32/no-output - 7991 _Primitive-break-if-addr<-named/imm32/next - 7992 # - branches to named blocks - 7993 _Primitive-break-if-addr<-named: - 7994 "break-if-addr<"/imm32/name - 7995 Single-lit-var/imm32/inouts - 7996 0/imm32/outputs - 7997 "0f 82/jump-if-addr<"/imm32/subx-name - 7998 0/imm32/no-rm32 - 7999 0/imm32/no-r32 - 8000 0/imm32/no-imm32 - 8001 1/imm32/disp32-is-first-inout - 8002 0/imm32/no-output - 8003 _Primitive-break-if-addr>=-named/imm32/next - 8004 _Primitive-break-if-addr>=-named: - 8005 "break-if-addr>="/imm32/name - 8006 Single-lit-var/imm32/inouts - 8007 0/imm32/outputs - 8008 "0f 83/jump-if-addr>="/imm32/subx-name - 8009 0/imm32/no-rm32 - 8010 0/imm32/no-r32 - 8011 0/imm32/no-imm32 - 8012 1/imm32/disp32-is-first-inout - 8013 0/imm32/no-output - 8014 _Primitive-break-if-=-named/imm32/next - 8015 _Primitive-break-if-=-named: - 8016 "break-if-="/imm32/name - 8017 Single-lit-var/imm32/inouts - 8018 0/imm32/outputs - 8019 "0f 84/jump-if-="/imm32/subx-name - 8020 0/imm32/no-rm32 - 8021 0/imm32/no-r32 - 8022 0/imm32/no-imm32 - 8023 1/imm32/disp32-is-first-inout - 8024 0/imm32/no-output - 8025 _Primitive-break-if-!=-named/imm32/next - 8026 _Primitive-break-if-!=-named: - 8027 "break-if-!="/imm32/name - 8028 Single-lit-var/imm32/inouts - 8029 0/imm32/outputs - 8030 "0f 85/jump-if-!="/imm32/subx-name - 8031 0/imm32/no-rm32 - 8032 0/imm32/no-r32 - 8033 0/imm32/no-imm32 - 8034 1/imm32/disp32-is-first-inout - 8035 0/imm32/no-output - 8036 _Primitive-break-if-addr<=-named/imm32/next - 8037 _Primitive-break-if-addr<=-named: - 8038 "break-if-addr<="/imm32/name - 8039 Single-lit-var/imm32/inouts - 8040 0/imm32/outputs - 8041 "0f 86/jump-if-addr<="/imm32/subx-name - 8042 0/imm32/no-rm32 - 8043 0/imm32/no-r32 - 8044 0/imm32/no-imm32 - 8045 1/imm32/disp32-is-first-inout - 8046 0/imm32/no-output - 8047 _Primitive-break-if-addr>-named/imm32/next - 8048 _Primitive-break-if-addr>-named: - 8049 "break-if-addr>"/imm32/name - 8050 Single-lit-var/imm32/inouts - 8051 0/imm32/outputs - 8052 "0f 87/jump-if-addr>"/imm32/subx-name - 8053 0/imm32/no-rm32 - 8054 0/imm32/no-r32 - 8055 0/imm32/no-imm32 - 8056 1/imm32/disp32-is-first-inout - 8057 0/imm32/no-output - 8058 _Primitive-break-if-<-named/imm32/next - 8059 _Primitive-break-if-<-named: - 8060 "break-if-<"/imm32/name - 8061 Single-lit-var/imm32/inouts - 8062 0/imm32/outputs - 8063 "0f 8c/jump-if-<"/imm32/subx-name - 8064 0/imm32/no-rm32 - 8065 0/imm32/no-r32 - 8066 0/imm32/no-imm32 - 8067 1/imm32/disp32-is-first-inout - 8068 0/imm32/no-output - 8069 _Primitive-break-if->=-named/imm32/next - 8070 _Primitive-break-if->=-named: - 8071 "break-if->="/imm32/name - 8072 Single-lit-var/imm32/inouts - 8073 0/imm32/outputs - 8074 "0f 8d/jump-if->="/imm32/subx-name - 8075 0/imm32/no-rm32 - 8076 0/imm32/no-r32 - 8077 0/imm32/no-imm32 - 8078 1/imm32/disp32-is-first-inout - 8079 0/imm32/no-output - 8080 _Primitive-break-if-<=-named/imm32/next - 8081 _Primitive-break-if-<=-named: - 8082 "break-if-<="/imm32/name - 8083 Single-lit-var/imm32/inouts - 8084 0/imm32/outputs - 8085 "0f 8e/jump-if-<="/imm32/subx-name - 8086 0/imm32/no-rm32 - 8087 0/imm32/no-r32 - 8088 0/imm32/no-imm32 - 8089 1/imm32/disp32-is-first-inout - 8090 0/imm32/no-output - 8091 _Primitive-break-if->-named/imm32/next - 8092 _Primitive-break-if->-named: - 8093 "break-if->"/imm32/name - 8094 Single-lit-var/imm32/inouts - 8095 0/imm32/outputs - 8096 "0f 8f/jump-if->"/imm32/subx-name - 8097 0/imm32/no-rm32 - 8098 0/imm32/no-r32 - 8099 0/imm32/no-imm32 - 8100 1/imm32/disp32-is-first-inout - 8101 0/imm32/no-output - 8102 _Primitive-break-named/imm32/next - 8103 _Primitive-break-named: - 8104 "break"/imm32/name - 8105 Single-lit-var/imm32/inouts - 8106 0/imm32/outputs - 8107 "e9/jump"/imm32/subx-name - 8108 0/imm32/no-rm32 - 8109 0/imm32/no-r32 - 8110 0/imm32/no-imm32 - 8111 1/imm32/disp32-is-first-inout - 8112 0/imm32/no-output - 8113 _Primitive-loop-if-addr<-named/imm32/next - 8114 _Primitive-loop-if-addr<-named: - 8115 "loop-if-addr<"/imm32/name - 8116 Single-lit-var/imm32/inouts - 8117 0/imm32/outputs - 8118 "0f 82/jump-if-addr<"/imm32/subx-name - 8119 0/imm32/no-rm32 - 8120 0/imm32/no-r32 - 8121 0/imm32/no-imm32 - 8122 1/imm32/disp32-is-first-inout - 8123 0/imm32/no-output - 8124 _Primitive-loop-if-addr>=-named/imm32/next - 8125 _Primitive-loop-if-addr>=-named: - 8126 "loop-if-addr>="/imm32/name - 8127 Single-lit-var/imm32/inouts - 8128 0/imm32/outputs - 8129 "0f 83/jump-if-addr>="/imm32/subx-name - 8130 0/imm32/no-rm32 - 8131 0/imm32/no-r32 - 8132 0/imm32/no-imm32 - 8133 1/imm32/disp32-is-first-inout - 8134 0/imm32/no-output - 8135 _Primitive-loop-if-=-named/imm32/next - 8136 _Primitive-loop-if-=-named: - 8137 "loop-if-="/imm32/name - 8138 Single-lit-var/imm32/inouts - 8139 0/imm32/outputs - 8140 "0f 84/jump-if-="/imm32/subx-name - 8141 0/imm32/no-rm32 - 8142 0/imm32/no-r32 - 8143 0/imm32/no-imm32 - 8144 1/imm32/disp32-is-first-inout - 8145 0/imm32/no-output - 8146 _Primitive-loop-if-!=-named/imm32/next - 8147 _Primitive-loop-if-!=-named: - 8148 "loop-if-!="/imm32/name - 8149 Single-lit-var/imm32/inouts - 8150 0/imm32/outputs - 8151 "0f 85/jump-if-!="/imm32/subx-name - 8152 0/imm32/no-rm32 - 8153 0/imm32/no-r32 - 8154 0/imm32/no-imm32 - 8155 1/imm32/disp32-is-first-inout - 8156 0/imm32/no-output - 8157 _Primitive-loop-if-addr<=-named/imm32/next - 8158 _Primitive-loop-if-addr<=-named: - 8159 "loop-if-addr<="/imm32/name - 8160 Single-lit-var/imm32/inouts - 8161 0/imm32/outputs - 8162 "0f 86/jump-if-addr<="/imm32/subx-name - 8163 0/imm32/no-rm32 - 8164 0/imm32/no-r32 - 8165 0/imm32/no-imm32 - 8166 1/imm32/disp32-is-first-inout - 8167 0/imm32/no-output - 8168 _Primitive-loop-if-addr>-named/imm32/next - 8169 _Primitive-loop-if-addr>-named: - 8170 "loop-if-addr>"/imm32/name - 8171 Single-lit-var/imm32/inouts - 8172 0/imm32/outputs - 8173 "0f 87/jump-if-addr>"/imm32/subx-name - 8174 0/imm32/no-rm32 - 8175 0/imm32/no-r32 - 8176 0/imm32/no-imm32 - 8177 1/imm32/disp32-is-first-inout - 8178 0/imm32/no-output - 8179 _Primitive-loop-if-<-named/imm32/next - 8180 _Primitive-loop-if-<-named: - 8181 "loop-if-<"/imm32/name - 8182 Single-lit-var/imm32/inouts - 8183 0/imm32/outputs - 8184 "0f 8c/jump-if-<"/imm32/subx-name - 8185 0/imm32/no-rm32 - 8186 0/imm32/no-r32 - 8187 0/imm32/no-imm32 - 8188 1/imm32/disp32-is-first-inout - 8189 0/imm32/no-output - 8190 _Primitive-loop-if->=-named/imm32/next - 8191 _Primitive-loop-if->=-named: - 8192 "loop-if->="/imm32/name - 8193 Single-lit-var/imm32/inouts - 8194 0/imm32/outputs - 8195 "0f 8d/jump-if->="/imm32/subx-name - 8196 0/imm32/no-rm32 - 8197 0/imm32/no-r32 - 8198 0/imm32/no-imm32 - 8199 1/imm32/disp32-is-first-inout - 8200 0/imm32/no-output - 8201 _Primitive-loop-if-<=-named/imm32/next - 8202 _Primitive-loop-if-<=-named: - 8203 "loop-if-<="/imm32/name - 8204 Single-lit-var/imm32/inouts - 8205 0/imm32/outputs - 8206 "0f 8e/jump-if-<="/imm32/subx-name - 8207 0/imm32/no-rm32 - 8208 0/imm32/no-r32 - 8209 0/imm32/no-imm32 - 8210 1/imm32/disp32-is-first-inout - 8211 0/imm32/no-output - 8212 _Primitive-loop-if->-named/imm32/next - 8213 _Primitive-loop-if->-named: - 8214 "loop-if->"/imm32/name - 8215 Single-lit-var/imm32/inouts - 8216 0/imm32/outputs - 8217 "0f 8f/jump-if->"/imm32/subx-name - 8218 0/imm32/no-rm32 - 8219 0/imm32/no-r32 - 8220 0/imm32/no-imm32 - 8221 1/imm32/disp32-is-first-inout - 8222 0/imm32/no-output - 8223 _Primitive-loop-named/imm32/next # we probably don't need an unconditional break - 8224 _Primitive-loop-named: - 8225 "loop"/imm32/name - 8226 Single-lit-var/imm32/inouts - 8227 0/imm32/outputs - 8228 "e9/jump"/imm32/subx-name - 8229 0/imm32/no-rm32 - 8230 0/imm32/no-r32 - 8231 0/imm32/no-imm32 - 8232 1/imm32/disp32-is-first-inout - 8233 0/imm32/no-output + 6872 0f 94/set-if-= %eax + 6873 81 4/subop/and %eax 0xff/imm32 + 6874 $power-of-2?:end: + 6875 # . epilogue + 6876 89/<- %esp 5/r32/ebp + 6877 5d/pop-to-ebp + 6878 c3/return + 6879 + 6880 num-shift-rights: # n: int -> result/eax: int + 6881 # precondition: n is a positive power of 2 + 6882 # . prologue + 6883 55/push-ebp + 6884 89/<- %ebp 4/r32/esp + 6885 # . save registers + 6886 51/push-ecx + 6887 # var curr/ecx: int = n + 6888 8b/-> *(ebp+8) 1/r32/ecx + 6889 # result = 0 + 6890 b8/copy-to-eax 0/imm32 + 6891 { + 6892 # if (curr <= 1) break + 6893 81 7/subop/compare %ecx 1/imm32 + 6894 7e/jump-if-<= break/disp8 + 6895 40/increment-eax + 6896 c1/shift 5/subop/arithmetic-right %ecx 1/imm8 + 6897 eb/jump loop/disp8 + 6898 } + 6899 $num-shift-rights:end: + 6900 # . restore registers + 6901 59/pop-to-ecx + 6902 # . epilogue + 6903 89/<- %esp 5/r32/ebp + 6904 5d/pop-to-ebp + 6905 c3/return + 6906 + 6907 print-mu-get-offset: # out: (addr buffered-file), stmt: (handle stmt) + 6908 # . prologue + 6909 55/push-ebp + 6910 89/<- %ebp 4/r32/esp + 6911 # . save registers + 6912 50/push-eax + 6913 # var second-inout/eax: (handle stmt-var) = stmt->inouts->next + 6914 8b/-> *(ebp+0xc) 0/r32/eax + 6915 8b/-> *(eax+8) 0/r32/eax # Stmt1-inouts + 6916 8b/-> *(eax+4) 0/r32/eax # Stmt-var-next + 6917 # var output-var/eax: (handle var) = second-inout->value + 6918 8b/-> *eax 0/r32/eax # Stmt-var-value + 6919 # print offset + 6920 #? (write-buffered Stderr "emitting offset from output var ") + 6921 #? (print-int32-buffered Stderr %eax) + 6922 #? (write-buffered Stderr Newline) + 6923 #? (flush Stderr) + 6924 (print-int32-buffered *(ebp+8) *(eax+0xc)) # Var-offset + 6925 $emit-get-offset:end: + 6926 # . restore registers + 6927 58/pop-to-eax + 6928 # . epilogue + 6929 89/<- %esp 5/r32/ebp + 6930 5d/pop-to-ebp + 6931 c3/return + 6932 + 6933 emit-subx-block: # out: (addr buffered-file), block: (handle block), vars: (addr stack (handle var)) + 6934 # . prologue + 6935 55/push-ebp + 6936 89/<- %ebp 4/r32/esp + 6937 # . save registers + 6938 50/push-eax + 6939 51/push-ecx + 6940 56/push-esi + 6941 # esi = block + 6942 8b/-> *(ebp+0xc) 6/r32/esi + 6943 # var stmts/eax: (handle list stmt) = block->statements + 6944 8b/-> *(esi+4) 0/r32/eax # Block-stmts + 6945 # + 6946 { + 6947 $emit-subx-block:check-empty: + 6948 3d/compare-eax-and 0/imm32 + 6949 0f 84/jump-if-= break/disp32 + 6950 (emit-indent *(ebp+8) *Curr-block-depth) + 6951 (write-buffered *(ebp+8) "{\n") + 6952 # var v/ecx: (addr array byte) = block->var->name + 6953 8b/-> *(esi+8) 1/r32/ecx # Block-var + 6954 (write-buffered *(ebp+8) *ecx) # Var-name + 6955 (write-buffered *(ebp+8) ":loop:\n") + 6956 ff 0/subop/increment *Curr-block-depth + 6957 (push *(ebp+0x10) %ecx) + 6958 (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10)) + 6959 (pop *(ebp+0x10)) # => eax + 6960 ff 1/subop/decrement *Curr-block-depth + 6961 (emit-indent *(ebp+8) *Curr-block-depth) + 6962 (write-buffered *(ebp+8) "}\n") + 6963 (write-buffered *(ebp+8) *ecx) # Var-name + 6964 (write-buffered *(ebp+8) ":break:\n") + 6965 } + 6966 $emit-subx-block:end: + 6967 # . restore registers + 6968 5e/pop-to-esi + 6969 59/pop-to-ecx + 6970 58/pop-to-eax + 6971 # . epilogue + 6972 89/<- %esp 5/r32/ebp + 6973 5d/pop-to-ebp + 6974 c3/return + 6975 + 6976 # Primitives supported + 6977 # For each operation, put variants with hard-coded registers before flexible ones. + 6978 == data + 6979 Primitives: + 6980 # - increment/decrement + 6981 _Primitive-inc-eax: + 6982 # var/eax <- increment => 40/increment-eax + 6983 "increment"/imm32/name + 6984 0/imm32/no-inouts + 6985 Single-int-var-in-eax/imm32/outputs + 6986 "40/increment-eax"/imm32/subx-name + 6987 0/imm32/no-rm32 + 6988 0/imm32/no-r32 + 6989 0/imm32/no-imm32 + 6990 0/imm32/no-disp32 + 6991 0/imm32/output-is-write-only + 6992 _Primitive-inc-ecx/imm32/next + 6993 _Primitive-inc-ecx: + 6994 # var/ecx <- increment => 41/increment-ecx + 6995 "increment"/imm32/name + 6996 0/imm32/no-inouts + 6997 Single-int-var-in-ecx/imm32/outputs + 6998 "41/increment-ecx"/imm32/subx-name + 6999 0/imm32/no-rm32 + 7000 0/imm32/no-r32 + 7001 0/imm32/no-imm32 + 7002 0/imm32/no-disp32 + 7003 0/imm32/output-is-write-only + 7004 _Primitive-inc-edx/imm32/next + 7005 _Primitive-inc-edx: + 7006 # var/edx <- increment => 42/increment-edx + 7007 "increment"/imm32/name + 7008 0/imm32/no-inouts + 7009 Single-int-var-in-edx/imm32/outputs + 7010 "42/increment-edx"/imm32/subx-name + 7011 0/imm32/no-rm32 + 7012 0/imm32/no-r32 + 7013 0/imm32/no-imm32 + 7014 0/imm32/no-disp32 + 7015 0/imm32/output-is-write-only + 7016 _Primitive-inc-ebx/imm32/next + 7017 _Primitive-inc-ebx: + 7018 # var/ebx <- increment => 43/increment-ebx + 7019 "increment"/imm32/name + 7020 0/imm32/no-inouts + 7021 Single-int-var-in-ebx/imm32/outputs + 7022 "43/increment-ebx"/imm32/subx-name + 7023 0/imm32/no-rm32 + 7024 0/imm32/no-r32 + 7025 0/imm32/no-imm32 + 7026 0/imm32/no-disp32 + 7027 0/imm32/output-is-write-only + 7028 _Primitive-inc-esi/imm32/next + 7029 _Primitive-inc-esi: + 7030 # var/esi <- increment => 46/increment-esi + 7031 "increment"/imm32/name + 7032 0/imm32/no-inouts + 7033 Single-int-var-in-esi/imm32/outputs + 7034 "46/increment-esi"/imm32/subx-name + 7035 0/imm32/no-rm32 + 7036 0/imm32/no-r32 + 7037 0/imm32/no-imm32 + 7038 0/imm32/no-disp32 + 7039 0/imm32/output-is-write-only + 7040 _Primitive-inc-edi/imm32/next + 7041 _Primitive-inc-edi: + 7042 # var/edi <- increment => 47/increment-edi + 7043 "increment"/imm32/name + 7044 0/imm32/no-inouts + 7045 Single-int-var-in-edi/imm32/outputs + 7046 "47/increment-edi"/imm32/subx-name + 7047 0/imm32/no-rm32 + 7048 0/imm32/no-r32 + 7049 0/imm32/no-imm32 + 7050 0/imm32/no-disp32 + 7051 0/imm32/output-is-write-only + 7052 _Primitive-dec-eax/imm32/next + 7053 _Primitive-dec-eax: + 7054 # var/eax <- decrement => 48/decrement-eax + 7055 "decrement"/imm32/name + 7056 0/imm32/no-inouts + 7057 Single-int-var-in-eax/imm32/outputs + 7058 "48/decrement-eax"/imm32/subx-name + 7059 0/imm32/no-rm32 + 7060 0/imm32/no-r32 + 7061 0/imm32/no-imm32 + 7062 0/imm32/no-disp32 + 7063 0/imm32/output-is-write-only + 7064 _Primitive-dec-ecx/imm32/next + 7065 _Primitive-dec-ecx: + 7066 # var/ecx <- decrement => 49/decrement-ecx + 7067 "decrement"/imm32/name + 7068 0/imm32/no-inouts + 7069 Single-int-var-in-ecx/imm32/outputs + 7070 "49/decrement-ecx"/imm32/subx-name + 7071 0/imm32/no-rm32 + 7072 0/imm32/no-r32 + 7073 0/imm32/no-imm32 + 7074 0/imm32/no-disp32 + 7075 0/imm32/output-is-write-only + 7076 _Primitive-dec-edx/imm32/next + 7077 _Primitive-dec-edx: + 7078 # var/edx <- decrement => 4a/decrement-edx + 7079 "decrement"/imm32/name + 7080 0/imm32/no-inouts + 7081 Single-int-var-in-edx/imm32/outputs + 7082 "4a/decrement-edx"/imm32/subx-name + 7083 0/imm32/no-rm32 + 7084 0/imm32/no-r32 + 7085 0/imm32/no-imm32 + 7086 0/imm32/no-disp32 + 7087 0/imm32/output-is-write-only + 7088 _Primitive-dec-ebx/imm32/next + 7089 _Primitive-dec-ebx: + 7090 # var/ebx <- decrement => 4b/decrement-ebx + 7091 "decrement"/imm32/name + 7092 0/imm32/no-inouts + 7093 Single-int-var-in-ebx/imm32/outputs + 7094 "4b/decrement-ebx"/imm32/subx-name + 7095 0/imm32/no-rm32 + 7096 0/imm32/no-r32 + 7097 0/imm32/no-imm32 + 7098 0/imm32/no-disp32 + 7099 0/imm32/output-is-write-only + 7100 _Primitive-dec-esi/imm32/next + 7101 _Primitive-dec-esi: + 7102 # var/esi <- decrement => 4e/decrement-esi + 7103 "decrement"/imm32/name + 7104 0/imm32/no-inouts + 7105 Single-int-var-in-esi/imm32/outputs + 7106 "4e/decrement-esi"/imm32/subx-name + 7107 0/imm32/no-rm32 + 7108 0/imm32/no-r32 + 7109 0/imm32/no-imm32 + 7110 0/imm32/no-disp32 + 7111 0/imm32/output-is-write-only + 7112 _Primitive-dec-edi/imm32/next + 7113 _Primitive-dec-edi: + 7114 # var/edi <- decrement => 4f/decrement-edi + 7115 "decrement"/imm32/name + 7116 0/imm32/no-inouts + 7117 Single-int-var-in-edi/imm32/outputs + 7118 "4f/decrement-edi"/imm32/subx-name + 7119 0/imm32/no-rm32 + 7120 0/imm32/no-r32 + 7121 0/imm32/no-imm32 + 7122 0/imm32/no-disp32 + 7123 0/imm32/output-is-write-only + 7124 _Primitive-inc-mem/imm32/next + 7125 _Primitive-inc-mem: + 7126 # increment var => ff 0/subop/increment *(ebp+__) + 7127 "increment"/imm32/name + 7128 Single-int-var-in-mem/imm32/inouts + 7129 0/imm32/no-outputs + 7130 "ff 0/subop/increment"/imm32/subx-name + 7131 1/imm32/rm32-is-first-inout + 7132 0/imm32/no-r32 + 7133 0/imm32/no-imm32 + 7134 0/imm32/no-disp32 + 7135 0/imm32/output-is-write-only + 7136 _Primitive-inc-reg/imm32/next + 7137 _Primitive-inc-reg: + 7138 # var/reg <- increment => ff 0/subop/increment %__ + 7139 "increment"/imm32/name + 7140 0/imm32/no-inouts + 7141 Single-int-var-in-some-register/imm32/outputs + 7142 "ff 0/subop/increment"/imm32/subx-name + 7143 3/imm32/rm32-is-first-output + 7144 0/imm32/no-r32 + 7145 0/imm32/no-imm32 + 7146 0/imm32/no-disp32 + 7147 0/imm32/output-is-write-only + 7148 _Primitive-dec-mem/imm32/next + 7149 _Primitive-dec-mem: + 7150 # decrement var => ff 1/subop/decrement *(ebp+__) + 7151 "decrement"/imm32/name + 7152 Single-int-var-in-mem/imm32/inouts + 7153 0/imm32/no-outputs + 7154 "ff 1/subop/decrement"/imm32/subx-name + 7155 1/imm32/rm32-is-first-inout + 7156 0/imm32/no-r32 + 7157 0/imm32/no-imm32 + 7158 0/imm32/no-disp32 + 7159 0/imm32/output-is-write-only + 7160 _Primitive-dec-reg/imm32/next + 7161 _Primitive-dec-reg: + 7162 # var/reg <- decrement => ff 1/subop/decrement %__ + 7163 "decrement"/imm32/name + 7164 0/imm32/no-inouts + 7165 Single-int-var-in-some-register/imm32/outputs + 7166 "ff 1/subop/decrement"/imm32/subx-name + 7167 3/imm32/rm32-is-first-output + 7168 0/imm32/no-r32 + 7169 0/imm32/no-imm32 + 7170 0/imm32/no-disp32 + 7171 0/imm32/output-is-write-only + 7172 _Primitive-add-to-eax/imm32/next + 7173 # - add + 7174 _Primitive-add-to-eax: + 7175 # var/eax <- add lit => 05/add-to-eax lit/imm32 + 7176 "add"/imm32/name + 7177 Single-lit-var/imm32/inouts + 7178 Single-int-var-in-eax/imm32/outputs + 7179 "05/add-to-eax"/imm32/subx-name + 7180 0/imm32/no-rm32 + 7181 0/imm32/no-r32 + 7182 1/imm32/imm32-is-first-inout + 7183 0/imm32/no-disp32 + 7184 0/imm32/output-is-write-only + 7185 _Primitive-add-reg-to-reg/imm32/next + 7186 _Primitive-add-reg-to-reg: + 7187 # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32 + 7188 "add"/imm32/name + 7189 Single-int-var-in-some-register/imm32/inouts + 7190 Single-int-var-in-some-register/imm32/outputs + 7191 "01/add-to"/imm32/subx-name + 7192 3/imm32/rm32-is-first-output + 7193 1/imm32/r32-is-first-inout + 7194 0/imm32/no-imm32 + 7195 0/imm32/no-disp32 + 7196 0/imm32/output-is-write-only + 7197 _Primitive-add-reg-to-mem/imm32/next + 7198 _Primitive-add-reg-to-mem: + 7199 # add-to var1 var2/reg => 01/add-to var1 var2/r32 + 7200 "add-to"/imm32/name + 7201 Two-args-int-stack-int-reg/imm32/inouts + 7202 0/imm32/outputs + 7203 "01/add-to"/imm32/subx-name + 7204 1/imm32/rm32-is-first-inout + 7205 2/imm32/r32-is-second-inout + 7206 0/imm32/no-imm32 + 7207 0/imm32/no-disp32 + 7208 0/imm32/output-is-write-only + 7209 _Primitive-add-mem-to-reg/imm32/next + 7210 _Primitive-add-mem-to-reg: + 7211 # var1/reg <- add var2 => 03/add var2/rm32 var1/r32 + 7212 "add"/imm32/name + 7213 Single-int-var-in-mem/imm32/inouts + 7214 Single-int-var-in-some-register/imm32/outputs + 7215 "03/add"/imm32/subx-name + 7216 1/imm32/rm32-is-first-inout + 7217 3/imm32/r32-is-first-output + 7218 0/imm32/no-imm32 + 7219 0/imm32/no-disp32 + 7220 0/imm32/output-is-write-only + 7221 _Primitive-add-lit-to-reg/imm32/next + 7222 _Primitive-add-lit-to-reg: + 7223 # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32 + 7224 "add"/imm32/name + 7225 Single-lit-var/imm32/inouts + 7226 Single-int-var-in-some-register/imm32/outputs + 7227 "81 0/subop/add"/imm32/subx-name + 7228 3/imm32/rm32-is-first-output + 7229 0/imm32/no-r32 + 7230 1/imm32/imm32-is-first-inout + 7231 0/imm32/no-disp32 + 7232 0/imm32/output-is-write-only + 7233 _Primitive-add-lit-to-mem/imm32/next + 7234 _Primitive-add-lit-to-mem: + 7235 # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32 + 7236 "add-to"/imm32/name + 7237 Int-var-and-literal/imm32/inouts + 7238 0/imm32/outputs + 7239 "81 0/subop/add"/imm32/subx-name + 7240 1/imm32/rm32-is-first-inout + 7241 0/imm32/no-r32 + 7242 2/imm32/imm32-is-second-inout + 7243 0/imm32/no-disp32 + 7244 0/imm32/output-is-write-only + 7245 _Primitive-subtract-from-eax/imm32/next + 7246 # - subtract + 7247 _Primitive-subtract-from-eax: + 7248 # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32 + 7249 "subtract"/imm32/name + 7250 Single-lit-var/imm32/inouts + 7251 Single-int-var-in-eax/imm32/outputs + 7252 "2d/subtract-from-eax"/imm32/subx-name + 7253 0/imm32/no-rm32 + 7254 0/imm32/no-r32 + 7255 1/imm32/imm32-is-first-inout + 7256 0/imm32/no-disp32 + 7257 0/imm32/output-is-write-only + 7258 _Primitive-subtract-reg-from-reg/imm32/next + 7259 _Primitive-subtract-reg-from-reg: + 7260 # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32 + 7261 "subtract"/imm32/name + 7262 Single-int-var-in-some-register/imm32/inouts + 7263 Single-int-var-in-some-register/imm32/outputs + 7264 "29/subtract-from"/imm32/subx-name + 7265 3/imm32/rm32-is-first-output + 7266 1/imm32/r32-is-first-inout + 7267 0/imm32/no-imm32 + 7268 0/imm32/no-disp32 + 7269 0/imm32/output-is-write-only + 7270 _Primitive-subtract-reg-from-mem/imm32/next + 7271 _Primitive-subtract-reg-from-mem: + 7272 # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32 + 7273 "subtract-from"/imm32/name + 7274 Two-args-int-stack-int-reg/imm32/inouts + 7275 0/imm32/outputs + 7276 "29/subtract-from"/imm32/subx-name + 7277 1/imm32/rm32-is-first-inout + 7278 2/imm32/r32-is-second-inout + 7279 0/imm32/no-imm32 + 7280 0/imm32/no-disp32 + 7281 0/imm32/output-is-write-only + 7282 _Primitive-subtract-mem-from-reg/imm32/next + 7283 _Primitive-subtract-mem-from-reg: + 7284 # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32 + 7285 "subtract"/imm32/name + 7286 Single-int-var-in-mem/imm32/inouts + 7287 Single-int-var-in-some-register/imm32/outputs + 7288 "2b/subtract"/imm32/subx-name + 7289 1/imm32/rm32-is-first-inout + 7290 3/imm32/r32-is-first-output + 7291 0/imm32/no-imm32 + 7292 0/imm32/no-disp32 + 7293 0/imm32/output-is-write-only + 7294 _Primitive-subtract-lit-from-reg/imm32/next + 7295 _Primitive-subtract-lit-from-reg: + 7296 # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32 + 7297 "subtract"/imm32/name + 7298 Single-lit-var/imm32/inouts + 7299 Single-int-var-in-some-register/imm32/outputs + 7300 "81 5/subop/subtract"/imm32/subx-name + 7301 3/imm32/rm32-is-first-output + 7302 0/imm32/no-r32 + 7303 1/imm32/imm32-is-first-inout + 7304 0/imm32/no-disp32 + 7305 0/imm32/output-is-write-only + 7306 _Primitive-subtract-lit-from-mem/imm32/next + 7307 _Primitive-subtract-lit-from-mem: + 7308 # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32 + 7309 "subtract-from"/imm32/name + 7310 Int-var-and-literal/imm32/inouts + 7311 0/imm32/outputs + 7312 "81 5/subop/subtract"/imm32/subx-name + 7313 1/imm32/rm32-is-first-inout + 7314 0/imm32/no-r32 + 7315 2/imm32/imm32-is-first-inout + 7316 0/imm32/no-disp32 + 7317 0/imm32/output-is-write-only + 7318 _Primitive-and-with-eax/imm32/next + 7319 # - and + 7320 _Primitive-and-with-eax: + 7321 # var/eax <- and lit => 25/and-with-eax lit/imm32 + 7322 "and"/imm32/name + 7323 Single-lit-var/imm32/inouts + 7324 Single-int-var-in-eax/imm32/outputs + 7325 "25/and-with-eax"/imm32/subx-name + 7326 0/imm32/no-rm32 + 7327 0/imm32/no-r32 + 7328 1/imm32/imm32-is-first-inout + 7329 0/imm32/no-disp32 + 7330 0/imm32/output-is-write-only + 7331 _Primitive-and-reg-with-reg/imm32/next + 7332 _Primitive-and-reg-with-reg: + 7333 # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32 + 7334 "and"/imm32/name + 7335 Single-int-var-in-some-register/imm32/inouts + 7336 Single-int-var-in-some-register/imm32/outputs + 7337 "21/and-with"/imm32/subx-name + 7338 3/imm32/rm32-is-first-output + 7339 1/imm32/r32-is-first-inout + 7340 0/imm32/no-imm32 + 7341 0/imm32/no-disp32 + 7342 0/imm32/output-is-write-only + 7343 _Primitive-and-reg-with-mem/imm32/next + 7344 _Primitive-and-reg-with-mem: + 7345 # and-with var1 var2/reg => 21/and-with var1 var2/r32 + 7346 "and-with"/imm32/name + 7347 Two-args-int-stack-int-reg/imm32/inouts + 7348 0/imm32/outputs + 7349 "21/and-with"/imm32/subx-name + 7350 1/imm32/rm32-is-first-inout + 7351 2/imm32/r32-is-second-inout + 7352 0/imm32/no-imm32 + 7353 0/imm32/no-disp32 + 7354 0/imm32/output-is-write-only + 7355 _Primitive-and-mem-with-reg/imm32/next + 7356 _Primitive-and-mem-with-reg: + 7357 # var1/reg <- and var2 => 23/and var2/rm32 var1/r32 + 7358 "and"/imm32/name + 7359 Single-int-var-in-mem/imm32/inouts + 7360 Single-int-var-in-some-register/imm32/outputs + 7361 "23/and"/imm32/subx-name + 7362 1/imm32/rm32-is-first-inout + 7363 3/imm32/r32-is-first-output + 7364 0/imm32/no-imm32 + 7365 0/imm32/no-disp32 + 7366 0/imm32/output-is-write-only + 7367 _Primitive-and-lit-with-reg/imm32/next + 7368 _Primitive-and-lit-with-reg: + 7369 # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32 + 7370 "and"/imm32/name + 7371 Single-lit-var/imm32/inouts + 7372 Single-int-var-in-some-register/imm32/outputs + 7373 "81 4/subop/and"/imm32/subx-name + 7374 3/imm32/rm32-is-first-output + 7375 0/imm32/no-r32 + 7376 1/imm32/imm32-is-first-inout + 7377 0/imm32/no-disp32 + 7378 0/imm32/output-is-write-only + 7379 _Primitive-and-lit-with-mem/imm32/next + 7380 _Primitive-and-lit-with-mem: + 7381 # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32 + 7382 "and-with"/imm32/name + 7383 Int-var-and-literal/imm32/inouts + 7384 0/imm32/outputs + 7385 "81 4/subop/and"/imm32/subx-name + 7386 1/imm32/rm32-is-first-inout + 7387 0/imm32/no-r32 + 7388 2/imm32/imm32-is-first-inout + 7389 0/imm32/no-disp32 + 7390 0/imm32/output-is-write-only + 7391 _Primitive-or-with-eax/imm32/next + 7392 # - or + 7393 _Primitive-or-with-eax: + 7394 # var/eax <- or lit => 0d/or-with-eax lit/imm32 + 7395 "or"/imm32/name + 7396 Single-lit-var/imm32/inouts + 7397 Single-int-var-in-eax/imm32/outputs + 7398 "0d/or-with-eax"/imm32/subx-name + 7399 0/imm32/no-rm32 + 7400 0/imm32/no-r32 + 7401 1/imm32/imm32-is-first-inout + 7402 0/imm32/no-disp32 + 7403 0/imm32/output-is-write-only + 7404 _Primitive-or-reg-with-reg/imm32/next + 7405 _Primitive-or-reg-with-reg: + 7406 # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32 + 7407 "or"/imm32/name + 7408 Single-int-var-in-some-register/imm32/inouts + 7409 Single-int-var-in-some-register/imm32/outputs + 7410 "09/or-with"/imm32/subx-name + 7411 3/imm32/rm32-is-first-output + 7412 1/imm32/r32-is-first-inout + 7413 0/imm32/no-imm32 + 7414 0/imm32/no-disp32 + 7415 0/imm32/output-is-write-only + 7416 _Primitive-or-reg-with-mem/imm32/next + 7417 _Primitive-or-reg-with-mem: + 7418 # or-with var1 var2/reg => 09/or-with var1 var2/r32 + 7419 "or-with"/imm32/name + 7420 Two-args-int-stack-int-reg/imm32/inouts + 7421 0/imm32/outputs + 7422 "09/or-with"/imm32/subx-name + 7423 1/imm32/rm32-is-first-inout + 7424 2/imm32/r32-is-second-inout + 7425 0/imm32/no-imm32 + 7426 0/imm32/no-disp32 + 7427 0/imm32/output-is-write-only + 7428 _Primitive-or-mem-with-reg/imm32/next + 7429 _Primitive-or-mem-with-reg: + 7430 # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32 + 7431 "or"/imm32/name + 7432 Single-int-var-in-mem/imm32/inouts + 7433 Single-int-var-in-some-register/imm32/outputs + 7434 "0b/or"/imm32/subx-name + 7435 1/imm32/rm32-is-first-inout + 7436 3/imm32/r32-is-first-output + 7437 0/imm32/no-imm32 + 7438 0/imm32/no-disp32 + 7439 0/imm32/output-is-write-only + 7440 _Primitive-or-lit-with-reg/imm32/next + 7441 _Primitive-or-lit-with-reg: + 7442 # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32 + 7443 "or"/imm32/name + 7444 Single-lit-var/imm32/inouts + 7445 Single-int-var-in-some-register/imm32/outputs + 7446 "81 1/subop/or"/imm32/subx-name + 7447 3/imm32/rm32-is-first-output + 7448 0/imm32/no-r32 + 7449 1/imm32/imm32-is-first-inout + 7450 0/imm32/no-disp32 + 7451 0/imm32/output-is-write-only + 7452 _Primitive-or-lit-with-mem/imm32/next + 7453 _Primitive-or-lit-with-mem: + 7454 # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32 + 7455 "or-with"/imm32/name + 7456 Int-var-and-literal/imm32/inouts + 7457 0/imm32/outputs + 7458 "81 1/subop/or"/imm32/subx-name + 7459 1/imm32/rm32-is-first-inout + 7460 0/imm32/no-r32 + 7461 2/imm32/imm32-is-second-inout + 7462 0/imm32/no-disp32 + 7463 0/imm32/output-is-write-only + 7464 _Primitive-xor-with-eax/imm32/next + 7465 # - xor + 7466 _Primitive-xor-with-eax: + 7467 # var/eax <- xor lit => 35/xor-with-eax lit/imm32 + 7468 "xor"/imm32/name + 7469 Single-lit-var/imm32/inouts + 7470 Single-int-var-in-eax/imm32/outputs + 7471 "35/xor-with-eax"/imm32/subx-name + 7472 0/imm32/no-rm32 + 7473 0/imm32/no-r32 + 7474 1/imm32/imm32-is-first-inout + 7475 0/imm32/no-disp32 + 7476 0/imm32/output-is-write-only + 7477 _Primitive-xor-reg-with-reg/imm32/next + 7478 _Primitive-xor-reg-with-reg: + 7479 # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32 + 7480 "xor"/imm32/name + 7481 Single-int-var-in-some-register/imm32/inouts + 7482 Single-int-var-in-some-register/imm32/outputs + 7483 "31/xor-with"/imm32/subx-name + 7484 3/imm32/rm32-is-first-output + 7485 1/imm32/r32-is-first-inout + 7486 0/imm32/no-imm32 + 7487 0/imm32/no-disp32 + 7488 0/imm32/output-is-write-only + 7489 _Primitive-xor-reg-with-mem/imm32/next + 7490 _Primitive-xor-reg-with-mem: + 7491 # xor-with var1 var2/reg => 31/xor-with var1 var2/r32 + 7492 "xor-with"/imm32/name + 7493 Two-args-int-stack-int-reg/imm32/inouts + 7494 0/imm32/outputs + 7495 "31/xor-with"/imm32/subx-name + 7496 1/imm32/rm32-is-first-inout + 7497 2/imm32/r32-is-second-inout + 7498 0/imm32/no-imm32 + 7499 0/imm32/no-disp32 + 7500 0/imm32/output-is-write-only + 7501 _Primitive-xor-mem-with-reg/imm32/next + 7502 _Primitive-xor-mem-with-reg: + 7503 # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32 + 7504 "xor"/imm32/name + 7505 Single-int-var-in-mem/imm32/inouts + 7506 Single-int-var-in-some-register/imm32/outputs + 7507 "33/xor"/imm32/subx-name + 7508 1/imm32/rm32-is-first-inout + 7509 3/imm32/r32-is-first-output + 7510 0/imm32/no-imm32 + 7511 0/imm32/no-disp32 + 7512 0/imm32/output-is-write-only + 7513 _Primitive-xor-lit-with-reg/imm32/next + 7514 _Primitive-xor-lit-with-reg: + 7515 # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32 + 7516 "xor"/imm32/name + 7517 Single-lit-var/imm32/inouts + 7518 Single-int-var-in-some-register/imm32/outputs + 7519 "81 6/subop/xor"/imm32/subx-name + 7520 3/imm32/rm32-is-first-output + 7521 0/imm32/no-r32 + 7522 1/imm32/imm32-is-first-inout + 7523 0/imm32/no-disp32 + 7524 0/imm32/output-is-write-only + 7525 _Primitive-xor-lit-with-mem/imm32/next + 7526 _Primitive-xor-lit-with-mem: + 7527 # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32 + 7528 "xor-with"/imm32/name + 7529 Int-var-and-literal/imm32/inouts + 7530 0/imm32/outputs + 7531 "81 6/subop/xor"/imm32/subx-name + 7532 1/imm32/rm32-is-first-inout + 7533 0/imm32/no-r32 + 7534 2/imm32/imm32-is-first-inout + 7535 0/imm32/no-disp32 + 7536 0/imm32/output-is-write-only + 7537 _Primitive-copy-to-eax/imm32/next + 7538 # - copy + 7539 _Primitive-copy-to-eax: + 7540 # var/eax <- copy lit => b8/copy-to-eax lit/imm32 + 7541 "copy"/imm32/name + 7542 Single-lit-var/imm32/inouts + 7543 Single-int-var-in-eax/imm32/outputs + 7544 "b8/copy-to-eax"/imm32/subx-name + 7545 0/imm32/no-rm32 + 7546 0/imm32/no-r32 + 7547 1/imm32/imm32-is-first-inout + 7548 0/imm32/no-disp32 + 7549 1/imm32/output-is-write-only + 7550 _Primitive-copy-to-ecx/imm32/next + 7551 _Primitive-copy-to-ecx: + 7552 # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32 + 7553 "copy"/imm32/name + 7554 Single-lit-var/imm32/inouts + 7555 Single-int-var-in-ecx/imm32/outputs + 7556 "b9/copy-to-ecx"/imm32/subx-name + 7557 0/imm32/no-rm32 + 7558 0/imm32/no-r32 + 7559 1/imm32/imm32-is-first-inout + 7560 0/imm32/no-disp32 + 7561 1/imm32/output-is-write-only + 7562 _Primitive-copy-to-edx/imm32/next + 7563 _Primitive-copy-to-edx: + 7564 # var/edx <- copy lit => ba/copy-to-edx lit/imm32 + 7565 "copy"/imm32/name + 7566 Single-lit-var/imm32/inouts + 7567 Single-int-var-in-edx/imm32/outputs + 7568 "ba/copy-to-edx"/imm32/subx-name + 7569 0/imm32/no-rm32 + 7570 0/imm32/no-r32 + 7571 1/imm32/imm32-is-first-inout + 7572 0/imm32/no-disp32 + 7573 1/imm32/output-is-write-only + 7574 _Primitive-copy-to-ebx/imm32/next + 7575 _Primitive-copy-to-ebx: + 7576 # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32 + 7577 "copy"/imm32/name + 7578 Single-lit-var/imm32/inouts + 7579 Single-int-var-in-ebx/imm32/outputs + 7580 "bb/copy-to-ebx"/imm32/subx-name + 7581 0/imm32/no-rm32 + 7582 0/imm32/no-r32 + 7583 1/imm32/imm32-is-first-inout + 7584 0/imm32/no-disp32 + 7585 1/imm32/output-is-write-only + 7586 _Primitive-copy-to-esi/imm32/next + 7587 _Primitive-copy-to-esi: + 7588 # var/esi <- copy lit => be/copy-to-esi lit/imm32 + 7589 "copy"/imm32/name + 7590 Single-lit-var/imm32/inouts + 7591 Single-int-var-in-esi/imm32/outputs + 7592 "be/copy-to-esi"/imm32/subx-name + 7593 0/imm32/no-rm32 + 7594 0/imm32/no-r32 + 7595 1/imm32/imm32-is-first-inout + 7596 0/imm32/no-disp32 + 7597 1/imm32/output-is-write-only + 7598 _Primitive-copy-to-edi/imm32/next + 7599 _Primitive-copy-to-edi: + 7600 # var/edi <- copy lit => bf/copy-to-edi lit/imm32 + 7601 "copy"/imm32/name + 7602 Single-lit-var/imm32/inouts + 7603 Single-int-var-in-edi/imm32/outputs + 7604 "bf/copy-to-edi"/imm32/subx-name + 7605 0/imm32/no-rm32 + 7606 0/imm32/no-r32 + 7607 1/imm32/imm32-is-first-inout + 7608 0/imm32/no-disp32 + 7609 1/imm32/output-is-write-only + 7610 _Primitive-copy-reg-to-reg/imm32/next + 7611 _Primitive-copy-reg-to-reg: + 7612 # var1/reg <- copy var2/reg => 89/copy-to var1/rm32 var2/r32 + 7613 "copy"/imm32/name + 7614 Single-int-var-in-some-register/imm32/inouts + 7615 Single-int-var-in-some-register/imm32/outputs + 7616 "89/copy-to"/imm32/subx-name + 7617 3/imm32/rm32-is-first-output + 7618 1/imm32/r32-is-first-inout + 7619 0/imm32/no-imm32 + 7620 0/imm32/no-disp32 + 7621 1/imm32/output-is-write-only + 7622 _Primitive-copy-reg-to-mem/imm32/next + 7623 _Primitive-copy-reg-to-mem: + 7624 # copy-to var1 var2/reg => 89/copy-to var1 var2/r32 + 7625 "copy-to"/imm32/name + 7626 Two-args-int-stack-int-reg/imm32/inouts + 7627 0/imm32/outputs + 7628 "89/copy-to"/imm32/subx-name + 7629 1/imm32/rm32-is-first-inout + 7630 2/imm32/r32-is-second-inout + 7631 0/imm32/no-imm32 + 7632 0/imm32/no-disp32 + 7633 1/imm32/output-is-write-only + 7634 _Primitive-copy-mem-to-reg/imm32/next + 7635 _Primitive-copy-mem-to-reg: + 7636 # var1/reg <- copy var2 => 8b/copy-from var2/rm32 var1/r32 + 7637 "copy"/imm32/name + 7638 Single-int-var-in-mem/imm32/inouts + 7639 Single-int-var-in-some-register/imm32/outputs + 7640 "8b/copy-from"/imm32/subx-name + 7641 1/imm32/rm32-is-first-inout + 7642 3/imm32/r32-is-first-output + 7643 0/imm32/no-imm32 + 7644 0/imm32/no-disp32 + 7645 1/imm32/output-is-write-only + 7646 _Primitive-copy-lit-to-reg/imm32/next + 7647 _Primitive-copy-lit-to-reg: + 7648 # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32 + 7649 "copy"/imm32/name + 7650 Single-lit-var/imm32/inouts + 7651 Single-int-var-in-some-register/imm32/outputs + 7652 "c7 0/subop/copy"/imm32/subx-name + 7653 3/imm32/rm32-is-first-output + 7654 0/imm32/no-r32 + 7655 1/imm32/imm32-is-first-inout + 7656 0/imm32/no-disp32 + 7657 1/imm32/output-is-write-only + 7658 _Primitive-copy-lit-to-mem/imm32/next + 7659 _Primitive-copy-lit-to-mem: + 7660 # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32 + 7661 "copy-to"/imm32/name + 7662 Int-var-and-literal/imm32/inouts + 7663 0/imm32/outputs + 7664 "c7 0/subop/copy"/imm32/subx-name + 7665 1/imm32/rm32-is-first-inout + 7666 0/imm32/no-r32 + 7667 2/imm32/imm32-is-first-inout + 7668 0/imm32/no-disp32 + 7669 1/imm32/output-is-write-only + 7670 _Primitive-compare-mem-with-reg/imm32/next + 7671 # - compare + 7672 _Primitive-compare-mem-with-reg: + 7673 # compare var1 var2/reg => 39/compare-> var1/rm32 var2/r32 + 7674 "compare"/imm32/name + 7675 Two-args-int-stack-int-reg/imm32/inouts + 7676 0/imm32/outputs + 7677 "39/compare->"/imm32/subx-name + 7678 1/imm32/rm32-is-first-inout + 7679 2/imm32/r32-is-second-inout + 7680 0/imm32/no-imm32 + 7681 0/imm32/no-disp32 + 7682 0/imm32/output-is-write-only + 7683 _Primitive-compare-reg-with-mem/imm32/next + 7684 _Primitive-compare-reg-with-mem: + 7685 # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32 + 7686 "compare"/imm32/name + 7687 Two-args-int-reg-int-stack/imm32/inouts + 7688 0/imm32/outputs + 7689 "3b/compare<-"/imm32/subx-name + 7690 2/imm32/rm32-is-second-inout + 7691 1/imm32/r32-is-first-inout + 7692 0/imm32/no-imm32 + 7693 0/imm32/no-disp32 + 7694 0/imm32/output-is-write-only + 7695 _Primitive-compare-eax-with-literal/imm32/next + 7696 _Primitive-compare-eax-with-literal: + 7697 # compare var1/eax n => 3d/compare-eax-with n/imm32 + 7698 "compare"/imm32/name + 7699 Two-args-int-eax-int-literal/imm32/inouts + 7700 0/imm32/outputs + 7701 "3d/compare-eax-with"/imm32/subx-name + 7702 0/imm32/no-rm32 + 7703 0/imm32/no-r32 + 7704 2/imm32/imm32-is-second-inout + 7705 0/imm32/no-disp32 + 7706 0/imm32/output-is-write-only + 7707 _Primitive-compare-reg-with-literal/imm32/next + 7708 _Primitive-compare-reg-with-literal: + 7709 # compare var1/reg n => 81 7/subop/compare %reg n/imm32 + 7710 "compare"/imm32/name + 7711 Int-var-in-register-and-literal/imm32/inouts + 7712 0/imm32/outputs + 7713 "81 7/subop/compare"/imm32/subx-name + 7714 1/imm32/rm32-is-first-inout + 7715 0/imm32/no-r32 + 7716 2/imm32/imm32-is-second-inout + 7717 0/imm32/no-disp32 + 7718 0/imm32/output-is-write-only + 7719 _Primitive-compare-mem-with-literal/imm32/next + 7720 _Primitive-compare-mem-with-literal: + 7721 # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32 + 7722 "compare"/imm32/name + 7723 Int-var-and-literal/imm32/inouts + 7724 0/imm32/outputs + 7725 "81 7/subop/compare"/imm32/subx-name + 7726 1/imm32/rm32-is-first-inout + 7727 0/imm32/no-r32 + 7728 2/imm32/imm32-is-second-inout + 7729 0/imm32/no-disp32 + 7730 0/imm32/output-is-write-only + 7731 _Primitive-multiply-reg-by-mem/imm32/next + 7732 # - multiply + 7733 _Primitive-multiply-reg-by-mem: + 7734 # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32 + 7735 "multiply"/imm32/name + 7736 Single-int-var-in-mem/imm32/inouts + 7737 Single-int-var-in-some-register/imm32/outputs + 7738 "0f af/multiply"/imm32/subx-name + 7739 1/imm32/rm32-is-first-inout + 7740 3/imm32/r32-is-first-output + 7741 0/imm32/no-imm32 + 7742 0/imm32/no-disp32 + 7743 0/imm32/output-is-write-only + 7744 _Primitive-break-if-addr</imm32/next + 7745 # - branches + 7746 _Primitive-break-if-addr<: + 7747 "break-if-addr<"/imm32/name + 7748 0/imm32/inouts + 7749 0/imm32/outputs + 7750 "0f 82/jump-if-addr< break/disp32"/imm32/subx-name + 7751 0/imm32/no-rm32 + 7752 0/imm32/no-r32 + 7753 0/imm32/no-imm32 + 7754 0/imm32/no-disp32 + 7755 0/imm32/no-output + 7756 _Primitive-break-if-addr>=/imm32/next + 7757 _Primitive-break-if-addr>=: + 7758 "break-if-addr>="/imm32/name + 7759 0/imm32/inouts + 7760 0/imm32/outputs + 7761 "0f 83/jump-if-addr>= break/disp32"/imm32/subx-name + 7762 0/imm32/no-rm32 + 7763 0/imm32/no-r32 + 7764 0/imm32/no-imm32 + 7765 0/imm32/no-disp32 + 7766 0/imm32/no-output + 7767 _Primitive-break-if-=/imm32/next + 7768 _Primitive-break-if-=: + 7769 "break-if-="/imm32/name + 7770 0/imm32/inouts + 7771 0/imm32/outputs + 7772 "0f 84/jump-if-= break/disp32"/imm32/subx-name + 7773 0/imm32/no-rm32 + 7774 0/imm32/no-r32 + 7775 0/imm32/no-imm32 + 7776 0/imm32/no-disp32 + 7777 0/imm32/no-output + 7778 _Primitive-break-if-!=/imm32/next + 7779 _Primitive-break-if-!=: + 7780 "break-if-!="/imm32/name + 7781 0/imm32/inouts + 7782 0/imm32/outputs + 7783 "0f 85/jump-if-!= break/disp32"/imm32/subx-name + 7784 0/imm32/no-rm32 + 7785 0/imm32/no-r32 + 7786 0/imm32/no-imm32 + 7787 0/imm32/no-disp32 + 7788 0/imm32/no-output + 7789 _Primitive-break-if-addr<=/imm32/next + 7790 _Primitive-break-if-addr<=: + 7791 "break-if-addr<="/imm32/name + 7792 0/imm32/inouts + 7793 0/imm32/outputs + 7794 "0f 86/jump-if-addr<= break/disp32"/imm32/subx-name + 7795 0/imm32/no-rm32 + 7796 0/imm32/no-r32 + 7797 0/imm32/no-imm32 + 7798 0/imm32/no-disp32 + 7799 0/imm32/no-output + 7800 _Primitive-break-if-addr>/imm32/next + 7801 _Primitive-break-if-addr>: + 7802 "break-if-addr>"/imm32/name + 7803 0/imm32/inouts + 7804 0/imm32/outputs + 7805 "0f 87/jump-if-addr> break/disp32"/imm32/subx-name + 7806 0/imm32/no-rm32 + 7807 0/imm32/no-r32 + 7808 0/imm32/no-imm32 + 7809 0/imm32/no-disp32 + 7810 0/imm32/no-output + 7811 _Primitive-break-if-</imm32/next + 7812 _Primitive-break-if-<: + 7813 "break-if-<"/imm32/name + 7814 0/imm32/inouts + 7815 0/imm32/outputs + 7816 "0f 8c/jump-if-< break/disp32"/imm32/subx-name + 7817 0/imm32/no-rm32 + 7818 0/imm32/no-r32 + 7819 0/imm32/no-imm32 + 7820 0/imm32/no-disp32 + 7821 0/imm32/no-output + 7822 _Primitive-break-if->=/imm32/next + 7823 _Primitive-break-if->=: + 7824 "break-if->="/imm32/name + 7825 0/imm32/inouts + 7826 0/imm32/outputs + 7827 "0f 8d/jump-if->= break/disp32"/imm32/subx-name + 7828 0/imm32/no-rm32 + 7829 0/imm32/no-r32 + 7830 0/imm32/no-imm32 + 7831 0/imm32/no-disp32 + 7832 0/imm32/no-output + 7833 _Primitive-break-if-<=/imm32/next + 7834 _Primitive-break-if-<=: + 7835 "break-if-<="/imm32/name + 7836 0/imm32/inouts + 7837 0/imm32/outputs + 7838 "0f 8e/jump-if-<= break/disp32"/imm32/subx-name + 7839 0/imm32/no-rm32 + 7840 0/imm32/no-r32 + 7841 0/imm32/no-imm32 + 7842 0/imm32/no-disp32 + 7843 0/imm32/no-output + 7844 _Primitive-break-if->/imm32/next + 7845 _Primitive-break-if->: + 7846 "break-if->"/imm32/name + 7847 0/imm32/inouts + 7848 0/imm32/outputs + 7849 "0f 8f/jump-if-> break/disp32"/imm32/subx-name + 7850 0/imm32/no-rm32 + 7851 0/imm32/no-r32 + 7852 0/imm32/no-imm32 + 7853 0/imm32/no-disp32 + 7854 0/imm32/no-output + 7855 _Primitive-break/imm32/next + 7856 _Primitive-break: + 7857 "break"/imm32/name + 7858 0/imm32/inouts + 7859 0/imm32/outputs + 7860 "e9/jump break/disp32"/imm32/subx-name + 7861 0/imm32/no-rm32 + 7862 0/imm32/no-r32 + 7863 0/imm32/no-imm32 + 7864 0/imm32/no-disp32 + 7865 0/imm32/no-output + 7866 _Primitive-loop-if-addr</imm32/next + 7867 _Primitive-loop-if-addr<: + 7868 "loop-if-addr<"/imm32/name + 7869 0/imm32/inouts + 7870 0/imm32/outputs + 7871 "0f 82/jump-if-addr< loop/disp32"/imm32/subx-name + 7872 0/imm32/no-rm32 + 7873 0/imm32/no-r32 + 7874 0/imm32/no-imm32 + 7875 0/imm32/no-disp32 + 7876 0/imm32/no-output + 7877 _Primitive-loop-if-addr>=/imm32/next + 7878 _Primitive-loop-if-addr>=: + 7879 "loop-if-addr>="/imm32/name + 7880 0/imm32/inouts + 7881 0/imm32/outputs + 7882 "0f 83/jump-if-addr>= loop/disp32"/imm32/subx-name + 7883 0/imm32/no-rm32 + 7884 0/imm32/no-r32 + 7885 0/imm32/no-imm32 + 7886 0/imm32/no-disp32 + 7887 0/imm32/no-output + 7888 _Primitive-loop-if-=/imm32/next + 7889 _Primitive-loop-if-=: + 7890 "loop-if-="/imm32/name + 7891 0/imm32/inouts + 7892 0/imm32/outputs + 7893 "0f 84/jump-if-= loop/disp32"/imm32/subx-name + 7894 0/imm32/no-rm32 + 7895 0/imm32/no-r32 + 7896 0/imm32/no-imm32 + 7897 0/imm32/no-disp32 + 7898 0/imm32/no-output + 7899 _Primitive-loop-if-!=/imm32/next + 7900 _Primitive-loop-if-!=: + 7901 "loop-if-!="/imm32/name + 7902 0/imm32/inouts + 7903 0/imm32/outputs + 7904 "0f 85/jump-if-!= loop/disp32"/imm32/subx-name + 7905 0/imm32/no-rm32 + 7906 0/imm32/no-r32 + 7907 0/imm32/no-imm32 + 7908 0/imm32/no-disp32 + 7909 0/imm32/no-output + 7910 _Primitive-loop-if-addr<=/imm32/next + 7911 _Primitive-loop-if-addr<=: + 7912 "loop-if-addr<="/imm32/name + 7913 0/imm32/inouts + 7914 0/imm32/outputs + 7915 "0f 86/jump-if-addr<= loop/disp32"/imm32/subx-name + 7916 0/imm32/no-rm32 + 7917 0/imm32/no-r32 + 7918 0/imm32/no-imm32 + 7919 0/imm32/no-disp32 + 7920 0/imm32/no-output + 7921 _Primitive-loop-if-addr>/imm32/next + 7922 _Primitive-loop-if-addr>: + 7923 "loop-if-addr>"/imm32/name + 7924 0/imm32/inouts + 7925 0/imm32/outputs + 7926 "0f 87/jump-if-addr> loop/disp32"/imm32/subx-name + 7927 0/imm32/no-rm32 + 7928 0/imm32/no-r32 + 7929 0/imm32/no-imm32 + 7930 0/imm32/no-disp32 + 7931 0/imm32/no-output + 7932 _Primitive-loop-if-</imm32/next + 7933 _Primitive-loop-if-<: + 7934 "loop-if-<"/imm32/name + 7935 0/imm32/inouts + 7936 0/imm32/outputs + 7937 "0f 8c/jump-if-< loop/disp32"/imm32/subx-name + 7938 0/imm32/no-rm32 + 7939 0/imm32/no-r32 + 7940 0/imm32/no-imm32 + 7941 0/imm32/no-disp32 + 7942 0/imm32/no-output + 7943 _Primitive-loop-if->=/imm32/next + 7944 _Primitive-loop-if->=: + 7945 "loop-if->="/imm32/name + 7946 0/imm32/inouts + 7947 0/imm32/outputs + 7948 "0f 8d/jump-if->= loop/disp32"/imm32/subx-name + 7949 0/imm32/no-rm32 + 7950 0/imm32/no-r32 + 7951 0/imm32/no-imm32 + 7952 0/imm32/no-disp32 + 7953 0/imm32/no-output + 7954 _Primitive-loop-if-<=/imm32/next + 7955 _Primitive-loop-if-<=: + 7956 "loop-if-<="/imm32/name + 7957 0/imm32/inouts + 7958 0/imm32/outputs + 7959 "0f 8e/jump-if-<= loop/disp32"/imm32/subx-name + 7960 0/imm32/no-rm32 + 7961 0/imm32/no-r32 + 7962 0/imm32/no-imm32 + 7963 0/imm32/no-disp32 + 7964 0/imm32/no-output + 7965 _Primitive-loop-if->/imm32/next + 7966 _Primitive-loop-if->: + 7967 "loop-if->"/imm32/name + 7968 0/imm32/inouts + 7969 0/imm32/outputs + 7970 "0f 8f/jump-if-> loop/disp32"/imm32/subx-name + 7971 0/imm32/no-rm32 + 7972 0/imm32/no-r32 + 7973 0/imm32/no-imm32 + 7974 0/imm32/no-disp32 + 7975 0/imm32/no-output + 7976 _Primitive-loop/imm32/next # we probably don't need an unconditional break + 7977 _Primitive-loop: + 7978 "loop"/imm32/name + 7979 0/imm32/inouts + 7980 0/imm32/outputs + 7981 "e9/jump loop/disp32"/imm32/subx-name + 7982 0/imm32/no-rm32 + 7983 0/imm32/no-r32 + 7984 0/imm32/no-imm32 + 7985 0/imm32/no-disp32 + 7986 0/imm32/no-output + 7987 _Primitive-break-if-addr<-named/imm32/next + 7988 # - branches to named blocks + 7989 _Primitive-break-if-addr<-named: + 7990 "break-if-addr<"/imm32/name + 7991 Single-lit-var/imm32/inouts + 7992 0/imm32/outputs + 7993 "0f 82/jump-if-addr<"/imm32/subx-name + 7994 0/imm32/no-rm32 + 7995 0/imm32/no-r32 + 7996 0/imm32/no-imm32 + 7997 1/imm32/disp32-is-first-inout + 7998 0/imm32/no-output + 7999 _Primitive-break-if-addr>=-named/imm32/next + 8000 _Primitive-break-if-addr>=-named: + 8001 "break-if-addr>="/imm32/name + 8002 Single-lit-var/imm32/inouts + 8003 0/imm32/outputs + 8004 "0f 83/jump-if-addr>="/imm32/subx-name + 8005 0/imm32/no-rm32 + 8006 0/imm32/no-r32 + 8007 0/imm32/no-imm32 + 8008 1/imm32/disp32-is-first-inout + 8009 0/imm32/no-output + 8010 _Primitive-break-if-=-named/imm32/next + 8011 _Primitive-break-if-=-named: + 8012 "break-if-="/imm32/name + 8013 Single-lit-var/imm32/inouts + 8014 0/imm32/outputs + 8015 "0f 84/jump-if-="/imm32/subx-name + 8016 0/imm32/no-rm32 + 8017 0/imm32/no-r32 + 8018 0/imm32/no-imm32 + 8019 1/imm32/disp32-is-first-inout + 8020 0/imm32/no-output + 8021 _Primitive-break-if-!=-named/imm32/next + 8022 _Primitive-break-if-!=-named: + 8023 "break-if-!="/imm32/name + 8024 Single-lit-var/imm32/inouts + 8025 0/imm32/outputs + 8026 "0f 85/jump-if-!="/imm32/subx-name + 8027 0/imm32/no-rm32 + 8028 0/imm32/no-r32 + 8029 0/imm32/no-imm32 + 8030 1/imm32/disp32-is-first-inout + 8031 0/imm32/no-output + 8032 _Primitive-break-if-addr<=-named/imm32/next + 8033 _Primitive-break-if-addr<=-named: + 8034 "break-if-addr<="/imm32/name + 8035 Single-lit-var/imm32/inouts + 8036 0/imm32/outputs + 8037 "0f 86/jump-if-addr<="/imm32/subx-name + 8038 0/imm32/no-rm32 + 8039 0/imm32/no-r32 + 8040 0/imm32/no-imm32 + 8041 1/imm32/disp32-is-first-inout + 8042 0/imm32/no-output + 8043 _Primitive-break-if-addr>-named/imm32/next + 8044 _Primitive-break-if-addr>-named: + 8045 "break-if-addr>"/imm32/name + 8046 Single-lit-var/imm32/inouts + 8047 0/imm32/outputs + 8048 "0f 87/jump-if-addr>"/imm32/subx-name + 8049 0/imm32/no-rm32 + 8050 0/imm32/no-r32 + 8051 0/imm32/no-imm32 + 8052 1/imm32/disp32-is-first-inout + 8053 0/imm32/no-output + 8054 _Primitive-break-if-<-named/imm32/next + 8055 _Primitive-break-if-<-named: + 8056 "break-if-<"/imm32/name + 8057 Single-lit-var/imm32/inouts + 8058 0/imm32/outputs + 8059 "0f 8c/jump-if-<"/imm32/subx-name + 8060 0/imm32/no-rm32 + 8061 0/imm32/no-r32 + 8062 0/imm32/no-imm32 + 8063 1/imm32/disp32-is-first-inout + 8064 0/imm32/no-output + 8065 _Primitive-break-if->=-named/imm32/next + 8066 _Primitive-break-if->=-named: + 8067 "break-if->="/imm32/name + 8068 Single-lit-var/imm32/inouts + 8069 0/imm32/outputs + 8070 "0f 8d/jump-if->="/imm32/subx-name + 8071 0/imm32/no-rm32 + 8072 0/imm32/no-r32 + 8073 0/imm32/no-imm32 + 8074 1/imm32/disp32-is-first-inout + 8075 0/imm32/no-output + 8076 _Primitive-break-if-<=-named/imm32/next + 8077 _Primitive-break-if-<=-named: + 8078 "break-if-<="/imm32/name + 8079 Single-lit-var/imm32/inouts + 8080 0/imm32/outputs + 8081 "0f 8e/jump-if-<="/imm32/subx-name + 8082 0/imm32/no-rm32 + 8083 0/imm32/no-r32 + 8084 0/imm32/no-imm32 + 8085 1/imm32/disp32-is-first-inout + 8086 0/imm32/no-output + 8087 _Primitive-break-if->-named/imm32/next + 8088 _Primitive-break-if->-named: + 8089 "break-if->"/imm32/name + 8090 Single-lit-var/imm32/inouts + 8091 0/imm32/outputs + 8092 "0f 8f/jump-if->"/imm32/subx-name + 8093 0/imm32/no-rm32 + 8094 0/imm32/no-r32 + 8095 0/imm32/no-imm32 + 8096 1/imm32/disp32-is-first-inout + 8097 0/imm32/no-output + 8098 _Primitive-break-named/imm32/next + 8099 _Primitive-break-named: + 8100 "break"/imm32/name + 8101 Single-lit-var/imm32/inouts + 8102 0/imm32/outputs + 8103 "e9/jump"/imm32/subx-name + 8104 0/imm32/no-rm32 + 8105 0/imm32/no-r32 + 8106 0/imm32/no-imm32 + 8107 1/imm32/disp32-is-first-inout + 8108 0/imm32/no-output + 8109 _Primitive-loop-if-addr<-named/imm32/next + 8110 _Primitive-loop-if-addr<-named: + 8111 "loop-if-addr<"/imm32/name + 8112 Single-lit-var/imm32/inouts + 8113 0/imm32/outputs + 8114 "0f 82/jump-if-addr<"/imm32/subx-name + 8115 0/imm32/no-rm32 + 8116 0/imm32/no-r32 + 8117 0/imm32/no-imm32 + 8118 1/imm32/disp32-is-first-inout + 8119 0/imm32/no-output + 8120 _Primitive-loop-if-addr>=-named/imm32/next + 8121 _Primitive-loop-if-addr>=-named: + 8122 "loop-if-addr>="/imm32/name + 8123 Single-lit-var/imm32/inouts + 8124 0/imm32/outputs + 8125 "0f 83/jump-if-addr>="/imm32/subx-name + 8126 0/imm32/no-rm32 + 8127 0/imm32/no-r32 + 8128 0/imm32/no-imm32 + 8129 1/imm32/disp32-is-first-inout + 8130 0/imm32/no-output + 8131 _Primitive-loop-if-=-named/imm32/next + 8132 _Primitive-loop-if-=-named: + 8133 "loop-if-="/imm32/name + 8134 Single-lit-var/imm32/inouts + 8135 0/imm32/outputs + 8136 "0f 84/jump-if-="/imm32/subx-name + 8137 0/imm32/no-rm32 + 8138 0/imm32/no-r32 + 8139 0/imm32/no-imm32 + 8140 1/imm32/disp32-is-first-inout + 8141 0/imm32/no-output + 8142 _Primitive-loop-if-!=-named/imm32/next + 8143 _Primitive-loop-if-!=-named: + 8144 "loop-if-!="/imm32/name + 8145 Single-lit-var/imm32/inouts + 8146 0/imm32/outputs + 8147 "0f 85/jump-if-!="/imm32/subx-name + 8148 0/imm32/no-rm32 + 8149 0/imm32/no-r32 + 8150 0/imm32/no-imm32 + 8151 1/imm32/disp32-is-first-inout + 8152 0/imm32/no-output + 8153 _Primitive-loop-if-addr<=-named/imm32/next + 8154 _Primitive-loop-if-addr<=-named: + 8155 "loop-if-addr<="/imm32/name + 8156 Single-lit-var/imm32/inouts + 8157 0/imm32/outputs + 8158 "0f 86/jump-if-addr<="/imm32/subx-name + 8159 0/imm32/no-rm32 + 8160 0/imm32/no-r32 + 8161 0/imm32/no-imm32 + 8162 1/imm32/disp32-is-first-inout + 8163 0/imm32/no-output + 8164 _Primitive-loop-if-addr>-named/imm32/next + 8165 _Primitive-loop-if-addr>-named: + 8166 "loop-if-addr>"/imm32/name + 8167 Single-lit-var/imm32/inouts + 8168 0/imm32/outputs + 8169 "0f 87/jump-if-addr>"/imm32/subx-name + 8170 0/imm32/no-rm32 + 8171 0/imm32/no-r32 + 8172 0/imm32/no-imm32 + 8173 1/imm32/disp32-is-first-inout + 8174 0/imm32/no-output + 8175 _Primitive-loop-if-<-named/imm32/next + 8176 _Primitive-loop-if-<-named: + 8177 "loop-if-<"/imm32/name + 8178 Single-lit-var/imm32/inouts + 8179 0/imm32/outputs + 8180 "0f 8c/jump-if-<"/imm32/subx-name + 8181 0/imm32/no-rm32 + 8182 0/imm32/no-r32 + 8183 0/imm32/no-imm32 + 8184 1/imm32/disp32-is-first-inout + 8185 0/imm32/no-output + 8186 _Primitive-loop-if->=-named/imm32/next + 8187 _Primitive-loop-if->=-named: + 8188 "loop-if->="/imm32/name + 8189 Single-lit-var/imm32/inouts + 8190 0/imm32/outputs + 8191 "0f 8d/jump-if->="/imm32/subx-name + 8192 0/imm32/no-rm32 + 8193 0/imm32/no-r32 + 8194 0/imm32/no-imm32 + 8195 1/imm32/disp32-is-first-inout + 8196 0/imm32/no-output + 8197 _Primitive-loop-if-<=-named/imm32/next + 8198 _Primitive-loop-if-<=-named: + 8199 "loop-if-<="/imm32/name + 8200 Single-lit-var/imm32/inouts + 8201 0/imm32/outputs + 8202 "0f 8e/jump-if-<="/imm32/subx-name + 8203 0/imm32/no-rm32 + 8204 0/imm32/no-r32 + 8205 0/imm32/no-imm32 + 8206 1/imm32/disp32-is-first-inout + 8207 0/imm32/no-output + 8208 _Primitive-loop-if->-named/imm32/next + 8209 _Primitive-loop-if->-named: + 8210 "loop-if->"/imm32/name + 8211 Single-lit-var/imm32/inouts + 8212 0/imm32/outputs + 8213 "0f 8f/jump-if->"/imm32/subx-name + 8214 0/imm32/no-rm32 + 8215 0/imm32/no-r32 + 8216 0/imm32/no-imm32 + 8217 1/imm32/disp32-is-first-inout + 8218 0/imm32/no-output + 8219 _Primitive-loop-named/imm32/next # we probably don't need an unconditional break + 8220 _Primitive-loop-named: + 8221 "loop"/imm32/name + 8222 Single-lit-var/imm32/inouts + 8223 0/imm32/outputs + 8224 "e9/jump"/imm32/subx-name + 8225 0/imm32/no-rm32 + 8226 0/imm32/no-r32 + 8227 0/imm32/no-imm32 + 8228 1/imm32/disp32-is-first-inout + 8229 0/imm32/no-output + 8230 0/imm32/next + 8231 + 8232 Single-int-var-in-mem: + 8233 Int-var-in-mem/imm32 8234 0/imm32/next 8235 - 8236 Single-int-var-in-mem: - 8237 Int-var-in-mem/imm32 - 8238 0/imm32/next - 8239 - 8240 Int-var-in-mem: - 8241 "arg1"/imm32/name - 8242 Type-int/imm32 - 8243 1/imm32/some-block-depth - 8244 1/imm32/some-stack-offset - 8245 0/imm32/no-register + 8236 Int-var-in-mem: + 8237 "arg1"/imm32/name + 8238 Type-int/imm32 + 8239 1/imm32/some-block-depth + 8240 1/imm32/some-stack-offset + 8241 0/imm32/no-register + 8242 + 8243 Two-args-int-stack-int-reg: + 8244 Int-var-in-mem/imm32 + 8245 Single-int-var-in-some-register/imm32/next 8246 - 8247 Two-args-int-stack-int-reg: - 8248 Int-var-in-mem/imm32 - 8249 Single-int-var-in-some-register/imm32/next + 8247 Two-args-int-reg-int-stack: + 8248 Int-var-in-some-register/imm32 + 8249 Single-int-var-in-mem/imm32/next 8250 - 8251 Two-args-int-reg-int-stack: - 8252 Int-var-in-some-register/imm32 - 8253 Single-int-var-in-mem/imm32/next + 8251 Two-args-int-eax-int-literal: + 8252 Int-var-in-eax/imm32 + 8253 Single-lit-var/imm32/next 8254 - 8255 Two-args-int-eax-int-literal: - 8256 Int-var-in-eax/imm32 - 8257 Single-lit-var/imm32/next + 8255 Int-var-and-literal: + 8256 Int-var-in-mem/imm32 + 8257 Single-lit-var/imm32/next 8258 - 8259 Int-var-and-literal: - 8260 Int-var-in-mem/imm32 - 8261 Single-lit-var/imm32/next + 8259 Int-var-in-register-and-literal: + 8260 Int-var-in-some-register/imm32 + 8261 Single-lit-var/imm32/next 8262 - 8263 Int-var-in-register-and-literal: - 8264 Int-var-in-some-register/imm32 - 8265 Single-lit-var/imm32/next + 8263 Single-int-var-in-some-register: + 8264 Int-var-in-some-register/imm32 + 8265 0/imm32/next 8266 - 8267 Single-int-var-in-some-register: - 8268 Int-var-in-some-register/imm32 - 8269 0/imm32/next - 8270 - 8271 Int-var-in-some-register: - 8272 "arg1"/imm32/name - 8273 Type-int/imm32 - 8274 1/imm32/some-block-depth - 8275 0/imm32/no-stack-offset - 8276 Any-register/imm32 + 8267 Int-var-in-some-register: + 8268 "arg1"/imm32/name + 8269 Type-int/imm32 + 8270 1/imm32/some-block-depth + 8271 0/imm32/no-stack-offset + 8272 Any-register/imm32 + 8273 + 8274 Single-int-var-in-eax: + 8275 Int-var-in-eax/imm32 + 8276 0/imm32/next 8277 - 8278 Single-int-var-in-eax: - 8279 Int-var-in-eax/imm32 - 8280 0/imm32/next - 8281 - 8282 Int-var-in-eax: - 8283 "arg1"/imm32/name - 8284 Type-int/imm32 - 8285 1/imm32/some-block-depth - 8286 0/imm32/no-stack-offset - 8287 "eax"/imm32/register + 8278 Int-var-in-eax: + 8279 "arg1"/imm32/name + 8280 Type-int/imm32 + 8281 1/imm32/some-block-depth + 8282 0/imm32/no-stack-offset + 8283 "eax"/imm32/register + 8284 + 8285 Single-int-var-in-ecx: + 8286 Int-var-in-ecx/imm32 + 8287 0/imm32/next 8288 - 8289 Single-int-var-in-ecx: - 8290 Int-var-in-ecx/imm32 - 8291 0/imm32/next - 8292 - 8293 Int-var-in-ecx: - 8294 "arg1"/imm32/name - 8295 Type-int/imm32 - 8296 1/imm32/some-block-depth - 8297 0/imm32/no-stack-offset - 8298 "ecx"/imm32/register + 8289 Int-var-in-ecx: + 8290 "arg1"/imm32/name + 8291 Type-int/imm32 + 8292 1/imm32/some-block-depth + 8293 0/imm32/no-stack-offset + 8294 "ecx"/imm32/register + 8295 + 8296 Single-int-var-in-edx: + 8297 Int-var-in-edx/imm32 + 8298 0/imm32/next 8299 - 8300 Single-int-var-in-edx: - 8301 Int-var-in-edx/imm32 - 8302 0/imm32/next - 8303 - 8304 Int-var-in-edx: - 8305 "arg1"/imm32/name - 8306 Type-int/imm32 - 8307 1/imm32/some-block-depth - 8308 0/imm32/no-stack-offset - 8309 "edx"/imm32/register + 8300 Int-var-in-edx: + 8301 "arg1"/imm32/name + 8302 Type-int/imm32 + 8303 1/imm32/some-block-depth + 8304 0/imm32/no-stack-offset + 8305 "edx"/imm32/register + 8306 + 8307 Single-int-var-in-ebx: + 8308 Int-var-in-ebx/imm32 + 8309 0/imm32/next 8310 - 8311 Single-int-var-in-ebx: - 8312 Int-var-in-ebx/imm32 - 8313 0/imm32/next - 8314 - 8315 Int-var-in-ebx: - 8316 "arg1"/imm32/name - 8317 Type-int/imm32 - 8318 1/imm32/some-block-depth - 8319 0/imm32/no-stack-offset - 8320 "ebx"/imm32/register + 8311 Int-var-in-ebx: + 8312 "arg1"/imm32/name + 8313 Type-int/imm32 + 8314 1/imm32/some-block-depth + 8315 0/imm32/no-stack-offset + 8316 "ebx"/imm32/register + 8317 + 8318 Single-int-var-in-esi: + 8319 Int-var-in-esi/imm32 + 8320 0/imm32/next 8321 - 8322 Single-int-var-in-esi: - 8323 Int-var-in-esi/imm32 - 8324 0/imm32/next - 8325 - 8326 Int-var-in-esi: - 8327 "arg1"/imm32/name - 8328 Type-int/imm32 - 8329 1/imm32/some-block-depth - 8330 0/imm32/no-stack-offset - 8331 "esi"/imm32/register + 8322 Int-var-in-esi: + 8323 "arg1"/imm32/name + 8324 Type-int/imm32 + 8325 1/imm32/some-block-depth + 8326 0/imm32/no-stack-offset + 8327 "esi"/imm32/register + 8328 + 8329 Single-int-var-in-edi: + 8330 Int-var-in-edi/imm32 + 8331 0/imm32/next 8332 - 8333 Single-int-var-in-edi: - 8334 Int-var-in-edi/imm32 - 8335 0/imm32/next - 8336 - 8337 Int-var-in-edi: - 8338 "arg1"/imm32/name - 8339 Type-int/imm32 - 8340 1/imm32/some-block-depth - 8341 0/imm32/no-stack-offset - 8342 "edi"/imm32/register + 8333 Int-var-in-edi: + 8334 "arg1"/imm32/name + 8335 Type-int/imm32 + 8336 1/imm32/some-block-depth + 8337 0/imm32/no-stack-offset + 8338 "edi"/imm32/register + 8339 + 8340 Single-lit-var: + 8341 Lit-var/imm32 + 8342 0/imm32/next 8343 - 8344 Single-lit-var: - 8345 Lit-var/imm32 - 8346 0/imm32/next - 8347 - 8348 Lit-var: - 8349 "literal"/imm32/name - 8350 Type-literal/imm32 - 8351 1/imm32/some-block-depth - 8352 0/imm32/no-stack-offset - 8353 0/imm32/no-register + 8344 Lit-var: + 8345 "literal"/imm32/name + 8346 Type-literal/imm32 + 8347 1/imm32/some-block-depth + 8348 0/imm32/no-stack-offset + 8349 0/imm32/no-register + 8350 + 8351 Type-int: + 8352 1/imm32/left/int + 8353 0/imm32/right/null 8354 - 8355 Type-int: - 8356 1/imm32/left/int + 8355 Type-literal: + 8356 0/imm32/left/literal 8357 0/imm32/right/null 8358 - 8359 Type-literal: - 8360 0/imm32/left/literal - 8361 0/imm32/right/null - 8362 - 8363 == code - 8364 emit-subx-primitive: # out: (addr buffered-file), stmt: (handle stmt), primitive: (handle function) - 8365 # . prologue - 8366 55/push-ebp - 8367 89/<- %ebp 4/r32/esp - 8368 # . save registers - 8369 50/push-eax - 8370 51/push-ecx - 8371 # ecx = primitive - 8372 8b/-> *(ebp+0x10) 1/r32/ecx - 8373 # emit primitive name - 8374 (emit-indent *(ebp+8) *Curr-block-depth) - 8375 (write-buffered *(ebp+8) *(ecx+0xc)) # Primitive-subx-name - 8376 # emit rm32 if necessary - 8377 (emit-subx-rm32 *(ebp+8) *(ecx+0x10) *(ebp+0xc)) # out, Primitive-subx-rm32, stmt - 8378 # emit r32 if necessary - 8379 (emit-subx-r32 *(ebp+8) *(ecx+0x14) *(ebp+0xc)) # out, Primitive-subx-r32, stmt - 8380 # emit imm32 if necessary - 8381 (emit-subx-imm32 *(ebp+8) *(ecx+0x18) *(ebp+0xc)) # out, Primitive-subx-imm32, stmt - 8382 # emit disp32 if necessary - 8383 (emit-subx-disp32 *(ebp+8) *(ecx+0x1c) *(ebp+0xc)) # out, Primitive-subx-disp32, stmt - 8384 (write-buffered *(ebp+8) Newline) - 8385 $emit-subx-primitive:end: - 8386 # . restore registers - 8387 59/pop-to-ecx - 8388 58/pop-to-eax - 8389 # . epilogue - 8390 89/<- %esp 5/r32/ebp - 8391 5d/pop-to-ebp - 8392 c3/return - 8393 - 8394 emit-subx-rm32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) - 8395 # . prologue - 8396 55/push-ebp - 8397 89/<- %ebp 4/r32/esp - 8398 # . save registers - 8399 50/push-eax - 8400 # if (l == 0) return - 8401 81 7/subop/compare *(ebp+0xc) 0/imm32 - 8402 74/jump-if-= $emit-subx-rm32:end/disp8 - 8403 # var v/eax: (handle var) - 8404 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax - 8405 (emit-subx-var-as-rm32 *(ebp+8) %eax) - 8406 $emit-subx-rm32:end: - 8407 # . restore registers - 8408 58/pop-to-eax - 8409 # . epilogue - 8410 89/<- %esp 5/r32/ebp - 8411 5d/pop-to-ebp - 8412 c3/return - 8413 - 8414 get-stmt-operand-from-arg-location: # stmt: (handle stmt), l: arg-location -> var/eax: (handle stmt-var) - 8415 # . prologue - 8416 55/push-ebp - 8417 89/<- %ebp 4/r32/esp - 8418 # . save registers - 8419 51/push-ecx - 8420 # eax = l - 8421 8b/-> *(ebp+0xc) 0/r32/eax - 8422 # ecx = stmt - 8423 8b/-> *(ebp+8) 1/r32/ecx - 8424 # if (l == 1) return stmt->inouts - 8425 { - 8426 3d/compare-eax-and 1/imm32 - 8427 75/jump-if-!= break/disp8 - 8428 $get-stmt-operand-from-arg-location:1: - 8429 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts - 8430 eb/jump $get-stmt-operand-from-arg-location:end/disp8 - 8431 } - 8432 # if (l == 2) return stmt->inouts->next - 8433 { - 8434 3d/compare-eax-and 2/imm32 - 8435 75/jump-if-!= break/disp8 - 8436 $get-stmt-operand-from-arg-location:2: - 8437 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts - 8438 8b/-> *(eax+4) 0/r32/eax # Stmt-var-next - 8439 eb/jump $get-stmt-operand-from-arg-location:end/disp8 - 8440 } - 8441 # if (l == 3) return stmt->outputs - 8442 { - 8443 3d/compare-eax-and 3/imm32 - 8444 75/jump-if-!= break/disp8 - 8445 $get-stmt-operand-from-arg-location:3: - 8446 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs - 8447 eb/jump $get-stmt-operand-from-arg-location:end/disp8 - 8448 } - 8449 # abort - 8450 e9/jump $get-stmt-operand-from-arg-location:abort/disp32 - 8451 $get-stmt-operand-from-arg-location:end: - 8452 # . restore registers - 8453 59/pop-to-ecx - 8454 # . epilogue - 8455 89/<- %esp 5/r32/ebp - 8456 5d/pop-to-ebp - 8457 c3/return - 8458 - 8459 $get-stmt-operand-from-arg-location:abort: - 8460 # error("invalid arg-location " eax) - 8461 (write-buffered Stderr "invalid arg-location ") - 8462 (print-int32-buffered Stderr %eax) - 8463 (write-buffered Stderr Newline) - 8464 (flush Stderr) - 8465 # . syscall(exit, 1) - 8466 bb/copy-to-ebx 1/imm32 - 8467 b8/copy-to-eax 1/imm32/exit - 8468 cd/syscall 0x80/imm8 - 8469 # never gets here - 8470 - 8471 emit-subx-r32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) - 8472 # . prologue - 8473 55/push-ebp - 8474 89/<- %ebp 4/r32/esp - 8475 # . save registers - 8476 50/push-eax - 8477 51/push-ecx - 8478 # if (location == 0) return - 8479 81 7/subop/compare *(ebp+0xc) 0/imm32 - 8480 0f 84/jump-if-= $emit-subx-r32:end/disp32 - 8481 # var v/eax: (handle var) - 8482 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax - 8483 8b/-> *eax 0/r32/eax # Stmt-var-value - 8484 (maybe-get Registers *(eax+0x10) 8) # Var-register => eax: (addr register-index) - 8485 (write-buffered *(ebp+8) Space) - 8486 (print-int32-buffered *(ebp+8) *eax) - 8487 (write-buffered *(ebp+8) "/r32") - 8488 $emit-subx-r32:end: - 8489 # . restore registers - 8490 59/pop-to-ecx - 8491 58/pop-to-eax - 8492 # . epilogue - 8493 89/<- %esp 5/r32/ebp - 8494 5d/pop-to-ebp - 8495 c3/return - 8496 - 8497 emit-subx-imm32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) - 8498 # . prologue - 8499 55/push-ebp - 8500 89/<- %ebp 4/r32/esp - 8501 # . save registers - 8502 50/push-eax - 8503 51/push-ecx - 8504 # if (location == 0) return - 8505 81 7/subop/compare *(ebp+0xc) 0/imm32 - 8506 74/jump-if-= $emit-subx-imm32:end/disp8 - 8507 # var v/eax: (handle var) - 8508 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax - 8509 8b/-> *eax 0/r32/eax # Stmt-var-value - 8510 (write-buffered *(ebp+8) Space) - 8511 (write-buffered *(ebp+8) *eax) # Var-name - 8512 (write-buffered *(ebp+8) "/imm32") - 8513 $emit-subx-imm32:end: - 8514 # . restore registers - 8515 59/pop-to-ecx - 8516 58/pop-to-eax - 8517 # . epilogue - 8518 89/<- %esp 5/r32/ebp - 8519 5d/pop-to-ebp - 8520 c3/return - 8521 - 8522 emit-subx-disp32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) - 8523 # . prologue - 8524 55/push-ebp - 8525 89/<- %ebp 4/r32/esp - 8526 # . save registers - 8527 50/push-eax - 8528 51/push-ecx - 8529 # if (location == 0) return - 8530 81 7/subop/compare *(ebp+0xc) 0/imm32 - 8531 0f 84/jump-if-= $emit-subx-disp32:end/disp32 - 8532 # var v/eax: (handle var) - 8533 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax - 8534 8b/-> *eax 0/r32/eax # Stmt-var-value - 8535 (write-buffered *(ebp+8) Space) - 8536 (write-buffered *(ebp+8) *eax) # Var-name - 8537 # hack: if instruction operation starts with "break", emit ":break" - 8538 # var name/ecx: (addr array byte) = stmt->operation - 8539 8b/-> *(ebp+0x10) 0/r32/eax - 8540 8b/-> *(eax+4) 1/r32/ecx - 8541 { - 8542 (string-starts-with? %ecx "break") # => eax - 8543 3d/compare-eax-and 0/imm32/false - 8544 74/jump-if-= break/disp8 - 8545 (write-buffered *(ebp+8) ":break") - 8546 } - 8547 # hack: if instruction operation starts with "loop", emit ":loop" - 8548 { - 8549 (string-starts-with? %ecx "loop") # => eax - 8550 3d/compare-eax-and 0/imm32/false - 8551 74/jump-if-= break/disp8 - 8552 (write-buffered *(ebp+8) ":loop") - 8553 } - 8554 (write-buffered *(ebp+8) "/disp32") - 8555 $emit-subx-disp32:end: - 8556 # . restore registers - 8557 59/pop-to-ecx - 8558 58/pop-to-eax - 8559 # . epilogue - 8560 89/<- %esp 5/r32/ebp - 8561 5d/pop-to-ebp - 8562 c3/return - 8563 - 8564 emit-subx-call: # out: (addr buffered-file), stmt: (handle stmt), callee: (handle function) - 8565 # . prologue - 8566 55/push-ebp - 8567 89/<- %ebp 4/r32/esp - 8568 # . save registers - 8569 51/push-ecx - 8570 # - 8571 (emit-indent *(ebp+8) *Curr-block-depth) - 8572 (write-buffered *(ebp+8) "(") - 8573 # - emit function name - 8574 8b/-> *(ebp+0x10) 1/r32/ecx - 8575 (write-buffered *(ebp+8) *(ecx+4)) # Function-subx-name - 8576 # - emit arguments - 8577 # var curr/ecx: (handle stmt-var) = stmt->inouts - 8578 8b/-> *(ebp+0xc) 1/r32/ecx - 8579 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts - 8580 { - 8581 # if (curr == null) break - 8582 81 7/subop/compare %ecx 0/imm32 - 8583 74/jump-if-= break/disp8 - 8584 # - 8585 (emit-subx-call-operand *(ebp+8) %ecx) - 8586 # curr = curr->next - 8587 8b/-> *(ecx+4) 1/r32/ecx # Stmt-var-next - 8588 eb/jump loop/disp8 - 8589 } - 8590 # - 8591 (write-buffered *(ebp+8) ")\n") - 8592 $emit-subx-call:end: - 8593 # . restore registers - 8594 59/pop-to-ecx - 8595 # . epilogue - 8596 89/<- %esp 5/r32/ebp - 8597 5d/pop-to-ebp - 8598 c3/return - 8599 - 8600 # like a function call, except we have no idea what function it is - 8601 # we hope it's defined in SubX and that the types are ok - 8602 emit-hailmary-call: # out: (addr buffered-file), stmt: (handle stmt) - 8603 # . prologue - 8604 55/push-ebp - 8605 89/<- %ebp 4/r32/esp - 8606 # . save registers - 8607 51/push-ecx - 8608 # - 8609 (emit-indent *(ebp+8) *Curr-block-depth) - 8610 (write-buffered *(ebp+8) "(") - 8611 # ecx = stmt - 8612 8b/-> *(ebp+0xc) 1/r32/ecx - 8613 # - emit function name - 8614 (write-buffered *(ebp+8) *(ecx+4)) # Stmt1-operation - 8615 # - emit arguments - 8616 # var curr/ecx: (handle stmt-var) = stmt->inouts - 8617 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts - 8618 { - 8619 # if (curr == null) break - 8620 81 7/subop/compare %ecx 0/imm32 - 8621 74/jump-if-= break/disp8 - 8622 # - 8623 (emit-subx-call-operand *(ebp+8) %ecx) - 8624 # curr = curr->next - 8625 8b/-> *(ecx+4) 1/r32/ecx # Stmt-var-next - 8626 eb/jump loop/disp8 - 8627 } - 8628 # - 8629 (write-buffered *(ebp+8) ")\n") - 8630 $emit-hailmary-call:end: - 8631 # . restore registers - 8632 59/pop-to-ecx - 8633 # . epilogue - 8634 89/<- %esp 5/r32/ebp - 8635 5d/pop-to-ebp - 8636 c3/return - 8637 - 8638 emit-subx-call-operand: # out: (addr buffered-file), s: (handle stmt-var) - 8639 # shares code with emit-subx-var-as-rm32 - 8640 # . prologue - 8641 55/push-ebp - 8642 89/<- %ebp 4/r32/esp - 8643 # . save registers - 8644 50/push-eax - 8645 51/push-ecx - 8646 56/push-esi - 8647 # ecx = s - 8648 8b/-> *(ebp+0xc) 1/r32/ecx - 8649 # var operand/esi: (handle var) = s->value - 8650 8b/-> *ecx 6/r32/esi # Stmt-var-value - 8651 # if (operand->register && s->is-deref?) emit "*__" - 8652 { - 8653 $emit-subx-call-operand:check-for-register-indirect: - 8654 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register - 8655 74/jump-if-= break/disp8 - 8656 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref - 8657 74/jump-if-= break/disp8 - 8658 $emit-subx-call-operand:register-indirect: - 8659 (write-buffered *(ebp+8) " *") - 8660 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register - 8661 e9/jump $emit-subx-call-operand:end/disp32 - 8662 } - 8663 # if (operand->register && !s->is-deref?) emit "%__" - 8664 { - 8665 $emit-subx-call-operand:check-for-register-direct: - 8666 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register - 8667 74/jump-if-= break/disp8 - 8668 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref - 8669 75/jump-if-!= break/disp8 - 8670 $emit-subx-call-operand:register-direct: - 8671 (write-buffered *(ebp+8) " %") - 8672 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register - 8673 e9/jump $emit-subx-call-operand:end/disp32 - 8674 } - 8675 # else if (operand->stack-offset) emit "*(ebp+__)" - 8676 { - 8677 81 7/subop/compare *(esi+0xc) 0/imm32 # Var-offset - 8678 74/jump-if-= break/disp8 - 8679 $emit-subx-call-operand:stack: - 8680 (write-buffered *(ebp+8) Space) - 8681 (write-buffered *(ebp+8) "*(ebp+") - 8682 (print-int32-buffered *(ebp+8) *(esi+0xc)) # Var-offset - 8683 (write-buffered *(ebp+8) ")") - 8684 e9/jump $emit-subx-call-operand:end/disp32 - 8685 } - 8686 # else if (operand->type == literal) emit "__" - 8687 { - 8688 8b/-> *(esi+4) 0/r32/eax # Var-type - 8689 81 7/subop/compare *eax 0/imm32 # Tree-left - 8690 75/jump-if-!= break/disp8 - 8691 $emit-subx-call-operand:literal: - 8692 (write-buffered *(ebp+8) Space) - 8693 (write-buffered *(ebp+8) *esi) - 8694 } - 8695 $emit-subx-call-operand:end: - 8696 # . restore registers - 8697 5e/pop-to-esi - 8698 59/pop-to-ecx - 8699 58/pop-to-eax - 8700 # . epilogue - 8701 89/<- %esp 5/r32/ebp - 8702 5d/pop-to-ebp - 8703 c3/return - 8704 - 8705 emit-subx-var-as-rm32: # out: (addr buffered-file), s: (handle stmt-var) - 8706 # . prologue - 8707 55/push-ebp - 8708 89/<- %ebp 4/r32/esp - 8709 # . save registers - 8710 50/push-eax - 8711 51/push-ecx - 8712 56/push-esi - 8713 # ecx = s - 8714 8b/-> *(ebp+0xc) 1/r32/ecx - 8715 # var operand/esi: (handle var) = s->value - 8716 8b/-> *ecx 6/r32/esi # Stmt-var-value - 8717 # if (operand->register && s->is-deref?) emit "*__" - 8718 { - 8719 $emit-subx-var-as-rm32:check-for-register-indirect: - 8720 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register - 8721 74/jump-if-= break/disp8 - 8722 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref - 8723 74/jump-if-= break/disp8 - 8724 $emit-subx-var-as-rm32:register-indirect: - 8725 (write-buffered *(ebp+8) " *") - 8726 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register - 8727 } - 8728 # if (operand->register && !s->is-deref?) emit "%__" - 8729 { - 8730 $emit-subx-var-as-rm32:check-for-register-direct: - 8731 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register - 8732 74/jump-if-= break/disp8 - 8733 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref - 8734 75/jump-if-!= break/disp8 - 8735 $emit-subx-var-as-rm32:register-direct: - 8736 (write-buffered *(ebp+8) " %") - 8737 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register - 8738 } - 8739 # else if (operand->stack-offset) emit "*(ebp+__)" - 8740 { - 8741 81 7/subop/compare *(esi+0xc) 0/imm32 # Var-offset - 8742 74/jump-if-= break/disp8 - 8743 $emit-subx-var-as-rm32:stack: - 8744 (write-buffered *(ebp+8) Space) - 8745 (write-buffered *(ebp+8) "*(ebp+") - 8746 (print-int32-buffered *(ebp+8) *(esi+0xc)) # Var-offset - 8747 (write-buffered *(ebp+8) ")") - 8748 } - 8749 $emit-subx-var-as-rm32:end: - 8750 # . restore registers - 8751 5e/pop-to-esi - 8752 59/pop-to-ecx - 8753 58/pop-to-eax - 8754 # . epilogue - 8755 89/<- %esp 5/r32/ebp - 8756 5d/pop-to-ebp - 8757 c3/return - 8758 - 8759 find-matching-function: # functions: (addr function), stmt: (handle stmt) -> result/eax: (handle function) - 8760 # . prologue - 8761 55/push-ebp - 8762 89/<- %ebp 4/r32/esp - 8763 # . save registers - 8764 51/push-ecx - 8765 # var curr/ecx: (handle function) = functions - 8766 8b/-> *(ebp+8) 1/r32/ecx - 8767 { - 8768 # if (curr == null) break - 8769 81 7/subop/compare %ecx 0/imm32 - 8770 74/jump-if-= break/disp8 - 8771 # if match(stmt, curr) return curr - 8772 { - 8773 (mu-stmt-matches-function? *(ebp+0xc) %ecx) # => eax - 8774 3d/compare-eax-and 0/imm32/false - 8775 74/jump-if-= break/disp8 - 8776 89/<- %eax 1/r32/ecx - 8777 eb/jump $find-matching-function:end/disp8 - 8778 } - 8779 # curr = curr->next - 8780 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next - 8781 eb/jump loop/disp8 - 8782 } - 8783 # return null - 8784 b8/copy-to-eax 0/imm32 - 8785 $find-matching-function:end: - 8786 # . restore registers - 8787 59/pop-to-ecx - 8788 # . epilogue - 8789 89/<- %esp 5/r32/ebp - 8790 5d/pop-to-ebp - 8791 c3/return - 8792 - 8793 find-matching-primitive: # primitives: (handle primitive), stmt: (handle stmt) -> result/eax: (handle primitive) - 8794 # . prologue - 8795 55/push-ebp - 8796 89/<- %ebp 4/r32/esp - 8797 # . save registers - 8798 51/push-ecx - 8799 # var curr/ecx: (handle primitive) = primitives - 8800 8b/-> *(ebp+8) 1/r32/ecx - 8801 { - 8802 $find-matching-primitive:loop: - 8803 # if (curr == null) break - 8804 81 7/subop/compare %ecx 0/imm32 - 8805 0f 84/jump-if-= break/disp32 - 8806 #? (write-buffered Stderr "prim: ") - 8807 #? (write-buffered Stderr *ecx) # Primitive-name - 8808 #? (write-buffered Stderr " => ") - 8809 #? (write-buffered Stderr *(ecx+0xc)) # Primitive-subx-name - 8810 #? (write-buffered Stderr Newline) - 8811 #? (flush Stderr) - 8812 # if match(curr, stmt) return curr - 8813 { - 8814 (mu-stmt-matches-primitive? *(ebp+0xc) %ecx) # => eax - 8815 3d/compare-eax-and 0/imm32/false - 8816 74/jump-if-= break/disp8 - 8817 89/<- %eax 1/r32/ecx - 8818 eb/jump $find-matching-primitive:end/disp8 - 8819 } - 8820 $find-matching-primitive:next-primitive: - 8821 # curr = curr->next - 8822 8b/-> *(ecx+0x24) 1/r32/ecx # Primitive-next - 8823 e9/jump loop/disp32 - 8824 } - 8825 # return null - 8826 b8/copy-to-eax 0/imm32 - 8827 $find-matching-primitive:end: - 8828 # . restore registers - 8829 59/pop-to-ecx - 8830 # . epilogue - 8831 89/<- %esp 5/r32/ebp - 8832 5d/pop-to-ebp - 8833 c3/return - 8834 - 8835 mu-stmt-matches-function?: # stmt: (handle stmt), function: (handle function) -> result/eax: boolean - 8836 # . prologue - 8837 55/push-ebp - 8838 89/<- %ebp 4/r32/esp - 8839 # . save registers - 8840 51/push-ecx - 8841 # return function->name == stmt->operation - 8842 8b/-> *(ebp+8) 1/r32/ecx - 8843 8b/-> *(ebp+0xc) 0/r32/eax - 8844 (string-equal? *(ecx+4) *eax) # Stmt1-operation, Function-name => eax - 8845 $mu-stmt-matches-function?:end: - 8846 # . restore registers - 8847 59/pop-to-ecx - 8848 # . epilogue - 8849 89/<- %esp 5/r32/ebp - 8850 5d/pop-to-ebp - 8851 c3/return - 8852 - 8853 mu-stmt-matches-primitive?: # stmt: (handle stmt), primitive: (handle primitive) -> result/eax: boolean - 8854 # A mu stmt matches a primitive if the name matches, all the inout vars - 8855 # match, and all the output vars match. - 8856 # Vars match if types match and registers match. - 8857 # In addition, a stmt output matches a primitive's output if types match - 8858 # and the primitive has a wildcard register. - 8859 # . prologue - 8860 55/push-ebp - 8861 89/<- %ebp 4/r32/esp - 8862 # . save registers - 8863 51/push-ecx - 8864 52/push-edx - 8865 53/push-ebx - 8866 56/push-esi - 8867 57/push-edi - 8868 # ecx = stmt - 8869 8b/-> *(ebp+8) 1/r32/ecx - 8870 # edx = primitive - 8871 8b/-> *(ebp+0xc) 2/r32/edx - 8872 { - 8873 $mu-stmt-matches-primitive?:check-name: - 8874 # if (primitive->name != stmt->operation) return false - 8875 (string-equal? *(ecx+4) *edx) # Stmt1-operation, Primitive-name => eax - 8876 3d/compare-eax-and 0/imm32/false - 8877 75/jump-if-!= break/disp8 - 8878 b8/copy-to-eax 0/imm32 - 8879 e9/jump $mu-stmt-matches-primitive?:end/disp32 - 8880 } - 8881 $mu-stmt-matches-primitive?:check-inouts: - 8882 # for (curr/esi in stmt->inouts, curr2/edi in primitive->inouts) - 8883 8b/-> *(ecx+8) 6/r32/esi # Stmt1-inouts or Regvardef-inouts - 8884 8b/-> *(edx+4) 7/r32/edi # Primitive-inouts - 8885 { - 8886 # if (curr == 0 && curr2 == 0) move on to check outputs - 8887 { - 8888 81 7/subop/compare %esi 0/imm32 - 8889 75/jump-if-!= break/disp8 - 8890 $mu-stmt-matches-primitive?:stmt-inout-is-null: - 8891 { - 8892 81 7/subop/compare %edi 0/imm32 - 8893 75/jump-if-!= break/disp8 - 8894 # - 8895 e9/jump $mu-stmt-matches-primitive?:check-outputs/disp32 - 8896 } - 8897 # return false - 8898 b8/copy-to-eax 0/imm32/false - 8899 e9/jump $mu-stmt-matches-primitive?:end/disp32 - 8900 } - 8901 # if (curr2 == 0) return false - 8902 { - 8903 81 7/subop/compare %edi 0/imm32 - 8904 75/jump-if-!= break/disp8 - 8905 $mu-stmt-matches-primitive?:prim-inout-is-null: - 8906 b8/copy-to-eax 0/imm32/false - 8907 e9/jump $mu-stmt-matches-primitive?:end/disp32 - 8908 } - 8909 # if (curr != curr2) return false - 8910 { - 8911 (operand-matches-primitive? %esi *edi) # List-value => eax - 8912 3d/compare-eax-and 0/imm32/false - 8913 75/jump-if-!= break/disp8 - 8914 b8/copy-to-eax 0/imm32/false - 8915 e9/jump $mu-stmt-matches-primitive?:end/disp32 - 8916 } - 8917 # curr=curr->next - 8918 8b/-> *(esi+4) 6/r32/esi # Stmt-var-next - 8919 # curr2=curr2->next - 8920 8b/-> *(edi+4) 7/r32/edi # Stmt-var-next - 8921 eb/jump loop/disp8 - 8922 } - 8923 $mu-stmt-matches-primitive?:check-outputs: - 8924 # for (curr/esi in stmt->outputs, curr2/edi in primitive->outputs) - 8925 8b/-> *(ecx+0xc) 6/r32/esi # Stmt1-outputs - 8926 8b/-> *(edx+8) 7/r32/edi # Primitive-outputs - 8927 { - 8928 # if (curr == 0) return (curr2 == 0) - 8929 { - 8930 $mu-stmt-matches-primitive?:check-output: - 8931 81 7/subop/compare %esi 0/imm32 - 8932 75/jump-if-!= break/disp8 - 8933 { - 8934 81 7/subop/compare %edi 0/imm32 - 8935 75/jump-if-!= break/disp8 - 8936 # return true - 8937 b8/copy-to-eax 1/imm32 - 8938 e9/jump $mu-stmt-matches-primitive?:end/disp32 - 8939 } - 8940 # return false - 8941 b8/copy-to-eax 0/imm32 - 8942 e9/jump $mu-stmt-matches-primitive?:end/disp32 - 8943 } - 8944 # if (curr2 == 0) return false - 8945 { - 8946 81 7/subop/compare %edi 0/imm32 - 8947 75/jump-if-!= break/disp8 - 8948 b8/copy-to-eax 0/imm32 - 8949 e9/jump $mu-stmt-matches-primitive?:end/disp32 - 8950 } - 8951 # if (curr != curr2) return false - 8952 { - 8953 (operand-matches-primitive? %esi *edi) # List-value => eax - 8954 3d/compare-eax-and 0/imm32/false - 8955 75/jump-if-!= break/disp8 - 8956 b8/copy-to-eax 0/imm32 - 8957 e9/jump $mu-stmt-matches-primitive?:end/disp32 - 8958 } - 8959 # curr=curr->next - 8960 8b/-> *(esi+4) 6/r32/esi # Stmt-var-next - 8961 # curr2=curr2->next - 8962 8b/-> *(edi+4) 7/r32/edi # Stmt-var-next - 8963 eb/jump loop/disp8 - 8964 } - 8965 $mu-stmt-matches-primitive?:return-true: - 8966 b8/copy-to-eax 1/imm32 - 8967 $mu-stmt-matches-primitive?:end: - 8968 # . restore registers - 8969 5f/pop-to-edi - 8970 5e/pop-to-esi - 8971 5b/pop-to-ebx - 8972 5a/pop-to-edx - 8973 59/pop-to-ecx - 8974 # . epilogue - 8975 89/<- %esp 5/r32/ebp - 8976 5d/pop-to-ebp - 8977 c3/return - 8978 - 8979 operand-matches-primitive?: # s: (handle stmt-var), prim-var: (handle var) -> result/eax: boolean - 8980 # . prologue - 8981 55/push-ebp - 8982 89/<- %ebp 4/r32/esp - 8983 # . save registers - 8984 51/push-ecx - 8985 56/push-esi - 8986 57/push-edi - 8987 # ecx = s - 8988 8b/-> *(ebp+8) 1/r32/ecx - 8989 # var var/esi : (handle var) = s->value - 8990 8b/-> *ecx 6/r32/esi # Stmt-var-value - 8991 # edi = prim-var - 8992 8b/-> *(ebp+0xc) 7/r32/edi - 8993 $operand-matches-primitive?:check-type: - 8994 # if (var->type != prim-var->type) return false - 8995 (subx-type-equal? *(esi+4) *(edi+4)) # Var-type, Var-type => eax - 8996 3d/compare-eax-and 0/imm32/false - 8997 b8/copy-to-eax 0/imm32/false - 8998 0f 84/jump-if-= $operand-matches-primitive?:end/disp32 - 8999 { - 9000 $operand-matches-primitive?:check-register: - 9001 # if prim-var is in memory and var is in register but dereference, match - 9002 { - 9003 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register - 9004 0f 85/jump-if-!= break/disp32 - 9005 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register - 9006 74/jump-if-= break/disp8 - 9007 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref - 9008 74/jump-if-= break/disp8 - 9009 e9/jump $operand-matches-primitive?:return-true/disp32 - 9010 } - 9011 # if prim-var is in register and var is in register but dereference, no match - 9012 { - 9013 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register - 9014 0f 84/jump-if-= break/disp32 - 9015 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register - 9016 0f 84/jump-if-= break/disp32 - 9017 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref - 9018 74/jump-if-= break/disp8 - 9019 e9/jump $operand-matches-primitive?:return-false/disp32 - 9020 } - 9021 # return false if var->register doesn't match prim-var->register - 9022 { - 9023 # if register addresses are equal, it's a match - 9024 8b/-> *(esi+0x10) 0/r32/eax # Var-register - 9025 39/compare *(edi+0x10) 0/r32/eax # Var-register - 9026 74/jump-if-= break/disp8 - 9027 # if either address is 0, return false - 9028 3d/compare-eax-and 0/imm32 - 9029 74/jump-if-= $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result - 9030 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register - 9031 74/jump-if-= $operand-matches-primitive?:return-false/disp8 - 9032 # if prim-var->register is wildcard, it's a match - 9033 (string-equal? *(edi+0x10) Any-register) # Var-register => eax + 8359 == code + 8360 emit-subx-primitive: # out: (addr buffered-file), stmt: (handle stmt), primitive: (handle function) + 8361 # . prologue + 8362 55/push-ebp + 8363 89/<- %ebp 4/r32/esp + 8364 # . save registers + 8365 50/push-eax + 8366 51/push-ecx + 8367 # ecx = primitive + 8368 8b/-> *(ebp+0x10) 1/r32/ecx + 8369 # emit primitive name + 8370 (emit-indent *(ebp+8) *Curr-block-depth) + 8371 (write-buffered *(ebp+8) *(ecx+0xc)) # Primitive-subx-name + 8372 # emit rm32 if necessary + 8373 (emit-subx-rm32 *(ebp+8) *(ecx+0x10) *(ebp+0xc)) # out, Primitive-subx-rm32, stmt + 8374 # emit r32 if necessary + 8375 (emit-subx-r32 *(ebp+8) *(ecx+0x14) *(ebp+0xc)) # out, Primitive-subx-r32, stmt + 8376 # emit imm32 if necessary + 8377 (emit-subx-imm32 *(ebp+8) *(ecx+0x18) *(ebp+0xc)) # out, Primitive-subx-imm32, stmt + 8378 # emit disp32 if necessary + 8379 (emit-subx-disp32 *(ebp+8) *(ecx+0x1c) *(ebp+0xc)) # out, Primitive-subx-disp32, stmt + 8380 (write-buffered *(ebp+8) Newline) + 8381 $emit-subx-primitive:end: + 8382 # . restore registers + 8383 59/pop-to-ecx + 8384 58/pop-to-eax + 8385 # . epilogue + 8386 89/<- %esp 5/r32/ebp + 8387 5d/pop-to-ebp + 8388 c3/return + 8389 + 8390 emit-subx-rm32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) + 8391 # . prologue + 8392 55/push-ebp + 8393 89/<- %ebp 4/r32/esp + 8394 # . save registers + 8395 50/push-eax + 8396 # if (l == 0) return + 8397 81 7/subop/compare *(ebp+0xc) 0/imm32 + 8398 74/jump-if-= $emit-subx-rm32:end/disp8 + 8399 # var v/eax: (handle var) + 8400 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax + 8401 (emit-subx-var-as-rm32 *(ebp+8) %eax) + 8402 $emit-subx-rm32:end: + 8403 # . restore registers + 8404 58/pop-to-eax + 8405 # . epilogue + 8406 89/<- %esp 5/r32/ebp + 8407 5d/pop-to-ebp + 8408 c3/return + 8409 + 8410 get-stmt-operand-from-arg-location: # stmt: (handle stmt), l: arg-location -> var/eax: (handle stmt-var) + 8411 # . prologue + 8412 55/push-ebp + 8413 89/<- %ebp 4/r32/esp + 8414 # . save registers + 8415 51/push-ecx + 8416 # eax = l + 8417 8b/-> *(ebp+0xc) 0/r32/eax + 8418 # ecx = stmt + 8419 8b/-> *(ebp+8) 1/r32/ecx + 8420 # if (l == 1) return stmt->inouts + 8421 { + 8422 3d/compare-eax-and 1/imm32 + 8423 75/jump-if-!= break/disp8 + 8424 $get-stmt-operand-from-arg-location:1: + 8425 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts + 8426 eb/jump $get-stmt-operand-from-arg-location:end/disp8 + 8427 } + 8428 # if (l == 2) return stmt->inouts->next + 8429 { + 8430 3d/compare-eax-and 2/imm32 + 8431 75/jump-if-!= break/disp8 + 8432 $get-stmt-operand-from-arg-location:2: + 8433 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts + 8434 8b/-> *(eax+4) 0/r32/eax # Stmt-var-next + 8435 eb/jump $get-stmt-operand-from-arg-location:end/disp8 + 8436 } + 8437 # if (l == 3) return stmt->outputs + 8438 { + 8439 3d/compare-eax-and 3/imm32 + 8440 75/jump-if-!= break/disp8 + 8441 $get-stmt-operand-from-arg-location:3: + 8442 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs + 8443 eb/jump $get-stmt-operand-from-arg-location:end/disp8 + 8444 } + 8445 # abort + 8446 e9/jump $get-stmt-operand-from-arg-location:abort/disp32 + 8447 $get-stmt-operand-from-arg-location:end: + 8448 # . restore registers + 8449 59/pop-to-ecx + 8450 # . epilogue + 8451 89/<- %esp 5/r32/ebp + 8452 5d/pop-to-ebp + 8453 c3/return + 8454 + 8455 $get-stmt-operand-from-arg-location:abort: + 8456 # error("invalid arg-location " eax) + 8457 (write-buffered Stderr "invalid arg-location ") + 8458 (print-int32-buffered Stderr %eax) + 8459 (write-buffered Stderr Newline) + 8460 (flush Stderr) + 8461 # . syscall(exit, 1) + 8462 bb/copy-to-ebx 1/imm32 + 8463 b8/copy-to-eax 1/imm32/exit + 8464 cd/syscall 0x80/imm8 + 8465 # never gets here + 8466 + 8467 emit-subx-r32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) + 8468 # . prologue + 8469 55/push-ebp + 8470 89/<- %ebp 4/r32/esp + 8471 # . save registers + 8472 50/push-eax + 8473 51/push-ecx + 8474 # if (location == 0) return + 8475 81 7/subop/compare *(ebp+0xc) 0/imm32 + 8476 0f 84/jump-if-= $emit-subx-r32:end/disp32 + 8477 # var v/eax: (handle var) + 8478 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax + 8479 8b/-> *eax 0/r32/eax # Stmt-var-value + 8480 (maybe-get Registers *(eax+0x10) 8) # Var-register => eax: (addr register-index) + 8481 (write-buffered *(ebp+8) Space) + 8482 (print-int32-buffered *(ebp+8) *eax) + 8483 (write-buffered *(ebp+8) "/r32") + 8484 $emit-subx-r32:end: + 8485 # . restore registers + 8486 59/pop-to-ecx + 8487 58/pop-to-eax + 8488 # . epilogue + 8489 89/<- %esp 5/r32/ebp + 8490 5d/pop-to-ebp + 8491 c3/return + 8492 + 8493 emit-subx-imm32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) + 8494 # . prologue + 8495 55/push-ebp + 8496 89/<- %ebp 4/r32/esp + 8497 # . save registers + 8498 50/push-eax + 8499 51/push-ecx + 8500 # if (location == 0) return + 8501 81 7/subop/compare *(ebp+0xc) 0/imm32 + 8502 74/jump-if-= $emit-subx-imm32:end/disp8 + 8503 # var v/eax: (handle var) + 8504 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax + 8505 8b/-> *eax 0/r32/eax # Stmt-var-value + 8506 (write-buffered *(ebp+8) Space) + 8507 (write-buffered *(ebp+8) *eax) # Var-name + 8508 (write-buffered *(ebp+8) "/imm32") + 8509 $emit-subx-imm32:end: + 8510 # . restore registers + 8511 59/pop-to-ecx + 8512 58/pop-to-eax + 8513 # . epilogue + 8514 89/<- %esp 5/r32/ebp + 8515 5d/pop-to-ebp + 8516 c3/return + 8517 + 8518 emit-subx-disp32: # out: (addr buffered-file), l: arg-location, stmt: (handle stmt) + 8519 # . prologue + 8520 55/push-ebp + 8521 89/<- %ebp 4/r32/esp + 8522 # . save registers + 8523 50/push-eax + 8524 51/push-ecx + 8525 # if (location == 0) return + 8526 81 7/subop/compare *(ebp+0xc) 0/imm32 + 8527 0f 84/jump-if-= $emit-subx-disp32:end/disp32 + 8528 # var v/eax: (handle var) + 8529 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax + 8530 8b/-> *eax 0/r32/eax # Stmt-var-value + 8531 (write-buffered *(ebp+8) Space) + 8532 (write-buffered *(ebp+8) *eax) # Var-name + 8533 # hack: if instruction operation starts with "break", emit ":break" + 8534 # var name/ecx: (addr array byte) = stmt->operation + 8535 8b/-> *(ebp+0x10) 0/r32/eax + 8536 8b/-> *(eax+4) 1/r32/ecx + 8537 { + 8538 (string-starts-with? %ecx "break") # => eax + 8539 3d/compare-eax-and 0/imm32/false + 8540 74/jump-if-= break/disp8 + 8541 (write-buffered *(ebp+8) ":break") + 8542 } + 8543 # hack: if instruction operation starts with "loop", emit ":loop" + 8544 { + 8545 (string-starts-with? %ecx "loop") # => eax + 8546 3d/compare-eax-and 0/imm32/false + 8547 74/jump-if-= break/disp8 + 8548 (write-buffered *(ebp+8) ":loop") + 8549 } + 8550 (write-buffered *(ebp+8) "/disp32") + 8551 $emit-subx-disp32:end: + 8552 # . restore registers + 8553 59/pop-to-ecx + 8554 58/pop-to-eax + 8555 # . epilogue + 8556 89/<- %esp 5/r32/ebp + 8557 5d/pop-to-ebp + 8558 c3/return + 8559 + 8560 emit-subx-call: # out: (addr buffered-file), stmt: (handle stmt), callee: (handle function) + 8561 # . prologue + 8562 55/push-ebp + 8563 89/<- %ebp 4/r32/esp + 8564 # . save registers + 8565 51/push-ecx + 8566 # + 8567 (emit-indent *(ebp+8) *Curr-block-depth) + 8568 (write-buffered *(ebp+8) "(") + 8569 # - emit function name + 8570 8b/-> *(ebp+0x10) 1/r32/ecx + 8571 (write-buffered *(ebp+8) *(ecx+4)) # Function-subx-name + 8572 # - emit arguments + 8573 # var curr/ecx: (handle stmt-var) = stmt->inouts + 8574 8b/-> *(ebp+0xc) 1/r32/ecx + 8575 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts + 8576 { + 8577 # if (curr == null) break + 8578 81 7/subop/compare %ecx 0/imm32 + 8579 74/jump-if-= break/disp8 + 8580 # + 8581 (emit-subx-call-operand *(ebp+8) %ecx) + 8582 # curr = curr->next + 8583 8b/-> *(ecx+4) 1/r32/ecx # Stmt-var-next + 8584 eb/jump loop/disp8 + 8585 } + 8586 # + 8587 (write-buffered *(ebp+8) ")\n") + 8588 $emit-subx-call:end: + 8589 # . restore registers + 8590 59/pop-to-ecx + 8591 # . epilogue + 8592 89/<- %esp 5/r32/ebp + 8593 5d/pop-to-ebp + 8594 c3/return + 8595 + 8596 # like a function call, except we have no idea what function it is + 8597 # we hope it's defined in SubX and that the types are ok + 8598 emit-hailmary-call: # out: (addr buffered-file), stmt: (handle stmt) + 8599 # . prologue + 8600 55/push-ebp + 8601 89/<- %ebp 4/r32/esp + 8602 # . save registers + 8603 51/push-ecx + 8604 # + 8605 (emit-indent *(ebp+8) *Curr-block-depth) + 8606 (write-buffered *(ebp+8) "(") + 8607 # ecx = stmt + 8608 8b/-> *(ebp+0xc) 1/r32/ecx + 8609 # - emit function name + 8610 (write-buffered *(ebp+8) *(ecx+4)) # Stmt1-operation + 8611 # - emit arguments + 8612 # var curr/ecx: (handle stmt-var) = stmt->inouts + 8613 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts + 8614 { + 8615 # if (curr == null) break + 8616 81 7/subop/compare %ecx 0/imm32 + 8617 74/jump-if-= break/disp8 + 8618 # + 8619 (emit-subx-call-operand *(ebp+8) %ecx) + 8620 # curr = curr->next + 8621 8b/-> *(ecx+4) 1/r32/ecx # Stmt-var-next + 8622 eb/jump loop/disp8 + 8623 } + 8624 # + 8625 (write-buffered *(ebp+8) ")\n") + 8626 $emit-hailmary-call:end: + 8627 # . restore registers + 8628 59/pop-to-ecx + 8629 # . epilogue + 8630 89/<- %esp 5/r32/ebp + 8631 5d/pop-to-ebp + 8632 c3/return + 8633 + 8634 emit-subx-call-operand: # out: (addr buffered-file), s: (handle stmt-var) + 8635 # shares code with emit-subx-var-as-rm32 + 8636 # . prologue + 8637 55/push-ebp + 8638 89/<- %ebp 4/r32/esp + 8639 # . save registers + 8640 50/push-eax + 8641 51/push-ecx + 8642 56/push-esi + 8643 # ecx = s + 8644 8b/-> *(ebp+0xc) 1/r32/ecx + 8645 # var operand/esi: (handle var) = s->value + 8646 8b/-> *ecx 6/r32/esi # Stmt-var-value + 8647 # if (operand->register && s->is-deref?) emit "*__" + 8648 { + 8649 $emit-subx-call-operand:check-for-register-indirect: + 8650 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register + 8651 74/jump-if-= break/disp8 + 8652 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref + 8653 74/jump-if-= break/disp8 + 8654 $emit-subx-call-operand:register-indirect: + 8655 (write-buffered *(ebp+8) " *") + 8656 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register + 8657 e9/jump $emit-subx-call-operand:end/disp32 + 8658 } + 8659 # if (operand->register && !s->is-deref?) emit "%__" + 8660 { + 8661 $emit-subx-call-operand:check-for-register-direct: + 8662 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register + 8663 74/jump-if-= break/disp8 + 8664 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref + 8665 75/jump-if-!= break/disp8 + 8666 $emit-subx-call-operand:register-direct: + 8667 (write-buffered *(ebp+8) " %") + 8668 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register + 8669 e9/jump $emit-subx-call-operand:end/disp32 + 8670 } + 8671 # else if (operand->stack-offset) emit "*(ebp+__)" + 8672 { + 8673 81 7/subop/compare *(esi+0xc) 0/imm32 # Var-offset + 8674 74/jump-if-= break/disp8 + 8675 $emit-subx-call-operand:stack: + 8676 (write-buffered *(ebp+8) Space) + 8677 (write-buffered *(ebp+8) "*(ebp+") + 8678 (print-int32-buffered *(ebp+8) *(esi+0xc)) # Var-offset + 8679 (write-buffered *(ebp+8) ")") + 8680 e9/jump $emit-subx-call-operand:end/disp32 + 8681 } + 8682 # else if (operand->type == literal) emit "__" + 8683 { + 8684 8b/-> *(esi+4) 0/r32/eax # Var-type + 8685 81 7/subop/compare *eax 0/imm32 # Tree-left + 8686 75/jump-if-!= break/disp8 + 8687 $emit-subx-call-operand:literal: + 8688 (write-buffered *(ebp+8) Space) + 8689 (write-buffered *(ebp+8) *esi) + 8690 } + 8691 $emit-subx-call-operand:end: + 8692 # . restore registers + 8693 5e/pop-to-esi + 8694 59/pop-to-ecx + 8695 58/pop-to-eax + 8696 # . epilogue + 8697 89/<- %esp 5/r32/ebp + 8698 5d/pop-to-ebp + 8699 c3/return + 8700 + 8701 emit-subx-var-as-rm32: # out: (addr buffered-file), s: (handle stmt-var) + 8702 # . prologue + 8703 55/push-ebp + 8704 89/<- %ebp 4/r32/esp + 8705 # . save registers + 8706 50/push-eax + 8707 51/push-ecx + 8708 56/push-esi + 8709 # ecx = s + 8710 8b/-> *(ebp+0xc) 1/r32/ecx + 8711 # var operand/esi: (handle var) = s->value + 8712 8b/-> *ecx 6/r32/esi # Stmt-var-value + 8713 # if (operand->register && s->is-deref?) emit "*__" + 8714 { + 8715 $emit-subx-var-as-rm32:check-for-register-indirect: + 8716 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register + 8717 74/jump-if-= break/disp8 + 8718 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref + 8719 74/jump-if-= break/disp8 + 8720 $emit-subx-var-as-rm32:register-indirect: + 8721 (write-buffered *(ebp+8) " *") + 8722 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register + 8723 } + 8724 # if (operand->register && !s->is-deref?) emit "%__" + 8725 { + 8726 $emit-subx-var-as-rm32:check-for-register-direct: + 8727 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register + 8728 74/jump-if-= break/disp8 + 8729 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref + 8730 75/jump-if-!= break/disp8 + 8731 $emit-subx-var-as-rm32:register-direct: + 8732 (write-buffered *(ebp+8) " %") + 8733 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register + 8734 } + 8735 # else if (operand->stack-offset) emit "*(ebp+__)" + 8736 { + 8737 81 7/subop/compare *(esi+0xc) 0/imm32 # Var-offset + 8738 74/jump-if-= break/disp8 + 8739 $emit-subx-var-as-rm32:stack: + 8740 (write-buffered *(ebp+8) Space) + 8741 (write-buffered *(ebp+8) "*(ebp+") + 8742 (print-int32-buffered *(ebp+8) *(esi+0xc)) # Var-offset + 8743 (write-buffered *(ebp+8) ")") + 8744 } + 8745 $emit-subx-var-as-rm32:end: + 8746 # . restore registers + 8747 5e/pop-to-esi + 8748 59/pop-to-ecx + 8749 58/pop-to-eax + 8750 # . epilogue + 8751 89/<- %esp 5/r32/ebp + 8752 5d/pop-to-ebp + 8753 c3/return + 8754 + 8755 find-matching-function: # functions: (addr function), stmt: (handle stmt) -> result/eax: (handle function) + 8756 # . prologue + 8757 55/push-ebp + 8758 89/<- %ebp 4/r32/esp + 8759 # . save registers + 8760 51/push-ecx + 8761 # var curr/ecx: (handle function) = functions + 8762 8b/-> *(ebp+8) 1/r32/ecx + 8763 { + 8764 # if (curr == null) break + 8765 81 7/subop/compare %ecx 0/imm32 + 8766 74/jump-if-= break/disp8 + 8767 # if match(stmt, curr) return curr + 8768 { + 8769 (mu-stmt-matches-function? *(ebp+0xc) %ecx) # => eax + 8770 3d/compare-eax-and 0/imm32/false + 8771 74/jump-if-= break/disp8 + 8772 89/<- %eax 1/r32/ecx + 8773 eb/jump $find-matching-function:end/disp8 + 8774 } + 8775 # curr = curr->next + 8776 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next + 8777 eb/jump loop/disp8 + 8778 } + 8779 # return null + 8780 b8/copy-to-eax 0/imm32 + 8781 $find-matching-function:end: + 8782 # . restore registers + 8783 59/pop-to-ecx + 8784 # . epilogue + 8785 89/<- %esp 5/r32/ebp + 8786 5d/pop-to-ebp + 8787 c3/return + 8788 + 8789 find-matching-primitive: # primitives: (handle primitive), stmt: (handle stmt) -> result/eax: (handle primitive) + 8790 # . prologue + 8791 55/push-ebp + 8792 89/<- %ebp 4/r32/esp + 8793 # . save registers + 8794 51/push-ecx + 8795 # var curr/ecx: (handle primitive) = primitives + 8796 8b/-> *(ebp+8) 1/r32/ecx + 8797 { + 8798 $find-matching-primitive:loop: + 8799 # if (curr == null) break + 8800 81 7/subop/compare %ecx 0/imm32 + 8801 0f 84/jump-if-= break/disp32 + 8802 #? (write-buffered Stderr "prim: ") + 8803 #? (write-buffered Stderr *ecx) # Primitive-name + 8804 #? (write-buffered Stderr " => ") + 8805 #? (write-buffered Stderr *(ecx+0xc)) # Primitive-subx-name + 8806 #? (write-buffered Stderr Newline) + 8807 #? (flush Stderr) + 8808 # if match(curr, stmt) return curr + 8809 { + 8810 (mu-stmt-matches-primitive? *(ebp+0xc) %ecx) # => eax + 8811 3d/compare-eax-and 0/imm32/false + 8812 74/jump-if-= break/disp8 + 8813 89/<- %eax 1/r32/ecx + 8814 eb/jump $find-matching-primitive:end/disp8 + 8815 } + 8816 $find-matching-primitive:next-primitive: + 8817 # curr = curr->next + 8818 8b/-> *(ecx+0x24) 1/r32/ecx # Primitive-next + 8819 e9/jump loop/disp32 + 8820 } + 8821 # return null + 8822 b8/copy-to-eax 0/imm32 + 8823 $find-matching-primitive:end: + 8824 # . restore registers + 8825 59/pop-to-ecx + 8826 # . epilogue + 8827 89/<- %esp 5/r32/ebp + 8828 5d/pop-to-ebp + 8829 c3/return + 8830 + 8831 mu-stmt-matches-function?: # stmt: (handle stmt), function: (handle function) -> result/eax: boolean + 8832 # . prologue + 8833 55/push-ebp + 8834 89/<- %ebp 4/r32/esp + 8835 # . save registers + 8836 51/push-ecx + 8837 # return function->name == stmt->operation + 8838 8b/-> *(ebp+8) 1/r32/ecx + 8839 8b/-> *(ebp+0xc) 0/r32/eax + 8840 (string-equal? *(ecx+4) *eax) # Stmt1-operation, Function-name => eax + 8841 $mu-stmt-matches-function?:end: + 8842 # . restore registers + 8843 59/pop-to-ecx + 8844 # . epilogue + 8845 89/<- %esp 5/r32/ebp + 8846 5d/pop-to-ebp + 8847 c3/return + 8848 + 8849 mu-stmt-matches-primitive?: # stmt: (handle stmt), primitive: (handle primitive) -> result/eax: boolean + 8850 # A mu stmt matches a primitive if the name matches, all the inout vars + 8851 # match, and all the output vars match. + 8852 # Vars match if types match and registers match. + 8853 # In addition, a stmt output matches a primitive's output if types match + 8854 # and the primitive has a wildcard register. + 8855 # . prologue + 8856 55/push-ebp + 8857 89/<- %ebp 4/r32/esp + 8858 # . save registers + 8859 51/push-ecx + 8860 52/push-edx + 8861 53/push-ebx + 8862 56/push-esi + 8863 57/push-edi + 8864 # ecx = stmt + 8865 8b/-> *(ebp+8) 1/r32/ecx + 8866 # edx = primitive + 8867 8b/-> *(ebp+0xc) 2/r32/edx + 8868 { + 8869 $mu-stmt-matches-primitive?:check-name: + 8870 # if (primitive->name != stmt->operation) return false + 8871 (string-equal? *(ecx+4) *edx) # Stmt1-operation, Primitive-name => eax + 8872 3d/compare-eax-and 0/imm32/false + 8873 75/jump-if-!= break/disp8 + 8874 b8/copy-to-eax 0/imm32 + 8875 e9/jump $mu-stmt-matches-primitive?:end/disp32 + 8876 } + 8877 $mu-stmt-matches-primitive?:check-inouts: + 8878 # for (curr/esi in stmt->inouts, curr2/edi in primitive->inouts) + 8879 8b/-> *(ecx+8) 6/r32/esi # Stmt1-inouts or Regvardef-inouts + 8880 8b/-> *(edx+4) 7/r32/edi # Primitive-inouts + 8881 { + 8882 # if (curr == 0 && curr2 == 0) move on to check outputs + 8883 { + 8884 81 7/subop/compare %esi 0/imm32 + 8885 75/jump-if-!= break/disp8 + 8886 $mu-stmt-matches-primitive?:stmt-inout-is-null: + 8887 { + 8888 81 7/subop/compare %edi 0/imm32 + 8889 75/jump-if-!= break/disp8 + 8890 # + 8891 e9/jump $mu-stmt-matches-primitive?:check-outputs/disp32 + 8892 } + 8893 # return false + 8894 b8/copy-to-eax 0/imm32/false + 8895 e9/jump $mu-stmt-matches-primitive?:end/disp32 + 8896 } + 8897 # if (curr2 == 0) return false + 8898 { + 8899 81 7/subop/compare %edi 0/imm32 + 8900 75/jump-if-!= break/disp8 + 8901 $mu-stmt-matches-primitive?:prim-inout-is-null: + 8902 b8/copy-to-eax 0/imm32/false + 8903 e9/jump $mu-stmt-matches-primitive?:end/disp32 + 8904 } + 8905 # if (curr != curr2) return false + 8906 { + 8907 (operand-matches-primitive? %esi *edi) # List-value => eax + 8908 3d/compare-eax-and 0/imm32/false + 8909 75/jump-if-!= break/disp8 + 8910 b8/copy-to-eax 0/imm32/false + 8911 e9/jump $mu-stmt-matches-primitive?:end/disp32 + 8912 } + 8913 # curr=curr->next + 8914 8b/-> *(esi+4) 6/r32/esi # Stmt-var-next + 8915 # curr2=curr2->next + 8916 8b/-> *(edi+4) 7/r32/edi # Stmt-var-next + 8917 eb/jump loop/disp8 + 8918 } + 8919 $mu-stmt-matches-primitive?:check-outputs: + 8920 # for (curr/esi in stmt->outputs, curr2/edi in primitive->outputs) + 8921 8b/-> *(ecx+0xc) 6/r32/esi # Stmt1-outputs + 8922 8b/-> *(edx+8) 7/r32/edi # Primitive-outputs + 8923 { + 8924 # if (curr == 0) return (curr2 == 0) + 8925 { + 8926 $mu-stmt-matches-primitive?:check-output: + 8927 81 7/subop/compare %esi 0/imm32 + 8928 75/jump-if-!= break/disp8 + 8929 { + 8930 81 7/subop/compare %edi 0/imm32 + 8931 75/jump-if-!= break/disp8 + 8932 # return true + 8933 b8/copy-to-eax 1/imm32 + 8934 e9/jump $mu-stmt-matches-primitive?:end/disp32 + 8935 } + 8936 # return false + 8937 b8/copy-to-eax 0/imm32 + 8938 e9/jump $mu-stmt-matches-primitive?:end/disp32 + 8939 } + 8940 # if (curr2 == 0) return false + 8941 { + 8942 81 7/subop/compare %edi 0/imm32 + 8943 75/jump-if-!= break/disp8 + 8944 b8/copy-to-eax 0/imm32 + 8945 e9/jump $mu-stmt-matches-primitive?:end/disp32 + 8946 } + 8947 # if (curr != curr2) return false + 8948 { + 8949 (operand-matches-primitive? %esi *edi) # List-value => eax + 8950 3d/compare-eax-and 0/imm32/false + 8951 75/jump-if-!= break/disp8 + 8952 b8/copy-to-eax 0/imm32 + 8953 e9/jump $mu-stmt-matches-primitive?:end/disp32 + 8954 } + 8955 # curr=curr->next + 8956 8b/-> *(esi+4) 6/r32/esi # Stmt-var-next + 8957 # curr2=curr2->next + 8958 8b/-> *(edi+4) 7/r32/edi # Stmt-var-next + 8959 eb/jump loop/disp8 + 8960 } + 8961 $mu-stmt-matches-primitive?:return-true: + 8962 b8/copy-to-eax 1/imm32 + 8963 $mu-stmt-matches-primitive?:end: + 8964 # . restore registers + 8965 5f/pop-to-edi + 8966 5e/pop-to-esi + 8967 5b/pop-to-ebx + 8968 5a/pop-to-edx + 8969 59/pop-to-ecx + 8970 # . epilogue + 8971 89/<- %esp 5/r32/ebp + 8972 5d/pop-to-ebp + 8973 c3/return + 8974 + 8975 operand-matches-primitive?: # s: (handle stmt-var), prim-var: (handle var) -> result/eax: boolean + 8976 # . prologue + 8977 55/push-ebp + 8978 89/<- %ebp 4/r32/esp + 8979 # . save registers + 8980 51/push-ecx + 8981 56/push-esi + 8982 57/push-edi + 8983 # ecx = s + 8984 8b/-> *(ebp+8) 1/r32/ecx + 8985 # var var/esi : (handle var) = s->value + 8986 8b/-> *ecx 6/r32/esi # Stmt-var-value + 8987 # edi = prim-var + 8988 8b/-> *(ebp+0xc) 7/r32/edi + 8989 $operand-matches-primitive?:check-type: + 8990 # if (var->type != prim-var->type) return false + 8991 (subx-type-equal? *(esi+4) *(edi+4)) # Var-type, Var-type => eax + 8992 3d/compare-eax-and 0/imm32/false + 8993 b8/copy-to-eax 0/imm32/false + 8994 0f 84/jump-if-= $operand-matches-primitive?:end/disp32 + 8995 { + 8996 $operand-matches-primitive?:check-register: + 8997 # if prim-var is in memory and var is in register but dereference, match + 8998 { + 8999 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register + 9000 0f 85/jump-if-!= break/disp32 + 9001 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register + 9002 74/jump-if-= break/disp8 + 9003 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref + 9004 74/jump-if-= break/disp8 + 9005 e9/jump $operand-matches-primitive?:return-true/disp32 + 9006 } + 9007 # if prim-var is in register and var is in register but dereference, no match + 9008 { + 9009 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register + 9010 0f 84/jump-if-= break/disp32 + 9011 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register + 9012 0f 84/jump-if-= break/disp32 + 9013 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref + 9014 74/jump-if-= break/disp8 + 9015 e9/jump $operand-matches-primitive?:return-false/disp32 + 9016 } + 9017 # return false if var->register doesn't match prim-var->register + 9018 { + 9019 # if register addresses are equal, it's a match + 9020 8b/-> *(esi+0x10) 0/r32/eax # Var-register + 9021 39/compare *(edi+0x10) 0/r32/eax # Var-register + 9022 74/jump-if-= break/disp8 + 9023 # if either address is 0, return false + 9024 3d/compare-eax-and 0/imm32 + 9025 74/jump-if-= $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result + 9026 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register + 9027 74/jump-if-= $operand-matches-primitive?:return-false/disp8 + 9028 # if prim-var->register is wildcard, it's a match + 9029 (string-equal? *(edi+0x10) Any-register) # Var-register => eax + 9030 3d/compare-eax-and 0/imm32/false + 9031 75/jump-if-!= break/disp8 + 9032 # if string contents aren't equal, return false + 9033 (string-equal? *(esi+0x10) *(edi+0x10)) # Var-register Var-register => eax 9034 3d/compare-eax-and 0/imm32/false - 9035 75/jump-if-!= break/disp8 - 9036 # if string contents aren't equal, return false - 9037 (string-equal? *(esi+0x10) *(edi+0x10)) # Var-register Var-register => eax - 9038 3d/compare-eax-and 0/imm32/false - 9039 74/jump-if-= $operand-matches-primitive?:return-false/disp8 - 9040 } - 9041 } - 9042 $operand-matches-primitive?:return-true: - 9043 b8/copy-to-eax 1/imm32/true - 9044 eb/jump $operand-matches-primitive?:end/disp8 - 9045 $operand-matches-primitive?:return-false: - 9046 b8/copy-to-eax 0/imm32/false - 9047 $operand-matches-primitive?:end: - 9048 # . restore registers - 9049 5f/pop-to-edi - 9050 5e/pop-to-esi - 9051 59/pop-to-ecx - 9052 # . epilogue - 9053 89/<- %esp 5/r32/ebp - 9054 5d/pop-to-ebp - 9055 c3/return - 9056 - 9057 subx-type-equal?: # a: (handle tree type-id), b: (handle tree type-id) -> result/eax: boolean - 9058 # . prologue - 9059 55/push-ebp - 9060 89/<- %ebp 4/r32/esp - 9061 # . save registers - 9062 51/push-ecx - 9063 # var alit/ecx: boolean = is-literal-type?(a) - 9064 (is-literal-type? *(ebp+8)) # => eax - 9065 89/<- %ecx 0/r32/eax - 9066 # var blit/eax: boolean = is-literal-type?(b) - 9067 (is-literal-type? *(ebp+0xc)) # => eax - 9068 # return alit == blit - 9069 39/compare %eax 1/r32/ecx - 9070 74/jump-if-= $subx-type-equal?:true/disp8 - 9071 $subx-type-equal?:false: # TODO: replace with setcc - 9072 b8/copy-to-eax 0/imm32/false - 9073 eb/jump $subx-type-equal?:end/disp8 - 9074 $subx-type-equal?:true: - 9075 b8/copy-to-eax 1/imm32/true - 9076 $subx-type-equal?:end: - 9077 # . restore registers - 9078 59/pop-to-ecx - 9079 # . epilogue - 9080 89/<- %esp 5/r32/ebp - 9081 5d/pop-to-ebp - 9082 c3/return - 9083 - 9084 is-literal-type?: # a: (handle tree type-id) -> result/eax: boolean - 9085 # . prologue - 9086 55/push-ebp - 9087 89/<- %ebp 4/r32/esp - 9088 # - 9089 8b/-> *(ebp+8) 0/r32/eax - 9090 # return (*eax == 0) # TODO: replace with setcc - 9091 81 7/subop/compare *eax 0/imm32/literal-type-id # Atom-type - 9092 75/jump-if-!= $is-literal-type?:false/disp8 - 9093 $is-literal-type?:true: - 9094 b8/copy-to-eax 1/imm32/true - 9095 eb/jump $is-literal-type?:end/disp8 - 9096 $is-literal-type?:false: - 9097 b8/copy-to-eax 0/imm32/false - 9098 $is-literal-type?:end: - 9099 # . epilogue - 9100 89/<- %esp 5/r32/ebp - 9101 5d/pop-to-ebp - 9102 c3/return - 9103 - 9104 test-emit-subx-stmt-primitive: - 9105 # Primitive operation on a variable on the stack. - 9106 # increment foo - 9107 # => - 9108 # ff 0/subop/increment *(ebp-8) + 9035 74/jump-if-= $operand-matches-primitive?:return-false/disp8 + 9036 } + 9037 } + 9038 $operand-matches-primitive?:return-true: + 9039 b8/copy-to-eax 1/imm32/true + 9040 eb/jump $operand-matches-primitive?:end/disp8 + 9041 $operand-matches-primitive?:return-false: + 9042 b8/copy-to-eax 0/imm32/false + 9043 $operand-matches-primitive?:end: + 9044 # . restore registers + 9045 5f/pop-to-edi + 9046 5e/pop-to-esi + 9047 59/pop-to-ecx + 9048 # . epilogue + 9049 89/<- %esp 5/r32/ebp + 9050 5d/pop-to-ebp + 9051 c3/return + 9052 + 9053 subx-type-equal?: # a: (handle tree type-id), b: (handle tree type-id) -> result/eax: boolean + 9054 # . prologue + 9055 55/push-ebp + 9056 89/<- %ebp 4/r32/esp + 9057 # . save registers + 9058 51/push-ecx + 9059 # var alit/ecx: boolean = is-literal-type?(a) + 9060 (is-literal-type? *(ebp+8)) # => eax + 9061 89/<- %ecx 0/r32/eax + 9062 # var blit/eax: boolean = is-literal-type?(b) + 9063 (is-literal-type? *(ebp+0xc)) # => eax + 9064 # return alit == blit + 9065 39/compare %eax 1/r32/ecx + 9066 0f 94/set-if-= %eax + 9067 81 4/subop/and %eax 0xff/imm32 + 9068 $subx-type-equal?:end: + 9069 # . restore registers + 9070 59/pop-to-ecx + 9071 # . epilogue + 9072 89/<- %esp 5/r32/ebp + 9073 5d/pop-to-ebp + 9074 c3/return + 9075 + 9076 is-literal-type?: # a: (handle tree type-id) -> result/eax: boolean + 9077 # . prologue + 9078 55/push-ebp + 9079 89/<- %ebp 4/r32/esp + 9080 # + 9081 8b/-> *(ebp+8) 0/r32/eax + 9082 # return (*eax == 0) + 9083 81 7/subop/compare *eax 0/imm32/literal-type-id # Atom-type + 9084 0f 94/set-if-= %eax + 9085 81 4/subop/and %eax 0xff/imm32 + 9086 $is-literal-type?:end: + 9087 # . epilogue + 9088 89/<- %esp 5/r32/ebp + 9089 5d/pop-to-ebp + 9090 c3/return + 9091 + 9092 test-emit-subx-stmt-primitive: + 9093 # Primitive operation on a variable on the stack. + 9094 # increment foo + 9095 # => + 9096 # ff 0/subop/increment *(ebp-8) + 9097 # + 9098 # There's a variable on the var stack as follows: + 9099 # name: 'foo' + 9100 # type: int + 9101 # stack-offset: -8 + 9102 # + 9103 # There's a primitive with this info: + 9104 # name: 'increment' + 9105 # inouts: int/mem + 9106 # value: 'ff 0/subop/increment' + 9107 # + 9108 # There's nothing in functions. 9109 # - 9110 # There's a variable on the var stack as follows: - 9111 # name: 'foo' - 9112 # type: int - 9113 # stack-offset: -8 - 9114 # - 9115 # There's a primitive with this info: - 9116 # name: 'increment' - 9117 # inouts: int/mem - 9118 # value: 'ff 0/subop/increment' - 9119 # - 9120 # There's nothing in functions. - 9121 # - 9122 # . prologue - 9123 55/push-ebp - 9124 89/<- %ebp 4/r32/esp - 9125 # setup - 9126 (clear-stream _test-output-stream) - 9127 (clear-stream $_test-output-buffered-file->buffer) - 9128 # var type/ecx: (handle tree type-id) = int - 9129 68/push 0/imm32/right/null - 9130 68/push 1/imm32/left/int - 9131 89/<- %ecx 4/r32/esp - 9132 # var var-foo/ecx: var - 9133 68/push 0/imm32/no-register - 9134 68/push -8/imm32/stack-offset - 9135 68/push 1/imm32/block-depth - 9136 51/push-ecx - 9137 68/push "foo"/imm32 - 9138 89/<- %ecx 4/r32/esp - 9139 # var operand/ebx: (handle stmt-var) - 9140 68/push 0/imm32/is-deref:false - 9141 68/push 0/imm32/next - 9142 51/push-ecx/var-foo - 9143 89/<- %ebx 4/r32/esp - 9144 # var stmt/esi: statement - 9145 68/push 0/imm32/next - 9146 68/push 0/imm32/outputs - 9147 53/push-ebx/operands - 9148 68/push "increment"/imm32/operation - 9149 68/push 1/imm32 - 9150 89/<- %esi 4/r32/esp - 9151 # var primitives/ebx: primitive - 9152 68/push 0/imm32/next - 9153 68/push 0/imm32/output-is-write-only - 9154 68/push 0/imm32/no-disp32 - 9155 68/push 0/imm32/no-imm32 - 9156 68/push 0/imm32/no-r32 - 9157 68/push 1/imm32/rm32-is-first-inout - 9158 68/push "ff 0/subop/increment"/imm32/subx-name - 9159 68/push 0/imm32/outputs - 9160 53/push-ebx/inouts # hack; in practice we won't have the same var in function definition and call - 9161 68/push "increment"/imm32/name - 9162 89/<- %ebx 4/r32/esp - 9163 # convert - 9164 c7 0/subop/copy *Curr-block-depth 0/imm32 - 9165 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0) - 9166 (flush _test-output-buffered-file) - 9167 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 9173 # check output - 9174 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-stmt-primitive") - 9175 # . epilogue - 9176 89/<- %esp 5/r32/ebp - 9177 5d/pop-to-ebp - 9178 c3/return - 9179 - 9180 test-emit-subx-stmt-primitive-register: - 9181 # Primitive operation on a variable in a register. - 9182 # foo <- increment - 9183 # => - 9184 # ff 0/subop/increment %eax # sub-optimal, but should suffice + 9110 # . prologue + 9111 55/push-ebp + 9112 89/<- %ebp 4/r32/esp + 9113 # setup + 9114 (clear-stream _test-output-stream) + 9115 (clear-stream $_test-output-buffered-file->buffer) + 9116 # var type/ecx: (handle tree type-id) = int + 9117 68/push 0/imm32/right/null + 9118 68/push 1/imm32/left/int + 9119 89/<- %ecx 4/r32/esp + 9120 # var var-foo/ecx: var + 9121 68/push 0/imm32/no-register + 9122 68/push -8/imm32/stack-offset + 9123 68/push 1/imm32/block-depth + 9124 51/push-ecx + 9125 68/push "foo"/imm32 + 9126 89/<- %ecx 4/r32/esp + 9127 # var operand/ebx: (handle stmt-var) + 9128 68/push 0/imm32/is-deref:false + 9129 68/push 0/imm32/next + 9130 51/push-ecx/var-foo + 9131 89/<- %ebx 4/r32/esp + 9132 # var stmt/esi: statement + 9133 68/push 0/imm32/next + 9134 68/push 0/imm32/outputs + 9135 53/push-ebx/operands + 9136 68/push "increment"/imm32/operation + 9137 68/push 1/imm32 + 9138 89/<- %esi 4/r32/esp + 9139 # var primitives/ebx: primitive + 9140 68/push 0/imm32/next + 9141 68/push 0/imm32/output-is-write-only + 9142 68/push 0/imm32/no-disp32 + 9143 68/push 0/imm32/no-imm32 + 9144 68/push 0/imm32/no-r32 + 9145 68/push 1/imm32/rm32-is-first-inout + 9146 68/push "ff 0/subop/increment"/imm32/subx-name + 9147 68/push 0/imm32/outputs + 9148 53/push-ebx/inouts # hack; in practice we won't have the same var in function definition and call + 9149 68/push "increment"/imm32/name + 9150 89/<- %ebx 4/r32/esp + 9151 # convert + 9152 c7 0/subop/copy *Curr-block-depth 0/imm32 + 9153 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0) + 9154 (flush _test-output-buffered-file) + 9155 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 9161 # check output + 9162 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-stmt-primitive") + 9163 # . epilogue + 9164 89/<- %esp 5/r32/ebp + 9165 5d/pop-to-ebp + 9166 c3/return + 9167 + 9168 test-emit-subx-stmt-primitive-register: + 9169 # Primitive operation on a variable in a register. + 9170 # foo <- increment + 9171 # => + 9172 # ff 0/subop/increment %eax # sub-optimal, but should suffice + 9173 # + 9174 # There's a variable on the var stack as follows: + 9175 # name: 'foo' + 9176 # type: int + 9177 # register: 'eax' + 9178 # + 9179 # There's a primitive with this info: + 9180 # name: 'increment' + 9181 # out: int/reg + 9182 # value: 'ff 0/subop/increment' + 9183 # + 9184 # There's nothing in functions. 9185 # - 9186 # There's a variable on the var stack as follows: - 9187 # name: 'foo' - 9188 # type: int - 9189 # register: 'eax' - 9190 # - 9191 # There's a primitive with this info: - 9192 # name: 'increment' - 9193 # out: int/reg - 9194 # value: 'ff 0/subop/increment' - 9195 # - 9196 # There's nothing in functions. - 9197 # - 9198 # . prologue - 9199 55/push-ebp - 9200 89/<- %ebp 4/r32/esp - 9201 # setup - 9202 (clear-stream _test-output-stream) - 9203 (clear-stream $_test-output-buffered-file->buffer) - 9204 # var type/ecx: (handle tree type-id) = int - 9205 68/push 0/imm32/right/null - 9206 68/push 1/imm32/left/int - 9207 89/<- %ecx 4/r32/esp - 9208 # var var-foo/ecx: var in eax - 9209 68/push "eax"/imm32/register - 9210 68/push 0/imm32/no-stack-offset - 9211 68/push 1/imm32/block-depth - 9212 51/push-ecx - 9213 68/push "foo"/imm32 - 9214 89/<- %ecx 4/r32/esp - 9215 # var operand/ebx: (handle stmt-var) - 9216 68/push 0/imm32/is-deref:false - 9217 68/push 0/imm32/next - 9218 51/push-ecx/var-foo - 9219 89/<- %ebx 4/r32/esp - 9220 # var stmt/esi: statement - 9221 68/push 0/imm32/next - 9222 53/push-ebx/outputs - 9223 68/push 0/imm32/inouts - 9224 68/push "increment"/imm32/operation - 9225 68/push 1/imm32 - 9226 89/<- %esi 4/r32/esp - 9227 # var formal-var/ebx: var in any register - 9228 68/push Any-register/imm32 - 9229 68/push 0/imm32/no-stack-offset - 9230 68/push 1/imm32/block-depth - 9231 ff 6/subop/push *(ecx+4) # Var-type - 9232 68/push "dummy"/imm32 - 9233 89/<- %ebx 4/r32/esp - 9234 # var operand/ebx: (handle stmt-var) - 9235 68/push 0/imm32/is-deref:false - 9236 68/push 0/imm32/next - 9237 53/push-ebx/formal-var + 9186 # . prologue + 9187 55/push-ebp + 9188 89/<- %ebp 4/r32/esp + 9189 # setup + 9190 (clear-stream _test-output-stream) + 9191 (clear-stream $_test-output-buffered-file->buffer) + 9192 # var type/ecx: (handle tree type-id) = int + 9193 68/push 0/imm32/right/null + 9194 68/push 1/imm32/left/int + 9195 89/<- %ecx 4/r32/esp + 9196 # var var-foo/ecx: var in eax + 9197 68/push "eax"/imm32/register + 9198 68/push 0/imm32/no-stack-offset + 9199 68/push 1/imm32/block-depth + 9200 51/push-ecx + 9201 68/push "foo"/imm32 + 9202 89/<- %ecx 4/r32/esp + 9203 # var operand/ebx: (handle stmt-var) + 9204 68/push 0/imm32/is-deref:false + 9205 68/push 0/imm32/next + 9206 51/push-ecx/var-foo + 9207 89/<- %ebx 4/r32/esp + 9208 # var stmt/esi: statement + 9209 68/push 0/imm32/next + 9210 53/push-ebx/outputs + 9211 68/push 0/imm32/inouts + 9212 68/push "increment"/imm32/operation + 9213 68/push 1/imm32 + 9214 89/<- %esi 4/r32/esp + 9215 # var formal-var/ebx: var in any register + 9216 68/push Any-register/imm32 + 9217 68/push 0/imm32/no-stack-offset + 9218 68/push 1/imm32/block-depth + 9219 ff 6/subop/push *(ecx+4) # Var-type + 9220 68/push "dummy"/imm32 + 9221 89/<- %ebx 4/r32/esp + 9222 # var operand/ebx: (handle stmt-var) + 9223 68/push 0/imm32/is-deref:false + 9224 68/push 0/imm32/next + 9225 53/push-ebx/formal-var + 9226 89/<- %ebx 4/r32/esp + 9227 # var primitives/ebx: primitive + 9228 68/push 0/imm32/next + 9229 68/push 0/imm32/output-is-write-only + 9230 68/push 0/imm32/no-disp32 + 9231 68/push 0/imm32/no-imm32 + 9232 68/push 0/imm32/no-r32 + 9233 68/push 3/imm32/rm32-in-first-output + 9234 68/push "ff 0/subop/increment"/imm32/subx-name + 9235 53/push-ebx/outputs + 9236 68/push 0/imm32/inouts + 9237 68/push "increment"/imm32/name 9238 89/<- %ebx 4/r32/esp - 9239 # var primitives/ebx: primitive - 9240 68/push 0/imm32/next - 9241 68/push 0/imm32/output-is-write-only - 9242 68/push 0/imm32/no-disp32 - 9243 68/push 0/imm32/no-imm32 - 9244 68/push 0/imm32/no-r32 - 9245 68/push 3/imm32/rm32-in-first-output - 9246 68/push "ff 0/subop/increment"/imm32/subx-name - 9247 53/push-ebx/outputs - 9248 68/push 0/imm32/inouts - 9249 68/push "increment"/imm32/name - 9250 89/<- %ebx 4/r32/esp - 9251 # convert - 9252 c7 0/subop/copy *Curr-block-depth 0/imm32 - 9253 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0) - 9254 (flush _test-output-buffered-file) - 9255 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 9261 # check output - 9262 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-primitive-register") - 9263 # . epilogue - 9264 89/<- %esp 5/r32/ebp - 9265 5d/pop-to-ebp - 9266 c3/return - 9267 - 9268 test-emit-subx-stmt-select-primitive: - 9269 # Select the right primitive between overloads. - 9270 # foo <- increment - 9271 # => - 9272 # ff 0/subop/increment %eax # sub-optimal, but should suffice - 9273 # - 9274 # There's a variable on the var stack as follows: - 9275 # name: 'foo' - 9276 # type: int - 9277 # register: 'eax' - 9278 # - 9279 # There's two primitives, as follows: - 9280 # - name: 'increment' - 9281 # out: int/reg - 9282 # value: 'ff 0/subop/increment' - 9283 # - name: 'increment' - 9284 # inout: int/mem - 9285 # value: 'ff 0/subop/increment' - 9286 # - 9287 # There's nothing in functions. - 9288 # - 9289 # . prologue - 9290 55/push-ebp - 9291 89/<- %ebp 4/r32/esp - 9292 # setup - 9293 (clear-stream _test-output-stream) - 9294 (clear-stream $_test-output-buffered-file->buffer) - 9295 # var type/ecx: (handle tree type-id) = int - 9296 68/push 0/imm32/right/null - 9297 68/push 1/imm32/left/int - 9298 89/<- %ecx 4/r32/esp - 9299 # var var-foo/ecx: var in eax - 9300 68/push "eax"/imm32/register - 9301 68/push 0/imm32/no-stack-offset - 9302 68/push 1/imm32/block-depth - 9303 51/push-ecx - 9304 68/push "foo"/imm32 - 9305 89/<- %ecx 4/r32/esp - 9306 # var real-outputs/edi: (handle stmt-var) - 9307 68/push 0/imm32/is-deref:false - 9308 68/push 0/imm32/next - 9309 51/push-ecx/var-foo - 9310 89/<- %edi 4/r32/esp - 9311 # var stmt/esi: statement - 9312 68/push 0/imm32/next - 9313 57/push-edi/outputs - 9314 68/push 0/imm32/inouts - 9315 68/push "increment"/imm32/operation - 9316 68/push 1/imm32 - 9317 89/<- %esi 4/r32/esp - 9318 # var formal-var/ebx: var in any register - 9319 68/push Any-register/imm32 - 9320 68/push 0/imm32/no-stack-offset - 9321 68/push 1/imm32/block-depth - 9322 ff 6/subop/push *(ecx+4) # Var-type - 9323 68/push "dummy"/imm32 - 9324 89/<- %ebx 4/r32/esp - 9325 # var formal-outputs/ebx: (handle stmt-var) - 9326 68/push 0/imm32/is-deref:false - 9327 68/push 0/imm32/next - 9328 53/push-ebx/formal-var + 9239 # convert + 9240 c7 0/subop/copy *Curr-block-depth 0/imm32 + 9241 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0) + 9242 (flush _test-output-buffered-file) + 9243 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 9249 # check output + 9250 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-primitive-register") + 9251 # . epilogue + 9252 89/<- %esp 5/r32/ebp + 9253 5d/pop-to-ebp + 9254 c3/return + 9255 + 9256 test-emit-subx-stmt-select-primitive: + 9257 # Select the right primitive between overloads. + 9258 # foo <- increment + 9259 # => + 9260 # ff 0/subop/increment %eax # sub-optimal, but should suffice + 9261 # + 9262 # There's a variable on the var stack as follows: + 9263 # name: 'foo' + 9264 # type: int + 9265 # register: 'eax' + 9266 # + 9267 # There's two primitives, as follows: + 9268 # - name: 'increment' + 9269 # out: int/reg + 9270 # value: 'ff 0/subop/increment' + 9271 # - name: 'increment' + 9272 # inout: int/mem + 9273 # value: 'ff 0/subop/increment' + 9274 # + 9275 # There's nothing in functions. + 9276 # + 9277 # . prologue + 9278 55/push-ebp + 9279 89/<- %ebp 4/r32/esp + 9280 # setup + 9281 (clear-stream _test-output-stream) + 9282 (clear-stream $_test-output-buffered-file->buffer) + 9283 # var type/ecx: (handle tree type-id) = int + 9284 68/push 0/imm32/right/null + 9285 68/push 1/imm32/left/int + 9286 89/<- %ecx 4/r32/esp + 9287 # var var-foo/ecx: var in eax + 9288 68/push "eax"/imm32/register + 9289 68/push 0/imm32/no-stack-offset + 9290 68/push 1/imm32/block-depth + 9291 51/push-ecx + 9292 68/push "foo"/imm32 + 9293 89/<- %ecx 4/r32/esp + 9294 # var real-outputs/edi: (handle stmt-var) + 9295 68/push 0/imm32/is-deref:false + 9296 68/push 0/imm32/next + 9297 51/push-ecx/var-foo + 9298 89/<- %edi 4/r32/esp + 9299 # var stmt/esi: statement + 9300 68/push 0/imm32/next + 9301 57/push-edi/outputs + 9302 68/push 0/imm32/inouts + 9303 68/push "increment"/imm32/operation + 9304 68/push 1/imm32 + 9305 89/<- %esi 4/r32/esp + 9306 # var formal-var/ebx: var in any register + 9307 68/push Any-register/imm32 + 9308 68/push 0/imm32/no-stack-offset + 9309 68/push 1/imm32/block-depth + 9310 ff 6/subop/push *(ecx+4) # Var-type + 9311 68/push "dummy"/imm32 + 9312 89/<- %ebx 4/r32/esp + 9313 # var formal-outputs/ebx: (handle stmt-var) + 9314 68/push 0/imm32/is-deref:false + 9315 68/push 0/imm32/next + 9316 53/push-ebx/formal-var + 9317 89/<- %ebx 4/r32/esp + 9318 # var primitive1/ebx: primitive + 9319 68/push 0/imm32/next + 9320 68/push 0/imm32/output-is-write-only + 9321 68/push 0/imm32/no-disp32 + 9322 68/push 0/imm32/no-imm32 + 9323 68/push 0/imm32/no-r32 + 9324 68/push 3/imm32/rm32-in-first-output + 9325 68/push "ff 0/subop/increment"/imm32/subx-name + 9326 53/push-ebx/outputs/formal-outputs + 9327 68/push 0/imm32/inouts + 9328 68/push "increment"/imm32/name 9329 89/<- %ebx 4/r32/esp - 9330 # var primitive1/ebx: primitive - 9331 68/push 0/imm32/next + 9330 # var primitives/ebx: primitive + 9331 53/push-ebx/next 9332 68/push 0/imm32/output-is-write-only 9333 68/push 0/imm32/no-disp32 9334 68/push 0/imm32/no-imm32 9335 68/push 0/imm32/no-r32 - 9336 68/push 3/imm32/rm32-in-first-output + 9336 68/push 1/imm32/rm32-is-first-inout 9337 68/push "ff 0/subop/increment"/imm32/subx-name - 9338 53/push-ebx/outputs/formal-outputs - 9339 68/push 0/imm32/inouts + 9338 68/push 0/imm32/outputs + 9339 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call 9340 68/push "increment"/imm32/name 9341 89/<- %ebx 4/r32/esp - 9342 # var primitives/ebx: primitive - 9343 53/push-ebx/next - 9344 68/push 0/imm32/output-is-write-only - 9345 68/push 0/imm32/no-disp32 - 9346 68/push 0/imm32/no-imm32 - 9347 68/push 0/imm32/no-r32 - 9348 68/push 1/imm32/rm32-is-first-inout - 9349 68/push "ff 0/subop/increment"/imm32/subx-name - 9350 68/push 0/imm32/outputs - 9351 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call - 9352 68/push "increment"/imm32/name - 9353 89/<- %ebx 4/r32/esp - 9354 # convert - 9355 c7 0/subop/copy *Curr-block-depth 0/imm32 - 9356 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0) - 9357 (flush _test-output-buffered-file) - 9358 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 9364 # check output - 9365 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive") - 9366 # . epilogue - 9367 89/<- %esp 5/r32/ebp - 9368 5d/pop-to-ebp - 9369 c3/return - 9370 - 9371 test-emit-subx-stmt-select-primitive-2: - 9372 # Select the right primitive between overloads. - 9373 # foo <- increment - 9374 # => - 9375 # ff 0/subop/increment %eax # sub-optimal, but should suffice - 9376 # - 9377 # There's a variable on the var stack as follows: - 9378 # name: 'foo' - 9379 # type: int - 9380 # register: 'eax' - 9381 # - 9382 # There's two primitives, as follows: - 9383 # - name: 'increment' - 9384 # out: int/reg - 9385 # value: 'ff 0/subop/increment' - 9386 # - name: 'increment' - 9387 # inout: int/mem - 9388 # value: 'ff 0/subop/increment' - 9389 # - 9390 # There's nothing in functions. - 9391 # - 9392 # . prologue - 9393 55/push-ebp - 9394 89/<- %ebp 4/r32/esp - 9395 # setup - 9396 (clear-stream _test-output-stream) - 9397 (clear-stream $_test-output-buffered-file->buffer) - 9398 # var type/ecx: (handle tree type-id) = int - 9399 68/push 0/imm32/right/null - 9400 68/push 1/imm32/left/int - 9401 89/<- %ecx 4/r32/esp - 9402 # var var-foo/ecx: var in eax - 9403 68/push "eax"/imm32/register - 9404 68/push 0/imm32/no-stack-offset - 9405 68/push 1/imm32/block-depth - 9406 51/push-ecx - 9407 68/push "foo"/imm32 - 9408 89/<- %ecx 4/r32/esp - 9409 # var inouts/edi: (handle stmt-var) - 9410 68/push 0/imm32/is-deref:false - 9411 68/push 0/imm32/next - 9412 51/push-ecx/var-foo - 9413 89/<- %edi 4/r32/esp - 9414 # var stmt/esi: statement - 9415 68/push 0/imm32/next - 9416 68/push 0/imm32/outputs - 9417 57/push-edi/inouts - 9418 68/push "increment"/imm32/operation - 9419 68/push 1/imm32 - 9420 89/<- %esi 4/r32/esp - 9421 # var formal-var/ebx: var in any register - 9422 68/push Any-register/imm32 - 9423 68/push 0/imm32/no-stack-offset - 9424 68/push 1/imm32/block-depth - 9425 ff 6/subop/push *(ecx+4) # Var-type - 9426 68/push "dummy"/imm32 - 9427 89/<- %ebx 4/r32/esp - 9428 # var operand/ebx: (handle stmt-var) - 9429 68/push 0/imm32/is-deref:false - 9430 68/push 0/imm32/next - 9431 53/push-ebx/formal-var + 9342 # convert + 9343 c7 0/subop/copy *Curr-block-depth 0/imm32 + 9344 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0) + 9345 (flush _test-output-buffered-file) + 9346 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 9352 # check output + 9353 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive") + 9354 # . epilogue + 9355 89/<- %esp 5/r32/ebp + 9356 5d/pop-to-ebp + 9357 c3/return + 9358 + 9359 test-emit-subx-stmt-select-primitive-2: + 9360 # Select the right primitive between overloads. + 9361 # foo <- increment + 9362 # => + 9363 # ff 0/subop/increment %eax # sub-optimal, but should suffice + 9364 # + 9365 # There's a variable on the var stack as follows: + 9366 # name: 'foo' + 9367 # type: int + 9368 # register: 'eax' + 9369 # + 9370 # There's two primitives, as follows: + 9371 # - name: 'increment' + 9372 # out: int/reg + 9373 # value: 'ff 0/subop/increment' + 9374 # - name: 'increment' + 9375 # inout: int/mem + 9376 # value: 'ff 0/subop/increment' + 9377 # + 9378 # There's nothing in functions. + 9379 # + 9380 # . prologue + 9381 55/push-ebp + 9382 89/<- %ebp 4/r32/esp + 9383 # setup + 9384 (clear-stream _test-output-stream) + 9385 (clear-stream $_test-output-buffered-file->buffer) + 9386 # var type/ecx: (handle tree type-id) = int + 9387 68/push 0/imm32/right/null + 9388 68/push 1/imm32/left/int + 9389 89/<- %ecx 4/r32/esp + 9390 # var var-foo/ecx: var in eax + 9391 68/push "eax"/imm32/register + 9392 68/push 0/imm32/no-stack-offset + 9393 68/push 1/imm32/block-depth + 9394 51/push-ecx + 9395 68/push "foo"/imm32 + 9396 89/<- %ecx 4/r32/esp + 9397 # var inouts/edi: (handle stmt-var) + 9398 68/push 0/imm32/is-deref:false + 9399 68/push 0/imm32/next + 9400 51/push-ecx/var-foo + 9401 89/<- %edi 4/r32/esp + 9402 # var stmt/esi: statement + 9403 68/push 0/imm32/next + 9404 68/push 0/imm32/outputs + 9405 57/push-edi/inouts + 9406 68/push "increment"/imm32/operation + 9407 68/push 1/imm32 + 9408 89/<- %esi 4/r32/esp + 9409 # var formal-var/ebx: var in any register + 9410 68/push Any-register/imm32 + 9411 68/push 0/imm32/no-stack-offset + 9412 68/push 1/imm32/block-depth + 9413 ff 6/subop/push *(ecx+4) # Var-type + 9414 68/push "dummy"/imm32 + 9415 89/<- %ebx 4/r32/esp + 9416 # var operand/ebx: (handle stmt-var) + 9417 68/push 0/imm32/is-deref:false + 9418 68/push 0/imm32/next + 9419 53/push-ebx/formal-var + 9420 89/<- %ebx 4/r32/esp + 9421 # var primitive1/ebx: primitive + 9422 68/push 0/imm32/next + 9423 68/push 0/imm32/output-is-write-only + 9424 68/push 0/imm32/no-disp32 + 9425 68/push 0/imm32/no-imm32 + 9426 68/push 0/imm32/no-r32 + 9427 68/push 3/imm32/rm32-in-first-output + 9428 68/push "ff 0/subop/increment"/imm32/subx-name + 9429 53/push-ebx/outputs/formal-outputs + 9430 68/push 0/imm32/inouts + 9431 68/push "increment"/imm32/name 9432 89/<- %ebx 4/r32/esp - 9433 # var primitive1/ebx: primitive - 9434 68/push 0/imm32/next + 9433 # var primitives/ebx: primitive + 9434 53/push-ebx/next 9435 68/push 0/imm32/output-is-write-only 9436 68/push 0/imm32/no-disp32 9437 68/push 0/imm32/no-imm32 9438 68/push 0/imm32/no-r32 - 9439 68/push 3/imm32/rm32-in-first-output + 9439 68/push 1/imm32/rm32-is-first-inout 9440 68/push "ff 0/subop/increment"/imm32/subx-name - 9441 53/push-ebx/outputs/formal-outputs - 9442 68/push 0/imm32/inouts + 9441 68/push 0/imm32/outputs + 9442 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call 9443 68/push "increment"/imm32/name 9444 89/<- %ebx 4/r32/esp - 9445 # var primitives/ebx: primitive - 9446 53/push-ebx/next - 9447 68/push 0/imm32/output-is-write-only - 9448 68/push 0/imm32/no-disp32 - 9449 68/push 0/imm32/no-imm32 - 9450 68/push 0/imm32/no-r32 - 9451 68/push 1/imm32/rm32-is-first-inout - 9452 68/push "ff 0/subop/increment"/imm32/subx-name - 9453 68/push 0/imm32/outputs - 9454 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call - 9455 68/push "increment"/imm32/name - 9456 89/<- %ebx 4/r32/esp - 9457 # convert - 9458 c7 0/subop/copy *Curr-block-depth 0/imm32 - 9459 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0) - 9460 (flush _test-output-buffered-file) - 9461 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 9467 # check output - 9468 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive-2") - 9469 # . epilogue - 9470 89/<- %esp 5/r32/ebp - 9471 5d/pop-to-ebp - 9472 c3/return - 9473 - 9474 test-increment-register: - 9475 # Select the right register between overloads. - 9476 # foo <- increment - 9477 # => - 9478 # 50/increment-eax - 9479 # - 9480 # There's a variable on the var stack as follows: - 9481 # name: 'foo' - 9482 # type: int - 9483 # register: 'eax' - 9484 # - 9485 # Primitives are the global definitions. - 9486 # - 9487 # There are no functions defined. - 9488 # - 9489 # . prologue - 9490 55/push-ebp - 9491 89/<- %ebp 4/r32/esp - 9492 # setup - 9493 (clear-stream _test-output-stream) - 9494 (clear-stream $_test-output-buffered-file->buffer) - 9495 # var type/ecx: (handle tree type-id) = int - 9496 68/push 0/imm32/right/null - 9497 68/push 1/imm32/left/int - 9498 89/<- %ecx 4/r32/esp - 9499 # var var-foo/ecx: var in eax - 9500 68/push "eax"/imm32/register - 9501 68/push 0/imm32/no-stack-offset - 9502 68/push 1/imm32/block-depth - 9503 51/push-ecx - 9504 68/push "foo"/imm32 - 9505 89/<- %ecx 4/r32/esp - 9506 # var real-outputs/edi: (handle stmt-var) - 9507 68/push 0/imm32/is-deref:false - 9508 68/push 0/imm32/next - 9509 51/push-ecx/var-foo - 9510 89/<- %edi 4/r32/esp - 9511 # var stmt/esi: statement - 9512 68/push 0/imm32/next - 9513 57/push-edi/outputs - 9514 68/push 0/imm32/inouts - 9515 68/push "increment"/imm32/operation - 9516 68/push 1/imm32/regular-stmt - 9517 89/<- %esi 4/r32/esp - 9518 # convert - 9519 c7 0/subop/copy *Curr-block-depth 0/imm32 - 9520 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) - 9521 (flush _test-output-buffered-file) - 9522 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 9528 # check output - 9529 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register") - 9530 # . epilogue - 9531 89/<- %esp 5/r32/ebp - 9532 5d/pop-to-ebp - 9533 c3/return - 9534 - 9535 test-increment-var: - 9536 # Select the right primitive between overloads. - 9537 # foo <- increment - 9538 # => - 9539 # ff 0/subop/increment %eax # sub-optimal, but should suffice - 9540 # - 9541 # There's a variable on the var stack as follows: - 9542 # name: 'foo' - 9543 # type: int - 9544 # register: 'eax' - 9545 # - 9546 # Primitives are the global definitions. - 9547 # - 9548 # There are no functions defined. - 9549 # - 9550 # . prologue - 9551 55/push-ebp - 9552 89/<- %ebp 4/r32/esp - 9553 # setup - 9554 (clear-stream _test-output-stream) - 9555 (clear-stream $_test-output-buffered-file->buffer) - 9556 # var type/ecx: (handle tree type-id) = int - 9557 68/push 0/imm32/right/null - 9558 68/push 1/imm32/left/int - 9559 89/<- %ecx 4/r32/esp - 9560 # var var-foo/ecx: var in eax - 9561 68/push "eax"/imm32/register - 9562 68/push 0/imm32/no-stack-offset - 9563 68/push 1/imm32/block-depth - 9564 51/push-ecx - 9565 68/push "foo"/imm32 - 9566 89/<- %ecx 4/r32/esp - 9567 # var inouts/edi: (handle stmt-var) - 9568 68/push 0/imm32/is-deref:false - 9569 68/push 0/imm32/next - 9570 51/push-ecx/var-foo - 9571 89/<- %edi 4/r32/esp - 9572 # var stmt/esi: statement - 9573 68/push 0/imm32/next - 9574 57/push-edi/outputs - 9575 68/push 0/imm32/inouts - 9576 68/push "increment"/imm32/operation - 9577 68/push 1/imm32 - 9578 89/<- %esi 4/r32/esp - 9579 # convert - 9580 c7 0/subop/copy *Curr-block-depth 0/imm32 - 9581 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) - 9582 (flush _test-output-buffered-file) - 9583 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 9589 # check output - 9590 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-var") - 9591 # . epilogue - 9592 89/<- %esp 5/r32/ebp - 9593 5d/pop-to-ebp - 9594 c3/return - 9595 - 9596 test-add-reg-to-reg: - 9597 # var1/reg <- add var2/reg - 9598 # => - 9599 # 01/add %var1 var2 - 9600 # - 9601 # . prologue - 9602 55/push-ebp - 9603 89/<- %ebp 4/r32/esp - 9604 # setup - 9605 (clear-stream _test-output-stream) - 9606 (clear-stream $_test-output-buffered-file->buffer) - 9607 # var type/ecx: (handle tree type-id) = int - 9608 68/push 0/imm32/right/null - 9609 68/push 1/imm32/left/int - 9610 89/<- %ecx 4/r32/esp - 9611 # var var-var1/ecx: var in eax - 9612 68/push "eax"/imm32/register - 9613 68/push 0/imm32/no-stack-offset - 9614 68/push 1/imm32/block-depth - 9615 51/push-ecx - 9616 68/push "var1"/imm32 - 9617 89/<- %ecx 4/r32/esp - 9618 # var var-var2/edx: var in ecx - 9619 68/push "ecx"/imm32/register - 9620 68/push 0/imm32/no-stack-offset - 9621 68/push 1/imm32/block-depth - 9622 ff 6/subop/push *(ecx+4) # Var-type - 9623 68/push "var2"/imm32 - 9624 89/<- %edx 4/r32/esp - 9625 # var inouts/esi: (handle stmt-var) = [var2] - 9626 68/push 0/imm32/is-deref:false - 9627 68/push 0/imm32/next - 9628 52/push-edx/var-var2 + 9445 # convert + 9446 c7 0/subop/copy *Curr-block-depth 0/imm32 + 9447 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0) + 9448 (flush _test-output-buffered-file) + 9449 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 9455 # check output + 9456 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive-2") + 9457 # . epilogue + 9458 89/<- %esp 5/r32/ebp + 9459 5d/pop-to-ebp + 9460 c3/return + 9461 + 9462 test-increment-register: + 9463 # Select the right register between overloads. + 9464 # foo <- increment + 9465 # => + 9466 # 50/increment-eax + 9467 # + 9468 # There's a variable on the var stack as follows: + 9469 # name: 'foo' + 9470 # type: int + 9471 # register: 'eax' + 9472 # + 9473 # Primitives are the global definitions. + 9474 # + 9475 # There are no functions defined. + 9476 # + 9477 # . prologue + 9478 55/push-ebp + 9479 89/<- %ebp 4/r32/esp + 9480 # setup + 9481 (clear-stream _test-output-stream) + 9482 (clear-stream $_test-output-buffered-file->buffer) + 9483 # var type/ecx: (handle tree type-id) = int + 9484 68/push 0/imm32/right/null + 9485 68/push 1/imm32/left/int + 9486 89/<- %ecx 4/r32/esp + 9487 # var var-foo/ecx: var in eax + 9488 68/push "eax"/imm32/register + 9489 68/push 0/imm32/no-stack-offset + 9490 68/push 1/imm32/block-depth + 9491 51/push-ecx + 9492 68/push "foo"/imm32 + 9493 89/<- %ecx 4/r32/esp + 9494 # var real-outputs/edi: (handle stmt-var) + 9495 68/push 0/imm32/is-deref:false + 9496 68/push 0/imm32/next + 9497 51/push-ecx/var-foo + 9498 89/<- %edi 4/r32/esp + 9499 # var stmt/esi: statement + 9500 68/push 0/imm32/next + 9501 57/push-edi/outputs + 9502 68/push 0/imm32/inouts + 9503 68/push "increment"/imm32/operation + 9504 68/push 1/imm32/regular-stmt + 9505 89/<- %esi 4/r32/esp + 9506 # convert + 9507 c7 0/subop/copy *Curr-block-depth 0/imm32 + 9508 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) + 9509 (flush _test-output-buffered-file) + 9510 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 9516 # check output + 9517 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register") + 9518 # . epilogue + 9519 89/<- %esp 5/r32/ebp + 9520 5d/pop-to-ebp + 9521 c3/return + 9522 + 9523 test-increment-var: + 9524 # Select the right primitive between overloads. + 9525 # foo <- increment + 9526 # => + 9527 # ff 0/subop/increment %eax # sub-optimal, but should suffice + 9528 # + 9529 # There's a variable on the var stack as follows: + 9530 # name: 'foo' + 9531 # type: int + 9532 # register: 'eax' + 9533 # + 9534 # Primitives are the global definitions. + 9535 # + 9536 # There are no functions defined. + 9537 # + 9538 # . prologue + 9539 55/push-ebp + 9540 89/<- %ebp 4/r32/esp + 9541 # setup + 9542 (clear-stream _test-output-stream) + 9543 (clear-stream $_test-output-buffered-file->buffer) + 9544 # var type/ecx: (handle tree type-id) = int + 9545 68/push 0/imm32/right/null + 9546 68/push 1/imm32/left/int + 9547 89/<- %ecx 4/r32/esp + 9548 # var var-foo/ecx: var in eax + 9549 68/push "eax"/imm32/register + 9550 68/push 0/imm32/no-stack-offset + 9551 68/push 1/imm32/block-depth + 9552 51/push-ecx + 9553 68/push "foo"/imm32 + 9554 89/<- %ecx 4/r32/esp + 9555 # var inouts/edi: (handle stmt-var) + 9556 68/push 0/imm32/is-deref:false + 9557 68/push 0/imm32/next + 9558 51/push-ecx/var-foo + 9559 89/<- %edi 4/r32/esp + 9560 # var stmt/esi: statement + 9561 68/push 0/imm32/next + 9562 57/push-edi/outputs + 9563 68/push 0/imm32/inouts + 9564 68/push "increment"/imm32/operation + 9565 68/push 1/imm32 + 9566 89/<- %esi 4/r32/esp + 9567 # convert + 9568 c7 0/subop/copy *Curr-block-depth 0/imm32 + 9569 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) + 9570 (flush _test-output-buffered-file) + 9571 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 9577 # check output + 9578 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-var") + 9579 # . epilogue + 9580 89/<- %esp 5/r32/ebp + 9581 5d/pop-to-ebp + 9582 c3/return + 9583 + 9584 test-add-reg-to-reg: + 9585 # var1/reg <- add var2/reg + 9586 # => + 9587 # 01/add %var1 var2 + 9588 # + 9589 # . prologue + 9590 55/push-ebp + 9591 89/<- %ebp 4/r32/esp + 9592 # setup + 9593 (clear-stream _test-output-stream) + 9594 (clear-stream $_test-output-buffered-file->buffer) + 9595 # var type/ecx: (handle tree type-id) = int + 9596 68/push 0/imm32/right/null + 9597 68/push 1/imm32/left/int + 9598 89/<- %ecx 4/r32/esp + 9599 # var var-var1/ecx: var in eax + 9600 68/push "eax"/imm32/register + 9601 68/push 0/imm32/no-stack-offset + 9602 68/push 1/imm32/block-depth + 9603 51/push-ecx + 9604 68/push "var1"/imm32 + 9605 89/<- %ecx 4/r32/esp + 9606 # var var-var2/edx: var in ecx + 9607 68/push "ecx"/imm32/register + 9608 68/push 0/imm32/no-stack-offset + 9609 68/push 1/imm32/block-depth + 9610 ff 6/subop/push *(ecx+4) # Var-type + 9611 68/push "var2"/imm32 + 9612 89/<- %edx 4/r32/esp + 9613 # var inouts/esi: (handle stmt-var) = [var2] + 9614 68/push 0/imm32/is-deref:false + 9615 68/push 0/imm32/next + 9616 52/push-edx/var-var2 + 9617 89/<- %esi 4/r32/esp + 9618 # var outputs/edi: (handle stmt-var) = [var1, var2] + 9619 68/push 0/imm32/is-deref:false + 9620 68/push 0/imm32/next + 9621 51/push-ecx/var-var1 + 9622 89/<- %edi 4/r32/esp + 9623 # var stmt/esi: statement + 9624 68/push 0/imm32/next + 9625 57/push-edi/outputs + 9626 56/push-esi/inouts + 9627 68/push "add"/imm32/operation + 9628 68/push 1/imm32 9629 89/<- %esi 4/r32/esp - 9630 # var outputs/edi: (handle stmt-var) = [var1, var2] - 9631 68/push 0/imm32/is-deref:false - 9632 68/push 0/imm32/next - 9633 51/push-ecx/var-var1 - 9634 89/<- %edi 4/r32/esp - 9635 # var stmt/esi: statement - 9636 68/push 0/imm32/next - 9637 57/push-edi/outputs - 9638 56/push-esi/inouts - 9639 68/push "add"/imm32/operation - 9640 68/push 1/imm32 - 9641 89/<- %esi 4/r32/esp - 9642 # convert - 9643 c7 0/subop/copy *Curr-block-depth 0/imm32 - 9644 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) - 9645 (flush _test-output-buffered-file) - 9646 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 9652 # check output - 9653 (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg") - 9654 # . epilogue - 9655 89/<- %esp 5/r32/ebp - 9656 5d/pop-to-ebp - 9657 c3/return - 9658 - 9659 test-add-reg-to-mem: - 9660 # add-to var1 var2/reg - 9661 # => - 9662 # 01/add *(ebp+__) var2 - 9663 # - 9664 # . prologue - 9665 55/push-ebp - 9666 89/<- %ebp 4/r32/esp - 9667 # setup - 9668 (clear-stream _test-output-stream) - 9669 (clear-stream $_test-output-buffered-file->buffer) - 9670 # var type/ecx: (handle tree type-id) = int - 9671 68/push 0/imm32/right/null - 9672 68/push 1/imm32/left/int - 9673 89/<- %ecx 4/r32/esp - 9674 # var var-var1/ecx: var - 9675 68/push 0/imm32/no-register - 9676 68/push 8/imm32/stack-offset - 9677 68/push 1/imm32/block-depth - 9678 51/push-ecx - 9679 68/push "var1"/imm32 - 9680 89/<- %ecx 4/r32/esp - 9681 # var var-var2/edx: var in ecx - 9682 68/push "ecx"/imm32/register - 9683 68/push 0/imm32/no-stack-offset - 9684 68/push 1/imm32/block-depth - 9685 ff 6/subop/push *(ecx+4) # Var-type - 9686 68/push "var2"/imm32 - 9687 89/<- %edx 4/r32/esp - 9688 # var inouts/esi: (handle stmt-var) = [var2] - 9689 68/push 0/imm32/is-deref:false - 9690 68/push 0/imm32/next - 9691 52/push-edx/var-var2 - 9692 89/<- %esi 4/r32/esp - 9693 # var inouts = (handle stmt-var) = [var1, var2] - 9694 56/push-esi/next - 9695 51/push-ecx/var-var1 - 9696 89/<- %esi 4/r32/esp - 9697 # var stmt/esi: statement - 9698 68/push 0/imm32/next - 9699 68/push 0/imm32/outputs - 9700 56/push-esi/inouts - 9701 68/push "add-to"/imm32/operation - 9702 68/push 1/imm32 - 9703 89/<- %esi 4/r32/esp - 9704 # convert - 9705 c7 0/subop/copy *Curr-block-depth 0/imm32 - 9706 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) - 9707 (flush _test-output-buffered-file) - 9708 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 9714 # check output - 9715 (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem") - 9716 # . epilogue - 9717 89/<- %esp 5/r32/ebp - 9718 5d/pop-to-ebp - 9719 c3/return - 9720 - 9721 test-add-mem-to-reg: - 9722 # var1/reg <- add var2 - 9723 # => - 9724 # 03/add *(ebp+__) var1 - 9725 # - 9726 # . prologue - 9727 55/push-ebp - 9728 89/<- %ebp 4/r32/esp - 9729 # setup - 9730 (clear-stream _test-output-stream) - 9731 (clear-stream $_test-output-buffered-file->buffer) - 9732 # var type/ecx: (handle tree type-id) = int - 9733 68/push 0/imm32/right/null - 9734 68/push 1/imm32/left/int - 9735 89/<- %ecx 4/r32/esp - 9736 # var var-var1/ecx: var in eax - 9737 68/push "eax"/imm32/register - 9738 68/push 0/imm32/no-stack-offset - 9739 68/push 1/imm32/block-depth - 9740 51/push-ecx - 9741 68/push "var1"/imm32 - 9742 89/<- %ecx 4/r32/esp - 9743 # var var-var2/edx: var - 9744 68/push 0/imm32/no-register - 9745 68/push 8/imm32/stack-offset - 9746 68/push 1/imm32/block-depth - 9747 ff 6/subop/push *(ecx+4) # Var-type - 9748 68/push "var2"/imm32 - 9749 89/<- %edx 4/r32/esp - 9750 # var inouts/esi: (handle stmt-var) = [var2] - 9751 68/push 0/imm32/is-deref:false - 9752 68/push 0/imm32/next - 9753 52/push-edx/var-var2 + 9630 # convert + 9631 c7 0/subop/copy *Curr-block-depth 0/imm32 + 9632 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) + 9633 (flush _test-output-buffered-file) + 9634 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 9640 # check output + 9641 (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg") + 9642 # . epilogue + 9643 89/<- %esp 5/r32/ebp + 9644 5d/pop-to-ebp + 9645 c3/return + 9646 + 9647 test-add-reg-to-mem: + 9648 # add-to var1 var2/reg + 9649 # => + 9650 # 01/add *(ebp+__) var2 + 9651 # + 9652 # . prologue + 9653 55/push-ebp + 9654 89/<- %ebp 4/r32/esp + 9655 # setup + 9656 (clear-stream _test-output-stream) + 9657 (clear-stream $_test-output-buffered-file->buffer) + 9658 # var type/ecx: (handle tree type-id) = int + 9659 68/push 0/imm32/right/null + 9660 68/push 1/imm32/left/int + 9661 89/<- %ecx 4/r32/esp + 9662 # var var-var1/ecx: var + 9663 68/push 0/imm32/no-register + 9664 68/push 8/imm32/stack-offset + 9665 68/push 1/imm32/block-depth + 9666 51/push-ecx + 9667 68/push "var1"/imm32 + 9668 89/<- %ecx 4/r32/esp + 9669 # var var-var2/edx: var in ecx + 9670 68/push "ecx"/imm32/register + 9671 68/push 0/imm32/no-stack-offset + 9672 68/push 1/imm32/block-depth + 9673 ff 6/subop/push *(ecx+4) # Var-type + 9674 68/push "var2"/imm32 + 9675 89/<- %edx 4/r32/esp + 9676 # var inouts/esi: (handle stmt-var) = [var2] + 9677 68/push 0/imm32/is-deref:false + 9678 68/push 0/imm32/next + 9679 52/push-edx/var-var2 + 9680 89/<- %esi 4/r32/esp + 9681 # var inouts = (handle stmt-var) = [var1, var2] + 9682 56/push-esi/next + 9683 51/push-ecx/var-var1 + 9684 89/<- %esi 4/r32/esp + 9685 # var stmt/esi: statement + 9686 68/push 0/imm32/next + 9687 68/push 0/imm32/outputs + 9688 56/push-esi/inouts + 9689 68/push "add-to"/imm32/operation + 9690 68/push 1/imm32 + 9691 89/<- %esi 4/r32/esp + 9692 # convert + 9693 c7 0/subop/copy *Curr-block-depth 0/imm32 + 9694 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) + 9695 (flush _test-output-buffered-file) + 9696 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 9702 # check output + 9703 (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem") + 9704 # . epilogue + 9705 89/<- %esp 5/r32/ebp + 9706 5d/pop-to-ebp + 9707 c3/return + 9708 + 9709 test-add-mem-to-reg: + 9710 # var1/reg <- add var2 + 9711 # => + 9712 # 03/add *(ebp+__) var1 + 9713 # + 9714 # . prologue + 9715 55/push-ebp + 9716 89/<- %ebp 4/r32/esp + 9717 # setup + 9718 (clear-stream _test-output-stream) + 9719 (clear-stream $_test-output-buffered-file->buffer) + 9720 # var type/ecx: (handle tree type-id) = int + 9721 68/push 0/imm32/right/null + 9722 68/push 1/imm32/left/int + 9723 89/<- %ecx 4/r32/esp + 9724 # var var-var1/ecx: var in eax + 9725 68/push "eax"/imm32/register + 9726 68/push 0/imm32/no-stack-offset + 9727 68/push 1/imm32/block-depth + 9728 51/push-ecx + 9729 68/push "var1"/imm32 + 9730 89/<- %ecx 4/r32/esp + 9731 # var var-var2/edx: var + 9732 68/push 0/imm32/no-register + 9733 68/push 8/imm32/stack-offset + 9734 68/push 1/imm32/block-depth + 9735 ff 6/subop/push *(ecx+4) # Var-type + 9736 68/push "var2"/imm32 + 9737 89/<- %edx 4/r32/esp + 9738 # var inouts/esi: (handle stmt-var) = [var2] + 9739 68/push 0/imm32/is-deref:false + 9740 68/push 0/imm32/next + 9741 52/push-edx/var-var2 + 9742 89/<- %esi 4/r32/esp + 9743 # var outputs/edi = (handle stmt-var) = [var1] + 9744 68/push 0/imm32/is-deref:false + 9745 68/push 0/imm32/next + 9746 51/push-ecx/var-var1 + 9747 89/<- %edi 4/r32/esp + 9748 # var stmt/esi: statement + 9749 68/push 0/imm32/next + 9750 57/push-edi/outputs + 9751 56/push-esi/inouts + 9752 68/push "add"/imm32/operation + 9753 68/push 1/imm32 9754 89/<- %esi 4/r32/esp - 9755 # var outputs/edi = (handle stmt-var) = [var1] - 9756 68/push 0/imm32/is-deref:false - 9757 68/push 0/imm32/next - 9758 51/push-ecx/var-var1 - 9759 89/<- %edi 4/r32/esp - 9760 # var stmt/esi: statement - 9761 68/push 0/imm32/next - 9762 57/push-edi/outputs - 9763 56/push-esi/inouts - 9764 68/push "add"/imm32/operation - 9765 68/push 1/imm32 - 9766 89/<- %esi 4/r32/esp - 9767 # convert - 9768 c7 0/subop/copy *Curr-block-depth 0/imm32 - 9769 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) - 9770 (flush _test-output-buffered-file) - 9771 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 9777 # check output - 9778 (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg") - 9779 # . epilogue - 9780 89/<- %esp 5/r32/ebp - 9781 5d/pop-to-ebp - 9782 c3/return - 9783 - 9784 test-add-literal-to-eax: - 9785 # var1/eax <- add 0x34 - 9786 # => - 9787 # 05/add-to-eax 0x34/imm32 - 9788 # - 9789 # . prologue - 9790 55/push-ebp - 9791 89/<- %ebp 4/r32/esp - 9792 # setup - 9793 (clear-stream _test-output-stream) - 9794 (clear-stream $_test-output-buffered-file->buffer) - 9795 # var type/ecx: (handle tree type-id) = int - 9796 68/push 0/imm32/right/null - 9797 68/push 1/imm32/left/int - 9798 89/<- %ecx 4/r32/esp - 9799 # var var-var1/ecx: var in eax - 9800 68/push "eax"/imm32/register - 9801 68/push 0/imm32/no-stack-offset - 9802 68/push 1/imm32/block-depth - 9803 51/push-ecx - 9804 68/push "var1"/imm32 - 9805 89/<- %ecx 4/r32/esp - 9806 # var type/edx: (handle tree type-id) = literal - 9807 68/push 0/imm32/right/null - 9808 68/push 0/imm32/left/literal - 9809 89/<- %edx 4/r32/esp - 9810 # var var-var2/edx: var literal - 9811 68/push 0/imm32/no-register - 9812 68/push 0/imm32/no-stack-offset - 9813 68/push 1/imm32/block-depth - 9814 52/push-edx - 9815 68/push "0x34"/imm32 - 9816 89/<- %edx 4/r32/esp - 9817 # var inouts/esi: (handle stmt-var) = [var2] - 9818 68/push 0/imm32/is-deref:false - 9819 68/push 0/imm32/next - 9820 52/push-edx/var-var2 + 9755 # convert + 9756 c7 0/subop/copy *Curr-block-depth 0/imm32 + 9757 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) + 9758 (flush _test-output-buffered-file) + 9759 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 9765 # check output + 9766 (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg") + 9767 # . epilogue + 9768 89/<- %esp 5/r32/ebp + 9769 5d/pop-to-ebp + 9770 c3/return + 9771 + 9772 test-add-literal-to-eax: + 9773 # var1/eax <- add 0x34 + 9774 # => + 9775 # 05/add-to-eax 0x34/imm32 + 9776 # + 9777 # . prologue + 9778 55/push-ebp + 9779 89/<- %ebp 4/r32/esp + 9780 # setup + 9781 (clear-stream _test-output-stream) + 9782 (clear-stream $_test-output-buffered-file->buffer) + 9783 # var type/ecx: (handle tree type-id) = int + 9784 68/push 0/imm32/right/null + 9785 68/push 1/imm32/left/int + 9786 89/<- %ecx 4/r32/esp + 9787 # var var-var1/ecx: var in eax + 9788 68/push "eax"/imm32/register + 9789 68/push 0/imm32/no-stack-offset + 9790 68/push 1/imm32/block-depth + 9791 51/push-ecx + 9792 68/push "var1"/imm32 + 9793 89/<- %ecx 4/r32/esp + 9794 # var type/edx: (handle tree type-id) = literal + 9795 68/push 0/imm32/right/null + 9796 68/push 0/imm32/left/literal + 9797 89/<- %edx 4/r32/esp + 9798 # var var-var2/edx: var literal + 9799 68/push 0/imm32/no-register + 9800 68/push 0/imm32/no-stack-offset + 9801 68/push 1/imm32/block-depth + 9802 52/push-edx + 9803 68/push "0x34"/imm32 + 9804 89/<- %edx 4/r32/esp + 9805 # var inouts/esi: (handle stmt-var) = [var2] + 9806 68/push 0/imm32/is-deref:false + 9807 68/push 0/imm32/next + 9808 52/push-edx/var-var2 + 9809 89/<- %esi 4/r32/esp + 9810 # var outputs/edi: (handle stmt-var) = [var1] + 9811 68/push 0/imm32/is-deref:false + 9812 68/push 0/imm32/next + 9813 51/push-ecx/var-var1 + 9814 89/<- %edi 4/r32/esp + 9815 # var stmt/esi: statement + 9816 68/push 0/imm32/next + 9817 57/push-edi/outputs + 9818 56/push-esi/inouts + 9819 68/push "add"/imm32/operation + 9820 68/push 1/imm32 9821 89/<- %esi 4/r32/esp - 9822 # var outputs/edi: (handle stmt-var) = [var1] - 9823 68/push 0/imm32/is-deref:false - 9824 68/push 0/imm32/next - 9825 51/push-ecx/var-var1 - 9826 89/<- %edi 4/r32/esp - 9827 # var stmt/esi: statement - 9828 68/push 0/imm32/next - 9829 57/push-edi/outputs - 9830 56/push-esi/inouts - 9831 68/push "add"/imm32/operation - 9832 68/push 1/imm32 - 9833 89/<- %esi 4/r32/esp - 9834 # convert - 9835 c7 0/subop/copy *Curr-block-depth 0/imm32 - 9836 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) - 9837 (flush _test-output-buffered-file) - 9838 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 9844 # check output - 9845 (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax") - 9846 # . epilogue - 9847 89/<- %esp 5/r32/ebp - 9848 5d/pop-to-ebp - 9849 c3/return - 9850 - 9851 test-add-literal-to-reg: - 9852 # var1/ecx <- add 0x34 - 9853 # => - 9854 # 81 0/subop/add %ecx 0x34/imm32 - 9855 # - 9856 # . prologue - 9857 55/push-ebp - 9858 89/<- %ebp 4/r32/esp - 9859 # setup - 9860 (clear-stream _test-output-stream) - 9861 (clear-stream $_test-output-buffered-file->buffer) - 9862 # var type/ecx: (handle tree type-id) = int - 9863 68/push 0/imm32/right/null - 9864 68/push 1/imm32/left/int - 9865 89/<- %ecx 4/r32/esp - 9866 # var var-var1/ecx: var in ecx - 9867 68/push "ecx"/imm32/register - 9868 68/push 0/imm32/no-stack-offset - 9869 68/push 1/imm32/block-depth - 9870 51/push-ecx - 9871 68/push "var1"/imm32 - 9872 89/<- %ecx 4/r32/esp - 9873 # var type/edx: (handle tree type-id) = literal - 9874 68/push 0/imm32/right/null - 9875 68/push 0/imm32/left/literal - 9876 89/<- %edx 4/r32/esp - 9877 # var var-var2/edx: var literal - 9878 68/push 0/imm32/no-register - 9879 68/push 0/imm32/no-stack-offset - 9880 68/push 1/imm32/block-depth - 9881 52/push-edx - 9882 68/push "0x34"/imm32 - 9883 89/<- %edx 4/r32/esp - 9884 # var inouts/esi: (handle stmt-var) = [var2] - 9885 68/push 0/imm32/is-deref:false - 9886 68/push 0/imm32/next - 9887 52/push-edx/var-var2 + 9822 # convert + 9823 c7 0/subop/copy *Curr-block-depth 0/imm32 + 9824 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) + 9825 (flush _test-output-buffered-file) + 9826 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 9832 # check output + 9833 (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax") + 9834 # . epilogue + 9835 89/<- %esp 5/r32/ebp + 9836 5d/pop-to-ebp + 9837 c3/return + 9838 + 9839 test-add-literal-to-reg: + 9840 # var1/ecx <- add 0x34 + 9841 # => + 9842 # 81 0/subop/add %ecx 0x34/imm32 + 9843 # + 9844 # . prologue + 9845 55/push-ebp + 9846 89/<- %ebp 4/r32/esp + 9847 # setup + 9848 (clear-stream _test-output-stream) + 9849 (clear-stream $_test-output-buffered-file->buffer) + 9850 # var type/ecx: (handle tree type-id) = int + 9851 68/push 0/imm32/right/null + 9852 68/push 1/imm32/left/int + 9853 89/<- %ecx 4/r32/esp + 9854 # var var-var1/ecx: var in ecx + 9855 68/push "ecx"/imm32/register + 9856 68/push 0/imm32/no-stack-offset + 9857 68/push 1/imm32/block-depth + 9858 51/push-ecx + 9859 68/push "var1"/imm32 + 9860 89/<- %ecx 4/r32/esp + 9861 # var type/edx: (handle tree type-id) = literal + 9862 68/push 0/imm32/right/null + 9863 68/push 0/imm32/left/literal + 9864 89/<- %edx 4/r32/esp + 9865 # var var-var2/edx: var literal + 9866 68/push 0/imm32/no-register + 9867 68/push 0/imm32/no-stack-offset + 9868 68/push 1/imm32/block-depth + 9869 52/push-edx + 9870 68/push "0x34"/imm32 + 9871 89/<- %edx 4/r32/esp + 9872 # var inouts/esi: (handle stmt-var) = [var2] + 9873 68/push 0/imm32/is-deref:false + 9874 68/push 0/imm32/next + 9875 52/push-edx/var-var2 + 9876 89/<- %esi 4/r32/esp + 9877 # var outputs/edi: (handle stmt-var) = [var1] + 9878 68/push 0/imm32/is-deref:false + 9879 68/push 0/imm32/next + 9880 51/push-ecx/var-var1 + 9881 89/<- %edi 4/r32/esp + 9882 # var stmt/esi: statement + 9883 68/push 0/imm32/next + 9884 57/push-edi/outputs + 9885 56/push-esi/inouts + 9886 68/push "add"/imm32/operation + 9887 68/push 1/imm32 9888 89/<- %esi 4/r32/esp - 9889 # var outputs/edi: (handle stmt-var) = [var1] - 9890 68/push 0/imm32/is-deref:false - 9891 68/push 0/imm32/next - 9892 51/push-ecx/var-var1 - 9893 89/<- %edi 4/r32/esp - 9894 # var stmt/esi: statement - 9895 68/push 0/imm32/next - 9896 57/push-edi/outputs - 9897 56/push-esi/inouts - 9898 68/push "add"/imm32/operation - 9899 68/push 1/imm32 - 9900 89/<- %esi 4/r32/esp - 9901 # convert - 9902 c7 0/subop/copy *Curr-block-depth 0/imm32 - 9903 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) - 9904 (flush _test-output-buffered-file) - 9905 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 9911 # check output - 9912 (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg") - 9913 # . epilogue - 9914 89/<- %esp 5/r32/ebp - 9915 5d/pop-to-ebp - 9916 c3/return - 9917 - 9918 test-add-literal-to-mem: - 9919 # add-to var1, 0x34 - 9920 # => - 9921 # 81 0/subop/add %eax 0x34/imm32 - 9922 # - 9923 # . prologue - 9924 55/push-ebp - 9925 89/<- %ebp 4/r32/esp - 9926 # setup - 9927 (clear-stream _test-output-stream) - 9928 (clear-stream $_test-output-buffered-file->buffer) - 9929 # var type/ecx: (handle tree type-id) = int - 9930 68/push 0/imm32/right/null - 9931 68/push 1/imm32/left/int - 9932 89/<- %ecx 4/r32/esp - 9933 # var var-var1/ecx: var - 9934 68/push 0/imm32/no-register - 9935 68/push 8/imm32/stack-offset - 9936 68/push 1/imm32/block-depth - 9937 51/push-ecx - 9938 68/push "var1"/imm32 - 9939 89/<- %ecx 4/r32/esp - 9940 # var type/edx: (handle tree type-id) = literal - 9941 68/push 0/imm32/right/null - 9942 68/push 0/imm32/left/literal - 9943 89/<- %edx 4/r32/esp - 9944 # var var-var2/edx: var literal - 9945 68/push 0/imm32/no-register - 9946 68/push 0/imm32/no-stack-offset - 9947 68/push 1/imm32/block-depth - 9948 52/push-edx - 9949 68/push "0x34"/imm32 - 9950 89/<- %edx 4/r32/esp - 9951 # var inouts/esi: (handle stmt-var) = [var2] - 9952 68/push 0/imm32/is-deref:false - 9953 68/push 0/imm32/next - 9954 52/push-edx/var-var2 + 9889 # convert + 9890 c7 0/subop/copy *Curr-block-depth 0/imm32 + 9891 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) + 9892 (flush _test-output-buffered-file) + 9893 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 9899 # check output + 9900 (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg") + 9901 # . epilogue + 9902 89/<- %esp 5/r32/ebp + 9903 5d/pop-to-ebp + 9904 c3/return + 9905 + 9906 test-add-literal-to-mem: + 9907 # add-to var1, 0x34 + 9908 # => + 9909 # 81 0/subop/add %eax 0x34/imm32 + 9910 # + 9911 # . prologue + 9912 55/push-ebp + 9913 89/<- %ebp 4/r32/esp + 9914 # setup + 9915 (clear-stream _test-output-stream) + 9916 (clear-stream $_test-output-buffered-file->buffer) + 9917 # var type/ecx: (handle tree type-id) = int + 9918 68/push 0/imm32/right/null + 9919 68/push 1/imm32/left/int + 9920 89/<- %ecx 4/r32/esp + 9921 # var var-var1/ecx: var + 9922 68/push 0/imm32/no-register + 9923 68/push 8/imm32/stack-offset + 9924 68/push 1/imm32/block-depth + 9925 51/push-ecx + 9926 68/push "var1"/imm32 + 9927 89/<- %ecx 4/r32/esp + 9928 # var type/edx: (handle tree type-id) = literal + 9929 68/push 0/imm32/right/null + 9930 68/push 0/imm32/left/literal + 9931 89/<- %edx 4/r32/esp + 9932 # var var-var2/edx: var literal + 9933 68/push 0/imm32/no-register + 9934 68/push 0/imm32/no-stack-offset + 9935 68/push 1/imm32/block-depth + 9936 52/push-edx + 9937 68/push "0x34"/imm32 + 9938 89/<- %edx 4/r32/esp + 9939 # var inouts/esi: (handle stmt-var) = [var2] + 9940 68/push 0/imm32/is-deref:false + 9941 68/push 0/imm32/next + 9942 52/push-edx/var-var2 + 9943 89/<- %esi 4/r32/esp + 9944 # var inouts = (handle stmt-var) = [var1, var2] + 9945 68/push 0/imm32/is-deref:false + 9946 56/push-esi/next + 9947 51/push-ecx/var-var1 + 9948 89/<- %esi 4/r32/esp + 9949 # var stmt/esi: statement + 9950 68/push 0/imm32/next + 9951 68/push 0/imm32/outputs + 9952 56/push-esi/inouts + 9953 68/push "add-to"/imm32/operation + 9954 68/push 1/imm32 9955 89/<- %esi 4/r32/esp - 9956 # var inouts = (handle stmt-var) = [var1, var2] - 9957 68/push 0/imm32/is-deref:false - 9958 56/push-esi/next - 9959 51/push-ecx/var-var1 - 9960 89/<- %esi 4/r32/esp - 9961 # var stmt/esi: statement - 9962 68/push 0/imm32/next - 9963 68/push 0/imm32/outputs - 9964 56/push-esi/inouts - 9965 68/push "add-to"/imm32/operation - 9966 68/push 1/imm32 - 9967 89/<- %esi 4/r32/esp - 9968 # convert - 9969 c7 0/subop/copy *Curr-block-depth 0/imm32 - 9970 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) - 9971 (flush _test-output-buffered-file) - 9972 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 9978 # check output - 9979 (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem") - 9980 # . epilogue - 9981 89/<- %esp 5/r32/ebp - 9982 5d/pop-to-ebp - 9983 c3/return - 9984 - 9985 test-compare-mem-with-reg: - 9986 # compare var1, var2/eax - 9987 # => - 9988 # 39/compare *(ebp+___) 0/r32/eax - 9989 # - 9990 # . prologue - 9991 55/push-ebp - 9992 89/<- %ebp 4/r32/esp - 9993 # setup - 9994 (clear-stream _test-output-stream) - 9995 (clear-stream $_test-output-buffered-file->buffer) - 9996 # var type/ecx: (handle tree type-id) = int - 9997 68/push 0/imm32/right/null - 9998 68/push 1/imm32/left/int - 9999 89/<- %ecx 4/r32/esp -10000 # var var-var2/ecx: var in eax -10001 68/push "eax"/imm32/register -10002 68/push 0/imm32/no-stack-offset -10003 68/push 1/imm32/block-depth -10004 51/push-ecx -10005 68/push "var2"/imm32 -10006 89/<- %ecx 4/r32/esp -10007 # var var-var1/edx: var -10008 68/push 0/imm32/no-register -10009 68/push 8/imm32/stack-offset -10010 68/push 1/imm32/block-depth -10011 ff 6/subop/push *(ecx+4) # Var-type -10012 68/push "var1"/imm32 -10013 89/<- %edx 4/r32/esp -10014 # var inouts/esi: (handle stmt-var) = [var2] -10015 68/push 0/imm32/is-deref:false -10016 68/push 0/imm32/next -10017 51/push-ecx/var-var2 + 9956 # convert + 9957 c7 0/subop/copy *Curr-block-depth 0/imm32 + 9958 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) + 9959 (flush _test-output-buffered-file) + 9960 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 9966 # check output + 9967 (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem") + 9968 # . epilogue + 9969 89/<- %esp 5/r32/ebp + 9970 5d/pop-to-ebp + 9971 c3/return + 9972 + 9973 test-compare-mem-with-reg: + 9974 # compare var1, var2/eax + 9975 # => + 9976 # 39/compare *(ebp+___) 0/r32/eax + 9977 # + 9978 # . prologue + 9979 55/push-ebp + 9980 89/<- %ebp 4/r32/esp + 9981 # setup + 9982 (clear-stream _test-output-stream) + 9983 (clear-stream $_test-output-buffered-file->buffer) + 9984 # var type/ecx: (handle tree type-id) = int + 9985 68/push 0/imm32/right/null + 9986 68/push 1/imm32/left/int + 9987 89/<- %ecx 4/r32/esp + 9988 # var var-var2/ecx: var in eax + 9989 68/push "eax"/imm32/register + 9990 68/push 0/imm32/no-stack-offset + 9991 68/push 1/imm32/block-depth + 9992 51/push-ecx + 9993 68/push "var2"/imm32 + 9994 89/<- %ecx 4/r32/esp + 9995 # var var-var1/edx: var + 9996 68/push 0/imm32/no-register + 9997 68/push 8/imm32/stack-offset + 9998 68/push 1/imm32/block-depth + 9999 ff 6/subop/push *(ecx+4) # Var-type +10000 68/push "var1"/imm32 +10001 89/<- %edx 4/r32/esp +10002 # var inouts/esi: (handle stmt-var) = [var2] +10003 68/push 0/imm32/is-deref:false +10004 68/push 0/imm32/next +10005 51/push-ecx/var-var2 +10006 89/<- %esi 4/r32/esp +10007 # inouts = [var1, var2] +10008 68/push 0/imm32/is-deref:false +10009 56/push-esi +10010 52/push-edx/var-var1 +10011 89/<- %esi 4/r32/esp +10012 # var stmt/esi: statement +10013 68/push 0/imm32/next +10014 68/push 0/imm32/outputs +10015 56/push-esi/inouts +10016 68/push "compare"/imm32/operation +10017 68/push 1/imm32 10018 89/<- %esi 4/r32/esp -10019 # inouts = [var1, var2] -10020 68/push 0/imm32/is-deref:false -10021 56/push-esi -10022 52/push-edx/var-var1 -10023 89/<- %esi 4/r32/esp -10024 # var stmt/esi: statement -10025 68/push 0/imm32/next -10026 68/push 0/imm32/outputs -10027 56/push-esi/inouts -10028 68/push "compare"/imm32/operation -10029 68/push 1/imm32 -10030 89/<- %esi 4/r32/esp -10031 # convert -10032 c7 0/subop/copy *Curr-block-depth 0/imm32 -10033 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -10034 (flush _test-output-buffered-file) -10035 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10041 # check output -10042 (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg") -10043 # . epilogue -10044 89/<- %esp 5/r32/ebp -10045 5d/pop-to-ebp -10046 c3/return -10047 -10048 test-compare-reg-with-mem: -10049 # compare var1/eax, var2 -10050 # => -10051 # 3b/compare *(ebp+___) 0/r32/eax -10052 # -10053 # . prologue -10054 55/push-ebp -10055 89/<- %ebp 4/r32/esp -10056 # setup -10057 (clear-stream _test-output-stream) -10058 (clear-stream $_test-output-buffered-file->buffer) -10059 # var type/ecx: (handle tree type-id) = int -10060 68/push 0/imm32/right/null -10061 68/push 1/imm32/left/int -10062 89/<- %ecx 4/r32/esp -10063 # var var-var1/ecx: var in eax -10064 68/push "eax"/imm32/register -10065 68/push 0/imm32/no-stack-offset -10066 68/push 1/imm32/block-depth -10067 51/push-ecx -10068 68/push "var1"/imm32 -10069 89/<- %ecx 4/r32/esp -10070 # var var-var2/edx: var -10071 68/push 0/imm32/no-register -10072 68/push 8/imm32/stack-offset -10073 68/push 1/imm32/block-depth -10074 ff 6/subop/push *(ecx+4) # Var-type -10075 68/push "var2"/imm32 -10076 89/<- %edx 4/r32/esp -10077 # var inouts/esi: (handle stmt-var) = [var2] -10078 68/push 0/imm32/is-deref:false -10079 68/push 0/imm32/next -10080 52/push-edx/var-var2 +10019 # convert +10020 c7 0/subop/copy *Curr-block-depth 0/imm32 +10021 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +10022 (flush _test-output-buffered-file) +10023 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +10029 # check output +10030 (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg") +10031 # . epilogue +10032 89/<- %esp 5/r32/ebp +10033 5d/pop-to-ebp +10034 c3/return +10035 +10036 test-compare-reg-with-mem: +10037 # compare var1/eax, var2 +10038 # => +10039 # 3b/compare *(ebp+___) 0/r32/eax +10040 # +10041 # . prologue +10042 55/push-ebp +10043 89/<- %ebp 4/r32/esp +10044 # setup +10045 (clear-stream _test-output-stream) +10046 (clear-stream $_test-output-buffered-file->buffer) +10047 # var type/ecx: (handle tree type-id) = int +10048 68/push 0/imm32/right/null +10049 68/push 1/imm32/left/int +10050 89/<- %ecx 4/r32/esp +10051 # var var-var1/ecx: var in eax +10052 68/push "eax"/imm32/register +10053 68/push 0/imm32/no-stack-offset +10054 68/push 1/imm32/block-depth +10055 51/push-ecx +10056 68/push "var1"/imm32 +10057 89/<- %ecx 4/r32/esp +10058 # var var-var2/edx: var +10059 68/push 0/imm32/no-register +10060 68/push 8/imm32/stack-offset +10061 68/push 1/imm32/block-depth +10062 ff 6/subop/push *(ecx+4) # Var-type +10063 68/push "var2"/imm32 +10064 89/<- %edx 4/r32/esp +10065 # var inouts/esi: (handle stmt-var) = [var2] +10066 68/push 0/imm32/is-deref:false +10067 68/push 0/imm32/next +10068 52/push-edx/var-var2 +10069 89/<- %esi 4/r32/esp +10070 # inouts = [var1, var2] +10071 68/push 0/imm32/is-deref:false +10072 56/push-esi +10073 51/push-ecx/var-var1 +10074 89/<- %esi 4/r32/esp +10075 # var stmt/esi: statement +10076 68/push 0/imm32/next +10077 68/push 0/imm32/outputs +10078 56/push-esi/inouts +10079 68/push "compare"/imm32/operation +10080 68/push 1/imm32 10081 89/<- %esi 4/r32/esp -10082 # inouts = [var1, var2] -10083 68/push 0/imm32/is-deref:false -10084 56/push-esi -10085 51/push-ecx/var-var1 -10086 89/<- %esi 4/r32/esp -10087 # var stmt/esi: statement -10088 68/push 0/imm32/next -10089 68/push 0/imm32/outputs -10090 56/push-esi/inouts -10091 68/push "compare"/imm32/operation -10092 68/push 1/imm32 -10093 89/<- %esi 4/r32/esp -10094 # convert -10095 c7 0/subop/copy *Curr-block-depth 0/imm32 -10096 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -10097 (flush _test-output-buffered-file) -10098 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10104 # check output -10105 (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem") -10106 # . epilogue -10107 89/<- %esp 5/r32/ebp -10108 5d/pop-to-ebp -10109 c3/return -10110 -10111 test-compare-mem-with-literal: -10112 # compare var1, 0x34 -10113 # => -10114 # 81 7/subop/compare *(ebp+___) 0x34/imm32 -10115 # -10116 # . prologue -10117 55/push-ebp -10118 89/<- %ebp 4/r32/esp -10119 # setup -10120 (clear-stream _test-output-stream) -10121 (clear-stream $_test-output-buffered-file->buffer) -10122 # var type/ecx: (handle tree type-id) = int -10123 68/push 0/imm32/right/null -10124 68/push 1/imm32/left/int -10125 89/<- %ecx 4/r32/esp -10126 # var var-var1/ecx: var -10127 68/push 0/imm32/no-register -10128 68/push 8/imm32/stack-offset -10129 68/push 1/imm32/block-depth -10130 51/push-ecx -10131 68/push "var1"/imm32 -10132 89/<- %ecx 4/r32/esp -10133 # var type/edx: (handle tree type-id) = literal -10134 68/push 0/imm32/right/null -10135 68/push 0/imm32/left/literal -10136 89/<- %edx 4/r32/esp -10137 # var var-var2/edx: var literal -10138 68/push 0/imm32/no-register -10139 68/push 0/imm32/no-stack-offset -10140 68/push 1/imm32/block-depth -10141 52/push-edx -10142 68/push "0x34"/imm32 -10143 89/<- %edx 4/r32/esp -10144 # var inouts/esi: (handle stmt-var) = [var2] -10145 68/push 0/imm32/is-deref:false -10146 68/push 0/imm32/next -10147 52/push-edx/var-var2 +10082 # convert +10083 c7 0/subop/copy *Curr-block-depth 0/imm32 +10084 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +10085 (flush _test-output-buffered-file) +10086 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +10092 # check output +10093 (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem") +10094 # . epilogue +10095 89/<- %esp 5/r32/ebp +10096 5d/pop-to-ebp +10097 c3/return +10098 +10099 test-compare-mem-with-literal: +10100 # compare var1, 0x34 +10101 # => +10102 # 81 7/subop/compare *(ebp+___) 0x34/imm32 +10103 # +10104 # . prologue +10105 55/push-ebp +10106 89/<- %ebp 4/r32/esp +10107 # setup +10108 (clear-stream _test-output-stream) +10109 (clear-stream $_test-output-buffered-file->buffer) +10110 # var type/ecx: (handle tree type-id) = int +10111 68/push 0/imm32/right/null +10112 68/push 1/imm32/left/int +10113 89/<- %ecx 4/r32/esp +10114 # var var-var1/ecx: var +10115 68/push 0/imm32/no-register +10116 68/push 8/imm32/stack-offset +10117 68/push 1/imm32/block-depth +10118 51/push-ecx +10119 68/push "var1"/imm32 +10120 89/<- %ecx 4/r32/esp +10121 # var type/edx: (handle tree type-id) = literal +10122 68/push 0/imm32/right/null +10123 68/push 0/imm32/left/literal +10124 89/<- %edx 4/r32/esp +10125 # var var-var2/edx: var literal +10126 68/push 0/imm32/no-register +10127 68/push 0/imm32/no-stack-offset +10128 68/push 1/imm32/block-depth +10129 52/push-edx +10130 68/push "0x34"/imm32 +10131 89/<- %edx 4/r32/esp +10132 # var inouts/esi: (handle stmt-var) = [var2] +10133 68/push 0/imm32/is-deref:false +10134 68/push 0/imm32/next +10135 52/push-edx/var-var2 +10136 89/<- %esi 4/r32/esp +10137 # inouts = [var1, var2] +10138 68/push 0/imm32/is-deref:false +10139 56/push-esi/next +10140 51/push-ecx/var-var1 +10141 89/<- %esi 4/r32/esp +10142 # var stmt/esi: statement +10143 68/push 0/imm32/next +10144 68/push 0/imm32/outputs +10145 56/push-esi/inouts +10146 68/push "compare"/imm32/operation +10147 68/push 1/imm32 10148 89/<- %esi 4/r32/esp -10149 # inouts = [var1, var2] -10150 68/push 0/imm32/is-deref:false -10151 56/push-esi/next -10152 51/push-ecx/var-var1 -10153 89/<- %esi 4/r32/esp -10154 # var stmt/esi: statement -10155 68/push 0/imm32/next -10156 68/push 0/imm32/outputs -10157 56/push-esi/inouts -10158 68/push "compare"/imm32/operation -10159 68/push 1/imm32 -10160 89/<- %esi 4/r32/esp -10161 # convert -10162 c7 0/subop/copy *Curr-block-depth 0/imm32 -10163 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -10164 (flush _test-output-buffered-file) -10165 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10171 # check output -10172 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal") -10173 # . epilogue -10174 89/<- %esp 5/r32/ebp -10175 5d/pop-to-ebp -10176 c3/return -10177 -10178 test-compare-eax-with-literal: -10179 # compare var1/eax 0x34 -10180 # => -10181 # 3d/compare-eax-with 0x34/imm32 -10182 # -10183 # . prologue -10184 55/push-ebp -10185 89/<- %ebp 4/r32/esp -10186 # setup -10187 (clear-stream _test-output-stream) -10188 (clear-stream $_test-output-buffered-file->buffer) -10189 # var type/ecx: (handle tree type-id) = int -10190 68/push 0/imm32/right/null -10191 68/push 1/imm32/left/int -10192 89/<- %ecx 4/r32/esp -10193 # var var-var1/ecx: var in eax -10194 68/push "eax"/imm32/register -10195 68/push 0/imm32/no-stack-offset -10196 68/push 1/imm32/block-depth -10197 51/push-ecx -10198 68/push "var1"/imm32 -10199 89/<- %ecx 4/r32/esp -10200 # var type/edx: (handle tree type-id) = literal -10201 68/push 0/imm32/right/null -10202 68/push 0/imm32/left/literal -10203 89/<- %edx 4/r32/esp -10204 # var var-var2/edx: var literal -10205 68/push 0/imm32/no-register -10206 68/push 0/imm32/no-stack-offset -10207 68/push 1/imm32/block-depth -10208 52/push-edx -10209 68/push "0x34"/imm32 -10210 89/<- %edx 4/r32/esp -10211 # var inouts/esi: (handle stmt-var) = [var2] -10212 68/push 0/imm32/is-deref:false -10213 68/push 0/imm32/next -10214 52/push-edx/var-var2 +10149 # convert +10150 c7 0/subop/copy *Curr-block-depth 0/imm32 +10151 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +10152 (flush _test-output-buffered-file) +10153 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +10159 # check output +10160 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal") +10161 # . epilogue +10162 89/<- %esp 5/r32/ebp +10163 5d/pop-to-ebp +10164 c3/return +10165 +10166 test-compare-eax-with-literal: +10167 # compare var1/eax 0x34 +10168 # => +10169 # 3d/compare-eax-with 0x34/imm32 +10170 # +10171 # . prologue +10172 55/push-ebp +10173 89/<- %ebp 4/r32/esp +10174 # setup +10175 (clear-stream _test-output-stream) +10176 (clear-stream $_test-output-buffered-file->buffer) +10177 # var type/ecx: (handle tree type-id) = int +10178 68/push 0/imm32/right/null +10179 68/push 1/imm32/left/int +10180 89/<- %ecx 4/r32/esp +10181 # var var-var1/ecx: var in eax +10182 68/push "eax"/imm32/register +10183 68/push 0/imm32/no-stack-offset +10184 68/push 1/imm32/block-depth +10185 51/push-ecx +10186 68/push "var1"/imm32 +10187 89/<- %ecx 4/r32/esp +10188 # var type/edx: (handle tree type-id) = literal +10189 68/push 0/imm32/right/null +10190 68/push 0/imm32/left/literal +10191 89/<- %edx 4/r32/esp +10192 # var var-var2/edx: var literal +10193 68/push 0/imm32/no-register +10194 68/push 0/imm32/no-stack-offset +10195 68/push 1/imm32/block-depth +10196 52/push-edx +10197 68/push "0x34"/imm32 +10198 89/<- %edx 4/r32/esp +10199 # var inouts/esi: (handle stmt-var) = [var2] +10200 68/push 0/imm32/is-deref:false +10201 68/push 0/imm32/next +10202 52/push-edx/var-var2 +10203 89/<- %esi 4/r32/esp +10204 # inouts = [var1, var2] +10205 68/push 0/imm32/is-deref:false +10206 56/push-esi/next +10207 51/push-ecx/var-var1 +10208 89/<- %esi 4/r32/esp +10209 # var stmt/esi: statement +10210 68/push 0/imm32/next +10211 68/push 0/imm32/outputs +10212 56/push-esi/inouts +10213 68/push "compare"/imm32/operation +10214 68/push 1/imm32/regular-stmt 10215 89/<- %esi 4/r32/esp -10216 # inouts = [var1, var2] -10217 68/push 0/imm32/is-deref:false -10218 56/push-esi/next -10219 51/push-ecx/var-var1 -10220 89/<- %esi 4/r32/esp -10221 # var stmt/esi: statement -10222 68/push 0/imm32/next -10223 68/push 0/imm32/outputs -10224 56/push-esi/inouts -10225 68/push "compare"/imm32/operation -10226 68/push 1/imm32/regular-stmt -10227 89/<- %esi 4/r32/esp -10228 # convert -10229 c7 0/subop/copy *Curr-block-depth 0/imm32 -10230 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -10231 (flush _test-output-buffered-file) -10232 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10238 # check output -10239 (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal") -10240 # . epilogue -10241 89/<- %esp 5/r32/ebp -10242 5d/pop-to-ebp -10243 c3/return -10244 -10245 test-compare-reg-with-literal: -10246 # compare var1/ecx 0x34 -10247 # => -10248 # 81 7/subop/compare %ecx 0x34/imm32 -10249 # -10250 # . prologue -10251 55/push-ebp -10252 89/<- %ebp 4/r32/esp -10253 # setup -10254 (clear-stream _test-output-stream) -10255 (clear-stream $_test-output-buffered-file->buffer) -10256 # var type/ecx: (handle tree type-id) = int -10257 68/push 0/imm32/right/null -10258 68/push 1/imm32/left/int -10259 89/<- %ecx 4/r32/esp -10260 # var var-var1/ecx: var in ecx -10261 68/push "ecx"/imm32/register -10262 68/push 0/imm32/no-stack-offset -10263 68/push 1/imm32/block-depth -10264 51/push-ecx -10265 68/push "var1"/imm32 -10266 89/<- %ecx 4/r32/esp -10267 # var type/edx: (handle tree type-id) = literal -10268 68/push 0/imm32/right/null -10269 68/push 0/imm32/left/literal -10270 89/<- %edx 4/r32/esp -10271 # var var-var2/edx: var literal -10272 68/push 0/imm32/no-register -10273 68/push 0/imm32/no-stack-offset -10274 68/push 1/imm32/block-depth -10275 52/push-edx -10276 68/push "0x34"/imm32 -10277 89/<- %edx 4/r32/esp -10278 # var inouts/esi: (handle stmt-var) = [var2] -10279 68/push 0/imm32/is-deref:false -10280 68/push 0/imm32/next -10281 52/push-edx/var-var2 +10216 # convert +10217 c7 0/subop/copy *Curr-block-depth 0/imm32 +10218 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +10219 (flush _test-output-buffered-file) +10220 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +10226 # check output +10227 (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal") +10228 # . epilogue +10229 89/<- %esp 5/r32/ebp +10230 5d/pop-to-ebp +10231 c3/return +10232 +10233 test-compare-reg-with-literal: +10234 # compare var1/ecx 0x34 +10235 # => +10236 # 81 7/subop/compare %ecx 0x34/imm32 +10237 # +10238 # . prologue +10239 55/push-ebp +10240 89/<- %ebp 4/r32/esp +10241 # setup +10242 (clear-stream _test-output-stream) +10243 (clear-stream $_test-output-buffered-file->buffer) +10244 # var type/ecx: (handle tree type-id) = int +10245 68/push 0/imm32/right/null +10246 68/push 1/imm32/left/int +10247 89/<- %ecx 4/r32/esp +10248 # var var-var1/ecx: var in ecx +10249 68/push "ecx"/imm32/register +10250 68/push 0/imm32/no-stack-offset +10251 68/push 1/imm32/block-depth +10252 51/push-ecx +10253 68/push "var1"/imm32 +10254 89/<- %ecx 4/r32/esp +10255 # var type/edx: (handle tree type-id) = literal +10256 68/push 0/imm32/right/null +10257 68/push 0/imm32/left/literal +10258 89/<- %edx 4/r32/esp +10259 # var var-var2/edx: var literal +10260 68/push 0/imm32/no-register +10261 68/push 0/imm32/no-stack-offset +10262 68/push 1/imm32/block-depth +10263 52/push-edx +10264 68/push "0x34"/imm32 +10265 89/<- %edx 4/r32/esp +10266 # var inouts/esi: (handle stmt-var) = [var2] +10267 68/push 0/imm32/is-deref:false +10268 68/push 0/imm32/next +10269 52/push-edx/var-var2 +10270 89/<- %esi 4/r32/esp +10271 # inouts = [var1, var2] +10272 68/push 0/imm32/is-deref:false +10273 56/push-esi/next +10274 51/push-ecx/var-var1 +10275 89/<- %esi 4/r32/esp +10276 # var stmt/esi: statement +10277 68/push 0/imm32/next +10278 68/push 0/imm32/outputs +10279 56/push-esi/inouts +10280 68/push "compare"/imm32/operation +10281 68/push 1/imm32/regular-stmt 10282 89/<- %esi 4/r32/esp -10283 # inouts = [var1, var2] -10284 68/push 0/imm32/is-deref:false -10285 56/push-esi/next -10286 51/push-ecx/var-var1 -10287 89/<- %esi 4/r32/esp -10288 # var stmt/esi: statement -10289 68/push 0/imm32/next -10290 68/push 0/imm32/outputs -10291 56/push-esi/inouts -10292 68/push "compare"/imm32/operation -10293 68/push 1/imm32/regular-stmt -10294 89/<- %esi 4/r32/esp -10295 # convert -10296 c7 0/subop/copy *Curr-block-depth 0/imm32 -10297 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) -10298 (flush _test-output-buffered-file) -10299 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10305 # check output -10306 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal") -10307 # . epilogue -10308 89/<- %esp 5/r32/ebp -10309 5d/pop-to-ebp -10310 c3/return -10311 -10312 test-emit-subx-stmt-function-call: -10313 # Call a function on a variable on the stack. -10314 # f foo -10315 # => -10316 # (f2 *(ebp-8)) -10317 # (Changing the function name supports overloading in general, but here it -10318 # just serves to help disambiguate things.) +10283 # convert +10284 c7 0/subop/copy *Curr-block-depth 0/imm32 +10285 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0) +10286 (flush _test-output-buffered-file) +10287 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +10293 # check output +10294 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal") +10295 # . epilogue +10296 89/<- %esp 5/r32/ebp +10297 5d/pop-to-ebp +10298 c3/return +10299 +10300 test-emit-subx-stmt-function-call: +10301 # Call a function on a variable on the stack. +10302 # f foo +10303 # => +10304 # (f2 *(ebp-8)) +10305 # (Changing the function name supports overloading in general, but here it +10306 # just serves to help disambiguate things.) +10307 # +10308 # There's a variable on the var stack as follows: +10309 # name: 'foo' +10310 # type: int +10311 # stack-offset: -8 +10312 # +10313 # There's nothing in primitives. +10314 # +10315 # There's a function with this info: +10316 # name: 'f' +10317 # inout: int/mem +10318 # value: 'f2' 10319 # -10320 # There's a variable on the var stack as follows: -10321 # name: 'foo' -10322 # type: int -10323 # stack-offset: -8 -10324 # -10325 # There's nothing in primitives. -10326 # -10327 # There's a function with this info: -10328 # name: 'f' -10329 # inout: int/mem -10330 # value: 'f2' -10331 # -10332 # . prologue -10333 55/push-ebp -10334 89/<- %ebp 4/r32/esp -10335 # setup -10336 (clear-stream _test-output-stream) -10337 (clear-stream $_test-output-buffered-file->buffer) -10338 # var type/ecx: (handle tree type-id) = int -10339 68/push 0/imm32/right/null -10340 68/push 1/imm32/left/int -10341 89/<- %ecx 4/r32/esp -10342 # var var-foo/ecx: var -10343 68/push 0/imm32/no-register -10344 68/push -8/imm32/stack-offset -10345 68/push 0/imm32/block-depth -10346 51/push-ecx -10347 68/push "foo"/imm32 -10348 89/<- %ecx 4/r32/esp -10349 # var inouts/esi: (handle stmt-var) -10350 68/push 0/imm32/is-deref:false -10351 68/push 0/imm32/next -10352 51/push-ecx/var-foo -10353 89/<- %esi 4/r32/esp -10354 # var stmt/esi: statement -10355 68/push 0/imm32/next -10356 68/push 0/imm32/outputs -10357 56/push-esi/inouts -10358 68/push "f"/imm32/operation -10359 68/push 1/imm32 -10360 89/<- %esi 4/r32/esp -10361 # var functions/ebx: function -10362 68/push 0/imm32/next -10363 68/push 0/imm32/body -10364 68/push 0/imm32/outputs -10365 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call -10366 68/push "f2"/imm32/subx-name -10367 68/push "f"/imm32/name -10368 89/<- %ebx 4/r32/esp -10369 # convert -10370 c7 0/subop/copy *Curr-block-depth 0/imm32 -10371 (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx) -10372 (flush _test-output-buffered-file) -10373 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10379 # check output -10380 (check-next-stream-line-equal _test-output-stream "(f2 *(ebp+0xfffffff8))" "F - test-emit-subx-stmt-function-call") -10381 # . epilogue -10382 89/<- %esp 5/r32/ebp -10383 5d/pop-to-ebp -10384 c3/return -10385 -10386 test-emit-subx-stmt-function-call-with-literal-arg: -10387 # Call a function on a literal. -10388 # f 34 -10389 # => -10390 # (f2 34) -10391 # -10392 # . prologue -10393 55/push-ebp -10394 89/<- %ebp 4/r32/esp -10395 # setup -10396 (clear-stream _test-output-stream) -10397 (clear-stream $_test-output-buffered-file->buffer) -10398 # var type/ecx: (handle tree type-id) = literal -10399 68/push 0/imm32/right/null -10400 68/push 0/imm32/left/literal -10401 89/<- %ecx 4/r32/esp -10402 # var var-foo/ecx: var literal -10403 68/push 0/imm32/no-register -10404 68/push 0/imm32/no-stack-offset -10405 68/push 0/imm32/block-depth -10406 51/push-ecx -10407 68/push "34"/imm32 -10408 89/<- %ecx 4/r32/esp -10409 # var inouts/esi: (handle stmt-var) -10410 68/push 0/imm32/is-deref:false -10411 68/push 0/imm32/next -10412 51/push-ecx/var-foo -10413 89/<- %esi 4/r32/esp -10414 # var stmt/esi: statement -10415 68/push 0/imm32/next -10416 68/push 0/imm32/outputs -10417 56/push-esi/inouts -10418 68/push "f"/imm32/operation -10419 68/push 1/imm32 -10420 89/<- %esi 4/r32/esp -10421 # var functions/ebx: function -10422 68/push 0/imm32/next -10423 68/push 0/imm32/body -10424 68/push 0/imm32/outputs -10425 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call -10426 68/push "f2"/imm32/subx-name -10427 68/push "f"/imm32/name -10428 89/<- %ebx 4/r32/esp -10429 # convert -10430 c7 0/subop/copy *Curr-block-depth 0/imm32 -10431 (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx) -10432 (flush _test-output-buffered-file) -10433 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10439 # check output -10440 (check-next-stream-line-equal _test-output-stream "(f2 34)" "F - test-emit-subx-stmt-function-call-with-literal-arg") -10441 # . epilogue -10442 89/<- %esp 5/r32/ebp -10443 5d/pop-to-ebp -10444 c3/return -10445 -10446 emit-indent: # out: (addr buffered-file), n: int -10447 # . prologue -10448 55/push-ebp -10449 89/<- %ebp 4/r32/esp -10450 # . save registers -10451 50/push-eax -10452 # var i/eax: int = n -10453 8b/-> *(ebp+0xc) 0/r32/eax -10454 { -10455 # if (i <= 0) break -10456 3d/compare-eax-with 0/imm32 -10457 7e/jump-if-<= break/disp8 -10458 (write-buffered *(ebp+8) " ") -10459 48/decrement-eax -10460 eb/jump loop/disp8 -10461 } -10462 $emit-indent:end: -10463 # . restore registers -10464 58/pop-to-eax -10465 # . epilogue -10466 89/<- %esp 5/r32/ebp -10467 5d/pop-to-ebp -10468 c3/return -10469 -10470 emit-subx-prologue: # out: (addr buffered-file) -10471 # . prologue -10472 55/push-ebp -10473 89/<- %ebp 4/r32/esp -10474 # -10475 (write-buffered *(ebp+8) " # . prologue\n") -10476 (write-buffered *(ebp+8) " 55/push-ebp\n") -10477 (write-buffered *(ebp+8) " 89/<- %ebp 4/r32/esp\n") -10478 $emit-subx-prologue:end: -10479 # . epilogue -10480 89/<- %esp 5/r32/ebp -10481 5d/pop-to-ebp -10482 c3/return -10483 -10484 emit-subx-epilogue: # out: (addr buffered-file) -10485 # . prologue -10486 55/push-ebp -10487 89/<- %ebp 4/r32/esp -10488 # -10489 (write-buffered *(ebp+8) " # . epilogue\n") -10490 (write-buffered *(ebp+8) " 89/<- %esp 5/r32/ebp\n") -10491 (write-buffered *(ebp+8) " 5d/pop-to-ebp\n") -10492 (write-buffered *(ebp+8) " c3/return\n") -10493 $emit-subx-epilogue:end: -10494 # . epilogue -10495 89/<- %esp 5/r32/ebp -10496 5d/pop-to-ebp -10497 c3/return +10320 # . prologue +10321 55/push-ebp +10322 89/<- %ebp 4/r32/esp +10323 # setup +10324 (clear-stream _test-output-stream) +10325 (clear-stream $_test-output-buffered-file->buffer) +10326 # var type/ecx: (handle tree type-id) = int +10327 68/push 0/imm32/right/null +10328 68/push 1/imm32/left/int +10329 89/<- %ecx 4/r32/esp +10330 # var var-foo/ecx: var +10331 68/push 0/imm32/no-register +10332 68/push -8/imm32/stack-offset +10333 68/push 0/imm32/block-depth +10334 51/push-ecx +10335 68/push "foo"/imm32 +10336 89/<- %ecx 4/r32/esp +10337 # var inouts/esi: (handle stmt-var) +10338 68/push 0/imm32/is-deref:false +10339 68/push 0/imm32/next +10340 51/push-ecx/var-foo +10341 89/<- %esi 4/r32/esp +10342 # var stmt/esi: statement +10343 68/push 0/imm32/next +10344 68/push 0/imm32/outputs +10345 56/push-esi/inouts +10346 68/push "f"/imm32/operation +10347 68/push 1/imm32 +10348 89/<- %esi 4/r32/esp +10349 # var functions/ebx: function +10350 68/push 0/imm32/next +10351 68/push 0/imm32/body +10352 68/push 0/imm32/outputs +10353 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call +10354 68/push "f2"/imm32/subx-name +10355 68/push "f"/imm32/name +10356 89/<- %ebx 4/r32/esp +10357 # convert +10358 c7 0/subop/copy *Curr-block-depth 0/imm32 +10359 (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx) +10360 (flush _test-output-buffered-file) +10361 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +10367 # check output +10368 (check-next-stream-line-equal _test-output-stream "(f2 *(ebp+0xfffffff8))" "F - test-emit-subx-stmt-function-call") +10369 # . epilogue +10370 89/<- %esp 5/r32/ebp +10371 5d/pop-to-ebp +10372 c3/return +10373 +10374 test-emit-subx-stmt-function-call-with-literal-arg: +10375 # Call a function on a literal. +10376 # f 34 +10377 # => +10378 # (f2 34) +10379 # +10380 # . prologue +10381 55/push-ebp +10382 89/<- %ebp 4/r32/esp +10383 # setup +10384 (clear-stream _test-output-stream) +10385 (clear-stream $_test-output-buffered-file->buffer) +10386 # var type/ecx: (handle tree type-id) = literal +10387 68/push 0/imm32/right/null +10388 68/push 0/imm32/left/literal +10389 89/<- %ecx 4/r32/esp +10390 # var var-foo/ecx: var literal +10391 68/push 0/imm32/no-register +10392 68/push 0/imm32/no-stack-offset +10393 68/push 0/imm32/block-depth +10394 51/push-ecx +10395 68/push "34"/imm32 +10396 89/<- %ecx 4/r32/esp +10397 # var inouts/esi: (handle stmt-var) +10398 68/push 0/imm32/is-deref:false +10399 68/push 0/imm32/next +10400 51/push-ecx/var-foo +10401 89/<- %esi 4/r32/esp +10402 # var stmt/esi: statement +10403 68/push 0/imm32/next +10404 68/push 0/imm32/outputs +10405 56/push-esi/inouts +10406 68/push "f"/imm32/operation +10407 68/push 1/imm32 +10408 89/<- %esi 4/r32/esp +10409 # var functions/ebx: function +10410 68/push 0/imm32/next +10411 68/push 0/imm32/body +10412 68/push 0/imm32/outputs +10413 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call +10414 68/push "f2"/imm32/subx-name +10415 68/push "f"/imm32/name +10416 89/<- %ebx 4/r32/esp +10417 # convert +10418 c7 0/subop/copy *Curr-block-depth 0/imm32 +10419 (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx) +10420 (flush _test-output-buffered-file) +10421 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +10427 # check output +10428 (check-next-stream-line-equal _test-output-stream "(f2 34)" "F - test-emit-subx-stmt-function-call-with-literal-arg") +10429 # . epilogue +10430 89/<- %esp 5/r32/ebp +10431 5d/pop-to-ebp +10432 c3/return +10433 +10434 emit-indent: # out: (addr buffered-file), n: int +10435 # . prologue +10436 55/push-ebp +10437 89/<- %ebp 4/r32/esp +10438 # . save registers +10439 50/push-eax +10440 # var i/eax: int = n +10441 8b/-> *(ebp+0xc) 0/r32/eax +10442 { +10443 # if (i <= 0) break +10444 3d/compare-eax-with 0/imm32 +10445 7e/jump-if-<= break/disp8 +10446 (write-buffered *(ebp+8) " ") +10447 48/decrement-eax +10448 eb/jump loop/disp8 +10449 } +10450 $emit-indent:end: +10451 # . restore registers +10452 58/pop-to-eax +10453 # . epilogue +10454 89/<- %esp 5/r32/ebp +10455 5d/pop-to-ebp +10456 c3/return +10457 +10458 emit-subx-prologue: # out: (addr buffered-file) +10459 # . prologue +10460 55/push-ebp +10461 89/<- %ebp 4/r32/esp +10462 # +10463 (write-buffered *(ebp+8) " # . prologue\n") +10464 (write-buffered *(ebp+8) " 55/push-ebp\n") +10465 (write-buffered *(ebp+8) " 89/<- %ebp 4/r32/esp\n") +10466 $emit-subx-prologue:end: +10467 # . epilogue +10468 89/<- %esp 5/r32/ebp +10469 5d/pop-to-ebp +10470 c3/return +10471 +10472 emit-subx-epilogue: # out: (addr buffered-file) +10473 # . prologue +10474 55/push-ebp +10475 89/<- %ebp 4/r32/esp +10476 # +10477 (write-buffered *(ebp+8) " # . epilogue\n") +10478 (write-buffered *(ebp+8) " 89/<- %esp 5/r32/ebp\n") +10479 (write-buffered *(ebp+8) " 5d/pop-to-ebp\n") +10480 (write-buffered *(ebp+8) " c3/return\n") +10481 $emit-subx-epilogue:end: +10482 # . epilogue +10483 89/<- %esp 5/r32/ebp +10484 5d/pop-to-ebp +10485 c3/return diff --git a/html/apps/pack.subx.html b/html/apps/pack.subx.html index 7bf6cc71..a01556fc 100644 --- a/html/apps/pack.subx.html +++ b/html/apps/pack.subx.html @@ -65,8 +65,8 @@ if ('onhashchange' in window) { 3 # uses are left untouched. 4 # 5 # To run: - 6 # $ ./subx translate init.linux 0*.subx apps/subx-params.subx apps/pack.subx -o apps/pack - 7 # $ echo '05/add-to-eax 0x20/imm32' |./subx run apps/pack + 6 # $ ./bootstrap translate init.linux 0*.subx apps/subx-params.subx apps/pack.subx -o apps/pack + 7 # $ echo '05/add-to-eax 0x20/imm32' |./bootstrap run apps/pack 8 # Expected output: 9 # 05 20 00 00 00 # 05/add-to-eax 0x20/imm32 10 # The original instruction gets included as a comment at the end of each @@ -4721,7 +4721,7 @@ if ('onhashchange' in window) { 5864 # . . push args 5865 51/push-ecx 5866 # . . call -5867 e8/call parse-hex-int-from-slice/disp32 +5867 e8/call parse-hex-int-from-slice/disp32 5868 # . . discard args 5869 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5870 $parse-datum-of-word:end: diff --git a/html/apps/random.subx.html b/html/apps/random.subx.html index 25db616e..882ce5d4 100644 --- a/html/apps/random.subx.html +++ b/html/apps/random.subx.html @@ -59,8 +59,8 @@ if ('onhashchange' in window) { 1 # Repeatedly read 32-bit numbers from /dev/random, print them to stdout. 2 # 3 # To run: - 4 # $ ./subx translate init.linux 0*.subx apps/random.subx -o apps/random - 5 # $ ./subx run apps/random + 4 # $ ./bootstrap translate init.linux 0*.subx apps/random.subx -o apps/random + 5 # $ ./bootstrap run apps/random 6 7 == code 0x09000000 8 # instruction effective address register displacement immediate diff --git a/html/apps/sigils.subx.html b/html/apps/sigils.subx.html index 6bec4179..6d3f9f23 100644 --- a/html/apps/sigils.subx.html +++ b/html/apps/sigils.subx.html @@ -64,36 +64,36 @@ if ('onhashchange' in window) { 2 # other related arguments. 3 # 4 # To run: - 5 # $ ./subx translate init.linux 0*.subx apps/subx-params.subx apps/sigils.subx -o apps/sigils + 5 # $ ./bootstrap translate init.linux 0*.subx apps/subx-params.subx apps/sigils.subx -o apps/sigils 6 # 7 # We currently support the following notations: 8 # 9 # 1. - 10 # $ echo '%eax' | ./subx run apps/sigils + 10 # $ echo '%eax' | ./bootstrap run apps/sigils 11 # 3/mod 0/rm32 12 # 13 # 2. - 14 # $ echo '*eax' | ./subx run apps/sigils + 14 # $ echo '*eax' | ./bootstrap run apps/sigils 15 # 0/mod 0/rm32 16 # 17 # 3. - 18 # $ echo '*(eax+4)' | ./subx run apps/sigils + 18 # $ echo '*(eax+4)' | ./bootstrap run apps/sigils 19 # 2/mod 0/rm32 4/disp32 20 # 21 # 4. - 22 # $ echo '*(eax+ecx)' | ./subx run apps/sigils + 22 # $ echo '*(eax+ecx)' | ./bootstrap run apps/sigils 23 # 0/mod 4/rm32 0/base 1/index 0/scale 24 # 25 # 5. - 26 # $ echo '*(eax+ecx+4)' | ./subx run apps/sigils + 26 # $ echo '*(eax+ecx+4)' | ./bootstrap run apps/sigils 27 # 2/mod 4/rm32 0/base 1/index 0/scale 4/disp32 28 # 29 # 6. - 30 # $ echo '*(eax+ecx<<2+4)' | ./subx run apps/sigils + 30 # $ echo '*(eax+ecx<<2+4)' | ./bootstrap run apps/sigils 31 # 2/mod 4/rm32 0/base 1/index 2/scale 4/disp32 32 # 33 # 7. - 34 # $ echo '*Foo' | ./subx run apps/sigils + 34 # $ echo '*Foo' | ./bootstrap run apps/sigils 35 # 0/mod 5/rm32/.disp32 Foo/disp32 36 # 37 # Addition isn't commutative here. Template must always be (base+index<<scale+disp), @@ -3650,7 +3650,7 @@ if ('onhashchange' in window) { 4052 # . . push args 4053 50/push-eax 4054 # . . call -4055 e8/call is-hex-digit?/disp32 +4055 e8/call is-hex-digit?/disp32 4056 # . . discard args 4057 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4058 # . if (eax == false) break @@ -3660,7 +3660,7 @@ if ('onhashchange' in window) { 4062 # . . copy arg to eax 4063 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL 4064 # . . call -4065 e8/call from-hex-char/disp32 +4065 e8/call from-hex-char/disp32 4066 # result = result * 16 + eax 4067 c1/shift 4/subop/left 3/mod/direct 7/rm32/edi . . . . . 4/imm8 # shift edi left by 4 bits 4068 01/add 3/mod/direct 7/rm32/edi . . . 0/r32/eax . . # add eax to edi @@ -4033,7 +4033,7 @@ if ('onhashchange' in window) { 4435 # . . push args 4436 50/push-eax 4437 # . . call -4438 e8/call is-hex-digit?/disp32 +4438 e8/call is-hex-digit?/disp32 4439 # . . discard args 4440 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4441 # . if (eax == false) break @@ -4043,7 +4043,7 @@ if ('onhashchange' in window) { 4445 # . . copy arg to eax 4446 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL 4447 # . . call -4448 e8/call from-hex-char/disp32 +4448 e8/call from-hex-char/disp32 4449 # result = result * 16 + eax 4450 c1/shift 4/subop/left 3/mod/direct 7/rm32/edi . . . . . 4/imm8 # shift edi left by 4 bits 4451 01/add 3/mod/direct 7/rm32/edi . . . 0/r32/eax . . # add eax to edi diff --git a/html/apps/survey.subx.html b/html/apps/survey.subx.html index 9acf8ac9..70952749 100644 --- a/html/apps/survey.subx.html +++ b/html/apps/survey.subx.html @@ -68,7 +68,7 @@ if ('onhashchange' in window) { 5 # b) add segment headers with addresses and offsets correctly filled in 6 # 7 # To build: - 8 # $ ./subx translate init.linux 0*.subx apps/subx-params.subx apps/survey.subx -o apps/survey + 8 # $ ./bootstrap translate init.linux 0*.subx apps/subx-params.subx apps/survey.subx -o apps/survey 9 # 10 # The expected input is a stream of bytes with segment headers, comments and 11 # some interspersed labels. @@ -86,7 +86,7 @@ if ('onhashchange' in window) { 23 # The output is the stream of bytes without segment headers or label definitions, 24 # and with label references replaced with numeric values/displacements. 25 # - 26 # $ cat x |./subx run apps/survey + 26 # $ cat x |./bootstrap run apps/survey 27 # ...ELF header bytes... 28 # # ELF header above will specify that code segment begins at this offset 29 # aa bb nn # some computed address @@ -672,7 +672,7 @@ if ('onhashchange' in window) { 990 # seg->address = parse-hex-int-from-slice(segment-tmp) 991 # . eax = parse-hex-int-from-slice(segment-tmp) 992 68/push compute-offsets:segment-tmp/imm32 - 993 e8/call parse-hex-int-from-slice/disp32 + 993 e8/call parse-hex-int-from-slice/disp32 994 # . . discard args 995 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 996 # . seg->address = eax diff --git a/html/apps/tests.subx.html b/html/apps/tests.subx.html index 2335bbb3..fa2ae715 100644 --- a/html/apps/tests.subx.html +++ b/html/apps/tests.subx.html @@ -62,7 +62,7 @@ if ('onhashchange' in window) { 2 # all functions starting with 'test-'. 3 # 4 # To build: - 5 # $ ./subx translate init.linux 0*.subx apps/subx-params.subx apps/tests.subx -o apps/tests + 5 # $ ./bootstrap translate init.linux 0*.subx apps/subx-params.subx apps/tests.subx -o apps/tests 6 7 == code 8 # instruction effective address register displacement immediate -- cgit 1.4.1-2-gfad0