compiler

Unnamed Compiled Systems Language Project
git clone http://frotz.net/git/compiler.git
Log | Files | Refs

risc5emu-fp.c (4458B)


      1 // Copyright © 2014 Peter De Wachter
      2 //
      3 // Permission to use, copy, modify, and/or distribute this software for
      4 // any purpose with or without fee is hereby granted, provided that the
      5 // above copyright notice and this permission notice appear in all
      6 // copies.
      7 //
      8 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
      9 // WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
     10 // WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
     11 // AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
     12 // DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
     13 // PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     14 // TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     15 // PERFORMANCE OF THIS SOFTWARE.
     16 
     17 // based on src/risc-fp.c from git@github.com:pdewacht/oberon-risc-emu.git
     18 
     19 #include "risc5emu-fp.h"
     20 
     21 uint32_t fp_add(uint32_t x, uint32_t y, bool u, bool v) {
     22   bool xs = (x & 0x80000000) != 0;
     23   uint32_t xe;
     24   int32_t x0;
     25   if (!u) {
     26     xe = (x >> 23) & 0xFF;
     27     uint32_t xm = ((x & 0x7FFFFF) << 1) | 0x1000000;
     28     x0 = (int32_t)(xs ? -xm : xm);
     29   } else {
     30     xe = 150;
     31     x0 = (int32_t)(x & 0x00FFFFFF) << 8 >> 7;
     32   }
     33 
     34   bool ys = (y & 0x80000000) != 0;
     35   uint32_t ye = (y >> 23) & 0xFF;
     36   uint32_t ym = ((y & 0x7FFFFF) << 1);
     37   if (!u && !v) ym |= 0x1000000;
     38   int32_t y0 = (int32_t)(ys ? -ym : ym);
     39 
     40   uint32_t e0;
     41   int32_t x3, y3;
     42   if (ye > xe) {
     43     uint32_t shift = ye - xe;
     44     e0 = ye;
     45     x3 = shift > 31 ? x0 >> 31 : x0 >> shift;
     46     y3 = y0;
     47   } else {
     48     uint32_t shift = xe - ye;
     49     e0 = xe;
     50     x3 = x0;
     51     y3 = shift > 31 ? y0 >> 31 : y0 >> shift;
     52   }
     53 
     54   uint32_t sum = ((xs << 26) | (xs << 25) | (x3 & 0x01FFFFFF))
     55     + ((ys << 26) | (ys << 25) | (y3 & 0x01FFFFFF));
     56 
     57   uint32_t s = (((sum & (1 << 26)) ? -sum : sum) + 1) & 0x07FFFFFF;
     58 
     59   uint32_t e1 = e0 + 1;
     60   uint32_t t3 = s >> 1;
     61   if ((s & 0x3FFFFFC) != 0) {
     62     while ((t3 & (1<<24)) == 0) {
     63       t3 <<= 1;
     64       e1--;
     65     }
     66   } else {
     67     t3 <<= 24;
     68     e1 -= 24;
     69   }
     70 
     71   bool xn = (x & 0x7FFFFFFF) == 0;
     72   bool yn = (y & 0x7FFFFFFF) == 0;
     73 
     74   if (v) {
     75     return (int32_t)(sum << 5) >> 6;
     76   } else if (xn) {
     77     return (u | yn) ? 0 : y;
     78   } else if (yn) {
     79     return x;
     80   } else if ((t3 & 0x01FFFFFF) == 0 || (e1 & 0x100) != 0) {
     81     return 0;
     82   } else {
     83     return ((sum & 0x04000000) << 5) | (e1 << 23) | ((t3 >> 1) & 0x7FFFFF);
     84   }
     85 }
     86 
     87 uint32_t fp_mul(uint32_t x, uint32_t y) {
     88   uint32_t sign = (x ^ y) & 0x80000000;
     89   uint32_t xe = (x >> 23) & 0xFF;
     90   uint32_t ye = (y >> 23) & 0xFF;
     91 
     92   uint32_t xm = (x & 0x7FFFFF) | 0x800000;
     93   uint32_t ym = (y & 0x7FFFFF) | 0x800000;
     94   uint64_t m = (uint64_t)xm * ym;
     95 
     96   uint32_t e1 = (xe + ye) - 127;
     97   uint32_t z0;
     98   if ((m & (1ULL << 47)) != 0) {
     99     e1++;
    100     z0 = ((m >> 23) + 1) & 0xFFFFFF;
    101   } else {
    102     z0 = ((m >> 22) + 1) & 0xFFFFFF;
    103   }
    104 
    105   if (xe == 0 || ye == 0) {
    106     return 0;
    107   } else if ((e1 & 0x100) == 0) {
    108     return sign | ((e1 & 0xFF) << 23) | (z0 >> 1);
    109   } else if ((e1 & 0x80) == 0) {
    110     return sign | (0xFF << 23) | (z0 >> 1);
    111   } else {
    112     return 0;
    113   }
    114 }
    115 
    116 uint32_t fp_div(uint32_t x, uint32_t y) {
    117   uint32_t sign = (x ^ y) & 0x80000000;
    118   uint32_t xe = (x >> 23) & 0xFF;
    119   uint32_t ye = (y >> 23) & 0xFF;
    120 
    121   uint32_t xm = (x & 0x7FFFFF) | 0x800000;
    122   uint32_t ym = (y & 0x7FFFFF) | 0x800000;
    123   uint32_t q1 = (uint32_t)(xm * (1ULL << 25) / ym);
    124 
    125   uint32_t e1 = (xe - ye) + 126;
    126   uint32_t q2;
    127   if ((q1 & (1 << 25)) != 0) {
    128     e1++;
    129     q2 = (q1 >> 1) & 0xFFFFFF;
    130   } else {
    131     q2 = q1 & 0xFFFFFF;
    132   }
    133   uint32_t q3 = q2 + 1;
    134 
    135   if (xe == 0) {
    136     return 0;
    137   } else if (ye == 0) {
    138     return sign | (0xFF << 23);
    139   } else if ((e1 & 0x100) == 0) {
    140     return sign | ((e1 & 0xFF) << 23) | (q3 >> 1);
    141   } else if ((e1 & 0x80) == 0) {
    142     return sign | (0xFF << 23) | (q2 >> 1);
    143   } else {
    144     return 0;
    145   }
    146 }
    147 
    148 struct idiv idiv(uint32_t x, uint32_t y, bool signed_div) {
    149   bool sign = ((int32_t)x < 0) & signed_div;
    150   uint32_t x0 = sign ? -x : x;
    151 
    152   uint64_t RQ = x0;
    153   for (int S = 0; S < 32; ++S) {
    154     uint32_t w0 = (uint32_t)(RQ >> 31);
    155     uint32_t w1 = w0 - y;
    156     if ((int32_t)w1 < 0) {
    157       RQ = ((uint64_t)w0 << 32) | ((RQ & 0x7FFFFFFFU) << 1);
    158     } else {
    159       RQ = ((uint64_t)w1 << 32) | ((RQ & 0x7FFFFFFFU) << 1) | 1;
    160     }
    161   }
    162 
    163   struct idiv d = { (uint32_t)RQ, (uint32_t)(RQ >> 32) };
    164   if (sign) {
    165     d.quot = -d.quot;
    166     if (d.rem) {
    167       d.quot -= 1;
    168       d.rem = y - d.rem;
    169     }
    170   }
    171   return d;
    172 }