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 interpretaton 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 == 0xe08bb00d {
    161 		// add sp to r11.
    162 		// might be part of a large stack offset address
    163 		// (or might not, but again no harm done).
    164 		regs[11] += regs[13]
    165 
    166 		if fptrace > 0 {
    167 			print("*** cpu R[11] += R[13] ", hex(regs[11]), "\n")
    168 		}
    169 		return 1
    170 	}
    171 	if i == 0xeef1fa10 {
    172 		regs[_CPSR] = regs[_CPSR]&0x0fffffff | m.fflag
    173 
    174 		if fptrace > 0 {
    175 			print("*** fpsr R[CPSR] = F[CPSR] ", hex(regs[_CPSR]), "\n")
    176 		}
    177 		return 1
    178 	}
    179 	if i&0xff000000 == 0xea000000 {
    180 		// unconditional branch
    181 		// can happen in the middle of floating point
    182 		// if the linker decides it is time to lay down
    183 		// a sequence of instruction stream constants.
    184 		delta := int32(i&0xffffff) << 8 >> 8 // sign extend
    185 
    186 		if fptrace > 0 {
    187 			print("*** cpu PC += ", hex((delta+2)*4), "\n")
    188 		}
    189 		return uint32(delta + 2)
    190 	}
    191 
    192 	// load/store regn is cpureg, regm is 8bit offset
    193 	regd = i >> 12 & 0xf
    194 	regn = i >> 16 & 0xf
    195 	regm = i & 0xff << 2 // PLUS or MINUS ??
    196 
    197 	switch i & 0xfff00f00 {
    198 	case 0xed900a00: // single load
    199 		uaddr := uintptr(regs[regn] + regm)
    200 		if uaddr < 4096 {
    201 			if fptrace > 0 {
    202 				print("*** load @", hex(uaddr), " => fault\n")
    203 			}
    204 			return _FAULT
    205 		}
    206 		addr := (*[1]uint32)(unsafe.Pointer(uaddr))
    207 		m.freglo[regd] = addr[0]
    208 
    209 		if fptrace > 0 {
    210 			print("*** load F[", regd, "] = ", hex(m.freglo[regd]), "\n")
    211 		}
    212 		return 1
    213 
    214 	case 0xed900b00: // double load
    215 		uaddr := uintptr(regs[regn] + regm)
    216 		if uaddr < 4096 {
    217 			if fptrace > 0 {
    218 				print("*** double load @", hex(uaddr), " => fault\n")
    219 			}
    220 			return _FAULT
    221 		}
    222 		addr := (*[2]uint32)(unsafe.Pointer(uaddr))
    223 		m.freglo[regd] = addr[0]
    224 		m.freghi[regd] = addr[1]
    225 
    226 		if fptrace > 0 {
    227 			print("*** load D[", regd, "] = ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    228 		}
    229 		return 1
    230 
    231 	case 0xed800a00: // single store
    232 		uaddr := uintptr(regs[regn] + regm)
    233 		if uaddr < 4096 {
    234 			if fptrace > 0 {
    235 				print("*** store @", hex(uaddr), " => fault\n")
    236 			}
    237 			return _FAULT
    238 		}
    239 		addr := (*[1]uint32)(unsafe.Pointer(uaddr))
    240 		addr[0] = m.freglo[regd]
    241 
    242 		if fptrace > 0 {
    243 			print("*** *(", addr, ") = ", hex(addr[0]), "\n")
    244 		}
    245 		return 1
    246 
    247 	case 0xed800b00: // double store
    248 		uaddr := uintptr(regs[regn] + regm)
    249 		if uaddr < 4096 {
    250 			if fptrace > 0 {
    251 				print("*** double store @", hex(uaddr), " => fault\n")
    252 			}
    253 			return _FAULT
    254 		}
    255 		addr := (*[2]uint32)(unsafe.Pointer(uaddr))
    256 		addr[0] = m.freglo[regd]
    257 		addr[1] = m.freghi[regd]
    258 
    259 		if fptrace > 0 {
    260 			print("*** *(", addr, ") = ", hex(addr[1]), "-", hex(addr[0]), "\n")
    261 		}
    262 		return 1
    263 	}
    264 
    265 	// regd, regm, regn are 4bit variables
    266 	regm = i >> 0 & 0xf
    267 	switch i & 0xfff00ff0 {
    268 	case 0xf3000110: // veor
    269 		m.freglo[regd] = m.freglo[regm] ^ m.freglo[regn]
    270 		m.freghi[regd] = m.freghi[regm] ^ m.freghi[regn]
    271 
    272 		if fptrace > 0 {
    273 			print("*** veor D[", regd, "] = ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    274 		}
    275 		return 1
    276 
    277 	case 0xeeb00b00: // D[regd] = const(regn,regm)
    278 		regn = regn<<4 | regm
    279 		regm = 0x40000000
    280 		if regn&0x80 != 0 {
    281 			regm |= 0x80000000
    282 		}
    283 		if regn&0x40 != 0 {
    284 			regm ^= 0x7fc00000
    285 		}
    286 		regm |= regn & 0x3f << 16
    287 		m.freglo[regd] = 0
    288 		m.freghi[regd] = regm
    289 
    290 		if fptrace > 0 {
    291 			print("*** immed D[", regd, "] = ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    292 		}
    293 		return 1
    294 
    295 	case 0xeeb00a00: // F[regd] = const(regn,regm)
    296 		regn = regn<<4 | regm
    297 		regm = 0x40000000
    298 		if regn&0x80 != 0 {
    299 			regm |= 0x80000000
    300 		}
    301 		if regn&0x40 != 0 {
    302 			regm ^= 0x7e000000
    303 		}
    304 		regm |= regn & 0x3f << 19
    305 		m.freglo[regd] = regm
    306 
    307 		if fptrace > 0 {
    308 			print("*** immed D[", regd, "] = ", hex(m.freglo[regd]), "\n")
    309 		}
    310 		return 1
    311 
    312 	case 0xee300b00: // D[regd] = D[regn]+D[regm]
    313 		fputd(regd, fadd64(fgetd(regn), fgetd(regm)))
    314 
    315 		if fptrace > 0 {
    316 			print("*** add D[", regd, "] = D[", regn, "]+D[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    317 		}
    318 		return 1
    319 
    320 	case 0xee300a00: // F[regd] = F[regn]+F[regm]
    321 		m.freglo[regd] = f64to32(fadd64(f32to64(m.freglo[regn]), f32to64(m.freglo[regm])))
    322 
    323 		if fptrace > 0 {
    324 			print("*** add F[", regd, "] = F[", regn, "]+F[", regm, "] ", hex(m.freglo[regd]), "\n")
    325 		}
    326 		return 1
    327 
    328 	case 0xee300b40: // D[regd] = D[regn]-D[regm]
    329 		fputd(regd, fsub64(fgetd(regn), fgetd(regm)))
    330 
    331 		if fptrace > 0 {
    332 			print("*** sub D[", regd, "] = D[", regn, "]-D[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    333 		}
    334 		return 1
    335 
    336 	case 0xee300a40: // F[regd] = F[regn]-F[regm]
    337 		m.freglo[regd] = f64to32(fsub64(f32to64(m.freglo[regn]), f32to64(m.freglo[regm])))
    338 
    339 		if fptrace > 0 {
    340 			print("*** sub F[", regd, "] = F[", regn, "]-F[", regm, "] ", hex(m.freglo[regd]), "\n")
    341 		}
    342 		return 1
    343 
    344 	case 0xee200b00: // D[regd] = D[regn]*D[regm]
    345 		fputd(regd, fmul64(fgetd(regn), fgetd(regm)))
    346 
    347 		if fptrace > 0 {
    348 			print("*** mul D[", regd, "] = D[", regn, "]*D[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    349 		}
    350 		return 1
    351 
    352 	case 0xee200a00: // F[regd] = F[regn]*F[regm]
    353 		m.freglo[regd] = f64to32(fmul64(f32to64(m.freglo[regn]), f32to64(m.freglo[regm])))
    354 
    355 		if fptrace > 0 {
    356 			print("*** mul F[", regd, "] = F[", regn, "]*F[", regm, "] ", hex(m.freglo[regd]), "\n")
    357 		}
    358 		return 1
    359 
    360 	case 0xee800b00: // D[regd] = D[regn]/D[regm]
    361 		fputd(regd, fdiv64(fgetd(regn), fgetd(regm)))
    362 
    363 		if fptrace > 0 {
    364 			print("*** div D[", regd, "] = D[", regn, "]/D[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    365 		}
    366 		return 1
    367 
    368 	case 0xee800a00: // F[regd] = F[regn]/F[regm]
    369 		m.freglo[regd] = f64to32(fdiv64(f32to64(m.freglo[regn]), f32to64(m.freglo[regm])))
    370 
    371 		if fptrace > 0 {
    372 			print("*** div F[", regd, "] = F[", regn, "]/F[", regm, "] ", hex(m.freglo[regd]), "\n")
    373 		}
    374 		return 1
    375 
    376 	case 0xee000b10: // S[regn] = R[regd] (MOVW) (regm ignored)
    377 		m.freglo[regn] = regs[regd]
    378 
    379 		if fptrace > 0 {
    380 			print("*** cpy S[", regn, "] = R[", regd, "] ", hex(m.freglo[regn]), "\n")
    381 		}
    382 		return 1
    383 
    384 	case 0xee100b10: // R[regd] = S[regn] (MOVW) (regm ignored)
    385 		regs[regd] = m.freglo[regn]
    386 
    387 		if fptrace > 0 {
    388 			print("*** cpy R[", regd, "] = S[", regn, "] ", hex(regs[regd]), "\n")
    389 		}
    390 		return 1
    391 	}
    392 
    393 	// regd, regm are 4bit variables
    394 	switch i & 0xffff0ff0 {
    395 	case 0xeeb00a40: // F[regd] = F[regm] (MOVF)
    396 		m.freglo[regd] = m.freglo[regm]
    397 
    398 		if fptrace > 0 {
    399 			print("*** F[", regd, "] = F[", regm, "] ", hex(m.freglo[regd]), "\n")
    400 		}
    401 		return 1
    402 
    403 	case 0xeeb00b40: // D[regd] = D[regm] (MOVD)
    404 		m.freglo[regd] = m.freglo[regm]
    405 		m.freghi[regd] = m.freghi[regm]
    406 
    407 		if fptrace > 0 {
    408 			print("*** D[", regd, "] = D[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    409 		}
    410 		return 1
    411 
    412 	case 0xeeb10bc0: // D[regd] = sqrt D[regm]
    413 		fputd(regd, sqrt(fgetd(regm)))
    414 
    415 		if fptrace > 0 {
    416 			print("*** D[", regd, "] = sqrt D[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    417 		}
    418 		return 1
    419 
    420 	case 0xeeb00bc0: // D[regd] = abs D[regm]
    421 		m.freglo[regd] = m.freglo[regm]
    422 		m.freghi[regd] = m.freghi[regm] & (1<<31 - 1)
    423 
    424 		if fptrace > 0 {
    425 			print("*** D[", regd, "] = abs D[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    426 		}
    427 		return 1
    428 
    429 	case 0xeeb00ac0: // F[regd] = abs F[regm]
    430 		m.freglo[regd] = m.freglo[regm] & (1<<31 - 1)
    431 
    432 		if fptrace > 0 {
    433 			print("*** F[", regd, "] = abs F[", regm, "] ", hex(m.freglo[regd]), "\n")
    434 		}
    435 		return 1
    436 
    437 	case 0xeeb40bc0: // D[regd] :: D[regm] (CMPD)
    438 		cmp, nan := fcmp64(fgetd(regd), fgetd(regm))
    439 		m.fflag = fstatus(nan, cmp)
    440 
    441 		if fptrace > 0 {
    442 			print("*** cmp D[", regd, "]::D[", regm, "] ", hex(m.fflag), "\n")
    443 		}
    444 		return 1
    445 
    446 	case 0xeeb40ac0: // F[regd] :: F[regm] (CMPF)
    447 		cmp, nan := fcmp64(f32to64(m.freglo[regd]), f32to64(m.freglo[regm]))
    448 		m.fflag = fstatus(nan, cmp)
    449 
    450 		if fptrace > 0 {
    451 			print("*** cmp F[", regd, "]::F[", regm, "] ", hex(m.fflag), "\n")
    452 		}
    453 		return 1
    454 
    455 	case 0xeeb70ac0: // D[regd] = F[regm] (MOVFD)
    456 		fputd(regd, f32to64(m.freglo[regm]))
    457 
    458 		if fptrace > 0 {
    459 			print("*** f2d D[", regd, "]=F[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    460 		}
    461 		return 1
    462 
    463 	case 0xeeb70bc0: // F[regd] = D[regm] (MOVDF)
    464 		m.freglo[regd] = f64to32(fgetd(regm))
    465 
    466 		if fptrace > 0 {
    467 			print("*** d2f F[", regd, "]=D[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    468 		}
    469 		return 1
    470 
    471 	case 0xeebd0ac0: // S[regd] = F[regm] (MOVFW)
    472 		sval, ok := f64toint(f32to64(m.freglo[regm]))
    473 		if !ok || int64(int32(sval)) != sval {
    474 			sval = 0
    475 		}
    476 		m.freglo[regd] = uint32(sval)
    477 		if fptrace > 0 {
    478 			print("*** fix S[", regd, "]=F[", regm, "] ", hex(m.freglo[regd]), "\n")
    479 		}
    480 		return 1
    481 
    482 	case 0xeebc0ac0: // S[regd] = F[regm] (MOVFW.U)
    483 		sval, ok := f64toint(f32to64(m.freglo[regm]))
    484 		if !ok || int64(uint32(sval)) != sval {
    485 			sval = 0
    486 		}
    487 		m.freglo[regd] = uint32(sval)
    488 
    489 		if fptrace > 0 {
    490 			print("*** fix unsigned S[", regd, "]=F[", regm, "] ", hex(m.freglo[regd]), "\n")
    491 		}
    492 		return 1
    493 
    494 	case 0xeebd0bc0: // S[regd] = D[regm] (MOVDW)
    495 		sval, ok := f64toint(fgetd(regm))
    496 		if !ok || int64(int32(sval)) != sval {
    497 			sval = 0
    498 		}
    499 		m.freglo[regd] = uint32(sval)
    500 
    501 		if fptrace > 0 {
    502 			print("*** fix S[", regd, "]=D[", regm, "] ", hex(m.freglo[regd]), "\n")
    503 		}
    504 		return 1
    505 
    506 	case 0xeebc0bc0: // S[regd] = D[regm] (MOVDW.U)
    507 		sval, ok := f64toint(fgetd(regm))
    508 		if !ok || int64(uint32(sval)) != sval {
    509 			sval = 0
    510 		}
    511 		m.freglo[regd] = uint32(sval)
    512 
    513 		if fptrace > 0 {
    514 			print("*** fix unsigned S[", regd, "]=D[", regm, "] ", hex(m.freglo[regd]), "\n")
    515 		}
    516 		return 1
    517 
    518 	case 0xeeb80ac0: // D[regd] = S[regm] (MOVWF)
    519 		cmp := int32(m.freglo[regm])
    520 		if cmp < 0 {
    521 			fputf(regd, f64to32(fintto64(int64(-cmp))))
    522 			m.freglo[regd] ^= 0x80000000
    523 		} else {
    524 			fputf(regd, f64to32(fintto64(int64(cmp))))
    525 		}
    526 
    527 		if fptrace > 0 {
    528 			print("*** float D[", regd, "]=S[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    529 		}
    530 		return 1
    531 
    532 	case 0xeeb80a40: // D[regd] = S[regm] (MOVWF.U)
    533 		fputf(regd, f64to32(fintto64(int64(m.freglo[regm]))))
    534 
    535 		if fptrace > 0 {
    536 			print("*** float unsigned D[", regd, "]=S[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    537 		}
    538 		return 1
    539 
    540 	case 0xeeb80bc0: // D[regd] = S[regm] (MOVWD)
    541 		cmp := int32(m.freglo[regm])
    542 		if cmp < 0 {
    543 			fputd(regd, fintto64(int64(-cmp)))
    544 			m.freghi[regd] ^= 0x80000000
    545 		} else {
    546 			fputd(regd, fintto64(int64(cmp)))
    547 		}
    548 
    549 		if fptrace > 0 {
    550 			print("*** float D[", regd, "]=S[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    551 		}
    552 		return 1
    553 
    554 	case 0xeeb80b40: // D[regd] = S[regm] (MOVWD.U)
    555 		fputd(regd, fintto64(int64(m.freglo[regm])))
    556 
    557 		if fptrace > 0 {
    558 			print("*** float unsigned D[", regd, "]=S[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
    559 		}
    560 		return 1
    561 	}
    562 
    563 	if i&0xff000000 == 0xee000000 || i&0xff000000 == 0xed000000 {
    564 		print("stepflt ", pc, " ", hex(i), "\n")
    565 		fabort()
    566 	}
    567 	return 0
    568 }
    569 
    570 //go:nosplit
    571 func _sfloat2(pc uint32, regs [15]uint32) (newpc uint32) {
    572 	systemstack(func() {
    573 		newpc = sfloat2(pc, &regs)
    574 	})
    575 	return
    576 }
    577 
    578 func _sfloatpanic()
    579 
    580 func sfloat2(pc uint32, regs *[15]uint32) uint32 {
    581 	first := true
    582 	for {
    583 		skip := stepflt((*uint32)(unsafe.Pointer(uintptr(pc))), regs)
    584 		if skip == 0 {
    585 			break
    586 		}
    587 		first = false
    588 		if skip == _FAULT {
    589 			// Encountered bad address in store/load.
    590 			// Record signal information and return to assembly
    591 			// trampoline that fakes the call.
    592 			const SIGSEGV = 11
    593 			curg := getg().m.curg
    594 			curg.sig = SIGSEGV
    595 			curg.sigcode0 = 0
    596 			curg.sigcode1 = 0
    597 			curg.sigpc = uintptr(pc)
    598 			pc = uint32(funcPC(_sfloatpanic))
    599 			break
    600 		}
    601 		pc += 4 * uint32(skip)
    602 	}
    603 	if first {
    604 		print("sfloat2 ", pc, " ", hex(*(*uint32)(unsafe.Pointer(uintptr(pc)))), "\n")
    605 		fabort() // not ok to fail first instruction
    606 	}
    607 	return pc
    608 }
    609