	.nolist
# Shark work-around

.if {STR_EQ[{GNX_CPU},ns32cg160]} | \
         {{FORCE_ALL_WKAROUND} & \
          { ~ {{STR_EQ[{GNX_CPU},ns32sf640]} | \
	       {STR_EQ[{GNX_CPU},ns32sf641]}}}}
.MACRO muld op1,op2
.macro_off
	muld {op1},{op2}
.macro_on
	nop
.ENDM
.endif

# Cuda work-around
.if {STR_EQ[{GNX_CPU},ns32gx320]} | \
         {{FORCE_ALL_WKAROUND} & \
          { ~ {{STR_EQ[{GNX_CPU},ns32sf640]} | \
	       {STR_EQ[{GNX_CPU},ns32sf641]}}}}

.MACRO mulw op1,op2
__mul__ {op1}, {op2}, w, 2
.ENDM

.MACRO mulb op1,op2
__mul__ {op1}, {op2}, b, 1
.ENDM

.MACRO __elim_reg_from_reglist__    reg, reg_num

	reg_num := {LIST_FIND[{reg_list},{reg}]}
	.if {reg_num} <> 0
		reg_list := {LIST_DEL[{reg_list},{reg_num}]}    
	.endif
.ENDM


.MACRO __mul__ op1, op2, b_or_w, pop_num
.if {STR_EQ[{OP_TYPE[{op2}]},GREG]}
	# if op2 is register no work-around is needed
	.macro_off
	mul{b_or_w} {op1},{op2}
	.macro_on
.else
	.nolist
	popd := 0
	popinst :=
	reg_list := [r0,r1,r2,r3,r4,r5,r6,r7]

	# Op1
	__elim_reg_from_reglist__   {OP_REG[{op1}]}
	__elim_reg_from_reglist__   {OP_INDEX_REG[{op1}]}

	newop1 := {op1}
	reg := {OP_REG[{op1}]}

	# memory_space -- always add 4 to displacement
	.if	{STR_EQ[{OP_TYPE[{op1}]},MEM_SPACE]} & \
		{STR_EQ[{SUB_STR[{reg},1,2]},sp]}

			newop1 := 4+{op1}

	# memory relative - always add 4 to inner displacement
	.elsif	{STR_EQ[{OP_TYPE[{op1}]},MEM_REL]} & \
		{STR_EQ[{SUB_STR[{reg},1,2]},sp]} 

			disp2 := {OP_DISP2[{op1}]}{OP_DISPSIZE2[{op1}]}
			disp1 := {OP_DISP1[{op1}]}{OP_DISPSIZE1[{op1}]}
			newop1 := {disp2}(4+{disp1}(sp)){OP_INDEX[{op1}]}

	# source tos - becomes 4(sp), and if not indexed we must
	# adjust stack later.
	.elsif	{STR_EQ[{OP_TYPE[{op1}]},TOS]}
		.if {OP_IS_INDEXED[{op1}]} = 0
			# if it is not scaled-index
			popd := 1
			popinst := adjspb $-{pop_num}
		.endif
		newop1 := 4(sp){OP_INDEX[{op1}]}
	.endif

	# Op2
	__elim_reg_from_reglist__   {OP_REG[{op2}]}
	__elim_reg_from_reglist__   {OP_INDEX_REG[{op2}]}

	newop2 := {op2}
	reg := {OP_REG[{op2}]}

	# memory_space -- always add 4 to displacement
	.if	{STR_EQ[{OP_TYPE[{op2}]},MEM_SPACE]} & \
		{STR_EQ[{SUB_STR[{reg},1,2]},sp]}

			newop2 := 4+{op2}

	# memory relative - always add 4 to inner displacement
	.elsif	{STR_EQ[{OP_TYPE[{op2}]},MEM_REL]} & \
		{STR_EQ[{SUB_STR[{reg},1,2]},sp]} 

			disp2 := {OP_DISP2[{op2}]}{OP_DISPSIZE2[{op2}]}
			disp1 := {OP_DISP1[{op2}]}{OP_DISPSIZE1[{op2}]}
			newop2 := {disp2}(4+{disp1}(sp)){OP_INDEX[{op2}]}

	# dest. tos - if source was tos - will become 4+x(sp), where
	# x is either 1 or 2. If source wasn't tos - becomes 4(sp).
	# No stack adjustment needed for tos destination.
	.elsif	{STR_EQ[{OP_TYPE[{op2}]},TOS]}
		.if {popd}	# First operand was also tos
			newop2 := {4 + {pop_num}}(sp)
		.else
			newop2 := 4(sp)
		.endif
		newop2 := {newop2}{OP_INDEX[{op2}]}
	.endif

	reg := {LIST_GET[{reg_list},1]}

	.list
	.macro_off
	#mul{b_or_w} {op1},{op2}
	movd	{reg},tos
	movx{b_or_w}d	{newop2},{reg}
	mul{b_or_w}	{newop1},{reg}
	mov{b_or_w}	{reg},{newop2}
	movd	tos,{reg}
	{popinst}
	.macro_on
.endif
.ENDM

.endif  # Cuda workaround

# Swordfish Work-arounds implemented:
#   1. Place a slot of nops before each emulation instruction.
# ----> Disabled, Yuval, Sept. 5 1991.
#   2. Place a slot of nops after each conditional branch.
# Use of a single long nop caused alignement problems, since not all branches 
# are scheduled by the compiler to be in PIPE B.
# Yuval, Sept. 4 1991.

.if {STR_EQ[{GNX_CPU},ns32sf640]} | {STR_EQ[{GNX_CPU},ns32sf641]}

.MACRO two_nops 
	orw	c0,c0,c0
	orw	c0,c0,c0
.ENDM

.MACRO beq dest
.macro_off 
	beq	{dest} 
.macro_on
	two_nops
.ENDM

.MACRO bne dest
.macro_off
	bne	{dest}
.macro_on
	two_nops
.ENDM

.MACRO bcs dest
.macro_off
	bcs	{dest}
.macro_on
	two_nops
.ENDM

.MACRO bcc dest
.macro_off
	bcc	{dest}
.macro_on
	two_nops
.ENDM

.MACRO bhi dest
.macro_off
	bhi	{dest}
.macro_on
	two_nops
.ENDM

.MACRO bls dest
.macro_off
	bls	{dest}
.macro_on
	two_nops
.ENDM

.MACRO bgt dest
.macro_off
	bgt	{dest}
.macro_on
	two_nops
.ENDM

.MACRO ble dest
.macro_off
	ble	{dest}
.macro_on
	two_nops
.ENDM

.MACRO bfs dest
.macro_off
	bfs	{dest}
.macro_on
	two_nops
.ENDM

.MACRO bfc dest
.macro_off
	bfc	{dest}
.macro_on
	two_nops
.ENDM

.MACRO blo dest
.macro_off
	blo	{dest}
.macro_on
	two_nops
.ENDM

.MACRO bhs dest
.macro_off
	bhs	{dest}
.macro_on
	two_nops
.ENDM

.MACRO blt dest
.macro_off
	blt	{dest}
.macro_on
	two_nops
.ENDM

.MACRO bge dest
.macro_off
	bge	{dest}
.macro_on
	two_nops
.ENDM

.MACRO  dest
.macro_off
		{dest}
.macro_on
	two_nops
.ENDM

.MACRO DISABLE_mbiti op1,op2,op3
	two_nops
.macro_off
	mbiti {op1},{op2},{op3}
.macro_on
.ENDM

.MACRO DISABLE_spr op1,op2 
.if {STR_EQ[{op2},c0]}
.else
	two_nops
.endif
.macro_off
	spr {op1},{op2}
.macro_on
.ENDM

.MACRO DISABLE_lpr op1,op2 
	two_nops
.macro_off
	lpr {op1},{op2}
.macro_on
.ENDM

.MACRO DISABLE_wait 
	two_nops
.macro_off
	wait
.macro_on
.ENDM

.MACRO DISABLE_retx 
	two_nops
.macro_off
	retx
.macro_on
.ENDM

.MACRO DISABLE_eoi 
	two_nops
.macro_off
	eoi
.macro_on
.ENDM

.MACRO DISABLE_cinv options
	two_nops
.macro_off
	cinv {options}
.macro_on
.ENDM

.endif
.list
