Search
lxdream.org :: lxdream/src/sh4/ia64abi.h :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/ia64abi.h
changeset 539:75f3e594d4a7
next547:d6e00ffc4adc
author nkeynes
date Wed Nov 21 11:40:15 2007 +0000 (12 years ago)
permissions -rw-r--r--
last change Add support for the darwin ABI
file annotate diff log raw
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/sh4/ia64abi.h Wed Nov 21 11:40:15 2007 +0000
1.3 @@ -0,0 +1,185 @@
1.4 +/**
1.5 + * $Id: ia64abi.in,v 1.20 2007-11-08 11:54:16 nkeynes Exp $
1.6 + *
1.7 + * Provides the implementation for the ia32 ABI (eg prologue, epilogue, and
1.8 + * calling conventions)
1.9 + *
1.10 + * Copyright (c) 2007 Nathan Keynes.
1.11 + *
1.12 + * This program is free software; you can redistribute it and/or modify
1.13 + * it under the terms of the GNU General Public License as published by
1.14 + * the Free Software Foundation; either version 2 of the License, or
1.15 + * (at your option) any later version.
1.16 + *
1.17 + * This program is distributed in the hope that it will be useful,
1.18 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.19 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.20 + * GNU General Public License for more details.
1.21 + */
1.22 +
1.23 +#ifndef __lxdream_x86_64abi_H
1.24 +#define __lxdream_x86_64abi_H 1
1.25 +
1.26 +
1.27 +#define load_ptr( reg, ptr ) load_imm64( reg, (uint64_t)ptr );
1.28 +
1.29 +/**
1.30 + * Note: clobbers EAX to make the indirect call - this isn't usually
1.31 + * a problem since the callee will usually clobber it anyway.
1.32 + * Size: 12 bytes
1.33 + */
1.34 +#define CALL_FUNC0_SIZE 12
1.35 +static inline void call_func0( void *ptr )
1.36 +{
1.37 + load_imm64(R_EAX, (uint64_t)ptr);
1.38 + CALL_r32(R_EAX);
1.39 +}
1.40 +
1.41 +#define CALL_FUNC1_SIZE 14
1.42 +static inline void call_func1( void *ptr, int arg1 )
1.43 +{
1.44 + MOV_r32_r32(arg1, R_EDI);
1.45 + call_func0(ptr);
1.46 +}
1.47 +
1.48 +#define CALL_FUNC2_SIZE 16
1.49 +static inline void call_func2( void *ptr, int arg1, int arg2 )
1.50 +{
1.51 + MOV_r32_r32(arg1, R_EDI);
1.52 + MOV_r32_r32(arg2, R_ESI);
1.53 + call_func0(ptr);
1.54 +}
1.55 +
1.56 +#define MEM_WRITE_DOUBLE_SIZE 39
1.57 +/**
1.58 + * Write a double (64-bit) value into memory, with the first word in arg2a, and
1.59 + * the second in arg2b
1.60 + */
1.61 +static inline void MEM_WRITE_DOUBLE( int addr, int arg2a, int arg2b )
1.62 +{
1.63 + PUSH_r32(arg2b);
1.64 + PUSH_r32(addr);
1.65 + call_func2(sh4_write_long, addr, arg2a);
1.66 + POP_r32(addr);
1.67 + POP_r32(arg2b);
1.68 + ADD_imm8s_r32(4, addr);
1.69 + call_func2(sh4_write_long, addr, arg2b);
1.70 +}
1.71 +
1.72 +#define MEM_READ_DOUBLE_SIZE 35
1.73 +/**
1.74 + * Read a double (64-bit) value from memory, writing the first word into arg2a
1.75 + * and the second into arg2b. The addr must not be in EAX
1.76 + */
1.77 +static inline void MEM_READ_DOUBLE( int addr, int arg2a, int arg2b )
1.78 +{
1.79 + PUSH_r32(addr);
1.80 + call_func1(sh4_read_long, addr);
1.81 + POP_r32(R_EDI);
1.82 + PUSH_r32(R_EAX);
1.83 + ADD_imm8s_r32(4, R_EDI);
1.84 + call_func0(sh4_read_long);
1.85 + MOV_r32_r32(R_EAX, arg2b);
1.86 + POP_r32(arg2a);
1.87 +}
1.88 +
1.89 +
1.90 +/**
1.91 + * Emit the 'start of block' assembly. Sets up the stack frame and save
1.92 + * SI/DI as required
1.93 + */
1.94 +void sh4_translate_begin_block( sh4addr_t pc )
1.95 +{
1.96 + PUSH_r32(R_EBP);
1.97 + /* mov &sh4r, ebp */
1.98 + load_ptr( R_EBP, &sh4r );
1.99 +
1.100 + sh4_x86.in_delay_slot = FALSE;
1.101 + sh4_x86.priv_checked = FALSE;
1.102 + sh4_x86.fpuen_checked = FALSE;
1.103 + sh4_x86.branch_taken = FALSE;
1.104 + sh4_x86.backpatch_posn = 0;
1.105 + sh4_x86.block_start_pc = pc;
1.106 + sh4_x86.tstate = TSTATE_NONE;
1.107 + sh4_x86.stack_posn = 0;
1.108 +}
1.109 +
1.110 +/**
1.111 + * Exit the block with sh4r.pc already written
1.112 + * Bytes: 15
1.113 + */
1.114 +void exit_block_pcset( pc )
1.115 +{
1.116 + load_imm32( R_ECX, ((pc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period ); // 5
1.117 + ADD_r32_sh4r( R_ECX, REG_OFFSET(slice_cycle) ); // 6
1.118 + load_spreg( R_EAX, REG_OFFSET(pc) );
1.119 + call_func1(xlat_get_code,R_EAX);
1.120 + POP_r32(R_EBP);
1.121 + RET();
1.122 +}
1.123 +
1.124 +#define EXIT_BLOCK_SIZE 35
1.125 +/**
1.126 + * Exit the block to an absolute PC
1.127 + */
1.128 +void exit_block( sh4addr_t pc, sh4addr_t endpc )
1.129 +{
1.130 + load_imm32( R_ECX, pc ); // 5
1.131 + store_spreg( R_ECX, REG_OFFSET(pc) ); // 3
1.132 + REXW(); MOV_moff32_EAX( xlat_get_lut_entry(pc) );
1.133 + REXW(); AND_imm8s_r32( 0xFC, R_EAX ); // 3
1.134 + load_imm32( R_ECX, ((endpc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period ); // 5
1.135 + ADD_r32_sh4r( R_ECX, REG_OFFSET(slice_cycle) ); // 6
1.136 + POP_r32(R_EBP);
1.137 + RET();
1.138 +}
1.139 +
1.140 +
1.141 +/**
1.142 + * Write the block trailer (exception handling block)
1.143 + */
1.144 +void sh4_translate_end_block( sh4addr_t pc ) {
1.145 + if( sh4_x86.branch_taken == FALSE ) {
1.146 + // Didn't exit unconditionally already, so write the termination here
1.147 + exit_block( pc, pc );
1.148 + }
1.149 + if( sh4_x86.backpatch_posn != 0 ) {
1.150 + uint8_t *end_ptr = xlat_output;
1.151 + // Exception termination. Jump block for various exception codes:
1.152 + load_imm32( R_EDI, EXC_DATA_ADDR_READ );
1.153 + JMP_rel8( 33, target1 );
1.154 + load_imm32( R_EDI, EXC_DATA_ADDR_WRITE );
1.155 + JMP_rel8( 26, target2 );
1.156 + load_imm32( R_EDI, EXC_ILLEGAL );
1.157 + JMP_rel8( 19, target3 );
1.158 + load_imm32( R_EDI, EXC_SLOT_ILLEGAL );
1.159 + JMP_rel8( 12, target4 );
1.160 + load_imm32( R_EDI, EXC_FPU_DISABLED );
1.161 + JMP_rel8( 5, target5 );
1.162 + load_imm32( R_EDI, EXC_SLOT_FPU_DISABLED );
1.163 + // target
1.164 + JMP_TARGET(target1);
1.165 + JMP_TARGET(target2);
1.166 + JMP_TARGET(target3);
1.167 + JMP_TARGET(target4);
1.168 + JMP_TARGET(target5);
1.169 + // Raise exception
1.170 + load_spreg( R_ECX, REG_OFFSET(pc) );
1.171 + ADD_r32_r32( R_EDX, R_ECX );
1.172 + ADD_r32_r32( R_EDX, R_ECX );
1.173 + store_spreg( R_ECX, REG_OFFSET(pc) );
1.174 + MOV_moff32_EAX( &sh4_cpu_period );
1.175 + MUL_r32( R_EDX );
1.176 + ADD_r32_sh4r( R_EAX, REG_OFFSET(slice_cycle) );
1.177 +
1.178 + call_func0( sh4_raise_exception );
1.179 + load_spreg( R_EAX, REG_OFFSET(pc) );
1.180 + call_func1(xlat_get_code,R_EAX);
1.181 + POP_r32(R_EBP);
1.182 + RET();
1.183 +
1.184 + sh4_x86_do_backpatch( end_ptr );
1.185 + }
1.186 +}
1.187 +
1.188 +#endif
1.189 \ No newline at end of file
.