Quellcode durchsuchen

PPC: Add table indexing with variable keys or uint8_t.

Mike Pall vor 15 Jahren
Ursprung
Commit
b4c8b05ad5
1 geänderte Dateien mit 132 neuen und 4 gelöschten Zeilen
  1. 132 4
      src/buildvm_ppc.dasc

+ 132 - 4
src/buildvm_ppc.dasc

@@ -1250,7 +1250,43 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     break;
 
   case BC_TGETV:
-    |  NYI
+    |  // RA = dst*8, RB = table*8, RC = key*8
+    |  evlddx TAB:RB, BASE, RB
+    |   evlddx RC, BASE, RC
+    |  checktab TAB:RB
+    |  checkfail ->vmeta_tgetv
+    |  checknum RC
+    |  checkfail >5
+    |  // Convert number key to integer
+    |  efdctsi TMP2, RC
+    |   lwz TMP0, TAB:RB->asize
+    |  efdcfsi TMP1, TMP2
+    |   cmplw cr0, TMP0, TMP2
+    |  efdcmpeq cr1, RC, TMP1
+    |   lwz TMP1, TAB:RB->array
+    |  crand 4*cr0+gt, 4*cr0+gt, 4*cr1+gt
+    |   slwi TMP2, TMP2, 3
+    |  ble ->vmeta_tgetv		// Integer key and in array part?
+    |  evlddx TMP1, TMP1, TMP2
+    |  checknil TMP1
+    |  checkok >2
+    |1:
+    |  evstddx TMP1, BASE, RA
+    |  ins_next
+    |
+    |2:  // Check for __index if table value is nil.
+    |  lwz TAB:TMP2, TAB:RB->metatable
+    |  cmpwi TAB:TMP2, 0
+    |  beq <1				// No metatable: done.
+    |  lbz TMP0, TAB:TMP2->nomm
+    |  andi. TMP0, TMP0, 1<<MM_index
+    |  bne <1				// 'no __index' flag set: done.
+    |  b ->vmeta_tgetv
+    |
+    |5:
+    |  checkstr STR:RC			// String key?
+    |  checkok ->BC_TGETS_Z
+    |  b ->vmeta_tgetv
     break;
   case BC_TGETS:
     |  // RA = dst*8, RB = table*8, RC = str_const*8 (~)
@@ -1299,11 +1335,71 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |  b ->vmeta_tgets
     break;
   case BC_TGETB:
-    |  NYI
+    |  // RA = dst*8, RB = table*8, RC = index*8
+    |  evlddx TAB:RB, BASE, RB
+    |   srwi TMP0, RC, 3
+    |  checktab TAB:RB
+    |  checkfail ->vmeta_tgetb
+    |  lwz TMP1, TAB:RB->asize
+    |   lwz TMP2, TAB:RB->array
+    |  cmplw TMP0, TMP1
+    |  bge ->vmeta_tgetb
+    |  evlddx TMP1, TMP2, RC
+    |  checknil TMP1
+    |  checkok >5
+    |1:
+    |  evstddx TMP1, BASE, RA
+    |  ins_next
+    |
+    |5:  // Check for __index if table value is nil.
+    |  lwz TAB:TMP2, TAB:RB->metatable
+    |  cmpwi TAB:TMP2, 0
+    |  beq <1				// No metatable: done.
+    |  lbz TMP2, TAB:TMP2->nomm
+    |  andi. TMP2, TMP2, 1<<MM_index
+    |  bne <1				// 'no __index' flag set: done.
+    |  b ->vmeta_tgetb			// Caveat: preserve TMP0!
     break;
 
   case BC_TSETV:
-    |  NYI
+    |  // RA = src*8, RB = table*8, RC = key*8
+    |  evlddx TAB:RB, BASE, RB
+    |   evlddx RC, BASE, RC
+    |  checktab TAB:RB
+    |  checkfail ->vmeta_tsetv
+    |  checknum RC
+    |  checkfail >5
+    |  // Convert number key to integer
+    |  efdctsi TMP2, RC
+    |    evlddx SAVE0, BASE, RA
+    |   lwz TMP0, TAB:RB->asize
+    |  efdcfsi TMP1, TMP2
+    |   cmplw cr0, TMP0, TMP2
+    |  efdcmpeq cr1, RC, TMP1
+    |   lwz TMP1, TAB:RB->array
+    |  crand 4*cr0+gt, 4*cr0+gt, 4*cr1+gt
+    |   slwi TMP2, TMP2, 3
+    |  ble ->vmeta_tsetv		// Integer key and in array part?
+    |  evlddx TMP0, TMP1, TMP2
+    |  checknil TMP0
+    |  checkok >2
+    |1:
+    |  evstddx SAVE0, TMP1, TMP2
+    |  ins_next
+    |
+    |2:  // Check for __newindex if previous value is nil.
+    |  lwz TAB:TMP3, TAB:RB->metatable
+    |  cmpwi TAB:TMP3, 0
+    |  beq <1				// No metatable: done.
+    |  lbz TMP0, TAB:TMP3->nomm
+    |  andi. TMP0, TMP0, 1<<MM_newindex
+    |  bne <1				// 'no __newindex' flag set: done.
+    |  b ->vmeta_tsetv
+    |
+    |5:
+    |  checkstr STR:RC			// String key?
+    |  checkok ->BC_TSETS_Z
+    |  b ->vmeta_tsetv
     break;
   case BC_TSETS:
     |  // RA = src*8, RB = table*8, RC = str_const*8 (~)
@@ -1382,7 +1478,39 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |  b <3
     break;
   case BC_TSETB:
-    |  NYI
+    |  // RA = src*8, RB = table*8, RC = index*8
+    |  evlddx TAB:RB, BASE, RB
+    |   srwi TMP0, RC, 3
+    |  checktab TAB:RB
+    |  checkfail ->vmeta_tsetb
+    |  lwz TMP1, TAB:RB->asize
+    |   lwz TMP2, TAB:RB->array
+    |    lbz TMP3, TAB:RB->marked
+    |  cmplw TMP0, TMP1
+    |   evlddx SAVE0, BASE, RA
+    |  bge ->vmeta_tsetb
+    |  evlddx TMP1, TMP2, RC
+    |  checknil TMP1
+    |  checkok >5
+    |1:
+    |  andi. TMP0, TMP3, LJ_GC_BLACK	// isblack(table)
+    |   evstddx SAVE0, TMP2, RC
+    |  bne >7
+    |2:
+    |  ins_next
+    |
+    |5:  // Check for __newindex if previous value is nil.
+    |  lwz TAB:TMP1, TAB:RB->metatable
+    |  cmpwi TAB:TMP1, 0
+    |  beq <1				// No metatable: done.
+    |  lbz TMP1, TAB:TMP1->nomm
+    |  andi. TMP1, TMP1, 1<<MM_newindex
+    |  bne <1				// 'no __newindex' flag set: done.
+    |  b ->vmeta_tsetb			// Caveat: preserve TMP0!
+    |
+    |7:  // Possible table write barrier for the value. Skip valiswhite check.
+    |  barrierback TAB:RB, TMP3, TMP0
+    |  b <2
     break;
 
   case BC_TSETM: