# Copyright (c) 2021, RISC OS Open Ltd
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met: 
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of RISC OS Open Ltd nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# 

DEFAULT()
{
	return aborttrap_ERROR_UNHANDLED;
}

# A8.6.53 LDM/LDMIA/LDMFD
LDMIA_A1(Rn,W,reglist)
{
	return aborttrap_LDMIA(ctx,Rn,reglist,W);
}

# A8.6.54 LDMDA/FA
LDMDA_A1(Rn,W,reglist)
{
	return aborttrap_LDMDA(ctx,Rn,reglist,W);
}

# A8.6.55 LDMDB/EA
LDMDB_A1(Rn,W,reglist)
{
	return aborttrap_LDMDB(ctx,Rn,reglist,W);
}

# A8.6.56 LDMIB/ED
LDMIB_A1(Rn,W,reglist)
{
	return aborttrap_LDMIB(ctx,Rn,reglist,W);
}

# A8.6.58 LDR (immediate, ARM)
LDR_imm_A1(Rt,Rn,imm12,P,U,W)
{
	return aborttrap_LDR_imm(ctx,Rt,Rn,imm12,P,U,!P || W);
}

# A8.6.59 LDR (literal)
LDR_lit_A1(Rt,imm12,U,nonstandard)
{
	if(nonstandard)
		return aborttrap_ERROR(Unexpected);
	return aborttrap_LDR_lit(ctx,Rt,imm12,U);
}

# A8.6.60 LDR (register)
LDR_reg_A1(Rt,Rn,imm5,type,Rm,P,U,W)
{
	eshift shift_t;
	uint32_t shift_n;
	decodeimmshift(type,imm5,&shift_t,&shift_n);
	return aborttrap_LDR_reg(ctx,Rt,Rn,Rm,P,U,!P || W,shift_t,shift_n);
}

# A8.6.62 LDRB (immediate, ARM)
LDRB_imm_A1(Rt,Rn,imm12,P,U,W)
{
	return aborttrap_LDRB_imm(ctx,Rt,Rn,imm12,P,U,!P || W);
}

# A8.6.63 LDRB (literal)
LDRB_lit_A1(Rt,imm12,U,nonstandard)
{
	if(nonstandard)
		return aborttrap_ERROR(Unexpected);
	return aborttrap_LDRB_lit(ctx,Rt,imm12,U);
}

# A8.6.64 LDRB (register)
LDRB_reg_A1(Rt,Rn,imm5,type,Rm,P,U,W)
{
	eshift shift_t;
	uint32_t shift_n;
	decodeimmshift(type,imm5,&shift_t,&shift_n);
	return aborttrap_LDRB_reg(ctx,Rt,Rn,Rm,P,U,!P || W,shift_t,shift_n);
}

# A8.6.65 LDRBT
LDRBT_A1(Rt,Rn,imm12,U)
{
	return aborttrap_LDRBT_imm(ctx,Rt,Rn,imm12,true,U);
}

LDRBT_A2(Rt,Rn,imm5,type,Rm,U)
{
	eshift shift_t;
	uint32_t shift_n;
	decodeimmshift(type,imm5,&shift_t,&shift_n);
	return aborttrap_LDRBT_reg(ctx,Rt,Rn,Rm,true,U,shift_t,shift_n);
}

# A8.6.86 LDRT
LDRT_A1(Rt,Rn,imm12,U)
{
	return aborttrap_LDRT_imm(ctx,Rt,Rn,imm12,true,U);
}

LDRT_A2(Rt,Rn,imm5,type,Rm,U)
{
	eshift shift_t;
	uint32_t shift_n;
	decodeimmshift(type,imm5,&shift_t,&shift_n);
	return aborttrap_LDRT_reg(ctx,Rt,Rn,Rm,true,U,shift_t,shift_n);
}

# A8.6.189 STM/STMIA/STMEA
STMIA_A1(Rn,W,reglist)
{
	return aborttrap_STMIA(ctx,Rn,reglist,W);
}

# A8.6.190 STMDA/ED
STMDA_A1(Rn,W,reglist)
{
	return aborttrap_STMDA(ctx,Rn,reglist,W);
}

