| #include <stdio.h> |
| #include "opcodes.h" |
| #include "dfp_utils.h" |
| #define __STDC_WANT_DEC_FP__ 1 |
| #include <float.h> |
| |
| #define I2D(insn, initial, target,round) \ |
| ({ \ |
| register int source asm("2") = initial; \ |
| register typeof(target) _t asm("f0"); \ |
| asm volatile(insn(round,0,0,2) :"=f" (_t):"d"(source)); \ |
| _t; \ |
| }) |
| |
| #define D2I(insn, initial, type, round, cc) \ |
| ({ \ |
| register type source asm("f0") = initial; \ |
| register int target asm ("2") = 0; \ |
| asm volatile(insn(round,0,2,0) \ |
| "ipm %1\n\t" \ |
| "srl %1,28\n\t" \ |
| :"=d" (target), "=d" (cc) :"f"(source):"cc"); \ |
| target; \ |
| }) |
| |
| |
| #define DO_PRINT_I2D(insn, l, d, round) \ |
| ({ \ |
| printf(#insn " round=%d %d -> ", 0x##round, l); \ |
| d = I2D(insn, l, d, round); \ |
| DFP_VAL_PRINT(d, typeof(d)); \ |
| printf("\n"); \ |
| }) |
| |
| #define DO_INSN_I2D(insn, round, type) \ |
| ({ \ |
| type d; \ |
| DO_PRINT_I2D(insn, 0, d, round); \ |
| DO_PRINT_I2D(insn, 1, d, round); \ |
| DO_PRINT_I2D(insn, 0xffffffff, d, round); \ |
| DO_PRINT_I2D(insn, 0x80000000, d, round); \ |
| DO_PRINT_I2D(insn, 0x7fffffff, d, round); \ |
| }) |
| |
| #define DO_PRINT_D2I(insn, d, type, round, cc) \ |
| ({ \ |
| printf(#insn " round=%d ", 0x##round); \ |
| DFP_VAL_PRINT(d, type); \ |
| printf(" -> %d ", D2I(insn, d, type, round, cc)); \ |
| printf("cc=%d\n", cc); \ |
| }) |
| |
| #define DO_INSN_D2I(insn, round, type) \ |
| ({ \ |
| int cc; \ |
| type d; \ |
| d = -1.1DD; \ |
| DO_PRINT_D2I(insn, d, type, round, cc); \ |
| d = 0.DD; \ |
| DO_PRINT_D2I(insn, d, type, round, cc); \ |
| d = 1.DD; \ |
| DO_PRINT_D2I(insn, d, type, round, cc); \ |
| d = 1.4DD; \ |
| DO_PRINT_D2I(insn, d, type, round, cc); \ |
| d = 1.5DD; \ |
| DO_PRINT_D2I(insn, d, type, round, cc); \ |
| d = 1.6DD; \ |
| DO_PRINT_D2I(insn, d, type, round, cc); \ |
| d = 1.6E+4DD; \ |
| DO_PRINT_D2I(insn, d, type, round, cc); \ |
| d = 1.6E+8DD; \ |
| DO_PRINT_D2I(insn, d, type, round, cc); \ |
| d = 1.6E+4DD; \ |
| DO_PRINT_D2I(insn, d, type, round, cc); \ |
| d = 1.6E+12DD; \ |
| DO_PRINT_D2I(insn, d, type, round, cc); \ |
| d = 1.6E+20DD; \ |
| DO_PRINT_D2I(insn, d, type, round, cc); \ |
| d = 1.6E+200DD; \ |
| DO_PRINT_D2I(insn, d, type, round, cc); \ |
| d = 1.6E-4DD; \ |
| DO_PRINT_D2I(insn, d, type, round, cc); \ |
| d = DEC32_MIN; \ |
| DO_PRINT_D2I(insn, d, type, round, cc); \ |
| d = DEC32_MAX; \ |
| DO_PRINT_D2I(insn, d, type, round, cc); \ |
| d = DEC64_MIN; \ |
| DO_PRINT_D2I(insn, d, type, round, cc); \ |
| d = DEC64_MAX; \ |
| DO_PRINT_D2I(insn, d, type, round, cc); \ |
| }) |
| |
| #define DO_D2I(round) \ |
| ({ \ |
| DO_INSN_D2I(CGDTRA, round, _Decimal64); \ |
| DO_INSN_D2I(CGXTRA, round, _Decimal128); \ |
| }) |
| |
| |
| int main() |
| { |
| /* rounding mode is not used for the I64 -> D128 conversion */ |
| DO_INSN_I2D(CXGTRA, 0, _Decimal128); |
| |
| /* Omit rounding mode value 0 and 2 as the current DFP rounding |
| mode is chosen for these values. */ |
| DO_INSN_I2D(CDGTRA, 1, _Decimal64); |
| DO_D2I(1); |
| |
| DO_INSN_I2D(CDGTRA, 3, _Decimal64); |
| DO_D2I(3); |
| |
| DO_INSN_I2D(CDGTRA, 4, _Decimal64); |
| DO_D2I(4); |
| |
| DO_INSN_I2D(CDGTRA, 5, _Decimal64); |
| DO_D2I(5); |
| |
| DO_INSN_I2D(CDGTRA, 6, _Decimal64); |
| DO_D2I(6); |
| |
| DO_INSN_I2D(CDGTRA, 7, _Decimal64); |
| DO_D2I(7); |
| |
| DO_INSN_I2D(CDGTRA, 8, _Decimal64); |
| DO_D2I(8); |
| |
| DO_INSN_I2D(CDGTRA, 9, _Decimal64); |
| DO_D2I(9); |
| |
| DO_INSN_I2D(CDGTRA, a, _Decimal64); |
| DO_D2I(a); |
| |
| DO_INSN_I2D(CDGTRA, b, _Decimal64); |
| DO_D2I(b); |
| |
| DO_INSN_I2D(CDGTRA, c, _Decimal64); |
| DO_D2I(c); |
| |
| DO_INSN_I2D(CDGTRA, d, _Decimal64); |
| DO_D2I(d); |
| |
| DO_INSN_I2D(CDGTRA, e, _Decimal64); |
| DO_D2I(e); |
| |
| DO_INSN_I2D(CDGTRA, f, _Decimal64); |
| DO_D2I(f); |
| |
| return 0; |
| } |