sh-dis/c/operations.h
Zack Buhman 7debad83b9 add support for non-FPU/UBC/MMU/cache SH4 instructions
Previously, ast transformations were performed informally as ad-hoc
modifications to the generated C source code. In this commit, the
same transformations are performed by rewriting the ast prior to code
generation time.

The most significant new transformer is transform_assignment_list.
This transforms assignments such as:

  a, b, c = f(b, c, d)

To:

  a = f(&b, &c, d)

The former syntax is used frequently in the manual's description of
FPU-related instructions.
2024-04-22 20:59:34 +08:00

137 lines
2.1 KiB
C

#pragma once
#include <stdint.h>
#include <assert.h>
//
// sign_extend
//
static inline int32_t sign_extend(uint32_t x, uint32_t b)
{
const uint32_t m = 1UL << (b - 1);
x = x & ((1UL << b) - 1);
const int32_t r = (x ^ m) - m;
return r;
}
static inline int64_t sign_extend64(uint64_t x)
{
return (int64_t)x;
}
static inline int32_t sign_extend32(uint32_t x)
{
return (int32_t)x;
}
static inline int32_t sign_extend16(uint32_t x)
{
return sign_extend(x, 16);
}
static inline int32_t sign_extend12(uint32_t x)
{
return sign_extend(x, 12);
}
static inline int32_t sign_extend8(uint32_t x)
{
return sign_extend(x, 8);
}
//
// zero_extend
//
static inline uint32_t zero_extend(uint32_t x, uint32_t b)
{
x = x & ((1ULL << b) - 1);
return x;
}
static inline uint32_t zero_extend32(uint32_t x)
{
return (uint32_t)x;
}
static inline uint32_t zero_extend16(uint32_t x)
{
return zero_extend(x, 16);
}
static inline uint32_t zero_extend8(uint32_t x)
{
return zero_extend(x, 8);
}
static inline uint32_t zero_extend5(uint32_t x)
{
return zero_extend(x, 5);
}
static inline uint32_t zero_extend4(uint32_t x)
{
return zero_extend(x, 4);
}
static inline uint32_t zero_extend1(uint32_t x)
{
return zero_extend(x, 1);
}
//
// signed_saturate
//
static inline uint64_t signed_saturate(uint64_t x, uint32_t b)
{
const int64_t upper = (1LL << (b - 1)) - 1;
const int64_t lower = -(1LL << (b - 1));
static_assert(-(1LL << (48 - 1)) < 0);
if (x > upper)
return upper;
else if (x < lower)
return lower;
else
return x;
}
static inline uint64_t signed_saturate48(uint64_t x)
{
return signed_saturate(x, 48);
}
static inline uint32_t signed_saturate32(uint32_t x)
{
return signed_saturate(x, 32);
}
//
// "convenience" functions
//
static inline uint32_t _register(uint32_t x)
{
return zero_extend(x, 32);
}
static inline uint32_t bit(uint32_t x)
{
return zero_extend(x, 1);
}
//
// "operations"
//
static inline int32_t unary_int(int64_t x)
{
return x != 0;
}
static inline int64_t bit_extract(int64_t n, int64_t b, int64_t m)
{
return (n >> b) & ((1 << m) - 1);
}