]> gitweb.factorcode.org Git - factor.git/blobdiff - vm/instruction_operands.cpp
webapps.wiki: adding search bar
[factor.git] / vm / instruction_operands.cpp
index af7d363aefa82f5beeb9db1cf3035a22dfa762d9..c59f3b9ed50d7a823bde50b8de1bbfd648089558 100644 (file)
 #include "master.hpp"
 
-namespace factor
-{
-
-instruction_operand::instruction_operand(relocation_entry rel_, code_block *compiled_, cell index_) :
-       rel(rel_), compiled(compiled_), index(index_), pointer((cell)compiled_->entry_point() + rel_.rel_offset()) {}
-
-/* Load a 32-bit value from a PowerPC LIS/ORI sequence */
-fixnum instruction_operand::load_value_2_2()
-{
-       cell *ptr = (cell *)pointer;
-       cell hi = (ptr[-2] & 0xffff);
-       cell lo = (ptr[-1] & 0xffff);
-       return hi << 16 | lo;
-}
-
-/* Load a value from a bitfield of a PowerPC instruction */
-fixnum instruction_operand::load_value_masked(cell mask, cell bits, cell shift)
-{
-       s32 *ptr = (s32 *)(pointer - sizeof(u32));
-
-       return (((*ptr & (s32)mask) << bits) >> bits) << shift;
+namespace factor {
+
+instruction_operand::instruction_operand(relocation_entry rel,
+                                         code_block* compiled, cell index)
+    : rel(rel),
+      compiled(compiled),
+      index(index),
+      pointer(compiled->entry_point() + rel.offset()) {}
+
+// Load a 32-bit value from a PowerPC LIS/ORI sequence
+fixnum instruction_operand::load_value_2_2() {
+  uint32_t* ptr = (uint32_t*)pointer;
+  cell hi = (ptr[-2] & 0xffff);
+  cell lo = (ptr[-1] & 0xffff);
+  return hi << 16 | lo;
 }
 
-fixnum instruction_operand::load_value(cell relative_to)
-{
-       switch(rel.rel_class())
-       {
-       case RC_ABSOLUTE_CELL:
-               return *(cell *)(pointer - sizeof(cell));
-       case RC_ABSOLUTE:
-               return *(u32 *)(pointer - sizeof(u32));
-       case RC_RELATIVE:
-               return *(s32 *)(pointer - sizeof(u32)) + relative_to;
-       case RC_ABSOLUTE_PPC_2_2:
-               return load_value_2_2();
-       case RC_ABSOLUTE_PPC_2:
-               return load_value_masked(rel_absolute_ppc_2_mask,16,0);
-       case RC_RELATIVE_PPC_2:
-               return load_value_masked(rel_relative_ppc_2_mask,16,0) + relative_to - sizeof(cell);
-       case RC_RELATIVE_PPC_3:
-               return load_value_masked(rel_relative_ppc_3_mask,6,0) + relative_to - sizeof(cell);
-       case RC_RELATIVE_ARM_3:
-               return load_value_masked(rel_relative_arm_3_mask,6,2) + relative_to + sizeof(cell);
-       case RC_INDIRECT_ARM:
-               return load_value_masked(rel_indirect_arm_mask,20,0) + relative_to;
-       case RC_INDIRECT_ARM_PC:
-               return load_value_masked(rel_indirect_arm_mask,20,0) + relative_to + sizeof(cell);
-       case RC_ABSOLUTE_2:
-               return *(u16 *)(pointer - sizeof(u16));
-       case RC_ABSOLUTE_1:
-               return *(u8 *)(pointer - sizeof(u8));
-       default:
-               critical_error("Bad rel class",rel.rel_class());
-               return 0;
-       }
+// Load a 64-bit value from a PowerPC LIS/ORI/SLDI/ORIS/ORI sequence
+fixnum instruction_operand::load_value_2_2_2_2() {
+  uint32_t* ptr = (uint32_t*)pointer;
+  uint64_t hhi = (ptr[-5] & 0xffff);
+  uint64_t hlo = (ptr[-4] & 0xffff);
+  uint64_t lhi = (ptr[-2] & 0xffff);
+  uint64_t llo = (ptr[-1] & 0xffff);
+  uint64_t val = hhi << 48 | hlo << 32 | lhi << 16 | llo;
+  return (cell)val;
 }
 
-fixnum instruction_operand::load_value()
-{
-       return load_value(pointer);
-}
+// Load a value from a bitfield of a PowerPC instruction
+fixnum instruction_operand::load_value_masked(cell mask, cell bits,
+                                              cell shift) {
+  int32_t* ptr = (int32_t*)(pointer - sizeof(uint32_t));
 
-cell instruction_operand::load_float()
-{
-       return (cell)load_value() - boxed_float_offset;
+  return (((*ptr & (int32_t)mask) << bits) >> bits) << shift;
 }
 
-cell instruction_operand::load_float(cell pointer)
-{
-       return (cell)load_value(pointer) - boxed_float_offset;
+fixnum instruction_operand::load_value(cell relative_to) {
+  switch (rel.klass()) {
+    case RC_ABSOLUTE_CELL:
+      return *(cell*)(pointer - sizeof(cell));
+    case RC_ABSOLUTE:
+      return *(uint32_t*)(pointer - sizeof(uint32_t));
+    case RC_RELATIVE:
+      return *(int32_t*)(pointer - sizeof(uint32_t)) + relative_to;
+    case RC_ABSOLUTE_PPC_2_2:
+      return load_value_2_2();
+    case RC_ABSOLUTE_PPC_2:
+      return load_value_masked(rel_absolute_ppc_2_mask, 16, 0);
+    case RC_RELATIVE_PPC_2_PC:
+      return load_value_masked(rel_relative_ppc_2_mask, 16, 0) + relative_to -
+             4;
+    case RC_RELATIVE_PPC_3_PC:
+      return load_value_masked(rel_relative_ppc_3_mask, 6, 0) + relative_to - 4;
+    case RC_RELATIVE_ARM_3:
+      return load_value_masked(rel_relative_arm_3_mask, 6, 2) + relative_to +
+             sizeof(cell);
+    case RC_INDIRECT_ARM:
+      return load_value_masked(rel_indirect_arm_mask, 20, 0) + relative_to;
+    case RC_INDIRECT_ARM_PC:
+      return load_value_masked(rel_indirect_arm_mask, 20, 0) + relative_to +
+             sizeof(cell);
+    case RC_ABSOLUTE_2:
+      return *(uint16_t*)(pointer - sizeof(uint16_t));
+    case RC_ABSOLUTE_1:
+      return *(uint8_t*)(pointer - sizeof(uint8_t));
+    case RC_ABSOLUTE_PPC_2_2_2_2:
+      return load_value_2_2_2_2();
+    default:
+      critical_error("Bad rel class", rel.klass());
+      return 0;
+  }
 }
 
-code_block *instruction_operand::load_code_block(cell relative_to)
-{
-       return ((code_block *)load_value(relative_to) - 1);
+code_block* instruction_operand::load_code_block() {
+  return ((code_block*)load_value(pointer) - 1);
 }
 
-code_block *instruction_operand::load_code_block()
-{
-       return load_code_block(pointer);
+// Store a 32-bit value into a PowerPC LIS/ORI sequence
+void instruction_operand::store_value_2_2(fixnum value) {
+  uint32_t* ptr = (uint32_t*)pointer;
+  ptr[-2] = ((ptr[-2] & ~0xffff) | ((value >> 16) & 0xffff));
+  ptr[-1] = ((ptr[-1] & ~0xffff) | (value & 0xffff));
 }
 
-/* Store a 32-bit value into a PowerPC LIS/ORI sequence */
-void instruction_operand::store_value_2_2(fixnum value)
-{
-       cell *ptr = (cell *)pointer;
-       ptr[-2] = ((ptr[-2] & ~0xffff) | ((value >> 16) & 0xffff));
-       ptr[-1] = ((ptr[-1] & ~0xffff) | (value & 0xffff));
-}
-
-/* Store a value into a bitfield of a PowerPC instruction */
-void instruction_operand::store_value_masked(fixnum value, cell mask, cell shift)
-{
-       u32 *ptr = (u32 *)(pointer - sizeof(u32));
-       *ptr = (u32)((*ptr & ~mask) | ((value >> shift) & mask));
-}
-
-void instruction_operand::store_value(fixnum absolute_value)
-{
-       fixnum relative_value = absolute_value - pointer;
-
-       switch(rel.rel_class())
-       {
-       case RC_ABSOLUTE_CELL:
-               *(cell *)(pointer - sizeof(cell)) = absolute_value;
-               break;
-       case RC_ABSOLUTE:
-               *(u32 *)(pointer - sizeof(u32)) = (u32)absolute_value;
-               break;
-       case RC_RELATIVE:
-               *(s32 *)(pointer - sizeof(s32)) = (s32)relative_value;
-               break;
-       case RC_ABSOLUTE_PPC_2_2:
-               store_value_2_2(absolute_value);
-               break;
-       case RC_ABSOLUTE_PPC_2:
-               store_value_masked(absolute_value,rel_absolute_ppc_2_mask,0);
-               break;
-       case RC_RELATIVE_PPC_2:
-               store_value_masked(relative_value + sizeof(cell),rel_relative_ppc_2_mask,0);
-               break;
-       case RC_RELATIVE_PPC_3:
-               store_value_masked(relative_value + sizeof(cell),rel_relative_ppc_3_mask,0);
-               break;
-       case RC_RELATIVE_ARM_3:
-               store_value_masked(relative_value - sizeof(cell),rel_relative_arm_3_mask,2);
-               break;
-       case RC_INDIRECT_ARM:
-               store_value_masked(relative_value,rel_indirect_arm_mask,0);
-               break;
-       case RC_INDIRECT_ARM_PC:
-               store_value_masked(relative_value - sizeof(cell),rel_indirect_arm_mask,0);
-               break;
-       case RC_ABSOLUTE_2:
-               *(u16 *)(pointer - sizeof(u16)) = (u16)absolute_value;
-               break;
-       case RC_ABSOLUTE_1:
-               *(u8 *)(pointer - sizeof(u8)) = (u8)absolute_value;
-               break;
-       default:
-               critical_error("Bad rel class",rel.rel_class());
-               break;
-       }
+// Store a 64-bit value into a PowerPC LIS/ORI/SLDI/ORIS/ORI sequence
+void instruction_operand::store_value_2_2_2_2(fixnum value) {
+  uint64_t val = value;
+  uint32_t* ptr = (uint32_t*)pointer;
+  ptr[-5] = ((ptr[-5] & ~0xffff) | ((val >> 48) & 0xffff));
+  ptr[-4] = ((ptr[-4] & ~0xffff) | ((val >> 32) & 0xffff));
+  ptr[-2] = ((ptr[-2] & ~0xffff) | ((val >> 16) & 0xffff));
+  ptr[-1] = ((ptr[-1] & ~0xffff) | ((val >> 0) & 0xffff));
 }
 
-void instruction_operand::store_float(cell value)
-{
-       store_value((fixnum)value + boxed_float_offset);
+// Store a value into a bitfield of a PowerPC instruction
+void instruction_operand::store_value_masked(fixnum value, cell mask,
+                                             cell shift) {
+  uint32_t* ptr = (uint32_t*)(pointer - sizeof(uint32_t));
+  *ptr = (uint32_t)((*ptr & ~mask) | ((value >> shift) & mask));
 }
 
-void instruction_operand::store_code_block(code_block *compiled)
-{
-       store_value((cell)compiled->entry_point());
+void instruction_operand::store_value(fixnum absolute_value) {
+  fixnum relative_value = absolute_value - pointer;
+
+  switch (rel.klass()) {
+    case RC_ABSOLUTE_CELL:
+      *(cell*)(pointer - sizeof(cell)) = absolute_value;
+      break;
+    case RC_ABSOLUTE:
+      *(uint32_t*)(pointer - sizeof(uint32_t)) = (uint32_t)absolute_value;
+      break;
+    case RC_RELATIVE:
+      *(int32_t*)(pointer - sizeof(int32_t)) = (int32_t)relative_value;
+      break;
+    case RC_ABSOLUTE_PPC_2_2:
+      store_value_2_2(absolute_value);
+      break;
+    case RC_ABSOLUTE_PPC_2:
+      store_value_masked(absolute_value, rel_absolute_ppc_2_mask, 0);
+      break;
+    case RC_RELATIVE_PPC_2_PC:
+      store_value_masked(relative_value + 4, rel_relative_ppc_2_mask, 0);
+      break;
+    case RC_RELATIVE_PPC_3_PC:
+      store_value_masked(relative_value + 4, rel_relative_ppc_3_mask, 0);
+      break;
+    case RC_RELATIVE_ARM_3:
+      store_value_masked(relative_value - sizeof(cell), rel_relative_arm_3_mask,
+                         2);
+      break;
+    case RC_INDIRECT_ARM:
+      store_value_masked(relative_value, rel_indirect_arm_mask, 0);
+      break;
+    case RC_INDIRECT_ARM_PC:
+      store_value_masked(relative_value - sizeof(cell), rel_indirect_arm_mask,
+                         0);
+      break;
+    case RC_ABSOLUTE_2:
+      *(uint16_t*)(pointer - sizeof(uint16_t)) = (uint16_t)absolute_value;
+      break;
+    case RC_ABSOLUTE_1:
+      *(uint8_t*)(pointer - sizeof(uint8_t)) = (uint8_t)absolute_value;
+      break;
+    case RC_ABSOLUTE_PPC_2_2_2_2:
+      store_value_2_2_2_2(absolute_value);
+      break;
+    default:
+      critical_error("Bad rel class", rel.klass());
+      break;
+  }
 }
 
 }