/*
 * Copyright 2005-2009 Clozure Associates
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef X86_EXCEPTIONS_H
#define X86_EXCEPTIONS_H 1

typedef uint8_t opcode, *pc;

void switch_to_foreign_stack(void*, ...);

#define INTN_OPCODE 0xcd

#define UUO_GC_TRAP    0xc4
#define UUO_ALLOC_TRAP 0xc5
#define UUO_DEBUG_TRAP 0xca
#define UUO_DEBUG_TRAP_WITH_STRING 0xcd
#define UUO_WATCH_TRAP 0xce
  #define WATCH_TRAP_FUNCTION_WATCH 0
  #define WATCH_TRAP_FUNCTION_UNWATCH 1

#define XUUO_OPCODE_0 0x0f
#define XUUO_OPCODE_1 0x0b

#define XUUO_TLB_TOO_SMALL 1
#define XUUO_INTERRUPT_NOW 2
#define XUUO_SUSPEND_NOW 3
#define XUUO_INTERRUPT 4
#define XUUO_SUSPEND 5
#define XUUO_SUSPEND_ALL 6
#define XUUO_RESUME 7
#define XUUO_RESUME_ALL 8
#define XUUO_KILL 9
#define XUUO_ALLOCATE_LIST 10

int callback_to_lisp (TCR *tcr, LispObj callback_macptr, ExceptionInformation *xp,
		      natural arg1, natural arg2, natural arg3, natural arg4,
		      natural arg5);


void
pc_luser_xp(ExceptionInformation*, TCR*, signed_natural*);


typedef enum {
  ID_unrecognized_alloc_instruction,
  ID_load_allocptr_reg_from_tcr_save_allocptr_instruction,
  ID_compare_allocptr_reg_to_tcr_save_allocbase_instruction,
  ID_branch_around_alloc_trap_instruction,
  ID_alloc_trap_instruction,
  ID_set_allocptr_header_instruction,
  ID_clear_tcr_save_allocptr_tag_instruction
} alloc_instruction_id;

/* sigaltstack isn't thread-specific on The World's Most Advanced OS */
#ifdef DARWIN
#undef USE_SIGALTSTACK
#else
#ifdef WINDOWS
#undef USE_SIGALTSTACK
#else
#define USE_SIGALTSTACK 1
#endif
#endif

#ifdef USE_SIGALTSTACK
void setup_sigaltstack(area *);
#endif

extern natural get_mxcsr();
extern void set_mxcsr(natural);
void enable_fp_exceptions(void);

void callback_for_gc_notification(ExceptionInformation *xp, TCR *tcr);

#ifdef DARWIN

#ifdef X8664
#define ts_pc(t) t->__rip
typedef x86_thread_state64_t native_thread_state_t;
#define NATIVE_THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT
#define NATIVE_THREAD_STATE_FLAVOR x86_THREAD_STATE64
typedef x86_float_state64_t native_float_state_t;
#define NATIVE_FLOAT_STATE_COUNT x86_FLOAT_STATE64_COUNT
#define NATIVE_FLOAT_STATE_FLAVOR x86_FLOAT_STATE64
typedef x86_exception_state64_t native_exception_state_t;
#define NATIVE_EXCEPTION_STATE_COUNT x86_EXCEPTION_STATE64_COUNT
#define NATIVE_EXCEPTION_STATE_FLAVOR x86_EXCEPTION_STATE64
#else
#define ts_pc(t) t->__eip
typedef x86_thread_state32_t native_thread_state_t;
#define NATIVE_THREAD_STATE_COUNT x86_THREAD_STATE32_COUNT
#define NATIVE_THREAD_STATE_FLAVOR x86_THREAD_STATE32
typedef x86_float_state32_t native_float_state_t;
#define NATIVE_FLOAT_STATE_COUNT x86_FLOAT_STATE32_COUNT
#define NATIVE_FLOAT_STATE_FLAVOR x86_FLOAT_STATE32
typedef x86_exception_state32_t native_exception_state_t;
#define NATIVE_EXCEPTION_STATE_COUNT x86_EXCEPTION_STATE32_COUNT
#define NATIVE_EXCEPTION_STATE_FLAVOR x86_EXCEPTION_STATE32
#endif

TCR *
find_tcr_from_exception_port(mach_port_t);

void
associate_tcr_with_exception_port(mach_port_t, TCR *);

void
disassociate_tcr_from_exception_port(mach_port_t);
#endif


#endif /* X86_EXCEPTIONS_H */

