]> git.unchartedbackwaters.co.uk Git - francis/libjit.git/commitdiff
Properly handle fixups on alpha. Implement JIT_OP_CALL_EXTERNAL.
authorThomas Cort <linuxgeek@gmail.com>
Sat, 12 Aug 2006 01:36:59 +0000 (01:36 +0000)
committerThomas Cort <linuxgeek@gmail.com>
Sat, 12 Aug 2006 01:36:59 +0000 (01:36 +0000)
ChangeLog
jit/jit-rules-alpha.c
jit/jit-rules-alpha.ins

index 15cb2fcdfd855e2348b24a033419f30b4d61ef32..68c68bf6f67ef7e92d50cbfc6676e6f56624b175 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2006-08-11  Thomas Cort  <linuxgeek@gmail.com>
+
+       * jit/jit-rules-alpha.c jit/jit-rules-alpha.ins Properly handle
+       fixups on alpha. Implement JIT_OP_CALL_EXTERNAL for alpha.
+
 2006-07-29  Aleksey Demakov  <ademakov@gmail.com>
 
        * jit/jit-reg-alloc.c (use_cheapest_register): allow a register that
index 581a1e01d7cab5ab0509c1bb9aa681888d32c85b..af41e563e409306180087c330c53e4919f22a628 100644 (file)
@@ -195,8 +195,12 @@ void _jit_gen_epilog(jit_gencode_t gen, jit_function_t func) {
        /* Perform fixups on any blocks that jump to the epilog */
        fixup = (void **)(gen->epilog_fixup);
        while (fixup) {
+               alpha_inst code = (alpha_inst) fixup;
                next     = (void **)(fixup[0]);
-               fixup[0] = (void*) ((jit_nint) inst - (jit_nint) fixup - 4);
+
+               _alpha_li64(code,ALPHA_AT,inst);
+               alpha_jmp(code,ALPHA_ZERO,ALPHA_AT,1);
+
                fixup    = next;
        }
 
@@ -420,8 +424,12 @@ void _jit_gen_start_block(jit_gencode_t gen, jit_block_t block) {
        fixup = (void **)(block->fixup_list);
 
        while (fixup) {
+               alpha_inst code = (alpha_inst) fixup;
                next     = (void **)(fixup[0]);
-               fixup[0] = (void*) ((jit_nint) block->address - (jit_nint) fixup - 4);
+
+               _alpha_li64(code,ALPHA_AT,(gen->posn.ptr));
+               alpha_jmp(code,ALPHA_ZERO,ALPHA_AT,1);
+
                fixup    = next;
        }
 
@@ -584,28 +592,28 @@ void _jit_gen_fix_value(jit_value_t value) {
  */
 void alpha_output_branch(jit_function_t func, alpha_inst inst, int opcode, jit_insn_t insn, int reg) {
        jit_block_t block;
-       short int offset;
 
        if (!(block = jit_block_from_label(func, (jit_label_t)(insn->dest))))
                return;
 
        if (block->address) {
                /* We already know the address of the block */
-
-               offset = ((unsigned long) block->address - (unsigned long) inst);
+               short offset = ((unsigned long) block->address - (unsigned long) inst);
                alpha_encode_branch(inst,opcode,reg,offset);
 
        } else {
-               /* Output a placeholder and record on the block's fixup list */
+               long *addr = (void*) inst;
 
-               if(block->fixup_list) {
-                       offset = (short int) ((unsigned long int) inst - (unsigned long int) block->fixup_list);
-               } else {
-                       offset = 0;
-               }
-
-               alpha_encode_branch(inst,opcode,reg,offset);
-               block->fixup_list = inst - 4;
+               /* Output a placeholder and record on the block's fixup list */
+               *addr = (long) block->fixup_list;
+               inst++; inst++;
+
+               alpha_nop(inst);
+               alpha_nop(inst);
+               alpha_nop(inst);
+               alpha_nop(inst);
+               alpha_nop(inst);
+               alpha_nop(inst);
        }
 }
 
@@ -613,7 +621,7 @@ void alpha_output_branch(jit_function_t func, alpha_inst inst, int opcode, jit_i
  * Jump to the current function's epilog.
  */
 void jump_to_epilog(jit_gencode_t gen, alpha_inst inst, jit_block_t block) {
-       short int offset;
+       long *addr = (void*) inst;
 
        /*
         * If the epilog is the next thing that we will output,
@@ -628,15 +636,30 @@ void jump_to_epilog(jit_gencode_t gen, alpha_inst inst, jit_block_t block) {
        if (!block)
                return;
 
+       /*
+        * fixups are slightly strange for the alpha port. On alpha you 
+        * cannot use an address stored in memory for jumps. The address 
+        * has to stored in a register.
+        *
+        * The fixups need the address stored in memory so that they can
+        * be 'fixed up' later. So what we do here is output the address
+        * and some nops. When it gets 'fixed up' we replace the address
+        * and 4 no-ops with opcodes to load the address into a register.
+        * Then we overwrite the last no-op with a jump opcode.
+        */
+
        /* Output a placeholder for the jump and add it to the fixup list */
-       if (gen->epilog_fixup) {
-               offset = (short int) ((unsigned long int) inst - (unsigned long int) gen->epilog_fixup);
-       } else {
-               offset = 0;
-       }
+       *addr = (long) gen->epilog_fixup;
+       inst++; inst++;
+
+       alpha_nop(inst);
+       alpha_nop(inst);
+       alpha_nop(inst);
+       alpha_nop(inst);
+       alpha_nop(inst);
+       alpha_nop(inst);        /* to be overwritten later with jmp */
 
-       alpha_br(inst, ALPHA_ZERO, offset);
-       gen->epilog_fixup = inst - 4;
+       (gen)->posn.ptr = (char*) inst;
 }
 
 #endif /* JIT_BACKEND_ALPHA */
index 10c0cbfc1db7548220af617c4f09327783d6415e..4d6ba61e4fc01dade85fb2287dbffd9a2e3cbc09 100644 (file)
@@ -396,3 +396,9 @@ JIT_OP_RETURN_LONG: unary_branch
        }
 
 /* TODO: JIT_OP_RETURN_FLOAT32 JIT_OP_RETURN_FLOAT64 JIT_OP_RETURN_NFLOAT */
+
+JIT_OP_CALL_EXTERNAL:
+       [] -> {
+               alpha_call(inst, (insn->dest));
+       }
+