github.com/goccy/go-jit@v0.0.0-20200514131505-ff78d45cf6af/internal/ccall/jit-rules-arm.c (about) 1 /* 2 * jit-rules-arm.c - Rules that define the characteristics of the ARM. 3 * 4 * Copyright (C) 2004 Southern Storm Software, Pty Ltd. 5 * Copyright (C) 2008 Michele Tartara <mikyt@users.sourceforge.net> 6 * 7 * This file is part of the libjit library. 8 * 9 * The libjit library is free software: you can redistribute it and/or 10 * modify it under the terms of the GNU Lesser General Public License 11 * as published by the Free Software Foundation, either version 2.1 of 12 * the License, or (at your option) any later version. 13 * 14 * The libjit library is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Lesser General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public 20 * License along with the libjit library. If not, see 21 * <http://www.gnu.org/licenses/>. 22 */ 23 24 #include "jit-internal.h" 25 #include "jit-rules.h" 26 #include "jit-apply-rules.h" 27 28 #if defined(JIT_BACKEND_ARM) 29 30 #include "jit-gen-arm.h" 31 #include "jit-reg-alloc.h" 32 #include "jit-setjmp.h" 33 #include <stdio.h> 34 #include <stdlib.h> 35 36 /* 37 * Pseudo register numbers for the ARM registers. These are not the 38 * same as the CPU instruction register numbers. The order of these 39 * values must match the order in "JIT_REG_INFO". 40 */ 41 #define ARM_REG_R0 0 42 #define ARM_REG_R1 1 43 #define ARM_REG_R2 2 44 #define ARM_REG_R3 3 45 #define ARM_REG_R4 4 46 #define ARM_REG_R5 5 47 #define ARM_REG_R6 6 48 #define ARM_REG_R7 7 49 #define ARM_REG_R8 8 50 #define ARM_REG_R9 9 51 #define ARM_REG_R10 10 52 #define ARM_REG_FP 11 53 #define ARM_REG_R12 12 54 #define ARM_REG_SP 13 55 #define ARM_REG_LR 14 56 #define ARM_REG_PC 15 57 58 #ifdef JIT_ARM_HAS_FPA 59 #define ARM_F0 16 60 #define ARM_F1 17 61 #define ARM_F2 18 62 #define ARM_F3 19 63 #define ARM_F4 20 64 #define ARM_F5 21 65 #define ARM_F6 22 66 #define ARM_F7 23 67 #endif 68 69 #ifdef JIT_ARM_HAS_VFP 70 #define ARM_REG_S0 16 71 #define ARM_REG_S1 17 72 #define ARM_REG_S2 18 73 #define ARM_REG_S3 19 74 #define ARM_REG_S4 20 75 #define ARM_REG_S5 21 76 #define ARM_REG_S6 22 77 #define ARM_REG_S7 23 78 #define ARM_REG_S8 24 79 #define ARM_REG_S9 25 80 #define ARM_REG_S10 26 81 #define ARM_REG_S11 27 82 #define ARM_REG_S12 28 83 #define ARM_REG_S13 29 84 #define ARM_REG_S14 30 85 #define ARM_REG_S15 31 86 #define ARM_REG_D8 32 87 #define ARM_REG_D9 33 88 #define ARM_REG_D10 34 89 #define ARM_REG_D11 35 90 #define ARM_REG_D12 36 91 #define ARM_REG_D13 37 92 #define ARM_REG_D14 38 93 #define ARM_REG_D15 39 94 #endif 95 96 /* 97 * Determine if a pseudo register number is word-based or float-based. 98 */ 99 #define IS_WORD_REG(reg) ((reg) <= ARM_REG_PC) 100 #define IS_FLOAT_REG(reg) ((reg) > ARM_REG_PC) 101 102 /* 103 * Round a size up to a multiple of the stack word size. 104 */ 105 #define ROUND_STACK(size) \ 106 (((size) + (sizeof(void *) - 1)) & ~(sizeof(void *) - 1)) 107 108 /* 109 * Given the first register of a long pair get the other register, 110 * only if the two are currently forming a pair 111 */ 112 #define jit_reg_current_other_reg(gen,reg) \ 113 (gen->contents[reg].is_long_start ? jit_reg_other_reg(reg) : -1) 114 115 /* 116 * Define the classes of registers 117 */ 118 static _jit_regclass_t *arm_reg; 119 static _jit_regclass_t *arm_freg; 120 static _jit_regclass_t *arm_freg32; 121 static _jit_regclass_t *arm_freg64; 122 static _jit_regclass_t *arm_lreg; 123 124 /* 125 * -------------------- Helper functions -------------------------- 126 */ 127 128 /* 129 * Load the instruction pointer from the generation context. 130 */ 131 #define jit_gen_load_inst_ptr(gen,inst) \ 132 do { \ 133 arm_inst_buf_init((inst), (gen)->ptr, (gen)->limit); \ 134 } while (0) 135 136 /* 137 * Save the instruction pointer back to the generation context. 138 */ 139 #define jit_gen_save_inst_ptr(gen,inst) \ 140 do { \ 141 (gen)->ptr = (unsigned char *)arm_inst_get_posn(inst); \ 142 } while (0) 143 144 /* 145 * Get a temporary register that isn't one of the specified registers. 146 * When this function is used EVERY REGISTER COULD BE DESTROYED!!! 147 * TODO: this function is only used by JIT_OP_STORE_RELATIVE_STRUCT, through memory_copy: remove 148 * the need of using it by substituting it with register allocation with [scratch reg] 149 */ 150 static int get_temp_reg(int reg1, int reg2, int reg3) 151 { 152 /* 153 * R0-R3 are not used because they could be needed for parameter passing. 154 * R4 is not used because it's used by jit_apply to store the base of the frame where 155 * it saves all the data it needs in order to restart execution after calling a compiled function. 156 * R9 is not used because it's the platform register and could have special 157 * uses on some ARM platform 158 * R11, R13-R15 are not used because they have special meaning on the ARM platform. 159 * The other registers are candidates for 160 */ 161 if(reg1 != ARM_R5 && reg2 != ARM_R5 && reg3 != ARM_R5) 162 { 163 return ARM_R5; 164 } 165 if(reg1 != ARM_R6 && reg2 != ARM_R6 && reg3 != ARM_R6) 166 { 167 return ARM_R6; 168 } 169 if(reg1 != ARM_R7 && reg2 != ARM_R7 && reg3 != ARM_R7) 170 { 171 return ARM_R7; 172 } 173 if(reg1 != ARM_R8 && reg2 != ARM_R8 && reg3 != ARM_R8) 174 { 175 return ARM_R8; 176 } 177 if(reg1 != ARM_R10 && reg2 != ARM_R10 && reg3 != ARM_R10) 178 { 179 return ARM_R10; 180 } 181 return ARM_R12; 182 } 183 184 static void mov_reg_imm (jit_gencode_t gen, arm_inst_buf *inst, int reg, int value); 185 186 /* 187 * Copy a block of memory that has a specific size. Other than 188 * the parameter pointers, all registers must be unused at this point. 189 */ 190 static arm_inst_buf memory_copy (jit_gencode_t gen, arm_inst_buf inst, int dreg, jit_nint doffset, int sreg, jit_nint soffset, jit_nuint size, int temp_reg) 191 { 192 //int temp_reg = get_temp_reg(dreg, sreg, -1); 193 if(temp_reg == -1) 194 { 195 temp_reg = get_temp_reg(dreg, sreg, -1); 196 } 197 if(size <= 4 * sizeof(void *)) 198 { 199 /* Use direct copies to copy the memory */ 200 int offset = 0; 201 while(size >= sizeof(void *)) 202 { 203 arm_mov_reg_membase(inst, temp_reg, sreg, soffset + offset, sizeof(void *)); 204 arm_mov_membase_reg(inst, dreg, doffset + offset, temp_reg, sizeof(void *)); 205 size -= sizeof(void *); 206 offset += sizeof(void *); 207 } 208 if(size >= 2) 209 { 210 arm_mov_reg_membase(inst, temp_reg, sreg, soffset + offset, 2); 211 arm_mov_membase_reg(inst, dreg, doffset + offset, temp_reg, 2); 212 size -= 2; 213 offset += 2; 214 } 215 if(size >= 1) 216 { 217 arm_mov_reg_membase(inst, temp_reg, sreg, soffset + offset, 1); 218 arm_mov_membase_reg(inst, dreg, doffset + offset, temp_reg, 1); 219 } 220 } 221 else 222 { 223 /* Call out to "jit_memcpy" to effect the copy */ 224 //Load the parameters in the right registers 225 //R2 <- size 226 mov_reg_imm(gen, &inst, ARM_R2, size); 227 //R1 <- source pointer 228 if(soffset == 0) 229 { 230 arm_mov_reg_reg(inst, ARM_R1, sreg); 231 } 232 else 233 { 234 arm_alu_reg_imm(inst, ARM_ADD, temp_reg, sreg, soffset); 235 arm_mov_reg_reg(inst, ARM_R1, temp_reg); 236 } 237 //R0 <- destination pointer 238 /* On ARM, the stack doesn't need special treatment, since parameters 239 are passed using registers, not using the stack as it's done on x86 */ 240 if(doffset == 0) 241 { 242 arm_mov_reg_reg(inst, ARM_R0, dreg); 243 } 244 else 245 { 246 arm_alu_reg_imm(inst, ARM_ADD, temp_reg, dreg, doffset); 247 arm_mov_reg_reg(inst, ARM_R0, temp_reg); 248 } 249 250 arm_call(inst, jit_memcpy); 251 } 252 return inst; 253 } 254 255 /* 256 * Flush the contents of the constant pool. 257 */ 258 static void flush_constants(jit_gencode_t gen, int after_epilog) 259 { 260 arm_inst_buf inst; 261 arm_inst_word *patch; 262 arm_inst_word *current; 263 arm_inst_word *fixup; 264 int index, value, offset; 265 266 /* Bail out if there are no constants to flush */ 267 if(!(gen->num_constants)) 268 { 269 return; 270 } 271 272 /* Initialize the cache output pointer */ 273 jit_gen_load_inst_ptr(gen, inst); 274 275 /* Jump over the constant pool if it is being output inline */ 276 if(!after_epilog) 277 { 278 patch = arm_inst_get_posn(inst); 279 arm_jump_imm(inst, 0); 280 } 281 else 282 { 283 patch = 0; 284 } 285 286 /* Align the constant pool, if requested */ 287 if(gen->align_constants && (((int)arm_inst_get_posn(inst)) & 7) != 0) 288 { 289 arm_inst_add(inst, 0); 290 } 291 292 /* Output the constant values and apply the necessary fixups */ 293 for(index = 0; index < gen->num_constants; ++index) 294 { 295 current = arm_inst_get_posn(inst); 296 arm_inst_add(inst, gen->constants[index]); 297 fixup = gen->fixup_constants[index]; 298 while(fixup != 0) 299 { 300 if((*fixup & 0x0F000000) == 0x05000000) 301 { 302 /* Word constant fixup */ 303 value = *fixup & 0x0FFF; 304 offset = ((arm_inst_get_posn(inst) - 1 - fixup) * 4) - 8; 305 *fixup = ((*fixup & ~0x0FFF) | offset); 306 } 307 else 308 { 309 /* Floating-point constant fixup */ 310 value = (*fixup & 0x00FF) * 4; 311 offset = ((arm_inst_get_posn(inst) - 1 - fixup) * 4) - 8; 312 *fixup = ((*fixup & ~0x00FF) | (offset / 4)); 313 } 314 if(value) 315 { 316 fixup -= value / sizeof(void *); 317 } 318 else 319 { 320 fixup = 0; 321 } 322 } 323 } 324 325 /* Backpatch the jump if necessary */ 326 if(!after_epilog) 327 { 328 arm_patch(inst, patch, arm_inst_get_posn(inst)); 329 } 330 331 /* Flush the pool state and restart */ 332 gen->num_constants = 0; 333 gen->align_constants = 0; 334 gen->first_constant_use = 0; 335 jit_gen_save_inst_ptr(gen, inst); 336 } 337 338 /* 339 * Perform a constant pool flush if we are too far from the starting point. 340 */ 341 static int flush_if_too_far(jit_gencode_t gen) 342 { 343 if(gen->first_constant_use && 344 (((arm_inst_word *)(gen->ptr)) - 345 ((arm_inst_word *)(gen->first_constant_use))) >= 100) 346 { 347 flush_constants(gen, 0); 348 return 1; 349 } 350 else 351 { 352 return 0; 353 } 354 } 355 356 /* 357 * Add a fixup for a particular constant pool entry. 358 */ 359 static void add_constant_fixup 360 (jit_gencode_t gen, int index, arm_inst_word *fixup) 361 { 362 arm_inst_word *prev; 363 int value; 364 if(((unsigned char *)fixup) >= gen->limit) 365 { 366 /* The instruction buffer is full, so don't record this fixup */ 367 return; 368 } 369 prev = gen->fixup_constants[index]; 370 if(prev) 371 { 372 value = (fixup - prev) * sizeof(void *); 373 } 374 else 375 { 376 value = 0; 377 } 378 if((*fixup & 0x0F000000) == 0x05000000) 379 { 380 //Word fixup 381 *fixup = ((*fixup & ~0x0FFF) | value); 382 } 383 else 384 { 385 //Float fixup 386 *fixup = ((*fixup & ~0x00FF) | (value / 4)); 387 } 388 gen->fixup_constants[index] = fixup; 389 if(!(gen->first_constant_use)) 390 { 391 gen->first_constant_use = fixup; 392 } 393 } 394 395 /* 396 * Add an immediate value to the constant pool. The constant 397 * is loaded from the instruction at "fixup". 398 */ 399 static void add_constant(jit_gencode_t gen, int value, arm_inst_word *fixup) 400 { 401 int index; 402 403 /* Search the constant pool for an existing copy of the value */ 404 for(index = 0; index < gen->num_constants; ++index) 405 { 406 if(gen->constants[index] == value) 407 { 408 add_constant_fixup(gen, index, fixup); 409 return; 410 } 411 } 412 413 /* Flush the constant pool if there is insufficient space */ 414 if(gen->num_constants >= JIT_ARM_MAX_CONSTANTS) 415 { 416 flush_constants(gen, 0); 417 } 418 419 /* Add the constant value to the pool */ 420 gen->constants[gen->num_constants] = value; 421 gen->fixup_constants[gen->num_constants] = 0; 422 ++(gen->num_constants); 423 add_constant_fixup(gen, gen->num_constants - 1, fixup); 424 } 425 426 /* 427 * Add a double-word immediate value to the constant pool. 428 */ 429 static void add_constant_dword 430 (jit_gencode_t gen, int value1, int value2, arm_inst_word *fixup, int align) 431 { 432 int index; 433 434 /* Make sure that the constant pool is properly aligned when output */ 435 if(align) 436 { 437 gen->align_constants = 1; 438 } 439 440 /* Search the constant pool for an existing copy of the value */ 441 for(index = 0; index < (gen->num_constants - 1); ++index) 442 { 443 if(gen->constants[index] == value1 && 444 gen->constants[index + 1] == value2) 445 { 446 if(!align || (index % 2) == 0) 447 { 448 add_constant_fixup(gen, index, fixup); 449 return; 450 } 451 } 452 } 453 454 /* Flush the constant pool if there is insufficient space */ 455 if(gen->num_constants >= (JIT_ARM_MAX_CONSTANTS - 1)) 456 { 457 flush_constants(gen, 0); 458 } 459 460 /* Align the constant pool on a 64-bit boundary if necessary */ 461 if(align && (gen->num_constants % 2) != 0) 462 { 463 gen->constants[gen->num_constants] = 0; 464 gen->fixup_constants[gen->num_constants] = 0; 465 ++(gen->num_constants); 466 } 467 468 /* Add the double word constant value to the pool */ 469 gen->constants[gen->num_constants] = value1; 470 gen->fixup_constants[gen->num_constants] = 0; 471 gen->constants[gen->num_constants+1] = value2; 472 gen->fixup_constants[gen->num_constants+1] = 0; 473 gen->num_constants += 2; 474 add_constant_fixup(gen, gen->num_constants - 2, fixup); 475 } 476 477 /* 478 * Load an immediate value into a word register. If the value is 479 * complicated, then add an entry to the constant pool. 480 */ 481 static void mov_reg_imm 482 (jit_gencode_t gen, arm_inst_buf *inst, int reg, int value) 483 { 484 arm_inst_word *fixup; 485 486 /* Bail out if the value is not complex enough to need a pool entry */ 487 if(!arm_is_complex_imm(value)) 488 { 489 arm_mov_reg_imm(*inst, reg, value); 490 return; 491 } 492 493 /* Output a placeholder to load the value later */ 494 fixup = arm_inst_get_posn(*inst); 495 arm_load_membase(*inst, reg, ARM_PC, 0); 496 497 /* Add the constant to the pool, which may cause a flush */ 498 jit_gen_save_inst_ptr(gen, *inst); 499 add_constant(gen, value, fixup); 500 jit_gen_load_inst_ptr(gen, *inst); 501 } 502 503 /* 504 * Load a float32 immediate value into a float register. If the value is 505 * complicated, then add an entry to the constant pool. 506 */ 507 static void mov_freg_imm_32 508 (jit_gencode_t gen, arm_inst_buf *inst, int reg, int value) 509 { 510 arm_inst_word *fixup; 511 512 /* Output a placeholder to load the value later */ 513 fixup = arm_inst_get_posn(*inst); 514 arm_load_membase_float32(*inst, reg, ARM_PC, 0); 515 516 /* Add the constant to the pool, which may cause a flush */ 517 jit_gen_save_inst_ptr(gen, *inst); 518 add_constant(gen, value, fixup); 519 jit_gen_load_inst_ptr(gen, *inst); 520 } 521 522 /* 523 * Load a float64 immediate value into a float register. If the value is 524 * complicated, then add an entry to the constant pool. 525 */ 526 static void mov_freg_imm_64 527 (jit_gencode_t gen, arm_inst_buf *inst, int reg, int value1, int value2) 528 { 529 arm_inst_word *fixup; 530 531 /* Output a placeholder to load the value later */ 532 fixup = arm_inst_get_posn(*inst); 533 arm_load_membase_float64(*inst, reg, ARM_PC, 0); 534 535 /* Add the constant to the pool, which may cause a flush */ 536 jit_gen_save_inst_ptr(gen, *inst); 537 add_constant_dword(gen, value1, value2, fixup, 1); 538 jit_gen_load_inst_ptr(gen, *inst); 539 } 540 541 /* 542 * Output a branch instruction. 543 */ 544 static void output_branch 545 (jit_function_t func, arm_inst_buf *inst, int cond, jit_insn_t insn) 546 { 547 jit_block_t block; 548 int offset; 549 //block = jit_block_from_label(func, (jit_label_t)(insn->dest)); 550 if((insn->flags & JIT_INSN_VALUE1_IS_LABEL) != 0) 551 { 552 /* "address_of_label" instruction */ 553 block = jit_block_from_label(func, (jit_label_t)(insn->value1)); 554 } 555 else 556 { 557 block = jit_block_from_label(func, (jit_label_t)(insn->dest)); 558 } 559 if(!block) 560 { 561 return; 562 } 563 if(arm_inst_get_posn(*inst) >= arm_inst_get_limit(*inst)) 564 { 565 /* The buffer has overflowed, so don't worry about fixups */ 566 return; 567 } 568 if(block->address) 569 { 570 /* We already know the address of the block */ 571 arm_branch(*inst, cond, block->address); 572 } 573 else 574 { 575 /* Output a placeholder and record on the block's fixup list */ 576 if(block->fixup_list) 577 { 578 offset = (int)(((unsigned char *)arm_inst_get_posn(*inst)) - 579 ((unsigned char *)(block->fixup_list))); 580 } 581 else 582 { 583 offset = 0; 584 } 585 arm_branch_imm(*inst, cond, offset); 586 block->fixup_list = (void *)(arm_inst_get_posn(*inst) - 1); 587 } 588 } 589 590 /* 591 * Throw a builtin exception. 592 */ 593 static void throw_builtin 594 (arm_inst_buf *inst, jit_function_t func, int cond, int type) 595 { 596 arm_inst_word *patch; 597 598 /* Branch past the following code if "cond" is not true */ 599 patch = arm_inst_get_posn(*inst); 600 arm_branch_imm(*inst, cond ^ 0x01, 0); 601 602 /* We need to update "catch_pc" if we have a "try" block */ 603 if(func->builder->setjmp_value != 0) 604 { 605 _jit_gen_fix_value(func->builder->setjmp_value); 606 arm_mov_reg_reg(*inst, ARM_WORK, ARM_PC); 607 arm_store_membase(*inst, ARM_WORK, ARM_FP, 608 func->builder->setjmp_value->frame_offset + 609 jit_jmp_catch_pc_offset); 610 } 611 612 /* Push the exception type onto the stack */ 613 arm_mov_reg_imm(*inst, ARM_WORK, type); 614 arm_push_reg(*inst, ARM_WORK); 615 616 /* Call the "jit_exception_builtin" function, which will never return */ 617 arm_call(*inst, jit_exception_builtin); 618 619 /* Back-patch the previous branch instruction */ 620 arm_patch(*inst, patch, arm_inst_get_posn(*inst)); 621 } 622 623 /* 624 * Jump to the current function's epilog. 625 */ 626 static void jump_to_epilog 627 (jit_gencode_t gen, arm_inst_buf *inst, jit_block_t block) 628 { 629 int offset; 630 631 /* If the epilog is the next thing that we will output, 632 then fall through to the epilog directly */ 633 if(_jit_block_is_final(block)) 634 { 635 return; 636 } 637 638 /* Bail out if the instruction buffer has overflowed */ 639 if(arm_inst_get_posn(*inst) >= arm_inst_get_limit(*inst)) 640 { 641 return; 642 } 643 644 /* Output a placeholder for the jump and add it to the fixup list */ 645 if(gen->epilog_fixup) 646 { 647 offset = (int)(((unsigned char *)arm_inst_get_posn(*inst)) - 648 ((unsigned char *)(gen->epilog_fixup))); 649 } 650 else 651 { 652 offset = 0; 653 } 654 arm_branch_imm(*inst, ARM_CC_AL, offset); 655 gen->epilog_fixup = (void *)(arm_inst_get_posn(*inst) - 1); 656 } 657 658 #define TODO() \ 659 do { \ 660 fprintf(stderr, "TODO at %s, %d\n", __FILE__, (int)__LINE__); \ 661 } while (0) 662 663 /* 664 * -------------------- End of helper functions ------------------------ 665 */ 666 667 668 /* 669 * Initialize the backend. 670 */ 671 void _jit_init_backend(void) 672 { 673 /* 674 * Init the various classes of registers 675 */ 676 677 /* WORD registers */ 678 arm_reg = _jit_regclass_create( 679 "reg", JIT_REG_WORD, 9, 680 ARM_REG_R0, ARM_REG_R1, 681 ARM_REG_R2, ARM_REG_R3, 682 ARM_REG_R4, ARM_REG_R5, 683 ARM_REG_R6, ARM_REG_R7, 684 ARM_REG_R8); 685 686 #ifdef JIT_ARM_HAS_FPA 687 /* float registers */ 688 arm_freg = _jit_regclass_create( 689 "freg64", JIT_REG_ARM_FLOAT, 4, 690 ARM_REG_F0, ARM_REG_F1, 691 ARM_REG_F2, ARM_REG_F3, 692 /*ARM_REG_F4, ARM_REG_F5, 693 ARM_REG_F6, ARM_REG_F7*/); 694 #endif 695 696 #ifdef JIT_ARM_HAS_VFP 697 /* 32-bits float registers */ 698 arm_freg32 = _jit_regclass_create( 699 "freg32", JIT_REG_ARM_FLOAT32, 16, 700 ARM_REG_S0, ARM_REG_S1, 701 ARM_REG_S2, ARM_REG_S3, 702 ARM_REG_S4, ARM_REG_S5, 703 ARM_REG_S6, ARM_REG_S7, 704 ARM_REG_S8, ARM_REG_S9, 705 ARM_REG_S10, ARM_REG_S11, 706 ARM_REG_S12, ARM_REG_S13, 707 ARM_REG_S14, ARM_REG_S15); 708 709 /* 64-bits float registers */ 710 arm_freg64 = _jit_regclass_create( 711 "freg64", JIT_REG_ARM_FLOAT64, 8, 712 ARM_REG_D8, ARM_REG_D9, 713 ARM_REG_D10, ARM_REG_D11, 714 ARM_REG_D12, ARM_REG_D13, 715 ARM_REG_D14, ARM_REG_D15); 716 #endif 717 718 /* Long registers */ 719 arm_lreg = _jit_regclass_create( 720 "lreg", JIT_REG_LONG, 2, 721 ARM_REG_R0, ARM_REG_R2); 722 } 723 724 void _jit_gen_get_elf_info(jit_elf_info_t *info) 725 { 726 info->machine = 40; /* EM_ARM */ 727 info->abi = 0; /* ELFOSABI_SYSV */ 728 info->abi_version = 0; 729 } 730 731 int _jit_setup_indirect_pointer(jit_function_t func, jit_value_t value) 732 { 733 return jit_insn_outgoing_reg(func, value, ARM_WORK); 734 } 735 736 int _jit_create_call_return_insns 737 (jit_function_t func, jit_type_t signature, 738 jit_value_t *args, unsigned int num_args, 739 jit_value_t return_value, int is_nested) 740 { 741 jit_type_t return_type; 742 int ptr_return; 743 744 /* Bail out now if we don't need to worry about return values */ 745 return_type = jit_type_normalize(jit_type_get_return(signature)); 746 ptr_return = jit_type_return_via_pointer(return_type); 747 if(!return_value || ptr_return) 748 { 749 return 1; 750 } 751 752 /* Structure values must be flushed into the frame, and 753 everything else ends up in a register */ 754 if(jit_type_is_struct(return_type) || jit_type_is_union(return_type)) 755 { 756 if(!jit_insn_flush_struct(func, return_value)) 757 { 758 return 0; 759 } 760 } 761 else if(return_type->kind != JIT_TYPE_VOID) 762 { 763 if(!jit_insn_return_reg(func, return_value, ARM_REG_R0)) 764 { 765 return 0; 766 } 767 } 768 769 /* Everything is back where it needs to be */ 770 return 1; 771 } 772 773 int _jit_opcode_is_supported(int opcode) 774 { 775 switch(opcode) 776 { 777 #define JIT_INCLUDE_SUPPORTED 778 #include "jit-rules-arm.inc" 779 #undef JIT_INCLUDE_SUPPORTED 780 } 781 return 0; 782 } 783 784 void *_jit_gen_prolog(jit_gencode_t gen, jit_function_t func, void *buf) 785 { 786 unsigned int prolog[JIT_PROLOG_SIZE / sizeof(int)]; 787 arm_inst_buf inst; 788 int reg, regset; 789 unsigned int saved; 790 unsigned int frame_size; 791 unsigned int stack_growth; 792 793 /* Initialize the instruction buffer */ 794 arm_inst_buf_init(inst, prolog, prolog + JIT_PROLOG_SIZE / sizeof(int)); 795 796 /* Determine which registers need to be preserved */ 797 regset = 0; 798 saved = 0; 799 for(reg = 0; reg <= 15; ++reg) 800 { 801 if(jit_reg_is_used(gen->touched, reg) && 802 (_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0) 803 { 804 regset |= (1 << reg); 805 saved += sizeof(void *); 806 } 807 } 808 809 /* Setup the frame, pushing all the callee-save registers */ 810 arm_setup_frame(inst, regset); 811 812 /* Allocate space for the local variable frame. Subtract off 813 the space for the registers that we just saved. The pc, lr, 814 and fp registers are always saved, so account for them too */ 815 stack_growth=(saved + 4 * sizeof(void *)); 816 frame_size = func->builder->frame_size - stack_growth; 817 frame_size = func->builder->frame_size - (saved + 3 * sizeof(void *)); 818 frame_size += (unsigned int)(func->builder->param_area_size); 819 while(frame_size % JIT_SP_ALIGN_PUBLIC != 0) 820 { 821 //Pad to reach the required stacl pointer alignment 822 frame_size++; 823 } 824 825 /* If the registers that get saved on the stack make it grow of a odd number 826 * of words, the preceding while isn't able anymore to compute the correct 827 * allignment. The following adds a correction when needed. 828 */ 829 if (stack_growth % JIT_SP_ALIGN_PUBLIC != 0) 830 { 831 //Pad to reach the required stack pointer alignment 832 frame_size += (stack_growth % JIT_SP_ALIGN_PUBLIC); 833 } 834 835 if(frame_size > 0) 836 { 837 arm_alu_reg_imm(inst, ARM_SUB, ARM_SP, ARM_SP, frame_size); 838 } 839 840 /* Copy the prolog into place and return the adjusted entry position */ 841 reg = (int)((arm_inst_get_posn(inst) - prolog) * sizeof(unsigned int)); 842 jit_memcpy(((unsigned char *)buf) + JIT_PROLOG_SIZE - reg, prolog, reg); 843 return (void *)(((unsigned char *)buf) + JIT_PROLOG_SIZE - reg); 844 } 845 846 void _jit_gen_epilog(jit_gencode_t gen, jit_function_t func) 847 { 848 int reg, regset; 849 arm_inst_buf inst; 850 void **fixup; 851 void **next; 852 jit_nint offset; 853 854 /* Initialize the instruction buffer */ 855 jit_gen_load_inst_ptr(gen, inst); 856 857 /* Determine which registers need to be restored when we return */ 858 regset = 0; 859 for(reg = 0; reg <= 15; ++reg) 860 { 861 if(jit_reg_is_used(gen->touched, reg) && 862 (_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0) 863 { 864 regset |= (1 << reg); 865 } 866 } 867 868 /* Apply fixups for blocks that jump to the epilog */ 869 fixup = (void **)(gen->epilog_fixup); 870 while(fixup != 0) 871 { 872 offset = (((jit_nint)(fixup[0])) & 0x00FFFFFF) << 2; 873 if(!offset) 874 { 875 next = 0; 876 } 877 else 878 { 879 next = (void **)(((unsigned char *)fixup) - offset); 880 } 881 arm_patch(inst, fixup, arm_inst_get_posn(inst)); 882 fixup = next; 883 } 884 gen->epilog_fixup = 0; 885 886 /* Pop the local stack frame and return */ 887 arm_pop_frame(inst, regset); 888 jit_gen_save_inst_ptr(gen, inst); 889 890 /* Flush the remainder of the constant pool */ 891 flush_constants(gen, 1); 892 } 893 894 #if 0 895 /* 896 * The ARM backend does not need this function because it uses 897 * _jit_create_indirector() instead. 898 */ 899 void *_jit_gen_redirector(jit_gencode_t gen, jit_function_t func) 900 { 901 void *ptr, *entry; 902 arm_inst_buf inst; 903 jit_gen_load_inst_ptr(gen, inst); 904 ptr = (void *)&(func->entry_point); 905 entry = gen->ptr; 906 arm_load_membase(inst, ARM_WORK, ARM_PC, 0); 907 arm_load_membase(inst, ARM_PC, ARM_WORK, 0); 908 arm_inst_add(inst, (unsigned int)ptr); 909 jit_gen_save_inst_ptr(gen, inst); 910 return entry; 911 } 912 #endif 913 /* 914 * Setup or teardown the ARM code output process. 915 */ 916 #define jit_cache_setup_output(needed) \ 917 arm_inst_buf inst; \ 918 jit_gen_load_inst_ptr(gen, inst) 919 #define jit_cache_end_output() \ 920 jit_gen_save_inst_ptr(gen, inst) 921 922 /** 923 * Spill the content of register "reg" (and "other_reg", if it's different from -1) 924 * into the global register or the memory area associated with "value" 925 * NB: it doesn't set value->in_global_register or value->in_frame. The caller has to 926 * take care of that. 927 */ 928 void _jit_gen_spill_reg(jit_gencode_t gen, int reg, 929 int other_reg, jit_value_t value) 930 { 931 int offset; 932 933 /* Make sure that we have sufficient space */ 934 jit_cache_setup_output(32); 935 if(flush_if_too_far(gen)) 936 { 937 jit_gen_load_inst_ptr(gen, inst); 938 } 939 940 /* Output an appropriate instruction to spill the value */ 941 if(value->has_global_register) 942 { 943 if (IS_FLOAT_REG(reg)) 944 { 945 printf("TODO:Copy from float reg to global reg is not handled properly in %s\n", __FILE__); 946 abort(); 947 } 948 else 949 { 950 arm_mov_reg_reg(inst, _jit_reg_info[value->global_reg].cpu_reg, _jit_reg_info[reg].cpu_reg); 951 } 952 } 953 else 954 { 955 _jit_gen_fix_value(value); 956 offset = (int)(value->frame_offset); 957 if(IS_WORD_REG(reg)) 958 { 959 arm_store_membase(inst, reg, ARM_FP, offset); 960 if(other_reg != -1) 961 { 962 /* Spill the other word register in a pair */ 963 offset += sizeof(void *); 964 arm_store_membase(inst, other_reg, ARM_FP, offset); 965 } 966 } 967 else if(jit_type_normalize(value->type)->kind == JIT_TYPE_FLOAT32) 968 { 969 arm_store_membase_float32(inst, _jit_reg_info[value->reg].cpu_reg, ARM_FP, offset); 970 } 971 else 972 { 973 arm_store_membase_float64(inst, _jit_reg_info[value->reg].cpu_reg, ARM_FP, offset); 974 } 975 } 976 977 /* End the code output process */ 978 jit_cache_end_output(); 979 } 980 981 void _jit_gen_free_reg(jit_gencode_t gen, int reg, 982 int other_reg, int value_used) 983 { 984 /* We don't have to do anything to free ARM registers */ 985 } 986 987 /* 988 * Loads the content of the value @var{value} into register @var{reg} and (if needed) @var{other_reg} 989 */ 990 void _jit_gen_load_value 991 (jit_gencode_t gen, int reg, int other_reg, jit_value_t value) 992 { 993 int offset; 994 995 /* Make sure that we have sufficient space */ 996 jit_cache_setup_output(32); 997 if(flush_if_too_far(gen)) 998 { 999 jit_gen_load_inst_ptr(gen, inst); 1000 } 1001 1002 if(value->is_constant) 1003 { 1004 /* Determine the type of constant to be loaded */ 1005 switch(jit_type_normalize(value->type)->kind) 1006 { 1007 case JIT_TYPE_SBYTE: 1008 case JIT_TYPE_UBYTE: 1009 case JIT_TYPE_SHORT: 1010 case JIT_TYPE_USHORT: 1011 case JIT_TYPE_INT: 1012 case JIT_TYPE_UINT: 1013 { 1014 mov_reg_imm(gen, &inst, _jit_reg_info[reg].cpu_reg, 1015 (jit_nint)(value->address)); 1016 } 1017 break; 1018 1019 case JIT_TYPE_LONG: 1020 case JIT_TYPE_ULONG: 1021 { 1022 jit_long long_value; 1023 long_value = jit_value_get_long_constant(value); 1024 mov_reg_imm(gen, &inst, _jit_reg_info[reg].cpu_reg, 1025 (jit_int)long_value); 1026 mov_reg_imm(gen, &inst, _jit_reg_info[reg].cpu_reg + 1, 1027 (jit_int)(long_value >> 32)); 1028 } 1029 break; 1030 1031 case JIT_TYPE_FLOAT32: 1032 { 1033 jit_float32 float32_value; 1034 float32_value = jit_value_get_float32_constant(value); 1035 if(IS_WORD_REG(reg)) 1036 { 1037 mov_reg_imm(gen, &inst, _jit_reg_info[reg].cpu_reg, 1038 *((int *)&float32_value)); 1039 } 1040 else 1041 { 1042 mov_freg_imm_32 1043 (gen, &inst, _jit_reg_info[reg].cpu_reg, 1044 *((int *)&float32_value)); 1045 } 1046 } 1047 break; 1048 1049 case JIT_TYPE_FLOAT64: 1050 case JIT_TYPE_NFLOAT: 1051 { 1052 jit_float64 float64_value; 1053 float64_value = jit_value_get_float64_constant(value); 1054 if(IS_WORD_REG(reg)) 1055 { 1056 mov_reg_imm 1057 (gen, &inst, _jit_reg_info[reg].cpu_reg, 1058 ((int *)&float64_value)[0]); 1059 mov_reg_imm 1060 (gen, &inst, _jit_reg_info[reg].cpu_reg + 1, 1061 ((int *)&float64_value)[1]); 1062 } 1063 else 1064 { 1065 mov_freg_imm_64 1066 (gen, &inst, _jit_reg_info[reg].cpu_reg, 1067 ((int *)&float64_value)[0], 1068 ((int *)&float64_value)[1]); 1069 } 1070 } 1071 break; 1072 } 1073 } 1074 else if(value->in_global_register) 1075 { 1076 /* Load the value out of a global register */ 1077 if(IS_FLOAT_REG(reg)) 1078 { 1079 /* Load into a floating point register */ 1080 #ifdef JIT_ARM_HAS_VFP 1081 /* Vector Floating Point instructions */ 1082 if(jit_type_normalize(value->type)->kind == JIT_TYPE_FLOAT32) 1083 { 1084 arm_mov_float_reg(inst, 1085 _jit_reg_info[reg].cpu_reg, 1086 _jit_reg_info[value->global_reg].cpu_reg); 1087 } 1088 else 1089 { 1090 //JIT_TYPE_FLOAT64 or JIT_TYPE_NFLOAT 1091 arm_mov_double_reg_reg(inst, 1092 _jit_reg_info[reg].cpu_reg, 1093 _jit_reg_info[value->global_reg].cpu_reg, 1094 _jit_reg_info[value->global_reg].cpu_reg + 1); 1095 } 1096 #endif 1097 #ifdef JIT_ARM_HAS_FPA 1098 /* Floating Point Architecture instructions */ 1099 TODO(); 1100 abort(); 1101 #endif 1102 } 1103 else 1104 { 1105 /* Load into a general-purpose register */ 1106 arm_mov_reg_reg(inst, 1107 _jit_reg_info[reg].cpu_reg, 1108 _jit_reg_info[value->global_reg].cpu_reg); 1109 } 1110 } 1111 else if(value->in_register) 1112 { 1113 /* The value is already in another register. Move it */ 1114 switch(jit_type_normalize(value->type)->kind) 1115 { 1116 case JIT_TYPE_SBYTE: 1117 case JIT_TYPE_UBYTE: 1118 case JIT_TYPE_SHORT: 1119 case JIT_TYPE_USHORT: 1120 case JIT_TYPE_INT: 1121 case JIT_TYPE_UINT: 1122 { 1123 arm_mov_reg_reg(inst, jit_reg_code(reg), jit_reg_code(value->reg)); 1124 } 1125 break; 1126 1127 case JIT_TYPE_LONG: 1128 case JIT_TYPE_ULONG: 1129 { 1130 assert(jit_reg_code(other_reg) !=-1); 1131 assert(jit_reg_other_reg(value->reg) != -1); 1132 1133 arm_mov_reg_reg(inst, jit_reg_code(reg), jit_reg_code(value->reg)); 1134 arm_mov_reg_reg(inst, jit_reg_code(other_reg), jit_reg_other_reg(value->reg)); 1135 } 1136 break; 1137 1138 case JIT_TYPE_FLOAT32: 1139 { 1140 #ifdef JIT_ARM_HAS_VFP 1141 /* Vector Floating Point instructions */ 1142 if(IS_FLOAT_REG(reg)) 1143 { 1144 if(IS_WORD_REG(value->reg)) 1145 { 1146 arm_mov_float_reg(inst, 1147 jit_reg_code(reg), 1148 jit_reg_code(value->reg)); 1149 } 1150 else 1151 { 1152 arm_alu_freg_32(inst, ARM_MVF, 1153 jit_reg_code(reg), 1154 jit_reg_code(value->reg)); 1155 } 1156 } 1157 else 1158 { 1159 if(IS_WORD_REG(value->reg)) 1160 { 1161 arm_mov_reg_reg(inst, 1162 jit_reg_code(reg), 1163 jit_reg_code(value->reg)); 1164 } 1165 else 1166 { 1167 arm_mov_reg_float(inst, 1168 jit_reg_code(reg), 1169 jit_reg_code(value->reg)); 1170 } 1171 } 1172 #endif 1173 #ifdef JIT_ARM_HAS_FPA 1174 /* Floating Point Architecture instructions */ 1175 TODO(); 1176 abort(); 1177 #endif 1178 } 1179 break; 1180 1181 case JIT_TYPE_FLOAT64: 1182 case JIT_TYPE_NFLOAT: 1183 { 1184 #ifdef JIT_ARM_HAS_VFP 1185 /* Vector Floating Point instruction */ 1186 if(IS_FLOAT_REG(reg)) 1187 { 1188 if(IS_WORD_REG(value->reg)) 1189 { 1190 assert(jit_reg_other_reg(value->reg) != -1); 1191 1192 arm_mov_double_reg_reg(inst, 1193 jit_reg_code(reg), 1194 jit_reg_code(value->reg), 1195 jit_reg_other_reg(value->reg)); 1196 } 1197 else 1198 { 1199 arm_alu_freg(inst, ARM_MVF, 1200 jit_reg_code(reg), 1201 jit_reg_code(value->reg)); 1202 } 1203 } 1204 else 1205 { 1206 if(IS_WORD_REG(value->reg)) 1207 { 1208 arm_mov_reg_reg(inst, 1209 jit_reg_code(reg), 1210 jit_reg_code(value->reg)); 1211 } 1212 else 1213 { 1214 assert(jit_reg_other_reg(reg)); 1215 arm_mov_reg_reg_double(inst, 1216 jit_reg_code(reg), 1217 jit_reg_other_reg(reg), 1218 jit_reg_code(value->reg)); 1219 } 1220 } 1221 #endif 1222 #ifdef JIT_ARM_HAS_FPA 1223 /* Floating Point Architecture instructions */ 1224 TODO(); 1225 abort(); 1226 #endif 1227 } 1228 break; 1229 } 1230 } 1231 else 1232 { 1233 /* Load from the stack */ 1234 assert(!value->in_global_register && !value->is_constant && !value->in_register); 1235 1236 /* Fix the position of the value in the stack frame */ 1237 _jit_gen_fix_value(value); 1238 offset = (int)(value->frame_offset); 1239 1240 switch(jit_type_normalize(value->type)->kind) 1241 { 1242 case JIT_TYPE_SBYTE: 1243 { 1244 arm_load_membase_sbyte(inst, _jit_reg_info[reg].cpu_reg, 1245 ARM_FP, offset); 1246 } 1247 break; 1248 1249 case JIT_TYPE_UBYTE: 1250 { 1251 arm_load_membase_byte(inst, _jit_reg_info[reg].cpu_reg, 1252 ARM_FP, offset); 1253 } 1254 break; 1255 1256 case JIT_TYPE_SHORT: 1257 { 1258 arm_load_membase_short(inst, _jit_reg_info[reg].cpu_reg, 1259 ARM_FP, offset); 1260 } 1261 break; 1262 1263 case JIT_TYPE_USHORT: 1264 { 1265 arm_load_membase_ushort(inst, _jit_reg_info[reg].cpu_reg, 1266 ARM_FP, offset); 1267 } 1268 break; 1269 1270 case JIT_TYPE_INT: 1271 case JIT_TYPE_UINT: 1272 { 1273 arm_load_membase(inst, _jit_reg_info[reg].cpu_reg, 1274 ARM_FP, offset); 1275 } 1276 break; 1277 1278 case JIT_TYPE_LONG: 1279 case JIT_TYPE_ULONG: 1280 { 1281 arm_load_membase(inst, _jit_reg_info[reg].cpu_reg, 1282 ARM_FP, offset); 1283 arm_load_membase(inst, _jit_reg_info[reg].cpu_reg + 1, 1284 ARM_FP, offset + 4); 1285 } 1286 break; 1287 1288 case JIT_TYPE_FLOAT32: 1289 { 1290 if(IS_WORD_REG(reg)) 1291 { 1292 arm_load_membase(inst, _jit_reg_info[reg].cpu_reg, 1293 ARM_FP, offset); 1294 } 1295 else 1296 { 1297 arm_load_membase_float32 1298 (inst, _jit_reg_info[reg].cpu_reg, ARM_FP, offset); 1299 } 1300 } 1301 break; 1302 1303 case JIT_TYPE_FLOAT64: 1304 case JIT_TYPE_NFLOAT: 1305 { 1306 if(IS_WORD_REG(reg)) 1307 { 1308 arm_load_membase(inst, _jit_reg_info[reg].cpu_reg, 1309 ARM_FP, offset); 1310 arm_load_membase(inst, _jit_reg_info[reg].cpu_reg + 1, 1311 ARM_FP, offset + 4); 1312 } 1313 else 1314 { 1315 arm_load_membase_float64 1316 (inst, _jit_reg_info[reg].cpu_reg, ARM_FP, offset); 1317 } 1318 } 1319 break; 1320 } 1321 } 1322 1323 /* End the code output process */ 1324 jit_cache_end_output(); 1325 } 1326 1327 /** 1328 * Loads a struct indicated by "value" into the given register reg 1329 */ 1330 void _jit_gen_load_value_struct (jit_gencode_t gen, int reg, jit_value_t value) 1331 { 1332 int offset; 1333 1334 /* Make sure that we have sufficient space */ 1335 jit_cache_setup_output(32); 1336 if(flush_if_too_far(gen)) 1337 { 1338 jit_gen_load_inst_ptr(gen, inst); 1339 } 1340 1341 if(value->is_constant) 1342 { 1343 TODO(); 1344 abort(); 1345 } 1346 else if(value->has_global_register) 1347 { 1348 /* 1349 * This value has been assinged a global register. This means 1350 * that it can use that register, but not necessarily that it's 1351 * already in it!! 1352 */ 1353 1354 /* Ensure that the value is already in the global_register */ 1355 if (!value->in_global_register) 1356 { 1357 /* Find the other register in a long pair */ 1358 int reg = value->reg; 1359 int other_reg = jit_reg_current_other_reg(gen,reg); 1360 1361 //Spill to the global register 1362 _jit_gen_spill_reg(gen, reg, other_reg, value); 1363 value->in_global_register=1; 1364 1365 /* A new instruction has probably been generated by _jit_gen_spill_reg: reload the inst pointer */ 1366 jit_gen_load_inst_ptr(gen, inst); 1367 } 1368 /* Load the value out of a global register */ 1369 arm_mov_reg_reg(inst, _jit_reg_info[reg].cpu_reg, 1370 _jit_reg_info[value->global_reg].cpu_reg); 1371 } 1372 else 1373 { 1374 /* Fix the position of the value in the stack frame */ 1375 _jit_gen_fix_value(value); 1376 offset = (int)(value->frame_offset); 1377 1378 /* Ensure that the value is already in the stack frame */ 1379 if(value->in_register) 1380 { 1381 /* Find the other register in a long pair */ 1382 int reg = value->reg; 1383 int other_reg = jit_reg_current_other_reg(gen,reg); 1384 1385 _jit_gen_spill_reg(gen, reg, other_reg, value); 1386 value->in_frame=1; 1387 1388 /* A new instruction has probably been generated by _jit_gen_spill_reg: reload the inst pointer */ 1389 jit_gen_load_inst_ptr(gen, inst); 1390 } 1391 1392 assert(jit_type_normalize(value->type)->kind==JIT_TYPE_STRUCT); 1393 1394 arm_load_membase(inst, _jit_reg_info[reg].cpu_reg, ARM_FP, offset); 1395 if (jit_type_get_size(jit_value_get_type(value)) > 4) 1396 { 1397 TODO(); 1398 abort(); 1399 } 1400 1401 } 1402 1403 /* End the code output process */ 1404 jit_cache_end_output(); 1405 } 1406 1407 void _jit_gen_spill_global(jit_gencode_t gen, int reg, jit_value_t value) 1408 { 1409 /* TODO: Implement if ARM needs it. */ 1410 } 1411 1412 void _jit_gen_load_global(jit_gencode_t gen, int reg, jit_value_t value) 1413 { 1414 jit_cache_setup_output(32); 1415 arm_load_membase(inst, _jit_reg_info[value->global_reg].cpu_reg, 1416 ARM_FP, value->frame_offset); 1417 jit_cache_end_output(); 1418 } 1419 1420 void _jit_gen_fix_value(jit_value_t value) 1421 { 1422 if(!(value->has_frame_offset) && !(value->is_constant)) 1423 { 1424 jit_nint size = (jit_nint)(ROUND_STACK(jit_type_get_size(value->type))); 1425 value->block->func->builder->frame_size += size; 1426 value->frame_offset = -(value->block->func->builder->frame_size); 1427 value->has_frame_offset = 1; 1428 } 1429 } 1430 1431 void _jit_gen_insn(jit_gencode_t gen, jit_function_t func, 1432 jit_block_t block, jit_insn_t insn) 1433 { 1434 flush_if_too_far(gen); 1435 switch(insn->opcode) 1436 { 1437 #define JIT_INCLUDE_RULES 1438 #include "jit-rules-arm.inc" 1439 #undef JIT_INCLUDE_RULES 1440 1441 default: 1442 { 1443 fprintf(stderr, "TODO(%x) at %s, %d\n", 1444 (int)(insn->opcode), __FILE__, (int)__LINE__); 1445 } 1446 break; 1447 } 1448 } 1449 1450 void _jit_gen_start_block(jit_gencode_t gen, jit_block_t block) 1451 { 1452 void **fixup; 1453 void **next; 1454 jit_nint offset; 1455 arm_inst_buf inst; 1456 1457 /* Set the address of this block */ 1458 block->address = (void *)(gen->ptr); 1459 1460 /* If this block has pending fixups, then apply them now */ 1461 fixup = (void **)(block->fixup_list); 1462 while(fixup != 0) 1463 { 1464 offset = (((jit_nint)(fixup[0])) & 0x00FFFFFF) << 2; 1465 if(!offset) 1466 { 1467 next = 0; 1468 } 1469 else 1470 { 1471 next = (void **)(((unsigned char *)fixup) - offset); 1472 } 1473 jit_gen_load_inst_ptr(gen, inst); 1474 arm_patch(inst, fixup, block->address); 1475 fixup = next; 1476 } 1477 block->fixup_list = 0; 1478 } 1479 1480 void _jit_gen_end_block(jit_gencode_t gen, jit_block_t block) 1481 { 1482 /* Nothing to do here for ARM */ 1483 } 1484 1485 int _jit_gen_is_global_candidate(jit_type_t type) 1486 { 1487 switch(jit_type_remove_tags(type)->kind) 1488 { 1489 case JIT_TYPE_INT: 1490 case JIT_TYPE_UINT: 1491 case JIT_TYPE_NINT: 1492 case JIT_TYPE_NUINT: 1493 case JIT_TYPE_PTR: 1494 case JIT_TYPE_SIGNATURE: return 1; 1495 } 1496 return 0; 1497 } 1498 1499 int 1500 _jit_reg_get_pair(jit_type_t type, int reg) 1501 { 1502 type = jit_type_normalize(type); 1503 if(type) 1504 { 1505 if(type->kind == JIT_TYPE_LONG || type->kind == JIT_TYPE_ULONG) 1506 { 1507 return jit_reg_other_reg(reg); 1508 } 1509 else if(type->kind == JIT_TYPE_FLOAT64 || type->kind == JIT_TYPE_NFLOAT) 1510 { 1511 if(reg == ARM_REG_R0) 1512 { 1513 return jit_reg_other_reg(reg); 1514 } 1515 } 1516 } 1517 return -1; 1518 } 1519 1520 #endif /* JIT_BACKEND_ARM */