Home | History | Annotate | Download | only in runtime
      1 // Copyright 2009 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // Software floating point interpretation of ARM 7500 FP instructions.
      6 // The interpretation is not bit compatible with the 7500.
      7 // It uses true little-endian doubles, while the 7500 used mixed-endian.
      8 
      9 package runtime
     10 
     11 import "unsafe"
     12 
     13 const (
     14 	_CPSR    = 14
     15 	_FLAGS_N = 1 << 31
     16 	_FLAGS_Z = 1 << 30
     17 	_FLAGS_C = 1 << 29
     18 	_FLAGS_V = 1 << 28
     19 )
     20 
     21 var fptrace = 0
     22 
     23 func fabort() {
     24 	throw("unsupported floating point instruction")
     25 }
     26 
     27 func fputf(reg uint32, val uint32) {
     28 	_g_ := getg()
     29 	_g_.m.freglo[reg] = val
     30 }
     31 
     32 func fputd(reg uint32, val uint64) {
     33 	_g_ := getg()
     34 	_g_.m.freglo[reg] = uint32(val)
     35 	_g_.m.freghi[reg] = uint32(val >> 32)
     36 }
     37 
     38 func fgetd(reg uint32) uint64 {
     39 	_g_ := getg()
     40 	return uint64(_g_.m.freglo[reg]) | uint64(_g_.m.freghi[reg])<<32
     41 }
     42 
     43 func fprintregs() {
     44 	_g_ := getg()
     45 	for i := range _g_.m.freglo {
     46 		print("\tf", i, ":\t", hex(_g_.m.freghi[i]), " ", hex(_g_.m.freglo[i]), "\n")
     47 	}
     48 }
     49 
     50 func fstatus(nan bool, cmp int32) uint32 {
     51 	if nan {
     52 		return _FLAGS_C | _FLAGS_V
     53 	}
     54 	if cmp == 0 {
     55 		return _FLAGS_Z | _FLAGS_C
     56 	}
     57 	if cmp < 0 {
     58 		return _FLAGS_N
     59 	}
     60 	return _FLAGS_C
     61 }
     62 
     63 // conditions array record the required CPSR cond field for the
     64 // first 5 pairs of conditional execution opcodes
     65 // higher 4 bits are must set, lower 4 bits are must clear
     66 var conditions = [10 / 2]uint32{
     67 	0 / 2: _FLAGS_Z>>24 | 0, // 0: EQ (Z set), 1: NE (Z clear)
     68 	2 / 2: _FLAGS_C>>24 | 0, // 2: CS/HS (C set), 3: CC/LO (C clear)
     69 	4 / 2: _FLAGS_N>>24 | 0, // 4: MI (N set), 5: PL (N clear)
     70 	6 / 2: _FLAGS_V>>24 | 0, // 6: VS (V set), 7: VC (V clear)
     71 	8 / 2: _FLAGS_C>>24 |
     72 		_FLAGS_Z>>28,
     73 }
     74 
     75 const _FAULT = 0x80000000 // impossible PC offset
     76 
     77 // returns number of words that the fp instruction
     78 // is occupying, 0 if next instruction isn't float.
     79 func stepflt(pc *uint32, regs *[15]uint32) uint32 {
     80 	var i, opc, regd, regm, regn, cpsr uint32
     81 
     82 	// m is locked in vlop_arm.s, so g.m cannot change during this function call,
     83 	// so caching it in a local variable is safe.
     84 	m := getg().m
     85 	i = *pc
     86 
     87 	if fptrace > 0 {
     88 		print("stepflt ", pc, " ", hex(i), " (cpsr ", hex(regs[_CPSR]>>28), ")\n")
     89 	}
     90 
     91 	opc = i >> 28
     92 	if opc == 14 { // common case first
     93 		goto execute
     94 	}
     95 
     96 	cpsr = regs[_CPSR] >> 28
     97 	switch opc {
     98 	case 0, 1, 2, 3, 4, 5, 6, 7, 8, 9:
     99 		if cpsr&(conditions[opc/2]>>4) == conditions[opc/2]>>4 &&
    100 			cpsr&(conditions[opc/2]&0xf) == 0 {
    101 			if opc&1 != 0 {
    102 				return 1
    103 			}
    104 		} else {
    105 			if opc&1 == 0 {
    106 				return 1
    107 			}
    108 		}
    109 
    110 	case 10, 11: // GE (N == V), LT (N != V)
    111 		if cpsr&(_FLAGS_N>>28) == cpsr&(_FLAGS_V>>28) {
    112 			if opc&1 != 0 {
    113 				return 1
    114 			}
    115 		} else {
    116 			if opc&1 == 0 {
    117 				return 1
    118 			}
    119 		}
    120 
    121 	case 12, 13: // GT (N == V and Z == 0), LE (N != V or Z == 1)
    122 		if cpsr&(_FLAGS_N>>28) == cpsr&(_FLAGS_V>>28) &&
    123 			cpsr&(_FLAGS_Z>>28) == 0 {
    124 			if opc&1 != 0 {
    125 				return 1
    126 			}
    127 		} else {
    128 			if opc&1 == 0 {
    129 				return 1
    130 			}
    131 		}
    132 
    133 	case 14: // AL
    134 		// ok
    135 
    136 	case 15: // shouldn't happen
    137 		return 0
    138 	}
    139 
    140 	if fptrace > 0 {
    141 		print("conditional ", hex(opc), " (cpsr ", hex(cpsr), ") pass\n")
    142 	}
    143 	i = 0xe<<28 | i&(1<<28-1)
    144 
    145 execute:
    146 	// special cases
    147 	if i&0xfffff000 == 0xe59fb000 {
    148 		// load r11 from pc-relative address.
    149 		// might be part of a floating point move
    150 		// (or might not, but no harm in simulating
    151 		// one instruction too many).
    152 		addr := (*[1]uint32)(add(unsafe.Pointer(pc), uintptr(i&0xfff+8)))
    153 		regs[11] = addr[0]
    154 
    155 		if fptrace > 0 {
    156 			print("*** cpu R[11] = *(", addr, ") ", hex(regs[11]), "\n")
    157 		}
    158 		return 1
    159 	}
    160 	if i == 0xe08fb00b {
    161 		// add pc to r11
    162 		// might be part of a PIC floating point move
    163 		// (or might not, but again no harm done).
    164 		regs[11] += uint32(uintptr(unsafe.Pointer(pc))) + 8
    165 
    166 		if fptrace > 0 {
    167 			print("*** cpu R[11] += pc ", hex(regs[11]), "\n")
    168 		}
    169 		return 1
    170 	}
    171 	if i&0xfffffff0 == 0xe08bb000 {
    172 		r := i & 0xf
    173 		// add r to r11.
    174 		// might be part of a large offset address calculation
    175 		// (or might not, but again no harm done).
    176 		regs[11] += regs[r]
    177 
    178 		if fptrace > 0 {
    179 			print("*** cpu R[11] += R[", r, "] ", hex(regs[11]), "\n")
    180 		}
    181 		return 1
    182 	}
    183 	if i == 0xeef1fa10 {
    184 		regs[_CPSR] = regs[_CPSR]&0x0fffffff | m.fflag
    185 
    186 		if fptrace > 0 {
    187 			print("*** fpsr R[CPSR] = F[CPSR] ", hex(regs[_CPSR]), "\n")
    188 		}
    189 		return 1
    190 	}
    191 	if i&0xff000000 == 0xea000000 {
    192 		// unconditional branch
    193 		// can happen in the middle of floating point
    194 		// if the linker decides it is time to lay down
    195 		// a sequence of instruction stream constants.
    196 		delta := int32(i&0xffffff) << 8 >> 8 // sign extend
    197 
    198 		if fptrace > 0 {
    199 			print("*** cpu PC += ", hex((delta+2)*4), "\n")
    200 		}
    201 		return uint32(delta + 2)
    202 	}
    203 
    204 	// load/store regn is cpureg, regm is 8bit offset
    205 	regd = i >> 12 & 0xf
    206 	regn = i >> 16 & 0xf
    207 	regm = i & 0xff << 2 // PLUS or MINUS ??
    208 
    209 	switch i & 0xfff00f00 {
    210 	case 0xed900a00: // single load
    211 		uaddr := uintptr(regs[regn] + regm)
    212 		if uaddr < 4096 {
    213 			if fptrace > 0 {
    214 				print("*** load @", hex(uaddr), " => fault\n")
    215 			}
    216 			return _FAULT
    217 		}
    218 		addr := (*[1]uint32)(unsafe.Pointer(uaddr))
    219 		m.freglo[regd] = addr[0]
    220 
    221 		if fptrace > 0 {
    222 			print("*** load F[", regd, "] = ", hex(m.freglo[regd]), "\n")
    223 		}
    224 		return 1
    225 
    226 	case 0xed900b00: // double load
    227 		uaddr := uintptr(regs[regn] + regm)
    228 		if uaddr < 4096 {
    229 			if fptrace > 0 {
    230 				print("*** double load @", hex(uaddr), " => fault\n")
    231 			}
    232 			return _FAULT
    233 		}
    234 		addr := (*[2]uint32)(unsafe.Pointer(uaddr))
    235 		m.freglo[regd] = addr[0]
    236 		m.freghi[regd] = addr[1]
    237 
    238 		if fptrace > 0 {
    239 			print("*** load D[", regd, "] = ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    240 		}
    241 		return 1
    242 
    243 	case 0xed800a00: // single store
    244 		uaddr := uintptr(regs[regn] + regm)
    245 		if uaddr < 4096 {
    246 			if fptrace > 0 {
    247 				print("*** store @", hex(uaddr), " => fault\n")
    248 			}
    249 			return _FAULT
    250 		}
    251 		addr := (*[1]uint32)(unsafe.Pointer(uaddr))
    252 		addr[0] = m.freglo[regd]
    253 
    254 		if fptrace > 0 {
    255 			print("*** *(", addr, ") = ", hex(addr[0]), "\n")
    256 		}
    257 		return 1
    258 
    259 	case 0xed800b00: // double store
    260 		uaddr := uintptr(regs[regn] + regm)
    261 		if uaddr < 4096 {
    262 			if fptrace > 0 {
    263 				print("*** double store @", hex(uaddr), " => fault\n")
    264 			}
    265 			return _FAULT
    266 		}
    267 		addr := (*[2]uint32)(unsafe.Pointer(uaddr))
    268 		addr[0] = m.freglo[regd]
    269 		addr[1] = m.freghi[regd]
    270 
    271 		if fptrace > 0 {
    272 			print("*** *(", addr, ") = ", hex(addr[1]), "-", hex(addr[0]), "\n")
    273 		}
    274 		return 1
    275 	}
    276 
    277 	// regd, regm, regn are 4bit variables
    278 	regm = i >> 0 & 0xf
    279 	switch i & 0xfff00ff0 {
    280 	case 0xf3000110: // veor
    281 		m.freglo[regd] = m.freglo[regm] ^ m.freglo[regn]
    282 		m.freghi[regd] = m.freghi[regm] ^ m.freghi[regn]
    283 
    284 		if fptrace > 0 {
    285 			print("*** veor D[", regd, "] = ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    286 		}
    287 		return 1
    288 
    289 	case 0xeeb00b00: // D[regd] = const(regn,regm)
    290 		regn = regn<<4 | regm
    291 		regm = 0x40000000
    292 		if regn&0x80 != 0 {
    293 			regm |= 0x80000000
    294 		}
    295 		if regn&0x40 != 0 {
    296 			regm ^= 0x7fc00000
    297 		}
    298 		regm |= regn & 0x3f << 16
    299 		m.freglo[regd] = 0
    300 		m.freghi[regd] = regm
    301 
    302 		if fptrace > 0 {
    303 			print("*** immed D[", regd, "] = ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    304 		}
    305 		return 1
    306 
    307 	case 0xeeb00a00: // F[regd] = const(regn,regm)
    308 		regn = regn<<4 | regm
    309 		regm = 0x40000000
    310 		if regn&0x80 != 0 {
    311 			regm |= 0x80000000
    312 		}
    313 		if regn&0x40 != 0 {
    314 			regm ^= 0x7e000000
    315 		}
    316 		regm |= regn & 0x3f << 19
    317 		m.freglo[regd] = regm
    318 
    319 		if fptrace > 0 {
    320 			print("*** immed D[", regd, "] = ", hex(m.freglo[regd]), "\n")
    321 		}
    322 		return 1
    323 
    324 	case 0xee300b00: // D[regd] = D[regn]+D[regm]
    325 		fputd(regd, fadd64(fgetd(regn), fgetd(regm)))
    326 
    327 		if fptrace > 0 {
    328 			print("*** add D[", regd, "] = D[", regn, "]+D[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    329 		}
    330 		return 1
    331 
    332 	case 0xee300a00: // F[regd] = F[regn]+F[regm]
    333 		m.freglo[regd] = f64to32(fadd64(f32to64(m.freglo[regn]), f32to64(m.freglo[regm])))
    334 
    335 		if fptrace > 0 {
    336 			print("*** add F[", regd, "] = F[", regn, "]+F[", regm, "] ", hex(m.freglo[regd]), "\n")
    337 		}
    338 		return 1
    339 
    340 	case 0xee300b40: // D[regd] = D[regn]-D[regm]
    341 		fputd(regd, fsub64(fgetd(regn), fgetd(regm)))
    342 
    343 		if fptrace > 0 {
    344 			print("*** sub D[", regd, "] = D[", regn, "]-D[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    345 		}
    346 		return 1
    347 
    348 	case 0xee300a40: // F[regd] = F[regn]-F[regm]
    349 		m.freglo[regd] = f64to32(fsub64(f32to64(m.freglo[regn]), f32to64(m.freglo[regm])))
    350 
    351 		if fptrace > 0 {
    352 			print("*** sub F[", regd, "] = F[", regn, "]-F[", regm, "] ", hex(m.freglo[regd]), "\n")
    353 		}
    354 		return 1
    355 
    356 	case 0xee200b00: // D[regd] = D[regn]*D[regm]
    357 		fputd(regd, fmul64(fgetd(regn), fgetd(regm)))
    358 
    359 		if fptrace > 0 {
    360 			print("*** mul D[", regd, "] = D[", regn, "]*D[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    361 		}
    362 		return 1
    363 
    364 	case 0xee200a00: // F[regd] = F[regn]*F[regm]
    365 		m.freglo[regd] = f64to32(fmul64(f32to64(m.freglo[regn]), f32to64(m.freglo[regm])))
    366 
    367 		if fptrace > 0 {
    368 			print("*** mul F[", regd, "] = F[", regn, "]*F[", regm, "] ", hex(m.freglo[regd]), "\n")
    369 		}
    370 		return 1
    371 
    372 	case 0xee800b00: // D[regd] = D[regn]/D[regm]
    373 		fputd(regd, fdiv64(fgetd(regn), fgetd(regm)))
    374 
    375 		if fptrace > 0 {
    376 			print("*** div D[", regd, "] = D[", regn, "]/D[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    377 		}
    378 		return 1
    379 
    380 	case 0xee800a00: // F[regd] = F[regn]/F[regm]
    381 		m.freglo[regd] = f64to32(fdiv64(f32to64(m.freglo[regn]), f32to64(m.freglo[regm])))
    382 
    383 		if fptrace > 0 {
    384 			print("*** div F[", regd, "] = F[", regn, "]/F[", regm, "] ", hex(m.freglo[regd]), "\n")
    385 		}
    386 		return 1
    387 
    388 	case 0xee000b10: // S[regn] = R[regd] (MOVW) (regm ignored)
    389 		m.freglo[regn] = regs[regd]
    390 
    391 		if fptrace > 0 {
    392 			print("*** cpy S[", regn, "] = R[", regd, "] ", hex(m.freglo[regn]), "\n")
    393 		}
    394 		return 1
    395 
    396 	case 0xee100b10: // R[regd] = S[regn] (MOVW) (regm ignored)
    397 		regs[regd] = m.freglo[regn]
    398 
    399 		if fptrace > 0 {
    400 			print("*** cpy R[", regd, "] = S[", regn, "] ", hex(regs[regd]), "\n")
    401 		}
    402 		return 1
    403 	}
    404 
    405 	// regd, regm are 4bit variables
    406 	switch i & 0xffff0ff0 {
    407 	case 0xeeb00a40: // F[regd] = F[regm] (MOVF)
    408 		m.freglo[regd] = m.freglo[regm]
    409 
    410 		if fptrace > 0 {
    411 			print("*** F[", regd, "] = F[", regm, "] ", hex(m.freglo[regd]), "\n")
    412 		}
    413 		return 1
    414 
    415 	case 0xeeb00b40: // D[regd] = D[regm] (MOVD)
    416 		m.freglo[regd] = m.freglo[regm]
    417 		m.freghi[regd] = m.freghi[regm]
    418 
    419 		if fptrace > 0 {
    420 			print("*** D[", regd, "] = D[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    421 		}
    422 		return 1
    423 
    424 	case 0xeeb10bc0: // D[regd] = sqrt D[regm]
    425 		fputd(regd, sqrt(fgetd(regm)))
    426 
    427 		if fptrace > 0 {
    428 			print("*** D[", regd, "] = sqrt D[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    429 		}
    430 		return 1
    431 
    432 	case 0xeeb00bc0: // D[regd] = abs D[regm]
    433 		m.freglo[regd] = m.freglo[regm]
    434 		m.freghi[regd] = m.freghi[regm] & (1<<31 - 1)
    435 
    436 		if fptrace > 0 {
    437 			print("*** D[", regd, "] = abs D[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    438 		}
    439 		return 1
    440 
    441 	case 0xeeb00ac0: // F[regd] = abs F[regm]
    442 		m.freglo[regd] = m.freglo[regm] & (1<<31 - 1)
    443 
    444 		if fptrace > 0 {
    445 			print("*** F[", regd, "] = abs F[", regm, "] ", hex(m.freglo[regd]), "\n")
    446 		}
    447 		return 1
    448 
    449 	case 0xeeb10b40: // D[regd] = neg D[regm]
    450 		m.freglo[regd] = m.freglo[regm]
    451 		m.freghi[regd] = m.freghi[regm] ^ 1<<31
    452 
    453 		if fptrace > 0 {
    454 			print("*** D[", regd, "] = neg D[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    455 		}
    456 		return 1
    457 
    458 	case 0xeeb10a40: // F[regd] = neg F[regm]
    459 		m.freglo[regd] = m.freglo[regm] ^ 1<<31
    460 
    461 		if fptrace > 0 {
    462 			print("*** F[", regd, "] = neg F[", regm, "] ", hex(m.freglo[regd]), "\n")
    463 		}
    464 		return 1
    465 
    466 	case 0xeeb40bc0: // D[regd] :: D[regm] (CMPD)
    467 		cmp, nan := fcmp64(fgetd(regd), fgetd(regm))
    468 		m.fflag = fstatus(nan, cmp)
    469 
    470 		if fptrace > 0 {
    471 			print("*** cmp D[", regd, "]::D[", regm, "] ", hex(m.fflag), "\n")
    472 		}
    473 		return 1
    474 
    475 	case 0xeeb40ac0: // F[regd] :: F[regm] (CMPF)
    476 		cmp, nan := fcmp64(f32to64(m.freglo[regd]), f32to64(m.freglo[regm]))
    477 		m.fflag = fstatus(nan, cmp)
    478 
    479 		if fptrace > 0 {
    480 			print("*** cmp F[", regd, "]::F[", regm, "] ", hex(m.fflag), "\n")
    481 		}
    482 		return 1
    483 
    484 	case 0xeeb50bc0: // D[regd] :: 0 (CMPD)
    485 		cmp, nan := fcmp64(fgetd(regd), 0)
    486 		m.fflag = fstatus(nan, cmp)
    487 
    488 		if fptrace > 0 {
    489 			print("*** cmp D[", regd, "]::0 ", hex(m.fflag), "\n")
    490 		}
    491 		return 1
    492 
    493 	case 0xeeb50ac0: // F[regd] :: 0 (CMPF)
    494 		cmp, nan := fcmp64(f32to64(m.freglo[regd]), 0)
    495 		m.fflag = fstatus(nan, cmp)
    496 
    497 		if fptrace > 0 {
    498 			print("*** cmp F[", regd, "]::0 ", hex(m.fflag), "\n")
    499 		}
    500 		return 1
    501 
    502 	case 0xeeb70ac0: // D[regd] = F[regm] (MOVFD)
    503 		fputd(regd, f32to64(m.freglo[regm]))
    504 
    505 		if fptrace > 0 {
    506 			print("*** f2d D[", regd, "]=F[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    507 		}
    508 		return 1
    509 
    510 	case 0xeeb70bc0: // F[regd] = D[regm] (MOVDF)
    511 		m.freglo[regd] = f64to32(fgetd(regm))
    512 
    513 		if fptrace > 0 {
    514 			print("*** d2f F[", regd, "]=D[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    515 		}
    516 		return 1
    517 
    518 	case 0xeebd0ac0: // S[regd] = F[regm] (MOVFW)
    519 		sval, ok := f64toint(f32to64(m.freglo[regm]))
    520 		if !ok || int64(int32(sval)) != sval {
    521 			sval = 0
    522 		}
    523 		m.freglo[regd] = uint32(sval)
    524 		if fptrace > 0 {
    525 			print("*** fix S[", regd, "]=F[", regm, "] ", hex(m.freglo[regd]), "\n")
    526 		}
    527 		return 1
    528 
    529 	case 0xeebc0ac0: // S[regd] = F[regm] (MOVFW.U)
    530 		sval, ok := f64toint(f32to64(m.freglo[regm]))
    531 		if !ok || int64(uint32(sval)) != sval {
    532 			sval = 0
    533 		}
    534 		m.freglo[regd] = uint32(sval)
    535 
    536 		if fptrace > 0 {
    537 			print("*** fix unsigned S[", regd, "]=F[", regm, "] ", hex(m.freglo[regd]), "\n")
    538 		}
    539 		return 1
    540 
    541 	case 0xeebd0bc0: // S[regd] = D[regm] (MOVDW)
    542 		sval, ok := f64toint(fgetd(regm))
    543 		if !ok || int64(int32(sval)) != sval {
    544 			sval = 0
    545 		}
    546 		m.freglo[regd] = uint32(sval)
    547 
    548 		if fptrace > 0 {
    549 			print("*** fix S[", regd, "]=D[", regm, "] ", hex(m.freglo[regd]), "\n")
    550 		}
    551 		return 1
    552 
    553 	case 0xeebc0bc0: // S[regd] = D[regm] (MOVDW.U)
    554 		sval, ok := f64toint(fgetd(regm))
    555 		if !ok || int64(uint32(sval)) != sval {
    556 			sval = 0
    557 		}
    558 		m.freglo[regd] = uint32(sval)
    559 
    560 		if fptrace > 0 {
    561 			print("*** fix unsigned S[", regd, "]=D[", regm, "] ", hex(m.freglo[regd]), "\n")
    562 		}
    563 		return 1
    564 
    565 	case 0xeeb80ac0: // D[regd] = S[regm] (MOVWF)
    566 		cmp := int32(m.freglo[regm])
    567 		if cmp < 0 {
    568 			fputf(regd, f64to32(fintto64(-int64(cmp))))
    569 			m.freglo[regd] ^= 0x80000000
    570 		} else {
    571 			fputf(regd, f64to32(fintto64(int64(cmp))))
    572 		}
    573 
    574 		if fptrace > 0 {
    575 			print("*** float D[", regd, "]=S[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    576 		}
    577 		return 1
    578 
    579 	case 0xeeb80a40: // D[regd] = S[regm] (MOVWF.U)
    580 		fputf(regd, f64to32(fintto64(int64(m.freglo[regm]))))
    581 
    582 		if fptrace > 0 {
    583 			print("*** float unsigned D[", regd, "]=S[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    584 		}
    585 		return 1
    586 
    587 	case 0xeeb80bc0: // D[regd] = S[regm] (MOVWD)
    588 		cmp := int32(m.freglo[regm])
    589 		if cmp < 0 {
    590 			fputd(regd, fintto64(-int64(cmp)))
    591 			m.freghi[regd] ^= 0x80000000
    592 		} else {
    593 			fputd(regd, fintto64(int64(cmp)))
    594 		}
    595 
    596 		if fptrace > 0 {
    597 			print("*** float D[", regd, "]=S[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    598 		}
    599 		return 1
    600 
    601 	case 0xeeb80b40: // D[regd] = S[regm] (MOVWD.U)
    602 		fputd(regd, fintto64(int64(m.freglo[regm])))
    603 
    604 		if fptrace > 0 {
    605 			print("*** float unsigned D[", regd, "]=S[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    606 		}
    607 		return 1
    608 	}
    609 
    610 	if i&0xff000000 == 0xee000000 || i&0xff000000 == 0xed000000 {
    611 		print("stepflt ", pc, " ", hex(i), "\n")
    612 		fabort()
    613 	}
    614 	return 0
    615 }
    616 
    617 //go:nosplit
    618 func _sfloat2(pc uint32, regs [15]uint32) (newpc uint32) {
    619 	systemstack(func() {
    620 		newpc = sfloat2(pc, &regs)
    621 	})
    622 	return
    623 }
    624 
    625 func _sfloatpanic()
    626 
    627 func sfloat2(pc uint32, regs *[15]uint32) uint32 {
    628 	first := true
    629 	for {
    630 		skip := stepflt((*uint32)(unsafe.Pointer(uintptr(pc))), regs)
    631 		if skip == 0 {
    632 			break
    633 		}
    634 		first = false
    635 		if skip == _FAULT {
    636 			// Encountered bad address in store/load.
    637 			// Record signal information and return to assembly
    638 			// trampoline that fakes the call.
    639 			const SIGSEGV = 11
    640 			curg := getg().m.curg
    641 			curg.sig = SIGSEGV
    642 			curg.sigcode0 = 0
    643 			curg.sigcode1 = 0
    644 			curg.sigpc = uintptr(pc)
    645 			pc = uint32(funcPC(_sfloatpanic))
    646 			break
    647 		}
    648 		pc += 4 * skip
    649 	}
    650 	if first {
    651 		print("sfloat2 ", pc, " ", hex(*(*uint32)(unsafe.Pointer(uintptr(pc)))), "\n")
    652 		fabort() // not ok to fail first instruction
    653 	}
    654 	return pc
    655 }
    656 
    657 // Stubs to pacify vet. Not safe to call from Go.
    658 // Calls to these functions are inserted by the compiler or assembler.
    659 func _sfloat()
    660 func udiv()
    661 func _div()
    662 func _divu()
    663 func _mod()
    664 func _modu()
    665