/* Implements special instruction mnemonics
Copyright 2001-2005 Craig Franklin
Copyright 2016 Molnár Károly
*/
#include "stdhdr.h"
#include "libgputils.h"
#include "gpasm.h"
#include "gpmsg.h"
#include "special.h"
#include "directive.h"
#include "evaluate.h"
/*------------------------------------------------------------------------------------------------*/
static pnode_t *
_make_constant_list(int Value1, int Value2)
{
return mk_list(mk_constant(Value1), mk_list(mk_constant(Value2), NULL));
}
/*------------------------------------------------------------------------------------------------*/
static pnode_t *
_add_symbol_constant(pnode_t *Parms, int Value)
{
return mk_list(PnListHead(Parms), mk_list(mk_constant(Value), NULL));
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_addcf(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
(void)Arity;
gpmsg(GPM_SPECIAL_MNEMONIC, NULL);
do_insn("btfsc", _make_constant_list(3, 0));
do_insn("incf", Parms);
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_adddcf(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
(void)Arity;
do_insn("btfsc", _make_constant_list(3, 1));
do_insn("incf", Parms);
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_b(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
(void)Arity;
do_insn("goto", Parms);
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_bc(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
(void)Arity;
do_insn("btfsc", _make_constant_list(3, 0));
do_insn("goto", Parms);
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_bdc(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
(void)Arity;
do_insn("btfsc", _make_constant_list(3, 1));
do_insn("goto", Parms);
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_bz(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
(void)Arity;
do_insn("btfsc", _make_constant_list(3, 2));
do_insn("goto", Parms);
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_bnc(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
(void)Arity;
do_insn("btfss", _make_constant_list(3, 0));
do_insn("goto", Parms);
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_bndc(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
(void)Arity;
do_insn("btfss", _make_constant_list(3, 1));
do_insn("goto", Parms);
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_bnz(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
(void)Arity;
do_insn("btfss", _make_constant_list(3, 2));
do_insn("goto", Parms);
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_clrc(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
if (Arity != 0) {
gpmsg(GPE_TOO_MANY_ARGU, NULL);
}
do_insn("bcf", _make_constant_list(3, 0));
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_clrdc(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
if (Arity != 0) {
gpmsg(GPE_TOO_MANY_ARGU, NULL);
}
do_insn("bcf", _make_constant_list(3, 1));
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_clrz(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
if (Arity != 0) {
gpmsg(GPE_TOO_MANY_ARGU, NULL);
}
do_insn("bcf", _make_constant_list(3, 2));
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_lcall(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
(void)Arity;
do_insn("pagesel", Parms);
do_insn("call", Parms);
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_lgoto(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
(void)Arity;
do_insn("pagesel", Parms);
do_insn("goto", Parms);
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_movfw(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
if (eval_enforce_arity(Arity, 1)) {
do_insn("movf", _add_symbol_constant(Parms, 0));
}
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_negf(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
if ((Arity == 1) || (Arity == 2)) {
do_insn("comf", _add_symbol_constant(Parms, 1));
do_insn("incf", Parms);
}
else {
eval_enforce_arity(Arity, 2);
}
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_setc(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
if (Arity != 0) {
gpmsg(GPE_TOO_MANY_ARGU, NULL);
}
do_insn("bsf", _make_constant_list(3, 0));
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_setdc(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
if (Arity != 0) {
gpmsg(GPE_TOO_MANY_ARGU, NULL);
}
do_insn("bsf", _make_constant_list(3, 1));
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_setz(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
if (Arity != 0) {
gpmsg(GPE_TOO_MANY_ARGU, NULL);
}
do_insn("bsf", _make_constant_list(3, 2));
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_skpc(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
if (Arity != 0) {
gpmsg(GPE_TOO_MANY_ARGU, NULL);
}
do_insn("btfss", _make_constant_list(3, 0));
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_skpdc(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
if (Arity != 0) {
gpmsg(GPE_TOO_MANY_ARGU, NULL);
}
do_insn("btfss", _make_constant_list(3, 1));
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_skpz(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
if (Arity != 0) {
gpmsg(GPE_TOO_MANY_ARGU, NULL);
}
do_insn("btfss", _make_constant_list(3, 2));
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_skpnc(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
if (Arity != 0) {
gpmsg(GPE_TOO_MANY_ARGU, NULL);
}
do_insn("btfsc", _make_constant_list(3, 0));
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_skpndc(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
if (Arity != 0) {
gpmsg(GPE_TOO_MANY_ARGU, NULL);
}
do_insn("btfsc", _make_constant_list(3, 1));
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_skpnz(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
if (Arity != 0) {
gpmsg(GPE_TOO_MANY_ARGU, NULL);
}
do_insn("btfsc", _make_constant_list(3, 2));
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_subcf(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
(void)Arity;
do_insn("btfsc", _make_constant_list(3, 0));
do_insn("decf", Parms);
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_subdcf(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
(void)Arity;
do_insn("btfsc", _make_constant_list(3, 1));
do_insn("decf", Parms);
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal
_do_tstf(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms)
{
(void)Name;
if (eval_enforce_arity(Arity, 1)) {
do_insn("movf", _add_symbol_constant(Parms, 1));
}
return Value;
}
/*------------------------------------------------------------------------------------------------*/
static gpasmVal _do_mode(gpasmVal Value, const char *Name, int Arity, pnode_t *Parms) {
pnode_t *val;
(void)Name;
if (eval_enforce_arity(Arity, 1)) {
val = PnListHead(Parms);
if (PnIsConstant(val) && (PnConstant(val) > 0x1F)) {
if (state.strict_level == 2) {
gpmsg(GPE_OUT_OF_RANGE, "Bad value: %i (%#x) > Limit: 0x1F",
PnConstant(val), PnConstant(val));
}
else {
gpmsg(GPW_OUT_OF_RANGE, "Bad value: %i (%#x) > Limit: 0x1F",
/*gp_find_highest_bit(0x1F),*/ PnConstant(val), PnConstant(val));
}
PnConstant(val) &= 0x1F;
}
do_insn("movlw", Parms);
do_insn("movwm", NULL);
}
return Value;
}
/*------------------------------------------------------------------------------------------------*/
/* PIC 12-bit and 14-bit "Special" instruction set. */
const insn_t special[] = {
{ "addcf", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_addcf },
{ "adddcf", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_adddcf },
{ "b", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_b },
{ "bc", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_bc },
{ "bdc", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_bdc },
{ "bz", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_bz },
{ "bnc", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_bnc },
{ "bndc", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_bndc },
{ "bnz", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_bnz },
{ "clrc", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_clrc },
{ "clrdc", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_clrdc },
{ "clrz", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_clrz },
{ "lcall", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_lcall },
{ "lgoto", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_lgoto },
{ "movfw", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_movfw },
{ "negf", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_negf },
{ "setc", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_setc },
{ "setdc", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_setdc },
{ "setz", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_setz },
{ "skpc", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_skpc },
{ "skpdc", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_skpdc },
{ "skpz", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_skpz },
{ "skpnc", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_skpnc },
{ "skpndc", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_skpndc },
{ "skpnz", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_skpnz },
{ "subcf", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_subcf },
{ "subdcf", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_subdcf },
{ "tstf", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_tstf }
};
const int num_op_special = TABLE_SIZE(special);
const insn_t op_sx_mode = {
"mode", 0, 0, ICODE_NONE, INSN_CLASS_FUNC, INV_MASK_NULL, 0, _do_mode
};
Detected encoding: UTF-8 | 0
|