#ifndef _ARCH_PPC_PSEUDO_INST_H_
#define _ARCH_PPC_PSEUDO_INST_H_
#include <architecture/ppc/reg_help.h>
#include <architecture/ppc/asm_help.h>
#ifdef __ASSEMBLER__
.set __no_at,0
.macro .at_off
.set __no_at,1
.endmacro
.macro .at_on
.set __no_at,0
.endmacro
.macro li32 .if $n != 2
.abort "invalid operands of li32"
.endif
.abs __is_abs,$1
.if !__is_abs
addis $0,0,hi16($1)
ori $0,$0,lo16($1)
.elseif $1 == 0
addi $0,0,0
.elseif ($1 & 0xffff) == 0
addis $0,0,hi16($1)
.elseif ($1 & 0xffff8000) == 0
addi $0,0,$1
.elseif ($1 & 0xffff8000) == 0xffff8000
addi $0,0,$1
.else
addis $0,0,hi16($1)
ori $0,$0,lo16($1)
.endif
.endmacro
.macro andi32. .if $n != 3
.abort "invalid operands of andi."
.endif
.set __used_at,0
.abs __is_abs,$2
.if !__is_abs
.set __used_at,1
li32 at,$2
and. $0,$1,at
.elseif ($2 & 0xffff0000) == 0
andi. $0,$1,$2
.elseif ($2 & 0xffff) == 0
andis. $0,$1,hi16($2)
.else
.set __used_at,1
li32 at,$2
and. $0,$1,at
.endif
.if __no_at & __used_at
.abort "Macro uses at while .no_at in effect"
.endif
.endmacro
.macro ori32 .if $n != 3
.abort "invalid operands of ori"
.endif
.abs __is_abs,$2
.if !__is_abs
oris $0,$1,hi16($2)
ori $0,$1,lo16($2)
.elseif ($2 & 0xffff0000) == 0
ori $0,$1,$2
.elseif ($2 & 0xffff) == 0
oris $0,$1,hi16($2)
.else
oris $0,$1,hi16($2)
ori $0,$1,lo16($2)
.endif
.endmacro
.macro xori32 .if $n != 3
.abort "invalid operands of xori"
.endif
.abs __is_abs,$2
.if !__is_abs
xoris $0,$1,hi16($2)
xori $0,$1,lo16($2)
.elseif ($2 & 0xffff0000) == 0
xori $0,$1,$2
.elseif ($2 & 0xffff) == 0
xoris $0,$1,hi16($2)
.else
xoris $0,$1,hi16($2)
xori $0,$1,lo16($2)
.endif
.endmacro
#define MEMREF_INST(op) \
.macro op ## 32 @\
.set __used_at,0 @\
.if $n == 3 @\
.greg __is_greg,$1 @\
.abs __is_abs,$2 @\
.if __is_abs @\
.if ($2 & 0xffff8000) == 0 @\
op $0,$2($1) @\
.elseif ($2 & 0xffff8000) == 0xffff8000 @\
op $0,$2($1) @\
.else @\
.if !__is_greg @\
.set __used_at,1 @\
lis at,ha16($2) @\
op $0,lo16($2)(at) @\
.else @\
.set __used_at,1 @\
lis at,ha16($2) @\
add at,at,$1 @\
op $0,lo16($2)(at) @\
.endif @\
.endif @\
.else @\
.if !__is_greg @\
.set __used_at,1 @\
lis at,ha16($2) @\
op $0,lo16($2)(at) @\
.else @\
.set __used_at,1 @\
lis at,ha16($2) @\
add at,at,$1 @\
op $0,lo16($2)(at) @\
.endif @\
.endif @\
.elseif $n == 2 @\
.greg __is_greg,$1 @\
.if !__is_greg @\
.abs __is_abs,$1 @\
.if __is_abs @\
.if ($1 & 0xffff8000) == 0 @\
op $0,$1(0) @\
.elseif ($1 & 0xffff8000) == 0xffff8000 @\
op $0,$1(0) @\
.else @\
.set __used_at,1 @\
lis at,ha16($1) @\
op $0,lo16($1)(at) @\
.endif @\
.else @\
.set __used_at,1 @\
lis at,ha16($1) @\
op $0,lo16($1)(at) @\
.endif @\
.else @\
op $0,0($1) @\
.endif @\
.else @\
.abort "Invalid operands of " #op "32" @\
.endif @\
.if __no_at & __used_at @\
.abort "Macro uses at while .no_at in effect" @\
.endif @\
.endmacro
MEMREF_INST(lbz)
MEMREF_INST(lhz)
MEMREF_INST(lha)
MEMREF_INST(lwz)
MEMREF_INST(lwa)
MEMREF_INST(ld)
MEMREF_INST(stb)
MEMREF_INST(sth)
MEMREF_INST(stw)
MEMREF_INST(std)
MEMREF_INST(lmw)
MEMREF_INST(lmd)
MEMREF_INST(stmw)
MEMREF_INST(stmd)
#define ARITH_INST(op, op3, sf) \
.macro op ## 32 ## sf @\
.if $n != 3 @\
.abort "invalid operands to " #op "32" @\
.endif @\
.abs __is_abs,$2 @\
.if __is_abs @\
.if ($2 & 0xffff8000) == 0 @\
op##sf $0,$1,$2 @\
.elseif ($2 & 0xffff8000) == 0xffff8000 @\
op##sf $0,$1,$2 @\
.elseif __no_at @\
.abort "Macro uses at while .no_at in effect" @\
.else @\
li32 at,$2 @\
op3##sf $0,$1,at @\
.endif @\
.elseif __no_at @\
.abort "Macro uses at while .no_at in effect" @\
.else @\
li32 at,$2 @\
op3##sf $0,$1,at @\
.endif @\
.endmacro
ARITH_INST(addi, add, )
ARITH_INST(subi, sub, )
ARITH_INST(addic, addc, )
ARITH_INST(subic, subc, )
ARITH_INST(addic, addc, .)
ARITH_INST(subic, subc, .)
ARITH_INST(mulli, mull, )
#define CMPEX_INST(op, op3) \
.macro op ## 32 @\
.if $n == 3 @\
.abs __is_abs,$2 @\
.if __is_abs @\
.if ($2 & 0xffff8000) == 0 @\
op $0,$1,$2 @\
.elseif ($2 & 0xffff8000) == 0xffff8000 @\
op $0,$1,$2 @\
.elseif __no_at @\
.abort "Macro uses at while .no_at in effect" @\
.else @\
li32 at,$2 @\
op3 $0,$1,at @\
.endif @\
.elseif __no_at @\
.abort "Macro uses at while .no_at in effect" @\
.else @\
li32 at,$2 @\
op3 $0,$1,at @\
.endif @\
.elseif $n == 2 @\
.abs __is_abs,$1 @\
.if __is_abs @\
.if ($1 & 0xffff8000) == 0 @\
op $0,$1 @\
.elseif ($1 & 0xffff8000) == 0xffff8000 @\
op $0,$1 @\
.elseif __no_at @\
.abort "Macro uses at while .no_at in effect" @\
.else @\
li32 at,$1 @\
op3 $0,at @\
.endif @\
.elseif __no_at @\
.abort "Macro uses at while .no_at in effect" @\
.else @\
li32 at,$1 @\
op3 $0,at @\
.endif @\
.else @\
.abort "invalid operands to " #op "32" @\
.endif @\
.endmacro
CMPEX_INST(cmpdi, cmpd)
CMPEX_INST(cmpwi, cmpw)
CMPEX_INST(cmpldi, cmpld)
CMPEX_INST(cmplwi, cmplw)
#define CMP_INST(op, op3) \
.macro op ## 32 @\
.if $n == 4 @\
.abs __is_abs,$3 @\
.if __is_abs @\
.if ($3 & 0xffff8000) == 0 @\
op $0,$1,$2,$3 @\
.elseif ($3 & 0xffff8000) == 0xffff8000 @\
op $0,$1,$2,$3 @\
.elseif __no_at @\
.abort "Macro uses at while .no_at in effect" @\
.else @\
li32 at,$3 @\
op3 $0,$1,$2,at @\
.endif @\
.elseif __no_at @\
.abort "Macro uses at while .no_at in effect" @\
.else @\
li32 at,$3 @\
op3 $0,$1,$2,at @\
.endif @\
.else @\
.abort "invalid operands to " #op "32" @\
.endif @\
.endmacro
CMP_INST(cmpi, cmp)
CMP_INST(cmpli, cmpl)
#endif
#endif