1/* Id: table.c,v 1.5 2014/12/27 21:18:19 ragge Exp */ 2/* $NetBSD: table.c,v 1.1.1.1 2016/02/09 20:28:39 plunky Exp $ */ 3/* 4 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). 5 * Copyright (c) 2014 Alan Cox (alan@lxorguk.ukuu.org.uk). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 32# include "pass2.h" 33 34/* 35 * TODO 36 * - clean up TLL usage so we are ready for 64bit longlong (T32 and T64?) 37 * - Clean up all the SHINT SHCH etc oddities for clarity 38 * - Better optimisation of constant multiply/divide etc on 8086 39 * - some how lose the final bogus sp adjust we generate 40 * - write helper lib for long and longlong ops 41 * - add an E class and virtual 4 register longlong model 42 * - bcc fastcall format 43 * 44 * - How to do configurable code-gen 45 * For 80186 we want to use the better shifts, push constant, mul/div 46 * features and enter/leave 47 * For 80286 it's not clear we need to do anything for real mode. However 48 * for large data/huge models protected mode means minimising ds/es 49 * reloads with the same data 50 * With 80386 there is lots more - but who wants 80386/16bit optimised 51 * code ! 52 * 53 * - FPU has not been tackled. FPU/FPU should be fine (barring the odd 54 * gnu style instruction forms), but FPU/other is quite different 55 * because the 4 byte conversions are now long not int and two register 56 * while 8 byte longlong ones are going to need some gymnastics once 57 * we support the virtual 64bit registers 58 * 59 * - FPU/noFPU option. Assuming FPU present on 8086 is a bit obnoxious 60 * as a default. Need to be able to generate entirely soft-float calls. 61 * 62 * - We can't currently do various conversions we'd like to have, notably 63 * things like "and ax, $ff" to convert AL into AX from uchar to uint 64 * (that needs core changes and also allocator changes to try and avoid 65 * high bits being occupied by other users) 66 * 67 * - Shifts should be optimised for 8/16/24/32 cases 68 * 69 * - No attempt is made to deal with larger models than tiny 70 * 71 * small mode should work (just keep constant data in data segments) 72 * 73 * large code/small data should be fine-ish. Really that implies 32bit 74 * void * but for most uses you want 32bit only to be function pointers 75 * even if its not to spec. Function entry/exit needs to allow for the 76 * extra 2 bytes, call becomes call far, call ptr becomes a bit trickier 77 * but not a lot. Not that ld86 can link large model yet! 78 * 79 * large data is much harder because an address is 32bit, half of which 80 * needs to keep getting stuck into a segment register. However we often 81 * (usually) work with multiple pointers to the same object. Any given 82 * object has a single segment so we will badly need optimisations to 83 * "share" segment data and avoid lots of duplicate register uses and 84 * mov es, foo statements. 85 * 86 * huge model makes all pointers 32bit and all objects 32bit sized. That 87 * probably makes the sharing es issue go away somewhat, but raises the 88 * ugly problems of pointer normalisation (00:10 is the same as 01:00 89 * which b*ggers up comparisons royally) and also protected mode where 90 * your segment jump as you go over 64K boundaries is different. On the 91 * bright side huge model performance will suck whatever the compiler 92 * does. 93 * 94 */ 95 96/* 64bit values */ 97# define T64 TLONGLONG|TULONGLONG 98/* 32bit values */ 99# define T32 TLONG|TULONG 100/* 16bit values */ 101# define T16 TINT|TUNSIGNED 102/* 16bit values including pointers */ 103# define TP16 TINT|TUNSIGNED|TPOINT 104/* 8bit values */ 105# define T8 TCHAR|TUCHAR 106 107#define SHINT SAREG /* short and int */ 108#define ININT INAREG 109#define SHCH SBREG /* shape for char */ 110#define INCH INBREG 111#define SHLL SCREG /* shape for long long FIXME */ 112#define INLL INCREG 113#define SHL SCREG /* shape for long*/ 114#define INL INCREG 115#define SHFL SDREG /* shape for float/double */ 116#define INFL INDREG /* shape for float/double */ 117 118struct optab table[] = { 119/* First entry must be an empty entry */ 120{ -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", }, 121 122/* PCONVs are usually not necessary */ 123{ PCONV, INAREG, 124 SAREG, T16|TPOINT, 125 SAREG, T16|TPOINT, 126 0, RLEFT, 127 "", }, 128 129/* 130 * A bunch conversions of integral<->integral types 131 * There are lots of them, first in table conversions to itself 132 * and then conversions from each type to the others. 133 */ 134 135/* itself to itself, including pointers */ 136 137/* convert (u)char to (u)char. */ 138{ SCONV, INCH, 139 SHCH, T8, 140 SHCH, T8, 141 0, RLEFT, 142 "", }, 143 144/* convert pointers to int. */ 145{ SCONV, ININT, 146 SHINT, TPOINT|T16, 147 SANY, T16, 148 0, RLEFT, 149 "", }, 150 151/* convert (u)long to (u)long. */ 152{ SCONV, INL, 153 SHL, T32, 154 SHL, T32, 155 0, RLEFT, 156 "", }, 157 158/* convert (u)long and (u)longlong to (u)longlong. */ 159{ SCONV, INLL, 160 SHLL, T64, 161 SHLL, T64, 162 0, RLEFT, 163 "", }, 164 165/* convert between float/double/long double. */ 166{ SCONV, INFL, 167 SHFL, TLDOUBLE|TDOUBLE|TFLOAT, 168 SHFL, TLDOUBLE|TDOUBLE|TFLOAT, 169 0, RLEFT, 170 "ZI", }, 171 172/* convert pointers to pointers. */ 173{ SCONV, ININT, 174 SHINT, TPOINT, 175 SANY, TPOINT, 176 0, RLEFT, 177 "", }, 178 179/* char to something */ 180 181/* convert char to 16bit types. */ 182 183/* 8086: Only as op on AL,AX */ 184{ SCONV, ININT, 185 SBREG, TCHAR, 186 SAREG, T16, 187 NSPECIAL|NAREG|NASL, RESC1, 188 " cbw\n", }, 189 190/* convert unsigned char to 16bit types. 191 We can do this one with any register */ 192{ SCONV, ININT, 193 SHCH|SOREG|SNAME, TUCHAR, 194 SAREG, T16, 195 NSPECIAL|NAREG, RESC1, 196 "ZT", }, 197 198/* convert char to (u)long 199 8086 can only do cbw/cwd on AX and AX:DX pair */ 200{ SCONV, INL, 201 SHCH, TCHAR, 202 SCREG, T32, 203 NSPECIAL|NCREG|NCSL, RESC1, 204 "; using AL\n cbw\n cwd\n", }, 205 206/* convert unsigned char to (u)long 207 we can do this with any register */ 208{ SCONV, INL, 209 SHCH|SOREG|SNAME, TUCHAR, 210 SANY, T32, 211 NCREG|NCSL, RESC1, 212 "ZT xor U1,U1\n", }, 213 214/* convert char (in register) to double XXX - use NTEMP */ 215/* FIXME : need NSPECIAL to force into AL 216 check AX:DX right way around ! */ 217{ SCONV, INFL, 218 SHCH|SOREG|SNAME, TCHAR, 219 SHFL, TLDOUBLE|TDOUBLE|TFLOAT, 220 NAREG|NASL|NDREG, RESC2, 221 " cbw\n cwd\n push ax\n push dx\n" 222 " fildl [sp]\n add sp, #4\n", }, 223 224/* convert (u)char (in register) to double XXX - use NTEMP */ 225/* FIXME : needs to use ZT to get sizes right, need a register 226 from somewhere to put 0 on the stack for the high bits */ 227{ SCONV, INFL, 228 SHCH|SOREG|SNAME, TUCHAR, 229 SHFL, TLDOUBLE|TDOUBLE|TFLOAT, 230 NAREG|NASL|NDREG, RESC2, 231 " mov A1 AL\n and A1, #0xff\n push A1\npush #0\n" 232 " fildl [sp]\n add sp,#4\n", }, 233 234/* 16bit to something */ 235 236/* convert 16bit to 16bit. */ 237{ SCONV, INAREG, 238 SAREG, T16, 239 SAREG, T16, 240 0, RLEFT, 241 "", }, 242 243/* convert 16bit (in memory) to char */ 244/* NOTE: uses new 'ZP' type for 'untyped right' */ 245{ SCONV, INCH, 246 SNAME|SOREG, TP16, 247 SHCH, T8, 248 NBREG|NBSL, RESC1, 249 " mov A1,ZP AL\n", }, 250 251/* convert 16bit (in reg) to char. Done as a special but basically a mov */ 252{ SCONV, INCH, 253 SAREG|SNAME|SOREG, TP16, 254 SHCH, T8, 255 NSPECIAL|NBREG|NBSL, RESC1, 256 "ZM", }, 257 258/* convert short/int to (u)long 259 This must go via AX so we can use cwd */ 260{ SCONV, INL, 261 SAREG, TINT, 262 SHL, T32, 263 NSPECIAL|NCREG|NCSL, RESC1, 264 " mov A1, AL\n cwd\n", }, 265 266/* convert unsigned short/int to (u)long 267 Any pair will do. Note currently the compiler can't optimise 268 out the reg->reg move involved */ 269{ SCONV, INLL, 270 SAREG|SOREG|SNAME, TUNSIGNED|TPOINT, 271 SHL, T32, 272 NCREG|NCSL, RESC1, 273 " mov A1,AL\n xor U1,U1\n", }, 274 275/* convert short/int (in memory) to float/double */ 276{ SCONV, INFL, 277 SOREG|SNAME, TINT, 278 SDREG, TLDOUBLE|TDOUBLE|TFLOAT, 279 NDREG, RESC1, 280 " fild AL\n", }, 281 282/* convert short/int (in register) to float/double */ 283{ SCONV, INFL, 284 SAREG, TINT, 285 SDREG, TLDOUBLE|TDOUBLE|TFLOAT, 286 NTEMP|NDREG, RESC1, 287 " push AL\n fild [sp]\n" 288 " inc sp\n inc sp\n", }, 289 290/* convert unsigned short/int/ptr to double XXX - use NTEMP */ 291/* FIXME: need to force this via AX so we can cwd, fix stack setup to 292 push both ax.dx*/ 293{ SCONV, INFL, 294 SAREG|SOREG|SNAME, TUNSIGNED|TPOINT, 295 SHFL, TLDOUBLE|TDOUBLE|TFLOAT, 296 NAREG|NASL|NDREG|NTEMP, RESC2, 297 " cwd\n push ax\n" 298 " fild [sp]\n inc sp\n" 299 " inc sp\n", }, 300 301/* long to something */ 302 303/* convert (u)long to (u)char (mem->reg) */ 304{ SCONV, INCH, 305 SOREG|SNAME, T32, 306 SANY, T8, 307 NBREG|NBSL, RESC1, 308 " mov A1, AL\n", }, 309 310/* convert (u)long to (u)char (reg->reg, hopefully nothing) */ 311{ SCONV, INCH, 312 SHL, T32, 313 SANY, T8, 314 NBREG|NBSL|NTEMP, RESC1, 315 "ZS", }, 316 317/* convert (u)long to (u)short (mem->reg) */ 318{ SCONV, INAREG, 319 SOREG|SNAME, T32, 320 SAREG, TP16, 321 NAREG|NASL, RESC1, 322 " mov A1,AL\n", }, 323 324/* convert (u)long to 16bit (reg->reg, hopefully nothing) */ 325{ SCONV, INAREG, 326 SHL|SOREG|SNAME, T32, 327 SAREG, T16, 328 NAREG|NASL|NTEMP, RESC1, 329 "ZS", }, 330 331/* FIXME: float stuff is all TODO */ 332 333/* convert long long (in memory) to floating */ 334{ SCONV, INFL, 335 SOREG|SNAME, TLONGLONG, 336 SHFL, TLDOUBLE|TDOUBLE|TFLOAT, 337 NDREG, RESC1, 338 " fild AL\n", }, 339 340/* convert long (in register) to floating */ 341{ SCONV, INFL, 342 SHL, TLONGLONG, 343 SHFL, TLDOUBLE|TDOUBLE|TFLOAT, 344 NTEMP|NDREG, RESC1, 345 " push UL\n push AL\n" 346 " fild [sp]\n add sp, #8\n", }, 347 348/* convert unsigned long to floating */ 349{ SCONV, INFL, 350 SCREG, TULONGLONG, 351 SDREG, TLDOUBLE|TDOUBLE|TFLOAT, 352 NDREG, RESC1, 353 "ZJ", }, 354 355/* float to something */ 356 357#if 0 /* go via int by adding an extra sconv in clocal() */ 358/* convert float/double to (u) char. XXX should use NTEMP here */ 359{ SCONV, INCH, 360 SHFL, TLDOUBLE|TDOUBLE|TFLOAT, 361 SHCH, T16|T8, 362 NBREG, RESC1, 363 " sub sp,#4\n fistpl [sp]\n pop A1\n pop U1\n", }, 364 365/* convert float/double to (u) int/short/char. XXX should use NTEMP here */ 366{ SCONV, INCH, 367 SHFL, TLDOUBLE|TDOUBLE|TFLOAT, 368 SHCH, T16|T8, 369 NCREG, RESC1, 370 " sub sp,#4\n fistpl (%sp)\n pop A1\n inc sp\n inc sp\n", }, 371#endif 372 373/* convert float/double to long XXX should use NTEMP here */ 374{ SCONV, INAREG, 375 SHFL, TLDOUBLE|TDOUBLE|TFLOAT, 376 SAREG, TLONG, 377 NAREG, RESC1, 378 " sub sp, #12\n" 379 " fstcw sp\n" 380 " fstcw 4[sp]\n" 381 " mov byte ptr 1[sp], #12\n" 382 " fldcw sp\n" 383 " fistp 8[sp]\n" 384 " movl A1, 8(p)\n" 385 " fldcw 4[sp]\n" 386 " add sp, #4\n", }, 387 388/* convert float/double to unsigned long. XXX should use NTEMP here */ 389{ SCONV, INAREG, 390 SHFL, TLDOUBLE|TDOUBLE|TFLOAT, 391 SAREG, TULONG, 392 NAREG, RESC1, 393 " sub sp, #16\n" 394 " fnstcw [sp]\n" 395 " fnstcw 4[sp]\n" 396 " mov byte ptr 1[sp], #12\n" 397 " fldcw [sp[\n" 398 " fistpq 8[sp]\n" 399 " mov word ptr 8[sp],A1\n" 400 " mov word ptr 10[sp],U1\n" 401 " fldcw 4[sp]\n" 402 " add sp, #16\n", }, 403 404/* convert float/double (in register) to long long */ 405{ SCONV, INLL, 406 SHFL, TLDOUBLE|TDOUBLE|TFLOAT, 407 SHLL, TLONGLONG, 408 NCREG, RESC1, 409 " sub sp, #16\n" 410 " fnstcw [sp]\n" 411 " fnstcw [sp]\n" 412 " mov byte ptr 1[sp], #12\n" 413 " fldcw [sp]\n" 414 " fistpq 8[sp]\n" 415 " movl 8[sp],A1\n" 416 " movl 10[sp],U1\n" 417 /* need to put 12/14 somewhere FIXME */ 418 " fldcw 4[sp]\n" 419 " add sp, #16\n", }, 420 421/* convert float/double (in register) to unsigned long long */ 422{ SCONV, INLL, 423 SHFL, TLDOUBLE|TDOUBLE|TFLOAT, 424 SHLL, TULONGLONG, 425 NCREG, RESC1, 426 " sub sp, #16\n" 427 " fnstcw [sp]\n" 428 " fnstcw 4[sp]\n" 429 " mov byte ptr 1[sp], #15\n" /* 64-bit prec */ 430 " fldcw [sp]\n" 431 " movl $0x5f000000, 8(%sp)\n" /* (float)(1<<63) */ 432 " fsubs 8[sp]\n" /* keep in range of fistpq */ 433 " fistpq 8[sp]\n" 434 " xor byte ptr 15[sp], #0x80\n" /* addq $1>>63 to 8(%sp) */ 435 " movl A1, 8[sp]\n" 436 " movl U1, 10[sp]\n" 437 " fldcw 4[sp]\n" 438 " add sp, #16\n", }, 439 440 441 442/* slut sconv */ 443 444/* 445 * Subroutine calls. 446 */ 447 448{ UCALL, FOREFF, 449 SCON, TANY, 450 SANY, TANY, 451 0, 0, 452 " call CL\nZC", }, 453 454{ CALL, FOREFF, 455 SCON, TANY, 456 SANY, TANY, 457 0, 0, 458 " call CL\nZC", }, 459 460//{ UCALL, FOREFF, 461// SCON, TANY, 462// SAREG, TP16, 463// 0, 0, 464// " call CL\nZC", }, 465 466{ CALL, INAREG, 467 SCON, TANY, 468 SAREG, TP16, 469 NAREG|NASL, RESC1, /* should be 0 */ 470 " call CL\nZC", }, 471 472{ UCALL, INAREG, 473 SCON, TANY, 474 SAREG, TP16, 475 NAREG|NASL, RESC1, /* should be 0 */ 476 " call CL\nZC", }, 477 478{ CALL, INBREG, 479 SCON, TANY, 480 SBREG, T8, 481 NBREG, RESC1, /* should be 0 */ 482 " call CL\nZC", }, 483 484{ UCALL, INBREG, 485 SCON, TANY, 486 SBREG, T8, 487 NBREG, RESC1, /* should be 0 */ 488 " call CL\nZC", }, 489 490{ CALL, INCREG, 491 SCON, TANY, 492 SCREG, TANY, 493 NCREG|NCSL, RESC1, /* should be 0 */ 494 " call CL\nZC", }, 495 496{ UCALL, INCREG, 497 SCON, TANY, 498 SCREG, TANY, 499 NCREG|NCSL, RESC1, /* should be 0 */ 500 " call CL\nZC", }, 501 502{ CALL, INDREG, 503 SCON, TANY, 504 SDREG, TANY, 505 NDREG|NDSL, RESC1, /* should be 0 */ 506 " call CL\nZC", }, 507 508{ UCALL, INDREG, 509 SCON, TANY, 510 SDREG, TANY, 511 NDREG|NDSL, RESC1, /* should be 0 */ 512 " call CL\nZC", }, 513 514{ CALL, FOREFF, 515 SAREG, TANY, 516 SANY, TANY, 517 0, 0, 518 " call *AL\nZC", }, 519 520{ UCALL, FOREFF, 521 SAREG, TANY, 522 SANY, TANY, 523 0, 0, 524 " call *AL\nZC", }, 525 526{ CALL, INAREG, 527 SAREG, TANY, 528 SANY, TANY, 529 NAREG|NASL, RESC1, /* should be 0 */ 530 " call *AL\nZC", }, 531 532{ UCALL, INAREG, 533 SAREG, TANY, 534 SANY, TANY, 535 NAREG|NASL, RESC1, /* should be 0 */ 536 " call *AL\nZC", }, 537 538{ CALL, INBREG, 539 SAREG, TANY, 540 SANY, TANY, 541 NBREG|NBSL, RESC1, /* should be 0 */ 542 " call *AL\nZC", }, 543 544{ UCALL, INBREG, 545 SAREG, TANY, 546 SANY, TANY, 547 NBREG|NBSL, RESC1, /* should be 0 */ 548 " call *AL\nZC", }, 549 550{ CALL, INCREG, 551 SAREG, TANY, 552 SANY, TANY, 553 NCREG|NCSL, RESC1, /* should be 0 */ 554 " call *AL\nZC", }, 555 556{ UCALL, INCREG, 557 SAREG, TANY, 558 SANY, TANY, 559 NCREG|NCSL, RESC1, /* should be 0 */ 560 " call *AL\nZC", }, 561 562{ CALL, INDREG, 563 SAREG, TANY, 564 SANY, TANY, 565 NDREG|NDSL, RESC1, /* should be 0 */ 566 " call *AL\nZC", }, 567 568{ UCALL, INDREG, 569 SAREG, TANY, 570 SANY, TANY, 571 NDREG|NDSL, RESC1, /* should be 0 */ 572 " call *AL\nZC", }, 573 574{ STCALL, FOREFF, 575 SCON, TANY, 576 SANY, TANY, 577 NAREG|NASL, 0, 578 " call CL\nZC", }, 579 580{ STCALL, INAREG, 581 SCON, TANY, 582 SANY, TANY, 583 NAREG|NASL, RESC1, /* should be 0 */ 584 " call CL\nZC", }, 585 586{ STCALL, INAREG, 587 SNAME|SAREG, TANY, 588 SANY, TANY, 589 NAREG|NASL, RESC1, /* should be 0 */ 590 " call *AL\nZC", }, 591 592/* 593 * The next rules handle all binop-style operators. 594 * 595 * 8 and 16bit we do directly, 32bit is a mix of helpers and 596 * direct operations. 64bit TODO, FPU lives in it's own little 597 * world. 598 */ 599{ PLUS, INL|FOREFF, 600 SHL, T32, 601 SHL|SNAME|SOREG, T32, 602 0, RLEFT, 603 " add AL,AR\n adc UL,UR\n", }, 604 605{ PLUS, INL|FOREFF, 606 SHL|SNAME|SOREG, T32, 607 SHL|SCON, T32, 608 0, RLEFT, 609 " add AL,AR\n adc UL,UR\n", }, 610 611/* Special treatment for long XXX - fix commutative check */ 612{ PLUS, INL|FOREFF, 613 SHL|SNAME|SOREG, T32, 614 SHL, T32, 615 0, RRIGHT, 616 " add AL,AR\n adc UL,UR\n", }, 617 618{ PLUS, INFL, 619 SHFL, TDOUBLE, 620 SNAME|SOREG, TDOUBLE, 621 0, RLEFT, 622 " faddl AR\n", }, 623 624{ PLUS, INFL|FOREFF, 625 SHFL, TLDOUBLE|TDOUBLE|TFLOAT, 626 SHFL, TLDOUBLE|TDOUBLE|TFLOAT, 627 0, RLEFT, 628 " faddp\n", }, 629 630{ PLUS, INAREG|FOREFF, 631 SAREG|SNAME|SOREG, TP16, 632 SONE, TANY, 633 0, RLEFT, 634 " inc AL\n", }, 635 636{ PLUS, INAREG|FOREFF, 637 SAREG|SNAME|SOREG, TP16, 638 STWO, TANY, 639 0, RLEFT, 640 " inc AL\n inc AL\n", }, 641 642{ PLUS, INCH|FOREFF, 643 SHCH|SNAME|SOREG, T8, 644 SONE, TANY, 645 0, RLEFT, 646 " inc AL\n", }, 647 648{ PLUS, INCH|FOREFF, 649 SHCH|SNAME|SOREG, T8, 650 STWO, TANY, 651 0, RLEFT, 652 " inc AL\n inc AL\n", }, 653 654{ PLUS, INAREG, 655 SAREG, T16, 656 SAREG, T16, 657 NAREG|NASL|NASR, RESC1, 658 " lea A1, [AL+AR]\n", }, 659 660{ MINUS, INAREG|FOREFF, 661 SAREG|SNAME|SOREG, TP16, 662 SONE, TANY, 663 0, RLEFT, 664 " dec AL\n", }, 665 666{ MINUS, INAREG|FOREFF, 667 SAREG|SNAME|SOREG, TP16, 668 STWO, TANY, 669 0, RLEFT, 670 " dec AL\n dec AL\n", }, 671 672{ MINUS, INCH|FOREFF, 673 SHCH|SNAME|SOREG, T8, 674 SONE, TANY, 675 0, RLEFT, 676 " dec AL\n", }, 677 678{ MINUS, INCH|FOREFF, 679 SHCH|SNAME|SOREG, T8, 680 STWO, TANY, 681 0, RLEFT, 682 " dec AL\n decl AL\n", }, 683 684/* address as register offset, negative */ 685{ MINUS, INLL|FOREFF, 686 SHL, T32, 687 SHL|SNAME|SOREG, T32, 688 0, RLEFT, 689 " sub AL,AR\n sbb UL,UR\n", }, 690 691{ MINUS, INL|FOREFF, 692 SHL|SNAME|SOREG, T32, 693 SHL|SCON, T32, 694 0, RLEFT, 695 " sub AL,AR\n sbb UL,UR\n", }, 696 697{ MINUS, INFL, 698 SHFL, TDOUBLE, 699 SNAME|SOREG, TDOUBLE, 700 0, RLEFT, 701 " fsubl AR\n", }, 702 703{ MINUS, INFL|FOREFF, 704 SHFL, TLDOUBLE|TDOUBLE|TFLOAT, 705 SHFL, TLDOUBLE|TDOUBLE|TFLOAT, 706 0, RLEFT, 707 " fsubZAp\n", }, 708 709/* Simple r/m->reg ops */ 710/* m/r |= r */ 711 712{ OPSIMP, INAREG|FOREFF|FORCC, 713 SHINT|SNAME|SOREG, TP16, 714 SHINT, TP16, 715 0, RLEFT|RESCC, 716 " Ow AL,AR\n", }, 717 718/* r |= r/m */ 719{ OPSIMP, INAREG|FOREFF|FORCC, 720 SHINT, T16, 721 SHINT|SNAME|SOREG, T16, 722 0, RLEFT|RESCC, 723 " Ow AL,AR\n", }, 724 725/* m/r |= r */ 726{ OPSIMP, INCH|FOREFF|FORCC, 727 SHCH, T8, 728 SHCH|SNAME|SOREG, T8, 729 0, RLEFT|RESCC, 730 " Ob AL,AR\n", }, 731 732/* r |= r/m */ 733{ OPSIMP, INCH|FOREFF|FORCC, 734 SHCH, T8, 735 SHCH|SNAME|SOREG, T8, 736 0, RLEFT|RESCC, 737 " Ob AL,AR\n", }, 738 739/* m/r |= const */ 740{ OPSIMP, INAREG|FOREFF|FORCC, 741 SHINT|SNAME|SOREG, TP16, 742 SCON, TANY, 743 0, RLEFT|RESCC, 744 " Ow AL,AR\n", }, 745 746{ OPSIMP, INCH|FOREFF|FORCC, 747 SHCH|SNAME|SOREG, T8, 748 SCON, TANY, 749 0, RLEFT|RESCC, 750 " Ob AL,AR\n", }, 751 752/* r |= r/m */ 753{ OPSIMP, INL|FOREFF, 754 SHL, T32, 755 SHL|SNAME|SOREG, T32, 756 0, RLEFT, 757 " Ow AL,AR\n Ow UL,UR\n", }, 758 759/* m/r |= r/const */ 760{ OPSIMP, INL|FOREFF, 761 SHL|SNAME|SOREG, T32, 762 SHL|SCON, T32, 763 0, RLEFT, 764 " Ow AL,AR\n Ow UL,UR\n", }, 765 766/* Try use-reg instructions first */ 767{ PLUS, INAREG, 768 SAREG, TP16, 769 SCON, TANY, 770 NAREG|NASL, RESC1, 771 " lea A1, CR[AL]\n", }, 772 773{ MINUS, INAREG, 774 SAREG, TP16, 775 SPCON, TANY, 776 NAREG|NASL, RESC1, 777 " lea A1, -CR[AL]\n", }, 778 779 780/* 781 * The next rules handle all shift operators. 782 */ 783/* (u)long left shift is emulated, longlong to do */ 784 785/* For 8086 we only have shift by 1 or shift by CL 786 787 We need a way to optimise shifts by 8/16/24/32/etc 788 shifts by 8 16 24 and 32 as moves between registers for 789 the bigger types. (eg >> 16 on a long might be mov dx, ax, 790 xor ax, ax) */ 791 792{ LS, INCREG, 793 SCREG, T32, 794 SHCH, T8, 795 0, RLEFT, 796 "ZO", }, 797 798/* Register 8086 timing is 2 for #1 versus 8 + 4/bin for multiple 799 so a lot of shifts would in fact best be done without using the cl 800 variant, especially including the cost of a) loading cl b) probably 801 having to boot something out of cx in the first place. For memory 802 its 15+EA v 20 + EA + 4/bit, so the other way. 803 804 8,16,24 should of course be done by loads.. FIXME 805 806 Also the compiler keeps generating mov dh, #8, mov cl, dh.. FIXME 807 808 For 80186 onwards we have shl reg, immediate (other than 1), 186 shift 809 is also much faster */ 810 811 812/* r/m <<= const 1*/ 813{ LS, INAREG|FOREFF, 814 SAREG|SNAME|SOREG, T16, 815 SONE, TANY, 816 0, RLEFT, 817 " shl AL,#1\n", }, 818 819/* r <<= const 2 */ 820{ LS, INAREG|FOREFF, 821 SAREG, T16, 822 STWO, TANY, 823 0, RLEFT, 824 " shl AL,#1\n shl AL,#1\n", }, 825 826/* r/m <<= r */ 827{ LS, INAREG|FOREFF, 828 SAREG|SNAME|SOREG, T16, 829 SHCH, T8, 830 NSPECIAL, RLEFT, 831 " shl AL,AR\n", }, 832 833{ LS, INCH|FOREFF, 834 SHCH|SNAME|SOREG, T8, 835 SONE, TANY, 836 NSPECIAL, RLEFT, 837 " sal AL,#1\n", }, 838 839{ LS, INCH|FOREFF, 840 SHCH, T8, 841 STWO, TANY, 842 NSPECIAL, RLEFT, 843 " sal AL,#1\n sal AL,#1", }, 844 845{ LS, INCH|FOREFF, 846 SHCH|SNAME|SOREG, T8, 847 SHCH, T8, 848 NSPECIAL, RLEFT, 849 " sal AL,AR\n", }, 850 851/* (u)long right shift is emulated. Use a 16bit register so the push 852 comes out sanely */ 853{ RS, INCREG, 854 SCREG, T32, 855 SHCH, T8, 856 0, RLEFT, 857 "ZO", }, 858 859{ RS, INAREG|FOREFF, 860 SAREG|SNAME|SOREG, TINT, 861 SHCH, T8, 862 NSPECIAL, RLEFT, 863 " sar AL,AR\n", }, 864 865{ RS, INAREG|FOREFF, 866 SAREG|SNAME|SOREG, TINT, 867 SONE, TANY, 868 NSPECIAL, RLEFT, 869 " sar AL,#1\n", }, 870 871{ RS, INAREG|FOREFF, 872 SAREG, TINT, 873 STWO, TANY, 874 NSPECIAL, RLEFT, 875 " sar AL,#1\n sar AL,#1", }, 876 877{ RS, INAREG|FOREFF, 878 SAREG|SNAME|SOREG, TUNSIGNED|TPOINT, 879 SHCH, T8, 880 NSPECIAL, RLEFT, 881 " shr AL,AR\n", }, 882 883{ RS, INAREG|FOREFF, 884 SAREG|SNAME|SOREG, TUNSIGNED, 885 SONE, TANY, 886 0, RLEFT, 887 " shr AL,#1\n", }, 888 889{ RS, INAREG|FOREFF, 890 SAREG, TUNSIGNED, 891 STWO, TANY, 892 0, RLEFT, 893 " shr AL,#1 shr AL,#1\n", }, 894 895{ RS, INCH|FOREFF, 896 SHCH|SNAME|SOREG, TCHAR, 897 SHCH, T8, 898 NSPECIAL, RLEFT, 899 " sar AL,AR\n", }, 900 901{ RS, INCH|FOREFF, 902 SHCH|SNAME|SOREG, TCHAR, 903 SONE, TANY, 904 NSPECIAL, RLEFT, 905 " sar AL,#1\n", }, 906 907{ RS, INCH|FOREFF, 908 SHCH|SNAME|SOREG, TCHAR, 909 STWO, TANY, 910 NSPECIAL, RLEFT, 911 " sar AL,#1\n sar AL,#1\n", }, 912 913{ RS, INCH|FOREFF, 914 SHCH|SNAME|SOREG, TUCHAR, 915 SHCH, T8, 916 NSPECIAL, RLEFT, 917 " shr AL,AR\n", }, 918 919{ RS, INCH|FOREFF, 920 SHCH|SNAME|SOREG, TUCHAR, 921 SONE, TANY, 922 NSPECIAL, RLEFT, 923 " shr AL,#1\n", }, 924 925{ RS, INCH|FOREFF, 926 SHCH|SNAME|SOREG, TUCHAR, 927 STWO, TANY, 928 NSPECIAL, RLEFT, 929 " shr AL,#1\n shr AL,#1\n", }, 930 931/* 932 * The next rules takes care of assignments. "=". 933 */ 934 935{ ASSIGN, FORCC|FOREFF|INL, 936 SHL, T32, 937 SMIXOR, TANY, 938 0, RDEST, 939 " xor AL,AL\n xor UL,UL\n", }, 940 941{ ASSIGN, FORCC|FOREFF|INL, 942 SHL, T32, 943 SMILWXOR, TANY, 944 0, RDEST, 945 " xor AL,AL\n mov UR,UL\n", }, 946 947{ ASSIGN, FORCC|FOREFF|INL, 948 SHL, T32, 949 SMIHWXOR, TANY, 950 0, RDEST, 951 " mov AL,AR\n xor UL,UL\n", }, 952 953{ ASSIGN, FOREFF|INL, 954 SHL, T32, 955 SCON, TANY, 956 0, RDEST, 957 " mov AL,AR\n mov UL,UR\n", }, 958 959{ ASSIGN, FOREFF, 960 SHL|SNAME|SOREG, T32, 961 SCON, TANY, 962 0, 0, 963 " mov AL,AR\n mov UL,UR\n", }, 964 965{ ASSIGN, FOREFF, 966 SAREG|SNAME|SOREG, TP16, 967 SCON, TANY, 968 0, 0, 969 " mov AL, AR\n", }, 970 971{ ASSIGN, FOREFF|INAREG, 972 SAREG, TP16, 973 SCON, TANY, 974 0, RDEST, 975 " mov AL, AR\n", }, 976 977{ ASSIGN, FOREFF, 978 SHCH|SNAME|SOREG, T8, 979 SCON, TANY, 980 0, 0, 981 " mov AL, AR\n", }, 982 983{ ASSIGN, FOREFF|INCH, 984 SHCH, T8, 985 SCON, TANY, 986 0, RDEST, 987 " mov AL, AR\n", }, 988 989{ ASSIGN, FOREFF|INL, 990 SNAME|SOREG, T32, 991 SHL, T32, 992 0, RDEST, 993 " mov AL,AR\n mov UL,UR\n", }, 994 995{ ASSIGN, FOREFF|INL, 996 SHL, T32, 997 SHL, T32, 998 0, RDEST, 999 "ZH", }, 1000 1001{ ASSIGN, FOREFF|INAREG, 1002 SAREG|SNAME|SOREG, TP16, 1003 SAREG, TP16, 1004 0, RDEST, 1005 " mov AL,AR\n", }, 1006 1007{ ASSIGN, FOREFF|INAREG, 1008 SAREG, TP16, 1009 SAREG|SNAME|SOREG, TP16, 1010 0, RDEST, 1011 " mov AL,AR\n", }, 1012 1013{ ASSIGN, FOREFF|INCH, 1014 SHCH|SNAME|SOREG, T8, 1015 SHCH, T8|T16, 1016 0, RDEST, 1017 " mov AL,AR\n", }, 1018 1019{ ASSIGN, INDREG|FOREFF, 1020 SHFL, TFLOAT|TDOUBLE|TLDOUBLE, 1021 SHFL, TFLOAT|TDOUBLE|TLDOUBLE, 1022 0, RDEST, 1023 "", }, /* This will always be in the correct register */ 1024 1025/* order of table entries is very important here! */ 1026{ ASSIGN, INFL, 1027 SNAME|SOREG, TLDOUBLE, 1028 SHFL, TFLOAT|TDOUBLE|TLDOUBLE, 1029 0, RDEST, 1030 " fstpt AL\n fldt AL\n", }, /* XXX */ 1031 1032{ ASSIGN, FOREFF, 1033 SNAME|SOREG, TLDOUBLE, 1034 SHFL, TFLOAT|TDOUBLE|TLDOUBLE, 1035 0, 0, 1036 " fstpt AL\n", }, 1037 1038{ ASSIGN, INFL, 1039 SNAME|SOREG, TDOUBLE, 1040 SHFL, TFLOAT|TDOUBLE|TLDOUBLE, 1041 0, RDEST, 1042 " fstl AL\n", }, 1043 1044{ ASSIGN, FOREFF, 1045 SNAME|SOREG, TDOUBLE, 1046 SHFL, TFLOAT|TDOUBLE|TLDOUBLE, 1047 0, 0, 1048 " fstpl AL\n", }, 1049 1050{ ASSIGN, INFL, 1051 SNAME|SOREG, TFLOAT, 1052 SHFL, TFLOAT|TDOUBLE|TLDOUBLE, 1053 0, RDEST, 1054 " fsts AL\n", }, 1055 1056{ ASSIGN, FOREFF, 1057 SNAME|SOREG, TFLOAT, 1058 SHFL, TFLOAT|TDOUBLE|TLDOUBLE, 1059 0, 0, 1060 " fstps AL\n", }, 1061/* end very important order */ 1062 1063{ ASSIGN, INFL|FOREFF, 1064 SHFL, TLDOUBLE, 1065 SHFL|SOREG|SNAME, TLDOUBLE, 1066 0, RDEST, 1067 " fldt AR\n", }, 1068 1069{ ASSIGN, INFL|FOREFF, 1070 SHFL, TDOUBLE, 1071 SHFL|SOREG|SNAME, TDOUBLE, 1072 0, RDEST, 1073 " fldl AR\n", }, 1074 1075{ ASSIGN, INFL|FOREFF, 1076 SHFL, TFLOAT, 1077 SHFL|SOREG|SNAME, TFLOAT, 1078 0, RDEST, 1079 " flds AR\n", }, 1080 1081/* Do not generate memcpy if return from funcall */ 1082#if 0 1083{ STASG, INAREG|FOREFF, 1084 SOREG|SNAME|SAREG, TPTRTO|TSTRUCT, 1085 SFUNCALL, TPTRTO|TSTRUCT, 1086 0, RRIGHT, 1087 "", }, 1088#endif 1089 1090{ STASG, INAREG|FOREFF, 1091 SOREG|SNAME, TANY, 1092 SAREG, TPTRTO|TANY, 1093 NSPECIAL|NAREG, RDEST, 1094 "F mov A1,si\nZQF mov si,A1\n", }, 1095 1096/* 1097 * DIV/MOD/MUL 1098 */ 1099/* long div is emulated */ 1100{ DIV, INCREG, 1101 SCREG|SNAME|SOREG|SCON, T32, 1102 SCREG|SNAME|SOREG|SCON, T32, 1103 NSPECIAL|NCREG|NCSL|NCSR, RESC1, 1104 "ZO", }, 1105 1106/* REVIEW We can only do (i)divb ax/byte and (i)divw (dx:ax)/word 1107 and the results are always in ah/al (remainer/mod) 1108 or dx:ax (dx = remainer, ax = mod) 1109 1110 Power of two needs to be done by shifts. For other cases of constants 1111 we need to implement two things 1112 1. Spotting add sequences for constants with few 1 bits on one side 1113 2. Spotting cases we can compute the magic constant to multiply with for 1114 the same result */ 1115 1116 1117{ DIV, INAREG, 1118 SAREG, TUNSIGNED|TPOINT, 1119 SAREG|SNAME|SOREG, TUNSIGNED|TPOINT, 1120 NSPECIAL, RDEST, 1121 " xor dx,dx\n divw AR\n", }, 1122 1123{ DIV, INCH, 1124 SHCH, TUCHAR, 1125 SHCH|SNAME|SOREG, TUCHAR, 1126 NSPECIAL, RDEST, 1127 " xor ah,ah\n divb AR\n", }, 1128 1129{ DIV, INFL, 1130 SHFL, TDOUBLE, 1131 SNAME|SOREG, TDOUBLE, 1132 0, RLEFT, 1133 " fdivl AR\n", }, 1134 1135{ DIV, INFL, 1136 SHFL, TLDOUBLE|TDOUBLE|TFLOAT, 1137 SHFL, TLDOUBLE|TDOUBLE|TFLOAT, 1138 0, RLEFT, 1139 " fdivZAp\n", }, 1140 1141/* (u)long mod is emulated */ 1142{ MOD, INCREG, 1143 SCREG|SNAME|SOREG|SCON, T32, 1144 SCREG|SNAME|SOREG|SCON, T32, 1145 NSPECIAL|NCREG|NCSL|NCSR, RESC1, 1146 "ZO", }, 1147 1148{ MOD, INAREG, 1149 SAREG, TP16, 1150 SAREG|SNAME|SOREG, TP16, 1151 NAREG|NSPECIAL, RESC1, 1152 " xor dx,dx\n divw AR\n", }, 1153 1154{ MOD, INCH, 1155 SHCH, TUCHAR, 1156 SHCH|SNAME|SOREG, TUCHAR, 1157 NBREG|NSPECIAL, RESC1, 1158 " xor ah,ah\n divb AR\n", }, 1159 1160/* (u)long mul is emulated */ 1161/* On 8086 we can only do multiplies of al * value into ax (for 8bit) 1162 or ax * value into dx:ax for 16bit 1163 1164 80186 allows us to do a signed multiply of a register with a constant 1165 into a second register 1166 1167 Same about shifts, and add optimisations applies here too */ 1168 1169/* 32bit mul is emulated (for now) */ 1170{ MUL, INCREG, 1171 SCREG|SNAME|SOREG|SCON, T32, 1172 SCREG|SNAME|SOREG|SCON, T32, 1173 NSPECIAL|NCREG|NCSL|NCSR, RESC1, 1174 "ZO", }, 1175 1176/* FIMXE: need special rules */ 1177{ MUL, INAREG, 1178 SAREG, T16|TPOINT, 1179 SAREG|SNAME|SOREG, T16|TPOINT, 1180 NSPECIAL, RDEST, 1181 " mul AR\n", }, 1182 1183{ MUL, INCH, 1184 SHCH, T8, 1185 SHCH|SNAME|SOREG, T8, 1186 NSPECIAL, RDEST, 1187 " mulb AR\n", }, 1188 1189{ MUL, INFL, 1190 SHFL, TDOUBLE, 1191 SNAME|SOREG, TDOUBLE, 1192 0, RLEFT, 1193 " fmull AR\n", }, 1194 1195{ MUL, INFL, 1196 SHFL , TLDOUBLE|TDOUBLE|TFLOAT, 1197 SHFL, TLDOUBLE|TDOUBLE|TFLOAT, 1198 0, RLEFT, 1199 " fmulp\n", }, 1200 1201/* 1202 * Indirection operators. 1203 */ 1204{ UMUL, INLL, 1205 SANY, TANY, 1206 SOREG, T32, 1207 NCREG, RESC1, 1208 " mov UL,U1\n mov AL,A1\n", }, 1209 1210{ UMUL, INAREG, 1211 SANY, TP16, 1212 SOREG, TP16, 1213 NAREG|NASL, RESC1, 1214 " mov AL,A1\n", }, 1215 1216{ UMUL, INCH, 1217 SANY, TANY, 1218 SOREG, T8, 1219 NBREG|NBSL, RESC1, 1220 " mov AL,A1\n", }, 1221 1222{ UMUL, INAREG, 1223 SANY, TANY, 1224 SOREG, T16, 1225 NAREG|NASL, RESC1, 1226 " mov AL,A1\n", }, 1227 1228{ UMUL, INFL, 1229 SANY, TANY, 1230 SOREG, TLDOUBLE, 1231 NDREG|NDSL, RESC1, 1232 " fldt AL\n", }, 1233 1234{ UMUL, INFL, 1235 SANY, TANY, 1236 SOREG, TDOUBLE, 1237 NDREG|NDSL, RESC1, 1238 " fldl AL\n", }, 1239 1240{ UMUL, INFL, 1241 SANY, TANY, 1242 SOREG, TFLOAT, 1243 NDREG|NDSL, RESC1, 1244 " flds AL\n", }, 1245 1246/* 1247 * Logical/branching operators 1248 */ 1249 1250/* Comparisions, take care of everything */ 1251{ OPLOG, FORCC, 1252 SHL|SOREG|SNAME, T32, 1253 SHL, T32, 1254 0, 0, 1255 "ZD", }, 1256 1257{ OPLOG, FORCC, 1258 SAREG|SOREG|SNAME, TP16, 1259 SCON|SAREG, TP16, 1260 0, RESCC, 1261 " cmp AL,AR\n", }, 1262 1263 1264{ OPLOG, FORCC, 1265 SCON|SAREG, TP16, 1266 SAREG|SOREG|SNAME, TP16, 1267 0, RESCC, 1268 " cmp AL,AR\n", }, 1269 1270{ OPLOG, FORCC, 1271 SBREG|SOREG|SNAME, T8, 1272 SCON|SBREG, TANY, 1273 0, RESCC, 1274 " cmpb AL,AR\n", }, 1275 1276{ OPLOG, FORCC, 1277 SCON|SBREG, T8, 1278 SBREG|SOREG|SNAME, TANY, 1279 0, RESCC, 1280 " cmpb AL,AR\n", }, 1281 1282{ OPLOG, FORCC, 1283 SDREG, TLDOUBLE|TDOUBLE|TFLOAT, 1284 SDREG, TLDOUBLE|TDOUBLE|TFLOAT, 1285 0, RNOP, 1286 "ZG", }, 1287 1288{ OPLOG, FORCC, 1289 SANY, TANY, 1290 SANY, TANY, 1291 REWRITE, 0, 1292 "diediedie!", }, 1293 1294/* AND/OR/ER/NOT */ 1295 1296/* FIXME: pcc generates nonsense ands, but they should be fixed somewhere 1297 if possible. In particular it will do the classic 32bit and with a 16bit 1298 0xFFFF by generating and ax,#ffff and bx,#0 1299 eg compiling 1300 sum1 = (sum1 & 0xFFFF) + (sum1 >> 16); 1301 writes a pile of crap code. 1302*/ 1303 1304 1305{ AND, INCREG|FOREFF, 1306 SCREG, T32, 1307 SCREG|SOREG|SNAME, T32, 1308 0, RLEFT, 1309 " and AR,AL\n and UR,UL\n", }, 1310 1311{ AND, INAREG|FOREFF, 1312 SAREG, T16, 1313 SAREG|SOREG|SNAME, T16, 1314 0, RLEFT, 1315 " and AR,AL\n", }, 1316 1317{ AND, INAREG|FOREFF, 1318 SAREG|SOREG|SNAME, T16, 1319 SCON|SAREG, T16, 1320 0, RLEFT, 1321 " and AR,AL\n", }, 1322 1323{ AND, INBREG|FOREFF, 1324 SBREG|SOREG|SNAME, T8, 1325 SCON|SBREG, T8, 1326 0, RLEFT, 1327 " and AR,AL\n", }, 1328 1329{ AND, INBREG|FOREFF, 1330 SBREG, T8, 1331 SBREG|SOREG|SNAME, T8, 1332 0, RLEFT, 1333 " and AR,AL\n", }, 1334/* AND/OR/ER/NOT */ 1335 1336/* 1337 * Jumps. 1338 */ 1339{ GOTO, FOREFF, 1340 SCON, TANY, 1341 SANY, TANY, 1342 0, RNOP, 1343 " jmp LL\n", }, 1344 1345#if defined(GCC_COMPAT) || defined(LANG_F77) 1346{ GOTO, FOREFF, 1347 SAREG, TANY, 1348 SANY, TANY, 1349 0, RNOP, 1350 " jmp *AL\n", }, 1351#endif 1352 1353/* 1354 * Convert LTYPE to reg. 1355 */ 1356{ OPLTYPE, FORCC|INL, 1357 SCREG, T32, 1358 SMIXOR, TANY, 1359 NCREG, RESC1, 1360 " xor U1,U1\n xor A1,A1\n", }, 1361 1362{ OPLTYPE, FORCC|INL, 1363 SCREG, T32, 1364 SMILWXOR, TANY, 1365 NCREG, RESC1, 1366 " mov U1,UL\n xor A1,A1\n", }, 1367 1368{ OPLTYPE, FORCC|INL, 1369 SCREG, T32, 1370 SMIHWXOR, TANY, 1371 NCREG, RESC1, 1372 " xor U1,U1\n mov A1,AL\n", }, 1373 1374{ OPLTYPE, INL, 1375 SANY, TANY, 1376 SCREG, T32, 1377 NCREG, RESC1, 1378 "ZK", }, 1379 1380{ OPLTYPE, INL, 1381 SANY, TANY, 1382 SCON|SOREG|SNAME, T32, 1383 NCREG, RESC1, 1384 " mov U1,UL\n mov A1,AL\n", }, 1385 1386{ OPLTYPE, FORCC|INAREG, 1387 SAREG, TP16, 1388 SMIXOR, TANY, 1389 NAREG|NASL, RESC1, 1390 " xor A1,A1\n", }, 1391 1392{ OPLTYPE, INAREG, 1393 SANY, TANY, 1394 SAREG|SCON|SOREG|SNAME, TP16, 1395 NAREG|NASL, RESC1, 1396 " mov A1,AL\n", }, 1397 1398{ OPLTYPE, INBREG, 1399 SANY, TANY, 1400 SBREG|SOREG|SNAME|SCON, T8, 1401 NBREG, RESC1, 1402 " mov A1,AL\n", }, 1403 1404{ OPLTYPE, FORCC|INAREG, 1405 SAREG, T16, 1406 SMIXOR, TANY, 1407 NAREG, RESC1, 1408 " xor A1,A1\n", }, 1409 1410{ OPLTYPE, INAREG, 1411 SANY, TANY, 1412 SAREG|SOREG|SNAME|SCON, T16, 1413 NAREG, RESC1, 1414 " mov A1,AL\n", }, 1415 1416{ OPLTYPE, INDREG, 1417 SANY, TLDOUBLE, 1418 SOREG|SNAME, TLDOUBLE, 1419 NDREG, RESC1, 1420 " fldt AL\n", }, 1421 1422{ OPLTYPE, INDREG, 1423 SANY, TDOUBLE, 1424 SOREG|SNAME, TDOUBLE, 1425 NDREG, RESC1, 1426 " fldl AL\n", }, 1427 1428{ OPLTYPE, INDREG, 1429 SANY, TFLOAT, 1430 SOREG|SNAME, TFLOAT, 1431 NDREG, RESC1, 1432 " flds AL\n", }, 1433 1434/* Only used in ?: constructs. The stack already contains correct value */ 1435{ OPLTYPE, INDREG, 1436 SANY, TFLOAT|TDOUBLE|TLDOUBLE, 1437 SDREG, TFLOAT|TDOUBLE|TLDOUBLE, 1438 NDREG, RESC1, 1439 "", }, 1440 1441/* 1442 * Negate a word. 1443 */ 1444 1445{ UMINUS, INCREG|FOREFF, 1446 SCREG, T32, 1447 SCREG, T32, 1448 0, RLEFT, 1449 " neg AL\n adc UL,#0\n neg UL\n", }, 1450 1451{ UMINUS, INAREG|FOREFF, 1452 SAREG, TP16, 1453 SAREG, TP16, 1454 0, RLEFT, 1455 " neg AL\n", }, 1456 1457{ UMINUS, INBREG|FOREFF, 1458 SBREG, T8, 1459 SBREG, T8, 1460 0, RLEFT, 1461 " neg AL\n", }, 1462 1463{ UMINUS, INFL|FOREFF, 1464 SHFL, TLDOUBLE|TDOUBLE|TFLOAT, 1465 SHFL, TLDOUBLE|TDOUBLE|TFLOAT, 1466 0, RLEFT, 1467 " fchs\n", }, 1468 1469{ COMPL, INCREG, 1470 SCREG, T32, 1471 SANY, TANY, 1472 0, RLEFT, 1473 " not AL\n not UL\n", }, 1474 1475{ COMPL, INAREG, 1476 SAREG, T16, 1477 SANY, TANY, 1478 0, RLEFT, 1479 " not AL\n", }, 1480 1481{ COMPL, INBREG, 1482 SBREG, T8, 1483 SANY, TANY, 1484 0, RLEFT, 1485 " not AL\n", }, 1486 1487/* 1488 * Arguments to functions. 1489 * 1490 * char has already been promoted to integer types 1491 */ 1492 1493/* Push immediate not 8086... Loading a register and pushing costs us 1494 4 + 11 clocks, loading memory would cost us 16 + EA */ 1495{ FUNARG, FOREFF, 1496 /*SCON|*/SCREG|SNAME|SOREG, T32, 1497 SANY, T32, 1498 0, RNULL, 1499 " push UL\n push AL\n", }, 1500 1501{ FUNARG, FOREFF, 1502 /*SCON|*/SAREG|SNAME|SOREG, T16|TPOINT, 1503 SANY, TP16, 1504 0, RNULL, 1505 " push AL\n", }, 1506 1507/* FIXME: FPU needs reworking into 4 regs or a memcpy */ 1508{ FUNARG, FOREFF, 1509 SNAME|SOREG, TDOUBLE, 1510 SANY, TDOUBLE, 1511 0, 0, 1512 " pushl UL\n pushl AL\n", }, 1513 1514{ FUNARG, FOREFF, 1515 SDREG, TDOUBLE, 1516 SANY, TDOUBLE, 1517 0, 0, 1518 " sub sp,#8\n fstpl [sp]\n", }, 1519 1520{ FUNARG, FOREFF, 1521 SNAME|SOREG, TFLOAT, 1522 SANY, TFLOAT, 1523 0, 0, 1524 " push UL\n push AL\n", }, 1525 1526{ FUNARG, FOREFF, 1527 SDREG, TFLOAT, 1528 SANY, TFLOAT, 1529 0, 0, 1530 " sub sp,#4\n fstps [sp]\n", }, 1531 1532{ FUNARG, FOREFF, 1533 SDREG, TLDOUBLE, 1534 SANY, TLDOUBLE, 1535 0, 0, 1536 " sub sp,#12\n fstpt [sp]\n", }, 1537 1538{ STARG, FOREFF, 1539 SAREG, TPTRTO|TSTRUCT, 1540 SANY, TSTRUCT, 1541 NSPECIAL, 0, 1542 "ZF", }, 1543 1544# define DF(x) FORREW,SANY,TANY,SANY,TANY,REWRITE,x,"" 1545 1546{ UMUL, DF( UMUL ), }, 1547 1548{ ASSIGN, DF(ASSIGN), }, 1549 1550{ STASG, DF(STASG), }, 1551 1552{ FLD, DF(FLD), }, 1553 1554{ OPLEAF, DF(NAME), }, 1555 1556/* { INIT, DF(INIT), }, */ 1557 1558{ OPUNARY, DF(UMINUS), }, 1559 1560{ OPANY, DF(BITYPE), }, 1561 1562{ FREE, FREE, FREE, FREE, FREE, FREE, FREE, FREE, "help; I'm in trouble\n" }, 1563}; 1564 1565int tablesize = sizeof(table)/sizeof(table[0]); 1566