ref: ce21cfad4e986512b165266cfabe18eec5453af6
parent: bfcef01211b5cd95031db3f03771314b244852b0
parent: dda3a066be61d1fdacaa2f05ce43907b04b3b9a0
author: AntonioND <[email protected]>
date: Sat Apr 8 09:30:10 EDT 2017
Merge pull request #160 from AntonioND/an/high-low Implement HIGH() and LOW() operators
--- a/include/asm/rpn.h
+++ b/include/asm/rpn.h
@@ -69,6 +69,8 @@
void
rpn_MOD(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
+void rpn_HIGH(struct Expression * expr, struct Expression * src);
+void rpn_LOW(struct Expression * expr, struct Expression * src);
void rpn_UNNEG(struct Expression * expr, struct Expression * src);
void rpn_UNNOT(struct Expression * expr, struct Expression * src);
UWORD rpn_PopByte(struct Expression * expr);
--- a/src/asm/asmy.y
+++ b/src/asm/asmy.y
@@ -473,6 +473,7 @@
%left T_OP_CEIL
%left T_OP_FLOOR
+%token T_OP_HIGH T_OP_LOW
%left T_OP_STRCMP
%left T_OP_STRIN
@@ -537,11 +538,12 @@
%token T_Z80_SLA T_Z80_SRA T_Z80_SRL T_Z80_SUB T_Z80_SWAP
%token T_Z80_XOR
-%token T_MODE_A T_MODE_B T_MODE_C T_MODE_C_IND T_MODE_D T_MODE_E T_MODE_H T_MODE_L
+%token T_TOKEN_A T_TOKEN_B T_TOKEN_C T_TOKEN_D T_TOKEN_E T_TOKEN_H T_TOKEN_L
%token T_MODE_AF
%token T_MODE_BC T_MODE_BC_IND
%token T_MODE_DE T_MODE_DE_IND
%token T_MODE_SP T_MODE_SP_IND
+%token T_MODE_C_IND
%token T_MODE_HL T_MODE_HL_IND T_MODE_HL_INDDEC T_MODE_HL_INDINC
%token T_CC_NZ T_CC_Z T_CC_NC
@@ -992,6 +994,10 @@
{ rpn_UNNEG(&$$,&$2); }
| T_OP_NOT relocconst %prec NEG
{ rpn_UNNOT(&$$,&$2); }
+ | T_OP_HIGH '(' relocconst ')'
+ { rpn_HIGH(&$$, &$3); }
+ | T_OP_LOW '(' relocconst ')'
+ { rpn_LOW(&$$, &$3); }
| T_OP_BANK '(' T_ID ')'
{ rpn_Bank(&$$,$3); $$.nVal = 0; }
| T_OP_DEF { oDontExpandStrings = true; } '(' T_ID ')'
@@ -1611,10 +1617,33 @@
comma : ','
;
+T_MODE_A : T_TOKEN_A
+ | T_OP_HIGH '(' T_MODE_AF ')'
+;
+T_MODE_B : T_TOKEN_B
+ | T_OP_HIGH '(' T_MODE_BC ')'
+;
+T_MODE_C : T_TOKEN_C
+ | T_OP_LOW '(' T_MODE_BC ')'
+;
+T_MODE_D : T_TOKEN_D
+ | T_OP_HIGH '(' T_MODE_DE ')'
+;
+T_MODE_E : T_TOKEN_E
+ | T_OP_LOW '(' T_MODE_DE ')'
+;
+T_MODE_H : T_TOKEN_H
+ | T_OP_HIGH '(' T_MODE_HL ')'
+;
+T_MODE_L : T_TOKEN_L
+ | T_OP_LOW '(' T_MODE_HL ')'
+;
+
+
ccode : T_CC_NZ { $$ = CC_NZ; }
| T_CC_Z { $$ = CC_Z; }
| T_CC_NC { $$ = CC_NC; }
- | T_MODE_C { $$ = CC_C; }
+ | T_TOKEN_C { $$ = CC_C; }
;
reg_r : T_MODE_B { $$ = REG_B; }
--- a/src/asm/globlex.c
+++ b/src/asm/globlex.c
@@ -282,6 +282,9 @@
{"atan", T_OP_ATAN},
{"atan2", T_OP_ATAN2},
+ {"high", T_OP_HIGH},
+ {"low", T_OP_LOW},
+
{"strcmp", T_OP_STRCMP},
{"strin", T_OP_STRIN},
{"strsub", T_OP_STRSUB},
--- a/src/asm/locallex.c
+++ b/src/asm/locallex.c
@@ -60,30 +60,31 @@
{"nz", T_CC_NZ},
{"z", T_CC_Z},
{"nc", T_CC_NC},
- /* { "c", T_MODE_C }, */
+ /* { "c", T_TOKEN_C }, */
+ {"[bc]", T_MODE_BC_IND},
+ {"[de]", T_MODE_DE_IND},
{"[hl]", T_MODE_HL_IND},
{"[hl+]", T_MODE_HL_INDINC},
{"[hl-]", T_MODE_HL_INDDEC},
{"[hli]", T_MODE_HL_INDINC},
{"[hld]", T_MODE_HL_INDDEC},
- {"hl", T_MODE_HL},
+ {"[sp]", T_MODE_SP_IND},
{"af", T_MODE_AF},
- {"[bc]", T_MODE_BC_IND},
{"bc", T_MODE_BC},
- {"[de]", T_MODE_DE_IND},
{"de", T_MODE_DE},
- {"[sp]", T_MODE_SP_IND},
+ {"hl", T_MODE_HL},
{"sp", T_MODE_SP},
- {"a", T_MODE_A},
- {"b", T_MODE_B},
- {"[$ff00+c]", T_MODE_C_IND},
{"[c]", T_MODE_C_IND},
- {"c", T_MODE_C},
- {"d", T_MODE_D},
- {"e", T_MODE_E},
- {"h", T_MODE_H},
- {"l", T_MODE_L},
+ {"[$ff00+c]", T_MODE_C_IND},
+
+ {"a", T_TOKEN_A},
+ {"b", T_TOKEN_B},
+ {"c", T_TOKEN_C},
+ {"d", T_TOKEN_D},
+ {"e", T_TOKEN_E},
+ {"h", T_TOKEN_H},
+ {"l", T_TOKEN_L},
{NULL, 0}
};
--- a/src/asm/rpn.c
+++ b/src/asm/rpn.c
@@ -183,6 +183,46 @@
}
void
+rpn_HIGH(struct Expression * expr, struct Expression * src)
+{
+ *expr = *src;
+
+ expr->nVal = (expr->nVal >> 8) & 0xFF;
+
+ pushbyte(expr, RPN_CONST);
+ pushbyte(expr, 8);
+ pushbyte(expr, 0);
+ pushbyte(expr, 0);
+ pushbyte(expr, 0);
+
+ pushbyte(expr, RPN_SHR);
+
+ pushbyte(expr, RPN_CONST);
+ pushbyte(expr, 0xFF);
+ pushbyte(expr, 0);
+ pushbyte(expr, 0);
+ pushbyte(expr, 0);
+
+ pushbyte(expr, RPN_AND);
+}
+
+void
+rpn_LOW(struct Expression * expr, struct Expression * src)
+{
+ *expr = *src;
+
+ expr->nVal = expr->nVal & 0xFF;
+
+ pushbyte(expr, RPN_CONST);
+ pushbyte(expr, 0xFF);
+ pushbyte(expr, 0);
+ pushbyte(expr, 0);
+ pushbyte(expr, 0);
+
+ pushbyte(expr, RPN_AND);
+}
+
+void
rpn_LOGEQU(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
--- /dev/null
+++ b/test/link/high-low-a.asm
@@ -1,0 +1,22 @@
+ldhilo : MACRO
+ ld HIGH(\1),LOW(\2)
+ENDM
+
+SECTION "r0", ROM0[$0]
+ld HIGH(af),a
+ld HIGH(bc),LOW(bc)
+ld LOW(bc),HIGH(bc)
+ld HIGH(de),LOW(de)
+ld LOW(de),HIGH(de)
+ ldhilo hl, hl
+ld LOW(hl),HIGH(hl)
+
+db HIGH(label+$AB)
+db LOW(label+$AB)
+
+db HIGH($1234)
+db LOW($1234)
+
+SECTION "o",OAM
+DS $10
+label:
--- /dev/null
+++ b/test/link/high-low-b.asm
@@ -1,0 +1,18 @@
+SECTION "r0", ROM0[$0]
+ld a,a
+ld b,c
+ld c,b
+ld d,e
+ld e,d
+ld h,l
+ld l,h
+
+db ((label+$AB) >> 8) & $FF
+db (label+$AB) & $FF
+
+db ($1234 >> 8) & $FF
+db $1234 & $FF
+
+SECTION "o",OAM
+DS $10
+label:
--- a/test/link/test.sh
+++ b/test/link/test.sh
@@ -1,5 +1,6 @@
otemp=$(mktemp)
gbtemp=$(mktemp)
+gbtemp2=$(mktemp)
outtemp=$(mktemp)
RGBASM=../../rgbasm
@@ -22,5 +23,11 @@
diff romx-tiny-no-t.out $outtemp
$RGBLINK -t -o $gbtemp $otemp > $outtemp 2>&1
diff romx-tiny-t.out $outtemp
+
+$RGBASM -o $otemp high-low-a.asm
+$RGBLINK -o $gbtemp $otemp
+$RGBASM -o $otemp high-low-b.asm
+$RGBLINK -o $gbtemp2 $otemp
+diff $gbtemp $gbtemp2
exit 0