github.com/goccy/go-jit@v0.0.0-20200514131505-ff78d45cf6af/internal/ccall/jit-rules-x86.c (about) 1 /* 2 * jit-rules-x86.c - Rules that define the characteristics of the x86. 3 * 4 * Copyright (C) 2004 Southern Storm Software, Pty Ltd. 5 * 6 * This file is part of the libjit library. 7 * 8 * The libjit library is free software: you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public License 10 * as published by the Free Software Foundation, either version 2.1 of 11 * the License, or (at your option) any later version. 12 * 13 * The libjit library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with the libjit library. If not, see 20 * <http://www.gnu.org/licenses/>. 21 */ 22 23 #include "jit-internal.h" 24 #include "jit-rules.h" 25 #include "jit-apply-rules.h" 26 27 #if defined(JIT_BACKEND_X86) 28 29 #include "jit-gen-x86.h" 30 #include "jit-reg-alloc.h" 31 #include "jit-setjmp.h" 32 #include <stdio.h> 33 34 /* 35 * Pseudo register numbers for the x86 registers. These are not the 36 * same as the CPU instruction register numbers. The order of these 37 * values must match the order in "JIT_REG_INFO". 38 */ 39 #define X86_REG_EAX 0 40 #define X86_REG_ECX 1 41 #define X86_REG_EDX 2 42 #define X86_REG_EBX 3 43 #define X86_REG_ESI 4 44 #define X86_REG_EDI 5 45 #define X86_REG_EBP 6 46 #define X86_REG_ESP 7 47 #define X86_REG_ST0 8 48 #define X86_REG_ST1 9 49 #define X86_REG_ST2 10 50 #define X86_REG_ST3 11 51 #define X86_REG_ST4 12 52 #define X86_REG_ST5 13 53 #define X86_REG_ST6 14 54 #define X86_REG_ST7 15 55 56 /* 57 * Determine if a pseudo register number is word-based or float-based. 58 */ 59 #define IS_WORD_REG(reg) ((reg) < X86_REG_ST0) 60 #define IS_FLOAT_REG(reg) ((reg) >= X86_REG_ST0) 61 62 /* 63 * Round a size up to a multiple of the stack word size. 64 */ 65 #define ROUND_STACK(size) \ 66 (((size) + (sizeof(void *) - 1)) & ~(sizeof(void *) - 1)) 67 68 static _jit_regclass_t *x86_reg; 69 static _jit_regclass_t *x86_breg; 70 static _jit_regclass_t *x86_freg; 71 static _jit_regclass_t *x86_lreg; 72 73 void _jit_init_backend(void) 74 { 75 x86_reg = _jit_regclass_create( 76 "reg", JIT_REG_WORD, 6, 77 X86_REG_EAX, X86_REG_ECX, 78 X86_REG_EDX, X86_REG_EBX, 79 X86_REG_ESI, X86_REG_EDI); 80 81 x86_breg = _jit_regclass_create( 82 "breg", JIT_REG_WORD, 4, 83 X86_REG_EAX, X86_REG_ECX, 84 X86_REG_EDX, X86_REG_EBX); 85 86 x86_freg = _jit_regclass_create( 87 "freg", JIT_REG_X86_FLOAT | JIT_REG_IN_STACK, 8, 88 X86_REG_ST0, X86_REG_ST1, 89 X86_REG_ST2, X86_REG_ST3, 90 X86_REG_ST4, X86_REG_ST5, 91 X86_REG_ST6, X86_REG_ST7); 92 93 x86_lreg = _jit_regclass_create( 94 "lreg", JIT_REG_LONG, 2, 95 X86_REG_EAX, X86_REG_ECX); 96 } 97 98 void _jit_gen_get_elf_info(jit_elf_info_t *info) 99 { 100 #ifdef JIT_NATIVE_INT32 101 info->machine = 3; /* EM_386 */ 102 #else 103 info->machine = 62; /* EM_X86_64 */ 104 #endif 105 #if JIT_APPLY_X86_FASTCALL == 0 106 info->abi = 0; /* ELFOSABI_SYSV */ 107 #else 108 info->abi = 186; /* Private code, indicating STDCALL/FASTCALL support */ 109 #endif 110 info->abi_version = 0; 111 } 112 113 int _jit_setup_indirect_pointer(jit_function_t func, jit_value_t value) 114 { 115 return jit_insn_outgoing_reg(func, value, X86_REG_EAX); 116 } 117 118 int _jit_create_call_return_insns 119 (jit_function_t func, jit_type_t signature, 120 jit_value_t *args, unsigned int num_args, 121 jit_value_t return_value, int is_nested) 122 { 123 jit_nint pop_bytes; 124 unsigned int size; 125 jit_type_t return_type; 126 int ptr_return; 127 128 /* Calculate the number of bytes that we need to pop */ 129 return_type = jit_type_normalize(jit_type_get_return(signature)); 130 ptr_return = jit_type_return_via_pointer(return_type); 131 #if JIT_APPLY_X86_FASTCALL == 1 132 if(jit_type_get_abi(signature) == jit_abi_stdcall || 133 jit_type_get_abi(signature) == jit_abi_fastcall) 134 { 135 /* STDCALL and FASTCALL functions pop their own arguments */ 136 pop_bytes = 0; 137 } 138 else 139 #endif 140 { 141 pop_bytes = 0; 142 while(num_args > 0) 143 { 144 --num_args; 145 size = jit_type_get_size(jit_value_get_type(args[num_args])); 146 pop_bytes += ROUND_STACK(size); 147 } 148 #if JIT_APPLY_X86_POP_STRUCT_RETURN == 1 149 if(ptr_return && is_nested) 150 { 151 /* Note: we only need this for nested functions, because 152 regular functions will pop the structure return for us */ 153 pop_bytes += sizeof(void *); 154 } 155 #else 156 if(ptr_return) 157 { 158 pop_bytes += sizeof(void *); 159 } 160 #endif 161 if(is_nested) 162 { 163 pop_bytes += sizeof(void *); 164 } 165 } 166 167 /* Pop the bytes from the system stack */ 168 if(pop_bytes > 0) 169 { 170 if(!jit_insn_defer_pop_stack(func, pop_bytes)) 171 { 172 return 0; 173 } 174 } 175 176 /* Bail out now if we don't need to worry about return values */ 177 if(!return_value || ptr_return) 178 { 179 return 1; 180 } 181 182 /* Structure values must be flushed into the frame, and 183 everything else ends up in a register */ 184 if(jit_type_is_struct(return_type) || jit_type_is_union(return_type)) 185 { 186 if(!jit_insn_flush_struct(func, return_value)) 187 { 188 return 0; 189 } 190 } 191 else if(return_type == jit_type_float32 || 192 return_type == jit_type_float64 || 193 return_type == jit_type_nfloat) 194 { 195 if(!jit_insn_return_reg(func, return_value, X86_REG_ST0)) 196 { 197 return 0; 198 } 199 } 200 else if(return_type->kind != JIT_TYPE_VOID) 201 { 202 if(!jit_insn_return_reg(func, return_value, X86_REG_EAX)) 203 { 204 return 0; 205 } 206 } 207 208 /* Everything is back where it needs to be */ 209 return 1; 210 } 211 212 int _jit_opcode_is_supported(int opcode) 213 { 214 switch(opcode) 215 { 216 #define JIT_INCLUDE_SUPPORTED 217 #include "jit-rules-x86.inc" 218 #undef JIT_INCLUDE_SUPPORTED 219 } 220 return 0; 221 } 222 223 void *_jit_gen_prolog(jit_gencode_t gen, jit_function_t func, void *buf) 224 { 225 unsigned char prolog[JIT_PROLOG_SIZE]; 226 unsigned char *inst = prolog; 227 int reg; 228 229 /* Push ebp onto the stack */ 230 x86_push_reg(inst, X86_EBP); 231 232 /* Initialize EBP for the current frame */ 233 x86_mov_reg_reg(inst, X86_EBP, X86_ESP, sizeof(void *)); 234 235 /* Allocate space for the local variable frame */ 236 if(func->builder->frame_size > 0) 237 { 238 x86_alu_reg_imm(inst, X86_SUB, X86_ESP, 239 (int)(func->builder->frame_size)); 240 } 241 242 /* Save registers that we need to preserve */ 243 for(reg = 0; reg <= 7; ++reg) 244 { 245 if(jit_reg_is_used(gen->touched, reg) && 246 (_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0) 247 { 248 x86_push_reg(inst, _jit_reg_info[reg].cpu_reg); 249 } 250 } 251 252 /* Copy the prolog into place and return the adjusted entry position */ 253 reg = (int)(inst - prolog); 254 jit_memcpy(((unsigned char *)buf) + JIT_PROLOG_SIZE - reg, prolog, reg); 255 return (void *)(((unsigned char *)buf) + JIT_PROLOG_SIZE - reg); 256 } 257 258 void _jit_gen_epilog(jit_gencode_t gen, jit_function_t func) 259 { 260 jit_nint pop_bytes = 0; 261 int reg, offset; 262 unsigned char *inst; 263 int struct_return_offset = 0; 264 void **fixup; 265 void **next; 266 267 /* Check if there is sufficient space for the epilog */ 268 _jit_gen_check_space(gen, 48); 269 270 #if JIT_APPLY_X86_FASTCALL == 1 271 /* Determine the number of parameter bytes to pop when we return */ 272 { 273 jit_type_t signature; 274 unsigned int num_params; 275 unsigned int param; 276 signature = func->signature; 277 if(jit_type_get_abi(signature) == jit_abi_stdcall || 278 jit_type_get_abi(signature) == jit_abi_fastcall) 279 { 280 if(func->nested_parent) 281 { 282 pop_bytes += sizeof(void *); 283 } 284 if(jit_type_return_via_pointer(jit_type_get_return(signature))) 285 { 286 struct_return_offset = 2 * sizeof(void *) + pop_bytes; 287 pop_bytes += sizeof(void *); 288 } 289 num_params = jit_type_num_params(signature); 290 for(param = 0; param < num_params; ++param) 291 { 292 pop_bytes += ROUND_STACK 293 (jit_type_get_size 294 (jit_type_get_param(signature, param))); 295 } 296 if(jit_type_get_abi(signature) == jit_abi_fastcall) 297 { 298 /* The first two words are in fastcall registers */ 299 if(pop_bytes > (2 * sizeof(void *))) 300 { 301 pop_bytes -= 2 * sizeof(void *); 302 } 303 else 304 { 305 pop_bytes = 0; 306 } 307 struct_return_offset = 0; 308 } 309 } 310 else if(!(func->nested_parent) && 311 jit_type_return_via_pointer(jit_type_get_return(signature))) 312 { 313 #if JIT_APPLY_X86_POP_STRUCT_RETURN == 1 314 pop_bytes += sizeof(void *); 315 #endif 316 struct_return_offset = 2 * sizeof(void *); 317 } 318 } 319 #else 320 { 321 /* We only need to pop structure pointers in non-nested functions */ 322 jit_type_t signature; 323 signature = func->signature; 324 if(!(func->nested_parent) && 325 jit_type_return_via_pointer(jit_type_get_return(signature))) 326 { 327 #if JIT_APPLY_X86_POP_STRUCT_RETURN == 1 328 pop_bytes += sizeof(void *); 329 #endif 330 struct_return_offset = 2 * sizeof(void *); 331 } 332 } 333 #endif 334 335 /* Perform fixups on any blocks that jump to the epilog */ 336 inst = gen->ptr; 337 fixup = (void **)(gen->epilog_fixup); 338 while(fixup != 0) 339 { 340 next = (void **)(fixup[0]); 341 fixup[0] = (void *)(((jit_nint)inst) - ((jit_nint)fixup) - 4); 342 fixup = next; 343 } 344 gen->epilog_fixup = 0; 345 346 /* If we are returning a structure via a pointer, then copy 347 the pointer value into EAX when we return */ 348 if(struct_return_offset != 0) 349 { 350 x86_mov_reg_membase(inst, X86_EAX, X86_EBP, struct_return_offset, 4); 351 } 352 353 /* Restore the callee save registers that we used */ 354 if(gen->stack_changed) 355 { 356 offset = -(func->builder->frame_size); 357 for(reg = 0; reg <= 7; ++reg) 358 { 359 if(jit_reg_is_used(gen->touched, reg) && 360 (_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0) 361 { 362 offset -= sizeof(void *); 363 x86_mov_reg_membase(inst, _jit_reg_info[reg].cpu_reg, 364 X86_EBP, offset, sizeof(void *)); 365 } 366 } 367 } 368 else 369 { 370 for(reg = 7; reg >= 0; --reg) 371 { 372 if(jit_reg_is_used(gen->touched, reg) && 373 (_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0) 374 { 375 x86_pop_reg(inst, _jit_reg_info[reg].cpu_reg); 376 } 377 } 378 } 379 380 /* Pop the stack frame and restore the saved copy of ebp */ 381 if(gen->stack_changed || func->builder->frame_size > 0) 382 { 383 x86_mov_reg_reg(inst, X86_ESP, X86_EBP, sizeof(void *)); 384 } 385 x86_pop_reg(inst, X86_EBP); 386 387 /* Return from the current function */ 388 if(pop_bytes > 0) 389 { 390 x86_ret_imm(inst, pop_bytes); 391 } 392 else 393 { 394 x86_ret(inst); 395 } 396 gen->ptr = inst; 397 } 398 399 #if 0 400 /* 401 * The x86 backend does not need this function because it uses 402 * _jit_create_indirector() instead. 403 */ 404 void *_jit_gen_redirector(jit_gencode_t gen, jit_function_t func) 405 { 406 void *ptr, *entry; 407 _jit_gen_check_space(gen, 8); 408 ptr = (void *)&(func->entry_point); 409 entry = gen->ptr; 410 x86_jump_mem(gen->ptr, ptr); 411 return entry; 412 } 413 #endif 414 415 /* 416 * Setup or teardown the x86 code output process. 417 */ 418 #define jit_cache_setup_output(needed) \ 419 unsigned char *inst = gen->ptr; \ 420 _jit_gen_check_space(gen, (needed)) 421 422 #define jit_cache_end_output() \ 423 gen->ptr = inst 424 425 /* 426 * Get a temporary register that isn't one of the specified registers. 427 */ 428 static int get_temp_reg(int reg1, int reg2, int reg3) 429 { 430 if(reg1 != X86_EAX && reg2 != X86_EAX && reg3 != X86_EAX) 431 { 432 return X86_EAX; 433 } 434 if(reg1 != X86_EDX && reg2 != X86_EDX && reg3 != X86_EDX) 435 { 436 return X86_EDX; 437 } 438 if(reg1 != X86_ECX && reg2 != X86_ECX && reg3 != X86_ECX) 439 { 440 return X86_ECX; 441 } 442 if(reg1 != X86_EBX && reg2 != X86_EBX && reg3 != X86_EBX) 443 { 444 return X86_EBX; 445 } 446 if(reg1 != X86_ESI && reg2 != X86_ESI && reg3 != X86_ESI) 447 { 448 return X86_ESI; 449 } 450 return X86_EDI; 451 } 452 453 /* 454 * Store a byte value to a membase address. 455 */ 456 static unsigned char *mov_membase_reg_byte 457 (unsigned char *inst, int basereg, int offset, int srcreg) 458 { 459 if(srcreg == X86_EAX || srcreg == X86_EBX || 460 srcreg == X86_ECX || srcreg == X86_EDX) 461 { 462 x86_mov_membase_reg(inst, basereg, offset, srcreg, 1); 463 } 464 else if(basereg != X86_EAX) 465 { 466 x86_push_reg(inst, X86_EAX); 467 x86_mov_reg_reg(inst, X86_EAX, srcreg, 4); 468 x86_mov_membase_reg(inst, basereg, offset, X86_EAX, 1); 469 x86_pop_reg(inst, X86_EAX); 470 } 471 else 472 { 473 x86_push_reg(inst, X86_EDX); 474 x86_mov_reg_reg(inst, X86_EDX, srcreg, 4); 475 x86_mov_membase_reg(inst, basereg, offset, X86_EDX, 1); 476 x86_pop_reg(inst, X86_EDX); 477 } 478 return inst; 479 } 480 481 /* 482 * Store a small structure from registers to a pointer. The base 483 * register must not be either "reg" or "other_reg". 484 */ 485 static unsigned char *store_small_struct 486 (unsigned char *inst, int reg, int other_reg, 487 int base_reg, jit_nint offset, jit_nint size, int preserve) 488 { 489 switch(size) 490 { 491 case 1: 492 { 493 inst = mov_membase_reg_byte(inst, base_reg, offset, reg); 494 } 495 break; 496 497 case 2: 498 { 499 x86_mov_membase_reg(inst, base_reg, offset, reg, 2); 500 } 501 break; 502 503 case 3: 504 { 505 if(preserve) 506 { 507 x86_push_reg(inst, reg); 508 } 509 x86_mov_membase_reg(inst, base_reg, offset, reg, 2); 510 x86_shift_reg_imm(inst, reg, X86_SHR, 16); 511 inst = mov_membase_reg_byte(inst, base_reg, offset + 2, reg); 512 if(preserve) 513 { 514 x86_pop_reg(inst, reg); 515 } 516 } 517 break; 518 519 case 4: 520 { 521 x86_mov_membase_reg(inst, base_reg, offset, reg, 4); 522 } 523 break; 524 525 case 5: 526 { 527 x86_mov_membase_reg(inst, base_reg, offset, reg, 4); 528 inst = mov_membase_reg_byte(inst, base_reg, offset + 4, other_reg); 529 } 530 break; 531 532 case 6: 533 { 534 x86_mov_membase_reg(inst, base_reg, offset, reg, 4); 535 x86_mov_membase_reg(inst, base_reg, offset + 4, other_reg, 2); 536 } 537 break; 538 539 case 7: 540 { 541 if(preserve) 542 { 543 x86_push_reg(inst, other_reg); 544 } 545 x86_mov_membase_reg(inst, base_reg, offset, reg, 4); 546 x86_mov_membase_reg(inst, base_reg, offset + 4, other_reg, 2); 547 x86_shift_reg_imm(inst, other_reg, X86_SHR, 16); 548 inst = mov_membase_reg_byte(inst, base_reg, offset + 6, other_reg); 549 if(preserve) 550 { 551 x86_pop_reg(inst, other_reg); 552 } 553 } 554 break; 555 556 case 8: 557 { 558 x86_mov_membase_reg(inst, base_reg, offset, reg, 4); 559 x86_mov_membase_reg(inst, base_reg, offset + 4, other_reg, 4); 560 } 561 break; 562 } 563 return inst; 564 } 565 566 void _jit_gen_spill_reg(jit_gencode_t gen, int reg, 567 int other_reg, jit_value_t value) 568 { 569 int offset; 570 571 /* Make sure that we have sufficient space */ 572 jit_cache_setup_output(16); 573 574 /* If the value is associated with a global register, then copy to that */ 575 if(value->has_global_register) 576 { 577 reg = _jit_reg_info[reg].cpu_reg; 578 other_reg = _jit_reg_info[value->global_reg].cpu_reg; 579 x86_mov_reg_reg(inst, other_reg, reg, sizeof(void *)); 580 jit_cache_end_output(); 581 return; 582 } 583 584 /* Fix the value in place within the local variable frame */ 585 _jit_gen_fix_value(value); 586 587 /* Output an appropriate instruction to spill the value */ 588 offset = (int)(value->frame_offset); 589 if(IS_WORD_REG(reg)) 590 { 591 /* Spill a word register. If the value is smaller than a word, 592 then we write the entire word. The local stack frame is 593 allocated such that the extra bytes will be simply ignored */ 594 reg = _jit_reg_info[reg].cpu_reg; 595 x86_mov_membase_reg(inst, X86_EBP, offset, reg, 4); 596 if(other_reg != -1) 597 { 598 /* Spill the other word register in a pair */ 599 reg = _jit_reg_info[other_reg].cpu_reg; 600 offset += sizeof(void *); 601 x86_mov_membase_reg(inst, X86_EBP, offset, reg, 4); 602 } 603 } 604 else 605 { 606 /* Spill the top of the floating-point register stack */ 607 switch(jit_type_normalize(value->type)->kind) 608 { 609 case JIT_TYPE_FLOAT32: 610 { 611 x86_fst_membase(inst, X86_EBP, offset, 0, 1); 612 } 613 break; 614 615 case JIT_TYPE_FLOAT64: 616 { 617 x86_fst_membase(inst, X86_EBP, offset, 1, 1); 618 } 619 break; 620 621 case JIT_TYPE_NFLOAT: 622 { 623 x86_fst80_membase(inst, X86_EBP, offset); 624 } 625 break; 626 } 627 } 628 629 /* End the code output process */ 630 jit_cache_end_output(); 631 } 632 633 void 634 _jit_gen_free_reg(jit_gencode_t gen, int reg, int other_reg, int value_used) 635 { 636 /* We only need to take explicit action if we are freeing a 637 floating-point register whose value hasn't been used yet */ 638 if(!value_used && IS_FLOAT_REG(reg)) 639 { 640 _jit_gen_check_space(gen, 2); 641 x86_fstp(gen->ptr, reg - X86_REG_ST0); 642 } 643 } 644 645 static int 646 fp_stack_index(jit_gencode_t gen, int reg) 647 { 648 return gen->reg_stack_top - reg - 1; 649 } 650 651 void 652 _jit_gen_exch_top(jit_gencode_t gen, int reg) 653 { 654 if(IS_FLOAT_REG(reg)) 655 { 656 jit_cache_setup_output(2); 657 x86_fxch(inst, fp_stack_index(gen, reg)); 658 jit_cache_end_output(); 659 } 660 } 661 662 void 663 _jit_gen_move_top(jit_gencode_t gen, int reg) 664 { 665 if(IS_FLOAT_REG(reg)) 666 { 667 jit_cache_setup_output(2); 668 x86_fstp(inst, fp_stack_index(gen, reg)); 669 jit_cache_end_output(); 670 } 671 } 672 673 void 674 _jit_gen_spill_top(jit_gencode_t gen, int reg, jit_value_t value, int pop) 675 { 676 int offset; 677 if(IS_FLOAT_REG(reg)) 678 { 679 /* Make sure that we have sufficient space */ 680 jit_cache_setup_output(16); 681 682 /* Fix the value in place within the local variable frame */ 683 _jit_gen_fix_value(value); 684 685 /* Output an appropriate instruction to spill the value */ 686 offset = (int)(value->frame_offset); 687 688 /* Spill the top of the floating-point register stack */ 689 switch(jit_type_normalize(value->type)->kind) 690 { 691 case JIT_TYPE_FLOAT32: 692 { 693 x86_fst_membase(inst, X86_EBP, offset, 0, pop); 694 } 695 break; 696 697 case JIT_TYPE_FLOAT64: 698 { 699 x86_fst_membase(inst, X86_EBP, offset, 1, pop); 700 } 701 break; 702 703 case JIT_TYPE_NFLOAT: 704 { 705 x86_fst80_membase(inst, X86_EBP, offset); 706 if(!pop) 707 { 708 x86_fld80_membase(inst, X86_EBP, offset); 709 } 710 } 711 break; 712 } 713 714 /* End the code output process */ 715 jit_cache_end_output(); 716 } 717 } 718 719 void 720 _jit_gen_load_value(jit_gencode_t gen, int reg, int other_reg, jit_value_t value) 721 { 722 jit_type_t type; 723 int src_reg, other_src_reg; 724 void *ptr; 725 int offset; 726 727 /* Make sure that we have sufficient space */ 728 jit_cache_setup_output(16); 729 730 type = jit_type_normalize(value->type); 731 732 /* Load zero */ 733 if(value->is_constant) 734 { 735 switch(type->kind) 736 { 737 case JIT_TYPE_SBYTE: 738 case JIT_TYPE_UBYTE: 739 case JIT_TYPE_SHORT: 740 case JIT_TYPE_USHORT: 741 case JIT_TYPE_INT: 742 case JIT_TYPE_UINT: 743 { 744 if((jit_nint)(value->address) == 0) 745 { 746 x86_clear_reg(inst, _jit_reg_info[reg].cpu_reg); 747 } 748 else 749 { 750 x86_mov_reg_imm(inst, _jit_reg_info[reg].cpu_reg, 751 (jit_nint)(value->address)); 752 } 753 } 754 break; 755 756 case JIT_TYPE_LONG: 757 case JIT_TYPE_ULONG: 758 { 759 jit_long long_value; 760 long_value = jit_value_get_long_constant(value); 761 if(long_value == 0) 762 { 763 #ifdef JIT_NATIVE_INT64 764 x86_clear_reg(inst, _jit_reg_info[reg].cpu_reg); 765 #else 766 x86_clear_reg(inst, _jit_reg_info[reg].cpu_reg); 767 x86_clear_reg(inst, _jit_reg_info[other_reg].cpu_reg); 768 #endif 769 } 770 else 771 { 772 #ifdef JIT_NATIVE_INT64 773 x86_mov_reg_imm(inst, _jit_reg_info[reg].cpu_reg, 774 (jit_nint)long_value); 775 #else 776 x86_mov_reg_imm(inst, _jit_reg_info[reg].cpu_reg, 777 (jit_int)long_value); 778 x86_mov_reg_imm(inst, _jit_reg_info[other_reg].cpu_reg, 779 (jit_int)(long_value >> 32)); 780 #endif 781 } 782 } 783 break; 784 785 case JIT_TYPE_FLOAT32: 786 { 787 jit_float32 float32_value; 788 float32_value = jit_value_get_float32_constant(value); 789 if(IS_WORD_REG(reg)) 790 { 791 union 792 { 793 jit_float32 float32_value; 794 jit_int int_value; 795 } un; 796 797 un.float32_value = float32_value; 798 x86_mov_reg_imm(inst, _jit_reg_info[reg].cpu_reg, un.int_value); 799 } 800 else 801 { 802 if(float32_value == (jit_float32) 0.0) 803 { 804 x86_fldz(inst); 805 } 806 else if(float32_value == (jit_float32) 1.0) 807 { 808 x86_fld1(inst); 809 } 810 else 811 { 812 ptr = _jit_gen_alloc(gen, sizeof(jit_float32)); 813 jit_memcpy(ptr, &float32_value, sizeof(float32_value)); 814 x86_fld(inst, ptr, 0); 815 } 816 } 817 } 818 break; 819 820 case JIT_TYPE_FLOAT64: 821 { 822 jit_float64 float64_value; 823 float64_value = jit_value_get_float64_constant(value); 824 if(IS_WORD_REG(reg)) 825 { 826 union 827 { 828 jit_float64 float64_value; 829 jit_int int_value[2]; 830 } un; 831 832 un.float64_value = float64_value; 833 x86_mov_reg_imm(inst, _jit_reg_info[reg].cpu_reg, 834 un.int_value[0]); 835 x86_mov_reg_imm(inst, _jit_reg_info[other_reg].cpu_reg, 836 un.int_value[1]); 837 } 838 else 839 { 840 if(float64_value == (jit_float64) 0.0) 841 { 842 x86_fldz(inst); 843 } 844 else if(float64_value == (jit_float64) 1.0) 845 { 846 x86_fld1(inst); 847 } 848 else 849 { 850 ptr = _jit_gen_alloc(gen, sizeof(jit_float64)); 851 jit_memcpy(ptr, &float64_value, sizeof(float64_value)); 852 x86_fld(inst, ptr, 1); 853 } 854 } 855 } 856 break; 857 858 case JIT_TYPE_NFLOAT: 859 { 860 jit_nfloat nfloat_value; 861 nfloat_value = jit_value_get_nfloat_constant(value); 862 if(IS_WORD_REG(reg) && sizeof(jit_nfloat) == sizeof(jit_float64)) 863 { 864 union 865 { 866 jit_nfloat nfloat_value; 867 jit_int int_value[2]; 868 } un; 869 870 un.nfloat_value = nfloat_value; 871 x86_mov_reg_imm(inst, _jit_reg_info[reg].cpu_reg, 872 un.int_value[0]); 873 x86_mov_reg_imm(inst, _jit_reg_info[other_reg].cpu_reg, 874 un.int_value[1]); 875 } 876 else 877 { 878 if(nfloat_value == (jit_nfloat) 0.0) 879 { 880 x86_fldz(inst); 881 } 882 else if(nfloat_value == (jit_nfloat) 1.0) 883 { 884 x86_fld1(inst); 885 } 886 else 887 { 888 ptr = _jit_gen_alloc(gen, sizeof(jit_nfloat)); 889 jit_memcpy(ptr, &nfloat_value, sizeof(nfloat_value)); 890 if(sizeof(jit_nfloat) == sizeof(jit_float64)) 891 { 892 x86_fld(inst, ptr, 1); 893 } 894 else 895 { 896 x86_fld80_mem(inst, ptr); 897 } 898 } 899 } 900 } 901 break; 902 } 903 } 904 else if(value->in_register || value->in_global_register) 905 { 906 if(value->in_register) 907 { 908 src_reg = value->reg; 909 if(other_reg >= 0) 910 { 911 other_src_reg = jit_reg_other_reg(src_reg); 912 } 913 else 914 { 915 other_src_reg = -1; 916 } 917 } 918 else 919 { 920 src_reg = value->global_reg; 921 other_src_reg = -1; 922 } 923 924 switch(type->kind) 925 { 926 #if 0 927 case JIT_TYPE_SBYTE: 928 { 929 x86_widen_reg(inst, _jit_reg_info[reg].cpu_reg, 930 _jit_reg_info[src_reg].cpu_reg, 1, 0); 931 } 932 break; 933 934 case JIT_TYPE_UBYTE: 935 { 936 x86_widen_reg(inst, _jit_reg_info[reg].cpu_reg, 937 _jit_reg_info[src_reg].cpu_reg, 0, 0); 938 } 939 break; 940 941 case JIT_TYPE_SHORT: 942 { 943 x86_widen_reg(inst, _jit_reg_info[reg].cpu_reg, 944 _jit_reg_info[src_reg].cpu_reg, 1, 1); 945 } 946 break; 947 948 case JIT_TYPE_USHORT: 949 { 950 x86_widen_reg(inst, _jit_reg_info[reg].cpu_reg, 951 _jit_reg_info[src_reg].cpu_reg, 0, 1); 952 } 953 break; 954 #else 955 case JIT_TYPE_SBYTE: 956 case JIT_TYPE_UBYTE: 957 case JIT_TYPE_SHORT: 958 case JIT_TYPE_USHORT: 959 #endif 960 case JIT_TYPE_INT: 961 case JIT_TYPE_UINT: 962 { 963 x86_mov_reg_reg(inst, _jit_reg_info[reg].cpu_reg, 964 _jit_reg_info[src_reg].cpu_reg, 4); 965 } 966 break; 967 968 case JIT_TYPE_LONG: 969 case JIT_TYPE_ULONG: 970 { 971 #ifdef JIT_NATIVE_INT64 972 x86_mov_reg_reg(inst, _jit_reg_info[reg].cpu_reg, 973 _jit_reg_info[src_reg].cpu_reg, 8); 974 #else 975 x86_mov_reg_reg(inst, _jit_reg_info[reg].cpu_reg, 976 _jit_reg_info[src_reg].cpu_reg, 4); 977 x86_mov_reg_reg(inst, _jit_reg_info[other_reg].cpu_reg, 978 _jit_reg_info[other_src_reg].cpu_reg, 4); 979 #endif 980 } 981 break; 982 983 case JIT_TYPE_FLOAT32: 984 case JIT_TYPE_FLOAT64: 985 case JIT_TYPE_NFLOAT: 986 { 987 if(!IS_WORD_REG(reg)) 988 { 989 x86_fld_reg(inst, fp_stack_index(gen, src_reg)); 990 } 991 } 992 break; 993 } 994 } 995 else 996 { 997 /* Fix the position of the value in the stack frame */ 998 _jit_gen_fix_value(value); 999 offset = (int)(value->frame_offset); 1000 1001 /* Load the value into the specified register */ 1002 switch(type->kind) 1003 { 1004 case JIT_TYPE_SBYTE: 1005 { 1006 x86_widen_membase(inst, _jit_reg_info[reg].cpu_reg, 1007 X86_EBP, offset, 1, 0); 1008 } 1009 break; 1010 1011 case JIT_TYPE_UBYTE: 1012 { 1013 x86_widen_membase(inst, _jit_reg_info[reg].cpu_reg, 1014 X86_EBP, offset, 0, 0); 1015 } 1016 break; 1017 1018 case JIT_TYPE_SHORT: 1019 { 1020 x86_widen_membase(inst, _jit_reg_info[reg].cpu_reg, 1021 X86_EBP, offset, 1, 1); 1022 } 1023 break; 1024 1025 case JIT_TYPE_USHORT: 1026 { 1027 x86_widen_membase(inst, _jit_reg_info[reg].cpu_reg, 1028 X86_EBP, offset, 0, 1); 1029 } 1030 break; 1031 1032 case JIT_TYPE_INT: 1033 case JIT_TYPE_UINT: 1034 { 1035 x86_mov_reg_membase(inst, _jit_reg_info[reg].cpu_reg, 1036 X86_EBP, offset, 4); 1037 } 1038 break; 1039 1040 case JIT_TYPE_LONG: 1041 case JIT_TYPE_ULONG: 1042 { 1043 #ifdef JIT_NATIVE_INT64 1044 x86_mov_reg_membase(inst, _jit_reg_info[reg].cpu_reg, 1045 X86_EBP, offset, 8); 1046 #else 1047 x86_mov_reg_membase(inst, _jit_reg_info[reg].cpu_reg, 1048 X86_EBP, offset, 4); 1049 x86_mov_reg_membase(inst, _jit_reg_info[other_reg].cpu_reg, 1050 X86_EBP, offset + 4, 4); 1051 #endif 1052 } 1053 break; 1054 1055 case JIT_TYPE_FLOAT32: 1056 { 1057 if(IS_WORD_REG(reg)) 1058 { 1059 x86_mov_reg_membase(inst, _jit_reg_info[reg].cpu_reg, 1060 X86_EBP, offset, 4); 1061 } 1062 else 1063 { 1064 x86_fld_membase(inst, X86_EBP, offset, 0); 1065 } 1066 } 1067 break; 1068 1069 case JIT_TYPE_FLOAT64: 1070 { 1071 if(IS_WORD_REG(reg)) 1072 { 1073 x86_mov_reg_membase(inst, _jit_reg_info[reg].cpu_reg, 1074 X86_EBP, offset, 4); 1075 x86_mov_reg_membase(inst, _jit_reg_info[other_reg].cpu_reg, 1076 X86_EBP, offset + 4, 4); 1077 } 1078 else 1079 { 1080 x86_fld_membase(inst, X86_EBP, offset, 1); 1081 } 1082 } 1083 break; 1084 1085 case JIT_TYPE_NFLOAT: 1086 { 1087 if(IS_WORD_REG(reg) && sizeof(jit_nfloat) == sizeof(jit_float64)) 1088 { 1089 x86_mov_reg_membase(inst, _jit_reg_info[reg].cpu_reg, 1090 X86_EBP, offset, 4); 1091 x86_mov_reg_membase(inst, _jit_reg_info[other_reg].cpu_reg, 1092 X86_EBP, offset + 4, 4); 1093 } 1094 else if(sizeof(jit_nfloat) == sizeof(jit_float64)) 1095 { 1096 x86_fld_membase(inst, X86_EBP, offset, 1); 1097 } 1098 else 1099 { 1100 x86_fld80_membase(inst, X86_EBP, offset); 1101 } 1102 } 1103 break; 1104 } 1105 } 1106 1107 /* End the code output process */ 1108 jit_cache_end_output(); 1109 } 1110 1111 void _jit_gen_spill_global(jit_gencode_t gen, int reg, jit_value_t value) 1112 { 1113 jit_cache_setup_output(16); 1114 if(value) 1115 { 1116 _jit_gen_fix_value(value); 1117 x86_mov_membase_reg(inst, 1118 X86_EBP, value->frame_offset, 1119 _jit_reg_info[value->global_reg].cpu_reg, sizeof(void *)); 1120 } 1121 else 1122 { 1123 x86_push_reg(inst, _jit_reg_info[reg].cpu_reg); 1124 } 1125 jit_cache_end_output(); 1126 } 1127 1128 void _jit_gen_load_global(jit_gencode_t gen, int reg, jit_value_t value) 1129 { 1130 jit_cache_setup_output(16); 1131 if(value) 1132 { 1133 x86_mov_reg_membase(inst, 1134 _jit_reg_info[value->global_reg].cpu_reg, 1135 X86_EBP, value->frame_offset, sizeof(void *)); 1136 } 1137 else 1138 { 1139 x86_pop_reg(inst, _jit_reg_info[reg].cpu_reg); 1140 } 1141 jit_cache_end_output(); 1142 } 1143 1144 void _jit_gen_fix_value(jit_value_t value) 1145 { 1146 if(!(value->has_frame_offset) && !(value->is_constant)) 1147 { 1148 jit_nint size = (jit_nint)(ROUND_STACK(jit_type_get_size(value->type))); 1149 value->block->func->builder->frame_size += size; 1150 value->frame_offset = -(value->block->func->builder->frame_size); 1151 value->has_frame_offset = 1; 1152 } 1153 } 1154 1155 /* 1156 * Set a register value based on a condition code. 1157 */ 1158 static unsigned char *setcc_reg 1159 (unsigned char *inst, int reg, int cond, int is_signed) 1160 { 1161 if(reg == X86_EAX || reg == X86_EBX || reg == X86_ECX || reg == X86_EDX) 1162 { 1163 /* Use a SETcc instruction if we have a basic register */ 1164 x86_set_reg(inst, cond, reg, is_signed); 1165 x86_widen_reg(inst, reg, reg, 0, 0); 1166 } 1167 else 1168 { 1169 /* The register is not useable as an 8-bit destination */ 1170 unsigned char *patch1, *patch2; 1171 patch1 = inst; 1172 x86_branch8(inst, cond, 0, is_signed); 1173 x86_clear_reg(inst, reg); 1174 patch2 = inst; 1175 x86_jump8(inst, 0); 1176 x86_patch(patch1, inst); 1177 x86_mov_reg_imm(inst, reg, 1); 1178 x86_patch(patch2, inst); 1179 } 1180 return inst; 1181 } 1182 1183 /* 1184 * Get the long form of a branch opcode. 1185 */ 1186 static int long_form_branch(int opcode) 1187 { 1188 if(opcode == 0xEB) 1189 { 1190 return 0xE9; 1191 } 1192 else 1193 { 1194 return opcode + 0x0F10; 1195 } 1196 } 1197 1198 /* 1199 * Output a branch instruction. 1200 */ 1201 static unsigned char *output_branch 1202 (jit_function_t func, unsigned char *inst, int opcode, jit_insn_t insn) 1203 { 1204 jit_block_t block; 1205 int offset; 1206 if((insn->flags & JIT_INSN_VALUE1_IS_LABEL) != 0) 1207 { 1208 /* "address_of_label" instruction */ 1209 block = jit_block_from_label(func, (jit_label_t)(insn->value1)); 1210 } 1211 else 1212 { 1213 block = jit_block_from_label(func, (jit_label_t)(insn->dest)); 1214 } 1215 if(!block) 1216 { 1217 return inst; 1218 } 1219 if(block->address) 1220 { 1221 /* We already know the address of the block */ 1222 offset = ((unsigned char *)(block->address)) - (inst + 2); 1223 if(x86_is_imm8(offset)) 1224 { 1225 /* We can output a short-form backwards branch */ 1226 *inst++ = (unsigned char)opcode; 1227 *inst++ = (unsigned char)offset; 1228 } 1229 else 1230 { 1231 /* We need to output a long-form backwards branch */ 1232 offset -= 3; 1233 opcode = long_form_branch(opcode); 1234 if(opcode < 256) 1235 { 1236 *inst++ = (unsigned char)opcode; 1237 } 1238 else 1239 { 1240 *inst++ = (unsigned char)(opcode >> 8); 1241 *inst++ = (unsigned char)opcode; 1242 --offset; 1243 } 1244 x86_imm_emit32(inst, offset); 1245 } 1246 } 1247 else 1248 { 1249 /* Output a placeholder and record on the block's fixup list */ 1250 opcode = long_form_branch(opcode); 1251 if(opcode < 256) 1252 { 1253 *inst++ = (unsigned char)opcode; 1254 } 1255 else 1256 { 1257 *inst++ = (unsigned char)(opcode >> 8); 1258 *inst++ = (unsigned char)opcode; 1259 } 1260 x86_imm_emit32(inst, (int)(block->fixup_list)); 1261 block->fixup_list = (void *)(inst - 4); 1262 } 1263 return inst; 1264 } 1265 1266 /* 1267 * Jump to the current function's epilog. 1268 */ 1269 static unsigned char * 1270 jump_to_epilog(jit_gencode_t gen, unsigned char *inst, jit_block_t block) 1271 { 1272 /* If the epilog is the next thing that we will output, 1273 then fall through to the epilog directly */ 1274 if(_jit_block_is_final(block)) 1275 { 1276 return inst; 1277 } 1278 1279 /* Output a placeholder for the jump and add it to the fixup list */ 1280 *inst++ = (unsigned char)0xE9; 1281 x86_imm_emit32(inst, (int)(gen->epilog_fixup)); 1282 gen->epilog_fixup = (void *)(inst - 4); 1283 return inst; 1284 } 1285 1286 /* 1287 * Throw a builtin exception. 1288 */ 1289 static unsigned char * 1290 throw_builtin(unsigned char *inst, jit_function_t func, int type) 1291 { 1292 /* We need to update "catch_pc" if we have a "try" block */ 1293 if(func->builder->setjmp_value != 0) 1294 { 1295 _jit_gen_fix_value(func->builder->setjmp_value); 1296 if(func->builder->position_independent) 1297 { 1298 x86_call_imm(inst, 0); 1299 x86_pop_membase(inst, X86_EBP, 1300 func->builder->setjmp_value->frame_offset 1301 + jit_jmp_catch_pc_offset); 1302 } 1303 else 1304 { 1305 int pc = (int) inst; 1306 x86_mov_membase_imm(inst, X86_EBP, 1307 func->builder->setjmp_value->frame_offset 1308 + jit_jmp_catch_pc_offset, pc, 4); 1309 } 1310 } 1311 1312 /* Push the exception type onto the stack */ 1313 x86_push_imm(inst, type); 1314 1315 /* Call the "jit_exception_builtin" function, which will never return */ 1316 x86_call_code(inst, jit_exception_builtin); 1317 return inst; 1318 } 1319 1320 /* 1321 * Copy a block of memory that has a specific size. Other than 1322 * the parameter pointers, all registers must be unused at this point. 1323 */ 1324 static unsigned char *memory_copy 1325 (jit_gencode_t gen, unsigned char *inst, int dreg, jit_nint doffset, 1326 int sreg, jit_nint soffset, jit_nuint size) 1327 { 1328 int temp_reg = get_temp_reg(dreg, sreg, -1); 1329 if(size <= 4 * sizeof(void *)) 1330 { 1331 /* Use direct copies to copy the memory */ 1332 int offset = 0; 1333 while(size >= sizeof(void *)) 1334 { 1335 x86_mov_reg_membase(inst, temp_reg, sreg, 1336 soffset + offset, sizeof(void *)); 1337 x86_mov_membase_reg(inst, dreg, doffset + offset, 1338 temp_reg, sizeof(void *)); 1339 size -= sizeof(void *); 1340 offset += sizeof(void *); 1341 } 1342 #ifdef JIT_NATIVE_INT64 1343 if(size >= 4) 1344 { 1345 x86_mov_reg_membase(inst, temp_reg, sreg, soffset + offset, 4); 1346 x86_mov_membase_reg(inst, dreg, doffset + offset, temp_reg, 4); 1347 size -= 4; 1348 offset += 4; 1349 } 1350 #endif 1351 if(size >= 2) 1352 { 1353 x86_mov_reg_membase(inst, temp_reg, sreg, soffset + offset, 2); 1354 x86_mov_membase_reg(inst, dreg, doffset + offset, temp_reg, 2); 1355 size -= 2; 1356 offset += 2; 1357 } 1358 if(size >= 1) 1359 { 1360 /* We assume that temp_reg is EAX, ECX, or EDX, which it 1361 should be after calling "get_temp_reg" */ 1362 x86_mov_reg_membase(inst, temp_reg, sreg, soffset + offset, 1); 1363 x86_mov_membase_reg(inst, dreg, doffset + offset, temp_reg, 1); 1364 } 1365 } 1366 else 1367 { 1368 /* Call out to "jit_memcpy" to effect the copy */ 1369 x86_push_imm(inst, size); 1370 if(soffset == 0) 1371 { 1372 x86_push_reg(inst, sreg); 1373 } 1374 else 1375 { 1376 x86_lea_membase(inst, temp_reg, sreg, soffset); 1377 x86_push_reg(inst, temp_reg); 1378 } 1379 if(dreg != X86_ESP) 1380 { 1381 if(doffset == 0) 1382 { 1383 x86_push_reg(inst, dreg); 1384 } 1385 else 1386 { 1387 x86_lea_membase(inst, temp_reg, dreg, doffset); 1388 x86_push_reg(inst, temp_reg); 1389 } 1390 } 1391 else 1392 { 1393 /* Copying a structure value onto the stack */ 1394 x86_lea_membase(inst, temp_reg, X86_ESP, 1395 doffset + 2 * sizeof(void *)); 1396 x86_push_reg(inst, temp_reg); 1397 } 1398 x86_call_code(inst, jit_memcpy); 1399 x86_alu_reg_imm(inst, X86_ADD, X86_ESP, 3 * sizeof(void *)); 1400 } 1401 return inst; 1402 } 1403 1404 #define TODO() \ 1405 do { \ 1406 fprintf(stderr, "TODO at %s, %d\n", __FILE__, (int)__LINE__); \ 1407 } while (0) 1408 1409 void _jit_gen_insn(jit_gencode_t gen, jit_function_t func, 1410 jit_block_t block, jit_insn_t insn) 1411 { 1412 switch(insn->opcode) 1413 { 1414 #define JIT_INCLUDE_RULES 1415 #include "jit-rules-x86.inc" 1416 #undef JIT_INCLUDE_RULES 1417 1418 default: 1419 { 1420 fprintf(stderr, "TODO(%x) at %s, %d\n", 1421 (int)(insn->opcode), __FILE__, (int)__LINE__); 1422 } 1423 break; 1424 } 1425 } 1426 1427 void _jit_gen_start_block(jit_gencode_t gen, jit_block_t block) 1428 { 1429 void **fixup; 1430 void **next; 1431 1432 /* Set the address of this block */ 1433 block->address = (void *)(gen->ptr); 1434 1435 /* If this block has pending fixups, then apply them now */ 1436 fixup = (void **)(block->fixup_list); 1437 while(fixup != 0) 1438 { 1439 next = (void **)(fixup[0]); 1440 fixup[0] = (void *) 1441 (((jit_nint)(block->address)) - ((jit_nint)fixup) - 4); 1442 fixup = next; 1443 } 1444 block->fixup_list = 0; 1445 1446 fixup = (void**)(block->fixup_absolute_list); 1447 while(fixup != 0) 1448 { 1449 next = (void **)(fixup[0]); 1450 fixup[0] = (void *)((jit_nint)(block->address)); 1451 fixup = next; 1452 } 1453 block->fixup_absolute_list = 0; 1454 } 1455 1456 void _jit_gen_end_block(jit_gencode_t gen, jit_block_t block) 1457 { 1458 /* Nothing to do here for x86 */ 1459 } 1460 1461 int _jit_gen_is_global_candidate(jit_type_t type) 1462 { 1463 switch(jit_type_remove_tags(type)->kind) 1464 { 1465 case JIT_TYPE_INT: 1466 case JIT_TYPE_UINT: 1467 case JIT_TYPE_NINT: 1468 case JIT_TYPE_NUINT: 1469 case JIT_TYPE_PTR: 1470 case JIT_TYPE_SIGNATURE: return 1; 1471 } 1472 return 0; 1473 } 1474 1475 int 1476 _jit_reg_get_pair(jit_type_t type, int reg) 1477 { 1478 type = jit_type_normalize(type); 1479 if(type) 1480 { 1481 if(type->kind == JIT_TYPE_LONG || type->kind == JIT_TYPE_ULONG) 1482 { 1483 return jit_reg_other_reg(reg); 1484 } 1485 } 1486 return -1; 1487 } 1488 1489 #endif /* JIT_BACKEND_X86 */