# A8.6.191 STMDB/FD
STMDB_A1(Rn,W,reglist)
{
	return aborttrap_STMDB(ctx,Rn,reglist,W);
}

# A8.6.192 STMIB/FA
STMIB_A1(Rn,W,reglist)
{
	return aborttrap_STMIB(ctx,Rn,reglist,W);
}

# A8.6.194 STR (immediate, ARM)
STR_imm_A1(Rt,Rn,imm12,P,U,W)
{
	return aborttrap_STR_imm(ctx,Rt,Rn,imm12,P,U,!P || W);
}

# A8.6.195 STR (register)
STR_reg_A1(Rt,Rn,imm5,type,Rm,P,U,W)
{
	eshift shift_t;
	uint32_t shift_n;
	decodeimmshift(type,imm5,&shift_t,&shift_n);
	return aborttrap_STR_reg(ctx,Rt,Rn,Rm,P,U,!P || W,shift_t,shift_n);
}

# A8.6.197 STRB (immediate, ARM)
STRB_imm_A1(Rt,Rn,imm12,P,U,W)
{
	return aborttrap_STRB_imm(ctx,Rt,Rn,imm12,P,U,!P || W);
}

# A8.6.198 STRB (register)
STRB_reg_A1(Rt,Rn,imm5,type,Rm,P,U,W)
{
	eshift shift_t;
	uint32_t shift_n;
	decodeimmshift(type,imm5,&shift_t,&shift_n);
	return aborttrap_STRB_reg(ctx,Rt,Rn,Rm,P,U,!P || W,shift_t,shift_n);
}

# A8.6.199 STRBT
STRBT_A1(Rt,Rn,imm12,U)
{
	return aborttrap_STRBT_imm(ctx,Rt,Rn,imm12,true,U);
}

STRBT_A2(Rt,Rn,imm5,type,Rm,U)
{
	eshift shift_t;
	uint32_t shift_n;
	decodeimmshift(type,imm5,&shift_t,&shift_n);
	return aborttrap_STRBT_reg(ctx,Rt,Rn,Rm,true,U,shift_t,shift_n);
}

# A8.6.210 STRT
STRT_A1(Rt,Rn,imm12,U)
{
	return aborttrap_STRT_imm(ctx,Rt,Rn,imm12,true,U);
}

STRT_A2(Rt,Rn,imm5,type,Rm,U)
{
	eshift shift_t;
	uint32_t shift_n;
	decodeimmshift(type,imm5,&shift_t,&shift_n);
	return aborttrap_STRT_reg(ctx,Rt,Rn,Rm,true,U,shift_t,shift_n);
}

# A8.6.219 SWP, SWPB
SWP_SWPB_A1(Rt,Rt2,Rn,B,nonstandard)
{
	if(nonstandard)
		return aborttrap_ERROR(Unexpected);
	return aborttrap_SWP(ctx,Rt,Rt2,Rn,B);
}

# B6.1.2 LDM (exception return)
LDM_exception_A1(Rn,reglist,P,U,W)
{
	return aborttrap_LDM_exception(ctx,Rn,reglist,W,U,(P==U));
}

# B6.1.3 LDM (user registers)
LDM_user_A1(Rn,reglist,P,U,nonstandard)
{
	if(nonstandard)
		return aborttrap_ERROR(Unexpected);
	return aborttrap_LDM_user(ctx,Rn,reglist,U,(P==U));
}

# B6.1.11 STM (user registers)
STM_user_A1(Rn,reglist,P,U,nonstandard)
{
	if(nonstandard)
		return aborttrap_ERROR(Unexpected);
	return aborttrap_STM_user(ctx,Rn,reglist,U,(P==U));
}

# A8.6.122 POP
# Map to the underlying LDM/LDR instruction, it exhibits the same behaviour
POP_A1 as if LDMIA_A1
POP_A2 as if LDR_imm_A1

# A8.6.123 PUSH
# Map to the underlying STM/STR instruction, it exhibits the same behaviour
PUSH_A1 as if STMDB_A1
PUSH_A2 as if STR_imm_A1