整数相关操作

整数类型

头文件包含 #include <stdint.h> ,128位整数需要gcc支持才行

int8_t   int16_t   int32_t   int64_t   __int128_t
uint8_t  uint16_t  uint32_t  uint64_t  __uint128_t

整数位操作

头文件包含 #include <byteswap.h>

#include <byteswap.h>
bswap_16(x);
bswap_32(x);
bswap_64(x);

基于汇编的重新实现,128bit整数swap需要优化

static inline uint32_t _bswap32(uint32_t _x) {
	uint32_t x = _x;  
	asm volatile("bswap %[x]" : [ x ] "+r"(x));  
	return x;
}
static inline uint16_t _bswap16(uint16_t _x) {  
	uint16_t x = _x;  
	asm volatile("xchgb %b[x1],%h[x2]" : [ x1 ] "=Q"(x) : [ x2 ] "0"(x));  
	return x;
}
static inline uint64_t _bswap64(uint64_t _x){  
	uint64_t x = _x;  
	asm volatile("bswap %[x]" : [ x ] "+r"(x));  
	return x;
}
static inline __uint128_t _bswap128(__uint128_t _x){	
	union {__uint128_t u128;uint64_t u64[2];} x;	
	x.u64[1]=_bswap64(_x&(uint64_t)(-1));	
	x.u64[0]=_bswap64((_x>>64)&(uint64_t)(-1)) ;	
	return x.u128;
}

应用

在项目中需要根据公式动态构建出一份c代码,ipv6部分使用128bit整数,在构建代码是使用如下方式:


typedef union ipv6_u{
  __uint128_t u128; 
  uint64_t u64[2]; 
  uint8_t u8[16];
} ipv6_t;

static char* op2str(int op, char opstr[]) {
  switch(op) {
  case EQ:
    strcpy(opstr, "==");
    break;
  case NEQ:
    strcpy(opstr, "!=");
    break;
  case GT:
    strcpy(opstr, ">");
    break;
  case LT:
    strcpy(opstr, "<");
    break;
  case GEQ:
    strcpy(opstr, ">=");
    break;
  case LEQ:
    strcpy(opstr, "<=");
    break;
  default:
    strcpy(opstr, "==");
    break;
  }
  return opstr;
}

static char* build_ipv6_expr(char* expr, int32_t op,
                               enum yytokentype direction,
                               ipv6_t* mask, ipv6_t* ip) {
  char opstr[10];
  char addr[1024];
  // mask.u64[2] ip.u64[2]
  // [0] -> low 64 bits for u128
  // [1] -> high 64 bits for u128

  if(mask->u128 != ((__uint128_t)(-1))) {
    sprintf(addr, "(*(__uint128_t*)(xdr + %jd) & ((__uint128_t)(0x%08jx)<<64|0x%08jx))",
            direction == IPV6_SRC ? hdr_offset.src_addrv6 : hdr_offset.dst_addrv6,
            mask->u64[1], // high 
            mask->u64[0]); // low
  } else {
    sprintf(addr, "*(__uint128_t*)(xdr + %jd)",
            direction == IPV6_SRC ? hdr_offset.src_addrv6 : hdr_offset.dst_addrv6);
  }

  op2str(op, opstr);
  switch(op) {
  case EQ:
  case NEQ:
    sprintf(expr, "%s %s ((__uint128_t)(0x%08jx)<<64|0x%08jx)", addr, opstr, ip->u64[1], ip->u64[0]);
    break;
  default:
    // byte swap, low convert to high; high -> low
    sprintf(expr, "_bswap128(%s) %s ((__uint128_t)(0x%08jx)<<64|0x%08jx)", addr, opstr, bswap_64(ip->u64[0]), bswap_64(ip->u64[1]));
    break;
  }
  return expr;
}

生成的代码如下:

(*(__uint128_t*)(xdr + 24) == ((__uint128_t)(0x100000000000000)<<64|0x5000000020000fc) || *(__uint128_t*)(xdr + 40) == ((__uint128_t)(0x100000000000000)<<64|0x5000000020000fc))

备注

  1. 为什么使用((__uint128_t)(0x%08jx)<<64|0x%08jx)
    a. snprintf无法打印128bit整数;
    b. c/c++代码中,无法直接常亮表示128bit整数,编译时会报错warning: integer constant is too large for its type
    c. 生成代码((__uint128_t)(0x100000000000000)<<64|0x5000000020000fc)可在编译时,由编译器优化。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值