137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan/* ===-- udivmodti4.c - Implement __udivmodti4 -----------------------------=== 237a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * 337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * The LLVM Compiler Infrastructure 437a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * 59ad441ffec97db647fee3725b3424284fb913e14Howard Hinnant * This file is dual licensed under the MIT and the University of Illinois Open 69ad441ffec97db647fee3725b3424284fb913e14Howard Hinnant * Source Licenses. See LICENSE.TXT for details. 737a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * 837a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * ===----------------------------------------------------------------------=== 937a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * 1037a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * This file implements __udivmodti4 for the compiler_rt library. 1137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * 1237a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * ===----------------------------------------------------------------------=== 1337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan */ 14b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 15b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar#include "int_lib.h" 16b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 177f2d7c75e713d778106d01a54e7aef40227bbf2dChandler Carruth#if __x86_64 187f2d7c75e713d778106d01a54e7aef40227bbf2dChandler Carruth 1937a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan/* Effects: if rem != 0, *rem = a % b 2037a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * Returns: a / b 2137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan */ 22b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 2337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan/* Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide */ 24b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 25b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbartu_int 26b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar__udivmodti4(tu_int a, tu_int b, tu_int* rem) 27b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar{ 28b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar const unsigned n_udword_bits = sizeof(du_int) * CHAR_BIT; 29b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar const unsigned n_utword_bits = sizeof(tu_int) * CHAR_BIT; 30b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar utwords n; 31b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar n.all = a; 32b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar utwords d; 33b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar d.all = b; 34b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar utwords q; 35b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar utwords r; 36b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar unsigned sr; 3737a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /* special cases, X is unknown, K != 0 */ 388bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan if (n.s.high == 0) 39b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar { 408bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan if (d.s.high == 0) 41b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar { 4237a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /* 0 X 4337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * --- 4437a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * 0 X 4537a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan */ 46b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar if (rem) 478bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan *rem = n.s.low % d.s.low; 488bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan return n.s.low / d.s.low; 49b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 5037a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /* 0 X 5137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * --- 5237a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * K X 5337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan */ 54b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar if (rem) 558bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan *rem = n.s.low; 56b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar return 0; 57b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 588bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan /* n.s.high != 0 */ 598bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan if (d.s.low == 0) 60b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar { 618bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan if (d.s.high == 0) 62b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar { 6337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /* K X 6437a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * --- 6537a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * 0 0 6637a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan */ 67b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar if (rem) 688bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan *rem = n.s.high % d.s.low; 698bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan return n.s.high / d.s.low; 70b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 718bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan /* d.s.high != 0 */ 728bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan if (n.s.low == 0) 73b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar { 7437a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /* K 0 7537a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * --- 7637a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * K 0 7737a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan */ 78b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar if (rem) 79b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar { 808bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan r.s.high = n.s.high % d.s.high; 818bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan r.s.low = 0; 82b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar *rem = r.all; 83b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 848bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan return n.s.high / d.s.high; 85b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 8637a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /* K K 8737a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * --- 8837a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * K 0 8937a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan */ 908bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan if ((d.s.high & (d.s.high - 1)) == 0) /* if d is a power of 2 */ 91b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar { 92b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar if (rem) 93b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar { 948bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan r.s.low = n.s.low; 958bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan r.s.high = n.s.high & (d.s.high - 1); 96b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar *rem = r.all; 97b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 988bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan return n.s.high >> __builtin_ctzll(d.s.high); 99b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 10037a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /* K K 10137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * --- 10237a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * K 0 10337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan */ 1048bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan sr = __builtin_clzll(d.s.high) - __builtin_clzll(n.s.high); 10537a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /* 0 <= sr <= n_udword_bits - 2 or sr large */ 106b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar if (sr > n_udword_bits - 2) 107b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar { 108b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar if (rem) 109b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar *rem = n.all; 110b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar return 0; 111b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 112b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar ++sr; 11337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /* 1 <= sr <= n_udword_bits - 1 */ 11437a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /* q.all = n.all << (n_utword_bits - sr); */ 1158bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan q.s.low = 0; 1168bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan q.s.high = n.s.low << (n_udword_bits - sr); 11737a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /* r.all = n.all >> sr; */ 1188bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan r.s.high = n.s.high >> sr; 1198bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan r.s.low = (n.s.high << (n_udword_bits - sr)) | (n.s.low >> sr); 120b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 1218bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan else /* d.s.low != 0 */ 122b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar { 1238bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan if (d.s.high == 0) 124b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar { 12537a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /* K X 12637a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * --- 12737a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * 0 K 12837a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan */ 1298bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan if ((d.s.low & (d.s.low - 1)) == 0) /* if d is a power of 2 */ 130b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar { 131b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar if (rem) 1328bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan *rem = n.s.low & (d.s.low - 1); 1338bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan if (d.s.low == 1) 134b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar return n.all; 1354fcc9aacd048741a4934f044a295d1ccf73a0173Joerg Sonnenberger sr = __builtin_ctzll(d.s.low); 1368bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan q.s.high = n.s.high >> sr; 1378bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan q.s.low = (n.s.high << (n_udword_bits - sr)) | (n.s.low >> sr); 138b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar return q.all; 139b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 14037a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /* K X 14137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * --- 14237a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * 0 K 14337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan */ 1448bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan sr = 1 + n_udword_bits + __builtin_clzll(d.s.low) 1458bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan - __builtin_clzll(n.s.high); 14637a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /* 2 <= sr <= n_utword_bits - 1 14737a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * q.all = n.all << (n_utword_bits - sr); 14837a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * r.all = n.all >> sr; 14937a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * if (sr == n_udword_bits) 15037a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * { 1518bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan * q.s.low = 0; 1528bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan * q.s.high = n.s.low; 1538bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan * r.s.high = 0; 1548bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan * r.s.low = n.s.high; 15537a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * } 15637a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * else if (sr < n_udword_bits) // 2 <= sr <= n_udword_bits - 1 15737a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * { 1588bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan * q.s.low = 0; 1598bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan * q.s.high = n.s.low << (n_udword_bits - sr); 1608bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan * r.s.high = n.s.high >> sr; 1618bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan * r.s.low = (n.s.high << (n_udword_bits - sr)) | (n.s.low >> sr); 16237a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * } 16337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * else // n_udword_bits + 1 <= sr <= n_utword_bits - 1 16437a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * { 1658bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan * q.s.low = n.s.low << (n_utword_bits - sr); 1668bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan * q.s.high = (n.s.high << (n_utword_bits - sr)) | 1678bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan * (n.s.low >> (sr - n_udword_bits)); 1688bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan * r.s.high = 0; 1698bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan * r.s.low = n.s.high >> (sr - n_udword_bits); 17037a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * } 17137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan */ 1728bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan q.s.low = (n.s.low << (n_utword_bits - sr)) & 173b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar ((di_int)(int)(n_udword_bits - sr) >> (n_udword_bits-1)); 1748bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan q.s.high = ((n.s.low << ( n_udword_bits - sr)) & 175b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar ((di_int)(int)(sr - n_udword_bits - 1) >> (n_udword_bits-1))) | 1768bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan (((n.s.high << (n_utword_bits - sr)) | 1778bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan (n.s.low >> (sr - n_udword_bits))) & 178b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar ((di_int)(int)(n_udword_bits - sr) >> (n_udword_bits-1))); 1798bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan r.s.high = (n.s.high >> sr) & 180b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar ((di_int)(int)(sr - n_udword_bits) >> (n_udword_bits-1)); 1818bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan r.s.low = ((n.s.high >> (sr - n_udword_bits)) & 182b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar ((di_int)(int)(n_udword_bits - sr - 1) >> (n_udword_bits-1))) | 1838bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan (((n.s.high << (n_udword_bits - sr)) | 1848bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan (n.s.low >> sr)) & 185b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar ((di_int)(int)(sr - n_udword_bits) >> (n_udword_bits-1))); 186b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 187b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar else 188b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar { 18937a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /* K X 19037a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * --- 19137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * K K 19237a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan */ 1938bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan sr = __builtin_clzll(d.s.high) - __builtin_clzll(n.s.high); 19437a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /*0 <= sr <= n_udword_bits - 1 or sr large */ 195b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar if (sr > n_udword_bits - 1) 196b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar { 197b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar if (rem) 198b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar *rem = n.all; 199b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar return 0; 200b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 201b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar ++sr; 20237a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /* 1 <= sr <= n_udword_bits */ 20337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /* q.all = n.all << (n_utword_bits - sr); */ 2048bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan q.s.low = 0; 2058bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan q.s.high = n.s.low << (n_udword_bits - sr); 20637a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /* r.all = n.all >> sr; 20737a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * if (sr < n_udword_bits) 20837a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * { 2098bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan * r.s.high = n.s.high >> sr; 2108bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan * r.s.low = (n.s.high << (n_udword_bits - sr)) | (n.s.low >> sr); 21137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * } 21237a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * else 21337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * { 2148bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan * r.s.high = 0; 2158bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan * r.s.low = n.s.high; 21637a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * } 21737a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan */ 2188bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan r.s.high = (n.s.high >> sr) & 219b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar ((di_int)(int)(sr - n_udword_bits) >> (n_udword_bits-1)); 2208bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan r.s.low = (n.s.high << (n_udword_bits - sr)) | 2218bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan ((n.s.low >> sr) & 222b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar ((di_int)(int)(sr - n_udword_bits) >> (n_udword_bits-1))); 223b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 224b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 22537a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /* Not a special case 22637a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * q and r are initialized with: 22737a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * q.all = n.all << (n_utword_bits - sr); 22837a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * r.all = n.all >> sr; 22937a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * 1 <= sr <= n_utword_bits - 1 23037a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan */ 231b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar su_int carry = 0; 232b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar for (; sr > 0; --sr) 233b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar { 23437a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /* r:q = ((r:q) << 1) | carry */ 2358bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan r.s.high = (r.s.high << 1) | (r.s.low >> (n_udword_bits - 1)); 2368bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan r.s.low = (r.s.low << 1) | (q.s.high >> (n_udword_bits - 1)); 2378bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan q.s.high = (q.s.high << 1) | (q.s.low >> (n_udword_bits - 1)); 2388bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan q.s.low = (q.s.low << 1) | carry; 23937a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan /* carry = 0; 24037a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * if (r.all >= d.all) 24137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * { 24237a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * r.all -= d.all; 24337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * carry = 1; 24437a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * } 24537a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan */ 246b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar const ti_int s = (ti_int)(d.all - r.all - 1) >> (n_utword_bits - 1); 247b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar carry = s & 1; 248b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar r.all -= d.all & s; 249b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar } 250b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar q.all = (q.all << 1) | carry; 251b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar if (rem) 252b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar *rem = r.all; 253b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar return q.all; 254b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar} 255b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar 2568bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan#endif /* __x86_64 */ 257