1/* $NetBSD: bds_emul.S,v 1.5 2011/08/16 06:55:11 matt Exp $ */ 2 3/* 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Ralph Campbell. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)fp.s 8.1 (Berkeley) 6/10/93 35 */ 36 37#include <sys/cdefs.h> 38 39#include <mips/asm.h> 40#include <mips/cpu.h> /* for MIPS_CURLWP */ 41#include <mips/trap.h> /* for T_RES_INST */ 42 43#include "assym.h" 44 45/* insns are reordered in the way as MIPS architecture imposes */ 46 .set reorder 47 48#define REG_REGMASK (0x1f << REG_SCALESHIFT) 49 50/* 51 * Emulate CPU instruction in branch delay slot. 52 * These instructions are not implemented and causes SIGILL. 53 * jump/branch 54 * COP0 55 * trap/syscall/break 56 * 57 * Args are same as mips_emul_fp, eg. 58 * void mips_emul_delayslot(uint32_t insn, struct trapframe *tf, uint32_t cause); 59 * It should be used to emulate an instruction in a branch delay slot. 60 */ 61LEAF(mips_emul_branchdelayslot) 62 REG_PROLOGUE 63 REG_S zero, TF_REG_ZERO(a1) # ensure zero has value 0 64 REG_EPILOGUE 65 move t3, ra # need to save this locally 66 67 srl t0, a0, 26-PTR_SCALESHIFT 68 andi t0, 0x3F << PTR_SCALESHIFT 69 PTR_L t9, bcemul_optbl(t0) 70 jr t9 71 72 .rdata 73bcemul_optbl: 74 PTR_WORD bcemul_special # 000 SPECIAL 75 PTR_WORD bcemul_sigill # 001 REGIMM 76 PTR_WORD bcemul_sigill # 002 J 77 PTR_WORD bcemul_sigill # 003 JAL 78 PTR_WORD bcemul_sigill # 004 BEQ 79 PTR_WORD bcemul_sigill # 005 BNE 80 PTR_WORD bcemul_sigill # 006 BLEZ 81 PTR_WORD bcemul_sigill # 007 BGTZ 82 PTR_WORD bcemul_addi # 010 ADDI 83 PTR_WORD bcemul_addiu # 011 ADDIU 84 PTR_WORD bcemul_slti # 012 SLTI 85 PTR_WORD bcemul_sltiu # 013 SLTIU 86 PTR_WORD bcemul_andi # 014 ANDI 87 PTR_WORD bcemul_ori # 015 ORI 88 PTR_WORD bcemul_xori # 016 XORI 89 PTR_WORD bcemul_lui # 017 LUI 90 PTR_WORD bcemul_sigill # 020 COP0 91 PTR_WORD _C_LABEL(mips_emul_fp) # 021 COP1 92 PTR_WORD bcemul_sigill # 022 COP2 93 PTR_WORD bcemul_sigill # 023 COP1X 94 PTR_WORD bcemul_sigill # 024 BEQL 95 PTR_WORD bcemul_sigill # 025 BNEL 96 PTR_WORD bcemul_sigill # 026 BNEZL 97 PTR_WORD bcemul_sigill # 027 BGTZL 98#ifdef __mips_o32 99 PTR_WORD bcemul_sigill # 030 DADDI (*) 100 PTR_WORD bcemul_sigill # 031 DADDIU (*) 101 PTR_WORD bcemul_sigill # 030 LDL (*) 102 PTR_WORD bcemul_sigill # 031 LDR (*) 103#else 104 PTR_WORD _C_LABEL(mips_emul_daddi) # 030 DADDI (*) 105 PTR_WORD _C_LABEL(mips_emul_daddiu) # 031 DADDIU (*) 106 PTR_WORD _C_LABEL(mips_emul_ldl) # 032 LDL (*) 107 PTR_WORD _C_LABEL(mips_emul_ldr) # 033 LDR (*) 108#endif 109 PTR_WORD bcemul_sigill # 034 SPECIAL2 110 PTR_WORD bcemul_sigill # 035 JALX 111 PTR_WORD bcemul_sigill # 036 MDMX 112 PTR_WORD bcemul_sigill # 037 SPECIAL3 113 PTR_WORD _C_LABEL(mips_emul_lb) # 040 LB 114 PTR_WORD _C_LABEL(mips_emul_lh) # 041 LH 115 PTR_WORD _C_LABEL(mips_emul_lwl) # 042 LWL 116 PTR_WORD _C_LABEL(mips_emul_lw) # 043 LW 117 PTR_WORD _C_LABEL(mips_emul_lbu) # 044 LBU 118 PTR_WORD _C_LABEL(mips_emul_lhu) # 045 LHU 119 PTR_WORD _C_LABEL(mips_emul_lwr) # 046 LWR 120#ifdef __mips_o32 121 PTR_WORD bcemul_sigill # 047 LWU (*) 122#else 123 PTR_WORD _C_LABEL(mips_emul_lwu) # 047 LWU (*) 124#endif 125 PTR_WORD _C_LABEL(mips_emul_sb) # 050 SB 126 PTR_WORD _C_LABEL(mips_emul_sh) # 051 SH 127 PTR_WORD _C_LABEL(mips_emul_swl) # 052 SWL 128 PTR_WORD _C_LABEL(mips_emul_sw) # 053 SW 129#ifdef __mips_o32 130 PTR_WORD bcemul_sigill # 054 SDL (*) 131 PTR_WORD bcemul_sigill # 055 SDR (*) 132#else 133 PTR_WORD _C_LABEL(mips_emul_sdl) # 054 SDL (*) 134 PTR_WORD _C_LABEL(mips_emul_sdr) # 055 SDR (*) 135#endif 136 PTR_WORD _C_LABEL(mips_emul_swr) # 056 SWR 137 PTR_WORD bcemul_sigill # 057 CACHE 138 PTR_WORD bcemul_sigill # 060 LL 139 PTR_WORD _C_LABEL(mips_emul_lwc1) # 061 LWC1 140 PTR_WORD bcemul_sigill # 062 LWC2 141 PTR_WORD bcemul_sigill # 063 PREF 142 PTR_WORD bcemul_sigill # 064 LLD (*) 143 PTR_WORD _C_LABEL(mips_emul_ldc1) # 065 LDC 144 PTR_WORD bcemul_sigill # 066 LDC2 145#ifdef __mips_o32 146 PTR_WORD bcemul_sigill # 067 LD (*) 147#else 148 PTR_WORD _C_LABEL(mips_emul_ld) # 067 LD (*) 149#endif 150 PTR_WORD bcemul_sigill # 070 SC 151 PTR_WORD _C_LABEL(mips_emul_swc1) # 071 SWC1 152 PTR_WORD bcemul_sigill # 072 SWC2 153 PTR_WORD bcemul_sigill # 073 154 PTR_WORD bcemul_sigill # 074 SCD (*) 155 PTR_WORD _C_LABEL(mips_emul_sdc1) # 075 SDC1 156 PTR_WORD bcemul_sigill # 076 SDC2 157#ifdef __mips_o32 158 PTR_WORD bcemul_sigill # 077 SD (*) 159#else 160 PTR_WORD _C_LABEL(mips_emul_sd) # 077 SD (*) 161#endif 162 163 .text 164bcemul_immed_prologue: 165 srl t1, a0, 21-REG_SCALESHIFT # rs (source) 166 srl t2, a0, 16-REG_SCALESHIFT # rt (dest) 167 andi t1, REG_REGMASK 168 andi t2, REG_REGMASK 169 PTR_ADDU t1, a1 170 PTR_ADDU t2, a1 171 sll v1, a0, 16 172 sra v1, v1, 16 # signed immed 173 REG_PROLOGUE 174 REG_L v0, TF_REG_ZERO(t1) # load source 175 REG_EPILOGUE 176 jr ra # execute the instruction 177 178bcemul_uimmed_prologue: 179 srl t1, a0, 21-REG_SCALESHIFT # rs (source) 180 srl t2, a0, 16-REG_SCALESHIFT # rt (dest) 181 andi t1, REG_REGMASK 182 andi t2, REG_REGMASK 183 PTR_ADDU t1, a1 184 PTR_ADDU t2, a1 185 andi v1, a0, 0xffff # unsigned immed 186 REG_PROLOGUE 187 REG_L v0, TF_REG_ZERO(t1) # load source 188 REG_EPILOGUE 189 jr ra 190 191#ifndef __mips_o32 192bcemul_daddi: 193 bal bcemul_immed_prologue 194 daddiu t0, v0, v1 195 b bcemul_check_add_overflow 196#endif 197 198bcemul_addi: 199 bal bcemul_immed_prologue 200 addu t0, v0, v1 201 202bcemul_check_add_overflow: 203 move ta0, t0 # result 204 move ta1, v0 # addend 1 205 move ta2, v1 # addend 2 206 207bcemul_check_overflow: 208 /* Overflow check */ 209 xor ta2, ta1 /* negative + positive can't overflow */ 210 bltz ta2, bcemul_store_and_done 211 212 /* must have added two positive or two negative numbers */ 213 xor ta1, ta0 /* result have same signedness as source? */ 214 bgez ta1, bcemul_store_and_done /* yes, then we didn't overflow */ 215 216 b bcemul_sigill 217 218bcemul_addiu: 219 bal bcemul_immed_prologue 220 addu t0, v0, v1 221 b bcemul_store_and_done 222 223#ifndef __mips_o32 224bcemul_daddiu: 225 bal bcemul_immed_prologue 226 daddu t0, v0, v1 227 b bcemul_store_and_done 228#endif 229 230bcemul_slti: 231 bal bcemul_immed_prologue 232 slt t0, v0, v1 233 b bcemul_store_and_done 234 235bcemul_sltiu: 236 bal bcemul_immed_prologue 237 sltu t0, v0, v1 238 b bcemul_store_and_done 239 240bcemul_andi: 241 bal bcemul_uimmed_prologue 242 and t0, v0, v1 243 b bcemul_store_and_done 244 245bcemul_ori: 246 bal bcemul_uimmed_prologue 247 or t0, v0, v1 248 b bcemul_store_and_done 249 250bcemul_xori: 251 bal bcemul_uimmed_prologue 252 xor t0, v0, v1 253 b bcemul_store_and_done 254 255bcemul_lui: 256 srl t2, a0, 16-REG_SCALESHIFT # rt 257 andi t2, REG_REGMASK 258 PTR_ADDU t2, a1 259 sll t0, a0, 16 260 b bcemul_store_and_done 261 262 .rdata 263bcemul_specialtbl: 264 PTR_WORD bcemul_special_genshift # 000 SLL 265 PTR_WORD bcemul_sigill # 001 MOVC1 266 PTR_WORD bcemul_special_genshift # 002 SRL 267 PTR_WORD bcemul_special_genshift # 003 SRA 268 PTR_WORD bcemul_special_genshiftv # 004 SLLV 269 PTR_WORD bcemul_sigill # 005 270 PTR_WORD bcemul_special_genshiftv # 006 SRLV 271 PTR_WORD bcemul_special_genshiftv # 007 SRAV 272 PTR_WORD bcemul_sigill # 010 JR 273 PTR_WORD bcemul_sigill # 011 JALR 274 PTR_WORD bcemul_sigill # 012 MOVZ 275 PTR_WORD bcemul_sigill # 013 MOVN 276 PTR_WORD bcemul_sigill # 014 SYSCALL 277 PTR_WORD bcemul_sigill # 015 BREAK 278 PTR_WORD bcemul_sigill # 016 279 PTR_WORD bcemul_special_sync # 017 SYNC 280 PTR_WORD bcemul_special_mfhilo # 020 MFHI 281 PTR_WORD bcemul_special_mthilo # 021 MTHI 282 PTR_WORD bcemul_special_mfhilo # 022 MFLO 283 PTR_WORD bcemul_special_mthilo # 023 MTLO 284#ifdef __mips_o32 285 PTR_WORD bcemul_sigill # 024 DSLLV (*) 286 PTR_WORD bcemul_sigill # 025 287 PTR_WORD bcemul_sigill # 026 DSRLV (*) 288 PTR_WORD bcemul_sigill # 027 DSRAV (*) 289#else 290 PTR_WORD bcemul_special_genshiftv # 024 DSLLV (*) 291 PTR_WORD bcemul_sigill # 025 292 PTR_WORD bcemul_special_genshiftv # 026 DSRLV (*) 293 PTR_WORD bcemul_special_genshiftv # 027 DSRAV (*) 294#endif 295 PTR_WORD bcemul_special_genmultdiv # 030 MULT 296 PTR_WORD bcemul_special_genmultdiv # 031 MULTU 297 PTR_WORD bcemul_special_genmultdiv # 032 DIV 298 PTR_WORD bcemul_special_genmultdiv # 033 DIVU 299#ifdef __mips_o32 300 PTR_WORD bcemul_sigill # 034 DMULT (*) 301 PTR_WORD bcemul_sigill # 035 DMULTU (*) 302 PTR_WORD bcemul_sigill # 036 DDIV (*) 303 PTR_WORD bcemul_sigill # 037 DDIVU (*) 304#else 305 PTR_WORD bcemul_special_genmultdiv # 034 DMULT (*) 306 PTR_WORD bcemul_special_genmultdiv # 035 DMULTU (*) 307 PTR_WORD bcemul_special_genmultdiv # 036 DDIV (*) 308 PTR_WORD bcemul_special_genmultdiv # 037 DDIVU (*) 309#endif 310 PTR_WORD bcemul_special_genadd # 040 ADD 311 PTR_WORD bcemul_special_gen3op # 041 ADDU 312 PTR_WORD bcemul_special_gensub # 042 SUB 313 PTR_WORD bcemul_special_gen3op # 043 SUBU 314 PTR_WORD bcemul_special_gen3op # 044 AND 315 PTR_WORD bcemul_special_gen3op # 045 OR 316 PTR_WORD bcemul_special_gen3op # 046 XOR 317 PTR_WORD bcemul_special_gen3op # 047 NOR 318 PTR_WORD bcemul_sigill # 050 319 PTR_WORD bcemul_sigill # 051 320 PTR_WORD bcemul_special_gen3op # 052 SLT 321 PTR_WORD bcemul_special_gen3op # 053 SLTU 322#ifdef __mips_o32 323 PTR_WORD bcemul_sigill # 054 DADD (*) 324 PTR_WORD bcemul_sigill # 055 DADDU (*) 325 PTR_WORD bcemul_sigill # 056 DSUB (*) 326 PTR_WORD bcemul_sigill # 057 DSUBU (*) 327#else 328 PTR_WORD bcemul_special_genadd # 054 DADD (*) 329 PTR_WORD bcemul_special_gen3op # 055 DADDU (*) 330 PTR_WORD bcemul_special_gensub # 056 DSUB (*) 331 PTR_WORD bcemul_special_gen3op # 057 DSUBU (*) 332#endif 333 PTR_WORD bcemul_sigill # 060 TGE 334 PTR_WORD bcemul_sigill # 061 TGEU 335 PTR_WORD bcemul_sigill # 062 TLT 336 PTR_WORD bcemul_sigill # 063 TLTU 337 PTR_WORD bcemul_sigill # 064 TEQ 338 PTR_WORD bcemul_sigill # 065 339 PTR_WORD bcemul_sigill # 066 TNE 340 PTR_WORD bcemul_sigill # 067 341#ifdef __mips_o32 342 PTR_WORD bcemul_sigill # 070 DSLL (*) 343 PTR_WORD bcemul_sigill # 071 344 PTR_WORD bcemul_sigill # 072 DSRL (*) 345 PTR_WORD bcemul_sigill # 073 DSRA (*) 346 PTR_WORD bcemul_sigill # 074 DSLL32 (*) 347 PTR_WORD bcemul_sigill # 075 348 PTR_WORD bcemul_sigill # 076 DSRL32 (*) 349 PTR_WORD bcemul_sigill # 077 DSRA32 (*) 350#else 351 PTR_WORD bcemul_special_genshift # 070 DSLL (*) 352 PTR_WORD bcemul_sigill # 071 353 PTR_WORD bcemul_special_genshift # 072 DSRL (*) 354 PTR_WORD bcemul_special_genshift # 073 DSRA (*) 355 PTR_WORD bcemul_special_genshift # 074 DSLL32 (*) 356 PTR_WORD bcemul_sigill # 075 357 PTR_WORD bcemul_special_genshift # 076 DSRL32 (*) 358 PTR_WORD bcemul_special_genshift # 077 DSRA32 (*) 359#endif 360 361 .text 362 .set push 363 .set noreorder 364 .set nomacro 365 .set mips64 366bcemul_special_op: 367 jr ra; sllv t0, v0, v1 # 000 SLL 368 jr ra; nop # 001 MOVC1 369 jr ra; srlv t0, v0, v1 # 002 SRL 370 jr ra; srav t0, v0, v1 # 003 SRA 371 jr ra; sllv t0, v0, v1 # 004 SLLV 372 jr ra; nop # 005 * 373 jr ra; srlv t0, v0, v1 # 006 SRLV 374 jr ra; srav t0, v0, v1 # 007 SRAV 375 376 jr ra; nop # 010 JR 377 jr ra; nop # 011 JALR 378 jr ra; movz t0, v0, v1 # 012 MOVZ 379 jr ra; movn t0, v0, v1 # 013 MOVN 380 jr ra; nop # 014 SYSCALL 381 jr ra; nop # 015 BREAK 382 jr ra; nop # 016 * 383 jr ra; nop # 017 SYNC 384 385 jr ra; mfhi t0 # 020 MFHI 386 jr ra; mthi v0 # 021 MTHI 387 jr ra; mflo t0 # 022 MFLO 388 jr ra; mtlo v0 # 023 MTLO 389 jr ra; dsllv t0, v0, v1 # 024 DSLLV 390 jr ra; nop # 025 * 391 jr ra; dsrlv t0, v0, v1 # 026 DSRLV 392 jr ra; dsrav t0, v0, v1 # 027 DSRAV 393 394 jr ra; mult v0, v1 # 030 MULT 395 jr ra; multu v0, v1 # 031 MULTU 396 jr ra; div $0, v0, v1 # 032 DIV 397 jr ra; divu $0, v0, v1 # 033 DIVU 398 jr ra; dmult v0, v1 # 034 DMULT 399 jr ra; dmultu v0, v1 # 035 DMULTU 400 jr ra; ddiv $0, v0, v1 # 036 DDIV 401 jr ra; ddivu $0, v0, v1 # 037 DDIVU 402 403 jr ra; add t0, v0, v1 # 040 ADD 404 jr ra; addu t0, v0, v1 # 041 ADDU 405 jr ra; sub t0, v0, v1 # 042 SUB 406 jr ra; subu t0, v0, v1 # 043 SUBU 407 jr ra; and t0, v0, v1 # 044 AND 408 jr ra; or t0, v0, v1 # 045 OR 409 jr ra; xor t0, v0, v1 # 046 XOR 410 jr ra; nor t0, v0, v1 # 047 NOR 411 412 jr ra; nop # 050 * 413 jr ra; nop # 051 * 414 jr ra; slt t0, v0, v1 # 052 SLT 415 jr ra; sltu t0, v0, v1 # 053 SLTU 416 jr ra; dadd t0, v0, v1 # 054 DADD 417 jr ra; daddu t0, v0, v1 # 055 DADDU 418 jr ra; dsub t0, v0, v1 # 056 DSUB 419 jr ra; dsubu t0, v0, v1 # 057 DSUBU 420 421 jr ra; tge v0, v1 # 060 TGE 422 jr ra; tgeu v0, v1 # 061 TGEU 423 jr ra; tlt v0, v1 # 062 TLT 424 jr ra; tltu v0, v1 # 063 TLTU 425 jr ra; teq v0, v1 # 064 TEQ 426 jr ra; nop # 065 * 427 jr ra; tne v0, v1 # 066 TNE 428 jr ra; nop # 067 * 429 430 jr ra; dsllv t0, v0, v1 # 070 DSLL 431 jr ra; nop # 071 * 432 jr ra; dsrlv t0, v0, v1 # 072 DSRL 433 jr ra; dsrav t0, v0, v1 # 073 DSRA 434 jr ra; dsllv t0, v0, v1 # 074 DSLL32 435 jr ra; nop # 075 * 436 jr ra; dsrlv t0, v0, v1 # 076 DSRL32 437 jr ra; dsrav t0, v0, v1 # 077 DSRA32 438 .set pop 439 440bcemul_special: 441 andi t0, a0, 0x3f # get special code 442 sll t1, t0, 3 # calculate index in specialop 443 sll t0, PTR_SCALESHIFT 444 PTR_L t9, bcemul_specialtbl(t0) 445 PTR_LA t0, bcemul_special_op(t1) 446 jr t9 447 448bcemul_special_3op_prologue: 449 move t9, t0 450 srl t0, a0, 21-REG_SCALESHIFT # rs (source1) 451 srl t1, a0, 16-REG_SCALESHIFT # rt (source2) 452 srl t2, a0, 11-REG_SCALESHIFT # rd (dest) 453 andi t0, REG_REGMASK 454 andi t1, REG_REGMASK 455 andi t2, REG_REGMASK 456 PTR_ADDU t0, a1 457 PTR_ADDU t1, a1 458 PTR_ADDU t2, a1 459 REG_PROLOGUE 460 REG_L v0, TF_REG_ZERO(t0) # load source1 461 REG_L v1, TF_REG_ZERO(t1) # load source2 462 REG_EPILOGUE 463 jr t9 464 465bcemul_special_2src_prologue: 466 move t9, t0 467 srl t0, a0, 21-REG_SCALESHIFT # rs (source1) 468 srl t1, a0, 16-REG_SCALESHIFT # rt (source2) 469 andi t0, REG_REGMASK 470 andi t1, REG_REGMASK 471 PTR_ADDU t0, a1 472 PTR_ADDU t1, a1 473 REG_PROLOGUE 474 REG_L v0, TF_REG_ZERO(t0) # load source1 475 REG_L v1, TF_REG_ZERO(t1) # load source2 476 REG_EPILOGUE 477 jr t9 478 479bcemul_special_genshift: 480 move t9, t0 481 srl t1, a0, 16-REG_SCALESHIFT # rt (source) 482 srl t2, a0, 11-REG_SCALESHIFT # rd (dest) 483 srl v1, a0, 6 # sa 484 andi t1, REG_REGMASK 485 andi t2, REG_REGMASK 486 beqz t2, bcemul_done # fast escape for nop variants 487 andi v1, 0x001F 488#ifndef __mips_o32 489 /* 490 * Deal with DSLL32, DSRA32, DSRL32 who need 32 added to their 491 * shift count. 492 */ 493 andi v0, a0, 077 # focus on special op 494 sltiu v0, v0, 074 # less than DSLL32? 495 xori v0, 1 # invert result 496 sll v0, 5 # shift by 5 (now 0 or 32) 497 addu v1, v0 # add to shift count 498#endif 499 PTR_ADDU t1, a1 500 PTR_ADDU t2, a1 501 REG_PROLOGUE 502 REG_L v0, TF_REG_ZERO(t1) # load source 503 REG_EPILOGUE 504 jal t9 505 j bcemul_store_and_done 506 507bcemul_special_sync: 508 b bcemul_done 509 510bcemul_special_mfhilo: 511 srl t2, a0, 11-REG_SCALESHIFT # rd (dest) 512 andi t2, REG_REGMASK 513 PTR_ADDU t1, a1, TF_REG_MULHI 514 PTR_ADDU t2, a1 515 and v0, a0, 2 # bit 1: 0=HI 1=LO 516 sll v0, REG_SCALESHIFT - 1 517#if TF_REG_MULLO < TF_REG_MULHI 518 PTR_SUBU t1, v0 519#else 520 PTR_ADDU t1, v0 521#endif 522 REG_PROLOGUE 523 REG_L t0, TF_REG_ZERO(t1) # load source (mullo or mulhi) 524 REG_EPILOGUE 525 b bcemul_store_and_done 526 527bcemul_special_mthilo: 528 srl t1, a0, 21-REG_SCALESHIFT # rs (source) 529 andi t1, REG_REGMASK 530 PTR_ADDU t1, a1 531 PTR_ADDU t2, a1, TF_REG_MULHI 532 and v0, a0, 2 # bit 1: 0=HI l=LO 533 sll v0, REG_SCALESHIFT - 1 534#if TF_REG_MULLO < TF_REG_MULHI 535 PTR_SUBU t2, v0 536#else 537 PTR_ADDU t2, v0 538#endif 539 REG_PROLOGUE 540 REG_L t0, TF_REG_ZERO(t1) 541 REG_EPILOGUE 542 b bcemul_store_and_done 543 544bcemul_special_genmultdiv: 545 bal bcemul_special_2src_prologue # grab operands and do it. 546 mflo v0 547 mfhi v1 548 REG_PROLOGUE 549 REG_S v0, TF_REG_MULLO(a1) 550 REG_S v1, TF_REG_MULHI(a1) 551 REG_EPILOGUE 552 b bcemul_done 553 554bcemul_special_genadd: 555 bal bcemul_special_3op_prologue 556 b bcemul_check_add_overflow 557 558bcemul_special_gensub: 559 bal bcemul_special_3op_prologue 560 561 /* 562 * t0 = v0 - v1 which means v0 = t0 + v1 563 * Now we can the same logic for overflow from addition. 564 */ 565 move ta0, v0 566 move ta1, t0 567 move ta2, v1 568 569 b bcemul_check_overflow 570 571bcemul_special_genshiftv: 572bcemul_special_gen3op: 573 bal bcemul_special_3op_prologue 574 #b bcemul_store_and_done # fallthrough to bcemul_store_and_done 575 576bcemul_store_and_done: 577 beq a1, t2, bcemul_done # don't store to zero 578 REG_PROLOGUE 579 REG_S t0, TF_REG_ZERO(t2) 580 REG_EPILOGUE 581 #b bcemul_done # fallthrough to bcemul_done 582 583bcemul_done: 584/* 585 * Succeeded to emulate instruction with no error 586 * so compute the next PC. 587 */ 588 PTR_SUBU sp, CALLFRAME_SIZ 589 REG_S t3, CALLFRAME_RA(sp) 590 REG_S s0, CALLFRAME_S0(sp) 591 move s0, a1 # save trapfame 592 593 /* Fetch previous branch instruction */ 594 REG_PROLOGUE 595 REG_L a0, TF_REG_EPC(s0) 596 REG_EPILOGUE 597 jal _C_LABEL(ufetch_uint32) 598 599 /* Calculate branch destination */ 600 sll t0, v0, 16 601 sra t0, t0, 16-2 602 REG_PROLOGUE 603 REG_L t1, TF_REG_EPC(s0) 604 PTR_ADDU t0, 4 605 PTR_ADDU t1, t0 606 REG_S t1, TF_REG_EPC(s0) 607 REG_EPILOGUE 608 609 REG_L ra, CALLFRAME_RA(sp) 610 REG_L s0, CALLFRAME_S0(sp) 611 PTR_ADDU sp, CALLFRAME_SIZ 612 jr ra 613 614/* 615 * Send SIGILL, SIGFPE. 616 * Args are same as mips_emul_fp. 617 */ 618bcemul_sigill: 619 li t0, 0xFFFFFF00 620 and a2, a2, t0 621 ori a2, a2, T_RES_INST << MIPS_CR_EXC_CODE_SHIFT 622 REG_PROLOGUE 623 REG_S a2, TF_REG_CAUSE(a1) 624 REG_EPILOGUE 625 626 move ra, t3 # restore ra 627 move a1, a0 # code = instruction 628 move a0, MIPS_CURLWP # get current process 629 j _C_LABEL(mips_fpuillinst) 630 631END(mips_emul_branchdelayslot) 632