1 %{ 2 3 include "sys.m"; 4 sys: Sys; 5 6 include "draw.m"; 7 8 include "bufio.m"; 9 bufio: Bufio; 10 Iobuf: import bufio; 11 12 include "math.m"; 13 math: Math; 14 export_real: import math; 15 16 include "string.m"; 17 str: String; 18 19 include "arg.m"; 20 21 include "../limbo/isa.m"; 22 23 YYSTYPE: adt { 24 inst: ref Inst; 25 addr: ref Addr; 26 op: int; 27 ival: big; 28 fval: real; 29 str: string; 30 sym: ref Sym; 31 listv: ref List; 32 }; 33 34 YYLEX: adt { 35 lval: YYSTYPE; 36 EOF: con -1; 37 lex: fn(l: self ref YYLEX): int; 38 error: fn(l: self ref YYLEX, msg: string); 39 40 numsym: fn(l: self ref YYLEX, first: int): int; 41 eatstring: fn(l: self ref YYLEX); 42 }; 43 44 Eof: con -1; 45 False: con 0; 46 True: con 1; 47 Strsize: con 1024; 48 Hashsize: con 128; 49 50 Addr: adt 51 { 52 mode: int; 53 off: int; 54 val: int; 55 sym: ref Sym; 56 57 text: fn(a: self ref Addr): string; 58 }; 59 60 List: adt 61 { 62 link: cyclic ref List; 63 addr: int; 64 typ: int; 65 pick{ 66 Int => ival: big; # DEFB, DEFW, DEFL 67 Bytes => b: array of byte; # DEFF, DEFS 68 Array => a: ref Array; # DEFA 69 } 70 }; 71 72 Inst: adt 73 { 74 op: int; 75 typ: int; 76 size: int; 77 reg: ref Addr; 78 src: ref Addr; 79 dst: ref Addr; 80 pc: int; 81 sym: ref Sym; 82 link: cyclic ref Inst; 83 84 text: fn(i: self ref Inst): string; 85 }; 86 87 Sym: adt 88 { 89 name: string; 90 lexval: int; 91 value: int; 92 ds: int; 93 }; 94 95 Desc: adt 96 { 97 id: int; 98 size: int; 99 np: int; 100 map: array of byte; 101 link: cyclic ref Desc; 102 }; 103 104 Array: adt 105 { 106 i: int; 107 size: int; 108 }; 109 110 Link: adt 111 { 112 desc: int; 113 addr: int; 114 typ: int; 115 name: string; 116 link: cyclic ref Link; 117 }; 118 119 Keywd: adt 120 { 121 name: string; 122 op: int; 123 terminal: int; 124 }; 125 126 Ldts: adt 127 { 128 n: int; 129 ldt: list of ref Ldt; 130 }; 131 132 Ldt: adt 133 { 134 sign: int; 135 name: string; 136 }; 137 138 Exc: adt 139 { 140 n1, n2, n3, n4, n5, n6: int; 141 etab: list of ref Etab; 142 }; 143 144 Etab: adt 145 { 146 n: int; 147 name: string; 148 }; 149 150 %} 151 152 %module Asm { 153 init: fn(nil: ref Draw->Context, nil: list of string); 154 } 155 156 %left '|' 157 %left '^' 158 %left '&' 159 %left '<' '>' 160 %left '+' '-' 161 %left '*' '/' '%' 162 163 %type<inst> label ilist inst 164 %type<ival> con expr heapid 165 %type<addr> addr raddr mem roff 166 %type<listv> elist 167 %type<str> ptrs 168 %token<op> TOKI0 TOKI1 TOKI2 TOKI3 169 %token <ival> TCONST 170 %token TOKSB TOKFP TOKHEAP TOKDB TOKDW TOKDL TOKDF TOKDS TOKVAR 171 %token TOKEXT TOKMOD TOKLINK TOKENTRY TOKARRAY TOKINDIR TOKAPOP TOKLDTS TOKEXCS TOKEXC TOKETAB TOKSRC 172 %token<sym> TID 173 %token<fval> TFCONST 174 %token<str> TSTRING 175 176 %% 177 prog : ilist 178 { 179 assem($1); 180 } 181 ; 182 183 ilist : 184 { $$ = nil; } 185 | ilist label 186 { 187 if($2 != nil) { 188 $2.link = $1; 189 $$ = $2; 190 } 191 else 192 $$ = $1; 193 } 194 ; 195 196 label : TID ':' inst 197 { 198 $3.sym = $1; 199 $$ = $3; 200 } 201 | TOKHEAP heapid ',' expr ptrs 202 { 203 heap(int $2, int $4, $5); 204 $$ = nil; 205 } 206 | data 207 { 208 $$ = nil; 209 } 210 | inst 211 ; 212 213 heapid : '$' expr 214 { 215 $$ = $2; 216 } 217 | TID 218 { 219 $1.value = heapid++; 220 $$ = big $1.value; 221 } 222 ; 223 224 ptrs : 225 { $$ = nil; } 226 | ',' TSTRING 227 { 228 $$ = $2; 229 } 230 ; 231 232 elist : expr 233 { 234 $$ = newi($1, nil); 235 } 236 | elist ',' expr 237 { 238 $$ = newi($3, $1); 239 } 240 ; 241 242 inst : TOKI3 addr ',' addr 243 { 244 $$ = ai($1); 245 $$.src = $2; 246 $$.dst = $4; 247 } 248 | TOKI3 addr ',' raddr ',' addr 249 { 250 $$ = ai($1); 251 $$.src = $2; 252 $$.reg = $4; 253 $$.dst = $6; 254 } 255 | TOKI2 addr ',' addr 256 { 257 $$ = ai($1); 258 $$.src = $2; 259 $$.dst = $4; 260 } 261 | TOKI1 addr 262 { 263 $$ = ai($1); 264 $$.dst = $2; 265 } 266 | TOKI0 267 { 268 $$ = ai($1); 269 } 270 ; 271 272 data : TOKDB expr ',' elist 273 { 274 data(DEFB, $2, $4); 275 } 276 | TOKDW expr ',' elist 277 { 278 data(DEFW, $2, $4); 279 } 280 | TOKDL expr ',' elist 281 { 282 data(DEFL, $2, $4); 283 } 284 | TOKDF expr ',' TCONST 285 { 286 data(DEFF, $2, newb(dtocanon(real $4), nil)); 287 } 288 | TOKDF expr ',' TFCONST 289 { 290 data(DEFF, $2, newb(dtocanon($4), nil)); 291 } 292 | TOKDF expr ',' TID 293 { 294 case $4.name { 295 "Inf" or "Infinity" => 296 b := array[] of {byte 16r7F, byte 16rF0, byte 0, byte 0, byte 0, byte 0, byte 0, byte 0}; 297 data(DEFF, $2, newb(b, nil)); 298 "NaN" => 299 b := array[] of {byte 16r7F, byte 16rFF, byte 16rFF, byte 16rFF, byte 16rFF, byte 16rFF, byte 16rFF, byte 16rFF}; 300 data(DEFF, $2, newb(b, nil)); 301 * => 302 diag(sys->sprint("bad value for real: %s", $4.name)); 303 } 304 } 305 | TOKDF expr ',' '-' TCONST 306 { 307 data(DEFF, $2, newb(dtocanon(-real $5), nil)); 308 } 309 | TOKDF expr ',' '-' TFCONST 310 { 311 data(DEFF, $2, newb(dtocanon(-$5), nil)); 312 } 313 | TOKDF expr ',' '-' TID 314 { 315 case $5.name { 316 "Inf" or "Infinity" => 317 b := array[] of {byte 16rFF, byte 16rF0, byte 0, byte 0, byte 0, byte 0, byte 0, byte 0}; 318 data(DEFF, $2, newb(b, nil)); 319 * => 320 diag(sys->sprint("bad value for real: %s", $5.name)); 321 } 322 } 323 | TOKDS expr ',' TSTRING 324 { 325 data(DEFS, $2, news($4, nil)); 326 } 327 | TOKVAR TID ',' expr 328 { 329 if($2.ds != 0) 330 diag(sys->sprint("%s declared twice", $2.name)); 331 $2.ds = int $4; 332 $2.value = dseg; 333 dseg += int $4; 334 } 335 | TOKEXT expr ',' expr ',' TSTRING 336 { 337 ext(int $2, int $4, $6); 338 } 339 | TOKLINK expr ',' expr ',' expr ',' TSTRING 340 { 341 mklink(int $2, int $4, int $6, $8); 342 } 343 | TOKMOD TID 344 { 345 if(amodule != nil) 346 diag(sys->sprint("this module already defined as %s", $2.name)); 347 else 348 amodule = $2; 349 } 350 | TOKENTRY expr ',' expr 351 { 352 if(pcentry >= 0) 353 diag(sys->sprint("this module already has entry point %d, %d" , pcentry, dentry)); 354 pcentry = int $2; 355 dentry = int $4; 356 } 357 | TOKARRAY expr ',' heapid ',' expr 358 { 359 data(DEFA, $2, newa(int $4, int $6)); 360 } 361 | TOKINDIR expr ',' expr 362 { 363 data(DIND, $2, newa(int $4, 0)); 364 } 365 | TOKAPOP 366 { 367 data(DAPOP, big 0, newa(0, 0)); 368 } 369 | TOKLDTS TID ',' expr 370 { 371 ldts(int $4); 372 } 373 | TOKEXCS expr 374 { 375 excs(int $2); 376 } 377 | TOKEXC expr ',' expr ',' expr ',' expr ',' expr ',' expr 378 { 379 exc(int $2, int $4, int $6, int $8, int $10, int $12); 380 } 381 | TOKETAB TSTRING ',' expr 382 { 383 etab($2, int $4); 384 } 385 | TOKETAB '*' ',' expr 386 { 387 etab(nil, int $4); 388 } 389 | TOKSRC TSTRING 390 { 391 source($2); 392 } 393 ; 394 395 raddr : '$' expr 396 { 397 $$ = aa($2); 398 $$.mode = AXIMM; 399 if($$.val > 16r7FFF || $$.val < -16r8000) 400 diag(sys->sprint("immediate %d too large for middle operand", $$.val)); 401 } 402 | roff 403 { 404 if($1.mode == AMP) 405 $1.mode = AXINM; 406 else 407 $1.mode = AXINF; 408 if($1.mode == AXINM && isoff2big($1.val)) 409 diag(sys->sprint("register offset %d(mp) too large", $1.val)); 410 if($1.mode == AXINF && isoff2big($1.val)) 411 diag(sys->sprint("register offset %d(fp) too large", $1.val)); 412 $$ = $1; 413 } 414 ; 415 416 addr : '$' expr 417 { 418 $$ = aa($2); 419 $$.mode = AIMM; 420 } 421 | TID 422 { 423 $$ = aa(big 0); 424 $$.sym = $1; 425 } 426 | mem 427 ; 428 429 mem : '*' roff 430 { 431 $2.mode |= AIND; 432 $$ = $2; 433 } 434 | expr '(' roff ')' 435 { 436 $3.mode |= AIND; 437 if($3.val & 3) 438 diag("indirect offset must be word size"); 439 if($3.mode == (AMP|AIND) && (isoff2big($3.val) || isoff2big(int $1))) 440 diag(sys->sprint("indirect offset %bd(%d(mp)) too large", $1, $3.val)); 441 if($3.mode == (AFP|AIND) && (isoff2big($3.val) || isoff2big(int $1))) 442 diag(sys->sprint("indirect offset %bd(%d(fp)) too large", $1, $3.val)); 443 $3.off = $3.val; 444 $3.val = int $1; 445 $$ = $3; 446 } 447 | roff 448 ; 449 450 roff : expr '(' TOKSB ')' 451 { 452 $$ = aa($1); 453 $$.mode = AMP; 454 } 455 | expr '(' TOKFP ')' 456 { 457 $$ = aa($1); 458 $$.mode = AFP; 459 } 460 ; 461 462 con : TCONST 463 | TID 464 { 465 $$ = big $1.value; 466 } 467 | '-' con 468 { 469 $$ = -$2; 470 } 471 | '+' con 472 { 473 $$ = $2; 474 } 475 | '~' con 476 { 477 $$ = ~$2; 478 } 479 | '(' expr ')' 480 { 481 $$ = $2; 482 } 483 ; 484 485 expr: con 486 | expr '+' expr 487 { 488 $$ = $1 + $3; 489 } 490 | expr '-' expr 491 { 492 $$ = $1 - $3; 493 } 494 | expr '*' expr 495 { 496 $$ = $1 * $3; 497 } 498 | expr '/' expr 499 { 500 $$ = $1 / $3; 501 } 502 | expr '%' expr 503 { 504 $$ = $1 % $3; 505 } 506 | expr '<' '<' expr 507 { 508 $$ = $1 << int $4; 509 } 510 | expr '>' '>' expr 511 { 512 $$ = $1 >> int $4; 513 } 514 | expr '&' expr 515 { 516 $$ = $1 & $3; 517 } 518 | expr '^' expr 519 { 520 $$ = $1 ^ $3; 521 } 522 | expr '|' expr 523 { 524 $$ = $1 | $3; 525 } 526 ; 527 %% 528 529 kinit() 530 { 531 for(i := 0; keywds[i].name != nil; i++) { 532 s := enter(keywds[i].name, keywds[i].terminal); 533 s.value = keywds[i].op; 534 } 535 536 enter("desc", TOKHEAP); 537 enter("mp", TOKSB); 538 enter("fp", TOKFP); 539 540 enter("byte", TOKDB); 541 enter("word", TOKDW); 542 enter("long", TOKDL); 543 enter("real", TOKDF); 544 enter("string", TOKDS); 545 enter("var", TOKVAR); 546 enter("ext", TOKEXT); 547 enter("module", TOKMOD); 548 enter("link", TOKLINK); 549 enter("entry", TOKENTRY); 550 enter("array", TOKARRAY); 551 enter("indir", TOKINDIR); 552 enter("apop", TOKAPOP); 553 enter("ldts", TOKLDTS); 554 enter("exceptions", TOKEXCS); 555 enter("exception", TOKEXC); 556 enter("exctab", TOKETAB); 557 enter("source", TOKSRC); 558 559 cmap['0'] = '\0'+1; 560 cmap['z'] = '\0'+1; 561 cmap['n'] = '\n'+1; 562 cmap['r'] = '\r'+1; 563 cmap['t'] = '\t'+1; 564 cmap['b'] = '\b'+1; 565 cmap['f'] = '\f'+1; 566 cmap['a'] = '\a'+1; 567 cmap['v'] = '\v'+1; 568 cmap['\\'] = '\\'+1; 569 cmap['"'] = '"'+1; 570 } 571 572 Bgetc(b: ref Iobuf): int 573 { 574 return b.getb(); 575 } 576 577 Bungetc(b: ref Iobuf) 578 { 579 b.ungetb(); 580 } 581 582 Bgetrune(b: ref Iobuf): int 583 { 584 return b.getc(); 585 } 586 587 Bputc(b: ref Iobuf, c: int) 588 { 589 b.putb(byte c); 590 } 591 592 strchr(s: string, c: int): string 593 { 594 for(i := 0; i < len s; i++) 595 if(s[i] == c) 596 return s[i:]; 597 return nil; 598 } 599 600 escchar(c: int): int 601 { 602 buf := array[32] of byte; 603 if(c >= '0' && c <= '9') { 604 n := 1; 605 buf[0] = byte c; 606 for(;;) { 607 c = Bgetc(bin); 608 if(c == Eof) 609 fatal(sys->sprint("%d: <eof> in escape sequence", line)); 610 if(strchr("0123456789xX", c) == nil) { 611 Bungetc(bin); 612 break; 613 } 614 buf[n++] = byte c; 615 } 616 return int string buf[0:n]; 617 } 618 619 n := cmap[c]; 620 if(n == 0) 621 return c; 622 return n-1; 623 } 624 625 strbuf := array[Strsize] of byte; 626 627 resizebuf() 628 { 629 t := array[len strbuf+Strsize] of byte; 630 t[0:] = strbuf; 631 strbuf = t; 632 } 633 634 YYLEX.eatstring(l: self ref YYLEX) 635 { 636 esc := 0; 637 Scan: 638 for(cnt := 0;;) { 639 c := Bgetc(bin); 640 case c { 641 Eof => 642 fatal(sys->sprint("%d: <eof> in string constant", line)); 643 644 '\n' => 645 line++; 646 diag("newline in string constant"); 647 break Scan; 648 649 '\\' => 650 if(esc) { 651 if(cnt >= len strbuf) 652 resizebuf(); 653 strbuf[cnt++] = byte c; 654 esc = 0; 655 break; 656 } 657 esc = 1; 658 659 '"' => 660 if(esc == 0) 661 break Scan; 662 c = escchar(c); 663 esc = 0; 664 if(cnt >= len strbuf) 665 resizebuf(); 666 strbuf[cnt++] = byte c; 667 668 * => 669 if(esc) { 670 c = escchar(c); 671 esc = 0; 672 } 673 if(cnt >= len strbuf) 674 resizebuf(); 675 strbuf[cnt++] = byte c; 676 } 677 } 678 l.lval.str = string strbuf[0: cnt]; 679 } 680 681 eatnl() 682 { 683 line++; 684 for(;;) { 685 c := Bgetc(bin); 686 if(c == Eof) 687 diag("eof in comment"); 688 if(c == '\n') 689 return; 690 } 691 } 692 693 YYLEX.lex(l: self ref YYLEX): int 694 { 695 for(;;){ 696 c := Bgetc(bin); 697 case c { 698 Eof => 699 return Eof; 700 '"' => 701 l.eatstring(); 702 return TSTRING; 703 ' ' or 704 '\t' or 705 '\r' => 706 continue; 707 '\n' => 708 line++; 709 '.' => 710 c = Bgetc(bin); 711 Bungetc(bin); 712 if(isdigit(c)) 713 return l.numsym('.'); 714 return '.'; 715 '#' => 716 eatnl(); 717 '(' or 718 ')' or 719 ';' or 720 ',' or 721 '~' or 722 '$' or 723 '+' or 724 '/' or 725 '%' or 726 '^' or 727 '*' or 728 '&' or 729 '=' or 730 '|' or 731 '<' or 732 '>' or 733 '-' or 734 ':' => 735 return c; 736 '\'' => 737 c = Bgetrune(bin); 738 if(c == '\\') 739 l.lval.ival = big escchar(Bgetc(bin)); 740 else 741 l.lval.ival = big c; 742 c = Bgetc(bin); 743 if(c != '\'') { 744 diag("missing '"); 745 Bungetc(bin); 746 } 747 return TCONST; 748 749 * => 750 return l.numsym(c); 751 } 752 } 753 } 754 755 isdigit(c: int): int 756 { 757 return c >= '0' && c <= '9'; 758 } 759 760 isxdigit(c: int): int 761 { 762 return c >= '0' && c <= '9' || c >= 'a' && c <= 'f' || c >= 'A' && c <= 'F'; 763 } 764 765 isalnum(c: int): int 766 { 767 return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || isdigit(c); 768 } 769 770 YYLEX.numsym(l: self ref YYLEX, first: int): int 771 { 772 Int, Hex, Frac, Expsign, Exp: con iota; 773 state: int; 774 775 symbol[0] = byte first; 776 p := 0; 777 778 if(first == '.') 779 state = Frac; 780 else 781 state = Int; 782 783 c: int; 784 if(isdigit(int symbol[p++]) || state == Frac) { 785 Collect: 786 for(;;) { 787 c = Bgetc(bin); 788 if(c < 0) 789 fatal(sys->sprint("%d: <eof> eating numeric", line)); 790 791 case state { 792 Int => 793 if(isdigit(c)) 794 break; 795 case c { 796 'x' or 797 'X' => 798 c = 'x'; 799 state = Hex; 800 '.' => 801 state = Frac; 802 'e' or 803 'E' => 804 c = 'e'; 805 state = Expsign; 806 * => 807 break Collect; 808 } 809 Hex => 810 if(!isxdigit(c)) 811 break Collect; 812 Frac => 813 if(isdigit(c)) 814 break; 815 if(c != 'e' && c != 'E') 816 break Collect; 817 c = 'e'; 818 state = Expsign; 819 Expsign => 820 state = Exp; 821 if(c == '-' || c == '+') 822 break; 823 if(!isdigit(c)) 824 break Collect; 825 Exp => 826 if(!isdigit(c)) 827 break Collect; 828 } 829 symbol[p++] = byte c; 830 } 831 832 # break Collect 833 lastsym = string symbol[0:p]; 834 Bungetc(bin); 835 case state { 836 Frac or 837 Expsign or 838 Exp => 839 l.lval.fval = real lastsym; 840 return TFCONST; 841 * => 842 if(len lastsym >= 3 && lastsym[0:2] == "0x") 843 (l.lval.ival, nil) = str->tobig(lastsym[2:], 16); 844 else 845 (l.lval.ival, nil) = str->tobig(lastsym, 10); 846 return TCONST; 847 } 848 } 849 850 for(;;) { 851 c = Bgetc(bin); 852 if(c < 0) 853 fatal(sys->sprint("%d <eof> eating symbols", line)); 854 # '$' and '/' can occur in fully-qualified Java class names 855 if(c != '_' && c != '.' && c != '/' && c != '$' && !isalnum(c)) { 856 Bungetc(bin); 857 break; 858 } 859 symbol[p++] = byte c; 860 } 861 862 lastsym = string symbol[0:p]; 863 s := enter(lastsym,TID); 864 case s.lexval { 865 TOKI0 or 866 TOKI1 or 867 TOKI2 or 868 TOKI3 => 869 l.lval.op = s.value; 870 * => 871 l.lval.sym = s; 872 } 873 return s.lexval; 874 } 875 876 hash := array[Hashsize] of list of ref Sym; 877 878 enter(name: string, stype: int): ref Sym 879 { 880 s := lookup(name); 881 if(s != nil) 882 return s; 883 884 h := 0; 885 for(p := 0; p < len name; p++) 886 h = h*3 + name[p]; 887 if(h < 0) 888 h = ~h; 889 h %= Hashsize; 890 891 s = ref Sym(name, stype, 0, 0); 892 hash[h] = s :: hash[h]; 893 return s; 894 } 895 896 lookup(name: string): ref Sym 897 { 898 h := 0; 899 for(p := 0; p < len name; p++) 900 h = h*3 + name[p]; 901 if(h < 0) 902 h = ~h; 903 h %= Hashsize; 904 905 for(l := hash[h]; l != nil; l = tl l) 906 if((s := hd l).name == name) 907 return s; 908 return nil; 909 } 910 911 YYLEX.error(l: self ref YYLEX, s: string) 912 { 913 if(s == "syntax error") { 914 l.error(sys->sprint("syntax error, near symbol '%s'", lastsym)); 915 return; 916 } 917 sys->print("%s %d: %s\n", file, line, s); 918 if(nerr++ > 10) { 919 sys->fprint(sys->fildes(2), "%s:%d: too many errors, giving up\n", file, line); 920 sys->remove(ofile); 921 raise "fail: yyerror"; 922 } 923 } 924 925 fatal(s: string) 926 { 927 sys->fprint(sys->fildes(2), "asm: %d (fatal compiler problem) %s\n", line, s); 928 raise "fail:"+s; 929 } 930 931 diag(s: string) 932 { 933 srcline := line; 934 sys->fprint(sys->fildes(2), "%s:%d: %s\n", file, srcline, s); 935 if(nerr++ > 10) { 936 sys->fprint(sys->fildes(2), "%s:%d: too many errors, giving up\n", file, line); 937 sys->remove(ofile); 938 raise "fail: error"; 939 } 940 } 941 942 zinst: Inst; 943 944 ai(op: int): ref Inst 945 { 946 i := ref zinst; 947 i.op = op; 948 949 return i; 950 } 951 952 aa(val: big): ref Addr 953 { 954 if(val <= big -1073741824 && val > big 1073741823) 955 diag("offset out of range"); 956 return ref Addr(0, 0, int val, nil); 957 } 958 959 isoff2big(o: int): int 960 { 961 return o < 0 || o > 16rFFFF; 962 } 963 964 inldt := 0; 965 nldts := 0; 966 aldts: list of ref Ldts; 967 curl: ref Ldts; 968 nexcs := 0; 969 aexcs: list of ref Exc; 970 cure: ref Exc; 971 srcpath: string; 972 973 bin: ref Iobuf; 974 bout: ref Iobuf; 975 976 line := 0; 977 heapid := 0; 978 symbol := array[1024] of byte; 979 lastsym: string; 980 nerr := 0; 981 cmap := array[256] of int; 982 file: string; 983 984 dlist: ref Desc; 985 dcout := 0; 986 dseg := 0; 987 dcount := 0; 988 989 mdata: ref List; 990 amodule: ref Sym; 991 links: ref Link; 992 linkt: ref Link; 993 nlink := 0; 994 listing := 0; 995 mustcompile := 0; 996 dontcompile := 0; 997 ofile: string; 998 dentry := 0; 999 pcentry := 0; 1000 1001 init(nil: ref Draw->Context, args: list of string) 1002 { 1003 sys = load Sys Sys->PATH; 1004 math = load Math Math->PATH; 1005 bufio = load Bufio Bufio->PATH; 1006 str = load String String->PATH; 1007 1008 arg := load Arg Arg->PATH; 1009 arg->setusage("asm [-l] file.s"); 1010 arg->init(args); 1011 while((c := arg->opt()) != 0){ 1012 case c { 1013 'C' => dontcompile++; 1014 'c' => mustcompile++; 1015 'l' => listing++; 1016 * => arg->usage(); 1017 } 1018 } 1019 args = arg->argv(); 1020 if(len args != 1) 1021 arg->usage(); 1022 arg = nil; 1023 1024 kinit(); 1025 pcentry = -1; 1026 dentry = -1; 1027 1028 file = hd args; 1029 bin = bufio->open(file, Bufio->OREAD); 1030 if(bin == nil) { 1031 sys->fprint(sys->fildes(2), "asm: can't open %s: %r\n", file); 1032 raise "fail: errors"; 1033 } 1034 p := strrchr(file, '/'); 1035 if(p == nil) 1036 p = file; 1037 else 1038 p = p[1:]; 1039 ofile = mkfile(p, ".s", ".dis"); 1040 bout = bufio->create(ofile, Bufio->OWRITE, 8r666); 1041 if(bout == nil){ 1042 sys->fprint(sys->fildes(2), "asm: can't create: %s: %r\n", ofile); 1043 raise "fail: errors"; 1044 } 1045 line = 1; 1046 yyparse(ref YYLEX); 1047 bout.close(); 1048 1049 if(nerr != 0){ 1050 sys->remove(ofile); 1051 raise "fail: errors"; 1052 } 1053 } 1054 1055 strrchr(s: string, c: int): string 1056 { 1057 for(i := len s; --i >= 0;) 1058 if(s[i] == c) 1059 return s[i:]; 1060 return nil; 1061 } 1062 1063 mkfile(file: string, oldext: string, ext: string): string 1064 { 1065 n := len file; 1066 n2 := len oldext; 1067 if(n >= n2 && file[n-n2:] == oldext) 1068 n -= n2; 1069 return file[0:n] + ext; 1070 } 1071 1072 opcode(i: ref Inst): int 1073 { 1074 if(i.op < 0 || i.op >= len keywds) 1075 fatal(sys->sprint("internal error: invalid op %d (%#x)", i.op, i.op)); 1076 return keywds[i.op].op; 1077 } 1078 1079 Inst.text(i: self ref Inst): string 1080 { 1081 if(i == nil) 1082 return "IZ"; 1083 1084 case keywds[i.op].terminal { 1085 TOKI0 => 1086 return sys->sprint("%s", keywds[i.op].name); 1087 TOKI1 => 1088 return sys->sprint("%s\t%s", keywds[i.op].name, i.dst.text()); 1089 TOKI3 => 1090 if(i.reg != nil) { 1091 pre := ""; 1092 post := ""; 1093 case i.reg.mode { 1094 AXIMM => 1095 pre = "$"; 1096 break; 1097 AXINF => 1098 post = "(fp)"; 1099 break; 1100 AXINM => 1101 post = "(mp)"; 1102 break; 1103 } 1104 return sys->sprint("%s\t%s, %s%d%s, %s", keywds[i.op].name, i.src.text(), pre, i.reg.val, post, i.dst.text()); 1105 } 1106 return sys->sprint("%s\t%s, %s", keywds[i.op].name, i.src.text(), i.dst.text()); 1107 TOKI2 => 1108 return sys->sprint("%s\t%s, %s", keywds[i.op].name, i.src.text(), i.dst.text()); 1109 * => 1110 return "IGOK"; 1111 } 1112 } 1113 1114 Addr.text(a: self ref Addr): string 1115 { 1116 if(a == nil) 1117 return "AZ"; 1118 1119 if(a.mode & AIND) { 1120 case a.mode & ~AIND { 1121 AFP => 1122 return sys->sprint("%d(%d(fp))", a.val, a.off); 1123 AMP => 1124 return sys->sprint("%d(%d(mp))", a.val, a.off); 1125 } 1126 } 1127 else { 1128 case a.mode { 1129 AFP => 1130 return sys->sprint("%d(fp)", a.val); 1131 AMP => 1132 return sys->sprint("%d(mp)", a.val); 1133 AIMM => 1134 return sys->sprint("$%d", a.val); 1135 } 1136 } 1137 1138 return "AGOK"; 1139 } 1140 1141 append[T](l: list of T, v: T): list of T 1142 { 1143 if(l == nil) 1144 return v :: nil; 1145 return hd l :: append(tl l, v); 1146 } 1147 1148 newa(i: int, size: int): ref List 1149 { 1150 a := ref Array(i, size); 1151 l := ref List.Array(nil, -1, 0, a); 1152 return l; 1153 } 1154 1155 # does order matter? 1156 newi(v: big, l: ref List): ref List 1157 { 1158 n := ref List.Int(nil, -1, 0, v); 1159 if(l == nil) 1160 return n; 1161 1162 for(t := l; t.link != nil; t = t.link) 1163 ; 1164 t.link = n; 1165 1166 return l; 1167 } 1168 1169 news(s: string, l: ref List): ref List 1170 { 1171 return ref List.Bytes(l, -1, 0, array of byte s); 1172 } 1173 1174 newb(a: array of byte, l: ref List): ref List 1175 { 1176 return ref List.Bytes(l, -1, 0, a); 1177 } 1178 1179 digit(x: int): int 1180 { 1181 if(x >= 'A' && x <= 'F') 1182 return x - 'A' + 10; 1183 if(x >= 'a' && x <= 'f') 1184 return x - 'a' + 10; 1185 if(x >= '0' && x <= '9') 1186 return x - '0'; 1187 diag("bad hex value in pointers"); 1188 return 0; 1189 } 1190 1191 heap(id: int, size: int, ptr: string) 1192 { 1193 d := ref Desc; 1194 d.id = id; 1195 d.size = size; 1196 size /= IBY2WD; 1197 d.map = array[size] of {* => byte 0}; 1198 d.np = 0; 1199 if(dlist == nil) 1200 dlist = d; 1201 else { 1202 f: ref Desc; 1203 for(f = dlist; f.link != nil; f = f.link) 1204 ; 1205 f.link = d; 1206 } 1207 d.link = nil; 1208 dcount++; 1209 1210 if(ptr == nil) 1211 return; 1212 if(len ptr & 1) { 1213 diag("pointer descriptor has odd length"); 1214 return; 1215 } 1216 1217 k := 0; 1218 l := len ptr; 1219 for(i := 0; i < l; i += 2) { 1220 d.map[k++] = byte ((digit(ptr[i])<<4)|digit(ptr[i+1])); 1221 if(k > size) { 1222 diag("pointer descriptor too long"); 1223 break; 1224 } 1225 } 1226 d.np = k; 1227 } 1228 1229 conout(val: int) 1230 { 1231 if(val >= -64 && val <= 63) { 1232 Bputc(bout, val & ~16r80); 1233 return; 1234 } 1235 if(val >= -8192 && val <= 8191) { 1236 Bputc(bout, ((val>>8) & ~16rC0) | 16r80); 1237 Bputc(bout, val); 1238 return; 1239 } 1240 if(val < 0 && ((val >> 29) & 7) != 7 1241 || val > 0 && (val >> 29) != 0) 1242 diag(sys->sprint("overflow in constant 0x%ux\n", val)); 1243 Bputc(bout, (val>>24) | 16rC0); 1244 Bputc(bout, val>>16); 1245 Bputc(bout, val>>8); 1246 Bputc(bout, val); 1247 } 1248 1249 aout(a: ref Addr) 1250 { 1251 if(a == nil) 1252 return; 1253 if(a.mode & AIND) 1254 conout(a.off); 1255 conout(a.val); 1256 } 1257 1258 Bputs(b: ref Iobuf, s: string) 1259 { 1260 for(i := 0; i < len s; i++) 1261 Bputc(b, s[i]); 1262 Bputc(b, '\0'); 1263 } 1264 1265 lout() 1266 { 1267 if(amodule == nil) 1268 amodule = enter("main", 0); 1269 1270 Bputs(bout, amodule.name); 1271 1272 for(l := links; l != nil; l = l.link) { 1273 conout(l.addr); 1274 conout(l.desc); 1275 Bputc(bout, l.typ>>24); 1276 Bputc(bout, l.typ>>16); 1277 Bputc(bout, l.typ>>8); 1278 Bputc(bout, l.typ); 1279 Bputs(bout, l.name); 1280 } 1281 } 1282 1283 ldtout() 1284 { 1285 conout(nldts); 1286 for(la := aldts; la != nil; la = tl la){ 1287 ls := hd la; 1288 conout(ls.n); 1289 for(l := ls.ldt; l != nil; l = tl l){ 1290 t := hd l; 1291 Bputc(bout, t.sign>>24); 1292 Bputc(bout, t.sign>>16); 1293 Bputc(bout, t.sign>>8); 1294 Bputc(bout, t.sign); 1295 Bputs(bout, t.name); 1296 } 1297 } 1298 conout(0); 1299 } 1300 1301 excout() 1302 { 1303 if(nexcs == 0) 1304 return; 1305 conout(nexcs); 1306 for(es := aexcs; es != nil; es = tl es){ 1307 e := hd es; 1308 conout(e.n3); 1309 conout(e.n1); 1310 conout(e.n2); 1311 conout(e.n4); 1312 conout(e.n5|(e.n6<<16)); 1313 for(ets := e.etab; ets != nil; ets = tl ets){ 1314 et := hd ets; 1315 if(et.name != nil) 1316 Bputs(bout, et.name); 1317 conout(et.n); 1318 } 1319 } 1320 conout(0); 1321 } 1322 1323 srcout() 1324 { 1325 if(srcpath == nil) 1326 return; 1327 Bputs(bout, srcpath); 1328 } 1329 1330 assem(i: ref Inst) 1331 { 1332 f: ref Inst; 1333 while(i != nil){ 1334 link := i.link; 1335 i.link = f; 1336 f = i; 1337 i = link; 1338 } 1339 i = f; 1340 1341 pc := 0; 1342 for(f = i; f != nil; f = f.link) { 1343 f.pc = pc++; 1344 if(f.sym != nil) 1345 f.sym.value = f.pc; 1346 } 1347 1348 if(pcentry >= pc) 1349 diag("entry pc out of range"); 1350 if(dentry >= dcount) 1351 diag("entry descriptor out of range"); 1352 1353 conout(XMAGIC); 1354 hints := 0; 1355 if(mustcompile) 1356 hints |= MUSTCOMPILE; 1357 if(dontcompile) 1358 hints |= DONTCOMPILE; 1359 hints |= HASLDT; 1360 if(nexcs > 0) 1361 hints |= HASEXCEPT; 1362 conout(hints); # Runtime flags 1363 conout(1024); # default stack size 1364 conout(pc); 1365 conout(dseg); 1366 conout(dcount); 1367 conout(nlink); 1368 conout(pcentry); 1369 conout(dentry); 1370 1371 for(f = i; f != nil; f = f.link) { 1372 if(f.dst != nil && f.dst.sym != nil) { 1373 f.dst.mode = AIMM; 1374 f.dst.val = f.dst.sym.value; 1375 } 1376 o := opcode(f); 1377 if(o == IRAISE){ 1378 f.src = f.dst; 1379 f.dst = nil; 1380 } 1381 Bputc(bout, o); 1382 n := 0; 1383 if(f.src != nil) 1384 n |= src(f.src.mode); 1385 else 1386 n |= src(AXXX); 1387 if(f.dst != nil) 1388 n |= dst(f.dst.mode); 1389 else 1390 n |= dst(AXXX); 1391 if(f.reg != nil) 1392 n |= f.reg.mode; 1393 else 1394 n |= AXNON; 1395 Bputc(bout, n); 1396 aout(f.reg); 1397 aout(f.src); 1398 aout(f.dst); 1399 1400 if(listing) 1401 sys->print("%4d %s\n", f.pc, f.text()); 1402 } 1403 1404 for(d := dlist; d != nil; d = d.link) { 1405 conout(d.id); 1406 conout(d.size); 1407 conout(d.np); 1408 for(n := 0; n < d.np; n++) 1409 Bputc(bout, int d.map[n]); 1410 } 1411 1412 dout(); 1413 lout(); 1414 ldtout(); 1415 excout(); 1416 srcout(); 1417 } 1418 1419 data(typ: int, addr: big, l: ref List) 1420 { 1421 if(inldt){ 1422 ldtw(int intof(l)); 1423 return; 1424 } 1425 1426 l.typ = typ; 1427 l.addr = int addr; 1428 1429 if(mdata == nil) 1430 mdata = l; 1431 else { 1432 for(f := mdata; f.link != nil; f = f.link) 1433 ; 1434 f.link = l; 1435 } 1436 } 1437 1438 ext(addr: int, typ: int, s: string) 1439 { 1440 if(inldt){ 1441 ldte(typ, s); 1442 return; 1443 } 1444 1445 data(DEFW, big addr, newi(big typ, nil)); 1446 1447 n: ref List; 1448 for(i := 0; i < len s; i++) 1449 n = newi(big s[i], n); 1450 data(DEFB, big(addr+IBY2WD), n); 1451 1452 if(addr+len s > dseg) 1453 diag("ext beyond mp"); 1454 } 1455 1456 mklink(desc: int, addr: int, typ: int, s: string) 1457 { 1458 for(ls := links; ls != nil; ls = ls.link) 1459 if(ls.name == s) 1460 diag(sys->sprint("%s already defined", s)); 1461 1462 nlink++; 1463 l := ref Link; 1464 l.desc = desc; 1465 l.addr = addr; 1466 l.typ = typ; 1467 l.name = s; 1468 l.link = nil; 1469 1470 if(links == nil) 1471 links = l; 1472 else 1473 linkt.link = l; 1474 linkt = l; 1475 } 1476 1477 intof(l: ref List): big 1478 { 1479 pick rl := l { 1480 Int => 1481 return rl.ival; 1482 * => 1483 raise "list botch"; 1484 } 1485 } 1486 1487 arrayof(l: ref List): ref Array 1488 { 1489 pick rl := l { 1490 Array => 1491 return rl.a; 1492 * => 1493 raise "list botch"; 1494 } 1495 } 1496 1497 bytesof(l: ref List): array of byte 1498 { 1499 pick rl := l { 1500 Bytes => 1501 return rl.b; 1502 * => 1503 raise "list botch"; 1504 } 1505 } 1506 1507 nel(l: ref List): (int, ref List) 1508 { 1509 n := 1; 1510 for(e := l.link; e != nil && e.addr == -1; e = e.link) 1511 n++; 1512 return (n, e); 1513 } 1514 1515 dout() 1516 { 1517 e: ref List; 1518 n: int; 1519 for(l := mdata; l != nil; l = e) { 1520 case l.typ { 1521 DEFB => 1522 (n, e) = nel(l); 1523 if(n < DMAX) 1524 Bputc(bout, dbyte(DEFB, n)); 1525 else { 1526 Bputc(bout, dbyte(DEFB, 0)); 1527 conout(n); 1528 } 1529 conout(l.addr); 1530 while(l != e) { 1531 Bputc(bout, int intof(l)); 1532 l = l.link; 1533 } 1534 break; 1535 DEFW => 1536 (n, e) = nel(l); 1537 if(n < DMAX) 1538 Bputc(bout, dbyte(DEFW, n)); 1539 else { 1540 Bputc(bout, dbyte(DEFW, 0)); 1541 conout(n); 1542 } 1543 conout(l.addr); 1544 while(l != e) { 1545 n = int intof(l); 1546 Bputc(bout, n>>24); 1547 Bputc(bout, n>>16); 1548 Bputc(bout, n>>8); 1549 Bputc(bout, n); 1550 l = l.link; 1551 } 1552 break; 1553 DEFL => 1554 (n, e) = nel(l); 1555 if(n < DMAX) 1556 Bputc(bout, dbyte(DEFL, n)); 1557 else { 1558 Bputc(bout, dbyte(DEFL, 0)); 1559 conout(n); 1560 } 1561 conout(l.addr); 1562 while(l != e) { 1563 b := intof(l); 1564 Bputc(bout, int (b>>56)); 1565 Bputc(bout, int (b>>48)); 1566 Bputc(bout, int (b>>40)); 1567 Bputc(bout, int (b>>32)); 1568 Bputc(bout, int (b>>24)); 1569 Bputc(bout, int (b>>16)); 1570 Bputc(bout, int (b>>8)); 1571 Bputc(bout, int b); 1572 l = l.link; 1573 } 1574 break; 1575 DEFF => 1576 (n, e) = nel(l); 1577 if(n < DMAX) 1578 Bputc(bout, dbyte(DEFF, n)); 1579 else { 1580 Bputc(bout, dbyte(DEFF, 0)); 1581 conout(n); 1582 } 1583 conout(l.addr); 1584 while(l != e) { 1585 b := bytesof(l); 1586 Bputc(bout, int b[0]); 1587 Bputc(bout, int b[1]); 1588 Bputc(bout, int b[2]); 1589 Bputc(bout, int b[3]); 1590 Bputc(bout, int b[4]); 1591 Bputc(bout, int b[5]); 1592 Bputc(bout, int b[6]); 1593 Bputc(bout, int b[7]); 1594 l = l.link; 1595 } 1596 break; 1597 DEFS => 1598 a := bytesof(l); 1599 n = len a; 1600 if(n < DMAX && n != 0) 1601 Bputc(bout, dbyte(DEFS, n)); 1602 else { 1603 Bputc(bout, dbyte(DEFS, 0)); 1604 conout(n); 1605 } 1606 conout(l.addr); 1607 for(i := 0; i < n; i++) 1608 Bputc(bout, int a[i]); 1609 1610 e = l.link; 1611 break; 1612 DEFA => 1613 Bputc(bout, dbyte(DEFA, 1)); 1614 conout(l.addr); 1615 ar := arrayof(l); 1616 Bputc(bout, ar.i>>24); 1617 Bputc(bout, ar.i>>16); 1618 Bputc(bout, ar.i>>8); 1619 Bputc(bout, ar.i); 1620 Bputc(bout, ar.size>>24); 1621 Bputc(bout, ar.size>>16); 1622 Bputc(bout, ar.size>>8); 1623 Bputc(bout, ar.size); 1624 e = l.link; 1625 break; 1626 DIND => 1627 Bputc(bout, dbyte(DIND, 1)); 1628 conout(l.addr); 1629 Bputc(bout, 0); 1630 Bputc(bout, 0); 1631 Bputc(bout, 0); 1632 Bputc(bout, 0); 1633 e = l.link; 1634 break; 1635 DAPOP => 1636 Bputc(bout, dbyte(DAPOP, 1)); 1637 conout(0); 1638 e = l.link; 1639 break; 1640 } 1641 } 1642 1643 Bputc(bout, dbyte(DEFZ, 0)); 1644 } 1645 1646 ldts(n: int) 1647 { 1648 nldts = n; 1649 inldt = 1; 1650 } 1651 1652 ldtw(n: int) 1653 { 1654 ls := ref Ldts(n, nil); 1655 aldts = append(aldts, ls); 1656 curl = ls; 1657 } 1658 1659 ldte(n: int, s: string) 1660 { 1661 l := ref Ldt(n, s); 1662 curl.ldt = append(curl.ldt, l); 1663 } 1664 1665 excs(n: int) 1666 { 1667 nexcs = n; 1668 } 1669 1670 exc(n1: int, n2: int, n3: int, n4: int, n5: int, n6: int) 1671 { 1672 e := ref Exc; 1673 e.n1 = n1; 1674 e.n2 = n2; 1675 e.n3 = n3; 1676 e.n4 = n4; 1677 e.n5 = n5; 1678 e.n6 = n6; 1679 e.etab = nil; 1680 aexcs = append(aexcs, e); 1681 cure = e; 1682 } 1683 1684 etab(s: string, n: int) 1685 { 1686 et := ref Etab; 1687 et.n = n; 1688 et.name = s; 1689 cure.etab = append(cure.etab, et); 1690 } 1691 1692 source(s: string) 1693 { 1694 srcpath = s; 1695 } 1696 1697 dtype(x: int): int 1698 { 1699 return (x>>4)&16rF; 1700 } 1701 1702 dbyte(x: int, l: int): int 1703 { 1704 return (x<<4) | l; 1705 } 1706 1707 dlen(x: int): int 1708 { 1709 return x & (DMAX-1); 1710 } 1711 1712 src(x: int): int 1713 { 1714 return x<<3; 1715 } 1716 1717 dst(x: int): int 1718 { 1719 return x<<0; 1720 } 1721 1722 dtocanon(d: real): array of byte 1723 { 1724 b := array[8] of byte; 1725 export_real(b, array[] of {d}); 1726 return b; 1727 } 1728 1729 keywds: array of Keywd = array[] of 1730 { 1731 ("nop", INOP, TOKI0), 1732 ("alt", IALT, TOKI3), 1733 ("nbalt", INBALT, TOKI3), 1734 ("goto", IGOTO, TOKI2), 1735 ("call", ICALL, TOKI2), 1736 ("frame", IFRAME, TOKI2), 1737 ("spawn", ISPAWN, TOKI2), 1738 ("runt", IRUNT, TOKI2), 1739 ("load", ILOAD, TOKI3), 1740 ("mcall", IMCALL, TOKI3), 1741 ("mspawn", IMSPAWN, TOKI3), 1742 ("mframe", IMFRAME, TOKI3), 1743 ("ret", IRET, TOKI0), 1744 ("jmp", IJMP, TOKI1), 1745 ("case", ICASE, TOKI2), 1746 ("exit", IEXIT, TOKI0), 1747 ("new", INEW, TOKI2), 1748 ("newa", INEWA, TOKI3), 1749 ("newcb", INEWCB, TOKI1), 1750 ("newcw", INEWCW, TOKI1), 1751 ("newcf", INEWCF, TOKI1), 1752 ("newcp", INEWCP, TOKI1), 1753 ("newcm", INEWCM, TOKI2), 1754 ("newcmp", INEWCMP, TOKI2), 1755 ("send", ISEND, TOKI2), 1756 ("recv", IRECV, TOKI2), 1757 ("consb", ICONSB, TOKI2), 1758 ("consw", ICONSW, TOKI2), 1759 ("consp", ICONSP, TOKI2), 1760 ("consf", ICONSF, TOKI2), 1761 ("consm", ICONSM, TOKI3), 1762 ("consmp", ICONSMP, TOKI3), 1763 ("headb", IHEADB, TOKI2), 1764 ("headw", IHEADW, TOKI2), 1765 ("headp", IHEADP, TOKI2), 1766 ("headf", IHEADF, TOKI2), 1767 ("headm", IHEADM, TOKI3), 1768 ("headmp", IHEADMP, TOKI3), 1769 ("tail", ITAIL, TOKI2), 1770 ("lea", ILEA, TOKI2), 1771 ("indx", IINDX, TOKI3), 1772 ("movp", IMOVP, TOKI2), 1773 ("movm", IMOVM, TOKI3), 1774 ("movmp", IMOVMP, TOKI3), 1775 ("movb", IMOVB, TOKI2), 1776 ("movw", IMOVW, TOKI2), 1777 ("movf", IMOVF, TOKI2), 1778 ("cvtbw", ICVTBW, TOKI2), 1779 ("cvtwb", ICVTWB, TOKI2), 1780 ("cvtfw", ICVTFW, TOKI2), 1781 ("cvtwf", ICVTWF, TOKI2), 1782 ("cvtca", ICVTCA, TOKI2), 1783 ("cvtac", ICVTAC, TOKI2), 1784 ("cvtwc", ICVTWC, TOKI2), 1785 ("cvtcw", ICVTCW, TOKI2), 1786 ("cvtfc", ICVTFC, TOKI2), 1787 ("cvtcf", ICVTCF, TOKI2), 1788 ("addb", IADDB, TOKI3), 1789 ("addw", IADDW, TOKI3), 1790 ("addf", IADDF, TOKI3), 1791 ("subb", ISUBB, TOKI3), 1792 ("subw", ISUBW, TOKI3), 1793 ("subf", ISUBF, TOKI3), 1794 ("mulb", IMULB, TOKI3), 1795 ("mulw", IMULW, TOKI3), 1796 ("mulf", IMULF, TOKI3), 1797 ("divb", IDIVB, TOKI3), 1798 ("divw", IDIVW, TOKI3), 1799 ("divf", IDIVF, TOKI3), 1800 ("modw", IMODW, TOKI3), 1801 ("modb", IMODB, TOKI3), 1802 ("andb", IANDB, TOKI3), 1803 ("andw", IANDW, TOKI3), 1804 ("orb", IORB, TOKI3), 1805 ("orw", IORW, TOKI3), 1806 ("xorb", IXORB, TOKI3), 1807 ("xorw", IXORW, TOKI3), 1808 ("shlb", ISHLB, TOKI3), 1809 ("shlw", ISHLW, TOKI3), 1810 ("shrb", ISHRB, TOKI3), 1811 ("shrw", ISHRW, TOKI3), 1812 ("insc", IINSC, TOKI3), 1813 ("indc", IINDC, TOKI3), 1814 ("addc", IADDC, TOKI3), 1815 ("lenc", ILENC, TOKI2), 1816 ("lena", ILENA, TOKI2), 1817 ("lenl", ILENL, TOKI2), 1818 ("beqb", IBEQB, TOKI3), 1819 ("bneb", IBNEB, TOKI3), 1820 ("bltb", IBLTB, TOKI3), 1821 ("bleb", IBLEB, TOKI3), 1822 ("bgtb", IBGTB, TOKI3), 1823 ("bgeb", IBGEB, TOKI3), 1824 ("beqw", IBEQW, TOKI3), 1825 ("bnew", IBNEW, TOKI3), 1826 ("bltw", IBLTW, TOKI3), 1827 ("blew", IBLEW, TOKI3), 1828 ("bgtw", IBGTW, TOKI3), 1829 ("bgew", IBGEW, TOKI3), 1830 ("beqf", IBEQF, TOKI3), 1831 ("bnef", IBNEF, TOKI3), 1832 ("bltf", IBLTF, TOKI3), 1833 ("blef", IBLEF, TOKI3), 1834 ("bgtf", IBGTF, TOKI3), 1835 ("bgef", IBGEF, TOKI3), 1836 ("beqc", IBEQC, TOKI3), 1837 ("bnec", IBNEC, TOKI3), 1838 ("bltc", IBLTC, TOKI3), 1839 ("blec", IBLEC, TOKI3), 1840 ("bgtc", IBGTC, TOKI3), 1841 ("bgec", IBGEC, TOKI3), 1842 ("slicea", ISLICEA, TOKI3), 1843 ("slicela", ISLICELA, TOKI3), 1844 ("slicec", ISLICEC, TOKI3), 1845 ("indw", IINDW, TOKI3), 1846 ("indf", IINDF, TOKI3), 1847 ("indb", IINDB, TOKI3), 1848 ("negf", INEGF, TOKI2), 1849 ("movl", IMOVL, TOKI2), 1850 ("addl", IADDL, TOKI3), 1851 ("subl", ISUBL, TOKI3), 1852 ("divl", IDIVL, TOKI3), 1853 ("modl", IMODL, TOKI3), 1854 ("mull", IMULL, TOKI3), 1855 ("andl", IANDL, TOKI3), 1856 ("orl", IORL, TOKI3), 1857 ("xorl", IXORL, TOKI3), 1858 ("shll", ISHLL, TOKI3), 1859 ("shrl", ISHRL, TOKI3), 1860 ("bnel", IBNEL, TOKI3), 1861 ("bltl", IBLTL, TOKI3), 1862 ("blel", IBLEL, TOKI3), 1863 ("bgtl", IBGTL, TOKI3), 1864 ("bgel", IBGEL, TOKI3), 1865 ("beql", IBEQL, TOKI3), 1866 ("cvtlf", ICVTLF, TOKI2), 1867 ("cvtfl", ICVTFL, TOKI2), 1868 ("cvtlw", ICVTLW, TOKI2), 1869 ("cvtwl", ICVTWL, TOKI2), 1870 ("cvtlc", ICVTLC, TOKI2), 1871 ("cvtcl", ICVTCL, TOKI2), 1872 ("headl", IHEADL, TOKI2), 1873 ("consl", ICONSL, TOKI2), 1874 ("newcl", INEWCL, TOKI1), 1875 ("casec", ICASEC, TOKI2), 1876 ("indl", IINDL, TOKI3), 1877 ("movpc", IMOVPC, TOKI2), 1878 ("tcmp", ITCMP, TOKI2), 1879 ("mnewz", IMNEWZ, TOKI3), 1880 ("cvtrf", ICVTRF, TOKI2), 1881 ("cvtfr", ICVTFR, TOKI2), 1882 ("cvtws", ICVTWS, TOKI2), 1883 ("cvtsw", ICVTSW, TOKI2), 1884 ("lsrw", ILSRW, TOKI3), 1885 ("lsrl", ILSRL, TOKI3), 1886 ("eclr", IECLR, TOKI0), 1887 ("newz", INEWZ, TOKI2), 1888 ("newaz", INEWAZ, TOKI3), 1889 ("raise", IRAISE, TOKI1), 1890 ("casel", ICASEL, TOKI2), 1891 ("mulx", IMULX, TOKI3), 1892 ("divx", IDIVX, TOKI3), 1893 ("cvtxx", ICVTXX, TOKI3), 1894 ("mulx0", IMULX0, TOKI3), 1895 ("divx0", IDIVX0, TOKI3), 1896 ("cvtxx0", ICVTXX0, TOKI3), 1897 ("mulx1", IMULX1, TOKI3), 1898 ("divx1", IDIVX1, TOKI3), 1899 ("cvtxx1", ICVTXX1, TOKI3), 1900 ("cvtfx", ICVTFX, TOKI3), 1901 ("cvtxf", ICVTXF, TOKI3), 1902 ("expw", IEXPW, TOKI3), 1903 ("expl", IEXPL, TOKI3), 1904 ("expf", IEXPF, TOKI3), 1905 ("self", ISELF, TOKI1), 1906 (nil, 0, 0), 1907 }; 1908