PPC: Add loop instructions.

This commit is contained in:
Mike Pall 2010-09-01 20:24:08 +02:00
parent 7ccdc8045b
commit 222e01fa83

View File

@ -223,6 +223,12 @@
|.macro checkanyfail, label; bns label; .endmacro |.macro checkanyfail, label; bns label; .endmacro
|.endif |.endif
| |
|.macro branch_RD
| srwi TMP0, RD, 1
| add PC, PC, TMP0
| addis PC, PC, -(BCBIAS_J*4 >> 16)
|.endmacro
|
|// Assumes DISPATCH is relative to GL. |// Assumes DISPATCH is relative to GL.
#define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field)) #define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field))
#define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field)) #define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field))
@ -906,6 +912,7 @@ static void build_subroutines(BuildCtx *ctx)
/* Generate the code for a single instruction. */ /* Generate the code for a single instruction. */
static void build_ins(BuildCtx *ctx, BCOp op, int defop) static void build_ins(BuildCtx *ctx, BCOp op, int defop)
{ {
int vk = 0;
|=>defop: |=>defop:
switch (op) { switch (op) {
@ -1230,7 +1237,51 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
#endif #endif
case BC_FORI: case BC_FORI:
case BC_IFORL: case BC_IFORL:
| NYI | // RA = base*8, RD = target (after end of loop or start of loop)
vk = (op == BC_IFORL || op == BC_JFORL);
| add RA, BASE, RA
| evldd TMP1, FORL_IDX*8(RA)
| evldd TMP2, FORL_STOP*8(RA)
| evldd TMP3, FORL_STEP*8(RA)
if (!vk) {
| evcmpgtu cr0, TMP1, TISNUM
| evcmpgtu cr1, TMP2, TISNUM
| evcmpgtu cr7, TMP3, TISNUM
| cror 4*cr0+lt, 4*cr0+lt, 4*cr1+lt
| cror 4*cr0+lt, 4*cr0+lt, 4*cr7+lt
| blt ->vmeta_for
}
if (vk) {
| efdadd TMP1, TMP1, TMP3
}
if (vk) {
| evstdd TMP1, FORL_IDX*8(RA)
}
| evcmpgts TMP3, TISNIL
| evstdd TMP1, FORL_EXT*8(RA)
| bge >2
| efdcmpgt TMP1, TMP2
|1:
if (op != BC_JFORL) {
| srwi RD, RD, 1
| add RD, PC, RD
if (op == BC_JFORI) {
| addis PC, RD, -(BCBIAS_J*4 >> 16)
} else {
| addis RD, RD, -(BCBIAS_J*4 >> 16)
}
}
if (op == BC_FORI) {
| iselgt PC, RD, PC
} else if (op == BC_IFORL) {
| iselgt PC, PC, RD
} else {
| ble =>BC_JLOOP
}
| ins_next
|2:
| efdcmpgt TMP2, TMP1
| b <1
break; break;
case BC_ITERL: case BC_ITERL:
@ -1245,26 +1296,46 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
break; break;
#endif #endif
case BC_IITERL: case BC_IITERL:
| NYI | // RA = base*8, RD = target
| evlddx TMP1, BASE, RA
| subi RA, RA, 8
| checknil TMP1
| checkok >1 // Stop if iterator returned nil.
if (op == BC_JITERL) {
| NYI
} else {
| branch_RD // Otherwise save control var + branch.
| evstddx TMP1, BASE, RA
}
|1:
| ins_next
break; break;
case BC_LOOP: case BC_LOOP:
| NYI | // RA = base*8, RD = target (loop extent)
| // Note: RA/RD is only used by trace recorder to determine scope/extent
| // This opcode does NOT jump, it's only purpose is to detect a hot loop.
#if LJ_HASJIT #if LJ_HASJIT
| // Fall through. Assumes BC_ILOOP follows. | hotloop
#endif #endif
| // Fall through. Assumes BC_ILOOP follows.
break; break;
case BC_ILOOP: case BC_ILOOP:
| NYI | // RA = base*8, RD = target (loop extent)
| ins_next
break; break;
case BC_JLOOP: case BC_JLOOP:
#if LJ_HASJIT
| NYI | NYI
#endif
break; break;
case BC_JMP: case BC_JMP:
| hotcall | // RA = base*8 (only used by trace recorder), RD = target
| branch_RD
| ins_next
break; break;
/* -- Function headers -------------------------------------------------- */ /* -- Function headers -------------------------------------------------- */