📄 ms_divmul.c
字号:
/* * Copyright (C) 1996-1998 by the Board of Trustees * of Leland Stanford Junior University. * * This file is part of the SimOS distribution. * See LICENSE file for terms of the license. * */ /* * ms_divmul - Code to simulate integer divide and multiply * instructions * * Jim Bennett * 1993, 1994 */#include "ms.h"#ifdef LITTLE_ENDIAN#define UPPER(reg) ((reg)|0x01)#define LOWER(reg) ((reg)&(~0x01))#else#define UPPER(reg) ((reg)&(~0x01))#define LOWER(reg) ((reg)|0x01)#endif#define LOWvoid opMULT (struct s_cpu_state *st, INST *ip, THREAD *th){ uint a, b, c, d, t; int rs, rt, rshi, rthi; WorkDecls; /* Get hi and lo half words of each word */ rs = Ireg(ip->r2); rt = Ireg(ip->r3); rshi = rs>>16; a = rshi; b = rs&0xffff; rthi = rt>>16; c = rthi; d = rt&0xffff; /* Compute hi and lo result. Note the carry out from */ /* lo_reg to hi_reg. */ t = (b*c + a*d)<<16; Ireg(LOWER(ip->r1)) = t + b*d; Ireg(UPPER(ip->r1)) = b*c + a*d; Ireg(UPPER(ip->r1)) = Ireg(UPPER(ip->r1))>>16; Ireg(UPPER(ip->r1)) = Ireg(UPPER(ip->r1)) + a*c; if (t+b*d < t) Ireg(UPPER(ip->r1))++; /* Make the result unavailable until the multiply */ /* latency has transpired. */#if MULT_LATENCY > 1 st->reg_excuse[(UPPER(ip->r1)>>1)] = ST_IMUL; Add_to_worklist (st, MULT_LATENCY, reg_writeback, (void *)(ip->r1));#endif}void opMULTU (struct s_cpu_state *st, INST *ip, THREAD *th){ uint a, b, c, d, t1, t2, rs, rt; WorkDecls; /* Get hi and lo half words of each word */ rs = Ireg(ip->r2); rt = Ireg(ip->r3); a = (rs>>16) & 0xffff; b = rs&0xffff; c = (rt>>16) & 0xffff; d = rt&0xffff; /* Compute hi and lo result. Note the carry out from */ /* lo_reg to hi_reg, and within hi_reg. */ t1 = (b*c + a*d)<<16; Ireg(LOWER(ip->r1)) = t1 + b*d; t2 = b*c + a*d; Ireg(UPPER(ip->r1)) = ((t2>>16) & 0xffff) + a*c; if (t1+b*d < t1) Ireg(UPPER(ip->r1))++; if (t2 < b*c) Ireg(UPPER(ip->r1)) += 0x00010000; /* Make the result unavailable until the multiply */ /* latency has transpired. */#if MULT_LATENCY > 1 st->reg_excuse[(UPPER(ip->r1)>>1)] = ST_IMUL; Add_to_worklist (st, MULT_LATENCY, reg_writeback, (void *)(ip->r1));#endif}void opDIV (struct s_cpu_state *st, INST *ip, THREAD *th){ int a, b; WorkDecls; a = Ireg(ip->r2); b = Ireg(ip->r3); if (b == 0) { Ireg(LOWER(ip->r1)) = 0; Ireg(UPPER(ip->r1)) = 0; } else { Ireg(LOWER(ip->r1)) = a/b; Ireg(UPPER(ip->r1)) = a-(Ireg(LOWER(ip->r1))*b); }#if DIV_LATENCY > 1 st->reg_excuse[(UPPER(ip->r1)>>1)] = ST_IDIV; Add_to_worklist (st, DIV_LATENCY, reg_writeback, (void *)(ip->r1));#endif}void opDIVU (struct s_cpu_state *st, INST *ip, THREAD *th){ uint a, b; WorkDecls; a = Ireg(ip->r2); b = Ireg(ip->r3); if (b == 0) { Ireg(LOWER(ip->r1)) = 0; Ireg(UPPER(ip->r1)) = 0; } else { Ireg(LOWER(ip->r1)) = a/b; Ireg(UPPER(ip->r1)) = a-(Ireg(LOWER(ip->r1))*b); }#if DIV_LATENCY > 1 st->reg_excuse[(UPPER(ip->r1)>>1)] = ST_IDIV; Add_to_worklist (st, DIV_LATENCY, reg_writeback, (void *)(ip->r1));#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -