| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | #include "master.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace factor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | instruction_operand::instruction_operand(relocation_entry rel_, code_block *compiled_, cell index_) : | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | 	rel(rel_), compiled(compiled_), index(index_), pointer((cell)compiled_->entry_point() + rel_.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 */ | 
					
						
							| 
									
										
										
										
											2009-11-23 19:51:08 -05:00
										 |  |  | fixnum instruction_operand::load_value_2_2() | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | { | 
					
						
							|  |  |  | 	cell *ptr = (cell *)pointer; | 
					
						
							| 
									
										
										
										
											2010-01-02 07:03:30 -05:00
										 |  |  | 	cell hi = (ptr[-2] & 0xffff); | 
					
						
							|  |  |  | 	cell lo = (ptr[-1] & 0xffff); | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 	return hi << 16 | lo; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Load a value from a bitfield of a PowerPC instruction */ | 
					
						
							| 
									
										
										
										
											2009-12-02 09:20:33 -05:00
										 |  |  | fixnum instruction_operand::load_value_masked(cell mask, cell bits, cell shift) | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-01-02 07:03:30 -05:00
										 |  |  | 	s32 *ptr = (s32 *)(pointer - sizeof(u32)); | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-02 07:03:30 -05:00
										 |  |  | 	return (((*ptr & (s32)mask) << bits) >> bits) << shift; | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-24 20:29:59 -05:00
										 |  |  | fixnum instruction_operand::load_value(cell relative_to) | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 	switch(rel.rel_class()) | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	case RC_ABSOLUTE_CELL: | 
					
						
							| 
									
										
										
										
											2010-01-02 07:03:30 -05:00
										 |  |  | 		return *(cell *)(pointer - sizeof(cell)); | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 	case RC_ABSOLUTE: | 
					
						
							| 
									
										
										
										
											2010-01-02 07:03:30 -05:00
										 |  |  | 		return *(u32 *)(pointer - sizeof(u32)); | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 	case RC_RELATIVE: | 
					
						
							| 
									
										
										
										
											2010-01-02 07:03:30 -05:00
										 |  |  | 		return *(s32 *)(pointer - sizeof(u32)) + relative_to; | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 	case RC_ABSOLUTE_PPC_2_2: | 
					
						
							| 
									
										
										
										
											2009-11-23 19:51:08 -05:00
										 |  |  | 		return load_value_2_2(); | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 	case RC_ABSOLUTE_PPC_2: | 
					
						
							| 
									
										
										
										
											2009-12-02 17:24:42 -05:00
										 |  |  | 		return load_value_masked(rel_absolute_ppc_2_mask,16,0); | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 	case RC_RELATIVE_PPC_2: | 
					
						
							| 
									
										
										
										
											2010-01-12 09:02:10 -05:00
										 |  |  | 		return load_value_masked(rel_relative_ppc_2_mask,16,0) + relative_to - sizeof(cell); | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 	case RC_RELATIVE_PPC_3: | 
					
						
							| 
									
										
										
										
											2010-01-12 09:02:10 -05:00
										 |  |  | 		return load_value_masked(rel_relative_ppc_3_mask,6,0) + relative_to - sizeof(cell); | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 	case RC_RELATIVE_ARM_3: | 
					
						
							| 
									
										
										
										
											2010-01-02 07:03:30 -05:00
										 |  |  | 		return load_value_masked(rel_relative_arm_3_mask,6,2) + relative_to + sizeof(cell); | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 	case RC_INDIRECT_ARM: | 
					
						
							| 
									
										
										
										
											2010-01-02 07:03:30 -05:00
										 |  |  | 		return load_value_masked(rel_indirect_arm_mask,20,0) + relative_to; | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 	case RC_INDIRECT_ARM_PC: | 
					
						
							| 
									
										
										
										
											2010-01-02 07:03:30 -05:00
										 |  |  | 		return load_value_masked(rel_indirect_arm_mask,20,0) + relative_to + sizeof(cell); | 
					
						
							|  |  |  | 	case RC_ABSOLUTE_2: | 
					
						
							|  |  |  | 		return *(u16 *)(pointer - sizeof(u16)); | 
					
						
							| 
									
										
										
										
											2010-04-12 17:22:41 -04:00
										 |  |  | 	case RC_ABSOLUTE_1: | 
					
						
							|  |  |  | 		return *(u8 *)(pointer - sizeof(u8)); | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 		critical_error("Bad rel class",rel.rel_class()); | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-24 20:29:59 -05:00
										 |  |  | fixnum instruction_operand::load_value() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return load_value(pointer); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | code_block *instruction_operand::load_code_block(cell relative_to) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return ((code_block *)load_value(relative_to) - 1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-25 18:20:48 -05:00
										 |  |  | code_block *instruction_operand::load_code_block() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 	return load_code_block(pointer); | 
					
						
							| 
									
										
										
										
											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 */ | 
					
						
							| 
									
										
										
										
											2009-11-23 19:51:08 -05:00
										 |  |  | void instruction_operand::store_value_2_2(fixnum value) | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | { | 
					
						
							|  |  |  | 	cell *ptr = (cell *)pointer; | 
					
						
							| 
									
										
										
										
											2010-01-02 07:03:30 -05:00
										 |  |  | 	ptr[-2] = ((ptr[-2] & ~0xffff) | ((value >> 16) & 0xffff)); | 
					
						
							|  |  |  | 	ptr[-1] = ((ptr[-1] & ~0xffff) | (value & 0xffff)); | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Store a value into a bitfield of a PowerPC instruction */ | 
					
						
							| 
									
										
										
										
											2009-12-02 09:20:33 -05:00
										 |  |  | void instruction_operand::store_value_masked(fixnum value, cell mask, cell shift) | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-01-02 07:03:30 -05:00
										 |  |  | 	u32 *ptr = (u32 *)(pointer - sizeof(u32)); | 
					
						
							| 
									
										
										
										
											2010-01-24 08:17:18 -05:00
										 |  |  | 	*ptr = (u32)((*ptr & ~mask) | ((value >> shift) & mask)); | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-23 19:51:08 -05:00
										 |  |  | void instruction_operand::store_value(fixnum absolute_value) | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | { | 
					
						
							|  |  |  | 	fixnum relative_value = absolute_value - pointer; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 	switch(rel.rel_class()) | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	case RC_ABSOLUTE_CELL: | 
					
						
							| 
									
										
										
										
											2010-01-02 07:03:30 -05:00
										 |  |  | 		*(cell *)(pointer - sizeof(cell)) = absolute_value; | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case RC_ABSOLUTE: | 
					
						
							| 
									
										
										
										
											2010-01-24 08:17:18 -05:00
										 |  |  | 		*(u32 *)(pointer - sizeof(u32)) = (u32)absolute_value; | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case RC_RELATIVE: | 
					
						
							| 
									
										
										
										
											2010-01-24 08:17:18 -05:00
										 |  |  | 		*(s32 *)(pointer - sizeof(s32)) = (s32)relative_value; | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case RC_ABSOLUTE_PPC_2_2: | 
					
						
							| 
									
										
										
										
											2009-11-23 19:51:08 -05:00
										 |  |  | 		store_value_2_2(absolute_value); | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case RC_ABSOLUTE_PPC_2: | 
					
						
							| 
									
										
										
										
											2009-11-23 19:51:08 -05:00
										 |  |  | 		store_value_masked(absolute_value,rel_absolute_ppc_2_mask,0); | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case RC_RELATIVE_PPC_2: | 
					
						
							| 
									
										
										
										
											2010-01-12 09:02:10 -05:00
										 |  |  | 		store_value_masked(relative_value + sizeof(cell),rel_relative_ppc_2_mask,0); | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case RC_RELATIVE_PPC_3: | 
					
						
							| 
									
										
										
										
											2010-01-12 09:02:10 -05:00
										 |  |  | 		store_value_masked(relative_value + sizeof(cell),rel_relative_ppc_3_mask,0); | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case RC_RELATIVE_ARM_3: | 
					
						
							| 
									
										
										
										
											2010-01-02 07:03:30 -05:00
										 |  |  | 		store_value_masked(relative_value - sizeof(cell),rel_relative_arm_3_mask,2); | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case RC_INDIRECT_ARM: | 
					
						
							| 
									
										
										
										
											2010-01-02 07:03:30 -05:00
										 |  |  | 		store_value_masked(relative_value,rel_indirect_arm_mask,0); | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case RC_INDIRECT_ARM_PC: | 
					
						
							| 
									
										
										
										
											2010-01-02 07:03:30 -05:00
										 |  |  | 		store_value_masked(relative_value - sizeof(cell),rel_indirect_arm_mask,0); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case RC_ABSOLUTE_2: | 
					
						
							| 
									
										
										
										
											2010-01-16 09:43:22 -05:00
										 |  |  | 		*(u16 *)(pointer - sizeof(u16)) = (u16)absolute_value; | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2010-04-12 17:22:41 -04:00
										 |  |  | 	case RC_ABSOLUTE_1: | 
					
						
							|  |  |  | 		*(u8 *)(pointer - sizeof(u8)) = (u8)absolute_value; | 
					
						
							|  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 		critical_error("Bad rel class",rel.rel_class()); | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-25 18:20:48 -05:00
										 |  |  | void instruction_operand::store_code_block(code_block *compiled) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | 	store_value((cell)compiled->entry_point()); | 
					
						
							| 
									
										
										
										
											2009-11-25 18:20:48 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | } |