[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[dotgnu-pnet-commits] libjit ChangeLog jit/jit-rules-arm.ins
From: |
Aleksey Demakov |
Subject: |
[dotgnu-pnet-commits] libjit ChangeLog jit/jit-rules-arm.ins |
Date: |
Tue, 24 Mar 2009 01:17:44 +0000 |
CVSROOT: /sources/dotgnu-pnet
Module name: libjit
Changes by: Aleksey Demakov <avd> 09/03/24 01:17:44
Modified files:
. : ChangeLog
jit : jit-rules-arm.ins
Log message:
arm idiv and memset opcodes
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/libjit/ChangeLog?cvsroot=dotgnu-pnet&r1=1.413&r2=1.414
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-rules-arm.ins?cvsroot=dotgnu-pnet&r1=1.3&r2=1.4
Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/ChangeLog,v
retrieving revision 1.413
retrieving revision 1.414
diff -u -b -r1.413 -r1.414
--- ChangeLog 24 Mar 2009 00:56:35 -0000 1.413
+++ ChangeLog 24 Mar 2009 01:17:44 -0000 1.414
@@ -6,7 +6,8 @@
* jit/jit-gen-arm.h: add more ARM codegen macros including VFP
support.
- * jit/jit-rules-arm.ins: restore ARM FPA rules.
+ * jit/jit-rules-arm.ins: restore ARM FPA rules, implement IDIV and
+ fix MEMSET opcodes.
* jit/jit-rules-arm.h, jit/jit-rules-arm.c: more ARM code.
* jit/jit-reg-alloc.c (_jit_regs_commit): fix typo.
Index: jit/jit-rules-arm.ins
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/jit/jit-rules-arm.ins,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- jit/jit-rules-arm.ins 23 Mar 2009 13:51:04 -0000 1.3
+++ jit/jit-rules-arm.ins 24 Mar 2009 01:17:44 -0000 1.4
@@ -182,6 +182,139 @@
}
}
+JIT_OP_IDIV:
+ [any, immzero] -> {
+ throw_builtin(&inst, func, ARM_CC_AL,
JIT_RESULT_DIVISION_BY_ZERO);
+ }
+ [reg, immu8, if("$2 == 1")] -> {
+ /* Division by 1. Return the value itself */
+ }
+ [reg, immu8, if("($2 % 2) == 0")] -> {
+ /* Handle special cases of small immediate divides */
+ switch($2)
+ {
+ //Integer divide by shifting
+ case 2:
+ {
+ arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, 1);
+ }
+ break;
+
+ case 4:
+ {
+ arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, 2);
+ }
+ break;
+
+ case 8:
+ {
+ arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, 3);
+ }
+ break;
+
+ case 16:
+ {
+ arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, 4);
+ }
+ break;
+
+ case 32:
+ {
+ arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, 5);
+ }
+ break;
+
+ case 64:
+ {
+ arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, 6);
+ }
+ break;
+
+ case 128:
+ {
+ arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, 7);
+ }
+ break;
+ }
+ }
+ [reg, imm, if("$2 == -1")] -> {
+ /* Dividing by -1 simply negates */
+ /*TODO: if the value to be divided by -1 is jit_min_int,
+ an exception (JIT_RESULT_ARITHMETIC) should probably be
thrown */
+ arm_alu_reg(inst, ARM_MVN, $1, $1);
+ }
+ [reg, imm, clobber("r0", "r1")] -> {
+ /* Every other immediate division:
+ ARM does not have an integer division operation. It's
emulated via software. */
+
+ //Put the dividend in the right position
+ if ($1 != ARM_R0)
+ arm_mov_reg_reg(inst, ARM_R0, $1);
+
+ //Put the divisor in the right position
+ mov_reg_imm(gen, &inst, ARM_R1, $2);
+
+ //Perform the division by calling a function from the runtime
ABI
+ extern int __aeabi_idiv(int numerator, int denominator);
+ arm_call(inst, __aeabi_idiv);
+
+ if($1 != ARM_R0)
+ {
+ //Move the result back where it is expected to be
+ arm_mov_reg_reg(inst, $1, ARM_R0);
+ }
+
+ }
+ [reg, reg, scratch reg, clobber("r0", "r1")] -> {
+ /* Every division taking data from two registers:
+ ARM does not have an integer division operation. It's
emulated via software. */
+
+ int dividend = $1;
+ int divisor = $2;
+ int scratch = $3;
+
+ //Put the dividend in the right position
+ if (dividend != ARM_R0)
+ {
+ if (divisor==ARM_R0)
+ {
+ //Prevent the divisor from being overwritten
+ if(dividend != ARM_R1)
+ {
+ //The place where the divisor should be
is free. Move it there
+ arm_mov_reg_reg(inst, ARM_R1, divisor);
+ divisor=1;
+ }
+ else
+ {
+ /* The dividend is where the divisor
should be.
+ We must use a scratch register to
swap them */
+ arm_mov_reg_reg(inst, scratch, divisor);
+ divisor=scratch;
+ }
+
+ }
+
+ arm_mov_reg_reg(inst, ARM_R0, dividend);
+ }
+
+ if (divisor != ARM_R1)
+ {
+ //Put the divisor in the right position
+ arm_mov_reg_reg(inst, ARM_R1, divisor);
+ }
+
+ //Perform the division by calling a function from the runtime
ABI
+ extern int __aeabi_idiv(int numerator, int denominator);
+ arm_call(inst, __aeabi_idiv);
+
+ //Move the result back where it is expected to be
+ if($1 != ARM_R0)
+ {
+ arm_mov_reg_reg(inst, $1, ARM_R0);
+ }
+ }
+
JIT_OP_INEG:
[reg] -> {
/* -x is the same as (0 - x) */
@@ -1870,73 +2003,53 @@
// $3 = length in bytes
// $4 = scratch register
- int scratchContains=0; //< Number of the parameter in the scratch
register. 0 means no param in scratch reg.
- int allOk=0;
+ int pointer=$1;
+ int value=$2;
+ int length=$3;
+ int scratch=$4;
+
/* Move the outgoing parameters in the right registers (if they are not
already where they should be */
- if ($1 != ARM_R0) {
- if($2 == ARM_R0)
+ if (pointer != ARM_R0) {
+ if(value == ARM_R0)
{
- arm_mov_reg_reg((inst), $4, ARM_R0);
- scratchContains=2;
+ //Prevent the value from being overwritten
+ arm_mov_reg_reg((inst), scratch, ARM_R0);
+ value=scratch;
}
- else if($3==ARM_R0)
+ else if(length==ARM_R0)
{
- arm_mov_reg_reg((inst), $4, ARM_R0);
- scratchContains=3;
+ //Prevent the length from being overwritten
+ arm_mov_reg_reg((inst), scratch, ARM_R0);
+ length=scratch;
}
- arm_mov_reg_reg((inst), ARM_R0, $1);
+
+ arm_mov_reg_reg((inst), ARM_R0, pointer);
+
+ //The register that contained the pointer is now free
+ scratch=pointer;
}
- if ($2 != ARM_R1)
+ if (value != ARM_R1)
{
- if ($3 == ARM_R1)
- {
- //We must save param 3, that's in ARM_R1
- if(scratchContains==2)
- {
- /*scratch reg contains the parameter that will
go in ARM_R1 and can't be overwritten. Copy param 3 directly to its register. */
- arm_mov_reg_reg(inst, ARM_R2, ARM_R1);
- allOk=1;
- }
- else
+ if (length == ARM_R1)
{
- assert(scratchContains==0);
- //Scratch reg is free. Use it to store param 3
- arm_mov_reg_reg(inst, $4, ARM_R1);
- scratchContains=3;
- }
+ //The length is stored in R1. Prevent it from being
overwritten
+ arm_mov_reg_reg(inst, scratch, length);
+ length=scratch;
}
//Set param 2
- if(scratchContains==2)
- {
- arm_mov_reg_reg((inst), ARM_R1, $4);
- }
- else
- {
- arm_mov_reg_reg((inst), ARM_R1, $2);
- }
- }
+ arm_mov_reg_reg((inst), ARM_R1, value);
- if(!allOk)
- {
- if($3 != ARM_R1)
- {
- //Param 3 still isn't in place
- if(scratchContains==3)
- {
- //Get param 3 from the scratch reg
- arm_mov_reg_reg(inst, ARM_R2, $4);
- }
- else
- {
- //Get param 3 from wherever it is
- arm_mov_reg_reg(inst, ARM_R2, $3);
+ //The register that contained the value is now free
+ scratch=value;
}
- allOk=1;
- }
+ if(length != ARM_R1)
+ {
+ //Param 3 still isn't in place: move it!
+ arm_mov_reg_reg(inst, ARM_R2, length);
}
arm_call(inst, jit_memset);