| 
									
										
										
										
											2009-05-04 02:46:13 -04:00
										 |  |  | namespace factor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-20 18:11:50 -04:00
										 |  |  | #ifdef FACTOR_64
 | 
					
						
							|  |  |  | #define FACTOR_CPU_STRING "ppc.64"
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #define FACTOR_CPU_STRING "ppc.32"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-06 20:53:52 -05:00
										 |  |  | #define CALLSTACK_BOTTOM(ctx) (void *)(ctx->callstack_seg->end - 32)
 | 
					
						
							| 
									
										
										
										
											2010-03-26 22:44:43 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-07 20:47:38 -04:00
										 |  |  | /* In the instruction sequence:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    LOAD32 r3,... | 
					
						
							|  |  |  |    B blah | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    the offset from the immediate operand to LOAD32 to the instruction after | 
					
						
							| 
									
										
										
										
											2010-01-12 09:02:10 -05:00
										 |  |  |    the branch is one instruction. */ | 
					
						
							|  |  |  | static const fixnum xt_tail_pic_offset = 4; | 
					
						
							| 
									
										
										
										
											2009-05-07 20:47:38 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-06 16:39:03 -04:00
										 |  |  | inline static void check_call_site(cell return_address) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-05-20 18:11:50 -04:00
										 |  |  | 	u32 insn = *(u32 *)return_address; | 
					
						
							| 
									
										
										
										
											2009-05-07 20:47:38 -04:00
										 |  |  | 	/* Check that absolute bit is 0 */ | 
					
						
							| 
									
										
										
										
											2011-11-17 23:42:30 -05:00
										 |  |  | 	FACTOR_ASSERT((insn & 0x2) == 0x0); | 
					
						
							| 
									
										
										
										
											2009-05-07 20:47:38 -04:00
										 |  |  | 	/* Check that instruction is branch */ | 
					
						
							| 
									
										
										
										
											2011-11-17 23:42:30 -05:00
										 |  |  | 	FACTOR_ASSERT((insn >> 26) == 0x12); | 
					
						
							| 
									
										
										
										
											2009-05-06 16:39:03 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-20 18:11:50 -04:00
										 |  |  | static const u32 b_mask = 0x3fffffc; | 
					
						
							| 
									
										
										
										
											2009-05-06 16:39:03 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | inline static void *get_call_target(cell return_address) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-05-20 18:11:50 -04:00
										 |  |  | 	return_address -= 4; | 
					
						
							| 
									
										
										
										
											2009-05-06 16:39:03 -04:00
										 |  |  | 	check_call_site(return_address); | 
					
						
							| 
									
										
										
										
											2009-05-07 20:47:38 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-20 18:11:50 -04:00
										 |  |  | 	u32 insn = *(u32 *)return_address; | 
					
						
							|  |  |  | 	u32 unsigned_addr = (insn & b_mask); | 
					
						
							|  |  |  | 	s32 signed_addr = (s32)(unsigned_addr << 6) >> 6; | 
					
						
							| 
									
										
										
										
											2009-05-06 16:39:03 -04:00
										 |  |  | 	return (void *)(signed_addr + return_address); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | inline static void set_call_target(cell return_address, void *target) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-05-20 18:11:50 -04:00
										 |  |  | 	return_address -= 4; | 
					
						
							| 
									
										
										
										
											2009-05-06 16:39:03 -04:00
										 |  |  | 	check_call_site(return_address); | 
					
						
							| 
									
										
										
										
											2009-05-07 20:47:38 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-20 18:11:50 -04:00
										 |  |  | 	u32 insn = *(u32 *)return_address; | 
					
						
							| 
									
										
										
										
											2009-05-07 20:47:38 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	fixnum relative_address = ((cell)target - return_address); | 
					
						
							| 
									
										
										
										
											2009-05-08 18:41:22 -04:00
										 |  |  | 	insn = ((insn & ~b_mask) | (relative_address & b_mask)); | 
					
						
							| 
									
										
										
										
											2011-05-20 18:11:50 -04:00
										 |  |  | 	*(u32 *)return_address = insn; | 
					
						
							| 
									
										
										
										
											2009-05-06 16:39:03 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Flush the cache line containing the call we just patched */ | 
					
						
							|  |  |  | 	__asm__ __volatile__ ("icbi 0, %0\n" "sync\n"::"r" (return_address):); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-07 20:47:38 -04:00
										 |  |  | inline static bool tail_call_site_p(cell return_address) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-05-20 18:11:50 -04:00
										 |  |  | 	return_address -= 4; | 
					
						
							|  |  |  | 	u32 insn = *(u32 *)return_address; | 
					
						
							| 
									
										
										
										
											2009-05-07 20:47:38 -04:00
										 |  |  | 	return (insn & 0x1) == 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-14 00:37:28 -04:00
										 |  |  | inline static unsigned int fpu_status(unsigned int status) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-02-06 02:06:26 -05:00
										 |  |  | 	unsigned int r = 0; | 
					
						
							| 
									
										
										
										
											2009-09-14 00:37:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-06 02:06:26 -05:00
										 |  |  | 	if (status & 0x20000000) | 
					
						
							| 
									
										
										
										
											2009-09-14 04:09:03 -04:00
										 |  |  | 		r |= FP_TRAP_INVALID_OPERATION; | 
					
						
							| 
									
										
										
										
											2010-02-06 02:06:26 -05:00
										 |  |  | 	if (status & 0x10000000) | 
					
						
							| 
									
										
										
										
											2009-09-14 04:09:03 -04:00
										 |  |  | 		r |= FP_TRAP_OVERFLOW; | 
					
						
							| 
									
										
										
										
											2010-02-06 02:06:26 -05:00
										 |  |  | 	if (status & 0x08000000) | 
					
						
							| 
									
										
										
										
											2009-09-14 04:09:03 -04:00
										 |  |  | 		r |= FP_TRAP_UNDERFLOW; | 
					
						
							| 
									
										
										
										
											2010-02-06 02:06:26 -05:00
										 |  |  | 	if (status & 0x04000000) | 
					
						
							| 
									
										
										
										
											2009-09-14 04:09:03 -04:00
										 |  |  | 		r |= FP_TRAP_ZERO_DIVIDE; | 
					
						
							| 
									
										
										
										
											2010-02-06 02:06:26 -05:00
										 |  |  | 	if (status & 0x02000000) | 
					
						
							| 
									
										
										
										
											2009-09-14 04:09:03 -04:00
										 |  |  | 		r |= FP_TRAP_INEXACT; | 
					
						
							| 
									
										
										
										
											2009-09-14 00:37:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-06 02:06:26 -05:00
										 |  |  | 	return r; | 
					
						
							| 
									
										
										
										
											2009-09-14 00:37:28 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-06 16:39:03 -04:00
										 |  |  | /* Defined in assembly */ | 
					
						
							| 
									
										
										
										
											2009-12-21 21:42:49 -05:00
										 |  |  | VM_C_API void flush_icache(cell start, cell len); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 02:46:13 -04:00
										 |  |  | } |