| #include <stdio.h> |
| #include <stdint.h> |
| #include "dfp_utils.h" |
| |
| /* Test various DFP ops: |
| - extract biased exponent 64/128 bit |
| - extract significance 64/128 bit |
| - insert biased exponent 64/128 bit |
| - load and test 64/128 bit |
| - shift left/right 64/128 bit |
| - reround 64/128 bit |
| */ |
| |
| void eedtr(_Decimal64 in) |
| { |
| long out; |
| asm volatile(".insn rre, 0xb3e50000, %[out], %[in]\n\t" |
| :[out] "=d" (out) :[in] "f" (in)); |
| printf("EEDTR "); |
| DFP_VAL_PRINT(in, _Decimal64); |
| printf(" -> %ld\n", out); |
| } |
| |
| void eextr(_Decimal128 in) |
| { |
| long out; |
| asm volatile(".insn rre, 0xb3ed0000, %[out], %[in]\n\t" |
| :[out] "=d" (out) :[in] "f" (in)); |
| printf("EEXTR "); |
| DFP_VAL_PRINT(in, _Decimal128); |
| printf(" -> %ld\n", out); |
| } |
| |
| void esdtr(_Decimal64 in) |
| { |
| long out; |
| asm volatile(".insn rre, 0xb3e70000, %[out], %[in]\n\t" |
| :[out] "=d" (out) :[in] "f" (in)); |
| printf("ESDTR "); |
| DFP_VAL_PRINT(in, _Decimal64); |
| printf(" -> %ld\n", out); |
| } |
| |
| void esxtr(_Decimal128 in) |
| { |
| long out; |
| asm volatile(".insn rre, 0xb3ef0000, %[out], %[in]\n\t" |
| :[out] "=d" (out) :[in] "f" (in)); |
| printf("ESXTR "); |
| DFP_VAL_PRINT(in, _Decimal128); |
| printf(" -> %ld\n", out); |
| } |
| |
| void iedtr(_Decimal64 in, long amount) |
| { |
| _Decimal64 out; |
| |
| asm volatile (".insn rrf, 0xb3f60000, %[out], %[amount], %[in], 0\n\t" |
| :[out]"=f"(out) |
| :[in]"f"(in), [amount]"d"(amount)); |
| |
| printf("IEDTR "); |
| DFP_VAL_PRINT(in, _Decimal64); |
| printf(", %ld -> ", amount); |
| DFP_VAL_PRINT(out, _Decimal64); |
| printf("\n"); |
| } |
| |
| void iextr(_Decimal128 in, long amount) |
| { |
| _Decimal128 out; |
| |
| asm volatile (".insn rrf, 0xb3fe0000, %[out], %[amount], %[in], 0\n\t" |
| :[out]"=f"(out) |
| :[in]"f"(in), [amount]"d"(amount)); |
| |
| printf("IEXTR "); |
| DFP_VAL_PRINT(in, _Decimal128); |
| printf(", %ld -> ", amount); |
| DFP_VAL_PRINT(out, _Decimal128); |
| printf("\n"); |
| } |
| |
| void ltdtr(_Decimal64 in) |
| { |
| _Decimal64 out; |
| int cc; |
| asm volatile(".insn rre, 0xb3d60000, %[out], %[in]\n\t" |
| "ipm %1\n\t" |
| "srl %1,28\n\t" |
| :[out] "=d" (out), "=d" (cc) |
| :[in] "f" (in)); |
| printf("LTDTR "); |
| DFP_VAL_PRINT(in, _Decimal64); |
| printf(" -> %d\n", cc); |
| } |
| |
| void ltxtr(_Decimal128 in) |
| { |
| _Decimal128 out; |
| int cc; |
| asm volatile(".insn rre, 0xb3de0000, %[out], %[in]\n\t" |
| "ipm %1\n\t" |
| "srl %1,28\n\t" |
| :[out] "=f" (out), "=d" (cc) |
| :[in] "f" (in)); |
| printf("LTXTR "); |
| DFP_VAL_PRINT(in, _Decimal128); |
| printf(" -> %d\n", cc); |
| } |
| |
| void qadtr(_Decimal64 op, _Decimal64 quan, uint8_t rm) |
| { |
| _Decimal64 out; |
| |
| asm volatile ( |
| ".insn rrf, 0xb3f50000, %[out], %[quan], %[op], %[rm]\n\t" |
| :[out]"=f"(out) |
| :[op]"f"(op), [quan]"f"(quan), [rm]"d"(rm) |
| ); |
| printf("QADTR "); |
| DFP_VAL_PRINT(op, _Decimal64); |
| printf(", "); |
| DFP_VAL_PRINT(quan, _Decimal64); |
| printf(", %x -> ", rm); |
| DFP_VAL_PRINT(out, _Decimal64); |
| printf("\n"); |
| } |
| |
| void quantize64(_Decimal64 op, _Decimal64 quan) |
| { |
| uint8_t i; |
| |
| for (i = 0; i < 16; i++) |
| qadtr(op, quan, i); |
| } |
| |
| void qaxtr(_Decimal128 op, _Decimal128 quan, uint8_t rm) |
| { |
| _Decimal128 out; |
| |
| asm volatile ( |
| ".insn rrf, 0xb3fd0000, %[out], %[quan], %[op], %[rm]\n\t" |
| :[out]"=f"(out) |
| :[op]"f"(op), [quan]"f"(quan), [rm]"d"(rm) |
| ); |
| printf("QAXTR "); |
| DFP_VAL_PRINT(op, _Decimal128); |
| printf(", "); |
| DFP_VAL_PRINT(quan, _Decimal128); |
| printf(", %x -> ", rm); |
| DFP_VAL_PRINT(out, _Decimal128); |
| printf("\n"); |
| } |
| |
| void quantize128(_Decimal128 op, _Decimal128 quan) |
| { |
| uint8_t i; |
| |
| for (i = 0; i < 16; i++) |
| qaxtr(op, quan, i); |
| } |
| |
| void rrdtr(_Decimal64 op, uint8_t sig, uint8_t rm) |
| { |
| _Decimal64 out; |
| |
| asm volatile ( |
| ".insn rrf, 0xb3f70000, %[out], %[sig], %[op], %[rm]\n\t" |
| :[out]"=f"(out) |
| :[op]"f"(op), [sig]"d"(sig), [rm]"d"(rm) |
| ); |
| printf("RRDTR "); |
| DFP_VAL_PRINT(op, _Decimal64); |
| printf(", %d, %x -> ", sig, rm); |
| DFP_VAL_PRINT(out, _Decimal64); |
| printf("\n"); |
| } |
| |
| void reround64(_Decimal64 op, uint8_t sig) |
| { |
| uint8_t i; |
| |
| for (i = 0; i < 16; i++) |
| rrdtr(op, sig, i); |
| } |
| |
| void rrxtr(_Decimal128 op, uint8_t sig, uint8_t rm) |
| { |
| _Decimal128 out; |
| |
| asm volatile ( |
| ".insn rrf, 0xb3ff0000, %[out], %[sig], %[op], %[rm]\n\t" |
| :[out]"=f"(out) |
| :[op]"f"(op), [sig]"d"(sig), [rm]"d"(rm) |
| ); |
| printf("RRXTR "); |
| DFP_VAL_PRINT(op, _Decimal128); |
| printf(", %d, %x -> ", sig, rm); |
| DFP_VAL_PRINT(out, _Decimal128); |
| printf("\n"); |
| } |
| |
| void reround128(_Decimal128 op, uint8_t sig) |
| { |
| uint8_t i; |
| |
| for (i = 0; i < 16; i++) |
| rrxtr(op, sig, i); |
| } |
| |
| void sldt(_Decimal64 in, unsigned long amount) |
| { |
| _Decimal64 out; |
| int *shift = (int *) amount; |
| |
| asm volatile (".insn rxf, 0xed0000000040, %[out], %[in], 0(%[amount])\n\t" |
| :[out]"=f"(out) |
| :[in]"f"(in),[amount]"a"(shift)); |
| |
| printf("SLDT "); |
| DFP_VAL_PRINT(in, _Decimal64); |
| printf(" -> "); |
| DFP_VAL_PRINT(out, _Decimal64); |
| printf("\n"); |
| } |
| |
| void slxt(_Decimal128 in, unsigned long amount) |
| { |
| _Decimal128 out; |
| int *shift = (int *) amount; |
| |
| asm volatile (".insn rxf, 0xed0000000048, %[out], %[in], 0(%[amount])\n\t" |
| :[out]"=f"(out) |
| :[in]"f"(in),[amount]"a"(shift)); |
| |
| printf("SLXT "); |
| DFP_VAL_PRINT(in, _Decimal128); |
| printf(" -> "); |
| DFP_VAL_PRINT(out, _Decimal128); |
| printf("\n"); |
| } |
| |
| void srdt(_Decimal64 in, unsigned long amount) |
| { |
| _Decimal64 out; |
| int *shift = (int *) amount; |
| |
| asm volatile (".insn rxf, 0xed0000000041, %[out], %[in], 0(%[amount])\n\t" |
| :[out]"=f"(out) |
| :[in]"f"(in),[amount]"a"(shift)); |
| |
| printf("SRDT "); |
| DFP_VAL_PRINT(in, _Decimal64); |
| printf(" -> "); |
| DFP_VAL_PRINT(out, _Decimal64); |
| printf("\n"); |
| } |
| |
| void srxt(_Decimal128 in, unsigned long amount) |
| { |
| _Decimal128 out; |
| int *shift = (int *) amount; |
| |
| asm volatile (".insn rxf, 0xed0000000049, %[out], %[in], 0(%[amount])\n\t" |
| :[out]"=f"(out) |
| :[in]"f"(in),[amount]"a"(shift)); |
| |
| printf("SRXT "); |
| DFP_VAL_PRINT(in, _Decimal128); |
| printf(" -> "); |
| DFP_VAL_PRINT(out, _Decimal128); |
| printf("\n"); |
| } |
| |
| int main() { |
| _Decimal64 d64 = 50.0005DD; |
| _Decimal128 d128 = 50.0005DL; |
| |
| eedtr(d64); |
| eedtr(-d64); |
| eedtr(0.DD); |
| eextr(d128); |
| eextr(-d128); |
| eextr(0.DL); |
| |
| esdtr(d64); |
| esdtr(-d64); |
| esdtr(0.DD); |
| esxtr(d128); |
| esxtr(-d128); |
| esxtr(0.DL); |
| |
| ltdtr(d64); |
| ltdtr(-d64); |
| ltdtr(0.0DD); |
| ltxtr(d128); |
| ltxtr(-d128); |
| ltxtr(0.0DL); |
| |
| d64 = 12345678.54321DD; |
| sldt(d64, 10); |
| sldt(-d64, 2); |
| sldt(0.DD, 2); |
| sldt(-0.DD, 2); |
| |
| srdt(d64, 5); |
| srdt(-d64, 2); |
| srdt(0.DD, 2); |
| srdt(-0.DD, 2); |
| |
| d128 = 12345678.54321DL; |
| slxt(d128, 10); |
| slxt(-d128, 2); |
| slxt(0.DL, 2); |
| slxt(-0.DL, 2); |
| |
| srxt(d128, 10); |
| srxt(-d128, 2); |
| srxt(0.DL, 2); |
| srxt(-0.DL, 2); |
| |
| d64 = 5.000005DD; |
| iedtr(d64, 391); |
| iedtr(d64, 392); |
| iedtr(d64, 393); |
| iedtr(-d64, 391); |
| iedtr(-d64, 392); |
| iedtr(-d64, 393); |
| iedtr(0.DD, 393); |
| iedtr(-0.DD, 393); |
| iedtr(1.DD, 393); |
| |
| d128 = 5.000005DL; |
| iextr(d128, 6169); |
| iextr(d128, 6170); |
| iextr(d128, 6171); |
| iextr(-d128, 6169); |
| iextr(-d128, 6170); |
| iextr(-d128, 6171); |
| iextr(0.DL, 6171); |
| iextr(-0.DL, 6171); |
| iextr(1.DL, 6171); |
| |
| d64 = 2.171234DD; |
| quantize64(d64, 0.001DD); |
| quantize64(-d64, 0.001DD); |
| quantize64(-d64, 0.DD); |
| quantize64(0.DD, 0.001DD); |
| |
| d128 = 26365343648.171234DL; |
| quantize128(d128, 230.01DL); |
| quantize128(-d128, 230.01DL); |
| quantize128(d128, 0.DL); |
| quantize128(-0.DL, 230.01DL); |
| |
| d64 = 2.174598DD; |
| reround64(d64, 3); |
| reround64(d64, 4); |
| reround64(d64, 5); |
| reround64(-d64, 3); |
| reround64(-d64, 4); |
| reround64(-d64, 5); |
| reround64(0.DD, 0); |
| |
| d128 = 2.174598DL; |
| reround128(d128, 3); |
| reround128(d128, 4); |
| reround128(d128, 5); |
| reround128(-d128, 3); |
| reround128(-d128, 4); |
| reround128(-d128, 5); |
| reround128(0.DL, 0); |
| |
| return 0; |
| } |