| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | #include "master.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:06:39 -04:00
										 |  |  | namespace factor { | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-12 23:20:43 -04:00
										 |  |  | instruction_operand::instruction_operand(relocation_entry rel, | 
					
						
							|  |  |  |                                          code_block* compiled, cell index) | 
					
						
							|  |  |  |     : rel(rel), | 
					
						
							|  |  |  |       compiled(compiled), | 
					
						
							|  |  |  |       index(index), | 
					
						
							| 
									
										
										
										
											2015-12-11 22:02:53 -05:00
										 |  |  |       pointer(compiled->entry_point() + rel.offset()) {} | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | /* Load a 32-bit value from a PowerPC LIS/ORI sequence */ | 
					
						
							| 
									
										
										
										
											2013-05-11 22:06:39 -04:00
										 |  |  | fixnum instruction_operand::load_value_2_2() { | 
					
						
							| 
									
										
										
										
											2013-05-13 00:28:25 -04:00
										 |  |  |   uint32_t* ptr = (uint32_t*)pointer; | 
					
						
							| 
									
										
										
										
											2013-05-11 22:06:39 -04:00
										 |  |  |   cell hi = (ptr[-2] & 0xffff); | 
					
						
							|  |  |  |   cell lo = (ptr[-1] & 0xffff); | 
					
						
							|  |  |  |   return hi << 16 | lo; | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-20 18:11:50 -04:00
										 |  |  | /* Load a 64-bit value from a PowerPC LIS/ORI/SLDI/ORIS/ORI sequence */ | 
					
						
							| 
									
										
										
										
											2013-05-11 22:06:39 -04:00
										 |  |  | fixnum instruction_operand::load_value_2_2_2_2() { | 
					
						
							| 
									
										
										
										
											2013-05-13 00:28:25 -04:00
										 |  |  |   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; | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |   return (cell)val; | 
					
						
							| 
									
										
										
										
											2011-05-20 18:11:50 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | /* Load a value from a bitfield of a PowerPC instruction */ | 
					
						
							| 
									
										
										
										
											2013-05-11 22:06:39 -04:00
										 |  |  | fixnum instruction_operand::load_value_masked(cell mask, cell bits, | 
					
						
							|  |  |  |                                               cell shift) { | 
					
						
							| 
									
										
										
										
											2013-05-13 00:28:25 -04:00
										 |  |  |   int32_t* ptr = (int32_t*)(pointer - sizeof(uint32_t)); | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |   return (((*ptr & (int32_t)mask) << bits) >> bits) << shift; | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:06:39 -04:00
										 |  |  | fixnum instruction_operand::load_value(cell relative_to) { | 
					
						
							| 
									
										
										
										
											2015-12-11 22:02:53 -05:00
										 |  |  |   switch (rel.klass()) { | 
					
						
							| 
									
										
										
										
											2013-05-11 22:06:39 -04:00
										 |  |  |     case RC_ABSOLUTE_CELL: | 
					
						
							|  |  |  |       return *(cell*)(pointer - sizeof(cell)); | 
					
						
							|  |  |  |     case RC_ABSOLUTE: | 
					
						
							| 
									
										
										
										
											2013-05-13 00:28:25 -04:00
										 |  |  |       return *(uint32_t*)(pointer - sizeof(uint32_t)); | 
					
						
							| 
									
										
										
										
											2013-05-11 22:06:39 -04:00
										 |  |  |     case RC_RELATIVE: | 
					
						
							| 
									
										
										
										
											2013-05-13 00:28:25 -04:00
										 |  |  |       return *(int32_t*)(pointer - sizeof(uint32_t)) + relative_to; | 
					
						
							| 
									
										
										
										
											2013-05-11 22:06:39 -04:00
										 |  |  |     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: | 
					
						
							| 
									
										
										
										
											2013-05-13 00:28:25 -04:00
										 |  |  |       return *(uint16_t*)(pointer - sizeof(uint16_t)); | 
					
						
							| 
									
										
										
										
											2013-05-11 22:06:39 -04:00
										 |  |  |     case RC_ABSOLUTE_1: | 
					
						
							| 
									
										
										
										
											2013-05-13 00:28:25 -04:00
										 |  |  |       return *(uint8_t*)(pointer - sizeof(uint8_t)); | 
					
						
							| 
									
										
										
										
											2013-05-11 22:06:39 -04:00
										 |  |  |     case RC_ABSOLUTE_PPC_2_2_2_2: | 
					
						
							|  |  |  |       return load_value_2_2_2_2(); | 
					
						
							|  |  |  |     default: | 
					
						
							| 
									
										
										
										
											2015-12-11 22:02:53 -05:00
										 |  |  |       critical_error("Bad rel class", rel.klass()); | 
					
						
							| 
									
										
										
										
											2013-05-11 22:06:39 -04:00
										 |  |  |       return 0; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:06:39 -04:00
										 |  |  | code_block* instruction_operand::load_code_block() { | 
					
						
							| 
									
										
										
										
											2015-12-13 02:23:55 -05:00
										 |  |  |   return ((code_block*)load_value(pointer) - 1); | 
					
						
							| 
									
										
										
										
											2009-11-25 18:20:48 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | /* Store a 32-bit value into a PowerPC LIS/ORI sequence */ | 
					
						
							| 
									
										
										
										
											2013-05-11 22:06:39 -04:00
										 |  |  | void instruction_operand::store_value_2_2(fixnum value) { | 
					
						
							| 
									
										
										
										
											2013-05-13 00:28:25 -04:00
										 |  |  |   uint32_t* ptr = (uint32_t*)pointer; | 
					
						
							| 
									
										
										
										
											2013-05-11 22:06:39 -04:00
										 |  |  |   ptr[-2] = ((ptr[-2] & ~0xffff) | ((value >> 16) & 0xffff)); | 
					
						
							|  |  |  |   ptr[-1] = ((ptr[-1] & ~0xffff) | (value & 0xffff)); | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-20 18:11:50 -04:00
										 |  |  | /* Store a 64-bit value into a PowerPC LIS/ORI/SLDI/ORIS/ORI sequence */ | 
					
						
							| 
									
										
										
										
											2013-05-11 22:06:39 -04:00
										 |  |  | void instruction_operand::store_value_2_2_2_2(fixnum value) { | 
					
						
							| 
									
										
										
										
											2013-05-13 00:28:25 -04:00
										 |  |  |   uint64_t val = value; | 
					
						
							|  |  |  |   uint32_t* ptr = (uint32_t*)pointer; | 
					
						
							| 
									
										
										
										
											2013-05-11 22:06:39 -04:00
										 |  |  |   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)); | 
					
						
							| 
									
										
										
										
											2011-05-20 18:11:50 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | /* Store a value into a bitfield of a PowerPC instruction */ | 
					
						
							| 
									
										
										
										
											2013-05-11 22:06:39 -04:00
										 |  |  | void instruction_operand::store_value_masked(fixnum value, cell mask, | 
					
						
							|  |  |  |                                              cell shift) { | 
					
						
							| 
									
										
										
										
											2013-05-13 00:28:25 -04:00
										 |  |  |   uint32_t* ptr = (uint32_t*)(pointer - sizeof(uint32_t)); | 
					
						
							|  |  |  |   *ptr = (uint32_t)((*ptr & ~mask) | ((value >> shift) & mask)); | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:06:39 -04:00
										 |  |  | void instruction_operand::store_value(fixnum absolute_value) { | 
					
						
							|  |  |  |   fixnum relative_value = absolute_value - pointer; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-11 22:02:53 -05:00
										 |  |  |   switch (rel.klass()) { | 
					
						
							| 
									
										
										
										
											2013-05-11 22:06:39 -04:00
										 |  |  |     case RC_ABSOLUTE_CELL: | 
					
						
							|  |  |  |       *(cell*)(pointer - sizeof(cell)) = absolute_value; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case RC_ABSOLUTE: | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |       *(uint32_t*)(pointer - sizeof(uint32_t)) = (uint32_t)absolute_value; | 
					
						
							| 
									
										
										
										
											2013-05-11 22:06:39 -04:00
										 |  |  |       break; | 
					
						
							|  |  |  |     case RC_RELATIVE: | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |       *(int32_t*)(pointer - sizeof(int32_t)) = (int32_t)relative_value; | 
					
						
							| 
									
										
										
										
											2013-05-11 22:06:39 -04:00
										 |  |  |       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: | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |       *(uint16_t*)(pointer - sizeof(uint16_t)) = (uint16_t)absolute_value; | 
					
						
							| 
									
										
										
										
											2013-05-11 22:06:39 -04:00
										 |  |  |       break; | 
					
						
							|  |  |  |     case RC_ABSOLUTE_1: | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |       *(uint8_t*)(pointer - sizeof(uint8_t)) = (uint8_t)absolute_value; | 
					
						
							| 
									
										
										
										
											2013-05-11 22:06:39 -04:00
										 |  |  |       break; | 
					
						
							|  |  |  |     case RC_ABSOLUTE_PPC_2_2_2_2: | 
					
						
							|  |  |  |       store_value_2_2_2_2(absolute_value); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     default: | 
					
						
							| 
									
										
										
										
											2015-12-11 22:02:53 -05:00
										 |  |  |       critical_error("Bad rel class", rel.klass()); | 
					
						
							| 
									
										
										
										
											2013-05-11 22:06:39 -04:00
										 |  |  |       break; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |