helper.c
来自「xen虚拟机源代码安装包」· C语言 代码 · 共 2,396 行 · 第 1/5 页
C
2,396 行
{ uint16_t res; res = a + b; if (((res ^ a) & 0x8000) && !((a ^ b) & 0x8000)) { if (a & 0x8000) res = 0x8000; else res = 0x7fff; } return res;}/* Perform 8-bit signed saturating addition. */static inline uint8_t add8_sat(uint8_t a, uint8_t b){ uint8_t res; res = a + b; if (((res ^ a) & 0x80) && !((a ^ b) & 0x80)) { if (a & 0x80) res = 0x80; else res = 0x7f; } return res;}/* Perform 16-bit signed saturating subtraction. */static inline uint16_t sub16_sat(uint16_t a, uint16_t b){ uint16_t res; res = a - b; if (((res ^ a) & 0x8000) && ((a ^ b) & 0x8000)) { if (a & 0x8000) res = 0x8000; else res = 0x7fff; } return res;}/* Perform 8-bit signed saturating subtraction. */static inline uint8_t sub8_sat(uint8_t a, uint8_t b){ uint8_t res; res = a - b; if (((res ^ a) & 0x80) && ((a ^ b) & 0x80)) { if (a & 0x80) res = 0x80; else res = 0x7f; } return res;}#define ADD16(a, b, n) RESULT(add16_sat(a, b), n, 16);#define SUB16(a, b, n) RESULT(sub16_sat(a, b), n, 16);#define ADD8(a, b, n) RESULT(add8_sat(a, b), n, 8);#define SUB8(a, b, n) RESULT(sub8_sat(a, b), n, 8);#define PFX q#include "op_addsub.h"/* Unsigned saturating arithmetic. */static inline uint16_t add16_usat(uint16_t a, uint16_t b){ uint16_t res; res = a + b; if (res < a) res = 0xffff; return res;}static inline uint16_t sub16_usat(uint16_t a, uint16_t b){ if (a < b) return a - b; else return 0;}static inline uint8_t add8_usat(uint8_t a, uint8_t b){ uint8_t res; res = a + b; if (res < a) res = 0xff; return res;}static inline uint8_t sub8_usat(uint8_t a, uint8_t b){ if (a < b) return a - b; else return 0;}#define ADD16(a, b, n) RESULT(add16_usat(a, b), n, 16);#define SUB16(a, b, n) RESULT(sub16_usat(a, b), n, 16);#define ADD8(a, b, n) RESULT(add8_usat(a, b), n, 8);#define SUB8(a, b, n) RESULT(sub8_usat(a, b), n, 8);#define PFX uq#include "op_addsub.h"/* Signed modulo arithmetic. */#define SARITH16(a, b, n, op) do { \ int32_t sum; \ sum = (int16_t)((uint16_t)(a) op (uint16_t)(b)); \ RESULT(sum, n, 16); \ if (sum >= 0) \ ge |= 3 << (n * 2); \ } while(0)#define SARITH8(a, b, n, op) do { \ int32_t sum; \ sum = (int8_t)((uint8_t)(a) op (uint8_t)(b)); \ RESULT(sum, n, 8); \ if (sum >= 0) \ ge |= 1 << n; \ } while(0)#define ADD16(a, b, n) SARITH16(a, b, n, +)#define SUB16(a, b, n) SARITH16(a, b, n, -)#define ADD8(a, b, n) SARITH8(a, b, n, +)#define SUB8(a, b, n) SARITH8(a, b, n, -)#define PFX s#define ARITH_GE#include "op_addsub.h"/* Unsigned modulo arithmetic. */#define ADD16(a, b, n) do { \ uint32_t sum; \ sum = (uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b); \ RESULT(sum, n, 16); \ if ((sum >> 16) == 0) \ ge |= 3 << (n * 2); \ } while(0)#define ADD8(a, b, n) do { \ uint32_t sum; \ sum = (uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b); \ RESULT(sum, n, 8); \ if ((sum >> 8) == 0) \ ge |= 3 << (n * 2); \ } while(0)#define SUB16(a, b, n) do { \ uint32_t sum; \ sum = (uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b); \ RESULT(sum, n, 16); \ if ((sum >> 16) == 0) \ ge |= 3 << (n * 2); \ } while(0)#define SUB8(a, b, n) do { \ uint32_t sum; \ sum = (uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b); \ RESULT(sum, n, 8); \ if ((sum >> 8) == 0) \ ge |= 3 << (n * 2); \ } while(0)#define PFX u#define ARITH_GE#include "op_addsub.h"/* Halved signed arithmetic. */#define ADD16(a, b, n) \ RESULT(((int32_t)(int16_t)(a) + (int32_t)(int16_t)(b)) >> 1, n, 16)#define SUB16(a, b, n) \ RESULT(((int32_t)(int16_t)(a) - (int32_t)(int16_t)(b)) >> 1, n, 16)#define ADD8(a, b, n) \ RESULT(((int32_t)(int8_t)(a) + (int32_t)(int8_t)(b)) >> 1, n, 8)#define SUB8(a, b, n) \ RESULT(((int32_t)(int8_t)(a) - (int32_t)(int8_t)(b)) >> 1, n, 8)#define PFX sh#include "op_addsub.h"/* Halved unsigned arithmetic. */#define ADD16(a, b, n) \ RESULT(((uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b)) >> 1, n, 16)#define SUB16(a, b, n) \ RESULT(((uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b)) >> 1, n, 16)#define ADD8(a, b, n) \ RESULT(((uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b)) >> 1, n, 8)#define SUB8(a, b, n) \ RESULT(((uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b)) >> 1, n, 8)#define PFX uh#include "op_addsub.h"static inline uint8_t do_usad(uint8_t a, uint8_t b){ if (a > b) return a - b; else return b - a;}/* Unsigned sum of absolute byte differences. */uint32_t HELPER(usad8)(uint32_t a, uint32_t b){ uint32_t sum; sum = do_usad(a, b); sum += do_usad(a >> 8, b >> 8); sum += do_usad(a >> 16, b >>16); sum += do_usad(a >> 24, b >> 24); return sum;}/* For ARMv6 SEL instruction. */uint32_t HELPER(sel_flags)(uint32_t flags, uint32_t a, uint32_t b){ uint32_t mask; mask = 0; if (flags & 1) mask |= 0xff; if (flags & 2) mask |= 0xff00; if (flags & 4) mask |= 0xff0000; if (flags & 8) mask |= 0xff000000; return (a & mask) | (b & ~mask);}uint32_t HELPER(logicq_cc)(uint64_t val){ return (val >> 32) | (val != 0);}/* VFP support. We follow the convention used for VFP instrunctions: Single precition routines have a "s" suffix, double precision a "d" suffix. *//* Convert host exception flags to vfp form. */static inline int vfp_exceptbits_from_host(int host_bits){ int target_bits = 0; if (host_bits & float_flag_invalid) target_bits |= 1; if (host_bits & float_flag_divbyzero) target_bits |= 2; if (host_bits & float_flag_overflow) target_bits |= 4; if (host_bits & float_flag_underflow) target_bits |= 8; if (host_bits & float_flag_inexact) target_bits |= 0x10; return target_bits;}uint32_t HELPER(vfp_get_fpscr)(CPUState *env){ int i; uint32_t fpscr; fpscr = (env->vfp.xregs[ARM_VFP_FPSCR] & 0xffc8ffff) | (env->vfp.vec_len << 16) | (env->vfp.vec_stride << 20); i = get_float_exception_flags(&env->vfp.fp_status); fpscr |= vfp_exceptbits_from_host(i); return fpscr;}/* Convert vfp exception flags to target form. */static inline int vfp_exceptbits_to_host(int target_bits){ int host_bits = 0; if (target_bits & 1) host_bits |= float_flag_invalid; if (target_bits & 2) host_bits |= float_flag_divbyzero; if (target_bits & 4) host_bits |= float_flag_overflow; if (target_bits & 8) host_bits |= float_flag_underflow; if (target_bits & 0x10) host_bits |= float_flag_inexact; return host_bits;}void HELPER(vfp_set_fpscr)(CPUState *env, uint32_t val){ int i; uint32_t changed; changed = env->vfp.xregs[ARM_VFP_FPSCR]; env->vfp.xregs[ARM_VFP_FPSCR] = (val & 0xffc8ffff); env->vfp.vec_len = (val >> 16) & 7; env->vfp.vec_stride = (val >> 20) & 3; changed ^= val; if (changed & (3 << 22)) { i = (val >> 22) & 3; switch (i) { case 0: i = float_round_nearest_even; break; case 1: i = float_round_up; break; case 2: i = float_round_down; break; case 3: i = float_round_to_zero; break; } set_float_rounding_mode(i, &env->vfp.fp_status); } i = vfp_exceptbits_to_host((val >> 8) & 0x1f); set_float_exception_flags(i, &env->vfp.fp_status); /* XXX: FZ and DN are not implemented. */}#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))#define VFP_BINOP(name) \float32 VFP_HELPER(name, s)(float32 a, float32 b, CPUState *env) \{ \ return float32_ ## name (a, b, &env->vfp.fp_status); \} \float64 VFP_HELPER(name, d)(float64 a, float64 b, CPUState *env) \{ \ return float64_ ## name (a, b, &env->vfp.fp_status); \}VFP_BINOP(add)VFP_BINOP(sub)VFP_BINOP(mul)VFP_BINOP(div)#undef VFP_BINOPfloat32 VFP_HELPER(neg, s)(float32 a){ return float32_chs(a);}float64 VFP_HELPER(neg, d)(float64 a){ return float64_chs(a);}float32 VFP_HELPER(abs, s)(float32 a){ return float32_abs(a);}float64 VFP_HELPER(abs, d)(float64 a){ return float64_abs(a);}float32 VFP_HELPER(sqrt, s)(float32 a, CPUState *env){ return float32_sqrt(a, &env->vfp.fp_status);}float64 VFP_HELPER(sqrt, d)(float64 a, CPUState *env){ return float64_sqrt(a, &env->vfp.fp_status);}/* XXX: check quiet/signaling case */#define DO_VFP_cmp(p, type) \void VFP_HELPER(cmp, p)(type a, type b, CPUState *env) \{ \ uint32_t flags; \ switch(type ## _compare_quiet(a, b, &env->vfp.fp_status)) { \ case 0: flags = 0x6; break; \ case -1: flags = 0x8; break; \ case 1: flags = 0x2; break; \ default: case 2: flags = 0x3; break; \ } \ env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28) \ | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \} \void VFP_HELPER(cmpe, p)(type a, type b, CPUState *env) \{ \ uint32_t flags; \ switch(type ## _compare(a, b, &env->vfp.fp_status)) { \ case 0: flags = 0x6; break; \ case -1: flags = 0x8; break; \ case 1: flags = 0x2; break; \ default: case 2: flags = 0x3; break; \ } \ env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28) \ | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \}DO_VFP_cmp(s, float32)DO_VFP_cmp(d, float64)#undef DO_VFP_cmp/* Helper routines to perform bitwise copies between float and int. */static inline float32 vfp_itos(uint32_t i){ union { uint32_t i; float32 s; } v; v.i = i; return v.s;}static inline uint32_t vfp_stoi(float32 s){ union { uint32_t i; float32 s; } v; v.s = s; return v.i;}static inline float64 vfp_itod(uint64_t i){ union { uint64_t i; float64 d; } v; v.i = i; return v.d;}static inline uint64_t vfp_dtoi(float64 d){ union { uint64_t i; float64 d; } v; v.d = d; return v.i;}/* Integer to float conversion. */float32 VFP_HELPER(uito, s)(float32 x, CPUState *env){ return uint32_to_float32(vfp_stoi(x), &env->vfp.fp_status);}float64 VFP_HELPER(uito, d)(float32 x, CPUState *env){ return uint32_to_float64(vfp_stoi(x), &env->vfp.fp_status);}float32 VFP_HELPER(sito, s)(float32 x, CPUState *env){ return int32_to_float32(vfp_stoi(x), &env->vfp.fp_status);}float64 VFP_HELPER(sito, d)(float32 x, CPUState *env){ return int32_to_float64(vfp_stoi(x), &env->vfp.fp_status);}/* Float to integer conversion. */float32 VFP_HELPER(toui, s)(float32 x, CPUState *env){ return vfp_i
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?