diff --git a/include/asm/rpn.h b/include/asm/rpn.h index 0972098b..88395f8d 100644 --- a/include/asm/rpn.h +++ b/include/asm/rpn.h @@ -69,6 +69,8 @@ rpn_DIV(struct Expression * expr, struct Expression * src1, 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); diff --git a/src/asm/asmy.y b/src/asm/asmy.y index 765ef468..861f50b2 100644 --- a/src/asm/asmy.y +++ b/src/asm/asmy.y @@ -473,6 +473,7 @@ void if_skip_to_endc( void ) %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 @@ void if_skip_to_endc( void ) %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 @@ relocconst : T_ID { 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 @@ op_a_n : const_8bit { $$ = $1; } 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; } diff --git a/src/asm/globlex.c b/src/asm/globlex.c index 4a762c95..c04fa52b 100644 --- a/src/asm/globlex.c +++ b/src/asm/globlex.c @@ -282,6 +282,9 @@ struct sLexInitString staticstrings[] = { {"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}, diff --git a/src/asm/locallex.c b/src/asm/locallex.c index a9e1e04b..4255c0fc 100644 --- a/src/asm/locallex.c +++ b/src/asm/locallex.c @@ -60,30 +60,31 @@ struct sLexInitString localstrings[] = { {"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}, - {"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}, + {"af", T_MODE_AF}, + {"bc", T_MODE_BC}, + {"de", T_MODE_DE}, + {"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} }; diff --git a/src/asm/rpn.c b/src/asm/rpn.c index 6487faf9..886d8f24 100644 --- a/src/asm/rpn.c +++ b/src/asm/rpn.c @@ -182,6 +182,46 @@ rpn_LOGAND(struct Expression * expr, struct Expression * src1, pushbyte(expr, RPN_LOGAND); } +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) diff --git a/test/link/high-low-a.asm b/test/link/high-low-a.asm new file mode 100644 index 00000000..91433887 --- /dev/null +++ b/test/link/high-low-a.asm @@ -0,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: diff --git a/test/link/high-low-b.asm b/test/link/high-low-b.asm new file mode 100644 index 00000000..be55313b --- /dev/null +++ b/test/link/high-low-b.asm @@ -0,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: diff --git a/test/link/test.sh b/test/link/test.sh index 80cfe0a9..ae2a26b4 100644 --- a/test/link/test.sh +++ b/test/link/test.sh @@ -1,5 +1,6 @@ otemp=$(mktemp) gbtemp=$(mktemp) +gbtemp2=$(mktemp) outtemp=$(mktemp) RGBASM=../../rgbasm @@ -23,4 +24,10 @@ 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