97 lines
3.5 KiB
C
97 lines
3.5 KiB
C
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#ifdef WIN32
|
||
#include <windows.h>
|
||
#endif
|
||
|
||
#include "SoftFloat/source/include/softfloat.h"
|
||
#include "internals.h"
|
||
|
||
#define _FLOAT_INCLUDE_F16_H
|
||
#define _FLOAT_INCLUDE_F32_H
|
||
extern void f16_print(float16_t v);
|
||
extern void f32_print(float32_t v);
|
||
|
||
#define CREATE_VAR(name) __##name = {name}
|
||
#define ADD_PREFIX(name) __##name
|
||
|
||
#define OPERATION_DISPATCH(OP1, OP2, ...) \
|
||
case OP1: { \
|
||
if (fmt == HALF) { \
|
||
float16_t REPEAT(CREATE_VAR, __VA_ARGS__); \
|
||
f16_print(f16_##OP2(REPEAT(ADD_PREFIX, __VA_ARGS__))); \
|
||
} else { \
|
||
float32_t REPEAT(CREATE_VAR, __VA_ARGS__); \
|
||
f32_print(f32_##OP2(REPEAT(ADD_PREFIX, __VA_ARGS__))); \
|
||
} \
|
||
} break
|
||
|
||
NORETURN void die() {
|
||
fprintf(stderr,
|
||
"Usage: \n"
|
||
"<fmt> <округление> <число>\n"
|
||
"<fmt> <округление> <операция2> <число1> <число2>\n"
|
||
"<fmt> <округление> <операция3> <число1> <число2> <число3>\n");
|
||
exit(1);
|
||
}
|
||
|
||
int skkv_to_sf(int rt) {
|
||
switch (rt) {
|
||
case 0:
|
||
return softfloat_round_minMag;
|
||
case 1:
|
||
return softfloat_round_near_even;
|
||
case 2:
|
||
return softfloat_round_max;
|
||
case 3:
|
||
return softfloat_round_min;
|
||
default:
|
||
unreachable();
|
||
}
|
||
}
|
||
|
||
|
||
float16_t f16_mad(float16_t a, float16_t b, float16_t c) { return f16_add(f16_mul(a, b), c); }
|
||
float32_t f32_mad(float32_t a, float32_t b, float32_t c) { return f32_add(f32_mul(a, b), c); }
|
||
|
||
THREAD_LOCAL uint_fast8_t softfloat_detectTininess = 0;
|
||
THREAD_LOCAL uint_fast8_t softfloat_exceptionFlags = 0;
|
||
THREAD_LOCAL uint_fast8_t softfloat_roundingMode;
|
||
|
||
int main(int argc, char **argv) {
|
||
#ifdef WIN32
|
||
SetConsoleCP(CP_UTF8);
|
||
SetConsoleOutputCP(CP_UTF8);
|
||
#endif
|
||
|
||
u32 a = 0, b = 0, c = 0;
|
||
Operation operation = PRN;
|
||
|
||
switch (argc) {
|
||
case 4:
|
||
sscanf(argv[3], "%X", &a);
|
||
break;
|
||
case 7:
|
||
sscanf(argv[6], "%X", &c);
|
||
case 6:
|
||
sscanf(argv[3], "%c", (char *) &operation);
|
||
sscanf(argv[4], "%X", &a);
|
||
sscanf(argv[5], "%X", &b);
|
||
break;
|
||
default:
|
||
die();
|
||
}
|
||
|
||
Format fmt = *argv[1];
|
||
softfloat_roundingMode = skkv_to_sf(*argv[2] - '0');
|
||
|
||
switch (operation) {
|
||
OPERATION_DISPATCH(PRN, nop, a);
|
||
OPERATION_DISPATCH(ADD, add, a, b);
|
||
OPERATION_DISPATCH(SUB, sub, a, b);
|
||
OPERATION_DISPATCH(DIV, div, a, b);
|
||
OPERATION_DISPATCH(MUL, mul, a, b);
|
||
OPERATION_DISPATCH(FMA, mulAdd, a, b, c);
|
||
OPERATION_DISPATCH(MAD, mad, a, b, c);
|
||
}
|
||
}
|