home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / kaffe-0.5p4-src.tgz / tar.out / contrib / kaffe / config / i386 / jit-i386.def next >
Text File  |  1996-09-28  |  24KB  |  1,418 lines

  1. /* jit-i386.def
  2.  * i386 instruction definition.
  3.  *
  4.  * Copyright (c) 1996 Systems Architecture Research Centre,
  5.  *           City University, London, UK.
  6.  *
  7.  * See the file "license.terms" for information on usage and redistribution
  8.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  9.  *
  10.  * Written by Tim Wilkinson <tim@sarc.city.ac.uk>, June 1996.
  11.  */
  12.  
  13. #undef    DEBUG
  14.  
  15. #ifdef DEBUG
  16. #define    debug(x)    printf##x
  17. #else
  18. #define    debug(x)
  19. #endif
  20.  
  21. #define    do_move_int(t, f) {                    \
  22.         OUT = 0x89;                    \
  23.         OUT = 0xC0|(f<<3)|t;                \
  24.         debug(("movl %s,%s\n", regname(f), regname(t)));\
  25.     }
  26.  
  27. #define    check_reg_01() {                     \
  28.         int _r_ = rreg_int(1);                \
  29.         int _w_ = wreg_int(0);                \
  30.         assert(_r_ == _w_);                \
  31.     }
  32.  
  33. #define    do_force_move_int(t, f, n)                \
  34.     if ((t) != (f)) {                    \
  35.         forceRegister(seq_slot(s, (n)), (t), Rint);    \
  36.         do_move_int((t), (f));                \
  37.         f = (t);                    \
  38.     }
  39.  
  40. #define    return_dst()    slot_return(seq_dst(s))
  41.  
  42.  
  43. char* rnames[] = { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" };
  44. #define    regname(n)    rnames[n]
  45.  
  46. #define    REG_eax        0
  47. #define    REG_ecx        1
  48. #define    REG_edx        2
  49. #define    REG_ebx        3
  50. #define    REG_esp        4
  51. #define    REG_ebp        5
  52. #define    REG_esi        6
  53. #define    REG_edi        7
  54. #define    REG_flt0    8
  55. #define    REG_dbl0    REG_flt0
  56.  
  57. /* --------------------------------------------------------------------- */
  58.  
  59. define_insn(unimplemented, unimplemented)
  60. {
  61.     abort();
  62. }
  63.  
  64. define_insn(nop, nop)
  65. {
  66.     OUT = 0x90;
  67. }
  68.  
  69. /* --------------------------------------------------------------------- */
  70.  
  71. define_insn(prologue, prologue_xxx)
  72. {
  73.     int framesize = SLOTSIZE * (maxLocal + maxStack + maxTemp - maxArgs);
  74.  
  75.     OUT = 0x50|REG_ebp;
  76.     OUT = 0x89;
  77.     OUT = 0xC0|(REG_esp<<3)|REG_ebp;
  78.     if (framesize > 0) {
  79.         OUT = 0x81;
  80.         OUT = 0xE8|REG_esp;
  81.         OUT = framesize & 0xff;
  82.         OUT = (framesize >> 8) & 0xff;
  83.         OUT = (framesize >> 16) & 0xff;
  84.         OUT = (framesize >> 24) & 0xff;
  85.     }
  86.     OUT = 0x50|REG_edi;
  87.     OUT = 0x50|REG_esi;
  88.     OUT = 0x50|REG_ebx;
  89.  
  90.     debug(("pushl ebp\n"));
  91.     debug(("movl esp,ebp\n"));
  92.     if (framesize > 0) {
  93.         debug(("subl #%d,esp\n", framesize));
  94.     }
  95.     debug(("pushl edi\n"));
  96.     debug(("pushl esi\n"));
  97.     debug(("pushl ebx\n"));
  98. }
  99.  
  100. define_insn(epilogue, epilogue_xxx)
  101. {
  102.     OUT = 0x58|REG_ebx;
  103.     OUT = 0x58|REG_esi;
  104.     OUT = 0x58|REG_edi;
  105.     OUT = 0x89;
  106.     OUT = 0xC0|(REG_ebp<<3)|REG_esp;
  107.     OUT = 0x58|REG_ebp;
  108.  
  109.     debug(("popl ebx\n"));
  110.     debug(("popl esi\n"));
  111.     debug(("popl edi\n"));
  112.     debug(("movl ebp,esp\n"));
  113.     debug(("popl ebp\n"));
  114. }
  115.  
  116. /* --------------------------------------------------------------------- */
  117.  
  118. define_insn(spill_int, spill_Rxx)
  119. {
  120.     int r = rreg_int(0);
  121.     /* int o = -4 * (1 + const_int(1)); */
  122.     int o = SLOT2FRAMEOFFSET(seq_dst(s));
  123.  
  124.     OUT = 0x89;
  125.     OUT = 0x80|(r<<3)|REG_ebp;
  126.     OUT = o & 0xff;
  127.     OUT = (o >> 8) & 0xff;
  128.     OUT = (o >> 16) & 0xff;
  129.     OUT = (o >> 24) & 0xff;
  130.  
  131.     debug(("movl %s,%d(ebp)\n", regname(r), o));
  132. }
  133.  
  134. define_insn(spill_float, fspill_Rxx)
  135. {
  136.     int r = rreg_float(0);
  137.     int o = SLOT2FRAMEOFFSET(seq_dst(s));
  138.  
  139.     OUT = 0xD9;
  140.     OUT = 0x98|REG_ebp;
  141.     OUT = o & 0xff;
  142.     OUT = (o >> 8) & 0xff;
  143.     OUT = (o >> 16) & 0xff;
  144.     OUT = (o >> 24) & 0xff;
  145.  
  146.     debug(("fstp %d(ebp)\n", o));
  147. }
  148.  
  149. define_insn(spill_double, fspilll_Rxx)
  150. {
  151.     int r = rreg_double(0);
  152.     int o = SLOT2FRAMEOFFSET(seq_dst(s));
  153.  
  154.     OUT = 0xDD;
  155.     OUT = 0x98|REG_ebp;
  156.     OUT = o & 0xff;
  157.     OUT = (o >> 8) & 0xff;
  158.     OUT = (o >> 16) & 0xff;
  159.     OUT = (o >> 24) & 0xff;
  160.  
  161.     debug(("fstpl %d(ebp)\n", o));
  162. }
  163.  
  164. define_insn(reload_int, reload_Rxx)
  165. {
  166.     int r = rreg_int(0);
  167.     /* int o = -4 * (1 + const_int(1)); */
  168.     int o = SLOT2FRAMEOFFSET(seq_dst(s));
  169.  
  170.     OUT = 0x8B; 
  171.     OUT = 0x80|(r<<3)|REG_ebp;
  172.     OUT = o & 0xff;
  173.     OUT = (o >> 8) & 0xff;
  174.     OUT = (o >> 16) & 0xff;
  175.     OUT = (o >> 24) & 0xff;
  176.  
  177.     debug(("movl %d(ebp),%s\n", o, regname(r)));
  178. }
  179.  
  180. define_insn(reload_float, freload_Rxx)
  181. {
  182.     int w = wreg_float(0);
  183.     int o = SLOT2FRAMEOFFSET(seq_dst(s));
  184.  
  185.     OUT = 0xD9;
  186.     OUT = 0x80|REG_ebp;
  187.     OUT = o & 0xff;
  188.     OUT = (o >> 8) & 0xff;
  189.     OUT = (o >> 16) & 0xff;
  190.     OUT = (o >> 24) & 0xff;
  191.  
  192.     debug(("fld %d(ebp)\n", o));
  193. }
  194.  
  195. define_insn(reload_double, freloadl_Rxx)
  196. {
  197.     int w = wreg_double(0);
  198.     int o = SLOT2FRAMEOFFSET(seq_dst(s));
  199.  
  200.     OUT = 0xDD;
  201.     OUT = 0x80|REG_ebp;
  202.     OUT = o & 0xff;
  203.     OUT = (o >> 8) & 0xff;
  204.     OUT = (o >> 16) & 0xff;
  205.     OUT = (o >> 24) & 0xff;
  206.  
  207.     debug(("fldl %d(ebp)\n", o));
  208. }
  209.  
  210. /* --------------------------------------------------------------------- */
  211.  
  212. define_insn(move_int_const, move_RxC)
  213. {
  214.     int val = const_int(2);
  215.     int w = wreg_int(0);
  216.     OUT = 0xB8|w;
  217.     OUT = val & 0xff;
  218.     OUT = (val >> 8) & 0xff;
  219.     OUT = (val >> 16) & 0xff;
  220.     OUT = (val >> 24) & 0xff;
  221.  
  222.     debug(("movl #%d,%s\n", val, regname(w)));
  223. }
  224.  
  225. define_insn(move_label_const, move_RxL)
  226. {
  227.     label* l = (label*)const_int(2);
  228.     int w = wreg_int(0);
  229.  
  230.     OUT = 0xB8|w;
  231.     l->type |= Llong|Labsolute;
  232.     l->at = (uintp)CODEPC;
  233.     OUT = 0;
  234.     OUT = 0;
  235.     OUT = 0;
  236.     OUT = 0;
  237.  
  238.     debug(("movl #?,%s\n", regname(w)));
  239. }
  240.  
  241. define_insn(move_int, move_RxR)
  242. {
  243.     int r = rreg_int(2);
  244.     int w = wreg_int(0);
  245.  
  246.     if (r != w) {
  247.         /* If destination is a return slot, clobber the register
  248.          * associated with it.  If we dont do this we might
  249.          * overwrite something which is still important.
  250.          */
  251.         if (return_dst()) {
  252.             clobberRegister(w);
  253.         }
  254.  
  255.         OUT = 0x89;
  256.         OUT = 0xC0|(r<<3)|w;
  257.  
  258.         debug(("movl %s,%s\n", regname(r), regname(w)));
  259.     }
  260. }
  261.  
  262. define_insn(move_float_const, fmove_RxC)
  263. {
  264.     double val = const_float(2);
  265.     int w = wreg_float(0);
  266.  
  267.     if (val == 0.0) {
  268.         OUT = 0xD9;
  269.         OUT = 0xEE;
  270.  
  271.         debug(("fldz\n"));
  272.     }
  273.     else if (val == 1.0) {
  274.         OUT = 0xD9;
  275.         OUT = 0xE8;
  276.  
  277.         debug(("fld1\n"));
  278.     }
  279.     else {
  280.         abort();
  281.     }
  282. }
  283.  
  284. define_insn(move_float, fmove_RxR)
  285. {
  286.     int or = rslot_float(2);
  287.     int ow = rslot_float(0);
  288.  
  289.     if (or != ow) {
  290.         int w = wreg_float(0);
  291.  
  292.         OUT = 0xD9;
  293.         OUT = 0x80|REG_ebp;
  294.         OUT = or & 0xff;
  295.         OUT = (or >> 8) & 0xff;
  296.         OUT = (or >> 16) & 0xff;
  297.         OUT = (or >> 24) & 0xff;
  298.  
  299.         debug(("fld %d(ebp)\n", or));
  300.     }
  301. }
  302.  
  303. define_insn(move_double_const, fmovel_RxC)
  304. {
  305.     double val = const_double(2);
  306.     int w = wreg_double(0);
  307.  
  308.     if (val == 0.0) {
  309.         OUT = 0xD9;
  310.         OUT = 0xEE;
  311.  
  312.         debug(("fldz\n"));
  313.     }
  314.     else if (val == 1.0) {
  315.         OUT = 0xD9;
  316.         OUT = 0xE8;
  317.  
  318.         debug(("fld1\n"));
  319.     }
  320.     else {
  321.         abort();
  322.     }
  323. }
  324.  
  325. define_insn(move_double, fmovel_RxR)
  326. {
  327.     int or = rslot_double(2);
  328.     int ow = rslot_double(0);
  329.  
  330.     if (or != ow) {
  331.         int w = wreg_double(0);
  332.  
  333.         OUT = 0xDD;
  334.         OUT = 0x80|REG_ebp;
  335.         OUT = or & 0xff;
  336.         OUT = (or >> 8) & 0xff;
  337.         OUT = (or >> 16) & 0xff;
  338.         OUT = (or >> 24) & 0xff;
  339.  
  340.         debug(("fldl %d(ebp)\n", or));
  341.     }
  342. }
  343.  
  344. /* --------------------------------------------------------------------- */
  345.  
  346. define_insn(add_int, add_RRR)
  347. {
  348.     int r;
  349.     int w;
  350.  
  351.     check_reg_01();
  352.  
  353.     r = rreg_int(2);
  354.     w = rwreg_int(0);
  355.  
  356.     OUT = 0x01;
  357.         OUT = 0xC0|(r<<3)|w;
  358.  
  359.     debug(("addl %s,%s\n", regname(r), regname(w)));
  360. }
  361.  
  362. define_insn(adc_int, adc_RRR)
  363. {
  364.     int r;
  365.     int w;
  366.  
  367.     r = rreg_int(2);
  368.     w = rwreg_int(0);
  369.  
  370.     OUT = 0x11;
  371.         OUT = 0xC0|(r<<3)|w;
  372.  
  373.     debug(("adcl %s,%s\n", regname(r), regname(w)));
  374. }
  375.  
  376. define_insn(add_float, fadd_RRR)
  377. {
  378.     int r2 = rslot_float(2);    /* Get r2 into memory */
  379.     int r1 = rreg_float(1);        /* Load r1 into the register stack */
  380.     int w = wreg_float(0);        /* Result will be in register stack */
  381.  
  382.     OUT = 0xD8;
  383.     OUT = 0x80|REG_ebp;
  384.     OUT = r2 & 0xff;
  385.     OUT = (r2 >> 8) & 0xff;
  386.     OUT = (r2 >> 16) & 0xff;
  387.     OUT = (r2 >> 24) & 0xff;
  388.  
  389.     debug(("fadd %d(ebp)\n", r2));
  390. }
  391.  
  392. define_insn(add_double, faddl_RRR)
  393. {
  394.     int r2 = rslot_double(2);    /* Get r2 into memory */
  395.     int r1 = rreg_double(1);    /* Load r1 into the register stack */
  396.     int w = wreg_double(0);        /* Result will be in register stack */
  397.  
  398.     OUT = 0xDC;
  399.     OUT = 0x80|REG_ebp;
  400.     OUT = r2 & 0xff;
  401.     OUT = (r2 >> 8) & 0xff;
  402.     OUT = (r2 >> 16) & 0xff;
  403.     OUT = (r2 >> 24) & 0xff;
  404.  
  405.     debug(("faddl %d(ebp)\n", r2));
  406. }
  407.  
  408. define_insn(sub_int, sub_RRR)
  409. {
  410.     int r;
  411.     int w;
  412.  
  413.     check_reg_01();
  414.  
  415.     r = rreg_int(2);
  416.     w = rwreg_int(0);
  417.  
  418.     OUT = 0x29;
  419.         OUT = 0xC0|(r<<3)|w;
  420.  
  421.     debug(("subl %s,%s\n", regname(r), regname(w)));
  422. }
  423.  
  424. define_insn(sbc_int, sbc_RRR)
  425. {
  426.     int r;
  427.     int w;
  428.  
  429.     r = rreg_int(2);
  430.     w = rwreg_int(0);
  431.  
  432.     OUT = 0x19;
  433.         OUT = 0xC0|(r<<3)|w;
  434.  
  435.     debug(("sbbl %s,%s\n", regname(r), regname(w)));
  436. }
  437.  
  438. define_insn(sub_float, fsub_RRR)
  439. {
  440.     int r2 = rslot_float(2);    /* Get r2 into memory */
  441.     int r1 = rreg_float(1);        /* Load r1 into the register stack */
  442.     int w = wreg_float(0);        /* Result will be in register stack */
  443.  
  444.     OUT = 0xD8;
  445.     OUT = 0xA0|REG_ebp;
  446.     OUT = r2 & 0xff;
  447.     OUT = (r2 >> 8) & 0xff;
  448.     OUT = (r2 >> 16) & 0xff;
  449.     OUT = (r2 >> 24) & 0xff;
  450.  
  451.     debug(("fsub %d(ebp)\n", r2));
  452. }
  453.  
  454. define_insn(sub_double, fsubl_RRR)
  455. {
  456.     int r2 = rslot_double(2);    /* Get r2 into memory */
  457.     int r1 = rreg_double(1);    /* Load r1 into the register stack */
  458.     int w = wreg_double(0);        /* Result will be in register stack */
  459.  
  460.     OUT = 0xDC;
  461.     OUT = 0xA0|REG_ebp;
  462.     OUT = r2 & 0xff;
  463.     OUT = (r2 >> 8) & 0xff;
  464.     OUT = (r2 >> 16) & 0xff;
  465.     OUT = (r2 >> 24) & 0xff;
  466.  
  467.     debug(("fsubl %d(ebp)\n", r2));
  468. }
  469.  
  470. define_insn(mul_int, mul_RRR)
  471. {
  472.     int r;
  473.     int w;
  474.  
  475.     check_reg_01();
  476.  
  477.     r = rreg_int(2);
  478.     w = rwreg_int(0);
  479.  
  480.     OUT = 0x0F;
  481.     OUT = 0xAF;
  482.         OUT = 0xC0|(w<<3)|r;
  483.  
  484.     debug(("imull %s,%s\n", regname(r), regname(w)));
  485. }
  486.  
  487. define_insn(mul_float, fmul_RRR)
  488. {
  489.     int r2 = rslot_float(2);    /* Get r2 into memory */
  490.     int r1 = rreg_float(1);        /* Load r1 into the register stack */
  491.     int w = wreg_float(0);        /* Result will be in register stack */
  492.  
  493.     OUT = 0xD8;
  494.     OUT = 0x88|REG_ebp;
  495.     OUT = r2 & 0xff;
  496.     OUT = (r2 >> 8) & 0xff;
  497.     OUT = (r2 >> 16) & 0xff;
  498.     OUT = (r2 >> 24) & 0xff;
  499.  
  500.     debug(("fmul %d(ebp)\n", r2));
  501. }
  502.  
  503. define_insn(mul_double, fmull_RRR)
  504. {
  505.     int r2 = rslot_double(2);    /* Get r2 into memory */
  506.     int r1 = rreg_double(1);    /* Load r1 into the register stack */
  507.     int w = wreg_double(0);        /* Result will be in register stack */
  508.  
  509.     OUT = 0xDC;
  510.     OUT = 0x88|REG_ebp;
  511.     OUT = r2 & 0xff;
  512.     OUT = (r2 >> 8) & 0xff;
  513.     OUT = (r2 >> 16) & 0xff;
  514.     OUT = (r2 >> 24) & 0xff;
  515.  
  516.     debug(("fmull %d(ebp)\n", r2));
  517. }
  518.  
  519. define_insn(div_int, div_RRR)
  520. {
  521.     int r;
  522.     int w;
  523.  
  524.     check_reg_01();
  525.  
  526.     w = rwreg_int(0);
  527.  
  528.     /* Can only divide accumulator. */
  529.     do_force_move_int(REG_eax, w, 0);
  530.  
  531.     /* EDX is also used so get hold of it */
  532.     clobberRegister(REG_edx);
  533.  
  534.     /* Setup EDX - should contains the sign of EAX */
  535.     do_move_int(REG_edx, REG_eax);
  536.     OUT = 0xC1;
  537.     OUT = 0xF8|REG_edx;
  538.     OUT = 31;
  539.     debug(("sarl #31,edx\n"));
  540.  
  541.     r = rreg_int(2);
  542.  
  543.     OUT = 0xF7;
  544.         OUT = 0xF8|r;
  545.  
  546.     assert(r != REG_eax);
  547.     assert(r != REG_edx);
  548.     debug(("idivl %s,%s\n", regname(r), regname(w)));
  549. }
  550.  
  551. define_insn(div_float, fdiv_RRR)
  552. {
  553.     int r2 = rslot_float(2);    /* Get r2 into memory */
  554.     int r1 = rreg_float(1);        /* Load r1 into the register stack */
  555.     int w = wreg_float(0);        /* Result will be in register stack */
  556.  
  557.     OUT = 0xD8;
  558.     OUT = 0xB0|REG_ebp;
  559.     OUT = r2 & 0xff;
  560.     OUT = (r2 >> 8) & 0xff;
  561.     OUT = (r2 >> 16) & 0xff;
  562.     OUT = (r2 >> 24) & 0xff;
  563.  
  564.     debug(("fdiv %d(ebp)\n", r2));
  565. }
  566.  
  567. define_insn(div_double, fdivl_RRR)
  568. {
  569.     int r2 = rslot_double(2);    /* Get r2 into memory */
  570.     int r1 = rreg_double(1);    /* Load r1 into the register stack */
  571.     int w = wreg_double(0);        /* Result will be in register stack */
  572.  
  573.     OUT = 0xDC;
  574.     OUT = 0xB0|REG_ebp;
  575.     OUT = r2 & 0xff;
  576.     OUT = (r2 >> 8) & 0xff;
  577.     OUT = (r2 >> 16) & 0xff;
  578.     OUT = (r2 >> 24) & 0xff;
  579.  
  580.     debug(("fdivl %d(ebp)\n", r2));
  581. }
  582.  
  583. define_insn(rem_int, rem_RRR)
  584. {
  585.     int r;
  586.     int w;
  587.  
  588.     check_reg_01();
  589.  
  590.     w = rwreg_int(0);
  591.  
  592.     /* Can only divide accumulator. */
  593.     do_force_move_int(REG_eax, w, 0);
  594.  
  595.     /* EDX is also used so get hold of it */
  596.     clobberRegister(REG_edx);
  597.  
  598.     /* Setup EDX - should contains the sign of EAX */
  599.     do_move_int(REG_edx, REG_eax);
  600.     OUT = 0xC1;
  601.     OUT = 0xF8|REG_edx;
  602.     OUT = 31;
  603.     debug(("sarl #31,edx\n"));
  604.  
  605.     r = rreg_int(2);
  606.  
  607.     OUT = 0xF7;
  608.         OUT = 0xF8|r;
  609.  
  610.     assert(r != REG_eax);
  611.     assert(r != REG_edx);
  612.     debug(("idivl %s,%s\n", regname(r), regname(w)));
  613.  
  614.     /* Result is in EDX not EAX - we must force the slot register */
  615.     forceRegister(seq_dst(s), REG_edx, Rint);
  616. }
  617.  
  618. /* --------------------------------------------------------------------- */
  619.  
  620. define_insn(and_int, and_RRR)
  621. {
  622.     int r;
  623.     int w;
  624.  
  625.     check_reg_01();
  626.  
  627.     r = rreg_int(2);
  628.     w = rwreg_int(0);
  629.  
  630.     OUT = 0x21;
  631.         OUT = 0xC0|(r<<3)|w;
  632.  
  633.     debug(("andl %s,%s\n", regname(r), regname(w)));
  634. }
  635.  
  636. define_insn(or_int, or_RRR)
  637. {
  638.     int r;
  639.     int w;
  640.  
  641.     check_reg_01();
  642.  
  643.     r = rreg_int(2);
  644.     w = rwreg_int(0);
  645.  
  646.     OUT = 0x09;
  647.         OUT = 0xC0|(r<<3)|w;
  648.  
  649.     debug(("orl %s,%s\n", regname(r), regname(w)));
  650. }
  651.  
  652. define_insn(xor_int, xor_RRR)
  653. {
  654.     int r;
  655.     int w;
  656.  
  657.     check_reg_01();
  658.  
  659.     r = rreg_int(2);
  660.     w = rwreg_int(0);
  661.  
  662.     OUT = 0x31;
  663.         OUT = 0xC0|(r<<3)|w;
  664.  
  665.     debug(("xorl %s,%s\n", regname(r), regname(w)));
  666. }
  667.  
  668. define_insn(ashr_int, ashr_RRR)
  669. {
  670.     int r;
  671.     int w;
  672.  
  673.     check_reg_01();
  674.  
  675.     r = rreg_int(2);
  676.  
  677.     /* Can only shift by ECX. */
  678.     do_force_move_int(REG_ecx, r, 2);
  679.  
  680.     w = rwreg_int(0);
  681.  
  682.     OUT = 0xD3;
  683.         OUT = 0xF8|w;
  684.  
  685.     debug(("sarl %s,%s\n", regname(r), regname(w)));
  686. }
  687.  
  688. define_insn(lshr_int, lshr_RRR)
  689. {
  690.     int r;
  691.     int w;
  692.  
  693.     check_reg_01();
  694.  
  695.     r = rreg_int(2);
  696.  
  697.     /* Can only shift by ECX. */
  698.     do_force_move_int(REG_ecx, r, 2);
  699.  
  700.     w = rwreg_int(0);
  701.  
  702.     OUT = 0xD3;
  703.         OUT = 0xE8|w;
  704.  
  705.     debug(("shrl %s,%s\n", regname(r), regname(w)));
  706. }
  707.  
  708. define_insn(lshl_int, lshl_RRR)
  709. {
  710.     int r;
  711.     int w;
  712.  
  713.     check_reg_01();
  714.  
  715.     r = rreg_int(2);
  716.  
  717.     /* Can only shift by ECX. */
  718.     do_force_move_int(REG_ecx, r, 2);
  719.  
  720.     w = rwreg_int(0);
  721.  
  722.     OUT = 0xD3;
  723.         OUT = 0xE0|w;
  724.  
  725.     debug(("shll %s,%s\n", regname(r), regname(w)));
  726. }
  727.  
  728. /* --------------------------------------------------------------------- */
  729.  
  730. define_insn(load_int, load_RxR)
  731. {
  732.     int r = rreg_int(2);
  733.     int w = wreg_int(0);
  734.  
  735.     OUT = 0x8B;
  736.     OUT = 0x00|(w<<3)|r;
  737.     if (r == REG_esp) {
  738.         OUT = 0x20|REG_esp;
  739.     }
  740.  
  741.     debug(("movl (%s),%s\n", regname(r), regname(w)));
  742. }
  743.  
  744. define_insn(load_float, fload_RxR)
  745. {
  746.     int r = rreg_int(2);
  747.     int w = wreg_float(0);
  748.  
  749.     OUT = 0xD9;
  750.     OUT = 0x00|r;
  751.  
  752.     debug(("fld (%s)\n", regname(r)));
  753. }
  754.  
  755. define_insn(load_double, floadl_RxR)
  756. {
  757.     int r = rreg_int(2);
  758.     int w = wreg_double(0);
  759.  
  760.     OUT = 0xDD;
  761.     OUT = 0x00|r;
  762.  
  763.     debug(("fldl (%s)\n", regname(r)));
  764. }
  765.  
  766. define_insn(store_int, store_xRR)
  767. {
  768.     int r = rreg_int(2);
  769.     int w = rreg_int(1);
  770.  
  771.     OUT = 0x89;
  772.     OUT = 0x00|(r<<3)|w;
  773.     if (w == REG_esp) {
  774.         OUT = 0x20|REG_esp;
  775.     }
  776.  
  777.     debug(("movl %s,(%s)\n", regname(r), regname(w)));
  778. }
  779.  
  780. define_insn(store_float, fstore_RxR)
  781. {
  782.     int r = rreg_float(2);
  783.     int w = rreg_int(1);
  784.  
  785.     OUT = 0xD9;
  786.     OUT = 0x18|w;
  787.  
  788.     debug(("fstp (%s)\n", regname(w)));
  789. }
  790.  
  791. define_insn(store_double, fstorel_RxR)
  792. {
  793.     int r = rreg_double(2);
  794.     int w = rreg_int(1);
  795.  
  796.     OUT = 0xDD;
  797.     OUT = 0x18|w;
  798.  
  799.     debug(("fstlp (%s)\n", regname(w)));
  800. }
  801.  
  802. /* --------------------------------------------------------------------- */
  803.  
  804. define_insn(cmp_int, cmp_xRR)
  805. {
  806.     int r1 = rreg_int(1);
  807.     int r2 = rreg_int(2);
  808.  
  809.     OUT = 0x39;
  810.     OUT = 0xC0|(r2<<3)|r1;
  811.  
  812.     debug(("cmpl %s,%s\n", regname(r2), regname(r1)));
  813. }
  814.  
  815. /* --------------------------------------------------------------------- */
  816.  
  817. define_insn(cvt_int_float, cvtif_RxR)
  818. {
  819.     int r = rslot_int(2);
  820.     int w = wreg_float(0);
  821.  
  822.     OUT = 0xDB;
  823.     OUT = 0x80|REG_ebp;
  824.     OUT = r & 0xff;
  825.     OUT = (r >> 8) & 0xff;
  826.     OUT = (r >> 16) & 0xff;
  827.     OUT = (r >> 24) & 0xff;
  828.  
  829.     debug(("fild %d(ebp)\n", r));
  830. }
  831.  
  832. define_insn(cvt_int_double, cvtid_RxR)
  833. {
  834.     int r = rslot_int(2);
  835.     int w = wreg_double(0);
  836.  
  837.     OUT = 0xDB;
  838.     OUT = 0x80|REG_ebp;
  839.     OUT = r & 0xff;
  840.     OUT = (r >> 8) & 0xff;
  841.     OUT = (r >> 16) & 0xff;
  842.     OUT = (r >> 24) & 0xff;
  843.  
  844.     debug(("fild %d(ebp)\n", r));
  845. }
  846.  
  847. define_insn(cvt_long_float, cvtlf_RxR)
  848. {
  849.     int r = rslot_long(2);
  850.     int w = wreg_float(0);
  851.  
  852.     OUT = 0xDF;
  853.     OUT = 0xA8|REG_ebp;
  854.     OUT = r & 0xff;
  855.     OUT = (r >> 8) & 0xff;
  856.     OUT = (r >> 16) & 0xff;
  857.     OUT = (r >> 24) & 0xff;
  858.  
  859.     debug(("fildll %d(ebp)\n", r));
  860. }
  861.  
  862. define_insn(cvt_long_double, cvtld_RxR)
  863. {
  864.     int r = rslot_long(2);
  865.     int w = wreg_double(0);
  866.  
  867.     OUT = 0xDF;
  868.     OUT = 0xA8|REG_ebp;
  869.     OUT = r & 0xff;
  870.     OUT = (r >> 8) & 0xff;
  871.     OUT = (r >> 16) & 0xff;
  872.     OUT = (r >> 24) & 0xff;
  873.  
  874.     debug(("fildll %d(ebp)\n", r));
  875. }
  876.  
  877. define_insn(cvt_float_int, cvtfi_RxR)
  878. {
  879.     int r = rreg_float(2);
  880.     int w = wslot_int(0);
  881.  
  882.     OUT = 0xDB;
  883.     OUT = 0x98|REG_ebp;
  884.     OUT = w & 0xff;
  885.     OUT = (w >> 8) & 0xff;
  886.     OUT = (w >> 16) & 0xff;
  887.     OUT = (w >> 24) & 0xff;
  888.  
  889.     debug(("fistp %d(ebp)\n", w));
  890. }
  891.  
  892. define_insn(cvt_double_int, cvtdi_RxR)
  893. {
  894.     int r = rreg_double(2);
  895.     int w = wslot_int(0);
  896.  
  897.     OUT = 0xDB;
  898.     OUT = 0x98|REG_ebp;
  899.     OUT = w & 0xff;
  900.     OUT = (w >> 8) & 0xff;
  901.     OUT = (w >> 16) & 0xff;
  902.     OUT = (w >> 24) & 0xff;
  903.  
  904.     debug(("fistp %d(ebp)\n", w));
  905. }
  906.  
  907. define_insn(cvt_float_long, cvtfl_RxR)
  908. {
  909.     int r = rreg_float(2);
  910.     int w = wslot_long(0);
  911.  
  912.     OUT = 0xDF;
  913.     OUT = 0xB8|REG_ebp;
  914.     OUT = w & 0xff;
  915.     OUT = (w >> 8) & 0xff;
  916.     OUT = (w >> 16) & 0xff;
  917.     OUT = (w >> 24) & 0xff;
  918.  
  919.     debug(("fistpl %d(ebp)\n", w));
  920. }
  921.  
  922. define_insn(cvt_double_long, cvtdl_RxR)
  923. {
  924.     int r = rreg_double(2);
  925.     int w = wslot_long(0);
  926.  
  927.     OUT = 0xDF;
  928.     OUT = 0xB8|REG_ebp;
  929.     OUT = w & 0xff;
  930.     OUT = (w >> 8) & 0xff;
  931.     OUT = (w >> 16) & 0xff;
  932.     OUT = (w >> 24) & 0xff;
  933.  
  934.     debug(("fistpl %d(ebp)\n", w));
  935. }
  936.  
  937. define_insn(cvt_float_double, cvtfd_RxR)
  938. {
  939.     int o = rslot_float(2);
  940.     int w = wreg_double(0);
  941.  
  942.     OUT = 0xD9;
  943.     OUT = 0x80|REG_ebp;
  944.     OUT = o & 0xff;
  945.     OUT = (o >> 8) & 0xff;
  946.     OUT = (o >> 16) & 0xff;
  947.     OUT = (o >> 24) & 0xff;
  948.  
  949.     debug(("fld %d(ebp)\n", o));
  950. }
  951.  
  952. define_insn(cvt_double_float, cvtdf_RxR)
  953. {
  954.     int o = rslot_double(2);
  955.     int w = wreg_float(0);
  956.  
  957.     OUT = 0xDD;
  958.     OUT = 0x80|REG_ebp;
  959.     OUT = o & 0xff;
  960.     OUT = (o >> 8) & 0xff;
  961.     OUT = (o >> 16) & 0xff;
  962.     OUT = (o >> 24) & 0xff;
  963.  
  964.     debug(("fldl %d(ebp)\n", o));
  965. }
  966.  
  967. /* --------------------------------------------------------------------- */
  968.  
  969. define_insn(build_key, set_word_xxC)
  970. {
  971.     jint val = const_int(2);
  972.  
  973.     OUT = val & 0xff;
  974.     OUT = (val >> 8) & 0xff;
  975.     OUT = (val >> 16) & 0xff;
  976.     OUT = (val >> 24) & 0xff;
  977.  
  978.     debug((".word %08x\n", val));
  979. }
  980.  
  981. define_insn(build_code_ref, set_wordpc_xxC)
  982. {
  983.     label* l = (label*)const_int(2);
  984.  
  985.     l->type |= Llong|Labsolute;
  986.     l->at = (uintp)CODEPC;
  987.     OUT = 0;
  988.     OUT = 0;
  989.     OUT = 0;
  990.     OUT = 0;
  991.     l->from = (uintp)CODEPC;
  992.     debug((".word ?\n"));
  993. }
  994.  
  995. /* --------------------------------------------------------------------- */
  996.  
  997. define_insn(set_label, set_label_xxC)
  998. {
  999.     label* l = (label*)const_int(2);
  1000.     l->to = (uint32)CODEPC;
  1001. }
  1002.  
  1003. define_insn(branch, branch_xCC)
  1004. {
  1005.     label* l = (label*)const_int(1);
  1006.     int bt = const_int(2);
  1007.  
  1008.     l->type |= Llong|Lrelative;
  1009.     switch (bt) {
  1010.     case ba:
  1011.         OUT = 0xE9;
  1012.         l->at = (uintp)CODEPC;
  1013.         OUT = 0;
  1014.         OUT = 0;
  1015.         OUT = 0;
  1016.         OUT = 0;
  1017.         l->from = (uintp)CODEPC;
  1018.         debug(("jmpl ?\n"));
  1019.         break;
  1020.     case beq:
  1021.         OUT = 0x0F;
  1022.         OUT = 0x84;
  1023.         l->at = (uintp)CODEPC;
  1024.         OUT = 0;
  1025.         OUT = 0;
  1026.         OUT = 0;
  1027.         OUT = 0;
  1028.         l->from = (uintp)CODEPC;
  1029.         debug(("je ?\n"));
  1030.         break;
  1031.     case bne:
  1032.         OUT = 0x0F;
  1033.         OUT = 0x85;
  1034.         l->at = (uintp)CODEPC;
  1035.         OUT = 0;
  1036.         OUT = 0;
  1037.         OUT = 0;
  1038.         OUT = 0;
  1039.         l->from = (uintp)CODEPC;
  1040.         debug(("jne ?\n"));
  1041.         break;
  1042.     case blt:
  1043.         OUT = 0x0F;
  1044.         OUT = 0x8C;
  1045.         l->at = (uintp)CODEPC;
  1046.         OUT = 0;
  1047.         OUT = 0;
  1048.         OUT = 0;
  1049.         OUT = 0;
  1050.         l->from = (uintp)CODEPC;
  1051.         debug(("jlt ?\n"));
  1052.         break;
  1053.     case ble:
  1054.         OUT = 0x0F;
  1055.         OUT = 0x8E;
  1056.         l->at = (uintp)CODEPC;
  1057.         OUT = 0;
  1058.         OUT = 0;
  1059.         OUT = 0;
  1060.         OUT = 0;
  1061.         l->from = (uintp)CODEPC;
  1062.         debug(("jle ?\n"));
  1063.         break;
  1064.     case bgt:
  1065.         OUT = 0x0F;
  1066.         OUT = 0x8F;
  1067.         l->at = (uintp)CODEPC;
  1068.         OUT = 0;
  1069.         OUT = 0;
  1070.         OUT = 0;
  1071.         OUT = 0;
  1072.         l->from = (uintp)CODEPC;
  1073.         debug(("jgt ?\n"));
  1074.         break;
  1075.     case bge:
  1076.         OUT = 0x0F;
  1077.         OUT = 0x8D;
  1078.         l->at = (uintp)CODEPC;
  1079.         OUT = 0;
  1080.         OUT = 0;
  1081.         OUT = 0;
  1082.         OUT = 0;
  1083.         l->from = (uintp)CODEPC;
  1084.         debug(("jge ?\n"));
  1085.         break;
  1086.     default:
  1087.         abort();
  1088.     }
  1089. }
  1090.  
  1091. define_insn(branch_indirect, branch_indirect_xRC)
  1092. {
  1093.     int r = rreg_int(1);
  1094.     assert(const_int(2) == ba);
  1095.  
  1096.     OUT = 0xFF;
  1097.     OUT = 0xE0|r;
  1098.  
  1099.     debug(("jmp (%s)\n", regname(r)));
  1100. }
  1101.  
  1102. define_insn(call_ref, call_xCC)
  1103. {
  1104.     label* l = (label*)const_int(1);
  1105.     assert(const_int(2) == ba);
  1106.  
  1107.     OUT = 0xE8;
  1108.     l->type |= Llong|Lrelative;
  1109.     l->at = (uintp)CODEPC;
  1110.     OUT = 0;
  1111.     OUT = 0;
  1112.     OUT = 0;
  1113.     OUT = 0;
  1114.     l->from = (uintp)CODEPC;
  1115.  
  1116.     debug(("call ?\n"));
  1117. }
  1118.  
  1119. define_insn(call, call_xRC)
  1120. {
  1121.     int r = rreg_int(1);
  1122.     assert(const_int(2) == ba);
  1123.  
  1124.     OUT = 0xFF;
  1125.     OUT = 0xD0|r;
  1126.  
  1127.     debug(("call %s\n", regname(r)));
  1128. }
  1129.  
  1130. define_insn(ret, ret_xxx)
  1131. {
  1132.     OUT = 0xC3;
  1133.  
  1134.     debug(("ret\n"));
  1135. }
  1136.  
  1137. define_insn(push_int, push_xxR)
  1138. {
  1139.     int r = rreg_int(2);
  1140.  
  1141.     OUT = 0xFF;
  1142.     OUT = 0xF0|r;
  1143.  
  1144.     debug(("pushl %s\n", regname(r)));
  1145. }
  1146.  
  1147. define_insn(push_float, fpush_xxR)
  1148. {
  1149.     int r = rreg_int(2);    /* Move the float into a register */
  1150.  
  1151.     OUT = 0xFF;
  1152.     OUT = 0xF0|r;
  1153.  
  1154.     debug(("pushl %s\n", regname(r)));
  1155. }
  1156.  
  1157. define_insn(push_double, fpushl_xxR)
  1158. {
  1159.     int r = rslot_int(2);    /* Move the float into a slot */
  1160.  
  1161.     OUT = 0xFF;
  1162.     OUT = 0xB0|REG_ebp;
  1163.     OUT = (r+4) & 0xff;
  1164.     OUT = ((r+4) >> 8) & 0xff;
  1165.     OUT = ((r+4) >> 16) & 0xff;
  1166.     OUT = ((r+4) >> 24) & 0xff;
  1167.  
  1168.     debug(("pushl %d(ebp)\n", (r+4)));
  1169.  
  1170.     OUT = 0xFF;
  1171.     OUT = 0xB0|REG_ebp;
  1172.     OUT = r & 0xff;
  1173.     OUT = (r >> 8) & 0xff;
  1174.     OUT = (r >> 16) & 0xff;
  1175.     OUT = (r >> 24) & 0xff;
  1176.  
  1177.     debug(("pushl %d(ebp)\n", r));
  1178. }
  1179.  
  1180. define_insn(popargs, popargs_xxC)
  1181. {
  1182.     int o = const_int(2);
  1183.     o *= 4;
  1184.  
  1185.     OUT = 0x81;
  1186.     OUT = 0xC0|REG_esp;
  1187.     OUT = o & 0xff;
  1188.     OUT = (o >> 8) & 0xff;
  1189.     OUT = (o >> 16) & 0xff;
  1190.     OUT = (o >> 24) & 0xff;
  1191.  
  1192.     debug(("addl %d,esp\n", o));
  1193. }
  1194.  
  1195. define_insn(return_int, return_Rxx)
  1196. {
  1197.     forceRegister(seq_dst(s), REG_eax, Rint);
  1198. }
  1199.  
  1200. define_insn(return_long, returnl_Rxx)
  1201. {
  1202.     forceRegister(seq_dst(s), REG_eax, Rint);
  1203.     forceRegister(seq_dst(s)+1, REG_edx, Rint);
  1204. }
  1205.  
  1206. define_insn(return_float, freturn_Rxx)
  1207. {
  1208.     forceRegister(seq_dst(s), REG_flt0, Rfloat);
  1209. }
  1210.  
  1211. define_insn(return_double, freturnl_Rxx)
  1212. {
  1213.     forceRegister(seq_dst(s), REG_dbl0, Rdouble);
  1214. }
  1215.  
  1216. /* --------------------------------------------------------------------- */
  1217.  
  1218. define_insn(add_int_const, add_RRC)
  1219. {
  1220.     int rw;
  1221.     int v;
  1222.  
  1223.     check_reg_01();
  1224.  
  1225.     v = const_int(2);
  1226.     rw = rwreg_int(0);
  1227.  
  1228.     OUT = 0x81;
  1229.         OUT = 0xC0|rw;
  1230.     OUT = v & 0xff;
  1231.     OUT = (v >> 8) & 0xff;
  1232.     OUT = (v >> 16) & 0xff;
  1233.     OUT = (v >> 24) & 0xff;
  1234.  
  1235.     debug(("addl #%d,%s\n", v, regname(rw)));
  1236. }
  1237.  
  1238. define_insn(sub_int_const, sub_RRC)
  1239. {
  1240.     int rw;
  1241.     int v;
  1242.  
  1243.     check_reg_01();
  1244.  
  1245.     v = const_int(2);
  1246.     rw = rwreg_int(0);
  1247.  
  1248.     OUT = 0x81;
  1249.         OUT = 0xE8|rw;
  1250.     OUT = v & 0xff;
  1251.     OUT = (v >> 8) & 0xff;
  1252.     OUT = (v >> 16) & 0xff;
  1253.     OUT = (v >> 24) & 0xff;
  1254.  
  1255.     debug(("subl #%d,%s\n", v, regname(rw)));
  1256. }
  1257.  
  1258. define_insn(load_int_addregconst, load_RRC)
  1259. {
  1260.     int v = const_int(2);
  1261.     int r = rreg_int(1);
  1262.     int w = wreg_int(0);
  1263.  
  1264.     assert(r != REG_esp);
  1265.     OUT = 0x8B; 
  1266.     OUT = 0x80|(w<<3)|r;
  1267.     OUT = v & 0xff;
  1268.     OUT = (v >> 8) & 0xff;
  1269.     OUT = (v >> 16) & 0xff;
  1270.     OUT = (v >> 24) & 0xff;
  1271.  
  1272.     debug(("movl %d(%s),%s\n", o, regname(r), regname(w)));
  1273. }
  1274.  
  1275. define_insn(load_byte, loadb_RxR)
  1276. {
  1277.     int r = rreg_int(2);
  1278.     int w = wreg_int(0);
  1279.  
  1280.     OUT = 0x0F;
  1281.     OUT = 0xBE;
  1282.     OUT = 0x00|(w<<3)|r;
  1283.     if (r == REG_esp) {
  1284.         OUT = 0x20|REG_esp;
  1285.     }
  1286.  
  1287.     debug(("movsb (%s),%s\n", regname(r), regname(w)));
  1288. }
  1289.  
  1290. define_insn(load_char, loadc_RxR)
  1291. {
  1292.     int r = rreg_int(2);
  1293.     int w = wreg_int(0);
  1294.  
  1295.     OUT = 0x0F;
  1296.     OUT = 0xB6;
  1297.     OUT = 0x00|(w<<3)|r;
  1298.     if (r == REG_esp) {
  1299.         OUT = 0x20|REG_esp;
  1300.     }
  1301.  
  1302.     debug(("movzb (%s),%s\n", regname(r), regname(w)));
  1303. }
  1304.  
  1305. define_insn(load_short, loads_RxR)
  1306. {
  1307.     int r = rreg_int(2);
  1308.     int w = wreg_int(0);
  1309.  
  1310.     OUT = 0x0F;
  1311.     OUT = 0xBF;
  1312.     OUT = 0x00|(w<<3)|r;
  1313.     if (r == REG_esp) {
  1314.         OUT = 0x20|REG_esp;
  1315.     }
  1316.  
  1317.     debug(("movsw (%s),%s\n", regname(r), regname(w)));
  1318. }
  1319.  
  1320. define_insn(store_int_addregconst, store_xRRC)
  1321. {
  1322.     int v;
  1323.     int r1;
  1324.     int r0;
  1325.  
  1326.     r0 = rreg_int(2);
  1327.     s = seq_seq(s, 1);
  1328.     assert(s->ref == 0);
  1329.     v = const_int(2);
  1330.     r1 = rreg_int(1);
  1331.  
  1332.     assert(r0 != REG_esp);
  1333.     OUT = 0x89; 
  1334.     OUT = 0x80|(r0<<3)|r1;
  1335.     OUT = v & 0xff;
  1336.     OUT = (v >> 8) & 0xff;
  1337.     OUT = (v >> 16) & 0xff;
  1338.     OUT = (v >> 24) & 0xff;
  1339.  
  1340.     debug(("movl %s,%d(%s)\n", regname(r0), v, regname(r1)));
  1341. }
  1342.  
  1343. define_insn(store_byte, storeb_xRR)
  1344. {
  1345.     int r = rreg_int(2);
  1346.     int w = rreg_int(1);
  1347.  
  1348.     OUT = 0x88;
  1349.     OUT = 0x00|(r<<3)|w;
  1350.     if (w == REG_esp) {
  1351.         OUT = 0x20|REG_esp;
  1352.     }
  1353.  
  1354.     debug(("movb %s,(%s)\n", regname(r), regname(w)));
  1355. }
  1356.  
  1357. define_insn(store_short, stores_xRR)
  1358. {
  1359.     int r = rreg_int(2);
  1360.     int w = rreg_int(1);
  1361.  
  1362.     OUT = 0x66;
  1363.     OUT = 0x89;
  1364.     OUT = 0x00|(r<<3)|w;
  1365.     if (w == REG_esp) {
  1366.         OUT = 0x20|REG_esp;
  1367.     }
  1368.  
  1369.     debug(("movw %s,(%s)\n", regname(r), regname(w)));
  1370. }
  1371.  
  1372. define_insn(cmp_int_const, cmp_xRC)
  1373. {
  1374.     int r1 = rreg_int(1);
  1375.     int v = const_int(2);
  1376.  
  1377.     OUT = 0x81;
  1378.         OUT = 0xF8|r1;
  1379.     OUT = v & 0xff;
  1380.     OUT = (v >> 8) & 0xff;
  1381.     OUT = (v >> 16) & 0xff;
  1382.     OUT = (v >> 24) & 0xff;
  1383.  
  1384.     debug(("cmpl #%d,%s\n", v, regname(r1)));
  1385. }
  1386.  
  1387. define_insn(push_int_const, push_xxC)
  1388. {
  1389.     int v = const_int(2);
  1390.  
  1391.     OUT = 0x68;
  1392.     OUT = v & 0xff;
  1393.     OUT = (v >> 8) & 0xff;
  1394.     OUT = (v >> 16) & 0xff;
  1395.     OUT = (v >> 24) & 0xff;
  1396.  
  1397.     debug(("pushl #%d\n", v));
  1398. }
  1399.  
  1400. define_insn(lshl_int_const, lshl_RRC)
  1401. {
  1402.     int rw;
  1403.     int v;
  1404.  
  1405.     check_reg_01();
  1406.  
  1407.     rw = rreg_int(0);
  1408.     v = const_int(2);
  1409.  
  1410.     assert(v < 256);
  1411.  
  1412.     OUT = 0xC1;
  1413.         OUT = 0xE0|rw;
  1414.     OUT = v
  1415.  
  1416.     debug(("shll #%d,%s\n", v, regname(rw)));
  1417. }
  1418.