/* ***************************************************************************** * bcd/mcs.c -- make a libg1m BCD out of an MCS BCD number. * Copyright (C) 2017 Thomas "Cakeisalie5" Touhey * * This file is part of libg1m. * libg1m is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3.0 of the License, * or (at your option) any later version. * * libg1m is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with libg1m; if not, see . * ************************************************************************** */ #include #define upr(N) (bytes[(N)] >> 4) #define lwr(N) (bytes[(N)] & 15) /** * g1m_bcd_frommcs: * Make a libg1m BCD out of an MCS BCD number. * * @arg raw the raw BCD. * @arg dest the not raw BCD. * @return the special bit, for simplicity. */ int g1m_bcd_frommcs(const g1m_mcsbcd_t *raw, g1m_bcd_t *bcd) { const unsigned char *bytes = raw->g1m_mcsbcd_BCDval; /* get the exponent and correct it */ int exp = (upr(0) & 7) * 100 + lwr(0) * 10 + upr(1), neg = 0; if (exp >= 500) exp -= 500, neg = 1; bcd->g1m_bcd_exp = (char)(exp - 99); /* set the flags */ bcd->g1m_bcd_flags = g1m_make_bcdflags((bytes[0] & 0x80) >> 7, neg, 15); /* get the mantissa */ bcd->g1m_bcd_mant[0] = lwr(1); bcd->g1m_bcd_mant[1] = upr(2); bcd->g1m_bcd_mant[2] = lwr(2); bcd->g1m_bcd_mant[3] = upr(3); bcd->g1m_bcd_mant[4] = lwr(3); bcd->g1m_bcd_mant[5] = upr(4); bcd->g1m_bcd_mant[6] = lwr(4); bcd->g1m_bcd_mant[7] = upr(5); bcd->g1m_bcd_mant[8] = lwr(5); bcd->g1m_bcd_mant[9] = upr(6); bcd->g1m_bcd_mant[10] = lwr(6); bcd->g1m_bcd_mant[11] = upr(7); bcd->g1m_bcd_mant[12] = lwr(7); bcd->g1m_bcd_mant[13] = upr(8); bcd->g1m_bcd_mant[14] = lwr(8); /* return the special bit */ return (g1m_bcd_has_special(bcd)); } /** * g1m_bcd_tomcs: * Make an MCS BCD number out of a libg1m BCD number. * * @arg bcd the not raw BCD. * @arg raw the raw BCD. */ # define g1m_bcd_m g1m_bcd_mant void g1m_bcd_tomcs(const g1m_bcd_t *bcd, g1m_mcsbcd_t *raw) { int exp = bcd->g1m_bcd_exp + 99; if (g1m_bcd_is_negative(bcd)) exp += 500; /* put the exponent (and first digit of the mantissa) */ div_t c = div(exp, 100); div_t d = div(c.rem, 10); raw->g1m_mcsbcd_BCDval[0] = (c.quot << 4) | d.quot | (!!g1m_bcd_has_special(bcd) << 7); raw->g1m_mcsbcd_BCDval[1] = (d.rem << 4) | bcd->g1m_bcd_mant[0]; /* put the mantissa */ raw->g1m_mcsbcd_BCDval[2] = (bcd->g1m_bcd_m[1] << 4) | bcd->g1m_bcd_m[2]; raw->g1m_mcsbcd_BCDval[3] = (bcd->g1m_bcd_m[3] << 4) | bcd->g1m_bcd_m[4]; raw->g1m_mcsbcd_BCDval[4] = (bcd->g1m_bcd_m[5] << 4) | bcd->g1m_bcd_m[6]; raw->g1m_mcsbcd_BCDval[5] = (bcd->g1m_bcd_m[7] << 4) | bcd->g1m_bcd_m[8]; raw->g1m_mcsbcd_BCDval[6] = (bcd->g1m_bcd_m[9] << 4) | bcd->g1m_bcd_m[10]; raw->g1m_mcsbcd_BCDval[7] = (bcd->g1m_bcd_m[11] << 4) | bcd->g1m_bcd_m[12]; raw->g1m_mcsbcd_BCDval[8] = (bcd->g1m_bcd_m[13] << 4) | bcd->g1m_bcd_m[14]; /* set the align zone */ raw->g1m_mcsbcd__align[0] = 0; raw->g1m_mcsbcd__align[1] = 0; raw->g1m_mcsbcd__align[2] = 0; }